diff --git a/.all-contributorsrc b/.all-contributorsrc index c0d428d36f..a68023539d 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -162,7 +162,7 @@ "code", "doc" ] - } + }, { "login": "lacoak21", "name": "Luisa Coakley", @@ -172,7 +172,7 @@ "code", "doc" ] - } + }, { "login": "nkerman", "name": "Nat Kerman", @@ -182,7 +182,7 @@ "code", "doc" ] - } + }, { "login": "torimarbois", "name": "Tori Marbois", @@ -192,6 +192,16 @@ "code", "doc" ] + }, + { + "login": "mfacchinelli", + "name": "Michele Facchinelli", + "avatar_url": "https://avatars.githubusercontent.com/u/19731497?v=4", + "profile": "https://github.com/mfacchinelli", + "contributions": [ + "code", + "test" + ] } ], "contributorsPerLine": 7, diff --git a/.github/issue_templates/Algorithim_development.md b/.github/issue_templates/Algorithim_development.md deleted file mode 100644 index 6081e74741..0000000000 --- a/.github/issue_templates/Algorithim_development.md +++ /dev/null @@ -1,30 +0,0 @@ -### Algorithm Description: - -### Requirements: - -> **Specify: (optional)** - -### Algorithm Code Information: -> Input data: -> > **Specify details:** -> -> Algorithm steps/pseudocode: -> > **Specify details:** -> -> Output data: -> > **Specify details:** - - -### Code: - -```python -# Code -``` - -#### Specify if any dependencies were added - - - -### Other Notes: - -### Related Issues/PRs: diff --git a/.github/issue_templates/Bug_reporting.md b/.github/issue_templates/Bug_reporting.md deleted file mode 100644 index d2156d95eb..0000000000 --- a/.github/issue_templates/Bug_reporting.md +++ /dev/null @@ -1,23 +0,0 @@ -## Description of the issue - -### Steps to reproduce the issue - - 1. - 2. - 3. - -### Code Snippet: - -```python -# Code -``` - -### Expected behavior (What should happen) - -### Actual behavior (What does happen) - -#### Additional notes - -### Affected areas (code, data, or process) - -### Suggested fix? diff --git a/.github/issue_templates/General_issue.md b/.github/issue_templates/General_issue.md deleted file mode 100644 index 7b344795ab..0000000000 --- a/.github/issue_templates/General_issue.md +++ /dev/null @@ -1,17 +0,0 @@ -### Topic: - -### Description: - -### Requirements - -> **Specify: (optional)** - -### Code Snippet (optional): - - ```python - # Code - ``` - -### Related (optional): - -### Follow-up comments: \ No newline at end of file diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md deleted file mode 100644 index d057cf0f01..0000000000 --- a/.github/pull_request_template.md +++ /dev/null @@ -1,32 +0,0 @@ -# Change Summary - -## Overview - - -## New Dependencies - - -## New Files - -- new file 1 - - description of new file 1's purpose - -## Deleted Files - -- deleted file 1 - - explanation for why file was deleted - -## Updated Files - -- updated file 1 - - description of change 1 in file 1 - - description of change 2 in file 2 -- updated file 2 - - descipriton of change 1 in file 2 - -## Testing - diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e10b187a36..d6b6b30d4c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -28,9 +28,9 @@ jobs: uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} - - uses: Gr1N/setup-poetry@v8 + - uses: Gr1N/setup-poetry@v9 with: - poetry-version: "1.8.0" + poetry-version: "2.3.4" - name: Install dependencies and app @@ -62,9 +62,9 @@ jobs: # Download external data before we run our tests so that # we don't try to download them in parallel poetry run python imap_processing/tests/conftest.py - poetry run pytest -vvv -n auto --color=yes --cov --cov-report=xml + poetry run pytest -vvv -n auto --color=yes --cov --cov-report=xml --log-disable=root else - poetry run pytest -vvv -n auto --color=yes --cov --cov-report=xml -m "not external_kernel and not external_test_data" + poetry run pytest -vvv -n auto --color=yes --cov --cov-report=xml --log-disable=root -m "not external_kernel and not external_test_data" fi - name: Upload coverage reports to Codecov diff --git a/.gitignore b/.gitignore index 45b31bbef0..d431ffa153 100644 --- a/.gitignore +++ b/.gitignore @@ -4,8 +4,6 @@ data/imap/ *.xlsx *.xls -# poetry dynamic version creation -_version.py # Documentation ignore docs/source/**/generated @@ -37,6 +35,8 @@ share/python-wheels/ .installed.cfg *.egg MANIFEST +.python-version +_version.py # PyInstaller # Usually these files are written by a python script from a template @@ -106,13 +106,6 @@ ipython_config.py # 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 - # pdm # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. #pdm.lock @@ -175,9 +168,13 @@ cython_debug/ # VSCode .vscode/ +# Claude +.claude/ + # Data that is downloaded data/ test_data/ +/imap_processing/tests/glows/validation_data/ /imap_processing/tests/mag/validation/L1c/T013/mag-l1b-l1c-t013-magi-burst-in.csv /imap_processing/tests/mag/validation/L1c/T013/mag-l1b-l1c-t013-mago-burst-in.csv /imap_processing/tests/mag/validation/L1c/T014/mag-l1b-l1c-t014-magi-burst-in.csv @@ -190,9 +187,10 @@ test_data/ /imap_processing/tests/mag/validation/L2/T021/mag-l1bc-l2-t021-mago-burst-in.csv /imap_processing/tests/swe/l1_validation/ /imap_processing/tests/swe/l2_validation/ - +imap_processing/tests/lo/test_cdfs/imap_lo_l1c_pset_20260101-repoint01261_v001.cdf +/imap_processing/tests/glows/validation_data/combined_de_l1a.csv # Ignore specific SPICE kernels that get downloaded from NAIF automatically for tests # marked with @pytest.mark.external_kernel **/de440*.bsp **/pck0001*.tpc -**/earth_*_combined.bpc \ No newline at end of file +**/earth_*_combined.bpc diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 1568f9a567..92dcb9837b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,46 +1,45 @@ ci: autofix_prs: false - autoupdate_schedule: 'quarterly' + autoupdate_schedule: "quarterly" skip: [poetry-lock] repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v5.0.0 + rev: v6.0.0 hooks: - - id: check-added-large-files - args: ['--maxkb=1000'] - - id: detect-aws-credentials - args: [--allow-missing-credentials] - - id: detect-private-key - - id: mixed-line-ending - - id: trailing-whitespace - exclude: ^imap_processing/tests/.*\.dat$ - - id: no-commit-to-branch - args: [--branch, main, --branch, dev] + - id: check-added-large-files + args: ["--maxkb=1000"] + - id: detect-aws-credentials + args: [--allow-missing-credentials] + - id: detect-private-key + - id: mixed-line-ending + - id: trailing-whitespace + exclude: ^imap_processing/tests/.*\.(dat|tf)$ + - id: no-commit-to-branch + args: [--branch, main, --branch, dev] - repo: https://github.com/astral-sh/ruff-pre-commit - rev: 'v0.12.8' + rev: "v0.15.2" hooks: - - id: ruff-check - args: [--fix] - - id: ruff-format + - id: ruff-check + args: [--fix] + - id: ruff-format - repo: https://github.com/codespell-project/codespell rev: v2.4.1 hooks: - id: codespell files: ^.*\.(py|md|rst|yml)$ - repo: https://github.com/python-poetry/poetry - rev: '1.8.0' # add version here + rev: "2.3.4" hooks: - id: poetry-check - id: poetry-lock - args: [--no-update] - repo: https://github.com/numpy/numpydoc - rev: 'v1.9.0' + rev: "v1.9.0" hooks: - id: numpydoc-validation - exclude: '^imap_processing/tests/|.*test.*' + exclude: "^imap_processing/tests/|.*test.*" - repo: https://github.com/pre-commit/mirrors-mypy - rev: 'v1.16.1' + rev: "v1.18.2" hooks: - id: mypy exclude: .*(tests|docs).* - additional_dependencies: [ numpy==1.26.4 ] + additional_dependencies: [numpy==2.3.5] diff --git a/README.md b/README.md index dfe695d2dd..360958412f 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # IMAP (Interstellar Mapping and Acceleration Probe) -[![All Contributors](https://img.shields.io/badge/all_contributors-13-orange.svg?style=flat-square)](#contributors-) +[![All Contributors](https://img.shields.io/badge/all_contributors-17-orange.svg?style=flat-square)](#contributors-) [![readthedocs](https://readthedocs.org/projects/imap-processing/badge/?version=latest)](https://imap-processing.readthedocs.io/en/latest/) @@ -18,7 +18,7 @@ Join the IMAP Git repository to be part of an exciting scientific endeavor, cont [IMAP Processing Documentation](https://imap-processing.readthedocs.io/en/latest/) -[Getting started](https://imap-processing.readthedocs.io/en/latest/development-guide/getting-started.html) +[Getting started](https://imap-processing.readthedocs.io/en/latest/development/index.html) # Credits [LASP (Laboratory of Atmospheric and Space Physics)](https://lasp.colorado.edu/) @@ -32,27 +32,28 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - + + + +
Greg Lucas
Greg Lucas

Tenzin Choedon
Tenzin Choedon

Laura Sandoval
Laura Sandoval

Sean Hoyt
Sean Hoyt

Gabriel Moraga
Gabriel Moraga

Matthew Bourque
Matthew Bourque

Maxine Hartnett
Maxine Hartnett

Greg Lucas
Greg Lucas

πŸ’» πŸ“– πŸ€” πŸš‡ 🚧 πŸ‘€
Tenzin Choedon
Tenzin Choedon

πŸ’» πŸ€” πŸš‡ πŸ’‘ 🚧 πŸ‘€ πŸ“–
Laura Sandoval
Laura Sandoval

πŸ‘€ πŸ’» πŸš‡ πŸ€”
Sean Hoyt
Sean Hoyt

πŸ’» πŸ€” πŸš‡ πŸ‘€ πŸ“– 🚧
Gabriel M.
Gabriel M.

πŸ’» πŸ€” πŸš‡ πŸ‘€ 🚧 πŸ“–
Matthew Bourque
Matthew Bourque

πŸ’» πŸ“– πŸ€” πŸš‡ πŸ‘€ 🚧
Maxine Hartnett
Maxine Hartnett

πŸ’» πŸ€” πŸš‡ πŸ‘€ πŸ“– 🚧
Bryan Harter
Bryan Harter

Marek Strumik
Marek Strumik

Veronica Martinez
Veronica Martinez

Tim Plummer
Tim Plummer

Daralynn Rhode
Daralynn Rhode

Ana Manica
Ana Manica

Luisa Coakley
Luisa Coakley

Bryan Harter
Bryan Harter

πŸ’» πŸ“–
mstrumik
mstrumik

πŸ‘€
Veronica Martinez
Veronica Martinez

πŸ‘€ πŸ’»
Tim Plummer
Tim Plummer

πŸ‘€ πŸ’»
Daralynn Rhode
Daralynn Rhode

πŸ’» πŸ“–
anamanica
anamanica

πŸ’» πŸ“–
Luisa Coakley
Luisa Coakley

πŸ’» πŸ“–
Nat Kerman
Nat Kerman

Tori Marbois
Tori Marbois

Nat Kerman
Nat Kerman

πŸ’» πŸ“–
Tori Marbois
Tori Marbois

πŸ’» πŸ“–
Michele Facchinelli
Michele Facchinelli

πŸ’» ⚠️
diff --git a/codecov.yml b/codecov.yml index 00a51990ca..e0fe79e91b 100644 --- a/codecov.yml +++ b/codecov.yml @@ -14,3 +14,6 @@ coverage: # Ignore coverage of fixtures ignore: - "**/conftest.py" + - "**/test_spacecraft_pset.py" + - "**/test_helio_pset.py" + - "**/*make_helio_index_maps.py" diff --git a/docs/source/code-documentation/cdf.rst b/docs/source/algorithm-code-documentation/cdf.rst similarity index 100% rename from docs/source/code-documentation/cdf.rst rename to docs/source/algorithm-code-documentation/cdf.rst diff --git a/docs/source/code-documentation/codice.rst b/docs/source/algorithm-code-documentation/codice.rst similarity index 86% rename from docs/source/code-documentation/codice.rst rename to docs/source/algorithm-code-documentation/codice.rst index 18f5a2f2e8..fdcd733adb 100644 --- a/docs/source/code-documentation/codice.rst +++ b/docs/source/algorithm-code-documentation/codice.rst @@ -8,21 +8,19 @@ CoDICE This is the CoDICE (Compact Dual Ion Composition Experiment) Instrument module, which contains the code for processing data from the CoDICE instrument. -The processing code to decommutate the CCSDS packets (L0) and create L1a data -products can be found below: +The processing code to decommutate the CCSDS packets (L0) and create higher level data products can be found below: .. autosummary:: :toctree: generated/ :template: autosummary.rst :recursive: - codice_l0 codice_l1a codice_l1b codice_l2 -The modules below contain various utility classes and functions to support L0 -and L1a processing: +The modules below contain various utility classes and functions to support L0 to +L2 processing: .. autosummary:: :toctree: generated/ diff --git a/docs/source/code-documentation/glows.rst b/docs/source/algorithm-code-documentation/glows.rst similarity index 100% rename from docs/source/code-documentation/glows.rst rename to docs/source/algorithm-code-documentation/glows.rst diff --git a/docs/source/code-documentation/hi.rst b/docs/source/algorithm-code-documentation/hi.rst similarity index 100% rename from docs/source/code-documentation/hi.rst rename to docs/source/algorithm-code-documentation/hi.rst diff --git a/docs/source/code-documentation/hit.rst b/docs/source/algorithm-code-documentation/hit.rst similarity index 100% rename from docs/source/code-documentation/hit.rst rename to docs/source/algorithm-code-documentation/hit.rst diff --git a/docs/source/code-documentation/idex.rst b/docs/source/algorithm-code-documentation/idex.rst similarity index 100% rename from docs/source/code-documentation/idex.rst rename to docs/source/algorithm-code-documentation/idex.rst diff --git a/docs/source/code-documentation/index.rst b/docs/source/algorithm-code-documentation/index.rst similarity index 91% rename from docs/source/code-documentation/index.rst rename to docs/source/algorithm-code-documentation/index.rst index 39b49150f8..98f1f5813c 100644 --- a/docs/source/code-documentation/index.rst +++ b/docs/source/algorithm-code-documentation/index.rst @@ -1,7 +1,7 @@ -.. _code-documentation: +.. _algorithm-code-documentation: -Code Documentation -================== +Algorithm Code Documentation +============================ .. currentmodule:: imap_processing @@ -15,7 +15,6 @@ Instruments .. toctree:: :maxdepth: 1 - cli codice glows hi @@ -26,6 +25,7 @@ Instruments swapi swe ultra + quicklooks Utilities --------- @@ -62,12 +62,4 @@ variable ``IMAP_DATA_DIR``. For example to use a temporary directory imap_cli --instrument codice --level 1 --data-dir /tmp/imap-data # or equivalently with an environment variable - IMAP_DATA_DIR=/tmp/imap-data imap_cli --instrument codice --level 1 - -Tools ------ - -.. toctree:: - :maxdepth: 2 - - tools/index \ No newline at end of file + IMAP_DATA_DIR=/tmp/imap-data imap_cli --instrument codice --level 1 \ No newline at end of file diff --git a/docs/source/code-documentation/lo.rst b/docs/source/algorithm-code-documentation/lo.rst similarity index 100% rename from docs/source/code-documentation/lo.rst rename to docs/source/algorithm-code-documentation/lo.rst diff --git a/docs/source/code-documentation/mag.rst b/docs/source/algorithm-code-documentation/mag.rst similarity index 100% rename from docs/source/code-documentation/mag.rst rename to docs/source/algorithm-code-documentation/mag.rst diff --git a/docs/source/algorithm-code-documentation/quicklooks.rst b/docs/source/algorithm-code-documentation/quicklooks.rst new file mode 100644 index 0000000000..7cef5e29a9 --- /dev/null +++ b/docs/source/algorithm-code-documentation/quicklooks.rst @@ -0,0 +1,154 @@ +Quicklook Generation +=========================== + +This document provides a high-level overview of the workflow and usage +of the ``QuicklookGenerator`` system. It is intended to help developers +understand how quicklook plots are produced from IMAP instrument data files. + +Overview +-------- + +Each instrument implements its own plotting logic +while sharing a common initialization, data-loading, +and dispatch workflow. + +The system is built around four major components: + +1. **Dataset loading** – converting a CDF file into an ``xarray.Dataset``. +2. **Instrument detection** – determining the correct quicklook + generator class. +3. **Abstract quicklook interface** – common API for all instruments. +4. **Instrument-specific subclasses** – actual plotting implementations. + +Workflow +-------- + +1. **User supplies a CDF file path**:: + + quicklook = get_instrument_quicklook("path/to/file.cdf") + +2. **The filename is parsed** using + ``ScienceFilePath.extract_filename_components`` to extract the + ``instrument`` field. + +3. **The correct Quicklook subclass is selected** via the + ``QuicklookGeneratorType`` enum. For example:: + + MAG β†’ MagQuicklookGenerator + + The pattern continues for each individual instrument. + +4. **The chosen class is instantiated**, and the constructor: + + - Loads the dataset using ``dataset_into_xarray``. + - Stores instrument metadata (such as the instrument name). + - Initializes plotting-related attributes. + +5. **The user calls** ``two_dimensional_plot(variable="...")``. + This method is implemented by each subclass and acts as a routing + mechanism that decides *which* quicklook plot to generate. + + Example for MAG:: + + mag_ql = MagQuicklookGenerator("imap_mag_20250101_v01.cdf") + mag_ql.two_dimensional_plot(variable="mag sensor co-ord") + +6. **The requested plot function runs**, accessing data from the internal + ``xarray.Dataset`` and generating figures using Matplotlib. + +7. **Plots are displayed**, and the workflow ends. No data is returnedβ€” + the quicklook system produces visualizations only. + +Core Components +--------------- + +Abstract Base Class: ``QuicklookGenerator`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The ``QuicklookGenerator`` abstract base class provides: + +- Unified dataset loading via ``dataset_into_xarray``. +- Common metadata attributes (instrument, title, axis labels, etc.). +- Basic validation to ensure that a dataset is present. +- An abstract method ``two_dimensional_plot``, which each instrument + subclass must implement as a dispatch mechanism. + +Time & Coordinate Handling +-------------------------- + +Instrument data often stores time in **J2000 nanoseconds**. These values +are converted to UTC timestamps using:: + + convert_j2000_to_utc(time_array) + +This conversion internally uses: + +- A fixed epoch: ``2000-01-01 11:58:55.816`` +- NumPy ``timedelta64`` arithmetic +- Output as ``datetime64[ns]`` UTC timestamps + +This routine is used across all instruments providing an ``epoch`` field. + +Instrument Dispatch Logic +------------------------- + +Users should begin quicklook generation by calling:: + + quicklook = get_instrument_quicklook(filename) + +This function: + +1. Extracts the instrument identifier from the filename. +2. Uses ``QuicklookGeneratorType`` to map the instrument to a class. +3. Returns an instantiated quicklook object. + +Example:: + + >>> ql = get_instrument_quicklook("imap_swapi_20250101_v02.cdf") + >>> ql.two_dimensional_plot("count rates") + +Adding Support for New Instruments +---------------------------------- + +To extend the quicklook system: + +1. Create a new subclass:: + + class NewInstQuicklookGenerator(QuicklookGenerator): + ... + +2. Implement ``two_dimensional_plot`` as a dispatch method. +3. Add plot functions as needed. +4. Register the class in the ``QuicklookGeneratorType`` enum. +5. Ensure that ``ScienceFilePath.extract_filename_components`` correctly + identifies the instrument. + +Instrument Team Support +----------------------- + +To implement a new instrument-specific quicklook, instrument teams must +provide a minimal set of information that defines what plots are +required and how the underlying data should be interpreted. + +Required Information +~~~~~~~~~~~~~~~~~~~~ + +1. **List of quicklook plots** + - A high-level description of each plot to be generated. + - Whether each plot is 1-D (line), 2-D (spectrogram), or multi-panel. + +2. **Variables required for each plot** + - CDF variable names. + - Which CDF files contain the required variables. + +3. **Time-axis requirements (if applicable)** + - Desired time range (full file, event-based selection, rolling window). + +4. **Plot formatting preferences** + - Preferred units or scaling (linear, log). + - Desired titles, axis labels, and annotations. + +5. **Special processing rules** + - Required calibrations or unit conversions. + - Masking rules for invalid ranges or quality flags. + - Any filtering or smoothing applied before plotting. diff --git a/docs/source/code-documentation/spice.rst b/docs/source/algorithm-code-documentation/spice.rst similarity index 100% rename from docs/source/code-documentation/spice.rst rename to docs/source/algorithm-code-documentation/spice.rst diff --git a/docs/source/code-documentation/swapi.rst b/docs/source/algorithm-code-documentation/swapi.rst similarity index 100% rename from docs/source/code-documentation/swapi.rst rename to docs/source/algorithm-code-documentation/swapi.rst diff --git a/docs/source/code-documentation/swe.rst b/docs/source/algorithm-code-documentation/swe.rst similarity index 100% rename from docs/source/code-documentation/swe.rst rename to docs/source/algorithm-code-documentation/swe.rst diff --git a/docs/source/code-documentation/ultra.rst b/docs/source/algorithm-code-documentation/ultra.rst similarity index 92% rename from docs/source/code-documentation/ultra.rst rename to docs/source/algorithm-code-documentation/ultra.rst index 7da27bb500..070cf3026f 100644 --- a/docs/source/code-documentation/ultra.rst +++ b/docs/source/algorithm-code-documentation/ultra.rst @@ -35,7 +35,7 @@ Level 1B Processing Code: l1b.ultra_l1b l1b.badtimes - l1b.cullingmask + l1b.goodtimes l1b.de l1b.extendedspin @@ -47,5 +47,5 @@ Level 1C Processing Code: :recursive: l1c.ultra_l1c - l1c.histogram - l1c.spacecraft_pset \ No newline at end of file + l1c.spacecraft_pset + l1c.helio_pset \ No newline at end of file diff --git a/docs/source/external-tools/cdf/cdf_introduction.rst b/docs/source/cdf-metadata/cdf_introduction.rst similarity index 99% rename from docs/source/external-tools/cdf/cdf_introduction.rst rename to docs/source/cdf-metadata/cdf_introduction.rst index bc8f963882..c814d37ab7 100644 --- a/docs/source/external-tools/cdf/cdf_introduction.rst +++ b/docs/source/cdf-metadata/cdf_introduction.rst @@ -32,7 +32,7 @@ The internal format of CDF files are described in the `cdf specification APID IntEnum class diff --git a/docs/source/code-documentation/tools/imap-data-access.rst b/docs/source/data-access/imap-data-access.rst similarity index 100% rename from docs/source/code-documentation/tools/imap-data-access.rst rename to docs/source/data-access/imap-data-access.rst diff --git a/docs/source/data-access/index.rst b/docs/source/data-access/index.rst index 80bc4b5ec8..d0c632ba01 100644 --- a/docs/source/data-access/index.rst +++ b/docs/source/data-access/index.rst @@ -1,4 +1,4 @@ -.. _data-access-api: +.. _data-access: Data Access API =============== @@ -7,13 +7,19 @@ The `imap-data-access `_ +repository. That script can add, remove, and list current keys. To add a key, +provide the name and email of the associated user or account and receive an API +key to give to the external user for access. + +Scope Options +^^^^^^^^^^^^^ + +When creating or updating API keys, you can specify different scopes to control +access: + +- ``full``: Full read and write access to all endpoints and data +- ``read``: Read-only access. Can query and download data but cannot upload or + modify files + +Usage Examples +^^^^^^^^^^^^^^ + +.. code-block:: bash + + python sds_data_manager/lambda_code/authorization/manage_api_keys.py list + python sds_data_manager/lambda_code/authorization/manage_api_keys.py add + python sds_data_manager/lambda_code/authorization/manage_api_keys.py remove + python sds_data_manager/lambda_code/authorization/manage_api_keys.py update_permission + + # Example: add a user with full access + AWS_PROFILE=imap-sdc-dev AWS_DEFAULT_REGION=us-west-2 \ + python sds_data_manager/lambda_code/authorization/manage_api_keys.py \ + add "First Last" "user@example.com" "full" + + # Example: add a user with read-only access + AWS_PROFILE=imap-sdc-dev AWS_DEFAULT_REGION=us-west-2 \ + python sds_data_manager/lambda_code/authorization/manage_api_keys.py \ + add "Read User" "reader@example.com" "read" File Validation --------------- @@ -222,7 +268,7 @@ REST API Specification .. code-block:: bash - curl -X GET -H "Accept: application/json" https://api.dev.imap-mission.com/upload/imap/swe/l0/2024/01/imap_swe_l0_sci_20240105_20240105_v00-01.pkts + curl -X GET -H "Accept: application/json" https://api.imap-mission.com/upload/imap/swe/l0/2024/01/imap_swe_l0_sci_20240105_20240105_v00-01.pkts **Possible Responses:** @@ -247,7 +293,7 @@ REST API Specification .. code-block:: bash - curl -X GET -H "Accept: application/json" https://api.dev.imap-mission.com/download/imap/swe/l0/2024/01/imap_swe_l0_sci_20240105_20240105_v00-01.pkts + curl -X GET -H "Accept: application/json" https://api.imap-mission.com/download/imap/swe/l0/2024/01/imap_swe_l0_sci_20240105_20240105_v00-01.pkts **Possible Responses:** @@ -265,7 +311,7 @@ REST API Specification .. code-block:: bash - curl -X GET -H "Accept: application/json" https://api.dev.imap-mission.com/query?instrument=swe&data_level=l0&descriptor=sci&start_date=20240105&end_date=20240105&extension=pkts + curl -X GET -H "Accept: application/json" https://api.imap-mission.com/query?instrument=swe&data_level=l0&descriptor=sci&start_date=20240105&end_date=20240105&extension=pkts **Possible Responses:** @@ -274,14 +320,10 @@ REST API Specification {"statusCode": 200, "headers": {"Content-Type": "application/json", "Access-Control-Allow-Origin": "*"}, "body": [{"file_path": "imap/swe/l0/2024/01/imap_swe_l0_sci_20240105_20240105_v00-05.pkts", "instrument": "swe", "data_level": "l0", "descriptor": "sci", "start_date": "20240105", "end_date": "20240105", "version": "v00-05", "extension": "pkts"}]} {"statusCode": 400, "headers": {"Content-Type": "application/json", "Access-Control-Allow-Origin": "*"}, "body": " is not a valid query parameter. Valid query parameters are: ['file_path', 'instrument', 'data_level', 'descriptor', 'start_date', 'end_date', 'version', 'extension']"} - -Other pages ------------ - .. toctree:: - :maxdepth: 1 - - calibration-files - data-dependency - naming-conventions + :maxdepth: 1 + :hidden: + generated/imap_data_access.io.download + generated/imap_data_access.io.query + generated/imap_data_access.io.upload diff --git a/docs/source/data-access/openapi.yml b/docs/source/data-access/openapi.yml index a59a191402..4598550542 100644 --- a/docs/source/data-access/openapi.yml +++ b/docs/source/data-access/openapi.yml @@ -1,7 +1,7 @@ openapi: 3.0.0 servers: - - description: Development IMAP SDC Server -host: https://api.dev.imap-mission.com/ + - description: Production IMAP SDC Server +host: https://api.imap-mission.com/ info: version: "0.1.0" title: IMAP SDC API @@ -229,4 +229,181 @@ paths: type: array items: type: string - format: uri \ No newline at end of file + format: uri + + '/spice-query': + get: + tags: + - SPICE Query + summary: Query for SPICE kernel metadata + operationId: spice-query + parameters: + - in: query + name: file_name + description: | + The name of a specific SPICE kernel file (e.g. ``naif0012.tls``). + required: false + schema: + type: string + - in: query + name: start_time + description: | + Coverage start time in TDB seconds since J2000. Returns kernels whose + coverage ends on or after this time. + required: false + schema: + type: string + - in: query + name: end_time + description: | + Coverage end time in TDB seconds since J2000. Returns kernels whose + coverage begins on or before this time. + required: false + schema: + type: string + - in: query + name: type + description: | + The SPICE kernel type to filter by. Accepted values are: + ``leapseconds``, ``planetary_constants``, ``imap_frames``, + ``science_frames``, ``spacecraft_clock``, ``earth_attitude``, + ``planetary_ephemeris``, ``ephemeris_reconstructed``, + ``ephemeris_nominal``, ``ephemeris_predicted``, ``ephemeris_90days``, + ``ephemeris_long``, ``ephemeris_launch``, ``attitude_history``, + ``attitude_predict``, ``pointing_attitude``. + required: false + schema: + type: string + - in: query + name: latest + description: | + If ``True``, only return the latest version of each kernel matching + the other query parameters. + required: false + schema: + type: string + - in: query + name: start_ingest_date + description: | + Filter results to kernels ingested on or after this date, in the + format ``YYYYMMDD``. + required: false + schema: + type: string + - in: query + name: end_ingest_date + description: | + Filter results to kernels ingested on or before this date, in the + format ``YYYYMMDD``. + required: false + schema: + type: string + responses: + '200': + description: Successful query β€” returns a list of SPICE kernel metadata objects + content: + application/json: + schema: + type: array + items: + type: object + '400': + description: Invalid query parameter or parameter value + content: + application/json: + schema: + type: string + + '/metakernel': + get: + tags: + - SPICE Query + summary: Retrieve a metakernel or list of SPICE kernel filenames for a time range + operationId: metakernel + parameters: + - in: query + name: start_time + description: | + Coverage start time. Accepts either TDB seconds since J2000 or a date + string in the format ``YYYYMMDD``. + required: true + schema: + type: string + - in: query + name: end_time + description: | + Coverage end time. Accepts either TDB seconds since J2000 or a date + string in the format ``YYYYMMDD``. + required: true + schema: + type: string + - in: query + name: spice_path + description: | + Root path for the SPICE directory. This path is prepended to all kernel file + locations in the returned metakernel. If omitted the paths are left + relative. Only applicable if ``list_files``` is ``False``. + required: false + schema: + type: string + - in: query + name: list_files + description: | + If ``True``, return only a list of kernel filenames instead of a full + metakernel file. + required: false + schema: + type: string + - in: query + name: require_coverage + description: | + If ``True``, the request will fail with a HTTP ``422`` status if there + are any gaps in coverage for the requested time range. + required: false + schema: + type: string + - in: query + name: file_types + description: | + Comma-separated list of kernel types to include. If omitted, all + available kernel types are included. Accepted values are: + ``leapseconds``, ``planetary_constants``, ``imap_frames``, + ``science_frames``, ``spacecraft_clock``, ``earth_attitude``, + ``planetary_ephemeris``, ``ephemeris_reconstructed``, + ``ephemeris_nominal``, ``ephemeris_predicted``, ``ephemeris_90days``, + ``ephemeris_long``, ``ephemeris_launch``, ``attitude_history``, + ``attitude_predict``, ``pointing_attitude``. + required: false + schema: + type: string + responses: + '200': + description: | + Successful response. Returns a metakernel file (text/plain) when + ``list_files`` is ``False`` (default), or a JSON array of kernel + filenames when ``list_files`` is ``True``. + content: + text/plain: + schema: + type: string + application/json: + schema: + type: array + items: + type: string + '404': + description: No kernel files found for the requested time range + content: + application/json: + schema: + type: string + '422': + description: | + Coverage gaps detected when ``require_coverage=True``. The response + body contains a list of the gap intervals. + content: + application/json: + schema: + type: array + items: + type: object \ No newline at end of file diff --git a/docs/source/data-access/spice-files.rst b/docs/source/data-access/spice-files.rst new file mode 100644 index 0000000000..2a840ddb6e --- /dev/null +++ b/docs/source/data-access/spice-files.rst @@ -0,0 +1,220 @@ +SPICE Files +=========== + +The IMAP SDC provides two REST API endpoints for accessing SPICE kernel data: +``/spice-query`` for querying kernel metadata and ``/metakernel`` for retrieving +a ready-to-use metakernel (or a list of kernel filenames) that covers a +requested time range. + +Both endpoints are accessible from the base URL: ``https://api.imap-mission.com`` + +.. _spice-query-endpoint: + +SPICE Query +----------- + +The ``/spice-query`` endpoint returns metadata for SPICE kernels stored in the +SDC database. Results can be filtered by kernel type, time range, ingestion +date, or filename. + +.. openapi:: openapi.yml + :group: + :include: /spice-query + +**Example Usage:** + +.. code-block:: bash + + # Query for all attitude_history kernels covering a time range + curl -X GET -H "Accept: application/json" \ + "https://api.imap-mission.com/spice-query?start_time=315576066&end_time=4575787269&type=attitude_history" + + # Query for a specific kernel by filename + curl -X GET -H "Accept: application/json" \ + "https://api.imap-mission.com/spice-query?file_name=naif0012.tls" + + # Query for the latest version of the spacecraft_clock kernel + curl -X GET -H "Accept: application/json" \ + "https://api.imap-mission.com/spice-query?type=spacecraft_clock&latest=True" + +**Possible Responses:** + +.. code-block:: json + + [ + { + "file_name": "ck/imap_2025_274_2025_276_001.ah.bc", + "file_root": "imap_2025_274_2025_276_.ah.bc", + "kernel_type": "attitude_history", + "version": 1, + "min_date_j2000": 812631669.2765242, + "max_date_j2000": 812725268.1910387, + "file_intervals_j2000": [ + [ + 812631669.2765242, + 812725268.1910387 + ] + ], + "min_date_datetime": "2025-10-01, 23:00:00", + "max_date_datetime": "2025-10-03, 00:59:59", + "file_intervals_datetime": [ + [ + "2025-10-01T23:00:00.094178+00:00", + "2025-10-03T00:59:59.008694+00:00" + ] + ], + "min_date_sclk": "1/0497055600:00000", + "max_date_sclk": "1/0497149199:00000", + "file_intervals_sclk": [ + [ + "1/0497055600:00000", + "1/0497149199:00000" + ] + ], + "sclk_kernel": "/tmp/naif0012.tls", + "lsk_kernel": "/tmp/imap_sclk_0147.tsc", + "ingestion_date": "2026-04-06, 23:57:54", + "timestamp": 1775519874 + }, + ] + +.. code-block:: json + + {"statusCode": 400, "body": " is not a valid query parameter. Valid query parameters are: ['file_name', 'start_time', 'end_time', 'type', 'latest', 'start_ingest_date', 'end_ingest_date']"} + +.. _metakernel-endpoint: + +Metakernel +---------- + +The ``/metakernel`` endpoint builds and returns a SPICE metakernel covering a +requested time range. By default the response is a ``.tm`` metakernel file that +can be loaded directly with ``spiceypy.furnsh()``. Passing ``list_files=True`` +returns a JSON list of kernel filenames instead. + +.. openapi:: openapi.yml + :group: + :include: /metakernel + +**Example Usage:** + +.. code-block:: bash + + # Retrieve a metakernel covering a time range for selected kernel types + curl -X GET -H "Accept: application/json" \ + "https://api.imap-mission.com/metakernel?start_time=797949057&end_time=798035454&file_types=leapseconds,attitude_history" + + # Get only a list of kernel filenames (no metakernel wrapper) + curl -X GET -H "Accept: application/json" \ + "https://api.imap-mission.com/metakernel?start_time=797949057&end_time=798035454&file_types=leapseconds,spacecraft_clock&list_files=True" + + # Retrieve a metakernel with a custom spice_path prefix in the output + curl -X GET -H "Accept: application/json" \ + "https://api.imap-mission.com/metakernel?start_time=797949057&end_time=798035454&spice_path=/my/path/imap" + +**Possible Responses:** + +Metakernel file (default, ``list_files`` omitted or ``False``): + +.. code-block:: text + + \begintext + + This is the most up to date Metakernel as of + 2026-04-13 18:19:21.912444+00:00. + + This attempts to cover data from + 797949057 to 798035454 + seconds since J2000. + + \begindata + + KERNELS_TO_LOAD = ( 'lsk/naif0012.tls', + 'fk/imap_130.tf', + 'fk/imap_science_120.tf', + 'sclk/imap_sclk_0147.tsc', + 'spk/de440.bsp' + ) + + \begintext + +List of filenames (``list_files=True``): + +.. code-block:: json + + ["naif0012.tls", "imap_130.tf", "imap_science_120.tf", "imap_sclk_0147.tsc", "de440.bsp"] + +Coverage gap error (``require_coverage=True`` and gaps exist): + +.. code-block:: json + + { + "statusCode": 422, + "body": { + "leapseconds_category": [], + "planetary_constants_category": [], + "imap_frames_category": [], + "science_frames_category": [], + "spacecraft_clock_category": [], + "earth_attitude_category": [], + "planetary_ephemeris_category": [], + "spacecraft_ephemeris_category": [[797990001, 798035454]], + "spacecraft_attitude_category": [[797949057, 797990000]], + "pointing_attitude_category": [] + } + } + +Each key is a SPICE kernel category. Empty lists indicate full coverage; non-empty +lists contain one or more ``[start_time, end_time]`` intervals (in TDB seconds +since J2000) where no kernel was found. + +No files found: + +.. code-block:: json + + {"statusCode": 404, "body": "No files found."} + +Kernel Types +------------ + +The following kernel type values are accepted by both the ``type`` parameter of +``/spice-query`` and the ``file_types`` parameter of ``/metakernel``: + +.. list-table:: + :header-rows: 1 + :widths: 30 70 + + * - Kernel Type + - Description + * - ``leapseconds`` + - Leapseconds kernel (LSK) + * - ``planetary_constants`` + - Planetary constants kernel (PCK) + * - ``imap_frames`` + - IMAP spacecraft frames kernel (FK) + * - ``science_frames`` + - Science instrument frames kernel (FK) + * - ``spacecraft_clock`` + - Spacecraft clock kernel (SCLK) + * - ``earth_attitude`` + - Earth attitude kernel + * - ``planetary_ephemeris`` + - Planetary ephemeris kernel (SPK) + * - ``ephemeris_reconstructed`` + - Reconstructed spacecraft ephemeris (SPK) + * - ``ephemeris_nominal`` + - Nominal spacecraft ephemeris (SPK) + * - ``ephemeris_predicted`` + - Predicted spacecraft ephemeris (SPK) + * - ``ephemeris_90days`` + - 90-day spacecraft ephemeris (SPK) + * - ``ephemeris_long`` + - Long-term spacecraft ephemeris (SPK) + * - ``ephemeris_launch`` + - Launch ephemeris (SPK) + * - ``attitude_history`` + - Historical spacecraft attitude kernel (CK) + * - ``attitude_predict`` + - Predicted spacecraft attitude kernel (CK) + * - ``pointing_attitude`` + - Pointing attitude kernel (CK) diff --git a/docs/source/development/cli.rst b/docs/source/development/cli.rst new file mode 100644 index 0000000000..88ffca04f9 --- /dev/null +++ b/docs/source/development/cli.rst @@ -0,0 +1,10 @@ +.. _cli: + +CLI +=== + +.. currentmodule:: imap_processing + +This is the CLI for running IMAP processing per instrument. + +TODO: more information to come in the future. diff --git a/docs/source/data-access/data-dependency.rst b/docs/source/development/data-dependency.rst similarity index 100% rename from docs/source/data-access/data-dependency.rst rename to docs/source/development/data-dependency.rst diff --git a/docs/source/development/doc-overview.rst b/docs/source/development/doc-overview.rst index e4db4e19f3..1824e38ae6 100644 --- a/docs/source/development/doc-overview.rst +++ b/docs/source/development/doc-overview.rst @@ -1,3 +1,5 @@ +.. _doc-overview: + Contributing to Documentation ============================= diff --git a/docs/source/development/docker.rst b/docs/source/development/docker.rst index 48003cc832..f5dd65ca80 100644 --- a/docs/source/development/docker.rst +++ b/docs/source/development/docker.rst @@ -1,5 +1,7 @@ +.. _docker: + Docker Workflow ----------------- +=============== This page describes how to build and run a Docker Image Locally and in AWS. diff --git a/docs/source/development/getting-started.rst b/docs/source/development/getting-started.rst index e14ec9c808..5d8d1bdcc2 100644 --- a/docs/source/development/getting-started.rst +++ b/docs/source/development/getting-started.rst @@ -9,7 +9,7 @@ Installing requirements Poetry Installation and Setup ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -``imap-processing`` uses :ref:`poetry-link` for dependency management. Check out our :ref:`style guide ` for more information on specific IMAP Poetry usage. +``imap-processing`` uses :ref:`poetry-link` for dependency management. Check out our :ref:`style guide ` for more information on specific IMAP Poetry usage. If you are upgrading from Poetry 1.x, see :ref:`upgrading-poetry`. If you're running locally, you can install the Python requirements with Poetry. @@ -17,7 +17,7 @@ To setup versioning *(recommended for developers)* .. code-block:: bash - poetry self add poetry-dynamic-versioning + poetry self add "poetry-dynamic-versioning[plugin]" To install without the extras @@ -31,19 +31,85 @@ To install all extras poetry install --all-extras -This will install the dependencies from `poetry.lock`, ensuring that consistent versions are used. Poetry also provides a virtual environment, which you will have to activate. +This will install the dependencies from `poetry.lock`, ensuring that consistent versions are used. +Poetry manages a virtual environment for the project, which you will need to activate. -.. code-block:: bash +.. note:: + + ``poetry shell`` was removed in Poetry 2. Use one of the following to activate + the virtual environment instead: + + .. code-block:: bash + + # Activate via Poetry (outputs the activation command) + source $(poetry env info --path)/bin/activate + + # Or on Windows (PowerShell) + & (poetry env info --path)\Scripts\activate.ps1 + + Alternatively, you can use the ``venv`` module to create and manage your + own virtual environment independently: + + .. code-block:: bash + + python3 -m venv .venv + source .venv/bin/activate + pip install -e ".[dev,test,tools]" + +.. note:: + + Some dependencies include compiled extensions and require system libraries + if no pre-built wheel is available for your platform. If installation fails + with a PEP 517 build error, install the relevant system libraries below and + then re-run the install command. + + **netcdf4** requires the NetCDF-C and HDF5 libraries: + + .. code-block:: bash + + # Debian/Ubuntu + sudo apt-get install -y libnetcdf-dev libhdf5-dev - poetry shell + # macOS (Homebrew) + brew install netcdf hdf5 + **scipy** provides pre-built wheels for Python 3.10–3.13. If you are using + Python 3.14 or later, no wheel is available yet and scipy must be compiled + from source, which requires a Fortran compiler and BLAS/LAPACK. The + simplest fix is to use Python 3.12 or 3.13. + + If you need to build from source, install the following: + + .. code-block:: bash + + # Debian/Ubuntu + sudo apt-get install -y gfortran libopenblas-dev pkg-config + + # macOS (Homebrew) + brew install openblas + + On Apple Silicon (M1/M2/M3), Homebrew installs to ``/opt/homebrew`` rather + than ``/usr/local``, so pkg-config cannot find OpenBLAS automatically. Set + ``PKG_CONFIG_PATH`` before running the install: + + .. code-block:: bash + + export PKG_CONFIG_PATH="/opt/homebrew/opt/openblas/lib/pkgconfig:$PKG_CONFIG_PATH" + + If you do not need the ``test`` extras, you can avoid these system + dependencies entirely by installing without them: + + .. code-block:: bash + + poetry install --extras "dev" In summary, the expected setup of ``Poetry`` for a development environment is: .. code-block:: bash - poetry self add poetry-dynamic-versioning + poetry self add "poetry-dynamic-versioning[plugin]" poetry install --all-extras + source $(poetry env info --path)/bin/activate Using IMAP processing @@ -55,10 +121,5 @@ Our tests are run using pytest: .. code-block:: bash - poetry shell + source $(poetry env info --path)/bin/activate pytest - -Related Information -------------------- - -For more information relating to infrastructure, see `sds-data-manager `_. \ No newline at end of file diff --git a/docs/source/development/git-access-roles.rst b/docs/source/development/git-access-roles.rst new file mode 100644 index 0000000000..d0cf439817 --- /dev/null +++ b/docs/source/development/git-access-roles.rst @@ -0,0 +1,56 @@ +.. _git-access-roles: + +GitHub Access & Permissions Guide +====================================== + +This document outlines the permission levels available in IMAP SDC +repositories. + +Overview +======== + +GitHub provides five repository roles with varying permission levels. +Below we outline the permissions needed to contribute to IMAP SDC repositories. + +--- + +What GitHub Users Can Access +============================= + +Any GitHub user (without invitation) can: + +- βœ… View **public repositories** +- βœ… Fork public repositories +- βœ… Create issues in public repos +- βœ… Comment on public issues +- βœ… Edit titles and descriptions of your own issues +- βœ… Create pull requests +- ❌ **Cannot** add label or assignees, etc to the issues +- ❌ **Cannot** trigger unit test workflows on PRs (requires SDC approval) +- ❌ **Cannot** request reviewers on PRs (SDC must assign reviewers) +- ❌ **Cannot** push code, merge PRs, or modify issues +- ❌ **Cannot** access private repositories + +--- + +Role Permissions & Responsibilities +----------------------------------- +GitHub Read Role +~~~~~~~~~~~~~~~~~ + +Read role should give same permissions as a user without invitation for IMAP SDC public repositories. +These permissions align with IMAP project requirements and are sufficient for most L0 to L3 code +contributors based on project guidelines. + + +Additional GitHub Roles +----------------------- + +Beyond the **GitHub Read** role (which is sufficient for most contributors), GitHub +provides additional permission levels: `Triage`, `Write`, `Maintain`, and `Admin`. +Please read the GitHub's breakdown of these roles and their permissions in the +`GitHub documentation on repository roles `_. + + +**If you need permissions** please contact the IMAP SDC team to request the +appropriate access level for your role. diff --git a/docs/source/development/style-guide/checklist-for-pull-requests.rst b/docs/source/development/git-workflow-and-style-guide/checklist-for-pull-requests.rst similarity index 100% rename from docs/source/development/style-guide/checklist-for-pull-requests.rst rename to docs/source/development/git-workflow-and-style-guide/checklist-for-pull-requests.rst diff --git a/docs/source/development/style-guide/git-and-github-workflow.rst b/docs/source/development/git-workflow-and-style-guide/git-and-github-workflow.rst similarity index 100% rename from docs/source/development/style-guide/git-and-github-workflow.rst rename to docs/source/development/git-workflow-and-style-guide/git-and-github-workflow.rst diff --git a/docs/source/development/git-workflow-and-style-guide/index.rst b/docs/source/development/git-workflow-and-style-guide/index.rst new file mode 100644 index 0000000000..1b91ba9c27 --- /dev/null +++ b/docs/source/development/git-workflow-and-style-guide/index.rst @@ -0,0 +1,20 @@ +.. _git-workflow-and-style-guide: + +GitHub Workflow and Style Guide +================================ + +This section covers best practices for contributing to the IMAP project, including workflow guidelines, code style standards, and security considerations. + +.. toctree:: + :maxdepth: 1 + + checklist-for-pull-requests + Git and GitHub Workflow + poetry-environment + python-coding + python-docstrings + review-standards + security + style-guide + tools-and-library-recommendations + versioning \ No newline at end of file diff --git a/docs/source/development/style-guide/poetry-environment.rst b/docs/source/development/git-workflow-and-style-guide/poetry-environment.rst similarity index 50% rename from docs/source/development/style-guide/poetry-environment.rst rename to docs/source/development/git-workflow-and-style-guide/poetry-environment.rst index e212a592ac..c4c9756e6d 100644 --- a/docs/source/development/style-guide/poetry-environment.rst +++ b/docs/source/development/git-workflow-and-style-guide/poetry-environment.rst @@ -6,18 +6,22 @@ Poetry Environment :ref:`Poetry ` is used for dependency management within this project. To update dependencies, you can either update ``pyproject.toml`` manually, or use ``poetry add ``. -If you do add dependencies, please make sure you define the version numbers mindfully. The best way to do this is to use -`caret notation `_ to allow for minor -version updates. For example, if you have tested the code using numpy version ``1.24.2``, the best way to specify the -dependency is to allow for updates to the right most version number: +If you do add dependencies, please make sure you define the version numbers mindfully. The required syntax depends on +which section of ``pyproject.toml`` you are editing: -:: +* **``[project] dependencies``** (main runtime deps) and **``[project.optional-dependencies]``** (extras) use + `PEP 508 `_ specifiers. For example, if you have tested with numpy + ``1.24.2`` and want to allow patch and minor updates up to the next major version:: - numpy = "^1.24" + "numpy>=1.24,<2" -This will allow for patches for security reasons without upgrading to ``1.25`` or beyond. Use your best judgement for -when packages can upgrade automatically, but try and avoid specifying only one specific version unless it is absolutely -required. +* **``[tool.poetry.group.*]``** sections (dev/test groups used only by Poetry) may continue to use + `Poetry caret notation `_:: + + numpy = "^1.24" + + Both forms allow updates to the rightmost non-zero version component. Use your best judgement for when packages can + upgrade automatically, but try to avoid pinning a single exact version unless it is absolutely required. The ``poetry.lock`` file contains the existing dependencies for the project. These are the dependencies that you should install to ensure you're getting the accepted versions for every package. If the ``poetry.lock`` file is not up-to-date, diff --git a/docs/source/development/style-guide/python-coding.rst b/docs/source/development/git-workflow-and-style-guide/python-coding.rst similarity index 100% rename from docs/source/development/style-guide/python-coding.rst rename to docs/source/development/git-workflow-and-style-guide/python-coding.rst diff --git a/docs/source/development/style-guide/python-docstrings.rst b/docs/source/development/git-workflow-and-style-guide/python-docstrings.rst similarity index 100% rename from docs/source/development/style-guide/python-docstrings.rst rename to docs/source/development/git-workflow-and-style-guide/python-docstrings.rst diff --git a/docs/source/development/style-guide/review-standards.rst b/docs/source/development/git-workflow-and-style-guide/review-standards.rst similarity index 100% rename from docs/source/development/style-guide/review-standards.rst rename to docs/source/development/git-workflow-and-style-guide/review-standards.rst diff --git a/docs/source/development/style-guide/security.rst b/docs/source/development/git-workflow-and-style-guide/security.rst similarity index 100% rename from docs/source/development/style-guide/security.rst rename to docs/source/development/git-workflow-and-style-guide/security.rst diff --git a/docs/source/development/style-guide/style-guide.rst b/docs/source/development/git-workflow-and-style-guide/style-guide.rst similarity index 87% rename from docs/source/development/style-guide/style-guide.rst rename to docs/source/development/git-workflow-and-style-guide/style-guide.rst index bf3bf70cba..38445f84c1 100644 --- a/docs/source/development/style-guide/style-guide.rst +++ b/docs/source/development/git-workflow-and-style-guide/style-guide.rst @@ -29,16 +29,3 @@ these items are provided below in the guide. Contributors can refer to the :ref:`checklist for contributors and reviewers of pull requests ` for assistance in making sure pull requests are adhering to these conventions. - -.. toctree:: - :maxdepth: 1 - - git-and-github-workflow - python-coding - python-docstrings - poetry-environment - security - tools-and-library-recommendations - versioning - checklist-for-pull-requests - review-standards \ No newline at end of file diff --git a/docs/source/development/style-guide/tools-and-library-recommendations.rst b/docs/source/development/git-workflow-and-style-guide/tools-and-library-recommendations.rst similarity index 100% rename from docs/source/development/style-guide/tools-and-library-recommendations.rst rename to docs/source/development/git-workflow-and-style-guide/tools-and-library-recommendations.rst diff --git a/docs/source/development/style-guide/versioning.rst b/docs/source/development/git-workflow-and-style-guide/versioning.rst similarity index 100% rename from docs/source/development/style-guide/versioning.rst rename to docs/source/development/git-workflow-and-style-guide/versioning.rst diff --git a/docs/source/development/index.rst b/docs/source/development/index.rst index b3ef157c4c..420441b07b 100644 --- a/docs/source/development/index.rst +++ b/docs/source/development/index.rst @@ -1,5 +1,5 @@ -Development -=========== +Onboarding and Collaboration +============================ :ref:`getting-started` @@ -14,9 +14,15 @@ be versioned appropriately to correspond with the code that produced them. .. toctree:: :maxdepth: 1 - getting-started + cli + data-dependency doc-overview docker + getting-started + git-access-roles + git-workflow-and-style-guide/index + poetry release-workflow - style-guide/style-guide - technology-stack \ No newline at end of file + upgrading-poetry + technology-stack + tools/index diff --git a/docs/source/external-tools/poetry.rst b/docs/source/development/poetry.rst similarity index 54% rename from docs/source/external-tools/poetry.rst rename to docs/source/development/poetry.rst index b99ba59f78..7b1a8f541f 100644 --- a/docs/source/external-tools/poetry.rst +++ b/docs/source/development/poetry.rst @@ -20,7 +20,7 @@ These advantages ensure that we can all install the same versions of tools, that Poetry also provides tools for automatically bumping dependency versions only where it makes sense. You can specify when a dependency should get a version change using Poetry's extensive `dependency specification `_ formatting. -Finally, Poetry provides a :ref:`shell `, which you can use as a virtual environment. This shell is automatically tied to the project directory, and allows developers to install dependency versions in an isolated environment. This means that, for example, if you have a different project using the same package with a different version, you can have each project with it's own version kept separate from conflicts. +Finally, Poetry manages a virtual environment tied to the project directory, which allows developers to install dependency versions in an isolated environment. This means that, for example, if you have a different project using the same package with a different version, you can have each project with its own version kept separate from conflicts. See :ref:`poetry-shell-link` for how to activate it. We have a :ref:`Poetry style guide` for specific recommendations about using Poetry in these projects. @@ -52,7 +52,7 @@ Poetry has a command to `add a new dependency `_ version specifiers (e.g. ``numpy>=1.24,<2``). Dependencies in ``[tool.poetry.group.*]`` sections continue to use Poetry's caret notation. The main project dependencies are always installed. You can also update the ``pyproject.toml`` file directly, using the existing formatting or the `Poetry documentation on it `_ as a guide. @@ -63,52 +63,84 @@ This will create a new version of the ``poetry.lock`` file, which should be comm .. _poetry-dependency-groups-link: -Dependency groups -^^^^^^^^^^^^^^^^^^ +Optional extras +^^^^^^^^^^^^^^^ -Poetry also provides dependency groups for separating dependencies into logical separations. If you are installing the project as an end user, you do not need the development tools. The testing environment does not need the documentation generation dependencies. In our case, the AWS Lambda environment does not need the same dependencies as the CDK deployment. Before you add a dependency to the main group, ask yourself if it would make more sense in one of the other existing dependency groups. +This project uses PEP 621 optional dependencies (extras) to separate dependencies into logical groups. If you are installing the project as an end user, you do not need the development tools. The testing environment does not need the documentation generation dependencies. Before you add a dependency to the main dependencies, ask yourself if it would make more sense in one of the existing extras (``dev``, ``test``, ``doc``, ``tools``, ``map_visualization``). -To add a dependency to an existing group, you can use the ``--group`` flag:: - - poetry add mkdocs --group docs - -These groups can be made optional as well, meaning they will not be installed by default when the user runs ``poetry install``. You can specify what groups to install using the ``--with`` or ``--without`` flags. - -Pip also provides a standard for optional dependencies. These can be installed when using ``pip`` instead of Poetry to install the dependencies. This goes under the ``[tool.poetry.extras]`` section in ``pyproject.toml``. These are separate, but similar to the optional dependencies. They can only be all installed or all not installed, with no splitting out into specific groups like the dependency groups. +To add a dependency to an existing extra, update the ``[project.optional-dependencies]`` section in ``pyproject.toml`` directly using PEP 508 version specifiers. These extras can be installed selectively when running ``poetry install`` or ``pip install``. .. _poetry-shell-link: -Installing and the Poetry Shell --------------------------------- +Installing and Activating the Virtual Environment +------------------------------------------------- To install the Poetry project, you can use the `install `_ command:: # We use dynamic versioning, which requires a plugin to be installed first - poetry self add poetry-dynamic-versioning + poetry self add "poetry-dynamic-versioning[plugin]" - # Install main dependencies and any dependency groups which are installed by default + # Install main dependencies only poetry install - # Install all extras + # Install all extras (dev, test, doc, tools, map_visualization) poetry install --all-extras - # install without specific dependency groups - poetry install --without test,docs + # Install with specific extras + poetry install --extras "test doc" + +By default, this command will install dependencies out of the ``poetry.lock`` file. + +.. note:: + + ``poetry shell`` was removed in Poetry 2. To activate the Poetry-managed + virtual environment, use: + + .. code-block:: bash + + source $(poetry env info --path)/bin/activate + + # To exit the virtual environment + deactivate - # Install with optional dependency groups - poetry install --with lambda_dev + On Windows (PowerShell): -By default, this command will install dependencies out of the ``poetry.lock`` file. This will also install into your Poetry shell for the project. + .. code-block:: powershell -The Poetry shell is a virtual environment tool provided by Poetry. To start the Poetry shell, with your dependencies installed, you can use the poetry `shell `_ command:: + & (poetry env info --path)\Scripts\activate.ps1 - poetry shell + You can also run a single command inside the environment without activating + it using ``poetry run``:: + + poetry run pytest + +.. _venv-alternative-link: + +Using a plain ``venv`` instead of Poetry's virtual environment +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +If you prefer to manage your virtual environment with the standard Python +``venv`` module rather than Poetry, you can do so by creating the environment +first and then running ``poetry install`` (or ``pip install``) inside it. +Poetry will detect the active virtual environment and install into it instead +of creating its own: + +.. code-block:: bash + + # Create and activate a venv + python3 -m venv .venv + source .venv/bin/activate # Windows: .venv\Scripts\activate.ps1 + + # Install via Poetry (uses the active venv) + poetry self add "poetry-dynamic-versioning[plugin]" + poetry install --all-extras - # To exit the shell - exit + # Or install directly with pip using the pyproject.toml extras + pip install -e ".[dev,test,tools]" -However, you are not required to use the Poetry shell as your virtual environment manager if you have another tool you prefer. +The ``venv`` approach avoids the need for ``poetry shell`` entirely: your +shell is already in the virtual environment after running ``source .venv/bin/activate``. -Poetry will, by default, not create a new virtual environment if it detects that it is running in a virtual environment already. So, for example, you can use a `Conda environment `_ by activating the environment first, and then running `poetry install`. +Poetry will, by default, not create a new virtual environment if it detects that it is running in a virtual environment already. So, for example, you can use a `Conda environment `_ by activating the environment first, and then running ``poetry install``. There are also `settings `_ surrounding the virtual environment that you can change to suit your workflow. diff --git a/docs/source/development/release-workflow.rst b/docs/source/development/release-workflow.rst index 222a3bb5f8..b775693464 100644 --- a/docs/source/development/release-workflow.rst +++ b/docs/source/development/release-workflow.rst @@ -19,7 +19,7 @@ are already completed. The three repositories are expected to be released at different cadences: * The ``imap_processing`` repository is released on a monthly cadence (typically the last day of the month, but can - vary depending on the availability of developers time to make the release. + vary depending on the availability of developers time to make the release), and also release on an as-needed basis. * The ``sds_data_manager`` repository is released on a as-needed basis, typically when enough changes have been made since the last release to justify a new release. * The ``imap-data-access`` repository is released whenever a new feature or bug fix is implemented, since this @@ -34,13 +34,17 @@ other repositories as well. Nominal releases """""""""""""""" -#. Make sure the ``dev`` branch is up-to-date with any changes you want included in the release (i.e. merge in any - feature branches using the nominal :ref:`git & GitHub Workflow `). +#. Make sure your local ``dev`` branch is up-to-date with any changes you want included in the release (i.e. merge in + any feature branches and update the branch against ``upstream`` using the nominal + :ref:`git & GitHub Workflow `). #. Create a new version branch off of ``dev``. The name of the branch should match the version number to be used for the release, which should follow the :ref:`software versioning ` conventions. The name should be prepended with ``v`` (e.g. ``v0.1.0``). #. Make any release-specific commits to the new version branch using the nominal ``git add``/``git commit`` cycle. This - may include commits that add release notes, or update version numbers in various configurations. + may include commits that add release notes, or update version numbers in various configurations. (Currently, the + ``imap_processing`` repo does not require any release-specific commits, as the versioning for that repo is fully + automated. The ``sds_data_manager`` and ``imap-data-access`` repositories currently require an update to the + hard-coded version number in the ``pyproject.toml`` file.) #. Push the version branch to the main ``IMAP-Science-Operations-Center`` ``imap_processing`` repo (i.e. ``upstream``). #. If there have been release-specific commits, In GitHub, create a pull request that merges the version branch into ``dev``. Proceed with the nominal review & merge process described in steps (10) and (11) in the :ref:`git & GitHub @@ -48,7 +52,8 @@ Nominal releases #. Create a `new release `_. Under "Choose a tag", create a new tag with the same name as the version branch (e.g. ``v0.1.0``). For "Release title", also use the name of the version branch (e.g. ``v0.1.0``). In the description box, include appropriate highlights and release - notes (you can use a previous release for an example of how this should be formatted). + notes (you can use a previous release for an example of how this should be formatted), or use the "Generate Release + Notes" button. Patches @@ -73,6 +78,7 @@ which you want to patch (e.g. ``v0.1.x``). Deployment ^^^^^^^^^^ -Once a release is created in GitHub, a SDC dev team member can follow the `CDK deployment steps -`_ to deploy the software to AWS. Once the -software is deployed, a user should be able to call the APIs. \ No newline at end of file +Once a release is created in GitHub, a GitHub action workflow is used to automatically deploy the changes. In the case +of ``sds_data_manager``, a ``Deploy`` workflow is used to deploy the software to AWS. For ``imap_processing`` and +``imap-data-access``, a ``Build and upload to PyPi`` workflow is used to build the package and upload it to PyPi. The +person performing the release should check that these workflows succeeded successfully. \ No newline at end of file diff --git a/docs/source/development/technology-stack.rst b/docs/source/development/technology-stack.rst index 76c5a39cdf..0eaed4914e 100644 --- a/docs/source/development/technology-stack.rst +++ b/docs/source/development/technology-stack.rst @@ -1,5 +1,7 @@ +.. _technology-stack: + Technology Stack ----------------- +================ This page lists the various technologies and libraries that the IMAP SDC utilizes along with a few notes on what they are used for, why they were chosen, diff --git a/docs/source/code-documentation/tools/cdf-global-attrs.rst b/docs/source/development/tools/cdf-global-attrs.rst similarity index 96% rename from docs/source/code-documentation/tools/cdf-global-attrs.rst rename to docs/source/development/tools/cdf-global-attrs.rst index a02278b5c4..1ee1ca9642 100644 --- a/docs/source/code-documentation/tools/cdf-global-attrs.rst +++ b/docs/source/development/tools/cdf-global-attrs.rst @@ -1,3 +1,5 @@ +.. _cdf-global-attrs: + Code for creating CDF attributes ================================ diff --git a/docs/source/code-documentation/tools/index.rst b/docs/source/development/tools/index.rst similarity index 80% rename from docs/source/code-documentation/tools/index.rst rename to docs/source/development/tools/index.rst index 9f68abfd1c..35bc36097e 100644 --- a/docs/source/code-documentation/tools/index.rst +++ b/docs/source/development/tools/index.rst @@ -1,3 +1,5 @@ +.. _tools: + Tools ===== @@ -8,5 +10,4 @@ These are tools written by the IMAP team that are used across multiple instrumen xtce-generator xarray-to-cdf - cdf-global-attrs - imap-data-access \ No newline at end of file + cdf-global-attrs \ No newline at end of file diff --git a/docs/source/code-documentation/tools/xarray-to-cdf.rst b/docs/source/development/tools/xarray-to-cdf.rst similarity index 100% rename from docs/source/code-documentation/tools/xarray-to-cdf.rst rename to docs/source/development/tools/xarray-to-cdf.rst diff --git a/docs/source/code-documentation/tools/xtce-generator.rst b/docs/source/development/tools/xtce-generator.rst similarity index 100% rename from docs/source/code-documentation/tools/xtce-generator.rst rename to docs/source/development/tools/xtce-generator.rst diff --git a/docs/source/development/upgrading-poetry.rst b/docs/source/development/upgrading-poetry.rst new file mode 100644 index 0000000000..5141f4e077 --- /dev/null +++ b/docs/source/development/upgrading-poetry.rst @@ -0,0 +1,53 @@ +.. _upgrading-poetry: + +Upgrading Poetry 1.x to 2.x +============================ + +Poetry 2.x introduces breaking changes, and it is not possible to run Poetry 1.x against a Poetry 2 project. This page covers two ways to +upgrade an existing Poetry 1.8 installation. + + +Option 1: In-place upgrade with ``poetry self update`` +------------------------------------------------------ + +:: + + poetry self update + +If you have the ``poetry-dynamic-versioning`` plugin installed, reinstall it +after upgrading:: + + poetry self add "poetry-dynamic-versioning[plugin]" + +Option 2: Uninstall and reinstall +---------------------------------- + +If the in-place upgrade fails or produces errors, a clean reinstall is more +reliable. + +**1. Uninstall the existing Poetry installation:** + +.. code-block:: bash + + # If installed via the official installer + curl -sSL https://install.python-poetry.org | python3 - --uninstall + + # If installed via pipx + pipx uninstall poetry + +**2. Install Poetry 2.x:** + +.. code-block:: bash + + # Via the official installer (recommended) + curl -sSL https://install.python-poetry.org | python3 - + + # Via pipx + pipx install poetry + +After install +------------- + +After install, reinstall the project using `poetry install --all-extras`. + +If you see any issues, please reach out to the SDC team (imap-sdc@lists.lasp.colorado.edu) for troubleshooting help. \ No newline at end of file diff --git a/docs/source/external-tools/index.rst b/docs/source/external-tools/index.rst deleted file mode 100644 index e8c95cfb3e..0000000000 --- a/docs/source/external-tools/index.rst +++ /dev/null @@ -1,10 +0,0 @@ -External Tools -============== - -This page provides documentation written by the IMAP team about external tools. - -.. toctree:: - :maxdepth: 1 - - poetry - cdf/index \ No newline at end of file diff --git a/docs/source/data-access/calibration-files.rst b/docs/source/filename-convention/calibration-files.rst similarity index 100% rename from docs/source/data-access/calibration-files.rst rename to docs/source/filename-convention/calibration-files.rst diff --git a/docs/source/filename-convention/index.rst b/docs/source/filename-convention/index.rst new file mode 100644 index 0000000000..eaa3e0c1f0 --- /dev/null +++ b/docs/source/filename-convention/index.rst @@ -0,0 +1,12 @@ +.. _filename-conventions: + +Filename Conventions +==================== + +This section describes the naming conventions used for IMAP data products and files. + +.. toctree:: + :maxdepth: 1 + + Science Filename Convention + Ancillary Filename Convention diff --git a/docs/source/data-access/naming-conventions.rst b/docs/source/filename-convention/naming-conventions.rst similarity index 100% rename from docs/source/data-access/naming-conventions.rst rename to docs/source/filename-convention/naming-conventions.rst diff --git a/docs/source/index.rst b/docs/source/index.rst index b93d17800a..2ae3dbb730 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -16,16 +16,19 @@ IMAP mission and being developed at To get started with the project: :ref:`getting-started`. -The explicit code interfaces and structure are described in the :ref:`code-documentation`. +The explicit code interfaces and structure are described in the :ref:`algorithm-code-documentation`. .. toctree:: :maxdepth: 1 - code-documentation/index - development/index - project-management/index - external-tools/index - data-access/index + Onboarding & Collaboration + IMAP Data Access Tool + CDF Metadata Resources + Filename Conventions + Algorithm Code Documentation + SDC Project Management + Infrastructure + If you make use of any ``imap_processing`` code, please consider citing it in your research. `https://zenodo.org/record/11168295 `_ diff --git a/docs/source/infrastructure/aws-setup.rst b/docs/source/infrastructure/aws-setup.rst new file mode 100644 index 0000000000..dc36ac07d6 --- /dev/null +++ b/docs/source/infrastructure/aws-setup.rst @@ -0,0 +1,47 @@ +AWS Setup +========= + +Download/requirements +~~~~~~~~~~~~~~~~~~~~~ + +Ensure you have installed Node.js (newer than version 14), AWS CLI, and Docker + +- `Node.js `_ +- `AWS CLI `_ +- `Docker `_ + +.. _aws-new-user: + +New User +~~~~~~~~~ + +#. Log-in to `AWS console `_ +#. Use *imap-sdc-development* for Account ID +#. Enter user name and password +#. Select IAM from *Services* menu or search IAM +#. Select *Users* from left menu +#. Click your user button +#. Select *Security Credentials* tab +#. Click *Create Access Key* +#. Make note of *Access Key ID* and *Secret Access Key* +#. You can download the .csv file if you want +#. Click *Close* + +Existing User +~~~~~~~~~~~~~ +#. In command line, run the following command to set up the aws environment:: + + aws configure + +#. Enter your *Access Key ID* and *Secret Access Key* (If you don't have them, see :ref:`aws-new-user`) +#. For region, set it to the AWS region you'd like to set up your SDS. For IMAP, we're using "us-west-2":: + + [imap] + region=us-west-2 + aws_access_key_id= + aws_secret_access_key= + +#. Then, you can set the profile used by cdk by setting the AWS_PROFILE environment variable to the profile name (in this case, imap):: + + export AWS_PROFILE=imap + diff --git a/docs/source/infrastructure/backup-deploy.rst b/docs/source/infrastructure/backup-deploy.rst new file mode 100644 index 0000000000..bb3e913144 --- /dev/null +++ b/docs/source/infrastructure/backup-deploy.rst @@ -0,0 +1,21 @@ +Deploying to Backup Account +=========================== + +Some of the CDK code is used to deploy a backup bucket for S3 replication. This page covers how to deploy this code into a different account. This backup code can be deployed into the normal dev account as well. + +Steps for deploying +^^^^^^^^^^^^^^^^^^^ +.. note:: + First, you will need to deploy the SdsDataManager stack to the source account (dev or prod). The steps to set up and deploy that are in the :doc:`cdk-deployment` doc. + +#. Set up your backup account credentials if you're using another account. This can be done by adding a new profile to AWS (i.e. ``imap-backup``) +#. Set your ``AWS_PROFILE`` environment variable to the backup account profile +#. Set the ``source_account`` variable in the "backup" section of the cdk.json file to the account number for the _source_ bucket (where the backed up items originate) +#. Update the ``account_name`` variable in the ``cdk.json`` file to "backup" +#. Finally, you will need to copy the Role arn deployed in SdsDataManager into :file:`sds_data_manager/stacks/backup_bucket_construct.py`. This arn can be found by going to the IAM console in the source account and searching for "BackupRole". +#. Run your ``cdk bootstrap`` command if you haven't already done so for the backup account. +#. Run ``cdk synth --context account_name=backup`` and check to confirm that the only stack being deployed is the "BackupBucket" stack +#. Run ``cdk deploy --context account_name=backup`` to deploy! + +.. note:: + Once the Backup bucket is deployed to the other account, you still need to set up :doc:`s3-replication` in the source account. diff --git a/docs/source/infrastructure/cdk-deployment-personal-aws.rst b/docs/source/infrastructure/cdk-deployment-personal-aws.rst new file mode 100644 index 0000000000..743b636031 --- /dev/null +++ b/docs/source/infrastructure/cdk-deployment-personal-aws.rst @@ -0,0 +1,53 @@ +Deploy CDK to Personal AWS Account +================================== + +1. Get a personal AWS account set up by submitting a `Service Desk ticket `_: + + a. Use the request type "Create AWS Account" under the "Cloud" section. + b. For "Project/Program Name", use ``IMAP`` + c. For "Speedtype", use the speedtype for the "IMAP SOC SDC SW and Sys Devl" project + d. For "Root Group Email Address to Associate with Account", use your LASP email address + e. For "Lead Technical Contact Name", use `Greg Lucas` + +2. Once the account is set up, `log in to AWS `_ and create a user in IAM. + + a. You'll likely want to give your user the ``AdministratorAccess`` policy. + +3. Next, go to ``Security Credentials`` for your new user and create an access key. This will be needed in step 6, so save the access key/secret access key. +4. On your local system, add a new profile to ``~/.aws/config`` for your personal account. This can be named anything you want, we'll call it ``my_profile`` for this example. +5. In your local command line, type ``aws configure`` to set up your credentials. +6. Paste your IAM access key and secret access key from step 3. +7. In the IMAP ``sds-data-manager`` repository, add a new context to ``cdk.json``. We'll call it ``my_context`` for this example. For example:: + + "backup": { + "account": "012345678901", + "source_account": "dev" + }, + "my_context": { + "account":"234567890123", + "region":"us-west-2" + }, + "dev": { + "account": "111122223333", + "domain_name": "example.com", + "region": "us-west-2" + }, + +*Do not put a domain field for your personal context* + +8. In your local terminal, go to the top of the ``sds-data-manager`` repository and run the following: + + a. ``cdk bootstrap --profile my_profile --context account_name=my_context`` + b. ``cdk synth --profile my_profile --context account_name=my_context`` + c. ``cdk deploy --profile my_profile --context account_name=my_context`` + + * Add ``--require-approval never`` to the end of step 9c if you don't want to be prompted for each stack. + * Note: Not sure if this happens to anyone else, but when the deployment gets this part of the deployment, there's no prompt and it hangs there forever. However, if I hit ``Enter``, a ``y/n`` prompt appears asking if I want to deploy. So if it gets stuck at that point, hit ``Enter``, then you can select ``y``. Terminal output example:: + + 0af60606a7e1: Pushed + 03f331fd9b29: Pushed + 03f331fd9b29: Pushed + c3418b25bdeef0d97b84f41688fa22e9d1c8bdf0927d3774d77588d87763a2f9: digest: sha256:83e8fd9ae28cee020091b2caa4faa421a400505e4ddfdb29fd693dec8b2a7a1d size: 2628 + 29143fef993fc62aeb3447a224679eafa9e60eaba00aa3bfaa60f0de9f9815bb: digest: sha256:e3c8f122ade7a0c1f598b3c7bbc08488c694aa9b7279e1367227ed0d0fba6c33 size: 2628 + +9. Before committing any changes, make sure to revert your ``cdk.json`` file to its original state. diff --git a/docs/source/infrastructure/cdk-deployment.rst b/docs/source/infrastructure/cdk-deployment.rst new file mode 100644 index 0000000000..bf0a8b749c --- /dev/null +++ b/docs/source/infrastructure/cdk-deployment.rst @@ -0,0 +1,100 @@ +.. _cdk-deployment: + +CDK Deployment +============== + +.. note:: + In most cases, deployments should be performed via GitHub Actions rather + than manually. Manual deployment is intended for special cases only. + +Deploy +~~~~~~ +The deploy configuration is controlled through the ``cdk.json`` file. +Each account has a name and the associated configuration parameters associated with it. +For example:: + + "dev": { + "account": "123456789012", + "domain_name": "website.com", + "region": "us-west-2" + } + +The parameters in this section are what control the deployment of the application. +The account and region are the environment to deploy the stacks into, and the +``domain_name`` is if you want to deploy it into a hosted domain name that you control. +Optionally, if you want to deploy to a new account or different subdomain you can +add an entirely new section with appropriate parameters. + +To deploy the application, you must have local credentials to be able to deploy to +the specified account and region. This can be done through environment variables +and AWS access key credentials:: + + export AWS_PROFILE= + +You'll then need to synthesize the CDK code with the command:: + + cdk synth --context account_name="dev" + +Then you can deploy the architecture with the following command:: + + cdk deploy --context account_name="dev" [ stack | --all ] + +After about 20-30 minutes or so, you should have a brand-new SDS set up in AWS. +The cloud infrastructure CDK source for the IMAP mission is maintained in the +``sds-data-manager`` repository; this page is mirrored in ``imap_processing`` +for documentation and reference only. + +Cleanup Resources +~~~~~~~~~~~~~~~~~ +During development, if you are creating resources that aren't intended to be shared, +and you do not intend to use the resources for more than a couple of days you should +do a destroy to avoid charges, especially with databases.:: + + cdk destroy --context account_name="dev" [ stack | --all ] + +Automatic Deployments +~~~~~~~~~~~~~~~~~~~~~ +The CDK code is automatically deployed to the dev account when a pull request is +merged into the dev branch. This is done through a GitHub Action that runs +the ``cdk deploy`` command. The GitHub Action is defined in the +``.github/workflows/deploy.yml`` file. It uses short lived credentials to deploy +the code to the dev account. The credentials are obtained through an OIDC +authentication process and an aws provided credentials action step. + +With a new account, there are several steps that are required to set this up +and authorize GitHub to deploy to the account. A summary link to the steps +is given here: https://github.com/aws-actions/configure-aws-credentials#OIDC +with the explicit steps as follows: + +#. Setup GitHub as an OIDC provider in your AWS account. This can be done + manually via the console or through a cloudformation template. These links give + a step-by-step process that you can follow. + https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-amazon-web-services#adding-the-identity-provider-to-aws + https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_oidc.html +#. Add a role and trust policy in AWS IAM that allows GitHub to assume the role. + https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-amazon-web-services#configuring-the-role-and-trust-policy + Specifically, make sure you restrict this role to only be invoked on the given + branches of your repository and not wide-open trust to the entire organization. +#. Attach a policy to the role that allows the role to deploy the CDK stacks, giving + it the appropriate permissions for the resources you require. + +Troubleshooting Lambda Architectures +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The project can be built on a local machine, but creating the layers can +sometimes cause issues if a developer is running on an ARM architecture (e.g. Macs). +The Lambda layers are designed to be built on an x86 architecture (GitHub Actions CI), +so if you are running on ARM architecture you may need to set some additional +environment variables to force the build to run on x86. + +Remove all Docker images and build artifacts before running the build command:: + + docker builder prune -a + docker image prune -a + # Remove the cdk.out directory where build artifacts are stored. + rm -rf cdk.out + +Then, set the environment variable to force Docker to use the x86 architecture:: + + DOCKER_DEFAULT_PLATFORM=linux/amd64 cdk synth --context account_name="dev" + diff --git a/docs/source/infrastructure/database-migration.rst b/docs/source/infrastructure/database-migration.rst new file mode 100644 index 0000000000..6fe7d14d84 --- /dev/null +++ b/docs/source/infrastructure/database-migration.rst @@ -0,0 +1,220 @@ +.. _database-migrations: + +Database Migrations with Alembic +================================= + +We use Alembic for database migrations. Alembic compares the database schema defined in the models to the current +state of the database and generates revision files containing the changes needed to update the schema. + +Docs: https://alembic.sqlalchemy.org/en/latest/index.html + +---- + +**Migration Workflow (Separated: DEV Test and PROD Deploy)** +------------------------------------------------------------- + +.. warning:: + + Be **extremely careful** to never mix up DEV and PROD. + ``DATABASE_URL`` is what determines which database you are operating on. + Before any command that can change schema/data, verify: + 1) ``DATABASE_URL`` points to the intended RDS instance (DEV or PROD) + 2) ``alembic current`` matches the intended environment + +A) DEV Migration + Testing (Steps 1–6) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +1. **Make your changes to the models** + + Make your desired changes to the models in ``sds_data_manager/lambda_code/SDSCode/database/models.py``. + +2. **Create a revision (DEV ONLY)** + + This compares the database RDS instance in aws to the DEV schema and generates a migration file with ``upgrade`` and ``downgrade``. + + .. important:: + + Never create revisions on PROD. + + .. code-block:: bash + + export DATABASE_URL=dev_database_url + alembic revision --autogenerate -m "description" + + This generates a new file in ``alembic/versions/``. **Always review the file before applying** β€” Alembic cannot + detect all changes. See what it misses here: + https://alembic.sqlalchemy.org/en/latest/autogenerate.html#what-does-autogenerate-detect-and-what-does-it-not-detect + +3. **Preview the SQL (Dry Run)** + + To see the SQL that would be run without actually applying it: + + .. code-block:: bash + + export DATABASE_URL=dev_database_url + alembic upgrade head --sql + +4. **Apply migration to DEV** + + .. code-block:: bash + + export DATABASE_URL=dev_database_url + alembic current + alembic upgrade head + +5. **Test on DEV** + + Test your changes thoroughly to ensure the migration works as expected. Connect to the database on DataGrip and + verify the schema changes. + +6. **Downgrade DEV to verify downgrade path** + + .. code-block:: bash + + export DATABASE_URL=dev_database_url + alembic downgrade -1 + + Make sure the downgrade works as expected. + +B) PROD Verification + Deployment (Steps 7–10) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +7. **Commit and push migration file + code changes** + +8. **Open PR, review, approve, merge** + + First re-check DEV after merge: + + .. code-block:: bash + + export DATABASE_URL=dev_database_url + alembic current + alembic upgrade head + + Then repeat **Step 3 (Dry Run)**, but on PROD: + + .. warning:: + + PROD safety gate (must all be true): + - ``DATABASE_URL=prod_database_url`` + - URL host/DB clearly match the PROD RDS instance + - ``alembic current`` is the expected PROD revision + + .. code-block:: bash + + export DATABASE_URL=prod_database_url + alembic current + alembic upgrade head --sql + alembic upgrade head + +10. **Post-deploy monitoring (DEV + PROD)** + + Confirm both environments are healthy and at expected revision: + run ``alembic current`` and functional checks. + +---- + +Setup (This is performed once) +------------------------------ + +Ensure you are in the root of the ``sdc-data-manager`` repo. + +.. code-block:: bash + + alembic init alembic + +Edit ``alembic/env.py`` and add the following at the top: + +.. code-block:: python + + # Override the URL from environment variable + # Do not hardcode the DATABASE_URL in the config file for security reasons + config.set_main_option("sqlalchemy.url", os.environ["DATABASE_URL"]) + +Import the database schema and point ``target_metadata`` to ``Base.metadata``: + +.. code-block:: python + + from sds_data_manager.lambda_code.SDSCode.database.models import Base + target_metadata = Base.metadata + +---- + +Connecting to the Database +--------------------------- + +The ``DATABASE_URL`` follows this format: + +.. code-block:: text + + driver://username:password@host:port/database_name + +We have different databases for DEV and PROD, so you will need to set the ``DATABASE_URL`` environment variable before +running any Alembic commands. + +To find the credentials: +1. Log into AWS account (dev or prod) +2. Go to **Secrets Manager** β†’ **Secrets** β†’ ``sdp-database-cred`` +3. Click **Retrieve secret value** +4. Construct the URL from those values +5. Verify the URL points to the intended RDS instance (DEV vs PROD) + +Export the URL: + +.. code-block:: bash + + export DATABASE_URL=postgresql://username:password@host:port/database_name + +Test the connection: + +.. code-block:: bash + + alembic current + +.. warning:: + + Always double check which database your ``DATABASE_URL`` is pointing to before running any commands. + ``DATABASE_URL`` is the environment boundary between DEV and PROD. + Always test on DEV first before applying to PROD. + + +Downtime Considerations +----------------------- + +Most schema changes in PostgreSQL are non-blocking, but some operations will lock tables and cause downtime: + +- **Adding a NOT NULL column without a default** β€” locks the table +- **Dropping a column** β€” locks the table briefly +- **Renaming a column or table** β€” locks the table +- **Adding a non-concurrent index** β€” locks the table for writes +- **Changing a column type** β€” locks the table and may require a full rewrite + +To minimize downtime on PROD, consider running heavy migrations during off-hours or using ``CONCURRENTLY`` +for index operations where possible. + +---- + +Troubleshooting +---------------- + +Can't locate revision identified by 'xxxx' +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The database has a revision recorded that no longer has a corresponding file. This usually means a migration +file was deleted after being applied. Connect directly to the database and clear the version table: + +.. code-block:: sql + + DELETE FROM alembic_version; + +Then stamp to a known good revision: + +.. code-block:: bash + + alembic stamp head + +Target database is not up to date +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +There are pending migrations. Run ``alembic current`` to see where the DB is, then ``alembic upgrade head`` +to apply. diff --git a/docs/source/infrastructure/ialirt-setup.rst b/docs/source/infrastructure/ialirt-setup.rst new file mode 100644 index 0000000000..ea92c0cc9c --- /dev/null +++ b/docs/source/infrastructure/ialirt-setup.rst @@ -0,0 +1,65 @@ +I-ALiRT Setup +============= + +Secrets Manager +~~~~~~~~~~~~~~~ + +Ensure you have a secret in AWS Secrets Manager with a username and password for the Nexus repo. The secret should be named `nexus-repo` and can be created using the following command:: + + aws secretsmanager create-secret --name nexus-credentials --description "Credentials for Nexus Docker registry" --secret-string '{"username":"your-username", "password":"your-password"}' + +Image Versioning +~~~~~~~~~~~~~~~~ +We will rely on semantic versioning for the images MAJOR.MINOR (e.g., 1.0). + +- MAJOR: Major changes. +- MINOR: Minor changes. + +For development we will keep the major changes at 0. + +Nexus Repo +~~~~~~~~~~ +We will have a versioned image and latest image in the Nexus repo. The versioned image will be tagged with the version number (e.g., 1.0) and the latest image will be the same as the most recent version. The reason that we do this is to ease the ability to switch out images in ECS. + +#. Check that you are not already logged in by running:: + + cat ~/.docker/config.json + +#. Ensure that the Nexus registry URL is not in the list of logged in registries. +#. Run the following command to login (you will be prompted for your WebIAM username and password):: + + docker login docker-registry.pdmz.lasp.colorado.edu + +#. Your `~/.docker/config.json` file should now contain a reference to the registry url. +#. Determine the appropriate version for your image based on the semantic versioning scheme (IOIS_MAJOR.IOIS_MINOR.DOCKER_VERSION). +#. Build the image and tag it with the Nexus registry URL:: + + docker build -t ialirt:X.Y.Z --rm . --no-cache + +#. Tag with the Nexus registry URL:: + + docker tag ialirt:X.Y.Z docker-registry.pdmz.lasp.colorado.edu/ialirt/ialirt:X.Y.Z + docker tag ialirt:X.Y.Z docker-registry.pdmz.lasp.colorado.edu/ialirt/ialirt:latest_{dev | prod} + +#. Push the image:: + + docker push docker-registry.pdmz.lasp.colorado.edu/ialirt/ialirt:X.Y.Z + docker push docker-registry.pdmz.lasp.colorado.edu/ialirt/ialirt:latest_{dev | prod} + +#. Images may be viewed on the Nexus website: https://artifacts.pdmz.lasp.colorado.edu +#. To verify that the latest image and the most recent version image are the same, run the following and compare the image IDs:: + + docker inspect --format='{{.Id}}' docker-registry.pdmz.lasp.colorado.edu/ialirt/ialirt:X.Y.Z + docker inspect --format='{{.Id}}' docker-registry.pdmz.lasp.colorado.edu/ialirt/ialirt:latest_{dev | prod} + +CDK Deployment +~~~~~~~~~~~~~~ +:ref:`cdk-deployment` + +ECS Recognition of a New Image +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +To have ECS recognize a new image the cdk must be redeployed:: + + aws ecs update-service --cluster --service --force-new-deployment --deployment-configuration maximumPercent=200,minimumHealthyPercent=0 + +The reason that we can only have a single task running is that the same ports would be in use by the old task, and as a result, the new task will fail to start because it wouldn't be able bind to the required ports. diff --git a/docs/source/infrastructure/index.rst b/docs/source/infrastructure/index.rst new file mode 100644 index 0000000000..fb011a1af9 --- /dev/null +++ b/docs/source/infrastructure/index.rst @@ -0,0 +1,19 @@ +.. _infrastructure: + +Infrastructure +============== + +This section covers the AWS cloud infrastructure and deployment documentation +for the IMAP Science Data System (SDS). This is only relevant for SDC infrastructure developers +directly updating infrastructure for running algorithm generation code. + +.. toctree:: + :maxdepth: 1 + + aws-setup + cdk-deployment + cdk-deployment-personal-aws + backup-deploy + s3-replication + ialirt-setup + database-migration diff --git a/docs/source/infrastructure/s3-replication.rst b/docs/source/infrastructure/s3-replication.rst new file mode 100644 index 0000000000..0b57d7db21 --- /dev/null +++ b/docs/source/infrastructure/s3-replication.rst @@ -0,0 +1,41 @@ +S3 Replication +============== + +Once you have finished :doc:`backup-deploy`, you can set up replication in the source bucket. + +Create a replication rule +^^^^^^^^^^^^^^^^^^^^^^^^^ + +#. Open your source S3 bucket in the AWS console +#. Under the "Management" tab, find the "Replication Rules" section +#. Click "Create replication rule" to create a new rule +#. Enter an ID. If this is a developer bucket, include your initials. Preferably, it should be clear this is a backup rule. +#. Under "Source Bucket", select "Apply to all objects in this bucket" +#. Under "Destination" select "Specify a bucket in another account" and enter the account number and bucket name +#. Under "IAM role", select the "SdsDataManager-{account_name}-BackupRole" +#. Then, save the rule, and select "Do not replicate existing objects" in the popup + +Now, items placed in the source bucket will be automatically replicated to the backup bucket! + +Copying items back into source account bucket +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +To restore files from the backup bucket into the main account bucket, we are going to `assume the role `_ created by SdsDataManager stack in the source account. Here, "source account" refers to the account with SdsDataManager deployed into it (i.e. dev or prod). + +#. Update ``~/.aws/config`` to include a new profile for this role. Here, ``source_profile`` should be the source account profile + + .. code-block:: ini + + [profile backup-role] + role_arn = arn:aws:iam:::role/ + source_profile = imap + +#. Update the role in the dev account to include a new principal: + + * Under the "Trust relationships" tab, edit the trust policy + * add a new principal to the trust policy with your username. You can do this via the GUI or just add under "principal": ``"AWS": "arn:aws:iam::>:user/hartnett"`` (update with your username) + * We can then assume this role in the AWS CLI with ``--profile`` + +#. Check your credentials: ``aws s3 ls --profile backup-role s3://sds-data-dev`` +#. To transfer all files from the backup bucket to the main bucket: ``aws s3 sync --profile backup-role s3://sds-data-backup s3://sds-data-dev`` +#. If you have any issues, you can check permissions by downloading and uploading locally (replace one of the bucket names with a local file path) diff --git a/imap_processing/_version.py b/imap_processing/_version.py new file mode 100644 index 0000000000..e3e53154fa --- /dev/null +++ b/imap_processing/_version.py @@ -0,0 +1,3 @@ +# These version placeholders will be replaced later during substitution. +__version__ = "0.0.0" +__version_tuple__ = (0, 0, 0) diff --git a/imap_processing/ancillary/ancillary_dataset_combiner.py b/imap_processing/ancillary/ancillary_dataset_combiner.py index 02e2d06a1a..9cd8bd2b68 100644 --- a/imap_processing/ancillary/ancillary_dataset_combiner.py +++ b/imap_processing/ancillary/ancillary_dataset_combiner.py @@ -123,7 +123,7 @@ def convert_to_timestamped_data(self, filename: str | Path) -> TimestampedData: ) end_dt = np.datetime64(formatted_str, "D") else: - end_dt = self.expected_end_date + end_dt = self.expected_end_date # type: ignore[assignment] return TimestampedData(start_dt, end_dt, dataset, filepath.version) @@ -231,7 +231,7 @@ def _combine_input_datasets(self) -> xr.Dataset: # noqa: PLR0912 # sort by version sorted_data_list = sorted( - self.timestamped_data, key=lambda x: (int(x.version[-3:])) + self.timestamped_data, key=lambda x: int(x.version[-3:]) ) epoch_data = xr.date_range( @@ -338,7 +338,7 @@ def __init__( ): super().__init__(ancillary_input, expected_end_date) - def convert_file_to_dataset(self, filepath: str | Path) -> xr.Dataset: + def convert_file_to_dataset(self, filepath: str | Path) -> xr.Dataset: # noqa: PLR0911 """ Convert GLOWS ancillary .dat files to xarray datasets. @@ -364,6 +364,19 @@ def convert_file_to_dataset(self, filepath: str | Path) -> xr.Dataset: if "excluded-regions" in filename: # Handle excluded regions (2 columns: longitude, latitude) data = np.loadtxt(filepath, comments="#") + if data.size == 0: + return xr.Dataset( + { + "ecliptic_longitude_deg": ( + ["region"], + np.array([], dtype=float), + ), + "ecliptic_latitude_deg": ( + ["region"], + np.array([], dtype=float), + ), + } + ) return xr.Dataset( { "ecliptic_longitude_deg": (["region"], data[:, 0]), @@ -412,6 +425,19 @@ def convert_file_to_dataset(self, filepath: str | Path) -> xr.Dataset: } ) + elif "l2-calibration" in filename: + # Handle calibration file (timestamp + cps_per_R float value) + with open(filepath) as f: + lines = [line.strip() for line in f if not line.startswith("#")] + identifiers = [line.split(" ", 1)[0] for line in lines] + values = [float(line.split(" ", 1)[1]) for line in lines] + return xr.Dataset( + { + "start_time_utc": (["time_block"], identifiers), + "cps_per_r": (["time_block"], values), + } + ) + elif filename.endswith(".json"): # Handle pipeline settings JSON file using the generic read_json method return self.convert_json_to_dataset(filepath) diff --git a/imap_processing/cdf/config/imap_codice_global_cdf_attrs.yaml b/imap_processing/cdf/config/imap_codice_global_cdf_attrs.yaml index c4032a0e7c..6bbd59e91f 100644 --- a/imap_processing/cdf/config/imap_codice_global_cdf_attrs.yaml +++ b/imap_processing/cdf/config/imap_codice_global_cdf_attrs.yaml @@ -1,6 +1,7 @@ instrument_base: &instrument_base Descriptor: &desc CoDICE>Compact Dual Ion Composition Experiment + Instrument_type: Particles (space) TEXT: &txt > The Compact Dual Ion Composition Experiment (CoDICE) will measure the distributions and composition of interstellar pickup ions (PUIs), particles that make it through the heliosheath into the heliosphere. CoDICE also collects and @@ -11,7 +12,6 @@ instrument_base: &instrument_base measured by the common TOF / E system. These measurements are critical in determining the Local Interstellar Medium (LISM) composition and flow properties, the origin of the enigmatic suprathermal tails on the solar wind distributions and advance understanding of the acceleration of particles in the heliosphere. - Instrument_type: Particles (space) # L1a @@ -234,3 +234,39 @@ imap_codice_l2_hi-direct-events: Data_type: L2_hi-direct-events>Level-2 Hi Event Data Logical_source: imap_codice_l2_hi-direct-events Logical_source_description: IMAP Mission CoDICE Hi Level-2 Event Data. + +imap_codice_l2_lo-sw-species: + <<: *instrument_base + Data_type: L2_lo-sw-species>Level-2 Lo Sunward Species Intensities Data + Logical_source: imap_codice_l2_lo-sw-species + Logical_source_description: IMAP Mission CoDICE Lo Level-2 Sunward Species Intensity Data. + +imap_codice_l2_lo-nsw-species: + <<: *instrument_base + Data_type: L2_lo-nsw-species>Level-2 Lo Non-Sunward Species Intensities Data + Logical_source: imap_codice_l2_lo-nsw-species + Logical_source_description: IMAP Mission CoDICE Lo Level-2 Non-Sunward Species Intensity Data. + +imap_codice_l2_lo-sw-angular: + <<: *instrument_base + Data_type: L2_lo-sw-angular>Level-2 Lo Sunward Angular Intensities Data + Logical_source: imap_codice_l2_lo-sw-angular + Logical_source_description: IMAP Mission CoDICE Lo Level-2 Sunward Angular Intensity Data. + +imap_codice_l2_lo-nsw-angular: + <<: *instrument_base + Data_type: L2_lo-nsw-angular>Level-2 Lo Non-Sunward Angular Intensities Data + Logical_source: imap_codice_l2_lo-nsw-angular + Logical_source_description: IMAP Mission CoDICE Lo Level-2 Non-Sunward Angular Intensity Data. + +imap_codice_l2_hi-omni: + <<: *instrument_base + Data_type: L2_hi-omni>Level-2 Hi Omnidirectional Species Intensities Data + Logical_source: imap_codice_l2_hi-omni + Logical_source_description: IMAP Mission CoDICE Hi Level-2 Omnidirectional Species Intensity Data. + +imap_codice_l2_hi-sectored: + <<: *instrument_base + Data_type: L2_hi-sectored>Level-2 Hi Sectored Species Intensities Data + Logical_source: imap_codice_l2_hi-sectored + Logical_source_description: IMAP Mission CoDICE Hi Level-2 Sectored Species Intensity Data. diff --git a/imap_processing/cdf/config/imap_codice_l1a_variable_attrs.yaml b/imap_processing/cdf/config/imap_codice_l1a_variable_attrs.yaml index e0715fc96c..260d8a508c 100644 --- a/imap_processing/cdf/config/imap_codice_l1a_variable_attrs.yaml +++ b/imap_processing/cdf/config/imap_codice_l1a_variable_attrs.yaml @@ -1,87 +1,38 @@ -# TODO: Add DEPEND_1 to energy delta variables (energy_h_minus, energy_h_plus, etc.) - # <=== Useful Variables ===> int_fillval: &int_fillval -9223372036854775808 -uint8_fillval: &uint8_fillval 255 -uint16_fillval: &uint16_fillval 65535 uint32_fillval: &uint32_fillval 4294967295 -real_fillval: &real_fillval -1.0e+31 +real_fillval: &real_fillval -1.0E+31 min_int: &min_int -9223372036854775808 min_epoch: &min_epoch -315575942816000000 max_int: &max_int 9223372036854775807 -max_uint8: &max_uint8 255 -max_uint16: &max_uint16 65535 -max_uint24: &max_uint24 8388607 max_uint32: &max_uint32 4294967295 max_epoch: &max_epoch 3155630469184000000 - -# <=== Defaults ===> -default_attrs: &default - DEPEND_0: epoch - DISPLAY_TYPE: no_plot - FIELDNAM: " " - FILLVAL: *int_fillval - FORMAT: I12 - SCALETYP: linear - UNITS: dN - VALIDMIN: *min_int - VALIDMAX: *max_int - VAR_TYPE: data - -hskp_attrs: &hskp_default - <<: *default - FILLVAL: *uint8_fillval - VAR_TYPE: support_data - -hi_energies_attrs: &hi_energies_default - DISPLAY_TYPE: no_plot - FIELDNAM: Energy Table - FILLVAL: *real_fillval - FORMAT: F12.9 - SCALETYP: log - UNITS: MeV/n - VALIDMIN: 0.0 - VALIDMAX: 200.00 - VAR_TYPE: support_data - -hi_priorities_attrs: &hi_priorities_default - DEPEND_0: epoch - DISPLAY_TYPE: time_series - FILLVAL: -1 - FORMAT: I5 - LABLAXIS: "events" - UNITS: events - VALIDMIN: 0 - VALIDMAX: *max_uint32 - VAR_TYPE: data - - # <=== Coordinates ===> epoch_delta_minus: CATDESC: Time from acquisition start to acquisition center FIELDNAM: epoch_delta_minus - FILLVAL: *int_fillval - FORMAT: I18 + FILLVAL: *real_fillval + FORMAT: F30.9 LABLAXIS: epoch_delta_minus SCALETYP: linear UNITS: ns - VALIDMIN: *min_int VALIDMAX: *max_int + VALIDMIN: *min_int VAR_TYPE: support_data epoch_delta_plus: CATDESC: Time from acquisition center to acquisition end FIELDNAM: epoch_delta_plus - FILLVAL: *int_fillval - FORMAT: I18 + FILLVAL: *real_fillval + FORMAT: F30.9 LABLAXIS: epoch_delta_plus SCALETYP: linear UNITS: ns - VALIDMIN: *min_int - VALIDMAX: *max_int + VALIDMAX: *max_epoch + VALIDMIN: *min_epoch VAR_TYPE: support_data esa_step: @@ -92,8 +43,8 @@ esa_step: LABLAXIS: Energy Index SCALETYP: linear UNITS: " " - VALIDMIN: 0 VALIDMAX: 127 + VALIDMIN: 0 VAR_TYPE: support_data event_num: @@ -104,8 +55,8 @@ event_num: LABLAXIS: Event Number SCALETYP: linear UNITS: " " - VALIDMIN: 0 VALIDMAX: 10000 + VALIDMIN: 0 VAR_TYPE: support_data inst_az: @@ -116,8 +67,8 @@ inst_az: LABLAXIS: Azimuth Index SCALETYP: linear UNITS: " " - VALIDMIN: 0 VALIDMAX: 31 + VALIDMIN: 0 VAR_TYPE: support_data spin_sector: @@ -128,44 +79,44 @@ spin_sector: LABLAXIS: Spin Sector SCALETYP: linear UNITS: " " - VALIDMIN: 0 VALIDMAX: 12 + VALIDMIN: 0 VAR_TYPE: support_data spin_sector_pairs: - CATDESC: Spin sector Pairs + CATDESC: Spin sector pairs that are summed over onboard FIELDNAM: Spin Sector Pairs FILLVAL: -1 FORMAT: I1 LABLAXIS: " " SCALETYP: linear UNITS: " " - VALIDMIN: 0 VALIDMAX: 6 + VALIDMIN: 0 VAR_TYPE: support_data -spin_sector_index: - CATDESC: Spin Sector Index - FIELDNAM: Spin Sector Index - FILLVAL: -1 +priority: + CATDESC: Priority Level + FIELDNAM: Priority Level + FILLVAL: *uint32_fillval FORMAT: I2 LABLAXIS: " " SCALETYP: linear UNITS: " " + VALIDMAX: 7 VALIDMIN: 0 - VALIDMAX: 12 VAR_TYPE: support_data -ssd_index: - CATDESC: SSD Index - FIELDNAM: SSD Index - FILLVAL: -1 - FORMAT: I2 - LABLAXIS: " " +k_factor_attrs: + CATDESC: K Factor constant that is used to convert voltages to energies + DEPEND_1: k_factor + FIELDNAM: K Factor + FORMAT: F6.2 + LABLAXIS: K Factor SCALETYP: linear UNITS: " " - VALIDMIN: 0 - VALIDMAX: 12 + VALIDMAX: 100.0 + VALIDMIN: 1.0 VAR_TYPE: support_data # <=== Labels ===> @@ -197,13 +148,6 @@ spin_sector_label: FORMAT: A2 VAR_TYPE: metadata -spin_sector_index_label: - CATDESC: Spin Sector Index - DEPEND_1: spin_sector_index - FIELDNAM: Spin Sector Index - FORMAT: A2 - VAR_TYPE: metadata - spin_sector_pairs_label: CATDESC: Spin Sector Pairs DEPEND_1: spin_sector_pairs @@ -211,17 +155,25 @@ spin_sector_pairs_label: FORMAT: A11 VAR_TYPE: metadata -ssd_index_label: - CATDESC: SSD Index - DEPEND_1: ssd_index - FIELDNAM: SSD Index +priority_label: + CATDESC: Priority Level + DEPEND_1: priority + FIELDNAM: Priority Level + FORMAT: A2 + VAR_TYPE: metadata + +# Common energy labels for species for omni and sectored data +energy_species_label: + CATDESC: Energy Table for {species} + DEPEND_1: energy_{species} + FIELDNAM: energy_{species} FORMAT: A2 VAR_TYPE: metadata # <=== Dataset Variable Attributes ===> -# The following are set in multiple data products -acquisition_time_per_step: +acquisition_time_per_esa_step: CATDESC: Acquisition time for each step of energy + DEPEND_0: epoch DEPEND_1: esa_step FIELDNAM: Acquisition Time FILLVAL: *real_fillval @@ -229,39 +181,27 @@ acquisition_time_per_step: LABLAXIS: Acquisition Time SCALETYP: linear UNITS: ms - VALIDMIN: 0.000000 VALIDMAX: 625.000000 + VALIDMIN: 0.000000 VAR_TYPE: support_data -counters_attrs: &counters - <<: *default - CATDESC: Fill in at creation - DISPLAY_TYPE: time_series - FIELDNAM: Fill in at creation - FILLVAL: *uint32_fillval - FORMAT: I7 - SCALETYP: linear - UNITS: counts - VALIDMIN: 0 - VALIDMAX: *max_uint32 - VAR_TYPE: data - -events_attrs: &events - <<: *default - CATDESC: Fill in at creation - DISPLAY_TYPE: time_series - FIELDNAM: Fill in at creation - FILLVAL: -1 - FORMAT: I8 +half_spin_per_esa_step: + CATDESC: Half spin number for each step of energy + DEPEND_0: epoch + DEPEND_1: esa_step + FIELDNAM: Half Spin Number + FILLVAL: 63 + FORMAT: I3 + LABLAXIS: Half Spin Number SCALETYP: linear - UNITS: counts + UNITS: half spin number + VALIDMAX: 63 VALIDMIN: 0 - VALIDMAX: *max_uint32 - VAR_TYPE: data + VAR_TYPE: support_data data_quality: - <<: *default CATDESC: Indicates whether data quality is suspect (1). + DEPEND_0: epoch DISPLAY_TYPE: time_series FIELDNAM: Data Quality FILLVAL: 255 @@ -269,77 +209,141 @@ data_quality: LABLAXIS: Data Quality SCALETYP: linear UNITS: " " - VALIDMIN: 0 VALIDMAX: 1 + VALIDMIN: 0 VAR_TYPE: data -direct_events_attrs: &direct_events - <<: *default - CATDESC: Fill in at creation +packet_version: + CATDESC: Packet version. Incremented each time the format of the packet changes. + DEPEND_0: epoch DISPLAY_TYPE: time_series - FIELDNAM: Fill in at creation - FILLVAL: 255 + FIELDNAM: Packet Version + FILLVAL: 65535 FORMAT: I5 - UNITS: unitless + LABLAXIS: Packet Version + SCALETYP: linear + UNITS: " " + VALIDMAX: 65535 VALIDMIN: 0 - VALIDMAX: 10000 + VAR_TYPE: data -energy_table: - CATDESC: ElectroStatic Analyzer Energy Values +voltage_table: + CATDESC: ElectroStatic Analyzer Voltage Values DEPEND_1: esa_step - FIELDNAM: Energy Table + FIELDNAM: Voltage Table FORMAT: F12.6 - LABLAXIS: eV + LABLAXIS: V SCALETYP: log - UNITS: eV - VALIDMIN: 1.0 + UNITS: V VALIDMAX: 14100.0 + VALIDMIN: 0.5 VAR_TYPE: support_data k_factor: CATDESC: K Factor constant that is used to convert voltages to energies + DEPEND_1: k_factor FIELDNAM: K Factor - FORMAT: F5.2 + FORMAT: F6.2 LABLAXIS: K Factor SCALETYP: linear UNITS: " " - VALIDMIN: 1.0 VALIDMAX: 100.0 + VALIDMIN: 1.0 VAR_TYPE: support_data nso_half_spin: - <<: *default CATDESC: When No Scan Operation (NSO) was activated + DEPEND_0: epoch DISPLAY_TYPE: time_series - FIELDNAM: NSO Mode + FIELDNAM: NSO Half Spin FILLVAL: 255 FORMAT: I3 LABLAXIS: NSO Half Spin SCALETYP: linear UNITS: half spin number + VALIDMAX: 255 + VALIDMIN: 0 + VAR_NOTES: Indicates the half spin when No Scan Operation (NSO) was activated. In NSO, the ESA voltage is set to the first step in the scan and remains fixed until the next cycle boundary. + VAR_TYPE: data + +nso_spin_sector: + CATDESC: Spin Sector When No Scan Operation (NSO) was activated + DEPEND_0: epoch + DISPLAY_TYPE: time_series + FIELDNAM: NSO Spin Sector + FILLVAL: 255 + FORMAT: I3 + LABLAXIS: NSO Spin Sector + SCALETYP: linear + UNITS: spin sector + VALIDMAX: 255 VALIDMIN: 0 + VAR_NOTES: Indicates the spin sector when No Scan Operation (NSO) was activated. In NSO, the ESA voltage is set to the first step in the scan and remains fixed until the next cycle boundary. + VAR_TYPE: data + +nso_esa_step: + CATDESC: Energy Step When No Scan Operation (NSO) was activated + DEPEND_0: epoch + DISPLAY_TYPE: time_series + FIELDNAM: NSO Energy Step + FILLVAL: 255 + FORMAT: I3 + LABLAXIS: NSO Energy Step + SCALETYP: linear + UNITS: energy step VALIDMAX: 255 - VAR_NOTES: Indicates the point when No Scan Operation (NSO) was activated. In NSO, the ESA voltage is set to the first step in the scan and remains fixed until the next cycle boundary. + VALIDMIN: 0 + VAR_NOTES: Indicates the energy step when No Scan Operation (NSO) was activated. In NSO, the ESA voltage is set to the first step in the scan and remains fixed until the next cycle boundary. VAR_TYPE: data rgfo_half_spin: - <<: *default - CATDESC: When Reduced Gain Factor Operation (RGFO) was activated + CATDESC: Half Spin When Reduced Gain Factor Operation (RGFO) was activated + DEPEND_0: epoch DISPLAY_TYPE: time_series - FIELDNAM: RGFO Mode + FIELDNAM: RGFO Half Spin FILLVAL: 255 FORMAT: I3 LABLAXIS: RGFO Half Spin SCALETYP: linear UNITS: half spin number + VALIDMAX: 255 VALIDMIN: 0 + VAR_NOTES: Indicates the half spin when Reduced Gain Factor Operation (RGFO) was activated. In RGFO, the Entrance ESA voltage is reduced in order to limit the number of ions that reach the detectors. + VAR_TYPE: data + +rgfo_spin_sector: + CATDESC: Spin Sector When Reduced Gain Factor Operation (RGFO) was activated + DEPEND_0: epoch + DISPLAY_TYPE: time_series + FIELDNAM: RGFO Spin Sector + FILLVAL: 255 + FORMAT: I3 + LABLAXIS: RGFO Spin Sector + SCALETYP: linear + UNITS: spin sector + VALIDMAX: 255 + VALIDMIN: 0 + VAR_NOTES: Indicates the spin sector when Reduced Gain Factor Operation (RGFO) was activated. In RGFO, the Entrance ESA voltage is reduced in order to limit the number of ions that reach the detectors. + VAR_TYPE: data + +rgfo_esa_step: + CATDESC: Energy Step When Reduced Gain Factor Operation (RGFO) was activated + DEPEND_0: epoch + DISPLAY_TYPE: time_series + FIELDNAM: RGFO Energy Step + FILLVAL: 255 + FORMAT: I3 + LABLAXIS: RGFO Energy Step + SCALETYP: linear + UNITS: energy step VALIDMAX: 255 - VAR_NOTES: Indicates the point when Reduced Gain Factor Operation (RGFO) was activated. In RGFO, the Entrance ESA voltage is reduced in order to limit the number of ions that reach the detectors. + VALIDMIN: 0 + VAR_NOTES: Indicates the energy step when Reduced Gain Factor Operation (RGFO) was activated. In RGFO, the Entrance ESA voltage is reduced in order to limit the number of ions that reach the detectors. VAR_TYPE: data spin_period: - <<: *default CATDESC: The spin period as reported by the spacecraft. + DEPEND_0: epoch DISPLAY_TYPE: time_series FIELDNAM: Spin Period FILLVAL: *real_fillval @@ -347,13 +351,13 @@ spin_period: LABLAXIS: Spin Period SCALETYP: linear UNITS: s - VALIDMIN: 0.0 VALIDMAX: 16.0 + VALIDMIN: 0.0 VAR_TYPE: data st_bias_gain_mode: - <<: *default CATDESC: Suprathermal Bias Gain Mode + DEPEND_0: epoch DISPLAY_TYPE: no_plot FIELDNAM: Suprathermal Bias Gain Mode FILLVAL: 255 @@ -361,14 +365,14 @@ st_bias_gain_mode: LABLAXIS: Suprathermal Bias Gain Mode SCALETYP: linear UNITS: " " - VALIDMIN: 0 VALIDMAX: 1 + VALIDMIN: 0 VAR_NOTES: Indicates whether FSW is tracking the Suprathermal High-Gain bias curve or the Suprathermal Low-Gain bias curve. VAR_TYPE: data sw_bias_gain_mode: - <<: *default CATDESC: Solarwind Bias Gain Mode + DEPEND_0: epoch DISPLAY_TYPE: no_plot FIELDNAM: Solarwind Bias Gain Mode FILLVAL: 255 @@ -376,3084 +380,553 @@ sw_bias_gain_mode: LABLAXIS: Solarwind Bias Gain Mode SCALETYP: linear UNITS: " " - VALIDMIN: 0 VALIDMAX: 1 + VALIDMIN: 0 VAR_NOTES: Indicates whether FSW is tracking the Solarwind High-Gain bias curve or the Solarwind Low-Gain bias curve. VAR_TYPE: data -# The following are data product-specific -# hi-counters-aggregated -hi-counters-aggregated-dcr: - <<: *events +# <=== Counter Variables Base Templates ===> +# Shared base for all counter data (Hi & Lo) +counters_base: &counters_base + DEPEND_0: epoch + DISPLAY_TYPE: time_series + FILLVAL: *real_fillval + FORMAT: F32.9 + SCALETYP: linear + UNITS: counts + VALIDMAX: *max_uint32 + VALIDMIN: 0 + VAR_TYPE: data + +# <=== Hi-counters-aggregated ===> +hi_counters_aggregated_default: &hi_counters_aggregated_default + <<: *counters_base + LABLAXIS: "events" + +hi-dcr: + <<: *hi_counters_aggregated_default CATDESC: Event B - Double Coincidence Rate (DCR) FIELDNAM: DCRs - LABLAXIS: "events" -hi-counters-aggregated-sto: - <<: *events +hi-starts_only: + <<: *hi_counters_aggregated_default CATDESC: Event C - Start Only (STO) FIELDNAM: Start Only - LABLAXIS: "events" -hi-counters-aggregated-spo: - <<: *events +hi-stops_only: + <<: *hi_counters_aggregated_default CATDESC: Event D - Stop Only (SPO) FIELDNAM: Stop Only - LABLAXIS: "events" -hi-counters-aggregated-reserved1: - <<: *events - CATDESC: Reserved 1 - FIELDNAM: Reserved 1 - LABLAXIS: "events" - -hi-counters-aggregated-mst: - <<: *events +hi-mst: + <<: *hi_counters_aggregated_default CATDESC: Event H - Multi Start (MST) FIELDNAM: Multi Start - LABLAXIS: "events" - -hi-counters-aggregated-reserved2: - <<: *events - CATDESC: Reserved 2 - FIELDNAM: Reserved 2 - LABLAXIS: "events" - -hi-counters-aggregated-reserved3: - <<: *events - CATDESC: Reserved 3 - FIELDNAM: Reserved 3 - LABLAXIS: "events" -hi-counters-aggregated-reserved4: - <<: *events - CATDESC: Reserved 4 - FIELDNAM: Reserved 4 - LABLAXIS: "events" +hi-singles_starts: + <<: *hi_counters_aggregated_default + CATDESC: Singles - Start + FIELDNAM: Singles - Start -hi-counters-aggregated-reserved5: - <<: *events - CATDESC: Reserved 5 - FIELDNAM: Reserved 5 - LABLAXIS: "events" +hi-singles_stops: + <<: *hi_counters_aggregated_default + CATDESC: Singles - Stop + FIELDNAM: Singles - Stop -hi-counters-aggregated-low_tof_cutoff: - <<: *events +hi-low_tof_cutoff: + <<: *hi_counters_aggregated_default CATDESC: Low TOF Cutoff FIELDNAM: Low TOF Cutoff - LABLAXIS: "events" - -hi-counters-aggregated-reserved6: - <<: *events - CATDESC: Reserved 6 - FIELDNAM: Reserved 6 - LABLAXIS: "events" -hi-counters-aggregated-reserved7: - <<: *events - CATDESC: Reserved 7 - FIELDNAM: Reserved 7 - LABLAXIS: "events" - -hi-counters-aggregated-asic1_flag_invalid: - <<: *events +hi-asic1_flag_invalid: + <<: *hi_counters_aggregated_default CATDESC: ASIC 1 Flag Invalid Count FIELDNAM: ASIC 1 Flag Invalid - LABLAXIS: "events" -hi-counters-aggregated-asic2_flag_invalid: - <<: *events +hi-asic2_flag_invalid: + <<: *hi_counters_aggregated_default CATDESC: ASIC 2 Flag Invalid Count FIELDNAM: ASIC 2 Flag Invalid - LABLAXIS: "events" -hi-counters-aggregated-asic1_channel_invalid: - <<: *events +hi-asic1_channel_invalid: + <<: *hi_counters_aggregated_default CATDESC: ASIC 1 Channel Invalid Count FIELDNAM: ASIC 1 Channel Invalid - LABLAXIS: "events" - -hi-counters-aggregated-asic2_channel_invalid: - <<: *events +hi-asic2_channel_invalid: + <<: *hi_counters_aggregated_default CATDESC: ASIC 2 Channel Invalid Count FIELDNAM: ASIC 2 Channel Invalid - LABLAXIS: "events" -# hi-counters-singles -hi-counters-singles-tcr: - <<: *counters - CATDESC: Rates - Event A (TCR) +# <=== Hi-counters-singles ===> +hi_counters_singles_default: &hi_counters_singles_default + <<: *counters_base + DEPEND_1: inst_az + LABL_PTR_1: inst_az_label + +hi-tcr: + <<: *hi_counters_singles_default + CATDESC: Event A - Triple Coincidence Rate (TCR) FIELDNAM: Rates - DEPEND_1: ssd_index - LABL_PTR_1: ssd_index_label - UNITS: events -hi-counters-singles-ssdo: - <<: *counters +hi-ssdo: + <<: *hi_counters_singles_default CATDESC: Rates - Event E (SSDO) FIELDNAM: Rates - DEPEND_1: ssd_index - LABL_PTR_1: ssd_index_label - UNITS: events -hi-counters-singles-stssd: - <<: *counters +hi-stssd: + <<: *hi_counters_singles_default CATDESC: Rates - Event G (STSSD) FIELDNAM: Rates - DEPEND_1: ssd_index - LABL_PTR_1: ssd_index_label - UNITS: events -# hi-ialirt -hi-ialirt-h: - <<: *counters - CATDESC: Omnidirectional H Counts - FIELDNAM: H - DEPEND_1: energy_h - LABL_PTR_1: energy_h +# Hi omni and sectored Attributes +hi-species-attrs: + CATDESC: Omnidirectional {species} counts + DEPEND_0: epoch + DEPEND_1: energy_{species} + DISPLAY_TYPE: time_series + FIELDNAM: Species {species} + FILLVAL: *real_fillval + FORMAT: F32.9 + LABL_PTR_1: energy_{species}_label + SCALETYP: linear + UNITS: counts + VALIDMAX: *max_uint32 + VALIDMIN: 0.0 + VAR_TYPE: data + +hi-species-unc-attrs: + CATDESC: Omnidirectional {species} counts uncertainty + DEPEND_0: epoch + DEPEND_1: energy_{species} + DISPLAY_TYPE: time_series + FIELDNAM: Species {species} + FILLVAL: *real_fillval + FORMAT: F32.9 + LABL_PTR_1: energy_{species}_label + SCALETYP: linear + UNITS: counts VALIDMAX: *max_uint32 + VALIDMIN: 0.0 + VAR_TYPE: data + +hi-energy-attrs: + CATDESC: Energy Table for {species} + DELTA_MINUS_VAR: energy_{species}_minus + DELTA_PLUS_VAR: energy_{species}_plus + DISPLAY_TYPE: no_plot + FIELDNAM: Energy Table + FILLVAL: *real_fillval + FORMAT: F12.9 + SCALETYP: log + UNITS: MeV/n + VALIDMAX: 200.00 + VALIDMIN: 0.0 + VAR_TYPE: support_data + +hi-energy-delta-attrs: + CATDESC: Energy Table {operation} value for {species} + DELTA_MINUS_VAR: energy_{species}_minus + DELTA_PLUS_VAR: energy_{species}_plus + DEPEND_0: energy_{species} + DISPLAY_TYPE: no_plot + FIELDNAM: Energy Delta {operation} + FILLVAL: *real_fillval + FORMAT: F12.9 + SCALETYP: log + UNITS: MeV/n + VALIDMAX: 200.00 + VALIDMIN: 0.0 + VAR_TYPE: support_data -hi-ialirt-energy_h: - <<: *hi_energies_default - CATDESC: Energy Table for h - DELTA_MINUS_VAR: energy_h_minus - DELTA_PLUS_VAR: energy_h_plus - -hi-ialirt-energy_h_minus: - <<: *hi_energies_default - CATDESC: Energy Table Minus Value for h - FIELDNAM: Energy Delta Minus - -hi-ialirt-energy_h_plus: - <<: *hi_energies_default - CATDESC: Energy Table Plus Value for h - FIELDNAM: Energy Delta Plus - -# hi-omni -hi-omni-h: - <<: *counters - CATDESC: Omnidirectional H Counts - FIELDNAM: H - DEPEND_1: energy_h - LABL_PTR_1: energy_h - -hi-omni-energy_h: - <<: *hi_energies_default - CATDESC: Energy Table for h - DELTA_MINUS_VAR: energy_h_minus - DELTA_PLUS_VAR: energy_h_plus - -hi-omni-energy_h_minus: - <<: *hi_energies_default - CATDESC: Energy Table Minus Value for h - FIELDNAM: Energy Delta Minus - -hi-omni-energy_h_plus: - <<: *hi_energies_default - CATDESC: Energy Table Plus Value for h - FIELDNAM: Energy Delta Plus - -hi-omni-he3: - <<: *counters - CATDESC: Omnidirectional He3 Counts - FIELDNAM: He3 - DEPEND_1: energy_he3 - LABL_PTR_1: energy_he3 - -hi-omni-energy_he3: - <<: *hi_energies_default - CATDESC: Energy Table for he3 - DELTA_MINUS_VAR: energy_he3_minus - DELTA_PLUS_VAR: energy_he3_plus - -hi-omni-energy_he3_minus: - <<: *hi_energies_default - CATDESC: Energy Table Minus Value for he3 - FIELDNAM: Energy Delta Minus - -hi-omni-energy_he3_plus: - <<: *hi_energies_default - CATDESC: Energy Table Plus Value for he3 - FIELDNAM: Energy Delta Plus - -hi-omni-he4: - <<: *counters - CATDESC: Omnidirectional He4 Counts - FIELDNAM: He4 - DEPEND_1: energy_he4 - LABL_PTR_1: energy_he4 - -hi-omni-energy_he4: - <<: *hi_energies_default - CATDESC: Energy Table for he4 - DELTA_MINUS_VAR: energy_he4_minus - DELTA_PLUS_VAR: energy_he4_plus - -hi-omni-energy_he4_minus: - <<: *hi_energies_default - CATDESC: Energy Table Minus Value for he4 - FIELDNAM: Energy Delta Minus - -hi-omni-energy_he4_plus: - <<: *hi_energies_default - CATDESC: Energy Table Plus Value for he4 - FIELDNAM: Energy Delta Plus - -hi-omni-c: - <<: *counters - CATDESC: Omnidirectional C Counts - FIELDNAM: C - DEPEND_1: energy_c - LABL_PTR_1: energy_c - -hi-omni-energy_c: - <<: *hi_energies_default - CATDESC: Energy Table for c - DELTA_MINUS_VAR: energy_c_minus - DELTA_PLUS_VAR: energy_c_plus - -hi-omni-energy_c_minus: - <<: *hi_energies_default - CATDESC: Energy Table Minus Value for c - FIELDNAM: Energy Delta Minus - -hi-omni-energy_c_plus: - <<: *hi_energies_default - CATDESC: Energy Table Plus Value for c - FIELDNAM: Energy Delta Plus - -hi-omni-o: - <<: *counters - CATDESC: Omnidirectional O Counts - FIELDNAM: O - DEPEND_1: energy_o - LABL_PTR_1: energy_o - -hi-omni-energy_o: - <<: *hi_energies_default - CATDESC: Energy Table for o - DELTA_MINUS_VAR: energy_o_minus - DELTA_PLUS_VAR: energy_o_plus - -hi-omni-energy_o_minus: - <<: *hi_energies_default - CATDESC: Energy Table Minus Value for o - FIELDNAM: Energy Delta Minus - -hi-omni-energy_o_plus: - <<: *hi_energies_default - CATDESC: Energy Table Plus Value for o - FIELDNAM: Energy Delta Plus - -hi-omni-ne_mg_si: - <<: *counters - CATDESC: Omnidirectional Ne_Mg_Si Counts - FIELDNAM: Ne_Mg_Si - DEPEND_1: energy_ne_mg_si - LABL_PTR_1: energy_ne_mg_si - -hi-omni-energy_ne_mg_si: - <<: *hi_energies_default - CATDESC: Energy Table for ne_mg_si - DELTA_MINUS_VAR: energy_ne_mg_si_minus - DELTA_PLUS_VAR: energy_ne_mg_si_plus - -hi-omni-energy_ne_mg_si_minus: - <<: *hi_energies_default - CATDESC: Energy Table Minus Value for ne_mg_si - FIELDNAM: Energy Delta Minus - -hi-omni-energy_ne_mg_si_plus: - <<: *hi_energies_default - CATDESC: Energy Table Plus Value for ne_mg_si - FIELDNAM: Energy Delta Plus - -hi-omni-fe: - <<: *counters - CATDESC: Omnidirectional Fe Counts - FIELDNAM: Fe - DEPEND_1: energy_fe - LABL_PTR_1: energy_fe - -hi-omni-energy_fe: - <<: *hi_energies_default - CATDESC: Energy Table for fe - DELTA_MINUS_VAR: energy_fe_minus - DELTA_PLUS_VAR: energy_fe_plus - -hi-omni-energy_fe_minus: - <<: *hi_energies_default - CATDESC: Energy Table Minus Value for fe - FIELDNAM: Energy Delta Minus - -hi-omni-energy_fe_plus: - <<: *hi_energies_default - CATDESC: Energy Table Plus Value for fe - FIELDNAM: Energy Delta Plus - -hi-omni-uh: - <<: *counters - CATDESC: Omnidirectional UH Counts - FIELDNAM: UH - DEPEND_1: energy_uh - LABL_PTR_1: energy_uh - -hi-omni-energy_uh: - <<: *hi_energies_default - CATDESC: Energy Table for uh - DELTA_MINUS_VAR: energy_uh_minus - DELTA_PLUS_VAR: energy_uh_plus - -hi-omni-energy_uh_minus: - <<: *hi_energies_default - CATDESC: Energy Table Minus Value for uh - FIELDNAM: Energy Delta Minus - -hi-omni-energy_uh_plus: - <<: *hi_energies_default - CATDESC: Energy Table Plus Value for uh - FIELDNAM: Energy Delta Plus - -hi-omni-junk: - <<: *counters - CATDESC: Junk (Root 2 spacing) - FIELDNAM: Junk - DEPEND_1: energy_junk - LABL_PTR_1: energy_junk - -hi-omni-energy_junk: - <<: *hi_energies_default - CATDESC: Energy Table for junk - DELTA_MINUS_VAR: energy_junk_minus - DELTA_PLUS_VAR: energy_junk_plus - -hi-omni-energy_junk_minus: - <<: *hi_energies_default - CATDESC: Energy Table Minus Value for junk - FIELDNAM: Energy Delta Minus - -hi-omni-energy_junk_plus: - <<: *hi_energies_default - CATDESC: Energy Table Plus Value for junk - FIELDNAM: Energy Delta Plus # hi-priority -hi-priority-Priority0: +hi_priorities_attrs: &hi_priorities_default + DEPEND_0: epoch + DISPLAY_TYPE: time_series + FILLVAL: *real_fillval + FORMAT: F32.9 + LABLAXIS: "events" + UNITS: events + VALIDMAX: *real_fillval + VALIDMIN: 0.0 + VAR_TYPE: data + +priority0: <<: *hi_priorities_default CATDESC: Priority 0 FIELDNAM: Priority 0 -hi-priority-Priority1: +priority1: <<: *hi_priorities_default CATDESC: Priority 1 FIELDNAM: Priority 1 -hi-priority-Priority2: +priority2: <<: *hi_priorities_default CATDESC: Priority 2 FIELDNAM: Priority 2 -hi-priority-Priority3: +priority3: <<: *hi_priorities_default CATDESC: Priority 3 FIELDNAM: Priority 3 -hi-priority-Priority4: +priority4: <<: *hi_priorities_default CATDESC: Priority 4 FIELDNAM: Priority 4 -hi-priority-Priority5: +priority5: <<: *hi_priorities_default CATDESC: Priority 5 FIELDNAM: Priority 5 -# hi-sectored -hi-sectored-h: - <<: *counters - CATDESC: Sectored H Counts - FIELDNAM: H - DEPEND_1: energy_h - DEPEND_2: ssd_index - DEPEND_3: spin_sector_index - LABL_PTR_1: energy_h - LABL_PTR_2: ssd_index_label - LABL_PTR_3: spin_sector_index_label - -hi-sectored-energy_h: - <<: *hi_energies_default - CATDESC: Energy Table for H - DELTA_MINUS_VAR: energy_h_minus - DELTA_PLUS_VAR: energy_h_plus - -hi-sectored-energy_h_minus: - <<: *hi_energies_default - CATDESC: Energy Table Minus Value for h - FIELDNAM: Energy Delta Minus - -hi-sectored-energy_h_plus: - <<: *hi_energies_default - CATDESC: Energy Table Plus Value for h - FIELDNAM: Energy Delta Plus - -hi-sectored-he3he4: - <<: *counters - CATDESC: Sectored He3He4 Counts - FIELDNAM: He3He4 - DEPEND_1: energy_he3he4 - DEPEND_2: ssd_index - DEPEND_3: spin_sector_index - LABL_PTR_1: energy_he3he4 - LABL_PTR_2: ssd_index_label - LABL_PTR_3: spin_sector_index_label - -hi-sectored-energy_he3he4: - <<: *hi_energies_default - CATDESC: Energy Table for He3He4 - DELTA_MINUS_VAR: energy_he3he4_minus - DELTA_PLUS_VAR: energy_he3he4_plus - -hi-sectored-energy_he3he4_minus: - <<: *hi_energies_default - CATDESC: Energy Table Minus Value for he3he4 - FIELDNAM: Energy Delta Minus - -hi-sectored-energy_he3he3_plus: - <<: *hi_energies_default - CATDESC: Energy Table Plus Value for he3he3 - FIELDNAM: Energy Delta Plus - -hi-sectored-cno: - <<: *counters - CATDESC: Sectored CNO Counts - FIELDNAM: CNO - DEPEND_1: energy_cno - DEPEND_2: ssd_index - DEPEND_3: spin_sector_index - LABL_PTR_1: energy_cno - LABL_PTR_2: ssd_index_label - LABL_PTR_3: spin_sector_index_label - -hi-sectored-energy_cno: - <<: *hi_energies_default - CATDESC: Energy Table for CNO - DELTA_MINUS_VAR: energy_cno_minus - DELTA_PLUS_VAR: energy_cno_plus - -hi-sectored-energy_cno_minus: - <<: *hi_energies_default - CATDESC: Energy Table Minus Value for cno - FIELDNAM: Energy Delta Minus - -hi-sectored-energy_cno_plus: - <<: *hi_energies_default - CATDESC: Energy Table Plus Value for cno - FIELDNAM: Energy Delta Plus - -hi-sectored-fe: - <<: *counters - CATDESC: Sectored Fe Counts - FIELDNAM: Fe - DEPEND_1: energy_fe - DEPEND_2: ssd_index - DEPEND_3: spin_sector_index - LABL_PTR_1: energy_fe - LABL_PTR_2: ssd_index_label - LABL_PTR_3: spin_sector_index_label - -hi-sectored-energy_fe: - <<: *hi_energies_default - CATDESC: Energy Table for Fe - DELTA_MINUS_VAR: energy_fe_minus - DELTA_PLUS_VAR: energy_fe_plus - -hi-sectored-energy_fe_minus: - <<: *hi_energies_default - CATDESC: Energy Table Minus Value for fe - FIELDNAM: Energy Delta Minus - -hi-sectored-energy_fe_plus: - <<: *hi_energies_default - CATDESC: Energy Table Plus Value for fe - FIELDNAM: Energy Delta Plus - -# lo-counters-aggregated -lo-counters-aggregated-tcr: - <<: *events - CATDESC: Triple Coincidence Rate - FIELDNAM: Event A - Triple Coincidence Rate - DEPEND_1: spin_sector_pairs - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_pairs_label - LABL_PTR_2: esa_step_label - -lo-counters-aggregated-dcr: - <<: *events - CATDESC: Double Coincidence Rate - FIELDNAM: Event B - Double Coincidence Rate - DEPEND_1: spin_sector_pairs - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_pairs_label - LABL_PTR_2: esa_step_label +# <=== Lo-counters-aggregated ===> +lo_counters_aggregated_default: &lo_counters_aggregated_default + <<: *counters_base + DEPEND_0: epoch + DEPEND_1: esa_step + DEPEND_2: spin_sector_pairs + LABL_PTR_1: esa_step_label + LABL_PTR_2: spin_sector_pairs_label -lo-counters-aggregated-tof_plus_apd: - <<: *events - CATDESC: TOF + APD - FIELDNAM: Event C - TOF + APD - DEPEND_1: spin_sector_pairs - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_pairs_label - LABL_PTR_2: esa_step_label +lo-tcr: + <<: *lo_counters_aggregated_default + CATDESC: Triple Coincidence Rate (TCR) + FIELDNAM: Event A - TCR -lo-counters-aggregated-tof_only: - <<: *events - CATDESC: TOF Only - FIELDNAM: Event D - TOF Only - DEPEND_1: spin_sector_pairs - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_pairs_label - LABL_PTR_2: esa_step_label +lo-dcr: + <<: *lo_counters_aggregated_default + CATDESC: Double Coincidence Rate (DCR) + FIELDNAM: Event B - DCR -lo-counters-aggregated-position_plus_apd: - <<: *events - CATDESC: Position + APD - FIELDNAM: Event E - Position + APD - DEPEND_1: spin_sector_pairs - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_pairs_label - LABL_PTR_2: esa_step_label +lo-low_tof_cutoff: + <<: *lo_counters_aggregated_default + CATDESC: Low TOF Cutoff + FIELDNAM: Low TOF Cutoff -lo-counters-aggregated-position_only: - <<: *events - CATDESC: Position Only - FIELDNAM: Event F - Position Only - DEPEND_1: spin_sector_pairs - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_pairs_label - LABL_PTR_2: esa_step_label +lo-asic1_flag_invalid: + <<: *lo_counters_aggregated_default + CATDESC: ASIC 1 Flag Invalid Count + FIELDNAM: ASIC 1 Flag Invalid + +lo-asic2_flag_invalid: + <<: *lo_counters_aggregated_default + CATDESC: ASIC 2 Flag Invalid Count + FIELDNAM: ASIC 2 Flag Invalid + +lo-asic1_channel_invalid: + <<: *lo_counters_aggregated_default + CATDESC: ASIC 1 Channel Invalid Count + FIELDNAM: ASIC 1 Channel Invalid +lo-asic2_channel_invalid: + <<: *lo_counters_aggregated_default + CATDESC: ASIC 2 Channel Invalid Count + FIELDNAM: ASIC 2 Channel Invalid + +lo-tof_plus_apd: + <<: *lo_counters_aggregated_default + CATDESC: TOF + APD + FIELDNAM: Event C - TOF + APD + +lo-tof_only: + <<: *lo_counters_aggregated_default + CATDESC: TOF Only + FIELDNAM: Event D - TOF Only + +lo-position_plus_apd: + <<: *lo_counters_aggregated_default + CATDESC: Position + APD + FIELDNAM: Event E - Position + APD + +lo-position_only: + <<: *lo_counters_aggregated_default + CATDESC: Position Only + FIELDNAM: Event F - Position Only -lo-counters-aggregated-sta_or_stb_plus_apd: - <<: *events +lo-sta_or_stb_plus_apd: + <<: *lo_counters_aggregated_default CATDESC: STA or STB + APD FIELDNAM: Event G - STA or STB + APD - DEPEND_1: spin_sector_pairs - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_pairs_label - LABL_PTR_2: esa_step_label -lo-counters-aggregated-sta_or_stb_only: - <<: *events +lo-sta_or_stb_only: + <<: *lo_counters_aggregated_default CATDESC: STA or STB Only - FIELDNAM: Event H - STA or STB Only - DEPEND_1: spin_sector_pairs - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_pairs_label - LABL_PTR_2: esa_step_label - -lo-counters-aggregated-reserved1: - <<: *events - CATDESC: Reserved - FIELDNAM: Reserved 1 - DEPEND_1: spin_sector_pairs - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_pairs_label - LABL_PTR_2: esa_step_label - -lo-counters-aggregated-reserved2: - <<: *events - CATDESC: Reserved - FIELDNAM: Reserved 2 - DEPEND_1: spin_sector_pairs - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_pairs_label - LABL_PTR_2: esa_step_label + FIELDNAM: Event H - STA or STB Onlys -lo-counters-aggregated-sp_only: - <<: *events +lo-sp_only: + <<: *lo_counters_aggregated_default CATDESC: SP Only FIELDNAM: Event K - SP Only - DEPEND_1: spin_sector_pairs - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_pairs_label - LABL_PTR_2: esa_step_label -lo-counters-aggregated-apd_only: - <<: *events +lo-apd_only: + <<: *lo_counters_aggregated_default CATDESC: APD Only FIELDNAM: Event L - APD Only - DEPEND_1: spin_sector_pairs - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_pairs_label - LABL_PTR_2: esa_step_label -lo-counters-aggregated-low_tof_cutoff: - <<: *events - CATDESC: Low TOF Cutoff - FIELDNAM: Low TOF Cutoff - DEPEND_1: spin_sector_pairs - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_pairs_label - LABL_PTR_2: esa_step_label - -lo-counters-aggregated-sta: - <<: *events +lo-sta: + <<: *lo_counters_aggregated_default CATDESC: Start A FIELDNAM: Singles - Start-A (STA) - DEPEND_1: spin_sector_pairs - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_pairs_label - LABL_PTR_2: esa_step_label -lo-counters-aggregated-stb: - <<: *events +lo-stb: + <<: *lo_counters_aggregated_default CATDESC: Start B FIELDNAM: Singles - Start-B (STB) - DEPEND_1: spin_sector_pairs - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_pairs_label - LABL_PTR_2: esa_step_label -lo-counters-aggregated-sp: - <<: *events +lo-sp: + <<: *lo_counters_aggregated_default CATDESC: Stop FIELDNAM: Singles - Stop (SP) - DEPEND_1: spin_sector_pairs - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_pairs_label - LABL_PTR_2: esa_step_label -lo-counters-aggregated-total_position_count: - <<: *events +lo-total_position_count: + <<: *lo_counters_aggregated_default CATDESC: Total Position Count FIELDNAM: Singles - Total Position Count - DEPEND_1: spin_sector_pairs - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_pairs_label - LABL_PTR_2: esa_step_label -lo-counters-aggregated-invalid_position_count: - <<: *events +lo-invalid_position_count: + <<: *lo_counters_aggregated_default CATDESC: Invalid Position Count FIELDNAM: Singles - Invalid Position Count - DEPEND_1: spin_sector_pairs - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_pairs_label - LABL_PTR_2: esa_step_label - -lo-counters-aggregated-asic1_flag_invalid: - <<: *events - CATDESC: ASIC 1 Flag Invalid - FIELDNAM: ASIC 1 Flag Invalid Count - DEPEND_1: spin_sector_pairs - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_pairs_label - LABL_PTR_2: esa_step_label - -lo-counters-aggregated-asic2_flag_invalid: - <<: *events - CATDESC: ASIC 2 Flag Invalid - FIELDNAM: ASIC 2 Flag Invalid Count - DEPEND_1: spin_sector_pairs - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_pairs_label - LABL_PTR_2: esa_step_label - -lo-counters-aggregated-asic1_channel_invalid: - <<: *events - CATDESC: ASIC 1 Channel Invalid - FIELDNAM: ASIC 1 Channel Invalid Count - DEPEND_1: spin_sector_pairs - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_pairs_label - LABL_PTR_2: esa_step_label - -lo-counters-aggregated-asic2_channel_invalid: - <<: *events - CATDESC: ASIC 2 Channel Invalid - FIELDNAM: ASIC 2 Channel Invalid Count - DEPEND_1: spin_sector_pairs - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_pairs_label - LABL_PTR_2: esa_step_label -lo-counters-aggregated-tec4_timeout_tof_no_pos: - <<: *events +lo-tec4_timeout_tof_no_pos: + <<: *lo_counters_aggregated_default CATDESC: TEC-4 Timeout TOF no Position FIELDNAM: TEC-4 Timeout Count; TOF, No Position - DEPEND_1: spin_sector_pairs - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_pairs_label - LABL_PTR_2: esa_step_label -lo-counters-aggregated-tec4_timeout_pos_no_tof: - <<: *events +lo-tec4_timeout_pos_no_tof: + <<: *lo_counters_aggregated_default CATDESC: TEC-4 Timeout Position no TOF FIELDNAM: TEC-4 Timeout Count; Position, No TOF - DEPEND_1: spin_sector_pairs - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_pairs_label - LABL_PTR_2: esa_step_label -lo-counters-aggregated-tec4_timeout_no_pos_tof: - <<: *events +lo-tec4_timeout_no_pos_tof: + <<: *lo_counters_aggregated_default CATDESC: TEC-4 Timeout No Position or TOF FIELDNAM: TEC-4 Timeout Count; No Position or TOF - DEPEND_1: spin_sector_pairs - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_pairs_label - LABL_PTR_2: esa_step_label -lo-counters-aggregated-tec5_timeout_tof_no_pos: - <<: *events +lo-tec5_timeout_tof_no_pos: + <<: *lo_counters_aggregated_default CATDESC: TEC-5 Timeout TOF no Position FIELDNAM: TEC-5 Timeout Count; TOF, No Position - DEPEND_1: spin_sector_pairs - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_pairs_label - LABL_PTR_2: esa_step_label -lo-counters-aggregated-tec5_timeout_pos_no_tof: - <<: *events +lo-tec5_timeout_pos_no_tof: + <<: *lo_counters_aggregated_default CATDESC: TEC-5 Timeout Position no TOF FIELDNAM: TEC-5 Timeout Count; Position, No TOF - DEPEND_1: spin_sector_pairs - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_pairs_label - LABL_PTR_2: esa_step_label -lo-counters-aggregated-tec5_timeout_no_pos_tof: - <<: *events +lo-tec5_timeout_no_pos_tof: + <<: *lo_counters_aggregated_default CATDESC: TEC-5 Timeout No Position or TOF FIELDNAM: TEC-5 Timeout Count; No Position or TOF - DEPEND_1: spin_sector_pairs - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_pairs_label - LABL_PTR_2: esa_step_label -# lo-counters-singles -lo-counters-singles-apd_singles: - <<: *counters +# <=== Lo-counters-singles ===> +lo_counters_singles: CATDESC: Single Rates (APD) - FIELDNAM: Rates - Single (APD) - DEPEND_1: inst_az + DEPEND_0: epoch + DEPEND_1: esa_step DEPEND_2: spin_sector_pairs - DEPEND_3: esa_step - LABL_PTR_1: inst_az_label + DEPEND_3: inst_az + DISPLAY_TYPE: time_series + FIELDNAM: Rates - Single (APD) + FILLVAL: *real_fillval + FORMAT: F32.9 + LABL_PTR_1: esa_step_label LABL_PTR_2: spin_sector_pairs_label - LABL_PTR_3: esa_step_label - -# lo-sw-angular -lo-sw-angular-hplus: - <<: *counters - CATDESC: Sunward H+ Species - FIELDNAM: SW - H+ - DEPEND_1: inst_az - DEPEND_2: spin_sector - DEPEND_3: esa_step - LABL_PTR_1: inst_az_label - LABL_PTR_2: spin_sector_label - LABL_PTR_3: esa_step_label - -lo-sw-angular-heplusplus: - <<: *counters - CATDESC: Sunward He++ Species - FIELDNAM: SW - He++ - DEPEND_1: inst_az - DEPEND_2: spin_sector - DEPEND_3: esa_step - LABL_PTR_1: inst_az_label - LABL_PTR_2: spin_sector_label - LABL_PTR_3: esa_step_label + LABL_PTR_3: inst_az_label + SCALETYP: linear + UNITS: counts + VALIDMAX: *max_uint32 + VALIDMIN: 0 + VAR_TYPE: data -lo-sw-angular-oplus6: - <<: *counters - CATDESC: Sunward O+6 Species - FIELDNAM: SW - O+6 - DEPEND_1: inst_az +# lo-angular attribute templates (combined versions of the previous entries) +lo-angular-attrs: + CATDESC: "{species} Sunward {direction} species" + DEPEND_0: epoch + DEPEND_1: esa_step DEPEND_2: spin_sector - DEPEND_3: esa_step - LABL_PTR_1: inst_az_label + DEPEND_3: inst_az + DISPLAY_TYPE: time_series + FIELDNAM: "SW - {species}" + FILLVAL: *real_fillval + FORMAT: F32.9 + LABL_PTR_1: esa_step_label LABL_PTR_2: spin_sector_label - LABL_PTR_3: esa_step_label + LABL_PTR_3: inst_az_label + UNITS: counts + VALIDMAX: *max_uint32 + VALIDMIN: 0 + VAR_TYPE: data -lo-sw-angular-fe_loq: - <<: *counters - CATDESC: Sunward Fe lowQ Species - FIELDNAM: SW - Fe lowQ - DEPEND_1: inst_az +lo-angular-unc-attrs: + CATDESC: "{species} Non-sunward {direction} species uncertainty" + DEPEND_0: epoch + DEPEND_1: esa_step DEPEND_2: spin_sector - DEPEND_3: esa_step - LABL_PTR_1: inst_az_label + DEPEND_3: inst_az + DISPLAY_TYPE: time_series + FIELDNAM: "NSW - {species}" + FILLVAL: *real_fillval + FORMAT: F19 + LABL_PTR_1: esa_step_label LABL_PTR_2: spin_sector_label - LABL_PTR_3: esa_step_label + LABL_PTR_3: inst_az_label + UNITS: counts + VALIDMAX: *max_uint32 + VALIDMIN: 0 + VAR_TYPE: data -lo-nsw-angular-heplusplus: - <<: *counters - CATDESC: Non-sunward He++ Species - FIELDNAM: NSW - He++ - DEPEND_1: inst_az +# lo-sw-priority +lo_priority_base: &lo_priority_base + DEPEND_0: epoch + DEPEND_1: esa_step DEPEND_2: spin_sector - DEPEND_3: esa_step - LABL_PTR_1: inst_az_label + DISPLAY_TYPE: time_series + FILLVAL: *real_fillval + FORMAT: F32.9 + LABL_PTR_1: esa_step_label LABL_PTR_2: spin_sector_label - LABL_PTR_3: esa_step_label + SCALETYP: linear + UNITS: counts + VALIDMAX: *max_uint32 + VALIDMIN: 0 + VAR_TYPE: data -# lo-sw-priority -lo-sw-priority-p0_tcrs: - <<: *counters +p0_tcrs: + <<: *lo_priority_base CATDESC: Sunward Sector Triple Coincidence Pickup Ions Priority - DEPEND_1: spin_sector - DEPEND_2: esa_step FIELDNAM: SW Sector Triple Coincidence PUI's - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label -lo-sw-priority-p1_hplus: - <<: *counters + +p1_hplus: + <<: *lo_priority_base CATDESC: Sunward Sector H+ Priority - DEPEND_1: spin_sector - DEPEND_2: esa_step FIELDNAM: SW Sector H+ - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label -lo-sw-priority-p2_heplusplus: - <<: *counters +p2_heplusplus: + <<: *lo_priority_base CATDESC: Sunward Sector He++ Priority - DEPEND_1: spin_sector - DEPEND_2: esa_step FIELDNAM: SW Sector He++ - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label -lo-sw-priority-p3_heavies: - <<: *counters +p3_heavies: + <<: *lo_priority_base CATDESC: Sunward Sector High Charge State Heavies Priority - DEPEND_1: spin_sector - DEPEND_2: esa_step FIELDNAM: SW Sector High Charge State Heavies - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label -lo-sw-priority-p4_dcrs: - <<: *counters +p4_dcrs: + <<: *lo_priority_base CATDESC: Sunward Sector Double Coincidence Pickup Ions Priority - DEPEND_1: spin_sector - DEPEND_2: esa_step FIELDNAM: SW Sector Double Coincidence PUI's - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label # lo-nsw-priority -lo-nsw-priority-p5_heavies: - <<: *counters +p5_heavies: + <<: *lo_priority_base CATDESC: Non-sunward Sector Heavies Priority - DEPEND_1: spin_sector - DEPEND_2: esa_step FIELDNAM: NSW Sector Heavies - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label -lo-nsw-priority-p6_hplus_heplusplus: - <<: *counters +p6_hplus_heplusplus: + <<: *lo_priority_base CATDESC: Non-sunward H+ and He++ Priority - DEPEND_1: spin_sector - DEPEND_2: esa_step FIELDNAM: NSW H+ and He++ - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label - -# lo-sw-species -lo-sw-species-hplus: - <<: *counters - CATDESC: H+ Sunward Species - FIELDNAM: SW - H+ - DEPEND_1: spin_sector - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label - -lo-sw-species-heplusplus: - <<: *counters - CATDESC: He++ Sunward Species - FIELDNAM: SW - He++ - DEPEND_1: spin_sector - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label - -lo-sw-species-cplus4: - <<: *counters - CATDESC: C+4 Sunward Species - FIELDNAM: SW - C+4 - DEPEND_1: spin_sector - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label - -lo-sw-species-cplus5: - <<: *counters - CATDESC: C+5 Sunward Species - FIELDNAM: SW - C+5 - DEPEND_1: spin_sector - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label - -lo-sw-species-cplus6: - <<: *counters - CATDESC: C+6 Sunward Species - FIELDNAM: SW - C+6 - DEPEND_1: spin_sector - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label - -lo-sw-species-oplus5: - <<: *counters - CATDESC: O+5 Sunward Species - FIELDNAM: SW - O+5 - DEPEND_1: spin_sector - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label - -lo-sw-species-oplus6: - <<: *counters - CATDESC: O+6 Sunward Species - FIELDNAM: SW - O+6 - DEPEND_1: spin_sector - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label - -lo-sw-species-oplus7: - <<: *counters - CATDESC: O+7 Sunward Species - FIELDNAM: SW - O+7 - DEPEND_1: spin_sector - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label - -lo-sw-species-oplus8: - <<: *counters - CATDESC: O+8 Sunward Species - FIELDNAM: SW - O+8 - DEPEND_1: spin_sector - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label - -lo-sw-species-ne: - <<: *counters - CATDESC: Ne Sunward Species - FIELDNAM: SW - Ne - DEPEND_1: spin_sector - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label -lo-sw-species-mg: - <<: *counters - CATDESC: Mg Sunward Species - FIELDNAM: SW - Mg - DEPEND_1: spin_sector - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label - -lo-sw-species-si: - <<: *counters - CATDESC: Si Sunward Species - FIELDNAM: SW - Si - DEPEND_1: spin_sector - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label - -lo-sw-species-fe_loq: - <<: *counters - CATDESC: Fe lowQ Sunward Species - FIELDNAM: SW - Fe lowQ - DEPEND_1: spin_sector - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label - -lo-sw-species-fe_hiq: - <<: *counters - CATDESC: Fe highQ Sunward Species - FIELDNAM: SW - Fe highQ - DEPEND_1: spin_sector - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label - -lo-sw-species-heplus: - <<: *counters - CATDESC: He+ Pickup Ion Sunward Species - FIELDNAM: SW - He+ (PUI) - DEPEND_1: spin_sector - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label - -lo-sw-species-cnoplus: - <<: *counters - CATDESC: CNO+ Pickup Ion Sunward Species - FIELDNAM: SW - CNO+ (PUI) - DEPEND_1: spin_sector - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label - -# lo-nsw-species -lo-nsw-species-hplus: - <<: *counters - CATDESC: H+ Non-sunward Species - FIELDNAM: NSW - H+ - DEPEND_1: spin_sector - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label - -lo-nsw-species-heplusplus: - <<: *counters - CATDESC: He++ Non-sunward Species - FIELDNAM: NSW - He++ - DEPEND_1: spin_sector - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label - -lo-nsw-species-c: - <<: *counters - CATDESC: C Non-sunward Species - FIELDNAM: NSW - C - DEPEND_1: spin_sector - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label - -lo-nsw-species-o: - <<: *counters - CATDESC: O Non-sunward Species - FIELDNAM: NSW - O - DEPEND_1: spin_sector - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label - -lo-nsw-species-ne_si_mg: - <<: *counters - CATDESC: Ne-Si-Mg Non-sunward Species - FIELDNAM: NSW - Ne_Si_Mg - DEPEND_1: spin_sector - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label - -lo-nsw-species-fe: - <<: *counters - CATDESC: Fe Non-sunward Species - FIELDNAM: NSW - Fe - DEPEND_1: spin_sector - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label - -lo-nsw-species-heplus: - <<: *counters - CATDESC: He+ Non-sunward Species - FIELDNAM: NSW - He+ - DEPEND_1: spin_sector - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label - -lo-nsw-species-cnoplus: - <<: *counters - CATDESC: CNO+ Non-sunward Species - FIELDNAM: NSW - CNO+ - DEPEND_1: spin_sector - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label - -# lo-ialirt -lo-ialirt-heplusplus: - <<: *counters - CATDESC: He++ Sunward Species - DEPEND_1: spin_sector - DEPEND_2: esa_step - FIELDNAM: SW - He++ - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label - VALIDMAX: *max_uint24 - -lo-ialirt-cplus5: - <<: *counters - CATDESC: C+5 Sunward Species - DEPEND_1: spin_sector - DEPEND_2: esa_step - FIELDNAM: SW - C+5 - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label - VALIDMAX: *max_uint24 - -lo-ialirt-cplus6: - <<: *counters - CATDESC: C+6 Sunward Species - DEPEND_1: spin_sector - DEPEND_2: esa_step - FIELDNAM: SW - C+6 - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label - VALIDMAX: *max_uint24 - -lo-ialirt-oplus6: - <<: *counters - CATDESC: O+6 Sunward Species - DEPEND_1: spin_sector - DEPEND_2: esa_step - FIELDNAM: SW - O+6 - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label - VALIDMAX: *max_uint24 - -lo-ialirt-oplus7: - <<: *counters - CATDESC: O+7 Sunward Species - DEPEND_1: spin_sector - DEPEND_2: esa_step - FIELDNAM: SW - O+7 - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label - VALIDMAX: *max_uint24 - -lo-ialirt-oplus8: - <<: *counters - CATDESC: O+8 Sunward Species - DEPEND_1: spin_sector - DEPEND_2: esa_step - FIELDNAM: SW - O+8 - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label - VALIDMAX: *max_uint24 - -lo-ialirt-mg: - <<: *counters - CATDESC: Mg Sunward Species - DEPEND_1: spin_sector - DEPEND_2: esa_step - FIELDNAM: SW - Mg - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label - VALIDMAX: *max_uint24 - -lo-ialirt-fe_loq: - <<: *counters - CATDESC: Fe lowQ Sunward Species - DEPEND_1: spin_sector - DEPEND_2: esa_step - FIELDNAM: SW - Fe lowQ - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label - VALIDMAX: *max_uint24 - -lo-ialirt-fe_hiq: - <<: *counters - CATDESC: Fe highQ Sunward Species - DEPEND_1: spin_sector - DEPEND_2: esa_step - FIELDNAM: SW - Fe highQ - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label - VALIDMAX: *max_uint24 - -# <=== Direct Events Attributes ===> -# TODO: The lo-direct-events product defines "gain" with different values -# than what is found in hi-direct-events. Come up with a way to -# distinguish these in the code. -p0_apd_id: - <<: *direct_events - CATDESC: Priority 0 APD ID - DEPEND_1: event_num - FIELDNAM: Priority 0 APD ID - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -p0_apd_energy: - <<: *direct_events - CATDESC: Priority 0 APD Energy - DEPEND_1: event_num - FIELDNAM: Priority 0 APD Energy - FILLVAL: 65535 - LABL_PTR_1: event_num_label - VALIDMAX: 512 - -p0_gain: - <<: *direct_events - CATDESC: Priority 0 APD Gain - DEPEND_1: event_num - FIELDNAM: Priority 0 APD Gain - LABL_PTR_1: event_num_label - VALIDMAX: 1 - -p0_data_quality: - <<: *direct_events - CATDESC: Priority 0 Data Quality - FIELDNAM: Priority 0 Data Quality - LABLAXIS: " " - VALIDMAX: 1 - -p0_energy_step: - <<: *direct_events - CATDESC: Priority 0 Energy Step - DEPEND_1: event_num - FIELDNAM: Priority 0 Energy Step - LABL_PTR_1: event_num_label - VALIDMAX: 128 - -p0_multi_flag: - <<: *direct_events - CATDESC: Priority 0 Multi Flag - DEPEND_1: event_num - FIELDNAM: Priority 0 Multi Flag - LABL_PTR_1: event_num_label - VALIDMAX: 1 - -p0_num_events: - <<: *direct_events - CATDESC: Priority 0 Number of Events - FIELDNAM: Priority 0 Number of Events - FILLVAL: 65535 - LABLAXIS: " " - -p0_type: - <<: *direct_events - CATDESC: Priority 0 PHA Type - DEPEND_1: event_num - FIELDNAM: Priority 0 PHA Type - LABL_PTR_1: event_num_label - VALIDMAX: 4 - -p0_position: - <<: *direct_events - CATDESC: Priority 0 Position - DEPEND_1: event_num - FIELDNAM: Priority 0 Position - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -p0_spin_sector: - <<: *direct_events - CATDESC: Priority 0 Spin Angle - DEPEND_1: event_num - FIELDNAM: Priority 0 Spin Angle - LABL_PTR_1: event_num_label - VALIDMAX: 128 - -p0_spin_number: - <<: *direct_events - CATDESC: Priority 0 Spin Number - DEPEND_1: event_num - FIELDNAM: Priority 0 Spin Number - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -p0_ssd_id: - <<: *direct_events - CATDESC: Priority 0 SSD ID or Azimuth Angle - DEPEND_1: event_num - FIELDNAM: Priority 0 SSD ID or Azimuth Angle - LABL_PTR_1: event_num_label - VALIDMAX: 32 -p0_ssd_energy: - <<: *direct_events - CATDESC: Priority 0 APD Energy - DEPEND_1: event_num - FIELDNAM: Priority 0 APD Energy - LABL_PTR_1: event_num_label - VALIDMAX: 2048 - -p0_tof: - <<: *direct_events - CATDESC: Priority 0 Time of Flight - DEPEND_1: event_num - FIELDNAM: Priority 0 Time of Flight - FILLVAL: 65535 - LABL_PTR_1: event_num_label - VALIDMAX: 1024 - -p0_type: - <<: *direct_events - CATDESC: Priority 0 Type - DEPEND_1: event_num - FIELDNAM: Priority 0 Type - LABL_PTR_1: event_num_label - VALIDMAX: 3 - -p1_apd_id: - <<: *direct_events - CATDESC: Priority 1 APD ID - DEPEND_1: event_num - FIELDNAM: Priority 1 APD ID - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -p1_apd_energy: - <<: *direct_events - CATDESC: Priority 1 APD Energy - DEPEND_1: event_num - FIELDNAM: Priority 1 APD Energy - FILLVAL: 65535 - LABL_PTR_1: event_num_label - VALIDMAX: 512 - -p1_gain: - <<: *direct_events - CATDESC: Priority 1 APD Gain - DEPEND_1: event_num - FIELDNAM: Priority 1 APD Gain - LABL_PTR_1: event_num_label - VALIDMAX: 1 - -p1_data_quality: - <<: *direct_events - CATDESC: Priority 1 Data Quality - FIELDNAM: Priority 1 Data Quality - LABLAXIS: " " - VALIDMAX: 1 - -p1_energy_step: - <<: *direct_events - CATDESC: Priority 1 Energy Step - DEPEND_1: event_num - FIELDNAM: Priority 1 Energy Step - LABL_PTR_1: event_num_label - VALIDMAX: 128 - -p1_multi_flag: - <<: *direct_events - CATDESC: Priority 1 Multi Flag - DEPEND_1: event_num - FIELDNAM: Priority 1 Multi Flag - LABL_PTR_1: event_num_label - VALIDMAX: 1 - -p1_num_events: - <<: *direct_events - CATDESC: Priority 1 Number of Events - FIELDNAM: Priority 1 Number of Events - FILLVAL: 65535 - LABLAXIS: " " - -p1_type: - <<: *direct_events - CATDESC: Priority 1 PHA Type - DEPEND_1: event_num - FIELDNAM: Priority 1 PHA Type - LABL_PTR_1: event_num_label - VALIDMAX: 4 - -p1_position: - <<: *direct_events - CATDESC: Priority 1 Position - DEPEND_1: event_num - FIELDNAM: Priority 1 Position - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -p1_spin_sector: - <<: *direct_events - CATDESC: Priority 1 Spin Angle - DEPEND_1: event_num - FIELDNAM: Priority 1 Spin Angle - LABL_PTR_1: event_num_label - VALIDMAX: 128 - -p1_spin_number: - <<: *direct_events - CATDESC: Priority 1 Spin Number - DEPEND_1: event_num - FIELDNAM: Priority 1 Spin Number - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -p1_ssd_id: - <<: *direct_events - CATDESC: Priority 1 SSD ID or Azimuth Angle - DEPEND_1: event_num - FIELDNAM: Priority 1 SSD ID or Azimuth Angle - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -p1_ssd_energy: - <<: *direct_events - CATDESC: Priority 1 APD Energy - DEPEND_1: event_num - FIELDNAM: Priority 1 APD Energy - LABL_PTR_1: event_num_label - VALIDMAX: 2048 - -p1_tof: - <<: *direct_events - CATDESC: Priority 1 Time of Flight - DEPEND_1: event_num - FIELDNAM: Priority 1 Time of Flight - FILLVAL: 65535 - LABL_PTR_1: event_num_label - VALIDMAX: 1024 - -p1_Type: - <<: *direct_events - CATDESC: Priority 1 Type - DEPEND_1: event_num - FIELDNAM: Priority 1 Type - LABL_PTR_1: event_num_label - VALIDMAX: 3 - -p2_apd_id: - <<: *direct_events - CATDESC: Priority 2 APD ID - DEPEND_1: event_num - FIELDNAM: Priority 2 APD ID - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -p2_apd_energy: - <<: *direct_events - CATDESC: Priority 2 APD Energy - DEPEND_1: event_num - FIELDNAM: Priority 2 APD Energy - FILLVAL: 65535 - LABL_PTR_1: event_num_label - VALIDMAX: 512 - -p2_gain: - <<: *direct_events - CATDESC: Priority 2 APD Gain - DEPEND_1: event_num - FIELDNAM: Priority 2 APD Gain - LABL_PTR_1: event_num_label - VALIDMAX: 1 - -p2_data_quality: - <<: *direct_events - CATDESC: Priority 2 Data Quality - FIELDNAM: Priority 2 Data Quality - LABLAXIS: " " - VALIDMAX: 1 - -p2_energy_step: - <<: *direct_events - CATDESC: Priority 2 Energy Step - DEPEND_1: event_num - FIELDNAM: Priority 2 Energy Step - LABL_PTR_1: event_num_label - VALIDMAX: 128 - -p2_multi_flag: - <<: *direct_events - CATDESC: Priority 2 Multi Flag - DEPEND_1: event_num - FIELDNAM: Priority 2 Multi Flag - LABL_PTR_1: event_num_label - VALIDMAX: 1 - -p2_num_events: - <<: *direct_events - CATDESC: Priority 2 Number of Events - FIELDNAM: Priority 2 Number of Events - FILLVAL: 65535 - LABLAXIS: " " - -p2_type: - <<: *direct_events - CATDESC: Priority 2 PHA Type - DEPEND_1: event_num - FIELDNAM: Priority 2 PHA Type - LABL_PTR_1: event_num_label - VALIDMAX: 4 - -p2_position: - <<: *direct_events - CATDESC: Priority 2 Position - DEPEND_1: event_num - FIELDNAM: Priority 2 Position - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -p2_spin_sector: - <<: *direct_events - CATDESC: Priority 2 Spin Angle - DEPEND_1: event_num - FIELDNAM: Priority 2 Spin Angle - LABL_PTR_1: event_num_label - VALIDMAX: 128 - -p2_spin_number: - <<: *direct_events - CATDESC: Priority 2 Spin Number - DEPEND_1: event_num - FIELDNAM: Priority 2 Spin Number - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -p2_ssd_id: - <<: *direct_events - CATDESC: Priority 2 SSD ID or Azimuth Angle - DEPEND_1: event_num - FIELDNAM: Priority 2 SSD ID or Azimuth Angle - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -p2_ssd_energy: - <<: *direct_events - CATDESC: Priority 2 APD Energy - DEPEND_1: event_num - FIELDNAM: Priority 2 APD Energy - LABL_PTR_1: event_num_label - VALIDMAX: 2048 - -p2_tof: - <<: *direct_events - CATDESC: Priority 2 Time of Flight - DEPEND_1: event_num - FIELDNAM: Priority 2 Time of Flight - FILLVAL: 65535 - LABL_PTR_1: event_num_label - VALIDMAX: 1024 - -p2_Type: - <<: *direct_events - CATDESC: Priority 2 Type - DEPEND_1: event_num - FIELDNAM: Priority 2 Type - LABL_PTR_1: event_num_label - VALIDMAX: 3 - -p3_apd_id: - <<: *direct_events - CATDESC: Priority 3 APD ID - DEPEND_1: event_num - FIELDNAM: Priority 3 APD ID - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -p3_apd_energy: - <<: *direct_events - CATDESC: Priority 3 APD Energy - DEPEND_1: event_num - FIELDNAM: Priority 3 APD Energy - FILLVAL: 65535 - LABL_PTR_1: event_num_label - VALIDMAX: 512 - -p3_gain: - <<: *direct_events - CATDESC: Priority 3 APD Gain - DEPEND_1: event_num - FIELDNAM: Priority 3 APD Gain - LABL_PTR_1: event_num_label - VALIDMAX: 1 - -p3_data_quality: - <<: *direct_events - CATDESC: Priority 3 Data Quality - FIELDNAM: Priority 3 Data Quality - LABLAXIS: " " - VALIDMAX: 1 - -p3_energy_step: - <<: *direct_events - CATDESC: Priority 3 Energy Step - DEPEND_1: event_num - FIELDNAM: Priority 3 Energy Step - LABL_PTR_1: event_num_label - VALIDMAX: 128 - -p3_multi_flag: - <<: *direct_events - CATDESC: Priority 3 Multi Flag - DEPEND_1: event_num - FIELDNAM: Priority 3 Multi Flag - LABL_PTR_1: event_num_label - VALIDMAX: 1 - -p3_num_events: - <<: *direct_events - CATDESC: Priority 3 Number of Events - FIELDNAM: Priority 3 Number of Events - FILLVAL: 65535 - LABLAXIS: " " - -p3_type: - <<: *direct_events - CATDESC: Priority 3 PHA Type - DEPEND_1: event_num - FIELDNAM: Priority 3 PHA Type - LABL_PTR_1: event_num_label - VALIDMAX: 4 - -p3_position: - <<: *direct_events - CATDESC: Priority 3 Position - DEPEND_1: event_num - FIELDNAM: Priority 3 Position - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -p3_spin_sector: - <<: *direct_events - CATDESC: Priority 3 Spin Angle - DEPEND_1: event_num - FIELDNAM: Priority 3 Spin Angle - LABL_PTR_1: event_num_label - VALIDMAX: 128 - -p3_spin_number: - <<: *direct_events - CATDESC: Priority 3 Spin Number - DEPEND_1: event_num - FIELDNAM: Priority 3 Spin Number - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -p3_ssd_id: - <<: *direct_events - CATDESC: Priority 3 SSD ID or Azimuth Angle - DEPEND_1: event_num - FIELDNAM: Priority 3 SSD ID or Azimuth Angle - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -p3_ssd_energy: - <<: *direct_events - CATDESC: Priority 3 APD Energy - DEPEND_1: event_num - FIELDNAM: Priority 3 APD Energy - LABL_PTR_1: event_num_label - VALIDMAX: 2048 - -p3_tof: - <<: *direct_events - CATDESC: Priority 3 Time of Flight - DEPEND_1: event_num - FIELDNAM: Priority 3 Time of Flight - FILLVAL: 65535 - LABL_PTR_1: event_num_label - VALIDMAX: 1024 - -p3_Type: - <<: *direct_events - CATDESC: Priority 3 Type - DEPEND_1: event_num - FIELDNAM: Priority 3 Type - LABL_PTR_1: event_num_label - VALIDMAX: 3 - -p4_apd_id: - <<: *direct_events - CATDESC: Priority 4 APD ID - DEPEND_1: event_num - FIELDNAM: Priority 4 APD ID - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -p4_apd_energy: - <<: *direct_events - CATDESC: Priority 4 APD Energy - DEPEND_1: event_num - FIELDNAM: Priority 4 APD Energy - FILLVAL: 65535 - LABL_PTR_1: event_num_label - VALIDMAX: 512 - -p4_gain: - <<: *direct_events - CATDESC: Priority 4 APD Gain - DEPEND_1: event_num - FIELDNAM: Priority 4 APD Gain - LABL_PTR_1: event_num_label - VALIDMAX: 1 - -p4_data_quality: - <<: *direct_events - CATDESC: Priority 4 Data Quality - FIELDNAM: Priority 4 Data Quality - LABLAXIS: " " - VALIDMAX: 1 - -p4_energy_step: - <<: *direct_events - CATDESC: Priority 4 Energy Step - DEPEND_1: event_num - FIELDNAM: Priority 4 Energy Step - LABL_PTR_1: event_num_label - VALIDMAX: 128 - -p4_multi_flag: - <<: *direct_events - CATDESC: Priority 4 Multi Flag - DEPEND_1: event_num - FIELDNAM: Priority 4 Multi Flag - LABL_PTR_1: event_num_label - VALIDMAX: 1 - -p4_num_events: - <<: *direct_events - CATDESC: Priority 4 Number of Events - FIELDNAM: Priority 4 Number of Events - FILLVAL: 65535 - LABLAXIS: " " - -p4_type: - <<: *direct_events - CATDESC: Priority 4 PHA Type - DEPEND_1: event_num - FIELDNAM: Priority 4 PHA Type - LABL_PTR_1: event_num_label - VALIDMAX: 4 - -p4_position: - <<: *direct_events - CATDESC: Priority 4 Position - DEPEND_1: event_num - FIELDNAM: Priority 4 Position - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -p4_spin_sector: - <<: *direct_events - CATDESC: Priority 4 Spin Angle - DEPEND_1: event_num - FIELDNAM: Priority 4 Spin Angle - LABL_PTR_1: event_num_label - VALIDMAX: 128 - -p4_spin_number: - <<: *direct_events - CATDESC: Priority 4 Spin Number - DEPEND_1: event_num - FIELDNAM: Priority 4 Spin Number - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -p4_ssd_id: - <<: *direct_events - CATDESC: Priority 4 SSD ID or Azimuth Angle - DEPEND_1: event_num - FIELDNAM: Priority 4 SSD ID or Azimuth Angle - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -p4_ssd_energy: - <<: *direct_events - CATDESC: Priority 4 APD Energy - DEPEND_1: event_num - FIELDNAM: Priority 4 APD Energy - LABL_PTR_1: event_num_label - VALIDMAX: 2048 - -p4_tof: - <<: *direct_events - CATDESC: Priority 4 Time of Flight - DEPEND_1: event_num - FIELDNAM: Priority 4 Time of Flight - FILLVAL: 65535 - LABL_PTR_1: event_num_label - VALIDMAX: 1024 - -p4_Type: - <<: *direct_events - CATDESC: Priority 4 Type - DEPEND_1: event_num - FIELDNAM: Priority 4 Type - LABL_PTR_1: event_num_label - VALIDMAX: 3 - -p5_apd_id: - <<: *direct_events - CATDESC: Priority 5 APD ID - DEPEND_1: event_num - FIELDNAM: Priority 5 APD ID - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -p5_apd_energy: - <<: *direct_events - CATDESC: Priority 5 APD Energy - DEPEND_1: event_num - FIELDNAM: Priority 5 APD Energy - FILLVAL: 65535 - LABL_PTR_1: event_num_label - VALIDMAX: 512 - -p5_gain: - <<: *direct_events - CATDESC: Priority 5 APD Gain - DEPEND_1: event_num - FIELDNAM: Priority 5 APD Gain - LABL_PTR_1: event_num_label - VALIDMAX: 1 - -p5_data_quality: - <<: *direct_events - CATDESC: Priority 5 Data Quality - FIELDNAM: Priority 5 Data Quality - LABLAXIS: " " - VALIDMAX: 1 - -p5_energy_step: - <<: *direct_events - CATDESC: Priority 5 Energy Step - DEPEND_1: event_num - FIELDNAM: Priority 5 Energy Step - LABL_PTR_1: event_num_label - VALIDMAX: 128 - -p5_multi_flag: - <<: *direct_events - CATDESC: Priority 5 Multi Flag - DEPEND_1: event_num - FIELDNAM: Priority 5 Multi Flag - LABL_PTR_1: event_num_label - VALIDMAX: 1 - -p5_num_events: - <<: *direct_events - CATDESC: Priority 5 Number of Events - FIELDNAM: Priority 5 Number of Events - FILLVAL: 65535 - LABLAXIS: " " - -p5_type: - <<: *direct_events - CATDESC: Priority 5 PHA Type - DEPEND_1: event_num - FIELDNAM: Priority 5 PHA Type - LABL_PTR_1: event_num_label - VALIDMAX: 4 - -p5_position: - <<: *direct_events - CATDESC: Priority 5 Position - DEPEND_1: event_num - FIELDNAM: Priority 5 Position - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -p5_spin_sector: - <<: *direct_events - CATDESC: Priority 5 Spin Angle - DEPEND_1: event_num - FIELDNAM: Priority 5 Spin Angle - LABL_PTR_1: event_num_label - VALIDMAX: 128 - -p5_spin_number: - <<: *direct_events - CATDESC: Priority 5 Spin Number - DEPEND_1: event_num - FIELDNAM: Priority 5 Spin Number - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -p5_ssd_id: - <<: *direct_events - CATDESC: Priority 5 SSD ID or Azimuth Angle - DEPEND_1: event_num - FIELDNAM: Priority 5 SSD ID or Azimuth Angle - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -p5_ssd_energy: - <<: *direct_events - CATDESC: Priority 5 APD Energy - DEPEND_1: event_num - FIELDNAM: Priority 5 APD Energy - LABL_PTR_1: event_num_label - VALIDMAX: 2048 - -p5_tof: - <<: *direct_events - CATDESC: Priority 5 Time of Flight - DEPEND_1: event_num - FIELDNAM: Priority 5 Time of Flight - FILLVAL: 65535 - LABL_PTR_1: event_num_label - VALIDMAX: 1024 - -p5_Type: - <<: *direct_events - CATDESC: Priority 5 Type - DEPEND_1: event_num - FIELDNAM: Priority 5 Type - LABL_PTR_1: event_num_label - VALIDMAX: 3 - -p6_apd_id: - <<: *direct_events - CATDESC: Priority 6 APD ID - DEPEND_1: event_num - FIELDNAM: Priority 6 APD ID - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -p6_apd_energy: - <<: *direct_events - CATDESC: Priority 6 APD Energy - DEPEND_1: event_num - FIELDNAM: Priority 6 APD Energy - FILLVAL: 65535 - LABL_PTR_1: event_num_label - VALIDMAX: 512 - -p6_gain: - <<: *direct_events - CATDESC: Priority 6 APD Gain - DEPEND_1: event_num - FIELDNAM: Priority 6 APD Gain - LABL_PTR_1: event_num_label - VALIDMAX: 1 - -p6_data_quality: - <<: *direct_events - CATDESC: Priority 6 Data Quality - FIELDNAM: Priority 6 Data Quality - LABLAXIS: " " - VALIDMAX: 1 - -p6_energy_step: - <<: *direct_events - CATDESC: Priority 6 Energy Step - DEPEND_1: event_num - FIELDNAM: Priority 6 Energy Step - LABL_PTR_1: event_num_label - VALIDMAX: 128 - -p6_multi_flag: - <<: *direct_events - CATDESC: Priority 6 Multi Flag - DEPEND_1: event_num - FIELDNAM: Priority 6 Multi Flag - LABL_PTR_1: event_num_label - VALIDMAX: 1 - -p6_num_events: - <<: *direct_events - CATDESC: Priority 6 Number of Events - FIELDNAM: Priority 6 Number of Events - FILLVAL: 65535 - LABLAXIS: " " - -p6_type: - <<: *direct_events - CATDESC: Priority 6 PHA Type - DEPEND_1: event_num - FIELDNAM: Priority 6 PHA Type - LABL_PTR_1: event_num_label - VALIDMAX: 4 - -p6_position: - <<: *direct_events - CATDESC: Priority 6 Position - DEPEND_1: event_num - FIELDNAM: Priority 6 Position - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -p6_spin_sector: - <<: *direct_events - CATDESC: Priority 6 Spin Angle - DEPEND_1: event_num - FIELDNAM: Priority 6 Spin Angle - LABL_PTR_1: event_num_label - VALIDMAX: 128 - -p6_tof: - <<: *direct_events - CATDESC: Priority 6 Time of Flight - DEPEND_1: event_num - FIELDNAM: Priority 6 Time of Flight - FILLVAL: 65535 - LABL_PTR_1: event_num_label - VALIDMAX: 1024 - -p7_apd_id: - <<: *direct_events - CATDESC: Priority 7 APD ID - DEPEND_1: event_num - FIELDNAM: Priority 7 APD ID - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -p7_apd_energy: - <<: *direct_events - CATDESC: Priority 7 APD Energy - DEPEND_1: event_num - FIELDNAM: Priority 7 APD Energy - FILLVAL: 65535 - LABL_PTR_1: event_num_label - VALIDMAX: 512 - -p7_gain: - <<: *direct_events - CATDESC: Priority 7 APD Gain - DEPEND_1: event_num - FIELDNAM: Priority 7 APD Gain - LABL_PTR_1: event_num_label - VALIDMAX: 1 - -p7_data_quality: - <<: *direct_events - CATDESC: Priority 7 Data Quality - FIELDNAM: Priority 7 Data Quality - LABLAXIS: " " - VALIDMAX: 1 - -p7_energy_step: - <<: *direct_events - CATDESC: Priority 7 Energy Step - DEPEND_1: event_num - FIELDNAM: Priority 7 Energy Step - LABL_PTR_1: event_num_label - VALIDMAX: 128 - -p7_multi_flag: - <<: *direct_events - CATDESC: Priority 7 Multi Flag - DEPEND_1: event_num - FIELDNAM: Priority 7 Multi Flag - LABL_PTR_1: event_num_label - VALIDMAX: 1 - -p7_num_events: - <<: *direct_events - CATDESC: Priority 7 Number of Events - FIELDNAM: Priority 7 Number of Events - FILLVAL: 65535 - LABLAXIS: " " - -p7_type: - <<: *direct_events - CATDESC: Priority 7 PHA Type - DEPEND_1: event_num - FIELDNAM: Priority 7 PHA Type - LABL_PTR_1: event_num_label - VALIDMAX: 4 - -p7_position: - <<: *direct_events - CATDESC: Priority 7 Position - DEPEND_1: event_num - FIELDNAM: Priority 7 Position - LABL_PTR_1: event_num_label - VALIDMAX: 32 +# lo species attrs +lo-species-attrs: + CATDESC: "{species} {direction} Species" + DEPEND_0: epoch + DEPEND_1: esa_step + DEPEND_2: spin_sector + DISPLAY_TYPE: time_series + FIELDNAM: "{direction} - {species}" + FILLVAL: *real_fillval + FORMAT: F32.9 + LABL_PTR_1: esa_step_label + LABL_PTR_2: spin_sector_label + UNITS: counts + VALIDMAX: *max_uint32 + VALIDMIN: 0 + VAR_TYPE: data -p7_spin_sector: - <<: *direct_events - CATDESC: Priority 7 Spin Angle - DEPEND_1: event_num - FIELDNAM: Priority 7 Spin Angle - LABL_PTR_1: event_num_label - VALIDMAX: 128 +lo-pui-species-attrs: + CATDESC: "{species} Pickup Ion {direction} Species" + DEPEND_0: epoch + DEPEND_1: esa_step + DEPEND_2: spin_sector + DISPLAY_TYPE: time_series + FIELDNAM: "{direction} - {species}" + FILLVAL: *real_fillval + FORMAT: F32.9 + LABL_PTR_1: esa_step_label + LABL_PTR_2: spin_sector_label + UNITS: counts + VALIDMAX: *max_uint32 + VALIDMIN: 0 + VAR_TYPE: data -p7_tof: - <<: *direct_events - CATDESC: Priority 7 Time of Flight - DEPEND_1: event_num - FIELDNAM: Priority 7 Time of Flight - FILLVAL: 65535 - LABL_PTR_1: event_num_label - VALIDMAX: 1024 - -# <=== CCSDS Header Attributes ===> -version: - <<: *hskp_default - CATDESC: CCSDS Packet Version Number (always 0) - FIELDNAM: Version - LABLAXIS: VERSION - -type: - <<: *hskp_default - CATDESC: CCSDS Packet Type Indicator (0=telemetry) - FIELDNAM: Type - LABLAXIS: TYPE - -sec_hdr_flg: - <<: *hskp_default - CATDESC: CCSDS Packet Secondary Header Flag (always 1) - FIELDNAM: Secondary Header Flag - LABLAXIS: SEC_HDR_FLG - -pkt_apid: - <<: *hskp_default - CATDESC: CCSDS Packet Application Process ID - FIELDNAM: Packet APID - FILLVAL: *uint16_fillval - LABLAXIS: PKT_APID - -seq_flgs: - <<: *hskp_default - CATDESC: CCSDS Packet Grouping Flags (3=not part of group) - FIELDNAM: Grouping Flags - LABLAXIS: SEQ_FLGS - -src_seq_ctr: - <<: *hskp_default - CATDESC: CCSDS Packet Sequence Count (increments with each new packet) - FIELDNAM: Packet Sequence Count - FILLVAL: *uint16_fillval - LABLAXIS: SRC_SEQ_CTR - -pkt_len: - <<: *hskp_default - CATDESC: CCSDS Packet Length (number of bytes after Packet length minus 1) - FIELDNAM: Packet Length - FILLVAL: *uint16_fillval - LABLAXIS: PKT_LEN - -shcoarse: - <<: *hskp_default - CATDESC: Secondary Header - Whole-seconds part of SCLK - FIELDNAM: S/C Time - Seconds - FILLVAL: *uint32_fillval - LABLAXIS: SHCOARSE +lo-species-unc-attrs: + CATDESC: "{species} {direction} Species uncertainty" + DEPEND_0: epoch + DEPEND_1: esa_step + DEPEND_2: spin_sector + DISPLAY_TYPE: time_series + FIELDNAM: "{direction} - {species}" + FILLVAL: *real_fillval + FORMAT: F20.9 + LABL_PTR_1: esa_step_label + LABL_PTR_2: spin_sector_label + UNITS: counts + VALIDMAX: *max_uint32 + VALIDMIN: 0 + VAR_TYPE: data -packet_version: - <<: *hskp_default - CATDESC: Packet Version - FIELDNAM: Packet Version - FILLVAL: *uint16_fillval - LABLAXIS: PACKET_VERSION - VAR_NOTES: Packet version - this will be incremented each time the format of the packet changes. - -chksum: - <<: *hskp_default - CATDESC: Packet Checksum - LABLAXIS: CHKSUM - FIELDNAM: Packet Checksum - -# <=== Housekeeping Attributes ===> -cmdexe: - <<: *hskp_default - LABLAXIS: CMDEXE - FIELDNAM: Number of commands executed - CATDESC: Number of commands executed. See VAR_NOTES for more details. - VAR_NOTES: Number of commands that have been executed. Counts 0-255, then rolls over to 0. Reset via CLR_LATCHED_SINGLE(COMMAND_COUNTS) [also resets cmdjrct, cmdacc, itf_error counts) - -cmdrjct: - <<: *hskp_default - LABLAXIS: CMDRJCT - FIELDNAM: Number of commands rejected - CATDESC: Number of commands rejected. See VAR_NOTES for more details. - VAR_NOTES: Number of commands that have been rejected. Counts 0-255, then rolls over to 0. Reset via CLR_LATCHED_SINGLE(COMMAND_COUNTS) [also resets cmdexe, cmdacc, itf_error counts) - -last_opcode: - <<: *hskp_default - LABLAXIS: LAST_OPCODE - FIELDNAM: Last executed opcode - FILLVAL: *uint16_fillval - CATDESC: Opcode of the last executed command - -mode: - <<: *hskp_default - LABLAXIS: MODE - FIELDNAM: Instrument Mode - CATDESC: Current operating mode - -memop_state: - <<: *hskp_default - LABLAXIS: MEMOP_STATE - FIELDNAM: Memory Operation State - CATDESC: State of the memory-operations handler - -memdump_state: - <<: *hskp_default - LABLAXIS: MEMDUMP_STATE - FIELDNAM: Memory Dump State - CATDESC: State of the memory-dump handler (busy/idle) - -itf_err_cnt: - <<: *hskp_default - LABLAXIS: ITF_ERR_CNT - FIELDNAM: Number of ITF errors encountered - CATDESC: Number of ITF Errors detected. See VAR_NOTES for more details. - VAR_NOTES: Number of ITF Errors that have been detected; counts 0-3, then rolls over to 0. Reset via CLR_LATCHED_SINGLE(COMMAND_COUNTS) [also resets cmdexe, cmdjrct, cmdacc counts) - -spin_cnt: - <<: *hskp_default - LABLAXIS: SPIN_CNT - FIELDNAM: Number of spin pulses received - CATDESC: Number of spin pulses received - -missed_pps_cnt: - <<: *hskp_default - LABLAXIS: MISSED_PPS_CNT - FIELDNAM: Number of missed PPS pulses - CATDESC: Number of missed PPS pulses. See VAR_NOTES for more details. - VAR_NOTES: Number of missed PPS pulses. Counts 0-3, then freezes at 3. Reset via CLR_LATCHED_SINGLE(PPS_STATS) - -wdog_timeout_cnt: - <<: *hskp_default - LABLAXIS: WDOG_TIMEOUT_CNT - FIELDNAM: Number of watchdog timeouts since last reset - CATDESC: Number of times the watchdog has timed out. - -hv_plug: - <<: *hskp_default - LABLAXIS: HV_PLUG - FIELDNAM: Status of the HV Disable Plug - CATDESC: Status of the HV plugs. See VAR_NOTES for more details. - VAR_NOTES: Current status of the HV SAFE/DISABLE plugs -- "SAFE" - all HVPS outputs provide 1/10 the commanded voltage; "DIS" - all HVPS outputs provide 0V, regardless of commanded voltage; "FULL" - HVPS outputs provide the full commanded voltage - -cmd_fifo_overrun_cnt: - <<: *hskp_default - LABLAXIS: CMD_FIFO_OVERRUN_CNT - FIELDNAM: Number of Command FIFO Overruns - CATDESC: Number of Command FIFO Overruns - -cmd_fifo_underrun_cnt: - <<: *hskp_default - LABLAXIS: CMD_FIFO_UNDERRUN_CNT - FIELDNAM: Number of Command FIFO Underruns - CATDESC: Number of Command FIFO Underruns - -cmd_fifo_parity_err_cnt: - <<: *hskp_default - LABLAXIS: CMD_FIFO_PARITY_ERR_CNT - FIELDNAM: Number of Command FIFO Parity Errors - CATDESC: Number of Command FIFO Parity Errors - -cmd_fifo_frame_err_cnt: - <<: *hskp_default - LABLAXIS: CMD_FIFO_FRAME_ERR_CNT - FIELDNAM: Number of Command FIFO Frame Errors - CATDESC: Number of Command FIFO Frame Errors - -tlm_fifo_overrun_cnt: - <<: *hskp_default - LABLAXIS: TLM_FIFO_OVERRUN_CNT - FIELDNAM: Number of Telemetry FIFO Overruns - CATDESC: Number of Telemetry FIFO Overruns - -spin_period_hskp: - <<: *hskp_default - LABLAXIS: SPIN_PERIOD - FIELDNAM: Spin Period - FILLVAL: *uint16_fillval - CATDESC: Current Spin Period - -spin_bin_period: - <<: *hskp_default - LABLAXIS: SPIN_BIN_PERIOD - FIELDNAM: Spin Bin Period - FILLVAL: *uint16_fillval - CATDESC: Spin Bin Period - -spin_period_timer: - <<: *hskp_default - LABLAXIS: SPIN_PERIOD_TIMER - FIELDNAM: Spin Period Timer - FILLVAL: *uint16_fillval - CATDESC: Spin Period Timer - -spin_timestamp_seconds: - <<: *hskp_default - LABLAXIS: SPIN_TIMESTAMP_SECONDS - FIELDNAM: Full-seconds timestamp of the most recent spin pulse - FILLVAL: *uint32_fillval - CATDESC: Full-seconds timestamp of the most recent spin pulse +lo-pui-species-unc-attrs: + CATDESC: "{species} Pickup Ion {direction} Species uncertainty" + DEPEND_0: epoch + DEPEND_1: esa_step + DEPEND_2: spin_sector + DISPLAY_TYPE: time_series + FIELDNAM: "{direction} - {species}" + FILLVAL: *real_fillval + FORMAT: F20.9 + LABL_PTR_1: esa_step_label + LABL_PTR_2: spin_sector_label + UNITS: counts + VALIDMAX: *max_uint32 + VALIDMIN: 0 + VAR_TYPE: data -spin_timestamp_subseconds: - <<: *hskp_default - LABLAXIS: SPIN_TIMESTAMP_SUBSECONDS - FIELDNAM: Sub-seconds timestamp of the most recent spin pulse - FILLVAL: *uint32_fillval - CATDESC: Sub-seconds timestamp of the most recent spin pulse - -spin_bin_index: - <<: *hskp_default - LABLAXIS: SPIN_BIN_INDEX - FIELDNAM: Spin Bin Index - FILLVAL: *uint16_fillval - CATDESC: Spin Bin Index - -optc_hv_cmd_err_cnt: - <<: *hskp_default - LABLAXIS: OPTICS_HV_CMD_ERR_CNT - FIELDNAM: Optics HV - Number of command errors - CATDESC: Optics HV - Number of command errors - -spare_1: - <<: *hskp_default - LABLAXIS: SPARE_1 - FIELDNAM: Spare for alignment - CATDESC: Spare for alignment - -optc_hv_arm_err_cnt: - <<: *hskp_default - LABLAXIS: OPTICS_HV_ARM_ERR_CNT - FIELDNAM: Optics HV - Number of arm errors - CATDESC: Optics HV - Number of arm errors - -optc_hv_master_en: - <<: *hskp_default - LABLAXIS: OPTICS_HV_MASTER_ENABLE - FIELDNAM: Optics HV - Master Enable - CATDESC: Optics HV - Master Enable - -iobulk_en: - <<: *hskp_default - LABLAXIS: OPTICS_HV_P15KV_ENABLE - FIELDNAM: Optics HV - P15KV Enable - CATDESC: Optics HV - P15KV Enable - -esab_en: - <<: *hskp_default - LABLAXIS: OPTICS_HV_ESAB_ENABLE - FIELDNAM: Optics HV - ESA B Enable - CATDESC: Optics HV - ESA B Enable - -spare_2: - <<: *hskp_default - LABLAXIS: SPARE_2 - FIELDNAM: Spare (was Optics HV - ESA B Range) - CATDESC: Spare (was Optics HV - ESA B Range) - -esaa_en: - <<: *hskp_default - LABLAXIS: OPTICS_HV_ESAA_ENABLE - FIELDNAM: Optics HV - ESA A Enable - CATDESC: Optics HV - ESA A Enable - -spare_3: - <<: *hskp_default - LABLAXIS: SPARE_3 - FIELDNAM: Spare (was Optics HV - ESA A Range) - CATDESC: Spare (was Optics HV - ESA A Range) - -snsr_hv_cmd_err_cnt: - <<: *hskp_default - LABLAXIS: SENSOR_HV_CMD_ERR_CNT - FIELDNAM: Sensor HV - Number of command errors - CATDESC: Sensor HV - Number of command errors - -snsr_hv_arm_err_cnt: - <<: *hskp_default - LABLAXIS: SENSOR_HV_ARM_ERR_CNT - FIELDNAM: Sensor HV - Number of Arm errors - CATDESC: Sensor HV - Number of Arm errors - -snsr_hv_master_en: - <<: *hskp_default - LABLAXIS: SENSOR_HV_MASTER_ENABLE - FIELDNAM: Sensor HV - Master Enable - CATDESC: Sensor HV - Master Enable - -apdb_en: - <<: *hskp_default - LABLAXIS: SENSOR_HV_APD_BIAS_ENABLE - FIELDNAM: Sensor HV - APD Bias Enable - CATDESC: Sensor HV - APD Bias Enable - -sbulk_en: - <<: *hskp_default - LABLAXIS: SENSOR_HV_P6KV_ENABLE - FIELDNAM: Sensor HV - p6KV Enable - CATDESC: Sensor HV - p6KV Enable - -stpmcp_en: - <<: *hskp_default - LABLAXIS: SENSOR_HV_STOP_MCP_ENABLE - FIELDNAM: Sensor HV - Stop MCP Enable - CATDESC: Sensor HV - Stop MCP Enable - -strmcp_en: - <<: *hskp_default - LABLAXIS: SENSOR_HV_START_MCP_ENABLE - FIELDNAM: Sensor HV - Start MCP Enable - CATDESC: Sensor HV - Start MCP Enable - -spare_4: - <<: *hskp_default - LABLAXIS: SPARE_4 - FIELDNAM: Spare for alignment - CATDESC: Spare for alignment - -esaa_dac: - <<: *hskp_default - LABLAXIS: OPTICS_HV_DAC_ESA_A - FIELDNAM: Optics HV - ESA A DAC - FILLVAL: *uint16_fillval - CATDESC: Optics HV - ESA A DAC - -esab_dac: - <<: *hskp_default - LABLAXIS: OPTICS_HV_DAC_ESA_B - FIELDNAM: Optics HV - ESA B DAC - FILLVAL: *uint16_fillval - CATDESC: Optics HV - ESA B DAC - -iobulk_dac: - <<: *hskp_default - LABLAXIS: OPTICS_HV_DAC_IONBULK - FIELDNAM: Optics HV - Ion Bulk DAC - FILLVAL: *uint16_fillval - CATDESC: Optics HV - Ion Bulk DAC - -ssdo_dac: - <<: *hskp_default - LABLAXIS: SENSOR_HV_DAC_SSDO - FIELDNAM: Sensor HV - SSDO Enable - FILLVAL: *uint16_fillval - CATDESC: Sensor HV - SSDO Enable - -ssdb_dac: - <<: *hskp_default - LABLAXIS: SENSOR_HV_DAC_SSDB - FIELDNAM: Sensor HV - SSD Bias Enable - FILLVAL: *uint16_fillval - CATDESC: Sensor HV - SSD Bias Enable - -apdb_dac: - <<: *hskp_default - LABLAXIS: SENSOR_HV_DAC_APDB - FIELDNAM: Sensor HV - ADP Bias Enable - FILLVAL: *uint16_fillval - CATDESC: Sensor HV - ADP Bias Enable - -apdb2_dac: - <<: *hskp_default - LABLAXIS: SENSOR_HV_DAC_APDB2 - FIELDNAM: Sensor HV - ADP Bias 2 Enable - FILLVAL: *uint16_fillval - CATDESC: Sensor HV - ADP Bias 2 Enable - -strmcp_dac: - <<: *hskp_default - LABLAXIS: SENSOR_HV_DAC_START_MCP - FIELDNAM: Sensor HV - Start MCP DAC - FILLVAL: *uint16_fillval - CATDESC: Sensor HV - Start MCP DAC - -stpmcp_dac: - <<: *hskp_default - LABLAXIS: SENSOR_HV_DAC_STOP_MCP - FIELDNAM: Sensor HV - Stop MCP DAC - FILLVAL: *uint16_fillval - CATDESC: Sensor HV - Stop MCP DAC - -stpog_dac: - <<: *hskp_default - LABLAXIS: SENSOR_HV_DAC_STOP_OPTICS_GRID - FIELDNAM: Sensor HV - Stop Optics Grid DAC - FILLVAL: *uint16_fillval - CATDESC: Sensor HV - Stop Optics Grid DAC - -sbulk_vmon: - <<: *hskp_default - LABLAXIS: SBULK_VMON - FIELDNAM: HVPS - V1 -- Sensor Bulk Voltage Monitor - FILLVAL: *uint16_fillval - CATDESC: HVPS - V1 -- Sensor Bulk Voltage Monitor - -ssdo_vmon: - <<: *hskp_default - LABLAXIS: SSDO_VMON - FIELDNAM: HVPS - V2 -- SSD Optics Voltage Monitor - FILLVAL: *uint16_fillval - CATDESC: HVPS - V2 -- SSD Optics Voltage Monitor - -ssdb_vmon: - <<: *hskp_default - LABLAXIS: SSDB_VMON - FIELDNAM: HVPS - V3 -- SSD Bias Voltage Monitor - FILLVAL: *uint16_fillval - CATDESC: HVPS - V3 -- SSD Bias Voltage Monitor - -apdb1_vmon: - <<: *hskp_default - LABLAXIS: APDB1_VMON - FIELDNAM: HVPS - V4 -- APD1 Bias Voltage Monitor - FILLVAL: *uint16_fillval - CATDESC: HVPS - V4 -- APD1 Bias Voltage Monitor - -apdb2_vmon: - <<: *hskp_default - LABLAXIS: APDB2_VMON - FIELDNAM: HVPS - V5 -- APD1 Bias Voltage Monitor - FILLVAL: *uint16_fillval - CATDESC: HVPS - V5 -- APD1 Bias Voltage Monitor - -iobulk_vmon: - <<: *hskp_default - LABLAXIS: IOBULK_VMON - FIELDNAM: HVPS - V6 -- IO Bulk Voltage Monitor - FILLVAL: *uint16_fillval - CATDESC: HVPS - V6 -- IO Bulk Voltage Monitor - -esaa_hi_vmon: - <<: *hskp_default - LABLAXIS: ESAA_HI_VMON - FIELDNAM: HVPS - V7 -- ESA A High Range Voltage Monitor - FILLVAL: *uint16_fillval - CATDESC: HVPS - V7 -- ESA A High Range Voltage Monitor - -spare_62: - <<: *hskp_default - LABLAXIS: SPARE_62 - FIELDNAM: Spare (was ESAA_LO_VMON) - CATDESC: Spare (was ESAA_LO_VMON) - -strmcp_vmon: - <<: *hskp_default - LABLAXIS: STRMCP_VMON - FIELDNAM: HVPS - V9 -- Start MCP Voltage Monitor - FILLVAL: *uint16_fillval - CATDESC: HVPS - V9 -- Start MCP Voltage Monitor - -stpmcp_vmon: - <<: *hskp_default - LABLAXIS: STPMCP_VMON - FIELDNAM: HVPS - V10 -- Stop MCP Voltage Monitor - FILLVAL: *uint16_fillval - CATDESC: HVPS - V10 -- Stop MCP Voltage Monitor - -stpog_vmon: - <<: *hskp_default - LABLAXIS: STPOG_VMON - FIELDNAM: HVPS - V11 -- Stop Optics Grid Voltage Monitor - FILLVAL: *uint16_fillval - CATDESC: HVPS - V11 -- Stop Optics Grid Voltage Monitor - -apdb1_imon: - <<: *hskp_default - LABLAXIS: APDB1_IMON - FIELDNAM: HVPS - V12 -- APD1 Bias Current Monitor - FILLVAL: *uint16_fillval - CATDESC: HVPS - V12 -- APD1 Bias Current Monitor - -esab_hi_vmon: - <<: *hskp_default - LABLAXIS: ESAB_HI_VMON - FIELDNAM: HVPS - V13 -- ESA A High Range Voltage Monitor - FILLVAL: *uint16_fillval - CATDESC: HVPS - V13 -- ESA A High Range Voltage Monitor - -spare_68: - <<: *hskp_default - LABLAXIS: SPARE_68 - FIELDNAM: Spare (was ESAB_LO_VMON) - CATDESC: Spare (was ESAB_LO_VMON) - -apdb2_imon: - <<: *hskp_default - LABLAXIS: APDB2_IMON - FIELDNAM: HVPS - V15 -- APD2 Bias Current Monitor - FILLVAL: *uint16_fillval - CATDESC: HVPS - V15 -- APD2 Bias Current Monitor - -ssdb_imon: - <<: *hskp_default - LABLAXIS: SSDB_IMON - FIELDNAM: HVPS - V16 -- SSD Bias Current Monitor - FILLVAL: *uint16_fillval - CATDESC: HVPS - V16 -- SSD Bias Current Monitor - -stpmcp_imon: - <<: *hskp_default - LABLAXIS: STPMCP_IMON - FIELDNAM: HVPS - I1 -- Stop MCP Current Monitor - FILLVAL: *uint16_fillval - CATDESC: HVPS - I1 -- Stop MCP Current Monitor - -iobulk_imon: - <<: *hskp_default - LABLAXIS: IOBULK_IMON - FIELDNAM: HVPS - I2 -- IO Bulk Current Monitor - FILLVAL: *uint16_fillval - CATDESC: HVPS - I2 -- IO Bulk Current Monitor - -strmcp_imon: - <<: *hskp_default - LABLAXIS: STRMCP_IMON - FIELDNAM: HVPS - I3 -- Start MCP Current Monitor - FILLVAL: *uint16_fillval - CATDESC: HVPS - I3 -- Start MCP Current Monitor - -mdm25p_14_t: - <<: *hskp_default - LABLAXIS: MDM25P_14_T - FIELDNAM: System Temperature 1 -- MDM25P - 14 Temperature - FILLVAL: *uint16_fillval - CATDESC: System Temperature 1 -- MDM25P - 14 Temperature - -mdm25p_15_t: - <<: *hskp_default - LABLAXIS: MDM25P_15_T - FIELDNAM: System Temperature 2 -- MDM25P - 15 Temperature - FILLVAL: *uint16_fillval - CATDESC: System Temperature 2 -- MDM25P - 15 Temperature - -mdm25p_16_t: - <<: *hskp_default - LABLAXIS: MDM25P_16_T - FIELDNAM: System Temperature 3 -- MDM25P - 16 Temperature - FILLVAL: *uint16_fillval - CATDESC: System Temperature 3 -- MDM25P - 16 Temperature - -mdm51p_27_t: - <<: *hskp_default - LABLAXIS: MDM51P_27_T - FIELDNAM: LO Temperature -- MDM51P - 27 Temperature - FILLVAL: *uint16_fillval - CATDESC: LO Temperature -- MDM51P - 27 Temperature - -io_hvps_t: - <<: *hskp_default - LABLAXIS: IO_HVPS_T - FIELDNAM: HVPS Temperature -- IO-HVPS Temperature - FILLVAL: *uint16_fillval - CATDESC: HVPS Temperature -- IO-HVPS Temperature - -lvps_12v_t: - <<: *hskp_default - LABLAXIS: LVPS_12V_T - FIELDNAM: LVPS Temperature 1 -- LVPS - 12V Temperature - FILLVAL: *uint16_fillval - CATDESC: LVPS Temperature 1 -- LVPS - 12V Temperature - -lvps_5v_t: - <<: *hskp_default - LABLAXIS: LVPS_5V_T - FIELDNAM: LVPS Temperature 2 -- LVPS - 5V Temperature - FILLVAL: *uint16_fillval - CATDESC: LVPS Temperature 2 -- LVPS - 5V Temperature - -lvps_3p3v_t: - <<: *hskp_default - LABLAXIS: LVPS_3P3V_T - FIELDNAM: LVPS Temperature 3 -- LVPS - +3.3V Temperature - FILLVAL: *uint16_fillval - CATDESC: LVPS Temperature 3 -- LVPS - +3.3V Temperature - -lvps_3p3v: - <<: *hskp_default - LABLAXIS: LVPS_3P3V - FIELDNAM: LVPS - Digital V1 -- LVPS - +3.3V - FILLVAL: *uint16_fillval - CATDESC: LVPS - Digital V1 -- LVPS - +3.3V - -lvps_5v: - <<: *hskp_default - LABLAXIS: LVPS_5V - FIELDNAM: LVPS - Digital V2 -- LVPS - +5V - FILLVAL: *uint16_fillval - CATDESC: LVPS - Digital V2 -- LVPS - +5V - -lvps_n5v: - <<: *hskp_default - LABLAXIS: LVPS_N5V - FIELDNAM: LVPS - Digital V3 -- LVPS - -5V - FILLVAL: *uint16_fillval - CATDESC: LVPS - Digital V3 -- LVPS - -5V - -lvps_12v: - <<: *hskp_default - LABLAXIS: LVPS_12V - FIELDNAM: LVPS - Digital V4 -- LVPS - +12V - FILLVAL: *uint16_fillval - CATDESC: LVPS - Digital V4 -- LVPS - +12V - -lvps_n12v: - <<: *hskp_default - LABLAXIS: LVPS_N12V - FIELDNAM: LVPS - Digital V5 -- LVPS - -12V - FILLVAL: *uint16_fillval - CATDESC: LVPS - Digital V5 -- LVPS - -12V - -lvps_3p3v_i: - <<: *hskp_default - LABLAXIS: LVPS_3P3V_I - FIELDNAM: LVPS - Digital I1 -- LVPS - +3.3V Current - FILLVAL: *uint16_fillval - CATDESC: LVPS - Digital I1 -- LVPS - +3.3V Current - -lvps_5v_i: - <<: *hskp_default - LABLAXIS: LVPS_5V_I - FIELDNAM: LVPS - Digital I2 -- LVPS - +5V Current - FILLVAL: *uint16_fillval - CATDESC: LVPS - Digital I2 -- LVPS - +5V Current - -lvps_n5v_i: - <<: *hskp_default - LABLAXIS: LVPS_N5V_I - FIELDNAM: LVPS - Digital I3 -- LVPS - -5V Current - FILLVAL: *uint16_fillval - CATDESC: LVPS - Digital I3 -- LVPS - -5V Current - -lvps_12v_i: - <<: *hskp_default - LABLAXIS: LVPS_12V_I - FIELDNAM: LVPS - Digital I4 -- LVPS - +12V Current - FILLVAL: *uint16_fillval - CATDESC: LVPS - Digital I4 -- LVPS - +12V Current - -lvps_n12v_i: - <<: *hskp_default - LABLAXIS: LVPS_N12V_I - FIELDNAM: LVPS - Digital I5 -- LVPS - -12V Current - FILLVAL: *uint16_fillval - CATDESC: LVPS - Digital I5 -- LVPS - -12V Current - -cdh_1p5v: - <<: *hskp_default - LABLAXIS: CDH_1P5V - FIELDNAM: CDH - + 1.5V - FILLVAL: *uint16_fillval - CATDESC: CDH - + 1.5V - -cdh_1p8v: - <<: *hskp_default - LABLAXIS: CDH_1P8V - FIELDNAM: CDH - +1.8V - FILLVAL: *uint16_fillval - CATDESC: CDH - +1.8V - -cdh_3p3v: - <<: *hskp_default - LABLAXIS: CDH_3P3V - FIELDNAM: CDH - +3.3V - FILLVAL: *uint16_fillval - CATDESC: CDH - +3.3V - -cdh_12v: - <<: *hskp_default - LABLAXIS: CDH_12V - FIELDNAM: CDH - +12V - FILLVAL: *uint16_fillval - CATDESC: CDH - +12V - -cdh_n12v: - <<: *hskp_default - LABLAXIS: CDH_N12V - FIELDNAM: CDH - -12V - FILLVAL: *uint16_fillval - CATDESC: CDH - -12V - -cdh_5v: - <<: *hskp_default - LABLAXIS: CDH_5V - FIELDNAM: CDH - +5V - FILLVAL: *uint16_fillval - CATDESC: CDH - +5V - -cdh_5v_adc: - <<: *hskp_default - LABLAXIS: CDH_5V_ADC - FIELDNAM: CDH - Analog Ref -- CDH - +5V ADC - FILLVAL: *uint16_fillval - CATDESC: CDH - Analog Ref -- CDH - +5V ADC - -tbd_hvps_1_if_err_cnt: - <<: *hskp_default - LABLAXIS: TBD_HVPS_1_IF_ERR_CNT - FIELDNAM: TBD - Placeholder for HVPS 1 Interface error counts - CATDESC: TBD - Placeholder for HVPS 1 Interface error counts - -tbd_hvps_2_if_err_cnt: - <<: *hskp_default - LABLAXIS: TBD_HVPS_2_IF_ERR_CNT - FIELDNAM: TBD - Placeholder for HVPS 2 Interface error counts - CATDESC: TBD - Placeholder for HVPS 2 Interface error counts - -tbd_fee_1_if_err_cnt: - <<: *hskp_default - LABLAXIS: TBD_FEE_1_IF_ERR_CNT - FIELDNAM: TBD - Placeholder for FEE 1 Interface error counts - CATDESC: TBD - Placeholder for FEE 1 Interface error counts - -tbd_fee_2_if_err_cnt: - <<: *hskp_default - LABLAXIS: TBD_FEE_2_IF_ERR_CNT - FIELDNAM: TBD - Placeholder for FEE 2 Interface error counts - CATDESC: TBD - Placeholder for FEE 2 Interface error counts - -tbd_macro_status: - <<: *hskp_default - LABLAXIS: TBD_MACRO_STATUS - FIELDNAM: TBD - Placeholder for Macro status - FILLVAL: *uint32_fillval - CATDESC: TBD - Placeholder for Macro status - -fdc_trigger_cnt_fsw: - <<: *hskp_default - LABLAXIS: FDC_TRIGGER_CNT_FSW - FIELDNAM: Indicates whether any CATEGORY 1 limits have triggered - CATDESC: Indicates any CATEGORY 1 limits triggered. See VAR_NOTES for more details. - VAR_NOTES: Indicates whether any CATEGORY 1 limits have triggered -- 2 bits -- 0=No triggers; 1=One trigger; 2=Two triggers; 3=More than two triggers - -fdc_trigger_cnt_hvps: - <<: *hskp_default - LABLAXIS: FDC_TRIGGER_CNT_HVPS - FIELDNAM: Indicates whether any CATEGORY 2 limits have triggered - CATDESC: Indicates whether any CATEGORY 2 limits have triggered - -fdc_trigger_cnt_cdh: - <<: *hskp_default - LABLAXIS: FDC_TRIGGER_CNT_CDH - FIELDNAM: Indicates whether any CATEGORY 3 limits have triggered - CATDESC: Indicates whether any CATEGORY 3 limits have triggered - -fdc_trigger_cnt_fee: - <<: *hskp_default - LABLAXIS: FDC_TRIGGER_CNT_FEE - FIELDNAM: Indicates whether any CATEGORY 4 limits have triggered - CATDESC: Indicates whether any CATEGORY 4 limits have triggered - -fdc_trigger_cnt_spare1: - <<: *hskp_default - LABLAXIS: FDC_TRIGGER_CNT_SPARE1 - FIELDNAM: Indicates whether any CATEGORY 5 limits have triggered - CATDESC: Indicates whether any CATEGORY 5 limits have triggered - -fdc_trigger_cnt_spare2: - <<: *hskp_default - LABLAXIS: FDC_TRIGGER_CNT_SPARE2 - FIELDNAM: Indicates whether any CATEGORY 6 limits have triggered - CATDESC: Indicates whether any CATEGORY 6 limits have triggered - -fdc_trigger_cnt_spare3: - <<: *hskp_default - LABLAXIS: FDC_TRIGGER_CNT_SPARE3 - FIELDNAM: Indicates whether any CATEGORY 7 limits have triggered - CATDESC: Indicates whether any CATEGORY 7 limits have triggered - -fdc_trigger_cnt_spare4: - <<: *hskp_default - LABLAXIS: FDC_TRIGGER_CNT_SPARE4 - FIELDNAM: Indicates whether any CATEGORY 8 limits have triggered - CATDESC: Indicates whether any CATEGORY 8 limits have triggered - -fdc_last_trigger_minmax: - <<: *hskp_default - LABLAXIS: FDC_LAST_TRIGGER_MINMAX - FIELDNAM: Indicates whether the most recent trigger was a minimum or maximum limit - CATDESC: Indicates whether the most recent trigger was a minimum or maximum limit - -fdc_last_trigger_id: - <<: *hskp_default - LABLAXIS: FDC_LAST_TRIGGER_ID - FIELDNAM: Indicates the ID of the most recent FDC trigger - FILLVAL: *uint16_fillval - CATDESC: Indicates the ID of the most recent FDC trigger - -fdc_last_trigger_action: - <<: *hskp_default - LABLAXIS: FDC_LAST_TRIGGER_ACTION - FIELDNAM: Indicates the action that was taken for the most recent FDC trigger - CATDESC: Indicates the action that was taken for the most recent FDC trigger - -round_robin_index: - <<: *hskp_default - LABLAXIS: ROUND_ROBIN_INDEX - FIELDNAM: Round Robin Parameter Report Index - FILLVAL: *uint32_fillval - CATDESC: Index for Round Robin parameter reporting. See VAR_NOTES for more details. - VAR_NOTES: Current index for the Round Robin parameter reporting. The Round Robin mechanism reports one value from the Parameter Table each time this packet is generated. +# <=== Direct Events Attributes ===> -round_robin_value: - <<: *hskp_default - LABLAXIS: ROUND_ROBIN_VALUE - FIELDNAM: Round Robin Parameter Report Value - FILLVAL: *uint32_fillval - CATDESC: Parameter value corresponding to the current Round_Robin_Index value. - -heater_control_state: - <<: *hskp_default - LABLAXIS: HEATER_CONTROL_STATE - FIELDNAM: State of the heater controller - CATDESC: Indicates whether FSW control of the operational heater is enabled - -heater_output_state: - <<: *hskp_default - LABLAXIS: HEATER_OUTPUT_STATE - FIELDNAM: State of the heater output - CATDESC: Indicates the current state of the physical heater output - -heater_output_state_2: - <<: *hskp_default - LABLAXIS: HEATER_OUTPUT_STATE_2 - FIELDNAM: State of the heater output 2 - CATDESC: Indicates the current state of the physical heater output - -spare_5: - <<: *hskp_default - LABLAXIS: SPARE_5 - FIELDNAM: Spare for alignment - CATDESC: Spare for alignment - -cpu_idle: - <<: *hskp_default - LABLAXIS: CPU_IDLE - FIELDNAM: CPU Idle Percent - CATDESC: CPU Idle Percent - -cdh_processor_t: - <<: *hskp_default - LABLAXIS: CDH_PROCESSOR_T - FIELDNAM: CDH - Processor Temp monitor - FILLVAL: *uint16_fillval - CATDESC: CDH - Processor Temp monitor - -cdh_1p8v_ldo_t: - <<: *hskp_default - LABLAXIS: CDH_1P8V_LDO_T - FIELDNAM: CDH - +1.8V LDO Temp monitor - FILLVAL: *uint16_fillval - CATDESC: CDH - +1.8V LDO Temp monitor - -cdh_1p5v_ldo_t: - <<: *hskp_default - LABLAXIS: CDH_1P5V_LDO_T - FIELDNAM: CDH - +1.5V LDO Temp monitor - FILLVAL: *uint16_fillval - CATDESC: CDH - +1.5V LDO Temp monitor - -cdh_sdram_t: - <<: *hskp_default - LABLAXIS: CDH_SDRAM_T - FIELDNAM: CDH - SDRAM Temp monitor - FILLVAL: *uint16_fillval - CATDESC: CDH - SDRAM Temp monitor - -snsr_hvps_t: - <<: *hskp_default - LABLAXIS: SNSR_HVPS_T - FIELDNAM: CoDICE - Sensor HVPS Temp monitor - FILLVAL: *uint16_fillval - CATDESC: CoDICE - Sensor HVPS Temp monitor - -fee_apd_3p3_digital_v: - <<: *hskp_default - LABLAXIS: FEE_APD_3P3_DIGITAL_V - FIELDNAM: FEE; APD Side +3.3V Digital - FILLVAL: *uint16_fillval - CATDESC: FEE; APD Side +3.3V Digital - -fee_apd_5p0_analog_v: - <<: *hskp_default - LABLAXIS: FEE_APD_5P0_ANALOG_V - FIELDNAM: FEE; APD Side +5.0V Analog - FILLVAL: *uint16_fillval - CATDESC: FEE; APD Side +5.0V Analog - -fee_apd_t: - <<: *hskp_default - LABLAXIS: FEE_APD_T - FIELDNAM: FEE; APD Side Temperature - FILLVAL: *uint16_fillval - CATDESC: FEE; APD Side Temperature - -fee_apd_12p0_analog_v: - <<: *hskp_default - LABLAXIS: FEE_APD_12P0_ANALOG_V - FIELDNAM: FEE; APD Side +12.0V Analog - FILLVAL: *uint16_fillval - CATDESC: FEE; APD Side +12.0V Analog - -fee_apd_eb_temp_1_t: - <<: *hskp_default - LABLAXIS: FEE_APD_EB_TEMP_1_T - FIELDNAM: FEE; AEB Temp Sensor 1 - FILLVAL: *uint16_fillval - CATDESC: FEE; AEB Temp Sensor 1 - -fee_apd_eb_temp_2_t: - <<: *hskp_default - LABLAXIS: FEE_APD_EB_TEMP_2_T - FIELDNAM: FEE; AEB Temp Sensor 2 - FILLVAL: *uint16_fillval - CATDESC: FEE; AEB Temp Sensor 2 - -fee_apd_eb_temp_3_t: - <<: *hskp_default - LABLAXIS: FEE_APD_EB_TEMP_3_T - FIELDNAM: FEE; AEB Temp Sensor 3 - FILLVAL: *uint16_fillval - CATDESC: FEE; AEB Temp Sensor 3 - -fee_apd_eb_temp_4_t: - <<: *hskp_default - LABLAXIS: FEE_APD_EB_TEMP_4_T - FIELDNAM: FEE; AEB Temp Sensor 4 - FILLVAL: *uint16_fillval - CATDESC: FEE; AEB Temp Sensor 4 - -fee_ssd_3p3_digital_v: - <<: *hskp_default - LABLAXIS: FEE_SSD_3P3_DIGITAL_V - FIELDNAM: FEE; SSD Side +3.3V Digital - FILLVAL: *uint16_fillval - CATDESC: FEE; SSD Side +3.3V Digital - -fee_ssd_5p0_analog_v: - <<: *hskp_default - LABLAXIS: FEE_SSD_5P0_ANALOG_V - FIELDNAM: FEE; SSD Side +5.0V Analog - FILLVAL: *uint16_fillval - CATDESC: FEE; SSD Side +5.0V Analog - -fee_ssd_t: - <<: *hskp_default - LABLAXIS: FEE_SSD_T - FIELDNAM: FEE; SSD Side Temperature - FILLVAL: *uint16_fillval - CATDESC: FEE; SSD Side Temperature - -fee_ssd_12p0_analog_v: - <<: *hskp_default - LABLAXIS: FEE_SSD_12P0_ANALOG_V - FIELDNAM: FEE; SSD Side +12.0V Analog - FILLVAL: *uint16_fillval - CATDESC: FEE; SSD Side +12.0V Analog - -fee_ssd_eb_temp_1_t: - <<: *hskp_default - LABLAXIS: FEE_SSD_EB_TEMP_1_T - FIELDNAM: FEE; SEB Temp Sensor 1 - FILLVAL: *uint16_fillval - CATDESC: FEE; SEB Temp Sensor 1 - -fee_ssd_eb_temp_2_t: - <<: *hskp_default - LABLAXIS: FEE_SSD_EB_TEMP_2_T - FIELDNAM: FEE; SEB Temp Sensor 2 - FILLVAL: *uint16_fillval - CATDESC: FEE; SEB Temp Sensor 2 - -fee_ssd_eb_temp_3_t: - <<: *hskp_default - LABLAXIS: FEE_SSD_EB_TEMP_3_T - FIELDNAM: FEE; SEB Temp Sensor 3 - FILLVAL: *uint16_fillval - CATDESC: FEE; SEB Temp Sensor 3 - -fee_ssd_eb_temp_4_t: - <<: *hskp_default - LABLAXIS: FEE_SSD_EB_TEMP_4_T - FIELDNAM: FEE; SEB Temp Sensor 4 - FILLVAL: *uint16_fillval - CATDESC: FEE; SEB Temp Sensor 4 - -spare_6: - <<: *hskp_default - LABLAXIS: SPARE_6 - FIELDNAM: Spare for alignment - CATDESC: Spare for alignment \ No newline at end of file +# Data quality and num of events attrs +de_2d_attrs: + CATDESC: Direct event data + DEPEND_0: epoch + DEPEND_1: priority + DICT_KEY: SPASE>Support>SupportQuantity:Other + DISPLAY_TYPE: spectogram + FIELDNAM: Direct Event Data + FILLVAL: -9223372036854775808 + FORMAT: I5 + LABLAXIS: Values + SCALETYP: linear + UNITS: " " + VALIDMAX: 65535 + VALIDMIN: 0 + VAR_TYPE: support_data + +# unpacked 64-bits attrs +de_3d_attrs: + CATDESC: Direct event data + DEPEND_0: epoch + DEPEND_1: priority + DEPEND_2: event_num + DICT_KEY: SPASE>Support>SupportQuantity:Other + DISPLAY_TYPE: spectogram + FIELDNAM: Direct Event Data + FILLVAL: -9223372036854775808 + FORMAT: I{num_digits} + LABLAXIS: Values + SCALETYP: linear + UNITS: " " + VALIDMAX: "{valid_max}" + VALIDMIN: 0 + VAR_TYPE: support_data diff --git a/imap_processing/cdf/config/imap_codice_l1b_variable_attrs.yaml b/imap_processing/cdf/config/imap_codice_l1b_variable_attrs.yaml deleted file mode 100644 index ac5fb08050..0000000000 --- a/imap_processing/cdf/config/imap_codice_l1b_variable_attrs.yaml +++ /dev/null @@ -1,3433 +0,0 @@ -# <=== Useful Variables ===> -int_fillval: &int_fillval -9223372036854775808 -uint8_fillval: &uint8_fillval 255 -uint16_fillval: &uint16_fillval 65535 -uint32_fillval: &uint32_fillval 4294967295 -real_fillval: &real_fillval -1.0e+31 - -min_int: &min_int -9223372036854775808 -min_epoch: &min_epoch -315575942816000000 - -max_int: &max_int 9223372036854775807 -max_uint8: &max_uint8 255 -max_uint16: &max_uint16 65535 -max_uint24: &max_uint24 8388607 -max_uint32: &max_uint32 4294967295 -max_real: &max_real 1.0e+31 -max_epoch: &max_epoch 3155630469184000000 - - -# <=== Defaults ===> -default_attrs: &default - DEPEND_0: epoch - DISPLAY_TYPE: no_plot - FIELDNAM: " " - FILLVAL: *int_fillval - FORMAT: I12 - SCALETYP: linear - UNITS: dN - VALIDMIN: *min_int - VALIDMAX: *max_int - VAR_TYPE: data - -hskp_attrs: &hskp_default - <<: *default - FILLVAL: *uint8_fillval - VAR_TYPE: support_data - -hi_energies_attrs: &hi_energies_default - DISPLAY_TYPE: no_plot - FIELDNAM: Energy Table - FILLVAL: *real_fillval - FORMAT: F12.9 - SCALETYP: log - UNITS: MeV/n - VALIDMIN: 0.0 - VALIDMAX: 200.00 - VAR_TYPE: support_data - -hi_priorities_attrs: &hi_priorities_default - DEPEND_0: epoch - DISPLAY_TYPE: time_series - FILLVAL: *real_fillval - FORMAT: F10.5 - LABLAXIS: "events" - UNITS: events - VALIDMIN: 0 - VALIDMAX: *max_uint32 - VAR_TYPE: data - - -# <=== Coordinates ===> -epoch_delta_minus: - CATDESC: Time from acquisition start to acquisition center - FIELDNAM: epoch_delta_minus - FILLVAL: *int_fillval - FORMAT: I18 - LABLAXIS: epoch_delta_minus - SCALETYP: linear - UNITS: ns - VALIDMIN: *min_int - VALIDMAX: *max_int - VAR_TYPE: support_data - -epoch_delta_plus: - CATDESC: Time from acquisition center to acquisition end - FIELDNAM: epoch_delta_plus - FILLVAL: *int_fillval - FORMAT: I18 - LABLAXIS: epoch_delta_plus - SCALETYP: linear - UNITS: ns - VALIDMIN: *min_int - VALIDMAX: *max_int - VAR_TYPE: support_data - -esa_step: - CATDESC: Energy per charge (E/q) sweeping step - FIELDNAM: Energy Index - FILLVAL: 254 - FORMAT: I3 - LABLAXIS: Energy Index - SCALETYP: linear - UNITS: " " - VALIDMIN: 0 - VALIDMAX: 127 - VAR_TYPE: support_data - -event_num: - CATDESC: Event Number - FIELDNAM: Event Number - FILLVAL: 65535 - FORMAT: I5 - LABLAXIS: Event Number - SCALETYP: linear - UNITS: " " - VALIDMIN: 0 - VALIDMAX: 10000 - VAR_TYPE: support_data - -inst_az: - CATDESC: Instrument Azimuth Index - FIELDNAM: Azimuth Index - FILLVAL: 254 - FORMAT: I3 - LABLAXIS: Azimuth Index - SCALETYP: linear - UNITS: " " - VALIDMIN: 0 - VALIDMAX: 31 - VAR_TYPE: support_data - -spin_sector: - CATDESC: Spin sector indicating range of spin angles - FIELDNAM: Spin Sector Index - FILLVAL: 254 - FORMAT: I3 - LABLAXIS: Spin Sector - SCALETYP: linear - UNITS: " " - VALIDMIN: 0 - VALIDMAX: 12 - VAR_TYPE: support_data - -spin_sector_pairs: - CATDESC: Spin sector Pairs - FIELDNAM: Spin Sector Pairs - FILLVAL: -1 - FORMAT: I1 - LABLAXIS: " " - SCALETYP: linear - UNITS: " " - VALIDMIN: 0 - VALIDMAX: 6 - VAR_TYPE: support_data - -spin_sector_index: - CATDESC: Spin Sector Index - FIELDNAM: Spin Sector Index - FILLVAL: -1 - FORMAT: I2 - LABLAXIS: " " - SCALETYP: linear - UNITS: " " - VALIDMIN: 0 - VALIDMAX: 12 - VAR_TYPE: support_data - -ssd_index: - CATDESC: SSD Index - FIELDNAM: SSD Index - FILLVAL: -1 - FORMAT: I2 - LABLAXIS: " " - SCALETYP: linear - UNITS: " " - VALIDMIN: 0 - VALIDMAX: 12 - VAR_TYPE: support_data - -# <=== Labels ===> -esa_step_label: - CATDESC: ESA Step - DEPEND_1: esa_step - FIELDNAM: ESA Step - FORMAT: A3 - VAR_TYPE: metadata - -event_num_label: - CATDESC: Event Number - DEPEND_1: event_num - FIELDNAM: Event Number - FORMAT: A5 - VAR_TYPE: metadata - -inst_az_label: - CATDESC: Instrument Azimuth - DEPEND_1: inst_az - FIELDNAM: Instrument Azimuth - FORMAT: A2 - VAR_TYPE: metadata - -spin_sector_label: - CATDESC: Spin Sector - DEPEND_1: spin_sector - FIELDNAM: Spin Sector - FORMAT: A2 - VAR_TYPE: metadata - -spin_sector_index_label: - CATDESC: Spin Sector Index - DEPEND_1: spin_sector_index - FIELDNAM: Spin Sector Index - FORMAT: A2 - VAR_TYPE: metadata - -spin_sector_pairs_label: - CATDESC: Spin Sector Pairs - DEPEND_1: spin_sector_pairs - FIELDNAM: Spin Sector Pairs - FORMAT: A11 - VAR_TYPE: metadata - -ssd_index_label: - CATDESC: SSD Index - DEPEND_1: ssd_index - FIELDNAM: SSD Index - FORMAT: A2 - VAR_TYPE: metadata - -# <=== Dataset Variable Attributes ===> -# The following are set in multiple data products -acquisition_time_per_step: - CATDESC: Acquisition time for each step of energy - DEPEND_1: esa_step - FIELDNAM: Acquisition Time - FILLVAL: *real_fillval - FORMAT: F10.3 - LABLAXIS: Acquisition Time - SCALETYP: linear - UNITS: ms - VALIDMIN: 0.000000 - VALIDMAX: 625.000000 - VAR_TYPE: support_data - -counters_attrs: &counters - <<: *default - CATDESC: Fill in at creation - DISPLAY_TYPE: time_series - FIELDNAM: Fill in at creation - FILLVAL: *real_fillval - FORMAT: F12.6 - SCALETYP: linear - UNITS: counts - VALIDMIN: 0 - VALIDMAX: *max_real - VAR_TYPE: data - -events_attrs: &events - <<: *default - CATDESC: Fill in at creation - DISPLAY_TYPE: time_series - FIELDNAM: Fill in at creation - FILLVAL: *real_fillval - FORMAT: F12.6 - SCALETYP: linear - UNITS: counts - VALIDMIN: 0 - VALIDMAX: *max_real - VAR_TYPE: data - -data_quality: - <<: *default - CATDESC: Indicates whether data quality is suspect (1). - DISPLAY_TYPE: time_series - FIELDNAM: Data Quality - FILLVAL: 255 - FORMAT: I1 - LABLAXIS: Data Quality - SCALETYP: linear - UNITS: " " - VALIDMIN: 0 - VALIDMAX: 1 - VAR_TYPE: data - -direct_events_attrs: &direct_events - <<: *default - CATDESC: Fill in at creation - DISPLAY_TYPE: time_series - FIELDNAM: Fill in at creation - FILLVAL: 255 - FORMAT: I5 - UNITS: unitless - VALIDMIN: 0 - VALIDMAX: 10000 - -energy_table: - CATDESC: ElectroStatic Analyzer Energy Values - DEPEND_1: esa_step - FIELDNAM: Energy Table - FORMAT: F12.6 - LABLAXIS: eV - SCALETYP: log - UNITS: eV - VALIDMIN: 1.0 - VALIDMAX: 14100.0 - VAR_TYPE: support_data - -k_factor: - CATDESC: K Factor constant that is used to convert voltages to energies - FIELDNAM: K Factor - FORMAT: F5.2 - LABLAXIS: K Factor - SCALETYP: linear - UNITS: " " - VALIDMIN: 1.0 - VALIDMAX: 100.0 - VAR_TYPE: support_data - -nso_half_spin: - <<: *default - CATDESC: When No Scan Operation (NSO) was activated - DISPLAY_TYPE: time_series - FIELDNAM: NSO Mode - FILLVAL: 255 - FORMAT: I3 - LABLAXIS: NSO Half Spin - SCALETYP: linear - UNITS: half spin number - VALIDMIN: 0 - VALIDMAX: 255 - VAR_NOTES: Indicates the point when No Scan Operation (NSO) was activated. In NSO, the ESA voltage is set to the first step in the scan and remains fixed until the next cycle boundary. - VAR_TYPE: data - -rgfo_half_spin: - <<: *default - CATDESC: When Reduced Gain Factor Operation (RGFO) was activated - DISPLAY_TYPE: time_series - FIELDNAM: RGFO Mode - FILLVAL: 255 - FORMAT: I3 - LABLAXIS: RGFO Half Spin - SCALETYP: linear - UNITS: half spin number - VALIDMIN: 0 - VALIDMAX: 255 - VAR_NOTES: Indicates the point when Reduced Gain Factor Operation (RGFO) was activated. In RGFO, the Entrance ESA voltage is reduced in order to limit the number of ions that reach the detectors. - VAR_TYPE: data - -spin_period: - <<: *default - CATDESC: The spin period as reported by the spacecraft. - DISPLAY_TYPE: time_series - FIELDNAM: Spin Period - FILLVAL: *real_fillval - FORMAT: F10.3 - LABLAXIS: Spin Period - SCALETYP: linear - UNITS: s - VALIDMIN: 0.0 - VALIDMAX: 16.0 - VAR_TYPE: data - -st_bias_gain_mode: - <<: *default - CATDESC: Suprathermal Bias Gain Mode - DISPLAY_TYPE: no_plot - FIELDNAM: Suprathermal Bias Gain Mode - FILLVAL: 255 - FORMAT: I1 - LABLAXIS: Suprathermal Bias Gain Mode - SCALETYP: linear - UNITS: " " - VALIDMIN: 0 - VALIDMAX: 1 - VAR_NOTES: Indicates whether FSW is tracking the Suprathermal High-Gain bias curve or the Suprathermal Low-Gain bias curve. - VAR_TYPE: data - -sw_bias_gain_mode: - <<: *default - CATDESC: Solarwind Bias Gain Mode - DISPLAY_TYPE: no_plot - FIELDNAM: Solarwind Bias Gain Mode - FILLVAL: 255 - FORMAT: I1 - LABLAXIS: Solarwind Bias Gain Mode - SCALETYP: linear - UNITS: " " - VALIDMIN: 0 - VALIDMAX: 1 - VAR_NOTES: Indicates whether FSW is tracking the Solarwind High-Gain bias curve or the Solarwind Low-Gain bias curve. - VAR_TYPE: data - -# The following are data product-specific -# hi-counters-aggregated -hi-counters-aggregated-DCR: - <<: *events - CATDESC: Event B - Double Coincidence Rate (DCR) - FIELDNAM: DCRs - LABLAXIS: "events" - -hi-counters-aggregated-STO: - <<: *events - CATDESC: Event C - Start Only (STO) - FIELDNAM: Start Only - LABLAXIS: "events" - -hi-counters-aggregated-SPO: - <<: *events - CATDESC: Event D - Stop Only (SPO) - FIELDNAM: Stop Only - LABLAXIS: "events" - -hi-counters-aggregated-Reserved1: - <<: *events - CATDESC: Reserved 1 - FIELDNAM: Reserved 1 - LABLAXIS: "events" - -hi-counters-aggregated-MST: - <<: *events - CATDESC: Event H - Multi Start (MST) - FIELDNAM: Multi Start - LABLAXIS: "events" - -hi-counters-aggregated-Reserved2: - <<: *events - CATDESC: Reserved 2 - FIELDNAM: Reserved 2 - LABLAXIS: "events" - -hi-counters-aggregated-Reserved3: - <<: *events - CATDESC: Reserved 3 - FIELDNAM: Reserved 3 - LABLAXIS: "events" - -hi-counters-aggregated-Reserved4: - <<: *events - CATDESC: Reserved 4 - FIELDNAM: Reserved 4 - LABLAXIS: "events" - -hi-counters-aggregated-Reserved5: - <<: *events - CATDESC: Reserved 5 - FIELDNAM: Reserved 5 - LABLAXIS: "events" - -hi-counters-aggregated-LowTOFCutoff: - <<: *events - CATDESC: Low TOF Cutoff - FIELDNAM: Low TOF Cutoff - LABLAXIS: "events" - -hi-counters-aggregated-Reserved6: - <<: *events - CATDESC: Reserved 6 - FIELDNAM: Reserved 6 - LABLAXIS: "events" - -hi-counters-aggregated-Reserved7: - <<: *events - CATDESC: Reserved 7 - FIELDNAM: Reserved 7 - LABLAXIS: "events" - -hi-counters-aggregated-ASIC1FlagInvalid: - <<: *events - CATDESC: ASIC 1 Flag Invalid Count - FIELDNAM: ASIC 1 Flag Invalid - LABLAXIS: "events" - -hi-counters-aggregated-ASIC2FlagInvalid: - <<: *events - CATDESC: ASIC 2 Flag Invalid Count - FIELDNAM: ASIC 2 Flag Invalid - LABLAXIS: "events" - -hi-counters-aggregated-ASIC1ChannelInvalid: - <<: *events - CATDESC: ASIC 1 Channel Invalid Count - FIELDNAM: ASIC 1 Channel Invalid - LABLAXIS: "events" - -hi-counters-aggregated-ASIC2ChannelInvalid: - <<: *events - CATDESC: ASIC 2 Channel Invalid Count - FIELDNAM: ASIC 2 Channel Invalid - LABLAXIS: "events" - -# hi-counters-singles -hi-counters-singles-tcr: - <<: *counters - CATDESC: Rates - Event A (TCR) - FIELDNAM: Rates - DEPEND_1: ssd_index - LABL_PTR_1: ssd_index_label - UNITS: events - -hi-counters-singles-ssdo: - <<: *counters - CATDESC: Rates - Event E (SSDO) - FIELDNAM: Rates - DEPEND_1: ssd_index - LABL_PTR_1: ssd_index_label - UNITS: events - -hi-counters-singles-stssd: - <<: *counters - CATDESC: Rates - Event G (STSSD) - FIELDNAM: Rates - DEPEND_1: ssd_index - LABL_PTR_1: ssd_index_label - UNITS: events - -# hi-ialirt -hi-ialirt-h: - <<: *counters - CATDESC: Omnidirectional H Rates - FIELDNAM: H - DEPEND_1: energy_h - LABL_PTR_1: energy_h - VALIDMAX: *max_uint32 - -hi-ialirt-energy_h: - <<: *hi_energies_default - CATDESC: Energy Table for h - DELTA_MINUS_VAR: energy_h_minus - DELTA_PLUS_VAR: energy_h_plus - -hi-ialirt-energy_h_delta: - <<: *hi_energies_default - CATDESC: Delta of energies for h - FIELDNAM: Delta Energy - -# hi-omni -hi-omni-h: - <<: *counters - CATDESC: Omnidirectional H Rates - FIELDNAM: H - DEPEND_1: energy_h - LABL_PTR_1: energy_h - -hi-omni-energy_h: - <<: *hi_energies_default - CATDESC: Energy Table for h - DELTA_MINUS_VAR: energy_h_minus - DELTA_PLUS_VAR: energy_h_plus - -hi-omni-energy_h_delta: - <<: *hi_energies_default - CATDESC: Delta of energies for h - FIELDNAM: Delta Energy - -hi-omni-he3: - <<: *counters - CATDESC: Omnidirectional He3 Rates - FIELDNAM: He3 - DEPEND_1: energy_he3 - LABL_PTR_1: energy_he3 - -hi-omni-energy_he3: - <<: *hi_energies_default - CATDESC: Energy Table for he3 - DELTA_MINUS_VAR: energy_he3_minus - DELTA_PLUS_VAR: energy_he3_plus - -hi-omni-energy_he3_delta: - <<: *hi_energies_default - CATDESC: Delta of energies for he3 - FIELDNAM: Delta Energy - -hi-omni-he4: - <<: *counters - CATDESC: Omnidirectional He4 Rates - FIELDNAM: He4 - DEPEND_1: energy_he4 - LABL_PTR_1: energy_he4 - -hi-omni-energy_he4: - <<: *hi_energies_default - CATDESC: Energy Table for he4 - DELTA_MINUS_VAR: energy_he4_minus - DELTA_PLUS_VAR: energy_he4_plus - -hi-omni-energy_he4_delta: - <<: *hi_energies_default - CATDESC: Delta of energies for he4 - FIELDNAM: Delta Energy - -hi-omni-c: - <<: *counters - CATDESC: Omnidirectional C Rates - FIELDNAM: C - DEPEND_1: energy_c - LABL_PTR_1: energy_c - -hi-omni-energy_c: - <<: *hi_energies_default - CATDESC: Energy Table for c - DELTA_MINUS_VAR: energy_c_minus - DELTA_PLUS_VAR: energy_c_plus - -hi-omni-energy_c_delta: - <<: *hi_energies_default - CATDESC: Delta of energies for c - FIELDNAM: Delta Energy - -hi-omni-o: - <<: *counters - CATDESC: Omnidirectional O Rates - FIELDNAM: O - DEPEND_1: energy_o - LABL_PTR_1: energy_o - -hi-omni-energy_o: - <<: *hi_energies_default - CATDESC: Energy Table for o - DELTA_MINUS_VAR: energy_o_minus - DELTA_PLUS_VAR: energy_o_plus - -hi-omni-energy_o_delta: - <<: *hi_energies_default - CATDESC: Delta of energies for o - FIELDNAM: Delta Energy - -hi-omni-ne_mg_si: - <<: *counters - CATDESC: Omnidirectional Ne_Mg_Si Rates - FIELDNAM: Ne_Mg_Si - DEPEND_1: energy_ne_mg_si - LABL_PTR_1: energy_ne_mg_si - -hi-omni-energy_ne_mg_si: - <<: *hi_energies_default - CATDESC: Energy Table for ne_mg_si - DELTA_MINUS_VAR: energy_ne_mg_si_minus - DELTA_PLUS_VAR: energy_ne_mg_si_plus - -hi-omni-energy_ne_mg_si_delta: - <<: *hi_energies_default - CATDESC: Delta of energies for ne_mg_si - FIELDNAM: Delta Energy - -hi-omni-fe: - <<: *counters - CATDESC: Omnidirectional Fe Rates - FIELDNAM: Fe - DEPEND_1: energy_fe - LABL_PTR_1: energy_fe - -hi-omni-energy_fe: - <<: *hi_energies_default - CATDESC: Energy Table for fe - DELTA_MINUS_VAR: energy_fe_minus - DELTA_PLUS_VAR: energy_fe_plus - -hi-omni-energy_fe_delta: - <<: *hi_energies_default - CATDESC: Delta of energies for fe - FIELDNAM: Delta Energy - -hi-omni-uh: - <<: *counters - CATDESC: Omnidirectional UH Rates - FIELDNAM: UH - DEPEND_1: energy_uh - LABL_PTR_1: energy_uh - -hi-omni-energy_uh: - <<: *hi_energies_default - CATDESC: Energy Table for uh - DELTA_MINUS_VAR: energy_uh_minus - DELTA_PLUS_VAR: energy_uh_plus - -hi-omni-energy_uh_delta: - <<: *hi_energies_default - CATDESC: Delta of energies for uh - FIELDNAM: Delta Energy - -hi-omni-junk: - <<: *counters - CATDESC: Junk (Root 2 spacing) - FIELDNAM: Junk - DEPEND_1: energy_junk - LABL_PTR_1: energy_junk - -hi-omni-energy_junk: - <<: *hi_energies_default - CATDESC: Energy Table for junk - DELTA_MINUS_VAR: energy_junk_minus - DELTA_PLUS_VAR: energy_junk_plus - -hi-omni-energy_junk_delta: - <<: *hi_energies_default - CATDESC: Delta of energies for junk - FIELDNAM: Delta Energy - -# hi-priority -hi-priority-Priority0: - <<: *hi_priorities_default - CATDESC: Priority 0 - FIELDNAM: Priority 0 - -hi-priority-Priority1: - <<: *hi_priorities_default - CATDESC: Priority 1 - FIELDNAM: Priority 1 - -hi-priority-Priority2: - <<: *hi_priorities_default - CATDESC: Priority 2 - FIELDNAM: Priority 2 - -hi-priority-Priority3: - <<: *hi_priorities_default - CATDESC: Priority 3 - FIELDNAM: Priority 3 - -hi-priority-Priority4: - <<: *hi_priorities_default - CATDESC: Priority 4 - FIELDNAM: Priority 4 - -hi-priority-Priority5: - <<: *hi_priorities_default - CATDESC: Priority 5 - FIELDNAM: Priority 5 - -# hi-sectored -hi-sectored-h: - <<: *counters - CATDESC: Sectored H Rates - FIELDNAM: H - DEPEND_1: energy_h - DEPEND_2: ssd_index - DEPEND_3: spin_sector_index - LABL_PTR_1: energy_h - LABL_PTR_2: ssd_index_label - LABL_PTR_3: spin_sector_index_label - -hi-sectored-energy_h: - <<: *hi_energies_default - CATDESC: Energy Table for H - DELTA_MINUS_VAR: energy_h_minus - DELTA_PLUS_VAR: energy_h_plus - -hi-sectored-energy_h_delta: - <<: *hi_energies_default - CATDESC: Delta of energies for H - FIELDNAM: Delta Energy - -hi-sectored-he3he4: - <<: *counters - CATDESC: Sectored He3He4 Rates - FIELDNAM: He3He4 - DEPEND_1: energy_he3he4 - DEPEND_2: ssd_index - DEPEND_3: spin_sector_index - LABL_PTR_1: energy_he3he4 - LABL_PTR_2: ssd_index_label - LABL_PTR_3: spin_sector_index_label - -hi-sectored-energy_he3he4: - <<: *hi_energies_default - CATDESC: Energy Table for He3He4 - DELTA_MINUS_VAR: energy_he3he4_minus - DELTA_PLUS_VAR: energy_he3he4_plus - -hi-sectored-energy_he3he4_delta: - <<: *hi_energies_default - CATDESC: Delta of energies for He3He4 - FIELDNAM: Delta Energy - -hi-sectored-cno: - <<: *counters - CATDESC: Sectored CNO Rates - FIELDNAM: CNO - DEPEND_1: energy_cno - DEPEND_2: ssd_index - DEPEND_3: spin_sector_index - LABL_PTR_1: energy_cno - LABL_PTR_2: ssd_index_label - LABL_PTR_3: spin_sector_index_label - -hi-sectored-energy_cno: - <<: *hi_energies_default - CATDESC: Energy Table for CNO - DELTA_MINUS_VAR: energy_cno_minus - DELTA_PLUS_VAR: energy_cno_plus - -hi-sectored-energy_cno_delta: - <<: *hi_energies_default - CATDESC: Delta of energies for CNO - FIELDNAM: Delta Energy - -hi-sectored-fe: - <<: *counters - CATDESC: Sectored Fe Rates - FIELDNAM: Fe - DEPEND_1: energy_fe - DEPEND_2: ssd_index - DEPEND_3: spin_sector_index - LABL_PTR_1: energy_fe - LABL_PTR_2: ssd_index_label - LABL_PTR_3: spin_sector_index_label - -hi-sectored-energy_fe: - <<: *hi_energies_default - CATDESC: Energy Table for Fe - DELTA_MINUS_VAR: energy_fe_minus - DELTA_PLUS_VAR: energy_fe_plus - -hi-sectored-energy_fe_delta: - <<: *hi_energies_default - CATDESC: Delta of energies for Fe - FIELDNAM: Delta Energy - -# lo-counters-aggregated -lo-counters-aggregated-TCR: - <<: *events - CATDESC: Triple Coincidence Rate - FIELDNAM: Event A - Triple Coincidence Rate - DEPEND_1: spin_sector_pairs - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_pairs_label - LABL_PTR_2: esa_step_label - -lo-counters-aggregated-DCR: - <<: *events - CATDESC: Double Coincidence Rate - FIELDNAM: Event B - Double Coincidence Rate - DEPEND_1: spin_sector_pairs - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_pairs_label - LABL_PTR_2: esa_step_label - -lo-counters-aggregated-TOFPlusAPD: - <<: *events - CATDESC: TOF + APD - FIELDNAM: Event C - TOF + APD - DEPEND_1: spin_sector_pairs - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_pairs_label - LABL_PTR_2: esa_step_label - -lo-counters-aggregated-TOFOnly: - <<: *events - CATDESC: TOF Only - FIELDNAM: Event D - TOF Only - DEPEND_1: spin_sector_pairs - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_pairs_label - LABL_PTR_2: esa_step_label - -lo-counters-aggregated-PositionPlusAPD: - <<: *events - CATDESC: Position + APD - FIELDNAM: Event E - Position + APD - DEPEND_1: spin_sector_pairs - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_pairs_label - LABL_PTR_2: esa_step_label - -lo-counters-aggregated-PositionOnly: - <<: *events - CATDESC: Position Only - FIELDNAM: Event F - Position Only - DEPEND_1: spin_sector_pairs - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_pairs_label - LABL_PTR_2: esa_step_label - -lo-counters-aggregated-STAorSTBPlusAPD: - <<: *events - CATDESC: STA or STB + APD - FIELDNAM: Event G - STA or STB + APD - DEPEND_1: spin_sector_pairs - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_pairs_label - LABL_PTR_2: esa_step_label - -lo-counters-aggregated-STAorSTBOnly: - <<: *events - CATDESC: STA or STB Only - FIELDNAM: Event H - STA or STB Only - DEPEND_1: spin_sector_pairs - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_pairs_label - LABL_PTR_2: esa_step_label - -lo-counters-aggregated-Reserved1: - <<: *events - CATDESC: Reserved - FIELDNAM: Reserved 1 - DEPEND_1: spin_sector_pairs - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_pairs_label - LABL_PTR_2: esa_step_label - -lo-counters-aggregated-Reserved2: - <<: *events - CATDESC: Reserved - FIELDNAM: Reserved 2 - DEPEND_1: spin_sector_pairs - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_pairs_label - LABL_PTR_2: esa_step_label - -lo-counters-aggregated-SPOnly: - <<: *events - CATDESC: SP Only - FIELDNAM: Event K - SP Only - DEPEND_1: spin_sector_pairs - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_pairs_label - LABL_PTR_2: esa_step_label - -lo-counters-aggregated-APDOnly: - <<: *events - CATDESC: APD Only - FIELDNAM: Event L - APD Only - DEPEND_1: spin_sector_pairs - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_pairs_label - LABL_PTR_2: esa_step_label - -lo-counters-aggregated-LowTOFCutoff: - <<: *events - CATDESC: Low TOF Cutoff - FIELDNAM: Low TOF Cutoff - DEPEND_1: spin_sector_pairs - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_pairs_label - LABL_PTR_2: esa_step_label - -lo-counters-aggregated-STA: - <<: *events - CATDESC: Start A - FIELDNAM: Singles - Start-A (STA) - DEPEND_1: spin_sector_pairs - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_pairs_label - LABL_PTR_2: esa_step_label - -lo-counters-aggregated-STB: - <<: *events - CATDESC: Start B - FIELDNAM: Singles - Start-B (STB) - DEPEND_1: spin_sector_pairs - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_pairs_label - LABL_PTR_2: esa_step_label - -lo-counters-aggregated-SP: - <<: *events - CATDESC: Stop - FIELDNAM: Singles - Stop (SP) - DEPEND_1: spin_sector_pairs - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_pairs_label - LABL_PTR_2: esa_step_label - -lo-counters-aggregated-TotalPositionCount: - <<: *events - CATDESC: Total Position Count - FIELDNAM: Singles - Total Position Count - DEPEND_1: spin_sector_pairs - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_pairs_label - LABL_PTR_2: esa_step_label - -lo-counters-aggregated-InvalidPositionCount: - <<: *events - CATDESC: Invalid Position Count - FIELDNAM: Singles - Invalid Position Count - DEPEND_1: spin_sector_pairs - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_pairs_label - LABL_PTR_2: esa_step_label - -lo-counters-aggregated-ASIC1FlagInvalid: - <<: *events - CATDESC: ASIC 1 Flag Invalid - FIELDNAM: ASIC 1 Flag Invalid Count - DEPEND_1: spin_sector_pairs - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_pairs_label - LABL_PTR_2: esa_step_label - -lo-counters-aggregated-ASIC2FlagInvalid: - <<: *events - CATDESC: ASIC 2 Flag Invalid - FIELDNAM: ASIC 2 Flag Invalid Count - DEPEND_1: spin_sector_pairs - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_pairs_label - LABL_PTR_2: esa_step_label - -lo-counters-aggregated-ASIC1ChannelInvalid: - <<: *events - CATDESC: ASIC 1 Channel Invalid - FIELDNAM: ASIC 1 Channel Invalid Count - DEPEND_1: spin_sector_pairs - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_pairs_label - LABL_PTR_2: esa_step_label - -lo-counters-aggregated-ASIC2ChannelInvalid: - <<: *events - CATDESC: ASIC 2 Channel Invalid - FIELDNAM: ASIC 2 Channel Invalid Count - DEPEND_1: spin_sector_pairs - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_pairs_label - LABL_PTR_2: esa_step_label - -lo-counters-aggregated-TEC4TimeoutTOFNoPos: - <<: *events - CATDESC: TEC-4 Timeout TOF no Position - FIELDNAM: TEC-4 Timeout Count; TOF, No Position - DEPEND_1: spin_sector_pairs - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_pairs_label - LABL_PTR_2: esa_step_label - -lo-counters-aggregated-TEC4TimeoutPosNoTOF: - <<: *events - CATDESC: TEC-4 Timeout Position no TOF - FIELDNAM: TEC-4 Timeout Count; Position, No TOF - DEPEND_1: spin_sector_pairs - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_pairs_label - LABL_PTR_2: esa_step_label - -lo-counters-aggregated-TEC4TimeoutNoPosTOF: - <<: *events - CATDESC: TEC-4 Timeout No Position or TOF - FIELDNAM: TEC-4 Timeout Count; No Position or TOF - DEPEND_1: spin_sector_pairs - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_pairs_label - LABL_PTR_2: esa_step_label - -lo-counters-aggregated-TEC5TimeoutTOFNoPos: - <<: *events - CATDESC: TEC-5 Timeout TOF no Position - FIELDNAM: TEC-5 Timeout Count; TOF, No Position - DEPEND_1: spin_sector_pairs - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_pairs_label - LABL_PTR_2: esa_step_label - -lo-counters-aggregated-TEC5TimeoutPosNoTOF: - <<: *events - CATDESC: TEC-5 Timeout Position no TOF - FIELDNAM: TEC-5 Timeout Count; Position, No TOF - DEPEND_1: spin_sector_pairs - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_pairs_label - LABL_PTR_2: esa_step_label - -lo-counters-aggregated-TEC5TimeoutNoPosTOF: - <<: *events - CATDESC: TEC-5 Timeout No Position or TOF - FIELDNAM: TEC-5 Timeout Count; No Position or TOF - DEPEND_1: spin_sector_pairs - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_pairs_label - LABL_PTR_2: esa_step_label - -# lo-counters-singles -lo-counters-singles-apd_singles: - <<: *counters - CATDESC: Single Rates (APD) - FIELDNAM: Rates - Single (APD) - DEPEND_1: inst_az - DEPEND_2: spin_sector_pairs - DEPEND_3: esa_step - LABL_PTR_1: inst_az_label - LABL_PTR_2: spin_sector_pairs_label - LABL_PTR_3: esa_step_label - -# lo-sw-angular -lo-sw-angular-hplus: - <<: *counters - CATDESC: Sunward H+ Species - FIELDNAM: SW - H+ - DEPEND_1: inst_az - DEPEND_2: spin_sector - DEPEND_3: esa_step - LABL_PTR_1: inst_az_label - LABL_PTR_2: spin_sector_label - LABL_PTR_3: esa_step_label - -lo-sw-angular-heplusplus: - <<: *counters - CATDESC: Sunward He++ Species - FIELDNAM: SW - He++ - DEPEND_1: inst_az - DEPEND_2: spin_sector - DEPEND_3: esa_step - LABL_PTR_1: inst_az_label - LABL_PTR_2: spin_sector_label - LABL_PTR_3: esa_step_label - -lo-sw-angular-oplus6: - <<: *counters - CATDESC: Sunward O+6 Species - FIELDNAM: SW - O+6 - DEPEND_1: inst_az - DEPEND_2: spin_sector - DEPEND_3: esa_step - LABL_PTR_1: inst_az_label - LABL_PTR_2: spin_sector_label - LABL_PTR_3: esa_step_label - -lo-sw-angular-fe_loq: - <<: *counters - CATDESC: Sunward Fe lowQ Species - FIELDNAM: SW - Fe lowQ - DEPEND_1: inst_az - DEPEND_2: spin_sector - DEPEND_3: esa_step - LABL_PTR_1: inst_az_label - LABL_PTR_2: spin_sector_label - LABL_PTR_3: esa_step_label - -lo-nsw-angular-heplusplus: - <<: *counters - CATDESC: Non-sunward He++ Species - FIELDNAM: NSW - He++ - DEPEND_1: inst_az - DEPEND_2: spin_sector - DEPEND_3: esa_step - LABL_PTR_1: inst_az_label - LABL_PTR_2: spin_sector_label - LABL_PTR_3: esa_step_label - -# lo-sw-priority -lo-sw-priority-p0_tcrs: - <<: *counters - CATDESC: Sunward Sector Triple Coincidence Pickup Ions Priority - DEPEND_1: spin_sector - DEPEND_2: esa_step - FIELDNAM: SW Sector Triple Coincidence PUI's - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label - -lo-sw-priority-p1_hplus: - <<: *counters - CATDESC: Sunward Sector H+ Priority - DEPEND_1: spin_sector - DEPEND_2: esa_step - FIELDNAM: SW Sector H+ - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label - -lo-sw-priority-p2_heplusplus: - <<: *counters - CATDESC: Sunward Sector He++ Priority - DEPEND_1: spin_sector - DEPEND_2: esa_step - FIELDNAM: SW Sector He++ - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label - -lo-sw-priority-p3_heavies: - <<: *counters - CATDESC: Sunward Sector High Charge State Heavies Priority - DEPEND_1: spin_sector - DEPEND_2: esa_step - FIELDNAM: SW Sector High Charge State Heavies - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label - -lo-sw-priority-p4_dcrs: - <<: *counters - CATDESC: Sunward Sector Double Coincidence Pickup Ions Priority - DEPEND_1: spin_sector - DEPEND_2: esa_step - FIELDNAM: SW Sector Double Coincidence PUI's - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label - -# lo-nsw-priority -lo-nsw-priority-p5_heavies: - <<: *counters - CATDESC: Non-sunward Sector Heavies Priority - DEPEND_1: spin_sector - DEPEND_2: esa_step - FIELDNAM: NSW Sector Heavies - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label - -lo-nsw-priority-p6_hplus_heplusplus: - <<: *counters - CATDESC: Non-sunward H+ and He++ Priority - DEPEND_1: spin_sector - DEPEND_2: esa_step - FIELDNAM: NSW H+ and He++ - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label - -# lo-sw-species -lo-sw-species-hplus: - <<: *counters - CATDESC: H+ Sunward Species - FIELDNAM: SW - H+ - DEPEND_1: spin_sector - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label - -lo-sw-species-heplusplus: - <<: *counters - CATDESC: He++ Sunward Species - FIELDNAM: SW - He++ - DEPEND_1: spin_sector - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label - -lo-sw-species-cplus4: - <<: *counters - CATDESC: C+4 Sunward Species - FIELDNAM: SW - C+4 - DEPEND_1: spin_sector - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label - -lo-sw-species-cplus5: - <<: *counters - CATDESC: C+5 Sunward Species - FIELDNAM: SW - C+5 - DEPEND_1: spin_sector - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label - -lo-sw-species-cplus6: - <<: *counters - CATDESC: C+6 Sunward Species - FIELDNAM: SW - C+6 - DEPEND_1: spin_sector - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label - -lo-sw-species-oplus5: - <<: *counters - CATDESC: O+5 Sunward Species - FIELDNAM: SW - O+5 - DEPEND_1: spin_sector - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label - -lo-sw-species-oplus6: - <<: *counters - CATDESC: O+6 Sunward Species - FIELDNAM: SW - O+6 - DEPEND_1: spin_sector - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label - -lo-sw-species-oplus7: - <<: *counters - CATDESC: O+7 Sunward Species - FIELDNAM: SW - O+7 - DEPEND_1: spin_sector - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label - -lo-sw-species-oplus8: - <<: *counters - CATDESC: O+8 Sunward Species - FIELDNAM: SW - O+8 - DEPEND_1: spin_sector - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label - -lo-sw-species-ne: - <<: *counters - CATDESC: Ne Sunward Species - FIELDNAM: SW - Ne - DEPEND_1: spin_sector - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label -lo-sw-species-mg: - <<: *counters - CATDESC: Mg Sunward Species - FIELDNAM: SW - Mg - DEPEND_1: spin_sector - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label - -lo-sw-species-si: - <<: *counters - CATDESC: Si Sunward Species - FIELDNAM: SW - Si - DEPEND_1: spin_sector - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label - -lo-sw-species-fe_loq: - <<: *counters - CATDESC: Fe lowQ Sunward Species - FIELDNAM: SW - Fe lowQ - DEPEND_1: spin_sector - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label - -lo-sw-species-fe_hiq: - <<: *counters - CATDESC: Fe highQ Sunward Species - FIELDNAM: SW - Fe highQ - DEPEND_1: spin_sector - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label - -lo-sw-species-heplus: - <<: *counters - CATDESC: He+ Pickup Ion Sunward Species - FIELDNAM: SW - He+ (PUI) - DEPEND_1: spin_sector - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label - -lo-sw-species-cnoplus: - <<: *counters - CATDESC: CNO+ Pickup Ion Sunward Species - FIELDNAM: SW - CNO+ (PUI) - DEPEND_1: spin_sector - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label - -# lo-nsw-species -lo-nsw-species-hplus: - <<: *counters - CATDESC: H+ Non-sunward Species - FIELDNAM: NSW - H+ - DEPEND_1: spin_sector - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label - -lo-nsw-species-heplusplus: - <<: *counters - CATDESC: He++ Non-sunward Species - FIELDNAM: NSW - He++ - DEPEND_1: spin_sector - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label - -lo-nsw-species-c: - <<: *counters - CATDESC: C Non-sunward Species - FIELDNAM: NSW - C - DEPEND_1: spin_sector - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label - -lo-nsw-species-o: - <<: *counters - CATDESC: O Non-sunward Species - FIELDNAM: NSW - O - DEPEND_1: spin_sector - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label - -lo-nsw-species-ne_si_mg: - <<: *counters - CATDESC: Ne-Si-Mg Non-sunward Species - FIELDNAM: NSW - Ne_Si_Mg - DEPEND_1: spin_sector - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label - -lo-nsw-species-fe: - <<: *counters - CATDESC: Fe Non-sunward Species - FIELDNAM: NSW - Fe - DEPEND_1: spin_sector - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label - -lo-nsw-species-heplus: - <<: *counters - CATDESC: He+ Non-sunward Species - FIELDNAM: NSW - He+ - DEPEND_1: spin_sector - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label - -lo-nsw-species-cnoplus: - <<: *counters - CATDESC: CNO+ Non-sunward Species - FIELDNAM: NSW - CNO+ - DEPEND_1: spin_sector - DEPEND_2: esa_step - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label - -# lo-ialirt -lo-ialirt-heplusplus: - <<: *counters - CATDESC: He++ Sunward Species - DEPEND_1: spin_sector - DEPEND_2: esa_step - FIELDNAM: SW - He++ - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label - VALIDMAX: *max_uint24 - -lo-ialirt-cplus5: - <<: *counters - CATDESC: C+5 Sunward Species - DEPEND_1: spin_sector - DEPEND_2: esa_step - FIELDNAM: SW - C+5 - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label - VALIDMAX: *max_uint24 - -lo-ialirt-cplus6: - <<: *counters - CATDESC: C+6 Sunward Species - DEPEND_1: spin_sector - DEPEND_2: esa_step - FIELDNAM: SW - C+6 - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label - VALIDMAX: *max_uint24 - -lo-ialirt-oplus6: - <<: *counters - CATDESC: O+6 Sunward Species - DEPEND_1: spin_sector - DEPEND_2: esa_step - FIELDNAM: SW - O+6 - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label - VALIDMAX: *max_uint24 - -lo-ialirt-oplus7: - <<: *counters - CATDESC: O+7 Sunward Species - DEPEND_1: spin_sector - DEPEND_2: esa_step - FIELDNAM: SW - O+7 - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label - VALIDMAX: *max_uint24 - -lo-ialirt-oplus8: - <<: *counters - CATDESC: O+8 Sunward Species - DEPEND_1: spin_sector - DEPEND_2: esa_step - FIELDNAM: SW - O+8 - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label - VALIDMAX: *max_uint24 - -lo-ialirt-mg: - <<: *counters - CATDESC: Mg Sunward Species - DEPEND_1: spin_sector - DEPEND_2: esa_step - FIELDNAM: SW - Mg - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label - VALIDMAX: *max_uint24 - -lo-ialirt-fe_loq: - <<: *counters - CATDESC: Fe lowQ Sunward Species - DEPEND_1: spin_sector - DEPEND_2: esa_step - FIELDNAM: SW - Fe lowQ - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label - VALIDMAX: *max_uint24 - -lo-ialirt-fe_hiq: - <<: *counters - CATDESC: Fe highQ Sunward Species - DEPEND_1: spin_sector - DEPEND_2: esa_step - FIELDNAM: SW - Fe highQ - LABL_PTR_1: spin_sector_label - LABL_PTR_2: esa_step_label - VALIDMAX: *max_uint24 - -# <=== Direct Events Attributes ===> -P0_APD_ID: - <<: *direct_events - CATDESC: Priority 0 APD ID - DEPEND_1: event_num - FIELDNAM: Priority 0 APD ID - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -P0_APDEnergy: - <<: *direct_events - CATDESC: Priority 0 APD Energy - DEPEND_1: event_num - FIELDNAM: Priority 0 APD Energy - FILLVAL: 65535 - LABL_PTR_1: event_num_label - VALIDMAX: 512 - -P0_APDGain: - <<: *direct_events - CATDESC: Priority 0 APD Gain - DEPEND_1: event_num - FIELDNAM: Priority 0 APD Gain - LABL_PTR_1: event_num_label - VALIDMAX: 1 - -P0_DataQuality: - <<: *direct_events - CATDESC: Priority 0 Data Quality - FIELDNAM: Priority 0 Data Quality - LABLAXIS: " " - VALIDMAX: 1 - -P0_EnergyStep: - <<: *direct_events - CATDESC: Priority 0 Energy Step - DEPEND_1: event_num - FIELDNAM: Priority 0 Energy Step - LABL_PTR_1: event_num_label - VALIDMAX: 128 - -P0_ERGE: - <<: *direct_events - CATDESC: Priority 0 Energy Range - DEPEND_1: event_num - FIELDNAM: Priority 0 Energy Range - LABL_PTR_1: event_num_label - VALIDMAX: 4 - -P0_MultiFlag: - <<: *direct_events - CATDESC: Priority 0 Multi Flag - DEPEND_1: event_num - FIELDNAM: Priority 0 Multi Flag - LABL_PTR_1: event_num_label - VALIDMAX: 1 - -P0_NumEvents: - <<: *direct_events - CATDESC: Priority 0 Number of Events - FIELDNAM: Priority 0 Number of Events - FILLVAL: 65535 - LABLAXIS: " " - -P0_PHAType: - <<: *direct_events - CATDESC: Priority 0 PHA Type - DEPEND_1: event_num - FIELDNAM: Priority 0 PHA Type - LABL_PTR_1: event_num_label - VALIDMAX: 4 - -P0_Position: - <<: *direct_events - CATDESC: Priority 0 Position - DEPEND_1: event_num - FIELDNAM: Priority 0 Position - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -P0_SpinAngle: - <<: *direct_events - CATDESC: Priority 0 Spin Angle - DEPEND_1: event_num - FIELDNAM: Priority 0 Spin Angle - LABL_PTR_1: event_num_label - VALIDMAX: 128 - -P0_SpinNumber: - <<: *direct_events - CATDESC: Priority 0 Spin Number - DEPEND_1: event_num - FIELDNAM: Priority 0 Spin Number - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -P0_SSD_ID: - <<: *direct_events - CATDESC: Priority 0 SSD ID or Azimuth Angle - DEPEND_1: event_num - FIELDNAM: Priority 0 SSD ID or Azimuth Angle - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -P0_SSDEnergy: - <<: *direct_events - CATDESC: Priority 0 APD Energy - DEPEND_1: event_num - FIELDNAM: Priority 0 APD Energy - LABL_PTR_1: event_num_label - VALIDMAX: 2048 - -P0_TOF: - <<: *direct_events - CATDESC: Priority 0 Time of Flight - DEPEND_1: event_num - FIELDNAM: Priority 0 Time of Flight - FILLVAL: 65535 - LABL_PTR_1: event_num_label - VALIDMAX: 1024 - -P0_Type: - <<: *direct_events - CATDESC: Priority 0 Type - DEPEND_1: event_num - FIELDNAM: Priority 0 Type - LABL_PTR_1: event_num_label - VALIDMAX: 3 - -P1_APD_ID: - <<: *direct_events - CATDESC: Priority 1 APD ID - DEPEND_1: event_num - FIELDNAM: Priority 1 APD ID - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -P1_APDEnergy: - <<: *direct_events - CATDESC: Priority 1 APD Energy - DEPEND_1: event_num - FIELDNAM: Priority 1 APD Energy - FILLVAL: 65535 - LABL_PTR_1: event_num_label - VALIDMAX: 512 - -P1_APDGain: - <<: *direct_events - CATDESC: Priority 1 APD Gain - DEPEND_1: event_num - FIELDNAM: Priority 1 APD Gain - LABL_PTR_1: event_num_label - VALIDMAX: 1 - -P1_DataQuality: - <<: *direct_events - CATDESC: Priority 1 Data Quality - FIELDNAM: Priority 1 Data Quality - LABLAXIS: " " - VALIDMAX: 1 - -P1_EnergyStep: - <<: *direct_events - CATDESC: Priority 1 Energy Step - DEPEND_1: event_num - FIELDNAM: Priority 1 Energy Step - LABL_PTR_1: event_num_label - VALIDMAX: 128 - -P1_ERGE: - <<: *direct_events - CATDESC: Priority 1 Energy Range - DEPEND_1: event_num - FIELDNAM: Priority 1 Energy Range - LABL_PTR_1: event_num_label - VALIDMAX: 4 - -P1_MultiFlag: - <<: *direct_events - CATDESC: Priority 1 Multi Flag - DEPEND_1: event_num - FIELDNAM: Priority 1 Multi Flag - LABL_PTR_1: event_num_label - VALIDMAX: 1 - -P1_NumEvents: - <<: *direct_events - CATDESC: Priority 1 Number of Events - FIELDNAM: Priority 1 Number of Events - FILLVAL: 65535 - LABLAXIS: " " - -P1_PHAType: - <<: *direct_events - CATDESC: Priority 1 PHA Type - DEPEND_1: event_num - FIELDNAM: Priority 1 PHA Type - LABL_PTR_1: event_num_label - VALIDMAX: 4 - -P1_Position: - <<: *direct_events - CATDESC: Priority 1 Position - DEPEND_1: event_num - FIELDNAM: Priority 1 Position - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -P1_SpinAngle: - <<: *direct_events - CATDESC: Priority 1 Spin Angle - DEPEND_1: event_num - FIELDNAM: Priority 1 Spin Angle - LABL_PTR_1: event_num_label - VALIDMAX: 128 - -P1_SpinNumber: - <<: *direct_events - CATDESC: Priority 1 Spin Number - DEPEND_1: event_num - FIELDNAM: Priority 1 Spin Number - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -P1_SSD_ID: - <<: *direct_events - CATDESC: Priority 1 SSD ID or Azimuth Angle - DEPEND_1: event_num - FIELDNAM: Priority 1 SSD ID or Azimuth Angle - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -P1_SSDEnergy: - <<: *direct_events - CATDESC: Priority 1 APD Energy - DEPEND_1: event_num - FIELDNAM: Priority 1 APD Energy - LABL_PTR_1: event_num_label - VALIDMAX: 2048 - -P1_TOF: - <<: *direct_events - CATDESC: Priority 1 Time of Flight - DEPEND_1: event_num - FIELDNAM: Priority 1 Time of Flight - FILLVAL: 65535 - LABL_PTR_1: event_num_label - VALIDMAX: 1024 - -P1_Type: - <<: *direct_events - CATDESC: Priority 1 Type - DEPEND_1: event_num - FIELDNAM: Priority 1 Type - LABL_PTR_1: event_num_label - VALIDMAX: 3 - -P2_APD_ID: - <<: *direct_events - CATDESC: Priority 2 APD ID - DEPEND_1: event_num - FIELDNAM: Priority 2 APD ID - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -P2_APDEnergy: - <<: *direct_events - CATDESC: Priority 2 APD Energy - DEPEND_1: event_num - FIELDNAM: Priority 2 APD Energy - FILLVAL: 65535 - LABL_PTR_1: event_num_label - VALIDMAX: 512 - -P2_APDGain: - <<: *direct_events - CATDESC: Priority 2 APD Gain - DEPEND_1: event_num - FIELDNAM: Priority 2 APD Gain - LABL_PTR_1: event_num_label - VALIDMAX: 1 - -P2_DataQuality: - <<: *direct_events - CATDESC: Priority 2 Data Quality - FIELDNAM: Priority 2 Data Quality - LABLAXIS: " " - VALIDMAX: 1 - -P2_EnergyStep: - <<: *direct_events - CATDESC: Priority 2 Energy Step - DEPEND_1: event_num - FIELDNAM: Priority 2 Energy Step - LABL_PTR_1: event_num_label - VALIDMAX: 128 - -P2_ERGE: - <<: *direct_events - CATDESC: Priority 2 Energy Range - DEPEND_1: event_num - FIELDNAM: Priority 2 Energy Range - LABL_PTR_1: event_num_label - VALIDMAX: 4 - -P2_MultiFlag: - <<: *direct_events - CATDESC: Priority 2 Multi Flag - DEPEND_1: event_num - FIELDNAM: Priority 2 Multi Flag - LABL_PTR_1: event_num_label - VALIDMAX: 1 - -P2_NumEvents: - <<: *direct_events - CATDESC: Priority 2 Number of Events - FIELDNAM: Priority 2 Number of Events - FILLVAL: 65535 - LABLAXIS: " " - -P2_PHAType: - <<: *direct_events - CATDESC: Priority 2 PHA Type - DEPEND_1: event_num - FIELDNAM: Priority 2 PHA Type - LABL_PTR_1: event_num_label - VALIDMAX: 4 - -P2_Position: - <<: *direct_events - CATDESC: Priority 2 Position - DEPEND_1: event_num - FIELDNAM: Priority 2 Position - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -P2_SpinAngle: - <<: *direct_events - CATDESC: Priority 2 Spin Angle - DEPEND_1: event_num - FIELDNAM: Priority 2 Spin Angle - LABL_PTR_1: event_num_label - VALIDMAX: 128 - -P2_SpinNumber: - <<: *direct_events - CATDESC: Priority 2 Spin Number - DEPEND_1: event_num - FIELDNAM: Priority 2 Spin Number - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -P2_SSD_ID: - <<: *direct_events - CATDESC: Priority 2 SSD ID or Azimuth Angle - DEPEND_1: event_num - FIELDNAM: Priority 2 SSD ID or Azimuth Angle - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -P2_SSDEnergy: - <<: *direct_events - CATDESC: Priority 2 APD Energy - DEPEND_1: event_num - FIELDNAM: Priority 2 APD Energy - LABL_PTR_1: event_num_label - VALIDMAX: 2048 - -P2_TOF: - <<: *direct_events - CATDESC: Priority 2 Time of Flight - DEPEND_1: event_num - FIELDNAM: Priority 2 Time of Flight - FILLVAL: 65535 - LABL_PTR_1: event_num_label - VALIDMAX: 1024 - -P2_Type: - <<: *direct_events - CATDESC: Priority 2 Type - DEPEND_1: event_num - FIELDNAM: Priority 2 Type - LABL_PTR_1: event_num_label - VALIDMAX: 3 - -P3_APD_ID: - <<: *direct_events - CATDESC: Priority 3 APD ID - DEPEND_1: event_num - FIELDNAM: Priority 3 APD ID - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -P3_APDEnergy: - <<: *direct_events - CATDESC: Priority 3 APD Energy - DEPEND_1: event_num - FIELDNAM: Priority 3 APD Energy - FILLVAL: 65535 - LABL_PTR_1: event_num_label - VALIDMAX: 512 - -P3_APDGain: - <<: *direct_events - CATDESC: Priority 3 APD Gain - DEPEND_1: event_num - FIELDNAM: Priority 3 APD Gain - LABL_PTR_1: event_num_label - VALIDMAX: 1 - -P3_DataQuality: - <<: *direct_events - CATDESC: Priority 3 Data Quality - FIELDNAM: Priority 3 Data Quality - LABLAXIS: " " - VALIDMAX: 1 - -P3_EnergyStep: - <<: *direct_events - CATDESC: Priority 3 Energy Step - DEPEND_1: event_num - FIELDNAM: Priority 3 Energy Step - LABL_PTR_1: event_num_label - VALIDMAX: 128 - -P3_ERGE: - <<: *direct_events - CATDESC: Priority 3 Energy Range - DEPEND_1: event_num - FIELDNAM: Priority 3 Energy Range - LABL_PTR_1: event_num_label - VALIDMAX: 4 - -P3_MultiFlag: - <<: *direct_events - CATDESC: Priority 3 Multi Flag - DEPEND_1: event_num - FIELDNAM: Priority 3 Multi Flag - LABL_PTR_1: event_num_label - VALIDMAX: 1 - -P3_NumEvents: - <<: *direct_events - CATDESC: Priority 3 Number of Events - FIELDNAM: Priority 3 Number of Events - FILLVAL: 65535 - LABLAXIS: " " - -P3_PHAType: - <<: *direct_events - CATDESC: Priority 3 PHA Type - DEPEND_1: event_num - FIELDNAM: Priority 3 PHA Type - LABL_PTR_1: event_num_label - VALIDMAX: 4 - -P3_Position: - <<: *direct_events - CATDESC: Priority 3 Position - DEPEND_1: event_num - FIELDNAM: Priority 3 Position - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -P3_SpinAngle: - <<: *direct_events - CATDESC: Priority 3 Spin Angle - DEPEND_1: event_num - FIELDNAM: Priority 3 Spin Angle - LABL_PTR_1: event_num_label - VALIDMAX: 128 - -P3_SpinNumber: - <<: *direct_events - CATDESC: Priority 3 Spin Number - DEPEND_1: event_num - FIELDNAM: Priority 3 Spin Number - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -P3_SSD_ID: - <<: *direct_events - CATDESC: Priority 3 SSD ID or Azimuth Angle - DEPEND_1: event_num - FIELDNAM: Priority 3 SSD ID or Azimuth Angle - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -P3_SSDEnergy: - <<: *direct_events - CATDESC: Priority 3 APD Energy - DEPEND_1: event_num - FIELDNAM: Priority 3 APD Energy - LABL_PTR_1: event_num_label - VALIDMAX: 2048 - -P3_TOF: - <<: *direct_events - CATDESC: Priority 3 Time of Flight - DEPEND_1: event_num - FIELDNAM: Priority 3 Time of Flight - FILLVAL: 65535 - LABL_PTR_1: event_num_label - VALIDMAX: 1024 - -P3_Type: - <<: *direct_events - CATDESC: Priority 3 Type - DEPEND_1: event_num - FIELDNAM: Priority 3 Type - LABL_PTR_1: event_num_label - VALIDMAX: 3 - -P4_APD_ID: - <<: *direct_events - CATDESC: Priority 4 APD ID - DEPEND_1: event_num - FIELDNAM: Priority 4 APD ID - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -P4_APDEnergy: - <<: *direct_events - CATDESC: Priority 4 APD Energy - DEPEND_1: event_num - FIELDNAM: Priority 4 APD Energy - FILLVAL: 65535 - LABL_PTR_1: event_num_label - VALIDMAX: 512 - -P4_APDGain: - <<: *direct_events - CATDESC: Priority 4 APD Gain - DEPEND_1: event_num - FIELDNAM: Priority 4 APD Gain - LABL_PTR_1: event_num_label - VALIDMAX: 1 - -P4_DataQuality: - <<: *direct_events - CATDESC: Priority 4 Data Quality - FIELDNAM: Priority 4 Data Quality - LABLAXIS: " " - VALIDMAX: 1 - -P4_EnergyStep: - <<: *direct_events - CATDESC: Priority 4 Energy Step - DEPEND_1: event_num - FIELDNAM: Priority 4 Energy Step - LABL_PTR_1: event_num_label - VALIDMAX: 128 - -P4_ERGE: - <<: *direct_events - CATDESC: Priority 4 Energy Range - DEPEND_1: event_num - FIELDNAM: Priority 4 Energy Range - LABL_PTR_1: event_num_label - VALIDMAX: 4 - -P4_MultiFlag: - <<: *direct_events - CATDESC: Priority 4 Multi Flag - DEPEND_1: event_num - FIELDNAM: Priority 4 Multi Flag - LABL_PTR_1: event_num_label - VALIDMAX: 1 - -P4_NumEvents: - <<: *direct_events - CATDESC: Priority 4 Number of Events - FIELDNAM: Priority 4 Number of Events - FILLVAL: 65535 - LABLAXIS: " " - -P4_PHAType: - <<: *direct_events - CATDESC: Priority 4 PHA Type - DEPEND_1: event_num - FIELDNAM: Priority 4 PHA Type - LABL_PTR_1: event_num_label - VALIDMAX: 4 - -P4_Position: - <<: *direct_events - CATDESC: Priority 4 Position - DEPEND_1: event_num - FIELDNAM: Priority 4 Position - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -P4_SpinAngle: - <<: *direct_events - CATDESC: Priority 4 Spin Angle - DEPEND_1: event_num - FIELDNAM: Priority 4 Spin Angle - LABL_PTR_1: event_num_label - VALIDMAX: 128 - -P4_SpinNumber: - <<: *direct_events - CATDESC: Priority 4 Spin Number - DEPEND_1: event_num - FIELDNAM: Priority 4 Spin Number - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -P4_SSD_ID: - <<: *direct_events - CATDESC: Priority 4 SSD ID or Azimuth Angle - DEPEND_1: event_num - FIELDNAM: Priority 4 SSD ID or Azimuth Angle - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -P4_SSDEnergy: - <<: *direct_events - CATDESC: Priority 4 APD Energy - DEPEND_1: event_num - FIELDNAM: Priority 4 APD Energy - LABL_PTR_1: event_num_label - VALIDMAX: 2048 - -P4_TOF: - <<: *direct_events - CATDESC: Priority 4 Time of Flight - DEPEND_1: event_num - FIELDNAM: Priority 4 Time of Flight - FILLVAL: 65535 - LABL_PTR_1: event_num_label - VALIDMAX: 1024 - -P4_Type: - <<: *direct_events - CATDESC: Priority 4 Type - DEPEND_1: event_num - FIELDNAM: Priority 4 Type - LABL_PTR_1: event_num_label - VALIDMAX: 3 - -P5_APD_ID: - <<: *direct_events - CATDESC: Priority 5 APD ID - DEPEND_1: event_num - FIELDNAM: Priority 5 APD ID - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -P5_APDEnergy: - <<: *direct_events - CATDESC: Priority 5 APD Energy - DEPEND_1: event_num - FIELDNAM: Priority 5 APD Energy - FILLVAL: 65535 - LABL_PTR_1: event_num_label - VALIDMAX: 512 - -P5_APDGain: - <<: *direct_events - CATDESC: Priority 5 APD Gain - DEPEND_1: event_num - FIELDNAM: Priority 5 APD Gain - LABL_PTR_1: event_num_label - VALIDMAX: 1 - -P5_DataQuality: - <<: *direct_events - CATDESC: Priority 5 Data Quality - FIELDNAM: Priority 5 Data Quality - LABLAXIS: " " - VALIDMAX: 1 - -P5_EnergyStep: - <<: *direct_events - CATDESC: Priority 5 Energy Step - DEPEND_1: event_num - FIELDNAM: Priority 5 Energy Step - LABL_PTR_1: event_num_label - VALIDMAX: 128 - -P5_ERGE: - <<: *direct_events - CATDESC: Priority 5 Energy Range - DEPEND_1: event_num - FIELDNAM: Priority 5 Energy Range - LABL_PTR_1: event_num_label - VALIDMAX: 4 - -P5_MultiFlag: - <<: *direct_events - CATDESC: Priority 5 Multi Flag - DEPEND_1: event_num - FIELDNAM: Priority 5 Multi Flag - LABL_PTR_1: event_num_label - VALIDMAX: 1 - -P5_NumEvents: - <<: *direct_events - CATDESC: Priority 5 Number of Events - FIELDNAM: Priority 5 Number of Events - FILLVAL: 65535 - LABLAXIS: " " - -P5_PHAType: - <<: *direct_events - CATDESC: Priority 5 PHA Type - DEPEND_1: event_num - FIELDNAM: Priority 5 PHA Type - LABL_PTR_1: event_num_label - VALIDMAX: 4 - -P5_Position: - <<: *direct_events - CATDESC: Priority 5 Position - DEPEND_1: event_num - FIELDNAM: Priority 5 Position - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -P5_SpinAngle: - <<: *direct_events - CATDESC: Priority 5 Spin Angle - DEPEND_1: event_num - FIELDNAM: Priority 5 Spin Angle - LABL_PTR_1: event_num_label - VALIDMAX: 128 - -P5_SpinNumber: - <<: *direct_events - CATDESC: Priority 5 Spin Number - DEPEND_1: event_num - FIELDNAM: Priority 5 Spin Number - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -P5_SSD_ID: - <<: *direct_events - CATDESC: Priority 5 SSD ID or Azimuth Angle - DEPEND_1: event_num - FIELDNAM: Priority 5 SSD ID or Azimuth Angle - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -P5_SSDEnergy: - <<: *direct_events - CATDESC: Priority 5 APD Energy - DEPEND_1: event_num - FIELDNAM: Priority 5 APD Energy - LABL_PTR_1: event_num_label - VALIDMAX: 2048 - -P5_TOF: - <<: *direct_events - CATDESC: Priority 5 Time of Flight - DEPEND_1: event_num - FIELDNAM: Priority 5 Time of Flight - FILLVAL: 65535 - LABL_PTR_1: event_num_label - VALIDMAX: 1024 - -P5_Type: - <<: *direct_events - CATDESC: Priority 5 Type - DEPEND_1: event_num - FIELDNAM: Priority 5 Type - LABL_PTR_1: event_num_label - VALIDMAX: 3 - -P6_APD_ID: - <<: *direct_events - CATDESC: Priority 6 APD ID - DEPEND_1: event_num - FIELDNAM: Priority 6 APD ID - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -P6_APDEnergy: - <<: *direct_events - CATDESC: Priority 6 APD Energy - DEPEND_1: event_num - FIELDNAM: Priority 6 APD Energy - FILLVAL: 65535 - LABL_PTR_1: event_num_label - VALIDMAX: 512 - -P6_APDGain: - <<: *direct_events - CATDESC: Priority 6 APD Gain - DEPEND_1: event_num - FIELDNAM: Priority 6 APD Gain - LABL_PTR_1: event_num_label - VALIDMAX: 1 - -P6_DataQuality: - <<: *direct_events - CATDESC: Priority 6 Data Quality - FIELDNAM: Priority 6 Data Quality - LABLAXIS: " " - VALIDMAX: 1 - -P6_EnergyStep: - <<: *direct_events - CATDESC: Priority 6 Energy Step - DEPEND_1: event_num - FIELDNAM: Priority 6 Energy Step - LABL_PTR_1: event_num_label - VALIDMAX: 128 - -P6_MultiFlag: - <<: *direct_events - CATDESC: Priority 6 Multi Flag - DEPEND_1: event_num - FIELDNAM: Priority 6 Multi Flag - LABL_PTR_1: event_num_label - VALIDMAX: 1 - -P6_NumEvents: - <<: *direct_events - CATDESC: Priority 6 Number of Events - FIELDNAM: Priority 6 Number of Events - FILLVAL: 65535 - LABLAXIS: " " - -P6_PHAType: - <<: *direct_events - CATDESC: Priority 6 PHA Type - DEPEND_1: event_num - FIELDNAM: Priority 6 PHA Type - LABL_PTR_1: event_num_label - VALIDMAX: 4 - -P6_Position: - <<: *direct_events - CATDESC: Priority 6 Position - DEPEND_1: event_num - FIELDNAM: Priority 6 Position - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -P6_SpinAngle: - <<: *direct_events - CATDESC: Priority 6 Spin Angle - DEPEND_1: event_num - FIELDNAM: Priority 6 Spin Angle - LABL_PTR_1: event_num_label - VALIDMAX: 128 - -P6_TOF: - <<: *direct_events - CATDESC: Priority 6 Time of Flight - DEPEND_1: event_num - FIELDNAM: Priority 6 Time of Flight - FILLVAL: 65535 - LABL_PTR_1: event_num_label - VALIDMAX: 1024 - -P7_APD_ID: - <<: *direct_events - CATDESC: Priority 7 APD ID - DEPEND_1: event_num - FIELDNAM: Priority 7 APD ID - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -P7_APDEnergy: - <<: *direct_events - CATDESC: Priority 7 APD Energy - DEPEND_1: event_num - FIELDNAM: Priority 7 APD Energy - FILLVAL: 65535 - LABL_PTR_1: event_num_label - VALIDMAX: 512 - -P7_APDGain: - <<: *direct_events - CATDESC: Priority 7 APD Gain - DEPEND_1: event_num - FIELDNAM: Priority 7 APD Gain - LABL_PTR_1: event_num_label - VALIDMAX: 1 - -P7_DataQuality: - <<: *direct_events - CATDESC: Priority 7 Data Quality - FIELDNAM: Priority 7 Data Quality - LABLAXIS: " " - VALIDMAX: 1 - -P7_EnergyStep: - <<: *direct_events - CATDESC: Priority 7 Energy Step - DEPEND_1: event_num - FIELDNAM: Priority 7 Energy Step - LABL_PTR_1: event_num_label - VALIDMAX: 128 - -P7_MultiFlag: - <<: *direct_events - CATDESC: Priority 7 Multi Flag - DEPEND_1: event_num - FIELDNAM: Priority 7 Multi Flag - LABL_PTR_1: event_num_label - VALIDMAX: 1 - -P7_NumEvents: - <<: *direct_events - CATDESC: Priority 7 Number of Events - FIELDNAM: Priority 7 Number of Events - FILLVAL: 65535 - LABLAXIS: " " - -P7_PHAType: - <<: *direct_events - CATDESC: Priority 7 PHA Type - DEPEND_1: event_num - FIELDNAM: Priority 7 PHA Type - LABL_PTR_1: event_num_label - VALIDMAX: 4 - -P7_Position: - <<: *direct_events - CATDESC: Priority 7 Position - DEPEND_1: event_num - FIELDNAM: Priority 7 Position - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -P7_SpinAngle: - <<: *direct_events - CATDESC: Priority 7 Spin Angle - DEPEND_1: event_num - FIELDNAM: Priority 7 Spin Angle - LABL_PTR_1: event_num_label - VALIDMAX: 128 - -P7_TOF: - <<: *direct_events - CATDESC: Priority 7 Time of Flight - DEPEND_1: event_num - FIELDNAM: Priority 7 Time of Flight - FILLVAL: 65535 - LABL_PTR_1: event_num_label - VALIDMAX: 1024 - -# <=== CCSDS Header Attributes ===> -version: - <<: *hskp_default - CATDESC: CCSDS Packet Version Number (always 0) - FIELDNAM: Version - LABLAXIS: VERSION - -type: - <<: *hskp_default - CATDESC: CCSDS Packet Type Indicator (0=telemetry) - FIELDNAM: Type - LABLAXIS: TYPE - -sec_hdr_flg: - <<: *hskp_default - CATDESC: CCSDS Packet Secondary Header Flag (always 1) - FIELDNAM: Secondary Header Flag - LABLAXIS: SEC_HDR_FLG - -pkt_apid: - <<: *hskp_default - CATDESC: CCSDS Packet Application Process ID - FIELDNAM: Packet APID - FILLVAL: *uint16_fillval - LABLAXIS: PKT_APID - -seq_flgs: - <<: *hskp_default - CATDESC: CCSDS Packet Grouping Flags (3=not part of group) - FIELDNAM: Grouping Flags - LABLAXIS: SEQ_FLGS - -src_seq_ctr: - <<: *hskp_default - CATDESC: CCSDS Packet Sequence Count (increments with each new packet) - FIELDNAM: Packet Sequence Count - FILLVAL: *uint16_fillval - LABLAXIS: SRC_SEQ_CTR - -pkt_len: - <<: *hskp_default - CATDESC: CCSDS Packet Length (number of bytes after Packet length minus 1) - FIELDNAM: Packet Length - FILLVAL: *uint16_fillval - LABLAXIS: PKT_LEN - -shcoarse: - <<: *hskp_default - CATDESC: Secondary Header - Whole-seconds part of SCLK - FIELDNAM: S/C Time - Seconds - FILLVAL: *uint32_fillval - LABLAXIS: SHCOARSE - -packet_version: - <<: *hskp_default - CATDESC: Packet Version - FIELDNAM: Packet Version - FILLVAL: *uint16_fillval - LABLAXIS: PACKET_VERSION - VAR_NOTES: Packet version - this will be incremented each time the format of the packet changes. - -chksum: - <<: *hskp_default - CATDESC: Packet Checksum - LABLAXIS: CHKSUM - FIELDNAM: Packet Checksum - -# <=== Housekeeping Attributes ===> -cmdexe: - <<: *hskp_default - LABLAXIS: CMDEXE - FIELDNAM: Number of commands executed - CATDESC: Number of commands executed. See VAR_NOTES for more details. - VAR_NOTES: Number of commands that have been executed. Counts 0-255, then rolls over to 0. Reset via CLR_LATCHED_SINGLE(COMMAND_COUNTS) [also resets cmdjrct, cmdacc, itf_error counts) - -cmdrjct: - <<: *hskp_default - LABLAXIS: CMDRJCT - FIELDNAM: Number of commands rejected - CATDESC: Number of commands rejected. See VAR_NOTES for more details. - VAR_NOTES: Number of commands that have been rejected. Counts 0-255, then rolls over to 0. Reset via CLR_LATCHED_SINGLE(COMMAND_COUNTS) [also resets cmdexe, cmdacc, itf_error counts) - -last_opcode: - <<: *hskp_default - LABLAXIS: LAST_OPCODE - FIELDNAM: Last executed opcode - FILLVAL: *uint16_fillval - CATDESC: Opcode of the last executed command - -mode: - <<: *hskp_default - LABLAXIS: MODE - FIELDNAM: Instrument Mode - CATDESC: Current operating mode - -memop_state: - <<: *hskp_default - LABLAXIS: MEMOP_STATE - FIELDNAM: Memory Operation State - CATDESC: State of the memory-operations handler - -memdump_state: - <<: *hskp_default - LABLAXIS: MEMDUMP_STATE - FIELDNAM: Memory Dump State - CATDESC: State of the memory-dump handler (busy/idle) - -itf_err_cnt: - <<: *hskp_default - LABLAXIS: ITF_ERR_CNT - FIELDNAM: Number of ITF errors encountered - CATDESC: Number of ITF Errors detected. See VAR_NOTES for more details. - VAR_NOTES: Number of ITF Errors that have been detected; counts 0-3, then rolls over to 0. Reset via CLR_LATCHED_SINGLE(COMMAND_COUNTS) [also resets cmdexe, cmdjrct, cmdacc counts) - -spin_cnt: - <<: *hskp_default - LABLAXIS: SPIN_CNT - FIELDNAM: Number of spin pulses received - CATDESC: Number of spin pulses received - -missed_pps_cnt: - <<: *hskp_default - LABLAXIS: MISSED_PPS_CNT - FIELDNAM: Number of missed PPS pulses - CATDESC: Number of missed PPS pulses. See VAR_NOTES for more details. - VAR_NOTES: Number of missed PPS pulses. Counts 0-3, then freezes at 3. Reset via CLR_LATCHED_SINGLE(PPS_STATS) - -wdog_timeout_cnt: - <<: *hskp_default - LABLAXIS: WDOG_TIMEOUT_CNT - FIELDNAM: Number of watchdog timeouts since last reset - CATDESC: Number of times the watchdog has timed out. - -hv_plug: - <<: *hskp_default - LABLAXIS: HV_PLUG - FIELDNAM: Status of the HV Disable Plug - CATDESC: Status of the HV plugs. See VAR_NOTES for more details. - VAR_NOTES: Current status of the HV SAFE/DISABLE plugs -- "SAFE" - all HVPS outputs provide 1/10 the commanded voltage; "DIS" - all HVPS outputs provide 0V, regardless of commanded voltage; "FULL" - HVPS outputs provide the full commanded voltage - -cmd_fifo_overrun_cnt: - <<: *hskp_default - LABLAXIS: CMD_FIFO_OVERRUN_CNT - FIELDNAM: Number of Command FIFO Overruns - CATDESC: Number of Command FIFO Overruns - -cmd_fifo_underrun_cnt: - <<: *hskp_default - LABLAXIS: CMD_FIFO_UNDERRUN_CNT - FIELDNAM: Number of Command FIFO Underruns - CATDESC: Number of Command FIFO Underruns - -cmd_fifo_parity_err_cnt: - <<: *hskp_default - LABLAXIS: CMD_FIFO_PARITY_ERR_CNT - FIELDNAM: Number of Command FIFO Parity Errors - CATDESC: Number of Command FIFO Parity Errors - -cmd_fifo_frame_err_cnt: - <<: *hskp_default - LABLAXIS: CMD_FIFO_FRAME_ERR_CNT - FIELDNAM: Number of Command FIFO Frame Errors - CATDESC: Number of Command FIFO Frame Errors - -tlm_fifo_overrun_cnt: - <<: *hskp_default - LABLAXIS: TLM_FIFO_OVERRUN_CNT - FIELDNAM: Number of Telemetry FIFO Overruns - CATDESC: Number of Telemetry FIFO Overruns - -spin_period_hskp: - <<: *hskp_default - LABLAXIS: SPIN_PERIOD - FIELDNAM: Spin Period - FILLVAL: *uint16_fillval - CATDESC: Current Spin Period - -spin_bin_period: - <<: *hskp_default - LABLAXIS: SPIN_BIN_PERIOD - FIELDNAM: Spin Bin Period - FILLVAL: *uint16_fillval - CATDESC: Spin Bin Period - -spin_period_timer: - <<: *hskp_default - LABLAXIS: SPIN_PERIOD_TIMER - FIELDNAM: Spin Period Timer - FILLVAL: *uint16_fillval - CATDESC: Spin Period Timer - -spin_timestamp_seconds: - <<: *hskp_default - LABLAXIS: SPIN_TIMESTAMP_SECONDS - FIELDNAM: Full-seconds timestamp of the most recent spin pulse - FILLVAL: *uint32_fillval - CATDESC: Full-seconds timestamp of the most recent spin pulse - -spin_timestamp_subseconds: - <<: *hskp_default - LABLAXIS: SPIN_TIMESTAMP_SUBSECONDS - FIELDNAM: Sub-seconds timestamp of the most recent spin pulse - FILLVAL: *uint32_fillval - CATDESC: Sub-seconds timestamp of the most recent spin pulse - -spin_bin_index: - <<: *hskp_default - LABLAXIS: SPIN_BIN_INDEX - FIELDNAM: Spin Bin Index - FILLVAL: *uint16_fillval - CATDESC: Spin Bin Index - -optc_hv_cmd_err_cnt: - <<: *hskp_default - LABLAXIS: OPTICS_HV_CMD_ERR_CNT - FIELDNAM: Optics HV - Number of command errors - CATDESC: Optics HV - Number of command errors - -spare_1: - <<: *hskp_default - LABLAXIS: SPARE_1 - FIELDNAM: Spare for alignment - CATDESC: Spare for alignment - -optc_hv_arm_err_cnt: - <<: *hskp_default - LABLAXIS: OPTICS_HV_ARM_ERR_CNT - FIELDNAM: Optics HV - Number of arm errors - CATDESC: Optics HV - Number of arm errors - -optc_hv_master_en: - <<: *hskp_default - LABLAXIS: OPTICS_HV_MASTER_ENABLE - FIELDNAM: Optics HV - Master Enable - CATDESC: Optics HV - Master Enable - -iobulk_en: - <<: *hskp_default - LABLAXIS: OPTICS_HV_P15KV_ENABLE - FIELDNAM: Optics HV - P15KV Enable - CATDESC: Optics HV - P15KV Enable - -esab_en: - <<: *hskp_default - LABLAXIS: OPTICS_HV_ESAB_ENABLE - FIELDNAM: Optics HV - ESA B Enable - CATDESC: Optics HV - ESA B Enable - -spare_2: - <<: *hskp_default - LABLAXIS: SPARE_2 - FIELDNAM: Spare (was Optics HV - ESA B Range) - CATDESC: Spare (was Optics HV - ESA B Range) - -esaa_en: - <<: *hskp_default - LABLAXIS: OPTICS_HV_ESAA_ENABLE - FIELDNAM: Optics HV - ESA A Enable - CATDESC: Optics HV - ESA A Enable - -spare_3: - <<: *hskp_default - LABLAXIS: SPARE_3 - FIELDNAM: Spare (was Optics HV - ESA A Range) - CATDESC: Spare (was Optics HV - ESA A Range) - -snsr_hv_cmd_err_cnt: - <<: *hskp_default - LABLAXIS: SENSOR_HV_CMD_ERR_CNT - FIELDNAM: Sensor HV - Number of command errors - CATDESC: Sensor HV - Number of command errors - -snsr_hv_arm_err_cnt: - <<: *hskp_default - LABLAXIS: SENSOR_HV_ARM_ERR_CNT - FIELDNAM: Sensor HV - Number of Arm errors - CATDESC: Sensor HV - Number of Arm errors - -snsr_hv_master_en: - <<: *hskp_default - LABLAXIS: SENSOR_HV_MASTER_ENABLE - FIELDNAM: Sensor HV - Master Enable - CATDESC: Sensor HV - Master Enable - -apdb_en: - <<: *hskp_default - LABLAXIS: SENSOR_HV_APD_BIAS_ENABLE - FIELDNAM: Sensor HV - APD Bias Enable - CATDESC: Sensor HV - APD Bias Enable - -sbulk_en: - <<: *hskp_default - LABLAXIS: SENSOR_HV_P6KV_ENABLE - FIELDNAM: Sensor HV - p6KV Enable - CATDESC: Sensor HV - p6KV Enable - -stpmcp_en: - <<: *hskp_default - LABLAXIS: SENSOR_HV_STOP_MCP_ENABLE - FIELDNAM: Sensor HV - Stop MCP Enable - CATDESC: Sensor HV - Stop MCP Enable - -strmcp_en: - <<: *hskp_default - LABLAXIS: SENSOR_HV_START_MCP_ENABLE - FIELDNAM: Sensor HV - Start MCP Enable - CATDESC: Sensor HV - Start MCP Enable - -spare_4: - <<: *hskp_default - LABLAXIS: SPARE_4 - FIELDNAM: Spare for alignment - CATDESC: Spare for alignment - -esaa_dac: - <<: *hskp_default - LABLAXIS: OPTICS_HV_DAC_ESA_A - FIELDNAM: Optics HV - ESA A DAC - FILLVAL: *uint16_fillval - CATDESC: Optics HV - ESA A DAC - -esab_dac: - <<: *hskp_default - LABLAXIS: OPTICS_HV_DAC_ESA_B - FIELDNAM: Optics HV - ESA B DAC - FILLVAL: *uint16_fillval - CATDESC: Optics HV - ESA B DAC - -iobulk_dac: - <<: *hskp_default - LABLAXIS: OPTICS_HV_DAC_IONBULK - FIELDNAM: Optics HV - Ion Bulk DAC - FILLVAL: *uint16_fillval - CATDESC: Optics HV - Ion Bulk DAC - -ssdo_dac: - <<: *hskp_default - LABLAXIS: SENSOR_HV_DAC_SSDO - FIELDNAM: Sensor HV - SSDO Enable - FILLVAL: *uint16_fillval - CATDESC: Sensor HV - SSDO Enable - -ssdb_dac: - <<: *hskp_default - LABLAXIS: SENSOR_HV_DAC_SSDB - FIELDNAM: Sensor HV - SSD Bias Enable - FILLVAL: *uint16_fillval - CATDESC: Sensor HV - SSD Bias Enable - -apdb_dac: - <<: *hskp_default - LABLAXIS: SENSOR_HV_DAC_APDB - FIELDNAM: Sensor HV - ADP Bias Enable - FILLVAL: *uint16_fillval - CATDESC: Sensor HV - ADP Bias Enable - -apdb2_dac: - <<: *hskp_default - LABLAXIS: SENSOR_HV_DAC_APDB2 - FIELDNAM: Sensor HV - ADP Bias 2 Enable - FILLVAL: *uint16_fillval - CATDESC: Sensor HV - ADP Bias 2 Enable - -strmcp_dac: - <<: *hskp_default - LABLAXIS: SENSOR_HV_DAC_START_MCP - FIELDNAM: Sensor HV - Start MCP DAC - FILLVAL: *uint16_fillval - CATDESC: Sensor HV - Start MCP DAC - -stpmcp_dac: - <<: *hskp_default - LABLAXIS: SENSOR_HV_DAC_STOP_MCP - FIELDNAM: Sensor HV - Stop MCP DAC - FILLVAL: *uint16_fillval - CATDESC: Sensor HV - Stop MCP DAC - -stpog_dac: - <<: *hskp_default - LABLAXIS: SENSOR_HV_DAC_STOP_OPTICS_GRID - FIELDNAM: Sensor HV - Stop Optics Grid DAC - FILLVAL: *uint16_fillval - CATDESC: Sensor HV - Stop Optics Grid DAC - -sbulk_vmon: - <<: *hskp_default - LABLAXIS: SBULK_VMON - FIELDNAM: HVPS - V1 -- Sensor Bulk Voltage Monitor - FILLVAL: *uint16_fillval - CATDESC: HVPS - V1 -- Sensor Bulk Voltage Monitor - -ssdo_vmon: - <<: *hskp_default - LABLAXIS: SSDO_VMON - FIELDNAM: HVPS - V2 -- SSD Optics Voltage Monitor - FILLVAL: *uint16_fillval - CATDESC: HVPS - V2 -- SSD Optics Voltage Monitor - -ssdb_vmon: - <<: *hskp_default - LABLAXIS: SSDB_VMON - FIELDNAM: HVPS - V3 -- SSD Bias Voltage Monitor - FILLVAL: *uint16_fillval - CATDESC: HVPS - V3 -- SSD Bias Voltage Monitor - -apdb1_vmon: - <<: *hskp_default - LABLAXIS: APDB1_VMON - FIELDNAM: HVPS - V4 -- APD1 Bias Voltage Monitor - FILLVAL: *uint16_fillval - CATDESC: HVPS - V4 -- APD1 Bias Voltage Monitor - -apdb2_vmon: - <<: *hskp_default - LABLAXIS: APDB2_VMON - FIELDNAM: HVPS - V5 -- APD1 Bias Voltage Monitor - FILLVAL: *uint16_fillval - CATDESC: HVPS - V5 -- APD1 Bias Voltage Monitor - -iobulk_vmon: - <<: *hskp_default - LABLAXIS: IOBULK_VMON - FIELDNAM: HVPS - V6 -- IO Bulk Voltage Monitor - FILLVAL: *uint16_fillval - CATDESC: HVPS - V6 -- IO Bulk Voltage Monitor - -esaa_hi_vmon: - <<: *hskp_default - LABLAXIS: ESAA_HI_VMON - FIELDNAM: HVPS - V7 -- ESA A High Range Voltage Monitor - FILLVAL: *uint16_fillval - CATDESC: HVPS - V7 -- ESA A High Range Voltage Monitor - -spare_62: - <<: *hskp_default - LABLAXIS: SPARE_62 - FIELDNAM: Spare (was ESAA_LO_VMON) - CATDESC: Spare (was ESAA_LO_VMON) - -strmcp_vmon: - <<: *hskp_default - LABLAXIS: STRMCP_VMON - FIELDNAM: HVPS - V9 -- Start MCP Voltage Monitor - FILLVAL: *uint16_fillval - CATDESC: HVPS - V9 -- Start MCP Voltage Monitor - -stpmcp_vmon: - <<: *hskp_default - LABLAXIS: STPMCP_VMON - FIELDNAM: HVPS - V10 -- Stop MCP Voltage Monitor - FILLVAL: *uint16_fillval - CATDESC: HVPS - V10 -- Stop MCP Voltage Monitor - -stpog_vmon: - <<: *hskp_default - LABLAXIS: STPOG_VMON - FIELDNAM: HVPS - V11 -- Stop Optics Grid Voltage Monitor - FILLVAL: *uint16_fillval - CATDESC: HVPS - V11 -- Stop Optics Grid Voltage Monitor - -apdb1_imon: - <<: *hskp_default - LABLAXIS: APDB1_IMON - FIELDNAM: HVPS - V12 -- APD1 Bias Current Monitor - FILLVAL: *uint16_fillval - CATDESC: HVPS - V12 -- APD1 Bias Current Monitor - -esab_hi_vmon: - <<: *hskp_default - LABLAXIS: ESAB_HI_VMON - FIELDNAM: HVPS - V13 -- ESA A High Range Voltage Monitor - FILLVAL: *uint16_fillval - CATDESC: HVPS - V13 -- ESA A High Range Voltage Monitor - -spare_68: - <<: *hskp_default - LABLAXIS: SPARE_68 - FIELDNAM: Spare (was ESAB_LO_VMON) - CATDESC: Spare (was ESAB_LO_VMON) - -apdb2_imon: - <<: *hskp_default - LABLAXIS: APDB2_IMON - FIELDNAM: HVPS - V15 -- APD2 Bias Current Monitor - FILLVAL: *uint16_fillval - CATDESC: HVPS - V15 -- APD2 Bias Current Monitor - -ssdb_imon: - <<: *hskp_default - LABLAXIS: SSDB_IMON - FIELDNAM: HVPS - V16 -- SSD Bias Current Monitor - FILLVAL: *uint16_fillval - CATDESC: HVPS - V16 -- SSD Bias Current Monitor - -stpmcp_imon: - <<: *hskp_default - LABLAXIS: STPMCP_IMON - FIELDNAM: HVPS - I1 -- Stop MCP Current Monitor - FILLVAL: *uint16_fillval - CATDESC: HVPS - I1 -- Stop MCP Current Monitor - -iobulk_imon: - <<: *hskp_default - LABLAXIS: IOBULK_IMON - FIELDNAM: HVPS - I2 -- IO Bulk Current Monitor - FILLVAL: *uint16_fillval - CATDESC: HVPS - I2 -- IO Bulk Current Monitor - -strmcp_imon: - <<: *hskp_default - LABLAXIS: STRMCP_IMON - FIELDNAM: HVPS - I3 -- Start MCP Current Monitor - FILLVAL: *uint16_fillval - CATDESC: HVPS - I3 -- Start MCP Current Monitor - -mdm25p_14_t: - <<: *hskp_default - LABLAXIS: MDM25P_14_T - FIELDNAM: System Temperature 1 -- MDM25P - 14 Temperature - FILLVAL: *uint16_fillval - CATDESC: System Temperature 1 -- MDM25P - 14 Temperature - -mdm25p_15_t: - <<: *hskp_default - LABLAXIS: MDM25P_15_T - FIELDNAM: System Temperature 2 -- MDM25P - 15 Temperature - FILLVAL: *uint16_fillval - CATDESC: System Temperature 2 -- MDM25P - 15 Temperature - -mdm25p_16_t: - <<: *hskp_default - LABLAXIS: MDM25P_16_T - FIELDNAM: System Temperature 3 -- MDM25P - 16 Temperature - FILLVAL: *uint16_fillval - CATDESC: System Temperature 3 -- MDM25P - 16 Temperature - -mdm51p_27_t: - <<: *hskp_default - LABLAXIS: MDM51P_27_T - FIELDNAM: LO Temperature -- MDM51P - 27 Temperature - FILLVAL: *uint16_fillval - CATDESC: LO Temperature -- MDM51P - 27 Temperature - -io_hvps_t: - <<: *hskp_default - LABLAXIS: IO_HVPS_T - FIELDNAM: HVPS Temperature -- IO-HVPS Temperature - FILLVAL: *uint16_fillval - CATDESC: HVPS Temperature -- IO-HVPS Temperature - -lvps_12v_t: - <<: *hskp_default - LABLAXIS: LVPS_12V_T - FIELDNAM: LVPS Temperature 1 -- LVPS - 12V Temperature - FILLVAL: *uint16_fillval - CATDESC: LVPS Temperature 1 -- LVPS - 12V Temperature - -lvps_5v_t: - <<: *hskp_default - LABLAXIS: LVPS_5V_T - FIELDNAM: LVPS Temperature 2 -- LVPS - 5V Temperature - FILLVAL: *uint16_fillval - CATDESC: LVPS Temperature 2 -- LVPS - 5V Temperature - -lvps_3p3v_t: - <<: *hskp_default - LABLAXIS: LVPS_3P3V_T - FIELDNAM: LVPS Temperature 3 -- LVPS - +3.3V Temperature - FILLVAL: *uint16_fillval - CATDESC: LVPS Temperature 3 -- LVPS - +3.3V Temperature - -lvps_3p3v: - <<: *hskp_default - LABLAXIS: LVPS_3P3V - FIELDNAM: LVPS - Digital V1 -- LVPS - +3.3V - FILLVAL: *uint16_fillval - CATDESC: LVPS - Digital V1 -- LVPS - +3.3V - -lvps_5v: - <<: *hskp_default - LABLAXIS: LVPS_5V - FIELDNAM: LVPS - Digital V2 -- LVPS - +5V - FILLVAL: *uint16_fillval - CATDESC: LVPS - Digital V2 -- LVPS - +5V - -lvps_n5v: - <<: *hskp_default - LABLAXIS: LVPS_N5V - FIELDNAM: LVPS - Digital V3 -- LVPS - -5V - FILLVAL: *uint16_fillval - CATDESC: LVPS - Digital V3 -- LVPS - -5V - -lvps_12v: - <<: *hskp_default - LABLAXIS: LVPS_12V - FIELDNAM: LVPS - Digital V4 -- LVPS - +12V - FILLVAL: *uint16_fillval - CATDESC: LVPS - Digital V4 -- LVPS - +12V - -lvps_n12v: - <<: *hskp_default - LABLAXIS: LVPS_N12V - FIELDNAM: LVPS - Digital V5 -- LVPS - -12V - FILLVAL: *uint16_fillval - CATDESC: LVPS - Digital V5 -- LVPS - -12V - -lvps_3p3v_i: - <<: *hskp_default - LABLAXIS: LVPS_3P3V_I - FIELDNAM: LVPS - Digital I1 -- LVPS - +3.3V Current - FILLVAL: *uint16_fillval - CATDESC: LVPS - Digital I1 -- LVPS - +3.3V Current - -lvps_5v_i: - <<: *hskp_default - LABLAXIS: LVPS_5V_I - FIELDNAM: LVPS - Digital I2 -- LVPS - +5V Current - FILLVAL: *uint16_fillval - CATDESC: LVPS - Digital I2 -- LVPS - +5V Current - -lvps_n5v_i: - <<: *hskp_default - LABLAXIS: LVPS_N5V_I - FIELDNAM: LVPS - Digital I3 -- LVPS - -5V Current - FILLVAL: *uint16_fillval - CATDESC: LVPS - Digital I3 -- LVPS - -5V Current - -lvps_12v_i: - <<: *hskp_default - LABLAXIS: LVPS_12V_I - FIELDNAM: LVPS - Digital I4 -- LVPS - +12V Current - FILLVAL: *uint16_fillval - CATDESC: LVPS - Digital I4 -- LVPS - +12V Current - -lvps_n12v_i: - <<: *hskp_default - LABLAXIS: LVPS_N12V_I - FIELDNAM: LVPS - Digital I5 -- LVPS - -12V Current - FILLVAL: *uint16_fillval - CATDESC: LVPS - Digital I5 -- LVPS - -12V Current - -cdh_1p5v: - <<: *hskp_default - LABLAXIS: CDH_1P5V - FIELDNAM: CDH - + 1.5V - FILLVAL: *uint16_fillval - CATDESC: CDH - + 1.5V - -cdh_1p8v: - <<: *hskp_default - LABLAXIS: CDH_1P8V - FIELDNAM: CDH - +1.8V - FILLVAL: *uint16_fillval - CATDESC: CDH - +1.8V - -cdh_3p3v: - <<: *hskp_default - LABLAXIS: CDH_3P3V - FIELDNAM: CDH - +3.3V - FILLVAL: *uint16_fillval - CATDESC: CDH - +3.3V - -cdh_12v: - <<: *hskp_default - LABLAXIS: CDH_12V - FIELDNAM: CDH - +12V - FILLVAL: *uint16_fillval - CATDESC: CDH - +12V - -cdh_n12v: - <<: *hskp_default - LABLAXIS: CDH_N12V - FIELDNAM: CDH - -12V - FILLVAL: *uint16_fillval - CATDESC: CDH - -12V - -cdh_5v: - <<: *hskp_default - LABLAXIS: CDH_5V - FIELDNAM: CDH - +5V - FILLVAL: *uint16_fillval - CATDESC: CDH - +5V - -cdh_5v_adc: - <<: *hskp_default - LABLAXIS: CDH_5V_ADC - FIELDNAM: CDH - Analog Ref -- CDH - +5V ADC - FILLVAL: *uint16_fillval - CATDESC: CDH - Analog Ref -- CDH - +5V ADC - -tbd_hvps_1_if_err_cnt: - <<: *hskp_default - LABLAXIS: TBD_HVPS_1_IF_ERR_CNT - FIELDNAM: TBD - Placeholder for HVPS 1 Interface error counts - CATDESC: TBD - Placeholder for HVPS 1 Interface error counts - -tbd_hvps_2_if_err_cnt: - <<: *hskp_default - LABLAXIS: TBD_HVPS_2_IF_ERR_CNT - FIELDNAM: TBD - Placeholder for HVPS 2 Interface error counts - CATDESC: TBD - Placeholder for HVPS 2 Interface error counts - -tbd_fee_1_if_err_cnt: - <<: *hskp_default - LABLAXIS: TBD_FEE_1_IF_ERR_CNT - FIELDNAM: TBD - Placeholder for FEE 1 Interface error counts - CATDESC: TBD - Placeholder for FEE 1 Interface error counts - -tbd_fee_2_if_err_cnt: - <<: *hskp_default - LABLAXIS: TBD_FEE_2_IF_ERR_CNT - FIELDNAM: TBD - Placeholder for FEE 2 Interface error counts - CATDESC: TBD - Placeholder for FEE 2 Interface error counts - -tbd_macro_status: - <<: *hskp_default - LABLAXIS: TBD_MACRO_STATUS - FIELDNAM: TBD - Placeholder for Macro status - FILLVAL: *uint32_fillval - CATDESC: TBD - Placeholder for Macro status - -fdc_trigger_cnt_fsw: - <<: *hskp_default - LABLAXIS: FDC_TRIGGER_CNT_FSW - FIELDNAM: Indicates whether any CATEGORY 1 limits have triggered - CATDESC: Indicates any CATEGORY 1 limits triggered. See VAR_NOTES for more details. - VAR_NOTES: Indicates whether any CATEGORY 1 limits have triggered -- 2 bits -- 0=No triggers; 1=One trigger; 2=Two triggers; 3=More than two triggers - -fdc_trigger_cnt_hvps: - <<: *hskp_default - LABLAXIS: FDC_TRIGGER_CNT_HVPS - FIELDNAM: Indicates whether any CATEGORY 2 limits have triggered - CATDESC: Indicates whether any CATEGORY 2 limits have triggered - -fdc_trigger_cnt_cdh: - <<: *hskp_default - LABLAXIS: FDC_TRIGGER_CNT_CDH - FIELDNAM: Indicates whether any CATEGORY 3 limits have triggered - CATDESC: Indicates whether any CATEGORY 3 limits have triggered - -fdc_trigger_cnt_fee: - <<: *hskp_default - LABLAXIS: FDC_TRIGGER_CNT_FEE - FIELDNAM: Indicates whether any CATEGORY 4 limits have triggered - CATDESC: Indicates whether any CATEGORY 4 limits have triggered - -fdc_trigger_cnt_spare1: - <<: *hskp_default - LABLAXIS: FDC_TRIGGER_CNT_SPARE1 - FIELDNAM: Indicates whether any CATEGORY 5 limits have triggered - CATDESC: Indicates whether any CATEGORY 5 limits have triggered - -fdc_trigger_cnt_spare2: - <<: *hskp_default - LABLAXIS: FDC_TRIGGER_CNT_SPARE2 - FIELDNAM: Indicates whether any CATEGORY 6 limits have triggered - CATDESC: Indicates whether any CATEGORY 6 limits have triggered - -fdc_trigger_cnt_spare3: - <<: *hskp_default - LABLAXIS: FDC_TRIGGER_CNT_SPARE3 - FIELDNAM: Indicates whether any CATEGORY 7 limits have triggered - CATDESC: Indicates whether any CATEGORY 7 limits have triggered - -fdc_trigger_cnt_spare4: - <<: *hskp_default - LABLAXIS: FDC_TRIGGER_CNT_SPARE4 - FIELDNAM: Indicates whether any CATEGORY 8 limits have triggered - CATDESC: Indicates whether any CATEGORY 8 limits have triggered - -fdc_last_trigger_minmax: - <<: *hskp_default - LABLAXIS: FDC_LAST_TRIGGER_MINMAX - FIELDNAM: Indicates whether the most recent trigger was a minimum or maximum limit - CATDESC: Indicates whether the most recent trigger was a minimum or maximum limit - -fdc_last_trigger_id: - <<: *hskp_default - LABLAXIS: FDC_LAST_TRIGGER_ID - FIELDNAM: Indicates the ID of the most recent FDC trigger - FILLVAL: *uint16_fillval - CATDESC: Indicates the ID of the most recent FDC trigger - -fdc_last_trigger_action: - <<: *hskp_default - LABLAXIS: FDC_LAST_TRIGGER_ACTION - FIELDNAM: Indicates the action that was taken for the most recent FDC trigger - CATDESC: Indicates the action that was taken for the most recent FDC trigger - -round_robin_index: - <<: *hskp_default - LABLAXIS: ROUND_ROBIN_INDEX - FIELDNAM: Round Robin Parameter Report Index - FILLVAL: *uint32_fillval - CATDESC: Index for Round Robin parameter reporting. See VAR_NOTES for more details. - VAR_NOTES: Current index for the Round Robin parameter reporting. The Round Robin mechanism reports one value from the Parameter Table each time this packet is generated. - -round_robin_value: - <<: *hskp_default - LABLAXIS: ROUND_ROBIN_VALUE - FIELDNAM: Round Robin Parameter Report Value - FILLVAL: *uint32_fillval - CATDESC: Parameter value corresponding to the current Round_Robin_Index value. - -heater_control_state: - <<: *hskp_default - LABLAXIS: HEATER_CONTROL_STATE - FIELDNAM: State of the heater controller - CATDESC: Indicates whether FSW control of the operational heater is enabled - -heater_output_state: - <<: *hskp_default - LABLAXIS: HEATER_OUTPUT_STATE - FIELDNAM: State of the heater output - CATDESC: Indicates the current state of the physical heater output - -heater_output_state_2: - <<: *hskp_default - LABLAXIS: HEATER_OUTPUT_STATE_2 - FIELDNAM: State of the heater output 2 - CATDESC: Indicates the current state of the physical heater output - -spare_5: - <<: *hskp_default - LABLAXIS: SPARE_5 - FIELDNAM: Spare for alignment - CATDESC: Spare for alignment - -cpu_idle: - <<: *hskp_default - LABLAXIS: CPU_IDLE - FIELDNAM: CPU Idle Percent - CATDESC: CPU Idle Percent - -cdh_processor_t: - <<: *hskp_default - LABLAXIS: CDH_PROCESSOR_T - FIELDNAM: CDH - Processor Temp monitor - FILLVAL: *uint16_fillval - CATDESC: CDH - Processor Temp monitor - -cdh_1p8v_ldo_t: - <<: *hskp_default - LABLAXIS: CDH_1P8V_LDO_T - FIELDNAM: CDH - +1.8V LDO Temp monitor - FILLVAL: *uint16_fillval - CATDESC: CDH - +1.8V LDO Temp monitor - -cdh_1p5v_ldo_t: - <<: *hskp_default - LABLAXIS: CDH_1P5V_LDO_T - FIELDNAM: CDH - +1.5V LDO Temp monitor - FILLVAL: *uint16_fillval - CATDESC: CDH - +1.5V LDO Temp monitor - -cdh_sdram_t: - <<: *hskp_default - LABLAXIS: CDH_SDRAM_T - FIELDNAM: CDH - SDRAM Temp monitor - FILLVAL: *uint16_fillval - CATDESC: CDH - SDRAM Temp monitor - -snsr_hvps_t: - <<: *hskp_default - LABLAXIS: SNSR_HVPS_T - FIELDNAM: CoDICE - Sensor HVPS Temp monitor - FILLVAL: *uint16_fillval - CATDESC: CoDICE - Sensor HVPS Temp monitor - -fee_apd_3p3_digital_v: - <<: *hskp_default - LABLAXIS: FEE_APD_3P3_DIGITAL_V - FIELDNAM: FEE; APD Side +3.3V Digital - FILLVAL: *uint16_fillval - CATDESC: FEE; APD Side +3.3V Digital - -fee_apd_5p0_analog_v: - <<: *hskp_default - LABLAXIS: FEE_APD_5P0_ANALOG_V - FIELDNAM: FEE; APD Side +5.0V Analog - FILLVAL: *uint16_fillval - CATDESC: FEE; APD Side +5.0V Analog - -fee_apd_t: - <<: *hskp_default - LABLAXIS: FEE_APD_T - FIELDNAM: FEE; APD Side Temperature - FILLVAL: *uint16_fillval - CATDESC: FEE; APD Side Temperature - -fee_apd_12p0_analog_v: - <<: *hskp_default - LABLAXIS: FEE_APD_12P0_ANALOG_V - FIELDNAM: FEE; APD Side +12.0V Analog - FILLVAL: *uint16_fillval - CATDESC: FEE; APD Side +12.0V Analog - -fee_apd_eb_temp_1_t: - <<: *hskp_default - LABLAXIS: FEE_APD_EB_TEMP_1_T - FIELDNAM: FEE; AEB Temp Sensor 1 - FILLVAL: *uint16_fillval - CATDESC: FEE; AEB Temp Sensor 1 - -fee_apd_eb_temp_2_t: - <<: *hskp_default - LABLAXIS: FEE_APD_EB_TEMP_2_T - FIELDNAM: FEE; AEB Temp Sensor 2 - FILLVAL: *uint16_fillval - CATDESC: FEE; AEB Temp Sensor 2 - -fee_apd_eb_temp_3_t: - <<: *hskp_default - LABLAXIS: FEE_APD_EB_TEMP_3_T - FIELDNAM: FEE; AEB Temp Sensor 3 - FILLVAL: *uint16_fillval - CATDESC: FEE; AEB Temp Sensor 3 - -fee_apd_eb_temp_4_t: - <<: *hskp_default - LABLAXIS: FEE_APD_EB_TEMP_4_T - FIELDNAM: FEE; AEB Temp Sensor 4 - FILLVAL: *uint16_fillval - CATDESC: FEE; AEB Temp Sensor 4 - -fee_ssd_3p3_digital_v: - <<: *hskp_default - LABLAXIS: FEE_SSD_3P3_DIGITAL_V - FIELDNAM: FEE; SSD Side +3.3V Digital - FILLVAL: *uint16_fillval - CATDESC: FEE; SSD Side +3.3V Digital - -fee_ssd_5p0_analog_v: - <<: *hskp_default - LABLAXIS: FEE_SSD_5P0_ANALOG_V - FIELDNAM: FEE; SSD Side +5.0V Analog - FILLVAL: *uint16_fillval - CATDESC: FEE; SSD Side +5.0V Analog - -fee_ssd_t: - <<: *hskp_default - LABLAXIS: FEE_SSD_T - FIELDNAM: FEE; SSD Side Temperature - FILLVAL: *uint16_fillval - CATDESC: FEE; SSD Side Temperature - -fee_ssd_12p0_analog_v: - <<: *hskp_default - LABLAXIS: FEE_SSD_12P0_ANALOG_V - FIELDNAM: FEE; SSD Side +12.0V Analog - FILLVAL: *uint16_fillval - CATDESC: FEE; SSD Side +12.0V Analog - -fee_ssd_eb_temp_1_t: - <<: *hskp_default - LABLAXIS: FEE_SSD_EB_TEMP_1_T - FIELDNAM: FEE; SEB Temp Sensor 1 - FILLVAL: *uint16_fillval - CATDESC: FEE; SEB Temp Sensor 1 - -fee_ssd_eb_temp_2_t: - <<: *hskp_default - LABLAXIS: FEE_SSD_EB_TEMP_2_T - FIELDNAM: FEE; SEB Temp Sensor 2 - FILLVAL: *uint16_fillval - CATDESC: FEE; SEB Temp Sensor 2 - -fee_ssd_eb_temp_3_t: - <<: *hskp_default - LABLAXIS: FEE_SSD_EB_TEMP_3_T - FIELDNAM: FEE; SEB Temp Sensor 3 - FILLVAL: *uint16_fillval - CATDESC: FEE; SEB Temp Sensor 3 - -fee_ssd_eb_temp_4_t: - <<: *hskp_default - LABLAXIS: FEE_SSD_EB_TEMP_4_T - FIELDNAM: FEE; SEB Temp Sensor 4 - FILLVAL: *uint16_fillval - CATDESC: FEE; SEB Temp Sensor 4 - -spare_6: - <<: *hskp_default - LABLAXIS: SPARE_6 - FIELDNAM: Spare for alignment - CATDESC: Spare for alignment \ No newline at end of file diff --git a/imap_processing/cdf/config/imap_codice_l2-hi-direct-events_variable_attrs.yaml b/imap_processing/cdf/config/imap_codice_l2-hi-direct-events_variable_attrs.yaml new file mode 100644 index 0000000000..e7e2814579 --- /dev/null +++ b/imap_processing/cdf/config/imap_codice_l2-hi-direct-events_variable_attrs.yaml @@ -0,0 +1,341 @@ +uint8_fillval: &uint8_fillval 255 +uint16_fillval: &uint16_fillval 65535 +real_fillval: &real_fillval -1.0e+31 +min_int: &min_int -9223372036854775808 +max_int: &max_int 9223372036854775807 + +# ------------------------------- Coordinates ------------------------------- +priority: + CATDESC: Priority Level + DICT_KEY: SPASE>Support>SupportQuantity:Other + FIELDNAM: Priority Level + FILLVAL: *uint8_fillval + FORMAT: I1 + LABLAXIS: Priority + SCALETYP: linear + UNITS: " " + VALIDMAX: 7 + VALIDMIN: 0 + VAR_TYPE: support_data + +event_num: + CATDESC: Event Number + DICT_KEY: SPASE>Support>SupportQuantity:Other + FIELDNAM: Event Number + FILLVAL: *uint16_fillval + FORMAT: I5 + LABLAXIS: Event Number + SCALETYP: linear + UNITS: " " + VALIDMAX: 10000 + VALIDMIN: 0 + VAR_TYPE: support_data + +epoch_delta_minus: + CATDESC: Time from acquisition start to acquisition center + DEPEND_0: epoch + DICT_KEY: SPASE>Support>SupportQuantity:Temporal,Qualifier:Uncertainty + DISPLAY_TYPE: 'no_plot' + FIELDNAM: epoch delta minus + FILLVAL: -9223372036854775808 + FORMAT: I18 + LABLAXIS: Epoch Delta Minus + SCALETYP: linear + UNITS: ns + VALIDMAX: *max_int + VALIDMIN: *min_int + VAR_TYPE: support_data + +epoch_delta_plus: + CATDESC: Time from acquisition center to acquisition end + DEPEND_0: epoch + DICT_KEY: SPASE>Support>SupportQuantity:Temporal,Qualifier:Uncertainty + DISPLAY_TYPE: 'no_plot' + FIELDNAM: epoch delta plus + FILLVAL: -9223372036854775808 + FORMAT: I18 + LABLAXIS: Epoch Delta Plus + SCALETYP: linear + UNITS: ns + VALIDMAX: *max_int + VALIDMIN: *min_int + VAR_TYPE: support_data + +# ------------------------------- Data Variables ------------------------------- +num_events: + CATDESC: Number of Events per Priority + DEPEND_0: epoch + DEPEND_1: priority + DICT_KEY: SPASE>Support>SupportQuantity:Other + FIELDNAM: Number of Events + FILLVAL: *uint16_fillval + FORMAT: I5 + LABLAXIS: Number of Events + LABL_PTR_1: priority_label + SCALETYP: linear + UNITS: " " + VALIDMAX: 10000 + VALIDMIN: 0 + VAR_TYPE: data + +data_quality: + CATDESC: Data Quality Flag per Priority + DEPEND_0: epoch + DEPEND_1: priority + DICT_KEY: SPASE>Support>SupportQuantity:DataQuality + FIELDNAM: Data Quality + FILLVAL: *uint8_fillval + FORMAT: I3 + LABLAXIS: Data Quality + LABL_PTR_1: priority_label + SCALETYP: linear + UNITS: " " + VALIDMAX: 255 + VALIDMIN: 0 + VAR_TYPE: data + +energy_step: + CATDESC: Energy Step Index + DEPEND_0: epoch + DEPEND_1: priority + DEPEND_2: event_num + DICT_KEY: SPASE>Support>SupportQuantity:Other + FIELDNAM: Energy Step + FILLVAL: *uint8_fillval + FORMAT: I3 + LABLAXIS: Energy Step + LABL_PTR_1: priority_label + LABL_PTR_2: event_num_label + SCALETYP: linear + UNITS: " " + VALIDMAX: 127 + VALIDMIN: 0 + VAR_TYPE: data + +energy_per_charge: + CATDESC: Energy per Charge + DEPEND_0: epoch + DEPEND_1: priority + DEPEND_2: event_num + DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:EnergyPerCharge + FIELDNAM: Energy per Charge + FILLVAL: *real_fillval + FORMAT: F12.4 + LABLAXIS: Energy per Charge + LABL_PTR_1: priority_label + LABL_PTR_2: event_num_label + SCALETYP: linear + UNITS: keV/q + VALIDMAX: 200.0 + VALIDMIN: 0.0 + VAR_TYPE: data + +gain: + CATDESC: Gain Setting + DEPEND_0: epoch + DEPEND_1: priority + DEPEND_2: event_num + DICT_KEY: SPASE>Support>SupportQuantity:Other + FIELDNAM: Gain + FILLVAL: *uint8_fillval + FORMAT: I1 + LABLAXIS: Gain + LABL_PTR_1: priority_label + LABL_PTR_2: event_num_label + SCALETYP: linear + UNITS: " " + VALIDMAX: 1 + VALIDMIN: 0 + VAR_TYPE: data + +multi_flag: + CATDESC: Multiple Event Flag + DEPEND_0: epoch + DEPEND_1: priority + DEPEND_2: event_num + DICT_KEY: SPASE>Support>SupportQuantity:DataQuality + FIELDNAM: Multi Flag + FILLVAL: *uint8_fillval + FORMAT: I1 + LABLAXIS: Multi Flag + LABL_PTR_1: priority_label + LABL_PTR_2: event_num_label + SCALETYP: linear + UNITS: " " + VALIDMAX: 1 + VALIDMIN: 0 + VAR_TYPE: data + +type: + CATDESC: Event Type + DEPEND_0: epoch + DEPEND_1: priority + DEPEND_2: event_num + DICT_KEY: SPASE>Support>SupportQuantity:Other + FIELDNAM: Type + FILLVAL: *uint8_fillval + FORMAT: I1 + LABLAXIS: Type + LABL_PTR_1: priority_label + LABL_PTR_2: event_num_label + SCALETYP: linear + UNITS: " " + VALIDMAX: 4 + VALIDMIN: 0 + VAR_TYPE: data + +tof: + CATDESC: Time of Flight + DEPEND_0: epoch + DEPEND_1: priority + DEPEND_2: event_num + DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:TimeOfFlight + FIELDNAM: Time of Flight + FILLVAL: *real_fillval + FORMAT: F12.4 + LABLAXIS: TOF + LABL_PTR_1: priority_label + LABL_PTR_2: event_num_label + SCALETYP: linear + UNITS: ns + VALIDMAX: 1024.0 + VALIDMIN: 0.0 + VAR_TYPE: data + +spin_sector: + CATDESC: Spin Sector Index + DEPEND_0: epoch + DEPEND_1: priority + DEPEND_2: event_num + DICT_KEY: SPASE>Support>SupportQuantity:Positional + FIELDNAM: Spin Sector Index + FILLVAL: *uint8_fillval + FORMAT: I2 + LABLAXIS: Spin Sector + LABL_PTR_1: priority_label + LABL_PTR_2: event_num_label + SCALETYP: linear + UNITS: " " + VALIDMAX: 23 + VALIDMIN: 0 + VAR_TYPE: support_data + +spin_angle: + CATDESC: Spin Angle + DEPEND_0: epoch + DEPEND_1: priority + DEPEND_2: event_num + DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:ArrivalDirection,Qualifier:DirectionAngle.AzimuthAngle + FIELDNAM: Spin Angle + FILLVAL: *real_fillval + FORMAT: F8.2 + LABL_PTR_1: priority_label + LABL_PTR_2: event_num_label + SCALETYP: linear + UNITS: degrees + VALIDMAX: 360.0 + VALIDMIN: 0.0 + VAR_TYPE: data + +elevation_angle: + CATDESC: Elevation Angle + DEPEND_0: epoch + DEPEND_1: priority + DEPEND_2: event_num + DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:ArrivalDirection,Qualifier:DirectionAngle.ElevationAngle + FIELDNAM: Elevation Angle + FILLVAL: *real_fillval + FORMAT: F8.2 + LABLAXIS: Elevation Angle + LABL_PTR_1: priority_label + LABL_PTR_2: event_num_label + SCALETYP: linear + UNITS: degrees + VALIDMAX: 180.0 + VALIDMIN: 0.0 + VAR_TYPE: data + +ssd_energy: + CATDESC: SSD Energy + DEPEND_0: epoch + DEPEND_1: priority + DEPEND_2: event_num + DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:Energy + FIELDNAM: SSD Energy + FILLVAL: *real_fillval + FORMAT: F12.4 + LABLAXIS: SSD Energy + LABL_PTR_1: priority_label + LABL_PTR_2: event_num_label + SCALETYP: linear + UNITS: keV + VALIDMAX: 512.0 + VALIDMIN: 0.0 + VAR_TYPE: data + +energy_per_nuc: + CATDESC: Energy per Nucleon + DEPEND_0: epoch + DEPEND_1: priority_label + DEPEND_2: event_num + DICT_KEY: SPASE>Support>SupportQuantity:Other + FIELDNAM: Energy per Nucleon + FILLVAL: *real_fillval + FORMAT: F12.4 + LABLAXIS: Energy per Nucleon + LABL_PTR_1: priority_label + LABL_PTR_2: event_num_label + SCALETYP: linear + UNITS: MeV/nuc + VALIDMAX: 200.0 + VALIDMIN: 0.0 + VAR_TYPE: data + +ssd_id: + CATDESC: SSD Identifier + DEPEND_0: epoch + DEPEND_1: priority + DEPEND_2: event_num + DICT_KEY: SPASE>Support>SupportQuantity:Other + FIELDNAM: SSD ID + FILLVAL: *uint8_fillval + FORMAT: I2 + LABLAXIS: SSD ID + LABL_PTR_1: priority_label + LABL_PTR_2: event_num_label + SCALETYP: linear + UNITS: " " + VALIDMAX: 15 + VALIDMIN: 0 + VAR_TYPE: data + +spin_number: + CATDESC: Spin Number + DEPEND_0: epoch + DEPEND_1: priority + DEPEND_2: event_num + DICT_KEY: SPASE>Support>SupportQuantity:Other + FIELDNAM: Spin Number + FILLVAL: *uint8_fillval + FORMAT: I10 + LABLAXIS: Spin Number + LABL_PTR_1: priority_label + LABL_PTR_2: event_num_label + SCALETYP: linear + UNITS: " " + VALIDMAX: 4294967295 + VALIDMIN: 0 + VAR_TYPE: support_data +# ------------------------------- labels ------------------------------- + +event_num_label: + CATDESC: Event Number Label + FIELDNAM: Event Number + FORMAT: A5 + VAR_TYPE: metadata + +priority_label: + CATDESC: Priority Level Label + FIELDNAM: Priority Level + FORMAT: A1 + VAR_TYPE: metadata diff --git a/imap_processing/cdf/config/imap_codice_l2-hi-omni_variable_attrs.yaml b/imap_processing/cdf/config/imap_codice_l2-hi-omni_variable_attrs.yaml new file mode 100644 index 0000000000..e131e34d28 --- /dev/null +++ b/imap_processing/cdf/config/imap_codice_l2-hi-omni_variable_attrs.yaml @@ -0,0 +1,627 @@ +# ----------------------------- Useful variables ----------------------------- +uint8_fillval: &uint8_fillval 255 +uint32_fillval: &uint32_fillval 4294967295 +real_fillval: &real_fillval -1.0e+31 + +min_int: &min_int -9223372036854775808 +max_int: &max_int 9223372036854775807 + +# --------------------------- Default attributes ----------------------------- +energy_attrs: &energy_default + CATDESC: Geometric mean energy per nucleon + DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:EnergyPerCharge,Qualifier:Characteristic + DISPLAY_TYPE: time_series + FIELDNAM: Energy Table + FILLVAL: *real_fillval + FORMAT: F32.1 + LABLAXIS: Energy + SCALETYP: log + UNITS: MeV/nuc + VALIDMAX: 200.0 + VALIDMIN: 0.0 + VAR_TYPE: support_data + +# ------------------------------- Coordinates ------------------------------- +epoch_delta_minus: + CATDESC: Time from acquisition start to acquisition center + DICT_KEY: SPASE>Support>SupportQuantity:Temporal,Qualifier:Uncertainty + FIELDNAM: epoch delta minus + FILLVAL: *min_int + FORMAT: I19 + LABLAXIS: Epoch Delta Minus + SCALETYP: linear + UNITS: ns + VALIDMAX: *max_int + VALIDMIN: *min_int + VAR_TYPE: support_data + +epoch_delta_plus: + CATDESC: Time from acquisition center to acquisition end + DICT_KEY: SPASE>Support>SupportQuantity:Temporal,Qualifier:Uncertainty + FIELDNAM: epoch delta plus + FILLVAL: *min_int + FORMAT: I19 + LABLAXIS: Epoch Delta Plus + SCALETYP: linear + UNITS: ns + VALIDMAX: *max_int + VALIDMIN: *min_int + VAR_TYPE: support_data + +energy_cno: + <<: *energy_default + DELTA_MINUS_VAR: energy_cno_minus + DELTA_PLUS_VAR: energy_cno_plus + +energy_fe: + <<: *energy_default + DELTA_MINUS_VAR: energy_fe_minus + DELTA_PLUS_VAR: energy_fe_plus + +energy_h: + <<: *energy_default + DELTA_MINUS_VAR: energy_h_minus + DELTA_PLUS_VAR: energy_h_plus + +energy_he3he4: + <<: *energy_default + DELTA_MINUS_VAR: energy_he3he4_minus + DELTA_PLUS_VAR: energy_he3he4_plus + +energy_c: + <<: *energy_default + DELTA_MINUS_VAR: energy_c_minus + DELTA_PLUS_VAR: energy_c_plus + +energy_he3: + <<: *energy_default + DELTA_MINUS_VAR: energy_he3_minus + DELTA_PLUS_VAR: energy_he3_plus + +energy_he4: + <<: *energy_default + DELTA_MINUS_VAR: energy_he4_minus + DELTA_PLUS_VAR: energy_he4_plus + +energy_junk: + <<: *energy_default + DELTA_MINUS_VAR: energy_junk_minus + DELTA_PLUS_VAR: energy_junk_plus + +energy_ne_mg_si: + <<: *energy_default + DELTA_MINUS_VAR: energy_ne_mg_si_minus + DELTA_PLUS_VAR: energy_ne_mg_si_plus + +energy_o: + <<: *energy_default + DELTA_MINUS_VAR: energy_o_minus + DELTA_PLUS_VAR: energy_o_plus + +energy_uh: + <<: *energy_default + DELTA_MINUS_VAR: energy_uh_minus + DELTA_PLUS_VAR: energy_uh_plus + +# ------------------------------- Label vars -------------------------------- +epoch_delta_minus_label: + CATDESC: Time from acquisition start to acquisition center + FIELDNAM: Epoch delta minus + FORMAT: A18 + VAR_TYPE: metadata + +epoch_delta_plus_label: + CATDESC: Time from acquisition center to acquisition end + FIELDNAM: Epoch delta plus + FORMAT: A18 + VAR_TYPE: metadata + +# ------------------------------- Labels ------------------------------------ +energy_cno_label: + CATDESC: Energy CNO + FIELDNAM: Energy CNO + FORMAT: A6 + VAR_TYPE: metadata + +energy_fe_label: + CATDESC: Energy Fe + FIELDNAM: Energy Fe + FORMAT: A6 + VAR_TYPE: metadata + +energy_h_label: + CATDESC: Energy H + FIELDNAM: Energy H + FORMAT: A6 + VAR_TYPE: metadata + +energy_he3he4_label: + CATDESC: Energy He3He4 + FIELDNAM: Energy He3He4 + FORMAT: A6 + VAR_TYPE: metadata + +energy_c_label: + CATDESC: Energy C + FIELDNAM: Energy C + FORMAT: A6 + VAR_TYPE: metadata + +energy_he3_label: + CATDESC: Energy He3 + FIELDNAM: Energy He3 + FORMAT: A6 + VAR_TYPE: metadata + +energy_he4_label: + CATDESC: Energy He4 + FIELDNAM: Energy He4 + FORMAT: A6 + VAR_TYPE: metadata + +energy_junk_label: + CATDESC: Energy Junk + FIELDNAM: Energy Junk + FORMAT: A6 + VAR_TYPE: metadata + +energy_ne_mg_si_label: + CATDESC: Energy NeMgSi + FIELDNAM: Energy NeMgSi + FORMAT: A6 + VAR_TYPE: metadata + +energy_o_label: + CATDESC: Energy O + FIELDNAM: Energy O + FORMAT: A6 + VAR_TYPE: metadata + +energy_uh_label: + CATDESC: Energy UH + FIELDNAM: Energy UH + FORMAT: A6 + VAR_TYPE: metadata + +# --------------------------- Dataset variable attrs ------------------------ +# The following are set in multiple data products +data_quality: + CATDESC: Indicates whether data quality is suspect (1). + DEPEND_0: epoch + DICT_KEY: SPASE>Support>SupportQuantity:DataQuality + DISPLAY_TYPE: time_series + FIELDNAM: Data Quality + FILLVAL: *uint8_fillval + FORMAT: '%d' + LABLAXIS: Data Quality + SCALETYP: linear + UNITS: ' ' + VALIDMAX: 1 + VALIDMIN: 0 + VAR_TYPE: data + VAR_TYPE: support_data + +# ----- hi-omni Attributes ----- +# Species plus and minus attrs: +energy_c_minus: + <<: *energy_default + CATDESC: Energy Table Minus value + DEPEND_1: energy_c + DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:EnergyPerCharge,Qualifier:Uncertainty + FIELDNAM: energy delta minus + +energy_c_plus: + <<: *energy_default + CATDESC: Energy Table Plus value + DEPEND_1: energy_c + DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:EnergyPerCharge,Qualifier:Uncertainty + FIELDNAM: energy delta plus + +energy_fe_minus: + <<: *energy_default + CATDESC: Energy Table Minus value + DEPEND_1: energy_fe + DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:EnergyPerCharge,Qualifier:Uncertainty + FIELDNAM: energy delta minus + +energy_fe_plus: + <<: *energy_default + CATDESC: Energy Table Plus value + DEPEND_1: energy_fe + DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:EnergyPerCharge,Qualifier:Uncertainty + FIELDNAM: energy delta plus + +energy_h_minus: + <<: *energy_default + CATDESC: Energy Table Minus value + DEPEND_1: energy_h + DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:EnergyPerCharge,Qualifier:Uncertainty + FIELDNAM: energy delta minus + +energy_h_plus: + <<: *energy_default + CATDESC: Energy Table Plus value + DEPEND_1: energy_h + DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:EnergyPerCharge,Qualifier:Uncertainty + FIELDNAM: energy delta plus + +energy_he3_minus: + <<: *energy_default + CATDESC: Energy Table Minus value + DEPEND_1: energy_he3 + DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:EnergyPerCharge,Qualifier:Uncertainty + FIELDNAM: energy delta minus + +energy_he3_plus: + <<: *energy_default + CATDESC: Energy Table Plus value + DEPEND_1: energy_he3 + DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:EnergyPerCharge,Qualifier:Uncertainty + FIELDNAM: energy delta plus + +energy_he4_minus: + <<: *energy_default + CATDESC: Energy Table Minus value + DEPEND_1: energy_he4 + DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:EnergyPerCharge,Qualifier:Uncertainty + FIELDNAM: energy delta minus + +energy_he4_plus: + <<: *energy_default + CATDESC: Energy Table Plus value + DEPEND_1: energy_he4 + DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:EnergyPerCharge,Qualifier:Uncertainty + FIELDNAM: energy delta plus + +energy_junk_minus: + <<: *energy_default + CATDESC: Energy Table Minus value + DEPEND_1: energy_junk + DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:EnergyPerCharge,Qualifier:Uncertainty + FIELDNAM: energy delta minus + +energy_junk_plus: + <<: *energy_default + CATDESC: Energy Table Plus value + DEPEND_1: energy_junk + DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:EnergyPerCharge,Qualifier:Uncertainty + FIELDNAM: energy delta plus + +energy_ne_mg_si_minus: + <<: *energy_default + CATDESC: Energy Table Minus value + DEPEND_1: energy_ne_mg_si + DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:EnergyPerCharge,Qualifier:Uncertainty + FIELDNAM: energy delta minus + +energy_ne_mg_si_plus: + <<: *energy_default + CATDESC: Energy Table Plus value + DEPEND_1: energy_ne_mg_si + DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:EnergyPerCharge,Qualifier:Uncertainty + FIELDNAM: energy delta plus + +energy_o_minus: + <<: *energy_default + CATDESC: Energy Table Minus value + DEPEND_1: energy_o + DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:EnergyPerCharge,Qualifier:Uncertainty + FIELDNAM: energy delta minus + +energy_o_plus: + <<: *energy_default + CATDESC: Energy Table Plus value + DEPEND_1: energy_o + DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:EnergyPerCharge,Qualifier:Uncertainty + FIELDNAM: energy delta plus + +energy_uh_minus: + <<: *energy_default + CATDESC: Energy Table Minus value + DEPEND_1: energy_uh + DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:EnergyPerCharge,Qualifier:Uncertainty + FIELDNAM: energy delta minus + +energy_uh_plus: + <<: *energy_default + CATDESC: Energy Table Plus value + DEPEND_1: energy_uh + DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:EnergyPerCharge,Qualifier:Uncertainty + FIELDNAM: energy delta plus + +# Uncertainty attrs: +unc_c: + CATDESC: Uncertainties for c (Root 2 spacing) + COORDINATE_SYSTEM: instrument frame + DEPEND_0: epoch + DEPEND_1: energy_c + DISPLAY_TYPE: time_series + FIELDNAM: Uncertainties for c + FILLVAL: *real_fillval + FORMAT: F32.1 + LABL_PTR_1: energy_c_label + SCALETYP: log + SI_CONVERSION: ' > ' + UNITS: '# / cm2 s sr MeV/nuc' + VALIDMAX: 4096.0 + VALIDMIN: 0.0 + VAR_TYPE: support_data + +unc_fe: + CATDESC: Uncertainties for fe (Root 2 spacing) + COORDINATE_SYSTEM: instrument frame + DEPEND_0: epoch + DEPEND_1: energy_fe + DISPLAY_TYPE: time_series + FIELDNAM: Uncertainties for fe + FILLVAL: *real_fillval + FORMAT: F32.1 + LABL_PTR_1: energy_fe_label + SCALETYP: log + SI_CONVERSION: ' > ' + UNITS: '# / cm2 s sr MeV/nuc' + VALIDMAX: 4096.0 + VALIDMIN: 0.0 + VAR_TYPE: support_data + +unc_h: + CATDESC: Uncertainties for h (Root 2 spacing) + COORDINATE_SYSTEM: instrument frame + DEPEND_0: epoch + DEPEND_1: energy_h + DISPLAY_TYPE: time_series + FIELDNAM: Uncertainties for h + FILLVAL: *real_fillval + FORMAT: F32.1 + LABL_PTR_1: energy_h_label + SCALETYP: log + SI_CONVERSION: ' > ' + UNITS: '# / cm2 s sr MeV/nuc' + VALIDMAX: 4096.0 + VALIDMIN: 0.0 + VAR_TYPE: support_data + +unc_he3: + CATDESC: Uncertainties for he3 (Root 2 spacing) + COORDINATE_SYSTEM: instrument frame + DEPEND_0: epoch + DEPEND_1: energy_he3 + DISPLAY_TYPE: time_series + FIELDNAM: Uncertainties for he3 + FILLVAL: *real_fillval + FORMAT: F32.1 + LABL_PTR_1: energy_he3_label + SCALETYP: log + SI_CONVERSION: ' > ' + UNITS: '# / cm2 s sr MeV/nuc' + VALIDMAX: 4096.0 + VALIDMIN: 0.0 + VAR_TYPE: support_data + +unc_he4: + CATDESC: Uncertainties for he4 (Root 2 spacing) + COORDINATE_SYSTEM: instrument frame + DEPEND_0: epoch + DEPEND_1: energy_he4 + DISPLAY_TYPE: time_series + FIELDNAM: Uncertainties for he4 + FILLVAL: *real_fillval + FORMAT: F32.1 + LABL_PTR_1: energy_he4_label + SCALETYP: log + SI_CONVERSION: ' > ' + UNITS: '# / cm2 s sr MeV/nuc' + VALIDMAX: 4096.0 + VALIDMIN: 0.0 + VAR_TYPE: support_data + +unc_junk: + CATDESC: Uncertainties for junk (Root 2 spacing) + COORDINATE_SYSTEM: instrument frame + DEPEND_0: epoch + DEPEND_1: energy_junk + DISPLAY_TYPE: time_series + FIELDNAM: Uncertainties for junk + FILLVAL: *real_fillval + FORMAT: F32.1 + LABL_PTR_1: energy_junk_label + SCALETYP: log + SI_CONVERSION: ' > ' + UNITS: '# / cm2 s sr MeV/nuc' + VALIDMAX: 4096.0 + VALIDMIN: 0.0 + VAR_TYPE: support_data + +unc_ne_mg_si: + CATDESC: Uncertainties for ne-mg-si (Root 2 spacing) + COORDINATE_SYSTEM: instrument frame + DEPEND_0: epoch + DEPEND_1: energy_ne_mg_si + DISPLAY_TYPE: time_series + FIELDNAM: Uncertainties for ne-mg-si + FILLVAL: *real_fillval + FORMAT: F32.1 + LABL_PTR_1: energy_ne_mg_si_label + SCALETYP: log + SI_CONVERSION: ' > ' + UNITS: '# / cm2 s sr MeV/nuc' + VALIDMAX: 4096.0 + VALIDMIN: 0.0 + VAR_TYPE: support_data + +unc_o: + CATDESC: Uncertainties for o (Root 2 spacing) + COORDINATE_SYSTEM: instrument frame + DEPEND_0: epoch + DEPEND_1: energy_o + DISPLAY_TYPE: time_series + FIELDNAM: Uncertainties for o + FILLVAL: *real_fillval + FORMAT: F32.1 + LABL_PTR_1: energy_o_label + SCALETYP: log + SI_CONVERSION: ' > ' + UNITS: '# / cm2 s sr MeV/nuc' + VALIDMAX: 4096.0 + VALIDMIN: 0.0 + VAR_TYPE: support_data + +unc_uh: + CATDESC: Uncertainties for uh (Root 2 spacing) + COORDINATE_SYSTEM: instrument frame + DEPEND_0: epoch + DEPEND_1: energy_uh + DISPLAY_TYPE: time_series + FIELDNAM: Uncertainties for uh + FILLVAL: *real_fillval + FORMAT: F32.1 + LABL_PTR_1: energy_uh_label + SCALETYP: log + SI_CONVERSION: ' > ' + UNITS: '# / cm2 s sr MeV/nuc' + VALIDMAX: 4096.0 + VALIDMIN: 0.0 + VAR_TYPE: support_data +c: + CATDESC: c (Root 2 spacing) + DEPEND_0: epoch + DEPEND_1: energy_c + DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:NumberFlux,Qualifier:Differential + DISPLAY_TYPE: time_series + FIELDNAM: Diff. Intensity - c + FILLVAL: *real_fillval + FORMAT: F32.1 + LABL_PTR_1: energy_c_label + SCALETYP: log + UNITS: '# / cm2 s sr MeV/nuc' + VALIDMAX: 16777216.0 + VALIDMIN: 0.0 + VAR_TYPE: data + +fe: + CATDESC: fe (Root 2 spacing) + DEPEND_0: epoch + DEPEND_1: energy_fe + DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:NumberFlux,Qualifier:Differential + DISPLAY_TYPE: time_series + FIELDNAM: Diff. Intensity - fe + FILLVAL: *real_fillval + FORMAT: F32.1 + LABL_PTR_1: energy_fe_label + SCALETYP: log + UNITS: '# / cm2 s sr MeV/nuc' + VALIDMAX: 16777216.0 + VALIDMIN: 0.0 + VAR_TYPE: data + +h: + CATDESC: h (Root 2 spacing) + DEPEND_0: epoch + DEPEND_1: energy_h + DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:NumberFlux,Qualifier:Differential + DISPLAY_TYPE: time_series + FIELDNAM: Diff. Intensity - h + FILLVAL: *real_fillval + FORMAT: F32.1 + LABL_PTR_1: energy_h_label + SCALETYP: log + UNITS: '# / cm2 s sr MeV/nuc' + VALIDMAX: 16777216.0 + VALIDMIN: 0.0 + VAR_TYPE: data + +he3: + CATDESC: he3 (Root 2 spacing) + DEPEND_0: epoch + DEPEND_1: energy_he3 + DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:NumberFlux,Qualifier:Differential + DISPLAY_TYPE: time_series + FIELDNAM: Diff. Intensity - he3 + FILLVAL: *real_fillval + FORMAT: F32.1 + LABL_PTR_1: energy_he3_label + SCALETYP: log + UNITS: '# / cm2 s sr MeV/nuc' + VALIDMAX: 16777216.0 + VALIDMIN: 0.0 + VAR_TYPE: data + +he4: + CATDESC: he4 (Root 2 spacing) + DEPEND_0: epoch + DEPEND_1: energy_he4 + DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:NumberFlux,Qualifier:Differential + DISPLAY_TYPE: time_series + FIELDNAM: Diff. Intensity - he4 + FILLVAL: *real_fillval + FORMAT: F32.1 + LABL_PTR_1: energy_he4_label + SCALETYP: log + UNITS: '# / cm2 s sr MeV/nuc' + VALIDMAX: 16777216.0 + VALIDMIN: 0.0 + VAR_TYPE: data + +junk: + CATDESC: junk (Root 2 spacing) + DEPEND_0: epoch + DEPEND_1: energy_junk + DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:NumberFlux,Qualifier:Differential + DISPLAY_TYPE: time_series + FIELDNAM: Diff. Intensity - junk + FILLVAL: *real_fillval + FORMAT: F32.1 + LABL_PTR_1: energy_junk_label + SCALETYP: log + UNITS: '# / cm2 s sr MeV/nuc' + VALIDMAX: 16777216.0 + VALIDMIN: 0.0 + VAR_TYPE: data + +ne_mg_si: + CATDESC: ne-mg-si (Root 2 spacing) + DEPEND_0: epoch + DEPEND_1: energy_ne_mg_si + DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:NumberFlux,Qualifier:Differential + DISPLAY_TYPE: time_series + FIELDNAM: Diff. Intensity - ne-mg-si + FILLVAL: *real_fillval + FORMAT: F32.1 + LABL_PTR_1: energy_ne_mg_si_label + SCALETYP: log + UNITS: '# / cm2 s sr MeV/nuc' + VALIDMAX: 16777216.0 + VALIDMIN: 0.0 + VAR_TYPE: data + +o: + CATDESC: o (Root 2 spacing) + DEPEND_0: epoch + DEPEND_1: energy_o + DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:NumberFlux,Qualifier:Differential + DISPLAY_TYPE: time_series + FIELDNAM: Diff. Intensity - o + FILLVAL: *real_fillval + FORMAT: F32.1 + LABL_PTR_1: energy_o_label + SCALETYP: log + UNITS: '# / cm2 s sr MeV/nuc' + VALIDMAX: 16777216.0 + VALIDMIN: 0.0 + VAR_TYPE: data + +uh: + CATDESC: uh (Root 2 spacing) + DEPEND_0: epoch + DEPEND_1: energy_uh + DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:NumberFlux,Qualifier:Differential + DISPLAY_TYPE: time_series + FIELDNAM: Diff. Intensity - uh + FILLVAL: *real_fillval + FORMAT: F32.1 + LABL_PTR_1: energy_uh_label + SCALETYP: log + UNITS: '# / cm2 s sr MeV/nuc' + VALIDMAX: 16777216.0 + VALIDMIN: 0.0 + VAR_TYPE: data diff --git a/imap_processing/cdf/config/imap_codice_l2-hi-sectored_variable_attrs.yaml b/imap_processing/cdf/config/imap_codice_l2-hi-sectored_variable_attrs.yaml new file mode 100644 index 0000000000..e583851b78 --- /dev/null +++ b/imap_processing/cdf/config/imap_codice_l2-hi-sectored_variable_attrs.yaml @@ -0,0 +1,423 @@ +# ----------------------------- Useful variables ----------------------------- +uint8_fillval: &uint8_fillval 255 +real_fillval: &real_fillval -1.0e+31 + +min_int: &min_int -9223372036854775808 +max_int: &max_int 9223372036854775807 + +# --------------------------- Default attributes ----------------------------- +energy_attrs: &energy_default + CATDESC: Geometric mean energy per nucleon + DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:EnergyPerCharge,Qualifier:Characteristic + FIELDNAM: Energy Table + FILLVAL: *real_fillval + FORMAT: F32.1 + LABLAXIS: Energy + SCALETYP: linear + UNITS: MeV/nuc + VALIDMAX: 200.0 + VALIDMIN: 0.0 + VAR_TYPE: support_data + +# ------------------------------- Coordinates ------------------------------- +epoch_delta_minus: + CATDESC: Time from acquisition start to acquisition center + DICT_KEY: SPASE>Support>SupportQuantity:Temporal,Qualifier:Uncertainty + FIELDNAM: epoch delta minus + FILLVAL: *min_int + FORMAT: I19 + LABLAXIS: Epoch Delta Minus + SCALETYP: linear + UNITS: ns + VALIDMAX: *max_int + VALIDMIN: *min_int + VAR_TYPE: support_data + +epoch_delta_plus: + CATDESC: Time from acquisition center to acquisition end + DICT_KEY: SPASE>Support>SupportQuantity:Temporal,Qualifier:Uncertainty + FIELDNAM: epoch delta plus + FILLVAL: *min_int + FORMAT: I19 + LABLAXIS: Epoch Delta Plus + SCALETYP: linear + UNITS: ns + VALIDMAX: *max_int + VALIDMIN: *min_int + VAR_TYPE: support_data + +elevation_angle: + CATDESC: Elevation Angle + FIELDNAM: Elevation Angle + FILLVAL: *real_fillval + FORMAT: F32.1 + LABLAXIS: Elevation Angle + SCALETYP: linear + UNITS: degrees + VALIDMAX: 180.0 + VALIDMIN: 0.0 + VAR_TYPE: support_data + +spin_sector: + CATDESC: Spin Sector Index + FIELDNAM: Spin Sector Index + FILLVAL: *uint8_fillval + FORMAT: I3 + LABLAXIS: " " + SCALETYP: linear + UNITS: " " + VALIDMAX: 12 + VALIDMIN: 0 + VAR_TYPE: support_data + +energy_cno: + <<: *energy_default + DELTA_MINUS_VAR: energy_cno_minus + DELTA_PLUS_VAR: energy_cno_plus + +energy_fe: + <<: *energy_default + DELTA_MINUS_VAR: energy_fe_minus + DELTA_PLUS_VAR: energy_fe_plus + +energy_h: + <<: *energy_default + DELTA_MINUS_VAR: energy_h_minus + DELTA_PLUS_VAR: energy_h_plus + +energy_he3he4: + <<: *energy_default + DELTA_MINUS_VAR: energy_he3he4_minus + DELTA_PLUS_VAR: energy_he3he4_plus + +# ------------------------------- Label vars -------------------------------- +event_num_label: + CATDESC: Event Number + FIELDNAM: Event Number + FORMAT: A5 + VAR_TYPE: metadata + +epoch_delta_minus_label: + CATDESC: Time from acquisition start to acquisition center + FIELDNAM: Epoch delta minus + FORMAT: A18 + VAR_TYPE: metadata + +epoch_delta_plus_label: + CATDESC: Time from acquisition center to acquisition end + FIELDNAM: Epoch delta plus + FORMAT: A18 + VAR_TYPE: metadata + +elevation_angle_label: + CATDESC: Elevation Angle + FIELDNAM: Elevation Angle + FORMAT: A6 + VAR_TYPE: metadata + +spin_sector_label: + CATDESC: Spin Sector + DEPEND_1: spin_sector + FIELDNAM: Spin Sector + FORMAT: A2 + VAR_TYPE: metadata + +# ------------------------------- Labels ------------------------------------ +energy_cno_label: + CATDESC: Energy CNO + FIELDNAM: Energy CNO + FORMAT: A6 + VAR_TYPE: metadata + +energy_fe_label: + CATDESC: Energy Fe + FIELDNAM: Energy Fe + FORMAT: A6 + VAR_TYPE: metadata + +energy_h_label: + CATDESC: Energy H + FIELDNAM: Energy H + FORMAT: A6 + VAR_TYPE: metadata + +energy_he3he4_label: + CATDESC: Energy He3He4 + FIELDNAM: Energy He3He4 + FORMAT: A6 + VAR_TYPE: metadata + +# --------------------------- Dataset variable attrs ------------------------ +data_quality: + CATDESC: Indicates whether data quality is suspect (1). + DEPEND_0: epoch + DICT_KEY: SPASE>Support>SupportQuantity:DataQuality + DISPLAY_TYPE: time_series + FIELDNAM: Data Quality + FILLVAL: *uint8_fillval + FORMAT: '%d' + LABLAXIS: Data Quality + SCALETYP: linear + UNITS: ' ' + VALIDMAX: 1 + VALIDMIN: 0 + VAR_TYPE: data + VAR_TYPE: support_data + +species_dim_attrs: &species_dim_attrs + DEPEND_0: epoch + DEPEND_1: energy_{species} + DEPEND_2: spin_sector + DEPEND_3: elevation_angle + LABL_PTR_1: energy_{species}_label + LABL_PTR_2: spin_sector_label + LABL_PTR_3: elevation_angle_label + +# species: +cno: + <<: *species_dim_attrs + CATDESC: cno (x2 spacing) + DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:NumberFlux,Qualifier:Differential + DISPLAY_TYPE: spectrogram + FIELDNAM: cno + FILLVAL: *real_fillval + FORMAT: E14.7 + SCALETYP: log + UNITS: '# / cm2 s sr MeV/nuc' + VALIDMAX: 16777216.0 + VALIDMIN: 0.0 + VAR_TYPE: data + +fe: + <<: *species_dim_attrs + CATDESC: fe (x2 spacing) + DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:NumberFlux,Qualifier:Differential + DISPLAY_TYPE: spectrogram + FIELDNAM: fe + FILLVAL: *real_fillval + FORMAT: F32.1 + SCALETYP: log + UNITS: '# / cm2 s sr MeV/nuc' + VALIDMAX: 16777216.0 + VALIDMIN: 0.0 + VAR_TYPE: data + +h: + <<: *species_dim_attrs + CATDESC: h (x2 spacing) + DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:NumberFlux,Qualifier:Differential + DISPLAY_TYPE: spectrogram + FIELDNAM: h + FILLVAL: *real_fillval + FORMAT: F32.1 + SCALETYP: log + UNITS: '# / cm2 s sr MeV/nuc' + VALIDMAX: 16777216.0 + VALIDMIN: 0.0 + VAR_TYPE: data + +he3he4: + <<: *species_dim_attrs + CATDESC: he3he4 (x2 spacing) + DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:NumberFlux,Qualifier:Differential + DISPLAY_TYPE: spectrogram + FIELDNAM: he3he4 + FILLVAL: *real_fillval + FORMAT: F32.1 + SCALETYP: log + UNITS: '# / cm2 s sr MeV/nuc' + VALIDMAX: 16777216.0 + VALIDMIN: 0.0 + VAR_TYPE: data + +# uncertainties: +unc_cno: + <<: *species_dim_attrs + CATDESC: Uncertainties for cno (x2 spacing) + COORDINATE_SYSTEM: instrument frame + DISPLAY_TYPE: spectrogram + FIELDNAM: Uncertainties for cno + FILLVAL: *real_fillval + FORMAT: F32.1 + SCALETYP: log + SI_CONVERSION: ' > ' + UNITS: '# / cm2 s sr MeV/nuc' + VALIDMAX: 4096.0 + VALIDMIN: 0.0 + VAR_TYPE: data + +unc_fe: + <<: *species_dim_attrs + CATDESC: Uncertainties for fe (x2 spacing) + COORDINATE_SYSTEM: instrument frame + DISPLAY_TYPE: spectrogram + FIELDNAM: Uncertainties for fe + FILLVAL: *real_fillval + FORMAT: F32.1 + SCALETYP: log + SI_CONVERSION: ' > ' + UNITS: '# / cm2 s sr MeV/nuc' + VALIDMAX: 4096.0 + VALIDMIN: 0.0 + VAR_TYPE: data + +unc_h: + <<: *species_dim_attrs + CATDESC: Uncertainties for h (x2 spacing) + COORDINATE_SYSTEM: instrument frame + DEPEND_0: epoch + DISPLAY_TYPE: spectrogram + FIELDNAM: Uncertainties for h + FILLVAL: *real_fillval + FORMAT: F32.1 + SCALETYP: log + SI_CONVERSION: ' > ' + UNITS: '# / cm2 s sr MeV/nuc' + VALIDMAX: 4096.0 + VALIDMIN: 0.0 + VAR_TYPE: data + +unc_he3he4: + <<: *species_dim_attrs + CATDESC: Uncertainties for he3he4 (x2 spacing) + COORDINATE_SYSTEM: instrument frame + DISPLAY_TYPE: spectrogram + FIELDNAM: Uncertainties for he3he4 + FILLVAL: *real_fillval + FORMAT: F32.1 + SCALETYP: log + SI_CONVERSION: ' > ' + UNITS: '# / cm2 s sr MeV/nuc' + VALIDMAX: 4096.0 + VALIDMIN: 0.0 + VAR_TYPE: data + +# energy deltas: +energy_cno_minus: + CATDESC: Energy Table Minus value + DEPEND_1: energy_cno + DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:EnergyPerCharge,Qualifier:Uncertainty + FIELDNAM: energy delta minus + FILLVAL: *real_fillval + FORMAT: F32.1 + LABLAXIS: Energy + SCALETYP: log + UNITS: MeV/nuc + VALIDMAX: 200.0 + VALIDMIN: 0.0 + VAR_TYPE: support_data + +energy_cno_plus: + CATDESC: Energy Table Plus value + DEPEND_1: energy_cno + DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:EnergyPerCharge,Qualifier:Uncertainty + FIELDNAM: energy delta plus + FILLVAL: *real_fillval + FORMAT: F32.1 + LABLAXIS: Energy + SCALETYP: log + UNITS: MeV/nuc + VALIDMAX: 200.0 + VALIDMIN: 0.0 + VAR_TYPE: support_data + +energy_fe_minus: + CATDESC: Energy Table Minus value + DEPEND_1: energy_fe + DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:EnergyPerCharge,Qualifier:Uncertainty + FIELDNAM: energy delta minus + FILLVAL: *real_fillval + FORMAT: F32.1 + LABLAXIS: Energy + SCALETYP: log + UNITS: MeV/nuc + VALIDMAX: 200.0 + VALIDMIN: 0.0 + VAR_TYPE: support_data + +energy_fe_plus: + CATDESC: Energy Table Plus value + DEPEND_1: energy_fe + DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:EnergyPerCharge,Qualifier:Uncertainty + FIELDNAM: energy delta plus + FILLVAL: *real_fillval + FORMAT: F32.1 + LABLAXIS: Energy + SCALETYP: log + UNITS: MeV/nuc + VALIDMAX: 200.0 + VALIDMIN: 0.0 + VAR_TYPE: support_data + +energy_h_minus: + CATDESC: Energy Table Minus value + DEPEND_1: energy_h + DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:EnergyPerCharge,Qualifier:Uncertainty + FIELDNAM: energy delta minus + FILLVAL: *real_fillval + FORMAT: F32.1 + LABLAXIS: Energy + SCALETYP: log + UNITS: MeV/nuc + VALIDMAX: 200.0 + VALIDMIN: 0.0 + VAR_TYPE: support_data + +energy_h_plus: + CATDESC: Energy Table Plus value + DEPEND_1: energy_h + DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:EnergyPerCharge,Qualifier:Uncertainty + FIELDNAM: energy delta plus + FILLVAL: *real_fillval + FORMAT: F32.1 + LABLAXIS: Energy + SCALETYP: log + UNITS: MeV/nuc + VALIDMAX: 200.0 + VALIDMIN: 0.0 + VAR_TYPE: support_data + +energy_he3he4_minus: + CATDESC: Energy Table Minus value + DEPEND_1: energy_he3he4 + DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:EnergyPerCharge,Qualifier:Uncertainty + FIELDNAM: energy delta minus + FILLVAL: *real_fillval + FORMAT: F32.1 + LABLAXIS: Energy + SCALETYP: log + UNITS: MeV/nuc + VALIDMAX: 200.0 + VALIDMIN: 0.0 + VAR_TYPE: support_data + +energy_he3he4_plus: + CATDESC: Energy Table Plus value + DEPEND_1: energy_he3he4 + DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:EnergyPerCharge,Qualifier:Uncertainty + FIELDNAM: energy delta plus + FILLVAL: *real_fillval + FORMAT: F32.1 + LABLAXIS: Energy + SCALETYP: log + UNITS: MeV/nuc + VALIDMAX: 200.0 + VALIDMIN: 0.0 + VAR_TYPE: support_data + +# spin angles: +spin_angle: + CATDESC: Spin Angle + DEPEND_1: spin_sector + DEPEND_2: elevation_angle + DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:ArrivalDirection,Qualifier:DirectionAngle.AzimuthAngle + FIELDNAM: Spin Angle + FILLVAL: *real_fillval + FORMAT: F32.1 + LABL_PTR_1: spin_sector_label + LABL_PTR_2: elevation_angle_label + SCALETYP: log + UNITS: degrees + VALIDMAX: 360.0 + VALIDMIN: 0.0 + VAR_TYPE: support_data diff --git a/imap_processing/cdf/config/imap_codice_l2-lo-angular_variable_attrs.yaml b/imap_processing/cdf/config/imap_codice_l2-lo-angular_variable_attrs.yaml new file mode 100644 index 0000000000..2443e5672f --- /dev/null +++ b/imap_processing/cdf/config/imap_codice_l2-lo-angular_variable_attrs.yaml @@ -0,0 +1,89 @@ +# ----------------------------- Useful variables ----------------------------- +real_fillval: &real_fillval -1.0e+31 +max_float: &max_float 3.4028235e+38 + +# ------------------------------- Coordinates ------------------------------- +elevation_angle: + CATDESC: Elevation Angle + FIELDNAM: Elevation Angle + FORMAT: I8 + LABLAXIS: Elevation Angle + SCALETYP: linear + UNITS: degrees + VALIDMAX: 180.0 + VALIDMIN: 0.0 + VAR_TYPE: support_data + +spin_sector: + CATDESC: Spin Sector Index + FIELDNAM: Spin Sector Index + FILLVAL: -1 + FORMAT: I2 + LABLAXIS: " " + SCALETYP: linear + UNITS: " " + VALIDMAX: 24 + VALIDMIN: 0 + VAR_TYPE: support_data + +# spin angle: +spin_angle: + CATDESC: Spin Angle + DEPEND_1: spin_sector + DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:ArrivalDirection,Qualifier:DirectionAngle.AzimuthAngle + FIELDNAM: Spin Angle + FILLVAL: *real_fillval + FORMAT: '%f' + LABL_PTR_1: spin_sector_label + SCALETYP: linear + UNITS: degrees + VALIDMAX: 360.0 + VALIDMIN: 0.0 + VAR_TYPE: support_data + +# ------------------------------- labels ------------------------------- +elevation_angle_label: + CATDESC: Elevation Angle + FIELDNAM: Elevation Angle + FORMAT: A6 + VAR_TYPE: metadata + +# ------------------------------- species ------------------------------- +# lo-angular attribute templates (combined versions of the previous entries) +lo-angular-attrs: + CATDESC: "{species} {direction} species" + DEPEND_0: epoch + DEPEND_1: esa_step + DEPEND_2: spin_sector + DEPEND_3: elevation_angle + DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:NumberFlux,Qualifier:Differential + DISPLAY_TYPE: time_series + FIELDNAM: "{direction} - {species}" + FILLVAL: *real_fillval + FORMAT: F13.4 + LABL_PTR_1: esa_step_label + LABL_PTR_2: spin_sector_label + LABL_PTR_3: elevation_angle_label + UNITS: "#/(cm^2-s-sr-keV/q)" + VALIDMAX: 16777216.0 + VALIDMIN: 0.0 + VAR_TYPE: data + +lo-angular-unc-attrs: + CATDESC: "{species} {direction} species uncertainty" + DEPEND_0: epoch + DEPEND_1: esa_step + DEPEND_2: spin_sector + DEPEND_3: elevation_angle + DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:NumberFlux,Qualifier:Uncertainty + DISPLAY_TYPE: time_series + FIELDNAM: "{direction} - {species}" + FILLVAL: *real_fillval + FORMAT: F13.4 + LABL_PTR_1: esa_step_label + LABL_PTR_2: spin_sector_label + LABL_PTR_3: elevation_angle_label + UNITS: "#/(cm^2-s-sr-keV/q)" + VALIDMAX: 16777216.0 + VALIDMIN: 0.0 + VAR_TYPE: data diff --git a/imap_processing/cdf/config/imap_codice_l2-lo-direct-events_variable_attrs.yaml b/imap_processing/cdf/config/imap_codice_l2-lo-direct-events_variable_attrs.yaml new file mode 100644 index 0000000000..35ffbdf766 --- /dev/null +++ b/imap_processing/cdf/config/imap_codice_l2-lo-direct-events_variable_attrs.yaml @@ -0,0 +1,339 @@ +# ----------------------------- Useful variables ----------------------------- +uint8_fillval: &uint8_fillval 255 +uint16_fillval: &uint16_fillval 65535 +real_fillval: &real_fillval -1.0e+31 +min_int: &min_int -9223372036854775808 +max_int: &max_int 9223372036854775807 +# ------------------------------- Coordinates ------------------------------- +priority: + CATDESC: Priority Level + DICT_KEY: SPASE>Support>SupportQuantity:Other + FIELDNAM: Priority Level + FILLVAL: *uint8_fillval + FORMAT: I1 + LABLAXIS: Priority + SCALETYP: linear + UNITS: " " + VALIDMAX: 7 + VALIDMIN: 0 + VAR_TYPE: support_data + +event_num: + CATDESC: Event Number + DICT_KEY: SPASE>Support>SupportQuantity:Other + FIELDNAM: Event Number + FILLVAL: *uint16_fillval + FORMAT: I5 + LABLAXIS: Event Number + SCALETYP: linear + UNITS: " " + VALIDMAX: 10000 + VALIDMIN: 0 + VAR_TYPE: support_data + +epoch_delta_minus: + CATDESC: Time from acquisition start to acquisition center + DEPEND_0: epoch + DICT_KEY: SPASE>Support>SupportQuantity:Temporal,Qualifier:Uncertainty + FIELDNAM: epoch delta minus + FILLVAL: -9223372036854775808 + FORMAT: I18 + LABLAXIS: Epoch Delta Minus + SCALETYP: linear + UNITS: ns + VALIDMAX: *max_int + VALIDMIN: *min_int + VAR_TYPE: support_data + +epoch_delta_plus: + CATDESC: Time from acquisition center to acquisition end + DEPEND_0: epoch + DICT_KEY: SPASE>Support>SupportQuantity:Temporal,Qualifier:Uncertainty + FIELDNAM: epoch delta plus + FILLVAL: -9223372036854775808 + FORMAT: I18 + LABLAXIS: Epoch Delta Plus + SCALETYP: linear + UNITS: ns + VALIDMAX: *max_int + VALIDMIN: *min_int + VAR_TYPE: support_data + +# ------------------------------- Data Variables ------------------------------- +num_events: + CATDESC: Number of Events per Priority + DEPEND_0: epoch + DEPEND_1: priority + DICT_KEY: SPASE>Support>SupportQuantity:Other + FIELDNAM: Number of Events + FILLVAL: *uint16_fillval + FORMAT: I5 + LABLAXIS: Number of Events + LABL_PTR_1: priority_label + SCALETYP: linear + UNITS: " " + VALIDMAX: 10000 + VALIDMIN: 0 + VAR_TYPE: data + +data_quality: + CATDESC: Data Quality Flag per Priority + DEPEND_0: epoch + DEPEND_1: priority + DICT_KEY: SPASE>Support>SupportQuantity:DataQuality + FIELDNAM: Data Quality + FILLVAL: *uint8_fillval + FORMAT: I3 + LABL_PTR_1: priority_label + SCALETYP: linear + UNITS: " " + VALIDMAX: 255 + VALIDMIN: 0 + VAR_TYPE: data + +energy_step: + CATDESC: Energy Step Index + DEPEND_0: epoch + DEPEND_1: priority + DEPEND_2: event_num + DICT_KEY: SPASE>Support>SupportQuantity:Other + FIELDNAM: Energy Step + FILLVAL: *uint8_fillval + FORMAT: I3 + LABLAXIS: Energy Step + LABL_PTR_1: priority_label + LABL_PTR_2: event_num_label + SCALETYP: linear + UNITS: " " + VALIDMAX: 127 + VALIDMIN: 0 + VAR_TYPE: data + +energy_per_charge: + CATDESC: Energy per Charge + DEPEND_0: epoch + DEPEND_1: priority + DEPEND_2: event_num + DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:EnergyPerCharge + FIELDNAM: Energy per Charge + FILLVAL: *real_fillval + FORMAT: F12.4 + LABLAXIS: Energy per Charge + LABL_PTR_1: priority_label + LABL_PTR_2: event_num_label + SCALETYP: linear + UNITS: keV/q + VALIDMAX: 200.0 + VALIDMIN: 0.0 + VAR_TYPE: data + +apd_energy: + CATDESC: APD Energy + DEPEND_0: epoch + DEPEND_1: priority + DEPEND_2: event_num + DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:Energy + FIELDNAM: APD Energy + FILLVAL: *real_fillval + FORMAT: F12.4 + LABLAXIS: APD Energy + LABL_PTR_1: priority_label + LABL_PTR_2: event_num_label + SCALETYP: linear + UNITS: keV + VALIDMAX: 512.0 + VALIDMIN: 0.0 + VAR_TYPE: data + +gain: + CATDESC: Gain Setting + DEPEND_0: epoch + DEPEND_1: priority + DEPEND_2: event_num + DICT_KEY: SPASE>Support>SupportQuantity:Other + FIELDNAM: Gain + FILLVAL: *uint8_fillval + FORMAT: I1 + LABLAXIS: Gain + LABL_PTR_1: priority_label + LABL_PTR_2: event_num_label + SCALETYP: linear + UNITS: " " + VALIDMAX: 1 + VALIDMIN: 0 + VAR_TYPE: data + +apd_id: + CATDESC: APD Identifier + DEPEND_0: epoch + DEPEND_1: priority + DEPEND_2: event_num + DICT_KEY: SPASE>Support>SupportQuantity:Other + FIELDNAM: APD ID + FILLVAL: *uint8_fillval + FORMAT: I2 + LABLAXIS: APD ID + LABL_PTR_1: priority_label + LABL_PTR_2: event_num_label + SCALETYP: linear + UNITS: " " + VALIDMAX: 31 + VALIDMIN: 0 + VAR_TYPE: data + +position: + CATDESC: Position Index + DEPEND_0: epoch + DEPEND_1: priority + DEPEND_2: event_num + DICT_KEY: SPASE>Support>SupportQuantity:Other + FIELDNAM: Position + FILLVAL: *uint8_fillval + FORMAT: I2 + LABLAXIS: Position + LABL_PTR_1: priority_label + LABL_PTR_2: event_num_label + SCALETYP: linear + UNITS: " " + VALIDMAX: 31 + VALIDMIN: 0 + VAR_TYPE: data + +multi_flag: + CATDESC: Multiple Event Flag + DEPEND_0: epoch + DEPEND_1: priority + DEPEND_2: event_num + DICT_KEY: SPASE>Support>SupportQuantity:DataQuality + FIELDNAM: Multi Flag + FILLVAL: *uint8_fillval + FORMAT: I1 + LABLAXIS: Multi Flag + LABL_PTR_1: priority_label + LABL_PTR_2: event_num_label + SCALETYP: linear + UNITS: " " + VALIDMAX: 1 + VALIDMIN: 0 + VAR_TYPE: data + +type: + CATDESC: Event Type + DEPEND_0: epoch + DEPEND_1: priority + DEPEND_2: event_num + DICT_KEY: SPASE>Support>SupportQuantity:Other + FIELDNAM: Type + FILLVAL: *uint8_fillval + FORMAT: I1 + LABLAXIS: Type + LABL_PTR_1: priority_label + LABL_PTR_2: event_num_label + SCALETYP: linear + UNITS: " " + VALIDMAX: 4 + VALIDMIN: 0 + VAR_TYPE: data + +tof: + CATDESC: Time of Flight + DEPEND_0: epoch + DEPEND_1: priority + DEPEND_2: event_num + DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:TimeOfFlight + FIELDNAM: Time of Flight + FILLVAL: *real_fillval + FORMAT: F12.4 + LABLAXIS: TOF + LABL_PTR_1: priority_label + LABL_PTR_2: event_num_label + SCALETYP: linear + UNITS: ns + VALIDMAX: 1024.0 + VALIDMIN: 0.0 + VAR_TYPE: data + +spin_sector: + CATDESC: Spin Sector Index + DEPEND_0: epoch + DEPEND_1: priority + DEPEND_2: event_num + DICT_KEY: SPASE>Support>SupportQuantity:Positional + FIELDNAM: Spin Sector Index + FILLVAL: *uint8_fillval + FORMAT: I2 + LABLAXIS: Spin Sector + LABL_PTR_1: priority_label + LABL_PTR_2: event_num_label + SCALETYP: linear + UNITS: " " + VALIDMAX: 23 + VALIDMIN: 0 + VAR_TYPE: support_data + +spin_angle: + CATDESC: Spin Angle + DEPEND_0: epoch + DEPEND_1: priority + DEPEND_2: event_num + DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:ArrivalDirection,Qualifier:DirectionAngle.AzimuthAngle + FIELDNAM: Spin Angle + FILLVAL: *real_fillval + FORMAT: F8.2 + LABL_PTR_1: priority_label + LABL_PTR_2: event_num_label + SCALETYP: linear + UNITS: degrees + VALIDMAX: 360.0 + VALIDMIN: 0.0 + VAR_TYPE: data + +elevation_angle: + CATDESC: Elevation Angle + DEPEND_0: epoch + DEPEND_1: priority + DEPEND_2: event_num + DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:ArrivalDirection,Qualifier:DirectionAngle.ElevationAngle + FIELDNAM: Elevation Angle + FILLVAL: *real_fillval + FORMAT: F8.2 + LABLAXIS: Elevation Angle + LABL_PTR_1: priority_label + LABL_PTR_2: event_num_label + SCALETYP: linear + UNITS: degrees + VALIDMAX: 180.0 + VALIDMIN: 0.0 + VAR_TYPE: data + +esa_step: + CATDESC: Energy per charge (E/q) sweeping step + DEPEND_0: epoch + DEPEND_1: priority + DEPEND_2: event_num + DICT_KEY: SPASE>Support>SupportQuantity:Other + FIELDNAM: Energy Index + FILLVAL: *uint8_fillval + FORMAT: I3 + LABLAXIS: Energy Index + LABL_PTR_1: priority_label + LABL_PTR_2: event_num_label + SCALETYP: linear + UNITS: " " + VALIDMAX: 127 + VALIDMIN: 0 + VAR_TYPE: data + +# ------------------------------- labels ------------------------------- + +event_num_label: + CATDESC: Event Number Label + FIELDNAM: Event Number + FORMAT: A5 + VAR_TYPE: metadata + +priority_label: + CATDESC: Priority Level Label + FIELDNAM: Priority Level + FORMAT: A1 + VAR_TYPE: metadata diff --git a/imap_processing/cdf/config/imap_codice_l2-lo-species_variable_attrs.yaml b/imap_processing/cdf/config/imap_codice_l2-lo-species_variable_attrs.yaml new file mode 100644 index 0000000000..5ea64a121b --- /dev/null +++ b/imap_processing/cdf/config/imap_codice_l2-lo-species_variable_attrs.yaml @@ -0,0 +1,147 @@ +# ----------------------------- Useful variables ----------------------------- +uint8_fillval: &uint8_fillval 255 +real_fillval: &real_fillval -1.0e+31 +max_float: &max_float 3.4028235e+38 +species_valid_max: &species_valid_max 1e20 + +# ------------------------------- Coordinates ------------------------------- +elevation_angle: + CATDESC: Elevation Angle + FIELDNAM: Elevation Angle + FILLVAL: *real_fillval + FORMAT: F32.1 + LABLAXIS: Elevation Angle + SCALETYP: linear + UNITS: degrees + VALIDMAX: 180.0 + VALIDMIN: 0.0 + VAR_TYPE: support_data + +spin_sector: + CATDESC: Spin Sector Index + FIELDNAM: Spin Sector Index + FILLVAL: *uint8_fillval + FORMAT: I3 + LABLAXIS: " " + SCALETYP: linear + UNITS: " " + VALIDMAX: 12 + VALIDMIN: 0 + VAR_TYPE: support_data + +# ------------------------------- labels ------------------------------- +elevation_angle_label: + CATDESC: Elevation Angle + FIELDNAM: Elevation Angle + FORMAT: A6 + VAR_TYPE: metadata + +# ------------------------------- species ------------------------------- +# lo species attrs +lo-species-attrs: + CATDESC: "{species} Non-sunward Species" + DEPEND_0: epoch + DEPEND_1: esa_step + DEPEND_2: spin_sector + DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:NumberFlux,Qualifier:Differential + DISPLAY_TYPE: spectrogram + FIELDNAM: "Non-sunward - {species}" + FILLVAL: *real_fillval + FORMAT: F32.1 + LABL_PTR_1: esa_step_label + LABL_PTR_2: spin_sector_label + SCALETYP: log + UNITS: "#/(cm^2-s-sr-keV/q)" + VALIDMAX: *species_valid_max + VALIDMIN: 0.0 + VAR_TYPE: data + +lo-pui-species-attrs: + CATDESC: "{species} Pickup Ion Sunward Species" + DEPEND_0: epoch + DEPEND_1: esa_step + DEPEND_2: spin_sector + DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:NumberFlux,Qualifier:Differential + DISPLAY_TYPE: spectrogram + FIELDNAM: "Sunward - {species}" + FILLVAL: *real_fillval + FORMAT: F32.1 + LABL_PTR_1: esa_step_label + LABL_PTR_2: spin_sector_label + SCALETYP: log + UNITS: "#/(cm^2-s-sr-keV/q)" + VALIDMAX: *species_valid_max + VALIDMIN: 0.0 + VAR_TYPE: data + +lo-sw-species-attrs: + CATDESC: "{species} Solar Wind Sunward Species" + DEPEND_0: epoch + DEPEND_1: esa_step + DEPEND_2: spin_sector + DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:NumberFlux,Qualifier:Differential + DISPLAY_TYPE: spectrogram + FIELDNAM: "Sunward - {species}" + FILLVAL: *real_fillval + FORMAT: F32.1 + LABL_PTR_1: esa_step_label + LABL_PTR_2: spin_sector_label + SCALETYP: log + UNITS: "#/(cm^2-s-sr-keV/q)" + VALIDMAX: *species_valid_max + VALIDMIN: 0.0 + VAR_TYPE: data + +lo-species-unc-attrs: + CATDESC: "{species} Non-sunward Species uncertainty" + DEPEND_0: epoch + DEPEND_1: esa_step + DEPEND_2: spin_sector + DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:NumberFlux,Qualifier:Uncertainty + DISPLAY_TYPE: spectrogram + FIELDNAM: "Non-sunward - {species}" + FILLVAL: *real_fillval + FORMAT: F32.1 + LABL_PTR_1: esa_step_label + LABL_PTR_2: spin_sector_label + SCALETYP: log + UNITS: "#/(cm^2-s-sr-keV/q)" + VALIDMAX: *species_valid_max + VALIDMIN: 0.0 + VAR_TYPE: data + +lo-pui-species-unc-attrs: + CATDESC: "{species} Pickup Ion Sunward Species uncertainty" + DEPEND_0: epoch + DEPEND_1: esa_step + DEPEND_2: spin_sector + DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:NumberFlux,Qualifier:Uncertainty + DISPLAY_TYPE: spectrogram + FIELDNAM: "Sunward - {species}" + FILLVAL: *real_fillval + FORMAT: F32.1 + LABL_PTR_1: esa_step_label + LABL_PTR_2: spin_sector_label + SCALETYP: log + UNITS: "#/(cm^2-s-sr-keV/q)" + VALIDMAX: *species_valid_max + VALIDMIN: 0.0 + VAR_TYPE: data + +lo-sw-species-unc-attrs: + CATDESC: "{species} Solar Wind Sunward Species uncertainty" + DEPEND_0: epoch + DEPEND_1: esa_step + DEPEND_2: spin_sector + DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:NumberFlux,Qualifier:Uncertainty + DISPLAY_TYPE: spectrogram + FIELDNAM: "Sunward - {species}" + FILLVAL: *real_fillval + FORMAT: F32.1 + LABL_PTR_1: esa_step_label + LABL_PTR_2: spin_sector_label + SCALETYP: log + UNITS: "#/(cm^2-s-sr-keV/q)" + VALIDMAX: *species_valid_max + VALIDMIN: 0.0 + VAR_TYPE: data diff --git a/imap_processing/cdf/config/imap_codice_l2_variable_attrs.yaml b/imap_processing/cdf/config/imap_codice_l2_variable_attrs.yaml deleted file mode 100644 index 4ef6bd9eba..0000000000 --- a/imap_processing/cdf/config/imap_codice_l2_variable_attrs.yaml +++ /dev/null @@ -1,1869 +0,0 @@ -# <=== Useful Variables ===> -int_fillval: &int_fillval -9223372036854775808 -uint8_fillval: &uint8_fillval 255 -uint16_fillval: &uint16_fillval 65535 -uint32_fillval: &uint32_fillval 4294967295 -real_fillval: &real_fillval -1.0e+31 - -min_int: &min_int -9223372036854775808 -min_epoch: &min_epoch -315575942816000000 - -max_int: &max_int 9223372036854775807 -max_uint8: &max_uint8 255 -max_uint16: &max_uint16 65535 -max_uint24: &max_uint24 8388607 -max_uint32: &max_uint32 4294967295 -max_epoch: &max_epoch 3155630469184000000 - -# TODO: Complete SPASE. 'Other' used temporarily. -# TODO: Update FORMAT to use fortran format -# TODO: Review VALIDMIN with CoDICE (VALIDMIN: 0.05000000074505806 ??) -# TODO: Update direct events attributes - products have new var names - - -# <=== Defaults ===> -default_attrs: &default - VAR_TYPE: data - DEPEND_0: epoch - DISPLAY_TYPE: no_plot - FIELDNAM: " " - FILLVAL: *int_fillval - FORMAT: I12 - SCALETYP: linear - UNITS: ' ' - VALIDMIN: *min_int - VALIDMAX: *max_int - DICT_KEY: SPASE>Support>SupportQuantity:Other - -direct_events_attrs: &direct_events_default - <<: *default - DISPLAY_TYPE: time_series - FILLVAL: *uint8_fillval - FORMAT: I5 - VALIDMIN: 0 - VALIDMAX: 10000 - -lo_ialirt_attrs: &lo_ialirt_default - <<: *default - DISPLAY_TYPE: time_series - FILLVAL: *real_fillval - FORMAT: '%lf' - LABLAXIS: ratio - UNITS: ' ' - VALIDMAX: 1.0e+31 - VALIDMIN: 0.0 - -lo_species_attrs: &lo_species_default - <<: *default - DEPEND_1: energy_table - DEPEND_2: spin_sector_index - LABL_PTR_1: energy_table_label - LABL_PTR_2: spin_sector_index_label - DISPLAY_TYPE: spectrogram - FORMAT: '%f' - SCALETYP: log - UNITS: particles / cm2 s sr keV/q - FILLVAL: *real_fillval - VALIDMAX: 10000000000.0 - VALIDMIN: 1.000000013351432e-10 - DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:NumberFlux,Qualifier:Differential - -lo_angular_attrs: &lo_angular_default - <<: *default - DEPEND_1: energy_table - DEPEND_2: elevation_angle - DEPEND_3: spin_angle - LABL_PTR_1: energy_table_label - LABL_PTR_2: elevation_angle_label - LABL_PTR_3: spin_angle_label - DISPLAY_TYPE: spectrogram - FORMAT: '%f' - SCALETYP: log - UNITS: particles / cm2 s sr keV/q - FILLVAL: *real_fillval - VALIDMAX: 10000000000.0 - VALIDMIN: 1.000000013351432e-10 - DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:NumberFlux,Qualifier:Differential - -hi_omni_attrs: &hi_omni_default - <<: *default - DISPLAY_TYPE: spectrogram - FORMAT: '%f' - LABLAXIS: Diff. Intensity - SCALETYP: linear - UNITS: '# / cm2 s sr MeV/nuc' - FILLVAL: *real_fillval - VALIDMAX: 16777216.0 - VALIDMIN: 0.0 - DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:NumberFlux,Qualifier:Differential - -hi_sectored_attrs: &hi_sectored_attrs_default - <<: *default - DISPLAY_TYPE: spectrogram - DEPEND_2: elevation_angle - DEPEND_3: spin_sector_index - LABL_PTR_2: elevation_angle_label - LABL_PTR_3: spin_sector_index_label - FILLVAL: *uint32_fillval - FORMAT: '%f' - UNITS: '# / cm2 s sr MeV/nuc' - VALIDMAX: 16777216 - VALIDMIN: 0 - DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:NumberFlux,Qualifier:Differential - -energy_attrs: &energy_default - VAR_TYPE: support_data - CATDESC: Geometric mean energy per nucleon - FIELDNAM: Energy Table - LABLAXIS: Energy - SCALETYP: log - UNITS: MeV/nuc - FORMAT: '%f' - FILLVAL: *real_fillval - VALIDMAX: 200.0 - VALIDMIN: 0.05000000074505806 - DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:EnergyPerCharge,Qualifier:Characteristic - -energy_delta_attrs: &energy_delta_default - <<: *energy_default - DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:EnergyPerCharge,Qualifier:Uncertainty - -spin_angles_attrs: &spin_angles_default - VAR_TYPE: support_data - CATDESC: Spin Angle - FIELDNAM: Spin Angle - SCALETYP: linear - UNITS: degrees - FILLVAL: *real_fillval - VALIDMAX: 360.0 - VALIDMIN: 0.0 - FORMAT: '%f' - DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:ArrivalDirection,Qualifer:DirectionAngle.AzimuthAngle - -spin_sector_index_attrs: &spin_sector_index_default - VAR_TYPE: support_data - DISPLAY_TYPE: no_plot - CATDESC: Spin Sector Index - FIELDNAM: Spin Sector Index - FORMAT: '%d' - LABLAXIS: Spin Sector Index - SCALETYP: linear - UNITS: ' ' - FILLVAL: *uint8_fillval - VALIDMAX: 1 - VALIDMIN: 0 - DICT_KEY: SPASE>Support>SupportQuantity:Other - - -# <=== Coordinates ===> -event_num: - CATDESC: Event Number - FIELDNAM: Event Number - FILLVAL: *uint16_fillval - FORMAT: I5 - LABLAXIS: Event Number - SCALETYP: linear - UNITS: ' ' - VALIDMIN: 0 - VALIDMAX: 10000 - VAR_TYPE: support_data - DICT_KEY: SPASE>Support>SupportQuantity:Other - -epoch_delta_minus: - CATDESC: Time from acquisition start to acquisition center - FIELDNAM: epoch delta minus - FILLVAL: *int_fillval - FORMAT: I18 - LABLAXIS: Epoch Delta Minus - SCALETYP: linear - UNITS: ns - VALIDMIN: *min_int - VALIDMAX: *max_int - VAR_TYPE: support_data - DICT_KEY: SPASE>Support>SupportQuantity:Temporal,Qualifier:Uncertainty - -epoch_delta_plus: - CATDESC: Time from acquisition center to acquisition end - FIELDNAM: epoch delta plus - FILLVAL: *int_fillval - FORMAT: I18 - LABLAXIS: Epoch Delta Plus - SCALETYP: linear - UNITS: ns - VALIDMIN: *min_int - VALIDMAX: *max_int - VAR_TYPE: support_data - DICT_KEY: SPASE>Support>SupportQuantity:Temporal,Qualifier:Uncertainty - -elevation_angle: - CATDESC: Elevation Angle - FIELDNAM: Elevation Angle - FORMAT: '%f' - LABLAXIS: Elevation Angle - SCALETYP: linear - UNITS: degrees - VALIDMAX: 180.0 - VALIDMIN: 0.0 - VAR_TYPE: support_data - -spin_angle: - <<: *spin_angles_default - LABLAXIS: Spin Angle - -energy_table: - CATDESC: Energy Table - FIELDNAM: Energy Table - FORMAT: '%f' - LABLAXIS: Energy per charge - SCALETYP: log - UNITS: keV/e - VALIDMAX: 82.0 - VALIDMIN: 0.5 - VAR_TYPE: support_data - -energy_cno: - <<: *energy_default - DELTA_MINUS_VAR: energy_cno_minus - DELTA_PLUS_VAR: energy_cno_plus - -energy_fe: - <<: *energy_default - DELTA_MINUS_VAR: energy_fe_minus - DELTA_PLUS_VAR: energy_fe_plus - -energy_h: - <<: *energy_default - DELTA_MINUS_VAR: energy_h_minus - DELTA_PLUS_VAR: energy_h_plus - -energy_he3he4: - <<: *energy_default - DELTA_MINUS_VAR: energy_he3he4_minus - DELTA_PLUS_VAR: energy_he3he4_plus - -energy_c: - <<: *energy_default - DELTA_MINUS_VAR: energy_c_minus - DELTA_PLUS_VAR: energy_c_plus - -energy_he3: - <<: *energy_default - DELTA_MINUS_VAR: energy_he3_minus - DELTA_PLUS_VAR: energy_he3_plus - -energy_he4: - <<: *energy_default - DELTA_MINUS_VAR: energy_he4_minus - DELTA_PLUS_VAR: energy_he4_plus - -energy_junk: - <<: *energy_default - DELTA_MINUS_VAR: energy_junk_minus - DELTA_PLUS_VAR: energy_junk_plus - -energy_ne_mg_si: - <<: *energy_default - DELTA_MINUS_VAR: energy_ne_mg_si_minus - DELTA_PLUS_VAR: energy_ne_mg_si_plus - -energy_o: - <<: *energy_default - DELTA_MINUS_VAR: energy_o_minus - DELTA_PLUS_VAR: energy_o_plus - -energy_uh: - <<: *energy_default - DELTA_MINUS_VAR: energy_uh_minus - DELTA_PLUS_VAR: energy_uh_plus - -hi-sectored-spin_sector_index: - <<: *spin_sector_index_default - VALIDMAX: 12 - -hi-ialirt-spin_sector_index: - <<: *spin_sector_index_default - VALIDMAX: 4 - -lo-nsw-species-spin_sector_index: - <<: *spin_sector_index_default - -lo-sw-species-spin_sector_index: - <<: *spin_sector_index_default - - -# <=== Labels ===> -#TODO: double check FORMAT for labels -event_num_label: - CATDESC: Event Number - FIELDNAM: Event Number - FORMAT: A5 - VAR_TYPE: metadata - -epoch_delta_minus_label: - CATDESC: Time from acquisition start to acquisition center - FIELDNAM: Epoch delta minus - FORMAT: A18 - VAR_TYPE: metadata - -epoch_delta_plus_label: - CATDESC: Time from acquisition center to acquisition end - FIELDNAM: Epoch delta plus - FORMAT: A18 - VAR_TYPE: metadata - -elevation_angle_label: - CATDESC: Elevation Angle - FIELDNAM: Elevation Angle - FORMAT: A6 - VAR_TYPE: metadata - -spin_angle_label: - CATDESC: Spin Angle - FIELDNAM: Spin Angle - FORMAT: A6 - VAR_TYPE: metadata - -energy_table_label: - CATDESC: Energy Table - FIELDNAM: Energy Table - FORMAT: A4 - VAR_TYPE: metadata - -energy_cno_label: - CATDESC: Energy CNO - FIELDNAM: Energy CNO - FORMAT: A6 - VAR_TYPE: metadata - -energy_fe_label: - CATDESC: Energy Fe - FIELDNAM: Energy Fe - FORMAT: A6 - VAR_TYPE: metadata - -energy_h_label: - CATDESC: Energy H - FIELDNAM: Energy H - FORMAT: A6 - VAR_TYPE: metadata - -energy_he3he4_label: - CATDESC: Energy He3He4 - FIELDNAM: Energy He3He4 - FORMAT: A6 - VAR_TYPE: metadata - -energy_c_label: - CATDESC: Energy C - FIELDNAM: Energy C - FORMAT: A6 - VAR_TYPE: metadata - -energy_he3_label: - CATDESC: Energy He3 - FIELDNAM: Energy He3 - FORMAT: A6 - VAR_TYPE: metadata - -energy_he4_label: - CATDESC: Energy He4 - FIELDNAM: Energy He4 - FORMAT: A6 - VAR_TYPE: metadata - -energy_junk_label: - CATDESC: Energy Junk - FIELDNAM: Energy Junk - FORMAT: A6 - VAR_TYPE: metadata - -energy_ne_mg_si_label: - CATDESC: Energy NeMgSi - FIELDNAM: Energy NeMgSi - FORMAT: A6 - VAR_TYPE: metadata - -energy_o_label: - CATDESC: Energy O - FIELDNAM: Energy O - FORMAT: A6 - VAR_TYPE: metadata - -energy_uh_label: - CATDESC: Energy UH - FIELDNAM: Energy UH - FORMAT: A6 - VAR_TYPE: metadata - -hi-sectored-spin_sector_index_label: - CATDESC: Spin Sector Index for Hi-Sectored - FIELDNAM: Spin Sector Index for Hi-Sectored - FORMAT: A2 - VAR_TYPE: metadata - -hi-ialirt-spin_sector_index_label: - CATDESC: Spin Sector Index for Hi I-ALiRT - FIELDNAM: Spin Sector Index for Hi I-ALiRT - FORMAT: A1 - VAR_TYPE: metadata - -lo-nsw-species-spin_sector_index_label: - CATDESC: Spin Sector Index for Lo NSW-Species - FIELDNAM: Spin Sector Index for Lo NSW-Species - FORMAT: A1 - VAR_TYPE: metadata - -lo-sw-species-spin_sector_index_label: - CATDESC: Spin Sector Index for Lo SW-Species - FIELDNAM: Spin Sector Index for Lo SW-Species - FORMAT: A1 - VAR_TYPE: metadata - - -# <=== Dataset Variable Attributes ===> - -# The following are set in multiple data products -data_quality: - <<: *default - VAR_TYPE: data - CATDESC: Indicates whether data quality is suspect (1). - DISPLAY_TYPE: time_series - FIELDNAM: Data Quality - FILLVAL: *uint8_fillval - FORMAT: '%d' - LABLAXIS: Data Quality - SCALETYP: linear - UNITS: ' ' - VALIDMAX: 1 - VALIDMIN: 0 - DICT_KEY: SPASE>Support>SupportQuantity:DataQuality - -# The following are data product-specific -# Direct Events Attributes - -# TODO: update var names to be lowercase and underscores. -P0_APD_ID: - <<: *direct_events_default - CATDESC: Priority 0 APD ID - DEPEND_1: event_num - FIELDNAM: Priority 0 APD ID - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -P0_APDEnergy: - <<: *direct_events_default - CATDESC: Priority 0 APD Energy - DEPEND_1: event_num - FIELDNAM: Priority 0 APD Energy - FILLVAL: *uint16_fillval - LABL_PTR_1: event_num_label - VALIDMAX: 512 - -P0_APDGain: - <<: *direct_events_default - CATDESC: Priority 0 APD Gain - DEPEND_1: event_num - FIELDNAM: Priority 0 APD Gain - LABL_PTR_1: event_num_label - VALIDMAX: 1 - -P0_DataQuality: - <<: *direct_events_default - CATDESC: Priority 0 Data Quality - FIELDNAM: Priority 0 Data Quality - LABLAXIS: " " - VALIDMAX: 1 - DICT_KEY: SPASE>Support>SupportQuantity:DataQuality - -P0_EnergyStep: - <<: *direct_events_default - CATDESC: Priority 0 Energy Step - DEPEND_1: event_num - FIELDNAM: Priority 0 Energy Step - LABL_PTR_1: event_num_label - VALIDMAX: 128 - -P0_ERGE: - <<: *direct_events_default - CATDESC: Priority 0 Energy Range - DEPEND_1: event_num - FIELDNAM: Priority 0 Energy Range - LABL_PTR_1: event_num_label - VALIDMAX: 4 - -P0_MultiFlag: - <<: *direct_events_default - CATDESC: Priority 0 Multi Flag - DEPEND_1: event_num - FIELDNAM: Priority 0 Multi Flag - LABL_PTR_1: event_num_label - VALIDMAX: 1 - -P0_NumEvents: - <<: *direct_events_default - CATDESC: Priority 0 Number of Events - FIELDNAM: Priority 0 Number of Events - FILLVAL: *uint16_fillval - LABLAXIS: " " - -P0_PHAType: - <<: *direct_events_default - CATDESC: Priority 0 PHA Type - DEPEND_1: event_num - FIELDNAM: Priority 0 PHA Type - LABL_PTR_1: event_num_label - VALIDMAX: 4 - -P0_Position: - <<: *direct_events_default - CATDESC: Priority 0 Position - DEPEND_1: event_num - FIELDNAM: Priority 0 Position - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -P0_SpinAngle: - <<: *direct_events_default - CATDESC: Priority 0 Spin Angle - DEPEND_1: event_num - FIELDNAM: Priority 0 Spin Angle - LABL_PTR_1: event_num_label - VALIDMAX: 128 - -P0_SpinNumber: - <<: *direct_events_default - CATDESC: Priority 0 Spin Number - DEPEND_1: event_num - FIELDNAM: Priority 0 Spin Number - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -P0_SSD_ID: - <<: *direct_events_default - CATDESC: Priority 0 SSD ID or Azimuth Angle - DEPEND_1: event_num - FIELDNAM: Priority 0 SSD ID or Azimuth Angle - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -P0_SSDEnergy: - <<: *direct_events_default - CATDESC: Priority 0 APD Energy - DEPEND_1: event_num - FIELDNAM: Priority 0 APD Energy - LABL_PTR_1: event_num_label - VALIDMAX: 2048 - -P0_TOF: - <<: *direct_events_default - CATDESC: Priority 0 Time of Flight - DEPEND_1: event_num - FIELDNAM: Priority 0 Time of Flight - FILLVAL: *uint16_fillval - LABL_PTR_1: event_num_label - VALIDMAX: 1024 - -P0_Type: - <<: *direct_events_default - CATDESC: Priority 0 Type - DEPEND_1: event_num - FIELDNAM: Priority 0 Type - LABL_PTR_1: event_num_label - VALIDMAX: 3 - -P1_APD_ID: - <<: *direct_events_default - CATDESC: Priority 1 APD ID - DEPEND_1: event_num - FIELDNAM: Priority 1 APD ID - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -P1_APDEnergy: - <<: *direct_events_default - CATDESC: Priority 1 APD Energy - DEPEND_1: event_num - FIELDNAM: Priority 1 APD Energy - FILLVAL: *uint16_fillval - LABL_PTR_1: event_num_label - VALIDMAX: 512 - -P1_APDGain: - <<: *direct_events_default - CATDESC: Priority 1 APD Gain - DEPEND_1: event_num - FIELDNAM: Priority 1 APD Gain - LABL_PTR_1: event_num_label - VALIDMAX: 1 - -P1_DataQuality: - <<: *direct_events_default - CATDESC: Priority 1 Data Quality - FIELDNAM: Priority 1 Data Quality - LABLAXIS: " " - VALIDMAX: 1 - DICT_KEY: SPASE>Support>SupportQuantity:DataQuality - -P1_EnergyStep: - <<: *direct_events_default - CATDESC: Priority 1 Energy Step - DEPEND_1: event_num - FIELDNAM: Priority 1 Energy Step - LABL_PTR_1: event_num_label - VALIDMAX: 128 - -P1_ERGE: - <<: *direct_events_default - CATDESC: Priority 1 Energy Range - DEPEND_1: event_num - FIELDNAM: Priority 1 Energy Range - LABL_PTR_1: event_num_label - VALIDMAX: 4 - -P1_MultiFlag: - <<: *direct_events_default - CATDESC: Priority 1 Multi Flag - DEPEND_1: event_num - FIELDNAM: Priority 1 Multi Flag - LABL_PTR_1: event_num_label - VALIDMAX: 1 - -P1_NumEvents: - <<: *direct_events_default - CATDESC: Priority 1 Number of Events - FIELDNAM: Priority 1 Number of Events - FILLVAL: *uint16_fillval - LABLAXIS: " " - -P1_PHAType: - <<: *direct_events_default - CATDESC: Priority 1 PHA Type - DEPEND_1: event_num - FIELDNAM: Priority 1 PHA Type - LABL_PTR_1: event_num_label - VALIDMAX: 4 - -P1_Position: - <<: *direct_events_default - CATDESC: Priority 1 Position - DEPEND_1: event_num - FIELDNAM: Priority 1 Position - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -P1_SpinAngle: - <<: *direct_events_default - CATDESC: Priority 1 Spin Angle - DEPEND_1: event_num - FIELDNAM: Priority 1 Spin Angle - LABL_PTR_1: event_num_label - VALIDMAX: 128 - -P1_SpinNumber: - <<: *direct_events_default - CATDESC: Priority 1 Spin Number - DEPEND_1: event_num - FIELDNAM: Priority 1 Spin Number - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -P1_SSD_ID: - <<: *direct_events_default - CATDESC: Priority 1 SSD ID or Azimuth Angle - DEPEND_1: event_num - FIELDNAM: Priority 1 SSD ID or Azimuth Angle - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -P1_SSDEnergy: - <<: *direct_events_default - CATDESC: Priority 1 APD Energy - DEPEND_1: event_num - FIELDNAM: Priority 1 APD Energy - LABL_PTR_1: event_num_label - VALIDMAX: 2048 - -P1_TOF: - <<: *direct_events_default - CATDESC: Priority 1 Time of Flight - DEPEND_1: event_num - FIELDNAM: Priority 1 Time of Flight - FILLVAL: *uint16_fillval - LABL_PTR_1: event_num_label - VALIDMAX: 1024 - -P1_Type: - <<: *direct_events_default - CATDESC: Priority 1 Type - DEPEND_1: event_num - FIELDNAM: Priority 1 Type - LABL_PTR_1: event_num_label - VALIDMAX: 3 - -P2_APD_ID: - <<: *direct_events_default - CATDESC: Priority 2 APD ID - DEPEND_1: event_num - FIELDNAM: Priority 2 APD ID - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -P2_APDEnergy: - <<: *direct_events_default - CATDESC: Priority 2 APD Energy - DEPEND_1: event_num - FIELDNAM: Priority 2 APD Energy - FILLVAL: *uint16_fillval - LABL_PTR_1: event_num_label - VALIDMAX: 512 - -P2_APDGain: - <<: *direct_events_default - CATDESC: Priority 2 APD Gain - DEPEND_1: event_num - FIELDNAM: Priority 2 APD Gain - LABL_PTR_1: event_num_label - VALIDMAX: 1 - -P2_DataQuality: - <<: *direct_events_default - CATDESC: Priority 2 Data Quality - FIELDNAM: Priority 2 Data Quality - LABLAXIS: " " - VALIDMAX: 1 - DICT_KEY: SPASE>Support>SupportQuantity:DataQuality - -P2_EnergyStep: - <<: *direct_events_default - CATDESC: Priority 2 Energy Step - DEPEND_1: event_num - FIELDNAM: Priority 2 Energy Step - LABL_PTR_1: event_num_label - VALIDMAX: 128 - -P2_ERGE: - <<: *direct_events_default - CATDESC: Priority 2 Energy Range - DEPEND_1: event_num - FIELDNAM: Priority 2 Energy Range - LABL_PTR_1: event_num_label - VALIDMAX: 4 - -P2_MultiFlag: - <<: *direct_events_default - CATDESC: Priority 2 Multi Flag - DEPEND_1: event_num - FIELDNAM: Priority 2 Multi Flag - LABL_PTR_1: event_num_label - VALIDMAX: 1 - -P2_NumEvents: - <<: *direct_events_default - CATDESC: Priority 2 Number of Events - FIELDNAM: Priority 2 Number of Events - FILLVAL: *uint16_fillval - LABLAXIS: " " - -P2_PHAType: - <<: *direct_events_default - CATDESC: Priority 2 PHA Type - DEPEND_1: event_num - FIELDNAM: Priority 2 PHA Type - LABL_PTR_1: event_num_label - VALIDMAX: 4 - -P2_Position: - <<: *direct_events_default - CATDESC: Priority 2 Position - DEPEND_1: event_num - FIELDNAM: Priority 2 Position - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -P2_SpinAngle: - <<: *direct_events_default - CATDESC: Priority 2 Spin Angle - DEPEND_1: event_num - FIELDNAM: Priority 2 Spin Angle - LABL_PTR_1: event_num_label - VALIDMAX: 128 - -P2_SpinNumber: - <<: *direct_events_default - CATDESC: Priority 2 Spin Number - DEPEND_1: event_num - FIELDNAM: Priority 2 Spin Number - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -P2_SSD_ID: - <<: *direct_events_default - CATDESC: Priority 2 SSD ID or Azimuth Angle - DEPEND_1: event_num - FIELDNAM: Priority 2 SSD ID or Azimuth Angle - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -P2_SSDEnergy: - <<: *direct_events_default - CATDESC: Priority 2 APD Energy - DEPEND_1: event_num - FIELDNAM: Priority 2 APD Energy - LABL_PTR_1: event_num_label - VALIDMAX: 2048 - -P2_TOF: - <<: *direct_events_default - CATDESC: Priority 2 Time of Flight - DEPEND_1: event_num - FIELDNAM: Priority 2 Time of Flight - FILLVAL: *uint16_fillval - LABL_PTR_1: event_num_label - VALIDMAX: 1024 - -P2_Type: - <<: *direct_events_default - CATDESC: Priority 2 Type - DEPEND_1: event_num - FIELDNAM: Priority 2 Type - LABL_PTR_1: event_num_label - VALIDMAX: 3 - -P3_APD_ID: - <<: *direct_events_default - CATDESC: Priority 3 APD ID - DEPEND_1: event_num - FIELDNAM: Priority 3 APD ID - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -P3_APDEnergy: - <<: *direct_events_default - CATDESC: Priority 3 APD Energy - DEPEND_1: event_num - FIELDNAM: Priority 3 APD Energy - FILLVAL: *uint16_fillval - LABL_PTR_1: event_num_label - VALIDMAX: 512 - -P3_APDGain: - <<: *direct_events_default - CATDESC: Priority 3 APD Gain - DEPEND_1: event_num - FIELDNAM: Priority 3 APD Gain - LABL_PTR_1: event_num_label - VALIDMAX: 1 - -P3_DataQuality: - <<: *direct_events_default - CATDESC: Priority 3 Data Quality - FIELDNAM: Priority 3 Data Quality - LABLAXIS: " " - VALIDMAX: 1 - DICT_KEY: SPASE>Support>SupportQuantity:DataQuality - -P3_EnergyStep: - <<: *direct_events_default - CATDESC: Priority 3 Energy Step - DEPEND_1: event_num - FIELDNAM: Priority 3 Energy Step - LABL_PTR_1: event_num_label - VALIDMAX: 128 - -P3_ERGE: - <<: *direct_events_default - CATDESC: Priority 3 Energy Range - DEPEND_1: event_num - FIELDNAM: Priority 3 Energy Range - LABL_PTR_1: event_num_label - VALIDMAX: 4 - -P3_MultiFlag: - <<: *direct_events_default - CATDESC: Priority 3 Multi Flag - DEPEND_1: event_num - FIELDNAM: Priority 3 Multi Flag - LABL_PTR_1: event_num_label - VALIDMAX: 1 - -P3_NumEvents: - <<: *direct_events_default - CATDESC: Priority 3 Number of Events - FIELDNAM: Priority 3 Number of Events - FILLVAL: *uint16_fillval - LABLAXIS: " " - -P3_PHAType: - <<: *direct_events_default - CATDESC: Priority 3 PHA Type - DEPEND_1: event_num - FIELDNAM: Priority 3 PHA Type - LABL_PTR_1: event_num_label - VALIDMAX: 4 - -P3_Position: - <<: *direct_events_default - CATDESC: Priority 3 Position - DEPEND_1: event_num - FIELDNAM: Priority 3 Position - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -P3_SpinAngle: - <<: *direct_events_default - CATDESC: Priority 3 Spin Angle - DEPEND_1: event_num - FIELDNAM: Priority 3 Spin Angle - LABL_PTR_1: event_num_label - VALIDMAX: 128 - -P3_SpinNumber: - <<: *direct_events_default - CATDESC: Priority 3 Spin Number - DEPEND_1: event_num - FIELDNAM: Priority 3 Spin Number - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -P3_SSD_ID: - <<: *direct_events_default - CATDESC: Priority 3 SSD ID or Azimuth Angle - DEPEND_1: event_num - FIELDNAM: Priority 3 SSD ID or Azimuth Angle - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -P3_SSDEnergy: - <<: *direct_events_default - CATDESC: Priority 3 APD Energy - DEPEND_1: event_num - FIELDNAM: Priority 3 APD Energy - LABL_PTR_1: event_num_label - VALIDMAX: 2048 - -P3_TOF: - <<: *direct_events_default - CATDESC: Priority 3 Time of Flight - DEPEND_1: event_num - FIELDNAM: Priority 3 Time of Flight - FILLVAL: *uint16_fillval - LABL_PTR_1: event_num_label - VALIDMAX: 1024 - -P3_Type: - <<: *direct_events_default - CATDESC: Priority 3 Type - DEPEND_1: event_num - FIELDNAM: Priority 3 Type - LABL_PTR_1: event_num_label - VALIDMAX: 3 - -P4_APD_ID: - <<: *direct_events_default - CATDESC: Priority 4 APD ID - DEPEND_1: event_num - FIELDNAM: Priority 4 APD ID - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -P4_APDEnergy: - <<: *direct_events_default - CATDESC: Priority 4 APD Energy - DEPEND_1: event_num - FIELDNAM: Priority 4 APD Energy - FILLVAL: *uint16_fillval - LABL_PTR_1: event_num_label - VALIDMAX: 512 - -P4_APDGain: - <<: *direct_events_default - CATDESC: Priority 4 APD Gain - DEPEND_1: event_num - FIELDNAM: Priority 4 APD Gain - LABL_PTR_1: event_num_label - VALIDMAX: 1 - -P4_DataQuality: - <<: *direct_events_default - CATDESC: Priority 4 Data Quality - FIELDNAM: Priority 4 Data Quality - LABLAXIS: " " - VALIDMAX: 1 - DICT_KEY: SPASE>Support>SupportQuantity:DataQuality - -P4_EnergyStep: - <<: *direct_events_default - CATDESC: Priority 4 Energy Step - DEPEND_1: event_num - FIELDNAM: Priority 4 Energy Step - LABL_PTR_1: event_num_label - VALIDMAX: 128 - -P4_ERGE: - <<: *direct_events_default - CATDESC: Priority 4 Energy Range - DEPEND_1: event_num - FIELDNAM: Priority 4 Energy Range - LABL_PTR_1: event_num_label - VALIDMAX: 4 - -P4_MultiFlag: - <<: *direct_events_default - CATDESC: Priority 4 Multi Flag - DEPEND_1: event_num - FIELDNAM: Priority 4 Multi Flag - LABL_PTR_1: event_num_label - VALIDMAX: 1 - -P4_NumEvents: - <<: *direct_events_default - CATDESC: Priority 4 Number of Events - FIELDNAM: Priority 4 Number of Events - FILLVAL: *uint16_fillval - LABLAXIS: " " - -P4_PHAType: - <<: *direct_events_default - CATDESC: Priority 4 PHA Type - DEPEND_1: event_num - FIELDNAM: Priority 4 PHA Type - LABL_PTR_1: event_num_label - VALIDMAX: 4 - -P4_Position: - <<: *direct_events_default - CATDESC: Priority 4 Position - DEPEND_1: event_num - FIELDNAM: Priority 4 Position - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -P4_SpinAngle: - <<: *direct_events_default - CATDESC: Priority 4 Spin Angle - DEPEND_1: event_num - FIELDNAM: Priority 4 Spin Angle - LABL_PTR_1: event_num_label - VALIDMAX: 128 - -P4_SpinNumber: - <<: *direct_events_default - CATDESC: Priority 4 Spin Number - DEPEND_1: event_num - FIELDNAM: Priority 4 Spin Number - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -P4_SSD_ID: - <<: *direct_events_default - CATDESC: Priority 4 SSD ID or Azimuth Angle - DEPEND_1: event_num - FIELDNAM: Priority 4 SSD ID or Azimuth Angle - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -P4_SSDEnergy: - <<: *direct_events_default - CATDESC: Priority 4 APD Energy - DEPEND_1: event_num - FIELDNAM: Priority 4 APD Energy - LABL_PTR_1: event_num_label - VALIDMAX: 2048 - -P4_TOF: - <<: *direct_events_default - CATDESC: Priority 4 Time of Flight - DEPEND_1: event_num - FIELDNAM: Priority 4 Time of Flight - FILLVAL: *uint16_fillval - LABL_PTR_1: event_num_label - VALIDMAX: 1024 - -P4_Type: - <<: *direct_events_default - CATDESC: Priority 4 Type - DEPEND_1: event_num - FIELDNAM: Priority 4 Type - LABL_PTR_1: event_num_label - VALIDMAX: 3 - -P5_APD_ID: - <<: *direct_events_default - CATDESC: Priority 5 APD ID - DEPEND_1: event_num - FIELDNAM: Priority 5 APD ID - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -P5_APDEnergy: - <<: *direct_events_default - CATDESC: Priority 5 APD Energy - DEPEND_1: event_num - FIELDNAM: Priority 5 APD Energy - FILLVAL: *uint16_fillval - LABL_PTR_1: event_num_label - VALIDMAX: 512 - -P5_APDGain: - <<: *direct_events_default - CATDESC: Priority 5 APD Gain - DEPEND_1: event_num - FIELDNAM: Priority 5 APD Gain - LABL_PTR_1: event_num_label - VALIDMAX: 1 - -P5_DataQuality: - <<: *direct_events_default - CATDESC: Priority 5 Data Quality - FIELDNAM: Priority 5 Data Quality - LABLAXIS: " " - VALIDMAX: 1 - DICT_KEY: SPASE>Support>SupportQuantity:DataQuality - -P5_EnergyStep: - <<: *direct_events_default - CATDESC: Priority 5 Energy Step - DEPEND_1: event_num - FIELDNAM: Priority 5 Energy Step - LABL_PTR_1: event_num_label - VALIDMAX: 128 - -P5_ERGE: - <<: *direct_events_default - CATDESC: Priority 5 Energy Range - DEPEND_1: event_num - FIELDNAM: Priority 5 Energy Range - LABL_PTR_1: event_num_label - VALIDMAX: 4 - -P5_MultiFlag: - <<: *direct_events_default - CATDESC: Priority 5 Multi Flag - DEPEND_1: event_num - FIELDNAM: Priority 5 Multi Flag - LABL_PTR_1: event_num_label - VALIDMAX: 1 - -P5_NumEvents: - <<: *direct_events_default - CATDESC: Priority 5 Number of Events - FIELDNAM: Priority 5 Number of Events - FILLVAL: *uint16_fillval - LABLAXIS: " " - -P5_PHAType: - <<: *direct_events_default - CATDESC: Priority 5 PHA Type - DEPEND_1: event_num - FIELDNAM: Priority 5 PHA Type - LABL_PTR_1: event_num_label - VALIDMAX: 4 - -P5_Position: - <<: *direct_events_default - CATDESC: Priority 5 Position - DEPEND_1: event_num - FIELDNAM: Priority 5 Position - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -P5_SpinAngle: - <<: *direct_events_default - CATDESC: Priority 5 Spin Angle - DEPEND_1: event_num - FIELDNAM: Priority 5 Spin Angle - LABL_PTR_1: event_num_label - VALIDMAX: 128 - -P5_SpinNumber: - <<: *direct_events_default - CATDESC: Priority 5 Spin Number - DEPEND_1: event_num - FIELDNAM: Priority 5 Spin Number - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -P5_SSD_ID: - <<: *direct_events_default - CATDESC: Priority 5 SSD ID or Azimuth Angle - DEPEND_1: event_num - FIELDNAM: Priority 5 SSD ID or Azimuth Angle - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -P5_SSDEnergy: - <<: *direct_events_default - CATDESC: Priority 5 APD Energy - DEPEND_1: event_num - FIELDNAM: Priority 5 APD Energy - LABL_PTR_1: event_num_label - VALIDMAX: 2048 - -P5_TOF: - <<: *direct_events_default - CATDESC: Priority 5 Time of Flight - DEPEND_1: event_num - FIELDNAM: Priority 5 Time of Flight - FILLVAL: *uint16_fillval - LABL_PTR_1: event_num_label - VALIDMAX: 1024 - -P5_Type: - <<: *direct_events_default - CATDESC: Priority 5 Type - DEPEND_1: event_num - FIELDNAM: Priority 5 Type - LABL_PTR_1: event_num_label - VALIDMAX: 3 - -P6_APD_ID: - <<: *direct_events_default - CATDESC: Priority 6 APD ID - DEPEND_1: event_num - FIELDNAM: Priority 6 APD ID - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -P6_APDEnergy: - <<: *direct_events_default - CATDESC: Priority 6 APD Energy - DEPEND_1: event_num - FIELDNAM: Priority 6 APD Energy - FILLVAL: *uint16_fillval - LABL_PTR_1: event_num_label - VALIDMAX: 512 - -P6_APDGain: - <<: *direct_events_default - CATDESC: Priority 6 APD Gain - DEPEND_1: event_num - FIELDNAM: Priority 6 APD Gain - LABL_PTR_1: event_num_label - VALIDMAX: 1 - -P6_DataQuality: - <<: *direct_events_default - CATDESC: Priority 6 Data Quality - FIELDNAM: Priority 6 Data Quality - LABLAXIS: " " - VALIDMAX: 1 - DICT_KEY: SPASE>Support>SupportQuantity:DataQuality - -P6_EnergyStep: - <<: *direct_events_default - CATDESC: Priority 6 Energy Step - DEPEND_1: event_num - FIELDNAM: Priority 6 Energy Step - LABL_PTR_1: event_num_label - VALIDMAX: 128 - -P6_MultiFlag: - <<: *direct_events_default - CATDESC: Priority 6 Multi Flag - DEPEND_1: event_num - FIELDNAM: Priority 6 Multi Flag - LABL_PTR_1: event_num_label - VALIDMAX: 1 - -P6_NumEvents: - <<: *direct_events_default - CATDESC: Priority 6 Number of Events - FIELDNAM: Priority 6 Number of Events - FILLVAL: *uint16_fillval - LABLAXIS: " " - -P6_PHAType: - <<: *direct_events_default - CATDESC: Priority 6 PHA Type - DEPEND_1: event_num - FIELDNAM: Priority 6 PHA Type - LABL_PTR_1: event_num_label - VALIDMAX: 4 - -P6_Position: - <<: *direct_events_default - CATDESC: Priority 6 Position - DEPEND_1: event_num - FIELDNAM: Priority 6 Position - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -P6_SpinAngle: - <<: *direct_events_default - CATDESC: Priority 6 Spin Angle - DEPEND_1: event_num - FIELDNAM: Priority 6 Spin Angle - LABL_PTR_1: event_num_label - VALIDMAX: 128 - -P6_TOF: - <<: *direct_events_default - CATDESC: Priority 6 Time of Flight - DEPEND_1: event_num - FIELDNAM: Priority 6 Time of Flight - FILLVAL: *uint16_fillval - LABL_PTR_1: event_num_label - VALIDMAX: 1024 - -P7_APD_ID: - <<: *direct_events_default - CATDESC: Priority 7 APD ID - DEPEND_1: event_num - FIELDNAM: Priority 7 APD ID - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -P7_APDEnergy: - <<: *direct_events_default - CATDESC: Priority 7 APD Energy - DEPEND_1: event_num - FIELDNAM: Priority 7 APD Energy - FILLVAL: *uint16_fillval - LABL_PTR_1: event_num_label - VALIDMAX: 512 - -P7_APDGain: - <<: *direct_events_default - CATDESC: Priority 7 APD Gain - DEPEND_1: event_num - FIELDNAM: Priority 7 APD Gain - LABL_PTR_1: event_num_label - VALIDMAX: 1 - -P7_DataQuality: - <<: *direct_events_default - CATDESC: Priority 7 Data Quality - FIELDNAM: Priority 7 Data Quality - LABLAXIS: " " - VALIDMAX: 1 - DICT_KEY: SPASE>Support>SupportQuantity:DataQuality - -P7_EnergyStep: - <<: *direct_events_default - CATDESC: Priority 7 Energy Step - DEPEND_1: event_num - FIELDNAM: Priority 7 Energy Step - LABL_PTR_1: event_num_label - VALIDMAX: 128 - -P7_MultiFlag: - <<: *direct_events_default - CATDESC: Priority 7 Multi Flag - DEPEND_1: event_num - FIELDNAM: Priority 7 Multi Flag - LABL_PTR_1: event_num_label - VALIDMAX: 1 - -P7_NumEvents: - <<: *direct_events_default - CATDESC: Priority 7 Number of Events - FIELDNAM: Priority 7 Number of Events - FILLVAL: *uint16_fillval - LABLAXIS: " " - -P7_PHAType: - <<: *direct_events_default - CATDESC: Priority 7 PHA Type - DEPEND_1: event_num - FIELDNAM: Priority 7 PHA Type - LABL_PTR_1: event_num_label - VALIDMAX: 4 - -P7_Position: - <<: *direct_events_default - CATDESC: Priority 7 Position - DEPEND_1: event_num - FIELDNAM: Priority 7 Position - LABL_PTR_1: event_num_label - VALIDMAX: 32 - -P7_SpinAngle: - <<: *direct_events_default - CATDESC: Priority 7 Spin Angle - DEPEND_1: event_num - FIELDNAM: Priority 7 Spin Angle - LABL_PTR_1: event_num_label - VALIDMAX: 128 - -P7_TOF: - <<: *direct_events_default - CATDESC: Priority 7 Time of Flight - DEPEND_1: event_num - FIELDNAM: Priority 7 Time of Flight - FILLVAL: *uint16_fillval - LABL_PTR_1: event_num_label - VALIDMAX: 1024 - - -# lo-sw-species Attributes -lo-sw-species-cnoplus: - <<: *lo_species_default - CATDESC: Counts - Sunward - CNO+ Pick Up Ions (PUI) - FIELDNAM: Counts - SW - CNO+ (PUI) - -lo-sw-species-cplus4: - <<: *lo_species_default - CATDESC: Counts - Sunward - C+4 - FIELDNAM: Counts - SW - C+4 - -lo-sw-species-cplus5: - <<: *lo_species_default - CATDESC: Counts - Sunward - C+5 - FIELDNAM: Counts - SW - C+5 - -lo-sw-species-cplus6: - <<: *lo_species_default - CATDESC: Counts - Sunward - C+6 - FIELDNAM: Counts - SW - C+6 - -lo-sw-species-fe_hiq: - <<: *lo_species_default - CATDESC: Counts - Sunward - Fe highQ - FIELDNAM: Counts - SW - Fe highQ - -lo-sw-species-fe_loq: - <<: *lo_species_default - CATDESC: Counts - Sunward - Fe lowQ - FIELDNAM: Counts - SW - Fe lowQ - -lo-sw-species-heplus: - <<: *lo_species_default - CATDESC: Counts - Sunward - He+ (PUI) - FIELDNAM: Counts - SW - He+ (PUI) - -lo-sw-species-heplusplus: - <<: *lo_species_default - CATDESC: Counts - Sunward - He++ - FIELDNAM: Counts - SW - He++ - -lo-sw-species-hplus: - <<: *lo_species_default - CATDESC: Counts - Sunward - H+ - FIELDNAM: Counts - SW - H+ - -lo-sw-species-mg: - <<: *lo_species_default - CATDESC: Counts - Sunward - Mg - FIELDNAM: Counts - SW - Mg - -lo-sw-species-ne: - <<: *lo_species_default - CATDESC: Counts - Sunward - Ne - FIELDNAM: Counts - SW - Ne - -lo-sw-species-oplus5: - <<: *lo_species_default - CATDESC: Counts - Sunward - O+5 - FIELDNAM: Counts - SW - O+5 - -lo-sw-species-oplus6: - <<: *lo_species_default - CATDESC: Counts - Sunward - O+6 - FIELDNAM: Counts - SW - O+6 - -lo-sw-species-oplus7: - <<: *lo_species_default - CATDESC: Counts - Sunward - O+7 - FIELDNAM: Counts - SW - O+7 - -lo-sw-species-oplus8: - <<: *lo_species_default - CATDESC: Counts - Sunward - O+8 - FIELDNAM: Counts - SW - O+8 - -lo-sw-species-si: - <<: *lo_species_default - CATDESC: Counts - Sunward - Si - FIELDNAM: Counts - SW - Si - -# lo-sw-angular Attributes -lo-sw-angular-fe_loq: - <<: *lo_angular_default - CATDESC: Counts - Sunward - Fe lowQ - FIELDNAM: Sunward Facing Counts - SW - Fe lowQ - -lo-sw-angular-heplusplus: - <<: *lo_angular_default - CATDESC: Counts - Sunward - He++ - FIELDNAM: Sunward Facing Counts - SW - He++ - -lo-sw-angular-hplus: - <<: *lo_angular_default - CATDESC: Counts - Sunward - H+ - FIELDNAM: Sunward Facing Counts - SW - H+ - -lo-sw-angular-oplus6: - <<: *lo_angular_default - CATDESC: Counts - Sunward - O+6 - FIELDNAM: Sunward Facing Counts - SW - O+6 - -# lo-nsw-species Attributes -lo-nsw-species-c: - <<: *lo_species_default - CATDESC: Counts - Non-Sunward - C - FIELDNAM: Counts - NSW - C - -lo-nsw-species-cnoplus: - <<: *lo_species_default - CATDESC: Counts - Non-Sunward - CNO+ - FIELDNAM: Counts - NSW - CNO+ - -lo-nsw-species-fe: - <<: *lo_species_default - CATDESC: Counts - Non-Sunward - Fe - FIELDNAM: Counts - NSW - Fe - -lo-nsw-species-heplus: - <<: *lo_species_default - CATDESC: Counts - Non-Sunward - He+ - FIELDNAM: Counts - NSW - He+ - -lo-nsw-species-heplusplus: - <<: *lo_species_default - CATDESC: Counts - Non-Sunward - He++ - FIELDNAM: Counts - NSW - He++ - -lo-nsw-species-hplus: - <<: *lo_species_default - CATDESC: Counts - Non-Sunward - H+ - FIELDNAM: Counts - NSW - H+ - -lo-nsw-species-ne_si_mg: - <<: *lo_species_default - CATDESC: Counts - Non-Sunward - Ne_Si_Mg - FIELDNAM: Counts - NSW - Ne_Si_Mg - -lo-nsw-species-o: - <<: *lo_species_default - CATDESC: Counts - Non-Sunward - O - FIELDNAM: Counts - NSW - O - -# lo-nsw-angular Attributes -lo-nsw-angular-heplusplus: - CATDESC: Counts - Non-Sunward - He++ - FIELDNAM: Non-Sunward Facing Counts - NSW - He++ - -# lo-ialirt Attributes -lo-ialirt-c_over_o_abundance_ratio: - <<: *lo_ialirt_default - CATDESC: Elemental Abundance Ratio - C/O - FIELDNAM: C/O - -lo-ialirt-c_plus_6_over_c_plus_5_ratio: - <<: *lo_ialirt_default - CATDESC: Charge State Ratio - C+6/C+5 - FIELDNAM: C+6/C+5 - -lo-ialirt-fe_low_over_fe_high_ratio: - <<: *lo_ialirt_default - CATDESC: Charge State Ratio - Fe(low)/Fe(high) - FIELDNAM: Fe(low)/Fe(high) - -lo-ialirt-fe_over_o_abundance_ratio: - <<: *lo_ialirt_default - CATDESC: Elemental Abundance Ratio - Fe/O - FIELDNAM: Fe/O - -lo-ialirt-mg_over_o_abundance_ratio: - <<: *lo_ialirt_default - CATDESC: Elemental Abundance Ratio - Mg/O - FIELDNAM: Mg/O - -lo-ialirt-o_plus_7_over_o_plus_6_ratio: - <<: *lo_ialirt_default - CATDESC: Charge State Ratio - O+7/O+6 - FIELDNAM: O+7/O+6 - -# hi-ialirt Attributes -hi-ialirt-energy_h_minus: - <<: *energy_delta_default - CATDESC: Energy Table Minus value - FIELDNAM: energy delta minus - DEPEND_1: energy_h - -hi-ialirt-energy_h_plus: - <<: *energy_delta_default - CATDESC: Energy Table Plus value - FIELDNAM: energy delta plus - DEPEND_1: energy_h - -hi-ialirt-h: - <<: *default - CATDESC: h (x2 spacing) - FIELDNAM: h Diff. Intensity - DEPEND_1: energy_h - DEPEND_2: ssd_index - DEPEND_3: spin_sector_index - LABL_PTR_1: energy_h_label - LABL_PTR_2: ssd_index_label - LABL_PTR_3: spin_sector_index_label - DISPLAY_TYPE: spectrogram - FILLVAL: 4294967294 - UNITS: '# / cm2 s sr MeV/nuc' - VALIDMAX: 16777216 - VALIDMIN: 0 - -hi-ialirt-spin_angles: - <<: *spin_angles_default - DEPEND_1: spin_sector_index - DEPEND_2: elevation_angle - LABL_PTR_1: spin_sector_index_label - LABL_PTR_2: elevation_angle_label - -# hi-omni Attributes -hi-omni-energy_c_minus: - <<: *energy_delta_default - CATDESC: Energy Table Minus value - FIELDNAM: energy delta minus - DEPEND_1: energy_c - -hi-omni-energy_c_plus: - <<: *energy_delta_default - CATDESC: Energy Table Plus value - FIELDNAM: energy delta plus - DEPEND_1: energy_c - -hi-omni-energy_fe_minus: - <<: *energy_delta_default - CATDESC: Energy Table Minus value - FIELDNAM: energy delta minus - DEPEND_1: energy_fe - -hi-omni-energy_fe_plus: - <<: *energy_delta_default - CATDESC: Energy Table Plus value - FIELDNAM: energy delta plus - DEPEND_1: energy_fe - -hi-omni-energy_h_minus: - <<: *energy_delta_default - CATDESC: Energy Table Minus value - FIELDNAM: energy delta minus - DEPEND_1: energy_h - -hi-omni-energy_h_plus: - <<: *energy_delta_default - CATDESC: Energy Table Plus value - FIELDNAM: energy delta plus - DEPEND_1: energy_h - -hi-omni-energy_he3_minus: - <<: *energy_delta_default - CATDESC: Energy Table Minus value - FIELDNAM: energy delta minus - DEPEND_1: energy_he3 - -hi-omni-energy_he3_plus: - <<: *energy_delta_default - CATDESC: Energy Table Plus value - FIELDNAM: energy delta plus - DEPEND_1: energy_he3 - -hi-omni-energy_he4_minus: - <<: *energy_delta_default - CATDESC: Energy Table Minus value - FIELDNAM: energy delta minus - DEPEND_1: energy_he4 - -hi-omni-energy_he4_plus: - <<: *energy_delta_default - CATDESC: Energy Table Plus value - FIELDNAM: energy delta plus - DEPEND_1: energy_he4 - -hi-omni-energy_junk_minus: - <<: *energy_delta_default - CATDESC: Energy Table Minus value - FIELDNAM: energy delta minus - DEPEND_1: energy_junk - -hi-omni-energy_junk_plus: - <<: *energy_delta_default - CATDESC: Energy Table Plus value - FIELDNAM: energy delta plus - DEPEND_1: energy_junk - -hi-omni-energy_ne_mg_si_minus: - <<: *energy_delta_default - CATDESC: Energy Table Minus value - FIELDNAM: energy delta minus - DEPEND_1: energy_ne_mg_si - -hi-omni-energy_ne_mg_si_plus: - <<: *energy_delta_default - CATDESC: Energy Table Plus value - FIELDNAM: energy delta plus - DEPEND_1: energy_ne_mg_si - -hi-omni-energy_o_minus: - <<: *energy_delta_default - CATDESC: Energy Table Minus value - FIELDNAM: energy delta minus - DEPEND_1: energy_o - -hi-omni-energy_o_plus: - <<: *energy_delta_default - CATDESC: Energy Table Plus value - FIELDNAM: energy delta plus - DEPEND_1: energy_o - -hi-omni-energy_uh_minus: - <<: *energy_delta_default - CATDESC: Energy Table Minus value - FIELDNAM: energy delta minus - DEPEND_1: energy_uh - -hi-omni-energy_uh_plus: - <<: *energy_delta_default - CATDESC: Energy Table Plus value - FIELDNAM: energy delta plus - DEPEND_1: energy_uh - -hi-omni-c: - <<: *hi_omni_default - CATDESC: c (Root 2 spacing) - FIELDNAM: c - DEPEND_1: energy_c - LABL_PTR_1: energy_c_label - -hi-omni-fe: - <<: *hi_omni_default - CATDESC: fe (Root 2 spacing) - FIELDNAM: fe - DEPEND_1: energy_fe - LABL_PTR_1: energy_fe_label - -hi-omni-h: - <<: *hi_omni_default - CATDESC: h (Root 2 spacing) - FIELDNAM: h - DEPEND_1: energy_h - LABL_PTR_1: energy_h_label - -hi-omni-he3: - <<: *hi_omni_default - CATDESC: he3 (Root 2 spacing) - FIELDNAM: he3 - DEPEND_1: energy_he3 - LABL_PTR_1: energy_he3_label - - -hi-omni-he4: - <<: *hi_omni_default - CATDESC: he4 (Root 2 spacing) - FIELDNAM: he4 - DEPEND_1: energy_he4 - LABL_PTR_1: energy_he4_label - -hi-omni-junk: - <<: *hi_omni_default - CATDESC: junk (Root 2 spacing) - FIELDNAM: junk - DEPEND_1: energy_junk - LABL_PTR_1: energy_junk_label - -hi-omni-ne_mg_si: - <<: *hi_omni_default - CATDESC: ne-mg-si (Root 2 spacing) - FIELDNAM: ne-mg-si - DEPEND_1: energy_ne_mg_si - LABL_PTR_1: energy_ne_mg_si_label - -hi-omni-o: - <<: *hi_omni_default - CATDESC: o (Root 2 spacing) - FIELDNAM: o - DEPEND_1: energy_o - LABL_PTR_1: energy_o_label - -hi-omni-uh: - <<: *hi_omni_default - CATDESC: uh (Root 2 spacing) - FIELDNAM: uh - DEPEND_1: energy_uh - LABL_PTR_1: energy_uh_label - -# hi-sectored Attributes -hi-sectored-cno: - <<: *hi_sectored_attrs_default - CATDESC: cno (x2 spacing) - FIELDNAM: cno - DEPEND_1: energy_cno - LABL_PTR_1: energy_cno_label - -hi-sectored-fe: - <<: *hi_sectored_attrs_default - CATDESC: fe (x2 spacing) - FIELDNAM: fe - DEPEND_1: energy_fe - LABL_PTR_1: energy_fe_label - -hi-sectored-h: - <<: *hi_sectored_attrs_default - CATDESC: h (x2 spacing) - FIELDNAM: h - DEPEND_1: energy_h - LABL_PTR_1: energy_h_label - -hi-sectored-he3he4: - <<: *hi_sectored_attrs_default - CATDESC: he3he4 (x2 spacing) - FIELDNAM: he3he4 - DEPEND_1: energy_he3he4 - LABL_PTR_1: energy_he3he4_label - -hi-sectored-energy_cno_minus: - <<: *energy_delta_default - CATDESC: Energy Table Minus value - FIELDNAM: energy delta minus - DEPEND_1: energy_cno - -hi-sectored-energy_cno_plus: - <<: *energy_delta_default - CATDESC: Energy Table Plus value - FIELDNAM: energy delta plus - DEPEND_1: energy_cno - -hi-sectored-energy_fe_minus: - <<: *energy_delta_default - CATDESC: Energy Table Minus value - FIELDNAM: energy delta minus - DEPEND_1: energy_fe - -hi-sectored-energy_fe_plus: - <<: *energy_delta_default - CATDESC: Energy Table Plus value - FIELDNAM: energy delta plus - DEPEND_1: energy_fe - -hi-sectored-energy_h_minus: - <<: *energy_delta_default - CATDESC: Energy Table Minus value - FIELDNAM: energy delta minus - DEPEND_1: energy_h - -hi-sectored-energy_h_plus: - <<: *energy_delta_default - CATDESC: Energy Table Plus value - FIELDNAM: energy delta plus - DEPEND_1: energy_h - -hi-sectored-energy_he3he4_minus: - <<: *energy_delta_default - CATDESC: Energy Table Minus value - FIELDNAM: energy delta minus - DEPEND_1: energy_he3he4 - -hi-sectored-energy_he3he4_plus: - <<: *energy_delta_default - CATDESC: Energy Table Plus value - FIELDNAM: energy delta plus - DEPEND_1: energy_he3he4 - -hi-sectored-spin_angles: - <<: *spin_angles_default - DEPEND_1: spin_sector_index - DEPEND_2: elevation_angle - LABL_PTR_1: spin_sector_index_label - LABL_PTR_2: elevation_angle_label - diff --git a/imap_processing/cdf/config/imap_constant_attrs.yaml b/imap_processing/cdf/config/imap_constant_attrs.yaml index 9cf320a12e..5ca7d059f3 100644 --- a/imap_processing/cdf/config/imap_constant_attrs.yaml +++ b/imap_processing/cdf/config/imap_constant_attrs.yaml @@ -5,32 +5,32 @@ epoch: CATDESC: Time, number of nanoseconds since J2000 with leap seconds included + DICT_KEY: "SPASE>Support>SupportQuantity:Temporal" FIELDNAM: epoch - LABLAXIS: epoch FILLVAL: -9223372036854775808 FORMAT: " " # Supposedly not required, fails in xarray_to_cdf - VALIDMIN: 315576066184000000 # 2010-01-01T00:00:00 mission start (APL 0 epoch) - VALIDMAX: 3155716869184000000 # 2100-01-01T00:00:00 mission end - UNITS: ns - VAR_TYPE: support_data - SCALETYP: linear + LABLAXIS: epoch MONOTON: INCREASE - TIME_BASE: J2000 - TIME_SCALE: Terrestrial Time REFERENCE_POSITION: Rotating Earth Geoid RESOLUTION: ' ' - DICT_KEY: "SPASE>Support>SupportQantity:Temporal" + SCALETYP: linear + TIME_BASE: J2000 + TIME_SCALE: Terrestrial Time + UNITS: ns + VALIDMAX: 3155716869184000000 # 2100-01-01T00:00:00 mission end + VALIDMIN: 315576066184000000 # 2010-01-01T00:00:00 mission start (APL 0 epoch) + VAR_TYPE: support_data # <=== Data Variables ===> # Default Attrs for all metadata variables unless overridden metadata_attrs: DEPEND_0: epoch - LABLAXIS: ' ' FILLVAL: -9223372036854775808 FORMAT: I19 + LABLAXIS: ' ' + SCALETYP: linear UNITS: ' ' - VALIDMIN: 0 VALIDMAX: 9223372036854769664 + VALIDMIN: 0 VAR_TYPE: support_data - SCALETYP: linear diff --git a/imap_processing/cdf/config/imap_default_global_cdf_attrs.yaml b/imap_processing/cdf/config/imap_default_global_cdf_attrs.yaml index 71c5dd65d0..a26d9d2845 100644 --- a/imap_processing/cdf/config/imap_default_global_cdf_attrs.yaml +++ b/imap_processing/cdf/config/imap_default_global_cdf_attrs.yaml @@ -1,17 +1,17 @@ # Reference for sections: https://spdf.gsfc.nasa.gov/istp_guide/gattributes.html # Reference from IBEX: https://spdf.gsfc.nasa.gov/pub/software/cdawlib/0SKELTABLES/ibex_h3_ena_lo_r08_omni_f3-gdf-maps_5yr_00000000_v01.skt -Project: STP>Solar Terrestrial Probes -Source_name: IMAP>Interstellar Mapping and Acceleration Probe +Acknowledgement: > + Please acknowledge the IMAP Mission Principal Investigator, Prof. David J. McComas of Princeton University. Discipline: Solar Physics>Heliospheric Physics +File_naming_convention: source_descriptor_datatype_yyyyMMdd_vNNN +HTTP_LINK: https://imap.princeton.edu/ +LINK_TITLE: IMAP The Interstellar Mapping and Acceleration Probe Mission_group: IMAP -PI_name: Prof. David J. McComas PI_affiliation: Princeton University -File_naming_convention: source_descriptor_datatype_yyyyMMdd_vNNN -Acknowledgement: > - Please acknowledge the IMAP Mission Principal Investigator, Prof. David J. McComas of Princeton University. +PI_name: Prof. David J. McComas +Project: STP>Solar Terrestrial Probes Rules_of_use: > All IMAP data products are publicly released and citable for use in publications. Please consult the IMAP team publications and personnel for further details on production, processing, and usage of these data. -LINK_TITLE: IMAP The Interstellar Mapping and Acceleration Probe -HTTP_LINK: https://imap.princeton.edu/ +Source_name: IMAP>Interstellar Mapping and Acceleration Probe diff --git a/imap_processing/cdf/config/imap_enamaps_l2-common_variable_attrs.yaml b/imap_processing/cdf/config/imap_enamaps_l2-common_variable_attrs.yaml index 9ec5aa4dfd..485f4f8973 100644 --- a/imap_processing/cdf/config/imap_enamaps_l2-common_variable_attrs.yaml +++ b/imap_processing/cdf/config/imap_enamaps_l2-common_variable_attrs.yaml @@ -19,100 +19,114 @@ default_int64_attrs: &default_int64 DEPEND_0: epoch DISPLAY_TYPE: time_series FILLVAL: -9223372036854775808 - VALIDMIN: -9223372036854775808 + FORMAT: I20 + UNITS: " " VALIDMAX: 9223372036854775807 + VALIDMIN: -9223372036854775808 VAR_TYPE: data - UNITS: " " - FORMAT: I20 dtype: int64 default_float32_attrs: &default_float32 - FORMAT: F18.6 FILLVAL: -1.0e31 - VALIDMIN: -3.4028235e+38 + FORMAT: F18.6 VALIDMAX: 3.4028235e+38 + VALIDMIN: -3.4028235e+38 dtype: float32 # Define Coordinate(s) which are tiling-independent energy: <<: *default_float32 CATDESC: Geometric mean of energy bin. - FIELDNAM: energy_bin_geometric_mean - LABLAXIS: Energy bin geometric mean - UNITS: KeV - VAR_TYPE: support_data - SCALE_TYP: linear # We might not have these set up yet DELTA_MINUS_VAR: energy_delta_minus DELTA_PLUS_VAR: energy_delta_plus DICT_KEY: SPASE>Particle>ParticleType:Atom,ParticleQuantity:Energy,Qualifier:Incident + FIELDNAM: energy_bin_geometric_mean + LABLAXIS: Energy bin geometric mean + SCALETYP: linear + UNITS: KeV + VAR_TYPE: support_data energy_label: - VAR_TYPE: metadata - CATDESC: Geometric mean of energy bin. - FIELDNAM: energy_bin_geometric_mean - FORMAT: A16 + CATDESC: Label variable for energy coordinate DEPEND_1: energy - -epoch_delta: - <<: *default_int64 - CATDESC: Number of nanoseconds covered by data included in this map product. - FIELDNAM: epoch_delta - UNITS: ns - VAR_TYPE: support_data - DISPLAY_TYPE: no_plot - TIME_SCALE: Terrestrial Time + FIELDNAM: energy label + FORMAT: A16 + VAR_TYPE: metadata energy_delta_minus: <<: *default_float32 - VAR_TYPE: support_data CATDESC: Difference between the energy bin center and lower edge. - LABLAXIS: energy - UNITS: KeV - FIELDNAM: energy_bin_delta_minus - DISPLAY_TYPE: no_plot DEPEND_1: energy - LABL_PTR_1: energy_label DICT_KEY: SPASE>Particle>ParticleType:Atom,ParticleQuantity:Energy,Qualifier:Uncertainty + DISPLAY_TYPE: no_plot + FIELDNAM: energy delta minus + LABLAXIS: energy + LABL_PTR_1: energy_label + UNITS: KeV + VAR_TYPE: support_data energy_delta_plus: <<: *default_float32 - VAR_TYPE: support_data CATDESC: Difference between the energy bin center and upper edge. + DEPEND_1: energy + DICT_KEY: SPASE>Particle>ParticleType:Atom,ParticleQuantity:Energy,Qualifier:Uncertainty + DISPLAY_TYPE: no_plot + FIELDNAM: energy delta plus LABLAXIS: energy + LABL_PTR_1: energy_label UNITS: KeV - FIELDNAM: energy_bin_delta_plus + VAR_TYPE: support_data + +epoch: + BIN_LOCATION: 0 + CATDESC: Map time range start, number of nanoseconds since J2000 with leap seconds included + DELTA_MINUS_VAR: epoch_delta_minus + DELTA_PLUS_VAR: epoch_delta + FIELDNAM: J2000 Nanoseconds + +epoch_delta: + <<: *default_int64 + CATDESC: Number of nanoseconds covered by data included in this map product. + DICT_KEY: SPASE>Support>SupportQuantity:Temporal DISPLAY_TYPE: no_plot - DEPEND_1: energy - LABL_PTR_1: energy_label - DICT_KEY: SPASE>Particle>ParticleType:Atom,ParticleQuantity:Energy,Qualifier:Uncertainty + FIELDNAM: epoch delta + TIME_SCALE: Terrestrial Time + UNITS: ns + VAR_TYPE: support_data + +epoch_delta_minus: + <<: *default_int64 + CATDESC: Number of nanoseconds before epoch included in this map product (always equal to zero). + DICT_KEY: SPASE>Support>SupportQuantity:Temporal + DISPLAY_TYPE: no_plot + FIELDNAM: epoch delta minus + TIME_SCALE: Terrestrial Time + UNITS: ns + VAR_TYPE: support_data # These two coordinates will be treated differently in the # HEALPix and rectangular tilings. They will be substantially overridden # in the tiling-specific YAML files. longitude: <<: *default_float32 - CATDESC: Pixel center longitude in range [0, 360]. - FIELDNAM: Longitude - LABLAXIS: Longitude - UNITS: degrees - VAR_TYPE: support_data - DISPLAY_TYPE: no_plot - VALIDMIN: 0 - VALIDMAX: 360 DICT_KEY: SPASE>Support>SupportQuantity:Orientation,Qualifier:DirectionAngle.AzimuthAngle,CoordinateSystemName:HAE,CoordinateRepresentation:Spherical + FIELDNAM: "{frame} Longitude" + LABLAXIS: "{frame} Longitude" + UNITS: deg + VALIDMAX: 360 + VALIDMIN: 0 + VAR_TYPE: support_data latitude: <<: *default_float32 - CATDESC: Pixel center latitude in range [-90, 90]. - FIELDNAM: Latitude - LABLAXIS: Latitude - UNITS: degrees - VAR_TYPE: support_data - DISPLAY_TYPE: no_plot - VALIDMIN: -90 - VALIDMAX: 90 DICT_KEY: SPASE>Support>SupportQuantity:Orientation,Qualifier:DirectionAngle.ElevationAngle,CoordinateSystemName:HAE,CoordinateRepresentation:Spherical + FIELDNAM: "{frame} Latitude" + LABLAXIS: "{frame} Latitude" + UNITS: deg + VALIDMAX: 90 + VALIDMIN: -90 + VAR_TYPE: support_data # Define Data variables, but not their pixel-level DEPENDs # (e.g. pixel_index for HEALPix maps, longitude/latitude for rectangular maps). @@ -120,105 +134,230 @@ latitude: ena_intensity: <<: *default_float32 CATDESC: Mono-energetic ENA intensity. - FIELDNAM: Intensity - UNITS: counts/(s * cm^2 * Sr * KeV) - DELTA_MINUS_VAR: ena_intensity_stat_unc - DELTA_PLUS_VAR: ena_intensity_stat_unc + DELTA_MINUS_VAR: ena_intensity_stat_uncert + DELTA_PLUS_VAR: ena_intensity_stat_uncert DEPEND_0: epoch - VAR_TYPE: data - LABLAXIS: Intensity - DISPLAY_TYPE: image DICT_KEY: SPASE>Particle>ParticleType:Atom,ParticleQuantity:NumberFlux,Qualifier:Incident,CoordinateSystemName:HAE,CoordinateRepresentation:Spherical + DISPLAY_TYPE: map_image + FIELDNAM: Intensity + LABLAXIS: Intensity + UNITS: cm -2 s -1 sr -1 keV -1 + VAR_TYPE: data -ena_intensity_stat_unc: +ena_intensity_stat_uncert: <<: *default_float32 CATDESC: ENA intensity statistical uncertainty. - FIELDNAM: Intensity stat unc - UNITS: counts/(s * cm^2 * Sr * KeV) DEPEND_0: epoch - VAR_TYPE: data - LABLAXIS: Statistical Unc - DISPLAY_TYPE: image DICT_KEY: SPASE>Particle>ParticleType:Atom,ParticleQuantity:NumberFlux,Qualifier:Uncertainty,CoordinateSystemName:HAE,CoordinateRepresentation:Spherical + DISPLAY_TYPE: map_image + FIELDNAM: Intensity stat unc + LABLAXIS: Statistical Unc + UNITS: cm -2 s -1 sr -1 keV -1 + VAR_TYPE: support_data ena_intensity_sys_err: <<: *default_float32 CATDESC: ENA intensity non-statistical error. - FIELDNAM: Intensity non-stat error - UNITS: counts/(s * cm^2 * Sr * KeV) DEPEND_0: epoch - VAR_TYPE: data - LABLAXIS: Non-Statistical Err - DISPLAY_TYPE: image DICT_KEY: SPASE>Particle>ParticleType:Atom,ParticleQuantity:NumberFlux,Qualifier:Uncertainty,CoordinateSystemName:HAE,CoordinateRepresentation:Spherical + DISPLAY_TYPE: map_image + FIELDNAM: Intensity non-stat error + LABLAXIS: Non-statistical Error + UNITS: cm -2 s -1 sr -1 keV -1 + VAR_TYPE: support_data -ena_rate: +ena_count_rate: <<: *default_float32 CATDESC: Mono-energetic ENA Rate. + DEPEND_0: epoch + DICT_KEY: SPASE>Particle>ParticleType:Atom,ParticleQuantity:NumberFlux,Qualifier:Incident,CoordinateSystemName:HAE,CoordinateRepresentation:Spherical + DISPLAY_TYPE: map_image FIELDNAM: Rate + LABLAXIS: Rate UNITS: counts/s - DEPEND_0: epoch VAR_TYPE: data + +ena_count_rate_stat_uncert: + <<: *default_float32 + CATDESC: ENA Rate statistical uncertainty. + DEPEND_0: epoch + DICT_KEY: SPASE>Particle>ParticleType:Atom,ParticleQuantity:NumberFlux,Qualifier:Uncertainty,CoordinateSystemName:HAE,CoordinateRepresentation:Spherical + DISPLAY_TYPE: map_image + FIELDNAM: Rate Uncertainty + LABLAXIS: Rate Uncertainty + UNITS: counts/s + VAR_TYPE: support_data + +bg_rate: + <<: *default_float32 + CATDESC: Total background count rate from non-ENA (non-heliospheric) sources, as calculated by ground processing; makes sense only for "uncombined" calibration products. + DEPEND_0: epoch + DICT_KEY: SPASE>Particle>ParticleType:Atom,ParticleQuantity:NumberFlux,Qualifier:Incident,CoordinateSystemName:HAE,CoordinateRepresentation:Spherical + DISPLAY_TYPE: map_image + FIELDNAM: Background Rate + FORMAT: F6.3 LABLAXIS: Rate - DISPLAY_TYPE: image + UNITS: count s-1 + VAR_TYPE: data + +bg_rate_stat_uncert: + <<: *default_float32 + CATDESC: Statistical uncertainty in the background count rate from non-ENA (non-heliospheric) sources. + DEPEND_0: epoch + DICT_KEY: SPASE>Particle>ParticleType:Atom,ParticleQuantity:NumberFlux,Qualifier:Uncertainty,CoordinateSystemName:HAE,CoordinateRepresentation:Spherical + DISPLAY_TYPE: map_image + FIELDNAM: Background Rate Stat Uncertainty + FORMAT: F6.3 + LABLAXIS: Rate Uncertainty + UNITS: count s-1 + VAR_TYPE: support_data + +bg_rate_sys_err: + <<: *default_float32 + CATDESC: Systematic error in the background count rate from non-ENA (non-heliospheric) sources. + DEPEND_0: epoch + DICT_KEY: SPASE>Particle>ParticleType:Atom,ParticleQuantity:NumberFlux,Qualifier:Uncertainty,CoordinateSystemName:HAE,CoordinateRepresentation:Spherical + DISPLAY_TYPE: map_image + FIELDNAM: Background Rate Sys Error + FORMAT: F6.3 + LABLAXIS: Rate Error + UNITS: count s-1 + VAR_TYPE: support_data + +bg_intensity: + <<: *default_float32 + CATDESC: Total background intensity from non-ENA (non-heliospheric) sources + DEPEND_0: epoch DICT_KEY: SPASE>Particle>ParticleType:Atom,ParticleQuantity:NumberFlux,Qualifier:Incident,CoordinateSystemName:HAE,CoordinateRepresentation:Spherical + DISPLAY_TYPE: map_image + FIELDNAM: Background Intensity + FORMAT: F8.3 + LABLAXIS: Intensity + UNITS: cm -2 s -1 sr -1 keV -1 + VAR_TYPE: data + +bg_intensity_stat_uncert: + <<: *default_float32 + CATDESC: Uncertainty in the background intensity from non-ENA (non-heliospheric) sources. + DEPEND_0: epoch + DICT_KEY: SPASE>Particle>ParticleType:Atom,ParticleQuantity:NumberFlux,Qualifier:Uncertainty,CoordinateSystemName:HAE,CoordinateRepresentation:Spherical + DISPLAY_TYPE: map_image + FIELDNAM: Background Intensity Statistical Uncertainty + FORMAT: F8.3 + LABLAXIS: Intensity Uncertainty + UNITS: cm -2 s -1 sr -1 keV -1 + VAR_TYPE: support_data + +bg_intensity_sys_err: + <<: *default_float32 + CATDESC: Non-statistical error in the background intensity from non-ENA (non-heliospheric) sources. + DEPEND_0: epoch + DICT_KEY: SPASE>Particle>ParticleType:Atom,ParticleQuantity:NumberFlux,Qualifier:Uncertainty,CoordinateSystemName:HAE,CoordinateRepresentation:Spherical + DISPLAY_TYPE: map_image + FIELDNAM: Background Intensity Non-statistical Error + FORMAT: F8.3 + LABLAXIS: Intensity Non-statistical Error + UNITS: cm -2 s -1 sr -1 keV -1 + VAR_TYPE: support_data ena_count: <<: *default_float32 CATDESC: Mono-energetic ENA Count. + DEPEND_0: epoch + DICT_KEY: SPASE>Particle>ParticleType:Atom,ParticleQuantity:NumberFlux,Qualifier:Incident,CoordinateSystemName:HAE,CoordinateRepresentation:Spherical + DISPLAY_TYPE: map_image FIELDNAM: Count + LABLAXIS: Count UNITS: counts - DEPEND_0: epoch VAR_TYPE: data - LABLAXIS: Count - DISPLAY_TYPE: image - DICT_KEY: SPASE>Particle>ParticleType:Atom,ParticleQuantity:NumberFlux,Qualifier:Incident,CoordinateSystemName:HAE,CoordinateRepresentation:Spherical sensitivity: <<: *default_float32 - CATDESC: Calibration/sensitivity factor calculated from multiple pointing sets. - FIELDNAM: sensitivity - UNITS: cm^-3 - DEPEND_0: epoch - VAR_TYPE: data - LABLAXIS: sensitivity - DISPLAY_TYPE: image + CATDESC: Averaged instrument sensitive area DICT_KEY: SPASE>Particle>ParticleType:Atom,ParticleQuantity:GeometricFactor,Qualifier:Directional,CoordinateSystemName:HAE,CoordinateRepresentation:Spherical + DISPLAY_TYPE: no_plot + FIELDNAM: Sensitivity + LABLAXIS: sensitivity + UNITS: cm^2 + VAR_TYPE: support_data exposure_factor: &exposure_factor <<: *default_float32 CATDESC: Exact or approximate time over which counts are accumulated. - FIELDNAM: Exposure Times DEPEND_0: epoch + DICT_KEY: SPASE>Support>SupportQuantity:Temporal + DISPLAY_TYPE: no_plot + FIELDNAM: Exposure Times + FORMAT: F5.2 + LABLAXIS: Exposure UNITS: s + VAR_NOTES: Exact or approximate exposure time over which counts in a pixel are accumulated. Used as a weighting factor for combining data quantities sensibly. VAR_TYPE: data - LABLAXIS: Exposure + +geometric_function: + <<: *default_float32 + CATDESC: Averaged aperture area as seen by the backstop. + DICT_KEY: SPASE>Particle>ParticleType:Atom,ParticleQuantity:GeometricFactor,Qualifier:Directional,CoordinateSystemName:HAE,CoordinateRepresentation:Spherical + DISPLAY_TYPE: no_plot + FIELDNAM: Geometric Function + LABLAXIS: Geometric Function + UNITS: cm^2 + VAR_TYPE: support_data + +efficiency: + <<: *default_float32 + CATDESC: Efficiency of the instrument in converting ENAs to valid events + DICT_KEY: SPASE>Particle>ParticleType:Atom,ParticleQuantity:Other + DISPLAY_TYPE: no_plot + FIELDNAM: Efficiency + LABLAXIS: Efficiency + UNITS: " " + VAR_TYPE: support_data + +positional_uncert_theta: + <<: *default_float32 + CATDESC: Averaged position uncertainty along the theta dimension of the instrument + DICT_KEY: SPASE>Particle>ParticleType:Atom,ParticleQuantity:ArrivalDirection,Qualifier:Uncertainty,CoordinateSystemName:HAE,CoordinateRepresentation:Spherical DISPLAY_TYPE: no_plot - DICT_KEY: SPASE>TemporalDescription:Exposure,Qualifier:Directional,CoordinateSystemName:HAE,CoordinateRepresentation:Spherical + FIELDNAM: Positional Uncertainty Theta + LABLAXIS: Position Uncertainty Theta + UNITS: degrees + VAR_TYPE: support_data + +positional_uncert_phi: + <<: *default_float32 + CATDESC: Averaged position uncertainty along the phi dimension of the instrument + DICT_KEY: SPASE>Particle>ParticleType:Atom,ParticleQuantity:ArrivalDirection,Qualifier:Uncertainty,CoordinateSystemName:HAE,CoordinateRepresentation:Spherical + DISPLAY_TYPE: no_plot + FIELDNAM: Positional Uncertainty Phi + LABLAXIS: Position Uncertainty Phi + UNITS: degrees + VAR_TYPE: support_data obs_date: &obs_date <<: *default_int64 - datatype: int64 - CATDESC: Exposure time weighted mean collection date of data in a pixel. - FIELDNAM: J2000 Nanoseconds - UNITS: ns + CATDESC: Mean collection date of data in a pixel DEPEND_0: epoch - VAR_TYPE: data - LABLAXIS: epoch - DISPLAY_TYPE: image DICT_KEY: SPASE>TemporalDescription:TimeSpan,Qualifier:Directional,CoordinateSystemName:HAE,CoordinateRepresentation:Spherical + DISPLAY_TYPE: no_plot + FIELDNAM: J2000 Nanoseconds + LABLAXIS: epoch + UNITS: ns + VAR_TYPE: support_data + datatype: int64 obs_date_range: <<: *default_int64 - datatype: int64 CATDESC: Standard deviation of the observation date. - FIELDNAM: Observation date range - UNITS: ns DEPEND_0: epoch - VAR_TYPE: data + DICT_KEY: SPASE>Support>SupportQuantity:Temporal + DISPLAY_TYPE: no_plot + FIELDNAM: Observation date range LABLAXIS: epoch - DISPLAY_TYPE: image TIME_SCALE: Terrestrial Time + UNITS: ns + VAR_TYPE: support_data + datatype: int64 # These copied metadata vars will allow for variables # to be either energy-dependent or independent. @@ -234,12 +373,11 @@ obs_date_range_energy_independent: solid_angle: <<: *default_float32 - VAR_TYPE: support_data CATDESC: Solid angle subtended by each pixel. - FIELDNAM: Solid Angle DEPEND_0: epoch - UNITS: sr - VAR_TYPE: data - LABLAXIS: Solid Angle - DISPLAY_TYPE: image DICT_KEY: SPASE>Support>SupportQuantity:Other + DISPLAY_TYPE: no_plot + FIELDNAM: Solid Angle + LABLAXIS: Solid Angle + UNITS: sr + VAR_TYPE: support_data diff --git a/imap_processing/cdf/config/imap_enamaps_l2-healpix_variable_attrs.yaml b/imap_processing/cdf/config/imap_enamaps_l2-healpix_variable_attrs.yaml index e34ede2649..1ee375273e 100644 --- a/imap_processing/cdf/config/imap_enamaps_l2-healpix_variable_attrs.yaml +++ b/imap_processing/cdf/config/imap_enamaps_l2-healpix_variable_attrs.yaml @@ -3,10 +3,10 @@ # ENA map attributes defined in imap_enamaps_l2-common_variable_attrs.yaml default_float32_attrs: &default_float32 - FORMAT: F12.6 FILLVAL: -1.0e31 - VALIDMIN: -3.4028235e+38 + FORMAT: F12.6 VALIDMAX: 3.4028235e+38 + VALIDMIN: -3.4028235e+38 dtype: float32 # Define Coordinates specifically for Healpix tiling @@ -14,23 +14,23 @@ pixel_index: # Max number of pixels in Healpix style map which can fit into a 32-bit integer # is with Healpix nside parameter = 16384, npix = 3221225472. Use the max of uint32 # as the fill value for the pixel index. - dtype: uint32 - FILLVAL: 4294967295 - VALIDMIN: 0 - VALIDMAX: 3221225472 - FORMAT: I12 CATDESC: Healpix index corresponding to the bin center. FIELDNAM: pixel_index + FILLVAL: 4294967295 + FORMAT: I12 LABLAXIS: "HEALPix #" UNITS: " " + VALIDMAX: 3221225472 + VALIDMIN: 0 VAR_TYPE: support_data + dtype: uint32 pixel_index_label: - VAR_TYPE: metadata CATDESC: Healpix index corresponding to the bin center. + DEPEND_1: pixel_index FIELDNAM: pixel_index FORMAT: A10 - DEPEND_1: pixel_index + VAR_TYPE: metadata # All variables below override the initial attributes defined in the common ENA Map # attributes file, imap_enamaps_l2-common_variable_attrs.yaml @@ -39,22 +39,29 @@ pixel_index_label: # (longitude, latitude are not dimension coordinates for healpix tiling, but rather # describe the lon/lat coordinate of the Healpix pixel center) longitude: + CATDESC: "HEALPix Pixel center longitude in {frame} reference frame in the range [0, 360]" DEPEND_1: pixel_index LABL_PTR_1: pixel_index_label latitude: + CATDESC: "HEALPix Pixel center latitude in {frame} reference frame in the range [-90, 90]" DEPEND_1: pixel_index LABL_PTR_1: pixel_index_label # Define Data variables +ena_count: + DEPEND_1: energy + DEPEND_2: pixel_index + LABL_PTR_1: energy_label + LABL_PTR_2: pixel_index_label + ena_intensity: DEPEND_1: energy DEPEND_2: pixel_index LABL_PTR_1: energy_label LABL_PTR_2: pixel_index_label - DISPLAY_TYPE: image -ena_intensity_stat_unc: +ena_intensity_stat_uncert: DEPEND_1: energy DEPEND_2: pixel_index LABL_PTR_1: energy_label @@ -72,6 +79,47 @@ sensitivity: LABL_PTR_1: energy_label LABL_PTR_2: pixel_index_label +efficiency: + DEPEND_1: energy + DEPEND_2: pixel_index + LABL_PTR_1: energy_label + LABL_PTR_2: pixel_index_label + +geometric_function: + DEPEND_1: energy + DEPEND_2: pixel_index + LABL_PTR_1: energy_label + LABL_PTR_2: pixel_index_label + +positional_uncert_theta: + DEPEND_1: energy + DEPEND_2: pixel_index + LABL_PTR_1: energy_label + LABL_PTR_2: pixel_index_label + +positional_uncert_phi: + DEPEND_1: energy + DEPEND_2: pixel_index + LABL_PTR_1: energy_label + LABL_PTR_2: pixel_index_label + +bg_rate: + DEPEND_1: energy + DEPEND_2: pixel_index + LABL_PTR_1: energy_label + LABL_PTR_2: pixel_index_label + +bg_rate_stat_uncert: + DEPEND_1: energy + DEPEND_2: pixel_index + LABL_PTR_1: energy_label + LABL_PTR_2: pixel_index_label + +bg_rate_sys_err: + DEPEND_1: energy + DEPEND_2: pixel_index + LABL_PTR_1: energy_label + LABL_PTR_2: pixel_index_label # These data variables will have an extra (energy) dimension # only if the energy dimension is present in the L1C data. # The default is energy-independent. @@ -99,6 +147,12 @@ obs_date: LABL_PTR_1: energy_label LABL_PTR_2: pixel_index_label +obs_date_range: + DEPEND_1: energy + DEPEND_2: pixel_index + LABL_PTR_1: energy_label + LABL_PTR_2: pixel_index_label + solid_angle: DEPEND_1: pixel_index LABL_PTR_1: pixel_index_label diff --git a/imap_processing/cdf/config/imap_enamaps_l2-rectangular_variable_attrs.yaml b/imap_processing/cdf/config/imap_enamaps_l2-rectangular_variable_attrs.yaml index b71ba61d23..781deb9cda 100644 --- a/imap_processing/cdf/config/imap_enamaps_l2-rectangular_variable_attrs.yaml +++ b/imap_processing/cdf/config/imap_enamaps_l2-rectangular_variable_attrs.yaml @@ -3,58 +3,76 @@ # ENA map attributes defined in imap_enamaps_l2-common_variable_attrs.yaml default_float32_attrs: &default_float32 - FORMAT: F12.6 FILLVAL: -1.0e31 - VALIDMIN: -3.4028235e+38 + FORMAT: F12.6 VALIDMAX: 3.4028235e+38 + VALIDMIN: -3.4028235e+38 dtype: float32 # Define Coordinates specifically for Rectangular tiling longitude_label: - VAR_TYPE: metadata CATDESC: Label variable for longitude. + DEPEND_1: longitude FIELDNAM: longitude label FORMAT: A8 - DEPEND_1: longitude + VAR_TYPE: metadata longitude_delta: - VAR_TYPE: metadata - dtype: float32 CATDESC: Half-width of longitude pixel + DEPEND_1: longitude + DICT_KEY: SPASE>Support>SupportQuantity:Other + FIELDNAM: longitude delta FORMAT: F12.6 + LABL_PTR_1: longitude_label UNITS: degrees - FIELDNAM: longitude delta - DICT_KEY: SPASE>Support>SupportQuantity:Other + VALIDMAX: 180.0 + VALIDMIN: 0.0 + VAR_TYPE: support_data + dtype: float32 latitude_label: - VAR_TYPE: metadata CATDESC: Label variable for latitude. + DEPEND_1: latitude FIELDNAM: latitude label FORMAT: A8 - DEPEND_1: latitude + VAR_TYPE: metadata latitude_delta: - VAR_TYPE: metadata - dtype: float32 CATDESC: Half-width of latitude pixel + DEPEND_1: latitude + DICT_KEY: SPASE>Support>SupportQuantity:Other + FIELDNAM: latitude delta FORMAT: F12.6 + LABL_PTR_1: latitude_label UNITS: degrees - FIELDNAM: latitude delta - DICT_KEY: SPASE>Support>SupportQuantity:Other + VALIDMAX: 90.0 + VALIDMIN: 0.0 + VAR_TYPE: support_data + dtype: float32 # All variables below override the initial attributes defined in the common ENA Map # attributes file, imap_enamaps_l2-common_variable_attrs.yaml longitude: + CATDESC: "Pixel center longitude in {frame} reference frame in the range [0, 360]" DELTA_MINUS_VAR: longitude_delta DELTA_PLUS_VAR: longitude_delta - SCALE_TYP: linear + FORMAT: I3 + LABL_PTR_1: longitude_label + MONOTON: INCREASE + SCALETYP: linear + latitude: + BIN_LOCATION: 0.5 + CATDESC: "Pixel center latitude in {frame} reference frame in the range [-90, 90]" DELTA_MINUS_VAR: latitude_delta DELTA_PLUS_VAR: latitude_delta - SCALE_TYP: linear + FORMAT: I2 + LABL_PTR_1: latitude_label + MONOTON: INCREASE + SCALETYP: linear # Define Data variables ena_intensity: @@ -65,7 +83,7 @@ ena_intensity: LABL_PTR_2: longitude_label LABL_PTR_3: latitude_label -ena_intensity_stat_unc: +ena_intensity_stat_uncert: DEPEND_1: energy DEPEND_2: longitude DEPEND_3: latitude @@ -81,7 +99,15 @@ ena_intensity_sys_err: LABL_PTR_2: longitude_label LABL_PTR_3: latitude_label -ena_rate: +ena_count_rate: + DEPEND_1: energy + DEPEND_2: longitude + DEPEND_3: latitude + LABL_PTR_1: energy_label + LABL_PTR_2: longitude_label + LABL_PTR_3: latitude_label + +ena_count_rate_stat_uncert: DEPEND_1: energy DEPEND_2: longitude DEPEND_3: latitude @@ -105,6 +131,54 @@ sensitivity: LABL_PTR_2: longitude_label LABL_PTR_3: latitude_label +bg_rate: + DEPEND_1: energy + DEPEND_2: longitude + DEPEND_3: latitude + LABL_PTR_1: energy_label + LABL_PTR_2: longitude_label + LABL_PTR_3: latitude_label + +bg_rate_stat_uncert: + DEPEND_1: energy + DEPEND_2: longitude + DEPEND_3: latitude + LABL_PTR_1: energy_label + LABL_PTR_2: longitude_label + LABL_PTR_3: latitude_label + +bg_rate_sys_err: + DEPEND_1: energy + DEPEND_2: longitude + DEPEND_3: latitude + LABL_PTR_1: energy_label + LABL_PTR_2: longitude_label + LABL_PTR_3: latitude_label + +bg_intensity: + DEPEND_1: energy + DEPEND_2: longitude + DEPEND_3: latitude + LABL_PTR_1: energy_label + LABL_PTR_2: longitude_label + LABL_PTR_3: latitude_label + +bg_intensity_stat_uncert: + DEPEND_1: energy + DEPEND_2: longitude + DEPEND_3: latitude + LABL_PTR_1: energy_label + LABL_PTR_2: longitude_label + LABL_PTR_3: latitude_label + +bg_intensity_sys_err: + DEPEND_1: energy + DEPEND_2: longitude + DEPEND_3: latitude + LABL_PTR_1: energy_label + LABL_PTR_2: longitude_label + LABL_PTR_3: latitude_label + # These data variables will have an extra (energy) dimension # only if the energy dimension is present in the L1C data. # The default is energy-independent. @@ -134,6 +208,38 @@ exposure_factor: LABL_PTR_2: longitude_label LABL_PTR_3: latitude_label +efficiency: + DEPEND_1: energy + DEPEND_2: longitude + DEPEND_3: latitude + LABL_PTR_1: energy_label + LABL_PTR_2: longitude_label + LABL_PTR_3: latitude_label + +geometric_function: + DEPEND_1: energy + DEPEND_2: longitude + DEPEND_3: latitude + LABL_PTR_1: energy_label + LABL_PTR_2: longitude_label + LABL_PTR_3: latitude_label + +positional_uncert_theta: + DEPEND_1: energy + DEPEND_2: longitude + DEPEND_3: latitude + LABL_PTR_1: energy_label + LABL_PTR_2: longitude_label + LABL_PTR_3: latitude_label + +positional_uncert_phi: + DEPEND_1: energy + DEPEND_2: longitude + DEPEND_3: latitude + LABL_PTR_1: energy_label + LABL_PTR_2: longitude_label + LABL_PTR_3: latitude_label + obs_date: DEPEND_1: energy DEPEND_2: longitude diff --git a/imap_processing/cdf/config/imap_glows_global_cdf_attrs.yaml b/imap_processing/cdf/config/imap_glows_global_cdf_attrs.yaml index 23d9db7743..5c0a82551c 100644 --- a/imap_processing/cdf/config/imap_glows_global_cdf_attrs.yaml +++ b/imap_processing/cdf/config/imap_glows_global_cdf_attrs.yaml @@ -1,5 +1,6 @@ instrument_base: &instrument_base Descriptor: GLOWS>GLObal Solar Wind Structure + Instrument_type: Imagers (space) TEXT: > The GLObal Solar Wind Structure (GLOWS) is a non-imaging single-pixel Lyman-alpha photometer to investigate the global heliolatitudinal structure of the solar wind @@ -10,7 +11,6 @@ instrument_base: &instrument_base along a scanning circle in the sky. GLOWS design and assembly is led by the Space Research Center, Warsaw, Poland (CBK PAN). See https://imap.princeton.edu/instruments/glows for more details. - Instrument_type: Imagers (space) imap_glows_l1a_hist: <<: *instrument_base diff --git a/imap_processing/cdf/config/imap_glows_l1a_variable_attrs.yaml b/imap_processing/cdf/config/imap_glows_l1a_variable_attrs.yaml index 51a33273ae..4a9dd39c5e 100644 --- a/imap_processing/cdf/config/imap_glows_l1a_variable_attrs.yaml +++ b/imap_processing/cdf/config/imap_glows_l1a_variable_attrs.yaml @@ -13,181 +13,169 @@ bins_label: default_attrs: &default_attrs # TODO: Remove unneeded attributes once SAMMI is fixed - RESOLUTION: ' ' DISPLAY_TYPE: no_plot + FILLVAL: *int_fillval + REFERENCE_POSITION: Rotating Earth Geoid + RESOLUTION: ' ' TIME_BASE: J2000 TIME_SCALE: Terrestrial Time - REFERENCE_POSITION: Rotating Earth Geoid UNITS: ' ' - FILLVAL: *int_fillval VALIDMIN: *min_epoch support_data_defaults: &support_data_defaults <<: *default_attrs DEPEND_0: epoch - VALIDMIN: 0 - VALIDMAX: 1 DISPLAY_TYPE: time_series - VAR_TYPE: support_data FORMAT: I10 RESOLUTION: ISO8601 + VALIDMAX: 1 + VALIDMIN: 0 + VAR_TYPE: support_data bins_attrs: <<: *default_attrs - VALIDMIN: 0 - VALIDMAX: 3599 CATDESC: Histogram bin number FIELDNAM: Bin number - FORMAT: I5 - VAR_TYPE: support_data - LABLAXIS: Counts - FILLVAL: -32768 + FILLVAL: *max_uint16 + FORMAT: I4 + LABLAXIS: Bin no. MONOTON: INCREASE SCALETYP: linear + VALIDMAX: 3599 + VALIDMIN: 0 + VAR_TYPE: support_data within_the_second: # Used to be per_second_attrs <<: *default_attrs - VALIDMIN: 0 + CATDESC: Ordinal number of direct event within a second + DISPLAY_TYPE: time_series + FIELDNAM: Ordinal number of direct event + FORMAT: I5 + LABLAXIS: Event no. VALIDMAX: 50000 - CATDESC: Direct events recorded in individual seconds # TBD any ideas how to define it - FIELDNAM: Direct events within a second - FORMAT: I10 + VALIDMIN: 0 VAR_TYPE: support_data - DISPLAY_TYPE: time_series - LABLAXIS: Direct Events direct_event_components_attrs: <<: *default_attrs - VALIDMIN: 0 + CATDESC: Direct-event component index (second, subsecond, pulse length, multi event) + FIELDNAM: Direct-event component index + FILLVAL: 255 + FORMAT: I1 + LABLAXIS: Index VALIDMAX: 3 - CATDESC: Components of a direct event (seconds, subseconds, impulse_length, multi_event) - FIELDNAM: Direct event components - FORMAT: I2 + VALIDMIN: 0 VAR_TYPE: support_data - LABLAXIS: Components - FILLVAL: 255 direct_events: <<: *default_attrs + CATDESC: Direct events grouped by seconds DEPEND_0: epoch DEPEND_1: within_the_second DEPEND_2: direct_event_components - VALIDMIN: 0 - VALIDMAX: *max_uint32 - CATDESC: Direct events grouped by epoch seconds FIELDNAM: Direct events + FILLVAL: *max_uint32 FORMAT: I10 + LABLAXIS: Direct events + VALIDMAX: *max_uint32_min_one + VALIDMIN: 0 VAR_TYPE: data - LABLAXIS: Counts - FILLVAL: *max_uint32_min_one histogram: <<: *default_attrs - VALIDMIN: 0 - VALIDMAX: 255 CATDESC: Histogram of photon counts in scanning-circle bins DEPEND_0: epoch DEPEND_1: bins - LABL_PTR_1: bins_label + DISPLAY_TYPE: spectrogram FIELDNAM: Histogram of photon counts - FORMAT: I4 - DISPLAY_TYPE: time_series - FILL_VAL: *max_uint16 - UNITS: counts + FILLVAL: *max_uint16 + FORMAT: I3 + LABL_PTR_1: bins_label + UNITS: '#' + VALIDMAX: 255 + VALIDMIN: 0 VAR_TYPE: data -pkts_file_name: - <<: *support_data_defaults - CATDESC: Name of input file with CCSDS packets data - DISPLAY_TYPE: no_plot - FIELDNAM: Packets-data input filename - FILLVAL: # TBD: what is fillval for strings? - FORMAT: S256 # TBC - LABLAXIS: File name - VALIDMAX: # TBD: what is validmax for a string? - VALIDMIN: # TBD: what is validmin for a string? - VAR_TYPE: metadata - first_spin_id: <<: *support_data_defaults CATDESC: The ordinal number of the first spin during histogram accumulation - FIELDNAM: Number of the first spin in histogram + FIELDNAM: Number of first spin FILLVAL: *max_uint32 - FORMAT: I11 - LABLAXIS: Spin number + FORMAT: I10 + LABLAXIS: Spin no. VALIDMAX: *max_uint32_min_one last_spin_id: <<: *support_data_defaults CATDESC: The ordinal number of the last spin during histogram accumulation - FIELDNAM: Number of the last spin in histogram + FIELDNAM: Number of last spin FILLVAL: *max_uint32 - FORMAT: I11 - LABLAXIS: Spin number + FORMAT: I10 + LABLAXIS: Spin no. VALIDMAX: *max_uint32_min_one imap_start_time: <<: *support_data_defaults - CATDESC: Histogram start time, IMAP-clock seconds - FIELDNAM: Histogram start time, IMAP-clock seconds + CATDESC: Histogram start time (IMAP clock) + FIELDNAM: Start time (IMAP clock) # TODO: Presumably float64 max or min should be here? - FILLVAL: *int_fillval - FORMAT: F16.6 - UNITS: seconds + FILLVAL: 1.0E+31 + FORMAT: F17.6 LABLAXIS: Start time + UNITS: s VALIDMAX: 4294967295.0 VALIDMIN: 0.0 imap_time_offset: <<: *support_data_defaults - CATDESC: Accumulation time in seconds for GLOWS histogram - FIELDNAM: Histogram accumulation time - # TODO: Presumably float64 max or min should be here? - FILLVAL: *int_fillval - FORMAT: F12.6 - UNITS: seconds - LABLAXIS: Duration - VALIDMAX: 4000.0 + CATDESC: Accumulation time for histogram (IMAP clock) + FIELDNAM: Accum. time (IMAP clock) + # TODO: Presumably float64 max or min should be here? + FILLVAL: 1.0E+31 + FORMAT: F10.6 + LABLAXIS: Accum. time + UNITS: s + VALIDMAX: 999.0 VALIDMIN: 0.0 glows_start_time: <<: *support_data_defaults - CATDESC: Histogram start time, GLOWS-clock seconds - FIELDNAM: Histogram start time, GLOWS-clock seconds - FILLVAL: *int_fillval - FORMAT: F16.6 - UNITS: seconds + CATDESC: Histogram start time (GLOWS clock) + FIELDNAM: Start time (GLOWS clock) + FILLVAL: 1.0E+31 + FORMAT: F17.6 LABLAXIS: Start time + UNITS: s VALIDMAX: 4294967295.0 VALIDMIN: 0.0 glows_time_offset: <<: *support_data_defaults - CATDESC: Accumulation time in seconds for GLOWS histogram - FIELDNAM: Histogram accumulation time - FILLVAL: *int_fillval - FORMAT: F12.6 - UNITS: seconds - LABLAXIS: Duration - VALIDMAX: 4000.0 # 15.38 s per spin x 256 spins = 3937.3 s, then rounded up + CATDESC: Accumulation time for histogram (GLOWS clock) + FIELDNAM: Accum. time (GLOWS clock) + FILLVAL: 1.0E+31 + FORMAT: F10.6 + LABLAXIS: Accum. time + UNITS: s + VALIDMAX: 999.0 # 15.38 s per spin x 64 spins = 984.32 s, then rounded up VALIDMIN: 0.0 flags_set_onboard: - # TODO: Verify uint32 fillval and uint16 validmax <<: *support_data_defaults + # TODO: Verify uint32 fillval and uint16 validmax CATDESC: Binary mask with histogram flags set onboard - FIELDNAM: Mask with histogram flags set onboard + FIELDNAM: Mask with flags set onboard FILLVAL: *max_uint32 - FORMAT: I6 - LABLAXIS: Mask value + FORMAT: I5 + LABLAXIS: Onboard mask VALIDMAX: *max_uint16 is_generated_on_ground: <<: *support_data_defaults - CATDESC: Flag indicating where histogram data was generated (1 - on the ground, 0 - onboard) + CATDESC: Flag indicating where histogram was generated (1 - on the ground, 0 - onboard) FIELDNAM: Histogram-creation-site flag - FILLVAL: -128 - FORMAT: I2 + FILLVAL: 255 + FORMAT: I1 LABLAXIS: Flag VALIDMAX: 1 @@ -195,10 +183,10 @@ number_of_spins_per_block: <<: *support_data_defaults CATDESC: Number of spins per block during accumulation of histogram FIELDNAM: Number of spins per block - FILLVAL: 65535 - FORMAT: I4 - LABLAXIS: Num of spins - VALIDMAX: 256 + FILLVAL: 255 + FORMAT: I2 + LABLAXIS: No. of spins + VALIDMAX: 64 VALIDMIN: 1 number_of_bins_per_histogram: @@ -206,27 +194,27 @@ number_of_bins_per_histogram: CATDESC: Number of histogram bins FIELDNAM: Number of histogram bins FILLVAL: *max_uint16 - FORMAT: I5 - LABLAXIS: Num of bins + FORMAT: I4 + LABLAXIS: No. of bins VALIDMAX: 3600 VALIDMIN: 225 number_of_events: <<: *support_data_defaults CATDESC: Total number of events/counts in the histogram - FIELDNAM: Total number of counts in histogram - FILLVAL: *int_fillval - FORMAT: I11 - LABLAXIS: Num of counts - VALIDMAX: *max_uint32 + FIELDNAM: Histogram total counts + FILLVAL: *max_uint32 + FORMAT: I10 + LABLAXIS: Total cts + VALIDMAX: *max_uint32_min_one filter_temperature_average: <<: *support_data_defaults CATDESC: Uint-encoded spin-block-averaged filter temperature FIELDNAM: Average filter temperature FILLVAL: *max_uint16 - FORMAT: I4 - LABLAXIS: Avgd Temperature + FORMAT: I3 + LABLAXIS: Temp avg VALIDMAX: 255 filter_temperature_variance: @@ -234,36 +222,37 @@ filter_temperature_variance: CATDESC: Uint-encoded spin-block-averaged variance of filter temperature FIELDNAM: Variance of filter temperature FILLVAL: *max_uint32 - FORMAT: I6 - LABLAXIS: Variance + FORMAT: I5 + LABLAXIS: Temp var VALIDMAX: *max_uint16 hv_voltage_average: <<: *support_data_defaults - CATDESC: Uint-encoded spin-block-averaged CEM voltage - FIELDNAM: Uint-encoded averaged CEM voltage - FILLVAL: *max_uint32 - FORMAT: I6 - LABLAXIS: Avg voltage - VALIDMAX: *max_uint16 + CATDESC: Uint-encoded spin-block-averaged HV voltage on CEM + FIELDNAM: Average HV voltage + FILLVAL: *max_uint16 + FORMAT: I5 + LABLAXIS: HV avg + VALIDMAX: 65534 hv_voltage_variance: <<: *support_data_defaults - CATDESC: variance of HV voltage on the CEM, uint encoded + CATDESC: Uint-encoded spin-block-averaged variance of HV voltage on CEM FIELDNAM: Uint encoded HV voltage variance - FILLVAL: *int_fillval - LABLAXIS: Variance - VALIDMAX: *max_uint32 + FILLVAL: *max_uint32 + FORMAT: I10 + LABLAXIS: HV var + VALIDMAX: *max_uint32_min_one spin_period_average: <<: *support_data_defaults CATDESC: Uint-encoded spin-block-averaged spin period DEPEND_0: epoch DISPLAY_TYPE: time_series - FIELDNAM: Uint-encoded average spin period + FIELDNAM: Average spin period FILLVAL: *max_uint32 - FORMAT: I6 - LABLAXIS: Spin period + FORMAT: I5 + LABLAXIS: Period avg UNITS: ' ' VALIDMAX: 50000 # TBC 15.38 s where 20.9712 s = 65535, rounded up VALIDMIN: 45000 # TBC 14.63 s where 20.9712 s = 65535, rounded down @@ -272,141 +261,143 @@ spin_period_average: spin_period_variance: <<: *support_data_defaults CATDESC: Uint-encoded spin-block-averaged variance of spin period - FIELDNAM: Uint-encoded variance of spin period - FILLVAL: *int_fillval + FIELDNAM: Variance of spin period + FILLVAL: *max_uint32 FORMAT: I10 - LABLAXIS: Variance - VALIDMAX: *max_uint32 + LABLAXIS: Period var + VALIDMAX: *max_uint32_min_one pulse_length_average: <<: *support_data_defaults CATDESC: Uint-encoded spin-block-averaged pulse length FIELDNAM: Averaged pulse length FILLVAL: *max_uint16 - FORMAT: I4 - LABLAXIS: Avg pulse len + FORMAT: I3 + LABLAXIS: Pulse avg VALIDMAX: 255 pulse_length_variance: <<: *support_data_defaults - CATDESC: Uint encoded spin-block-averaged variance of pulse length + CATDESC: Uint-encoded spin-block-averaged variance of pulse length FIELDNAM: Variance of pulse length FILLVAL: *max_uint32 - FORMAT: I10 - LABLAXIS: Variance + FORMAT: I5 + LABLAXIS: Pulse var VALIDMAX: *max_uint16 + # End of not-in--dicts in generate_de_dataset # support_data seq_count_in_pkts_file: <<: *support_data_defaults # TBD: problem with several values associated with one epoch value - CATDESC: Ordinal number of a packet in a sequence of multiple CCSDS packets - FIELDNAM: Packet sequence counter - FILLVAL: *max_uint32 - FORMAT: I6 - LABLAXIS: Counter + CATDESC: Ordinal number of a packet in a sequence of CCSDS packets with the same APID + FIELDNAM: Packet number in sequence + FILLVAL: *max_uint16 + FORMAT: I5 + LABLAXIS: Pkt no. VALIDMAX: 65534 # uint16_max - 1, because it must be less than VALIDMAX for number_of_de_packets number_of_de_packets: <<: *support_data_defaults - CATDESC: Number of packets for a given portion (second) of direct-event data + CATDESC: Number of packets in a given segment (second) of direct-event data FIELDNAM: Number of DE packets FILLVAL: *max_uint32 FORMAT: I5 - LABLAXIS: Num of packets - VALIDMAX: *max_uint16 + LABLAXIS: No. of pkts + VALIDMAX: 65534 # End of support data # data_every_second in glows_l1a.py imap_sclk_last_pps: <<: *support_data_defaults - CATDESC: IMAP-clock seconds for last PPS - FIELDNAM: IMAP-clock seconds for last PPS + CATDESC: Latest PPS arrival time (IMAP clock) + FIELDNAM: Latest PPS time (IMAP clock) FILLVAL: *max_uint32 - FORMAT: I11 - LABLAXIS: IMAP seconds - UNITS: seconds + FORMAT: I10 + LABLAXIS: PPS time + UNITS: s VALIDMAX: *max_uint32_min_one glows_sclk_last_pps: <<: *support_data_defaults - CATDESC: GLOWS-clock seconds for last PPS - FIELDNAM: GLOWS-clock seconds for last PPS + CATDESC: Latest PPS arrival time (GLOWS clock, seconds) DISPLAY_TYPE: no_plot + FIELDNAM: Latest PPS time (GLOWS seconds) FILLVAL: *max_uint32 - FORMAT: I11 - LABLAXIS: GLOWS seconds - UNITS: seconds + FORMAT: I10 + LABLAXIS: PPS time + UNITS: s VALIDMAX: *max_uint32_min_one glows_ssclk_last_pps: <<: *support_data_defaults - CATDESC: GLOWS-clock subseconds for last PPS - FIELDNAM: GLOWS-clock subseconds for last PPS + CATDESC: Latest PPS arrival time (GLOWS clock, subseconds) DISPLAY_TYPE: no_plot + FIELDNAM: Latest PPS time (GLOWS subseconds) FILLVAL: *max_uint32 - LABLAXIS: GLOWS subseconds + FORMAT: I7 + LABLAXIS: PPS time VALIDMAX: 1999999 imap_sclk_next_pps: <<: *support_data_defaults - CATDESC: IMAP-clock seconds for next PPS - FIELDNAM: IMAP-clock seconds for next PPS + CATDESC: Next PPS estimated arrival time (IMAP clock) + FIELDNAM: Next PPS time (IMAP clock) FILLVAL: *max_uint32 - FORMAT: I11 - LABLAXIS: IMAP seconds - UNITS: seconds + FORMAT: I10 + LABLAXIS: PPS time + UNITS: s VALIDMAX: *max_uint32_min_one catbed_heater_active: <<: *support_data_defaults - CATDESC: Catbed-heater activity flag (1 - active, 0 - not active) - FIELDNAM: Catbed-heater activity flag - FILLVAL: -128 - FORMAT: I2 + CATDESC: Repointing maneuver flag (1 - active, 0 - not active) + FIELDNAM: Repointing maneuver flag + FILLVAL: 255 + FORMAT: I1 LABLAXIS: Flag spin_period_valid: <<: *support_data_defaults - CATDESC: Spin-period-validity flag (1 - valid, 0 - invalid) + CATDESC: Spin-period validity flag (1 - valid, 0 - invalid) FIELDNAM: Spin-period-validity flag - FILLVAL: -128 - FORMAT: I2 + FILLVAL: 255 + FORMAT: I1 LABLAXIS: Flag spin_phase_at_next_pps_valid: <<: *support_data_defaults CATDESC: Spin-phase-at-next-PPS validity flag (1 - valid, 0 - invalid) FIELDNAM: Spin-phase-at-next-PPS validity flag - FILLVAL: -128 - FORMAT: I2 + FILLVAL: 255 + FORMAT: I1 LABLAXIS: Flag spin_period_source: <<: *support_data_defaults CATDESC: Spin-period-source flag (0 - from ITF, 1 - estimated by GLOWS AppSW) FIELDNAM: Spin-period-source flag - FILLVAL: -128 - FORMAT: I2 + FILLVAL: 255 + FORMAT: I1 LABLAXIS: Flag spin_period: <<: *support_data_defaults - CATDESC: Uint encoded spin period value - FIELDNAM: Uint encoded spin period value + CATDESC: Uint-encoded spin period + FIELDNAM: Spin period FILLVAL: *max_uint16 - FORMAT: I6 + FORMAT: I5 LABLAXIS: Spin period VALIDMAX: 50000 # TBC 15.38 s where 20.9712 s = 65535, rounded up VALIDMIN: 45000 # TBC 14.63 s where 20.9712 s = 65535, rounded down spin_phase_at_next_pps: <<: *support_data_defaults - CATDESC: Uint encoded next spin phase value - FIELDNAM: Uint encoded next spin phase value + CATDESC: Uint-encoded next-PPS spin phase + FIELDNAM: Next-PPS spin phase FILLVAL: *max_uint32 - FORMAT: I6 + FORMAT: I5 LABLAXIS: Spin phase VALIDMAX: *max_uint16 @@ -415,83 +406,83 @@ number_of_completed_spins: CATDESC: Number of completed spins FIELDNAM: Number of completed spins FILLVAL: *max_uint32 - FORMAT: I11 - LABLAXIS: Num of spins + FORMAT: I10 + LABLAXIS: No. of spins VALIDMAX: *max_uint32_min_one filter_temperature: <<: *support_data_defaults - CATDESC: Uint encoded filter temperature + CATDESC: Uint-encoded filter temperature + DISPLAY_TYPE: time_series FIELDNAM: Filter temperature FILLVAL: *max_uint32 - FORMAT: I6 + FORMAT: I5 LABLAXIS: Temperature VALIDMAX: *max_uint16 - DISPLAY_TYPE: time_series hv_voltage: <<: *support_data_defaults - CATDESC: Uint encoded CEM voltage - FIELDNAM: Uint encoded CEM voltage + CATDESC: Uint-encoded HV voltage on CEM + FIELDNAM: HV voltage FILLVAL: *max_uint32 - FORMAT: I6 - LABLAXIS: Voltage + FORMAT: I5 + LABLAXIS: HV VALIDMAX: *max_uint16 glows_time_on_pps_valid: <<: *support_data_defaults CATDESC: GLOWS-time-on-PPS-arrival validity flag (1 - valid, 0 - not valid) FIELDNAM: GLOWS time validity flag - FILLVAL: -128 - FORMAT: I2 + FILLVAL: 255 + FORMAT: I1 LABLAXIS: Flag time_status_valid: <<: *support_data_defaults - CATDESC: Time-status-data-structure-validity flag (1 - valid, 0 - invalid) - FIELDNAM: Time-status-structure-validity flag - FILLVAL: -128 - FORMAT: I2 + CATDESC: Time-status-data (ITF) validity flag (1 - valid, 0 - invalid) + FIELDNAM: Time-status-data validity flag + FILLVAL: 255 + FORMAT: I1 LABLAXIS: Flag housekeeping_valid: <<: *support_data_defaults CATDESC: GLOWS housekeeping validity flag (1 - valid, 0 - invalid) FIELDNAM: Housekeeping validity flag - FILLVAL: -128 - FORMAT: I2 + FILLVAL: 255 + FORMAT: I1 LABLAXIS: Flag is_pps_autogenerated: <<: *support_data_defaults CATDESC: Flag indicating whether PPS is autogenerated (1 - autogenerated, 0 - external) - FIELDNAM: Autogenerated-PPS flag - FILLVAL: -128 - FORMAT: I2 + FIELDNAM: PPS-autogenerated flag + FILLVAL: 255 + FORMAT: I1 LABLAXIS: Flag hv_test_in_progress: <<: *support_data_defaults CATDESC: HV-test-in-progress flag (1 - test is on, 0 - test is off) FIELDNAM: HV-test-in-progress flag - FILLVAL: -128 - FORMAT: I2 + FILLVAL: 255 + FORMAT: I1 LABLAXIS: Flag pulse_test_in_progress: <<: *support_data_defaults CATDESC: Pulse-test-in-progress flag (1 - test is on, 0 - test is off) FIELDNAM: Pulse-test-in-progress flag - FILLVAL: -128 # int8_min - FORMAT: I2 + FILLVAL: 255 # uint8_max + FORMAT: I1 LABLAXIS: Flag memory_error_detected: <<: *support_data_defaults CATDESC: Memory-error flag (1 - error detected, 0 - no error) FIELDNAM: Memory-error flag - FILLVAL: -128 - FORMAT: I2 + FILLVAL: 255 + FORMAT: I1 LABLAXIS: Flag # End of data_every_second @@ -504,11 +495,3 @@ missing_packets_sequence: # Used to be missing_packets_sequence LABLAXIS: Metadata VALIDMAX: 1000000000 VAR_TYPE: metadata - -flight_software_version: - <<: *support_data_defaults - CATDESC: GLOWS flight software version - FIELDNAM: GLOWS flight software version - FILLVAL: *max_uint32 - LABLAXIS: Version - VALIDMAX: 16777215 diff --git a/imap_processing/cdf/config/imap_glows_l1b_variable_attrs.yaml b/imap_processing/cdf/config/imap_glows_l1b_variable_attrs.yaml index 1b410b5f68..cae0cca2d7 100644 --- a/imap_processing/cdf/config/imap_glows_l1b_variable_attrs.yaml +++ b/imap_processing/cdf/config/imap_glows_l1b_variable_attrs.yaml @@ -1,8 +1,8 @@ int_fillval: &int_fillval -9223372036854775808 -max_uint32: &max_uint32 4294967295 -max_uint32_min_one: &max_uint32_min_one 4294967294 max_uint16: &max_uint16 65535 max_uint16_min_one: &max_uint16_min_one 65534 +max_uint32: &max_uint32 4294967295 +max_uint32_min_one: &max_uint32_min_one 4294967294 min_epoch: &min_epoch -315575942816000000 max_epoch: &max_epoch 3155630469184000000 @@ -28,32 +28,35 @@ bins_label: default_attrs: &default_attrs # TODO: Remove unneeded attributes once SAMMI is fixed - RESOLUTION: ' ' DISPLAY_TYPE: no_plot + FILLVAL: *int_fillval + REFERENCE_POSITION: Rotating Earth Geoid + RESOLUTION: ' ' TIME_BASE: J2000 TIME_SCALE: Terrestrial Time - REFERENCE_POSITION: Rotating Earth Geoid UNITS: ' ' - FILLVAL: *int_fillval VALIDMIN: *min_epoch +derived_from_spice_kernels: &derived_from_spice_kernels + VAR_NOTES: Derived from SPICE Kernels + support_data_defaults: &support_data_defaults <<: *default_attrs DEPEND_0: epoch - VALIDMIN: 0 - VALIDMAX: 1 DISPLAY_TYPE: time_series - VAR_TYPE: support_data FORMAT: I10 RESOLUTION: ISO8601 + VALIDMAX: 1 + VALIDMIN: 0 + VAR_TYPE: support_data time_data_defaults: &time_data_defaults <<: *support_data_defaults FILLVAL: 1.0E+31 FORMAT: F17.6 UNITS: s - VALIDMIN: 0.0 VALIDMAX: 4294967295.0 + VALIDMIN: 0.0 flag_data_defaults: &flag_data_defaults <<: *support_data_defaults @@ -63,28 +66,28 @@ flag_data_defaults: &flag_data_defaults bins_attrs: <<: *default_attrs - VALIDMIN: 0 - VALIDMAX: 3599 CATDESC: Bin number in histogram FIELDNAM: Bin number + FILLVAL: *max_uint16 FORMAT: I4 - VAR_TYPE: support_data LABLAXIS: Bin no. - FILLVAL: *max_uint16 MONOTON: INCREASE SCALETYP: linear + VALIDMAX: 3599 + VALIDMIN: 0 + VAR_TYPE: support_data within_the_second_attrs: # Used to be per_second_attrs <<: *default_attrs - VALIDMIN: 0 - VALIDMAX: 50000 CATDESC: Ordinal number of direct event within a second + DISPLAY_TYPE: no_plot FIELDNAM: Ordinal number of direct event + FILLVAL: *max_uint16 FORMAT: I5 - VAR_TYPE: support_data - DISPLAY_TYPE: no_plot LABLAXIS: Event no. - FILLVAL: *max_uint16 + VALIDMAX: 50000 + VALIDMIN: 0 + VAR_TYPE: support_data #direct_event_components_attrs: # <<: *default_attrs @@ -113,32 +116,20 @@ within_the_second_attrs: # Used to be per_second_attrs histogram: <<: *default_attrs - VALIDMIN: 0 - VALIDMAX: 255 CATDESC: Histogram of photon counts in scanning-circle bins DEPEND_0: epoch DEPEND_1: bins - LABL_PTR_1: bins_label - LABLAXIS: Counts - FIELDNAM: Histogram of photon counts - FORMAT: I3 DISPLAY_TYPE: spectrogram + FIELDNAM: Histogram of photon counts FILLVAL: *max_uint16 + FORMAT: I3 + LABLAXIS: Counts + LABL_PTR_1: bins_label UNITS: '#' + VALIDMAX: 255 + VALIDMIN: 0 VAR_TYPE: data -pkts_file_name: - <<: *support_data_defaults - CATDESC: Name of input file with L0 CCSDS packets data - DISPLAY_TYPE: no_plot - FIELDNAM: L0 data input filename - FILLVAL: # TBD: what is fillval for strings? - FORMAT: S256 # TBC - LABLAXIS: File name # MS: is this needed for no_plot? - VALIDMAX: # TBD: what is validmax for a string? - VALIDMIN: # TBD: what is validmin for a string? - VAR_TYPE: metadata - first_spin_id: <<: *support_data_defaults CATDESC: Ordinal number of the first spin during histogram accumulation @@ -167,9 +158,9 @@ imap_time_offset: <<: *time_data_defaults CATDESC: Accumulation time for histogram (IMAP clock) FIELDNAM: Accum. time (IMAP clock) + FORMAT: F10.6 LABLAXIS: Accum. time VALIDMAX: 999.0 - FORMAT: F10.6 glows_start_time: <<: *time_data_defaults @@ -181,9 +172,9 @@ glows_time_offset: <<: *time_data_defaults CATDESC: Accumulation time for histogram (GLOWS clock) FIELDNAM: Accum. time (GLOWS clock) + FORMAT: F10.6 LABLAXIS: Accum. time VALIDMAX: 999.0 - FORMAT: F10.6 is_generated_on_ground: <<: *flag_data_defaults @@ -203,9 +194,11 @@ number_of_spins_per_block: VALIDMIN: 1 unique_block_identifier: - <<: *support_data_defaults CATDESC: YYYY-MM-DDThh:mm:ss based on IMAP UTC time + DEPEND_0: epoch FIELDNAM: YYYY-MM-DDThh:mm:ss based on IMAP UTC time + FORMAT: A19 + VAR_TYPE: support_data number_of_bins_per_histogram: <<: *support_data_defaults @@ -219,27 +212,27 @@ number_of_bins_per_histogram: ecliptic_attrs: <<: *default_attrs - VALIDMIN: 0 - VALIDMAX: 2 CATDESC: Component index for cartesian ecliptic coordinates FIELDNAM: Component index + FILLVAL: 255 + FORMAT: I1 LABLAXIS: Index UNITS: ' ' - FILLVAL: 255 + VALIDMAX: 2 + VALIDMIN: 0 VAR_TYPE: support_data - FORMAT: I1 latitudinal_attrs: <<: *default_attrs - VALIDMIN: 0 - VALIDMAX: 360 CATDESC: Component index for cartesian latitudinal coordinates FIELDNAM: Component index + FILLVAL: 999 + FORMAT: I3 LABLAXIS: Index UNITS: ' ' - FILLVAL: 999 + VALIDMAX: 360 + VALIDMIN: 0 VAR_TYPE: support_data - FORMAT: I3 number_of_events: <<: *support_data_defaults @@ -258,8 +251,8 @@ filter_temperature_average: FORMAT: F6.2 LABLAXIS: Temp UNITS: Celsius - VALIDMIN: -30.0 VALIDMAX: 60.0 + VALIDMIN: -30.0 filter_temperature_std_dev: <<: *support_data_defaults @@ -290,8 +283,8 @@ hv_voltage_std_dev: FORMAT: E9.3 LABLAXIS: HV std dev UNITS: 'V' - VALIDMIN: 0.0 VALIDMAX: 3500.0 + VALIDMIN: 0.0 spin_period_average: <<: *support_data_defaults @@ -303,8 +296,8 @@ spin_period_average: FORMAT: F9.6 LABLAXIS: Period UNITS: s - VALIDMIN: 14.6 VALIDMAX: 15.4 + VALIDMIN: 14.6 #VAR_TYPE: support_data spin_period_std_dev: @@ -315,8 +308,8 @@ spin_period_std_dev: FORMAT: E9.3 LABLAXIS: Period std dev UNITS: s - VALIDMIN: 0.0 VALIDMAX: 9.9 + VALIDMIN: 0.0 # TODO review these spin_period_ground_average: @@ -329,8 +322,8 @@ spin_period_ground_average: FORMAT: F9.6 LABLAXIS: Period UNITS: s - VALIDMIN: 14.6 VALIDMAX: 15.4 + VALIDMIN: 14.6 #VAR_TYPE: support_data spin_period_ground_std_dev: @@ -341,8 +334,8 @@ spin_period_ground_std_dev: FORMAT: E9.3 LABLAXIS: Period std dev UNITS: s - VALIDMIN: 0.0 VALIDMAX: 9.9 + VALIDMIN: 0.0 pulse_length_average: <<: *support_data_defaults @@ -352,8 +345,8 @@ pulse_length_average: FORMAT: F5.2 LABLAXIS: Pulse len UNITS: us - VALIDMIN: 0.0 VALIDMAX: 12.75 + VALIDMIN: 0.0 pulse_length_std_dev: <<: *support_data_defaults @@ -363,104 +356,111 @@ pulse_length_std_dev: FORMAT: E9.3 LABLAXIS: Pulse std dev UNITS: us - VALIDMIN: 0.0 VALIDMAX: 12.75 + VALIDMIN: 0.0 position_angle_offset_average: <<: *support_data_defaults + <<: *derived_from_spice_kernels CATDESC: Spin-block-averaged position-angle offset FIELDNAM: Average position-angle offset FILLVAL: 1.0E+31 FORMAT: F10.6 LABLAXIS: Offset angle UNITS: 'degrees' - VALIDMIN: 0.0 VALIDMAX: 360.0 + VALIDMIN: 0.0 position_angle_offset_std_dev: <<: *support_data_defaults + <<: *derived_from_spice_kernels CATDESC: Standard deviation of position-angle offset FIELDNAM: Std dev of position-angle offset FILLVAL: 1.0E+31 FORMAT: E9.3 LABLAXIS: Offset std dev UNITS: 'degrees' - VALIDMIN: 0.0 VALIDMAX: 360.0 + VALIDMIN: 0.0 spin_axis_orientation_average: # this is a two-element variable, DEPEND needed? <<: *support_data_defaults + <<: *derived_from_spice_kernels CATDESC: Spin-block-averaged spin-axis pointing (ecliptic lon and lat) FIELDNAM: Average spin-axis pointing FILLVAL: 1.0E+31 FORMAT: F7.3 LABLAXIS: Lon/lat # see comment in the section start UNITS: 'degrees' - VALIDMIN: -90.0 VALIDMAX: 360.0 + VALIDMIN: -90.0 spin_axis_orientation_std_dev: # this is a two-element variable, DEPEND needed? <<: *support_data_defaults + <<: *derived_from_spice_kernels CATDESC: Standard deviation of spin axis pointing FIELDNAM: Std dev of spin axis pointing FILLVAL: 1.0E+31 FORMAT: E9.3 LABLAXIS: Lon/lat std dev UNITS: 'degrees' - VALIDMIN: 0.0 VALIDMAX: 360.0 + VALIDMIN: 0.0 spacecraft_location_average: <<: *support_data_defaults + <<: *derived_from_spice_kernels + CATDESC: Spin-block-averaged spacecraft location (ecliptic frame) DEPEND_1: ecliptic DISPLAY_TYPE: no_plot - CATDESC: Spin-block-averaged spacecraft location (ecliptic frame) FIELDNAM: Average spacecraft location FILLVAL: 1.0E+31 FORMAT: E13.6 LABLAXIS: Loc UNITS: 'km' - VALIDMIN: -9.999999999E+8 VALIDMAX: 9.999999999E+8 + VALIDMIN: -9.999999999E+8 spacecraft_location_std_dev: <<: *support_data_defaults + <<: *derived_from_spice_kernels + CATDESC: Standard deviation of spacecraft location DEPEND_1: ecliptic DISPLAY_TYPE: no_plot - CATDESC: Standard deviation of spacecraft location FIELDNAM: Std dev of spacecraft location FILLVAL: 1.0E+31 FORMAT: E9.3 LABLAXIS: Loc std dev UNITS: 'km' - VALIDMIN: 0.0 VALIDMAX: 50000.0 # 50 km/s * 15.38 s * 64 spins < 50000.0 + VALIDMIN: 0.0 spacecraft_velocity_average: <<: *support_data_defaults + <<: *derived_from_spice_kernels + CATDESC: Spin-block-averaged spacecraft velocity (ecliptic frame) DEPEND_1: ecliptic DISPLAY_TYPE: no_plot - CATDESC: Spin-block-averaged spacecraft velocity (ecliptic frame) FIELDNAM: Average spacecraft velocity FILLVAL: 1.0E+31 FORMAT: E13.6 LABLAXIS: Vsc UNITS: 'km/s' - VALIDMIN: -50.0 VALIDMAX: 50.0 + VALIDMIN: -50.0 spacecraft_velocity_std_dev: <<: *support_data_defaults + CATDESC: Standard deviation of spacecraft velocity DEPEND_1: ecliptic DISPLAY_TYPE: no_plot - CATDESC: Standard deviation of spacecraft velocity FIELDNAM: Std dev of spacecraft velocity FILLVAL: 1.0E+31 FORMAT: E9.3 LABLAXIS: Vsc std dev UNITS: 'km/s' - VALIDMIN: 0.0 VALIDMAX: 10.0 + VALIDMIN: 0.0 # End of not-in--dicts in generate_de_dataset @@ -489,32 +489,32 @@ number_of_de_packets: imap_time_last_pps: <<: *time_data_defaults CATDESC: Latest PPS arrival time (IMAP clock) - FIELDNAM: Latest PPS time (IMAP clock) DISPLAY_TYPE: no_plot - LABLAXIS: PPS time + FIELDNAM: Latest PPS time (IMAP clock) + FILLVAL: *max_uint32 FORMAT: I10 + LABLAXIS: PPS time VALIDMAX: *max_uint32_min_one - FILLVAL: *max_uint32 glows_time_last_pps: <<: *time_data_defaults CATDESC: Latest PPS arrival time (GLOWS clock) - FIELDNAM: Latest PPS time (GLOWS clock) DISPLAY_TYPE: no_plot + FIELDNAM: Latest PPS time (GLOWS clock) + FILLVAL: 1.0e+31 LABLAXIS: PPS time VALIDMAX: 4294967295.0 - FILLVAL: 1.0e+31 imap_time_next_pps: <<: *time_data_defaults CATDESC: Next PPS estimated arrival time (IMAP clock) - FIELDNAM: Next PPS time (IMAP clock) DISPLAY_TYPE: no_plot + FIELDNAM: Next PPS time (IMAP clock) + FILLVAL: *max_uint32 FILLVAL: *max_uint32 - LABLAXIS: PPS time FORMAT: I10 + LABLAXIS: PPS time VALIDMAX: *max_uint32_min_one - FILLVAL: *max_uint32 #catbed_heater_active: # <<: *flag_data_defaults @@ -544,22 +544,23 @@ spin_period: FORMAT: F9.6 LABLAXIS: Spin period UNITS: s - VALIDMIN: 14.6 VALIDMAX: 15.4 + VALIDMIN: 14.6 # TODO: Review this imap_spin_angle_bin_cntr: <<: *support_data_defaults - DISPLAY_TYPE: no_plot - DEPEND_1: bins + <<: *derived_from_spice_kernels CATDESC: IMAP spin angle for bin centers + DEPEND_1: bins + DISPLAY_TYPE: no_plot FIELDNAM: Spin angle for bin centers FILLVAL: 1.0E+31 FORMAT: F7.3 LABLAXIS: Spin angle UNITS: 'degrees' - VALIDMIN: 0.0 VALIDMAX: 360.0 + VALIDMIN: 0.0 spin_phase_at_next_pps: <<: *support_data_defaults @@ -569,8 +570,8 @@ spin_phase_at_next_pps: FORMAT: F7.3 LABLAXIS: Spin phase UNITS: 'degrees' - VALIDMIN: 0.0 VALIDMAX: 360.0 + VALIDMIN: 0.0 number_of_completed_spins: <<: *support_data_defaults @@ -589,8 +590,8 @@ filter_temperature: FORMAT: F6.2 LABLAXIS: Temp UNITS: Celsius - VALIDMIN: -30.0 VALIDMAX: 60.0 + VALIDMIN: -30.0 hv_voltage: <<: *support_data_defaults @@ -641,30 +642,30 @@ hv_voltage: direct_event_glows_times: <<: *time_data_defaults + CATDESC: Times of direct events (photon detection times, GLOWS clock) DEPEND_1: within_the_second DISPLAY_TYPE: no_plot - VAR_TYPE: data - CATDESC: Times of direct events (photon detection times, GLOWS clock) FIELDNAM: Direct-event times (GLOWS clock) - LABLAXIS: DE time FILLVAL: 1.0e+31 + LABLAXIS: DE time VALIDMAX: 4294967295.0 + VAR_TYPE: data # TODO: review direct_event_pulse_lengths: <<: *support_data_defaults + CATDESC: Pulse lengths for direct events DEPEND_1: within_the_second DISPLAY_TYPE: no_plot - LABL_PTR_1: within_the_second_label - VAR_TYPE: support_data - CATDESC: Pulse lengths for direct events FIELDNAM: Pulse lengths for direct events - LABLAXIS: Pulse len FILLVAL: 1.0E+31 FORMAT: F5.2 + LABLAXIS: Pulse len + LABL_PTR_1: within_the_second_label UNITS: us - VALIDMIN: 0.0 VALIDMAX: 12.75 + VALIDMIN: 0.0 + VAR_TYPE: support_data missing_packets_sequence: # Used to be missing_packets_sequence <<: *support_data_defaults @@ -676,39 +677,30 @@ missing_packets_sequence: # Used to be missing_packets_sequence VALIDMAX: 1000000000 VAR_TYPE: metadata -flight_software_version: - <<: *support_data_defaults - CATDESC: GLOWS flight software version - FIELDNAM: GLOWS flight software version - FILLVAL: *max_uint32 - FORMAT: I8 - LABLAXIS: FSW ver - VALIDMAX: 16777215 - # Flags # MS: this needs to be thoroughly discussed bad_time_flag_hist_attrs: # MS: this should be different for DE and HIST <<: *default_attrs - FILLVAL: -1 CATDESC: Flag index for histogram flags FIELDNAM: Flag index - UNITS: ' ' + FILLVAL: -1 FORMAT: I2 LABLAXIS: Index - VALIDMIN: 0 + UNITS: ' ' VALIDMAX: 16 + VALIDMIN: 0 VAR_TYPE: support_data flag_de_attrs: # MS: this should be different for DE and HIST <<: *default_attrs - FILLVAL: -1 CATDESC: Flag index for DE flags FIELDNAM: Flag index - UNITS: ' ' + FILLVAL: -1 FORMAT: I2 LABLAXIS: Index - VALIDMIN: 0 + UNITS: ' ' VALIDMAX: 16 + VALIDMIN: 0 VAR_TYPE: support_data flags_set_onboard: @@ -724,14 +716,14 @@ flags_set_onboard: bad_angle_flags_attrs: <<: *default_attrs CATDESC: Binary mask for bad-angle flags - FIELDNAM: Mask with bad-angle flags DISPLAY_TYPE: no_plot - LABLAXIS: Bad-angle mask + FIELDNAM: Mask with bad-angle flags FILLVAL: -1 - UNITS: ' ' FORMAT: I2 - VALIDMIN: 0 + LABLAXIS: Bad-angle mask + UNITS: ' ' VALIDMAX: 16 + VALIDMIN: 0 VAR_TYPE: support_data @@ -741,32 +733,32 @@ bad_angle_flags_attrs: histogram_flag_array: # MS does not understand what is this exactly <<: *flag_data_defaults CATDESC: Bad-angle mask for histogram bins + DEPEND_1: bad_angle_flags + DEPEND_2: bins DISPLAY_TYPE: no_plot FIELDNAM: Bad-angle mask for histogram LABLAXIS: Mask - DEPEND_1: bad_angle_flags - DEPEND_2: bins - VALIDMIN: 0 VALIDMAX: 1 + VALIDMIN: 0 de_flags: <<: *flag_data_defaults - DEPEND_1: flags CATDESC: Flags for per-second-grouped direct events - FIELDNAM: Flags for direct events + DEPEND_1: flags DISPLAY_TYPE: no_plot - VALIDMIN: 0 + FIELDNAM: Flags for direct events VALIDMAX: 1 + VALIDMIN: 0 # Decoded on-board flags into a length 16 array flags: # MS: is this related to flags_set_onboard? <<: *support_data_defaults CATDESC: Bad-time mask for histogram + DEPEND_1: bad_time_flags DISPLAY_TYPE: no_plot FIELDNAM: Bad-time mask for histogram + FILLVAL: -128 + FORMAT: I1 LABLAXIS: Mask - DEPEND_1: bad_time_flags - VALIDMIN: 0 VALIDMAX: 1 - FORMAT: I1 - FILLVAL: -128 + VALIDMIN: 0 diff --git a/imap_processing/cdf/config/imap_glows_l2_variable_attrs.yaml b/imap_processing/cdf/config/imap_glows_l2_variable_attrs.yaml index a39be0389b..209b93e097 100644 --- a/imap_processing/cdf/config/imap_glows_l2_variable_attrs.yaml +++ b/imap_processing/cdf/config/imap_glows_l2_variable_attrs.yaml @@ -19,497 +19,515 @@ flags_label: default_attrs: &default_attrs # TODO: Remove unneeded attributes once SAMMI is fixed - RESOLUTION: ' ' DISPLAY_TYPE: no_plot + FILLVAL: *int_fillval + REFERENCE_POSITION: Rotating Earth Geoid + RESOLUTION: ' ' TIME_BASE: J2000 TIME_SCALE: Terrestrial Time - REFERENCE_POSITION: Rotating Earth Geoid UNITS: ' ' - FILLVAL: *int_fillval VALIDMIN: *min_epoch support_data_defaults: &support_data_defaults <<: *default_attrs DEPEND_0: epoch - VALIDMIN: 0 - VALIDMAX: 1 DISPLAY_TYPE: time_series - VAR_TYPE: support_data FORMAT: I10 RESOLUTION: ISO8601 + VALIDMAX: 1 + VALIDMIN: 0 + VAR_TYPE: support_data +# UTC Strings time_data_defaults: &time_data_defaults <<: *support_data_defaults - FILLVAL: 0 - FORMAT: I1000 - UNITS: N/A - VALIDMIN: 0 - VALIDMAX: 0 DICT_KEY: SPASE>Support>SupportQuantity:Temporal + FILLVAL: ' ' + FORMAT: A30 + UNITS: N/A + VALIDMAX: ' ' + VALIDMIN: ' ' lightcurve_defaults: &lightcurve_defaults <<: *support_data_defaults - DISPLAY_TYPE: no_plot DEPEND_1: bins - VAR_TYPE: data + DISPLAY_TYPE: no_plot LABL_PTR_1: bins_label + VAR_TYPE: data + + derived_from_spice_kernels: &derived_from_spice_kernels + VAR_NOTES: Derived from SPICE Kernels bins_dim: <<: *default_attrs - VALIDMIN: 0 - VALIDMAX: 3599 CATDESC: Histogram bin number + DICT_KEY: SPASE>Support>SupportQuantity:Other FIELDNAM: Bin number + FILLVAL: *max_uint16 FORMAT: I4 - VAR_TYPE: support_data LABLAXIS: Bin no. - FILLVAL: *max_uint16 MONOTON: INCREASE SCALETYP: linear - DICT_KEY: SPASE>Support>SupportQuantity:Other + VALIDMAX: 3599 + VALIDMIN: 0 + VAR_TYPE: support_data flags_dim: <<: *default_attrs - FILLVAL: 255 CATDESC: Flag index for daily-occurrence counters of L1B flags + DICT_KEY: SPASE>Support>SupportQuantity:Other FIELDNAM: L1B flag index - UNITS: ' ' + FILLVAL: 255 FORMAT: I2 LABLAXIS: Index + UNITS: ' ' VALIDMAX: 16 VALIDMIN: 0 VAR_TYPE: support_data - DICT_KEY: SPASE>Support>SupportQuantity:Other ecliptic_dim: <<: *default_attrs # TODO: Update validmin and validmax - VALIDMIN: 0 - VALIDMAX: 2 CATDESC: Component index for cartesian ecliptic coordinates + DICT_KEY: SPASE>Support>SupportQuantity:Orientation FIELDNAM: Component index + FILLVAL: 255 + FORMAT: I1 LABLAXIS: Index UNITS: ' ' - FILLVAL: 255 + VALIDMAX: 2 + VALIDMIN: 0 VAR_TYPE: support_data - FORMAT: I1 - DICT_KEY: SPASE>Support>SupportQuantity:Orientation number_of_good_l1b_inputs: <<: *support_data_defaults CATDESC: Number of good L1B inputs per observational day + DICT_KEY: SPASE>Support>SupportQuantity:Other FIELDNAM: Number of good L1B inputs - LABLAXIS: No. of L1B - FILLVAL: *max_uint16 + FILLVAL: -9223372036854775808 FORMAT: I5 + LABLAXIS: No. of L1B VALIDMAX: 20000 # 3 days * 86400 s / 14.6 s rounded up - DICT_KEY: SPASE>Support>SupportQuantity:Other total_l1b_inputs: <<: *support_data_defaults CATDESC: Total number of L1B inputs per observational day + DICT_KEY: SPASE>Support>SupportQuantity:Other FIELDNAM: Total number of L1B inputs - LABLAXIS: No. of L1B - FILLVAL: *max_uint16 + FILLVAL: -9223372036854775808 FORMAT: I5 + LABLAXIS: No. of L1B VALIDMAX: 20000 - DICT_KEY: SPASE>Support>SupportQuantity:Other identifier: <<: *support_data_defaults CATDESC: Spin pointing number to identify observational day + DICT_KEY: SPASE>Support>SupportQuantity:Temporal FIELDNAM: Spin pointing number - LABLAXIS: Pointing no. - FILLVAL: *max_uint32 + FILLVAL: -9223372036854775808 FORMAT: I5 + LABLAXIS: Pointing no. VALIDMAX: 99999 - DICT_KEY: SPASE>Support>SupportQuantity:Temporal + +flight_software_version: + <<: *support_data_defaults + CATDESC: GLOWS flight software version + FIELDNAM: GLOWS flight software version + FILLVAL: -9223372036854775808 + FORMAT: I8 + LABLAXIS: FSW ver + VALIDMAX: 16777215 + +pkts_file_name: + CATDESC: Name of L0 packets file data originated + FIELDNAM: Packets File Name + FILLVAL: ' ' + FORMAT: A49 + VAR_TYPE: metadata start_time: <<: *time_data_defaults CATDESC: Start time (UTC) of observational day - FIELDNAM: Observation start time UTC DISPLAY_TYPE: no_plot + FIELDNAM: Observation start time UTC LABLAXIS: N/A end_time: <<: *time_data_defaults CATDESC: End time (UTC) of observational day - FIELDNAM: Observation end time UTC DISPLAY_TYPE: no_plot + FIELDNAM: Observation end time UTC LABLAXIS: N/A filter_temperature_average: <<: *support_data_defaults CATDESC: Filter temperature averaged over observational day + DICT_KEY: SPASE>Support>SupportQuantity:Other FIELDNAM: Average filter temperature - FILLVAL: 1.0E+31 + FILLVAL: -1.0E+31 FORMAT: F6.2 LABLAXIS: Temp - VALIDMIN: -30.0 - VALIDMAX: 60.0 UNITS: Celsius - DICT_KEY: SPASE>Support>SupportQuantity:Other + VALIDMAX: 60.0 + VALIDMIN: -30.0 filter_temperature_std_dev: <<: *support_data_defaults CATDESC: Standard deviation of filter temperature + DICT_KEY: SPASE>Support>SupportQuantity:Housekeeping FIELDNAM: Std dev of filter temperature - FILLVAL: 1.0E+31 + FILLVAL: -1.0E+31 FORMAT: E9.3 LABLAXIS: Temp std dev - VALIDMIN: 0.0 - VALIDMAX: 90.0 UNITS: Celsius - DICT_KEY: SPASE>Support>SupportQuantity:Housekeeping + VALIDMAX: 90.0 + VALIDMIN: 0.0 hv_voltage_average: <<: *support_data_defaults CATDESC: CEM HV voltage averaged over observational day + DICT_KEY: SPASE>Support>SupportQuantity:Housekeeping FIELDNAM: Average HV voltage - FILLVAL: 1.0E+31 + FILLVAL: -1.0E+31 FORMAT: F7.2 LABLAXIS: HV - VALIDMIN: 0.0 - VALIDMAX: 3500.0 UNITS: V - DICT_KEY: SPASE>Support>SupportQuantity:Housekeeping + VALIDMAX: 3500.0 + VALIDMIN: 0.0 hv_voltage_std_dev: <<: *support_data_defaults CATDESC: Standard deviation of CEM HV voltage + DICT_KEY: SPASE>Support>SupportQuantity:Housekeeping FIELDNAM: Std dev of HV voltage - FILLVAL: 1.0E+31 + FILLVAL: -1.0E+31 FORMAT: E9.3 LABLAXIS: HV std dev - VALIDMIN: 0.0 - VALIDMAX: 3500.0 UNITS: V - DICT_KEY: SPASE>Support>SupportQuantity:Housekeeping + VALIDMAX: 3500.0 + VALIDMIN: 0.0 spin_period_average: <<: *support_data_defaults - CATDESC: Spin period averaged over observational day #DEPEND_0: epoch #DISPLAY_TYPE: time_series + CATDESC: Spin period averaged over observational day + DICT_KEY: SPASE>Support>SupportQuantity:SpinPeriod FIELDNAM: Average spin period - FILLVAL: 1.0E+31 + FILLVAL: -1.0E+31 FORMAT: F9.6 LABLAXIS: Period UNITS: s - VALIDMIN: 14.6 VALIDMAX: 15.4 - DICT_KEY: SPASE>Support>SupportQuantity:SpinPeriod + VALIDMIN: 14.6 spin_period_std_dev: <<: *support_data_defaults CATDESC: Standard deviation of spin period + DICT_KEY: SPASE>Support>SupportQuantity:DataQuality FIELDNAM: Std dev of spin period - FILLVAL: 1.0E+31 + FILLVAL: -1.0E+31 FORMAT: E9.3 LABLAXIS: Period std dev UNITS: s - VALIDMIN: 0.0 VALIDMAX: 9.9 - DICT_KEY: SPASE>Support>SupportQuantity:DataQuality + VALIDMIN: 0.0 # TODO review these spin_period_ground_average: <<: *support_data_defaults - CATDESC: Spin period (ground processing) averaged over observational day #DEPEND_0: epoch #DISPLAY_TYPE: time_series + CATDESC: Spin period (ground processing) averaged over observational day + DICT_KEY: SPASE>Support>SupportQuantity:SpinPeriod FIELDNAM: Average spin period (ground) - FILLVAL: 1.0E+31 + FILLVAL: -1.0E+31 FORMAT: F9.6 LABLAXIS: Period UNITS: s - VALIDMIN: 14.6 VALIDMAX: 15.4 - DICT_KEY: SPASE>Support>SupportQuantity:SpinPeriod + VALIDMIN: 14.6 spin_period_ground_std_dev: <<: *support_data_defaults CATDESC: Standard deviation of spin period (ground processing) + DICT_KEY: SPASE>Support>SupportQuantity:DataQuality FIELDNAM: Std dev of spin period (ground) - FILLVAL: 1.0E+31 + FILLVAL: -1.0E+31 FORMAT: E9.3 LABLAXIS: Period std dev UNITS: s - VALIDMIN: 0.0 VALIDMAX: 9.9 - DICT_KEY: SPASE>Support>SupportQuantity:DataQuality + VALIDMIN: 0.0 pulse_length_average: <<: *support_data_defaults CATDESC: Pulse length averaged over observational day + DICT_KEY: SPASE>Support>SupportQuantity:Housekeeping FIELDNAM: Average pulse length - FILLVAL: 1.0e+31 + FILLVAL: -1.0e+31 FORMAT: F5.2 LABLAXIS: Pulse UNITS: us - VALIDMIN: 0.0 VALIDMAX: 12.75 - DICT_KEY: SPASE>Support>SupportQuantity:Housekeeping + VALIDMIN: 0.0 pulse_length_std_dev: <<: *support_data_defaults CATDESC: Standard deviation of pulse length + DICT_KEY: SPASE>Support>SupportQuantity:Housekeeping FIELDNAM: Std dev of pulse length - FILLVAL: 1.0e+31 + FILLVAL: -1.0e+31 FORMAT: E9.3 LABLAXIS: Pulse std dev UNITS: us - VALIDMIN: 0.0 VALIDMAX: 12.75 - DICT_KEY: SPASE>Support>SupportQuantity:Housekeeping + VALIDMIN: 0.0 position_angle_offset_average: <<: *support_data_defaults + <<: *derived_from_spice_kernels CATDESC: Position angle offset averaged over observational day + DICT_KEY: SPASE>Support>SupportQuantity:Positional FIELDNAM: Average position angle offset - FILLVAL: 1.0e+31 + FILLVAL: -1.0e+31 FORMAT: F10.6 LABLAXIS: Offset angle UNITS: degrees - VALIDMIN: 0.0 VALIDMAX: 360.0 - DICT_KEY: SPASE>Support>SupportQuantity:Positional + VALIDMIN: 0.0 position_angle_offset_std_dev: <<: *support_data_defaults + <<: *derived_from_spice_kernels CATDESC: Standard deviation of position angle offset + DICT_KEY: SPASE>Support>SupportQuantity:DataQuality FIELDNAM: Std dev of position angle offset - FILLVAL: 1.0e+31 + FILLVAL: -1.0e+31 FORMAT: E9.3 LABLAXIS: Offset std dev UNITS: degrees - VALIDMIN: 0.0 VALIDMAX: 360.0 - DICT_KEY: SPASE>Support>SupportQuantity:DataQuality + VALIDMIN: 0.0 spin_axis_orientation_average: <<: *support_data_defaults + <<: *derived_from_spice_kernels CATDESC: Spin axis pointing averaged over observational day (ecliptic lon and lat) + DICT_KEY: SPASE>Support>SupportQuantity:SpinPhase FIELDNAM: Average spin axis pointing - FILLVAL: 1.0e+31 + FILLVAL: -1.0e+31 FORMAT: F7.3 LABLAXIS: Lon/lat UNITS: degrees - VALIDMIN: -90.0 VALIDMAX: 360.0 - DICT_KEY: SPASE>Support>SupportQuantity:SpinPhase + VALIDMIN: -90.0 spin_axis_orientation_std_dev: <<: *support_data_defaults + <<: *derived_from_spice_kernels CATDESC: Standard deviation of spin axis pointing + DICT_KEY: SPASE>Support>SupportQuantity:DataQuality FIELDNAM: Std dev of spin axis pointing - FILLVAL: 1.0e+31 + FILLVAL: -1.0e+31 FORMAT: E9.3 LABLAXIS: Lon/lat std dev UNITS: degrees - VALIDMIN: 0.0 VALIDMAX: 360.0 - DICT_KEY: SPASE>Support>SupportQuantity:DataQuality + VALIDMIN: 0.0 spacecraft_location_average: <<: *support_data_defaults + <<: *derived_from_spice_kernels + CATDESC: Spacecraft location averaged over observational day (ecliptic frame) DEPEND_1: ecliptic + DICT_KEY: SPASE>Support>SupportQuantity:Positional DISPLAY_TYPE: no_plot - CATDESC: Spacecraft location averaged over observational day (ecliptic frame) FIELDNAM: Average spacecraft location - FILLVAL: 1.0e+31 + FILLVAL: -1.0e+31 FORMAT: E13.6 LABLAXIS: Loc UNITS: km - VALIDMIN: -9.999999999E+8 VALIDMAX: 9.999999999E+8 - DICT_KEY: SPASE>Support>SupportQuantity:Positional - + VALIDMIN: -9.999999999E+8 spacecraft_location_std_dev: <<: *support_data_defaults + <<: *derived_from_spice_kernels + CATDESC: Standard deviation of spacecraft location DEPEND_1: ecliptic + DICT_KEY: SPASE>Support>SupportQuantity:DataQuality DISPLAY_TYPE: no_plot - CATDESC: Standard deviation of spacecraft location FIELDNAM: Std dev of spacecraft location - FILLVAL: 1.0e+31 + FILLVAL: -1.0E+31 FORMAT: E9.3 LABLAXIS: Loc std dev UNITS: km - VALIDMIN: 0.0 VALIDMAX: 1.5E+7 # 50 km/s * 3 days * 86400 s < 1.5e7 - DICT_KEY: SPASE>Support>SupportQuantity:DataQuality + VALIDMIN: 0.0 spacecraft_velocity_average: <<: *support_data_defaults + <<: *derived_from_spice_kernels + CATDESC: Spacecraft velocity averaged over observational day (ecliptic frame) DEPEND_1: ecliptic + DICT_KEY: SPASE>Support>SupportQuantity:Velocity DISPLAY_TYPE: no_plot - CATDESC: Spacecraft velocity averaged over observational day (ecliptic frame) FIELDNAM: Average spacecraft velocity - FILLVAL: 1.0e+31 + FILLVAL: -1.0E+31 FORMAT: E13.6 LABLAXIS: Vsc UNITS: km/s - VALIDMIN: -50.0 VALIDMAX: 50.0 - DICT_KEY: SPASE>Support>SupportQuantity:Velocity + VALIDMIN: -50.0 spacecraft_velocity_std_dev: <<: *support_data_defaults + <<: *derived_from_spice_kernels + CATDESC: Standard deviation of spacecraft velocity DEPEND_1: ecliptic + DICT_KEY: SPASE>Support>SupportQuantity:DataQuality DISPLAY_TYPE: no_plot - CATDESC: Standard deviation of spacecraft velocity FIELDNAM: Std dev of spacecraft velocity - FILLVAL: 1.0e+31 + FILLVAL: -1.0E+31 FORMAT: E9.3 LABLAXIS: Vsc std dev UNITS: km/s - VALIDMIN: 0.0 VALIDMAX: 9.9 - DICT_KEY: SPASE>Support>SupportQuantity:DataQuality + VALIDMIN: 0.0 bad_time_flag_occurrences: <<: *support_data_defaults CATDESC: Numbers of occurences for each bad-time flag during observational day - FIELDNAM: Occurrences of bad-time flags DEPEND_1: flags + DICT_KEY: SPASE>Support>SupportQuantity:DataQuality DISPLAY_TYPE: no_plot - LABL_PTR_1: flags_label # MS: I do not understand this - FILLVAL: *max_uint16 + FIELDNAM: Occurrences of bad-time flags + FILLVAL: 65535 FORMAT: I5 - VALIDMAX: 20000 LABLAXIS: No. of cases - DICT_KEY: SPASE>Support>SupportQuantity:DataQuality + LABL_PTR_1: flags_label # MS: I do not understand this + VALIDMAX: 65535 + VALIDMIN: 0 spin_angle: <<: *lightcurve_defaults CATDESC: Spin angle (measured from north) for bin centers + DICT_KEY: SPASE>Support>SupportQuantity:SpinPhase FIELDNAM: Spin angle for bin centers - VAR_TYPE: support_data - FILLVAL: 1.0e+31 + FILLVAL: -1.0E+31 + FORMAT: F7.3 LABLAXIS: Spin angle UNITS: degrees - FORMAT: F7.3 - VALIDMIN: 0.0 VALIDMAX: 360.0 - DICT_KEY: SPASE>Support>SupportQuantity:SpinPhase + VALIDMIN: 0.0 + VAR_TYPE: support_data photon_flux: <<: *lightcurve_defaults CATDESC: Photon flux in scanning-circle bins averaged over observational day + DELTA_MINUS_VAR: flux_uncertainties + DELTA_PLUS_VAR: flux_uncertainties + DICT_KEY: SPASE>Wave>WaveType:Electromagnetic,WaveQuantity:Intensity,Qualifier:Scalar DISPLAY_TYPE: spectrogram FIELDNAM: Pointing-averaged photon flux - FILLVAL: 1.0e+31 + FILLVAL: -1.0E+31 + FORMAT: F8.2 LABLAXIS: Flux UNITS: Rayleigh - FORMAT: F8.2 - VALIDMIN: 0.0 VALIDMAX: 30000.0 # max 30000 cps in FDIR / from 1 to 3.37 cps-per-R + VALIDMIN: 0.0 + # uncertainties are symmetrcial, so same value is used for +/- # SPASE data pulled from TWINS 1 LAD metadata - DICT_KEY: SPASE>Wave>WaveType:Electromagnetic,WaveQuantity:Intensity,Qualifier:Scalar raw_histograms: <<: *lightcurve_defaults CATDESC: Histogram of counts for observational day + DICT_KEY: SPASE>Support>SupportQuantity:Other DISPLAY_TYPE: spectrogram FIELDNAM: Histogram of counts - FILLVAL: *max_uint32 + FILLVAL: -9223372036854775808 + FORMAT: I8 LABLAXIS: Counts UNITS: '#' - FORMAT: I8 - VALIDMIN: 0 VALIDMAX: 35000000 # max 30000 cps in FDIR * 3 days * 86400 s / 225 bins rounded up - DICT_KEY: SPASE>Support>SupportQuantity:Other + VALIDMIN: 0 exposure_times: <<: *lightcurve_defaults CATDESC: Exposure times for histogram bins for observational day + DICT_KEY: SPASE>Support>SupportQuantity:Other DISPLAY_TYPE: spectrogram FIELDNAM: Exposure time per bin - FILLVAL: 1.0e+31 + FILLVAL: -1.0E+31 + FORMAT: F7.2 LABLAXIS: Bin exposure UNITS: s - FORMAT: F7.2 - VALIDMIN: 0.0 VALIDMAX: 1200.0 # 3 days * 86400 s / 225 bins rounded up - DICT_KEY: SPASE>Support>SupportQuantity:Other + VALIDMIN: 0.0 flux_uncertainties: <<: *lightcurve_defaults CATDESC: Statistical uncertainties for photon flux + DICT_KEY: SPASE>Support>SupportQuantity:DataQuality FIELDNAM: Photon flux uncertainties - VAR_TYPE: support_data - FILLVAL: 1.0e+31 + FILLVAL: -1.0E+31 + FORMAT: F8.2 LABLAXIS: Flux uncert UNITS: Rayleigh - FORMAT: F8.2 - VALIDMIN: 0.0 VALIDMAX: 30000.0 # the same VALIDMAX as for photon_flux assumed - DICT_KEY: SPASE>Support>SupportQuantity:DataQuality + VALIDMIN: 0.0 + VAR_TYPE: support_data histogram_flag_array: <<: *lightcurve_defaults CATDESC: Bad-angle flags for histogram bins + DICT_KEY: SPASE>Support>SupportQuantity:DataQuality FIELDNAM: Bad-angle flags for histogram - VAR_TYPE: support_data FILLVAL: 255 + FORMAT: I2 LABLAXIS: Mask value UNITS: ' ' - FORMAT: I2 - VALIDMIN: 0 VALIDMAX: 15 # only 4 bits currently used - DICT_KEY: SPASE>Support>SupportQuantity:DataQuality + VALIDMIN: 0 + VAR_TYPE: support_data ecliptic_lon: <<: *lightcurve_defaults CATDESC: Ecliptic longitudes of bin centers + DICT_KEY: SPASE>Support>SupportQuantity:Positional FIELDNAM: Ecliptic longitudes of bins - VAR_TYPE: support_data - FILLVAL: 1.0e+31 + FILLVAL: -1.0E+31 + FORMAT: F7.3 LABLAXIS: Bin lon UNITS: degrees - FORMAT: F7.3 - VALIDMIN: 0.0 VALIDMAX: 360.0 - DICT_KEY: SPASE>Support>SupportQuantity:Positional + VALIDMIN: 0.0 + VAR_TYPE: support_data ecliptic_lat: <<: *lightcurve_defaults CATDESC: Ecliptic latitudes of bin centers + DICT_KEY: SPASE>Support>SupportQuantity:Positional FIELDNAM: Ecliptic latitudes of bins - VAR_TYPE: support_data - FILLVAL: 1.0e+31 + FILLVAL: -1.0E+31 + FORMAT: F7.3 LABLAXIS: Bin lat UNITS: degrees - FORMAT: F7.3 - VALIDMIN: -90.0 VALIDMAX: 90.0 - DICT_KEY: SPASE>Support>SupportQuantity:Positional + VALIDMIN: -90.0 + VAR_TYPE: support_data number_of_bins: <<: *support_data_defaults CATDESC: Number of bins in histogram + DICT_KEY: SPASE>Support>SupportQuantity:Other FIELDNAM: Number of bins in histogram - VAR_TYPE: support_data - FILLVAL: *max_uint16 + FILLVAL: -9223372036854775808 + FORMAT: I4 LABLAXIS: No. of bins UNITS: ' ' - FORMAT: I4 - VALIDMIN: 225 VALIDMAX: 3600 - DICT_KEY: SPASE>Support>SupportQuantity:Other - -# M. Strumik comment: this variable is obsolete and should not be used -raw_uncertainties: - <<: *lightcurve_defaults - CATDESC: Statistical uncertainties for counts histogram - FIELDNAM: Counts-histogram uncertainties + VALIDMIN: 225 VAR_TYPE: support_data - FILLVAL: *max_uint16 - LABLAXIS: Counts - UNITS: '#' - FORMAT: I4 - VALIDMIN: 0 - VALIDMAX: 6000 # sqrt(VALIDMAX for raw_histogram) diff --git a/imap_processing/cdf/config/imap_hi_global_cdf_attrs.yaml b/imap_processing/cdf/config/imap_hi_global_cdf_attrs.yaml index 89333de0a6..9be70c4d15 100644 --- a/imap_processing/cdf/config/imap_hi_global_cdf_attrs.yaml +++ b/imap_processing/cdf/config/imap_hi_global_cdf_attrs.yaml @@ -49,13 +49,17 @@ imap_hi_l1b_hk_attrs: Logical_source: imap_hi_l1b_{sensor}-hk Logical_source_description: IMAP-Hi Instrument Level-1B Housekeeping Data. +imap_hi_l1b_goodtimes_attrs: + Data_type: L1B_GOODTIMES>Level-1B Good Times + Logical_source: imap_hi_l1b_{sensor}-goodtimes + Logical_source_description: IMAP-Hi Instrument Level-1B Good Times Data. + imap_hi_l1c_pset_attrs: Data_type: L1C_PSET>Level-1C Pointing Set Logical_source: imap_hi_l1c_{sensor}-pset Logical_source_description: IMAP-Hi Instrument Level-1C Pointing Set Data. -# TODO: Finalize these global attributes -imap_hi_l2_enamap-sf: +imap_hi_l2_enamap: Data_type: L2_{descriptor}>Level-2 ENA Intensity Map for Hi{sensor} Logical_source: imap_hi_l2_{descriptor} - Logical_source_description: IMAP-Hi Instrument Level-2 ENA Intensity Map Data for Hi{sensor} on rectangular tiling. \ No newline at end of file + Logical_source_description: IMAP-Hi Instrument Level-2 ENA Intensity Map Data for Hi{sensor} on rectangular tiling. diff --git a/imap_processing/cdf/config/imap_hi_variable_attrs.yaml b/imap_processing/cdf/config/imap_hi_variable_attrs.yaml index cba537d1b0..acd6f2d97b 100644 --- a/imap_processing/cdf/config/imap_hi_variable_attrs.yaml +++ b/imap_processing/cdf/config/imap_hi_variable_attrs.yaml @@ -3,64 +3,64 @@ default_attrs: &default DEPEND_0: epoch DISPLAY_TYPE: time_series FORMAT: I12 + SCALE_TYPE: linear UNITS: " " VAR_TYPE: data - SCALE_TYPE: linear default_uint8_attrs: &default_uint8 <<: *default FILLVAL: 255 FORMAT: I3 - VALIDMIN: 0 VALIDMAX: 255 + VALIDMIN: 0 dtype: uint8 default_uint16_attrs: &default_uint16 <<: *default FILLVAL: 65535 FORMAT: I5 - VALIDMIN: 0 VALIDMAX: 65535 + VALIDMIN: 0 dtype: uint16 default_uint32_attrs: &default_uint32 <<: *default FILLVAL: 4294967295 FORMAT: I10 - VALIDMIN: 0 VALIDMAX: 4294967295 + VALIDMIN: 0 dtype: uint32 default_int64_attrs: &default_int64 <<: *default FILLVAL: -9223372036854775808 FORMAT: I20 - VALIDMIN: -9223372036854775808 VALIDMAX: 9223372036854775807 + VALIDMIN: -9223372036854775808 dtype: int64 default_int32_attrs: &default_int32 <<: *default FILLVAL: -2147483648 FORMAT: I10 - VALIDMIN: -2147483648 VALIDMAX: 2147483647 + VALIDMIN: -2147483648 dtype: int32 default_float32_attrs: &default_float32 <<: *default - FILLVAL: .NAN + FILLVAL: -1.0e31 FORMAT: F10.2 - VALIDMIN: -3.4028235e+38 VALIDMAX: 3.4028235e+38 + VALIDMIN: -3.4028235e+38 dtype: float32 default_float64_attrs: &default_float64 <<: *default - FILLVAL: .NAN + FILLVAL: -1.0e31 FORMAT: F10.2 - VALIDMIN: -1.7976931348623157e+308 VALIDMAX: 1.7976931348623157e+308 + VALIDMIN: -1.7976931348623157e+308 dtype: float64 default_ccsds_version: &default_ccsds_version @@ -126,8 +126,8 @@ hi_esa_step: &hi_esa_step FILLVAL: 255 FORMAT: I2 LABLAXIS: ESA step - VALIDMIN: 0 VALIDMAX: 16 + VALIDMIN: 0 VAR_NOTES: > ESA (electrostatic analyzer) stepping number is 4-bit integer value that indicates which row of the onboard stepping table was used to set voltages of the inner and @@ -203,8 +203,8 @@ hi_de_trigger_id: FILLVAL: 0 FORMAT: I1 LABLAXIS: ID - VALIDMIN: 1 VALIDMAX: 3 + VALIDMIN: 1 VAR_NOTES: > The trigger ID is 2-bits. It represents which detector was hit first. It can be 1, 2, 3 for detector A, B, C respectively. @@ -252,20 +252,21 @@ hi_de_ccsds_index: # LABL_PTR_i expects VAR_TYPE of metadata with char data type hi_hist_angle_label: CATDESC: Angle bin centers for histogram data. + DEPEND_1: angle FIELDNAM: ANGLE FORMAT: A5 VAR_TYPE: metadata hi_hist_angle: - SCALE_TYPE: linear CATDESC: Angle bin centers for histogram data. FIELDNAM: ANGLE FILLVAL: 65535 - VALIDMIN: 0 - VALIDMAX: 360 FORMAT: I3 - UNITS: deg LABLAXIS: ANGLE + SCALE_TYPE: linear + UNITS: deg + VALIDMAX: 360 + VALIDMIN: 0 VAR_TYPE: support_data dtype: uint16 @@ -305,11 +306,11 @@ hi_hist_num_of_spins: hi_hist_counters: <<: *default_uint16 CATDESC: Angular histogram of {counter_name} type events - FIELDNAM: "{counter_name} histogram" - VALIDMAX: 4095 DEPEND_1: angle - LABL_PTR_1: angle_label + FIELDNAM: "{counter_name} histogram" FORMAT: I4 + LABL_PTR_1: angle_label + VALIDMAX: 4095 hi_hist_cksum: <<: *default_ccsds_cksum @@ -323,8 +324,8 @@ hi_de_coincidence_type: FILLVAL: 0 FORMAT: I2 LABLAXIS: Type - VALIDMIN: 0 VALIDMAX: 15 + VALIDMIN: 0 VAR_NOTES: > A 4-bit quantity, representable as a hexadecimal digit, made up of the ORed quantities: (A hit? 8:0) | (B hit? 4:0) @@ -335,8 +336,8 @@ default_esa_energy_step: &default_esa_energy_step FIELDNAM: ESA energy step FILLVAL: 255 FORMAT: I2 - VALIDMIN: 0 VALIDMAX: 12 + VALIDMIN: 0 hi_de_esa_energy_step: <<: *default_uint8 @@ -349,8 +350,8 @@ default_l1b_tof: &default_l1b_tof FORMAT: I3 LABLAXIS: Time of Flight UNITS: ns - VALIDMIN: -512 VALIDMAX: 512 + VALIDMIN: -512 hi_de_tof_ab: <<: *default_l1b_tof @@ -379,8 +380,8 @@ hi_de_spin_phase: FIELDNAM: Spin Phase FORMAT: F4.3 LABLAXIS: Spin Phase - VALIDMIN: 0 VALIDMAX: 1 + VALIDMIN: 0 hi_de_hae_latitude: <<: *default_float32 @@ -389,9 +390,9 @@ hi_de_hae_latitude: FIELDNAM: Ecliptic Latitude FORMAT: F5.2 LABLAXIS: Lat - VALIDMIN: -180 - VALIDMAX: 180 UNITS: deg + VALIDMAX: 180 + VALIDMIN: -180 hi_de_hae_longitude: <<: *default_float32 @@ -400,9 +401,9 @@ hi_de_hae_longitude: FIELDNAM: Ecliptic Longitude FORMAT: F5.2 LABLAXIS: Lon - VALIDMIN: 0 - VALIDMAX: 360 UNITS: deg + VALIDMAX: 360 + VALIDMIN: 0 hi_de_quality_flag: <<: *default_uint16 @@ -412,8 +413,8 @@ hi_de_quality_flag: FILLVAL: 65535 FORMAT: I5 LABLAXIS: Qlt Flag - VALIDMIN: 0 VALIDMAX: 65535 + VALIDMIN: 0 VAR_NOTES: > Bitwise quality flag {TODO: Store bitwise definition here?} @@ -424,24 +425,55 @@ hi_de_nominal_bin: FIELDNAM: Histogram Bin Number FORMAT: I2 LABLAXIS: Hist Bin \# - VALIDMIN: 0 VALIDMAX: 89 + VALIDMIN: 0 + +hi_de_esa_step_met: + <<: *default_float64 + CATDESC: Mission Elapsed Time (MET) in seconds of when the ESA was stepped + FIELDNAM: ESA Start MET + LABLAXIS: ESA Start MET + UNITS: seconds + VAR_TYPE: support_data + +hi_de_ccsds_qf: + <<: *default_uint8 + CATDESC: CCSDS packet quality flag bitmask + FIELDNAM: CCSDS Quality Flag + FORMAT: I3 + LABLAXIS: CCSDS QF + VALIDMAX: 255 + VALIDMIN: 0 + VAR_NOTES: > + Bitwise quality flag for CCSDS packet. Bit 0 (value 1): packet was full + (contained 664 events). Bit 2 (value 4): packet contained events from an + invalid spin. # ======= L1C PSET Section ======= # Define override values for epoch as defined in imap_constant_attrs.yaml hi_pset_epoch: - CATDESC: Midpoint time of pointing, number of nanoseconds since J2000 with leap seconds included - BIN_LOCATION: 0.5 + BIN_LOCATION: 0 + CATDESC: Start time of pointing, number of nanoseconds since J2000 with leap seconds included + DELTA_PLUS_VAR: epoch_delta + +hi_pset_epoch_delta: + <<: *default_int64 + CATDESC: Number of nanoseconds in spacecraft pointing covered by this pointing set product + DISPLAY_TYPE: no_plot + FIELDNAM: epoch delta + TIME_SCALE: Terrestrial Time + UNITS: ns + VAR_TYPE: support_data hi_pset_esa_energy_step: <<: *default_esa_energy_step LABLAXIS: Energy Step + MONOTON: INCREASE + SCALE_TYP: linear UNITS: " " - VALIDMIN: 0 VALIDMAX: 12 - SCALE_TYP: linear - MONOTON: INCREASE + VALIDMIN: 0 VAR_TYPE: support_data dtype: uint8 @@ -451,11 +483,11 @@ hi_pset_calibration_prod: FILLVAL: 65535 FORMAT: I1 LABLAXIS: Calibration Prod - UNITS: " " - SCALE_TYP: linear MONOTON: INCREASE - VALIDMIN: 0 + SCALE_TYP: linear + UNITS: " " VALIDMAX: 9 + VALIDMIN: 0 VAR_TYPE: support_data dtype: uint8 @@ -465,16 +497,16 @@ hi_pset_spin_angle_bin: FILLVAL: 65535 FORMAT: I3 LABLAXIS: Bin Index - UNITS: " " - SCALE_TYP: linear MONOTON: INCREASE - VALIDMIN: 0 + SCALE_TYP: linear + UNITS: " " VALIDMAX: 3599 - VAR_TYPE: support_data + VALIDMIN: 0 VAR_NOTES: > Bins are defined by spin angle about the mean axis of rotation for the pointing set. Spin angle bins start at closest to ecliptic North. Bin zero is centered at 0.05 degrees spinward of ecliptic North and all bins are 0.1 degrees wide. + VAR_TYPE: support_data dtype: uint16 # Based on SPDF example of a vector magnetic field variable at the following link, @@ -483,117 +515,117 @@ hi_pset_spin_angle_bin: hi_pset_despun_z: <<: *default_float32 CATDESC: Unit vector corresponding to Despun Pointing Frame z-axis in HAE Ecliptic coordinates + DISPLAY_TYPE: no_plot FIELDNAM: Despun Frame z-axis in HAE coordinates FORMAT: F5.3 LABL_PTR_1: label_vector_HAE UNITS: " " - VALIDMIN: -1 VALIDMAX: 1 - DISPLAY_TYPE: no_plot + VALIDMIN: -1 VAR_TYPE: support_data hi_pset_hae_latitude: <<: *default_float32 CATDESC: Latitude of bin center in HAE coordinates - FIELDNAM: HAE Latitude DEPEND_0: epoch DEPEND_1: spin_angle_bin DISPLAY_TYPE: no_plot + FIELDNAM: HAE Latitude FORMAT: F5.2 LABLAXIS: Latitude UNITS: deg - VALIDMIN: 0 VALIDMAX: 180 + VALIDMIN: 0 hi_pset_hae_longitude: <<: *default_float32 CATDESC: Longitude of bin center in HAE coordinates - FIELDNAM: HAE Longitude DEPEND_0: epoch DEPEND_1: spin_angle_bin DISPLAY_TYPE: no_plot + FIELDNAM: HAE Longitude FORMAT: F5.2 LABLAXIS: Latitude UNITS: deg - VALIDMIN: 0 VALIDMAX: 360 + VALIDMIN: 0 hi_pset_counts: <<: *default_uint16 CATDESC: Binned direct events counts during good times - FIELDNAM: Binned DE counts DEPEND_0: epoch DEPEND_1: esa_energy_step DEPEND_2: calibration_prod DEPEND_3: spin_angle_bin + DISPLAY_TYPE: stack_plot + FIELDNAM: Binned DE counts + FORMAT: I5 LABL_PTR_1: esa_energy_step_label LABL_PTR_2: calibration_prod_label LABL_PTR_3: spin_bin_label - DISPLAY_TYPE: stack_plot - FORMAT: I5 hi_pset_exposure_times: <<: *default_float32 CATDESC: Exposure times for each bin during good times - FIELDNAM: Bin exposure times DEPEND_0: epoch DEPEND_1: esa_energy_step DEPEND_2: spin_angle_bin + DISPLAY_TYPE: stack_plot + FIELDNAM: Bin exposure times + FORMAT: F6.2 LABL_PTR_1: esa_energy_step_label LABL_PTR_2: spin_bin_label UNITS: sec - DISPLAY_TYPE: stack_plot - FORMAT: F6.2 hi_pset_background_rates: <<: *default_float32 CATDESC: Background count rates - FIELDNAM: Background count rates DEPEND_0: epoch DEPEND_1: esa_energy_step DEPEND_2: calibration_prod DEPEND_3: spin_angle_bin + DISPLAY_TYPE: stack_plot + FIELDNAM: Background count rates + FORMAT: F4.2 LABL_PTR_1: esa_energy_step_label LABL_PTR_2: calibration_prod_label LABL_PTR_3: spin_bin_label UNITS: counts / s - DISPLAY_TYPE: stack_plot - FORMAT: F4.2 hi_pset_background_rates_uncertainty: <<: *default_float32 CATDESC: Background count rate uncertainties - FIELDNAM: Background count rate uncertainties DEPEND_0: epoch DEPEND_1: esa_energy_step DEPEND_2: calibration_prod DEPEND_3: spin_angle_bin + DISPLAY_TYPE: stack_plot + FIELDNAM: Background count rate uncertainties + FORMAT: F4.2 LABL_PTR_1: esa_energy_step_label LABL_PTR_2: calibration_prod_label LABL_PTR_3: spin_bin_label UNITS: counts / s - DISPLAY_TYPE: stack_plot - FORMAT: F4.2 # <=== pset label Attributes ===> hi_pset_spin_bin_label: CATDESC: Label spin angle bin - FIELDNAM: Label spin angle bin DEPEND_1: spin_angle_bin + FIELDNAM: Label spin angle bin FORMAT: A4 VAR_TYPE: metadata hi_pset_esa_energy_step_label: CATDESC: Label esa step - FIELDNAM: Label esa step DEPEND_1: esa_energy_step + FIELDNAM: Label esa step FORMAT: A4 VAR_TYPE: metadata hi_pset_calibration_prod_label: CATDESC: Label calibration product - FIELDNAM: Label calibration product DEPEND_1: calibration_prod + FIELDNAM: Label calibration product FORMAT: A4 VAR_TYPE: metadata @@ -601,4 +633,65 @@ hi_pset_label_vector_HAE: CATDESC: Label cartesian despun_z FIELDNAM: Label cartesian despun_z FORMAT: A5 - VAR_TYPE: metadata \ No newline at end of file + VAR_TYPE: metadata + +# <=== L1B Goodtimes Attributes ===> +hi_goodtimes_met: + <<: *default_float64 + CATDESC: Mission Elapsed Time for each 8-spin histogram packet + DEPEND_0: epoch + FIELDNAM: MET + LABLAXIS: MET + UNITS: s + VALIDMAX: 1.7976931348623157e+308 + VALIDMIN: 0 + VAR_TYPE: support_data + +hi_goodtimes_cull_flags: + <<: *default_uint8 + CATDESC: Cull flags indicating good (0) or bad (non-zero) times per spin bin + DEPEND_0: epoch + DEPEND_1: spin_bin + DISPLAY_TYPE: spectrogram + FIELDNAM: Cull Flags + LABLAXIS: Cull Code + LABL_PTR_1: spin_bin_label + UNITS: " " + VAR_NOTES: > + Cull flags array with dimensions (epoch, spin_bin). Value of 0 indicates good time, + non-zero values indicate bad times with specific cull reason codes. + Cull code 1 (LOOSE) indicates times removed by quality filters. + +hi_goodtimes_esa_step: + <<: *default_uint8 + CATDESC: ESA energy step for each 8-spin histogram packet + DEPEND_0: epoch + FIELDNAM: ESA Step + LABLAXIS: ESA Step + UNITS: " " + VALIDMAX: 10 + VALIDMIN: 1 + VAR_TYPE: support_data + +hi_goodtimes_spin_bin: + CATDESC: Spin angle bin index + FIELDNAM: Spin Bin + FILLVAL: 255 + FORMAT: I2 + LABLAXIS: Spin Bin + UNITS: " " + VALIDMAX: 89 + VALIDMIN: 0 + VAR_NOTES: > + Spin angle bins numbered 0-89, covering 0-360 degrees of spacecraft spin. + Each bin is 4 degrees wide. + VAR_TYPE: support_data + dtype: uint8 + +hi_goodtimes_spin_bin_label: + CATDESC: Label for spin bin + DEPEND_0: spin_bin + FIELDNAM: Spin Bin Label + FORMAT: A3 + VAR_TYPE: metadata + diff --git a/imap_processing/cdf/config/imap_hit_global_cdf_attrs.yaml b/imap_processing/cdf/config/imap_hit_global_cdf_attrs.yaml index bd26a321c3..5dcbb17177 100644 --- a/imap_processing/cdf/config/imap_hit_global_cdf_attrs.yaml +++ b/imap_processing/cdf/config/imap_hit_global_cdf_attrs.yaml @@ -1,6 +1,7 @@ instrument_base: &instrument_base Descriptor: &desc HIT>IMAP High-energy Ion Telescope + Instrument_type: Particles (space) TEXT: &txt > The High-energy Ion Telescope (HIT) measures the elemental composition, energy spectra, angle distributions, and arrival times of high-energy ions. HIT delivers full-sky @@ -8,7 +9,6 @@ instrument_base: &instrument_base measurements, such as observing shock-accelerated ions, determining the origin of the solar energetic particles (SEPs) spectra, and resolving particle transport in the heliosphere. See https://imap.princeton.edu/instruments/hit for more details. - Instrument_type: Particles (space) # L1a imap_hit_l1a_hk: diff --git a/imap_processing/cdf/config/imap_hit_l1a_variable_attrs.yaml b/imap_processing/cdf/config/imap_hit_l1a_variable_attrs.yaml index 52a25593f8..ad07ee2079 100644 --- a/imap_processing/cdf/config/imap_hit_l1a_variable_attrs.yaml +++ b/imap_processing/cdf/config/imap_hit_l1a_variable_attrs.yaml @@ -5,43 +5,43 @@ default_attrs: &default DISPLAY_TYPE: time_series FILLVAL: -9223372036854775808 FORMAT: I12 - VALIDMIN: 0 + SCALETYP: linear + UNITS: ' ' VALIDMAX: 9223372036854775807 + VALIDMIN: 0 VAR_TYPE: data - UNITS: ' ' - SCALETYP: linear default_uint8_attrs: &default_uint8 DISPLAY_TYPE: time_series - VAR_TYPE: data - UNITS: ' ' - SCALETYP: linear FILLVAL: 255 FORMAT: I3 - VALIDMIN: 0 + SCALETYP: linear + UNITS: ' ' VALIDMAX: 255 + VALIDMIN: 0 + VAR_TYPE: data default_uint16_attrs: &default_uint16 DISPLAY_TYPE: time_series - VAR_TYPE: data - UNITS: ' ' - SCALETYP: linear FILLVAL: 65535 FORMAT: I5 - VALIDMIN: 0 + SCALETYP: linear + UNITS: ' ' VALIDMAX: 65535 + VALIDMIN: 0 + VAR_TYPE: data default_uint32_attrs: &default_uint32 <<: *default FILLVAL: 4294967295 FORMAT: I10 - VALIDMIN: 0 VALIDMAX: 4294967295 + VALIDMIN: 0 default_hk_attrs: &default_hk <<: *default - VALIDMAX: 4095 FORMAT: I4 + VALIDMAX: 4095 default_hk_support_attrs: &default_hk_support <<: *default @@ -51,68 +51,68 @@ default_hk_support_attrs: &default_hk_support default_counts_attrs: &default_counts <<: *default DISPLAY_TYPE: time_series - VAR_TYPE: data FORMAT: I10 - VALIDMIN: 0 - VALIDMAX: 10000000000 - UNITS: counts SCALETYP: log + UNITS: counts + VALIDMAX: 10000000000 + VALIDMIN: 0 + VAR_TYPE: data default_counts_support_attrs: &default_counts_support DISPLAY_TYPE: no_plot - VAR_TYPE: support_data FILLVAL: -1.00E+31 - VALIDMIN: 0 - VALIDMAX: 1000 - UNITS: ' ' SCALETYP: linear + UNITS: ' ' + VALIDMAX: 1000 + VALIDMIN: 0 + VAR_TYPE: support_data default_index_attrs: &default_index DISPLAY_TYPE: no_plot - VAR_TYPE: support_data - VALIDMIN: 0 - VALIDMAX: 1000 FILLVAL: 4294967295 FORMAT: I10 - UNITS: ' ' SCALETYP: linear + UNITS: ' ' + VALIDMAX: 1000 + VALIDMIN: 0 + VAR_TYPE: support_data default_energy_attrs: &default_energy - VAR_TYPE: support_data DISPLAY_TYPE: no_plot - LABLAXIS: Energy FILLVAL: -1.00E+31 - VALIDMIN: 0 - VALIDMAX: 1000 FORMAT: F6.1 - UNITS: MeV/nuc + LABLAXIS: Energy SCALETYP: log + UNITS: MeV/nuc + VALIDMAX: 1000 + VALIDMIN: 0 + VAR_TYPE: support_data default_uncertainty_attrs: &default_uncertainty DEPEND_0: epoch - VAR_TYPE: support_data DISPLAY_TYPE: no_plot - VALIDMIN: 0 - VALIDMAX: 10000000000 FILLVAL: -1.00E+31 FORMAT: F15.3 - UNITS: counts SCALETYP: log + UNITS: counts + VALIDMAX: 10000000000 + VALIDMIN: 0 + VAR_TYPE: support_data # <=== Coordinates ===> sc_tick: CATDESC: Raw spacecraft tick time per integration - FIELDNAM: Spacecraft Tick - LABLAXIS: sc_tick - FORMAT: I10 - VAR_TYPE: support_data DISPLAY_TYPE: no_plot - VALIDMIN: 0 - VALIDMAX: 4294967295 + FIELDNAM: Spacecraft Tick FILLVAL: 4294967295 - UNITS: ' ' + FORMAT: I10 + LABLAXIS: sc_tick SCALETYP: linear + UNITS: ' ' + VALIDMAX: 4294967295 + VALIDMIN: 0 + VAR_TYPE: support_data # Counts Dataset Coordinates @@ -120,116 +120,116 @@ zenith: <<: *default_counts_support CATDESC: Angle from the spin axis (0 deg.) to anti-spin axis (180 deg.) in 8 bins FIELDNAM: Zenith - LABLAXIS: Zenith FORMAT: F12.2 + LABLAXIS: Zenith UNITS: deg azimuth: <<: *default_counts_support CATDESC: Spin angle in 15 bins (0 deg. is zero of spin phase) FIELDNAM: Azimuth - LABLAXIS: Azimuth FORMAT: F12.2 + LABLAXIS: Azimuth UNITS: Deg gain: <<: *default_counts_support CATDESC: Single rates gain. 0=low, 1=high FIELDNAM: gain - LABLAXIS: Gain - FORMAT: I10 FILLVAL: 65535 + FORMAT: I10 + LABLAXIS: Gain sngrates_index: <<: *default_index CATDESC: Single rates index FIELDNAM: sngrates_index - LABLAXIS: sngrates index FILLVAL: 4294967295 + LABLAXIS: sngrates index coinrates_index: <<: *default_index CATDESC: Coincidence rates index FIELDNAM: coinrates_index - LABLAXIS: coinrates index FILLVAL: 4294967295 + LABLAXIS: coinrates index pbufrates_index: <<: *default_index CATDESC: Priority buffer rates index FIELDNAM: pbufrates_index - LABLAXIS: pbufrates index FILLVAL: 4294967295 + LABLAXIS: pbufrates index l2fgrates_index: <<: *default_index CATDESC: Range 2 foreground rates index FIELDNAM: l2fgrates_index - LABLAXIS: l2fgrates index FILLVAL: 4294967295 + LABLAXIS: l2fgrates index l2bgrates_index: <<: *default_index CATDESC: Range 2 background rates index FIELDNAM: l2bgrates_index - LABLAXIS: l2bgrates index FILLVAL: 4294967295 + LABLAXIS: l2bgrates index l3fgrates_index: <<: *default_index CATDESC: Range 3 foreground rates index FIELDNAM: l3fgrates index - LABLAXIS: l3fgrates index FILLVAL: 4294967295 + LABLAXIS: l3fgrates index l3bgrates_index: <<: *default_index CATDESC: Range 3 background rates index FIELDNAM: l3bgrates index - LABLAXIS: l3bgrates index FILLVAL: 4294967295 + LABLAXIS: l3bgrates index penfgrates_index: <<: *default_index CATDESC: Range 4 foreground rates index FIELDNAM: penfgrates index - LABLAXIS: penfgrates index FILLVAL: 4294967295 + LABLAXIS: penfgrates index penbgrates_index: <<: *default_index CATDESC: Range 4 background rates index FIELDNAM: penbgrates index - LABLAXIS: penbgrates index FILLVAL: 4294967295 + LABLAXIS: penbgrates index ialirtrates_index: <<: *default_index CATDESC: ialirtrates index FIELDNAM: ialirtrates index - LABLAXIS: ialirtrates index FILLVAL: 4294967295 + LABLAXIS: ialirtrates index l4fgrates_index: <<: *default_index CATDESC: L4 ions foreground rates index FIELDNAM: l4fgrates index - LABLAXIS: l4fgrates index FILLVAL: 4294967295 + LABLAXIS: l4fgrates index l4bgrates_index: <<: *default_index CATDESC: L4 ions background rates index FIELDNAM: l4bgrates index - LABLAXIS: l4bgrates index FILLVAL: 4294967295 + LABLAXIS: l4bgrates index h_energy_mean: <<: *default_energy CATDESC: H sectored geometric mean energy per nucleon - FIELDNAM: H energy mean DELTA_MINUS_VAR: h_energy_delta_minus DELTA_PLUS_VAR: h_energy_delta_plus + FIELDNAM: H energy mean he4_energy_mean: <<: *default_energy @@ -254,17 +254,17 @@ fe_energy_mean: # Housekeeping Dataset Coordinates adc_channels: + CATDESC: ADC Channel DISPLAY_TYPE: no_plot + FIELDNAM: ADC Channel FILLVAL: -9223372036854775808 - UNITS: ' ' + FORMAT: I2 + LABLAXIS: Channel SCALETYP: linear - VALIDMIN: 0 + UNITS: ' ' VALIDMAX: 63 + VALIDMIN: 0 VAR_TYPE: support data - CATDESC: ADC Channel - FIELDNAM: ADC Channel - LABLAXIS: Channel - FORMAT: I2 # <=== Label Attributes ===> @@ -408,58 +408,58 @@ fe_energy_mean_label: version: <<: *default_uint8 CATDESC: CCSDS packet version number + DEPEND_1: sc_tick FIELDNAM: CCSDS version LABLAXIS: Value VAR_TYPE: support_data - DEPEND_1: sc_tick type: <<: *default_uint8 CATDESC: CCSDS packet type + DEPEND_1: sc_tick FIELDNAM: CCSDS type LABLAXIS: Value VAR_TYPE: support_data - DEPEND_1: sc_tick sec_hdr_flg: <<: *default_uint8 CATDESC: CCSDS secondary header flag + DEPEND_1: sc_tick FIELDNAM: CCSDS secondary header flag LABLAXIS: Value VAR_TYPE: support_data - DEPEND_1: sc_tick pkt_apid: <<: *default_uint16 CATDESC: CCSDS application process ID + DEPEND_1: sc_tick FIELDNAM: CCSDS APID LABLAXIS: Value VAR_TYPE: support_data - DEPEND_1: sc_tick seq_flgs: <<: *default_uint8 CATDESC: CCSDS sequence flags + DEPEND_1: sc_tick FIELDNAM: CCSDS sequence flags LABLAXIS: Value VAR_TYPE: support_data - DEPEND_1: sc_tick src_seq_ctr: <<: *default_uint16 CATDESC: CCSDS source sequence counter + DEPEND_1: sc_tick FIELDNAM: CCSDS sequence counter LABLAXIS: Value VAR_TYPE: support_data - DEPEND_1: sc_tick pkt_len: <<: *default_uint16 CATDESC: CCSDS packet length + DEPEND_1: sc_tick FIELDNAM: CCSDS packet length LABLAXIS: Value VAR_TYPE: support_data - DEPEND_1: sc_tick # Counts dataset variables hdr_frame_version: @@ -471,8 +471,8 @@ hdr_frame_version: hdr_dynamic_threshold_state: <<: *default_uint8 - DEPEND_0: epoch CATDESC: Raw header dynamic threshold state per integration + DEPEND_0: epoch FIELDNAM: hdr_dynamic_threshold_state LABLAXIS: State UNITS: state @@ -520,476 +520,476 @@ livetime_counter: num_trig: <<: *default_counts CATDESC: Raw number of triggers - FIELDNAM: num_trig - LABLAXIS: Counts DELTA_MINUS_VAR: num_trig_stat_uncert_minus DELTA_PLUS_VAR: num_trig_stat_uncert_plus + FIELDNAM: num_trig + LABLAXIS: Counts num_reject: <<: *default_counts CATDESC: Raw number of rejected events - FIELDNAM: num_reject - LABLAXIS: Counts DELTA_MINUS_VAR: num_reject_stat_uncert_minus DELTA_PLUS_VAR: num_reject_stat_uncert_plus + FIELDNAM: num_reject + LABLAXIS: Counts num_acc_w_pha: <<: *default_counts CATDESC: Raw number of accepted events with PHA data - FIELDNAM: num_acc_w_pha - LABLAXIS: Counts DELTA_MINUS_VAR: num_acc_w_pha_stat_uncert_minus DELTA_PLUS_VAR: num_acc_w_pha_stat_uncert_plus + FIELDNAM: num_acc_w_pha + LABLAXIS: Counts num_acc_no_pha: <<: *default_counts CATDESC: Raw number of events without PHA data - FIELDNAM: num_acc_no_pha - LABLAXIS: Counts DELTA_MINUS_VAR: num_acc_no_pha_stat_uncert_minus DELTA_PLUS_VAR: num_acc_no_pha_stat_uncert_plus + FIELDNAM: num_acc_no_pha + LABLAXIS: Counts num_haz_trig: <<: *default_counts CATDESC: Raw number of events triggered with a hazard condition - FIELDNAM: num_haz_trig - LABLAXIS: Counts DELTA_MINUS_VAR: num_haz_trig_stat_uncert_minus DELTA_PLUS_VAR: num_haz_trig_stat_uncert_plus + FIELDNAM: num_haz_trig + LABLAXIS: Counts num_haz_reject: <<: *default_counts CATDESC: Raw number of events rejected for hazard condition - FIELDNAM: num_haz_reject - LABLAXIS: Counts DELTA_MINUS_VAR: num_haz_reject_stat_uncert_minus DELTA_PLUS_VAR: num_haz_reject_stat_uncert_plus + FIELDNAM: num_haz_reject + LABLAXIS: Counts num_haz_acc_w_pha: <<: *default_counts CATDESC: Raw number of events with hazard condition with PHA data - FIELDNAM: num_haz_acc_w_pha - LABLAXIS: Counts DELTA_MINUS_VAR: num_haz_acc_w_pha_stat_uncert_minus DELTA_PLUS_VAR: num_haz_acc_w_pha_stat_uncert_plus + FIELDNAM: num_haz_acc_w_pha + LABLAXIS: Counts num_haz_acc_no_pha: <<: *default_counts CATDESC: Raw number of events accepted with hazard condition without PHA data - FIELDNAM: num_haz_acc_no_pha - LABLAXIS: Counts DELTA_MINUS_VAR: num_haz_acc_no_pha_stat_uncert_minus DELTA_PLUS_VAR: num_haz_acc_no_pha_stat_uncert_plus + FIELDNAM: num_haz_acc_no_pha + LABLAXIS: Counts nread: <<: *default_counts CATDESC: Raw number of events read from event FIFO - FIELDNAM: nread - LABLAXIS: Counts DELTA_MINUS_VAR: nread_stat_uncert_minus DELTA_PLUS_VAR: nread_stat_uncert_plus + FIELDNAM: nread + LABLAXIS: Counts nhazard: <<: *default_counts CATDESC: Raw number of events rejected for Hazard condition - FIELDNAM: nhazard - LABLAXIS: Counts DELTA_MINUS_VAR: nhazard_stat_uncert_minus DELTA_PLUS_VAR: nhazard_stat_uncert_plus + FIELDNAM: nhazard + LABLAXIS: Counts nadcstim: <<: *default_counts CATDESC: Raw number of ADC-calibration STIM events - FIELDNAM: nadcstim - LABLAXIS: Counts DELTA_MINUS_VAR: nadcstim_stat_uncert_minus DELTA_PLUS_VAR: nadcstim_stat_uncert_plus + FIELDNAM: nadcstim + LABLAXIS: Counts nodd: <<: *default_counts CATDESC: Raw number of odd events - FIELDNAM: nodd - LABLAXIS: Counts DELTA_MINUS_VAR: nodd_stat_uncert_minus DELTA_PLUS_VAR: nodd_stat_uncert_plus + FIELDNAM: nodd + LABLAXIS: Counts noddfix: <<: *default_counts CATDESC: Raw number of fixed odd events - FIELDNAM: noddfix - LABLAXIS: Counts DELTA_MINUS_VAR: noddfix_stat_uncert_minus DELTA_PLUS_VAR: noddfix_stat_uncert_plus + FIELDNAM: noddfix + LABLAXIS: Counts nmulti: <<: *default_counts CATDESC: Raw number of events with multiple hits in relevant layers - FIELDNAM: nmulti - LABLAXIS: Counts DELTA_MINUS_VAR: nmulti_stat_uncert_minus DELTA_PLUS_VAR: nmulti_stat_uncert_plus + FIELDNAM: nmulti + LABLAXIS: Counts nmultifix: <<: *default_counts CATDESC: Raw number of fix multi events - FIELDNAM: nmultifix - LABLAXIS: Counts DELTA_MINUS_VAR: nmultifix_stat_uncert_minus DELTA_PLUS_VAR: nmultifix_stat_uncert_plus + FIELDNAM: nmultifix + LABLAXIS: Counts nbadtraj: <<: *default_counts CATDESC: Raw number of events rejected for inconsistent/bad trajectory - FIELDNAM: nbadtraj - LABLAXIS: Counts DELTA_MINUS_VAR: nbadtraj_stat_uncert_minus DELTA_PLUS_VAR: nbadtraj_stat_uncert_plus + FIELDNAM: nbadtraj + LABLAXIS: Counts nl2: <<: *default_counts CATDESC: Raw number of events sorted into L12 event category - FIELDNAM: nl2 - LABLAXIS: Counts DELTA_MINUS_VAR: nl2_stat_uncert_minus DELTA_PLUS_VAR: nl2_stat_uncert_plus + FIELDNAM: nl2 + LABLAXIS: Counts nl3: <<: *default_counts CATDESC: Raw number of events sorted into L123 event category - FIELDNAM: nl3 - LABLAXIS: Counts DELTA_MINUS_VAR: nl3_stat_uncert_minus DELTA_PLUS_VAR: nl3_stat_uncert_plus + FIELDNAM: nl3 + LABLAXIS: Counts nl4: <<: *default_counts CATDESC: Raw number of events sorted into L1423 event category - FIELDNAM: nl4 - LABLAXIS: Counts DELTA_MINUS_VAR: nl4_stat_uncert_minus DELTA_PLUS_VAR: nl4_stat_uncert_plus + FIELDNAM: nl4 + LABLAXIS: Counts npen: <<: *default_counts CATDESC: Raw number of events sorted into PEN event category - FIELDNAM: npen - LABLAXIS: Counts DELTA_MINUS_VAR: npen_stat_uncert_minus DELTA_PLUS_VAR: npen_stat_uncert_plus + FIELDNAM: npen + LABLAXIS: Counts nformat: <<: *default_counts CATDESC: Raw number of events handled by the telemetry event formatter - FIELDNAM: nformat - LABLAXIS: Counts DELTA_MINUS_VAR: nformat_stat_uncert_minus DELTA_PLUS_VAR: nformat_stat_uncert_plus + FIELDNAM: nformat + LABLAXIS: Counts naside: <<: *default_counts CATDESC: Raw number of events the software assumed were A-side events - FIELDNAM: naside - LABLAXIS: Counts DELTA_MINUS_VAR: naside_stat_uncert_minus DELTA_PLUS_VAR: naside_stat_uncert_plus + FIELDNAM: naside + LABLAXIS: Counts nbside: <<: *default_counts CATDESC: Raw number of events the software assumed were B-side events - FIELDNAM: nbside - LABLAXIS: Counts DELTA_MINUS_VAR: nbside_stat_uncert_minus DELTA_PLUS_VAR: nbside_stat_uncert_plus + FIELDNAM: nbside + LABLAXIS: Counts nerror: <<: *default_counts CATDESC: Raw number of events that caused a processing error - FIELDNAM: nerror - LABLAXIS: Counts DELTA_MINUS_VAR: nerror_stat_uncert_minus DELTA_PLUS_VAR: nerror_stat_uncert_plus + FIELDNAM: nerror + LABLAXIS: Counts nbadtags: <<: *default_counts CATDESC: Raw number of events with bad tags from onboard event-processing - FIELDNAM: nbadtags - LABLAXIS: Counts DELTA_MINUS_VAR: nbadtags_stat_uncert_minus DELTA_PLUS_VAR: nbadtags_stat_uncert_plus + FIELDNAM: nbadtags + LABLAXIS: Counts sngrates: <<: *default_counts + CATDESC: Raw single rates per integration + DELTA_MINUS_VAR: sngrates_stat_uncert_minus + DELTA_PLUS_VAR: sngrates_stat_uncert_plus DEPEND_1: gain DEPEND_2: sngrates_index - CATDESC: Raw single rates per integration FIELDNAM: sngrates LABL_PTR_1: gain_label LABL_PTR_2: sngrates_index_label - DELTA_MINUS_VAR: sngrates_stat_uncert_minus - DELTA_PLUS_VAR: sngrates_stat_uncert_plus coinrates: <<: *default_counts - DEPEND_1: coinrates_index CATDESC: Raw coincidence rates per integration - FIELDNAM: coinrates - LABL_PTR_1: coinrates_index_label DELTA_MINUS_VAR: coinrates_stat_uncert_minus DELTA_PLUS_VAR: coinrates_stat_uncert_plus + DEPEND_1: coinrates_index + FIELDNAM: coinrates + LABL_PTR_1: coinrates_index_label pbufrates: <<: *default_counts - DEPEND_1: pbufrates_index CATDESC: Raw priority buffer rates per integration - FIELDNAM: pbufrates - LABL_PTR_1: pbufrates_index_label DELTA_MINUS_VAR: pbufrates_stat_uncert_minus DELTA_PLUS_VAR: pbufrates_stat_uncert_plus + DEPEND_1: pbufrates_index + FIELDNAM: pbufrates + LABL_PTR_1: pbufrates_index_label l2fgrates: <<: *default_counts - DEPEND_1: l2fgrates_index CATDESC: Raw range 2 foreground rates per integration - FIELDNAM: l2fgrates - LABL_PTR_1: l2fgrates_index_label DELTA_MINUS_VAR: l2fgrates_stat_uncert_minus DELTA_PLUS_VAR: l2fgrates_stat_uncert_plus + DEPEND_1: l2fgrates_index + FIELDNAM: l2fgrates + LABL_PTR_1: l2fgrates_index_label l2bgrates: <<: *default_counts - DEPEND_1: l2bgrates_index CATDESC: Raw range 2 background rates per integration - FIELDNAM: l2bgrates - LABL_PTR_1: l2bgrates_index_label DELTA_MINUS_VAR: l2bgrates_stat_uncert_minus DELTA_PLUS_VAR: l2bgrates_stat_uncert_plus + DEPEND_1: l2bgrates_index + FIELDNAM: l2bgrates + LABL_PTR_1: l2bgrates_index_label l3fgrates: <<: *default_counts - DEPEND_1: l3fgrates_index CATDESC: Raw range 3 foreground rates per integration - FIELDNAM: l3fgrates - LABL_PTR_1: l3fgrates_index_label DELTA_MINUS_VAR: l3fgrates_stat_uncert_minus DELTA_PLUS_VAR: l3fgrates_stat_uncert_plus + DEPEND_1: l3fgrates_index + FIELDNAM: l3fgrates + LABL_PTR_1: l3fgrates_index_label l3bgrates: <<: *default_counts - DEPEND_1: l3bgrates_index CATDESC: Raw range 3 background rates per integration - FIELDNAM: l3bgrates - LABL_PTR_1: l3bgrates_index_label DELTA_MINUS_VAR: l3bgrates_stat_uncert_minus DELTA_PLUS_VAR: l3bgrates_stat_uncert_plus + DEPEND_1: l3bgrates_index + FIELDNAM: l3bgrates + LABL_PTR_1: l3bgrates_index_label penfgrates: <<: *default_counts - DEPEND_1: penfgrates_index CATDESC: Raw range 4 foreground rates per integration - FIELDNAM: penfgrates - LABL_PTR_1: penfgrates_index_label DELTA_MINUS_VAR: penfgrates_stat_uncert_minus DELTA_PLUS_VAR: penfgrates_stat_uncert_plus + DEPEND_1: penfgrates_index + FIELDNAM: penfgrates + LABL_PTR_1: penfgrates_index_label penbgrates: <<: *default_counts - DEPEND_1: penbgrates_index CATDESC: Raw range 4 background rates per integration - FIELDNAM: penbgrates - LABL_PTR_1: penbgrates_index_label DELTA_MINUS_VAR: penbgrates_stat_uncert_minus DELTA_PLUS_VAR: penbgrates_stat_uncert_plus + DEPEND_1: penbgrates_index + FIELDNAM: penbgrates + LABL_PTR_1: penbgrates_index_label ialirtrates: <<: *default_counts - DEPEND_1: ialirtrates_index CATDESC: Raw ialirtrates per integration - FIELDNAM: ialirtrates - LABL_PTR_1: ialirtrates_index_label DELTA_MINUS_VAR: ialirtrates_stat_uncert_minus DELTA_PLUS_VAR: ialirtrates_stat_uncert_plus + DEPEND_1: ialirtrates_index + FIELDNAM: ialirtrates + LABL_PTR_1: ialirtrates_index_label l4fgrates: <<: *default_counts - DEPEND_1: l4fgrates_index CATDESC: Raw L4 ions foreground rates per integration - FIELDNAM: l4fgrates - LABL_PTR_1: l4fgrates_index_label DELTA_MINUS_VAR: l4fgrates_stat_uncert_minus DELTA_PLUS_VAR: l4fgrates_stat_uncert_plus + DEPEND_1: l4fgrates_index + FIELDNAM: l4fgrates + LABL_PTR_1: l4fgrates_index_label l4bgrates: <<: *default_counts - DEPEND_1: l4bgrates_index CATDESC: Raw L4 ions background rates per integration - FIELDNAM: l4bgrates - LABL_PTR_1: l4bgrates_index_label DELTA_MINUS_VAR: l4bgrates_stat_uncert_minus DELTA_PLUS_VAR: l4bgrates_stat_uncert_plus + DEPEND_1: l4bgrates_index + FIELDNAM: l4bgrates + LABL_PTR_1: l4bgrates_index_label sectorates: <<: *default_counts + CATDESC: Raw sectored rates per integration + DELTA_MINUS_VAR: sectorates_stat_uncert_minus + DELTA_PLUS_VAR: sectorates_stat_uncert_plus DEPEND_1: azimuth DEPEND_2: zenith - CATDESC: Raw sectored rates per integration FIELDNAM: Sectored rates LABL_PTR_1: azimuth_label LABL_PTR_2: zenith_label - DELTA_MINUS_VAR: sectorates_stat_uncert_minus - DELTA_PLUS_VAR: sectorates_stat_uncert_plus h_sectored_counts: <<: *default_counts CATDESC: Raw H sectored counts per integration - FIELDNAM: H sectored counts + DELTA_MINUS_VAR: h_sectored_counts_stat_uncert_minus + DELTA_PLUS_VAR: h_sectored_counts_stat_uncert_plus DEPEND_1: h_energy_mean DEPEND_2: azimuth DEPEND_3: zenith + FIELDNAM: H sectored counts LABL_PTR_1: h_energy_mean_label LABL_PTR_2: azimuth_label LABL_PTR_3: zenith_label - DELTA_MINUS_VAR: h_sectored_counts_stat_uncert_minus - DELTA_PLUS_VAR: h_sectored_counts_stat_uncert_plus he4_sectored_counts: <<: *default_counts CATDESC: Raw He4 sectored counts per integration - FIELDNAM: He4 sectored counts + DELTA_MINUS_VAR: he4_sectored_counts_stat_uncert_minus + DELTA_PLUS_VAR: he4_sectored_counts_stat_uncert_plus DEPEND_1: he4_energy_mean DEPEND_2: azimuth DEPEND_3: zenith + FIELDNAM: He4 sectored counts LABL_PTR_1: he4_energy_mean_label LABL_PTR_2: azimuth_label LABL_PTR_3: zenith_label - DELTA_MINUS_VAR: he4_sectored_counts_stat_uncert_minus - DELTA_PLUS_VAR: he4_sectored_counts_stat_uncert_plus cno_sectored_counts: <<: *default_counts CATDESC: Raw C, N, O sectored counts per integration - FIELDNAM: C, N, O sectored counts + DELTA_MINUS_VAR: cno_sectored_counts_stat_uncert_minus + DELTA_PLUS_VAR: cno_sectored_counts_stat_uncert_plus DEPEND_1: cno_energy_mean DEPEND_2: azimuth DEPEND_3: zenith + FIELDNAM: C, N, O sectored counts LABL_PTR_1: cno_energy_mean_label LABL_PTR_2: azimuth_label LABL_PTR_3: zenith_label - DELTA_MINUS_VAR: cno_sectored_counts_stat_uncert_minus - DELTA_PLUS_VAR: cno_sectored_counts_stat_uncert_plus nemgsi_sectored_counts: <<: *default_counts CATDESC: Raw Ne, Mg, Si sectored counts per integration - FIELDNAM: Ne, Mg, Si sectored counts + DELTA_MINUS_VAR: nemgsi_sectored_counts_stat_uncert_minus + DELTA_PLUS_VAR: nemgsi_sectored_counts_stat_uncert_plus DEPEND_1: nemgsi_energy_mean DEPEND_2: azimuth DEPEND_3: zenith + FIELDNAM: Ne, Mg, Si sectored counts LABL_PTR_1: nemgsi_energy_mean_label LABL_PTR_2: azimuth_label LABL_PTR_3: zenith_label - DELTA_MINUS_VAR: nemgsi_sectored_counts_stat_uncert_minus - DELTA_PLUS_VAR: nemgsi_sectored_counts_stat_uncert_plus fe_sectored_counts: <<: *default_counts CATDESC: Raw Fe sectored counts per integration - FIELDNAM: Fe sectored counts + DELTA_MINUS_VAR: fe_sectored_counts_stat_uncert_minus + DELTA_PLUS_VAR: fe_sectored_counts_stat_uncert_plus DEPEND_1: fe_energy_mean DEPEND_2: azimuth DEPEND_3: zenith + FIELDNAM: Fe sectored counts LABL_PTR_1: fe_energy_mean_label LABL_PTR_2: azimuth_label LABL_PTR_3: zenith_label - DELTA_MINUS_VAR: fe_sectored_counts_stat_uncert_minus - DELTA_PLUS_VAR: fe_sectored_counts_stat_uncert_plus # Counts energy delta variables h_energy_delta_plus: <<: *default_energy - DEPEND_1: h_energy_mean CATDESC: H energy per nucleon delta plus (maximum bin energy per nuc. minus geometric mean) + DEPEND_1: h_energy_mean FIELDNAM: H energy delta plus h_energy_delta_minus: <<: *default_energy - DEPEND_1: h_energy_mean CATDESC: H energy per nucleon delta minus (geometric mean minus minimum bin energy per nuc.) + DEPEND_1: h_energy_mean FIELDNAM: H energy delta minus he4_energy_delta_plus: <<: *default_energy - DEPEND_1: he4_energy_mean CATDESC: He4 energy per nucleon delta plus (maximum bin energy per nuc. minus geometric mean) + DEPEND_1: he4_energy_mean FIELDNAM: He4 energy delta plus he4_energy_delta_minus: <<: *default_energy - DEPEND_1: he4_energy_mean CATDESC: He4 energy per nucleon delta minus (geometric mean minus minimum bin energy per nuc.) + DEPEND_1: he4_energy_mean FIELDNAM: He4 energy delta minus cno_energy_delta_plus: <<: *default_energy - DEPEND_1: cno_energy_mean CATDESC: C, N, O energy per nucleon delta plus (maximum bin energy per nuc. minus geometric mean) + DEPEND_1: cno_energy_mean FIELDNAM: C, N, O energy delta plus cno_energy_delta_minus: <<: *default_energy - DEPEND_1: cno_energy_mean CATDESC: C, N, O energy per nucleon delta minus (geometric mean minus minimum bin energy per nuc.) + DEPEND_1: cno_energy_mean FIELDNAM: C, N, O energy delta minus nemgsi_energy_delta_plus: <<: *default_energy - DEPEND_1: nemgsi_energy_mean CATDESC: Ne, Mg, Si energy per nucleon delta plus (maximum bin energy per nuc. minus geometric mean) + DEPEND_1: nemgsi_energy_mean FIELDNAM: Ne, Mg, Si energy delta plus nemgsi_energy_delta_minus: <<: *default_energy - DEPEND_1: nemgsi_energy_mean CATDESC: Ne, Mg, Si energy per nucleon delta minus (geometric mean minus minimum bin energy per nuc.) + DEPEND_1: nemgsi_energy_mean FIELDNAM: Ne, Mg, Si energy delta minus fe_energy_delta_plus: <<: *default_energy - DEPEND_1: fe_energy_mean CATDESC: Fe energy per nucleon delta plus (maximum bin energy per nuc. minus geometric mean) + DEPEND_1: fe_energy_mean FIELDNAM: Fe energy delta plus fe_energy_delta_minus: <<: *default_energy - DEPEND_1: fe_energy_mean CATDESC: Fe energy per nucleon delta minus (geometric mean minus minimum bin energy per nuc.) + DEPEND_1: fe_energy_mean FIELDNAM: Fe energy delta minus # Counts uncertainty variables sectorates_stat_uncert_plus: <<: *default_uncertainty CATDESC: Plus statistical uncertainty for sector rates - FIELDNAM: Sectored Rates Uncertainty DEPEND_1: azimuth DEPEND_2: zenith + FIELDNAM: Sectored Rates Uncertainty LABL_PTR_1: azimuth_label LABL_PTR_2: zenith_label sectorates_stat_uncert_minus: <<: *default_uncertainty CATDESC: Minus statistical uncertainty for sector rates - FIELDNAM: Sectored Rates Uncertainty DEPEND_1: azimuth DEPEND_2: zenith + FIELDNAM: Sectored Rates Uncertainty LABL_PTR_1: azimuth_label LABL_PTR_2: zenith_label h_sectored_counts_stat_uncert_plus: <<: *default_uncertainty CATDESC: Plus statistical uncertainty for H - FIELDNAM: H Uncertainty DEPEND_1: h_energy_mean DEPEND_2: azimuth DEPEND_3: zenith + FIELDNAM: H Uncertainty LABL_PTR_1: h_energy_mean_label LABL_PTR_2: azimuth_label LABL_PTR_3: zenith_label @@ -997,10 +997,10 @@ h_sectored_counts_stat_uncert_plus: h_sectored_counts_stat_uncert_minus: <<: *default_uncertainty CATDESC: Minus statistical uncertainty for H - FIELDNAM: H Uncertainty DEPEND_1: h_energy_mean DEPEND_2: azimuth DEPEND_3: zenith + FIELDNAM: H Uncertainty LABL_PTR_1: h_energy_mean_label LABL_PTR_2: azimuth_label LABL_PTR_3: zenith_label @@ -1008,10 +1008,10 @@ h_sectored_counts_stat_uncert_minus: he4_sectored_counts_stat_uncert_plus: <<: *default_uncertainty CATDESC: Plus statistical uncertainty for He4 - FIELDNAM: He4 Uncertainty DEPEND_1: he4_energy_mean DEPEND_2: azimuth DEPEND_3: zenith + FIELDNAM: He4 Uncertainty LABL_PTR_1: he4_energy_mean_label LABL_PTR_2: azimuth_label LABL_PTR_3: zenith_label @@ -1019,10 +1019,10 @@ he4_sectored_counts_stat_uncert_plus: he4_sectored_counts_stat_uncert_minus: <<: *default_uncertainty CATDESC: Minus statistical uncertainty for He4 - FIELDNAM: He4 Uncertainty DEPEND_1: he4_energy_mean DEPEND_2: azimuth DEPEND_3: zenith + FIELDNAM: He4 Uncertainty LABL_PTR_1: he4_energy_mean_label LABL_PTR_2: azimuth_label LABL_PTR_3: zenith_label @@ -1030,10 +1030,10 @@ he4_sectored_counts_stat_uncert_minus: cno_sectored_counts_stat_uncert_plus: <<: *default_uncertainty CATDESC: Plus statistical uncertainty for C, N, O - FIELDNAM: CNO Uncertainty DEPEND_1: cno_energy_mean DEPEND_2: azimuth DEPEND_3: zenith + FIELDNAM: CNO Uncertainty LABL_PTR_1: cno_energy_mean_label LABL_PTR_2: azimuth_label LABL_PTR_3: zenith_label @@ -1041,10 +1041,10 @@ cno_sectored_counts_stat_uncert_plus: cno_sectored_counts_stat_uncert_minus: <<: *default_uncertainty CATDESC: Minus statistical uncertainty for C, N, O - FIELDNAM: CNO Uncertainty DEPEND_1: cno_energy_mean DEPEND_2: azimuth DEPEND_3: zenith + FIELDNAM: CNO Uncertainty LABL_PTR_1: cno_energy_mean_label LABL_PTR_2: azimuth_label LABL_PTR_3: zenith_label @@ -1052,10 +1052,10 @@ cno_sectored_counts_stat_uncert_minus: nemgsi_sectored_counts_stat_uncert_plus: <<: *default_uncertainty CATDESC: Plus statistical uncertainty for Ne, Mg, Si - FIELDNAM: NeMgSi Uncertainty DEPEND_1: nemgsi_energy_mean DEPEND_2: azimuth DEPEND_3: zenith + FIELDNAM: NeMgSi Uncertainty LABL_PTR_1: nemgsi_energy_mean_label LABL_PTR_2: azimuth_label LABL_PTR_3: zenith_label @@ -1063,10 +1063,10 @@ nemgsi_sectored_counts_stat_uncert_plus: nemgsi_sectored_counts_stat_uncert_minus: <<: *default_uncertainty CATDESC: Minus statistical uncertainty for Ne, Mg, Si - FIELDNAM: NeMgSi Uncertainty DEPEND_1: nemgsi_energy_mean DEPEND_2: azimuth DEPEND_3: zenith + FIELDNAM: NeMgSi Uncertainty LABL_PTR_1: nemgsi_energy_mean_label LABL_PTR_2: azimuth_label LABL_PTR_3: zenith_label @@ -1074,10 +1074,10 @@ nemgsi_sectored_counts_stat_uncert_minus: fe_sectored_counts_stat_uncert_plus: <<: *default_uncertainty CATDESC: Plus statistical uncertainty for Fe - FIELDNAM: Fe Uncertainty DEPEND_1: fe_energy_mean DEPEND_2: azimuth DEPEND_3: zenith + FIELDNAM: Fe Uncertainty LABL_PTR_1: fe_energy_mean_label LABL_PTR_2: azimuth_label LABL_PTR_3: zenith_label @@ -1085,10 +1085,10 @@ fe_sectored_counts_stat_uncert_plus: fe_sectored_counts_stat_uncert_minus: <<: *default_uncertainty CATDESC: Minus statistical uncertainty for Fe - FIELDNAM: Fe Uncertainty DEPEND_1: fe_energy_mean DEPEND_2: azimuth DEPEND_3: zenith + FIELDNAM: Fe Uncertainty LABL_PTR_1: fe_energy_mean_label LABL_PTR_2: azimuth_label LABL_PTR_3: zenith_label @@ -1096,173 +1096,173 @@ fe_sectored_counts_stat_uncert_minus: sngrates_stat_uncert_plus: <<: *default_uncertainty CATDESC: Plus statistical uncertainty for single rates - FIELDNAM: sngrates uncertainty DEPEND_1: gain DEPEND_2: sngrates_index + FIELDNAM: sngrates uncertainty LABL_PTR_1: gain_label LABL_PTR_2: sngrates_index_label sngrates_stat_uncert_minus: <<: *default_uncertainty CATDESC: Minus statistical uncertainty for single rates - FIELDNAM: sngrates uncertainty DEPEND_1: gain DEPEND_2: sngrates_index + FIELDNAM: sngrates uncertainty LABL_PTR_1: gain_label LABL_PTR_2: sngrates_index_label coinrates_stat_uncert_plus: <<: *default_uncertainty CATDESC: Plus statistical uncertainty for coincidence rates - FIELDNAM: coinrates uncertainty DEPEND_1: coinrates_index + FIELDNAM: coinrates uncertainty LABL_PTR_1: coinrates_index_label coinrates_stat_uncert_minus: <<: *default_uncertainty CATDESC: Minus statistical uncertainty for coincidence rates - FIELDNAM: coinrates uncertainty DEPEND_1: coinrates_index + FIELDNAM: coinrates uncertainty LABL_PTR_1: coinrates_index_label pbufrates_stat_uncert_plus: <<: *default_uncertainty CATDESC: Plus statistical uncertainty for priority buffer rates - FIELDNAM: pbufrates uncertainty DEPEND_1: pbufrates_index + FIELDNAM: pbufrates uncertainty LABL_PTR_1: pbufrates_index_label pbufrates_stat_uncert_minus: <<: *default_uncertainty CATDESC: Minus statistical uncertainty for priority buffer rates - FIELDNAM: pbufrates uncertainty DEPEND_1: pbufrates_index + FIELDNAM: pbufrates uncertainty LABL_PTR_1: pbufrates_index_label l2fgrates_stat_uncert_plus: <<: *default_uncertainty CATDESC: Plus statistical uncertainty for range 2 foreground rates - FIELDNAM: l2fgrates uncertainty DEPEND_1: l2fgrates_index + FIELDNAM: l2fgrates uncertainty LABL_PTR_1: l2fgrates_index_label l2fgrates_stat_uncert_minus: <<: *default_uncertainty CATDESC: Minus statistical uncertainty for range 2 foreground rates - FIELDNAM: l2fgrates uncertainty DEPEND_1: l2fgrates_index + FIELDNAM: l2fgrates uncertainty LABL_PTR_1: l2fgrates_index_label l2bgrates_stat_uncert_plus: <<: *default_uncertainty CATDESC: Plus statistical uncertainty for range 2 background rates - FIELDNAM: l2bgrates uncertainty DEPEND_1: l2bgrates_index + FIELDNAM: l2bgrates uncertainty LABL_PTR_1: l2bgrates_index_label l2bgrates_stat_uncert_minus: <<: *default_uncertainty CATDESC: Minus statistical uncertainty for range 2 background rates - FIELDNAM: l2bgrates uncertainty DEPEND_1: l2bgrates_index + FIELDNAM: l2bgrates uncertainty LABL_PTR_1: l2bgrates_index_label l3fgrates_stat_uncert_plus: <<: *default_uncertainty CATDESC: Plus statistical uncertainty for range 3 foreground rates - FIELDNAM: l3fgrates uncertainty DEPEND_1: l3fgrates_index + FIELDNAM: l3fgrates uncertainty LABL_PTR_1: l3fgrates_index_label l3fgrates_stat_uncert_minus: <<: *default_uncertainty CATDESC: Minus statistical uncertainty for range 3 foreground rates - FIELDNAM: l3fgrates uncertainty DEPEND_1: l3fgrates_index + FIELDNAM: l3fgrates uncertainty LABL_PTR_1: l3fgrates_index_label l3bgrates_stat_uncert_plus: <<: *default_uncertainty CATDESC: Plus statistical uncertainty for range 3 background rates - FIELDNAM: l3bgrates uncertainty DEPEND_1: l3bgrates_index + FIELDNAM: l3bgrates uncertainty LABL_PTR_1: l3bgrates_index_label l3bgrates_stat_uncert_minus: <<: *default_uncertainty CATDESC: Minus statistical uncertainty for range 3 background rates - FIELDNAM: l3bgrates uncertainty DEPEND_1: l3bgrates_index + FIELDNAM: l3bgrates uncertainty LABL_PTR_1: l3bgrates_index_label penfgrates_stat_uncert_plus: <<: *default_uncertainty CATDESC: Plus statistical uncertainty for range 4 foreground rates - FIELDNAM: penfgrates uncertainty DEPEND_1: penfgrates_index + FIELDNAM: penfgrates uncertainty LABL_PTR_1: penfgrates_index_label penfgrates_stat_uncert_minus: <<: *default_uncertainty CATDESC: Minus statistical uncertainty for range 4 foreground rates - FIELDNAM: penfgrates uncertainty DEPEND_1: penfgrates_index + FIELDNAM: penfgrates uncertainty LABL_PTR_1: penfgrates_index_label penbgrates_stat_uncert_plus: <<: *default_uncertainty CATDESC: Plus statistical uncertainty for range 4 background rates - FIELDNAM: penbgrates uncertainty DEPEND_1: penbgrates_index + FIELDNAM: penbgrates uncertainty LABL_PTR_1: penbgrates_index_label penbgrates_stat_uncert_minus: <<: *default_uncertainty CATDESC: Minus statistical uncertainty for range 4 background rates - FIELDNAM: penbgrates uncertainty DEPEND_1: penbgrates_index + FIELDNAM: penbgrates uncertainty LABL_PTR_1: penbgrates_index_label ialirtrates_stat_uncert_plus: <<: *default_uncertainty CATDESC: Plus statistical uncertainty for ialirtrates - FIELDNAM: ialirtrates uncertainty DEPEND_1: ialirtrates_index + FIELDNAM: ialirtrates uncertainty LABL_PTR_1: ialirtrates_index_label ialirtrates_stat_uncert_minus: <<: *default_uncertainty CATDESC: Minus statistical uncertainty for ialirtrates - FIELDNAM: ialirtrates uncertainty DEPEND_1: ialirtrates_index + FIELDNAM: ialirtrates uncertainty LABL_PTR_1: ialirtrates_index_label l4fgrates_stat_uncert_plus: <<: *default_uncertainty CATDESC: Plus statistical uncertainty for L4 ions foreground rates - FIELDNAM: l4fgrates uncertainty DEPEND_1: l4fgrates_index + FIELDNAM: l4fgrates uncertainty LABL_PTR_1: l4fgrates_index_label l4fgrates_stat_uncert_minus: <<: *default_uncertainty CATDESC: Minus statistical uncertainty for L4 ions foreground rates - FIELDNAM: l4fgrates uncertainty DEPEND_1: l4fgrates_index + FIELDNAM: l4fgrates uncertainty LABL_PTR_1: l4fgrates_index_label l4bgrates_stat_uncert_plus: <<: *default_uncertainty CATDESC: Plus statistical uncertainty for L4 ions background rates - FIELDNAM: l4bgrates uncertainty DEPEND_1: l4bgrates_index + FIELDNAM: l4bgrates uncertainty LABL_PTR_1: l4bgrates_index_label l4bgrates_stat_uncert_minus: <<: *default_uncertainty CATDESC: Minus statistical uncertainty for L4 ions background rates - FIELDNAM: l4bgrates uncertainty DEPEND_1: l4bgrates_index + FIELDNAM: l4bgrates uncertainty LABL_PTR_1: l4bgrates_index_label num_trig_stat_uncert_plus: @@ -1517,260 +1517,260 @@ nbadtags_stat_uncert_minus: # PHA dataset variables pha_raw: - DEPEND_0: epoch CATDESC: Raw instrument pulse height analyzer data. Further processed in HIT L3 data. - VAR_TYPE: ignore_data + DEPEND_0: epoch DISPLAY_TYPE: no_plot + VAR_TYPE: ignore_data # Housekeeping dataset variables fsw_version_a: <<: *default_hk_support - VALIDMAX: 63 CATDESC: Flight Software Version Number (A.B.C bits) FIELDNAM: Flight Software Version Number A - LABLAXIS: FSW A FORMAT: I2 + LABLAXIS: FSW A + VALIDMAX: 63 fsw_version_b: <<: *default_hk_support - VALIDMAX: 63 CATDESC: Flight Software Version Number (A.B.C bits) FIELDNAM: Flight Software Version Number B - LABLAXIS: FSW B FORMAT: I2 + LABLAXIS: FSW B + VALIDMAX: 63 fsw_version_c: <<: *default_hk_support - VALIDMAX: 63 CATDESC: Flight Software Version Number (A.B.C bits) FIELDNAM: Flight Software Version Number C - LABLAXIS: FSW C FORMAT: I2 + LABLAXIS: FSW C + VALIDMAX: 63 num_good_cmds: <<: *default_hk_support - VALIDMAX: 255 CATDESC: Number of Good Commands FIELDNAM: Number of Good Commands - LABLAXIS: Counts FORMAT: I3 + LABLAXIS: Counts + VALIDMAX: 255 last_good_cmd: <<: *default_hk_support - VALIDMAX: 255 CATDESC: Last Good Command FIELDNAM: Last Good Command - LABLAXIS: Last cmd FORMAT: I3 + LABLAXIS: Last cmd + VALIDMAX: 255 last_good_seq_num: <<: *default_hk_support - VALIDMAX: 255 CATDESC: Last Good Sequence Number FIELDNAM: Last Good Sequence Number - LABLAXIS: Last num FORMAT: I3 + LABLAXIS: Last num + VALIDMAX: 255 num_bad_cmds: <<: *default_hk_support - VALIDMAX: 255 CATDESC: Number of Bad Commands FIELDNAM: Number of Bad Commands - LABLAXIS: Counts FORMAT: I3 + LABLAXIS: Counts + VALIDMAX: 255 last_bad_cmd: <<: *default_hk_support - VALIDMAX: 255 CATDESC: Last Bad Command FIELDNAM: Last Bad Command - LABLAXIS: Last cmd FORMAT: I3 + LABLAXIS: Last cmd + VALIDMAX: 255 last_bad_seq_num: <<: *default_hk_support - VALIDMAX: 255 CATDESC: Last Bad Sequence Number FIELDNAM: Last Bad Sequence Number - LABLAXIS: Last num FORMAT: I3 + LABLAXIS: Last num + VALIDMAX: 255 fee_running: <<: *default_hk_support - VALIDMAX: 1 CATDESC: State - FEE Running (1) or Reset (0) FIELDNAM: FEE Running (1) or Reset (0) - LABLAXIS: State FORMAT: I1 + LABLAXIS: State + VALIDMAX: 1 mram_disabled: <<: *default_hk_support - VALIDMAX: 1 CATDESC: State - MRAM Disabled (1) or Enabled (0) FIELDNAM: MRAM Disabled (1) or Enabled (0) - LABLAXIS: State FORMAT: I1 + LABLAXIS: State + VALIDMAX: 1 enable_50khz: <<: *default_hk_support - VALIDMAX: 1 CATDESC: State - 50kHz Enabled (1) or Disabled (0) FIELDNAM: 50kHz Enabled (1) or Disabled (0) - LABLAXIS: State FORMAT: I1 + LABLAXIS: State + VALIDMAX: 1 enable_hvps: <<: *default_hk_support - VALIDMAX: 1 CATDESC: State - HVPS Enabled (1) or Disabled (0) FIELDNAM: HVPS Enabled (1) or Disabled (0) - LABLAXIS: State FORMAT: I1 + LABLAXIS: State + VALIDMAX: 1 table_status: <<: *default_hk_support - VALIDMAX: 1 CATDESC: State - Table Status OK (1) or Error (0) FIELDNAM: Table Status OK (1) or Error (0) - LABLAXIS: Status FORMAT: I1 + LABLAXIS: Status + VALIDMAX: 1 heater_control: <<: *default_hk_support - VALIDMAX: 2 CATDESC: State - Heater Control (0=None, 1=Pri, 2=Sec) FIELDNAM: Heater Control (0=None, 1=Pri, 2=Sec) - LABLAXIS: State FORMAT: I1 + LABLAXIS: State + VALIDMAX: 2 adc_mode: <<: *default_hk_support - VALIDMAX: 3 CATDESC: State - ADC Mode (0=quiet, 1=normal, 2=adcstim, 3=adcThreshold) FIELDNAM: ADC Mode (0=quiet, 1=normal, 2=adcstim, 3=adcThreshold) - LABLAXIS: ADC mode FORMAT: I1 + LABLAXIS: ADC mode + VALIDMAX: 3 mode: <<: *default_hk_support - VALIDMAX: 3 CATDESC: State - Mode (0=Boot, 1=Maintenance, 2=Standby, 3=Science) FIELDNAM: Mode (0=Boot, 1=Maintenance, 2=Standby, 3=Science) - LABLAXIS: Mode FORMAT: I1 + LABLAXIS: Mode + VALIDMAX: 3 dyn_thresh_lvl: <<: *default_hk_support - VALIDMAX: 3 CATDESC: Dynamic Threshold Level (0-3) FIELDNAM: Dynamic Threshold Level (0-3) - LABLAXIS: Level FORMAT: I1 + LABLAXIS: Level + VALIDMAX: 3 num_evnt_last_hk: <<: *default_hk_support - VALIDMAX: 4294967295 CATDESC: Number of Events Since Last HK Update FIELDNAM: Number of Events Since Last HK Update - LABLAXIS: Num events FORMAT: I10 + LABLAXIS: Num events + VALIDMAX: 4294967295 num_errors: <<: *default_hk_support - VALIDMAX: 255 CATDESC: Number of Errors FIELDNAM: Number of Errors - LABLAXIS: Num errors FORMAT: I3 + LABLAXIS: Num errors + VALIDMAX: 255 last_error_num: <<: *default_hk_support - VALIDMAX: 255 CATDESC: State - Last Error Number FIELDNAM: Last Error Number - LABLAXIS: Error num FORMAT: I3 + LABLAXIS: Error num + VALIDMAX: 255 code_checksum: <<: *default_hk_support - VALIDMAX: 65535 CATDESC: Code Checksum FIELDNAM: Code Checksum - LABLAXIS: Checksum FORMAT: I5 + LABLAXIS: Checksum + VALIDMAX: 65535 spin_period_short: <<: *default_hk_support - VALIDMAX: 65535 CATDESC: Spin Period Short at T=0 FIELDNAM: Spin Period Short at T=0 - LABLAXIS: Spin period short FORMAT: I5 + LABLAXIS: Spin period short + VALIDMAX: 65535 spin_period_long: <<: *default_hk_support - VALIDMAX: 65535 CATDESC: Spin Period Long at T=0 FIELDNAM: Spin Period Long at T=0 - LABLAXIS: Spin period long FORMAT: I5 + LABLAXIS: Spin period long + VALIDMAX: 65535 leak_i: <<: *default_hk_support - DEPEND_1: adc_channels CATDESC: Leakage Current [I] + DEPEND_1: adc_channels FIELDNAM: Leakage Current [I] - LABLAXIS: Current I - LABEL_PTR_1: adc_channels_label FORMAT: I19 + LABEL_PTR_1: adc_channels_label + LABLAXIS: Current I phasic_stat: <<: *default_hk_support - VALIDMAX: 1 CATDESC: State - Phasic Status FIELDNAM: Phasic Status - LABLAXIS: Status FORMAT: I1 + LABLAXIS: Status + VALIDMAX: 1 active_heater: <<: *default_hk_support - VALIDMAX: 1 CATDESC: State - Active Heater FIELDNAM: Active Heater - LABLAXIS: State FORMAT: I1 + LABLAXIS: State + VALIDMAX: 1 heater_on: <<: *default_hk_support - VALIDMAX: 1 CATDESC: State - Heater On/Off FIELDNAM: Heater On/Off - LABLAXIS: State FORMAT: I1 + LABLAXIS: State + VALIDMAX: 1 test_pulser_on: <<: *default_hk_support - VALIDMAX: 1 CATDESC: State - Test Pulser On/Off FIELDNAM: Test Pulser On/Off - LABLAXIS: State FORMAT: I1 + LABLAXIS: State + VALIDMAX: 1 dac0_enable: <<: *default_hk_support - VALIDMAX: 1 CATDESC: State - DAC 0 Enable FIELDNAM: DAC 0 Enable - LABLAXIS: State FORMAT: I1 + LABLAXIS: State + VALIDMAX: 1 dac1_enable: <<: *default_hk_support - VALIDMAX: 1 CATDESC: State - DAC 1 Enable FIELDNAM: DAC 1 Enable - LABLAXIS: State FORMAT: I1 + LABLAXIS: State + VALIDMAX: 1 preamp_l234a: <<: *default_hk diff --git a/imap_processing/cdf/config/imap_hit_l1b_variable_attrs.yaml b/imap_processing/cdf/config/imap_hit_l1b_variable_attrs.yaml index fa991add4d..6404af87c0 100644 --- a/imap_processing/cdf/config/imap_hit_l1b_variable_attrs.yaml +++ b/imap_processing/cdf/config/imap_hit_l1b_variable_attrs.yaml @@ -7,11 +7,11 @@ default_attrs: &default DISPLAY_TYPE: time_series FILLVAL: -9223372036854775808 FORMAT: I12 - VALIDMIN: 0 + SCALETYP: linear + UNITS: ' ' VALIDMAX: 9223372036854775807 + VALIDMIN: 0 VAR_TYPE: data - UNITS: ' ' - SCALETYP: linear hk_support_attrs: &hk_support_default <<: *default @@ -26,23 +26,23 @@ default_uint32_attrs: &default_uint32 <<: *default FILLVAL: 4294967295 FORMAT: I10 - VALIDMIN: 0 VALIDMAX: 4294967295 + VALIDMIN: 0 dtype: uint32 # <=== Coordinates ===> adc_channels: # adc_channels is a dependency for leak_i data variable + CATDESC: ADC Channel DISPLAY_TYPE: no_plot + FIELDNAM: ADC Channel FILLVAL: -9223372036854775808 - UNITS: ' ' + FORMAT: I2 + LABLAXIS: Channel SCALETYP: linear - VALIDMIN: 0 + UNITS: ' ' VALIDMAX: 63 + VALIDMIN: 0 VAR_TYPE: metadata - CATDESC: ADC Channel - FIELDNAM: ADC Channel - LABLAXIS: Channel - FORMAT: I2 # <=== Label Attributes ===> # LABL_PTR_i expects VAR_TYPE of metadata with char data type @@ -64,485 +64,485 @@ sc_tick: fsw_version_a: <<: *hk_support_default - VALIDMAX: 63 CATDESC: Flight Software Version Number (A.B.C bits) FIELDNAM: Flight Software Version Number A - LABLAXIS: FSW A FORMAT: I2 + LABLAXIS: FSW A + VALIDMAX: 63 fsw_version_b: <<: *hk_support_default - VALIDMAX: 63 CATDESC: Flight Software Version Number (A.B.C bits) FIELDNAM: Flight Software Version Number B - LABLAXIS: FSW B FORMAT: I2 + LABLAXIS: FSW B + VALIDMAX: 63 fsw_version_c: <<: *hk_support_default - VALIDMAX: 63 CATDESC: Flight Software Version Number (A.B.C bits) FIELDNAM: Flight Software Version Number C - LABLAXIS: FSW C FORMAT: I2 + LABLAXIS: FSW C + VALIDMAX: 63 num_good_cmds: <<: *hk_support_default - VALIDMAX: 255 CATDESC: Number of Good Commands FIELDNAM: Number of Good Commands - LABLAXIS: Counts FORMAT: I3 + LABLAXIS: Counts + VALIDMAX: 255 last_good_cmd: <<: *hk_support_default - VALIDMAX: 255 CATDESC: Last Good Command FIELDNAM: Last Good Command - LABLAXIS: Last cmd FORMAT: I3 + LABLAXIS: Last cmd + VALIDMAX: 255 last_good_seq_num: <<: *hk_support_default - VALIDMAX: 255 CATDESC: Last Good Sequence Number FIELDNAM: Last Good Sequence Number - LABLAXIS: Last num FORMAT: I3 + LABLAXIS: Last num + VALIDMAX: 255 num_bad_cmds: <<: *hk_support_default - VALIDMAX: 255 CATDESC: Number of Bad Commands FIELDNAM: Number of Bad Commands - LABLAXIS: Counts FORMAT: I3 + LABLAXIS: Counts + VALIDMAX: 255 last_bad_cmd: <<: *hk_support_default - VALIDMAX: 255 CATDESC: Last Bad Command FIELDNAM: Last Bad Command - LABLAXIS: Last cmd FORMAT: I3 + LABLAXIS: Last cmd + VALIDMAX: 255 last_bad_seq_num: <<: *hk_support_default - VALIDMAX: 255 CATDESC: Last Bad Sequence Number FIELDNAM: Last Bad Sequence Number - LABLAXIS: Last num FORMAT: I3 + LABLAXIS: Last num + VALIDMAX: 255 fee_running: <<: *metadata_default CATDESC: State - FEE Running (1) or Reset (0) FIELDNAM: FEE Running (1) or Reset (0) - LABLAXIS: State FORMAT: A7 + LABLAXIS: State mram_disabled: <<: *metadata_default CATDESC: State - MRAM Disabled (1) or Enabled (0) FIELDNAM: MRAM Disabled (1) or Enabled (0) - LABLAXIS: State FORMAT: A8 + LABLAXIS: State enable_50khz: <<: *metadata_default CATDESC: State - 50kHz Enabled (1) or Disabled (0) FIELDNAM: 50kHz Enabled (1) or Disabled (0) - LABLAXIS: State FORMAT: A8 + LABLAXIS: State enable_hvps: <<: *metadata_default CATDESC: State - HVPS Enabled (1) or Disabled (0) FIELDNAM: HVPS Enabled (1) or Disabled (0) - LABLAXIS: State FORMAT: A8 + LABLAXIS: State table_status: <<: *metadata_default CATDESC: State - Table Status OK (1) or Error (0) FIELDNAM: Table Status OK (1) or Error (0) - LABLAXIS: Status FORMAT: A5 + LABLAXIS: Status heater_control: <<: *metadata_default CATDESC: State - Heater Control (0=None, 1=Pri, 2=Sec) FIELDNAM: Heater Control (0=None, 1=Pri, 2=Sec) - LABLAXIS: State FORMAT: A4 + LABLAXIS: State adc_mode: <<: *metadata_default CATDESC: State - ADC Mode (0=quiet, 1=normal, 2=adcstim, 3=adcThreshold FIELDNAM: ADC Mode (0=quiet, 1=normal, 2=adcstim, 3=adcThreshold) - LABLAXIS: ADC mode FORMAT: A12 + LABLAXIS: ADC mode mode: <<: *metadata_default CATDESC: State - Mode (0=Boot, 1=Maintenance, 2=Standby, 3=Science) FIELDNAM: Mode (0=Boot, 1=Maintenance, 2=Standby, 3=Science) - LABLAXIS: Mode FORMAT: A11 + LABLAXIS: Mode dyn_thresh_lvl: <<: *hk_support_default - VALIDMAX: 3 CATDESC: Dynamic Threshold Level (0-3) FIELDNAM: Dynamic Threshold Level (0-3) - LABLAXIS: Level FORMAT: I1 + LABLAXIS: Level + VALIDMAX: 3 num_evnt_last_hk: <<: *hk_support_default - VALIDMAX: 4294967295 CATDESC: Number of Events Since Last HK Update FIELDNAM: Number of Events Since Last HK Update - LABLAXIS: Num events FORMAT: I10 + LABLAXIS: Num events + VALIDMAX: 4294967295 num_errors: <<: *hk_support_default - VALIDMAX: 255 CATDESC: Number of Errors FIELDNAM: Number of Errors - LABLAXIS: Num errors FORMAT: I3 + LABLAXIS: Num errors + VALIDMAX: 255 last_error_num: <<: *metadata_default CATDESC: State - Last Error Number FIELDNAM: Last Error Number - LABLAXIS: Error num FORMAT: A18 + LABLAXIS: Error num code_checksum: <<: *hk_support_default - VALIDMAX: 65535 CATDESC: Code Checksum FIELDNAM: Code Checksum - LABLAXIS: Checksum FORMAT: I5 + LABLAXIS: Checksum + VALIDMAX: 65535 spin_period_short: <<: *hk_support_default - VALIDMAX: 65535 CATDESC: Spin Period Short at T=0 FIELDNAM: Spin Period Short at T=0 - LABLAXIS: Spin period short FORMAT: I5 + LABLAXIS: Spin period short + VALIDMAX: 65535 spin_period_long: <<: *hk_support_default - VALIDMAX: 65535 CATDESC: Spin Period Long at T=0 FIELDNAM: Spin Period Long at T=0 - LABLAXIS: Spin period long FORMAT: I5 + LABLAXIS: Spin period long + VALIDMAX: 65535 leak_i: <<: *hk_support_default - DEPEND_1: adc_channels CATDESC: Leakage Current [I] + DEPEND_1: adc_channels FIELDNAM: Leakage Current [I] + FORMAT: I19 LABLAXIS: Current I labl_ptr: adc_channels - FORMAT: I19 phasic_stat: <<: *metadata_default CATDESC: State - Phasic Status FIELDNAM: Phasic Status - LABLAXIS: Status FORMAT: A7 + LABLAXIS: Status active_heater: <<: *metadata_default CATDESC: State - Active Heater FIELDNAM: Active Heater - LABLAXIS: State FORMAT: A9 + LABLAXIS: State heater_on: <<: *metadata_default CATDESC: State - Heater On/Off FIELDNAM: Heater On/Off - LABLAXIS: State FORMAT: A3 + LABLAXIS: State test_pulser_on: <<: *metadata_default CATDESC: State - Test Pulser On/Off FIELDNAM: Test Pulser On/Off - LABLAXIS: State FORMAT: A3 + LABLAXIS: State dac0_enable: <<: *metadata_default CATDESC: State - DAC 0 Enable FIELDNAM: DAC 0 Enable - LABLAXIS: State FORMAT: A7 + LABLAXIS: State dac1_enable: <<: *metadata_default CATDESC: State - DAC 1 Enable FIELDNAM: DAC 1 Enable - LABLAXIS: State FORMAT: A7 + LABLAXIS: State preamp_l234a: <<: *default - VALIDMAX: 10000000000 CATDESC: Preamp L234A Voltage FIELDNAM: Preamp L234A Voltage - LABLAXIS: Voltage + FILLVAL: -1.0000000E+31 FORMAT: F9.3 + LABLAXIS: Voltage UNITS: V - FILLVAL: -1.0000000E+31 + VALIDMAX: 10000000000 preamp_l1a: <<: *default - VALIDMAX: 10000000000 CATDESC: Preamp L1A Voltage FIELDNAM: Preamp L1A Voltage - LABLAXIS: Voltage + FILLVAL: -1.0000000E+31 FORMAT: F9.3 + LABLAXIS: Voltage UNITS: V - FILLVAL: -1.0000000E+31 + VALIDMAX: 10000000000 preamp_l1b: <<: *default - VALIDMAX: 10000000000 CATDESC: Preamp L1B Voltage FIELDNAM: Preamp L1B Voltage - LABLAXIS: Voltage + FILLVAL: -1.0000000E+31 FORMAT: F9.3 + LABLAXIS: Voltage UNITS: V - FILLVAL: -1.0000000E+31 + VALIDMAX: 10000000000 preamp_l234b: <<: *default - VALIDMAX: 10000000000 CATDESC: Preamp L234B Voltage FIELDNAM: Preamp L234B Voltage - LABLAXIS: Voltage + FILLVAL: -1.0000000E+31 FORMAT: F9.3 + LABLAXIS: Voltage UNITS: V - FILLVAL: -1.0000000E+31 + VALIDMAX: 10000000000 temp0: <<: *default - VALIDMIN: -25 - VALIDMAX: 10000000000 CATDESC: FEE LDO Regulator Mounted on the Board Next to the Low-dropout Regulator FIELDNAM: FEE LDO Regulator - LABLAXIS: Temperature + FILLVAL: -1.0000000E+31 FORMAT: F9.3 + LABLAXIS: Temperature UNITS: C - FILLVAL: -1.0000000E+31 + VALIDMAX: 10000000000 + VALIDMIN: -25 temp1: <<: *default - VALIDMIN: -25 - VALIDMAX: 10000000000 CATDESC: Primary Heater Mounted on the Board Next to the Primary Heater Circuit FIELDNAM: Primary Heater - LABLAXIS: Temperature + FILLVAL: -1.0000000E+31 FORMAT: F9.3 + LABLAXIS: Temperature UNITS: C - FILLVAL: -1.0000000E+31 + VALIDMAX: 10000000000 + VALIDMIN: -25 temp2: <<: *default - VALIDMIN: -25 - VALIDMAX: 10000000000 CATDESC: FEE FPGA Mounted on the Board Next to the FPGA FIELDNAM: FEE FPGA - LABLAXIS: Temperature + FILLVAL: -1.0000000E+31 FORMAT: F9.3 + LABLAXIS: Temperature UNITS: C - FILLVAL: -1.0000000E+31 + VALIDMAX: 10000000000 + VALIDMIN: -25 temp3: <<: *default - VALIDMIN: -25 - VALIDMAX: 10000000000 CATDESC: Secondary Heater FIELDNAM: Secondary Heater - LABLAXIS: Temperature + FILLVAL: -1.0000000E+31 FORMAT: F9.3 + LABLAXIS: Temperature UNITS: C - FILLVAL: -1.0000000E+31 + VALIDMAX: 10000000000 + VALIDMIN: -25 analog_temp: <<: *default - VALIDMIN: -25 - VALIDMAX: 10000000000 CATDESC: Chassis Temp Mounted on the Analog Board Close to Thermostats, Heaters, and Chassis FIELDNAM: Analog Temp - LABLAXIS: Temperature + FILLVAL: -1.0000000E+31 FORMAT: F9.3 + LABLAXIS: Temperature UNITS: C - FILLVAL: -1.0000000E+31 + VALIDMAX: 10000000000 + VALIDMIN: -25 hvps_temp: <<: *default - VALIDMIN: -25 - VALIDMAX: 10000000000 CATDESC: Board Temp Mounted Inside Faraday Cage in Middle of Board Near Connector Side FIELDNAM: Board Temp - LABLAXIS: Temperature + FILLVAL: -1.0000000E+31 FORMAT: F9.3 + LABLAXIS: Temperature UNITS: C - FILLVAL: -1.0000000E+31 + VALIDMAX: 10000000000 + VALIDMIN: -25 idpu_temp: <<: *default - VALIDMIN: -25 - VALIDMAX: 10000000000 CATDESC: LDO Temp Mounted on Top of the Low-dropout Regulator FIELDNAM: LDO Temp - LABLAXIS: Temperature + FILLVAL: -1.0000000E+31 FORMAT: F9.3 + LABLAXIS: Temperature UNITS: C - FILLVAL: -1.0000000E+31 + VALIDMAX: 10000000000 + VALIDMIN: -25 lvps_temp: <<: *default - VALIDMIN: -25 - VALIDMAX: 10000000000 CATDESC: Board Temp Mounted in the Middle of Board on Opposite Side of Hottest Component FIELDNAM: Board Temp - LABLAXIS: Temperature + FILLVAL: -1.0000000E+31 FORMAT: F9.3 + LABLAXIS: Temperature UNITS: C - FILLVAL: -1.0000000E+31 + VALIDMAX: 10000000000 + VALIDMIN: -25 ebox_3d4vd: <<: *default - VALIDMAX: 10000000000 CATDESC: 3.4VD Ebox (Digital) FIELDNAM: 3.4VD Ebox (Digital) - LABLAXIS: Voltage + FILLVAL: -1.0000000E+31 FORMAT: F9.3 + LABLAXIS: Voltage UNITS: V - FILLVAL: -1.0000000E+31 + VALIDMAX: 10000000000 ebox_5d1vd: <<: *default - VALIDMAX: 10000000000 CATDESC: 5.1VD Ebox (Digital) FIELDNAM: 5.1VD Ebox (Digital) - LABLAXIS: Voltage + FILLVAL: -1.0000000E+31 FORMAT: F9.3 + LABLAXIS: Voltage UNITS: V - FILLVAL: -1.0000000E+31 + VALIDMAX: 10000000000 ebox_p12va: <<: *default - VALIDMAX: 10000000000 CATDESC: +12VA Ebox (Analog) FIELDNAM: +12VA Ebox (Analog) - LABLAXIS: Voltage + FILLVAL: -1.0000000E+31 FORMAT: F9.3 + LABLAXIS: Voltage UNITS: V - FILLVAL: -1.0000000E+31 + VALIDMAX: 10000000000 ebox_m12va: <<: *default - VALIDMIN: -12.2 - VALIDMAX: 10000000000 CATDESC: -12VA Ebox (Analog) FIELDNAM: -12VA Ebox (Analog) - LABLAXIS: Voltage + FILLVAL: -1.0000000E+31 FORMAT: F9.3 + LABLAXIS: Voltage UNITS: V - FILLVAL: -1.0000000E+31 + VALIDMAX: 10000000000 + VALIDMIN: -12.2 ebox_p5d7va: <<: *default - VALIDMAX: 10000000000 CATDESC: +5.7VA Ebox (Analog) FIELDNAM: +5.7VA Ebox (Analog) - LABLAXIS: Voltage + FILLVAL: -1.0000000E+31 FORMAT: F9.3 + LABLAXIS: Voltage UNITS: V - FILLVAL: -1.0000000E+31 + VALIDMAX: 10000000000 ebox_m5d7va: <<: *default - VALIDMIN: -6 - VALIDMAX: 10000000000 CATDESC: -5.7VA Ebox (Analog) FIELDNAM: -5.7VA Ebox (Analog) - LABLAXIS: Voltage + FILLVAL: -1.0000000E+31 FORMAT: F9.3 + LABLAXIS: Voltage UNITS: V - FILLVAL: -1.0000000E+31 + VALIDMAX: 10000000000 + VALIDMIN: -6 ref_p5v: <<: *default - VALIDMAX: 10000000000 CATDESC: +5V ref FIELDNAM: +5V ref - LABLAXIS: Voltage + FILLVAL: -1.0000000E+31 FORMAT: F9.3 + LABLAXIS: Voltage UNITS: V - FILLVAL: -1.0000000E+31 + VALIDMAX: 10000000000 l1ab_bias: <<: *default - VALIDMAX: 10000000000 CATDESC: L1A/B Bias FIELDNAM: L1A/B Bias - LABLAXIS: Voltage + FILLVAL: -1.0000000E+31 FORMAT: F9.3 + LABLAXIS: Voltage UNITS: V - FILLVAL: -1.0000000E+31 + VALIDMAX: 10000000000 l2ab_bias: <<: *default - VALIDMAX: 10000000000 CATDESC: L2A/B Bias FIELDNAM: L2A/B Bias - LABLAXIS: Voltage + FILLVAL: -1.0000000E+31 FORMAT: F9.3 + LABLAXIS: Voltage UNITS: V - FILLVAL: -1.0000000E+31 + VALIDMAX: 10000000000 l34a_bias: <<: *default - VALIDMAX: 10000000000 CATDESC: L3/4A Bias FIELDNAM: L3/4A Bias - LABLAXIS: Voltage + FILLVAL: -1.0000000E+31 FORMAT: F9.3 + LABLAXIS: Voltage UNITS: V - FILLVAL: -1.0000000E+31 + VALIDMAX: 10000000000 l34b_bias: <<: *default - VALIDMAX: 10000000000 CATDESC: L3/4B Bias FIELDNAM: L3/4B Bias - LABLAXIS: Voltage + FILLVAL: -1.0000000E+31 FORMAT: F9.3 + LABLAXIS: Voltage UNITS: V - FILLVAL: -1.0000000E+31 + VALIDMAX: 10000000000 ebox_p2d0vd: <<: *default - VALIDMAX: 10000000000 CATDESC: +2.0VD Ebox (Digital) FIELDNAM: +2.0VD Ebox (Digital) - LABLAXIS: Voltage + FILLVAL: -1.0000000E+31 FORMAT: F9.3 + LABLAXIS: Voltage UNITS: V - FILLVAL: -1.0000000E+31 + VALIDMAX: 10000000000 diff --git a/imap_processing/cdf/config/imap_hit_l2_variable_attrs.yaml b/imap_processing/cdf/config/imap_hit_l2_variable_attrs.yaml index d99bdcf481..0fa85ae795 100644 --- a/imap_processing/cdf/config/imap_hit_l2_variable_attrs.yaml +++ b/imap_processing/cdf/config/imap_hit_l2_variable_attrs.yaml @@ -1,28 +1,28 @@ # <=== Defaults ===> default_particle_attrs: &default_particle DEPEND_0: epoch - VAR_TYPE: data + DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:NumberFlux,Qualifier:Differential DISPLAY_TYPE: spectrogram FILLVAL: -1.00E+31 - VALIDMIN: 0.0 - VALIDMAX: 10000000000.0 FORMAT: F14.3 - UNITS: 1/(cm^2 s MeV/nuc sr) - SCALETYP: log - SCALEMIN: 0.0001 SCALEMAX: 1000.0 - DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:NumberFlux,Qualifier:Differential + SCALEMIN: 0.0001 + SCALETYP: log + UNITS: 1/(cm^2 s MeV/nuc sr) + VALIDMAX: 10000000000.0 + VALIDMIN: 0.0 + VAR_TYPE: data default_energy_attrs: &default_energy - VAR_TYPE: support_data - LABLAXIS: Energy + DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:EnergyPerCharge,Qualifier:Characteristic FILLVAL: -1.00E+31 - VALIDMIN: 0.0 - VALIDMAX: 1000.0 FORMAT: F6.1 - UNITS: MeV/nuc + LABLAXIS: Energy SCALETYP: log - DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:EnergyPerCharge,Qualifier:Characteristic + UNITS: MeV/nuc + VALIDMAX: 1000.0 + VALIDMIN: 0.0 + VAR_TYPE: support_data default_energy_delta_attrs: &default_energy_delta <<: *default_energy @@ -30,170 +30,170 @@ default_energy_delta_attrs: &default_energy_delta default_uncertainty_attrs: &default_uncertainty DEPEND_0: epoch - VAR_TYPE: support_data - VALIDMIN: 0.0 - VALIDMAX: 10000000000.0 + DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:NumberFlux,Qualifier:Differential_Uncertainty FILLVAL: -1.00E+31 FORMAT: F14.3 UNITS: 1/(cm^2 s MeV/nuc sr) - DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:NumberFlux,Qualifier:Differential_Uncertainty + VALIDMAX: 10000000000.0 + VALIDMIN: 0.0 + VAR_TYPE: support_data default_angle_attrs: &default_angle - VAR_TYPE: support_data FILLVAL: -1.00E+31 - VALIDMIN: 0.0 - VALIDMAX: 1000.0 FORMAT: F12.2 - UNITS: Deg SCALETYP: linear + UNITS: Deg + VALIDMAX: 1000.0 + VALIDMIN: 0.0 + VAR_TYPE: support_data # <=== Coordinates ===> zenith: <<: *default_angle CATDESC: Angle from the spin axis (0 deg.) to anti-spin axis (180 deg.) in 8 bins + DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:ArrivalDirection,Qualifer:DirectionAngle.PolarAngle FIELDNAM: Zenith LABLAXIS: Zenith - DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:ArrivalDirection,Qualifer:DirectionAngle.PolarAngle azimuth: <<: *default_angle CATDESC: Spin angle in 15 bins (0 deg. is zero of spin phase) + DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:ArrivalDirection,Qualifer:DirectionAngle.AzimuthAngle FIELDNAM: Azimuth LABLAXIS: Azimuth - DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:ArrivalDirection,Qualifer:DirectionAngle.AzimuthAngle h_energy_mean: <<: *default_energy CATDESC: Geometric mean energy per nucleon for H - FIELDNAM: H Energy DELTA_MINUS_VAR: h_energy_delta_minus DELTA_PLUS_VAR: h_energy_delta_plus + FIELDNAM: H Energy he3_energy_mean: <<: *default_energy CATDESC: Geometric mean energy per nucleon for He3 - FIELDNAM: He3 Energy DELTA_MINUS_VAR: he3_energy_delta_minus DELTA_PLUS_VAR: he3_energy_delta_plus + FIELDNAM: He3 Energy he4_energy_mean: <<: *default_energy CATDESC: Geometric mean energy per nucleon for He4 - FIELDNAM: He4 Energy DELTA_MINUS_VAR: he4_energy_delta_minus DELTA_PLUS_VAR: he4_energy_delta_plus + FIELDNAM: He4 Energy he_energy_mean: <<: *default_energy CATDESC: Geometric mean energy per nucleon for He - FIELDNAM: He Energy DELTA_MINUS_VAR: he_energy_delta_minus DELTA_PLUS_VAR: he_energy_delta_plus + FIELDNAM: He Energy c_energy_mean: <<: *default_energy CATDESC: Geometric mean energy per nucleon for C - FIELDNAM: C Energy DELTA_MINUS_VAR: c_energy_delta_minus DELTA_PLUS_VAR: c_energy_delta_plus + FIELDNAM: C Energy n_energy_mean: <<: *default_energy CATDESC: Geometric mean energy per nucleon for N - FIELDNAM: N Energy DELTA_MINUS_VAR: n_energy_delta_minus DELTA_PLUS_VAR: n_energy_delta_plus + FIELDNAM: N Energy o_energy_mean: <<: *default_energy CATDESC: Geometric mean energy per nucleon for O - FIELDNAM: O Energy DELTA_MINUS_VAR: o_energy_delta_minus DELTA_PLUS_VAR: o_energy_delta_plus + FIELDNAM: O Energy ne_energy_mean: <<: *default_energy CATDESC: Geometric mean energy per nucleon for Ne - FIELDNAM: Ne Energy DELTA_MINUS_VAR: ne_energy_delta_minus DELTA_PLUS_VAR: ne_energy_delta_plus + FIELDNAM: Ne Energy na_energy_mean: <<: *default_energy CATDESC: Geometric mean energy per nucleon for Na - FIELDNAM: Na Energy DELTA_MINUS_VAR: na_energy_delta_minus DELTA_PLUS_VAR: na_energy_delta_plus + FIELDNAM: Na Energy mg_energy_mean: <<: *default_energy CATDESC: Geometric mean energy per nucleon for Mg - FIELDNAM: Mg Energy DELTA_MINUS_VAR: mg_energy_delta_minus DELTA_PLUS_VAR: mg_energy_delta_plus + FIELDNAM: Mg Energy si_energy_mean: <<: *default_energy CATDESC: Geometric mean energy per nucleon for Si - FIELDNAM: Si Energy DELTA_MINUS_VAR: si_energy_delta_minus DELTA_PLUS_VAR: si_energy_delta_plus + FIELDNAM: Si Energy s_energy_mean: <<: *default_energy CATDESC: Geometric mean energy per nucleon for S - FIELDNAM: S Energy DELTA_MINUS_VAR: s_energy_delta_minus DELTA_PLUS_VAR: s_energy_delta_plus + FIELDNAM: S Energy al_energy_mean: <<: *default_energy CATDESC: Geometric mean energy per nucleon for Al - FIELDNAM: Al Energy DELTA_MINUS_VAR: al_energy_delta_minus DELTA_PLUS_VAR: al_energy_delta_plus + FIELDNAM: Al Energy ar_energy_mean: <<: *default_energy CATDESC: Geometric mean energy per nucleon for Ar - FIELDNAM: Ar Energy DELTA_MINUS_VAR: ar_energy_delta_minus DELTA_PLUS_VAR: ar_energy_delta_plus + FIELDNAM: Ar Energy ca_energy_mean: <<: *default_energy CATDESC: Geometric mean energy per nucleon for Ca - FIELDNAM: Ca Energy DELTA_MINUS_VAR: ca_energy_delta_minus DELTA_PLUS_VAR: ca_energy_delta_plus + FIELDNAM: Ca Energy fe_energy_mean: <<: *default_energy CATDESC: Geometric mean energy per nucleon for Fe - FIELDNAM: Fe Energy DELTA_MINUS_VAR: fe_energy_delta_minus DELTA_PLUS_VAR: fe_energy_delta_plus + FIELDNAM: Fe Energy ni_energy_mean: <<: *default_energy CATDESC: Geometric mean energy per nucleon for Ni - FIELDNAM: Ni Energy DELTA_MINUS_VAR: ni_energy_delta_minus DELTA_PLUS_VAR: ni_energy_delta_plus + FIELDNAM: Ni Energy nemgsi_energy_mean: <<: *default_energy CATDESC: Geometric mean energy per nucleon for NeMgSi - FIELDNAM: NeMgSi Energy DELTA_MINUS_VAR: nemgsi_energy_delta_minus DELTA_PLUS_VAR: nemgsi_energy_delta_plus + FIELDNAM: NeMgSi Energy cno_energy_mean: <<: *default_energy CATDESC: Geometric mean energy per nucleon for CNO - FIELDNAM: CNO Energy DELTA_MINUS_VAR: cno_energy_delta_minus DELTA_PLUS_VAR: cno_energy_delta_plus + FIELDNAM: CNO Energy # <=== Labels ===> @@ -326,1247 +326,1247 @@ cno_energy_mean_label: # <=== Data Variables ===> dynamic_threshold_state: - DEPEND_0: epoch - VAR_TYPE: data CATDESC: Raw dynamic threshold state per integration + DEPEND_0: epoch + DICT_KEY: SPASE>Support>SupportQuantity:InstrumentMode + DISPLAY_TYPE: time_series FIELDNAM: Dynamic threshold state - LABLAXIS: State - VALIDMIN: 0 - VALIDMAX: 3 FILLVAL: -128 - DISPLAY_TYPE: time_series FORMAT: I1 - UNITS: " " - SCALETYP: linear - SCALEMIN: 0 + LABLAXIS: State SCALEMAX: 1000 - DICT_KEY: SPASE>Support>SupportQuantity:InstrumentMode + SCALEMIN: 0 + SCALETYP: linear + UNITS: " " + VALIDMAX: 3 + VALIDMIN: 0 + VAR_TYPE: data # Standard Intensity Variables h_standard_intensity: <<: *default_particle - DEPEND_1: h_energy_mean CATDESC: H Standard Omnidirectional Intensity in 12 energy bins - LABLAXIS: h_energy_mean_label + DELTA_MINUS_VAR: h_total_uncert_minus + DELTA_PLUS_VAR: h_total_uncert_plus + DEPEND_1: h_energy_mean FIELDNAM: H Intensity Standard - DELTA_MINUS_VAR: h_total_uncert_plus - DELTA_PLUS_VAR: h_total_uncert_minus + LABLAXIS: h_energy_mean_label he3_standard_intensity: <<: *default_particle - DEPEND_1: he3_energy_mean CATDESC: He3 Standard Omnidirectional Intensity in 11 energy bins + DELTA_MINUS_VAR: he3_total_uncert_minus + DELTA_PLUS_VAR: he3_total_uncert_plus + DEPEND_1: he3_energy_mean FIELDNAM: He3 Intensity Standard LABLAXIS: he3_energy_mean_label - DELTA_MINUS_VAR: he3_total_uncert_plus - DELTA_PLUS_VAR: he3_total_uncert_minus he4_standard_intensity: <<: *default_particle - DEPEND_1: he4_energy_mean CATDESC: He4 Standard Omnidirectional Intensity in 12 energy bins + DELTA_MINUS_VAR: he4_total_uncert_minus + DELTA_PLUS_VAR: he4_total_uncert_plus + DEPEND_1: he4_energy_mean FIELDNAM: He4 Intensity Standard LABLAXIS: he4_energy_mean_label - DELTA_MINUS_VAR: he4_total_uncert_plus - DELTA_PLUS_VAR: he4_total_uncert_minus he_standard_intensity: <<: *default_particle - DEPEND_1: he_energy_mean CATDESC: He (total) Standard Omnidirectional Intensity in 11 energy bins + DELTA_MINUS_VAR: he_total_uncert_minus + DELTA_PLUS_VAR: he_total_uncert_plus + DEPEND_1: he_energy_mean FIELDNAM: He Intensity Standard LABLAXIS: he_energy_mean_label - DELTA_MINUS_VAR: he_total_uncert_plus - DELTA_PLUS_VAR: he_total_uncert_minus c_standard_intensity: <<: *default_particle - DEPEND_1: c_energy_mean CATDESC: C Standard Omnidirectional Intensity in 12 energy bins + DELTA_MINUS_VAR: c_total_uncert_minus + DELTA_PLUS_VAR: c_total_uncert_plus + DEPEND_1: c_energy_mean FIELDNAM: C Intensity Standard LABLAXIS: c_energy_mean_label - DELTA_MINUS_VAR: c_total_uncert_plus - DELTA_PLUS_VAR: c_total_uncert_minus o_standard_intensity: <<: *default_particle - DEPEND_1: o_energy_mean CATDESC: O Standard Omnidirectional Intensity in 12 energy bins + DELTA_MINUS_VAR: o_total_uncert_minus + DELTA_PLUS_VAR: o_total_uncert_plus + DEPEND_1: o_energy_mean FIELDNAM: O Intensity Standard LABLAXIS: o_energy_mean_label - DELTA_MINUS_VAR: o_total_uncert_plus - DELTA_PLUS_VAR: o_total_uncert_minus n_standard_intensity: <<: *default_particle - DEPEND_1: n_energy_mean CATDESC: N Standard Omnidirectional Intensity in 12 energy bins + DELTA_MINUS_VAR: n_total_uncert_minus + DELTA_PLUS_VAR: n_total_uncert_plus + DEPEND_1: n_energy_mean FIELDNAM: N Intensity Standard LABLAXIS: n_energy_mean_label - DELTA_MINUS_VAR: n_total_uncert_plus - DELTA_PLUS_VAR: n_total_uncert_minus ne_standard_intensity: <<: *default_particle - DEPEND_1: ne_energy_mean CATDESC: Ne Standard Omnidirectional Intensity in 13 energy bins + DELTA_MINUS_VAR: ne_total_uncert_minus + DELTA_PLUS_VAR: ne_total_uncert_plus + DEPEND_1: ne_energy_mean FIELDNAM: Ne Intensity Standard LABLAXIS: ne_energy_mean_label - DELTA_MINUS_VAR: ne_total_uncert_plus - DELTA_PLUS_VAR: ne_total_uncert_minus na_standard_intensity: <<: *default_particle - DEPEND_1: na_energy_mean CATDESC: Na Standard Omnidirectional Intensity in 8 energy bins + DELTA_MINUS_VAR: na_total_uncert_minus + DELTA_PLUS_VAR: na_total_uncert_plus + DEPEND_1: na_energy_mean FIELDNAM: Na Intensity Standard LABLAXIS: na_energy_mean_label - DELTA_MINUS_VAR: na_total_uncert_plus - DELTA_PLUS_VAR: na_total_uncert_minus mg_standard_intensity: <<: *default_particle - DEPEND_1: mg_energy_mean CATDESC: Mg Standard Omnidirectional Intensity in 14 energy bins + DELTA_MINUS_VAR: mg_total_uncert_minus + DELTA_PLUS_VAR: mg_total_uncert_plus + DEPEND_1: mg_energy_mean FIELDNAM: Mg Intensity Standard LABLAXIS: mg_energy_mean_label - DELTA_MINUS_VAR: mg_total_uncert_plus - DELTA_PLUS_VAR: mg_total_uncert_minus al_standard_intensity: <<: *default_particle - DEPEND_1: al_energy_mean CATDESC: Al Standard Omnidirectional Intensity in 9 energy bins + DELTA_MINUS_VAR: al_total_uncert_minus + DELTA_PLUS_VAR: al_total_uncert_plus + DEPEND_1: al_energy_mean FIELDNAM: Al Intensity Standard LABLAXIS: al_energy_mean_label - DELTA_MINUS_VAR: al_total_uncert_plus - DELTA_PLUS_VAR: al_total_uncert_minus si_standard_intensity: <<: *default_particle - DEPEND_1: si_energy_mean CATDESC: Si Standard Omnidirectional Intensity in 14 energy bins + DELTA_MINUS_VAR: si_total_uncert_minus + DELTA_PLUS_VAR: si_total_uncert_plus + DEPEND_1: si_energy_mean FIELDNAM: Si Intensity Standard LABLAXIS: si_energy_mean_label - DELTA_MINUS_VAR: si_total_uncert_plus - DELTA_PLUS_VAR: si_total_uncert_minus s_standard_intensity: <<: *default_particle - DEPEND_1: s_energy_mean CATDESC: S Standard Omnidirectional Intensity in 13 energy bins + DELTA_MINUS_VAR: s_total_uncert_minus + DELTA_PLUS_VAR: s_total_uncert_plus + DEPEND_1: s_energy_mean FIELDNAM: S Intensity Standard LABLAXIS: s_energy_mean_label - DELTA_MINUS_VAR: s_total_uncert_plus - DELTA_PLUS_VAR: s_total_uncert_minus ar_standard_intensity: <<: *default_particle - DEPEND_1: ar_energy_mean CATDESC: Ar Standard Omnidirectional Intensity in 13 energy bins + DELTA_MINUS_VAR: ar_total_uncert_minus + DELTA_PLUS_VAR: ar_total_uncert_plus + DEPEND_1: ar_energy_mean FIELDNAM: Ar Intensity Standard LABLAXIS: ar_energy_mean_label - DELTA_MINUS_VAR: ar_total_uncert_plus - DELTA_PLUS_VAR: ar_total_uncert_minus ca_standard_intensity: <<: *default_particle - DEPEND_1: ca_energy_mean CATDESC: Ca Standard Omnidirectional Intensity in 13 energy bins + DELTA_MINUS_VAR: ca_total_uncert_minus + DELTA_PLUS_VAR: ca_total_uncert_plus + DEPEND_1: ca_energy_mean FIELDNAM: Ca Intensity Standard LABLAXIS: ca_energy_mean_label - DELTA_MINUS_VAR: ca_total_uncert_plus - DELTA_PLUS_VAR: ca_total_uncert_minus fe_standard_intensity: <<: *default_particle - DEPEND_1: fe_energy_mean CATDESC: Fe Standard Omnidirectional Intensity in 16 energy bins + DELTA_MINUS_VAR: fe_total_uncert_minus + DELTA_PLUS_VAR: fe_total_uncert_plus + DEPEND_1: fe_energy_mean FIELDNAM: Fe Intensity Standard LABLAXIS: fe_energy_mean_label - DELTA_MINUS_VAR: fe_total_uncert_plus - DELTA_PLUS_VAR: fe_total_uncert_minus ni_standard_intensity: <<: *default_particle - DEPEND_1: ni_energy_mean CATDESC: Ni Standard Omnidirectional Intensity in 9 energy bins + DELTA_MINUS_VAR: ni_total_uncert_minus + DELTA_PLUS_VAR: ni_total_uncert_plus + DEPEND_1: ni_energy_mean FIELDNAM: Ni Intensity Standard LABLAXIS: ni_energy_mean_label - DELTA_MINUS_VAR: ni_total_uncert_plus - DELTA_PLUS_VAR: ni_total_uncert_minus # Summed Intensity Variables h_summed_intensity: <<: *default_particle - DEPEND_1: h_energy_mean CATDESC: H Summed Omnidirectional Intensity in 4 energy bins (useful for quiet times) - LABLAXIS: h_energy_mean_label + DELTA_MINUS_VAR: h_total_uncert_minus + DELTA_PLUS_VAR: h_total_uncert_plus + DEPEND_1: h_energy_mean FIELDNAM: H intensity summed - DELTA_MINUS_VAR: h_total_uncert_plus - DELTA_PLUS_VAR: h_total_uncert_minus + LABLAXIS: h_energy_mean_label he3_summed_intensity: <<: *default_particle - DEPEND_1: he3_energy_mean CATDESC: He3 Summed Omnidirectional Intensity in 3 energy bins (useful for quiet times) + DELTA_MINUS_VAR: he3_total_uncert_minus + DELTA_PLUS_VAR: he3_total_uncert_plus + DEPEND_1: he3_energy_mean FIELDNAM: He3 intensity summed LABLAXIS: he3_energy_mean_label - DELTA_MINUS_VAR: he3_total_uncert_plus - DELTA_PLUS_VAR: he3_total_uncert_minus he4_summed_intensity: <<: *default_particle - DEPEND_1: he4_energy_mean CATDESC: He4 Summed Omnidirectional Intensity in 4 energy bins (useful for quiet times) + DELTA_MINUS_VAR: he4_total_uncert_minus + DELTA_PLUS_VAR: he4_total_uncert_plus + DEPEND_1: he4_energy_mean FIELDNAM: He4 intensity summed LABLAXIS: he4_energy_mean_label - DELTA_MINUS_VAR: he4_total_uncert_plus - DELTA_PLUS_VAR: he4_total_uncert_minus he_summed_intensity: <<: *default_particle - DEPEND_1: he_energy_mean CATDESC: He (total) Summed Omnidirectional Intensity in 3 energy bins (useful for quiet times) + DELTA_MINUS_VAR: he_total_uncert_minus + DELTA_PLUS_VAR: he_total_uncert_plus + DEPEND_1: he_energy_mean FIELDNAM: He intensity summed LABLAXIS: he_energy_mean_label - DELTA_MINUS_VAR: he_total_uncert_plus - DELTA_PLUS_VAR: he_total_uncert_minus c_summed_intensity: <<: *default_particle - DEPEND_1: c_energy_mean CATDESC: C Summed Omnidirectional Intensity in 4 energy bins (useful for quiet times) + DELTA_MINUS_VAR: c_total_uncert_minus + DELTA_PLUS_VAR: c_total_uncert_plus + DEPEND_1: c_energy_mean FIELDNAM: C intensity summed LABLAXIS: c_energy_mean_label - DELTA_MINUS_VAR: c_total_uncert_plus - DELTA_PLUS_VAR: c_total_uncert_minus o_summed_intensity: <<: *default_particle - DEPEND_1: o_energy_mean CATDESC: O Summed Omnidirectional Intensity in 4 energy bins (useful for quiet times) + DELTA_MINUS_VAR: o_total_uncert_minus + DELTA_PLUS_VAR: o_total_uncert_plus + DEPEND_1: o_energy_mean FIELDNAM: O intensity summed LABLAXIS: o_energy_mean_label - DELTA_MINUS_VAR: o_total_uncert_plus - DELTA_PLUS_VAR: o_total_uncert_minus n_summed_intensity: <<: *default_particle - DEPEND_1: n_energy_mean CATDESC: N Summed Omnidirectional Intensity in 4 energy bins (useful for quiet times) + DELTA_MINUS_VAR: n_total_uncert_minus + DELTA_PLUS_VAR: n_total_uncert_plus + DEPEND_1: n_energy_mean FIELDNAM: N intensity summed LABLAXIS: n_energy_mean_label - DELTA_MINUS_VAR: n_total_uncert_plus - DELTA_PLUS_VAR: n_total_uncert_minus ne_summed_intensity: <<: *default_particle - DEPEND_1: ne_energy_mean CATDESC: Ne Summed Omnidirectional Intensity in 4 energy bins (useful for quiet times) + DELTA_MINUS_VAR: ne_total_uncert_minus + DELTA_PLUS_VAR: ne_total_uncert_plus + DEPEND_1: ne_energy_mean FIELDNAM: Ne intensity summed LABLAXIS: ne_energy_mean_label - DELTA_MINUS_VAR: ne_total_uncert_plus - DELTA_PLUS_VAR: ne_total_uncert_minus na_summed_intensity: <<: *default_particle - DEPEND_1: na_energy_mean CATDESC: Na Summed Omnidirectional Intensity in 2 energy bins (useful for quiet times) + DELTA_MINUS_VAR: na_total_uncert_minus + DELTA_PLUS_VAR: na_total_uncert_plus + DEPEND_1: na_energy_mean FIELDNAM: Na intensity summed LABLAXIS: na_energy_mean_label - DELTA_MINUS_VAR: na_total_uncert_plus - DELTA_PLUS_VAR: na_total_uncert_minus mg_summed_intensity: <<: *default_particle - DEPEND_1: mg_energy_mean CATDESC: Mg Summed Omnidirectional Intensity in 4 energy bins (useful for quiet times) + DELTA_MINUS_VAR: mg_total_uncert_minus + DELTA_PLUS_VAR: mg_total_uncert_plus + DEPEND_1: mg_energy_mean FIELDNAM: Mg intensity summed LABLAXIS: mg_energy_mean_label - DELTA_MINUS_VAR: mg_total_uncert_plus - DELTA_PLUS_VAR: mg_total_uncert_minus al_summed_intensity: <<: *default_particle - DEPEND_1: al_energy_mean CATDESC: Al Summed Omnidirectional Intensity in 3 energy bins (useful for quiet times) + DELTA_MINUS_VAR: al_total_uncert_minus + DELTA_PLUS_VAR: al_total_uncert_plus + DEPEND_1: al_energy_mean FIELDNAM: Al intensity summed LABLAXIS: al_energy_mean_label - DELTA_MINUS_VAR: al_total_uncert_plus - DELTA_PLUS_VAR: al_total_uncert_minus si_summed_intensity: <<: *default_particle - DEPEND_1: si_energy_mean CATDESC: Si Summed Omnidirectional Intensity in 5 energy bins (useful for quiet times) + DELTA_MINUS_VAR: si_total_uncert_minus + DELTA_PLUS_VAR: si_total_uncert_plus + DEPEND_1: si_energy_mean FIELDNAM: Si intensity summed LABLAXIS: si_energy_mean_label - DELTA_MINUS_VAR: si_total_uncert_plus - DELTA_PLUS_VAR: si_total_uncert_minus s_summed_intensity: <<: *default_particle - DEPEND_1: s_energy_mean CATDESC: S Summed Omnidirectional Intensity in 5 energy bins (useful for quiet times) + DELTA_MINUS_VAR: s_total_uncert_minus + DELTA_PLUS_VAR: s_total_uncert_plus + DEPEND_1: s_energy_mean FIELDNAM: S intensity summed LABLAXIS: s_energy_mean_label - DELTA_MINUS_VAR: s_total_uncert_plus - DELTA_PLUS_VAR: s_total_uncert_minus ar_summed_intensity: <<: *default_particle - DEPEND_1: ar_energy_mean CATDESC: Ar Summed Omnidirectional Intensity in 5 energy bins (useful for quiet times) + DELTA_MINUS_VAR: ar_total_uncert_minus + DELTA_PLUS_VAR: ar_total_uncert_plus + DEPEND_1: ar_energy_mean FIELDNAM: Ar intensity summed LABLAXIS: ar_energy_mean_label - DELTA_MINUS_VAR: ar_total_uncert_plus - DELTA_PLUS_VAR: ar_total_uncert_minus ca_summed_intensity: <<: *default_particle - DEPEND_1: ca_energy_mean CATDESC: Ca Summed Omnidirectional Intensity in 5 energy bins (useful for quiet times) + DELTA_MINUS_VAR: ca_total_uncert_minus + DELTA_PLUS_VAR: ca_total_uncert_plus + DEPEND_1: ca_energy_mean FIELDNAM: Ca intensity summed LABLAXIS: ca_energy_mean_label - DELTA_MINUS_VAR: ca_total_uncert_plus - DELTA_PLUS_VAR: ca_total_uncert_minus fe_summed_intensity: <<: *default_particle - DEPEND_1: fe_energy_mean CATDESC: Fe Summed Omnidirectional Intensity in 5 energy bins (useful for quiet times) + DELTA_MINUS_VAR: fe_total_uncert_minus + DELTA_PLUS_VAR: fe_total_uncert_plus + DEPEND_1: fe_energy_mean FIELDNAM: Fe intensity summed LABLAXIS: fe_energy_mean_label - DELTA_MINUS_VAR: fe_total_uncert_plus - DELTA_PLUS_VAR: fe_total_uncert_minus ni_summed_intensity: <<: *default_particle - DEPEND_1: ni_energy_mean CATDESC: Ni Summed Omnidirectional Intensity in 3 energy bins (useful for quiet times) + DELTA_MINUS_VAR: ni_total_uncert_minus + DELTA_PLUS_VAR: ni_total_uncert_plus + DEPEND_1: ni_energy_mean FIELDNAM: Ni intensity summed LABLAXIS: ni_energy_mean_label - DELTA_MINUS_VAR: ni_total_uncert_plus - DELTA_PLUS_VAR: ni_total_uncert_minus # Energy Delta Variables h_energy_delta_plus: <<: *default_energy_delta - DEPEND_1: h_energy_mean CATDESC: H energy per nucleon delta plus (maximum bin energy per nuc. minus geometric mean) + DEPEND_1: h_energy_mean FIELDNAM: H energy delta plus h_energy_delta_minus: <<: *default_energy_delta - DEPEND_1: h_energy_mean CATDESC: H energy per nucleon delta minus (geometric mean minus minimum bin energy per nuc.) + DEPEND_1: h_energy_mean FIELDNAM: H energy delta minus he3_energy_delta_plus: <<: *default_energy_delta - DEPEND_1: he3_energy_mean CATDESC: He3 energy per nucleon delta plus (maximum bin energy per nuc. minus geometric mean) + DEPEND_1: he3_energy_mean FIELDNAM: He3 energy delta plus he3_energy_delta_minus: <<: *default_energy_delta - DEPEND_1: he3_energy_mean CATDESC: He3 energy per nucleon delta minus (geometric mean minus minimum bin energy per nuc.) + DEPEND_1: he3_energy_mean FIELDNAM: He3 energy delta minus he4_energy_delta_plus: <<: *default_energy_delta - DEPEND_1: he4_energy_mean CATDESC: He4 energy per nucleon delta plus (maximum bin energy per nuc. minus geometric mean) + DEPEND_1: he4_energy_mean FIELDNAM: He4 energy delta plus he4_energy_delta_minus: <<: *default_energy_delta - DEPEND_1: he4_energy_mean CATDESC: He4 energy per nucleon delta minus (geometric mean minus minimum bin energy per nuc.) + DEPEND_1: he4_energy_mean FIELDNAM: He4 energy delta minus he_energy_delta_plus: <<: *default_energy_delta - DEPEND_1: he_energy_mean CATDESC: He energy per nucleon delta plus (maximum bin energy per nuc. minus geometric mean) + DEPEND_1: he_energy_mean FIELDNAM: He energy delta plus he_energy_delta_minus: <<: *default_energy_delta - DEPEND_1: he_energy_mean CATDESC: He energy per nucleon delta minus (geometric mean minus minimum bin energy per nuc.) + DEPEND_1: he_energy_mean FIELDNAM: He energy delta minus c_energy_delta_plus: <<: *default_energy_delta - DEPEND_1: c_energy_mean CATDESC: C energy per nucleon delta plus (maximum bin energy per nuc. minus geometric mean) + DEPEND_1: c_energy_mean FIELDNAM: C energy delta plus c_energy_delta_minus: <<: *default_energy_delta - DEPEND_1: c_energy_mean CATDESC: C energy per nucleon delta minus (geometric mean minus minimum bin energy per nuc.) + DEPEND_1: c_energy_mean FIELDNAM: C energy delta minus o_energy_delta_plus: <<: *default_energy_delta - DEPEND_1: o_energy_mean CATDESC: O energy per nucleon delta plus (maximum bin energy per nuc. minus geometric mean) + DEPEND_1: o_energy_mean FIELDNAM: O energy delta plus o_energy_delta_minus: <<: *default_energy_delta - DEPEND_1: o_energy_mean CATDESC: O energy per nucleon delta minus (geometric mean minus minimum bin energy per nuc.) + DEPEND_1: o_energy_mean FIELDNAM: O energy delta minus n_energy_delta_plus: <<: *default_energy_delta - DEPEND_1: n_energy_mean CATDESC: N energy per nucleon delta plus (maximum bin energy per nuc. minus geometric mean) + DEPEND_1: n_energy_mean FIELDNAM: N energy delta plus n_energy_delta_minus: <<: *default_energy_delta - DEPEND_1: n_energy_mean CATDESC: N energy per nucleon delta minus (geometric mean minus minimum bin energy per nuc.) + DEPEND_1: n_energy_mean FIELDNAM: N energy delta minus ne_energy_delta_plus: <<: *default_energy_delta - DEPEND_1: ne_energy_mean CATDESC: Ne energy per nucleon delta plus (maximum bin energy per nuc. minus geometric mean) + DEPEND_1: ne_energy_mean FIELDNAM: Ne energy delta plus ne_energy_delta_minus: <<: *default_energy_delta - DEPEND_1: ne_energy_mean CATDESC: Ne energy per nucleon delta minus (geometric mean minus minimum bin energy per nuc.) + DEPEND_1: ne_energy_mean FIELDNAM: Ne energy delta minus na_energy_delta_plus: <<: *default_energy_delta - DEPEND_1: na_energy_mean CATDESC: Na energy per nucleon delta plus (maximum bin energy per nuc. minus geometric mean) + DEPEND_1: na_energy_mean FIELDNAM: Na energy delta plus na_energy_delta_minus: <<: *default_energy_delta - DEPEND_1: na_energy_mean CATDESC: Na energy per nucleon delta minus (geometric mean minus minimum bin energy per nuc.) + DEPEND_1: na_energy_mean FIELDNAM: Na energy delta minus mg_energy_delta_plus: <<: *default_energy_delta - DEPEND_1: mg_energy_mean CATDESC: Mg energy per nucleon delta plus (maximum bin energy per nuc. minus geometric mean) + DEPEND_1: mg_energy_mean FIELDNAM: Mg energy delta plus mg_energy_delta_minus: <<: *default_energy_delta - DEPEND_1: mg_energy_mean CATDESC: Mg energy per nucleon delta minus (geometric mean minus minimum bin energy per nuc.) + DEPEND_1: mg_energy_mean FIELDNAM: Mg energy delta minus al_energy_delta_plus: <<: *default_energy_delta - DEPEND_1: al_energy_mean CATDESC: Al energy per nucleon delta plus (maximum bin energy per nuc. minus geometric mean) + DEPEND_1: al_energy_mean FIELDNAM: Al energy delta plus al_energy_delta_minus: <<: *default_energy_delta - DEPEND_1: al_energy_mean CATDESC: Al energy per nucleon delta minus (geometric mean minus minimum bin energy per nuc.) + DEPEND_1: al_energy_mean FIELDNAM: Al energy delta minus si_energy_delta_plus: <<: *default_energy_delta - DEPEND_1: si_energy_mean CATDESC: Si energy per nucleon delta plus (maximum bin energy per nuc. minus geometric mean) + DEPEND_1: si_energy_mean FIELDNAM: Si energy delta plus si_energy_delta_minus: <<: *default_energy_delta - DEPEND_1: si_energy_mean CATDESC: Si energy per nucleon delta minus (geometric mean minus minimum bin energy per nuc.) + DEPEND_1: si_energy_mean FIELDNAM: Si energy delta minus s_energy_delta_plus: <<: *default_energy_delta - DEPEND_1: s_energy_mean CATDESC: S energy per nucleon delta plus (maximum bin energy per nuc. minus geometric mean) + DEPEND_1: s_energy_mean FIELDNAM: S energy delta plus s_energy_delta_minus: <<: *default_energy_delta - DEPEND_1: s_energy_mean CATDESC: S energy per nucleon delta minus (geometric mean minus minimum bin energy per nuc.) + DEPEND_1: s_energy_mean FIELDNAM: S energy delta minus ar_energy_delta_plus: <<: *default_energy_delta - DEPEND_1: ar_energy_mean CATDESC: Ar energy per nucleon delta plus (maximum bin energy per nuc. minus geometric mean) + DEPEND_1: ar_energy_mean FIELDNAM: Ar energy delta plus ar_energy_delta_minus: <<: *default_energy_delta - DEPEND_1: ar_energy_mean CATDESC: Ar energy per nucleon delta minus (geometric mean minus minimum bin energy per nuc.) + DEPEND_1: ar_energy_mean FIELDNAM: Ar energy delta minus ca_energy_delta_plus: <<: *default_energy_delta - DEPEND_1: ca_energy_mean CATDESC: Ca energy per nucleon delta plus (maximum bin energy per nuc. minus geometric mean) + DEPEND_1: ca_energy_mean FIELDNAM: Ca energy delta plus ca_energy_delta_minus: <<: *default_energy_delta - DEPEND_1: ca_energy_mean CATDESC: Ca energy per nucleon delta minus (geometric mean minus minimum bin energy per nuc.) + DEPEND_1: ca_energy_mean FIELDNAM: Ca energy delta minus fe_energy_delta_plus: <<: *default_energy_delta - DEPEND_1: fe_energy_mean CATDESC: Fe energy per nucleon delta plus (maximum bin energy per nuc. minus geometric mean) + DEPEND_1: fe_energy_mean FIELDNAM: Fe energy delta plus fe_energy_delta_minus: <<: *default_energy_delta - DEPEND_1: fe_energy_mean CATDESC: Fe energy per nucleon delta minus (geometric mean minus minimum bin energy per nuc.) + DEPEND_1: fe_energy_mean FIELDNAM: Fe energy delta minus ni_energy_delta_plus: <<: *default_energy_delta - DEPEND_1: ni_energy_mean CATDESC: Ni energy per nucleon delta plus (maximum bin energy per nuc. minus geometric mean) + DEPEND_1: ni_energy_mean FIELDNAM: Ni energy delta plus ni_energy_delta_minus: <<: *default_energy_delta - DEPEND_1: ni_energy_mean CATDESC: Ni energy per nucleon delta minus (geometric mean minus minimum bin energy per nuc.) + DEPEND_1: ni_energy_mean FIELDNAM: Ni energy delta minus # Uncertainty Variables (statistical, systematic, and total) h_stat_uncert_plus: <<: *default_uncertainty - DEPEND_1: h_energy_mean CATDESC: Plus statistical uncertainty for H + DEPEND_1: h_energy_mean FIELDNAM: H plus statistical uncertainty LABL_PTR_1: h_energy_mean_label h_stat_uncert_minus: <<: *default_uncertainty - DEPEND_1: h_energy_mean CATDESC: Minus statistical uncertainty for H + DEPEND_1: h_energy_mean FIELDNAM: H minus statistical uncertainty LABL_PTR_1: h_energy_mean_label h_sys_err_plus: <<: *default_uncertainty - DEPEND_1: h_energy_mean CATDESC: Plus Systematic uncertainty for H + DEPEND_1: h_energy_mean FIELDNAM: H Plus Systematic Uncertainty LABL_PTR_1: h_energy_mean_label h_sys_err_minus: <<: *default_uncertainty - DEPEND_1: h_energy_mean CATDESC: Minus systematic uncertainty for H + DEPEND_1: h_energy_mean FIELDNAM: H minus systematic uncertainty LABL_PTR_1: h_energy_mean_label h_total_uncert_plus: <<: *default_uncertainty - DEPEND_1: h_energy_mean CATDESC: Plus total (statistical and systematic added in quadrature) uncertainty for H + DEPEND_1: h_energy_mean FIELDNAM: H plus total uncertainty LABL_PTR_1: h_energy_mean_label h_total_uncert_minus: <<: *default_uncertainty - DEPEND_1: h_energy_mean CATDESC: Minus total (statistical and systematic added in quadrature) uncertainty for H + DEPEND_1: h_energy_mean FIELDNAM: H minus total uncertainty LABL_PTR_1: h_energy_mean_label he3_stat_uncert_plus: <<: *default_uncertainty - DEPEND_1: he3_energy_mean CATDESC: Plus statistical uncertainty for He3 + DEPEND_1: he3_energy_mean FIELDNAM: He3 plus statistical uncertainty LABL_PTR_1: he3_energy_mean_label he3_stat_uncert_minus: <<: *default_uncertainty - DEPEND_1: he3_energy_mean CATDESC: Minus statistical uncertainty for He3 + DEPEND_1: he3_energy_mean FIELDNAM: He3 minus statistical uncertainty LABL_PTR_1: he3_energy_mean_label he3_sys_err_plus: <<: *default_uncertainty - DEPEND_1: he3_energy_mean CATDESC: Plus systematic uncertainty for He3 + DEPEND_1: he3_energy_mean FIELDNAM: He3 Plus Systematic Uncertainty LABL_PTR_1: he3_energy_mean_label he3_sys_err_minus: <<: *default_uncertainty - DEPEND_1: he3_energy_mean CATDESC: Minus systematic uncertainty for He3 + DEPEND_1: he3_energy_mean FIELDNAM: He3 minus systematic uncertainty LABL_PTR_1: he3_energy_mean_label he3_total_uncert_plus: <<: *default_uncertainty - DEPEND_1: he3_energy_mean CATDESC: Plus total (statistical and systematic added in quadrature) uncertainty for He3 + DEPEND_1: he3_energy_mean FIELDNAM: He3 Plus Total Uncertainty LABL_PTR_1: he3_energy_mean_label he3_total_uncert_minus: <<: *default_uncertainty - DEPEND_1: he3_energy_mean CATDESC: Minus total (statistical and systematic added in quadrature) uncertainty for He3 + DEPEND_1: he3_energy_mean FIELDNAM: He3 minus total uncertainty LABL_PTR_1: he3_energy_mean_label he4_stat_uncert_plus: <<: *default_uncertainty - DEPEND_1: he4_energy_mean CATDESC: Plus statistical uncertainty for He4 + DEPEND_1: he4_energy_mean FIELDNAM: He4 plus statistical uncertainty LABL_PTR_1: he4_energy_mean_label he4_stat_uncert_minus: <<: *default_uncertainty - DEPEND_1: he4_energy_mean CATDESC: Minus statistical uncertainty for He4 + DEPEND_1: he4_energy_mean FIELDNAM: He4 minus statistical uncertainty LABL_PTR_1: he4_energy_mean_label he4_sys_err_plus: <<: *default_uncertainty - DEPEND_1: he4_energy_mean CATDESC: Plus systematic uncertainty for He4 + DEPEND_1: he4_energy_mean FIELDNAM: He4 Plus Systematic Uncertainty LABL_PTR_1: he4_energy_mean_label he4_sys_err_minus: <<: *default_uncertainty - DEPEND_1: he4_energy_mean CATDESC: Minus systematic uncertainty for He4 + DEPEND_1: he4_energy_mean FIELDNAM: He4 minus systematic uncertainty LABL_PTR_1: he4_energy_mean_label he4_total_uncert_plus: <<: *default_uncertainty - DEPEND_1: he4_energy_mean CATDESC: Plus total (statistical and systematic added in quadrature) uncertainty for He4 + DEPEND_1: he4_energy_mean FIELDNAM: He4 plus total uncertainty LABL_PTR_1: he4_energy_mean_label he4_total_uncert_minus: <<: *default_uncertainty - DEPEND_1: he4_energy_mean CATDESC: Minus total (statistical and systematic added in quadrature) uncertainty for He4 + DEPEND_1: he4_energy_mean FIELDNAM: He4 minus total uncertainty LABL_PTR_1: he4_energy_mean_label he_stat_uncert_plus: <<: *default_uncertainty - DEPEND_1: he_energy_mean CATDESC: Plus statistical uncertainty for He + DEPEND_1: he_energy_mean FIELDNAM: He plus statistical uncertainty LABL_PTR_1: he_energy_mean_label he_stat_uncert_minus: <<: *default_uncertainty - DEPEND_1: he_energy_mean CATDESC: Minus statistical uncertainty for He + DEPEND_1: he_energy_mean FIELDNAM: He minus statistical uncertainty LABL_PTR_1: he_energy_mean_label he_sys_err_plus: <<: *default_uncertainty - DEPEND_1: he_energy_mean CATDESC: Plus systematic uncertainty for He + DEPEND_1: he_energy_mean FIELDNAM: He plus systematic uncertainty LABL_PTR_1: he_energy_mean_label he_sys_err_minus: <<: *default_uncertainty - DEPEND_1: he_energy_mean CATDESC: Minus systematic uncertainty for He + DEPEND_1: he_energy_mean FIELDNAM: He minus systematic uncertainty LABL_PTR_1: he_energy_mean_label he_total_uncert_plus: <<: *default_uncertainty - DEPEND_1: he_energy_mean CATDESC: Plus total (statistical and systematic added in quadrature) uncertainty for He + DEPEND_1: he_energy_mean FIELDNAM: He plus total uncertainty LABL_PTR_1: he_energy_mean_label he_total_uncert_minus: <<: *default_uncertainty - DEPEND_1: he_energy_mean CATDESC: Minus total (statistical and systematic added in quadrature) uncertainty for He + DEPEND_1: he_energy_mean FIELDNAM: He Minus Total Uncertainty LABL_PTR_1: he_energy_mean_label c_stat_uncert_plus: <<: *default_uncertainty - DEPEND_1: c_energy_mean CATDESC: Plus statistical uncertainty for C + DEPEND_1: c_energy_mean FIELDNAM: C plus statistical uncertainty LABL_PTR_1: c_energy_mean_label c_stat_uncert_minus: <<: *default_uncertainty - DEPEND_1: c_energy_mean CATDESC: Minus statistical uncertainty for C + DEPEND_1: c_energy_mean FIELDNAM: C minus statistical uncertainty LABL_PTR_1: c_energy_mean_label c_sys_err_plus: <<: *default_uncertainty - DEPEND_1: c_energy_mean CATDESC: Plus systematic uncertainty for C + DEPEND_1: c_energy_mean FIELDNAM: C Plus Systematic Uncertainty LABL_PTR_1: c_energy_mean_label c_sys_err_minus: <<: *default_uncertainty - DEPEND_1: c_energy_mean CATDESC: Minus systematic uncertainty for C + DEPEND_1: c_energy_mean FIELDNAM: C minus systematic uncertainty LABL_PTR_1: c_energy_mean_label c_total_uncert_plus: <<: *default_uncertainty - DEPEND_1: c_energy_mean CATDESC: Plus total (statistical and systematic added in quadrature) uncertainty for C + DEPEND_1: c_energy_mean FIELDNAM: C plus total uncertainty LABL_PTR_1: c_energy_mean_label c_total_uncert_minus: <<: *default_uncertainty - DEPEND_1: c_energy_mean CATDESC: Minus total (statistical and systematic added in quadrature) uncertainty for C + DEPEND_1: c_energy_mean FIELDNAM: C Minus Total Uncertainty LABL_PTR_1: c_energy_mean_label o_stat_uncert_plus: <<: *default_uncertainty - DEPEND_1: o_energy_mean CATDESC: Plus statistical uncertainty for O + DEPEND_1: o_energy_mean FIELDNAM: O plus statistical uncertainty LABL_PTR_1: o_energy_mean_label o_stat_uncert_minus: <<: *default_uncertainty - DEPEND_1: o_energy_mean CATDESC: Minus statistical uncertainty for O + DEPEND_1: o_energy_mean FIELDNAM: O minus statistical uncertainty LABL_PTR_1: o_energy_mean_label o_sys_err_plus: <<: *default_uncertainty - DEPEND_1: o_energy_mean CATDESC: Plus systematic uncertainty for O + DEPEND_1: o_energy_mean FIELDNAM: O Plus Systematic Uncertainty LABL_PTR_1: o_energy_mean_label o_sys_err_minus: <<: *default_uncertainty - DEPEND_1: o_energy_mean CATDESC: Minus systematic uncertainty for O + DEPEND_1: o_energy_mean FIELDNAM: O minus systematic uncertainty LABL_PTR_1: o_energy_mean_label o_total_uncert_plus: <<: *default_uncertainty - DEPEND_1: o_energy_mean CATDESC: Plus total (statistical and systematic added in quadrature) uncertainty for O + DEPEND_1: o_energy_mean FIELDNAM: O plus total uncertainty LABL_PTR_1: o_energy_mean_label o_total_uncert_minus: <<: *default_uncertainty - DEPEND_1: o_energy_mean CATDESC: Minus total (statistical and systematic added in quadrature) uncertainty for O + DEPEND_1: o_energy_mean FIELDNAM: O Minus Total Uncertainty LABL_PTR_1: o_energy_mean_label n_stat_uncert_plus: <<: *default_uncertainty - DEPEND_1: n_energy_mean CATDESC: Plus statistical uncertainty for N + DEPEND_1: n_energy_mean FIELDNAM: N plus statistical uncertainty LABL_PTR_1: n_energy_mean_label n_stat_uncert_minus: <<: *default_uncertainty - DEPEND_1: n_energy_mean CATDESC: Minus statistical uncertainty for N + DEPEND_1: n_energy_mean FIELDNAM: N minus statistical uncertainty LABL_PTR_1: n_energy_mean_label n_sys_err_plus: <<: *default_uncertainty - DEPEND_1: n_energy_mean CATDESC: Plus systematic uncertainty for N + DEPEND_1: n_energy_mean FIELDNAM: N Plus Systematic Uncertainty LABL_PTR_1: n_energy_mean_label n_sys_err_minus: <<: *default_uncertainty - DEPEND_1: n_energy_mean CATDESC: Minus systematic uncertainty for N + DEPEND_1: n_energy_mean FIELDNAM: N minus systematic uncertainty LABL_PTR_1: n_energy_mean_label n_total_uncert_plus: <<: *default_uncertainty - DEPEND_1: n_energy_mean CATDESC: Plus total (statistical and systematic added in quadrature) uncertainty for N + DEPEND_1: n_energy_mean FIELDNAM: N plus total uncertainty LABL_PTR_1: n_energy_mean_label n_total_uncert_minus: <<: *default_uncertainty - DEPEND_1: n_energy_mean CATDESC: Minus total (statistical and systematic added in quadrature) uncertainty for N + DEPEND_1: n_energy_mean FIELDNAM: N Minus Total Uncertainty LABL_PTR_1: n_energy_mean_label ne_stat_uncert_plus: <<: *default_uncertainty - DEPEND_1: ne_energy_mean CATDESC: Plus statistical uncertainty for Ne + DEPEND_1: ne_energy_mean FIELDNAM: Ne plus statistical uncertainty LABL_PTR_1: ne_energy_mean_label ne_stat_uncert_minus: <<: *default_uncertainty - DEPEND_1: ne_energy_mean CATDESC: Minus statistical uncertainty for Ne + DEPEND_1: ne_energy_mean FIELDNAM: Ne minus statistical uncertainty LABL_PTR_1: ne_energy_mean_label ne_sys_err_plus: <<: *default_uncertainty - DEPEND_1: ne_energy_mean CATDESC: Plus systematic uncertainty for Ne + DEPEND_1: ne_energy_mean FIELDNAM: Ne Plus Systematic Uncertainty LABL_PTR_1: ne_energy_mean_label ne_sys_err_minus: <<: *default_uncertainty - DEPEND_1: ne_energy_mean CATDESC: Minus systematic uncertainty for Ne + DEPEND_1: ne_energy_mean FIELDNAM: Ne minus systematic uncertainty LABL_PTR_1: ne_energy_mean_label ne_total_uncert_plus: <<: *default_uncertainty - DEPEND_1: ne_energy_mean CATDESC: Plus total (statistical and systematic added in quadrature) uncertainty for Ne + DEPEND_1: ne_energy_mean FIELDNAM: Ne plus total uncertainty LABL_PTR_1: ne_energy_mean_label ne_total_uncert_minus: <<: *default_uncertainty - DEPEND_1: ne_energy_mean CATDESC: Minus total (statistical and systematic added in quadrature) uncertainty for Ne + DEPEND_1: ne_energy_mean FIELDNAM: Ne minus total uncertainty LABL_PTR_1: ne_energy_mean_label na_stat_uncert_plus: <<: *default_uncertainty - DEPEND_1: na_energy_mean CATDESC: Plus statistical uncertainty for Na + DEPEND_1: na_energy_mean FIELDNAM: Na plus statistical uncertainty LABL_PTR_1: na_energy_mean_label na_stat_uncert_minus: <<: *default_uncertainty - DEPEND_1: na_energy_mean CATDESC: Minus statistical uncertainty for Na + DEPEND_1: na_energy_mean FIELDNAM: Na minus statistical uncertainty LABL_PTR_1: na_energy_mean_label na_sys_err_plus: <<: *default_uncertainty - DEPEND_1: na_energy_mean CATDESC: Plus systematic uncertainty for Na + DEPEND_1: na_energy_mean FIELDNAM: Na Plus Systematic Uncertainty LABL_PTR_1: na_energy_mean_label na_sys_err_minus: <<: *default_uncertainty - DEPEND_1: na_energy_mean CATDESC: Minus systematic uncertainty for Na + DEPEND_1: na_energy_mean FIELDNAM: Na minus systematic uncertainty LABL_PTR_1: na_energy_mean_label na_total_uncert_plus: <<: *default_uncertainty - DEPEND_1: na_energy_mean CATDESC: Plus total (statistical and systematic added in quadrature) uncertainty for Na + DEPEND_1: na_energy_mean FIELDNAM: Na plus total uncertainty LABL_PTR_1: na_energy_mean_label na_total_uncert_minus: <<: *default_uncertainty - DEPEND_1: na_energy_mean CATDESC: Minus total (statistical and systematic added in quadrature) uncertainty for Na + DEPEND_1: na_energy_mean FIELDNAM: Na minus total uncertainty LABL_PTR_1: na_energy_mean_label mg_stat_uncert_plus: <<: *default_uncertainty - DEPEND_1: mg_energy_mean CATDESC: Plus statistical uncertainty for Mg + DEPEND_1: mg_energy_mean FIELDNAM: Mg plus statistical uncertainty LABL_PTR_1: mg_energy_mean_label mg_stat_uncert_minus: <<: *default_uncertainty - DEPEND_1: mg_energy_mean CATDESC: Minus statistical uncertainty for Mg + DEPEND_1: mg_energy_mean FIELDNAM: Mg minus statistical uncertainty LABL_PTR_1: mg_energy_mean_label mg_sys_err_plus: <<: *default_uncertainty - DEPEND_1: mg_energy_mean CATDESC: Plus systematic uncertainty for Mg + DEPEND_1: mg_energy_mean FIELDNAM: Mg Plus Systematic Uncertainty LABL_PTR_1: mg_energy_mean_label mg_sys_err_minus: <<: *default_uncertainty - DEPEND_1: mg_energy_mean CATDESC: Minus systematic uncertainty for Mg + DEPEND_1: mg_energy_mean FIELDNAM: Mg minus systematic uncertainty LABL_PTR_1: mg_energy_mean_label mg_total_uncert_plus: <<: *default_uncertainty - DEPEND_1: mg_energy_mean CATDESC: Plus total (statistical and systematic added in quadrature) uncertainty for Mg + DEPEND_1: mg_energy_mean FIELDNAM: Mg plus total uncertainty LABL_PTR_1: mg_energy_mean_label mg_total_uncert_minus: <<: *default_uncertainty - DEPEND_1: mg_energy_mean CATDESC: Minus total (statistical and systematic added in quadrature) uncertainty for Mg + DEPEND_1: mg_energy_mean FIELDNAM: Mg minus total uncertainty LABL_PTR_1: mg_energy_mean_label al_stat_uncert_plus: <<: *default_uncertainty - DEPEND_1: al_energy_mean CATDESC: Plus statistical uncertainty for Al + DEPEND_1: al_energy_mean FIELDNAM: Al plus statistical uncertainty LABL_PTR_1: al_energy_mean_label al_stat_uncert_minus: <<: *default_uncertainty - DEPEND_1: al_energy_mean CATDESC: Minus statistical uncertainty for Al + DEPEND_1: al_energy_mean FIELDNAM: Al minus statistical uncertainty LABL_PTR_1: al_energy_mean_label al_sys_err_plus: <<: *default_uncertainty - DEPEND_1: al_energy_mean CATDESC: Plus systematic uncertainty for Al + DEPEND_1: al_energy_mean FIELDNAM: Al Plus Systematic Uncertainty LABL_PTR_1: al_energy_mean_label al_sys_err_minus: <<: *default_uncertainty - DEPEND_1: al_energy_mean CATDESC: Minus systematic uncertainty for Al + DEPEND_1: al_energy_mean FIELDNAM: Al minus systematic uncertainty LABL_PTR_1: al_energy_mean_label al_total_uncert_plus: <<: *default_uncertainty - DEPEND_1: al_energy_mean CATDESC: Plus total (statistical and systematic added in quadrature) uncertainty for Al + DEPEND_1: al_energy_mean FIELDNAM: Al plus total uncertainty LABL_PTR_1: al_energy_mean_label al_total_uncert_minus: <<: *default_uncertainty - DEPEND_1: al_energy_mean CATDESC: Minus total (statistical and systematic added in quadrature) uncertainty for Al + DEPEND_1: al_energy_mean FIELDNAM: Al minus total uncertainty LABL_PTR_1: al_energy_mean_label si_stat_uncert_plus: <<: *default_uncertainty - DEPEND_1: si_energy_mean CATDESC: Plus statistical uncertainty for Si + DEPEND_1: si_energy_mean FIELDNAM: Si plus statistical uncertainty LABL_PTR_1: si_energy_mean_label si_stat_uncert_minus: <<: *default_uncertainty - DEPEND_1: si_energy_mean CATDESC: Minus statistical uncertainty for Si + DEPEND_1: si_energy_mean FIELDNAM: Si minus statistical uncertainty LABL_PTR_1: si_energy_mean_label si_sys_err_plus: <<: *default_uncertainty - DEPEND_1: si_energy_mean CATDESC: Plus systematic uncertainty for Si + DEPEND_1: si_energy_mean FIELDNAM: Si Plus Systematic Uncertainty LABL_PTR_1: si_energy_mean_label si_sys_err_minus: <<: *default_uncertainty - DEPEND_1: si_energy_mean CATDESC: Minus systematic uncertainty for Si + DEPEND_1: si_energy_mean FIELDNAM: Si minus systematic uncertainty LABL_PTR_1: si_energy_mean_label si_total_uncert_plus: <<: *default_uncertainty - DEPEND_1: si_energy_mean CATDESC: Plus total (statistical and systematic added in quadrature) uncertainty for Si + DEPEND_1: si_energy_mean FIELDNAM: Si plus total uncertainty LABL_PTR_1: si_energy_mean_label si_total_uncert_minus: <<: *default_uncertainty - DEPEND_1: si_energy_mean CATDESC: Minus total (statistical and systematic added in quadrature) uncertainty for Si + DEPEND_1: si_energy_mean FIELDNAM: Si minus total uncertainty LABL_PTR_1: si_energy_mean_label s_stat_uncert_plus: <<: *default_uncertainty - DEPEND_1: s_energy_mean CATDESC: Plus statistical uncertainty for S + DEPEND_1: s_energy_mean FIELDNAM: S plus statistical uncertainty LABL_PTR_1: s_energy_mean_label s_stat_uncert_minus: <<: *default_uncertainty - DEPEND_1: s_energy_mean CATDESC: Minus statistical uncertainty for S + DEPEND_1: s_energy_mean FIELDNAM: S minus statistical uncertainty LABL_PTR_1: s_energy_mean_label s_sys_err_plus: <<: *default_uncertainty - DEPEND_1: s_energy_mean CATDESC: Plus systematic uncertainty for S + DEPEND_1: s_energy_mean FIELDNAM: S Plus Systematic Uncertainty LABL_PTR_1: s_energy_mean_label s_sys_err_minus: <<: *default_uncertainty - DEPEND_1: s_energy_mean CATDESC: Minus systematic uncertainty for S + DEPEND_1: s_energy_mean FIELDNAM: S minus systematic uncertainty LABL_PTR_1: s_energy_mean_label s_total_uncert_plus: <<: *default_uncertainty - DEPEND_1: s_energy_mean CATDESC: Plus total (statistical and systematic added in quadrature) uncertainty for S + DEPEND_1: s_energy_mean FIELDNAM: S plus total uncertainty LABL_PTR_1: s_energy_mean_label s_total_uncert_minus: <<: *default_uncertainty - DEPEND_1: s_energy_mean CATDESC: Minus total (statistical and systematic added in quadrature) uncertainty for S + DEPEND_1: s_energy_mean FIELDNAM: S minus total uncertainty LABL_PTR_1: s_energy_mean_label ar_stat_uncert_plus: <<: *default_uncertainty - DEPEND_1: ar_energy_mean CATDESC: Plus statistical uncertainty for Ar + DEPEND_1: ar_energy_mean FIELDNAM: Ar plus statistical uncertainty LABL_PTR_1: ar_energy_mean_label ar_stat_uncert_minus: <<: *default_uncertainty - DEPEND_1: ar_energy_mean CATDESC: Minus statistical uncertainty for Ar + DEPEND_1: ar_energy_mean FIELDNAM: Ar minus statistical uncertainty LABL_PTR_1: ar_energy_mean_label ar_sys_err_plus: <<: *default_uncertainty - DEPEND_1: ar_energy_mean CATDESC: Plus systematic uncertainty for Ar + DEPEND_1: ar_energy_mean FIELDNAM: Ar Plus Systematic Uncertainty LABL_PTR_1: ar_energy_mean_label ar_sys_err_minus: <<: *default_uncertainty - DEPEND_1: ar_energy_mean CATDESC: Minus systematic uncertainty for Ar + DEPEND_1: ar_energy_mean FIELDNAM: Ar minus systematic uncertainty LABL_PTR_1: ar_energy_mean_label ar_total_uncert_plus: <<: *default_uncertainty - DEPEND_1: ar_energy_mean CATDESC: Plus total (statistical and systematic added in quadrature) uncertainty for Ar + DEPEND_1: ar_energy_mean FIELDNAM: Ar plus total uncertainty LABL_PTR_1: ar_energy_mean_label ar_total_uncert_minus: <<: *default_uncertainty - DEPEND_1: ar_energy_mean CATDESC: Minus total (statistical and systematic added in quadrature) uncertainty for Ar + DEPEND_1: ar_energy_mean FIELDNAM: Ar minus total uncertainty LABL_PTR_1: ar_energy_mean_label ca_stat_uncert_plus: <<: *default_uncertainty - DEPEND_1: ca_energy_mean CATDESC: Plus statistical uncertainty for Ca + DEPEND_1: ca_energy_mean FIELDNAM: Ca plus statistical uncertainty LABL_PTR_1: ca_energy_mean_label ca_stat_uncert_minus: <<: *default_uncertainty - DEPEND_1: ca_energy_mean CATDESC: Minus statistical uncertainty for Ca + DEPEND_1: ca_energy_mean FIELDNAM: Ca minus statistical uncertainty LABL_PTR_1: ca_energy_mean_label ca_sys_err_plus: <<: *default_uncertainty - DEPEND_1: ca_energy_mean CATDESC: Plus systematic uncertainty for Ca + DEPEND_1: ca_energy_mean FIELDNAM: Ca Plus Systematic Uncertainty LABL_PTR_1: ca_energy_mean_label ca_sys_err_minus: <<: *default_uncertainty - DEPEND_1: ca_energy_mean CATDESC: Minus systematic uncertainty for Ca + DEPEND_1: ca_energy_mean FIELDNAM: Ca minus systematic uncertainty LABL_PTR_1: ca_energy_mean_label ca_total_uncert_plus: <<: *default_uncertainty - DEPEND_1: ca_energy_mean CATDESC: Plus total (statistical and systematic added in quadrature) uncertainty for Ca + DEPEND_1: ca_energy_mean FIELDNAM: Ca plus total uncertainty LABL_PTR_1: ca_energy_mean_label ca_total_uncert_minus: <<: *default_uncertainty - DEPEND_1: ca_energy_mean CATDESC: Minus total (statistical and systematic added in quadrature) uncertainty for Ca + DEPEND_1: ca_energy_mean FIELDNAM: Ca minus total uncertainty LABL_PTR_1: ca_energy_mean_label fe_stat_uncert_plus: <<: *default_uncertainty - DEPEND_1: fe_energy_mean CATDESC: Plus statistical uncertainty for Fe + DEPEND_1: fe_energy_mean FIELDNAM: Fe plus statistical uncertainty LABL_PTR_1: fe_energy_mean_label fe_stat_uncert_minus: <<: *default_uncertainty - DEPEND_1: fe_energy_mean CATDESC: Minus statistical uncertainty for Fe + DEPEND_1: fe_energy_mean FIELDNAM: Fe minus statistical uncertainty LABL_PTR_1: fe_energy_mean_label fe_sys_err_plus: <<: *default_uncertainty - DEPEND_1: fe_energy_mean CATDESC: Plus systematic uncertainty for Fe + DEPEND_1: fe_energy_mean FIELDNAM: Fe Plus Systematic Uncertainty LABL_PTR_1: fe_energy_mean_label fe_sys_err_minus: <<: *default_uncertainty - DEPEND_1: fe_energy_mean CATDESC: Minus systematic uncertainty for Fe + DEPEND_1: fe_energy_mean FIELDNAM: Fe minus systematic uncertainty LABL_PTR_1: fe_energy_mean_label fe_total_uncert_plus: <<: *default_uncertainty - DEPEND_1: fe_energy_mean CATDESC: Plus total (statistical and systematic added in quadrature) uncertainty for Fe + DEPEND_1: fe_energy_mean FIELDNAM: Fe plus total uncertainty LABL_PTR_1: fe_energy_mean_label fe_total_uncert_minus: <<: *default_uncertainty - DEPEND_1: fe_energy_mean CATDESC: Minus total (statistical and systematic added in quadrature) uncertainty for Fe + DEPEND_1: fe_energy_mean FIELDNAM: Fe minus total uncertainty LABL_PTR_1: fe_energy_mean_label ni_stat_uncert_plus: <<: *default_uncertainty - DEPEND_1: ni_energy_mean CATDESC: Plus statistical uncertainty for Ni + DEPEND_1: ni_energy_mean FIELDNAM: Ni plus statistical uncertainty LABL_PTR_1: ni_energy_mean_label ni_stat_uncert_minus: <<: *default_uncertainty - DEPEND_1: ni_energy_mean CATDESC: Minus statistical uncertainty for Ni + DEPEND_1: ni_energy_mean FIELDNAM: Ni minus statistical uncertainty LABL_PTR_1: ni_energy_mean_label ni_sys_err_plus: <<: *default_uncertainty - DEPEND_1: ni_energy_mean CATDESC: Plus systematic uncertainty for Ni + DEPEND_1: ni_energy_mean FIELDNAM: Ni Plus Systematic Uncertainty LABL_PTR_1: ni_energy_mean_label ni_sys_err_minus: <<: *default_uncertainty - DEPEND_1: ni_energy_mean CATDESC: Minus systematic uncertainty for Ni + DEPEND_1: ni_energy_mean FIELDNAM: Ni minus systematic uncertainty LABL_PTR_1: ni_energy_mean_label ni_total_uncert_plus: <<: *default_uncertainty - DEPEND_1: ni_energy_mean CATDESC: Plus total (statistical and systematic added in quadrature) uncertainty for Ni + DEPEND_1: ni_energy_mean FIELDNAM: Ni plus total uncertainty LABL_PTR_1: ni_energy_mean_label ni_total_uncert_minus: <<: *default_uncertainty - DEPEND_1: ni_energy_mean CATDESC: Minus total (statistical and systematic added in quadrature) uncertainty for Ni + DEPEND_1: ni_energy_mean FIELDNAM: Ni minus total uncertainty LABL_PTR_1: ni_energy_mean_label @@ -1577,423 +1577,423 @@ ni_total_uncert_minus: h_macropixel_intensity: <<: *default_particle CATDESC: H Macropixel Intensity + DELTA_MINUS_VAR: h_total_uncert_minus + DELTA_PLUS_VAR: h_total_uncert_plus DEPEND_1: h_energy_mean DEPEND_2: azimuth DEPEND_3: zenith + FIELDNAM: H Intensity Macropixel LABL_PTR_1: h_energy_mean_label LABL_PTR_2: azimuth_label LABL_PTR_3: zenith_label - FIELDNAM: H Intensity Macropixel - DELTA_MINUS_VAR: h_total_uncert_plus - DELTA_PLUS_VAR: h_total_uncert_minus he4_macropixel_intensity: <<: *default_particle CATDESC: He4 Macropixel Intensity + DELTA_MINUS_VAR: he4_total_uncert_minus + DELTA_PLUS_VAR: he4_total_uncert_plus DEPEND_1: he4_energy_mean DEPEND_2: azimuth DEPEND_3: zenith + FIELDNAM: He4 Intensity Macropixel LABL_PTR_1: he4_energy_mean_label LABL_PTR_2: azimuth_label LABL_PTR_3: zenith_label - FIELDNAM: He4 Intensity Macropixel - DELTA_MINUS_VAR: he4_total_uncert_plus - DELTA_PLUS_VAR: he4_total_uncert_minus cno_macropixel_intensity: <<: *default_particle CATDESC: C, N, O Macropixel Intensity + DELTA_MINUS_VAR: cno_total_uncert_minus + DELTA_PLUS_VAR: cno_total_uncert_plus DEPEND_1: cno_energy_mean DEPEND_2: azimuth DEPEND_3: zenith + FIELDNAM: CNO Intensity Macropixel LABL_PTR_1: cno_energy_mean_label LABL_PTR_2: azimuth_label LABL_PTR_3: zenith_label - FIELDNAM: CNO Intensity Macropixel - DELTA_MINUS_VAR: cno_total_uncert_plus - DELTA_PLUS_VAR: cno_total_uncert_minus nemgsi_macropixel_intensity: <<: *default_particle CATDESC: NeMgSi Macropixel Intensity + DELTA_MINUS_VAR: nemgsi_total_uncert_minus + DELTA_PLUS_VAR: nemgsi_total_uncert_plus DEPEND_1: nemgsi_energy_mean DEPEND_2: azimuth DEPEND_3: zenith + FIELDNAM: NeMgSi Intensity Macropixel LABL_PTR_1: nemgsi_energy_mean_label LABL_PTR_2: azimuth_label LABL_PTR_3: zenith_label - FIELDNAM: NeMgSi Intensity Macropixel - DELTA_MINUS_VAR: nemgsi_total_uncert_plus - DELTA_PLUS_VAR: nemgsi_total_uncert_minus fe_macropixel_intensity: <<: *default_particle CATDESC: Fe Macropixel Intensity + DELTA_MINUS_VAR: fe_total_uncert_minus + DELTA_PLUS_VAR: fe_total_uncert_plus DEPEND_1: fe_energy_mean DEPEND_2: azimuth DEPEND_3: zenith + FIELDNAM: Fe Intensity Macropixel LABL_PTR_1: fe_energy_mean_label LABL_PTR_2: azimuth_label LABL_PTR_3: zenith_label - FIELDNAM: Fe Intensity Macropixel - DELTA_MINUS_VAR: fe_total_uncert_plus - DELTA_PLUS_VAR: fe_total_uncert_minus # Energy Delta Variables cno_energy_delta_plus: <<: *default_energy_delta - DEPEND_1: cno_energy_mean CATDESC: C, N, O energy per nucleon delta plus (maximum bin energy per nuc. minus geometric mean) + DEPEND_1: cno_energy_mean FIELDNAM: CNO energy delta plus cno_energy_delta_minus: <<: *default_energy_delta - DEPEND_1: cno_energy_mean CATDESC: C, N, O energy per nucleon delta minus (geometric mean minus minimum bin energy per nuc.) + DEPEND_1: cno_energy_mean FIELDNAM: CNO energy delta minus nemgsi_energy_delta_plus: <<: *default_energy_delta - DEPEND_1: nemgsi_energy_mean CATDESC: Ne, Mg, Si energy per nucleon delta plus (maximum bin energy per nuc. minus geometric mean) + DEPEND_1: nemgsi_energy_mean FIELDNAM: NeMgSi energy delta plus nemgsi_energy_delta_minus: <<: *default_energy_delta - DEPEND_1: nemgsi_energy_mean CATDESC: Ne, Mg, Si energy per nucleon delta minus (geometric mean minus minimum bin energy per nuc.) + DEPEND_1: nemgsi_energy_mean FIELDNAM: NeMgSi energy delta minus # Uncertainty Variables (statistical, systematic, and total) h_stat_uncert_plus_macropixel: <<: *default_uncertainty + CATDESC: Plus statistical uncertainty for H Macropixel DEPEND_1: h_energy_mean DEPEND_2: azimuth DEPEND_3: zenith + FIELDNAM: H plus statistical uncertainty LABL_PTR_1: h_energy_mean_label LABL_PTR_2: azimuth_label LABL_PTR_3: zenith_label - CATDESC: Plus statistical uncertainty for H Macropixel - FIELDNAM: H plus statistical uncertainty h_stat_uncert_minus_macropixel: <<: *default_uncertainty + CATDESC: Minus statistical uncertainty for H Macropixel DEPEND_1: h_energy_mean DEPEND_2: azimuth DEPEND_3: zenith + FIELDNAM: H minus statistical uncertainty LABL_PTR_1: h_energy_mean_label LABL_PTR_2: azimuth_label LABL_PTR_3: zenith_label - CATDESC: Minus statistical uncertainty for H Macropixel - FIELDNAM: H minus statistical uncertainty h_sys_err_plus_macropixel: <<: *default_uncertainty + CATDESC: Plus systematic uncertainty for H Macropixel DEPEND_1: h_energy_mean DEPEND_2: azimuth DEPEND_3: zenith + FIELDNAM: H Plus Systematic Uncertainty LABL_PTR_1: h_energy_mean_label LABL_PTR_2: azimuth_label LABL_PTR_3: zenith_label - CATDESC: Plus systematic uncertainty for H Macropixel - FIELDNAM: H Plus Systematic Uncertainty h_sys_err_minus_macropixel: <<: *default_uncertainty + CATDESC: Minus systematic uncertainty for H Macropixel DEPEND_1: h_energy_mean DEPEND_2: azimuth DEPEND_3: zenith + FIELDNAM: H minus systematic uncertainty LABL_PTR_1: h_energy_mean_label LABL_PTR_2: azimuth_label LABL_PTR_3: zenith_label - CATDESC: Minus systematic uncertainty for H Macropixel - FIELDNAM: H minus systematic uncertainty h_total_uncert_plus_macropixel: <<: *default_uncertainty + CATDESC: Plus total (statistical and systematic added in quadrature) uncertainty for H Macropixel DEPEND_1: h_energy_mean DEPEND_2: azimuth DEPEND_3: zenith + FIELDNAM: H plus total uncertainty LABL_PTR_1: h_energy_mean_label LABL_PTR_2: azimuth_label LABL_PTR_3: zenith_label - CATDESC: Plus total (statistical and systematic added in quadrature) uncertainty for H Macropixel - FIELDNAM: H plus total uncertainty h_total_uncert_minus_macropixel: <<: *default_uncertainty + CATDESC: Minus total (statistical and systematic added in quadrature) uncertainty for H Macropixel DEPEND_1: h_energy_mean DEPEND_2: azimuth DEPEND_3: zenith + FIELDNAM: H minus total uncertainty LABL_PTR_1: h_energy_mean_label LABL_PTR_2: azimuth_label LABL_PTR_3: zenith_label - CATDESC: Minus total (statistical and systematic added in quadrature) uncertainty for H Macropixel - FIELDNAM: H minus total uncertainty he4_stat_uncert_plus_macropixel: <<: *default_uncertainty + CATDESC: Plus statistical uncertainty for He4 Macropixel DEPEND_1: he4_energy_mean DEPEND_2: azimuth DEPEND_3: zenith + FIELDNAM: He4 plus statistical uncertainty LABL_PTR_1: he4_energy_mean_label LABL_PTR_2: azimuth_label LABL_PTR_3: zenith_label - CATDESC: Plus statistical uncertainty for He4 Macropixel - FIELDNAM: He4 plus statistical uncertainty he4_stat_uncert_minus_macropixel: <<: *default_uncertainty + CATDESC: Minus statistical uncertainty for He4 Macropixel DEPEND_1: he4_energy_mean DEPEND_2: azimuth DEPEND_3: zenith + FIELDNAM: He4 minus statistical uncertainty LABL_PTR_1: he4_energy_mean_label LABL_PTR_2: azimuth_label LABL_PTR_3: zenith_label - CATDESC: Minus statistical uncertainty for He4 Macropixel - FIELDNAM: He4 minus statistical uncertainty he4_sys_err_plus_macropixel: <<: *default_uncertainty + CATDESC: Plus systematic uncertainty for He4 Macropixel DEPEND_1: he4_energy_mean DEPEND_2: azimuth DEPEND_3: zenith + FIELDNAM: He4 Plus Systematic Uncertainty LABL_PTR_1: he4_energy_mean_label LABL_PTR_2: azimuth_label LABL_PTR_3: zenith_label - CATDESC: Plus systematic uncertainty for He4 Macropixel - FIELDNAM: He4 Plus Systematic Uncertainty he4_sys_err_minus_macropixel: <<: *default_uncertainty + CATDESC: Minus systematic uncertainty for He4 Macropixel DEPEND_1: he4_energy_mean DEPEND_2: azimuth DEPEND_3: zenith + FIELDNAM: He4 minus systematic uncertainty LABL_PTR_1: he4_energy_mean_label LABL_PTR_2: azimuth_label LABL_PTR_3: zenith_label - CATDESC: Minus systematic uncertainty for He4 Macropixel - FIELDNAM: He4 minus systematic uncertainty he4_total_uncert_plus_macropixel: <<: *default_uncertainty + CATDESC: Plus total (statistical and systematic added in quadrature) uncertainty for He4 Macropixel DEPEND_1: he4_energy_mean DEPEND_2: azimuth DEPEND_3: zenith + FIELDNAM: He4 plus total uncertainty LABL_PTR_1: he4_energy_mean_label LABL_PTR_2: azimuth_label LABL_PTR_3: zenith_label - CATDESC: Plus total (statistical and systematic added in quadrature) uncertainty for He4 Macropixel - FIELDNAM: He4 plus total uncertainty he4_total_uncert_minus_macropixel: <<: *default_uncertainty + CATDESC: Minus total (statistical and systematic added in quadrature) uncertainty for He4 Macropixel DEPEND_1: he4_energy_mean DEPEND_2: azimuth DEPEND_3: zenith + FIELDNAM: He4 minus total uncertainty LABL_PTR_1: he4_energy_mean_label LABL_PTR_2: azimuth_label LABL_PTR_3: zenith_label - CATDESC: Minus total (statistical and systematic added in quadrature) uncertainty for He4 Macropixel - FIELDNAM: He4 minus total uncertainty cno_stat_uncert_plus_macropixel: <<: *default_uncertainty + CATDESC: Plus statistical uncertainty for C, N, O Macropixel DEPEND_1: cno_energy_mean DEPEND_2: azimuth DEPEND_3: zenith + FIELDNAM: CNO plus statistical uncertainty LABL_PTR_1: cno_energy_mean_label LABL_PTR_2: azimuth_label LABL_PTR_3: zenith_label - CATDESC: Plus statistical uncertainty for C, N, O Macropixel - FIELDNAM: CNO plus statistical uncertainty cno_stat_uncert_minus_macropixel: <<: *default_uncertainty + CATDESC: Minus statistical uncertainty for C, N, O Macropixel DEPEND_1: cno_energy_mean DEPEND_2: azimuth DEPEND_3: zenith + FIELDNAM: CNO minus statistical uncertainty LABL_PTR_1: cno_energy_mean_label LABL_PTR_2: azimuth_label LABL_PTR_3: zenith_label - CATDESC: Minus statistical uncertainty for C, N, O Macropixel - FIELDNAM: CNO minus statistical uncertainty cno_sys_err_plus_macropixel: <<: *default_uncertainty + CATDESC: Plus systematic uncertainty for C, N, O Macropixel DEPEND_1: cno_energy_mean DEPEND_2: azimuth DEPEND_3: zenith + FIELDNAM: CNO Plus Systematic Uncertainty LABL_PTR_1: cno_energy_mean_label LABL_PTR_2: azimuth_label LABL_PTR_3: zenith_label - CATDESC: Plus systematic uncertainty for C, N, O Macropixel - FIELDNAM: CNO Plus Systematic Uncertainty cno_sys_err_minus_macropixel: <<: *default_uncertainty + CATDESC: Minus systematic uncertainty for C, N, O Macropixel DEPEND_1: cno_energy_mean DEPEND_2: azimuth DEPEND_3: zenith + FIELDNAM: CNO minus systematic uncertainty LABL_PTR_1: cno_energy_mean_label LABL_PTR_2: azimuth_label LABL_PTR_3: zenith_label - CATDESC: Minus systematic uncertainty for C, N, O Macropixel - FIELDNAM: CNO minus systematic uncertainty cno_total_uncert_plus_macropixel: <<: *default_uncertainty + CATDESC: Plus total (statistical and systematic added in quadrature) uncertainty for C, N, O Macropixel DEPEND_1: cno_energy_mean DEPEND_2: azimuth DEPEND_3: zenith + FIELDNAM: CNO plus total uncertainty LABL_PTR_1: cno_energy_mean_label LABL_PTR_2: azimuth_label LABL_PTR_3: zenith_label - CATDESC: Plus total (statistical and systematic added in quadrature) uncertainty for C, N, O Macropixel - FIELDNAM: CNO plus total uncertainty cno_total_uncert_minus_macropixel: <<: *default_uncertainty + CATDESC: Minus total (statistical and systematic added in quadrature) uncertainty for C, N, O Macropixel DEPEND_1: cno_energy_mean DEPEND_2: azimuth DEPEND_3: zenith + FIELDNAM: CNO minus total uncertainty LABL_PTR_1: cno_energy_mean_label LABL_PTR_2: azimuth_label LABL_PTR_3: zenith_label - CATDESC: Minus total (statistical and systematic added in quadrature) uncertainty for C, N, O Macropixel - FIELDNAM: CNO minus total uncertainty nemgsi_stat_uncert_plus_macropixel: <<: *default_uncertainty + CATDESC: Plus statistical uncertainty for Ne, Mg, Si Macropixel DEPEND_1: nemgsi_energy_mean DEPEND_2: azimuth DEPEND_3: zenith + FIELDNAM: NeMgSi plus statistical uncertainty LABL_PTR_1: nemgsi_energy_mean_label LABL_PTR_2: azimuth_label LABL_PTR_3: zenith_label - CATDESC: Plus statistical uncertainty for Ne, Mg, Si Macropixel - FIELDNAM: NeMgSi plus statistical uncertainty nemgsi_stat_uncert_minus_macropixel: <<: *default_uncertainty + CATDESC: Minus statistical uncertainty for Ne, Mg, Si Macropixel DEPEND_1: nemgsi_energy_mean DEPEND_2: azimuth DEPEND_3: zenith + FIELDNAM: NeMgSi minus statistical uncertainty LABL_PTR_1: nemgsi_energy_mean_label LABL_PTR_2: azimuth_label LABL_PTR_3: zenith_label - CATDESC: Minus statistical uncertainty for Ne, Mg, Si Macropixel - FIELDNAM: NeMgSi minus statistical uncertainty nemgsi_sys_err_plus_macropixel: <<: *default_uncertainty + CATDESC: Plus systematic uncertainty for Ne, Mg, Si Macropixel DEPEND_1: nemgsi_energy_mean DEPEND_2: azimuth DEPEND_3: zenith + FIELDNAM: NeMgSi Plus Systematic Uncertainty LABL_PTR_1: nemgsi_energy_mean_label LABL_PTR_2: azimuth_label LABL_PTR_3: zenith_label - CATDESC: Plus systematic uncertainty for Ne, Mg, Si Macropixel - FIELDNAM: NeMgSi Plus Systematic Uncertainty nemgsi_sys_err_minus_macropixel: <<: *default_uncertainty + CATDESC: Minus systematic uncertainty for Ne, Mg, Si Macropixel DEPEND_1: nemgsi_energy_mean DEPEND_2: azimuth DEPEND_3: zenith + FIELDNAM: NeMgSi minus systematic uncertainty LABL_PTR_1: nemgsi_energy_mean_label LABL_PTR_2: azimuth_label LABL_PTR_3: zenith_label - CATDESC: Minus systematic uncertainty for Ne, Mg, Si Macropixel - FIELDNAM: NeMgSi minus systematic uncertainty nemgsi_total_uncert_plus_macropixel: <<: *default_uncertainty + CATDESC: Plus total (statistical and systematic added in quadrature) uncertainty for Ne, Mg, Si Macropixel DEPEND_1: nemgsi_energy_mean DEPEND_2: azimuth DEPEND_3: zenith + FIELDNAM: NeMgSi plus total uncertainty LABL_PTR_1: nemgsi_energy_mean_label LABL_PTR_2: azimuth_label LABL_PTR_3: zenith_label - CATDESC: Plus total (statistical and systematic added in quadrature) uncertainty for Ne, Mg, Si Macropixel - FIELDNAM: NeMgSi plus total uncertainty nemgsi_total_uncert_minus_macropixel: <<: *default_uncertainty + CATDESC: Minus total (statistical and systematic added in quadrature) uncertainty for Ne, Mg, Si Macropixel DEPEND_1: nemgsi_energy_mean DEPEND_2: azimuth DEPEND_3: zenith + FIELDNAM: NeMgSi minus total uncertainty LABL_PTR_1: nemgsi_energy_mean_label LABL_PTR_2: azimuth_label LABL_PTR_3: zenith_label - CATDESC: Minus total (statistical and systematic added in quadrature) uncertainty for Ne, Mg, Si Macropixel - FIELDNAM: NeMgSi minus total uncertainty fe_stat_uncert_plus_macropixel: <<: *default_uncertainty + CATDESC: Plus statistical uncertainty for Fe Macropixel DEPEND_1: fe_energy_mean DEPEND_2: azimuth DEPEND_3: zenith + FIELDNAM: Fe plus statistical uncertainty LABL_PTR_1: fe_energy_mean_label LABL_PTR_2: azimuth_label LABL_PTR_3: zenith_label - CATDESC: Plus statistical uncertainty for Fe Macropixel - FIELDNAM: Fe plus statistical uncertainty fe_stat_uncert_minus_macropixel: <<: *default_uncertainty + CATDESC: Minus statistical uncertainty for Fe Macropixel DEPEND_1: fe_energy_mean DEPEND_2: azimuth DEPEND_3: zenith + FIELDNAM: Fe minus statistical uncertainty LABL_PTR_1: fe_energy_mean_label LABL_PTR_2: azimuth_label LABL_PTR_3: zenith_label - CATDESC: Minus statistical uncertainty for Fe Macropixel - FIELDNAM: Fe minus statistical uncertainty fe_sys_err_plus_macropixel: <<: *default_uncertainty + CATDESC: Plus systematic uncertainty for Fe Macropixel DEPEND_1: fe_energy_mean DEPEND_2: azimuth DEPEND_3: zenith + FIELDNAM: Fe Plus Systematic Uncertainty LABL_PTR_1: fe_energy_mean_label LABL_PTR_2: azimuth_label LABL_PTR_3: zenith_label - CATDESC: Plus systematic uncertainty for Fe Macropixel - FIELDNAM: Fe Plus Systematic Uncertainty fe_sys_err_minus_macropixel: <<: *default_uncertainty + CATDESC: Minus systematic uncertainty for Fe Macropixel DEPEND_1: fe_energy_mean DEPEND_2: azimuth DEPEND_3: zenith + FIELDNAM: Fe minus systematic uncertainty LABL_PTR_1: fe_energy_mean_label LABL_PTR_2: azimuth_label LABL_PTR_3: zenith_label - CATDESC: Minus systematic uncertainty for Fe Macropixel - FIELDNAM: Fe minus systematic uncertainty fe_total_uncert_plus_macropixel: <<: *default_uncertainty + CATDESC: Plus total (statistical and systematic added in quadrature) uncertainty for Fe Macropixel DEPEND_1: fe_energy_mean DEPEND_2: azimuth DEPEND_3: zenith + FIELDNAM: Fe plus total uncertainty LABL_PTR_1: fe_energy_mean_label LABL_PTR_2: azimuth_label LABL_PTR_3: zenith_label - CATDESC: Plus total (statistical and systematic added in quadrature) uncertainty for Fe Macropixel - FIELDNAM: Fe plus total uncertainty fe_total_uncert_minus_macropixel: <<: *default_uncertainty + CATDESC: Minus total (statistical and systematic added in quadrature) uncertainty for Fe Macropixel DEPEND_1: fe_energy_mean DEPEND_2: azimuth DEPEND_3: zenith + FIELDNAM: Fe minus total uncertainty LABL_PTR_1: fe_energy_mean_label LABL_PTR_2: azimuth_label LABL_PTR_3: zenith_label - CATDESC: Minus total (statistical and systematic added in quadrature) uncertainty for Fe Macropixel - FIELDNAM: Fe minus total uncertainty diff --git a/imap_processing/cdf/config/imap_ialirt_global_cdf_attrs.yaml b/imap_processing/cdf/config/imap_ialirt_global_cdf_attrs.yaml index 0b300fa93d..395ee6ba9e 100644 --- a/imap_processing/cdf/config/imap_ialirt_global_cdf_attrs.yaml +++ b/imap_processing/cdf/config/imap_ialirt_global_cdf_attrs.yaml @@ -9,10 +9,14 @@ instrument_base: &instrument_base HIT (High-energy Ion Telescope), MAG (Magnetometer), and SWAPI (Solar Wind and Pickup Ion). See https://imap.princeton.edu for more details. - Instrument_type: "Multiple Instruments" +Instrument_type: + - "Particles (space)" + - "Magnetic Fields (space)" + - "Plasma and Solar Wind (space)" + - "Ephemeris/Attitude/Ancillary" imap_ialirt_l1_realtime: <<: *instrument_base Data_type: L1_REALTIME>Level-1 Realtime Logical_source: imap_ialirt_l1_realtime - Logical_source_description: IMAP-IALiRT Instrument Level-1 Realtime Data. + Logical_source_description: IMAP Active Link for Real-Time (I-ALiRT) Level-1 Data. diff --git a/imap_processing/cdf/config/imap_ialirt_l1_variable_attrs.yaml b/imap_processing/cdf/config/imap_ialirt_l1_variable_attrs.yaml index ac00482b1c..46420dc4d5 100644 --- a/imap_processing/cdf/config/imap_ialirt_l1_variable_attrs.yaml +++ b/imap_processing/cdf/config/imap_ialirt_l1_variable_attrs.yaml @@ -1,396 +1,669 @@ +# Epochs +instrument_epoch: &instrument_epoch + CATDESC: Time, number of nanoseconds since J2000 with leap seconds included + CDF_DATA_TYPE: "CDF_TIME_TT2000" + DICT_KEY: "SPASE>Support>SupportQuantity:Temporal" + FIELDNAM: epoch + FILLVAL: -9223372036854775808 + FORMAT: " " # Supposedly not required, fails in xarray_to_cdf + LABLAXIS: epoch + MONOTON: INCREASE + REFERENCE_POSITION: Rotating Earth Geoid + RESOLUTION: ' ' + SCALETYP: linear + TIME_BASE: J2000 + TIME_SCALE: Terrestrial Time + UNITS: ns + VALIDMAX: 3155716869184000000 # 2100-01-01T00:00:00 mission end + VALIDMIN: 315576066184000000 # 2010-01-01T00:00:00 mission start (APL 0 epoch) + VAR_TYPE: support_data + +codice_hi_epoch: + <<: *instrument_epoch + CATDESC: Time CoDICE-Hi instrument took the measurement, number of nanoseconds since J2000 with leap seconds included + FIELDNAM: CoDICE-Hi epoch + +codice_lo_epoch: + <<: *instrument_epoch + CATDESC: Time CoDICE-Lo instrument took the measurement, number of nanoseconds since J2000 with leap seconds included + FIELDNAM: CoDICE-Lo epoch + +hit_epoch: + <<: *instrument_epoch + CATDESC: Time HIT instrument took the measurement, number of nanoseconds since J2000 with leap seconds included + FIELDNAM: HIT epoch + +mag_epoch: + <<: *instrument_epoch + CATDESC: Time MAG instrument took the measurement, number of nanoseconds since J2000 with leap seconds included + FIELDNAM: MAG epoch + +swapi_epoch: + <<: *instrument_epoch + CATDESC: Time SWAPI instrument took the measurement, number of nanoseconds since J2000 with leap seconds included + FIELDNAM: SWAPI epoch + +swe_epoch: + <<: *instrument_epoch + CATDESC: Time SWE instrument took the measurement, number of nanoseconds since J2000 with leap seconds included + FIELDNAM: SWE epoch + +ephemeris_epoch: + <<: *instrument_epoch + CATDESC: Time of ephemeris measurement, number of nanoseconds since J2000 with leap seconds included + FIELDNAM: Ephemeris epoch + +# Defaults default_attrs: &default # Assumed values for all variable attrs unless overwritten - DEPEND_0: epoch + DEPEND_0: ephemeris_epoch DISPLAY_TYPE: time_series FILLVAL: -9223372036854775808 FORMAT: I12 - VALIDMIN: -9223372036854775808 + UNITS: " " VALIDMAX: 9223372036854775807 + VALIDMIN: -9223372036854775808 VAR_TYPE: data - UNITS: " " - -component: - CATDESC: Component direction (x, y, z) - FIELDNAM: component - LABLAXIS: component - FORMAT: A3 - VAR_TYPE: metadata - UNITS: " " - -RTN_component: - CATDESC: Component direction (radial, tangential, normal) - FIELDNAM: RTN_component - LABLAXIS: RTN_component - FORMAT: A3 - VAR_TYPE: metadata - UNITS: " " - -esa_step: - CATDESC: ESA step number. The nominal central energies for the 8 i-ALiRT channels are 100.4, 140, 194, 270, 376, 523, 727, and 1011 eV. - FIELDNAM: esa_step - LABLAXIS: esa_step - FORMAT: I2 - VALIDMIN: 0 - VALIDMAX: 7 - VAR_TYPE: metadata - UNITS: " " - -codice_hi_h_energy_ranges: - CATDESC: CoDICE-Hi energy ranges - FIELDNAM: codice_hi_h_energy_ranges - LABLAXIS: codice_hi_h_energy_ranges - FORMAT: I3 - VALIDMIN: 0 - VALIDMAX: 14 - VAR_TYPE: metadata - UNITS: " " - -codice_hi_h_elevation: - CATDESC: CoDICE-Hi elevation - FIELDNAM: codice_hi_h_elevation - LABLAXIS: codice_hi_h_elevation - FORMAT: I3 - VALIDMIN: 0 - VALIDMAX: 4 - VAR_TYPE: metadata - UNITS: " " - -codice_hi_h_spin_angle: - CATDESC: CoDICE-Hi spin_angle - FIELDNAM: codice_hi_h_spin_angle - LABLAXIS: codice_hi_h_spin_angle - FORMAT: I3 - VALIDMIN: 0 - VALIDMAX: 4 - VAR_TYPE: metadata - UNITS: " " default_uint8_attrs: &default_uint8 <<: *default FILLVAL: 255 FORMAT: I3 - VALIDMIN: 0 VALIDMAX: 255 + VALIDMIN: 0 dtype: uint8 default_uint16_attrs: &default_uint16 <<: *default FILLVAL: 65535 FORMAT: I5 - VALIDMIN: 0 VALIDMAX: 65535 + VALIDMIN: 0 dtype: uint16 default_uint32_attrs: &default_uint32 <<: *default FILLVAL: 4294967295 FORMAT: I10 - VALIDMIN: 0 VALIDMAX: 4294967295 + VALIDMIN: 0 dtype: uint32 default_int64_attrs: &default_int64 <<: *default FILLVAL: -9223372036854775808 FORMAT: I20 - VALIDMIN: -9223372036854775808 VALIDMAX: 9223372036854775807 + VALIDMIN: -9223372036854775808 dtype: int64 default_int32_attrs: &default_int32 <<: *default FILLVAL: -2147483648 FORMAT: I10 - VALIDMIN: -2147483648 VALIDMAX: 2147483647 + VALIDMIN: -2147483648 dtype: int32 default_float32_attrs: &default_float32 <<: *default FILLVAL: -1.0e31 FORMAT: F12.6 - VALIDMIN: -3.4028235e+38 VALIDMAX: 3.4028235e+38 + VALIDMIN: -3.4028235e+38 dtype: float32 default_float64_attrs: &default_float64 <<: *default FILLVAL: -1.0e31 FORMAT: F10.2 - VALIDMIN: -1.7976931348623157e+308 VALIDMAX: 1.7976931348623157e+308 + VALIDMIN: -1.7976931348623157e+308 dtype: float64 +# Labels +B_GSM_labels: + CATDESC: B GSM component labels + FIELDNAM: B GSM component labels + FORMAT: A8 + UNITS: " " + VAR_TYPE: metadata + +B_GSE_labels: + CATDESC: B GSE component labels + FIELDNAM: B GSE component labels + FORMAT: A8 + UNITS: " " + VAR_TYPE: metadata + +B_RTN_labels: + CATDESC: B RTN component labels B radial (RTN), B tangential (RTN), B normal (RTN) + FIELDNAM: B RTN component labels + FORMAT: A18 + UNITS: " " + VAR_TYPE: metadata + +sc_GSM_position_labels: + CATDESC: Spacecraft position labels in GSM coordinates + FIELDNAM: Spacecraft GSM position labels + FORMAT: A8 + UNITS: " " + VAR_TYPE: metadata + +sc_GSM_velocity_labels: + CATDESC: Spacecraft velocity labels in GSM coordinates + FIELDNAM: Spacecraft GSM velocity labels + FORMAT: A8 + UNITS: " " + VAR_TYPE: metadata + +sc_GSE_position_labels: + CATDESC: Spacecraft position labels in GSE coordinates + FIELDNAM: Spacecraft GSE position labels + FORMAT: A8 + UNITS: " " + VAR_TYPE: metadata + +sc_GSE_velocity_labels: + CATDESC: Spacecraft velocity labels in GSE coordinates + FIELDNAM: Spacecraft GSE velocity labels + FORMAT: A8 + UNITS: " " + VAR_TYPE: metadata + +codice_hi_energy_center: + CATDESC: CoDICE-Hi proton energy bin (MeV) + DELTA_MINUS_VAR: codice_hi_energy_minus + DELTA_PLUS_VAR: codice_hi_energy_plus + FIELDNAM: CoDICE-Hi proton energy bin + FILLVAL: -1.0e31 + FORMAT: F12.6 + LABLAXIS: Proton energy bin + UNITS: "MeV" + VALIDMAX: 20.0 + VALIDMIN: 0.0 + VAR_TYPE: support_data + dtype: float32 + +codice_hi_energy_minus: + CATDESC: CoDICE-Hi proton energy bin lower delta (MeV) + FIELDNAM: CoDICE-Hi proton energy bin lower delta + FILLVAL: -1.0e31 + FORMAT: F12.6 + LABLAXIS: Energy lower delta + UNITS: "MeV" + VALIDMAX: 20.0 + VALIDMIN: 0.0 + VAR_TYPE: support_data + dtype: float32 + +codice_hi_energy_plus: + CATDESC: CoDICE-Hi proton energy bin upper delta (MeV) + FIELDNAM: CoDICE-Hi proton energy bin upper delta + FILLVAL: -1.0e31 + FORMAT: F12.6 + LABLAXIS: Energy upper delta + UNITS: "MeV" + VALIDMAX: 20.0 + VALIDMIN: 0.0 + VAR_TYPE: support_data + dtype: float32 + +codice_hi_polar: + CATDESC: Polar Angle + FIELDNAM: Polar Angle + FILLVAL: -1.0e31 + FORMAT: F12.6 + LABLAXIS: Polar Angle + SCALETYP: linear + UNITS: degrees + VALIDMAX: 180.0 + VALIDMIN: 0.0 + VAR_TYPE: support_data + dtype: float32 + +codice_hi_polar_labels: + CATDESC: CoDICE-Hi polar labels + FIELDNAM: CoDICE-Hi polar labels + FORMAT: A12 + UNITS: " " + VAR_TYPE: metadata + +codice_hi_spin_sector: + CATDESC: CoDICE-Hi spin sector index + FIELDNAM: CoDICE-Hi spin sector index + FORMAT: I2 + LABLAXIS: Spin sector index + UNITS: " " + VALIDMAX: 3 + VALIDMIN: 0 + VAR_TYPE: support_data + dtype: int32 + +codice_hi_spin_sector_labels: + CATDESC: CoDICE-Hi spin sector labels + FIELDNAM: CoDICE-Hi spin sector labels + FORMAT: A8 + UNITS: " " + VAR_TYPE: metadata + +swe_electron_energy: + CATDESC: SWE electron channels (nominal central energies) + FIELDNAM: SWE electron channels + FILLVAL: -1.0e31 + FORMAT: F6.1 + LABLAXIS: SWE electron channels + UNITS: "eV" + VALIDMAX: 2000.0 + VALIDMIN: 0.0 + VAR_TYPE: support_data + dtype: float32 + +# Variables codice_hi_h: <<: *default_float32 - CATDESC: H intensities in 15 energy ranges and binned into 4 azimuths and 4 spin angle bins - FIELDNAM: H intensities - LABLAXIS: Diff. Intensity - UNITS: "# / cm2-sr-s- MeV" - VALIDMIN: 0 + CATDESC: Proton flux from CoDICE-Hi in 15 energy bins between 0.02 to 3.62 MeV over 4 spin angles and 4 polar angles + DEPEND_0: codice_hi_epoch + DEPEND_1: codice_hi_energy_center + DEPEND_2: codice_hi_spin_sector + DEPEND_3: codice_hi_polar + DISPLAY_TYPE: no_plot + FIELDNAM: H+ intensity + FORMAT: F11.1 + LABLAXIS: H+ intensity + UNITS: "counts / cm2-sr-s-MeV" VALIDMAX: 100000000.0 - DEPEND_1: codice_hi_h_energy_ranges - DEPEND_2: codice_hi_h_elevation - DEPEND_3: codice_hi_h_spin_angle + VALIDMIN: 0 + VAR_NOTES: Energy ranges (MeV) are 0.0200 to 0.0283, 0.0283 to 0.0400, 0.0400 to 0.0566, 0.0566 to 0.0800, 0.0800 to 0.113, 0.113 to 0.160, 0.160 to 0.226, 0.226 to 0.320, 0.320 to 0.453, 0.453 to 0.640, 0.640 to 0.905, 0.905 to 1.28, 1.28 to 1.81, 1.81 to 2.56, 2.56 to 3.62. codice_lo_c_over_o_abundance: <<: *default_float32 - CATDESC: C/O abundance ratio - FIELDNAM: C/O - LABLAXIS: ratio + CATDESC: C/O elemental abundance ratio from CoDICE-Lo + DEPEND_0: codice_lo_epoch + FIELDNAM: C/O abundance ratio + FORMAT: F16.6 + LABLAXIS: C/O ratio UNITS: " " - VALIDMIN: 0 VALIDMAX: 100000000.0 + VALIDMIN: 0 codice_lo_mg_over_o_abundance: <<: *default_float32 - CATDESC: Mg/O abundance ratio - FIELDNAM: Mg/O - LABLAXIS: ratio + CATDESC: Mg/O elemental abundance ratio from CoDICE-Lo + DEPEND_0: codice_lo_epoch + FIELDNAM: Mg/O abundance ratio + FORMAT: F16.6 + LABLAXIS: Mg/O ratio UNITS: " " - VALIDMIN: 0 VALIDMAX: 100000000.0 + VALIDMIN: 0 codice_lo_fe_over_o_abundance: <<: *default_float32 - CATDESC: Fe/O abundance ratio - FIELDNAM: Fe/O - LABLAXIS: ratio + CATDESC: Fe/O elemental abundance ratio from CoDICE-Lo + DEPEND_0: codice_lo_epoch + FIELDNAM: Fe/O abundance ratio + FORMAT: F16.6 + LABLAXIS: Fe/O ratio UNITS: " " - VALIDMIN: 0 VALIDMAX: 100000000.0 + VALIDMIN: 0 -codice_lo_c_plus_6_over_c_plus_5_ratio: +codice_lo_c_plus_6_over_c_plus_5: <<: *default_float32 - CATDESC: C+6/C+5 charge state ratio - FIELDNAM: C+6/C+5 - LABLAXIS: ratio + CATDESC: C+6/C+5 charge state ratio from CoDICE-Lo + DEPEND_0: codice_lo_epoch + FIELDNAM: C+6/C+5 charge state ratio + FORMAT: F16.6 + LABLAXIS: C+6/C+5 ratio UNITS: " " - VALIDMIN: 0 VALIDMAX: 100000000.0 + VALIDMIN: 0 -codice_lo_o_plus_7_over_o_plus_6_ratio: +codice_lo_o_plus_7_over_o_plus_6: <<: *default_float32 - CATDESC: O+7/O+6 charge state ratio - FIELDNAM: O+7/O+6 - LABLAXIS: ratio + CATDESC: O+7/O+6 charge state ratio from CoDICE-Lo + DEPEND_0: codice_lo_epoch + FIELDNAM: O7+/O6+ charge state ratio + FORMAT: F16.6 + LABLAXIS: O7+/O6+ ratio UNITS: " " - VALIDMIN: 0 VALIDMAX: 100000000.0 + VALIDMIN: 0 -codice_lo_fe_low_over_fe_high_ratio: +codice_lo_fe_low_over_fe_high: <<: *default_float32 - CATDESC: Fe low/Fe high charge state ratio - FIELDNAM: Fe low/Fe high - LABLAXIS: ratio + CATDESC: Fe low/Fe high charge state ratio from CoDICE-Lo + DEPEND_0: codice_lo_epoch + FIELDNAM: Fe low/high charge state ratio + FORMAT: F16.6 + LABLAXIS: Fe low/high ratio UNITS: " " - VALIDMIN: 0 VALIDMAX: 100000000.0 + VALIDMIN: 0 hit_e_a_side_low_en: - <<: *default_uint32 - CATDESC: Low energy (~300 keV) electrons (A-side) - FIELDNAM: Low energy (~300 keV) electrons (A-side) - LABLAXIS: hit_e_a_side_low_en + <<: *default_float32 + CATDESC: Count rates from HIT for electrons above 0.5 MeV, A-side aperture (anti-sunward) look direction + DEPEND_0: hit_epoch + FIELDNAM: Low energy electron count rate (A-side) + LABLAXIS: A-side e- >0.5 MeV UNITS: counts + VALIDMAX: 1000000000.0 + VALIDMIN: 0 + VAR_NOTES: A-side indicates the HIT aperture that is nominally looking in the anti-sunward direction. B-side indicates the aperture looking nominally in the sunward direction. hit_e_a_side_med_en: - <<: *default_uint32 - CATDESC: Medium energy (~3 MeV) electrons (A-side) - FIELDNAM: Medium energy (~3 MeV) electrons (A-side) - LABLAXIS: hit_e_a_side_med_en + <<: *default_float32 + CATDESC: Counts from HIT for electrons below 1 MeV, A-side aperture (sunward directed particles) look direction + DEPEND_0: hit_epoch + FIELDNAM: Medium energy electron count rate (A-side) + FORMAT: F17.6 + LABLAXIS: A-side e- <1 MeV UNITS: counts + VALIDMAX: 1000000000.0 + VALIDMIN: 0 + VAR_NOTES: A-side indicates the HIT aperture that is nominally looking in the anti-sunward direction. B-side indicates the aperture looking nominally in the sunward direction. hit_e_a_side_high_en: - <<: *default_uint32 - CATDESC: High energy (>3 MeV) electrons (A-side) - FIELDNAM: High energy (>3 MeV) electrons (A-side) - LABLAXIS: hit_e_a_side_high_en + <<: *default_float32 + CATDESC: High energy (>3 MeV) electron count rate (A-side, anti-sunward) + DEPEND_0: hit_epoch + FIELDNAM: High energy electron count rate (A-side) + LABLAXIS: A-side e- >3 MeV UNITS: counts + VALIDMAX: 1000000000.0 + VALIDMIN: 0 + VAR_NOTES: A-side indicates the HIT aperture that is nominally looking in the anti-sunward direction. B-side indicates the aperture looking nominally in the sunward direction. hit_e_b_side_low_en: - <<: *default_uint32 - CATDESC: Low energy (~300 keV) electrons (B-side) - FIELDNAM: Low energy (~300 keV) electrons (B-side) - LABLAXIS: hit_e_b_side_low_en + <<: *default_float32 + CATDESC: Count rates from HIT for electrons above 0.5 MeV, B-side aperture (sunward) look direction + DEPEND_0: hit_epoch + FIELDNAM: Low energy electron count rate (B-side) + LABLAXIS: B-side e- >0.5 MeV UNITS: counts + VALIDMAX: 1000000000.0 + VALIDMIN: 0 + VAR_NOTES: A-side indicates the HIT aperture that is nominally looking in the anti-sunward direction. B-side indicates the aperture looking nominally in the sunward direction. hit_e_b_side_med_en: - <<: *default_uint32 - CATDESC: Medium energy (~3 MeV) electrons (B-side) - FIELDNAM: Medium energy (~3 MeV) electrons (B-side) - LABLAXIS: hit_e_b_side_med_en + <<: *default_float32 + CATDESC: Counts from HIT for electrons below 1 MeV, B-side aperture (anti-sunward directed particles) look direction + DEPEND_0: hit_epoch + FIELDNAM: Medium energy electron count rate (B-side) + FORMAT: F17.6 + LABLAXIS: B-side e- <1 MeV UNITS: counts + VALIDMAX: 1000000000.0 + VALIDMIN: 0 + VAR_NOTES: A-side indicates the HIT aperture that is nominally looking in the anti-sunward direction. B-side indicates the aperture looking nominally in the sunward direction. hit_e_b_side_high_en: - <<: *default_uint32 - CATDESC: High energy (>3 MeV) electrons (B-side) - FIELDNAM: High energy (>3 MeV) electrons (B-side) - LABLAXIS: hit_e_b_side_high_en + <<: *default_float32 + CATDESC: High energy (>3 MeV) electron count rate (B-side, sunward) + DEPEND_0: hit_epoch + FIELDNAM: High energy electron count rate (B-side) + LABLAXIS: B-side e- >3 MeV + UNITS: counts + VALIDMAX: 1000000000.0 + VALIDMIN: 0 + VAR_NOTES: A-side indicates the HIT aperture that is nominally looking in the anti-sunward direction. B-side indicates the aperture looking nominally in the sunward direction. + +hit_h_omni_low_en: + <<: *default_float32 + CATDESC: Counts from HIT for protons between 6 to 8 MeV, omnidirectional + DEPEND_0: hit_epoch + FIELDNAM: Proton count rate 6 to 8 MeV (omni) + FORMAT: F17.6 + LABLAXIS: Omni H+ 6 to 8 MeV UNITS: counts + VALIDMAX: 1000000000.0 + VALIDMIN: 0 + VAR_NOTES: Omni indicates the sum of the number of particles divided by the area of the full sky. hit_h_omni_med_en: - <<: *default_uint32 - CATDESC: Medium energy (12–70 MeV) protons (Omnidirectional) - FIELDNAM: Medium energy (12–70 MeV) protons (Omnidirectional) - LABLAXIS: hit_h_omni_med_en + <<: *default_float32 + CATDESC: Counts from HIT for protons between 12 to 15 MeV, omnidirectional + DEPEND_0: hit_epoch + FIELDNAM: Proton count rate 12 to 15 MeV (omni) + FORMAT: F17.6 + LABLAXIS: Omni H+ 12 to 15 MeV UNITS: counts + VALIDMAX: 1000000000.0 + VALIDMIN: 0 + VAR_NOTES: Omni indicates the sum of the number of particles divided by the area of the full sky. hit_h_a_side_high_en: - <<: *default_uint32 - CATDESC: High energy (>70 MeV) protons (A-side) - FIELDNAM: High energy (>70 MeV) protons (A-side) - LABLAXIS: hit_h_a_side_high_en + <<: *default_float32 + CATDESC: High energy (>70 MeV) proton count rate (A-side, anti-sunward) + DEPEND_0: hit_epoch + FIELDNAM: Proton count rate >70 MeV (A-side) + LABLAXIS: A-side H >70 MeV UNITS: counts + VALIDMAX: 1000000000.0 + VALIDMIN: 0 + VAR_NOTES: A-side indicates the HIT aperture that is nominally looking in the anti-sunward direction. B-side indicates the aperture looking nominally in the sunward direction. hit_h_b_side_high_en: - <<: *default_uint32 - CATDESC: High energy (>70 MeV) protons (B-side) - FIELDNAM: High energy (>70 MeV) protons (B-side) - LABLAXIS: hit_h_b_side_high_en + <<: *default_float32 + CATDESC: High energy (>70 MeV) proton count rate (B-side, sunward) + DEPEND_0: hit_epoch + FIELDNAM: Proton count rate >70 MeV (B-side) + LABLAXIS: B-side H >70 MeV UNITS: counts + VALIDMAX: 1000000000.0 + VALIDMIN: 0 + VAR_NOTES: A-side indicates the HIT aperture that is nominally looking in the anti-sunward direction. B-side indicates the aperture looking nominally in the sunward direction. hit_he_omni_low_en: - <<: *default_uint32 - CATDESC: Low energy (6–8 MeV/nuc) He (Omnidirectional) - FIELDNAM: Low energy (6–8 MeV/nuc) He (Omnidirectional) - LABLAXIS: hit_he_omni_low_en + <<: *default_float32 + CATDESC: Counts from HIT for He4 between 6 to 8 MeV/nuc, omnidirectional + DEPEND_0: hit_epoch + FIELDNAM: Helium count rate 6 to 8 MeV/nuc (omni) + FORMAT: F17.6 + LABLAXIS: Omni He 6 to 8 MeV/nuc UNITS: counts + VALIDMAX: 1000000000.0 + VALIDMIN: 0 + VAR_NOTES: Omni indicates the sum of the number of particles divided by the area of the full sky. hit_he_omni_high_en: - <<: *default_uint32 - CATDESC: High energy (15–70 MeV/nuc) He (Omnidirectional) - FIELDNAM: High energy (15–70 MeV/nuc) He (Omnidirectional) - LABLAXIS: hit_he_omni_high_en - UNITS: counts - -mag_epoch: <<: *default_float32 - CATDESC: MAG instrument epoch - FIELDNAM: mag_epoch - LABLAXIS: mag_epoch - UNITS: ns - VALIDMIN: 0.0 - VALIDMAX: 9223372036854775807 + CATDESC: Counts from HIT for He4 between 15 to 70 MeV/nuc, omnidirectional + DEPEND_0: hit_epoch + FIELDNAM: Helium count rate 15 to 70 MeV/nuc (omni) + FORMAT: F17.6 + LABLAXIS: Omni He 15 to 70 MeV/nuc + UNITS: counts + VALIDMAX: 1000000000.0 + VALIDMIN: 0 + VAR_NOTES: Omni indicates the sum of the number of particles divided by the area of the full sky. -mag_B_GSE: +mag_B_magnitude: <<: *default_float32 - CATDESC: Magnetic field vector in GSE coordinates - FIELDNAM: mag_B_GSE - LABL_PTR_1: component + CATDESC: Magnitude of the magnetic field vector from MAG + DEPEND_0: mag_epoch + FIELDNAM: B vector magnitude + LABLAXIS: B Magnitude UNITS: nT - DEPEND_1: component - VALIDMIN: -65000 - VALIDMAX: 65000 + VALIDMAX: 65000.0 + VALIDMIN: 0.0 -mag_B_GSM: +mag_theta_B_GSE: <<: *default_float32 - CATDESC: Magnetic field vector in GSM coordinates - FIELDNAM: mag_B_GSM - LABL_PTR_1: component - UNITS: nT - DEPEND_1: component - VALIDMIN: -65000 - VALIDMAX: 65000 + CATDESC: Elevation (theta) angle of the magnetic field in GSE coordinates from MAG + DEPEND_0: mag_epoch + FIELDNAM: B elevation angle in GSE coordinates + LABLAXIS: B elevation (GSE) + UNITS: degrees + VALIDMAX: 90.0 + VALIDMIN: -90.0 -mag_B_RTN: +mag_phi_B_GSE: <<: *default_float32 - CATDESC: Magnetic field vector in RTN coordinates - FIELDNAM: mag_B_RTN - LABL_PTR_1: RTN_component - UNITS: nT - DEPEND_1: RTN_component - VALIDMIN: -65000 - VALIDMAX: 65000 + CATDESC: Azimuth (phi) angle of the magnetic field in GSE coordinates from MAG + DEPEND_0: mag_epoch + FIELDNAM: B azimuth angle in GSE coordinates + LABLAXIS: B azimuth (GSE) + UNITS: degrees + VALIDMAX: 360.0 + VALIDMIN: 0.0 -mag_B_magnitude: +mag_theta_B_GSM: <<: *default_float32 - CATDESC: Magnitude of the magnetic field vector - FIELDNAM: mag_B_magnitude - LABLAXIS: "|B|" - UNITS: nT - VALIDMIN: 0 - VALIDMAX: 65000 + CATDESC: Elevation (theta) angle of the magnetic field in GSM coordinates from MAG + DEPEND_0: mag_epoch + FIELDNAM: B elevation angle in GSM coordinates + LABLAXIS: B elevation (GSM) + UNITS: degrees + VALIDMAX: 90.0 + VALIDMIN: -90.0 mag_phi_B_GSM: <<: *default_float32 - CATDESC: Azimuth angle (Ο†) of the magnetic field in GSM coordinates - FIELDNAM: mag_phi_B_GSM - LABLAXIS: mag_phi_B_GSM + CATDESC: Azimuth (phi) angle of the magnetic field in GSM coordinates from MAG + DEPEND_0: mag_epoch + FIELDNAM: B azimuth angle in GSM coordinates + LABLAXIS: B azimuth (GSM) UNITS: degrees - VALIDMIN: 0 - VALIDMAX: 360 + VALIDMAX: 360.0 + VALIDMIN: 0.0 -mag_theta_B_GSM: +mag_B_GSE: <<: *default_float32 - CATDESC: Elevation angle (ΞΈ) of the magnetic field in GSM coordinates - FIELDNAM: mag_theta_B_GSM - LABLAXIS: mag_theta_B_GSM - UNITS: degrees - VALIDMIN: -90 - VALIDMAX: 90 + CATDESC: Magnetic field vector in GSE coordinates from MAG + DEPEND_0: mag_epoch + FIELDNAM: B vector in GSE coordinates + FORMAT: F13.6 + LABLAXIS: B (GSE) + LABL_PTR_1: B_GSE_labels + UNITS: nT + VALIDMAX: 65000.0 + VALIDMIN: -65000.0 -mag_phi_B_GSE: +mag_B_GSM: <<: *default_float32 - CATDESC: Azimuth angle (Ο†) of the magnetic field in GSE coordinates - FIELDNAM: mag_phi_B_GSE - LABLAXIS: mag_phi_B_GSE - UNITS: degrees - VALIDMIN: 0 - VALIDMAX: 360 + CATDESC: Magnetic field vector in GSM coordinates from MAG + DEPEND_0: mag_epoch + FIELDNAM: B vector in GSM coordinates + FORMAT: F13.6 + LABLAXIS: B (GSM) + LABL_PTR_1: B_GSM_labels + UNITS: nT + VALIDMAX: 65000.0 + VALIDMIN: -65000.0 -mag_theta_B_GSE: +mag_B_RTN: <<: *default_float32 - CATDESC: Elevation angle (ΞΈ) of the magnetic field in GSE coordinates - FIELDNAM: mag_theta_B_GSE - LABLAXIS: mag_theta_B_GSE - UNITS: degrees - VALIDMIN: -90 - VALIDMAX: 90 + CATDESC: Magnetic field vector in RTN coordinates from MAG + DEPEND_0: mag_epoch + FIELDNAM: B vector in RTN coordinates + FORMAT: F13.6 + LABLAXIS: B (RTN) + LABL_PTR_1: B_RTN_labels + UNITS: nT + VALIDMAX: 65000.0 + VALIDMIN: -65000.0 swapi_pseudo_proton_density: <<: *default_float32 - CATDESC: Pseudo density of solar wind protons - FIELDNAM: swapi_pseudo_proton_density - LABLAXIS: swapi_pseudo_proton_density + CATDESC: Pseudo solar wind proton number density from SWAPI + DEPEND_0: swapi_epoch + FIELDNAM: SW proton pseudo density + LABLAXIS: SW p pseudo N UNITS: 1/cm^3 - VALIDMIN: 0.0 VALIDMAX: 1000.0 + VALIDMIN: 0.0 + VAR_NOTES: The pseudo density is derived using a simplified analytical model of solar wind proton density. swapi_pseudo_proton_speed: <<: *default_float32 - CATDESC: Pseudo speed of solar wind protons in solar inertial frame - FIELDNAM: swapi_pseudo_proton_speed - LABLAXIS: swapi_pseudo_proton_speed + CATDESC: Pseudo solar wind proton speed from SWAPI + DEPEND_0: swapi_epoch + FIELDNAM: SW proton pseudo V in solar inertial frame + LABLAXIS: SW p pseudo V UNITS: km/sec - VALIDMIN: 0.0 VALIDMAX: 10000.0 + VALIDMIN: 0.0 + VAR_NOTES: The pseudo speed is derived using a simplified analytical model of solar wind proton speed. swapi_pseudo_proton_temperature: <<: *default_float32 - CATDESC: Pseudo temperature of solar wind protons in plasma frame - FIELDNAM: swapi_pseudo_proton_temperature - LABLAXIS: swapi_pseudo_proton_temperature + CATDESC: Pseudo solar wind proton temperature from SWAPI + DEPEND_0: swapi_epoch + FIELDNAM: SW proton pseudo temperature + FORMAT: F15.6 + LABLAXIS: SW p pseudo T UNITS: Kelvin - VALIDMIN: 0.0 VALIDMAX: 50000000.0 + VALIDMIN: 0.0 + VAR_NOTES: The pseudo temperature is derived using a simplified analytical model of solar wind proton speed. # SWE Normalized Counts swe_normalized_counts: - <<: *default_uint32 - CATDESC: Normalized electron counts - FIELDNAM: swe_normalized_counts - LABLAXIS: swe_normalized_counts - UNITS: Normalized counts + <<: *default_int64 + CATDESC: Normalized electron counts from SWE in 8 energy bins between 100.4 to 1101 eV + DEPEND_0: swe_epoch + DEPEND_1: swe_electron_energy + DISPLAY_TYPE: stack_plot + FIELDNAM: Normalized electron counts + LABLAXIS: Electron counts + SCALETYP: log + UNITS: normalized counts + VALIDMAX: 5000000000000 VALIDMIN: 0 - VALIDMAX: 500000 - DEPEND_1: esa_step + VAR_NOTES: The nominal central energies for the 8 i-ALiRT channels are 100.4, 140, 194, 270, 376, 523, 727, and 1011 eV. swe_counterstreaming_electrons: - <<: *default_uint8 - CATDESC: Counterstreaming electrons - FIELDNAM: swe_counterstreaming_electrons - LABLAXIS: swe_counterstreaming_electrons - UNITS: "" - VALIDMIN: 0 - VALIDMAX: 1 + <<: *default_uint8 + CATDESC: Binary value from SWE indicating the presence (1) or absence (0) of counterstreaming electron flow + DEPEND_0: swe_epoch + FIELDNAM: Counterstreaming e- (1=counterstreaming) + LABLAXIS: Counterstreaming e- + UNITS: "1=counterstreaming" + VALIDMAX: 1 + VALIDMIN: 0 + VAR_NOTES: A value of 1 indicates that counterstreaming electrons were observed, a value of 0 indicates unidirectional electron flow. + +sc_position_GSE: + <<: *default_float32 + CATDESC: Spacecraft position vector in GSE coordinates + FIELDNAM: Spacecraft position in GSE + FORMAT: F15.6 + LABLAXIS: SC position (GSE) + LABL_PTR_1: sc_GSE_position_labels + UNITS: km + VALIDMAX: 3000000.0 + VALIDMIN: -3000000.0 + +sc_velocity_GSE: + <<: *default_float32 + CATDESC: Spacecraft velocity vector in GSE coordinates + FIELDNAM: Spacecraft velocity in GSE + LABLAXIS: SC velocity (GSE) + LABL_PTR_1: sc_GSE_velocity_labels + UNITS: km/s + VALIDMAX: 1000.0 + VALIDMIN: -1000.0 + +sc_position_GSM: + <<: *default_float32 + CATDESC: Spacecraft position in GSM coordinates + FIELDNAM: Spacecraft position in GSM coordinates + FORMAT: F15.6 + LABLAXIS: SC position (GSM) + LABL_PTR_1: sc_GSM_position_labels + UNITS: km + VALIDMAX: 3000000.0 + VALIDMIN: -3000000.0 + +sc_velocity_GSM: + <<: *default_float32 + CATDESC: Spacecraft velocity vector in GSM coordinates + FIELDNAM: Spacecraft velocity in GSM + LABLAXIS: SC velocity (GSM) + LABL_PTR_1: sc_GSM_velocity_labels + UNITS: km/s + VALIDMAX: 1000.0 + VALIDMIN: -1000.0 diff --git a/imap_processing/cdf/config/imap_idex_global_cdf_attrs.yaml b/imap_processing/cdf/config/imap_idex_global_cdf_attrs.yaml index 706bad945f..14cdb25c0f 100644 --- a/imap_processing/cdf/config/imap_idex_global_cdf_attrs.yaml +++ b/imap_processing/cdf/config/imap_idex_global_cdf_attrs.yaml @@ -1,5 +1,6 @@ instrument_base: &instrument_base Descriptor: IDEX>Interstellar Dust Experiment + Instrument_type: Particles (space) TEXT: > The Interstellar Dust Experiment (IDEX) is a time-of-flight (TOF) dust impact ionization mass spectrometer on the IMAP mission that @@ -7,7 +8,6 @@ instrument_base: &instrument_base of interstellar dust and interplanetary dust particles. Each record contains the data from a single dust impact. See https://imap.princeton.edu/instruments/idex for more details. - Instrument_type: Particles (space) imap_idex_l1a_sci: <<: *instrument_base @@ -15,11 +15,11 @@ imap_idex_l1a_sci: Logical_source: imap_idex_l1a_sci-1week Logical_source_description: IMAP Mission IDEX Instrument Level-1A Weekly Data. -imap_idex_l1a_evt: - <<: *instrument_base - Data_type: L1A_EVT>Level-1A Event Message Data - Logical_source: imap_idex_l1a_evt - Logical_source_description: IMAP Mission IDEX Instrument Level-1A Event Message Data. +imap_idex_l1a_msg: + <<: *instrument_base + Data_type: L1A_MSG>Level-1A Event Message Data + Logical_source: imap_idex_l1a_msg + Logical_source_description: IMAP Mission IDEX Instrument Level-1A Event Message Data. imap_idex_l1a_catlst: <<: *instrument_base @@ -33,11 +33,11 @@ imap_idex_l1b_sci: Logical_source: imap_idex_l1b_sci-1week Logical_source_description: IMAP Mission IDEX Instrument Level-1B Weekly Data. -imap_idex_l1b_evt: - <<: *instrument_base - Data_type: L1B_EVT>Level-1B Event Message Data - Logical_source: imap_idex_l1b_evt - Logical_source_description: IMAP Mission IDEX Instrument Level-1B Event Message Data. +imap_idex_l1b_msg: + <<: *instrument_base + Data_type: L1B_MSG>Level-1B Event Message Data + Logical_source: imap_idex_l1b_msg + Logical_source_description: IMAP Mission IDEX Instrument Level-1B Event Message Data. imap_idex_l1b_catlst: <<: *instrument_base @@ -58,16 +58,9 @@ imap_idex_l2b_sci: Logical_source: imap_idex_l2b_sci-1mo Logical_source_description: IMAP Mission IDEX Instrument Level-2B Monthly Data -imap_idex_l2c_sci-healpix: - <<: *instrument_base - Data_level: 2C - Data_type: L2C_HEALPIX-MAP-1MO>Level-2C HEALPIX Map Monthly Data - Logical_source: imap_idex_l2c_healpix-map-1mo - Logical_source_description: IMAP Mission IDEX Instrument Level-2C Monthly Data Healpix - imap_idex_l2c_sci-rectangular: <<: *instrument_base Data_level: 2C Data_type: L2C_RECTANGULAR-MAP-1MO>Level-2C Rectangular Map Monthly Data Logical_source: imap_idex_l2c_rectangular-map-1mo - Logical_source_description: IMAP Mission IDEX Instrument Level-2C Monthly Data Rectangular \ No newline at end of file + Logical_source_description: IMAP Mission IDEX Instrument Level-2C Rectangular Map Monthly Data diff --git a/imap_processing/cdf/config/imap_idex_l1a_variable_attrs.yaml b/imap_processing/cdf/config/imap_idex_l1a_variable_attrs.yaml index 8765d2e6a7..62002646ea 100644 --- a/imap_processing/cdf/config/imap_idex_l1a_variable_attrs.yaml +++ b/imap_processing/cdf/config/imap_idex_l1a_variable_attrs.yaml @@ -13,25 +13,25 @@ sample_rate_max: &sample_rate_max 130 # <=== Base Attributes ===> string_base_attrs: &string_base - DEPEND_0: epoch CATDESC: " " + DEPEND_0: epoch FIELDNAM: " " FILLVAL: " " FORMAT: A3 VAR_TYPE: metadata l1a_data_base: &l1a_data_base - VALIDMIN: *data_min - VALIDMAX: *data_max - DISPLAY_TYPE: spectrogram - DEPEND_0: epoch - FORMAT: I12 - UNITS: dN - VAR_TYPE: data CATDESC: "" + DEPEND_0: epoch + DISPLAY_TYPE: spectrogram FIELDNAM: "" FILLVAL: *int_fillval + FORMAT: I12 LABLAXIS: "" + UNITS: dN + VALIDMAX: *data_max + VALIDMIN: *data_min + VAR_TYPE: data l1a_tof_base: &l1a_tof_base <<: *l1a_data_base @@ -44,75 +44,76 @@ l1a_target_base: &l1a_target_base LABL_PTR_1: time_low_sample_rate_label sample_rate_base: &sample_rate_base - DISPLAY_TYPE: no_plot CATDESC: "" + DEPEND_0: epoch + DISPLAY_TYPE: no_plot FIELDNAM: "" FILLVAL: -1.0e+31 - VALIDMIN: *sample_rate_min - VALIDMAX: *sample_rate_max - DEPEND_0: epoch FORMAT: F64.5 - SCALETYP: linear LABLAXIS: Time + SCALETYP: linear UNITS: microseconds - VAR_TYPE: data + VALIDMAX: *sample_rate_max + VALIDMIN: *sample_rate_min VAR_NOTES: The number of microseconds since the event. 0 is the start of data collection, negative numbers represent data collected prior to a dust event + VAR_TYPE: data trigger_base: &trigger_base - VALIDMIN: 0 - VALIDMAX: *max_uint32 + CATDESC: "" DEPEND_0: epoch DISPLAY_TYPE: no_plot - CATDESC: "" FIELDNAM: "" - VAR_TYPE: support_data FILLVAL: *int_fillval - LABLAXIS: "" FORMAT: I10 + LABLAXIS: "" UNITS: " " + VALIDMAX: *max_uint32 + VALIDMIN: 0 + VAR_TYPE: support_data # <=== LABL_PTR_i Attributes ===> time_high_sample_rate_label: CATDESC: High sample rate time steps for a dust event. + DEPEND_1: time_high_sample_rate_index + DICT_KEY: SPASE>Support>SupportQuantity:Other FIELDNAM: High Sample Rate Time FORMAT: A5 VAR_TYPE: metadata - DEPEND_1: time_high_sample_rate_index - DICT_KEY: SPASE>Support>SupportQuantity:Other time_low_sample_rate_label: CATDESC: Low sample rate time steps for a dust event. + DEPEND_1: time_low_sample_rate_index + DICT_KEY: SPASE>Support>SupportQuantity:Other FIELDNAM: Low Sample Rate Time FORMAT: A5 VAR_TYPE: metadata - DEPEND_1: time_low_sample_rate_index - DICT_KEY: SPASE>Support>SupportQuantity:Other # <=== Instrument Setting Attributes ===> low_sample_rate_attrs: <<: *sample_rate_base CATDESC: Low sample rate time steps for a dust event. + DEPEND_1: time_low_sample_rate_index + DICT_KEY: SPASE>Support>SupportQuantity:Temporal FIELDNAM: Low Sample Rate Time VAR_NOTES: The low sample rate in microseconds. Steps are approximately 1/4.025 microseconds in duration. Used by the Ion_Grid, Target_Low, and Target_High variables. - DEPEND_1: time_low_sample_rate_index - DICT_KEY: SPASE>Support>SupportQuantity:Temporal high_sample_rate_attrs: <<: *sample_rate_base CATDESC: High sample rate time steps for a dust event. + DEPEND_1: time_high_sample_rate_index + DICT_KEY: SPASE>Support>SupportQuantity:Temporal FIELDNAM: High Sample Rate Time VAR_NOTES: The high sample rate in microseconds. Steps are approximately 1/260 microseconds in duration. Used by the TOF_High, TOF_Mid, and TOF_Low variables. - DEPEND_1: time_high_sample_rate_index - DICT_KEY: SPASE>Support>SupportQuantity:Temporal time_low_sample_rate_index: CATDESC: Low sampling rate time index + DICT_KEY: SPASE>Support>SupportQuantity:Other FIELDNAM: Low sample rate FILLVAL: *int_fillval FORMAT: I3 @@ -122,10 +123,10 @@ time_low_sample_rate_index: VALIDMAX: 511 VALIDMIN: 0 VAR_TYPE: support_data - DICT_KEY: SPASE>Support>SupportQuantity:Other time_high_sample_rate_index: CATDESC: High sampling rate time index + DICT_KEY: SPASE>Support>SupportQuantity:Other FIELDNAM: High sample rate FILLVAL: *int_fillval FORMAT: I4 @@ -135,7 +136,6 @@ time_high_sample_rate_index: VALIDMAX: 8188 VALIDMIN: 0 VAR_TYPE: support_data - DICT_KEY: SPASE>Support>SupportQuantity:Other tof_high_attrs: <<: *l1a_tof_base @@ -157,9 +157,9 @@ tof_mid_attrs: tof_low_attrs: <<: *l1a_tof_base - FILLVAL: *int_fillval CATDESC: Time of flight waveform on the low-gain channel FIELDNAM: Low Gain Time of Flight + FILLVAL: *int_fillval LABLAXIS: TOF Low Ampl. VAR_NOTES: Low gain channel of the time-of-flight signal. Sampled at 260 Megasamples per second, with a 10-bit resolution. @@ -197,6 +197,7 @@ shcoarse: <<: *trigger_base CATDESC: Time of packet generation (not data acquisition), as integer seconds since epoch FIELDNAM: Secondary header coarse time + FILLVAL: 4294967295 LABLAXIS: Packet Generation Time (Coarse) UNITS: seconds @@ -204,17 +205,41 @@ shfine: <<: *trigger_base CATDESC: Time of packet generation, each DN represents 20usec within current second FIELDNAM: Secondary header fine time - VALIDMAX: *max_uint16 + FILLVAL: 65535 LABLAXIS: Packet Generation Time (Fine) + UNITS: microseconds + VALIDMAX: *max_uint16 + +elsec_evtpkt: + <<: *trigger_base + CATDESC: Time of event message, as integer seconds. + FIELDNAM: Event message coarse time + FILLVAL: 4294967295 + LABLAXIS: Event Message Time (Coarse) UNITS: seconds +elssec_evtpkt: + <<: *trigger_base + CATDESC: Time of event message, each DN represents 20usec within current second. + FIELDNAM: Event message fine time + FILLVAL: 65535 + LABLAXIS: Event Message Time (Fine) + UNITS: microseconds + VALIDMAX: *max_uint16 + +messages: + <<: *string_base + CATDESC: Rendered IDEX event message text + FIELDNAM: Event message text + FORMAT: A160 + checksum: <<: *trigger_base CATDESC: CRC 16 Checksum FIELDNAM: Checksum UNITS: " " -idx__sci0aid: +aid: <<: *trigger_base CATDESC: Accountability identifier for this event FIELDNAM: Accountability identifier @@ -236,8 +261,8 @@ idx__sci0spare1: <<: *trigger_base CATDESC: Spare for alignment FIELDNAM: Sci spare 1 - VALIDMAX: 8191 LABLAXIS: Sci Spare 1 + VALIDMAX: 8191 idx__sci0pack: <<: *string_base @@ -258,36 +283,36 @@ idx__sci0evtnum: <<: *trigger_base CATDESC: Event number FIELDNAM: Event number - VALIDMAX: *max_uint16 LABLAXIS: Event Number + VALIDMAX: *max_uint16 idx__sci0cat: <<: *trigger_base CATDESC: Category assigned to this event (for most recent processing operation) FIELDNAM: Category - VALIDMAX: *max_uint16 LABLAXIS: Category + VALIDMAX: *max_uint16 idx__sci0qual: <<: *trigger_base CATDESC: Quality factor assigned to this category FIELDNAM: Quality factor - VALIDMAX: *max_uint8 LABLAXIS: Quality factor + VALIDMAX: *max_uint8 idx__sci0fragoff: <<: *trigger_base CATDESC: Starting offset for this data when reconstructing data that spans multiple packets (fragmented) FIELDNAM: Fragmentation offset - VALIDMAX: *max_uint16 LABLAXIS: Offset + VALIDMAX: *max_uint16 idx__sci0ver: <<: *trigger_base CATDESC: Science CSC version number for this header FIELDNAM: Version number - VALIDMAX: *max_uint16 LABLAXIS: Version number + VALIDMAX: *max_uint16 idx__sci0time32: <<: *trigger_base @@ -323,64 +348,64 @@ idx__txhdrsp00: <<: *trigger_base CATDESC: Spare for alignment FIELDNAM: Spare 0 - VALIDMAX: *max_uint16 LABLAXIS: Spare 0 + VALIDMAX: *max_uint16 idx__txhdrtimesec1: <<: *trigger_base CATDESC: Trigger time, bits 31:16 of the coarse timestamp (integer seconds since epoch) FIELDNAM: Trigger time - VALIDMAX: *max_uint16 LABLAXIS: Trigger Time + VALIDMAX: *max_uint16 idx__txhdrtimesec2: <<: *trigger_base CATDESC: Trigger time, bits 15:0 of the coarse timestamp (integer seconds since epoch) FIELDNAM: Trigger time - VALIDMAX: *max_uint16 LABLAXIS: Trigger Time + VALIDMAX: *max_uint16 idx__txhdrtimesubs: <<: *trigger_base CATDESC: Trigger time, subseconds field FIELDNAM: Trigger time - VALIDMAX: *max_uint16 LABLAXIS: Trigger time + VALIDMAX: *max_uint16 idx__txhdrsp01: <<: *trigger_base CATDESC: Spare for alignment FIELDNAM: Spare 1 - VALIDMAX: 1 LABLAXIS: Spare 1 + VALIDMAX: 1 idx__txhdrtrigoffset: <<: *trigger_base CATDESC: Trigger offset FIELDNAM: Trigger offset - VALIDMAX: 7 LABLAXIS: Trigger offset + VALIDMAX: 7 idx__txhdrsp02: <<: *trigger_base CATDESC: Spare for alignment FIELDNAM: Spare 2 - VALIDMAX: 1 LABLAXIS: Spare 2 + VALIDMAX: 1 idx__txhdrtrigid: <<: *trigger_base CATDESC: Identifies which channel(s) caused this event to be captured (multiple concurrent triggers are possible) FIELDNAM: Trigger ID - VALIDMAX: 1024 LABLAXIS: Trigger ID + VALIDMAX: 1024 idx__txhdrevtnum: <<: *trigger_base CATDESC: Event number, an incrementing counter to uniquely identify one event in dataset FIELDNAM: Event Number - VALIDMAX: *max_uint16 LABLAXIS: Event Number + VALIDMAX: *max_uint16 idx__txhdrblocks: <<: *trigger_base @@ -428,15 +453,15 @@ idx__txhdrsp03: <<: *trigger_base CATDESC: Spare for alignment FIELDNAM: Spare 3 - VALIDMAX: 1 LABLAXIS: Spare 3 + VALIDMAX: 1 idx__txhdrlsadc: <<: *trigger_base CATDESC: Settings for Low Speed (target) ADC triggering FIELDNAM: Low Speed ADC triggering - VALIDMAX: 16777215 LABLAXIS: ADC Triggering + VALIDMAX: 16777215 idx__txhdrpolstat: <<: *string_base @@ -447,8 +472,8 @@ idx__txhdrsp04: <<: *trigger_base CATDESC: Spare for alignment FIELDNAM: Spare 4 - VALIDMAX: 4194303 LABLAXIS: Spare 4 + VALIDMAX: 4194303 idx__txhdrpolctrl: <<: *string_base @@ -469,22 +494,22 @@ idx__txhdrmgtrigmode: <<: *trigger_base CATDESC: Trigger mode for mid-gain TOF channel FIELDNAM: MG trigger mode - VALIDMAX: 3 LABLAXIS: Trigger Mode + VALIDMAX: 3 idx__txhdrlgtrigmode: <<: *trigger_base CATDESC: Trigger mode for low-gain TOF channel FIELDNAM: LG trigger mode - VALIDMAX: 3 LABLAXIS: Trigger Mode + VALIDMAX: 3 idx__txhdrhgtrigmode: <<: *trigger_base CATDESC: Trigger mode for high-gain TOF channel FIELDNAM: HG trigger mode - VALIDMAX: 3 LABLAXIS: Trigger Mode + VALIDMAX: 3 idx__txhdrsp05: <<: *trigger_base @@ -706,22 +731,22 @@ idx__txhdrfswmajor: <<: *trigger_base CATDESC: Major version number for FSW FIELDNAM: Major version - VALIDMAX: *max_uint8 LABLAXIS: Major Version + VALIDMAX: *max_uint8 idx__txhdrfswminor: <<: *trigger_base CATDESC: Minor version number for FSW FIELDNAM: Minor version - VALIDMAX: *max_uint8 LABLAXIS: Minor Version + VALIDMAX: *max_uint8 idx__txhdrfswpatch: <<: *trigger_base CATDESC: Patch version number for FSW FIELDNAM: Patch version - VALIDMAX: *max_uint16 LABLAXIS: Patch Version + VALIDMAX: *max_uint16 idx__txhdrfswhvstat: <<: *trigger_base @@ -789,12 +814,12 @@ idx__syncsci0pkt: <<: *trigger_base CATDESC: Synchronization marker FIELDNAM: Synchronization marker - VALIDMAX: *max_uint16 LABLAXIS: Synchronization Marker + VALIDMAX: *max_uint16 idx__crcsci0pkt: <<: *trigger_base CATDESC: CRC CCITT-16 FIELDNAM: CRC CCITT-16 - VALIDMAX: *max_uint16 LABLAXIS: CRC CCITT-16 + VALIDMAX: *max_uint16 diff --git a/imap_processing/cdf/config/imap_idex_l1b_variable_attrs.yaml b/imap_processing/cdf/config/imap_idex_l1b_variable_attrs.yaml index 74bce1e800..0739e5b1f0 100644 --- a/imap_processing/cdf/config/imap_idex_l1b_variable_attrs.yaml +++ b/imap_processing/cdf/config/imap_idex_l1b_variable_attrs.yaml @@ -3,30 +3,34 @@ double_fillval: &double_fillval -1.0E31 data_min: &data_min 0 data_max: &data_max 4095 +spice_data_min: &spice_data_min -2.0e7 +spice_data_max: &spice_data_max 2.0e7 + +dead_max: &dead_max 4.065248492307693 # <=== Base Attributes ===> string_base_attrs: &string_base CATDESC: " " + DEPEND_0: epoch + DISPLAY_TYPE: no_plot FIELDNAM: " " FORMAT: A3 LABLAXIS: "none" - VAR_TYPE: metadata - DISPLAY_TYPE: no_plot - DEPEND_0: epoch UNITS: " " + VAR_TYPE: metadata l1b_data_base: &l1b_data_base - VALIDMIN: *data_min - VALIDMAX: *data_max - DISPLAY_TYPE: spectrogram - DEPEND_0: epoch - FORMAT: F12.6 - UNITS: pC - VAR_TYPE: data CATDESC: "" + DEPEND_0: epoch + DISPLAY_TYPE: spectrogram FIELDNAM: "" FILLVAL: *double_fillval + FORMAT: F12.6 LABLAXIS: "" + UNITS: pC + VALIDMAX: *data_max + VALIDMIN: *data_min + VAR_TYPE: data l1b_tof_base: &l1b_tof_base <<: *l1b_data_base @@ -45,20 +49,69 @@ trigger_base: &trigger_base spice_base: &spice_base <<: *l1b_data_base - VAR_TYPE: data DISPLAY_TYPE: time_series - UNITS: Degrees + VALIDMAX: *spice_data_max + VALIDMIN: *spice_data_min + VAR_TYPE: data # <=== Instrument Setting Attributes ===> -trigger_mode: +trigger_mode_lg: <<: *string_base - FIELDNAM: Trigger Mode - CATDESC: Channel and mode that triggered the event + CATDESC: Low Gain Trigger Mode. + FIELDNAM: Low Gain Trigger Mode -trigger_level: +trigger_level_lg: <<: *trigger_base - FIELDNAM: Trigger Level - CATDESC: Threshold signal level that triggered the event + CATDESC: Low Gain Trigger Level threshold. + FIELDNAM: Low Gain Trigger Level + +trigger_mode_mg: + <<: *string_base + CATDESC: Mid Gain Trigger Mode. + FIELDNAM: Mid Gain Trigger Mode + +trigger_level_mg: + <<: *trigger_base + CATDESC: Mid Gain Trigger level threshold. + FIELDNAM: Mid Gain Trigger Level + + +trigger_mode_hg: + <<: *string_base + CATDESC: High Gain Trigger Mode. + FIELDNAM: High Gain Trigger Mode + +trigger_level_hg: + <<: *trigger_base + CATDESC: High Trigger Level threshold. + FIELDNAM: High Trigger Level + +trigger_origin: + <<: *string_base + CATDESC: Trigger Origin of the event. + FIELDNAM: Trigger Origin + +pulser_on: + <<: *trigger_base + CATDESC: Pulser state flag derived from message events (0=off, 1=on). + FIELDNAM: Pulser On + FILLVAL: 255 + FORMAT: I1 + LABLAXIS: Pulser On + VALIDMAX: 1 + VALIDMIN: 0 + VAR_TYPE: support_data + +science_on: + <<: *trigger_base + CATDESC: Science acquisition state flag derived from message events (0=off, 1=on). + FIELDNAM: Science On + FILLVAL: 255 + FORMAT: I1 + LABLAXIS: Science On + VALIDMAX: 1 + VALIDMIN: 0 + VAR_TYPE: support_data tof_high: <<: *l1b_tof_base @@ -117,311 +170,333 @@ ion_grid: detector_voltage: <<: *trigger_base - FIELDNAM: Detector Voltage CATDESC: Voltage reading of Detector on HVPS Board (ADC Channel 0) + FIELDNAM: Detector Voltage LABLAXIS: Voltage UNITS: V sensor_voltage: <<: *trigger_base - FIELDNAM: Sensor Voltage CATDESC: Voltage reading of Detector on HVPS Board (ADC Channel 0) + FIELDNAM: Sensor Voltage LABLAXIS: Voltage UNITS: V target_voltage: <<: *trigger_base - FIELDNAM: Target Voltage CATDESC: Voltage reading of Target on HVPS Board (ADC Channel 2) + FIELDNAM: Target Voltage LABLAXIS: Voltage UNITS: V reflectron_voltage: <<: *trigger_base - FIELDNAM: Reflectron Voltage CATDESC: Voltage reading of Reflectron on HVPS Board (ADC Channel 3) + FIELDNAM: Reflectron Voltage LABLAXIS: Voltage UNITS: V rejection_voltage: <<: *trigger_base - FIELDNAM: Rejection Voltage CATDESC: Voltage reading of Rejection on HVPS Board (ADC Channel 4) + FIELDNAM: Rejection Voltage LABLAXIS: Voltage UNITS: V current_hvps_sensor: <<: *trigger_base - FIELDNAM: Detector Current CATDESC: Reading of Detector current on HVPS Board (ADC Channel 5) + FIELDNAM: Detector Current LABLAXIS: Current UNITS: mA current_1v_pol: <<: *trigger_base - FIELDNAM: 1V POL Current CATDESC: High side current reading on 1.0V bus on Processor Board (ADC channel 0) + FIELDNAM: 1V POL Current LABLAXIS: Current UNITS: mA current_1p9v_pol: <<: *trigger_base - FIELDNAM: 1.9V POL Current CATDESC: High side current reading on 1.9V bus on Processor Board (ADC channel 1) + FIELDNAM: 1.9V POL Current LABLAXIS: Current UNITS: mA temperature_1: <<: *trigger_base - FORMAT: F12.6 - FIELDNAM: ProcBd Temp1 CATDESC: Temperature reading near high speed ADCs on Processor Board (ADC channel 2) + FIELDNAM: ProcBd Temp1 + FORMAT: F12.6 LABLAXIS: Temperature UNITS: C temperature_2: <<: *trigger_base - FORMAT: F12.6 - FIELDNAM: ProcBd Temp2 CATDESC: Temperature reading near center of Processor Board (ADC channel 3) + FIELDNAM: ProcBd Temp2 + FORMAT: F12.6 LABLAXIS: Temperature UNITS: C voltage_1v_bus: <<: *trigger_base - FIELDNAM: 1V Voltage CATDESC: Voltage reading of 1.0V bus on Processor Board (ADC channel 4) + FIELDNAM: 1V Voltage LABLAXIS: Voltage UNITS: V fpga_temperature: <<: *trigger_base - FIELDNAM: FPGA Temp CATDESC: Temperature reading on FPGA on Processor Board (ADC channel 5) + FIELDNAM: FPGA Temp LABLAXIS: Temperature UNITS: C voltage_1p9v_bus: <<: *trigger_base - FIELDNAM: 1.9V Voltage CATDESC: Voltage reading of 1.9V bus on Processor Board (ADC channel 6) + FIELDNAM: 1.9V Voltage LABLAXIS: Voltage UNITS: V voltage_3p3v_bus: <<: *trigger_base - FIELDNAM: 3.3V Voltage CATDESC: Voltage reading of 3.3V bus on Processor Board (ADC channel 7) + FIELDNAM: 3.3V Voltage LABLAXIS: Voltage UNITS: V positive_current_hvps: <<: *trigger_base - FIELDNAM: Sensor IP CATDESC: Reading of HVPS Sensor positive current (ADC Channel 6) + FIELDNAM: Sensor IP LABLAXIS: Current UNITS: mA negative_current_hvps: <<: *trigger_base - FIELDNAM: Sensor IN CATDESC: Reading of HVPS Sensor negative current (ADC Channel 7) + FIELDNAM: Sensor IN LABLAXIS: Current UNITS: mA voltage_3p3_ref: <<: *trigger_base - FIELDNAM: P3.3VREF_HK CATDESC: Positive voltage reading on +3.3V bus Housekeeping reference on LVPS Board (ADC 0 channel 0) + FIELDNAM: P3.3VREF_HK LABLAXIS: Voltage UNITS: V voltage_3p3_op_ref: <<: *trigger_base - FIELDNAM: P3.3VREF_OP CATDESC: Positive voltage reading on +3.3V bus Operations reference on LVPS Board (ADC 0 channel 1) + FIELDNAM: P3.3VREF_OP LABLAXIS: Voltage UNITS: V voltage_neg6v_bus: <<: *trigger_base - FIELDNAM: N6V CATDESC: Negative voltage reading on -6V bus on LVPS Board (ADC 0 channel 2) + FIELDNAM: N6V LABLAXIS: Voltage UNITS: V voltage_pos6v_bus: <<: *trigger_base - FIELDNAM: P6V CATDESC: Positive voltage reading on +6V bus on LVPS Board (ADC 0 channel 3) + FIELDNAM: P6V LABLAXIS: Voltage UNITS: V voltage_pos16v_bus: <<: *trigger_base - FIELDNAM: P16V CATDESC: Positive voltage reading on +16V bus on LVPS Board (ADC 0 channel 4) + FIELDNAM: P16V LABLAXIS: Voltage UNITS: V voltage_pos3p3v_bus: <<: *trigger_base - FIELDNAM: P3.3V CATDESC: Positive voltage reading on +3.3V bus on LVPS Board (ADC 0 channel 5) + FIELDNAM: P3.3V LABLAXIS: Voltage UNITS: V voltage_neg5v_bus: <<: *trigger_base - FIELDNAM: N5V CATDESC: Negative voltage reading on -5V bus on LVPS Board (ADC 0 channel 6) + FIELDNAM: N5V LABLAXIS: Voltage UNITS: V voltage_pos5v_bus: <<: *trigger_base - FIELDNAM: P5V CATDESC: Positive voltage reading on +5V bus on LVPS Board (ADC 0 channel 7) + FIELDNAM: P5V LABLAXIS: Voltage UNITS: V current_3p3v_bus: <<: *trigger_base - FIELDNAM: P3.3_IMON CATDESC: Positive current reading on +3.3V bus on LVPS Board (ADC 1 channel 0) + FIELDNAM: P3.3_IMON LABLAXIS: Current UNITS: A current_16v_bus: <<: *trigger_base - FIELDNAM: P16V_IMON CATDESC: Positive current reading on +16V bus on LVPS Board (ADC 1 channel 1) + FIELDNAM: P16V_IMON LABLAXIS: Current UNITS: A current_6v_bus: <<: *trigger_base - FIELDNAM: P6V_IMON CATDESC: Positive current reading on +6V bus on LVPS Board (ADC 1 channel 2) + FIELDNAM: P6V_IMON LABLAXIS: Current UNITS: A current_neg6v_bus: <<: *trigger_base - FIELDNAM: N6V_IMON CATDESC: Negative current reading on -6V bus on LVPS Board (ADC 1 channel 3) + FIELDNAM: N6V_IMON LABLAXIS: Current UNITS: A current_5v_bus: <<: *trigger_base - FIELDNAM: P5V_IMON CATDESC: Positive current reading on +5V bus on LVPS Board (ADC 1 channel 4) + FIELDNAM: P5V_IMON LABLAXIS: Current UNITS: A current_neg5v_bus: <<: *trigger_base - FIELDNAM: N5V_IMON CATDESC: Negative current reading on -5V bus on LVPS Board (ADC 1 channel 5) + FIELDNAM: N5V_IMON LABLAXIS: Current UNITS: A current_2p5v_bus: <<: *trigger_base - FIELDNAM: P2.5V_IMON CATDESC: Positive current reading on +2.5V bus on LVPS Board (ADC 1 channel 6) + FIELDNAM: P2.5V_IMON LABLAXIS: Current UNITS: A current_neg2p5v_bus: <<: *trigger_base - FIELDNAM: N2.5V_IMON CATDESC: Negative current reading on -2.5V bus on LVPS Board (ADC 1 channel 7) + FIELDNAM: N2.5V_IMON LABLAXIS: Current UNITS: A +# <=== Dead Time Attributes ===> +dead_time: + <<: *l1b_data_base + CATDESC: Event dead time + DEPEND_0: epoch + FIELDNAM: event_dead_time + FILLVAL: *double_fillval + FORMAT: F12.6 + LABLAXIS: event_dead_time + UNITS: s + VALIDMAX: *dead_max + VALIDMIN: *data_min + VAR_TYPE: data + # <=== Spice Data Attributes ===> -# TODO: Get actual validmin and vaildmax for ephemeris attrs ephemeris_position_x: <<: *spice_base - FIELDNAM: Position X CATDESC: Cartesian coord X positions for the IMAP spacecraft in the ECLIPJ2000 frame. + DICT_KEY: SPASE>Support>SupportQuantity:Positional + FIELDNAM: Position X LABLAXIS: Position X UNITS: km - DICT_KEY: SPASE>Support>SupportQuantity:Positional ephemeris_position_y: <<: *spice_base - FIELDNAM: Position Y CATDESC: Cartesian coord Y positions for the IMAP spacecraft in the ECLIPJ2000 frame. + DICT_KEY: SPASE>Support>SupportQuantity:Positional + FIELDNAM: Position Y LABLAXIS: Position Y UNITS: km - DICT_KEY: SPASE>Support>SupportQuantity:Positional ephemeris_position_z: <<: *spice_base + CATDESC: Cartesian coord Z positions for the IMAP spacecraft in the ECLIPJ2000 frame. + DICT_KEY: SPASE>Support>SupportQuantity:Positional FIELDNAM: Position Z - CATDESC: Cartesian coordinate Z positions for the IMAP spacecraft in the ECLIPJ2000 frame. LABLAXIS: Position Z UNITS: km - DICT_KEY: SPASE>Support>SupportQuantity:Positional ephemeris_velocity_x: <<: *spice_base - FIELDNAM: Velocity X CATDESC: Velocity X positions for the IMAP spacecraft in the ECLIPJ2000 frame. + DICT_KEY: SPASE>Support>SupportQuantity:Velocity + FIELDNAM: Velocity X LABLAXIS: Velocity X UNITS: km/s - DICT_KEY: SPASE>Support>SupportQuantity:Velocity ephemeris_velocity_y: <<: *spice_base - FIELDNAM: Velocity Y CATDESC: Velocity Y positions for the IMAP spacecraft in the ECLIPJ2000 frame. + DICT_KEY: SPASE>Support>SupportQuantity:Velocity + FIELDNAM: Velocity Y LABLAXIS: Velocity Y UNITS: km/s - DICT_KEY: SPASE>Support>SupportQuantity:Velocity ephemeris_velocity_z: <<: *spice_base - FIELDNAM: Velocity Z CATDESC: Velocity Z positions for the IMAP spacecraft in the ECLIPJ2000 frame. + DICT_KEY: SPASE>Support>SupportQuantity:Velocity + FIELDNAM: Velocity Z LABLAXIS: Velocity Z UNITS: km/s - DICT_KEY: SPASE>Support>SupportQuantity:Velocity longitude: <<: *spice_base - VALIDMIN: 0 - FIELDNAM: Longitude CATDESC: Longitude of the dust event as observed from Earth in the ECLIPJ2000 frame. - LABLAXIS: Longitude DICT_KEY: SPASE>Support>SupportQuantity:Longitude + FIELDNAM: Longitude + LABLAXIS: Longitude + UNITS: Degrees + VALIDMAX: 360 + VALIDMIN: 0 latitude: <<: *spice_base - FIELDNAM: Latitude CATDESC: Latitude of the dust event as observed from Earth in the ECLIPJ2000 frame. - LABLAXIS: Latitude DICT_KEY: SPASE>Support>SupportQuantity:Latitude + FIELDNAM: Latitude + LABLAXIS: Latitude + UNITS: Degrees + VALIDMAX: 90 + VALIDMIN: -90 spin_phase: <<: *spice_base - VALIDMIN: 0 - FIELDNAM: Spin Phase CATDESC: IMAP Spin Phase - LABLAXIS: Spin Phase - FORMAT: F12.6 - FILLVAL: *double_fillval DICT_KEY: SPASE>Support>SupportQuantity:SpinPhase + FIELDNAM: Spin Phase + FILLVAL: *int_fillval + FORMAT: I3 + LABLAXIS: Spin Phase + UNITS: Degrees + VALIDMAX: 360 + VALIDMIN: 0 solar_longitude: <<: *spice_base - VALIDMAX: 180 - FIELDNAM: Solar Longitude CATDESC: Solar Longitude of the IMAP spacecraft - LABLAXIS: Solar Longitude DICT_KEY: SPASE>Support>SupportQuantity:Longitude + FIELDNAM: Solar Longitude + LABLAXIS: Solar Longitude + UNITS: Degrees + VALIDMAX: 180 + VALIDMIN: -180 diff --git a/imap_processing/cdf/config/imap_idex_l2a_variable_attrs.yaml b/imap_processing/cdf/config/imap_idex_l2a_variable_attrs.yaml index 9e80b310d9..200b9c2b74 100644 --- a/imap_processing/cdf/config/imap_idex_l2a_variable_attrs.yaml +++ b/imap_processing/cdf/config/imap_idex_l2a_variable_attrs.yaml @@ -4,356 +4,358 @@ int_maxval: &int_maxval 9223372036854775807 # <=== Base Attributes ===> fit_parameter_base: &fit_parameter_base - UNITS: " " - VAR_TYPE: data DEPEND_0: epoch DEPEND_1: target_fit_parameter_index + DICT_KEY: SPASE>Particle>ParticleType:Dust>ParticleQuantity:Current>Qualifier:Fit # TODO quantity should be charge but there is no SPASE charge + DISPLAY_TYPE: no_plot + FILLVAL: *double_fillval + FORMAT: F20.6 LABL_PTR_1: target_fit_parameter_labels - VALIDMIN: 0 + UNITS: " " VALIDMAX: *int_maxval - FORMAT: F20.6 - FILLVAL: *double_fillval - DISPLAY_TYPE: no_plot - DICT_KEY: SPASE>Particle>ParticleType:Dust>ParticleQuantity:Current>Qualifier:Fit # TODO quantity should be charge but there is no SPASE charge + VALIDMIN: 0 + VAR_TYPE: data impact_charge_base: &impact_charge_base + DEPEND_0: epoch + DICT_KEY: SPASE>Particle>ParticleType:Dust>ParticleQuantity:Current>Qualifier:Derived # TODO quantity should be charge but there is no SPASE charge + DISPLAY_TYPE: time_series + FILLVAL: *double_fillval + FORMAT: F20.4 UNITS: pC - VALIDMIN: *int_fillval VALIDMAX: *int_maxval + VALIDMIN: *int_fillval VAR_TYPE: data + +mass_estimate_base: &mass_estimate_base DEPEND_0: epoch + DICT_KEY: SPASE>Particle>ParticleType:Dust>ParticleQuantity:Mass>Qualifier:Derived DISPLAY_TYPE: time_series - FORMAT: F20.4 FILLVAL: *double_fillval - DICT_KEY: SPASE>Particle>ParticleType:Dust>ParticleQuantity:Current>Qualifier:Derived # TODO quantity should be charge but there is no SPASE charge - -mass_estimate_base: &mass_estimate_base + FORMAT: F20.4 UNITS: Kg - VALIDMIN: 0.0 VALIDMAX: *int_maxval + VALIDMIN: 0.0 VAR_TYPE: data + +velocity_estimate_base: &velocity_estimate_base DEPEND_0: epoch + DICT_KEY: SPASE>Particle>ParticleType:Dust>ParticleQuantity:Velocity>Qualifier:Derived DISPLAY_TYPE: time_series - FORMAT: F20.4 FILLVAL: *double_fillval - DICT_KEY: SPASE>Particle>ParticleType:Dust>ParticleQuantity:Mass>Qualifier:Derived - -velocity_estimate_base: &velocity_estimate_base + FORMAT: F20.4 UNITS: km/s - VALIDMIN: 0.0 VALIDMAX: *int_maxval + VALIDMIN: 0.0 VAR_TYPE: data + +chi_square_base: &chi_square_base DEPEND_0: epoch + DICT_KEY: SPASE>Support>SupportQuantity:DataQuality DISPLAY_TYPE: time_series - FORMAT: F20.4 FILLVAL: *double_fillval - DICT_KEY: SPASE>Particle>ParticleType:Dust>ParticleQuantity:Velocity>Qualifier:Derived - -chi_square_base: &chi_square_base + FORMAT: F20.4 UNITS: " " - VALIDMIN: 0.0 VALIDMAX: *int_maxval + VALIDMIN: 0.0 VAR_TYPE: data - DEPEND_0: epoch - DISPLAY_TYPE: time_series - FORMAT: F20.4 - FILLVAL: *double_fillval - DICT_KEY: SPASE>Support>SupportQuantity:DataQuality fit_results_base: &fit_results_base - UNITS: pC - VALIDMIN: 0 - VALIDMAX: *int_maxval - VAR_TYPE: data DEPEND_0: epoch DEPEND_1: time_low_sample_rate_index - LABL_PTR_1: time_low_sample_rate_label + DICT_KEY: SPASE>Particle>ParticleType:Dust>ParticleQuantity:Current>Qualifier:Derived # TODO quantity should be charge but there is no SPASE charge DISPLAY_TYPE: spectrogram - FORMAT: F20.4 FILLVAL: *double_fillval - DICT_KEY: SPASE>Particle>ParticleType:Dust>ParticleQuantity:Current>Qualifier:Derived # TODO quantity should be charge but there is no SPASE charge + FORMAT: F20.4 + LABL_PTR_1: time_low_sample_rate_label + UNITS: pC + VALIDMAX: *int_maxval + VALIDMIN: 0 + VAR_TYPE: data # <=== LABL_PTR_i Attributes ===> peak_fit_parameter_labels: CATDESC: Labels for EMG fit parameters (mu, sigma, lambda) - FIELDNAM: EMG Parameter Labels - VAR_TYPE: metadata - FORMAT: A8 DEPEND_1: peak_fit_parameter_index DICT_KEY: SPASE>Support>SupportQuantity:Other + FIELDNAM: EMG Parameter Labels + FORMAT: A8 + VAR_TYPE: metadata target_fit_parameter_labels: CATDESC: Labels for the target fit parameters. + DEPEND_1: target_fit_parameter_index + DICT_KEY: SPASE>Support>SupportQuantity:Other FIELDNAM: Target Fit Parameter Labels + FORMAT: A8 VAR_NOTES: Parameters include time_of_impact, constant_offset, amplitude, rise_time, discharge_time. VAR_TYPE: metadata - FORMAT: A8 - DEPEND_1: target_fit_parameter_index - DICT_KEY: SPASE>Support>SupportQuantity:Other mass_labels: CATDESC: Labels for mass index values - FIELDNAM: Mass Labels - VAR_TYPE: metadata - FORMAT: A8 DEPEND_1: mass_index DICT_KEY: SPASE>Support>SupportQuantity:Other + FIELDNAM: Mass Labels + FORMAT: A8 + VAR_TYPE: metadata # <=== Index Attributes ===> peak_fit_parameter_index: CATDESC: Peak fit parameter index + DICT_KEY: SPASE>Support>SupportQuantity:Other # TODO what to do for indices? FIELDNAM: Peak Fit Parameter Index - UNITS: " " - FORMAT: I2 - VAR_TYPE: support_data - VALIDMIN: 0 - VALIDMAX: 2 FILLVAL: *int_fillval + FORMAT: I2 LABL_PTR_1: peak_fit_parameter_labels - DICT_KEY: SPASE>Support>SupportQuantity:Other # TODO what to do for indices? + UNITS: " " + VALIDMAX: 2 + VALIDMIN: 0 + VAR_TYPE: support_data target_fit_parameter_index: CATDESC: Target fit parameter index + DICT_KEY: SPASE>Support>SupportQuantity:Other # TODO what to do for indices? FIELDNAM: Target Fit Parameter Index - UNITS: " " - FORMAT: I4 - VAR_TYPE: support_data - VALIDMIN: 0 - VALIDMAX: 4 FILLVAL: *int_fillval + FORMAT: I4 LABL_PTR_1: target_fit_parameter_labels - DICT_KEY: SPASE>Support>SupportQuantity:Other # TODO what to do for indices? + UNITS: " " + VALIDMAX: 4 + VALIDMIN: 0 + VAR_TYPE: support_data mass_index: CATDESC: Mass index values from 1 to 500 + DICT_KEY: SPASE>Support>SupportQuantity:Other # TODO what to do for indices? FIELDNAM: Mass Index - UNITS: Kg + FILLVAL: *int_fillval FORMAT: I4 - VAR_TYPE: support_data - SCALETYP: linear LABLAXIS: Mass Index - VALIDMIN: 0 - VALIDMAX: 500 - FILLVAL: *int_fillval LABL_PTR_1: mass_labels - DICT_KEY: SPASE>Support>SupportQuantity:Other # TODO what to do for indices? + SCALETYP: linear + UNITS: Kg + VALIDMAX: 500 + VALIDMIN: 0 + VAR_TYPE: support_data # <=== Data Attributes ===> tof_snr: CATDESC: TOF High signal to noise ratio. - FIELDNAM: TOF Signal to Noise Ratio - UNITS: pC - VALIDMIN: 0.0 - VALIDMAX: *int_maxval - VAR_TYPE: data DEPEND_0: epoch + DICT_KEY: SPASE>Support>SupportQuantity:DataQuality DISPLAY_TYPE: time_series - FORMAT: F20.3 + FIELDNAM: TOF Signal to Noise Ratio FILLVAL: *double_fillval + FORMAT: F20.3 LABLAXIS: TOF High SNR - DICT_KEY: SPASE>Support>SupportQuantity:DataQuality + UNITS: pC + VALIDMAX: *int_maxval + VALIDMIN: 0.0 + VAR_TYPE: data tof_peak_kappa: CATDESC: TOF High spectrum with x-axis converted from time to mass. - FIELDNAM: Mass Scale - UNITS: Kg - VALIDMIN: 0.0 - VALIDMAX: 1.0 - VAR_TYPE: data DEPEND_0: epoch + DICT_KEY: SPASE>Support>SupportQuantity:DataQuality DISPLAY_TYPE: time_series - FORMAT: F10.3 + FIELDNAM: Mass Scale FILLVAL: *double_fillval + FORMAT: F10.3 LABLAXIS: TOF High Kappa - DICT_KEY: SPASE>Support>SupportQuantity:DataQuality + UNITS: Kg + VALIDMAX: 1.0 + VALIDMIN: 0.0 + VAR_TYPE: data tof_peak_fit_parameters: CATDESC: EMG fit parameters (mu, sigma, lambda) for TOF High peaks. - FIELDNAM: TOF Peak Fit Parameters - UNITS: " " - VAR_TYPE: support_data DEPEND_0: epoch DEPEND_1: mass_index DEPEND_2: peak_fit_parameter_index + DICT_KEY: SPASE>Particle>ParticleType:Ion>ParticleQuantity:Current>Qualifier:Fit # TODO quantity should be charge but there is no SPASE charge + DISPLAY_TYPE: no_plot + FIELDNAM: TOF Peak Fit Parameters + FILLVAL: *double_fillval + FORMAT: F20.6 + LABLAXIS: TOF Fit Parameters LABL_PTR_1: mass_labels LABL_PTR_2: peak_fit_parameter_labels - VALIDMIN: 0 + UNITS: " " VALIDMAX: *int_maxval - LABLAXIS: TOF Peak Fit Parameters - FORMAT: F20.6 - FILLVAL: *double_fillval - DISPLAY_TYPE: no_plot - DICT_KEY: SPASE>Particle>ParticleType:Ion>ParticleQuantity:Current>Qualifier:Fit # TODO quantity should be charge but there is no SPASE charge + VALIDMIN: 0 + VAR_TYPE: support_data tof_peak_area_under_fit: CATDESC: Area under the EMG curve for each mass peak. - FIELDNAM: TOF Peak Area - UNITS: " " - VAR_TYPE: data DEPEND_0: epoch DEPEND_1: mass_index - LABL_PTR_1: mass_labels - LABLAXIS: Area Under Peak - VALIDMIN: 0 - VALIDMAX: *int_maxval + DICT_KEY: SPASE>Particle>ParticleType:Ion>ParticleQuantity:Current>Qualifier:Integral # TODO quantity should be charge but there is no SPASE charge DISPLAY_TYPE: spectrogram - FORMAT: F20.6 + FIELDNAM: TOF Peak Area FILLVAL: *double_fillval - DICT_KEY: SPASE>Particle>ParticleType:Ion>ParticleQuantity:Current>Qualifier:Integral # TODO quantity should be charge but there is no SPASE charge + FORMAT: F20.6 + LABLAXIS: Area Under Peak + LABL_PTR_1: mass_labels + UNITS: " " + VALIDMAX: *int_maxval + VALIDMIN: 0 + VAR_TYPE: data tof_peak_chi_squared: <<: *chi_square_base - DEPEND_1: mass_index - LABL_PTR_1: mass_labels CATDESC: Chi squared value for the TOF peak emg fits. - FIELDNAM: Chi Square (TOF peak fits)) + DEPEND_1: mass_index + DISPLAY_TYPE: spectrogram + FIELDNAM: Chi Square (TOF peak fits) + LABLAXIS: Chi Square (TOF) tof_peak_reduced_chi_squared: <<: *chi_square_base - DEPEND_1: mass_index - LABL_PTR_1: mass_labels CATDESC: Reduced chi squared value for the TOF peak emg fits. + DEPEND_1: mass_index + DISPLAY_TYPE: spectrogram FIELDNAM: Reduced Chi Square (TOF peak fits) + LABLAXIS: Red Chi Square (TOF) mass_scale: CATDESC: TOF High spectrum with x-axis converted from time to mass. - FIELDNAM: Mass Scale - UNITS: Kg - VALIDMIN: 0.0 - VALIDMAX: *int_maxval - FILLVAL: *double_fillval - VAR_TYPE: data DEPEND_0: epoch DEPEND_1: time_high_sample_rate_index - LABL_PTR_1: time_high_sample_rate_label - LABLAXIS: Mass Scale + DICT_KEY: SPASE>Support>SupportQuantity:Temporal DISPLAY_TYPE: spectrogram + FIELDNAM: Mass Scale + FILLVAL: *double_fillval FORMAT: F20.6 - DICT_KEY: SPASE>Support>SupportQuantity:Temporal + LABLAXIS: Mass Scale + LABL_PTR_1: time_high_sample_rate_label + UNITS: Kg + VALIDMAX: *int_maxval + VALIDMIN: 0.0 + VAR_TYPE: data target_low_fit_parameters: <<: *fit_parameter_base CATDESC: Fitted parameters for Target Low impact signal. - VAR_NOTES: Parameters include time of impact, constant offset, amplitude, rise time, discharge time. FIELDNAM: Target Low Fit Parameters + VAR_NOTES: Parameters include time of impact, constant offset, amplitude, rise time, discharge time. target_low_impact_charge: <<: *impact_charge_base - LABLAXIS: Target Low Impact Charge - CATDESC: Total charge from the dust impact on Target Low channel derived from the fitted curve. + CATDESC: Total charge from the dust impact on Target Low (TL) channel derived from the fitted curve. FIELDNAM: Target Low Impact Charge + LABLAXIS: TL Impact Charge target_low_dust_mass_estimate: <<: *mass_estimate_base - LABLAXIS: Target Low Dust Mass Estimate CATDESC: Estimated dust mass from Target Low signal based on impact charge. FIELDNAM: Estimated Dust Mass (Target Low) + LABLAXIS: TL Dust Mass Est target_low_velocity_estimate: <<: *velocity_estimate_base - LABLAXIS: Target Low Velocity Estimate CATDESC: Estimated particle velocity from Target Low signal based on impact charge. FIELDNAM: Estimated Velocity (Target Low) + LABLAXIS: TL Velocity Est target_low_chi_squared: <<: *chi_square_base - LABLAXIS: Target Low Chi Square CATDESC: Chi squared value for the Target Low signal fit. FIELDNAM: Chi Square (Target Low) + LABLAXIS: TL Chi Square target_low_reduced_chi_squared: <<: *chi_square_base - LABLAXIS: Target Low Reduced Chi Square CATDESC: Reduced chi squared value for the Target Low signal fit. FIELDNAM: Reduced Chi Square (Target Low) + LABLAXIS: TL Red Chi Square target_low_fit_results: <<: *fit_results_base - LABLAXIS: Target Low Fit Results CATDESC: Values of Target Low signal fit evaluated at each time point. FIELDNAM: Target Low Fit results + LABLAXIS: TL Fit Results target_high_fit_parameters: <<: *fit_parameter_base CATDESC: Fitted parameters for Target High impact signal. - VAR_NOTES: Parameters include time of impact, constant offset, amplitude, rise time, discharge time. FIELDNAM: Target High Fit Parameters + VAR_NOTES: Parameters include time of impact, constant offset, amplitude, rise time, discharge time. target_high_impact_charge: <<: *impact_charge_base - LABLAXIS: Target High Impact Charge - CATDESC: Charge from the dust impact on Target High derived from the fitted curve. + CATDESC: Charge from the dust impact on Target High (TH) derived from the fitted curve. FIELDNAM: Target High Impact Charge + LABLAXIS: TH Impact Charge target_high_dust_mass_estimate: <<: *mass_estimate_base - LABLAXIS: Target High Dust Mass Estimate CATDESC: Estimated dust mass from Target High signal based on impact charge. FIELDNAM: Estimated Dust Mass (Target High) + LABLAXIS: TH Dust Mass Est target_high_velocity_estimate: <<: *velocity_estimate_base - LABLAXIS: Target High Velocity Estimate CATDESC: Estimated particle velocity from Target High signal based on impact charge. FIELDNAM: Estimated Velocity (Target High) + LABLAXIS: TH Velocity Est target_high_chi_squared: <<: *chi_square_base - LABLAXIS: Target High Chi Square CATDESC: Chi squared value for the Target High signal fit. FIELDNAM: Chi Square (Target High) + LABLAXIS: TH Chi Square target_high_reduced_chi_squared: <<: *chi_square_base - LABLAXIS: Target High Reduced Chi Square CATDESC: Reduced chi squared value for the Target Low signal fit. FIELDNAM: Reduced Chi Square (Target High) + LABLAXIS: TH Red Chi Square target_high_fit_results: <<: *fit_results_base - LABLAXIS: Target High Fit Results CATDESC: Values of Target High signal fit evaluated at each time point. FIELDNAM: Target High Fit Results + LABLAXIS: TH Fit Results ion_grid_fit_parameters: <<: *fit_parameter_base CATDESC: Fitted parameters for Ion Grid impact signal. - VAR_NOTES: Parameters include time of impact, constant offset, amplitude, rise time, discharge time. FIELDNAM: Ion Grid Fit Parameters + VAR_NOTES: Parameters include time of impact, constant offset, amplitude, rise time, discharge time. ion_grid_impact_charge: <<: *impact_charge_base - LABLAXIS: Ion Grid Impact Charge - CATDESC: Charge from the dust impact on Ion Grid channel derived from the fitted curve. + CATDESC: Charge from the dust impact on Ion Grid (IG) channel derived from the fitted curve. FIELDNAM: Ion Grid Impact Charge + LABLAXIS: IG Impact Charge ion_grid_dust_mass_estimate: <<: *mass_estimate_base - LABLAXIS: Ion Grid Dust Mass Estimate CATDESC: Estimated dust mass from Ion Grid signal based on impact charge. FIELDNAM: Estimated Dust Mass (Ion Grid) + LABLAXIS: IG Dust Mass Est ion_grid_velocity_estimate: <<: *velocity_estimate_base - LABLAXIS: Ion Grid Velocity Estimate CATDESC: Estimated particle velocity from Ion Grid signal based on impact charge. FIELDNAM: Estimated Velocity (Ion Grid) + LABLAXIS: IG Velocity Est ion_grid_chi_squared: <<: *chi_square_base - LABLAXIS: Ion Grid Chi Square CATDESC: Chi squared value for the Ion Grid signal fit. FIELDNAM: Chi Square (Ion Grid) + LABLAXIS: IG Chi Square ion_grid_reduced_chi_squared: <<: *chi_square_base - LABLAXIS: Ion Grid Reduced Chi Square CATDESC: Reduced chi squared value for the Ion Grid signal fit. FIELDNAM: Reduced Chi Square (Ion Grid) + LABLAXIS: IG Red Chi Square ion_grid_fit_results: <<: *fit_results_base - LABLAXIS: Ion Grid Fit Results CATDESC: Values of Ion Grid signal fit evaluated at each time point. - FIELDNAM: Ion Grid Fit Results \ No newline at end of file + FIELDNAM: Ion Grid Fit Results + LABLAXIS: IG Fit Results diff --git a/imap_processing/cdf/config/imap_idex_l2b_variable_attrs.yaml b/imap_processing/cdf/config/imap_idex_l2b_variable_attrs.yaml index 0fc6cc529d..2edf05a4ef 100644 --- a/imap_processing/cdf/config/imap_idex_l2b_variable_attrs.yaml +++ b/imap_processing/cdf/config/imap_idex_l2b_variable_attrs.yaml @@ -4,161 +4,195 @@ double_fillval: &double_fillval -1.0E31 # Label attributes mass_labels: - CATDESC: Labels for Mass (kg) - FIELDNAM: Mass (kg) - VAR_TYPE: metadata - FORMAT: A8 + CATDESC: Labels for Mass DEPEND_1: mass DICT_KEY: SPASE>Support>SupportQuantity:Other + FIELDNAM: Mass + FORMAT: A8 + VAR_TYPE: metadata charge_labels: CATDESC: Labels for Impact Charge (fC) - FIELDNAM: Impact Charge (fC) - VAR_TYPE: metadata - FORMAT: A8 DEPEND_1: impact_charge DICT_KEY: SPASE>Support>SupportQuantity:Other + FIELDNAM: Impact Charge (fC) + FORMAT: A8 + VAR_TYPE: metadata spin_phase_labels: CATDESC: Labels for Spin Phase (deg) - FIELDNAM: Spin Phase (deg) - VAR_TYPE: metadata - FORMAT: A8 DEPEND_1: spin_phase DICT_KEY: SPASE>Support>SupportQuantity:Other + FIELDNAM: Spin Phase (deg) + FORMAT: A8 + VAR_TYPE: metadata # Index attributes mass: CATDESC: Log-spaced mass - FIELDNAM: Mass (kg) - UNITS: kg + DICT_KEY: SPASE>Particle>ParticleType:Dust,ParticleQuantity:Mass + FIELDNAM: Mass + FILLVAL: *double_fillval FORMAT: E10.4 - VAR_TYPE: support_data + LABLAXIS: Mass + LABL_PTR_1: mass_labels SCALETYP: log - LABLAXIS: Mass (kg) - VALIDMIN: 0.0 + UNITS: kg VALIDMAX: 1.00e-14 - FILLVAL: *double_fillval - LABL_PTR_1: mass_labels - DICT_KEY: SPASE>Support>SupportQuantity:Other + VALIDMIN: 0.0 + VAR_TYPE: support_data spin_phase: CATDESC: The spacecraft spin phase at the time of detection - VAR_NOTES: This is given in 4 bins [315-45, 45-135, 135-225, 225-315] degrees. - FIELDNAM: Spin Phase (deg) - LABLAXIS: Spin Phase (deg) - VAR_TYPE: support_data - SCALETYP: linear + DICT_KEY: SPASE>Support>SupportQuantity:SpinPhase,Qualifier:Array + FIELDNAM: Spin Phase FILLVAL: *int_fillval - FORMAT: I4 - VALIDMIN: 0.0 - VALIDMAX: 360 + FORMAT: I8 + LABLAXIS: Spin Phase LABL_PTR_1: spin_phase_labels + SCALETYP: linear UNITS: deg - DICT_KEY: SPASE>SupportQuantity:SpinPhase,Qualifier:Array + VALIDMAX: 360 + VALIDMIN: 0 + VAR_NOTES: This is given in 4 bins [315-45, 45-135, 135-225, 225-315] degrees. + VAR_TYPE: support_data impact_charge: CATDESC: Log-spaced impact charge - FIELDNAM: Impact Charge (fC) - LABLAXIS: Impact Charge (fC) - VAR_TYPE: support_data - SCALETYP: log + DICT_KEY: SPASE>Support>SupportQuantity:Other + FIELDNAM: Impact Charge FILLVAL: *int_fillval FORMAT: E10.3 - VALIDMIN: 0.0 - VALIDMAX: 1.00e04 + LABLAXIS: Impact Charge LABL_PTR_1: spin_phase_labels + SCALETYP: log UNITS: fC - DICT_KEY: SPASE>Support>SupportQuantity:Other + VALIDMAX: 1.00e04 + VALIDMIN: 0.0 + VAR_TYPE: support_data # Base attributes for charge and mass variables base_charge: &base_charge CATDESC: " " - FIELDNAM: " " DEPEND_0: epoch DEPEND_1: impact_charge DEPEND_2: spin_phase - LABL_PTR_1: charge_labels - LABL_PTR_2: spin_phase_labels DISPLAY_TYPE: spectrogram - VAR_TYPE: data + FIELDNAM: " " FILLVAL: *int_fillval FORMAT: E10.3 - VALIDMIN: -1 + LABL_PTR_1: charge_labels + LABL_PTR_2: spin_phase_labels VALIDMAX: *int_maxval + VALIDMIN: -1 + VAR_TYPE: data base_mass: &base_mass CATDESC: " " - FIELDNAM: " " DEPEND_0: epoch DEPEND_1: mass DEPEND_2: spin_phase - LABL_PTR_1: mass_labels - LABL_PTR_2: spin_phase_labels DISPLAY_TYPE: spectrogram - VAR_TYPE: data + FIELDNAM: " " FILLVAL: *int_fillval FORMAT: E10.3 - VALIDMIN: 0.0 + LABL_PTR_1: mass_labels + LABL_PTR_2: spin_phase_labels VALIDMAX: *int_maxval + VALIDMIN: 0.0 + VAR_TYPE: data rate_by_charge: <<: *base_charge CATDESC: Count rate per day by impact charge and spin phase. - FIELDNAM: Rate (day^-1) by Charge - UNITS: day^-1 + DICT_KEY: SPASE>Particle>ParticleType:Dust,ParticleQuantity:CountRate,Qualifier:Array + FIELDNAM: Rate by Charge FILLVAL: *double_fillval - DICT_KEY: SPASE>SupportQuantity:CountRate,Qualifier:Array + UNITS: day^-1 rate_by_mass: <<: *base_mass CATDESC: Count rate per day by mass and spin phase. - FIELDNAM: Rate (day^-1) by Mass - UNITS: day^-1 + DICT_KEY: SPASE>Particle>ParticleType:Dust,ParticleQuantity:CountRate,Qualifier:Array + FIELDNAM: Rate by Mass FILLVAL: *double_fillval - DICT_KEY: SPASE>SupportQuantity:CountRate,Qualifier:Array + UNITS: day^-1 counts_by_charge: <<: *base_charge CATDESC: Count by impact charge and spin phase. + DICT_KEY: SPASE>Particle>ParticleType:Dust,ParticleQuantity:Counts,Qualifier:Array FIELDNAM: Counts by Charge FORMAT: I8 UNITS: counts - DICT_KEY: SPASE>Particle>ParticleType:Dust,ParticleQuantity:Counts,Qualifier:Array counts_by_mass: <<: *base_mass CATDESC: Count by mass and spin phase. + DICT_KEY: SPASE>Particle>ParticleType:Dust,ParticleQuantity:Counts,Qualifier:Array FIELDNAM: Counts by Mass FORMAT: I8 UNITS: counts - DICT_KEY: SPASE>Particle>ParticleType:Dust,ParticleQuantity:Counts,Qualifier:Array impact_day_of_year: CATDESC: The unique day of the years when dust impacts occurred. - FIELDNAM: Impact Day of Year - LABLAXIS: Impact DOY DEPEND_0: epoch + DICT_KEY: SPASE>Support>SupportQuantity:Temporal DISPLAY_TYPE: time_series + FIELDNAM: Impact Day of Year FILLVAL: *int_fillval FORMAT: I3 - VALIDMIN: 1 + LABLAXIS: Impact DOY + UNITS: days VALIDMAX: 366 + VALIDMIN: 1 VAR_TYPE: data - UNITS: days - DICT_KEY: SPASE>SupportQuantity:Temporal,Qualifier:Array rate_calculation_quality_flags: CATDESC: Quality flag for rate calculation (1 = good, 0 = insufficient IDEX uptime data) - FIELDNAM: Rate Quality Flag - LABLAXIS: Quality Flag DEPEND_0: epoch + DICT_KEY: SPASE>Support>SupportQuantity:QualityFlag DISPLAY_TYPE: time_series + FIELDNAM: Rate Quality Flag FILLVAL: 255 FORMAT: I1 - VALIDMIN: 0 + LABLAXIS: Quality Flag + UNITS: " " VALIDMAX: 1 + VALIDMIN: 0 VAR_TYPE: data + +on_off_times: + CATDESC: Science acquisition on/off event times. + CDF_DATA_TYPE: "CDF_TIME_TT2000" + DICT_KEY: SPASE>Support>SupportQuantity:Temporal + FIELDNAM: On/Off Times + FILLVAL: -9223372036854775808 + FORMAT: " " + LABLAXIS: On/Off Times + MONOTON: INCREASE + REFERENCE_POSITION: Rotating Earth Geoid + RESOLUTION: ' ' + SCALETYP: linear + TIME_BASE: J2000 + TIME_SCALE: Terrestrial Time + UNITS: ns + VALIDMAX: 3155716869184000000 + VALIDMIN: 315576066184000000 + VAR_TYPE: support_data + +on_off_events: + CATDESC: Science acquisition on/off event values (1 = on, 0 = off). + DEPEND_0: on_off_times + DICT_KEY: SPASE>Support>SupportQuantity:Other + FIELDNAM: On/Off Events + FILLVAL: 255 + FORMAT: I1 + LABLAXIS: On/Off Events + SCALETYP: linear UNITS: " " - DICT_KEY: SPASE>SupportQuantity:QualityFlag,Qualifier:Array + VALIDMAX: 1 + VALIDMIN: 0 + VAR_TYPE: support_data + diff --git a/imap_processing/cdf/config/imap_idex_l2c_variable_attrs.yaml b/imap_processing/cdf/config/imap_idex_l2c_variable_attrs.yaml index 9a2f22b7be..087de061f4 100644 --- a/imap_processing/cdf/config/imap_idex_l2c_variable_attrs.yaml +++ b/imap_processing/cdf/config/imap_idex_l2c_variable_attrs.yaml @@ -5,33 +5,33 @@ double_fillval: &double_fillval -1.0E31 # Base attributes for charge and mass variables base_charge: &base_charge CATDESC: " " - FIELDNAM: " " DEPEND_0: epoch DEPEND_1: impact_charge DEPEND_2: spin_phase - LABL_PTR_1: charge_labels - LABL_PTR_2: spin_phase_labels DISPLAY_TYPE: spectrogram - VAR_TYPE: data + FIELDNAM: " " FILLVAL: *int_fillval FORMAT: E10.3 - VALIDMIN: -1 + LABL_PTR_1: charge_labels + LABL_PTR_2: spin_phase_labels VALIDMAX: *int_maxval + VALIDMIN: -1 + VAR_TYPE: data base_mass: &base_mass CATDESC: " " - FIELDNAM: " " DEPEND_0: epoch DEPEND_1: mass DEPEND_2: spin_phase - LABL_PTR_1: mass_labels - LABL_PTR_2: spin_phase_labels DISPLAY_TYPE: spectrogram - VAR_TYPE: data + FIELDNAM: " " FILLVAL: *int_fillval FORMAT: E10.3 - VALIDMIN: 0.0 + LABL_PTR_1: mass_labels + LABL_PTR_2: spin_phase_labels VALIDMAX: *int_maxval + VALIDMIN: 0.0 + VAR_TYPE: data base_charge_map: &base_charge_map <<: *base_charge @@ -50,71 +50,105 @@ base_mass_map: &base_mass_map # Label attributes rectangular_lon_pixel_label: CATDESC: Longitude pixel index label for IDEX SkyMap. + DICT_KEY: SPASE>Support>SupportQuantity:Other FIELDNAM: Longitude pixel label FORMAT: A5 VAR_TYPE: metadata - DICT_KEY: SPASE>Support>SupportQuantity:Other rectangular_lat_pixel_label: CATDESC: Latitude pixel index label for IDEX SkyMap. + DICT_KEY: SPASE>Support>SupportQuantity:Other FIELDNAM: Latitude pixel label FORMAT: A5 VAR_TYPE: metadata - DICT_KEY: SPASE>Support>SupportQuantity:Other # Vars rectangular_lon_pixel: CATDESC: Longitude pixel center for IDEX SkyMap + DICT_KEY: SPASE>Support>SupportQuantity:Positional FIELDNAM: Rectangular Longitude Center + FILLVAL: *double_fillval FORMAT: F12.6 LABLAXIS: Longitude Pixel - VAR_TYPE: support_data UNITS: degrees - VALIDMIN: 0 VALIDMAX: 360 - FILLVAL: *double_fillval - DICT_KEY: SPASE>Support>SupportQuantity:Positional + VALIDMIN: 0 + VAR_TYPE: support_data rectangular_lat_pixel: CATDESC: Latitude pixel center for IDEX SkyMap + DICT_KEY: SPASE>Support>SupportQuantity:Positional FIELDNAM: Rectangular Latitude Center + FILLVAL: *double_fillval FORMAT: F12.6 LABLAXIS: Latitude Pixel - VAR_TYPE: support_data UNITS: degrees - VALIDMIN: -90 VALIDMAX: 90 - FILLVAL: *double_fillval - DICT_KEY: SPASE>Support>SupportQuantity:Positional + VALIDMIN: -90 + VAR_TYPE: support_data rate_by_charge_map: <<: *base_charge_map CATDESC: Count rate per day by impact charge, longitude, and latitude. - FIELDNAM: Rate (day^-1) by Charge Map - UNITS: day^-1 - FILLVAL: *double_fillval DICT_KEY: SPASE>SupportQuantity:CountRate,Qualifier:Array + FIELDNAM: Rate by Charge Map + FILLVAL: *double_fillval + UNITS: day^-1 counts_by_charge_map: <<: *base_charge_map CATDESC: Count by impact charge, longitude, and latitude. + DICT_KEY: SPASE>Particle>ParticleType:Dust,ParticleQuantity:Counts,Qualifier:Array FIELDNAM: Counts by Charge Map FORMAT: I8 UNITS: counts - DICT_KEY: SPASE>Particle>ParticleType:Dust,ParticleQuantity:Counts,Qualifier:Array counts_by_mass_map: <<: *base_mass_map CATDESC: Count by mass, longitude, and latitude. + DICT_KEY: SPASE>Particle>ParticleType:Dust,ParticleQuantity:Counts,Qualifier:Array FIELDNAM: Counts by Mass Map FORMAT: I8 UNITS: counts - DICT_KEY: SPASE>Particle>ParticleType:Dust,ParticleQuantity:Counts,Qualifier:Array rate_by_mass_map: <<: *base_mass_map CATDESC: Count rate per day by mass, longitude, and latitude. - FIELDNAM: Rate (day^-1) by Mass Map - UNITS: day^-1 + DICT_KEY: SPASE>SupportQuantity:CountRate,Qualifier:Array + FIELDNAM: Rate by Mass Map FILLVAL: *double_fillval - DICT_KEY: SPASE>SupportQuantity:CountRate,Qualifier:Array \ No newline at end of file + UNITS: day^-1 + + +on_off_times: + CATDESC: Science acquisition on/off event times. + CDF_DATA_TYPE: "CDF_TIME_TT2000" + DICT_KEY: SPASE>Support>SupportQuantity:Temporal + FIELDNAM: On/Off Times + FILLVAL: -9223372036854775808 + FORMAT: " " + LABLAXIS: On/Off Times + MONOTON: INCREASE + REFERENCE_POSITION: Rotating Earth Geoid + RESOLUTION: ' ' + SCALETYP: linear + TIME_BASE: J2000 + TIME_SCALE: Terrestrial Time + UNITS: ns + VALIDMAX: 3155716869184000000 + VALIDMIN: 315576066184000000 + VAR_TYPE: support_data + +on_off_events: + CATDESC: Science acquisition on/off event values (1 = on, 0 = off). + DEPEND_0: on_off_times + DICT_KEY: SPASE>Support>SupportQuantity:Other + FIELDNAM: On/Off Events + FILLVAL: 255 + FORMAT: I1 + LABLAXIS: On/Off Events + SCALETYP: linear + UNITS: " " + VALIDMAX: 1 + VALIDMIN: 0 + VAR_TYPE: support_data diff --git a/imap_processing/cdf/config/imap_lo_global_cdf_attrs.yaml b/imap_processing/cdf/config/imap_lo_global_cdf_attrs.yaml index a622c3451e..b6e2b8448d 100644 --- a/imap_processing/cdf/config/imap_lo_global_cdf_attrs.yaml +++ b/imap_processing/cdf/config/imap_lo_global_cdf_attrs.yaml @@ -1,9 +1,9 @@ instrument_base: &instrument_base Descriptor: Lo>IMAP Low-Energy (IMAP-Lo) Energetic Neutral Atom Imager + Instrument_type: "Particles (space)" TEXT: > IMAP-Lo is a single-pixel neutral atom imager that delivers energy and position measurements of low-energy Interstellar Neutral (ISN) atoms tracked over the ecliptic longitude >180deg and global maps of energetic neutral atoms (ENAs). Mounted on a pivot platform, IMAP-Lo tracks the flow of these ions through the local interstellar medium (LISM) to precisely determine the species-dependent flow speed, temperature, and direction of the LISM that surrounds, interacts with, and determines the outer boundaries of the global heliosphere. IMAP-Lo uses the pivoting field of view (FOV) to view variable angles out to 90deg from the spin axis. This assists IMAP-Lo to pinpoint the intersection between the ISN inflow speed and longitude to uniquely determine the LISM flow vector. Data from IMAP-Lo will help us be able to see from inside the heliosphere what it is like just outside the solar system, our local neighborhood. - Instrument_type: "Particles (space)" imap_lo_l1a_de: <<: *instrument_base @@ -65,10 +65,10 @@ imap_lo_l1b_monitorrates: Logical_source: imap_lo_l1b_monitorrates Logical_source_description: IMAP Mission IMAP-Lo Instrument Level-1B Data -imap_lo_l1b_histogramrates: +imap_lo_l1b_histrates: <<: *instrument_base - Data_type: L1B_histogramrates>Level-1B Histogram Rates - Logical_source: imap_lo_l1b_histogramrrates + Data_type: L1B_histrates>Level-1B Histogram Rates + Logical_source: imap_lo_l1b_histrates Logical_source_description: IMAP Mission IMAP-Lo Instrument Level-1B Data imap_lo_l1b_derates: @@ -95,6 +95,24 @@ imap_lo_l1b_shk: Logical_source: imap_lo_l1b_shk Logical_source_description: IMAP Mission IMAP-Lo Instrument Level-1B Data +imap_lo_l1b_instrument-status-summary: + <<: *instrument_base + Data_type: L1B_star>Level-1B Status Summary + Logical_source: imap_lo_l1b_instrument-status-summary + Logical_source_description: IMAP Mission IMAP-Lo Instrument Level-1B Data + +imap_lo_l1b_bgrates: + <<: *instrument_base + Data_type: L1B_goodtimes>Level-1B Background Rates List + Logical_source: imap_lo_l1b_bgrates + Logical_source_description: IMAP Mission IMAP-Lo Instrument Level-1B Data + +imap_lo_l1b_goodtimes: + <<: *instrument_base + Data_type: L1B_goodtimes>Level-1B Goodtimes List + Logical_source: imap_lo_l1b_goodtimes + Logical_source_description: IMAP Mission IMAP-Lo Instrument Level-1B Data + imap_lo_l1c_goodtimes: <<: *instrument_base Data_type: L1C_goodtimes>Level-1C Goodtimes List @@ -107,8 +125,9 @@ imap_lo_l1c_pset: Logical_source: imap_lo_l1c_pset Logical_source_description: IMAP Mission IMAP-Lo Instrument Level-1C Data -imap_lo_l2_l090-ena-h-sf-nsp-ram-hae-6deg-3mo: +# Global attributes for different sensors and sky tiling types and durations +imap_lo_l2_enamap: <<: *instrument_base - Data_type: L2_l090-ena-h-sf-nsp-ram-hae-6deg-3mo>Level-2 Low-Energy ENA Maps - Logical_source: imap_lo_l2_l090-ena-h-sf-nsp-ram-hae-6deg-3mo - Logical_source_description: IMAP Mission IMAP-Lo Instrument Level-2 Low-Energy ENA Maps \ No newline at end of file + Data_type: L2_{descriptor}>Level-2 Intensity Map for Lo + Logical_source: imap_lo_l2_{descriptor} + Logical_source_description: IMAP-Lo Instrument Level-2 Intensity Map Data for Lo diff --git a/imap_processing/cdf/config/imap_lo_l1a_variable_attrs.yaml b/imap_processing/cdf/config/imap_lo_l1a_variable_attrs.yaml index 1f47b25823..174199bb88 100644 --- a/imap_processing/cdf/config/imap_lo_l1a_variable_attrs.yaml +++ b/imap_processing/cdf/config/imap_lo_l1a_variable_attrs.yaml @@ -7,40 +7,40 @@ default_uint8_attrs: &default_uint8 <<: *default FILLVAL: 255 FORMAT: I3 - VALIDMIN: 0 VALIDMAX: 255 + VALIDMIN: 0 dtype: uint8 default_uint16_attrs: &default_uint16 <<: *default FILLVAL: 65535 FORMAT: I5 - VALIDMIN: 0 VALIDMAX: 65535 + VALIDMIN: 0 dtype: uint16 default_uint32_attrs: &default_uint32 <<: *default FILLVAL: 4294967295 FORMAT: I10 - VALIDMIN: 0 VALIDMAX: 4294967295 + VALIDMIN: 0 dtype: uint32 default_int64_attrs: &default_int64 <<: *default FILLVAL: 18446744073709551615 FORMAT: I20 - VALIDMIN: 0 VALIDMAX: 18446744073709551615 + VALIDMIN: 0 dtype: int64 default_int32_attrs: &default_int32 <<: *default FILLVAL: -2147483648 FORMAT: I10 - VALIDMIN: -2147483648 VALIDMAX: 2147483647 + VALIDMIN: -2147483648 dtype: int32 coord_default_attrs: &coord_default @@ -49,34 +49,34 @@ coord_default_attrs: &coord_default de_default_attrs: &de_default <<: *default - VAR_TYPE: support_data DEPEND_1: direct_events LABL_PTR_1: direct_events_label + VAR_TYPE: support_data hist_az_60_default: &hist_az_60_default <<: *default_uint32 - VAR_TYPE: data DEPEND_0: epoch DEPEND_1: esa_step DEPEND_2: azimuth_60 LABL_PTR_1: azimuth_60_label LABL_PTR_2: esa_step_label + VAR_TYPE: data hist_az_6_default: &hist_az_6_default <<: *default_uint32 - VAR_TYPE: data DEPEND_0: epoch DEPEND_1: esa_step DEPEND_2: azimuth_6 LABL_PTR_1: azimuth_6_label LABL_PTR_2: esa_step_label + VAR_TYPE: data spin_default_attrs: &spin_default <<: *default - VAR_TYPE: data DEPEND_0: epoch DEPEND_1: spin LABL_PTR_1: spin_label + VAR_TYPE: data esa_step_label: CATDESC: ESA Steps @@ -87,23 +87,22 @@ esa_step_label: esa_step_coord: <<: *coord_default <<: *default_uint8 - VALIDMIN: 1 - VALIDMAX: 7 - FORMAT: I1 CATDESC: Energy Step - DEPEND_1: esa_step FIELDNAM: Energy Step + FORMAT: I1 LABLAXIS: ESA LABL_PTR_1: esa_step_label + VALIDMAX: 7 + VALIDMIN: 1 shcoarse: <<: *default_uint32 CATDESC: Mission Elapsed Time - DEPEND_1: shcoarse + DEPEND_0: epoch FIELDNAM: Spacecraft Time + LABLAXIS: SHCOARSE Units: 'ns' VAR_TYPE: support_data - LABLAXIS: SHCOARSE # Direct Events Attributes ## Coordinates @@ -124,114 +123,114 @@ direct_events: de_time: <<: *de_default <<: *default_uint16 - VALIDMAX: 4096 - FORMAT: I4 CATDESC: Time relative to spin start FIELDNAM: Direct Event Time - UNITS: microseconds + FORMAT: I4 LABLAXIS: DE time + UNITS: microseconds + VALIDMAX: 4096 esa_step: <<: *de_default <<: *default_uint8 - VALIDMIN: 1 - VALIDMAX: 7 - FORMAT: I1 CATDESC: Energy Step FIELDNAM: Energy Step + FORMAT: I1 LABLAXIS: ESA + VALIDMAX: 7 + VALIDMIN: 1 mode: <<: *de_default <<: *default_uint8 - VALIDMAX: 1 - FORMAT: I1 CATDESC: Energy Stepping Mode FIELDNAM: ESA Mode + FORMAT: I1 LABLAXIS: ESA Mode + VALIDMAX: 1 tof0: <<: *de_default <<: *default_uint16 - VALIDMAX: 4096 - FORMAT: I4 CATDESC: Time of Flight FIELDNAM: Time of Flight 2 + FORMAT: I4 LABLAXIS: ToF 0 + VALIDMAX: 4096 tof1: <<: *de_default <<: *default_uint16 - VALIDMAX: 4096 - FORMAT: I4 CATDESC: Time of Flight FIELDNAM: Time of Flight 1 + FORMAT: I4 LABLAXIS: ToF 1 + VALIDMAX: 4096 tof2: <<: *de_default <<: *default_uint16 - VALIDMAX: 4096 - FORMAT: I4 CATDESC: Time of Flight FIELDNAM: Time of Flight 2 + FORMAT: I4 LABLAXIS: ToF 2 + VALIDMAX: 4096 tof3: <<: *de_default <<: *default_uint16 - VALIDMAX: 4096 - FORMAT: I4 CATDESC: Time of Flight FIELDNAM: Time of Flight 3 + FORMAT: I4 LABLAXIS: ToF 3 + VALIDMAX: 4096 cksm: <<: *de_default <<: *default_uint8 - VALIDMAX: 15 CATDESC: checksum TBD FIELDNAM: Checksum FORMAT: I2 LABLAXIS: Checksum + VALIDMAX: 15 pos: <<: *de_default <<: *default_uint8 - VALIDMAX: 4 - FORMAT: I1 CATDESC: Stop position FIELDNAM: Stop Position + FORMAT: I1 LABLAXIS: Stop Position + VALIDMAX: 4 coincidence_type: <<: *de_default <<: *default_uint8 - VALIDMAX: 15 - FORMAT: I2 CATDESC: Direct Event Coincidence Type FIELDNAM: Coincidence Type + FORMAT: I2 LABLAXIS: Coincidence Type + VALIDMAX: 15 de_count: <<: *default <<: *default_uint16 - VAR_TYPE: data - VALIDMAX: 32767 - DEPEND_0: epoch CATDESC: Direct Event Counts + DEPEND_0: epoch FIELDNAM: Direct Event Count LABLAXIS: Direct Event Count + VALIDMAX: 32767 + VAR_TYPE: data passes: <<: *default <<: *default_uint16 - VAR_TYPE: data - VALIDMAX: 32767 - DEPEND_0: epoch CATDESC: Passes through raw data + DEPEND_0: epoch FIELDNAM: Direct Event Passes LABLAXIS: Direct Event Passes + VALIDMAX: 32767 + VAR_TYPE: data # Direct Events Attributes - END # Histogram Attributes @@ -245,12 +244,11 @@ azimuth_6_label: azimuth_6: <<: *coord_default <<: *default_uint8 - VALIDMAX: 59 CATDESC: azimuth spin bins (, 6 degrees) FIELDNAM: Azimuth bins - DEPEND_1: azimuth_6 LABLAXIS: Az bins LABL_PTR_1: azimuth_6_label + VALIDMAX: 59 azimuth_60_label: CATDESC: azimuth spin bins (, 60 degrees) @@ -261,12 +259,11 @@ azimuth_60_label: azimuth_60: <<: *coord_default <<: *default_uint8 - VALIDMAX: 5 CATDESC: azimuth spin bins (, 60 degrees) FIELDNAM: Azimuth bins - DEPEND_1: azimuth_60 LABLAXIS: Az bins LABL_PTR_1: azimuth_60_label + VALIDMAX: 5 ## Fields start_a: @@ -311,8 +308,8 @@ tof3_count: tof0_tof1: <<: *hist_az_6_default - catdesc: Triple Coincidence 0/1 count FIELDNAM: Triple Coincidence 0/1 count + catdesc: Triple Coincidence 0/1 count tof0_tof2: <<: *hist_az_6_default @@ -321,8 +318,8 @@ tof0_tof2: tof1_tof2: <<: *hist_az_6_default - catdesc: Triple Coincidence 1/2 count FIELDNAM: Triple Coincidence 1/2 count + catdesc: Triple Coincidence 1/2 count silver: <<: *hist_az_6_default @@ -385,26 +382,26 @@ oxygen: star_sample: <<: *coord_default <<: *default_uint16 - VALIDMAX: 719 CATDESC: indices of star sensor samples for pointing FIELDNAM: Star Sensor Sample Indices in Pointing + VALIDMAX: 719 ## Fields star_sensor: <<: *default_uint32 CATDESC: Star Sensor FIFO Data DEPEND_1: star_sample - VAR_TYPE: support_data FIELDNAM: Star Sensor FIFO Data LABLAXIS: star sensor FIFO data + VAR_TYPE: support_data count: <<: *default_uint16 CATDESC: Number of star sensor samples in packet - FIELDNAM: Number of star sensor samples DEPEND_0: epoch - VAR_TYPE: support_data + FIELDNAM: Number of star sensor samples LABLAXIS: Number of star sensor samples + VAR_TYPE: support_data # Star Sensor Attributes - END # Spin Attributes @@ -413,9 +410,8 @@ spin: <<: *default_uint16 CATDESC: Spin numbers in pointing FIELDNAM: Spin numbers - DEPEND_1: spin - VAR_TYPE: support_data LABLAXIS: Spin numbers + VAR_TYPE: support_data spin_label: CATDESC: Spin numbers in pointing @@ -426,47 +422,47 @@ spin_label: ## Spin Fields num_completed: <<: *default_uint16 - DEPEND_0: epoch - VAR_TYPE: support_data CATDESC: Number of spins completed + DEPEND_0: epoch FIELDNAM: Number of spins completed LABLAXIS: Number of spins completed + VAR_TYPE: support_data acq_start_sec: <<: *default_uint32 - DEPEND_0: epoch - VAR_TYPE: support_data CATDESC: Acquisition start + DEPEND_0: epoch FIELDNAM: Acquisition start seconds - UNITS: s LABLAXIS: Acquisition start seconds + UNITS: s + VAR_TYPE: support_data acq_start_subsec: <<: *default_uint32 - DEPEND_0: epoch - VAR_TYPE: support_data CATDESC: Acquisition start + DEPEND_0: epoch FIELDNAM: Acquisition start sub-seconds - UNITS: ms LABLAXIS: Acquisition start sub-seconds + UNITS: ms + VAR_TYPE: support_data acq_end_sec: <<: *default_uint32 - DEPEND_0: epoch - VAR_TYPE: support_data CATDESC: Acquisition end + DEPEND_0: epoch FIELDNAM: Acquisition end seconds - UNITS: s LABLAXIS: Acquisition end seconds + UNITS: s + VAR_TYPE: support_data acq_end_subsec: <<: *default_uint32 - DEPEND_0: epoch - VAR_TYPE: support_data CATDESC: Acquisition end + DEPEND_0: epoch FIELDNAM: Acquisition end sub-seconds - UNITS: ms LABLAXIS: Acquisition end sub-seconds + UNITS: ms + VAR_TYPE: support_data start_sec_spin: <<: *spin_default @@ -511,4 +507,4 @@ period_source_spin: <<: *default_uint32 CATDESC: Spin period source FIELDNAM: Spin period source -# Spin Attributes - END \ No newline at end of file +# Spin Attributes - END diff --git a/imap_processing/cdf/config/imap_lo_l1b_variable_attrs.yaml b/imap_processing/cdf/config/imap_lo_l1b_variable_attrs.yaml index 0e57459581..24d6925c35 100644 --- a/imap_processing/cdf/config/imap_lo_l1b_variable_attrs.yaml +++ b/imap_processing/cdf/config/imap_lo_l1b_variable_attrs.yaml @@ -1,13 +1,13 @@ default_attrs: &default # Assumed values for all variable attrs unless overwritten + DEPEND_0: epoch DISPLAY_TYPE: time_series FILLVAL: -9223372036854775808 FORMAT: F19.3 - VALIDMIN: 0 - DEPEND_0: epoch + UNITS: ' ' VALIDMAX: 9223372036854775807 + VALIDMIN: 0 VAR_TYPE: data - UNITS: ' ' direction_vec_label: CATDESC: Directional vector for each direct event @@ -17,105 +17,293 @@ direction_vec_label: esa_step: <<: *default - VALIDMIN: 1 - VALIDMAX: 7 CATDESC: Energy Step DEPEND_0: epoch FIELDNAM: Energy Step FORMAT: I1 LABLAXIS: ESA + VALIDMAX: 7 + VALIDMIN: 1 mode: <<: *default - VALIDMAX: 1 CATDESC: Energy Stepping Mode. 0 = high-throughput, 1 = high-resolution FIELDNAM: ESA Mode FORMAT: I1 - VAR_TYPE: data LABLAXIS: ESA Mode + VALIDMAX: 1 + VAR_TYPE: data tof0: <<: *default CATDESC: Time of Flight FIELDNAM: Time of Flight 2 FILLVAL: -1.0000000E+31 - UNITS: ns LABLAXIS: ToF 0 + UNITS: ns tof1: <<: *default CATDESC: Time of Flight FIELDNAM: Time of Flight 1 FILLVAL: -1.0000000E+31 - UNITS: ns LABLAXIS: ToF 1 + UNITS: ns tof2: <<: *default CATDESC: Time of Flight FIELDNAM: Time of Flight 2 FILLVAL: -1.0000000E+31 - UNITS: ns LABLAXIS: ToF 2 + UNITS: ns tof3: <<: *default CATDESC: Time of Flight FIELDNAM: Time of Flight 3 FILLVAL: -1.0000000E+31 - UNITS: ns LABLAXIS: ToF 3 + UNITS: ns coincidence_type: <<: *default - VALIDMAX: 14 CATDESC: Coincidence type for the direct event FIELDNAM: Coincidence type FORMAT: I2 LABLAXIS: coincidence type + VALIDMAX: 14 pos: <<: *default - VALIDMAX: 4 CATDESC: Stop position FIELDNAM: Stop Position FORMAT: I1 LABLAXIS: Stop Position + VALIDMAX: 4 coincidence: <<: *default - VALIDMAX: 2 CATDESC: Species of Direct Event. 0=light, 1=heavy, 2=other FIELDNAM: Species FORMAT: I1 LABLAXIS: Species + VALIDMAX: 2 badtime: <<: *default - VALIDMIN: 1 - VALIDMAX: 2 CATDESC: Flag if DE measured in badtime 1 = yes, 2 = no FIELDNAM: Badtime Flag FORMAT: I1 LABLAXIS: Badtime flag + VALIDMAX: 2 + VALIDMIN: 1 direction_vec: - FORMAT: I1 - VALIDMIN: 0 - DEPEND_1: direction_vec CATDESC: Direction Vector Position (X, Y, Z) + DEPEND_1: direction_vec FIELDNAM: Direction Vector Position + FORMAT: I1 + LABLAXIS: (X, Y, Z) + UNITS: ' ' VALIDMAX: 2 + VALIDMIN: 0 VAR_TYPE: support_data - UNITS: ' ' - LABLAXIS: (X, Y, Z) direction: <<: *default - VALIDMAX: 1 CATDESC: Directional vector for each direct event - FIELDNAM: Direction DEPEND_1: direction_vec + FIELDNAM: Direction FORMAT: I1 LABLAXIS: Direction - LABL_PTR_1: direction_vec_label \ No newline at end of file + LABL_PTR_1: direction_vec_label + VALIDMAX: 1 + +# Star Sensor L1B Attributes +met: + <<: *default + CATDESC: Start Mission Elapsed Time of averaging period + FIELDNAM: MET + FORMAT: I16 + VAR_TYPE: support_data + +spin_angle: + CATDESC: Spin angle in degrees + FIELDNAM: Spin Angle + FILLVAL: -1.0e31 + FORMAT: F8.3 + UNITS: deg + VALIDMAX: 360.0 + VALIDMIN: 0.0 + VAR_TYPE: support_data + +spin_angle_bin: + <<: *default + CATDESC: Original spin angle bin index (before sorting) + DEPEND_0: spin_angle + FIELDNAM: Spin Angle Bin + FORMAT: I3 + UNITS: ' ' + VALIDMAX: 719 + VALIDMIN: 0 + VAR_TYPE: support_data + +avg_amplitude: + <<: *default + CATDESC: Average star sensor amplitude per spin angle bin + DEPEND_0: epoch + DEPEND_1: spin_angle + FIELDNAM: Average Amplitude + FILLVAL: -1.0000000E+31 + FORMAT: F12.4 + LABLAXIS: Amplitude + UNITS: mV + +count_per_bin: + <<: *default + CATDESC: Number of samples per spin angle bin + DEPEND_0: epoch + DEPEND_1: spin_angle + FIELDNAM: Count Per Bin + FORMAT: I6 + LABLAXIS: Sample Count + UNITS: ' ' + VALIDMAX: 100000 + VALIDMIN: 0 + +pivot: + CATDESC: Pivot angle derived from housekeeping data + FIELDNAM: Pivot Angle + FILLVAL: -1.0000000E+31 + FORMAT: F8.3 + LABLAXIS: Pivot Angle + UNITS: deg + VALIDMAX: 180.0 + VALIDMIN: 0.0 + VAR_TYPE: support_data + +pivot_de: + CATDESC: Pivot angle derived from direct event data + FIELDNAM: Pivot Angle (DE) + FILLVAL: -1.0000000E+31 + FORMAT: F8.3 + LABLAXIS: Pivot Angle DE + UNITS: deg + VALIDMAX: 180.0 + VALIDMIN: 0.0 + VAR_TYPE: support_data + +gt_start_met: + <<: *default + CATDESC: Good time interval start in Mission Elapsed Time + FIELDNAM: Good Time Start MET + FILLVAL: -1.0000000E+31 + FORMAT: F19.3 + LABLAXIS: GT Start + UNITS: s + VALIDMAX: 1.0000000E+31 + VAR_TYPE: support_data + +gt_end_met: + <<: *default + CATDESC: Good time interval end in Mission Elapsed Time + FIELDNAM: Good Time End MET + FILLVAL: -1.0000000E+31 + FORMAT: F19.3 + LABLAXIS: GT End + UNITS: s + VALIDMAX: 1.0000000E+31 + VAR_TYPE: support_data + +h_background_rates: + CATDESC: Hydrogen background rates per ESA level + DEPEND_0: esa_step + FIELDNAM: H Background Rates + FILLVAL: -1.0000000E+31 + FORMAT: F12.6 + LABLAXIS: H BG Rate + UNITS: counts/s + VALIDMAX: 1.0000000E+31 + VALIDMIN: 0.0 + VAR_TYPE: data + +h_background_variance: + CATDESC: Hydrogen background rate variance per ESA level + DEPEND_0: esa_step + FIELDNAM: H Background Variance + FILLVAL: -1.0000000E+31 + FORMAT: F12.6 + LABLAXIS: H BG Variance + UNITS: (counts/s)^2 + VALIDMAX: 1.0000000E+31 + VALIDMIN: 0.0 + VAR_TYPE: data + +h_synthetic_floor: + CATDESC: Hydrogen synthetic background floor + FIELDNAM: H Synthetic Floor + FILLVAL: -1.0000000E+31 + FORMAT: F12.6 + LABLAXIS: H Synthetic Floor + UNITS: counts/s + VALIDMAX: 1.0000000E+31 + VALIDMIN: 0.0 + VAR_TYPE: support_data + +h_proxy_floor: + CATDESC: Hydrogen proxy background floor + FIELDNAM: H Proxy Floor + FILLVAL: -1.0000000E+31 + FORMAT: F12.6 + LABLAXIS: H Proxy Floor + UNITS: counts/s + VALIDMAX: 1.0000000E+31 + VALIDMIN: 0.0 + VAR_TYPE: support_data + +o_background_rates: + CATDESC: Oxygen background rates per ESA level + DEPEND_0: esa_step + FIELDNAM: O Background Rates + FILLVAL: -1.0000000E+31 + FORMAT: F12.6 + LABLAXIS: O BG Rate + UNITS: counts/s + VALIDMAX: 1.0000000E+31 + VALIDMIN: 0.0 + VAR_TYPE: data + +o_background_variance: + CATDESC: Oxygen background rate variance per ESA level + DEPEND_0: esa_step + FIELDNAM: O Background Variance + FILLVAL: -1.0000000E+31 + FORMAT: F12.6 + LABLAXIS: O BG Variance + UNITS: (counts/s)^2 + VALIDMAX: 1.0000000E+31 + VALIDMIN: 0.0 + VAR_TYPE: data + +o_synthetic_floor: + CATDESC: Oxygen synthetic background floor + FIELDNAM: O Synthetic Floor + FILLVAL: -1.0000000E+31 + FORMAT: F12.6 + LABLAXIS: O Synthetic Floor + UNITS: counts/s + VALIDMAX: 1.0000000E+31 + VALIDMIN: 0.0 + VAR_TYPE: support_data + +o_proxy_floor: + CATDESC: Oxygen proxy background floor + FIELDNAM: O Proxy Floor + FILLVAL: -1.0000000E+31 + FORMAT: F12.6 + LABLAXIS: O Proxy Floor + UNITS: counts/s + VALIDMAX: 1.0000000E+31 + VALIDMIN: 0.0 + VAR_TYPE: support_data diff --git a/imap_processing/cdf/config/imap_lo_l1c_variable_attrs.yaml b/imap_processing/cdf/config/imap_lo_l1c_variable_attrs.yaml index a034bcd73e..bbe59c0f06 100644 --- a/imap_processing/cdf/config/imap_lo_l1c_variable_attrs.yaml +++ b/imap_processing/cdf/config/imap_lo_l1c_variable_attrs.yaml @@ -1,13 +1,28 @@ default_attrs: &default # Assumed values for all variable attrs unless overwritten + DEPEND_0: epoch DISPLAY_TYPE: time_series FILLVAL: -9223372036854775808 FORMAT: F19.3 - VALIDMIN: 0 - DEPEND_0: epoch + UNITS: " " VALIDMAX: 9223372036854775807 + VALIDMIN: 0 VAR_TYPE: data - UNITS: " " + +default_float32_attrs: &default_float32 + <<: *default + FILLVAL: -1.0e31 + FORMAT: F12.6 + VALIDMAX: 3.4028235e+38 + VALIDMIN: -3.4028235e+38 + dtype: float32 + +component: + CATDESC: Cartesian components (x,y,z) + FIELDNAM: component + FORMAT: A3 + LABLAXIS: component + VAR_TYPE: metadata # Non-epoch Coordinates esa_energy_step_label: @@ -17,14 +32,14 @@ esa_energy_step_label: VAR_TYPE: metadata esa_energy_step: - VALIDMIN: 1 - VALIDMAX: 7 CATDESC: Energy Step FIELDNAM: Energy Step - UNITS: " " FORMAT: I1 - VAR_TYPE: support_data LABLAXIS: ESA + UNITS: " " + VALIDMAX: 7 + VALIDMIN: 1 + VAR_TYPE: support_data spin_angle_label: CATDESC: Spin angles @@ -33,14 +48,14 @@ spin_angle_label: VAR_TYPE: metadata spin_angle: - VALIDMIN: 0 - VALIDMAX: 360 CATDESC: Spin angle bin center in despun pointing frame FIELDNAM: Spin angle - UNITS: "degrees" FORMAT: I4 - VAR_TYPE: support_data LABLAXIS: spin angle + UNITS: "degrees" + VALIDMAX: 360 + VALIDMIN: 0 + VAR_TYPE: support_data off_angle_label: CATDESC: Off axis angles @@ -49,30 +64,30 @@ off_angle_label: VAR_TYPE: metadata off_angle: - VALIDMIN: -2 - VALIDMAX: 2 CATDESC: Off axis angle bin center in despun pointing frame FIELDNAM: Off axis angle - UNITS: "degrees" FORMAT: I4 - VAR_TYPE: support_data LABLAXIS: off angle + UNITS: "degrees" + VALIDMAX: 2 + VALIDMIN: -2 + VAR_TYPE: support_data pointing_start_met: <<: *default CATDESC: MET of start of pointing FIELDNAM: Pointing start time FORMAT: I12 - UNITS: s LABLAXIS: pointing start + UNITS: s pointing_end_met: <<: *default CATDESC: MET of end of pointing FIELDNAM: Pointing end time FORMAT: I12 - UNITS: s LABLAXIS: pointing end + UNITS: s start_spin_number: <<: *default @@ -90,55 +105,55 @@ end_spin_number: pivot_angle: <<: *default - VALIDMAX: 360 CATDESC: Pivot angle for pointing FIELDNAM: Pivot angle FORMAT: I12 - UNITS: degrees LABLAXIS: pivot angle + UNITS: degrees + VALIDMAX: 360 esa_mode: <<: *default - DEPEND_1: esa_energy_step CATDESC: Science Mode for Pointing + DEPEND_1: esa_energy_step FIELDNAM: Science Mode FORMAT: I12 LABLAXIS: esa mode hae_longitude: <<: *default - VALIDMAX: 360 CATDESC: Bin longitudes in HAE coordinates + DEPEND_1: spin_angle + DEPEND_2: off_angle FIELDNAM: Bin longitudes FORMAT: I12 - UNITS: degrees LABLAXIS: longitude - DEPEND_1: spin_angle - DEPEND_2: off_angle LABL_PTR_1: spin_angle_label LABL_PTR_2: off_angle_label + UNITS: degrees + VALIDMAX: 360 hae_latitude: <<: *default - VALIDMIN: -90 - VALIDMAX: 90 CATDESC: Bin latitudes in HAE coordinates + DEPEND_1: spin_angle + DEPEND_2: off_angle FIELDNAM: Bin latitudes FORMAT: I12 - UNITS: degrees LABLAXIS: latitude - DEPEND_1: spin_angle - DEPEND_2: off_angle LABL_PTR_1: spin_angle_label LABL_PTR_2: off_angle_label + UNITS: degrees + VALIDMAX: 90 + VALIDMIN: -90 exposure_time: <<: *default CATDESC: Exposure times by ESA step - FIELDNAM: Exposure Times DEPEND_1: esa_energy_step DEPEND_2: spin_angle DEPEND_3: off_angle + FIELDNAM: Exposure Times LABL_PTR_1: esa_energy_step_label LABL_PTR_2: spin_angle_label LABL_PTR_3: off_angle_label @@ -147,14 +162,14 @@ exposure_time: triples_counts: <<: *default CATDESC: Counts for triple coincidence events - FIELDNAM: triples coincidence counts DEPEND_1: esa_energy_step DEPEND_2: spin_angle DEPEND_3: off_angle + FIELDNAM: triples coincidence counts + FORMAT: I12 LABL_PTR_1: esa_energy_step_label LABL_PTR_2: spin_angle_label LABL_PTR_3: off_angle_label - FORMAT: I12 doubles_counts: <<: *default @@ -172,52 +187,52 @@ doubles_counts: h_counts: <<: *default CATDESC: Counts for Hydrogen events - FIELDNAM: Hydrogen counts DEPEND_1: esa_energy_step DEPEND_2: spin_angle DEPEND_3: off_angle + FIELDNAM: Hydrogen counts + FORMAT: I12 LABL_PTR_1: esa_energy_step_label LABL_PTR_2: spin_angle_label LABL_PTR_3: off_angle_label - FORMAT: I12 h_background_rates: <<: *default CATDESC: Background Hydrogen rates - FIELDNAM: Background Hydrogen rates + DELTA_MINUS_VAR: h_background_rates_stat_uncert + DELTA_PLUS_VAR: h_background_rates_stat_uncert DEPEND_1: esa_energy_step DEPEND_2: spin_angle DEPEND_3: off_angle + FIELDNAM: Background Hydrogen rates + FORMAT: I12 LABL_PTR_1: esa_energy_step_label LABL_PTR_2: spin_angle_label LABL_PTR_3: off_angle_label - FORMAT: I12 - DELTA_PLUS_VAR: h_background_rates_stat_uncert - DELTA_MINUS_VAR: h_background_rates_stat_uncert h_background_rates_stat_uncert: <<: *default CATDESC: Background Hydrogen rates statistical uncertainty - FIELDNAM: Background Hydrogen rates stat uncertainty DEPEND_1: esa_energy_step DEPEND_2: spin_angle DEPEND_3: off_angle + FIELDNAM: Background Hydrogen rates stat uncertainty + FORMAT: I12 LABL_PTR_1: esa_energy_step_label LABL_PTR_2: spin_angle_label LABL_PTR_3: off_angle_label - FORMAT: I12 h_background_rates_sys_err: <<: *default CATDESC: Background Hydrogen rates systematic error - FIELDNAM: Background Hydrogen rates systematic error DEPEND_1: esa_energy_step DEPEND_2: spin_angle DEPEND_3: off_angle + FIELDNAM: Background Hydrogen rates systematic error + FORMAT: I12 LABL_PTR_1: esa_energy_step_label LABL_PTR_2: spin_angle_label LABL_PTR_3: off_angle_label - FORMAT: I12 o_counts: <<: *default @@ -225,8 +240,8 @@ o_counts: DEPEND_1: esa_energy_step DEPEND_2: spin_angle DEPEND_3: off_angle - FORMAT: I12 FIELDNAM: Oxygen count rates + FORMAT: I12 LABL_PTR_1: esa_energy_step_label LABL_PTR_2: spin_angle_label LABL_PTR_3: off_angle_label @@ -234,37 +249,61 @@ o_counts: o_background_rates: <<: *default CATDESC: Background Oxygen rates - FIELDNAM: Background Oxygen rates + DELTA_MINUS_VAR: o_background_rates_stat_uncert + DELTA_PLUS_VAR: o_background_rates_stat_uncert DEPEND_1: esa_energy_step DEPEND_2: spin_angle DEPEND_3: off_angle + FIELDNAM: Background Oxygen rates + FORMAT: I12 LABL_PTR_1: esa_energy_step_label LABL_PTR_2: spin_angle_label LABL_PTR_3: off_angle_label - FORMAT: I12 - DELTA_PLUS_VAR: o_background_rates_stat_uncert - DELTA_MINUS_VAR: o_background_rates_stat_uncert o_background_rates_stat_uncert: <<: *default CATDESC: Background Oxygen rates statistical uncertainty - FIELDNAM: Background Oxygen rates stat uncertainty DEPEND_1: esa_energy_step DEPEND_2: spin_angle DEPEND_3: off_angle + FIELDNAM: Background Oxygen rates stat uncertainty + FORMAT: I12 LABL_PTR_1: esa_energy_step_label LABL_PTR_2: spin_angle_label LABL_PTR_3: off_angle_label - FORMAT: I12 o_background_rates_sys_err: <<: *default CATDESC: Background Oxygen rates systematic error - FIELDNAM: Background Oxygen rates systematic error DEPEND_1: esa_energy_step DEPEND_2: spin_angle DEPEND_3: off_angle + FIELDNAM: Background Oxygen rates systematic error + FORMAT: I12 LABL_PTR_1: esa_energy_step_label LABL_PTR_2: spin_angle_label LABL_PTR_3: off_angle_label - FORMAT: I12 \ No newline at end of file + +sc_velocity: + <<: *default_float32 + CATDESC: x,y,z-components in the HAE coordinate system of the mean velocity vector, in km/s + FIELDNAM: sc_velocity + FORMAT: F12.2 + LABLAXIS: spacecraft velocity + LABL_PTR_1: label_vector_HAE + UNITS: "km/s" + +sc_position: + <<: *default_float32 + CATDESC: x,y,z-components in the HAE coordinate system of the mean spacecraft position, in km + FIELDNAM: sc_position + FORMAT: F12.2 + LABLAXIS: spacecraft position + LABL_PTR_1: label_vector_HAE + UNITS: "km" + +label_vector_HAE: + CATDESC: Cartesian components (x,y,z) + FIELDNAM: Cartesian components + FORMAT: A5 + VAR_TYPE: metadata \ No newline at end of file diff --git a/imap_processing/cdf/config/imap_mag_global_cdf_attrs.yaml b/imap_processing/cdf/config/imap_mag_global_cdf_attrs.yaml index ccf6c7ab0b..4e6b218fb2 100644 --- a/imap_processing/cdf/config/imap_mag_global_cdf_attrs.yaml +++ b/imap_processing/cdf/config/imap_mag_global_cdf_attrs.yaml @@ -1,6 +1,7 @@ default: &default Descriptor: MAG>Magnetometer + Instrument_type: Magnetic Fields (space) TEXT: > The IMAP magnetometer MAG consists of two vector magnetic field sensors which measure the magnetic field in the vicinity of the @@ -10,7 +11,6 @@ default: &default MAG design, assembly, operations, and calibration are led by Imperial College London. See https://imap.princeton.edu/spacecraft/instruments/magnetometer-mag for more details. - Instrument_type: Magnetic Fields (space) imap_mag_l1a_norm-raw: <<: *default @@ -194,4 +194,18 @@ imap_mag_l2_burst-gse: Data_type: L2_burst-gse>Level 2 burst rate data in GSE Logical_source: imap_mag_l2_burst-gse Logical_source_description: IMAP Mission Burst Rate Instrument Level-2 Data in - Geocentric Solar Ecliptic Reference Frame. \ No newline at end of file + Geocentric Solar Ecliptic Reference Frame. + +imap_mag_l2_norm-gsm: + <<: *default + Data_type: L2_norm-gsm>Level 2 normal rate data in GSM + Logical_source: imap_mag_l2_norm-gsm + Logical_source_description: IMAP Mission Normal Rate Instrument Level-2 Data in + Geocentric Solar Magnetospheric Reference Frame. + +imap_mag_l2_burst-gsm: + <<: *default + Data_type: L2_burst-gsm>Level 2 burst rate data in GSM + Logical_source: imap_mag_l2_burst-gsm + Logical_source_description: IMAP Mission Burst Rate Instrument Level-2 Data in + Geocentric Solar Magnetospheric Reference Frame. diff --git a/imap_processing/cdf/config/imap_mag_l1a_variable_attrs.yaml b/imap_processing/cdf/config/imap_mag_l1a_variable_attrs.yaml index dd11e29b9a..83ccf8b39e 100644 --- a/imap_processing/cdf/config/imap_mag_l1a_variable_attrs.yaml +++ b/imap_processing/cdf/config/imap_mag_l1a_variable_attrs.yaml @@ -6,25 +6,25 @@ default_attrs: &default DISPLAY_TYPE: time_series FILLVAL: -9223372036854775808 FORMAT: I12 - VALIDMIN: -9223372036854775808 + UNITS: ' ' VALIDMAX: 9223372036854775807 + VALIDMIN: -9223372036854775808 VAR_TYPE: data - UNITS: ' ' default_coords: &default_coords # Assumed values for all coordinate attrs unless overwritten - FORMAT: F2.4 # Float with 4 digits - VAR_TYPE: support_data DISPLAY_TYPE: time_series FILLVAL: -9223372036854775808 - VALIDMIN: -9223372036854775808 - VALIDMAX: 9223372036854775807 + FORMAT: F2.4 # Float with 4 digits UNITS: counts + VALIDMAX: 9223372036854775807 + VALIDMIN: -9223372036854775808 + VAR_TYPE: support_data mag_support_attrs: &support_default <<: *default - VAR_TYPE: support_data DICT_KEY: SPASE>Support>SupportQuantity:Other + VAR_TYPE: support_data mag_metadata_attrs: &metadata_default <<: *default @@ -46,26 +46,26 @@ raw_vector_attrs: &raw_vectors_default <<: *default CATDESC: Raw unprocessed magnetic field vector data in bytes DEPEND_1: direction - LABL_PTR_1: direction_label FIELDNAM: Magnetic Field Vector FORMAT: I3 + LABL_PTR_1: direction_label vector_attrs: &vectors_default <<: *default CATDESC: Magnetic field vector with x y z and sensor range varying by time DEPEND_1: direction FIELDNAM: Magnetic Field Vector - LABL_PTR_1: direction_label FILLVAL: 9223372036854775807 FORMAT: F12.5 + LABL_PTR_1: direction_label mag_flag_attrs: <<: *default - VALIDMIN: 0 - VALIDMAX: 1 DISPLAY_TYPE: time_series FILLVAL: 255 FORMAT: I1 + VALIDMAX: 1 + VALIDMIN: 0 raw_direction_attrs: <<: *default_coords @@ -76,42 +76,42 @@ raw_direction_attrs: direction_attrs: <<: *default_coords CATDESC: Magnetic field vector + DISPLAY_TYPE: time_series FIELDNAM: \[xyz\] magnetic field vector FORMAT: I3 - VAR_TYPE: support_data - DISPLAY_TYPE: time_series LABLAXIS: Magnetic field vector + VAR_TYPE: support_data compression_attrs: <<: *default_coords CATDESC: Data compression flag + DISPLAY_TYPE: no_plot FIELDNAM: Compression - LABLAXIS: Compressed FORMAT: I2 - VAR_TYPE: support_data + LABLAXIS: Compressed VALIDMAX: 21 VALIDMIN: 0 - DISPLAY_TYPE: no_plot + VAR_TYPE: support_data compression_flags_attrs: <<: *support_default CATDESC: Compression information per time stamp, includes a flag and the compression width - FIELDNAM: Compression information per time stamp DEPEND_0: epoch DEPEND_1: compression + DISPLAY_TYPE: no_plot + FIELDNAM: Compression information per time stamp FORMAT: I2 + LABL_PTR_1: compression_label VALIDMAX: 21 VALIDMIN: 0 - LABL_PTR_1: compression_label - DISPLAY_TYPE: no_plot pus_version: <<: *support_default CATDESC: PUS Version number FIELDNAM: PUS Version number - LABLAXIS: PUS Version FILLVAL: 8 FORMAT: I1 + LABLAXIS: PUS Version VALIDMAX: 7 VALIDMIN: 0 @@ -119,9 +119,9 @@ pus_stype: <<: *support_default CATDESC: PUS Service type FIELDNAM: PUS Service type - LABLAXIS: PUS type FILLVAL: 255 FORMAT: I3 + LABLAXIS: PUS type VALIDMAX: 255 VALIDMIN: 0 @@ -129,9 +129,9 @@ pus_ssubtype: <<: *support_default CATDESC: PUS Service subtype. Equal to the number of seconds of data minus 1 FIELDNAM: Number of seconds of data minus 1 - LABLAXIS: PUS Subtype FILLVAL: 255 FORMAT: I3 + LABLAXIS: PUS Subtype UNITS: 's' VALIDMAX: 255 VALIDMIN: 0 @@ -139,13 +139,13 @@ pus_ssubtype: compression: <<: *support_default CATDESC: Data compression flag + DICT_KEY: SPASE>Support>SupportQuantity:InstrumentMode FIELDNAM: Data is compressed - LABLAXIS: Compressed FILLVAL: 255 FORMAT: I1 + LABLAXIS: Compressed VALIDMAX: 1 VALIDMIN: 0 - DICT_KEY: SPASE>Support>SupportQuantity:InstrumentMode compression_width: <<: *support_default @@ -153,9 +153,9 @@ compression_width: DEPEND_0: epoch DISPLAY_TYPE: time_series FIELDNAM: Compressed data bit width - LABLAXIS: Bit width FILLVAL: 255 FORMAT: I2 + LABLAXIS: Bit width UNITS: 'bits' VALIDMAX: 21 VALIDMIN: 0 @@ -163,112 +163,112 @@ compression_width: mago_act: <<: *support_default CATDESC: MAGo Active status + DICT_KEY: SPASE>Support>SupportQuantity:Housekeeping FIELDNAM: MAGo Sensor Active - LABLAXIS: MAGo Active FILLVAL: 255 FORMAT: I1 + LABLAXIS: MAGo Active UNITS: ' ' VALIDMAX: 1 VALIDMIN: 0 - DICT_KEY: SPASE>Support>SupportQuantity:Housekeeping magi_act: <<: *support_default CATDESC: MAGi Active status + DICT_KEY: SPASE>Support>SupportQuantity:Housekeeping FIELDNAM: MAGi Sensor Active - LABLAXIS: MAGi Active FILLVAL: 255 FORMAT: I1 + LABLAXIS: MAGi Active UNITS: ' ' VALIDMAX: 1 VALIDMIN: 0 - DICT_KEY: SPASE>Support>SupportQuantity:Housekeeping pri_sens: <<: *support_default CATDESC: Indicates the primary sensor. 0 is MAGo, 1 is MAGi + DICT_KEY: SPASE>Support>SupportQuantity:InstrumentMode FIELDNAM: Primary Sensor - LABLAXIS: Primary Sensor FILLVAL: 255 FORMAT: I1 + LABLAXIS: Primary Sensor UNITS: ' ' VALIDMAX: 1 VALIDMIN: 0 - DICT_KEY: SPASE>Support>SupportQuantity:InstrumentMode pri_vecsec: <<: *support_default CATDESC: Primary vectors per second + DICT_KEY: SPASE>Support>SupportQuantity:Housekeeping FIELDNAM: Primary vectors per second - LABLAXIS: Primary Vectors FILLVAL: 0 FORMAT: I3 + LABLAXIS: Primary Vectors UNITS: 'Hz' VALIDMAX: 128 VALIDMIN: 1 - DICT_KEY: SPASE>Support>SupportQuantity:Housekeeping sec_vecsec: <<: *support_default CATDESC: Secondary vectors per second + DICT_KEY: SPASE>Support>SupportQuantity:Housekeeping FIELDNAM: Secondary vectors per second - LABLAXIS: Secondary Vectorss FILLVAL: 0 FORMAT: I3 + LABLAXIS: Secondary Vectorss UNITS: 'Hz' VALIDMAX: 128 VALIDMIN: 1 - DICT_KEY: SPASE>Support>SupportQuantity:Housekeeping pri_coarsetm: <<: *support_default CATDESC: Primary coarse time, mission SCLK in whole seconds + DICT_KEY: SPASE>Support>SupportQuantity:Temporal FIELDNAM: Primary coarse time - LABLAXIS: Primary coarse time FILLVAL: 4294967295 FORMAT: I10 + LABLAXIS: Primary coarse time UNITS: 's' VALIDMAX: 4294967295 VALIDMIN: 0 VAR_TYPE: support_data - DICT_KEY: SPASE>Support>SupportQuantity:Temporal pri_fntm: <<: *support_default CATDESC: Primary fine time, mission SCLK in 16bit subseconds + DICT_KEY: SPASE>Support>SupportQuantity:Temporal FIELDNAM: Primary fine time (16 bit subsecond) - LABLAXIS: Primary fine time FILLVAL: 65536 FORMAT: I5 + LABLAXIS: Primary fine time UNITS: ' ' VALIDMAX: 65535 VALIDMIN: 0 - DICT_KEY: SPASE>Support>SupportQuantity:Temporal sec_coarsetm: <<: *support_default CATDESC: Secondary coarse time, mission SCLK in whole seconds + DICT_KEY: SPASE>Support>SupportQuantity:Temporal FIELDNAM: Secondary coarse time - LABLAXIS: Secondary coarse time FILLVAL: 4294967295 FORMAT: I10 + LABLAXIS: Secondary coarse time UNITS: 's' VALIDMAX: 4294967295 VALIDMIN: 0 VAR_TYPE: support_data - DICT_KEY: SPASE>Support>SupportQuantity:Temporal sec_fntm: <<: *support_default CATDESC: Secondary fine time, mission SCLK in 16bit subseconds + DICT_KEY: SPASE>Support>SupportQuantity:Temporal FIELDNAM: Secondary fine time (16 bit subsecond) - LABLAXIS: Secondary fine time FILLVAL: 65536 FORMAT: I5 + LABLAXIS: Secondary fine time UNITS: ' ' VALIDMAX: 65535 VALIDMIN: 0 - DICT_KEY: SPASE>Support>SupportQuantity:Temporal vectors: <<: *raw_vectors_default @@ -281,58 +281,58 @@ vectors: version: <<: *metadata_default CATDESC: CCSDS Packet version number + DICT_KEY: SPASE>Support>SupportQuantity:HouseKeeping FIELDNAM: CCSDS Packet version number - LABLAXIS: CCSDS Packet version FILLVAL: 8 FORMAT: I1 + LABLAXIS: CCSDS Packet version UNITS: ' ' VALIDMAX: 7 VALIDMIN: 0 - DICT_KEY: SPASE>Support>SupportQuantity:HouseKeeping type: <<: *metadata_default CATDESC: CCSDS Packet type + DICT_KEY: SPASE>Support>SupportQuantity:Housekeeping FIELDNAM: CCSDS Packet type - LABLAXIS: Packet Type FILLVAL: 2 FORMAT: I1 + LABLAXIS: Packet Type UNITS: ' ' VALIDMAX: 1 VALIDMIN: 0 - DICT_KEY: SPASE>Support>SupportQuantity:Housekeeping sec_hdr_flg: <<: *metadata_default CATDESC: CCSDS Packet Secondary header flag + DICT_KEY: SPASE>Support>SupportQuantity:Housekeeping FIELDNAM: CCSDS Packet Secondary header flag - LABLAXIS: Sec header flag FILLVAL: 2 FORMAT: I1 + LABLAXIS: Sec header flag UNITS: ' ' VALIDMAX: 1 VALIDMIN: 0 - DICT_KEY: SPASE>Support>SupportQuantity:Housekeeping pkt_apid: <<: *metadata_default CATDESC: CCSDS Packet Application Process ID + DICT_KEY: SPASE>Support>SupportQuantity:Housekeeping FIELDNAM: CCSDS Packet Application Process ID - LABLAXIS: APID FILLVAL: 2048 FORMAT: H3 + LABLAXIS: APID UNITS: ' ' VALIDMAX: 2047 VALIDMIN: 0 - DICT_KEY: SPASE>Support>SupportQuantity:Housekeeping seq_flgs: <<: *metadata_default CATDESC: CCSDS Packet Grouping flags FIELDNAM: CCSDS Packet Grouping flags - LABLAXIS: Packet Grouping FILLVAL: 4 FORMAT: I1 + LABLAXIS: Packet Grouping UNITS: ' ' VALIDMAX: 3 VALIDMIN: 0 @@ -340,22 +340,22 @@ seq_flgs: src_seq_ctr: <<: *metadata_default CATDESC: CCSDS Packet Source Sequence Counter + DICT_KEY: SPASE>Support>SupportQuantity:Housekeeping FIELDNAM: CCSDS Packet Source Sequence Counter - LABLAXIS: Seq Counter FILLVAL: 16384 FORMAT: I5 + LABLAXIS: Seq Counter UNITS: ' ' VALIDMAX: 16383 VALIDMIN: 0 - DICT_KEY: SPASE>Support>SupportQuantity:Housekeeping pkt_len: <<: *metadata_default CATDESC: CCSDS Packet Length FIELDNAM: CCSDS Packet Length - LABLAXIS: Packet Length FILLVAL: 65535 FORMAT: I5 + LABLAXIS: Packet Length UNITS: ' ' VALIDMAX: 65535 - VALIDMIN: 0 \ No newline at end of file + VALIDMIN: 0 diff --git a/imap_processing/cdf/config/imap_mag_l1b_variable_attrs.yaml b/imap_processing/cdf/config/imap_mag_l1b_variable_attrs.yaml index e91eaa4bdb..5f9a5cce8f 100644 --- a/imap_processing/cdf/config/imap_mag_l1b_variable_attrs.yaml +++ b/imap_processing/cdf/config/imap_mag_l1b_variable_attrs.yaml @@ -6,25 +6,25 @@ default_attrs: &default DISPLAY_TYPE: time_series FILLVAL: -9223372036854775808 FORMAT: I12 - VALIDMIN: -9223372036854775808 + UNITS: ' ' VALIDMAX: 9223372036854775807 + VALIDMIN: -9223372036854775808 VAR_TYPE: data - UNITS: ' ' default_coords: &default_coords # Assumed values for all coordinate attrs unless overwritten - FORMAT: F2.4 # Float with 4 digits - VAR_TYPE: support_data DISPLAY_TYPE: time_series FILLVAL: -9223372036854775808 - VALIDMIN: -9223372036854775808 - VALIDMAX: 9223372036854775807 + FORMAT: F2.4 # Float with 4 digits UNITS: counts + VALIDMAX: 9223372036854775807 + VALIDMIN: -9223372036854775808 + VAR_TYPE: support_data mag_support_attrs: &support_default <<: *default - VAR_TYPE: support_data DICT_KEY: SPASE>Support>SupportQuantity:Other + VAR_TYPE: support_data mag_metadata_attrs: &metadata_default <<: *default @@ -46,26 +46,26 @@ raw_vector_attrs: &raw_vectors_default <<: *default CATDESC: Raw unprocessed magnetic field vector data in bytes DEPEND_1: direction - LABL_PTR_1: direction_label FIELDNAM: Magnetic Field Vector FORMAT: I3 + LABL_PTR_1: direction_label vector_attrs: &vectors_default <<: *default CATDESC: Magnetic field vectors with x y z and sensor range varying by time DEPEND_1: direction FIELDNAM: Magnetic Field - LABL_PTR_1: direction_label FILLVAL: 9223372036854775807 FORMAT: F12.5 + LABL_PTR_1: direction_label mag_flag_attrs: <<: *default - VALIDMIN: 0 - VALIDMAX: 1 DISPLAY_TYPE: time_series FILLVAL: 255 FORMAT: I1 + VALIDMAX: 1 + VALIDMIN: 0 raw_direction_attrs: <<: *default_coords @@ -76,45 +76,45 @@ raw_direction_attrs: direction_attrs: <<: *default_coords CATDESC: Magnetic field vector + DISPLAY_TYPE: time_series FIELDNAM: \[xyz\] magnetic field vector FORMAT: I3 - VAR_TYPE: support_data - DISPLAY_TYPE: time_series LABLAXIS: Magnetic field vector + VAR_TYPE: support_data compression_attrs: <<: *default_coords CATDESC: Data compression flag + DISPLAY_TYPE: no_plot FIELDNAM: Compression - LABLAXIS: Compressed FORMAT: I2 - VAR_TYPE: support_data + LABLAXIS: Compressed VALIDMAX: 21 VALIDMIN: 0 - DISPLAY_TYPE: no_plot + VAR_TYPE: support_data compression_flags_attrs: <<: *support_default CATDESC: Compression information per time stamp, includes a flag and the compression width - FIELDNAM: Compression information per time stamp DEPEND_0: epoch DEPEND_1: compression + DISPLAY_TYPE: no_plot + FIELDNAM: Compression information per time stamp FORMAT: I2 + LABL_PTR_1: compression_label VALIDMAX: 21 VALIDMIN: 0 - LABL_PTR_1: compression_label - DISPLAY_TYPE: no_plot compression: <<: *support_default CATDESC: Data compression flag + DICT_KEY: SPASE>Support>SupportQuantity:InstrumentMode FIELDNAM: Data is compressed - LABLAXIS: Compressed FILLVAL: 255 FORMAT: I1 + LABLAXIS: Compressed VALIDMAX: 1 VALIDMIN: 0 - DICT_KEY: SPASE>Support>SupportQuantity:InstrumentMode compression_width: <<: *support_default @@ -122,9 +122,9 @@ compression_width: DEPEND_0: epoch DISPLAY_TYPE: time_series FIELDNAM: Compressed data bit width - LABLAXIS: Bit width FILLVAL: 255 FORMAT: I2 + LABLAXIS: Bit width UNITS: 'bits' VALIDMAX: 21 VALIDMIN: 0 @@ -132,29 +132,29 @@ compression_width: pri_sens: <<: *support_default CATDESC: Indicates the primary sensor. 0 is MAGo, 1 is MAGi + DICT_KEY: SPASE>Support>SupportQuantity:InstrumentMode FIELDNAM: Primary Sensor - LABLAXIS: Primary Sensor FILLVAL: 255 FORMAT: I1 + LABLAXIS: Primary Sensor UNITS: ' ' VALIDMAX: 1 VALIDMIN: 0 - DICT_KEY: SPASE>Support>SupportQuantity:InstrumentMode vecsec: <<: *support_default CATDESC: Vectors per second + DICT_KEY: SPASE>Support>SupportQuantity:Housekeeping FIELDNAM: Vectors per second - LABLAXIS: Vectors/sec FILLVAL: 0 FORMAT: I3 + LABLAXIS: Vectors/sec UNITS: 'Hz' VALIDMAX: 128 VALIDMIN: 1 - DICT_KEY: SPASE>Support>SupportQuantity:Housekeeping vectors: <<: *vectors_default CATDESC: Magnetic field vectors with x y z and sensor range varying by time FIELDNAM: Magnetic field - LABLAXIS: Magnetic field \ No newline at end of file + LABLAXIS: Magnetic field diff --git a/imap_processing/cdf/config/imap_mag_l1c_variable_attrs.yaml b/imap_processing/cdf/config/imap_mag_l1c_variable_attrs.yaml index 0c1cbe981f..40dc5f0dfa 100644 --- a/imap_processing/cdf/config/imap_mag_l1c_variable_attrs.yaml +++ b/imap_processing/cdf/config/imap_mag_l1c_variable_attrs.yaml @@ -6,25 +6,25 @@ default_attrs: &default DISPLAY_TYPE: time_series FILLVAL: -1.0e+31 FORMAT: I12 - VALIDMIN: -9223372036854775808 + UNITS: ' ' VALIDMAX: 9223372036854775807 + VALIDMIN: -9223372036854775808 VAR_TYPE: data - UNITS: ' ' default_coords: &default_coords # Assumed values for all coordinate attrs unless overwritten - FORMAT: F2.4 # Float with 4 digits - VAR_TYPE: support_data DISPLAY_TYPE: time_series FILLVAL: -9223372036854775808 - VALIDMIN: -9223372036854775808 - VALIDMAX: 9223372036854775807 + FORMAT: F2.4 # Float with 4 digits UNITS: counts + VALIDMAX: 9223372036854775807 + VALIDMIN: -9223372036854775808 + VAR_TYPE: support_data mag_support_attrs: &support_default <<: *default - VAR_TYPE: support_data DICT_KEY: SPASE>Support>SupportQuantity:Other + VAR_TYPE: support_data mag_metadata_attrs: &metadata_default <<: *default @@ -46,26 +46,26 @@ raw_vector_attrs: &raw_vectors_default <<: *default CATDESC: Raw unprocessed magnetic field vector data in bytes DEPEND_1: direction - LABL_PTR_1: direction_label FIELDNAM: Magnetic Field Vector FORMAT: I3 + LABL_PTR_1: direction_label vector_attrs: &vectors_default <<: *default CATDESC: Magnetic field vectors with x y z and sensor range varying by time DEPEND_1: direction FIELDNAM: Magnetic Field Vector - LABL_PTR_1: direction_label FILLVAL: 9223372036854775807 FORMAT: F12.5 + LABL_PTR_1: direction_label mag_flag_attrs: <<: *default - VALIDMIN: 0 - VALIDMAX: 1 DISPLAY_TYPE: time_series FILLVAL: 255 FORMAT: I1 + VALIDMAX: 1 + VALIDMIN: 0 raw_direction_attrs: <<: *default_coords @@ -76,68 +76,68 @@ raw_direction_attrs: direction_attrs: <<: *default_coords CATDESC: Magnetic field vector + DISPLAY_TYPE: time_series FIELDNAM: \[xyz\] magnetic field vector FORMAT: I3 - VAR_TYPE: support_data - DISPLAY_TYPE: time_series LABLAXIS: Magnetic field vector + VAR_TYPE: support_data compression_attrs: <<: *default_coords CATDESC: Data compression flag + DISPLAY_TYPE: no_plot FIELDNAM: Compression - LABLAXIS: Compressed FORMAT: I2 - VAR_TYPE: support_data + LABLAXIS: Compressed VALIDMAX: 21 VALIDMIN: 0 - DISPLAY_TYPE: no_plot + VAR_TYPE: support_data compression_flags_attrs: <<: *support_default CATDESC: Compression information per time stamp, includes a flag and the compression width - FIELDNAM: Compression information per time stamp DEPEND_0: epoch DEPEND_1: compression + DISPLAY_TYPE: no_plot + FIELDNAM: Compression information per time stamp FORMAT: I2 + LABL_PTR_1: compression_label VALIDMAX: 21 VALIDMIN: 0 - LABL_PTR_1: compression_label - DISPLAY_TYPE: no_plot generated_flag_attrs: <<: *support_default CATDESC: Flag indicating data has been downsampled and interpolated from higher frequency measurements + DICT_KEY: SPASE>Support>SupportQuantity:Other FIELDNAM: Generated Flag - LABLAXIS: Generated Flag FILLVAL: 255 FORMAT: I1 + LABLAXIS: Generated Flag UNITS: ' ' VALIDMAX: 1 VALIDMIN: 0 - DICT_KEY: SPASE>Support>SupportQuantity:Other vector_magnitude_attrs: <<: *support_default CATDESC: Magnitude of the magnetic field vector + DICT_KEY: SPASE>Field>FieldQuantity:Magnetic,Qualifier:Scalar FIELDNAM: Magnetic Field Magnitude - LABLAXIS: "|B|" FORMAT: F12.5 + LABLAXIS: "|B|" UNITS: nT - VALIDMIN: 0 VALIDMAX: 9223372036854775807 - DICT_KEY: SPASE>Field>FieldQuantity:Magnetic,Qualifier:Scalar + VALIDMIN: 0 compression: <<: *support_default CATDESC: Data compression flag + DICT_KEY: SPASE>Support>SupportQuantity:InstrumentMode FIELDNAM: Data is compressed - LABLAXIS: Compressed FILLVAL: 255 FORMAT: I1 + LABLAXIS: Compressed VALIDMAX: 1 VALIDMIN: 0 - DICT_KEY: SPASE>Support>SupportQuantity:InstrumentMode compression_width: <<: *support_default @@ -145,9 +145,9 @@ compression_width: DEPEND_0: epoch DISPLAY_TYPE: time_series FIELDNAM: Compressed data bit width - LABLAXIS: Bit width FILLVAL: 255 FORMAT: I2 + LABLAXIS: Bit width UNITS: 'bits' VALIDMAX: 21 VALIDMIN: 0 @@ -155,29 +155,29 @@ compression_width: pri_sens: <<: *support_default CATDESC: Indicates the primary sensor. 0 is MAGo, 1 is MAGi + DICT_KEY: SPASE>Support>SupportQuantity:InstrumentMode FIELDNAM: Primary Sensor - LABLAXIS: Primary Sensor FILLVAL: 255 FORMAT: I1 + LABLAXIS: Primary Sensor UNITS: ' ' VALIDMAX: 1 VALIDMIN: 0 - DICT_KEY: SPASE>Support>SupportQuantity:InstrumentMode vecsec: <<: *support_default CATDESC: Vectors per second + DICT_KEY: SPASE>Support>SupportQuantity:Housekeeping FIELDNAM: Vectors per second - LABLAXIS: Vectors/sec FILLVAL: 0 FORMAT: I3 + LABLAXIS: Vectors/sec UNITS: 'Hz' VALIDMAX: 128 VALIDMIN: 1 - DICT_KEY: SPASE>Support>SupportQuantity:Housekeeping vectors: <<: *vectors_default CATDESC: Magnetic field vectors with x y z and sensor range varying by time FIELDNAM: Magnetic field - LABLAXIS: Magnetic field \ No newline at end of file + LABLAXIS: Magnetic field diff --git a/imap_processing/cdf/config/imap_mag_l2_variable_attrs.yaml b/imap_processing/cdf/config/imap_mag_l2_variable_attrs.yaml index f8063bf5f9..bb193c8280 100644 --- a/imap_processing/cdf/config/imap_mag_l2_variable_attrs.yaml +++ b/imap_processing/cdf/config/imap_mag_l2_variable_attrs.yaml @@ -6,25 +6,25 @@ default_attrs: &default DISPLAY_TYPE: time_series FILLVAL: -9223372036854775808 FORMAT: I12 - VALIDMIN: -9223372036854775808 + UNITS: ' ' VALIDMAX: 9223372036854775807 + VALIDMIN: -9223372036854775808 VAR_TYPE: data - UNITS: ' ' default_coords: &default_coords # Assumed values for all coordinate attrs unless overwritten - FORMAT: F2.4 # Float with 4 digits - VAR_TYPE: support_data DISPLAY_TYPE: time_series FILLVAL: -9223372036854775808 - VALIDMIN: -9223372036854775808 - VALIDMAX: 9223372036854775807 + FORMAT: F2.4 # Float with 4 digits UNITS: counts + VALIDMAX: 9223372036854775807 + VALIDMIN: -9223372036854775808 + VAR_TYPE: support_data mag_support_attrs: &support_default <<: *default - VAR_TYPE: support_data DICT_KEY: SPASE>Support>SupportQuantity:Other + VAR_TYPE: support_data mag_metadata_attrs: &metadata_default <<: *default @@ -45,70 +45,108 @@ compression_label: vector_attrs: &vectors_default <<: *default CATDESC: Magnetic field vectors with x y z varying by time + CDF_DATA_TYPE: CDF_FLOAT DEPEND_1: direction + DICT_KEY: "SPASE>Field>FieldQuantity:Magnetic,Qualifier:Vector,CoordinateSystemName:DSRF,CoordinateRepresentation:Cartesian" FIELDNAM: Magnetic Field Vector - LABL_PTR_1: direction_label FILLVAL: 9223372036854775807 FORMAT: F12.5 + LABL_PTR_1: direction_label + +# Frame-specific vector attributes +vector_attrs_srf: + <<: *vectors_default + CATDESC: Magnetic field vectors with x y z varying by time in Spacecraft Reference Frame + DICT_KEY: "SPASE>Field>FieldQuantity:Magnetic,Qualifier:Vector,CoordinateSystemName:SRF,CoordinateRepresentation:Cartesian" + +vector_attrs_dsrf: + <<: *vectors_default + CATDESC: Magnetic field vectors with x y z varying by time in Despun Spacecraft Reference Frame DICT_KEY: "SPASE>Field>FieldQuantity:Magnetic,Qualifier:Vector,CoordinateSystemName:DSRF,CoordinateRepresentation:Cartesian" +vector_attrs_gse: + <<: *vectors_default + CATDESC: Magnetic field vectors with x y z varying by time in Geocentric Solar Ecliptic Reference Frame + DICT_KEY: "SPASE>Field>FieldQuantity:Magnetic,Qualifier:Vector,CoordinateSystemName:GSE,CoordinateRepresentation:Cartesian" + +vector_attrs_gsm: + <<: *vectors_default + CATDESC: Magnetic field vectors with x y z varying by time in Geocentric Solar Magnetospheric Reference Frame + DICT_KEY: "SPASE>Field>FieldQuantity:Magnetic,Qualifier:Vector,CoordinateSystemName:GSM,CoordinateRepresentation:Cartesian" + +vector_attrs_rtn: + <<: *vectors_default + CATDESC: Magnetic field vectors with r t n varying by time in Radial-Tangential-Normal Reference Frame + DICT_KEY: "SPASE>Field>FieldQuantity:Magnetic,Qualifier:Vector,CoordinateSystemName:RTN,CoordinateRepresentation:Cartesian" + direction_attrs: <<: *default_coords CATDESC: Magnetic field vector + DICT_KEY: SPASE>Support>SupportQuantity:Orientation + DISPLAY_TYPE: time_series FIELDNAM: \[xyz\] magnetic field vector FORMAT: I3 - VAR_TYPE: support_data - DISPLAY_TYPE: time_series LABLAXIS: Magnetic field vector - DICT_KEY: SPASE>Support>SupportQuantity:Orientation + VAR_TYPE: support_data -# TODO: Add magnitude and range attributes, remove this -fill: +magnitude: <<: *support_default - CATDESC: Compression bit width - DEPEND_0: epoch - DISPLAY_TYPE: time_series - FIELDNAM: Compressed data bit width - LABLAXIS: Bit width + CATDESC: Magnitude of the magnetic field vector + CDF_DATA_TYPE: CDF_FLOAT + DICT_KEY: SPASE>Field>FieldQuantity:Magnetic,Qualifier:Scalar + FIELDNAM: Magnetic Field Magnitude + FILLVAL: -1.0e+31 + FORMAT: F12.5 + LABLAXIS: "|B|" + UNITS: nT + VALIDMAX: 1.0e+5 + VALIDMIN: 0 + +range: + <<: *support_default + CATDESC: Sensor range setting + CDF_DATA_TYPE: CDF_UINT1 + DICT_KEY: SPASE>Support>SupportQuantity:InstrumentMode + FIELDNAM: Sensor Range FILLVAL: 255 - FORMAT: I2 - UNITS: 'bits' - VALIDMAX: 21 + FORMAT: I1 + LABLAXIS: Range + UNITS: ' ' + VALIDMAX: 3 VALIDMIN: 0 - DICT_KEY: SPASE>Support>SupportQuantity:Other pri_sens: <<: *support_default CATDESC: Indicates the primary sensor. 0 is MAGo, 1 is MAGi + DICT_KEY: SPASE>Support>SupportQuantity:InstrumentMode FIELDNAM: Primary Sensor - LABLAXIS: Primary Sensor FILLVAL: 255 FORMAT: I1 + LABLAXIS: Primary Sensor UNITS: ' ' VALIDMAX: 1 VALIDMIN: 0 - DICT_KEY: SPASE>Support>SupportQuantity:InstrumentMode qf_bitmask: <<: *support_default CATDESC: Eight-bit Data quality bitmask + DICT_KEY: SPASE>Support>SupportQuantity:DataQuality FIELDNAM: Quality Flag - LABLAXIS: QF FILLVAL: 255 FORMAT: I3 + LABLAXIS: QF VALIDMAX: 255 VALIDMIN: 0 - DICT_KEY: SPASE>Support>SupportQuantity:DataQuality qf: <<: *support_default CATDESC: Data quality flag + DICT_KEY: SPASE>Support>SupportQuantity:DataQuality FIELDNAM: Quality Flag - LABLAXIS: QF FILLVAL: 255 FORMAT: I1 + LABLAXIS: QF VALIDMAX: 1 VALIDMIN: 0 - DICT_KEY: SPASE>Support>SupportQuantity:DataQuality diff --git a/imap_processing/cdf/config/imap_spacecraft_variable_attrs.yaml b/imap_processing/cdf/config/imap_spacecraft_variable_attrs.yaml index 05feb178b5..c06ce16dc9 100644 --- a/imap_processing/cdf/config/imap_spacecraft_variable_attrs.yaml +++ b/imap_processing/cdf/config/imap_spacecraft_variable_attrs.yaml @@ -3,16 +3,16 @@ default_attrs: &default DEPEND_0: epoch DISPLAY_TYPE: time_series FORMAT: I12 + SCALE_TYPE: linear UNITS: " " VAR_TYPE: data - SCALE_TYPE: linear default_float32_attrs: &default_float32_attrs <<: *default FILLVAL: .NAN FORMAT: F7.6 - VALIDMIN: -1 VALIDMAX: 1 + VALIDMIN: -1 dtype: float32 quat_x: diff --git a/imap_processing/cdf/config/imap_swapi_global_cdf_attrs.yaml b/imap_processing/cdf/config/imap_swapi_global_cdf_attrs.yaml index e13976da38..e137cb56a5 100644 --- a/imap_processing/cdf/config/imap_swapi_global_cdf_attrs.yaml +++ b/imap_processing/cdf/config/imap_swapi_global_cdf_attrs.yaml @@ -1,5 +1,6 @@ instrument_base: &instrument_base Descriptor: SWAPI>Solar Wind and Pickup Ion + Instrument_type: Particles (space) TEXT: > The Solar Wind and Pickup Ion (SWAPI) instrument measures several different elements of the solar wind, including hydrogen (H) and helium (He) ions, @@ -8,7 +9,6 @@ instrument_base: &instrument_base data contains primary, secondary, coincidence counts per ESA voltage step and time. Level-2 data contains the same data as level-1 but counts are converted to rates by dividing counts by time. - Instrument_type: Particles (space) imap_swapi_l1_sci: <<: *instrument_base diff --git a/imap_processing/cdf/config/imap_swapi_variable_attrs.yaml b/imap_processing/cdf/config/imap_swapi_variable_attrs.yaml index 879da48e05..5a94f6f84a 100644 --- a/imap_processing/cdf/config/imap_swapi_variable_attrs.yaml +++ b/imap_processing/cdf/config/imap_swapi_variable_attrs.yaml @@ -1,6 +1,7 @@ # <=== Coordinates ===> esa_step: CATDESC: Energy step id in lookup table + DICT_KEY: "SPASE>Support>SupportQuantity:Other" FIELDNAM: Energy Step FILLVAL: 255 FORMAT: I2 @@ -10,7 +11,6 @@ esa_step: VALIDMAX: 71 VALIDMIN: 0 VAR_TYPE: support_data - DICT_KEY: "SPASE>Support>SupportQuantity:Other" # <=== LABL_PTR_i Attributes ===> esa_step_label: @@ -23,32 +23,32 @@ esa_step_label: counts_default: &counts_default DEPEND_0: epoch DEPEND_1: esa_step + DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:Counts,Qualifier:Array DISPLAY_TYPE: spectrogram - LABL_PTR_1: esa_step_label - FILLVAL: 65535 + FILLVAL: -1.0000000E+31 FORMAT: I5 + LABL_PTR_1: esa_step_label + SCALETYP: linear UNITS: counts - VALIDMIN: 0 VALIDMAX: 65535 + VALIDMIN: 0 VAR_TYPE: data - SCALETYP: linear - DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:Counts,Qualifier:Array flags_default: CATDESC: Bitwise flag. There are 13 flags. See VAR_NOTES for more details. - FIELDNAM: Quality Flag - LABLAXIS: Flags DEPEND_0: epoch DEPEND_1: esa_step + DICT_KEY: SPASE>Support>SupportQuantity:EncodedParameter DISPLAY_TYPE: spectrogram - LABL_PTR_1: esa_step_label + FIELDNAM: Quality Flag FILLVAL: 65535 FORMAT: I5 + LABLAXIS: Flags + LABL_PTR_1: esa_step_label + SCALETYP: linear UNITS: ' ' - VALIDMIN: 0 VALIDMAX: 8191 - VAR_TYPE: data - SCALETYP: linear + VALIDMIN: 0 VAR_NOTES: > There are 13 flags in total, first three flags are from science packets and remaining 10 flags are from housekeeping packets. Flags are stored @@ -57,118 +57,107 @@ flags_default: Then, the remaining 13 bits from right are used for 13 flags. The flags are as follows, "OVR_T_ST", "UND_T_ST", "PCEM_CNT_ST", "SCEM_CNT_ST","PCEM_V_ST", "PCEM_I_ST", "PCEM_INT_ST", "SCEM_V_ST", "SCEM_I_ST", "SCEM_INT_ST". - DICT_KEY: SPASE>Support>SupportQuantity:EncodedParameter + VAR_TYPE: data counts_uncertainty_default: &counts_uncertainty_default DEPEND_0: epoch DEPEND_1: esa_step + DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:Counts,Qualifier:Uncertainty DISPLAY_TYPE: spectrogram - LABL_PTR_1: esa_step_label FILLVAL: -1.0000000E+31 FORMAT: E19.5 + LABL_PTR_1: esa_step_label + SCALETYP: linear UNITS: counts - VALIDMIN: 0.0 VALIDMAX: 1.7976931348623157e+308 # TODO: find actual value + VALIDMIN: 0.0 VAR_TYPE: data - SCALETYP: linear - DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:Counts,Qualifier:Uncertainty rate_uncertainty_default: &rate_uncertainty_default DEPEND_0: epoch DEPEND_1: esa_step + DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:CountRate,Qualifier:Uncertainty DISPLAY_TYPE: spectrogram - LABL_PTR_1: esa_step_label FILLVAL: -1.0000000E+31 FORMAT: E19.5 + LABL_PTR_1: esa_step_label + SCALETYP: linear UNITS: counts + VALIDMAX: 4.519655172413793E+05 # 65535 counts / 0.145 s livetime VALIDMIN: 0.0 - VALIDMAX: 1.7976931348623157e+308 # TODO: find actual value VAR_TYPE: data - SCALETYP: linear - DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:CountRate,Qualifier:Uncertainty rate_default: &rate_default DEPEND_0: epoch DEPEND_1: esa_step + DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:CountRate,Qualifier:Average DISPLAY_TYPE: spectrogram - LABL_PTR_1: esa_step_label FILLVAL: -1.0000000E+31 FORMAT: E19.5 - UNITS: counts + LABL_PTR_1: esa_step_label + SCALETYP: linear + UNITS: counts/s + VALIDMAX: 4.519655172413793E+05 # 65535 counts / 0.145 s livetime VALIDMIN: 0.0 - VALIDMAX: 1.7976931348623157e+308 # TODO: find actual value VAR_TYPE: data - SCALETYP: linear - DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:CountRate,Qualifier:Average esa_energy: CATDESC: ESA Energy. - FIELDNAM: ESA Energy - LABLAXIS: Energy(eV) DEPEND_0: epoch DEPEND_1: esa_step - LABL_PTR_1: esa_step_label + DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:EnergyPerCharge + FIELDNAM: ESA Energy FILLVAL: -9223372036854775808 FORMAT: I5 + LABLAXIS: Energy(eV) + LABL_PTR_1: esa_step_label + SCALETYP: linear UNITS: eV / q - VALIDMIN: 0 VALIDMAX: 65535 + VALIDMIN: 0 VAR_TYPE: support_data - SCALETYP: linear - DICT_KEY: SPASE>Particle>ParticleType:Ion,ParticleQuantity:EnergyPerCharge metadata_default: &metadata_default DEPEND_0: epoch + DICT_KEY: SPASE>Support>SupportQuantity:Other FILLVAL: 65535 FORMAT: I5 + SCALETYP: linear UNITS: " " - VALIDMIN: 0 VALIDMAX: 65535 + VALIDMIN: 0 VAR_TYPE: support_data - SCALETYP: linear - DICT_KEY: SPASE>Support>SupportQuantity:Other sci_start_time: - CATDESC: Start time of sweep + CATDESC: Start time of sweep in UTC DEPEND_0: epoch + DICT_KEY: "SPASE>Support>SupportQantity:Temporal" FIELDNAM: Science Start time - LABLAXIS: sci_start_time - FILLVAL: -9223372036854775808 - FORMAT: " " # Supposedly not required, fails in xarray_to_cdf - VALIDMIN: -9223372036854775808 - VALIDMAX: 9223372036854775807 - UNITS: ns + FORMAT: A23 VAR_TYPE: support_data - SCALETYP: linear - MONOTON: INCREASE - TIME_BASE: J2000 - TIME_SCALE: Terrestrial Time - REFERENCE_POSITION: Rotating Earth Geoid - RESOLUTION: ' ' - DICT_KEY: "SPASE>Support>SupportQantity:Temporal" # Minimum attrs setting for HK data hk_attrs: &hk_attrs CATDESC: Housekeeping data - FIELDNAM: Housekeeping - LABLAXIS: Values DEPEND_0: epoch + DICT_KEY: SPASE>Support>SupportQuantity:Other + FIELDNAM: Housekeeping FILLVAL: -9223372036854775808 FORMAT: I19 + LABLAXIS: Values + SCALETYP: linear UNITS: " " - VALIDMIN: 0 VALIDMAX: 9223372036854775807 + VALIDMIN: 0 VAR_TYPE: support_data - SCALETYP: linear - DICT_KEY: SPASE>Support>SupportQuantity:Other # L1B HK data attrs for data with string values l1b_hk_string_attrs: &l1b_hk_string_attrs CATDESC: Housekeeping derived data + DEPEND_0: epoch FIELDNAM: Housekeeing Human Readable State FORMAT: A80 VAR_TYPE: metadata - DEPEND_0: epoch pcem_counts: <<: *counts_default diff --git a/imap_processing/cdf/config/imap_swe_global_cdf_attrs.yaml b/imap_processing/cdf/config/imap_swe_global_cdf_attrs.yaml index f2b2dcbfac..d473399263 100644 --- a/imap_processing/cdf/config/imap_swe_global_cdf_attrs.yaml +++ b/imap_processing/cdf/config/imap_swe_global_cdf_attrs.yaml @@ -1,12 +1,12 @@ instrument_base: &instrument_base Descriptor: SWE>Solar Wind Electron + Instrument_type: "Particles (space)" TEXT: > The IMAP Solar Wind Electron (SWE) instrument measures the solar wind electrons in the heliosphere. SWE will contribute to our understanding of the acceleration and transport of charged particles in the heliosphere. SWE design and assembly is led by the Princeton Plasma Physics Laboratory. See https://imap.princeton.edu/instruments/swe for more details. - Instrument_type: "Particles (space)" imap_swe_l1a_sci: <<: *instrument_base diff --git a/imap_processing/cdf/config/imap_swe_l1a_variable_attrs.yaml b/imap_processing/cdf/config/imap_swe_l1a_variable_attrs.yaml index 20bb957f08..7207e0a09b 100644 --- a/imap_processing/cdf/config/imap_swe_l1a_variable_attrs.yaml +++ b/imap_processing/cdf/config/imap_swe_l1a_variable_attrs.yaml @@ -49,46 +49,46 @@ cem_id_label: default_attrs: &default DEPEND_0: epoch DISPLAY_TYPE: 'no_plot' - LABLAXIS: ' ' FILLVAL: -9223372036854775808 FORMAT: I19 + LABLAXIS: ' ' + SCALETYP: linear UNITS: ' ' - VALIDMIN: 0 VALIDMAX: 9223372036854769664 + VALIDMIN: 0 VAR_TYPE: support_data - SCALETYP: linear raw_counts: CATDESC: Raw Counts stored in 8bits length DEPEND_0: epoch DEPEND_1: spin_sector DEPEND_2: cem_id - LABL_PTR_1: spin_sector_label - LABL_PTR_2: cem_id_label DISPLAY_TYPE: spectrogram FIELDNAM: Raw Counts + FILLVAL: -9223372036854775808 FORMAT: I3 + LABL_PTR_1: spin_sector_label + LABL_PTR_2: cem_id_label + SCALETYP: linear UNITS: counts VALIDMAX: 255 VALIDMIN: 0 - FILLVAL: -9223372036854775808 VAR_TYPE: data - SCALETYP: linear science_data: CATDESC: Decompressed Counts DEPEND_0: epoch DEPEND_1: spin_sector DEPEND_2: cem_id - LABL_PTR_1: spin_sector_label - LABL_PTR_2: cem_id_label DISPLAY_TYPE: spectrogram FIELDNAM: Decompressed Counts + FILLVAL: -9223372036854775808 FORMAT: I5 + LABL_PTR_1: spin_sector_label + LABL_PTR_2: cem_id_label UNITS: counts VALIDMAX: 66539 VALIDMIN: 0 - FILLVAL: -9223372036854775808 VAR_TYPE: data shcoarse: @@ -239,12 +239,12 @@ cksum: non_science_attrs: CATDESC: SWE data DEPEND_0: epoch + DISPLAY_TYPE: time_series FIELDNAM: SWE Raw Data FILLVAL: -9223372036854775808 FORMAT: I19 - UNITS: ' ' LABLAXIS: Values - VALIDMIN: 0 + UNITS: ' ' VALIDMAX: 9223372036854769664 + VALIDMIN: 0 VAR_TYPE: support_data - DISPLAY_TYPE: time_series diff --git a/imap_processing/cdf/config/imap_swe_l1b_variable_attrs.yaml b/imap_processing/cdf/config/imap_swe_l1b_variable_attrs.yaml index fa0d2769b4..f322006e19 100644 --- a/imap_processing/cdf/config/imap_swe_l1b_variable_attrs.yaml +++ b/imap_processing/cdf/config/imap_swe_l1b_variable_attrs.yaml @@ -79,15 +79,15 @@ cycle_label: default_attrs: &default DEPEND_0: epoch DEPEND_1: cycle - LABL_PTR_1: cycle_label DISPLAY_TYPE: time_series FILLVAL: -9223372036854775808 FORMAT: I20 + LABL_PTR_1: cycle_label + SCALETYP: linear UNITS: " " - VALIDMIN: 0 VALIDMAX: 9223372036854769664 + VALIDMIN: 0 VAR_TYPE: support_data - SCALETYP: linear science_data: CATDESC: Electron count rates organized by voltage step and spin sector and CEM @@ -95,73 +95,76 @@ science_data: DEPEND_1: esa_step DEPEND_2: spin_sector DEPEND_3: cem_id - LABL_PTR_1: esa_step_label - LABL_PTR_2: spin_sector_label - LABL_PTR_3: cem_id_label DISPLAY_TYPE: spectrogram FIELDNAM: Counts rate by volt step and spin sector and CEM - FORMAT: E14.7 FILLVAL: -9223372036854775808 + FORMAT: E14.7 + LABL_PTR_1: esa_step_label + LABL_PTR_2: spin_sector_label + LABL_PTR_3: cem_id_label UNITS: counts/sec VALIDMAX: 0.000015514 VALIDMIN: 0 - VAR_TYPE: data VAR_NOTES: > Metadata field acq_duration is 17 uint. Max value of uint17 is 131071. Dividing max counts by acq_duration gave validmax + VAR_TYPE: data counts_stat_uncert: CATDESC: Counts statistical uncertainty - FIELDNAM: Counts Stats Uncertainty DEPEND_0: epoch DEPEND_1: esa_step DEPEND_2: spin_sector DEPEND_3: cem_id - LABL_PTR_1: esa_step_label - LABL_PTR_2: spin_sector_label - LABL_PTR_3: cem_id_label + DICT_KEY: SPASE>Particle>ParticleType:Electron,ParticleQuantity:Counts,Qualifier:Uncertainty DISPLAY_TYPE: spectrogram + FIELDNAM: Counts Stats Uncertainty FILLVAL: -1.0000000E+31 FORMAT: E19.5 + LABL_PTR_1: esa_step_label + LABL_PTR_2: spin_sector_label + LABL_PTR_3: cem_id_label + SCALETYP: linear UNITS: counts - VALIDMIN: 0.0 VALIDMAX: 1.7976931348623157e+308 # TODO: find actual value + VALIDMIN: 0.0 VAR_TYPE: data - SCALETYP: linear - DICT_KEY: SPASE>Particle>ParticleType:Electron,ParticleQuantity:Counts,Qualifier:Uncertainty acquisition_time: CATDESC: Acquisition time organized by voltage step and spin sector DEPEND_0: epoch DEPEND_1: esa_step DEPEND_2: spin_sector - LABL_PTR_1: esa_step_label - LABL_PTR_2: spin_sector_label DISPLAY_TYPE: spectrogram FIELDNAM: Acquisition time by volt step and spin sector FILLVAL: -9223372036854775808 + FORMAT: I10 + LABL_PTR_1: esa_step_label + LABL_PTR_2: spin_sector_label UNITS: sec - VAR_TYPE: support_data + VALIDMAX: 3155716869184000000 # 2100-01-01T00:00:00 mission end + VALIDMIN: 315576066184000000 # 2010-01-01T00:00:00 mission start (APL 0 epoch) VAR_NOTES: > This stores the acquisition times of each measurement. This time is calculated by combining ACQ_START_COARSE, ACQ_START_FINE, acquisition duration and settle duration. It is time of each energy step and each science measurement. + VAR_TYPE: support_data acq_duration: CATDESC: Acquisition duration DEPEND_0: epoch DEPEND_1: esa_step DEPEND_2: spin_sector - LABL_PTR_1: esa_step_label - LABL_PTR_2: spin_sector_label DISPLAY_TYPE: spectrogram FIELDNAM: Acquisition Duration - FORMAT: I10 - VALIDMIN: 0 - VALIDMAX: 4290000000 FILLVAL: -9223372036854775808 + FORMAT: I10 + LABL_PTR_1: esa_step_label + LABL_PTR_2: spin_sector_label UNITS: microseconds + VALIDMAX: 4290000000 + VALIDMIN: 0 VAR_TYPE: support_data esa_energy: @@ -169,12 +172,12 @@ esa_energy: DEPEND_0: epoch DEPEND_1: esa_step DEPEND_2: spin_sector - LABL_PTR_1: esa_step_label - LABL_PTR_2: spin_sector_label DISPLAY_TYPE: time_series FIELDNAM: ESA Energies - FORMAT: E14.7 FILLVAL: -9223372036854775808 + FORMAT: E14.7 + LABL_PTR_1: esa_step_label + LABL_PTR_2: spin_sector_label UNITS: eV VALIDMAX: 65535 VALIDMIN: 0.000015514 @@ -238,17 +241,17 @@ spin_phase: <<: *default CATDESC: Spin phase FIELDNAM: Spin Phase + FILLVAL: -9223372036854775808 FORMAT: E14.7 VALIDMAX: 65535 - FILLVAL: -9223372036854775808 spin_period: <<: *default CATDESC: Spin period FIELDNAM: Spin Period + FILLVAL: -9223372036854775808 FORMAT: E14.7 VALIDMAX: 65535 - FILLVAL: -9223372036854775808 repoint_warning: <<: *default @@ -301,9 +304,9 @@ threshold_dac: <<: *default CATDESC: Threshold DAC value FIELDNAM: Threshold DAC Value + FILLVAL: -9223372036854775808 FORMAT: E14.7 VALIDMAX: 65535 - FILLVAL: -9223372036854775808 stim_cfg_reg: <<: *default @@ -321,24 +324,45 @@ cksum: FORMAT: I5 VALIDMAX: 65535 +data_quality: + CATDESC: > + In-flight calibration quality flags. Bit 2 (LAST_CAL_INTERVAL): set if any + acquisition time in this cycle was extrapolated using the last two entries + in the calibration table. + DEPEND_0: epoch + DICT_KEY: SPASE>Support>SupportQuantity:DataQuality + DISPLAY_TYPE: time_series + FIELDNAM: SWE data quality flags + FILLVAL: 255 + FORMAT: I3 + SCALETYP: linear + UNITS: " " + VALIDMAX: 255 + VALIDMIN: 0 + VAR_NOTES: > + There is 1 flag currently in use. Stored as a bitwise flag. Bit 2 + (LAST_CAL_INTERVAL, value 4): counter values were extrapolated using the last two + calibration table entries. All other bits are reserved. + VAR_TYPE: support_data + # <=== HK Variables ===> # L1B HK data attrs for data with string values l1b_hk_string_attrs: CATDESC: Housekeeping derived data + DEPEND_0: epoch FIELDNAM: Housekeeing Human Readable State FORMAT: A80 VAR_TYPE: metadata - DEPEND_0: epoch l1b_hk_attrs: CATDESC: SWE HK data - FIELDNAM: SWE Housekeeping Data - LABLAXIS: Values DEPEND_0: epoch + DISPLAY_TYPE: time_series + FIELDNAM: SWE Housekeeping Data FILLVAL: -9223372036854775808 FORMAT: I19 + LABLAXIS: Values UNITS: ' ' - VALIDMIN: 0 VALIDMAX: 9223372036854769664 + VALIDMIN: 0 VAR_TYPE: support_data - DISPLAY_TYPE: time_series diff --git a/imap_processing/cdf/config/imap_swe_l2_variable_attrs.yaml b/imap_processing/cdf/config/imap_swe_l2_variable_attrs.yaml index 446defa4f3..c61e8494bc 100644 --- a/imap_processing/cdf/config/imap_swe_l2_variable_attrs.yaml +++ b/imap_processing/cdf/config/imap_swe_l2_variable_attrs.yaml @@ -45,11 +45,11 @@ inst_az: UNITS: Degree VALIDMAX: 359.999 VALIDMIN: 0.00 - VAR_TYPE: support_data VAR_NOTES: > Bin CENTERS - Assuming 0.5 sec measurements and a spin starting at Angle=0, these are the angles at the middle of each measurement bin. + VAR_TYPE: support_data cem_id: CATDESC: CEM detector number @@ -132,17 +132,17 @@ inst_az_spin_sector: DEPEND_0: epoch DEPEND_1: esa_step DEPEND_2: spin_sector - LABL_PTR_1: esa_step_label - LABL_PTR_2: spin_sector_label + DICT_KEY: SPASE>Support>SupportQuantity:SpinPhase,Qualifier:Array,CoordinateSystemName:SC,CoordinateRepresentation:Spherical DISPLAY_TYPE: spectrogram FIELDNAM: Spin Angle FILLVAL: -1.0E+31 FORMAT: E10.5 + LABL_PTR_1: esa_step_label + LABL_PTR_2: spin_sector_label UNITS: Degree VALIDMAX: 359.99 VALIDMIN: 0.0 VAR_TYPE: data - DICT_KEY: SPASE>Support>SupportQuantity:SpinPhase,Qualifier:Array,CoordinateSystemName:SC,CoordinateRepresentation:Spherical phase_space_density_spin_sector: CATDESC: Phase space density organized by ESA step and spin sector and CEM @@ -150,18 +150,18 @@ phase_space_density_spin_sector: DEPEND_1: esa_step DEPEND_2: spin_sector DEPEND_3: cem_id - LABL_PTR_1: esa_step_label - LABL_PTR_2: spin_sector_label - LABL_PTR_3: cem_id_label + DICT_KEY: SPASE>Particle>ParticleType:Electron,ParticleQuantity:PhaseSpaceDensity,Qualifier:Array DISPLAY_TYPE: spectrogram FIELDNAM: Phase Space Density FILLVAL: -1.0E+31 - UNITS: s^3 / cm^6 FORMAT: E14.7 + LABL_PTR_1: esa_step_label + LABL_PTR_2: spin_sector_label + LABL_PTR_3: cem_id_label + UNITS: s^3 / cm^6 VALIDMAX: 0.000000000000001 VALIDMIN: 0.0 VAR_TYPE: data - DICT_KEY: SPASE>Particle>ParticleType:Electron,ParticleQuantity:PhaseSpaceDensity,Qualifier:Array phase_space_density: @@ -170,18 +170,18 @@ phase_space_density: DEPEND_1: energy DEPEND_2: inst_az DEPEND_3: inst_el - LABL_PTR_1: energy_label - LABL_PTR_2: inst_az_label - LABL_PTR_3: inst_el_label + DICT_KEY: SPASE>Particle>ParticleType:Electron,ParticleQuantity:PhaseSpaceDensity,Qualifier:Array DISPLAY_TYPE: spectrogram FIELDNAM: Phase Space Density FILLVAL: -1.0E+31 - UNITS: s^3 / cm^6 FORMAT: E14.7 + LABL_PTR_1: energy_label + LABL_PTR_2: inst_az_label + LABL_PTR_3: inst_el_label + UNITS: s^3 / cm^6 VALIDMAX: 1.0E-15 VALIDMIN: 0.0 VAR_TYPE: data - DICT_KEY: SPASE>Particle>ParticleType:Electron,ParticleQuantity:PhaseSpaceDensity,Qualifier:Array flux_spin_sector: CATDESC: Number flux organized by ESA step and spin sector and CEM @@ -189,18 +189,18 @@ flux_spin_sector: DEPEND_1: esa_step DEPEND_2: spin_sector DEPEND_3: cem_id - LABL_PTR_1: esa_step_label - LABL_PTR_2: spin_sector_label - LABL_PTR_3: cem_id_label + DICT_KEY: SPASE>Particle>ParticleType:Electron,ParticleQuantity:NumberFlux,Qualifier:Array DISPLAY_TYPE: spectrogram FIELDNAM: Flux FILLVAL: -1.0E+31 - UNITS: 1 / (2 * eV * cm^2 * s * ster) FORMAT: E14.7 + LABL_PTR_1: esa_step_label + LABL_PTR_2: spin_sector_label + LABL_PTR_3: cem_id_label + UNITS: 1 / (2 * eV * cm^2 * s * ster) VALIDMAX: 1.0E+9 VALIDMIN: 0.0 VAR_TYPE: data - DICT_KEY: SPASE>Particle>ParticleType:Electron,ParticleQuantity:NumberFlux,Qualifier:Array flux: CATDESC: Number flux organized by energy (eV), spin angle, CEM angle @@ -208,94 +208,115 @@ flux: DEPEND_1: energy DEPEND_2: inst_az DEPEND_3: inst_el - LABL_PTR_1: energy_label - LABL_PTR_2: inst_az_label - LABL_PTR_3: inst_el_label + DICT_KEY: SPASE>Particle>ParticleType:Electron,ParticleQuantity:NumberFlux,Qualifier:Array DISPLAY_TYPE: spectrogram FIELDNAM: Flux FILLVAL: -1.0E+31 - UNITS: 1 / (2 * eV * cm^2 * s * ster) FORMAT: E14.7 + LABL_PTR_1: energy_label + LABL_PTR_2: inst_az_label + LABL_PTR_3: inst_el_label + UNITS: 1 / (2 * eV * cm^2 * s * ster) VALIDMAX: 1.0E+9 VALIDMIN: 0.0 VAR_TYPE: data - DICT_KEY: SPASE>Particle>ParticleType:Electron,ParticleQuantity:NumberFlux,Qualifier:Array psd_stat_uncert: CATDESC: Phase space density statistical uncertainty - FIELDNAM: Phase Space Density Stats Uncertainty DEPEND_0: epoch DEPEND_1: esa_step DEPEND_2: spin_sector DEPEND_3: cem_id - LABL_PTR_1: esa_step_label - LABL_PTR_2: spin_sector_label - LABL_PTR_3: cem_id_label + DICT_KEY: SPASE>Particle>ParticleType:Electron,ParticleQuantity:Counts,Qualifier:Uncertainty DISPLAY_TYPE: spectrogram + FIELDNAM: Phase Space Density Stats Uncertainty FILLVAL: -1.0000000E+31 FORMAT: E19.5 + LABL_PTR_1: esa_step_label + LABL_PTR_2: spin_sector_label + LABL_PTR_3: cem_id_label + SCALETYP: linear UNITS: counts - VALIDMIN: 0.0 VALIDMAX: 1.7976931348623157e+308 # TODO: find actual value + VALIDMIN: 0.0 VAR_TYPE: data - SCALETYP: linear - DICT_KEY: SPASE>Particle>ParticleType:Electron,ParticleQuantity:Counts,Qualifier:Uncertainty flux_stat_uncert: CATDESC: Flux statistical uncertainty - FIELDNAM: Flux Stats Uncertainty DEPEND_0: epoch DEPEND_1: esa_step DEPEND_2: spin_sector DEPEND_3: cem_id - LABL_PTR_1: esa_step_label - LABL_PTR_2: spin_sector_label - LABL_PTR_3: cem_id_label + DICT_KEY: SPASE>Particle>ParticleType:Electron,ParticleQuantity:Counts,Qualifier:Uncertainty DISPLAY_TYPE: spectrogram + FIELDNAM: Flux Stats Uncertainty FILLVAL: -1.0000000E+31 FORMAT: E19.5 + LABL_PTR_1: esa_step_label + LABL_PTR_2: spin_sector_label + LABL_PTR_3: cem_id_label + SCALETYP: linear UNITS: counts - VALIDMIN: 0.0 VALIDMAX: 1.7976931348623157e+308 # TODO: find actual value + VALIDMIN: 0.0 VAR_TYPE: data - SCALETYP: linear - DICT_KEY: SPASE>Particle>ParticleType:Electron,ParticleQuantity:Counts,Qualifier:Uncertainty acquisition_time: CATDESC: Acquisition time organized by ESA step and spin sector DEPEND_0: epoch DEPEND_1: esa_step DEPEND_2: spin_sector - LABL_PTR_1: esa_step_label - LABL_PTR_2: spin_sector_label + DICT_KEY: SPASE>Support>SupportQuantity:Temporal,Qualifier:Array DISPLAY_TYPE: spectrogram FIELDNAM: Acquisition time by ESA step and spin sector FILLVAL: -1.0E+31 FORMAT: E20.4 + LABL_PTR_1: esa_step_label + LABL_PTR_2: spin_sector_label + UNITS: sec VALIDMAX: 9223372036854775807 VALIDMIN: 0 - UNITS: sec - VAR_TYPE: support_data VAR_NOTES: > This stores the acquisition times of each measurement. This time is calculated by combining ACQ_START_COARSE, ACQ_START_FINE, acquisition duration and settle duration. It is center time of each science measurement (each energy and angle step). - DICT_KEY: SPASE>Support>SupportQuantity:Temporal,Qualifier:Array + VAR_TYPE: support_data acq_duration: CATDESC: Acquisition duration DEPEND_0: epoch DEPEND_1: esa_step DEPEND_2: spin_sector - LABL_PTR_1: esa_step_label - LABL_PTR_2: spin_sector_label + DICT_KEY: SPASE>Support>SupportQuantity:Temporal,Qualifier:Array DISPLAY_TYPE: spectrogram FIELDNAM: Acquisition Duration - FORMAT: I10 - VALIDMIN: 0 - VALIDMAX: 4290000000 FILLVAL: -9223372036854775808 + FORMAT: I10 + LABL_PTR_1: esa_step_label + LABL_PTR_2: spin_sector_label UNITS: microseconds + VALIDMAX: 4290000000 + VALIDMIN: 0 + VAR_TYPE: support_data + +data_quality: + CATDESC: > + In-flight calibration quality flags. Bit 2 (LAST_CAL_INTERVAL): set if any + acquisition time in this cycle was extrapolated using the last two entries + in the calibration table. + DEPEND_0: epoch + DICT_KEY: SPASE>Support>SupportQuantity:DataQuality + DISPLAY_TYPE: time_series + FIELDNAM: SWE data quality flags + FILLVAL: 255 + FORMAT: I3 + SCALETYP: linear + UNITS: " " + VALIDMAX: 255 + VALIDMIN: 0 + VAR_NOTES: > + There is 1 flag currently in use. Stored as a bitwise flag. Bit 2 + (LAST_CAL_INTERVAL, value 4): counter values were extrapolated using the last two + calibration table entries. All other bits are reserved. VAR_TYPE: support_data - DICT_KEY: SPASE>Support>SupportQuantity:Temporal,Qualifier:Array diff --git a/imap_processing/cdf/config/imap_ultra_global_cdf_attrs.yaml b/imap_processing/cdf/config/imap_ultra_global_cdf_attrs.yaml index 1f6cf51a95..3abc0144e7 100644 --- a/imap_processing/cdf/config/imap_ultra_global_cdf_attrs.yaml +++ b/imap_processing/cdf/config/imap_ultra_global_cdf_attrs.yaml @@ -1,12 +1,12 @@ instrument_base: &instrument_base Descriptor: Ultra>IMAP Ultra-Energy (IMAP-Ultra) Energetic Neutral Atom Imager + Instrument_type: "Particles (space)" TEXT: > Ultra captures images of very energetic neutral atoms, particularly hydrogen (H) atoms, produced in the solar system at the heliosheath, the region where the solar wind slows, compresses, and becomes much hotter as it meets the interstellar medium (ISM). The instrument also measures the distribution of solar wind electrons and protons, and the magnetic field. See https://imap.princeton.edu/instruments/ultra for more details. - Instrument_type: "Particles (space)" imap_ultra_l1a_45sensor-aux: <<: *instrument_base @@ -68,28 +68,28 @@ imap_ultra_l1a_90sensor-histogram-ena-extof-hi-ang: Logical_source: imap_ultra_l1a_90sensor-histogram-ena-extof-hi-ang Logical_source_description: IMAP-Ultra Instrument Level-1A ExTOF Hi Angular Data. -imap_ultra_l1a_45sensor-histogram-ena-extof-hi-time: +imap_ultra_l1a_45sensor-histogram-ion-extof-hi-time: <<: *instrument_base Data_type: L1A_Histogram>Level-1A ExTOF - Logical_source: imap_ultra_l1a_45sensor-histogram-ena-extof-hi-time + Logical_source: imap_ultra_l1a_45sensor-histogram-ion-extof-hi-time Logical_source_description: IMAP-Ultra Instrument Level-1A ExTOF Hi Time Data. -imap_ultra_l1a_90sensor-histogram-ena-extof-hi-time: +imap_ultra_l1a_90sensor-histogram-ion-extof-hi-time: <<: *instrument_base Data_type: L1A_Histogram>Level-1A ExTOF - Logical_source: imap_ultra_l1a_90sensor-histogram-ena-extof-hi-time + Logical_source: imap_ultra_l1a_90sensor-histogram-ion-extof-hi-time Logical_source_description: IMAP-Ultra Instrument Level-1A ExTOF Hi Time Data. -imap_ultra_l1a_45sensor-histogram-ena-extof-hi-nrg: +imap_ultra_l1a_45sensor-histogram-ion-extof-hi-nrg: <<: *instrument_base Data_type: L1A_Histogram>Level-1A ExTOF - Logical_source: imap_ultra_l1a_45sensor-histogram-ena-extof-hi-nrg + Logical_source: imap_ultra_l1a_45sensor-histogram-ion-extof-hi-nrg Logical_source_description: IMAP-Ultra Instrument Level-1A ExTOF Hi Energy Data. -imap_ultra_l1a_90sensor-histogram-ena-extof-hi-nrg: +imap_ultra_l1a_90sensor-histogram-ion-extof-hi-nrg: <<: *instrument_base Data_type: L1A_Histogram>Level-1A ExTOF - Logical_source: imap_ultra_l1a_90sensor-histogram-ena-extof-hi-nrg + Logical_source: imap_ultra_l1a_90sensor-histogram-ion-extof-hi-nrg Logical_source_description: IMAP-Ultra Instrument Level-1A ExTOF Hi Energy Data. imap_ultra_l1a_45sensor-rates: @@ -212,6 +212,54 @@ imap_ultra_l1b_90sensor-de: Logical_source: imap_ultra_l1b_90sensor-de Logical_source_description: IMAP-Ultra Instrument Level-1B Direct Event Data. +imap_ultra_l1b_45sensor-priority-1-de: + <<: *instrument_base + Data_type: L1B_PRIORITY_1_DE>Level-1B Priority 1 Direct Event + Logical_source: imap_ultra_l1b_45sensor-priority-1-de + Logical_source_description: IMAP-Ultra Instrument Level-1B Priority 1 Direct Event Data. + +imap_ultra_l1b_90sensor-priority-1-de: + <<: *instrument_base + Data_type: L1B_PRIORITY_1_DE>Level-1B Priority 1 Direct Event + Logical_source: imap_ultra_l1b_90sensor-priority-1-de + Logical_source_description: IMAP-Ultra Instrument Level-1B Priority 1 Direct Event Data. + +imap_ultra_l1b_45sensor-priority-2-de: + <<: *instrument_base + Data_type: L1B_PRIORITY_2_DE>Level-1B Priority 2 Direct Event + Logical_source: imap_ultra_l1b_45sensor-priority-2-de + Logical_source_description: IMAP-Ultra Instrument Level-1B Priority 2 Direct Event Data. + +imap_ultra_l1b_90sensor-priority-2-de: + <<: *instrument_base + Data_type: L1B_PRIORITY_2_DE>Level-1B Priority 2 Direct Event + Logical_source: imap_ultra_l1b_90sensor-priority-2-de + Logical_source_description: IMAP-Ultra Instrument Level-1B Priority 2 Direct Event Data. + +imap_ultra_l1b_45sensor-priority-3-de: + <<: *instrument_base + Data_type: L1B_PRIORITY_3_DE>Level-1B Priority 3 Direct Event + Logical_source: imap_ultra_l1b_45sensor-priority-3-de + Logical_source_description: IMAP-Ultra Instrument Level-1B Priority 3 Direct Event Data. + +imap_ultra_l1b_90sensor-priority-3-de: + <<: *instrument_base + Data_type: L1B_PRIORITY_3_DE>Level-1B Priority 3 Direct Event + Logical_source: imap_ultra_l1b_90sensor-priority-3-de + Logical_source_description: IMAP-Ultra Instrument Level-1B Priority 3 Direct Event Data. + +imap_ultra_l1b_45sensor-priority-4-de: + <<: *instrument_base + Data_type: L1B_PRIORITY_4_DE>Level-1B Priority 4 Direct Event + Logical_source: imap_ultra_l1b_45sensor-priority-4-de + Logical_source_description: IMAP-Ultra Instrument Level-1B Priority 4 Direct Event Data. + +imap_ultra_l1b_90sensor-priority-4-de: + <<: *instrument_base + Data_type: L1B_PRIORITY_4_DE>Level-1B Priority 4 Direct Event + Logical_source: imap_ultra_l1b_90sensor-priority-4-de + Logical_source_description: IMAP-Ultra Instrument Level-1B Priority 4 Direct Event Data. + imap_ultra_l1b_45sensor-extendedspin: <<: *instrument_base Data_type: L1B_45Sensor-ExtendedSpin>Level-1B Extended Spin for Ultra45 @@ -224,17 +272,17 @@ imap_ultra_l1b_90sensor-extendedspin: Logical_source: imap_ultra_l1b_90sensor-extendedspin Logical_source_description: IMAP-Ultra Instrument Level-1B Extended Spin Data. -imap_ultra_l1b_45sensor-cullingmask: +imap_ultra_l1b_45sensor-goodtimes: <<: *instrument_base - Data_type: L1B_45Sensor-CullingMask>Level-1B Culling Mask for Ultra45 - Logical_source: imap_ultra_l1b_45sensor-cullingmask - Logical_source_description: IMAP-Ultra Instrument Level-1B Culling Mask Data. + Data_type: L1B_45Sensor-Goodtimes>Level-1B Goodtimes for Ultra45 + Logical_source: imap_ultra_l1b_45sensor-goodtimes + Logical_source_description: IMAP-Ultra Instrument Level-1B Goodtimes Data. -imap_ultra_l1b_90sensor-cullingmask: +imap_ultra_l1b_90sensor-goodtimes: <<: *instrument_base - Data_type: L1B_90Sensor-CullingMask>Level-1B Culling Mask for Ultra90 - Logical_source: imap_ultra_l1b_90sensor-cullingmask - Logical_source_description: IMAP-Ultra Instrument Level-1B Culling Mask Data. + Data_type: L1B_90Sensor-Goodtimes>Level-1B Goodtimes for Ultra90 + Logical_source: imap_ultra_l1b_90sensor-goodtimes + Logical_source_description: IMAP-Ultra Instrument Level-1B Goodtimes Data. imap_ultra_l1b_45sensor-badtimes: <<: *instrument_base @@ -260,6 +308,18 @@ imap_ultra_l1c_90sensor-spacecraftpset: Logical_source: imap_ultra_l1c_90sensor-spacecraftpset Logical_source_description: IMAP-Ultra Instrument Level-1C Spacecraft Pointing Set Grid. +imap_ultra_l1c_45sensor-spacecraftpset-nonproton: + <<: *instrument_base + Data_type: L1C_45Sensor-PSET>Level-1C Pointing Set Grid for Ultra45 + Logical_source: imap_ultra_l1c_45sensor-spacecraftpset-nonproton + Logical_source_description: IMAP-Ultra Instrument Level-1C Spacecraft Pointing Set Grid for Non-Proton Species. + +imap_ultra_l1c_90sensor-spacecraftpset-nonproton: + <<: *instrument_base + Data_type: L1C_90Sensor-PSET>Level-1C Pointing Set Grid for Ultra90 + Logical_source: imap_ultra_l1c_90sensor-spacecraftpset-nonproton + Logical_source_description: IMAP-Ultra Instrument Level-1C Spacecraft Pointing Set Grid for Non-Proton Species. + imap_ultra_l1c_45sensor-heliopset: <<: *instrument_base Data_type: L1C_45Sensor-PSET>Level-1C Pointing Set Grid for Ultra45 diff --git a/imap_processing/cdf/config/imap_ultra_l1a_variable_attrs.yaml b/imap_processing/cdf/config/imap_ultra_l1a_variable_attrs.yaml index ddd5484be9..d939a79758 100644 --- a/imap_processing/cdf/config/imap_ultra_l1a_variable_attrs.yaml +++ b/imap_processing/cdf/config/imap_ultra_l1a_variable_attrs.yaml @@ -5,2010 +5,2013 @@ default_attrs: &default DISPLAY_TYPE: time_series FILLVAL: -9223372036854775808 FORMAT: I12 - VALIDMIN: -9223372036854775808 + UNITS: " " VALIDMAX: 9223372036854775807 + VALIDMIN: -9223372036854775808 VAR_TYPE: data - UNITS: " " default_uint8_attrs: &default_uint8 <<: *default FILLVAL: 255 FORMAT: I3 - VALIDMIN: 0 VALIDMAX: 255 + VALIDMIN: 0 dtype: uint8 default_uint16_attrs: &default_uint16 <<: *default FILLVAL: 65535 FORMAT: I5 - VALIDMIN: 0 VALIDMAX: 65535 + VALIDMIN: 0 dtype: uint16 default_uint32_attrs: &default_uint32 <<: *default FILLVAL: 4294967295 FORMAT: I10 - VALIDMIN: 0 VALIDMAX: 4294967295 + VALIDMIN: 0 dtype: uint32 default_int64_attrs: &default_int64 <<: *default FILLVAL: -9223372036854775808 FORMAT: I20 - VALIDMIN: -9223372036854775808 VALIDMAX: 9223372036854775807 + VALIDMIN: -9223372036854775808 dtype: int64 default_int32_attrs: &default_int32 <<: *default FILLVAL: -2147483648 FORMAT: I10 - VALIDMIN: -2147483648 VALIDMAX: 2147483647 + VALIDMIN: -2147483648 dtype: int32 default_float32_attrs: &default_float32 <<: *default FILLVAL: -1.0e31 FORMAT: F10.2 - VALIDMIN: -3.4028235e+38 VALIDMAX: 3.4028235e+38 + VALIDMIN: -3.4028235e+38 dtype: float32 default_float64_attrs: &default_float64 <<: *default FILLVAL: -1.0e31 FORMAT: F10.2 - VALIDMIN: -1.7976931348623157e+308 VALIDMAX: 1.7976931348623157e+308 + VALIDMIN: -1.7976931348623157e+308 dtype: float64 shcoarse: <<: *default_uint32 CATDESC: CCSDS mission elapsed time (SHCOARSE=MET). 32-bit integer value that represents the MET in seconds. + DEPEND_0: epoch FIELDNAM: Mission Elapsed Time(MET) LABLAXIS: CCSDS MET UNITS: sec VAR_TYPE: support_data - DEPEND_0: epoch sid: <<: *default_uint8 CATDESC: Science ID (always totals 8). + DEPEND_0: epoch FIELDNAM: SID LABLAXIS: SID UNITS: " " - DEPEND_0: epoch ssd_sum: <<: *default_uint32 CATDESC: SSD Energy Sum. + DEPEND_0: epoch FIELDNAM: ssd_sum LABLAXIS: ssd energy sum UNITS: " " - DEPEND_0: epoch ssd0_energy_led: <<: *default_uint32 CATDESC: SSD0 Energy LED. + DEPEND_0: epoch FIELDNAM: ssd0_energy_led LABLAXIS: ssd0 energy led UNITS: " " - DEPEND_0: epoch ssd1_energy_led: <<: *default_uint32 CATDESC: SSD1 Energy LED. + DEPEND_0: epoch FIELDNAM: ssd1_energy_led LABLAXIS: ssd1 energy led UNITS: " " - DEPEND_0: epoch ssd2_energy_led: <<: *default_uint32 CATDESC: SSD2 Energy LED. + DEPEND_0: epoch FIELDNAM: ssd2_energy_led LABLAXIS: ssd2 energy led UNITS: " " - DEPEND_0: epoch ssd3_energy_led: <<: *default_uint32 CATDESC: SSD3 Energy LED. + DEPEND_0: epoch FIELDNAM: ssd3_energy_led LABLAXIS: ssd3 energy led UNITS: " " - DEPEND_0: epoch ssd4_energy_led: <<: *default_uint32 CATDESC: SSD4 Energy LED. + DEPEND_0: epoch FIELDNAM: ssd4_energy_led LABLAXIS: ssd4 energy led UNITS: " " - DEPEND_0: epoch ssd5_energy_led: <<: *default_uint32 CATDESC: SSD5 Energy LED. + DEPEND_0: epoch FIELDNAM: ssd5_energy_led LABLAXIS: ssd5 energy led UNITS: " " - DEPEND_0: epoch ssd6_energy_led: <<: *default_uint32 CATDESC: SSD6 Energy LED. + DEPEND_0: epoch FIELDNAM: ssd6_energy_led LABLAXIS: ssd6 energy led UNITS: " " - DEPEND_0: epoch ssd7_energy_led: <<: *default_uint32 CATDESC: SSD7 Energy LED. + DEPEND_0: epoch FIELDNAM: ssd7_energy_led LABLAXIS: ssd7 energy led UNITS: " " - DEPEND_0: epoch processed_events: <<: *default_uint32 CATDESC: Processed Events. + DEPEND_0: epoch FIELDNAM: processed_events LABLAXIS: processed events UNITS: " " - DEPEND_0: epoch spin: <<: *default_uint32 CATDESC: Spin number. + DEPEND_0: epoch FIELDNAM: spin_number LABLAXIS: spin number UNITS: " " - DEPEND_0: epoch abortflag: <<: *default_uint8 CATDESC: Flag for integration aborted. + DEPEND_0: epoch FIELDNAM: abortflag LABLAXIS: abortflag UNITS: " " - DEPEND_0: epoch startdelay: <<: *default_uint8 CATDESC: Integration start delay. + DEPEND_0: epoch FIELDNAM: startdelay LABLAXIS: startdelay UNITS: "ms" - DEPEND_0: epoch count: <<: *default CATDESC: Counts for a spin. + DEPEND_0: epoch FIELDNAM: counts LABLAXIS: counts # TODO: come back to format UNITS: counts - DEPEND_0: epoch version: <<: *default_uint8 CATDESC: CCSDS packet version number + DEPEND_0: epoch FIELDNAM: CCSDS version VAR_TYPE: support_data - DEPEND_0: epoch type: <<: *default_uint8 CATDESC: CCSDS packet type + DEPEND_0: epoch FIELDNAM: CCSDS type VAR_TYPE: support_data - DEPEND_0: epoch alarmtype: <<: *default_uint8 CATDESC: Alarm type + DEPEND_0: epoch FIELDNAM: alarm type VAR_TYPE: alarm_type - DEPEND_0: epoch sec_hdr_flg: <<: *default_uint8 CATDESC: CCSDS secondary header flag + DEPEND_0: epoch FIELDNAM: CCSDS secondary header flag VAR_TYPE: support_data - DEPEND_0: epoch pkt_apid: <<: *default_uint16 CATDESC: CCSDS application process ID + DEPEND_0: epoch FIELDNAM: CCSDS APID VAR_TYPE: support_data - DEPEND_0: epoch seq_flgs: <<: *default_uint8 CATDESC: CCSDS sequence flags + DEPEND_0: epoch FIELDNAM: CCSDS sequence flags VAR_TYPE: support_data - DEPEND_0: epoch src_seq_ctr: <<: *default_uint16 CATDESC: CCSDS source sequence counter + DEPEND_0: epoch FIELDNAM: CCSDS sequence counter VAR_TYPE: support_data - DEPEND_0: epoch pkt_len: <<: *default_uint16 CATDESC: CCSDS packet length + DEPEND_0: epoch FIELDNAM: CCSDS packet length VAR_TYPE: support_data - DEPEND_0: epoch coin_type: <<: *default_uint8 CATDESC: Coincidence Type + DEPEND_0: epoch FIELDNAM: Coin Type LABLAXIS: coin_type UNITS: " " - DEPEND_0: epoch start_type: <<: *default_uint8 CATDESC: Start Type + DEPEND_0: epoch FIELDNAM: Start Type LABLAXIS: start_type UNITS: " " - DEPEND_0: epoch stop_type: <<: *default_uint8 CATDESC: Stop Type + DEPEND_0: epoch FIELDNAM: Stop Type LABLAXIS: stop_type UNITS: " " - DEPEND_0: epoch start_pos_tdc: <<: *default_uint32 CATDESC: Start Position Time to Digital Converter + DEPEND_0: epoch FIELDNAM: StartPosTDC LABLAXIS: start_pos_tdc UNITS: " " - DEPEND_0: epoch stop_north_tdc: <<: *default_uint32 CATDESC: Stop North Time to Digital Converter + DEPEND_0: epoch FIELDNAM: StopNorthTDC LABLAXIS: stop_north_tdc UNITS: " " - DEPEND_0: epoch stop_east_tdc: <<: *default_uint32 CATDESC: Stop East Time to Digital Converter + DEPEND_0: epoch FIELDNAM: StopEastTDC LABLAXIS: stop_east_tdc UNITS: " " - DEPEND_0: epoch stop_south_tdc: <<: *default_uint32 CATDESC: Stop South Time to Digital Converter + DEPEND_0: epoch FIELDNAM: StopSouthTDC LABLAXIS: stop_south_tdc UNITS: " " - DEPEND_0: epoch stop_west_tdc: <<: *default_uint32 CATDESC: Stop West Time to Digital Converter + DEPEND_0: epoch FIELDNAM: StopWestTDC LABLAXIS: stop_west_tdc UNITS: " " - DEPEND_0: epoch coin_north_tdc: <<: *default_uint32 CATDESC: Coincidence North Time to Digital Converter + DEPEND_0: epoch FIELDNAM: CoinNorthTDC LABLAXIS: coin_north_tdc UNITS: " " - DEPEND_0: epoch coin_south_tdc: <<: *default_uint32 CATDESC: Coincidence South Time to Digital Converter + DEPEND_0: epoch FIELDNAM: CoinSouthTDC LABLAXIS: coin_south_tdc UNITS: " " - DEPEND_0: epoch coin_discrete_tdc: <<: *default_uint32 CATDESC: Coincidence Discrete Time to Digital Converter + DEPEND_0: epoch FIELDNAM: CoinDiscreteTDC LABLAXIS: coin_discrete_tdc UNITS: " " - DEPEND_0: epoch energy_ph: <<: *default_uint32 CATDESC: Energy or Pulse Height + DEPEND_0: epoch FIELDNAM: EnergyOrPH LABLAXIS: energy_ph UNITS: " " - DEPEND_0: epoch pulse_width: <<: *default_uint32 CATDESC: Pulse Width + DEPEND_0: epoch FIELDNAM: PulseWidth LABLAXIS: pulse_width UNITS: " " - DEPEND_0: epoch event_flag_cnt: <<: *default_uint8 CATDESC: Event Flag Count + DEPEND_0: epoch FIELDNAM: CnT LABLAXIS: event_flag_cnt UNITS: " " - DEPEND_0: epoch event_flag_phcmpsl: <<: *default_uint8 CATDESC: Event Flag PHCmpSL + DEPEND_0: epoch FIELDNAM: PHCmpSL LABLAXIS: event_flag_phcmpsl UNITS: " " - DEPEND_0: epoch event_flag_phcmpsr: <<: *default_uint8 CATDESC: Event Flag PHCmpSR + DEPEND_0: epoch FIELDNAM: PHCmpSR LABLAXIS: event_flag_phcmpsr UNITS: " " - DEPEND_0: epoch event_flag_phcmpcd: <<: *default_uint8 CATDESC: Event Flag PHCmpCD + DEPEND_0: epoch FIELDNAM: PHCmpCD LABLAXIS: event_flag_phcmpcd UNITS: " " - DEPEND_0: epoch ssd_flag_7: <<: *default_uint8 CATDESC: SSD Flag 7 + DEPEND_0: epoch FIELDNAM: SSDS7 LABLAXIS: ssd_flag_7 UNITS: " " - DEPEND_0: epoch ssd_flag_6: <<: *default_uint8 CATDESC: SSD Flag 6 + DEPEND_0: epoch FIELDNAM: SSDS6 LABLAXIS: ssd_flag_6 UNITS: " " - DEPEND_0: epoch ssd_flag_5: <<: *default_uint8 CATDESC: SSD Flag 5 + DEPEND_0: epoch FIELDNAM: SSDS5 LABLAXIS: ssd_flag_5 UNITS: " " - DEPEND_0: epoch ssd_flag_4: <<: *default_uint8 CATDESC: SSD Flag 4 + DEPEND_0: epoch FIELDNAM: SSDS4 LABLAXIS: ssd_flag_4 UNITS: " " - DEPEND_0: epoch ssd_flag_3: <<: *default_uint8 CATDESC: SSD Flag 3 + DEPEND_0: epoch FIELDNAM: SSDS3 LABLAXIS: ssd_flag_3 UNITS: " " - DEPEND_0: epoch ssd_flag_2: <<: *default_uint8 CATDESC: SSD Flag 2 + DEPEND_0: epoch FIELDNAM: SSDS2 LABLAXIS: ssd_flag_2 UNITS: " " - DEPEND_0: epoch ssd_flag_1: <<: *default_uint8 CATDESC: SSD Flag 1 + DEPEND_0: epoch FIELDNAM: SSDS1 LABLAXIS: ssd_flag_1 UNITS: " " - DEPEND_0: epoch ssd_flag_0: <<: *default_uint8 CATDESC: SSD Flag 0 + DEPEND_0: epoch FIELDNAM: SSDS0 LABLAXIS: ssd_flag_0 UNITS: " " - DEPEND_0: epoch cfd_flag_cointn: <<: *default_uint8 CATDESC: CFD Coincidence Flag Top North + DEPEND_0: epoch FIELDNAM: CFDCoinTN LABLAXIS: cfd_flag_cointn UNITS: " " - DEPEND_0: epoch cfd_flag_coinbn: <<: *default_uint8 CATDESC: CFD Coincidence Flag Bottom North + DEPEND_0: epoch FIELDNAM: CFDCoinBN LABLAXIS: cfd_flag_coinbn UNITS: " " - DEPEND_0: epoch cfd_flag_coints: <<: *default_uint8 CATDESC: CFD Coincidence Flag Top South + DEPEND_0: epoch FIELDNAM: CFDCoinTS LABLAXIS: cfd_flag_coints UNITS: " " - DEPEND_0: epoch cfd_flag_coinbs: <<: *default_uint8 CATDESC: CFD Coincidence Flag Bottom South + DEPEND_0: epoch FIELDNAM: CFDCoinBS LABLAXIS: cfd_flag_coinbs UNITS: " " - DEPEND_0: epoch cfd_flag_coind: <<: *default_uint8 CATDESC: CFD Coincidence Flag Discrete + DEPEND_0: epoch FIELDNAM: CFDCoinD LABLAXIS: cfd_flag_coind UNITS: " " - DEPEND_0: epoch cfd_flag_startrf: <<: *default_uint8 CATDESC: CFD Start Right Full Flag + DEPEND_0: epoch FIELDNAM: CFDStartRF LABLAXIS: cfd_flag_startrf UNITS: " " - DEPEND_0: epoch cfd_flag_startlf: <<: *default_uint8 CATDESC: CFD Start Left Full Flag + DEPEND_0: epoch FIELDNAM: CFDStartLF LABLAXIS: cfd_flag_startlf UNITS: " " - DEPEND_0: epoch cfd_flag_startrp: <<: *default_uint8 CATDESC: CFD Start Position Right Flag + DEPEND_0: epoch FIELDNAM: CFDStartRP LABLAXIS: cfd_flag_startrp UNITS: " " - DEPEND_0: epoch cfd_flag_startlp: <<: *default_uint8 CATDESC: CFD Start Position Left Flag + DEPEND_0: epoch FIELDNAM: CFDStartLP LABLAXIS: cfd_flag_startlp UNITS: " " - DEPEND_0: epoch cfd_flag_stoptn: <<: *default_uint8 CATDESC: CFD Stop Top North Flag + DEPEND_0: epoch FIELDNAM: CFDStopTN LABLAXIS: cfd_flag_stoptn UNITS: " " - DEPEND_0: epoch cfd_flag_stopbn: <<: *default_uint8 CATDESC: CFD Stop Bottom North Flag + DEPEND_0: epoch FIELDNAM: CFDStopBN LABLAXIS: cfd_flag_stopbn UNITS: " " - DEPEND_0: epoch cfd_flag_stopte: <<: *default_uint8 CATDESC: CFD Stop Top East Flag + DEPEND_0: epoch FIELDNAM: CFDStopTE LABLAXIS: cfd_flag_stopte UNITS: " " - DEPEND_0: epoch cfd_flag_stopbe: <<: *default_uint8 CATDESC: CFD Stop Bottom East Flag + DEPEND_0: epoch FIELDNAM: CFDStopBE LABLAXIS: cfd_flag_stopbe UNITS: " " - DEPEND_0: epoch cfd_flag_stopts: <<: *default_uint8 CATDESC: CFD Stop Top South Flag + DEPEND_0: epoch FIELDNAM: CFDStopTS LABLAXIS: cfd_flag_stopts UNITS: " " - DEPEND_0: epoch cfd_flag_stopbs: <<: *default_uint8 CATDESC: CFD Stop Bottom South Flag + DEPEND_0: epoch FIELDNAM: CFDStopBS LABLAXIS: cfd_flag_stopbs UNITS: " " - DEPEND_0: epoch cfd_flag_stoptw: <<: *default_uint8 CATDESC: CFD Stop Top West Flag + DEPEND_0: epoch FIELDNAM: CFDStopTW LABLAXIS: cfd_flag_stoptw UNITS: " " - DEPEND_0: epoch cfd_flag_stopbw: <<: *default_uint8 CATDESC: CFD Stop Bottom West Flag + DEPEND_0: epoch FIELDNAM: CFDStopBW LABLAXIS: cfd_flag_stopbw UNITS: " " - DEPEND_0: epoch bin: <<: *default_uint32 CATDESC: Event bin index + DEPEND_0: epoch FIELDNAM: Bin LABLAXIS: bin UNITS: " " - DEPEND_0: epoch phase_angle: <<: *default_uint32 CATDESC: Phase angle + DEPEND_0: epoch FIELDNAM: PhaseAngle LABLAXIS: phase_angle UNITS: degrees - DEPEND_0: epoch p00: <<: *default_uint32 CATDESC: Starting pixel + DEPEND_0: epoch FIELDNAM: Starting pixel LABLAXIS: p00 UNITS: " " - DEPEND_0: epoch packetdata: <<: *default_uint32 CATDESC: Image Packet Data + DEPEND_0: epoch FIELDNAM: Image Packet Data LABLAXIS: packetdata UNITS: " " - DEPEND_0: epoch fastdata_00: <<: *default_uint32 CATDESC: Fast-compressed rate data + DEPEND_0: epoch FIELDNAM: Fast-compressed rate data LABLAXIS: fastdata_00 UNITS: " " - DEPEND_0: epoch start_rf: <<: *default_uint32 CATDESC: Start Right Full CFD Pulses + DEPEND_0: epoch FIELDNAM: StartRF LABLAXIS: start_rf UNITS: " " - DEPEND_0: epoch start_lf: <<: *default_uint32 CATDESC: Start Left Full CFD Pulses + DEPEND_0: epoch FIELDNAM: StartLF LABLAXIS: start_lf UNITS: " " - DEPEND_0: epoch start_rp: <<: *default_uint32 CATDESC: Start Position Right CFD Pulses + DEPEND_0: epoch FIELDNAM: StartRP LABLAXIS: start_rp UNITS: " " - DEPEND_0: epoch start_lp: <<: *default_uint32 CATDESC: Start Position Left CFD Pulses + DEPEND_0: epoch FIELDNAM: StartLP LABLAXIS: start_lp UNITS: " " - DEPEND_0: epoch stop_tn: <<: *default_uint32 CATDESC: Stop Top North CFD Pulses + DEPEND_0: epoch FIELDNAM: StopTN LABLAXIS: stop_tn UNITS: " " - DEPEND_0: epoch stop_bn: <<: *default_uint32 CATDESC: Stop Bottom North CFD Pulses + DEPEND_0: epoch FIELDNAM: StopBN LABLAXIS: stop_bn UNITS: " " - DEPEND_0: epoch stop_te: <<: *default_uint32 CATDESC: Stop Top East CFD Pulses + DEPEND_0: epoch FIELDNAM: StopTE LABLAXIS: stop_te UNITS: " " - DEPEND_0: epoch stop_be: <<: *default_uint32 CATDESC: Stop Bottom East CFD Pulses + DEPEND_0: epoch FIELDNAM: StopBE LABLAXIS: stop_be UNITS: " " - DEPEND_0: epoch stop_ts: <<: *default_uint32 CATDESC: Stop Top South CFD Pulses + DEPEND_0: epoch FIELDNAM: StopTS LABLAXIS: stop_ts UNITS: " " - DEPEND_0: epoch stop_bs: <<: *default_uint32 CATDESC: Stop Bottom South CFD Pulses + DEPEND_0: epoch FIELDNAM: StopBS LABLAXIS: stop_bs UNITS: " " - DEPEND_0: epoch stop_tw: <<: *default_uint32 CATDESC: Stop Top West CFD Pulses + DEPEND_0: epoch FIELDNAM: StopTW LABLAXIS: stop_tw UNITS: " " - DEPEND_0: epoch stop_bw: <<: *default_uint32 CATDESC: Stop Bottom West CFD Pulses + DEPEND_0: epoch FIELDNAM: StopBW LABLAXIS: stop_bw UNITS: " " - DEPEND_0: epoch coin_tn: <<: *default_uint32 CATDESC: Coincidence Top North CFD Pulses + DEPEND_0: epoch FIELDNAM: CoinTN LABLAXIS: coin_tn UNITS: " " - DEPEND_0: epoch coin_bn: <<: *default_uint32 CATDESC: Coincidence Bottom North CFD Pulses + DEPEND_0: epoch FIELDNAM: CoinBN LABLAXIS: coin_bn UNITS: " " - DEPEND_0: epoch coin_ts: <<: *default_uint32 CATDESC: Coincidence Top South CFD Pulses + DEPEND_0: epoch FIELDNAM: CoinTS LABLAXIS: coin_ts UNITS: " " - DEPEND_0: epoch coin_bs: <<: *default_uint32 CATDESC: Coincidence Bottom South CFD Pulses + DEPEND_0: epoch FIELDNAM: CoinBS LABLAXIS: coin_bs UNITS: " " - DEPEND_0: epoch coin_d: <<: *default_uint32 CATDESC: Coincidence Discrete CFD Pulses + DEPEND_0: epoch FIELDNAM: CoinD LABLAXIS: coin_d UNITS: " " - DEPEND_0: epoch ssd0: <<: *default_uint32 CATDESC: SSD Energy Pulses 0 + DEPEND_0: epoch FIELDNAM: SSD0 LABLAXIS: ssd0 UNITS: " " - DEPEND_0: epoch ssd1: <<: *default_uint32 CATDESC: SSD Energy Pulses 1 + DEPEND_0: epoch FIELDNAM: SSD1 LABLAXIS: ssd1 UNITS: " " - DEPEND_0: epoch ssd2: <<: *default_uint32 CATDESC: SSD Energy Pulses 2 + DEPEND_0: epoch FIELDNAM: SSD2 LABLAXIS: ssd2 UNITS: " " - DEPEND_0: epoch ssd3: <<: *default_uint32 CATDESC: SSD Energy Pulses 3 + DEPEND_0: epoch FIELDNAM: SSD3 LABLAXIS: ssd3 UNITS: " " - DEPEND_0: epoch ssd4: <<: *default_uint32 CATDESC: SSD Energy Pulses 4 + DEPEND_0: epoch FIELDNAM: SSD4 LABLAXIS: ssd4 UNITS: " " - DEPEND_0: epoch ssd5: <<: *default_uint32 CATDESC: SSD Energy Pulses 5 + DEPEND_0: epoch FIELDNAM: SSD5 LABLAXIS: ssd5 UNITS: " " - DEPEND_0: epoch ssd6: <<: *default_uint32 CATDESC: SSD Energy Pulses 6 + DEPEND_0: epoch FIELDNAM: SSD6 LABLAXIS: ssd6 UNITS: " " - DEPEND_0: epoch ssd7: <<: *default_uint32 CATDESC: SSD Energy Pulses 7 + DEPEND_0: epoch FIELDNAM: SSD7 LABLAXIS: ssd7 UNITS: " " - DEPEND_0: epoch start_pos: <<: *default_uint32 CATDESC: Start Position TDC VE Pulses + DEPEND_0: epoch FIELDNAM: StartPos LABLAXIS: start_pos UNITS: " " - DEPEND_0: epoch stop_n: <<: *default_uint32 CATDESC: Stop North TDC VE Pulses + DEPEND_0: epoch FIELDNAM: StopN LABLAXIS: stop_n UNITS: " " - DEPEND_0: epoch stop_e: <<: *default_uint32 CATDESC: Stop East TDC VE Pulses + DEPEND_0: epoch FIELDNAM: StopE LABLAXIS: stop_e UNITS: " " - DEPEND_0: epoch stop_s: <<: *default_uint32 CATDESC: Stop South TDC VE Pulses + DEPEND_0: epoch FIELDNAM: StopS LABLAXIS: stop_s UNITS: " " - DEPEND_0: epoch stop_w: <<: *default_uint32 CATDESC: Stop West TDC VE Pulses + DEPEND_0: epoch FIELDNAM: StopW LABLAXIS: stop_w UNITS: " " - DEPEND_0: epoch coin_n_tdc: <<: *default_uint32 CATDESC: Coincidence North TDC VE Pulses + DEPEND_0: epoch FIELDNAM: CoinNTDC LABLAXIS: coin_n_tdc UNITS: " " - DEPEND_0: epoch coin_d_tdc: <<: *default_uint32 CATDESC: Coincidence Discrete TDC VE Pulses + DEPEND_0: epoch FIELDNAM: CoinDTDC LABLAXIS: coin_d_tdc UNITS: " " - DEPEND_0: epoch coin_s_tdc: <<: *default_uint32 CATDESC: Coincidence South TDC VE Pulses + DEPEND_0: epoch FIELDNAM: CoinSTDC LABLAXIS: coin_s_tdc UNITS: " " - DEPEND_0: epoch stop_top_n: <<: *default_uint32 CATDESC: Stop Top North Valid PH Flag + DEPEND_0: epoch FIELDNAM: StopTopN LABLAXIS: stop_top_n UNITS: " " - DEPEND_0: epoch stop_bot_n: <<: *default_uint32 CATDESC: Stop Bottom North Valid PH Flag + DEPEND_0: epoch FIELDNAM: StopBotN LABLAXIS: stop_bot_n UNITS: " " - DEPEND_0: epoch start_right_stop_coin_single: <<: *default_uint32 CATDESC: Start-Right/Stop Single Coincidence + DEPEND_0: epoch FIELDNAM: StartRightStopCoinSingle LABLAXIS: start_right_stop_coin_single UNITS: " " - DEPEND_0: epoch start_left_stop_coin_single: <<: *default_uint32 CATDESC: Start-Left/Stop Single Coincidence + DEPEND_0: epoch FIELDNAM: StartLeftStopCoinSingle LABLAXIS: start_left_stop_coin_single UNITS: " " - DEPEND_0: epoch start_right_stop_coin_double: <<: *default_uint32 CATDESC: Start-Right/Stop/Coin Double Coincidence + DEPEND_0: epoch FIELDNAM: StartRightStopCoinDouble LABLAXIS: start_right_stop_coin_double UNITS: " " - DEPEND_0: epoch start_left_stop_coin_double: <<: *default_uint32 CATDESC: Start-Left/Stop/Coin Double Coincidence + DEPEND_0: epoch FIELDNAM: StartLeftStopCoinDouble LABLAXIS: start_left_stop_coin_double UNITS: " " - DEPEND_0: epoch start_stop_coin_pos: <<: *default_uint32 CATDESC: Start/Stop/Coin Position Match + DEPEND_0: epoch FIELDNAM: StartStopCoinPos LABLAXIS: start_stop_coin_pos UNITS: " " - DEPEND_0: epoch start_right_ssd_coin_d: <<: *default_uint32 CATDESC: Start-Right/SSD/Coin-D Coincidence + DEPEND_0: epoch FIELDNAM: StartRightSSDCoinD LABLAXIS: start_right_ssd_coin_d UNITS: " " - DEPEND_0: epoch start_left_ssd_coin_d: <<: *default_uint32 CATDESC: Start-Left/SSD/Coin-D Coincidence + DEPEND_0: epoch FIELDNAM: StartLeftSSDCoinD LABLAXIS: start_left_ssd_coin_d UNITS: " " - DEPEND_0: epoch event_active_time: <<: *default_uint32 CATDESC: Event Analysis Activity Time + DEPEND_0: epoch FIELDNAM: EventActiveTime LABLAXIS: event_active_time UNITS: " " - DEPEND_0: epoch fifo_valid_events: <<: *default_uint32 CATDESC: FIFO Valid Events + DEPEND_0: epoch FIELDNAM: FIFOValidEvents LABLAXIS: fifo_valid_events UNITS: " " - DEPEND_0: epoch pulser_events: <<: *default_uint32 CATDESC: Pulser Events + DEPEND_0: epoch FIELDNAM: PulserEvents LABLAXIS: pulser_events UNITS: " " - DEPEND_0: epoch window_stop_coin: <<: *default_uint32 CATDESC: Windowed Stop/Coin Coincidence + DEPEND_0: epoch FIELDNAM: WindowStopCoin LABLAXIS: window_stop_coin UNITS: " " - DEPEND_0: epoch start_left_window_stop_coin: <<: *default_uint32 CATDESC: Start Left + Window Stop/Coin Coincidence + DEPEND_0: epoch FIELDNAM: StartLeftWindowStopCoin LABLAXIS: start_left_window_stop_coin UNITS: " " - DEPEND_0: epoch start_right_window_stop_coin: <<: *default_uint32 CATDESC: Start Right + Window Stop/Coin Coincidence + DEPEND_0: epoch FIELDNAM: StartRightWindowStopCoin LABLAXIS: start_right_window_stop_coin UNITS: " " - DEPEND_0: epoch timespinstart: <<: *default_uint32 CATDESC: Spin start time (comparable to the Universal Spin Table). + DEPEND_0: epoch FIELDNAM: spin_start_time LABLAXIS: spin start time UNITS: s - DEPEND_0: epoch timespinstartsub: <<: *default_uint32 CATDESC: Spin start time subseconds (comparable to the Universal Spin Table). + DEPEND_0: epoch FIELDNAM: spin_start_time_subseconds LABLAXIS: spin start time subseconds UNITS: ms - DEPEND_0: epoch duration: <<: *default CATDESC: Spin duration. + DEPEND_0: epoch FIELDNAM: duration LABLAXIS: duration UNITS: s - DEPEND_0: epoch spinnumber: <<: *default_uint32 CATDESC: Spin number. + DEPEND_0: epoch FIELDNAM: spin_number LABLAXIS: spin number UNITS: " " - DEPEND_0: epoch timespindata: <<: *default_uint32 # TODO: get more information about this variable CATDESC: Spin data time. + DEPEND_0: epoch FIELDNAM: spin_data_time LABLAXIS: spin data time UNITS: " " - DEPEND_0: epoch spinperiod: <<: *default_uint32 CATDESC: Spin period (equivalent to the Universal Spin Table). + DEPEND_0: epoch FIELDNAM: spin_period LABLAXIS: spin_period UNITS: s - DEPEND_0: epoch spinphase: <<: *default_uint32 CATDESC: Spin Phase + DEPEND_0: epoch FIELDNAM: spin_phase LABLAXIS: spinphase UNITS: degrees - DEPEND_0: epoch spinperiodvalid: <<: *default_uint8 CATDESC: Spin period valid bit + DEPEND_0: epoch FIELDNAM: spin_period_valid LABLAXIS: spinperiodvalid UNITS: " " - DEPEND_0: epoch spinphasevalid: <<: *default_uint8 CATDESC: Spin phase valid bit + DEPEND_0: epoch FIELDNAM: spin_phase_valid LABLAXIS: spinphasevalid UNITS: " " - DEPEND_0: epoch spinperiodsource: <<: *default_uint8 CATDESC: Spin period source bit + DEPEND_0: epoch FIELDNAM: spin_period_source LABLAXIS: spinperiodsource UNITS: " " - DEPEND_0: epoch catbedheaterflag: <<: *default_uint8 CATDESC: Catbead heater flag + DEPEND_0: epoch FIELDNAM: catbedheaterflag LABLAXIS: catbedheaterflag UNITS: " " - DEPEND_0: epoch spare1: <<: *default_uint8 CATDESC: Spare + DEPEND_0: epoch FIELDNAM: spare1 LABLAXIS: spare1 UNITS: " " - DEPEND_0: epoch ints: <<: *default_uint8 CATDESC: Spins + DEPEND_0: epoch FIELDNAM: ints LABLAXIS: ints UNITS: " " - DEPEND_0: epoch intn1: <<: *default_uint8 CATDESC: Integration Multiplier 1 + DEPEND_0: epoch FIELDNAM: intn1 LABLAXIS: intn1 UNITS: " " - DEPEND_0: epoch intn2: <<: *default_uint8 CATDESC: Integration Multiplier 2 + DEPEND_0: epoch FIELDNAM: intn2 LABLAXIS: intn2 UNITS: " " - DEPEND_0: epoch spare2: <<: *default_uint8 CATDESC: Reserved + DEPEND_0: epoch FIELDNAM: spare2 LABLAXIS: spare2 UNITS: " " - DEPEND_0: epoch hwmode: <<: *default_uint8 CATDESC: Hardware mode + DEPEND_0: epoch FIELDNAM: hwmode LABLAXIS: hwmode UNITS: " " - DEPEND_0: epoch imcenb: <<: *default_uint8 CATDESC: IMCENB mode + DEPEND_0: epoch FIELDNAM: imcenb LABLAXIS: imcenb UNITS: " " - DEPEND_0: epoch leftdeflectioncharge: <<: *default_uint8 CATDESC: LEFTDEFLECTIONCHARGE mode + DEPEND_0: epoch FIELDNAM: leftdeflectioncharge LABLAXIS: leftdeflectioncharge UNITS: " " - DEPEND_0: epoch rightdeflectioncharge: <<: *default_uint8 CATDESC: RIGHTDEFLECTIONCHARGE mode + DEPEND_0: epoch FIELDNAM: rightdeflectioncharge LABLAXIS: rightdeflectioncharge UNITS: " " - DEPEND_0: epoch spare3: <<: *default_uint8 CATDESC: Spare + DEPEND_0: epoch FIELDNAM: spare3 LABLAXIS: spare3 UNITS: " " - DEPEND_0: epoch event_id: - <<: *default_int64 - CATDESC: Calculated unique event IDs as 64-bit integers. + CATDESC: Calculated unique event IDs as 50 character hex strings. + DEPEND_0: epoch FIELDNAM: event id + FILLVAL: "0x0" + FORMAT: A50 LABLAXIS: event_id + VAR_TYPE: metadata address: <<: *default_float32 CATDESC: Address + DEPEND_0: epoch FIELDNAM: address LABLAXIS: address UNITS: ' ' - DEPEND_0: epoch alarmcount: <<: *default_float32 CATDESC: Alarmcount + DEPEND_0: epoch FIELDNAM: alarmcount LABLAXIS: alarmcount UNITS: ' ' - DEPEND_0: epoch alarmid: <<: *default_float32 CATDESC: Alarmid + DEPEND_0: epoch FIELDNAM: alarmid LABLAXIS: alarmid UNITS: ' ' - DEPEND_0: epoch arguments: <<: *default_uint8 CATDESC: Arguments + DEPEND_0: epoch FIELDNAM: arguments LABLAXIS: arguments UNITS: ' ' - DEPEND_0: epoch aux: <<: *default_float32 CATDESC: Aux + DEPEND_0: epoch FIELDNAM: aux LABLAXIS: aux UNITS: ' ' - DEPEND_0: epoch baselinechannel: <<: *default_float32 CATDESC: Baselinechannel + DEPEND_0: epoch FIELDNAM: baselinechannel LABLAXIS: baselinechannel UNITS: ' ' - DEPEND_0: epoch baselinesample: <<: *default_float32 CATDESC: Baselinesample + DEPEND_0: epoch FIELDNAM: baselinesample LABLAXIS: baselinesample UNITS: ' ' - DEPEND_0: epoch baselinestate: <<: *default_float32 CATDESC: Baselinestate + DEPEND_0: epoch FIELDNAM: baselinestate LABLAXIS: baselinestate UNITS: ' ' - DEPEND_0: epoch blockno: <<: *default_float32 CATDESC: Blockno + DEPEND_0: epoch FIELDNAM: blockno LABLAXIS: blockno UNITS: ' ' - DEPEND_0: epoch bottommcp_i: <<: *default_float32 CATDESC: Bottommcp i + DEPEND_0: epoch FIELDNAM: bottommcp_i LABLAXIS: bottommcp_i UNITS: ' ' - DEPEND_0: epoch bottommcp_i_hi: <<: *default_float32 CATDESC: Bottommcp i hi + DEPEND_0: epoch FIELDNAM: bottommcp_i_hi LABLAXIS: bottommcp_i_hi UNITS: ' ' - DEPEND_0: epoch bottommcp_i_lo: <<: *default_float32 CATDESC: Bottommcp i lo + DEPEND_0: epoch FIELDNAM: bottommcp_i_lo LABLAXIS: bottommcp_i_lo UNITS: ' ' - DEPEND_0: epoch bottommcp_v: <<: *default_float32 CATDESC: Bottommcp v + DEPEND_0: epoch FIELDNAM: bottommcp_v LABLAXIS: bottommcp_v UNITS: ' ' - DEPEND_0: epoch bottommcp_v_hi: <<: *default_float32 CATDESC: Bottommcp v hi + DEPEND_0: epoch FIELDNAM: bottommcp_v_hi LABLAXIS: bottommcp_v_hi UNITS: ' ' - DEPEND_0: epoch bottommcp_v_lo: <<: *default_float32 CATDESC: Bottommcp v lo + DEPEND_0: epoch FIELDNAM: bottommcp_v_lo LABLAXIS: bottommcp_v_lo UNITS: ' ' - DEPEND_0: epoch bottommcphvfault: <<: *default_float32 CATDESC: Bottommcphvfault + DEPEND_0: epoch FIELDNAM: bottommcphvfault LABLAXIS: bottommcphvfault UNITS: ' ' - DEPEND_0: epoch bottommcphvgoal: <<: *default_float32 CATDESC: Bottommcphvgoal + DEPEND_0: epoch FIELDNAM: bottommcphvgoal LABLAXIS: bottommcphvgoal UNITS: ' ' - DEPEND_0: epoch bottommcphvilim: <<: *default_float32 CATDESC: Bottommcphvilim + DEPEND_0: epoch FIELDNAM: bottommcphvilim LABLAXIS: bottommcphvilim UNITS: ' ' - DEPEND_0: epoch bottommcphvlim: <<: *default_float32 CATDESC: Bottommcphvlim + DEPEND_0: epoch FIELDNAM: bottommcphvlim LABLAXIS: bottommcphvlim UNITS: ' ' - DEPEND_0: epoch bottommcphvmonitor: <<: *default_float32 CATDESC: Bottommcphvmonitor + DEPEND_0: epoch FIELDNAM: bottommcphvmonitor LABLAXIS: bottommcphvmonitor UNITS: ' ' - DEPEND_0: epoch bottommcphvtrip: <<: *default_float32 CATDESC: Bottommcphvtrip + DEPEND_0: epoch FIELDNAM: bottommcphvtrip LABLAXIS: bottommcphvtrip UNITS: ' ' - DEPEND_0: epoch bottommcphvv: <<: *default_float32 CATDESC: Bottommcphvv + DEPEND_0: epoch FIELDNAM: bottommcphvv LABLAXIS: bottommcphvv UNITS: ' ' - DEPEND_0: epoch cause: <<: *default_float32 CATDESC: Cause + DEPEND_0: epoch FIELDNAM: cause LABLAXIS: cause UNITS: ' ' - DEPEND_0: epoch checksum: <<: *default_uint16 CATDESC: Checksums + DEPEND_0: epoch FIELDNAM: checksums LABLAXIS: checksums UNITS: ' ' - DEPEND_0: epoch checksums: <<: *default_float32 CATDESC: Checksums + DEPEND_0: epoch FIELDNAM: checksums LABLAXIS: checksums UNITS: ' ' - DEPEND_0: epoch cmdexec: <<: *default_float32 CATDESC: Cmdexec + DEPEND_0: epoch FIELDNAM: cmdexec LABLAXIS: cmdexec UNITS: ' ' - DEPEND_0: epoch cmdreject: <<: *default_float32 CATDESC: Cmdreject + DEPEND_0: epoch FIELDNAM: cmdreject LABLAXIS: cmdreject UNITS: ' ' - DEPEND_0: epoch coderam: <<: *default_float32 CATDESC: Coderam + DEPEND_0: epoch FIELDNAM: coderam LABLAXIS: coderam UNITS: ' ' - DEPEND_0: epoch coinbnautozero: <<: *default_float32 CATDESC: Coinbnautozero + DEPEND_0: epoch FIELDNAM: coinbnautozero LABLAXIS: coinbnautozero UNITS: ' ' - DEPEND_0: epoch coinbncfdthresh: <<: *default_float32 CATDESC: Coinbncfdthresh + DEPEND_0: epoch FIELDNAM: coinbncfdthresh LABLAXIS: coinbncfdthresh UNITS: ' ' - DEPEND_0: epoch coinbsautozero: <<: *default_float32 CATDESC: Coinbsautozero + DEPEND_0: epoch FIELDNAM: coinbsautozero LABLAXIS: coinbsautozero UNITS: ' ' - DEPEND_0: epoch coinbscfdthresh: <<: *default_float32 CATDESC: Coinbscfdthresh + DEPEND_0: epoch FIELDNAM: coinbscfdthresh LABLAXIS: coinbscfdthresh UNITS: ' ' - DEPEND_0: epoch coindautozero: <<: *default_float32 CATDESC: Coindautozero + DEPEND_0: epoch FIELDNAM: coindautozero LABLAXIS: coindautozero UNITS: ' ' - DEPEND_0: epoch coindcfdthresh: <<: *default_float32 CATDESC: Coindcfdthresh + DEPEND_0: epoch FIELDNAM: coindcfdthresh LABLAXIS: coindcfdthresh UNITS: ' ' - DEPEND_0: epoch coindphthresh: <<: *default_float32 CATDESC: Coindphthresh + DEPEND_0: epoch FIELDNAM: coindphthresh LABLAXIS: coindphthresh UNITS: ' ' - DEPEND_0: epoch coindpulsedelay: <<: *default_float32 CATDESC: Coindpulsedelay + DEPEND_0: epoch FIELDNAM: coindpulsedelay LABLAXIS: coindpulsedelay UNITS: ' ' - DEPEND_0: epoch coindpulsestate: <<: *default_float32 CATDESC: Coindpulsestate + DEPEND_0: epoch FIELDNAM: coindpulsestate LABLAXIS: coindpulsestate UNITS: ' ' - DEPEND_0: epoch coinratehighthresh: <<: *default_float32 CATDESC: Coinratehighthresh + DEPEND_0: epoch FIELDNAM: coinratehighthresh LABLAXIS: coinratehighthresh UNITS: ' ' - DEPEND_0: epoch cointnautozero: <<: *default_float32 CATDESC: Cointnautozero + DEPEND_0: epoch FIELDNAM: cointnautozero LABLAXIS: cointnautozero UNITS: ' ' - DEPEND_0: epoch cointncfdthresh: <<: *default_float32 CATDESC: Cointncfdthresh + DEPEND_0: epoch FIELDNAM: cointncfdthresh LABLAXIS: cointncfdthresh UNITS: ' ' - DEPEND_0: epoch cointsautozero: <<: *default_float32 CATDESC: Cointsautozero + DEPEND_0: epoch FIELDNAM: cointsautozero LABLAXIS: cointsautozero UNITS: ' ' - DEPEND_0: epoch cointscfdthresh: <<: *default_float32 CATDESC: Cointscfdthresh + DEPEND_0: epoch FIELDNAM: cointscfdthresh LABLAXIS: cointscfdthresh UNITS: ' ' - DEPEND_0: epoch compdata: <<: *default_float32 CATDESC: Compdata + DEPEND_0: epoch FIELDNAM: compdata LABLAXIS: compdata UNITS: ' ' - DEPEND_0: epoch crc_value: <<: *default_float32 CATDESC: Crc value + DEPEND_0: epoch FIELDNAM: crc_value LABLAXIS: crc_value UNITS: ' ' - DEPEND_0: epoch deflhvdiscthresh: <<: *default_float32 CATDESC: Deflhvdiscthresh + DEPEND_0: epoch FIELDNAM: deflhvdiscthresh LABLAXIS: deflhvdiscthresh UNITS: ' ' - DEPEND_0: epoch deflhvrampdownrate: <<: *default_float32 CATDESC: Deflhvrampdownrate + DEPEND_0: epoch FIELDNAM: deflhvrampdownrate LABLAXIS: deflhvrampdownrate UNITS: ' ' - DEPEND_0: epoch deflhvrampuprate: <<: *default_float32 CATDESC: Deflhvrampuprate + DEPEND_0: epoch FIELDNAM: deflhvrampuprate LABLAXIS: deflhvrampuprate UNITS: ' ' - DEPEND_0: epoch deflhvsafelim: <<: *default_float32 CATDESC: Deflhvsafelim + DEPEND_0: epoch FIELDNAM: deflhvsafelim LABLAXIS: deflhvsafelim UNITS: ' ' - DEPEND_0: epoch diagnosticmode: <<: *default_float32 CATDESC: Diagnosticmode + DEPEND_0: epoch FIELDNAM: diagnosticmode LABLAXIS: diagnosticmode UNITS: ' ' - DEPEND_0: epoch dumpdata: CATDESC: Dumpdata + DEPEND_0: epoch FIELDNAM: dumpdata LABLAXIS: dumpdata UNITS: ' ' - DEPEND_0: epoch dumplength: <<: *default_float32 CATDESC: Dumplength + DEPEND_0: epoch FIELDNAM: dumplength LABLAXIS: dumplength UNITS: ' ' - DEPEND_0: epoch enaextofhighangcadence: <<: *default_float32 CATDESC: Enaextofhighangcadence + DEPEND_0: epoch FIELDNAM: enaextofhighangcadence LABLAXIS: enaextofhighangcadence UNITS: ' ' - DEPEND_0: epoch enaextofhighangstate: <<: *default_float32 CATDESC: Enaextofhighangstate + DEPEND_0: epoch FIELDNAM: enaextofhighangstate LABLAXIS: enaextofhighangstate UNITS: ' ' - DEPEND_0: epoch enaphxtofhighangcadence: <<: *default_float32 CATDESC: Enaphxtofhighangcadence + DEPEND_0: epoch FIELDNAM: enaphxtofhighangcadence LABLAXIS: enaphxtofhighangcadence UNITS: ' ' - DEPEND_0: epoch enaphxtofhighangstate: <<: *default_float32 CATDESC: Enaphxtofhighangstate + DEPEND_0: epoch FIELDNAM: enaphxtofhighangstate LABLAXIS: enaphxtofhighangstate UNITS: ' ' - DEPEND_0: epoch enaphxtofhighegycadence: <<: *default_float32 CATDESC: Enaphxtofhighegycadence + DEPEND_0: epoch FIELDNAM: enaphxtofhighegycadence LABLAXIS: enaphxtofhighegycadence UNITS: ' ' - DEPEND_0: epoch enaphxtofhighegystate: <<: *default_float32 CATDESC: Enaphxtofhighegystate + DEPEND_0: epoch FIELDNAM: enaphxtofhighegystate LABLAXIS: enaphxtofhighegystate UNITS: ' ' - DEPEND_0: epoch enaphxtofhightimecadence: <<: *default_float32 CATDESC: Enaphxtofhightimecadence + DEPEND_0: epoch FIELDNAM: enaphxtofhightimecadence LABLAXIS: enaphxtofhightimecadence UNITS: ' ' - DEPEND_0: epoch enaphxtofhightimestate: <<: *default_float32 CATDESC: Enaphxtofhightimestate + DEPEND_0: epoch FIELDNAM: enaphxtofhightimestate LABLAXIS: enaphxtofhightimestate UNITS: ' ' - DEPEND_0: epoch energymodeegystate: <<: *default_float32 CATDESC: Energymodeegystate + DEPEND_0: epoch FIELDNAM: energymodeegystate LABLAXIS: energymodeegystate UNITS: ' ' - DEPEND_0: epoch energymodeegytrg: <<: *default_float32 CATDESC: Energymodeegytrg + DEPEND_0: epoch FIELDNAM: energymodeegytrg LABLAXIS: energymodeegytrg UNITS: ' ' - DEPEND_0: epoch energymodephstate: <<: *default_float32 CATDESC: Energymodephstate + DEPEND_0: epoch FIELDNAM: energymodephstate LABLAXIS: energymodephstate UNITS: ' ' - DEPEND_0: epoch energymodephtrg: <<: *default_float32 CATDESC: Energymodephtrg + DEPEND_0: epoch FIELDNAM: energymodephtrg LABLAXIS: energymodephtrg UNITS: ' ' - DEPEND_0: epoch energyratescadence: <<: *default_float32 CATDESC: Energyratescadence + DEPEND_0: epoch FIELDNAM: energyratescadence LABLAXIS: energyratescadence UNITS: ' ' - DEPEND_0: epoch energyratesstate: <<: *default_float32 CATDESC: Energyratesstate + DEPEND_0: epoch FIELDNAM: energyratesstate LABLAXIS: energyratesstate UNITS: ' ' - DEPEND_0: epoch energyrawevents: <<: *default_float32 CATDESC: Energyrawevents + DEPEND_0: epoch FIELDNAM: energyrawevents LABLAXIS: energyrawevents UNITS: ' ' - DEPEND_0: epoch energyspectracadence: <<: *default_float32 CATDESC: Energyspectracadence + DEPEND_0: epoch FIELDNAM: energyspectracadence LABLAXIS: energyspectracadence UNITS: ' ' - DEPEND_0: epoch energyspectrastate: <<: *default_float32 CATDESC: Energyspectrastate + DEPEND_0: epoch FIELDNAM: energyspectrastate LABLAXIS: energyspectrastate UNITS: ' ' - DEPEND_0: epoch etofbtoff: <<: *default_float32 CATDESC: Etofbtoff + DEPEND_0: epoch FIELDNAM: etofbtoff LABLAXIS: etofbtoff UNITS: ' ' - DEPEND_0: epoch etofmax: <<: *default_float32 CATDESC: Etofmax + DEPEND_0: epoch FIELDNAM: etofmax LABLAXIS: etofmax UNITS: ' ' - DEPEND_0: epoch etofmin: <<: *default_float32 CATDESC: Etofmin + DEPEND_0: epoch FIELDNAM: etofmin LABLAXIS: etofmin UNITS: ' ' - DEPEND_0: epoch etofoff1: <<: *default_float32 CATDESC: Etofoff1 + DEPEND_0: epoch FIELDNAM: etofoff1 LABLAXIS: etofoff1 UNITS: ' ' - DEPEND_0: epoch etofoff2: <<: *default_float32 CATDESC: Etofoff2 + DEPEND_0: epoch FIELDNAM: etofoff2 LABLAXIS: etofoff2 UNITS: ' ' - DEPEND_0: epoch etofsc: <<: *default_float32 CATDESC: Etofsc + DEPEND_0: epoch FIELDNAM: etofsc LABLAXIS: etofsc UNITS: ' ' - DEPEND_0: epoch etofslope1: <<: *default_float32 CATDESC: Etofslope1 + DEPEND_0: epoch FIELDNAM: etofslope1 LABLAXIS: etofslope1 UNITS: ' ' - DEPEND_0: epoch etofslope2: <<: *default_float32 CATDESC: Etofslope2 + DEPEND_0: epoch FIELDNAM: etofslope2 LABLAXIS: etofslope2 UNITS: ' ' - DEPEND_0: epoch etoftpoff: <<: *default_float32 CATDESC: Etoftpoff + DEPEND_0: epoch FIELDNAM: etoftpoff LABLAXIS: etoftpoff UNITS: ' ' - DEPEND_0: epoch eventcontrol_spare: <<: *default_float32 CATDESC: Eventcontrol spare + DEPEND_0: epoch FIELDNAM: eventcontrol_spare LABLAXIS: eventcontrol_spare UNITS: ' ' - DEPEND_0: epoch eventdata: <<: *default_float32 CATDESC: Eventdata + DEPEND_0: epoch FIELDNAM: eventdata LABLAXIS: eventdata UNITS: ' ' - DEPEND_0: epoch firstmacro: <<: *default_float32 CATDESC: Firstmacro + DEPEND_0: epoch FIELDNAM: firstmacro LABLAXIS: firstmacro UNITS: ' ' - DEPEND_0: epoch front2kv_v: <<: *default_float32 CATDESC: Front2kv v + DEPEND_0: epoch FIELDNAM: front2kv_v LABLAXIS: front2kv_v UNITS: ' ' - DEPEND_0: epoch front2kv_v_hi: <<: *default_float32 CATDESC: Front2kv v hi + DEPEND_0: epoch FIELDNAM: front2kv_v_hi LABLAXIS: front2kv_v_hi UNITS: ' ' - DEPEND_0: epoch front2kv_v_lo: <<: *default_float32 CATDESC: Front2kv v lo + DEPEND_0: epoch FIELDNAM: front2kv_v_lo LABLAXIS: front2kv_v_lo UNITS: ' ' - DEPEND_0: epoch frontmcp_i: <<: *default_float32 CATDESC: Frontmcp i + DEPEND_0: epoch FIELDNAM: frontmcp_i LABLAXIS: frontmcp_i UNITS: ' ' - DEPEND_0: epoch frontmcp_i_hi: <<: *default_float32 CATDESC: Frontmcp i hi + DEPEND_0: epoch FIELDNAM: frontmcp_i_hi LABLAXIS: frontmcp_i_hi UNITS: ' ' - DEPEND_0: epoch frontmcp_i_lo: <<: *default_float32 CATDESC: Frontmcp i lo + DEPEND_0: epoch FIELDNAM: frontmcp_i_lo LABLAXIS: frontmcp_i_lo UNITS: ' ' - DEPEND_0: epoch frontmcp_t: <<: *default_float32 CATDESC: Frontmcp t + DEPEND_0: epoch FIELDNAM: frontmcp_t LABLAXIS: frontmcp_t UNITS: ' ' - DEPEND_0: epoch frontmcp_t_hi: <<: *default_float32 CATDESC: Frontmcp t hi + DEPEND_0: epoch FIELDNAM: frontmcp_t_hi LABLAXIS: frontmcp_t_hi UNITS: ' ' - DEPEND_0: epoch frontmcp_t_lo: <<: *default_float32 CATDESC: Frontmcp t lo + DEPEND_0: epoch FIELDNAM: frontmcp_t_lo LABLAXIS: frontmcp_t_lo UNITS: ' ' - DEPEND_0: epoch frontmcp_v: <<: *default_float32 CATDESC: Frontmcp v + DEPEND_0: epoch FIELDNAM: frontmcp_v LABLAXIS: frontmcp_v UNITS: ' ' - DEPEND_0: epoch frontmcp_v_hi: <<: *default_float32 CATDESC: Frontmcp v hi + DEPEND_0: epoch FIELDNAM: frontmcp_v_hi LABLAXIS: frontmcp_v_hi UNITS: ' ' - DEPEND_0: epoch frontmcp_v_lo: <<: *default_float32 CATDESC: Frontmcp v lo + DEPEND_0: epoch FIELDNAM: frontmcp_v_lo LABLAXIS: frontmcp_v_lo UNITS: ' ' - DEPEND_0: epoch frontmcphvfault: <<: *default_float32 CATDESC: Frontmcphvfault + DEPEND_0: epoch FIELDNAM: frontmcphvfault LABLAXIS: frontmcphvfault UNITS: ' ' - DEPEND_0: epoch frontmcphvgoal: <<: *default_float32 CATDESC: Frontmcphvgoal + DEPEND_0: epoch FIELDNAM: frontmcphvgoal LABLAXIS: frontmcphvgoal UNITS: ' ' - DEPEND_0: epoch frontmcphvilim: <<: *default_float32 CATDESC: Frontmcphvilim + DEPEND_0: epoch FIELDNAM: frontmcphvilim LABLAXIS: frontmcphvilim UNITS: ' ' - DEPEND_0: epoch frontmcphvlim: <<: *default_float32 CATDESC: Frontmcphvlim + DEPEND_0: epoch FIELDNAM: frontmcphvlim LABLAXIS: frontmcphvlim UNITS: ' ' - DEPEND_0: epoch frontmcphvmonitor: <<: *default_float32 CATDESC: Frontmcphvmonitor + DEPEND_0: epoch FIELDNAM: frontmcphvmonitor LABLAXIS: frontmcphvmonitor UNITS: ' ' - DEPEND_0: epoch frontmcphvsafemult: <<: *default_float32 CATDESC: Frontmcphvsafemult + DEPEND_0: epoch FIELDNAM: frontmcphvsafemult LABLAXIS: frontmcphvsafemult UNITS: ' ' - DEPEND_0: epoch frontmcphvtrip: <<: *default_float32 CATDESC: Frontmcphvtrip + DEPEND_0: epoch FIELDNAM: frontmcphvtrip LABLAXIS: frontmcphvtrip UNITS: ' ' - DEPEND_0: epoch frontmcphvv: <<: *default_float32 CATDESC: Frontmcphvv + DEPEND_0: epoch FIELDNAM: frontmcphvv LABLAXIS: frontmcphvv UNITS: ' ' - DEPEND_0: epoch hvclock: <<: *default_float32 CATDESC: Hvclock + DEPEND_0: epoch FIELDNAM: hvclock LABLAXIS: hvclock UNITS: ' ' - DEPEND_0: epoch hvfullstate: <<: *default_float32 CATDESC: Hvfullstate + DEPEND_0: epoch FIELDNAM: hvfullstate LABLAXIS: hvfullstate UNITS: ' ' - DEPEND_0: epoch hvovercurrentcontrol_spare: <<: *default_float32 CATDESC: Hvovercurrentcontrol spare + DEPEND_0: epoch FIELDNAM: hvovercurrentcontrol_spare LABLAXIS: hvovercurrentcontrol_spare UNITS: ' ' - DEPEND_0: epoch hvovercurrentstatus_spare: <<: *default_float32 @@ -2020,3140 +2023,3140 @@ hvovercurrentstatus_spare: hvplugstate: <<: *default_float32 CATDESC: Hvplugstate + DEPEND_0: epoch FIELDNAM: hvplugstate LABLAXIS: hvplugstate UNITS: ' ' - DEPEND_0: epoch hvpsp15v_v: <<: *default_float32 CATDESC: Hvpsp15v v + DEPEND_0: epoch FIELDNAM: hvpsp15v_v LABLAXIS: hvpsp15v_v UNITS: ' ' - DEPEND_0: epoch hvpsp15v_v_hi: <<: *default_float32 CATDESC: Hvpsp15v v hi + DEPEND_0: epoch FIELDNAM: hvpsp15v_v_hi LABLAXIS: hvpsp15v_v_hi UNITS: ' ' - DEPEND_0: epoch hvpsp15v_v_lo: <<: *default_float32 CATDESC: Hvpsp15v v lo + DEPEND_0: epoch FIELDNAM: hvpsp15v_v_lo LABLAXIS: hvpsp15v_v_lo UNITS: ' ' - DEPEND_0: epoch hvpsp3p3v_v: <<: *default_float32 CATDESC: Hvpsp3p3v v + DEPEND_0: epoch FIELDNAM: hvpsp3p3v_v LABLAXIS: hvpsp3p3v_v UNITS: ' ' - DEPEND_0: epoch hvpsp3p3v_v_hi: <<: *default_float32 CATDESC: Hvpsp3p3v v hi + DEPEND_0: epoch FIELDNAM: hvpsp3p3v_v_hi LABLAXIS: hvpsp3p3v_v_hi UNITS: ' ' - DEPEND_0: epoch hvpsp3p3v_v_lo: <<: *default_float32 CATDESC: Hvpsp3p3v v lo + DEPEND_0: epoch FIELDNAM: hvpsp3p3v_v_lo LABLAXIS: hvpsp3p3v_v_lo UNITS: ' ' - DEPEND_0: epoch hvstate: <<: *default_float32 CATDESC: Hvstate + DEPEND_0: epoch FIELDNAM: hvstate LABLAXIS: hvstate UNITS: ' ' - DEPEND_0: epoch id: <<: *default_float32 CATDESC: Id + DEPEND_0: epoch FIELDNAM: id LABLAXIS: id UNITS: ' ' - DEPEND_0: epoch identity: <<: *default_float32 CATDESC: Identity + DEPEND_0: epoch FIELDNAM: identity LABLAXIS: identity UNITS: ' ' - DEPEND_0: epoch imagemodedblreq: <<: *default_float32 CATDESC: Imagemodedblreq + DEPEND_0: epoch FIELDNAM: imagemodedblreq LABLAXIS: imagemodedblreq UNITS: ' ' - DEPEND_0: epoch imagemodedblstate: <<: *default_float32 CATDESC: Imagemodedblstate + DEPEND_0: epoch FIELDNAM: imagemodedblstate LABLAXIS: imagemodedblstate UNITS: ' ' - DEPEND_0: epoch imagemodemulrej: <<: *default_float32 CATDESC: Imagemodemulrej + DEPEND_0: epoch FIELDNAM: imagemodemulrej LABLAXIS: imagemodemulrej UNITS: ' ' - DEPEND_0: epoch imagemodephreq: <<: *default_float32 CATDESC: Imagemodephreq + DEPEND_0: epoch FIELDNAM: imagemodephreq LABLAXIS: imagemodephreq UNITS: ' ' - DEPEND_0: epoch imagemodepwrej: <<: *default_float32 CATDESC: Imagemodepwrej + DEPEND_0: epoch FIELDNAM: imagemodepwrej LABLAXIS: imagemodepwrej UNITS: ' ' - DEPEND_0: epoch imagemodestartlfpwthresh: <<: *default_float32 CATDESC: Imagemodestartlfpwthresh + DEPEND_0: epoch FIELDNAM: imagemodestartlfpwthresh LABLAXIS: imagemodestartlfpwthresh UNITS: ' ' - DEPEND_0: epoch imagemodestartrfpwthresh: <<: *default_float32 CATDESC: Imagemodestartrfpwthresh + DEPEND_0: epoch FIELDNAM: imagemodestartrfpwthresh LABLAXIS: imagemodestartrfpwthresh UNITS: ' ' - DEPEND_0: epoch imagemodetimreq: <<: *default_float32 CATDESC: Imagemodetimreq + DEPEND_0: epoch FIELDNAM: imagemodetimreq LABLAXIS: imagemodetimreq UNITS: ' ' - DEPEND_0: epoch imagemodetimstate: <<: *default_float32 CATDESC: Imagemodetimstate + DEPEND_0: epoch FIELDNAM: imagemodetimstate LABLAXIS: imagemodetimstate UNITS: ' ' - DEPEND_0: epoch imagepriority1events: <<: *default_float32 CATDESC: Imagepriority1events + DEPEND_0: epoch FIELDNAM: imagepriority1events LABLAXIS: imagepriority1events UNITS: ' ' - DEPEND_0: epoch imagepriority2events: <<: *default_float32 CATDESC: Imagepriority2events + DEPEND_0: epoch FIELDNAM: imagepriority2events LABLAXIS: imagepriority2events UNITS: ' ' - DEPEND_0: epoch imagepriority3events: <<: *default_float32 CATDESC: Imagepriority3events + DEPEND_0: epoch FIELDNAM: imagepriority3events LABLAXIS: imagepriority3events UNITS: ' ' - DEPEND_0: epoch imagepriority4events: <<: *default_float32 CATDESC: Imagepriority4events + DEPEND_0: epoch FIELDNAM: imagepriority4events LABLAXIS: imagepriority4events UNITS: ' ' - DEPEND_0: epoch imageratescadence: <<: *default_float32 CATDESC: Imageratescadence + DEPEND_0: epoch FIELDNAM: imageratescadence LABLAXIS: imageratescadence UNITS: ' ' - DEPEND_0: epoch imageratesstate: <<: *default_float32 CATDESC: Imageratesstate + DEPEND_0: epoch FIELDNAM: imageratesstate LABLAXIS: imageratesstate UNITS: ' ' - DEPEND_0: epoch imagerawevents: <<: *default_float32 CATDESC: Imagerawevents + DEPEND_0: epoch FIELDNAM: imagerawevents LABLAXIS: imagerawevents UNITS: ' ' - DEPEND_0: epoch imcstate: <<: *default_float32 CATDESC: Imcstate + DEPEND_0: epoch FIELDNAM: imcstate LABLAXIS: imcstate UNITS: ' ' - DEPEND_0: epoch instrumentcontrol_spare: <<: *default_float32 CATDESC: Instrumentcontrol spare + DEPEND_0: epoch FIELDNAM: instrumentcontrol_spare LABLAXIS: instrumentcontrol_spare UNITS: ' ' - DEPEND_0: epoch instrumentstatus_spare: <<: *default_float32 CATDESC: Instrumentstatus spare + DEPEND_0: epoch FIELDNAM: instrumentstatus_spare LABLAXIS: instrumentstatus_spare UNITS: ' ' - DEPEND_0: epoch intmultipliern1: <<: *default_float32 CATDESC: Intmultipliern1 + DEPEND_0: epoch FIELDNAM: intmultipliern1 LABLAXIS: intmultipliern1 UNITS: ' ' - DEPEND_0: epoch intmultipliern2: <<: *default_float32 CATDESC: Intmultipliern2 + DEPEND_0: epoch FIELDNAM: intmultipliern2 LABLAXIS: intmultipliern2 UNITS: ' ' - DEPEND_0: epoch ionextofhighegycadence: <<: *default_float32 CATDESC: Ionextofhighegycadence + DEPEND_0: epoch FIELDNAM: ionextofhighegycadence LABLAXIS: ionextofhighegycadence UNITS: ' ' - DEPEND_0: epoch ionextofhighegystate: <<: *default_float32 CATDESC: Ionextofhighegystate + DEPEND_0: epoch FIELDNAM: ionextofhighegystate LABLAXIS: ionextofhighegystate UNITS: ' ' - DEPEND_0: epoch ionextofhightimecadence: <<: *default_float32 CATDESC: Ionextofhightimecadence + DEPEND_0: epoch FIELDNAM: ionextofhightimecadence LABLAXIS: ionextofhightimecadence UNITS: ' ' - DEPEND_0: epoch ionextofhightimestate: <<: *default_float32 CATDESC: Ionextofhightimestate + DEPEND_0: epoch FIELDNAM: ionextofhightimestate LABLAXIS: ionextofhightimestate UNITS: ' ' - DEPEND_0: epoch lastmacro: <<: *default_float32 CATDESC: Lastmacro + DEPEND_0: epoch FIELDNAM: lastmacro LABLAXIS: lastmacro UNITS: ' ' - DEPEND_0: epoch leftdeflection_v: <<: *default_float32 CATDESC: Leftdeflection v + DEPEND_0: epoch FIELDNAM: leftdeflection_v LABLAXIS: leftdeflection_v UNITS: ' ' - DEPEND_0: epoch leftdeflection_v_hi: <<: *default_float32 CATDESC: Leftdeflection v hi + DEPEND_0: epoch FIELDNAM: leftdeflection_v_hi LABLAXIS: leftdeflection_v_hi UNITS: ' ' - DEPEND_0: epoch leftdeflection_v_lo: <<: *default_float32 CATDESC: Leftdeflection v lo + DEPEND_0: epoch FIELDNAM: leftdeflection_v_lo LABLAXIS: leftdeflection_v_lo UNITS: ' ' - DEPEND_0: epoch leftdeflectionsupply_p: <<: *default_float32 CATDESC: Leftdeflectionsupply p + DEPEND_0: epoch FIELDNAM: leftdeflectionsupply_p LABLAXIS: leftdeflectionsupply_p UNITS: ' ' - DEPEND_0: epoch leftdeflectionsupply_p_hi: <<: *default_float32 CATDESC: Leftdeflectionsupply p hi + DEPEND_0: epoch FIELDNAM: leftdeflectionsupply_p_hi LABLAXIS: leftdeflectionsupply_p_hi UNITS: ' ' - DEPEND_0: epoch leftdeflectionsupply_p_lo: <<: *default_float32 CATDESC: Leftdeflectionsupply p lo + DEPEND_0: epoch FIELDNAM: leftdeflectionsupply_p_lo LABLAXIS: leftdeflectionsupply_p_lo UNITS: ' ' - DEPEND_0: epoch leftdfldischrate: <<: *default_float32 CATDESC: Leftdfldischrate + DEPEND_0: epoch FIELDNAM: leftdfldischrate LABLAXIS: leftdfldischrate UNITS: ' ' - DEPEND_0: epoch leftdfldischrate_hi: <<: *default_float32 CATDESC: Leftdfldischrate hi + DEPEND_0: epoch FIELDNAM: leftdfldischrate_hi LABLAXIS: leftdfldischrate_hi UNITS: ' ' - DEPEND_0: epoch leftdfldischrate_lo: <<: *default_float32 CATDESC: Leftdfldischrate lo + DEPEND_0: epoch FIELDNAM: leftdfldischrate_lo LABLAXIS: leftdfldischrate_lo UNITS: ' ' - DEPEND_0: epoch leftdfldischratelim: <<: *default_float32 CATDESC: Leftdfldischratelim + DEPEND_0: epoch FIELDNAM: leftdfldischratelim LABLAXIS: leftdfldischratelim UNITS: ' ' - DEPEND_0: epoch leftdflhvgoal: <<: *default_float32 CATDESC: Leftdflhvgoal + DEPEND_0: epoch FIELDNAM: leftdflhvgoal LABLAXIS: leftdflhvgoal UNITS: ' ' - DEPEND_0: epoch leftdflhvlim: <<: *default_float32 CATDESC: Leftdflhvlim + DEPEND_0: epoch FIELDNAM: leftdflhvlim LABLAXIS: leftdflhvlim UNITS: ' ' - DEPEND_0: epoch leftdflhvv: <<: *default_float32 CATDESC: Leftdflhvv + DEPEND_0: epoch FIELDNAM: leftdflhvv LABLAXIS: leftdflhvv UNITS: ' ' - DEPEND_0: epoch leftshutter_t: <<: *default_float32 CATDESC: Leftshutter t + DEPEND_0: epoch FIELDNAM: leftshutter_t LABLAXIS: leftshutter_t UNITS: ' ' - DEPEND_0: epoch leftshutter_t_hi: <<: *default_float32 CATDESC: Leftshutter t hi + DEPEND_0: epoch FIELDNAM: leftshutter_t_hi LABLAXIS: leftshutter_t_hi UNITS: ' ' - DEPEND_0: epoch leftshutter_t_lo: <<: *default_float32 CATDESC: Leftshutter t lo + DEPEND_0: epoch FIELDNAM: leftshutter_t_lo LABLAXIS: leftshutter_t_lo UNITS: ' ' - DEPEND_0: epoch leftshutterhomesteps: <<: *default_float32 CATDESC: Leftshutterhomesteps + DEPEND_0: epoch FIELDNAM: leftshutterhomesteps LABLAXIS: leftshutterhomesteps UNITS: ' ' - DEPEND_0: epoch leftshutterstep: <<: *default_float32 CATDESC: Leftshutterstep + DEPEND_0: epoch FIELDNAM: leftshutterstep LABLAXIS: leftshutterstep UNITS: ' ' - DEPEND_0: epoch leftshuttertt: <<: *default_float32 CATDESC: Leftshuttertt + DEPEND_0: epoch FIELDNAM: leftshuttertt LABLAXIS: leftshuttertt UNITS: ' ' - DEPEND_0: epoch looback0delay: <<: *default_float32 CATDESC: Looback0delay + DEPEND_0: epoch FIELDNAM: looback0delay LABLAXIS: looback0delay UNITS: ' ' - DEPEND_0: epoch looback1delay: <<: *default_float32 CATDESC: Looback1delay + DEPEND_0: epoch FIELDNAM: looback1delay LABLAXIS: looback1delay UNITS: ' ' - DEPEND_0: epoch looback2delay: <<: *default_float32 CATDESC: Looback2delay + DEPEND_0: epoch FIELDNAM: looback2delay LABLAXIS: looback2delay UNITS: ' ' - DEPEND_0: epoch lvpdsdigitalout_spare: <<: *default_float32 CATDESC: Lvpdsdigitalout spare + DEPEND_0: epoch FIELDNAM: lvpdsdigitalout_spare LABLAXIS: lvpdsdigitalout_spare UNITS: ' ' - DEPEND_0: epoch lvps_t: <<: *default_float32 CATDESC: Lvps t + DEPEND_0: epoch FIELDNAM: lvps_t LABLAXIS: lvps_t UNITS: ' ' - DEPEND_0: epoch lvps_t_hi: <<: *default_float32 CATDESC: Lvps t hi + DEPEND_0: epoch FIELDNAM: lvps_t_hi LABLAXIS: lvps_t_hi UNITS: ' ' - DEPEND_0: epoch lvps_t_lo: <<: *default_float32 CATDESC: Lvps t lo + DEPEND_0: epoch FIELDNAM: lvps_t_lo LABLAXIS: lvps_t_lo UNITS: ' ' - DEPEND_0: epoch lvpsp15v_i: <<: *default_float32 CATDESC: Lvpsp15v i + DEPEND_0: epoch FIELDNAM: lvpsp15v_i LABLAXIS: lvpsp15v_i UNITS: ' ' - DEPEND_0: epoch lvpsp15v_i_hi: <<: *default_float32 CATDESC: Lvpsp15v i hi + DEPEND_0: epoch FIELDNAM: lvpsp15v_i_hi LABLAXIS: lvpsp15v_i_hi UNITS: ' ' - DEPEND_0: epoch lvpsp15v_i_lo: <<: *default_float32 CATDESC: Lvpsp15v i lo + DEPEND_0: epoch FIELDNAM: lvpsp15v_i_lo LABLAXIS: lvpsp15v_i_lo UNITS: ' ' - DEPEND_0: epoch lvpsp15v_v: <<: *default_float32 CATDESC: Lvpsp15v v + DEPEND_0: epoch FIELDNAM: lvpsp15v_v LABLAXIS: lvpsp15v_v UNITS: ' ' - DEPEND_0: epoch lvpsp15v_v_hi: <<: *default_float32 CATDESC: Lvpsp15v v hi + DEPEND_0: epoch FIELDNAM: lvpsp15v_v_hi LABLAXIS: lvpsp15v_v_hi UNITS: ' ' - DEPEND_0: epoch lvpsp15v_v_lo: <<: *default_float32 CATDESC: Lvpsp15v v lo + DEPEND_0: epoch FIELDNAM: lvpsp15v_v_lo LABLAXIS: lvpsp15v_v_lo UNITS: ' ' - DEPEND_0: epoch lvpsp1p5v_i: <<: *default_float32 CATDESC: Lvpsp1p5v i + DEPEND_0: epoch FIELDNAM: lvpsp1p5v_i LABLAXIS: lvpsp1p5v_i UNITS: ' ' - DEPEND_0: epoch lvpsp1p5v_i_hi: <<: *default_float32 CATDESC: Lvpsp1p5v i hi + DEPEND_0: epoch FIELDNAM: lvpsp1p5v_i_hi LABLAXIS: lvpsp1p5v_i_hi UNITS: ' ' - DEPEND_0: epoch lvpsp1p5v_i_lo: <<: *default_float32 CATDESC: Lvpsp1p5v i lo + DEPEND_0: epoch FIELDNAM: lvpsp1p5v_i_lo LABLAXIS: lvpsp1p5v_i_lo UNITS: ' ' - DEPEND_0: epoch lvpsp1p5v_v: <<: *default_float32 CATDESC: Lvpsp1p5v v + DEPEND_0: epoch FIELDNAM: lvpsp1p5v_v LABLAXIS: lvpsp1p5v_v UNITS: ' ' - DEPEND_0: epoch lvpsp1p5v_v_hi: <<: *default_float32 CATDESC: Lvpsp1p5v v hi + DEPEND_0: epoch FIELDNAM: lvpsp1p5v_v_hi LABLAXIS: lvpsp1p5v_v_hi UNITS: ' ' - DEPEND_0: epoch lvpsp1p5v_v_lo: <<: *default_float32 CATDESC: Lvpsp1p5v v lo + DEPEND_0: epoch FIELDNAM: lvpsp1p5v_v_lo LABLAXIS: lvpsp1p5v_v_lo UNITS: ' ' - DEPEND_0: epoch lvpsp3p3v_i: <<: *default_float32 CATDESC: Lvpsp3p3v i + DEPEND_0: epoch FIELDNAM: lvpsp3p3v_i LABLAXIS: lvpsp3p3v_i UNITS: ' ' - DEPEND_0: epoch lvpsp3p3v_i_hi: <<: *default_float32 CATDESC: Lvpsp3p3v i hi + DEPEND_0: epoch FIELDNAM: lvpsp3p3v_i_hi LABLAXIS: lvpsp3p3v_i_hi UNITS: ' ' - DEPEND_0: epoch lvpsp3p3v_i_lo: <<: *default_float32 CATDESC: Lvpsp3p3v i lo + DEPEND_0: epoch FIELDNAM: lvpsp3p3v_i_lo LABLAXIS: lvpsp3p3v_i_lo UNITS: ' ' - DEPEND_0: epoch lvpsp3p3v_v: <<: *default_float32 CATDESC: Lvpsp3p3v v + DEPEND_0: epoch FIELDNAM: lvpsp3p3v_v LABLAXIS: lvpsp3p3v_v UNITS: ' ' - DEPEND_0: epoch lvpsp3p3v_v_hi: <<: *default_float32 CATDESC: Lvpsp3p3v v hi + DEPEND_0: epoch FIELDNAM: lvpsp3p3v_v_hi LABLAXIS: lvpsp3p3v_v_hi UNITS: ' ' - DEPEND_0: epoch lvpsp3p3v_v_lo: <<: *default_float32 CATDESC: Lvpsp3p3v v lo + DEPEND_0: epoch FIELDNAM: lvpsp3p3v_v_lo LABLAXIS: lvpsp3p3v_v_lo UNITS: ' ' - DEPEND_0: epoch lvpsp3p5v_v: <<: *default_float32 CATDESC: Lvpsp3p5v v + DEPEND_0: epoch FIELDNAM: lvpsp3p5v_v LABLAXIS: lvpsp3p5v_v UNITS: ' ' - DEPEND_0: epoch lvpsp3p5v_v_hi: <<: *default_float32 CATDESC: Lvpsp3p5v v hi + DEPEND_0: epoch FIELDNAM: lvpsp3p5v_v_hi LABLAXIS: lvpsp3p5v_v_hi UNITS: ' ' - DEPEND_0: epoch lvpsp3p5v_v_lo: <<: *default_float32 CATDESC: Lvpsp3p5v v lo + DEPEND_0: epoch FIELDNAM: lvpsp3p5v_v_lo LABLAXIS: lvpsp3p5v_v_lo UNITS: ' ' - DEPEND_0: epoch lvpsp5v_i: <<: *default_float32 CATDESC: Lvpsp5v i + DEPEND_0: epoch FIELDNAM: lvpsp5v_i LABLAXIS: lvpsp5v_i UNITS: ' ' - DEPEND_0: epoch lvpsp5v_i_hi: <<: *default_float32 CATDESC: Lvpsp5v i hi + DEPEND_0: epoch FIELDNAM: lvpsp5v_i_hi LABLAXIS: lvpsp5v_i_hi UNITS: ' ' - DEPEND_0: epoch lvpsp5v_i_lo: <<: *default_float32 CATDESC: Lvpsp5v i lo + DEPEND_0: epoch FIELDNAM: lvpsp5v_i_lo LABLAXIS: lvpsp5v_i_lo UNITS: ' ' - DEPEND_0: epoch lvpsp5v_v: <<: *default_float32 CATDESC: Lvpsp5v v + DEPEND_0: epoch FIELDNAM: lvpsp5v_v LABLAXIS: lvpsp5v_v UNITS: ' ' - DEPEND_0: epoch lvpsp5v_v_hi: <<: *default_float32 CATDESC: Lvpsp5v v hi + DEPEND_0: epoch FIELDNAM: lvpsp5v_v_hi LABLAXIS: lvpsp5v_v_hi UNITS: ' ' - DEPEND_0: epoch lvpsp5v_v_lo: <<: *default_float32 CATDESC: Lvpsp5v v lo + DEPEND_0: epoch FIELDNAM: lvpsp5v_v_lo LABLAXIS: lvpsp5v_v_lo UNITS: ' ' - DEPEND_0: epoch lvpsprimary_i: <<: *default_float32 CATDESC: Lvpsprimary i + DEPEND_0: epoch FIELDNAM: lvpsprimary_i LABLAXIS: lvpsprimary_i UNITS: ' ' - DEPEND_0: epoch lvpsprimary_i_hi: <<: *default_float32 CATDESC: Lvpsprimary i hi + DEPEND_0: epoch FIELDNAM: lvpsprimary_i_hi LABLAXIS: lvpsprimary_i_hi UNITS: ' ' - DEPEND_0: epoch lvpsprimary_i_lo: <<: *default_float32 CATDESC: Lvpsprimary i lo + DEPEND_0: epoch FIELDNAM: lvpsprimary_i_lo LABLAXIS: lvpsprimary_i_lo UNITS: ' ' - DEPEND_0: epoch maccmdexec: <<: *default_float32 CATDESC: Maccmdexec + DEPEND_0: epoch FIELDNAM: maccmdexec LABLAXIS: maccmdexec UNITS: ' ' - DEPEND_0: epoch maccmdreject: <<: *default_float32 CATDESC: Maccmdreject + DEPEND_0: epoch FIELDNAM: maccmdreject LABLAXIS: maccmdreject UNITS: ' ' - DEPEND_0: epoch macid: <<: *default_float32 CATDESC: Macid + DEPEND_0: epoch FIELDNAM: macid LABLAXIS: macid UNITS: ' ' - DEPEND_0: epoch maclearn: <<: *default_float32 CATDESC: Maclearn + DEPEND_0: epoch FIELDNAM: maclearn LABLAXIS: maclearn UNITS: ' ' - DEPEND_0: epoch macro: <<: *default_float32 CATDESC: Macro + DEPEND_0: epoch FIELDNAM: macro LABLAXIS: macro UNITS: ' ' - DEPEND_0: epoch macroblocks: <<: *default_float32 CATDESC: Macroblocks + DEPEND_0: epoch FIELDNAM: macroblocks LABLAXIS: macroblocks UNITS: ' ' - DEPEND_0: epoch macrodata: CATDESC: Macrodata + DEPEND_0: epoch FIELDNAM: macrodata LABLAXIS: macrodata UNITS: ' ' - DEPEND_0: epoch macroid: <<: *default_float32 CATDESC: Macroid + DEPEND_0: epoch FIELDNAM: macroid LABLAXIS: macroid UNITS: ' ' - DEPEND_0: epoch maxenergyselect: <<: *default_float32 CATDESC: Maxenergyselect + DEPEND_0: epoch FIELDNAM: maxenergyselect LABLAXIS: maxenergyselect UNITS: ' ' - DEPEND_0: epoch mcphvrampdownrate: <<: *default_float32 CATDESC: Mcphvrampdownrate + DEPEND_0: epoch FIELDNAM: mcphvrampdownrate LABLAXIS: mcphvrampdownrate UNITS: ' ' - DEPEND_0: epoch mcphvrampuprate: <<: *default_float32 CATDESC: Mcphvrampuprate + DEPEND_0: epoch FIELDNAM: mcphvrampuprate LABLAXIS: mcphvrampuprate UNITS: ' ' - DEPEND_0: epoch mcphvsafegap: <<: *default_float32 CATDESC: Mcphvsafegap + DEPEND_0: epoch FIELDNAM: mcphvsafegap LABLAXIS: mcphvsafegap UNITS: ' ' - DEPEND_0: epoch mcphvsafelim: <<: *default_float32 CATDESC: Mcphvsafelim + DEPEND_0: epoch FIELDNAM: mcphvsafelim LABLAXIS: mcphvsafelim UNITS: ' ' - DEPEND_0: epoch mcppreamppower: <<: *default_float32 CATDESC: Mcppreamppower + DEPEND_0: epoch FIELDNAM: mcppreamppower LABLAXIS: mcppreamppower UNITS: ' ' - DEPEND_0: epoch mcppulseamplitude: <<: *default_float32 CATDESC: Mcppulseamplitude + DEPEND_0: epoch FIELDNAM: mcppulseamplitude LABLAXIS: mcppulseamplitude UNITS: ' ' - DEPEND_0: epoch mcpsupply_p: <<: *default_float32 CATDESC: Mcpsupply p + DEPEND_0: epoch FIELDNAM: mcpsupply_p LABLAXIS: mcpsupply_p UNITS: ' ' - DEPEND_0: epoch mcpsupply_p_hi: <<: *default_float32 CATDESC: Mcpsupply p hi + DEPEND_0: epoch FIELDNAM: mcpsupply_p_hi LABLAXIS: mcpsupply_p_hi UNITS: ' ' - DEPEND_0: epoch mcpsupply_p_lo: <<: *default_float32 CATDESC: Mcpsupply p lo + DEPEND_0: epoch FIELDNAM: mcpsupply_p_lo LABLAXIS: mcpsupply_p_lo UNITS: ' ' - DEPEND_0: epoch memlength: <<: *default_float32 CATDESC: Memlength + DEPEND_0: epoch FIELDNAM: memlength LABLAXIS: memlength UNITS: ' ' - DEPEND_0: epoch memwrite: <<: *default_float32 CATDESC: Memwrite + DEPEND_0: epoch FIELDNAM: memwrite LABLAXIS: memwrite UNITS: ' ' - DEPEND_0: epoch monitorresponse: <<: *default_float32 CATDESC: Monitorresponse + DEPEND_0: epoch FIELDNAM: monitorresponse LABLAXIS: monitorresponse UNITS: ' ' - DEPEND_0: epoch nvmemstate: <<: *default_float32 CATDESC: Nvmemstate + DEPEND_0: epoch FIELDNAM: nvmemstate LABLAXIS: nvmemstate UNITS: ' ' - DEPEND_0: epoch opampbias_v: <<: *default_float32 CATDESC: Opampbias v + DEPEND_0: epoch FIELDNAM: opampbias_v LABLAXIS: opampbias_v UNITS: ' ' - DEPEND_0: epoch opampbias_v_hi: <<: *default_float32 CATDESC: Opampbias v hi + DEPEND_0: epoch FIELDNAM: opampbias_v_hi LABLAXIS: opampbias_v_hi UNITS: ' ' - DEPEND_0: epoch opampbias_v_lo: <<: *default_float32 CATDESC: Opampbias v lo + DEPEND_0: epoch FIELDNAM: opampbias_v_lo LABLAXIS: opampbias_v_lo UNITS: ' ' - DEPEND_0: epoch opcode: <<: *default_float32 CATDESC: Opcode + DEPEND_0: epoch FIELDNAM: opcode LABLAXIS: opcode UNITS: ' ' - DEPEND_0: epoch pathmediumthresh: <<: *default_float32 CATDESC: Pathmediumthresh + DEPEND_0: epoch FIELDNAM: pathmediumthresh LABLAXIS: pathmediumthresh UNITS: ' ' - DEPEND_0: epoch pathsteepthresh: <<: *default_float32 CATDESC: Pathsteepthresh + DEPEND_0: epoch FIELDNAM: pathsteepthresh LABLAXIS: pathsteepthresh UNITS: ' ' - DEPEND_0: epoch phreference: <<: *default_float32 CATDESC: Phreference + DEPEND_0: epoch FIELDNAM: phreference LABLAXIS: phreference UNITS: ' ' - DEPEND_0: epoch powerreg_spare: <<: *default_float32 CATDESC: Powerreg spare + DEPEND_0: epoch FIELDNAM: powerreg_spare LABLAXIS: powerreg_spare UNITS: ' ' - DEPEND_0: epoch powerrequest: <<: *default_float32 CATDESC: Powerrequest + DEPEND_0: epoch FIELDNAM: powerrequest LABLAXIS: powerrequest UNITS: ' ' - DEPEND_0: epoch pulserate: <<: *default_float32 CATDESC: Pulserate + DEPEND_0: epoch FIELDNAM: pulserate LABLAXIS: pulserate UNITS: ' ' - DEPEND_0: epoch ratedata: <<: *default_float32 CATDESC: Ratedata + DEPEND_0: epoch FIELDNAM: ratedata LABLAXIS: ratedata UNITS: ' ' - DEPEND_0: epoch raterecoverytime: <<: *default_float32 CATDESC: Raterecoverytime + DEPEND_0: epoch FIELDNAM: raterecoverytime LABLAXIS: raterecoverytime UNITS: ' ' - DEPEND_0: epoch ratestoohigh: <<: *default_float32 CATDESC: Ratestoohigh + DEPEND_0: epoch FIELDNAM: ratestoohigh LABLAXIS: ratestoohigh UNITS: ' ' - DEPEND_0: epoch result: <<: *default_float32 CATDESC: Result + DEPEND_0: epoch FIELDNAM: result LABLAXIS: result UNITS: ' ' - DEPEND_0: epoch result_description: CATDESC: Result description + DEPEND_0: epoch FIELDNAM: result_description LABLAXIS: result description UNITS: ' ' - DEPEND_0: epoch rightdeflection_v: <<: *default_float32 CATDESC: Rightdeflection v + DEPEND_0: epoch FIELDNAM: rightdeflection_v LABLAXIS: rightdeflection_v UNITS: ' ' - DEPEND_0: epoch rightdeflection_v_hi: <<: *default_float32 CATDESC: Rightdeflection v hi + DEPEND_0: epoch FIELDNAM: rightdeflection_v_hi LABLAXIS: rightdeflection_v_hi UNITS: ' ' - DEPEND_0: epoch rightdeflection_v_lo: <<: *default_float32 CATDESC: Rightdeflection v lo + DEPEND_0: epoch FIELDNAM: rightdeflection_v_lo LABLAXIS: rightdeflection_v_lo UNITS: ' ' - DEPEND_0: epoch rightdeflectionsupply_p: <<: *default_float32 CATDESC: Rightdeflectionsupply p + DEPEND_0: epoch FIELDNAM: rightdeflectionsupply_p LABLAXIS: rightdeflectionsupply_p UNITS: ' ' - DEPEND_0: epoch rightdeflectionsupply_p_hi: <<: *default_float32 CATDESC: Rightdeflectionsupply p hi + DEPEND_0: epoch FIELDNAM: rightdeflectionsupply_p_hi LABLAXIS: rightdeflectionsupply_p_hi UNITS: ' ' - DEPEND_0: epoch rightdeflectionsupply_p_lo: <<: *default_float32 CATDESC: Rightdeflectionsupply p lo + DEPEND_0: epoch FIELDNAM: rightdeflectionsupply_p_lo LABLAXIS: rightdeflectionsupply_p_lo UNITS: ' ' - DEPEND_0: epoch rightdfldischrate: <<: *default_float32 CATDESC: Rightdfldischrate + DEPEND_0: epoch FIELDNAM: rightdfldischrate LABLAXIS: rightdfldischrate UNITS: ' ' - DEPEND_0: epoch rightdfldischrate_hi: <<: *default_float32 CATDESC: Rightdfldischrate hi + DEPEND_0: epoch FIELDNAM: rightdfldischrate_hi LABLAXIS: rightdfldischrate_hi UNITS: ' ' - DEPEND_0: epoch rightdfldischrate_lo: <<: *default_float32 CATDESC: Rightdfldischrate lo + DEPEND_0: epoch FIELDNAM: rightdfldischrate_lo LABLAXIS: rightdfldischrate_lo UNITS: ' ' - DEPEND_0: epoch rightdfldischratelim: <<: *default_float32 CATDESC: Rightdfldischratelim + DEPEND_0: epoch FIELDNAM: rightdfldischratelim LABLAXIS: rightdfldischratelim UNITS: ' ' - DEPEND_0: epoch rightdflhvgoal: <<: *default_float32 CATDESC: Rightdflhvgoal + DEPEND_0: epoch FIELDNAM: rightdflhvgoal LABLAXIS: rightdflhvgoal UNITS: ' ' - DEPEND_0: epoch rightdflhvlim: <<: *default_float32 CATDESC: Rightdflhvlim + DEPEND_0: epoch FIELDNAM: rightdflhvlim LABLAXIS: rightdflhvlim UNITS: ' ' - DEPEND_0: epoch rightdflhvv: <<: *default_float32 CATDESC: Rightdflhvv + DEPEND_0: epoch FIELDNAM: rightdflhvv LABLAXIS: rightdflhvv UNITS: ' ' - DEPEND_0: epoch rightshutter_t: <<: *default_float32 CATDESC: Rightshutter t + DEPEND_0: epoch FIELDNAM: rightshutter_t LABLAXIS: rightshutter_t UNITS: ' ' - DEPEND_0: epoch rightshutter_t_hi: <<: *default_float32 CATDESC: Rightshutter t hi + DEPEND_0: epoch FIELDNAM: rightshutter_t_hi LABLAXIS: rightshutter_t_hi UNITS: ' ' - DEPEND_0: epoch rightshutter_t_lo: <<: *default_float32 CATDESC: Rightshutter t lo + DEPEND_0: epoch FIELDNAM: rightshutter_t_lo LABLAXIS: rightshutter_t_lo UNITS: ' ' - DEPEND_0: epoch rightshutterhomesteps: <<: *default_float32 CATDESC: Rightshutterhomesteps + DEPEND_0: epoch FIELDNAM: rightshutterhomesteps LABLAXIS: rightshutterhomesteps UNITS: ' ' - DEPEND_0: epoch rightshutterstep: <<: *default_float32 CATDESC: Rightshutterstep + DEPEND_0: epoch FIELDNAM: rightshutterstep LABLAXIS: rightshutterstep UNITS: ' ' - DEPEND_0: epoch rightshuttertt: <<: *default_float32 CATDESC: Rightshuttertt + DEPEND_0: epoch FIELDNAM: rightshuttertt LABLAXIS: rightshuttertt UNITS: ' ' - DEPEND_0: epoch safingtime: <<: *default_float32 CATDESC: Safingtime + DEPEND_0: epoch FIELDNAM: safingtime LABLAXIS: safingtime UNITS: ' ' - DEPEND_0: epoch shutteractuator: <<: *default_float32 CATDESC: Shutteractuator + DEPEND_0: epoch FIELDNAM: shutteractuator LABLAXIS: shutteractuator UNITS: ' ' - DEPEND_0: epoch shutteractuatorselect: <<: *default_float32 CATDESC: Shutteractuatorselect + DEPEND_0: epoch FIELDNAM: shutteractuatorselect LABLAXIS: shutteractuatorselect UNITS: ' ' - DEPEND_0: epoch shutterheattime: <<: *default_float32 CATDESC: Shutterheattime + DEPEND_0: epoch FIELDNAM: shutterheattime LABLAXIS: shutterheattime UNITS: ' ' - DEPEND_0: epoch shuttermotorduty: <<: *default_float32 CATDESC: Shuttermotorduty + DEPEND_0: epoch FIELDNAM: shuttermotorduty LABLAXIS: shuttermotorduty UNITS: ' ' - DEPEND_0: epoch shuttermotorfreq: <<: *default_float32 CATDESC: Shuttermotorfreq + DEPEND_0: epoch FIELDNAM: shuttermotorfreq LABLAXIS: shuttermotorfreq UNITS: ' ' - DEPEND_0: epoch shutterp15v_i_adjust: <<: *default_float32 CATDESC: Shutterp15v i adjust + DEPEND_0: epoch FIELDNAM: shutterp15v_i_adjust LABLAXIS: shutterp15v_i_adjust UNITS: ' ' - DEPEND_0: epoch shutterphase: <<: *default_float32 CATDESC: Shutterphase + DEPEND_0: epoch FIELDNAM: shutterphase LABLAXIS: shutterphase UNITS: ' ' - DEPEND_0: epoch shutterplugstate: <<: *default_float32 CATDESC: Shutterplugstate + DEPEND_0: epoch FIELDNAM: shutterplugstate LABLAXIS: shutterplugstate UNITS: ' ' - DEPEND_0: epoch shutterprimary_i_adjust: <<: *default_float32 CATDESC: Shutterprimary i adjust + DEPEND_0: epoch FIELDNAM: shutterprimary_i_adjust LABLAXIS: shutterprimary_i_adjust UNITS: ' ' - DEPEND_0: epoch shutterselect: <<: *default_float32 CATDESC: Shutterselect + DEPEND_0: epoch FIELDNAM: shutterselect LABLAXIS: shutterselect UNITS: ' ' - DEPEND_0: epoch spare10: <<: *default_float32 CATDESC: Spare10 + DEPEND_0: epoch FIELDNAM: spare10 LABLAXIS: spare10 UNITS: ' ' - DEPEND_0: epoch spare4: <<: *default_float32 CATDESC: Spare4 + DEPEND_0: epoch FIELDNAM: spare4 LABLAXIS: spare4 UNITS: ' ' - DEPEND_0: epoch spare5: <<: *default_float32 CATDESC: Spare5 + DEPEND_0: epoch FIELDNAM: spare5 LABLAXIS: spare5 UNITS: ' ' - DEPEND_0: epoch spare6: <<: *default_float32 CATDESC: Spare6 + DEPEND_0: epoch FIELDNAM: spare6 LABLAXIS: spare6 UNITS: ' ' - DEPEND_0: epoch spare7: <<: *default_float32 CATDESC: Spare7 + DEPEND_0: epoch FIELDNAM: spare7 LABLAXIS: spare7 UNITS: ' ' - DEPEND_0: epoch spare8: <<: *default_float32 CATDESC: Spare8 + DEPEND_0: epoch FIELDNAM: spare8 LABLAXIS: spare8 UNITS: ' ' - DEPEND_0: epoch spare9: <<: *default_float32 CATDESC: Spare9 + DEPEND_0: epoch FIELDNAM: spare9 LABLAXIS: spare9 UNITS: ' ' - DEPEND_0: epoch spbtphoff: <<: *default_float32 CATDESC: Spbtphoff + DEPEND_0: epoch FIELDNAM: spbtphoff LABLAXIS: spbtphoff UNITS: ' ' - DEPEND_0: epoch sptpphoff: <<: *default_float32 CATDESC: Sptpphoff + DEPEND_0: epoch FIELDNAM: sptpphoff LABLAXIS: sptpphoff UNITS: ' ' - DEPEND_0: epoch ssd0energystate: <<: *default_float32 CATDESC: Ssd0energystate + DEPEND_0: epoch FIELDNAM: ssd0energystate LABLAXIS: ssd0energystate UNITS: ' ' - DEPEND_0: epoch ssd0energythresh: <<: *default_float32 CATDESC: Ssd0energythresh + DEPEND_0: epoch FIELDNAM: ssd0energythresh LABLAXIS: ssd0energythresh UNITS: ' ' - DEPEND_0: epoch ssd0pixenergybaseline: <<: *default_float32 CATDESC: Ssd0pixenergybaseline + DEPEND_0: epoch FIELDNAM: ssd0pixenergybaseline LABLAXIS: ssd0pixenergybaseline UNITS: ' ' - DEPEND_0: epoch ssd1energystate: <<: *default_float32 CATDESC: Ssd1energystate + DEPEND_0: epoch FIELDNAM: ssd1energystate LABLAXIS: ssd1energystate UNITS: ' ' - DEPEND_0: epoch ssd1energythresh: <<: *default_float32 CATDESC: Ssd1energythresh + DEPEND_0: epoch FIELDNAM: ssd1energythresh LABLAXIS: ssd1energythresh UNITS: ' ' - DEPEND_0: epoch ssd1pixenergybaseline: <<: *default_float32 CATDESC: Ssd1pixenergybaseline + DEPEND_0: epoch FIELDNAM: ssd1pixenergybaseline LABLAXIS: ssd1pixenergybaseline UNITS: ' ' - DEPEND_0: epoch ssd2energystate: <<: *default_float32 CATDESC: Ssd2energystate + DEPEND_0: epoch FIELDNAM: ssd2energystate LABLAXIS: ssd2energystate UNITS: ' ' - DEPEND_0: epoch ssd2energythresh: <<: *default_float32 CATDESC: Ssd2energythresh + DEPEND_0: epoch FIELDNAM: ssd2energythresh LABLAXIS: ssd2energythresh UNITS: ' ' - DEPEND_0: epoch ssd2pixenergybaseline: <<: *default_float32 CATDESC: Ssd2pixenergybaseline + DEPEND_0: epoch FIELDNAM: ssd2pixenergybaseline LABLAXIS: ssd2pixenergybaseline UNITS: ' ' - DEPEND_0: epoch ssd3energystate: <<: *default_float32 CATDESC: Ssd3energystate + DEPEND_0: epoch FIELDNAM: ssd3energystate LABLAXIS: ssd3energystate UNITS: ' ' - DEPEND_0: epoch ssd3energythresh: <<: *default_float32 CATDESC: Ssd3energythresh + DEPEND_0: epoch FIELDNAM: ssd3energythresh LABLAXIS: ssd3energythresh UNITS: ' ' - DEPEND_0: epoch ssd3pixenergybaseline: <<: *default_float32 CATDESC: Ssd3pixenergybaseline + DEPEND_0: epoch FIELDNAM: ssd3pixenergybaseline LABLAXIS: ssd3pixenergybaseline UNITS: ' ' - DEPEND_0: epoch ssd4energystate: <<: *default_float32 CATDESC: Ssd4energystate + DEPEND_0: epoch FIELDNAM: ssd4energystate LABLAXIS: ssd4energystate UNITS: ' ' - DEPEND_0: epoch ssd4energythresh: <<: *default_float32 CATDESC: Ssd4energythresh + DEPEND_0: epoch FIELDNAM: ssd4energythresh LABLAXIS: ssd4energythresh UNITS: ' ' - DEPEND_0: epoch ssd4pixenergybaseline: <<: *default_float32 CATDESC: Ssd4pixenergybaseline + DEPEND_0: epoch FIELDNAM: ssd4pixenergybaseline LABLAXIS: ssd4pixenergybaseline UNITS: ' ' - DEPEND_0: epoch ssd5energystate: <<: *default_float32 CATDESC: Ssd5energystate + DEPEND_0: epoch FIELDNAM: ssd5energystate LABLAXIS: ssd5energystate UNITS: ' ' - DEPEND_0: epoch ssd5energythresh: <<: *default_float32 CATDESC: Ssd5energythresh + DEPEND_0: epoch FIELDNAM: ssd5energythresh LABLAXIS: ssd5energythresh UNITS: ' ' - DEPEND_0: epoch ssd5pixenergybaseline: <<: *default_float32 CATDESC: Ssd5pixenergybaseline + DEPEND_0: epoch FIELDNAM: ssd5pixenergybaseline LABLAXIS: ssd5pixenergybaseline UNITS: ' ' - DEPEND_0: epoch ssd6energystate: <<: *default_float32 CATDESC: Ssd6energystate + DEPEND_0: epoch FIELDNAM: ssd6energystate LABLAXIS: ssd6energystate UNITS: ' ' - DEPEND_0: epoch ssd6energythresh: <<: *default_float32 CATDESC: Ssd6energythresh + DEPEND_0: epoch FIELDNAM: ssd6energythresh LABLAXIS: ssd6energythresh UNITS: ' ' - DEPEND_0: epoch ssd6pixenergybaseline: <<: *default_float32 CATDESC: Ssd6pixenergybaseline + DEPEND_0: epoch FIELDNAM: ssd6pixenergybaseline LABLAXIS: ssd6pixenergybaseline UNITS: ' ' - DEPEND_0: epoch ssd7energystate: <<: *default_float32 CATDESC: Ssd7energystate + DEPEND_0: epoch FIELDNAM: ssd7energystate LABLAXIS: ssd7energystate UNITS: ' ' - DEPEND_0: epoch ssd7energythresh: <<: *default_float32 CATDESC: Ssd7energythresh + DEPEND_0: epoch FIELDNAM: ssd7energythresh LABLAXIS: ssd7energythresh UNITS: ' ' - DEPEND_0: epoch ssd7pixenergybaseline: <<: *default_float32 CATDESC: Ssd7pixenergybaseline + DEPEND_0: epoch FIELDNAM: ssd7pixenergybaseline LABLAXIS: ssd7pixenergybaseline UNITS: ' ' - DEPEND_0: epoch ssdbv_i: <<: *default_float32 CATDESC: Ssdbv i + DEPEND_0: epoch FIELDNAM: ssdbv_i LABLAXIS: ssdbv_i UNITS: ' ' - DEPEND_0: epoch ssdbv_i_hi: <<: *default_float32 CATDESC: Ssdbv i hi + DEPEND_0: epoch FIELDNAM: ssdbv_i_hi LABLAXIS: ssdbv_i_hi UNITS: ' ' - DEPEND_0: epoch ssdbv_i_lo: <<: *default_float32 CATDESC: Ssdbv i lo + DEPEND_0: epoch FIELDNAM: ssdbv_i_lo LABLAXIS: ssdbv_i_lo UNITS: ' ' - DEPEND_0: epoch ssdbv_v: <<: *default_float32 CATDESC: Ssdbv v + DEPEND_0: epoch FIELDNAM: ssdbv_v LABLAXIS: ssdbv_v UNITS: ' ' - DEPEND_0: epoch ssdbv_v_hi: <<: *default_float32 CATDESC: Ssdbv v hi + DEPEND_0: epoch FIELDNAM: ssdbv_v_hi LABLAXIS: ssdbv_v_hi UNITS: ' ' - DEPEND_0: epoch ssdbv_v_lo: <<: *default_float32 CATDESC: Ssdbv v lo + DEPEND_0: epoch FIELDNAM: ssdbv_v_lo LABLAXIS: ssdbv_v_lo UNITS: ' ' - DEPEND_0: epoch ssdbvgoal: <<: *default_float32 CATDESC: Ssdbvgoal + DEPEND_0: epoch FIELDNAM: ssdbvgoal LABLAXIS: ssdbvgoal UNITS: ' ' - DEPEND_0: epoch ssdbvlim: <<: *default_float32 CATDESC: Ssdbvlim + DEPEND_0: epoch FIELDNAM: ssdbvlim LABLAXIS: ssdbvlim UNITS: ' ' - DEPEND_0: epoch ssdbvrampdownrate: <<: *default_float32 CATDESC: Ssdbvrampdownrate + DEPEND_0: epoch FIELDNAM: ssdbvrampdownrate LABLAXIS: ssdbvrampdownrate UNITS: ' ' - DEPEND_0: epoch ssdbvrampuprate: <<: *default_float32 CATDESC: Ssdbvrampuprate + DEPEND_0: epoch FIELDNAM: ssdbvrampuprate LABLAXIS: ssdbvrampuprate UNITS: ' ' - DEPEND_0: epoch ssdbvv: <<: *default_float32 CATDESC: Ssdbvv + DEPEND_0: epoch FIELDNAM: ssdbvv LABLAXIS: ssdbvv UNITS: ' ' - DEPEND_0: epoch ssdpreamppower: <<: *default_float32 CATDESC: Ssdpreamppower + DEPEND_0: epoch FIELDNAM: ssdpreamppower LABLAXIS: ssdpreamppower UNITS: ' ' - DEPEND_0: epoch ssdpulseamplitude: <<: *default_float32 CATDESC: Ssdpulseamplitude + DEPEND_0: epoch FIELDNAM: ssdpulseamplitude LABLAXIS: ssdpulseamplitude UNITS: ' ' - DEPEND_0: epoch ssdpulsedelay: <<: *default_float32 CATDESC: Ssdpulsedelay + DEPEND_0: epoch FIELDNAM: ssdpulsedelay LABLAXIS: ssdpulsedelay UNITS: ' ' - DEPEND_0: epoch ssdpulsestate: <<: *default_float32 CATDESC: Ssdpulsestate + DEPEND_0: epoch FIELDNAM: ssdpulsestate LABLAXIS: ssdpulsestate UNITS: ' ' - DEPEND_0: epoch ssdreference: <<: *default_float32 CATDESC: Ssdreference + DEPEND_0: epoch FIELDNAM: ssdreference LABLAXIS: ssdreference UNITS: ' ' - DEPEND_0: epoch startfullpulsestate: <<: *default_float32 CATDESC: Startfullpulsestate + DEPEND_0: epoch FIELDNAM: startfullpulsestate LABLAXIS: startfullpulsestate UNITS: ' ' - DEPEND_0: epoch startlfautozero: <<: *default_float32 CATDESC: Startlfautozero + DEPEND_0: epoch FIELDNAM: startlfautozero LABLAXIS: startlfautozero UNITS: ' ' - DEPEND_0: epoch startlfcfdthresh: <<: *default_float32 CATDESC: Startlfcfdthresh + DEPEND_0: epoch FIELDNAM: startlfcfdthresh LABLAXIS: startlfcfdthresh UNITS: ' ' - DEPEND_0: epoch startlfphthresh: <<: *default_float32 CATDESC: Startlfphthresh + DEPEND_0: epoch FIELDNAM: startlfphthresh LABLAXIS: startlfphthresh UNITS: ' ' - DEPEND_0: epoch startlpautozero: <<: *default_float32 CATDESC: Startlpautozero + DEPEND_0: epoch FIELDNAM: startlpautozero LABLAXIS: startlpautozero UNITS: ' ' - DEPEND_0: epoch startlpcfdthresh: <<: *default_float32 CATDESC: Startlpcfdthresh + DEPEND_0: epoch FIELDNAM: startlpcfdthresh LABLAXIS: startlpcfdthresh UNITS: ' ' - DEPEND_0: epoch startposdelay: <<: *default_float32 CATDESC: Startposdelay + DEPEND_0: epoch FIELDNAM: startposdelay LABLAXIS: startposdelay UNITS: ' ' - DEPEND_0: epoch startratehighthresh: <<: *default_float32 CATDESC: Startratehighthresh + DEPEND_0: epoch FIELDNAM: startratehighthresh LABLAXIS: startratehighthresh UNITS: ' ' - DEPEND_0: epoch startrfautozero: <<: *default_float32 CATDESC: Startrfautozero + DEPEND_0: epoch FIELDNAM: startrfautozero LABLAXIS: startrfautozero UNITS: ' ' - DEPEND_0: epoch startrfcfdthresh: <<: *default_float32 CATDESC: Startrfcfdthresh + DEPEND_0: epoch FIELDNAM: startrfcfdthresh LABLAXIS: startrfcfdthresh UNITS: ' ' - DEPEND_0: epoch startrfphthresh: <<: *default_float32 CATDESC: Startrfphthresh + DEPEND_0: epoch FIELDNAM: startrfphthresh LABLAXIS: startrfphthresh UNITS: ' ' - DEPEND_0: epoch startrpautozero: <<: *default_float32 CATDESC: Startrpautozero + DEPEND_0: epoch FIELDNAM: startrpautozero LABLAXIS: startrpautozero UNITS: ' ' - DEPEND_0: epoch startrpcfdthresh: <<: *default_float32 CATDESC: Startrpcfdthresh + DEPEND_0: epoch FIELDNAM: startrpcfdthresh LABLAXIS: startrpcfdthresh UNITS: ' ' - DEPEND_0: epoch statusint: <<: *default_float32 CATDESC: Statusint + DEPEND_0: epoch FIELDNAM: statusint LABLAXIS: statusint UNITS: ' ' - DEPEND_0: epoch stopbeautozero: <<: *default_float32 CATDESC: Stopbeautozero + DEPEND_0: epoch FIELDNAM: stopbeautozero LABLAXIS: stopbeautozero UNITS: ' ' - DEPEND_0: epoch stopbecfdthresh: <<: *default_float32 CATDESC: Stopbecfdthresh + DEPEND_0: epoch FIELDNAM: stopbecfdthresh LABLAXIS: stopbecfdthresh UNITS: ' ' - DEPEND_0: epoch stopbnautozero: <<: *default_float32 CATDESC: Stopbnautozero + DEPEND_0: epoch FIELDNAM: stopbnautozero LABLAXIS: stopbnautozero UNITS: ' ' - DEPEND_0: epoch stopbncfdthresh: <<: *default_float32 CATDESC: Stopbncfdthresh + DEPEND_0: epoch FIELDNAM: stopbncfdthresh LABLAXIS: stopbncfdthresh UNITS: ' ' - DEPEND_0: epoch stopbnphthresh: <<: *default_float32 CATDESC: Stopbnphthresh + DEPEND_0: epoch FIELDNAM: stopbnphthresh LABLAXIS: stopbnphthresh UNITS: ' ' - DEPEND_0: epoch stopbsautozero: <<: *default_float32 CATDESC: Stopbsautozero + DEPEND_0: epoch FIELDNAM: stopbsautozero LABLAXIS: stopbsautozero UNITS: ' ' - DEPEND_0: epoch stopbscfdthresh: <<: *default_float32 CATDESC: Stopbscfdthresh + DEPEND_0: epoch FIELDNAM: stopbscfdthresh LABLAXIS: stopbscfdthresh UNITS: ' ' - DEPEND_0: epoch stopbwautozero: <<: *default_float32 CATDESC: Stopbwautozero + DEPEND_0: epoch FIELDNAM: stopbwautozero LABLAXIS: stopbwautozero UNITS: ' ' - DEPEND_0: epoch stopbwcfdthresh: <<: *default_float32 CATDESC: Stopbwcfdthresh + DEPEND_0: epoch FIELDNAM: stopbwcfdthresh LABLAXIS: stopbwcfdthresh UNITS: ' ' - DEPEND_0: epoch stopcoinnorthpulsedelay: <<: *default_float32 CATDESC: Stopcoinnorthpulsedelay + DEPEND_0: epoch FIELDNAM: stopcoinnorthpulsedelay LABLAXIS: stopcoinnorthpulsedelay UNITS: ' ' - DEPEND_0: epoch stopcoinnorthpulsestate: <<: *default_float32 CATDESC: Stopcoinnorthpulsestate + DEPEND_0: epoch FIELDNAM: stopcoinnorthpulsestate LABLAXIS: stopcoinnorthpulsestate UNITS: ' ' - DEPEND_0: epoch stopcoinsouthpulsedelay: <<: *default_float32 CATDESC: Stopcoinsouthpulsedelay + DEPEND_0: epoch FIELDNAM: stopcoinsouthpulsedelay LABLAXIS: stopcoinsouthpulsedelay UNITS: ' ' - DEPEND_0: epoch stopcoinsouthpulsestate: <<: *default_float32 CATDESC: Stopcoinsouthpulsestate + DEPEND_0: epoch FIELDNAM: stopcoinsouthpulsestate LABLAXIS: stopcoinsouthpulsestate UNITS: ' ' - DEPEND_0: epoch stopeastpulsedelay: <<: *default_float32 CATDESC: Stopeastpulsedelay + DEPEND_0: epoch FIELDNAM: stopeastpulsedelay LABLAXIS: stopeastpulsedelay UNITS: ' ' - DEPEND_0: epoch stopeastpulsestate: <<: *default_float32 CATDESC: Stopeastpulsestate + DEPEND_0: epoch FIELDNAM: stopeastpulsestate LABLAXIS: stopeastpulsestate UNITS: ' ' - DEPEND_0: epoch stopratehighthresh: <<: *default_float32 CATDESC: Stopratehighthresh + DEPEND_0: epoch FIELDNAM: stopratehighthresh LABLAXIS: stopratehighthresh UNITS: ' ' - DEPEND_0: epoch stopteautozero: <<: *default_float32 CATDESC: Stopteautozero + DEPEND_0: epoch FIELDNAM: stopteautozero LABLAXIS: stopteautozero UNITS: ' ' - DEPEND_0: epoch stoptecfdthresh: <<: *default_float32 CATDESC: Stoptecfdthresh + DEPEND_0: epoch FIELDNAM: stoptecfdthresh LABLAXIS: stoptecfdthresh UNITS: ' ' - DEPEND_0: epoch stoptnautozero: <<: *default_float32 CATDESC: Stoptnautozero + DEPEND_0: epoch FIELDNAM: stoptnautozero LABLAXIS: stoptnautozero UNITS: ' ' - DEPEND_0: epoch stoptncfdthresh: <<: *default_float32 CATDESC: Stoptncfdthresh + DEPEND_0: epoch FIELDNAM: stoptncfdthresh LABLAXIS: stoptncfdthresh UNITS: ' ' - DEPEND_0: epoch stoptnphthresh: <<: *default_float32 CATDESC: Stoptnphthresh + DEPEND_0: epoch FIELDNAM: stoptnphthresh LABLAXIS: stoptnphthresh UNITS: ' ' - DEPEND_0: epoch stoptsautozero: <<: *default_float32 CATDESC: Stoptsautozero + DEPEND_0: epoch FIELDNAM: stoptsautozero LABLAXIS: stoptsautozero UNITS: ' ' - DEPEND_0: epoch stoptscfdthresh: <<: *default_float32 CATDESC: Stoptscfdthresh + DEPEND_0: epoch FIELDNAM: stoptscfdthresh LABLAXIS: stoptscfdthresh UNITS: ' ' - DEPEND_0: epoch stoptwautozero: <<: *default_float32 CATDESC: Stoptwautozero + DEPEND_0: epoch FIELDNAM: stoptwautozero LABLAXIS: stoptwautozero UNITS: ' ' - DEPEND_0: epoch stoptwcfdthresh: <<: *default_float32 CATDESC: Stoptwcfdthresh + DEPEND_0: epoch FIELDNAM: stoptwcfdthresh LABLAXIS: stoptwcfdthresh UNITS: ' ' - DEPEND_0: epoch stopwestpulsedelay: <<: *default_float32 CATDESC: Stopwestpulsedelay + DEPEND_0: epoch FIELDNAM: stopwestpulsedelay LABLAXIS: stopwestpulsedelay UNITS: ' ' - DEPEND_0: epoch stopwestpulsestate: <<: *default_float32 CATDESC: Stopwestpulsestate + DEPEND_0: epoch FIELDNAM: stopwestpulsestate LABLAXIS: stopwestpulsestate UNITS: ' ' - DEPEND_0: epoch swtime: <<: *default_float32 CATDESC: Swtime + DEPEND_0: epoch FIELDNAM: swtime LABLAXIS: swtime UNITS: ' ' - DEPEND_0: epoch swversion: <<: *default_float32 CATDESC: Swversion + DEPEND_0: epoch FIELDNAM: swversion LABLAXIS: swversion UNITS: ' ' - DEPEND_0: epoch test1: <<: *default_float32 CATDESC: Test1 + DEPEND_0: epoch FIELDNAM: test1 LABLAXIS: test1 UNITS: ' ' - DEPEND_0: epoch test2: <<: *default_float32 CATDESC: Test2 + DEPEND_0: epoch FIELDNAM: test2 LABLAXIS: test2 UNITS: ' ' - DEPEND_0: epoch text: CATDESC: Command text per packet + DEPEND_0: epoch FIELDNAM: text LABLAXIS: text UNITS: ' ' - DEPEND_0: epoch text_0: <<: *default_float32 CATDESC: Text 0 + DEPEND_0: epoch FIELDNAM: text_0 LABLAXIS: text_0 UNITS: ' ' - DEPEND_0: epoch text_1: <<: *default_float32 CATDESC: Text 1 + DEPEND_0: epoch FIELDNAM: text_1 LABLAXIS: text_1 UNITS: ' ' - DEPEND_0: epoch text_10: <<: *default_float32 CATDESC: Text 10 + DEPEND_0: epoch FIELDNAM: text_10 LABLAXIS: text_10 UNITS: ' ' - DEPEND_0: epoch text_11: <<: *default_float32 CATDESC: Text 11 + DEPEND_0: epoch FIELDNAM: text_11 LABLAXIS: text_11 UNITS: ' ' - DEPEND_0: epoch text_12: <<: *default_float32 CATDESC: Text 12 + DEPEND_0: epoch FIELDNAM: text_12 LABLAXIS: text_12 UNITS: ' ' - DEPEND_0: epoch text_13: <<: *default_float32 CATDESC: Text 13 + DEPEND_0: epoch FIELDNAM: text_13 LABLAXIS: text_13 UNITS: ' ' - DEPEND_0: epoch text_14: <<: *default_float32 CATDESC: Text 14 + DEPEND_0: epoch FIELDNAM: text_14 LABLAXIS: text_14 UNITS: ' ' - DEPEND_0: epoch text_15: <<: *default_float32 CATDESC: Text 15 + DEPEND_0: epoch FIELDNAM: text_15 LABLAXIS: text_15 UNITS: ' ' - DEPEND_0: epoch text_16: <<: *default_float32 CATDESC: Text 16 + DEPEND_0: epoch FIELDNAM: text_16 LABLAXIS: text_16 UNITS: ' ' - DEPEND_0: epoch text_17: <<: *default_float32 CATDESC: Text 17 + DEPEND_0: epoch FIELDNAM: text_17 LABLAXIS: text_17 UNITS: ' ' - DEPEND_0: epoch text_18: <<: *default_float32 CATDESC: Text 18 + DEPEND_0: epoch FIELDNAM: text_18 LABLAXIS: text_18 UNITS: ' ' - DEPEND_0: epoch text_19: <<: *default_float32 CATDESC: Text 19 + DEPEND_0: epoch FIELDNAM: text_19 LABLAXIS: text_19 UNITS: ' ' - DEPEND_0: epoch text_2: <<: *default_float32 CATDESC: Text 2 + DEPEND_0: epoch FIELDNAM: text_2 LABLAXIS: text_2 UNITS: ' ' - DEPEND_0: epoch text_20: <<: *default_float32 CATDESC: Text 20 + DEPEND_0: epoch FIELDNAM: text_20 LABLAXIS: text_20 UNITS: ' ' - DEPEND_0: epoch text_21: <<: *default_float32 CATDESC: Text 21 + DEPEND_0: epoch FIELDNAM: text_21 LABLAXIS: text_21 UNITS: ' ' - DEPEND_0: epoch text_22: <<: *default_float32 CATDESC: Text 22 + DEPEND_0: epoch FIELDNAM: text_22 LABLAXIS: text_22 UNITS: ' ' - DEPEND_0: epoch text_23: <<: *default_float32 CATDESC: Text 23 + DEPEND_0: epoch FIELDNAM: text_23 LABLAXIS: text_23 UNITS: ' ' - DEPEND_0: epoch text_24: <<: *default_float32 CATDESC: Text 24 + DEPEND_0: epoch FIELDNAM: text_24 LABLAXIS: text_24 UNITS: ' ' - DEPEND_0: epoch text_25: <<: *default_float32 CATDESC: Text 25 + DEPEND_0: epoch FIELDNAM: text_25 LABLAXIS: text_25 UNITS: ' ' - DEPEND_0: epoch text_26: <<: *default_float32 CATDESC: Text 26 + DEPEND_0: epoch FIELDNAM: text_26 LABLAXIS: text_26 UNITS: ' ' - DEPEND_0: epoch text_27: <<: *default_float32 CATDESC: Text 27 + DEPEND_0: epoch FIELDNAM: text_27 LABLAXIS: text_27 UNITS: ' ' - DEPEND_0: epoch text_28: <<: *default_float32 CATDESC: Text 28 + DEPEND_0: epoch FIELDNAM: text_28 LABLAXIS: text_28 UNITS: ' ' - DEPEND_0: epoch text_29: <<: *default_float32 CATDESC: Text 29 + DEPEND_0: epoch FIELDNAM: text_29 LABLAXIS: text_29 UNITS: ' ' - DEPEND_0: epoch text_3: <<: *default_float32 CATDESC: Text 3 + DEPEND_0: epoch FIELDNAM: text_3 LABLAXIS: text_3 UNITS: ' ' - DEPEND_0: epoch text_30: <<: *default_float32 CATDESC: Text 30 + DEPEND_0: epoch FIELDNAM: text_30 LABLAXIS: text_30 UNITS: ' ' - DEPEND_0: epoch text_31: <<: *default_float32 CATDESC: Text 31 + DEPEND_0: epoch FIELDNAM: text_31 LABLAXIS: text_31 UNITS: ' ' - DEPEND_0: epoch text_32: <<: *default_float32 CATDESC: Text 32 + DEPEND_0: epoch FIELDNAM: text_32 LABLAXIS: text_32 UNITS: ' ' - DEPEND_0: epoch text_33: <<: *default_float32 CATDESC: Text 33 + DEPEND_0: epoch FIELDNAM: text_33 LABLAXIS: text_33 UNITS: ' ' - DEPEND_0: epoch text_34: <<: *default_float32 CATDESC: Text 34 + DEPEND_0: epoch FIELDNAM: text_34 LABLAXIS: text_34 UNITS: ' ' - DEPEND_0: epoch text_35: <<: *default_float32 CATDESC: Text 35 + DEPEND_0: epoch FIELDNAM: text_35 LABLAXIS: text_35 UNITS: ' ' - DEPEND_0: epoch text_36: <<: *default_float32 CATDESC: Text 36 + DEPEND_0: epoch FIELDNAM: text_36 LABLAXIS: text_36 UNITS: ' ' - DEPEND_0: epoch text_37: <<: *default_float32 CATDESC: Text 37 + DEPEND_0: epoch FIELDNAM: text_37 LABLAXIS: text_37 UNITS: ' ' - DEPEND_0: epoch text_38: <<: *default_float32 CATDESC: Text 38 + DEPEND_0: epoch FIELDNAM: text_38 LABLAXIS: text_38 UNITS: ' ' - DEPEND_0: epoch text_39: <<: *default_float32 CATDESC: Text 39 + DEPEND_0: epoch FIELDNAM: text_39 LABLAXIS: text_39 UNITS: ' ' - DEPEND_0: epoch text_4: <<: *default_float32 CATDESC: Text 4 + DEPEND_0: epoch FIELDNAM: text_4 LABLAXIS: text_4 UNITS: ' ' - DEPEND_0: epoch text_40: <<: *default_float32 CATDESC: Text 40 + DEPEND_0: epoch FIELDNAM: text_40 LABLAXIS: text_40 UNITS: ' ' - DEPEND_0: epoch text_41: <<: *default_float32 CATDESC: Text 41 + DEPEND_0: epoch FIELDNAM: text_41 LABLAXIS: text_41 UNITS: ' ' - DEPEND_0: epoch text_42: <<: *default_float32 CATDESC: Text 42 + DEPEND_0: epoch FIELDNAM: text_42 LABLAXIS: text_42 UNITS: ' ' - DEPEND_0: epoch text_43: <<: *default_float32 CATDESC: Text 43 + DEPEND_0: epoch FIELDNAM: text_43 LABLAXIS: text_43 UNITS: ' ' - DEPEND_0: epoch text_44: <<: *default_float32 CATDESC: Text 44 + DEPEND_0: epoch FIELDNAM: text_44 LABLAXIS: text_44 UNITS: ' ' - DEPEND_0: epoch text_45: <<: *default_float32 CATDESC: Text 45 + DEPEND_0: epoch FIELDNAM: text_45 LABLAXIS: text_45 UNITS: ' ' - DEPEND_0: epoch text_46: <<: *default_float32 CATDESC: Text 46 + DEPEND_0: epoch FIELDNAM: text_46 LABLAXIS: text_46 UNITS: ' ' - DEPEND_0: epoch text_47: <<: *default_float32 CATDESC: Text 47 + DEPEND_0: epoch FIELDNAM: text_47 LABLAXIS: text_47 UNITS: ' ' - DEPEND_0: epoch text_48: <<: *default_float32 CATDESC: Text 48 + DEPEND_0: epoch FIELDNAM: text_48 LABLAXIS: text_48 UNITS: ' ' - DEPEND_0: epoch text_49: <<: *default_float32 CATDESC: Text 49 + DEPEND_0: epoch FIELDNAM: text_49 LABLAXIS: text_49 UNITS: ' ' - DEPEND_0: epoch text_5: <<: *default_float32 CATDESC: Text 5 + DEPEND_0: epoch FIELDNAM: text_5 LABLAXIS: text_5 UNITS: ' ' - DEPEND_0: epoch text_50: <<: *default_float32 CATDESC: Text 50 + DEPEND_0: epoch FIELDNAM: text_50 LABLAXIS: text_50 UNITS: ' ' - DEPEND_0: epoch text_51: <<: *default_float32 CATDESC: Text 51 + DEPEND_0: epoch FIELDNAM: text_51 LABLAXIS: text_51 UNITS: ' ' - DEPEND_0: epoch text_52: <<: *default_float32 CATDESC: Text 52 + DEPEND_0: epoch FIELDNAM: text_52 LABLAXIS: text_52 UNITS: ' ' - DEPEND_0: epoch text_53: <<: *default_float32 CATDESC: Text 53 + DEPEND_0: epoch FIELDNAM: text_53 LABLAXIS: text_53 UNITS: ' ' - DEPEND_0: epoch text_54: <<: *default_float32 CATDESC: Text 54 + DEPEND_0: epoch FIELDNAM: text_54 LABLAXIS: text_54 UNITS: ' ' - DEPEND_0: epoch text_55: <<: *default_float32 CATDESC: Text 55 + DEPEND_0: epoch FIELDNAM: text_55 LABLAXIS: text_55 UNITS: ' ' - DEPEND_0: epoch text_56: <<: *default_float32 CATDESC: Text 56 + DEPEND_0: epoch FIELDNAM: text_56 LABLAXIS: text_56 UNITS: ' ' - DEPEND_0: epoch text_57: <<: *default_float32 CATDESC: Text 57 + DEPEND_0: epoch FIELDNAM: text_57 LABLAXIS: text_57 UNITS: ' ' - DEPEND_0: epoch text_58: <<: *default_float32 CATDESC: Text 58 + DEPEND_0: epoch FIELDNAM: text_58 LABLAXIS: text_58 UNITS: ' ' - DEPEND_0: epoch text_59: <<: *default_float32 CATDESC: Text 59 + DEPEND_0: epoch FIELDNAM: text_59 LABLAXIS: text_59 UNITS: ' ' - DEPEND_0: epoch text_6: <<: *default_float32 CATDESC: Text 6 + DEPEND_0: epoch FIELDNAM: text_6 LABLAXIS: text_6 UNITS: ' ' - DEPEND_0: epoch text_60: <<: *default_float32 CATDESC: Text 60 + DEPEND_0: epoch FIELDNAM: text_60 LABLAXIS: text_60 UNITS: ' ' - DEPEND_0: epoch text_61: <<: *default_float32 CATDESC: Text 61 + DEPEND_0: epoch FIELDNAM: text_61 LABLAXIS: text_61 UNITS: ' ' - DEPEND_0: epoch text_62: <<: *default_float32 CATDESC: Text 62 + DEPEND_0: epoch FIELDNAM: text_62 LABLAXIS: text_62 UNITS: ' ' - DEPEND_0: epoch text_63: <<: *default_float32 CATDESC: Text 63 + DEPEND_0: epoch FIELDNAM: text_63 LABLAXIS: text_63 UNITS: ' ' - DEPEND_0: epoch text_64: <<: *default_float32 CATDESC: Text 64 + DEPEND_0: epoch FIELDNAM: text_64 LABLAXIS: text_64 UNITS: ' ' - DEPEND_0: epoch text_65: <<: *default_float32 CATDESC: Text 65 + DEPEND_0: epoch FIELDNAM: text_65 LABLAXIS: text_65 UNITS: ' ' - DEPEND_0: epoch text_66: <<: *default_float32 CATDESC: Text 66 + DEPEND_0: epoch FIELDNAM: text_66 LABLAXIS: text_66 UNITS: ' ' - DEPEND_0: epoch text_67: <<: *default_float32 CATDESC: Text 67 + DEPEND_0: epoch FIELDNAM: text_67 LABLAXIS: text_67 UNITS: ' ' - DEPEND_0: epoch text_68: <<: *default_float32 CATDESC: Text 68 + DEPEND_0: epoch FIELDNAM: text_68 LABLAXIS: text_68 UNITS: ' ' - DEPEND_0: epoch text_69: <<: *default_float32 CATDESC: Text 69 + DEPEND_0: epoch FIELDNAM: text_69 LABLAXIS: text_69 UNITS: ' ' - DEPEND_0: epoch text_7: <<: *default_float32 CATDESC: Text 7 + DEPEND_0: epoch FIELDNAM: text_7 LABLAXIS: text_7 UNITS: ' ' - DEPEND_0: epoch text_70: <<: *default_float32 CATDESC: Text 70 + DEPEND_0: epoch FIELDNAM: text_70 LABLAXIS: text_70 UNITS: ' ' - DEPEND_0: epoch text_71: <<: *default_float32 CATDESC: Text 71 + DEPEND_0: epoch FIELDNAM: text_71 LABLAXIS: text_71 UNITS: ' ' - DEPEND_0: epoch text_72: <<: *default_float32 CATDESC: Text 72 + DEPEND_0: epoch FIELDNAM: text_72 LABLAXIS: text_72 UNITS: ' ' - DEPEND_0: epoch text_73: <<: *default_float32 CATDESC: Text 73 + DEPEND_0: epoch FIELDNAM: text_73 LABLAXIS: text_73 UNITS: ' ' - DEPEND_0: epoch text_74: <<: *default_float32 CATDESC: Text 74 + DEPEND_0: epoch FIELDNAM: text_74 LABLAXIS: text_74 UNITS: ' ' - DEPEND_0: epoch text_75: <<: *default_float32 CATDESC: Text 75 + DEPEND_0: epoch FIELDNAM: text_75 LABLAXIS: text_75 UNITS: ' ' - DEPEND_0: epoch text_76: <<: *default_float32 CATDESC: Text 76 + DEPEND_0: epoch FIELDNAM: text_76 LABLAXIS: text_76 UNITS: ' ' - DEPEND_0: epoch text_8: <<: *default_float32 CATDESC: Text 8 + DEPEND_0: epoch FIELDNAM: text_8 LABLAXIS: text_8 UNITS: ' ' - DEPEND_0: epoch text_9: <<: *default_float32 CATDESC: Text 9 + DEPEND_0: epoch FIELDNAM: text_9 LABLAXIS: text_9 UNITS: ' ' - DEPEND_0: epoch textlength: <<: *default_float32 CATDESC: Textlength + DEPEND_0: epoch FIELDNAM: textlength LABLAXIS: textlength UNITS: ' ' - DEPEND_0: epoch tlmvolume: <<: *default_float32 CATDESC: Tlmvolume + DEPEND_0: epoch FIELDNAM: tlmvolume LABLAXIS: tlmvolume UNITS: ' ' - DEPEND_0: epoch tofbtoff: <<: *default_float32 CATDESC: Tofbtoff + DEPEND_0: epoch FIELDNAM: tofbtoff LABLAXIS: tofbtoff UNITS: ' ' - DEPEND_0: epoch tofdiffbtmax: <<: *default_float32 CATDESC: Tofdiffbtmax + DEPEND_0: epoch FIELDNAM: tofdiffbtmax LABLAXIS: tofdiffbtmax UNITS: ' ' - DEPEND_0: epoch tofdiffbtmin: <<: *default_float32 CATDESC: Tofdiffbtmin + DEPEND_0: epoch FIELDNAM: tofdiffbtmin LABLAXIS: tofdiffbtmin UNITS: ' ' - DEPEND_0: epoch tofdifftpmax: <<: *default_float32 CATDESC: Tofdifftpmax + DEPEND_0: epoch FIELDNAM: tofdifftpmax LABLAXIS: tofdifftpmax UNITS: ' ' - DEPEND_0: epoch tofdifftpmin: <<: *default_float32 CATDESC: Tofdifftpmin + DEPEND_0: epoch FIELDNAM: tofdifftpmin LABLAXIS: tofdifftpmin UNITS: ' ' - DEPEND_0: epoch tofsc: <<: *default_float32 CATDESC: Tofsc + DEPEND_0: epoch FIELDNAM: tofsc LABLAXIS: tofsc UNITS: ' ' - DEPEND_0: epoch tofssdltoff0: <<: *default_float32 CATDESC: Tofssdltoff0 + DEPEND_0: epoch FIELDNAM: tofssdltoff0 LABLAXIS: tofssdltoff0 UNITS: ' ' - DEPEND_0: epoch tofssdltoff1: <<: *default_float32 CATDESC: Tofssdltoff1 + DEPEND_0: epoch FIELDNAM: tofssdltoff1 LABLAXIS: tofssdltoff1 UNITS: ' ' - DEPEND_0: epoch tofssdltoff2: <<: *default_float32 CATDESC: Tofssdltoff2 + DEPEND_0: epoch FIELDNAM: tofssdltoff2 LABLAXIS: tofssdltoff2 UNITS: ' ' - DEPEND_0: epoch tofssdltoff3: <<: *default_float32 CATDESC: Tofssdltoff3 + DEPEND_0: epoch FIELDNAM: tofssdltoff3 LABLAXIS: tofssdltoff3 UNITS: ' ' - DEPEND_0: epoch tofssdltoff4: <<: *default_float32 CATDESC: Tofssdltoff4 + DEPEND_0: epoch FIELDNAM: tofssdltoff4 LABLAXIS: tofssdltoff4 UNITS: ' ' - DEPEND_0: epoch tofssdltoff5: <<: *default_float32 CATDESC: Tofssdltoff5 + DEPEND_0: epoch FIELDNAM: tofssdltoff5 LABLAXIS: tofssdltoff5 UNITS: ' ' - DEPEND_0: epoch tofssdltoff6: <<: *default_float32 CATDESC: Tofssdltoff6 + DEPEND_0: epoch FIELDNAM: tofssdltoff6 LABLAXIS: tofssdltoff6 UNITS: ' ' - DEPEND_0: epoch tofssdltoff7: <<: *default_float32 CATDESC: Tofssdltoff7 + DEPEND_0: epoch FIELDNAM: tofssdltoff7 LABLAXIS: tofssdltoff7 UNITS: ' ' - DEPEND_0: epoch tofssdrtoff0: <<: *default_float32 CATDESC: Tofssdrtoff0 + DEPEND_0: epoch FIELDNAM: tofssdrtoff0 LABLAXIS: tofssdrtoff0 UNITS: ' ' - DEPEND_0: epoch tofssdrtoff1: <<: *default_float32 CATDESC: Tofssdrtoff1 + DEPEND_0: epoch FIELDNAM: tofssdrtoff1 LABLAXIS: tofssdrtoff1 UNITS: ' ' - DEPEND_0: epoch tofssdrtoff2: <<: *default_float32 CATDESC: Tofssdrtoff2 + DEPEND_0: epoch FIELDNAM: tofssdrtoff2 LABLAXIS: tofssdrtoff2 UNITS: ' ' - DEPEND_0: epoch tofssdrtoff3: <<: *default_float32 CATDESC: Tofssdrtoff3 + DEPEND_0: epoch FIELDNAM: tofssdrtoff3 LABLAXIS: tofssdrtoff3 UNITS: ' ' - DEPEND_0: epoch tofssdrtoff4: <<: *default_float32 CATDESC: Tofssdrtoff4 + DEPEND_0: epoch FIELDNAM: tofssdrtoff4 LABLAXIS: tofssdrtoff4 UNITS: ' ' - DEPEND_0: epoch tofssdrtoff5: <<: *default_float32 CATDESC: Tofssdrtoff5 + DEPEND_0: epoch FIELDNAM: tofssdrtoff5 LABLAXIS: tofssdrtoff5 UNITS: ' ' - DEPEND_0: epoch tofssdrtoff6: <<: *default_float32 CATDESC: Tofssdrtoff6 + DEPEND_0: epoch FIELDNAM: tofssdrtoff6 LABLAXIS: tofssdrtoff6 UNITS: ' ' - DEPEND_0: epoch tofssdrtoff7: <<: *default_float32 CATDESC: Tofssdrtoff7 + DEPEND_0: epoch FIELDNAM: tofssdrtoff7 LABLAXIS: tofssdrtoff7 UNITS: ' ' - DEPEND_0: epoch tofssdsc: <<: *default_float32 CATDESC: Tofssdsc + DEPEND_0: epoch FIELDNAM: tofssdsc LABLAXIS: tofssdsc UNITS: ' ' - DEPEND_0: epoch tofssdtotoff: <<: *default_float32 CATDESC: Tofssdtotoff + DEPEND_0: epoch FIELDNAM: tofssdtotoff LABLAXIS: tofssdtotoff UNITS: ' ' - DEPEND_0: epoch toftpoff: <<: *default_float32 CATDESC: Toftpoff + DEPEND_0: epoch FIELDNAM: toftpoff LABLAXIS: toftpoff UNITS: ' ' - DEPEND_0: epoch topmcp_i: <<: *default_float32 CATDESC: Topmcp i + DEPEND_0: epoch FIELDNAM: topmcp_i LABLAXIS: topmcp_i UNITS: ' ' - DEPEND_0: epoch topmcp_i_hi: <<: *default_float32 CATDESC: Topmcp i hi + DEPEND_0: epoch FIELDNAM: topmcp_i_hi LABLAXIS: topmcp_i_hi UNITS: ' ' - DEPEND_0: epoch topmcp_i_lo: <<: *default_float32 CATDESC: Topmcp i lo + DEPEND_0: epoch FIELDNAM: topmcp_i_lo LABLAXIS: topmcp_i_lo UNITS: ' ' - DEPEND_0: epoch topmcp_v: <<: *default_float32 CATDESC: Topmcp v + DEPEND_0: epoch FIELDNAM: topmcp_v LABLAXIS: topmcp_v UNITS: ' ' - DEPEND_0: epoch topmcp_v_hi: <<: *default_float32 CATDESC: Topmcp v hi + DEPEND_0: epoch FIELDNAM: topmcp_v_hi LABLAXIS: topmcp_v_hi UNITS: ' ' - DEPEND_0: epoch topmcp_v_lo: <<: *default_float32 CATDESC: Topmcp v lo + DEPEND_0: epoch FIELDNAM: topmcp_v_lo LABLAXIS: topmcp_v_lo UNITS: ' ' - DEPEND_0: epoch topmcphvfault: <<: *default_float32 CATDESC: Topmcphvfault + DEPEND_0: epoch FIELDNAM: topmcphvfault LABLAXIS: topmcphvfault UNITS: ' ' - DEPEND_0: epoch topmcphvgoal: <<: *default_float32 CATDESC: Topmcphvgoal + DEPEND_0: epoch FIELDNAM: topmcphvgoal LABLAXIS: topmcphvgoal UNITS: ' ' - DEPEND_0: epoch topmcphvilim: <<: *default_float32 CATDESC: Topmcphvilim + DEPEND_0: epoch FIELDNAM: topmcphvilim LABLAXIS: topmcphvilim UNITS: ' ' - DEPEND_0: epoch topmcphvlim: <<: *default_float32 CATDESC: Topmcphvlim + DEPEND_0: epoch FIELDNAM: topmcphvlim LABLAXIS: topmcphvlim UNITS: ' ' - DEPEND_0: epoch topmcphvmonitor: <<: *default_float32 CATDESC: Topmcphvmonitor + DEPEND_0: epoch FIELDNAM: topmcphvmonitor LABLAXIS: topmcphvmonitor UNITS: ' ' - DEPEND_0: epoch topmcphvtrip: <<: *default_float32 CATDESC: Topmcphvtrip + DEPEND_0: epoch FIELDNAM: topmcphvtrip LABLAXIS: topmcphvtrip UNITS: ' ' - DEPEND_0: epoch topmcphvv: <<: *default_float32 CATDESC: Topmcphvv + DEPEND_0: epoch FIELDNAM: topmcphvv LABLAXIS: topmcphvv UNITS: ' ' - DEPEND_0: epoch unused: <<: *default_float32 CATDESC: Unused + DEPEND_0: epoch FIELDNAM: unused LABLAXIS: unused UNITS: ' ' - DEPEND_0: epoch value: <<: *default_float32 CATDESC: Value + DEPEND_0: epoch FIELDNAM: value LABLAXIS: value UNITS: ' ' - DEPEND_0: epoch watchaddr: <<: *default_float32 CATDESC: Watchaddr + DEPEND_0: epoch FIELDNAM: watchaddr LABLAXIS: watchaddr UNITS: ' ' - DEPEND_0: epoch watchdata_0: <<: *default_float32 CATDESC: Watchdata 0 + DEPEND_0: epoch FIELDNAM: watchdata_0 LABLAXIS: watchdata_0 UNITS: ' ' - DEPEND_0: epoch watchdata_1: <<: *default_float32 CATDESC: Watchdata 1 + DEPEND_0: epoch FIELDNAM: watchdata_1 LABLAXIS: watchdata_1 UNITS: ' ' - DEPEND_0: epoch watchmemid: <<: *default_float32 CATDESC: Watchmemid + DEPEND_0: epoch FIELDNAM: watchmemid LABLAXIS: watchmemid UNITS: ' ' - DEPEND_0: epoch xcoinbtoff: <<: *default_float32 CATDESC: Xcoinbtoff + DEPEND_0: epoch FIELDNAM: xcoinbtoff LABLAXIS: xcoinbtoff UNITS: ' ' - DEPEND_0: epoch xcoinbtsc: <<: *default_float32 CATDESC: Xcoinbtsc + DEPEND_0: epoch FIELDNAM: xcoinbtsc LABLAXIS: xcoinbtsc UNITS: ' ' - DEPEND_0: epoch xcointpoff: <<: *default_float32 CATDESC: Xcointpoff + DEPEND_0: epoch FIELDNAM: xcointpoff LABLAXIS: xcointpoff UNITS: ' ' - DEPEND_0: epoch xcointpsc: <<: *default_float32 CATDESC: Xcointpsc + DEPEND_0: epoch FIELDNAM: xcointpsc LABLAXIS: xcointpsc UNITS: ' ' - DEPEND_0: epoch xftltoff: <<: *default_float32 CATDESC: Xftltoff + DEPEND_0: epoch FIELDNAM: xftltoff LABLAXIS: xftltoff UNITS: ' ' - DEPEND_0: epoch xftrtoff: <<: *default_float32 CATDESC: Xftrtoff + DEPEND_0: epoch FIELDNAM: xftrtoff LABLAXIS: xftrtoff UNITS: ' ' - DEPEND_0: epoch xftsc: <<: *default_float32 CATDESC: Xftsc + DEPEND_0: epoch FIELDNAM: xftsc LABLAXIS: xftsc UNITS: ' ' - DEPEND_0: epoch xfttof: <<: *default_float32 CATDESC: Xfttof + DEPEND_0: epoch FIELDNAM: xfttof LABLAXIS: xfttof UNITS: ' ' - DEPEND_0: epoch ybkssd0: <<: *default_float32 CATDESC: Ybkssd0 + DEPEND_0: epoch FIELDNAM: ybkssd0 LABLAXIS: ybkssd0 UNITS: ' ' - DEPEND_0: epoch ybkssd1: <<: *default_float32 CATDESC: Ybkssd1 + DEPEND_0: epoch FIELDNAM: ybkssd1 LABLAXIS: ybkssd1 UNITS: ' ' - DEPEND_0: epoch ybkssd2: <<: *default_float32 CATDESC: Ybkssd2 + DEPEND_0: epoch FIELDNAM: ybkssd2 LABLAXIS: ybkssd2 UNITS: ' ' - DEPEND_0: epoch ybkssd3: <<: *default_float32 CATDESC: Ybkssd3 + DEPEND_0: epoch FIELDNAM: ybkssd3 LABLAXIS: ybkssd3 UNITS: ' ' - DEPEND_0: epoch ybkssd4: <<: *default_float32 CATDESC: Ybkssd4 + DEPEND_0: epoch FIELDNAM: ybkssd4 LABLAXIS: ybkssd4 UNITS: ' ' - DEPEND_0: epoch ybkssd5: <<: *default_float32 CATDESC: Ybkssd5 + DEPEND_0: epoch FIELDNAM: ybkssd5 LABLAXIS: ybkssd5 UNITS: ' ' - DEPEND_0: epoch ybkssd6: <<: *default_float32 CATDESC: Ybkssd6 + DEPEND_0: epoch FIELDNAM: ybkssd6 LABLAXIS: ybkssd6 UNITS: ' ' - DEPEND_0: epoch ybkssd7: <<: *default_float32 CATDESC: Ybkssd7 + DEPEND_0: epoch FIELDNAM: ybkssd7 LABLAXIS: ybkssd7 UNITS: ' ' - DEPEND_0: epoch diff --git a/imap_processing/cdf/config/imap_ultra_l1b_variable_attrs.yaml b/imap_processing/cdf/config/imap_ultra_l1b_variable_attrs.yaml index a51404c3ba..b6f4adf96d 100644 --- a/imap_processing/cdf/config/imap_ultra_l1b_variable_attrs.yaml +++ b/imap_processing/cdf/config/imap_ultra_l1b_variable_attrs.yaml @@ -4,74 +4,90 @@ default_attrs: &default DISPLAY_TYPE: time_series FILLVAL: -9223372036854775808 FORMAT: I12 - VALIDMIN: -9223372036854775808 + UNITS: " " VALIDMAX: 9223372036854775807 + VALIDMIN: -9223372036854775808 VAR_TYPE: data - UNITS: " " component: CATDESC: Velocity components (vx, vy, vz) FIELDNAM: component - LABLAXIS: component FORMAT: A3 + LABLAXIS: component VAR_TYPE: metadata default_uint8_attrs: &default_uint8 <<: *default FILLVAL: 255 FORMAT: I3 - VALIDMIN: 0 VALIDMAX: 255 + VALIDMIN: 0 dtype: uint8 default_uint16_attrs: &default_uint16 <<: *default FILLVAL: 65535 FORMAT: I5 - VALIDMIN: 0 VALIDMAX: 65535 + VALIDMIN: 0 dtype: uint16 default_uint32_attrs: &default_uint32 <<: *default FILLVAL: 4294967295 FORMAT: I10 - VALIDMIN: 0 VALIDMAX: 4294967295 + VALIDMIN: 0 dtype: uint32 default_int64_attrs: &default_int64 <<: *default FILLVAL: -9223372036854775808 FORMAT: I20 - VALIDMIN: -9223372036854775808 VALIDMAX: 9223372036854775807 + VALIDMIN: -9223372036854775808 dtype: int64 default_int32_attrs: &default_int32 <<: *default FILLVAL: -2147483648 FORMAT: I10 - VALIDMIN: -2147483648 VALIDMAX: 2147483647 + VALIDMIN: -2147483648 dtype: int32 default_float32_attrs: &default_float32 <<: *default FILLVAL: -1.0e31 FORMAT: F12.6 - VALIDMIN: -3.4028235e+38 VALIDMAX: 3.4028235e+38 + VALIDMIN: -3.4028235e+38 dtype: float32 default_float64_attrs: &default_float64 <<: *default FILLVAL: -1.0e31 FORMAT: F10.2 - VALIDMIN: -1.7976931348623157e+308 VALIDMAX: 1.7976931348623157e+308 + VALIDMIN: -1.7976931348623157e+308 dtype: float64 +computed_ebin: + <<: *default_uint8 + CATDESC: Computed event bin index + DEPEND_0: epoch + FIELDNAM: Computed ebin + LABLAXIS: computed_ebin + UNITS: " " + +ebin: + <<: *default_uint8 + CATDESC: Event bin index + DEPEND_0: epoch + FIELDNAM: Ebin + LABLAXIS: ebin + UNITS: " " + x_front: <<: *default_float32 CATDESC: x front position @@ -222,8 +238,8 @@ energy_heliosphere: species: <<: *default_uint8 + CATDESC: Label species type. Non-proton (heavy ion) = 0, proton = 1, misc = 3 DISPLAY_TYPE: no_plot - CATDESC: Label species type. FIELDNAM: Label species type. LABLAXIS: species UNITS: " " @@ -337,37 +353,34 @@ de_event_met: DISPLAY_TYPE: no_plot FIELDNAM: Mission Elapsed Time LABLAXIS: DE MET + SCALE_TYP: linear UNITS: ns VAR_TYPE: support_data - SCALE_TYP: linear spin_start_time: <<: *default CATDESC: Spin start time from Universal Spin Table. + DEPEND_0: spin_number FIELDNAM: spin_start_time LABLAXIS: spin start time # TODO: come back to format UNITS: s - DEPEND_0: epoch - DEPEND_1: spin_number spin_period: <<: *default CATDESC: Spin period from Universal Spin Table. + DEPEND_0: spin_number FIELDNAM: spin_period LABLAXIS: spin_period UNITS: s - DEPEND_0: epoch - DEPEND_1: spin_number spin_rate: <<: *default CATDESC: Spin rate from Universal Spin Table. + DEPEND_0: spin_number FIELDNAM: spin_rate LABLAXIS: spin_rate UNITS: rpm - DEPEND_0: epoch - DEPEND_1: spin_number rate_start_pulses: <<: *default @@ -413,101 +426,90 @@ rate_rejected_events: ena_rates: <<: *default_float32 CATDESC: Rates calculated from de packet. + DEPEND_0: energy_bin_geometric_mean + DEPEND_1: spin_number FIELDNAM: ena_rates LABLAXIS: ena rates - DEPEND_0: epoch - DEPEND_1: spin_number - DEPEND_2: energy_bin_geometric_mean UNITS: " " start_pulses_per_spin: <<: *default_float32 CATDESC: Total start pulses per spin. + DEPEND_0: spin_number FIELDNAM: start_pulses_per_spin LABLAXIS: start pulses per spin - DEPEND_0: epoch - DEPEND_1: spin_number UNITS: " " stop_pulses_per_spin: <<: *default_float32 CATDESC: Total start pulses per spin. + DEPEND_0: spin_number FIELDNAM: stop_pulses_per_spin LABLAXIS: stop pulses per spin - DEPEND_0: epoch - DEPEND_1: spin_number UNITS: " " coin_pulses_per_spin: <<: *default_float32 CATDESC: Total coincidence pulses per spin. + DEPEND_0: spin_number FIELDNAM: coin_pulses_per_spin LABLAXIS: coin_pulses_per_spin - DEPEND_0: epoch - DEPEND_1: spin_number UNITS: " " rejected_events_per_spin: <<: *default_uint16 CATDESC: Rejected events per spin. + DEPEND_0: spin_number FIELDNAM: rejected_events_per_spin LABLAXIS: rejected events per spin - DEPEND_0: epoch - DEPEND_1: spin_number UNITS: " " ena_rates_threshold: <<: *default_float32 CATDESC: Rates threshold used for flagging data. + DEPEND_0: energy_bin_geometric_mean + DEPEND_1: spin_number FIELDNAM: ena_rates_threshold LABLAXIS: ena_rates_threshold - DEPEND_0: epoch - DEPEND_1: spin_number - DEPEND_2: energy_bin_geometric_mean UNITS: " " quality_ena_rates: <<: *default_uint16 CATDESC: Spin filter derived from Ultra ena rates. Bitwise flagging used to filter the spin. + DEPEND_0: spin_number FIELDNAM: quality_ena_rates LABLAXIS: quality_ena_rates - DEPEND_0: epoch - DEPEND_1: spin_number - DEPEND_2: energy_bin_geometric_mean UNITS: " " quality_attitude: <<: *default_uint16 CATDESC: Spin filter derived from IMAP attitude. Bitwise flagging used to filter the spin. + DEPEND_0: spin_number + DEPEND_1: energy_bin_geometric_mean FIELDNAM: quality_attitude LABLAXIS: quality attitude # TODO: come back to format UNITS: " " - DEPEND_0: epoch - DEPEND_1: spin_number - DEPEND_2: energy_bin_geometric_mean quality_instruments: <<: *default_uint16 CATDESC: Spin filter derived from instruments other than Ultra. Bitwise flagging used to filter the spin. + DEPEND_0: spin_number + DEPEND_1: energy_bin_geometric_mean FIELDNAM: quality_instruments LABLAXIS: quality instruments # TODO: come back to format UNITS: " " - DEPEND_0: epoch - DEPEND_1: spin_number - DEPEND_2: energy_bin_geometric_mean quality_hk: <<: *default_uint16 CATDESC: Spin filter derived from housekeeping data. Bitwise flagging used to filter the spin. + DEPEND_0: spin_number + DEPEND_1: energy_bin_geometric_mean FIELDNAM: quality_hk LABLAXIS: quality hk # TODO: come back to format UNITS: " " - DEPEND_0: epoch - DEPEND_1: spin_number - DEPEND_2: energy_bin_geometric_mean quality_outliers: <<: *default_uint16 @@ -520,7 +522,61 @@ quality_outliers: quality_scattering: <<: *default_uint16 CATDESC: Quality flag for direct event scattering. + DEPEND_0: spin_number FIELDNAM: quality_scattering LABLAXIS: quality_scattering # TODO: come back to format UNITS: " " + +quality_low_voltage: + <<: *default_uint16 + CATDESC: Quality flag for low voltage spins. + DEPEND_0: spin_number + FIELDNAM: quality_low_voltage + LABLAXIS: quality_low_voltage + # TODO: come back to format + UNITS: " " + +quality_high_energy: + <<: *default_uint16 + CATDESC: Quality flag for high energy spins. + DEPEND_0: spin_number + FIELDNAM: quality_high_energy + LABLAXIS: quality_high_energy + # TODO: come back to format + UNITS: " " + +quality_statistics: + <<: *default_uint16 + CATDESC: Quality flag for spins that are statistically inconsistent. + DEPEND_0: spin_number + FIELDNAM: quality_statistics + LABLAXIS: quality_statistics + # TODO: come back to format + UNITS: " " + +energy_range_edges: + CATDESC: Energy range edges used for culling data. + DEPEND_0: energy_range_edges_dim + DISPLAY_TYPE: no_plot + FIELDNAM: Energy Range Edges + FILLVAL: -1.0e+31 + FORMAT: F12.4 + LABLAXIS: Energy Edges + UNITS: keV + VALIDMAX: 5000 + VALIDMIN: 0.0 + VAR_TYPE: support_data + +energy_range_flags: + CATDESC: Bit flags describing culling energy ranges. + DEPEND_0: energy_range_flags_dim + DISPLAY_TYPE: no_plot + FIELDNAM: Energy Range Flags + FILLVAL: 0 + FORMAT: I5 + LABLAXIS: Range Flags + UNITS: " " + VALIDMAX: 65534 + VALIDMIN: 1 + VAR_TYPE: support_data diff --git a/imap_processing/cdf/config/imap_ultra_l1c_variable_attrs.yaml b/imap_processing/cdf/config/imap_ultra_l1c_variable_attrs.yaml index 9e1124225a..9c9271cddd 100644 --- a/imap_processing/cdf/config/imap_ultra_l1c_variable_attrs.yaml +++ b/imap_processing/cdf/config/imap_ultra_l1c_variable_attrs.yaml @@ -1,22 +1,36 @@ +float_32_fillval: &float_32_fillval -1.0e31 +min_int: &min_int -9223372036854775808 +max_int: &max_int 9223372036854775807 +min_float: &min_float -3.4028235e+38 +max_float: &max_float 3.4028235e+38 + default_attrs: &default # Assumed values for all variable attrs unless overwritten DEPEND_0: epoch DISPLAY_TYPE: time_series - FILLVAL: -9223372036854775808 + FILLVAL: *min_int FORMAT: I12 - VALIDMIN: -9223372036854775808 - VALIDMAX: 9223372036854775807 - VAR_TYPE: data UNITS: " " + VALIDMAX: *max_int + VALIDMIN: *min_int + VAR_TYPE: data default_float32_attrs: &default_float32 <<: *default - FILLVAL: -1.0e31 + FILLVAL: *float_32_fillval FORMAT: F12.6 - VALIDMIN: -3.4028235e+38 - VALIDMAX: 3.4028235e+38 + VALIDMAX: *max_float + VALIDMIN: *min_float dtype: float32 +default_uint16_attrs: &default_uint16 + <<: *default + FILLVAL: 65535 + FORMAT: I5 + VALIDMAX: 65535 + VALIDMIN: 0 + dtype: uint16 + energy_dependent_attrs: &energy_dependent <<: *default_float32 DEPEND_1: energy_bin_geometric_mean @@ -57,32 +71,33 @@ dead_time_ratio: sensitivity: <<: *energy_dependent - CATDESC: Calibration/sensitivity factor. + CATDESC: Averaged instrument sensitive area. FIELDNAM: sensitivity LABLAXIS: sensitivity # TODO: come back to format - UNITS: counts/second + UNITS: cm^2 geometric_function: <<: *energy_dependent - CATDESC: The effective sensitive area as a function of theta and phi in instrument frame (energy independent). + CATDESC: Averaged aperture area as seen by the backstop. FIELDNAM: geometric_function LABLAXIS: Geometric Factor - UNITS: " " + UNITS: cm^2 VALIDMIN: 0.0 efficiency: <<: *energy_dependent - CATDESC: Estimated event efficiency for particles path through the instrument. + CATDESC: Efficiency of the instrument in converting ENAs to valid events. FIELDNAM: efficiency LABLAXIS: Efficiency UNITS: " " - VALIDMIN: 0.0 VALIDMAX: 1.0 + VALIDMIN: 0.0 exposure_factor: <<: *energy_dependent CATDESC: Exposure time with the deadtime correction applied for a pointing. + DEPEND_0: epoch FIELDNAM: exposure_factor LABLAXIS: exposure factor # TODO: come back to format @@ -91,20 +106,56 @@ exposure_factor: helio_exposure_factor: <<: *energy_dependent CATDESC: Exposure time with the deadtime correction applied for a pointing. + DEPEND_0: epoch FIELDNAM: exposure_factor LABLAXIS: exposure factor # TODO: come back to format UNITS: seconds +scatter_theta: + <<: *energy_dependent + CATDESC: Scattering theta values for a pointing (reported as gaussian uncertainty). + FIELDNAM: scatter_theta + LABLAXIS: scatter theta + UNITS: degrees + +scatter_phi: + <<: *energy_dependent + CATDESC: Scattering phi values for a pointing (reported as gaussian uncertainty). + FIELDNAM: scatter_phi + LABLAXIS: scatter phi + UNITS: degrees + +scatter_threshold: + <<: *energy_dependent + CATDESC: Scattering threshold values for each energy bin for a pointing. + FIELDNAM: scatter_threshold + LABLAXIS: scatter threshold + UNITS: degrees + counts: <<: *default CATDESC: Counts for a spin. DEPEND_1: energy_bin_geometric_mean - DEPEND_2: pixel_index + DEPEND_2: counts_pixel_index FIELDNAM: counts LABLAXIS: counts # TODO: come back to format UNITS: counts + VAR_NOTES: Counts healpix maps are sampled at finer resolution to help maintain the pointing accuracy for each event. + Since count maps are a binned integral quantity, they necessarily require a non-spun approach per Pointing, unlike + exposure time and sensitivities. + + +quality_flags: + <<: *default_uint16 + CATDESC: Spin filter derived from Ultra ena rates. Bitwise flagging used to filter the spin. + DEPEND_0: epoch + DEPEND_1: spin_number + DEPEND_2: energy_bin_geometric_mean + FIELDNAM: quality_ena_rates + LABLAXIS: quality_ena_rates + UNITS: " " background_rates: <<: *default_float32 @@ -130,6 +181,18 @@ shcoarse: # TODO: come back to format UNITS: seconds +epoch_delta: + <<: *default + CATDESC: Number of nanoseconds in spacecraft pointing covered by this pointing set product + DISPLAY_TYPE: no_plot + FIELDNAM: epoch delta + FORMAT: I20 + SCALE_TYPE: linear + TIME_SCALE: Terrestrial Time + UNITS: ns + VAR_TYPE: support_data + dtype: int64 + energy_bin_delta: <<: *default_float32 CATDESC: Difference between the energy bin edges. @@ -137,3 +200,73 @@ energy_bin_delta: FIELDNAM: energy_bin_delta LABLAXIS: energy bin delta UNITS: keV + +energy_delta_minus: + <<: *default_float32 + CATDESC: Difference between the energy bin center and lower edge. + DEPEND_1: energy_bin_geometric_mean + DISPLAY_TYPE: no_plot + FIELDNAM: energy_bin_delta_minus + LABLAXIS: energy + UNITS: KeV + VAR_TYPE: support_data + +energy_delta_plus: + <<: *default_float32 + CATDESC: Difference between the energy bin center and upper edge. + DEPEND_1: energy_bin_geometric_mean + DISPLAY_TYPE: no_plot + FIELDNAM: energy_bin_delta_plus + LABLAXIS: energy + UNITS: KeV + VAR_TYPE: support_data + + +# COORDS +energy_bin_geometric_mean: + CATDESC: Geometric mean energy of each energy bin. + DISPLAY_TYPE: no_plot + FIELDNAM: energy_bin_geometric_mean + FILLVAL: *float_32_fillval + FORMAT: F12.6 + LABLAXIS: Energy + UNITS: keV + VALIDMAX: *max_float + VALIDMIN: *min_float + VAR_TYPE: support_data + +pixel_index: + CATDESC: HEALPix pixel index. + DISPLAY_TYPE: no_plot + FIELDNAM: pixel_index + FILLVAL: *min_int + FORMAT: I12 + LABLAXIS: Pixel Index + UNITS: " " + VALIDMAX: *max_int + VALIDMIN: *min_int + VAR_TYPE: support_data + +counts_pixel_index: + CATDESC: Counts variable HEALPix pixel index. + DISPLAY_TYPE: no_plot + FIELDNAM: counts_pixel_index + FILLVAL: *min_int + FORMAT: I12 + LABLAXIS: Counts Pixel Index + UNITS: " " + VALIDMAX: *max_int + VALIDMIN: *min_int + VAR_TYPE: support_data + +spin_phase_step: + CATDESC: Spin phase step index (1ms resolution). + DISPLAY_TYPE: no_plot + FIELDNAM: spin_phase_step + FILLVAL: *min_int + FORMAT: I12 + LABLAXIS: Spin Phase Step + UNITS: " " + VALIDMAX: *max_int + VALIDMIN: *min_int + VAR_TYPE: support_data diff --git a/imap_processing/cdf/utils.py b/imap_processing/cdf/utils.py index 1770e77616..99900e08d3 100644 --- a/imap_processing/cdf/utils.py +++ b/imap_processing/cdf/utils.py @@ -2,6 +2,7 @@ from __future__ import annotations +import datetime import logging import re import warnings @@ -10,6 +11,7 @@ import imap_data_access import numpy as np import xarray as xr +from cdflib.logging import logger as cdflib_logger from cdflib.xarray import cdf_to_xarray, xarray_to_cdf from cdflib.xarray.cdf_to_xarray import ISTP_TO_XARRAY_ATTRS @@ -28,7 +30,7 @@ def load_cdf( Parameters ---------- - file_path : Path or ImapFilePath or str + file_path : pathlib.Path or ImapFilePath or str The path to the CDF file or ImapFilePath object. remove_xarray_attrs : bool Whether to remove the xarray attributes that get injected by the @@ -48,6 +50,9 @@ def load_cdf( # round-trip of writing and then loading a cdf keeps the dataset the same. if "to_datetime" not in kwargs: kwargs["to_datetime"] = False # type: ignore + # By default, load fillvalues as nan + if "fillval_to_nan" not in kwargs: + kwargs["fillval_to_nan"] = True # type: ignore dataset = cdf_to_xarray(file_path, **kwargs) # cdf_to_xarray converts single-value attributes to lists @@ -97,7 +102,7 @@ def write_cdf( Returns ------- - file_path : Path + file_path : pathlib.Path Path to the file created. """ # Create the filename from the global attributes @@ -148,6 +153,10 @@ def write_cdf( dataset.attrs["Logical_file_id"] = file_path.stem # Add the processing version to the dataset attributes dataset.attrs["ground_software_version"] = imap_processing._version.__version__ + dataset.attrs["Generation_date"] = datetime.datetime.now( + datetime.timezone.utc + ).strftime("%Y%m%d") + dataset.attrs["Generated_by"] = "IMAP Science Data Center" # Convert the xarray object to a CDF if "l1" in data_level: @@ -161,7 +170,17 @@ def write_cdf( if "compression" not in extra_cdf_kwargs: extra_cdf_kwargs["compression"] = 6 # type: ignore - xarray_to_cdf(dataset, str(file_path), **extra_cdf_kwargs) + prev_cdflib_level = cdflib_logger.level + try: + if not extra_cdf_kwargs.get("istp", False): + # Suppress cdflib logging messages for data levels that don't need + # strict ISTP compliance + logger.info("Disabling cdflib ISTP logging for level 1 data products") + cdflib_logger.setLevel(logging.ERROR) + xarray_to_cdf(dataset, str(file_path), **extra_cdf_kwargs) + finally: + # Set back to the previous logging level + cdflib_logger.setLevel(prev_cdflib_level) return file_path diff --git a/imap_processing/cli.py b/imap_processing/cli.py index 67d93ce34a..fab4383c4d 100644 --- a/imap_processing/cli.py +++ b/imap_processing/cli.py @@ -13,6 +13,7 @@ from __future__ import annotations import argparse +import json import logging import re import sys @@ -24,8 +25,9 @@ import numpy as np import spiceypy import xarray as xr -from imap_data_access import ScienceFilePath -from imap_data_access.io import download +from cdflib.xarray import xarray_to_cdf +from cdflib.xarray.xarray_to_cdf import ISTPError +from imap_data_access.io import IMAPDataAccessError, download from imap_data_access.processing_input import ( ProcessingInputCollection, ProcessingInputType, @@ -52,9 +54,9 @@ # call cdf.utils.write_cdf from imap_processing.codice import codice_l1a, codice_l1b, codice_l2 from imap_processing.glows.l1a.glows_l1a import glows_l1a -from imap_processing.glows.l1b.glows_l1b import glows_l1b +from imap_processing.glows.l1b.glows_l1b import glows_l1b, glows_l1b_de from imap_processing.glows.l2.glows_l2 import glows_l2 -from imap_processing.hi import hi_l1a, hi_l1b, hi_l1c, hi_l2 +from imap_processing.hi import hi_goodtimes, hi_l1a, hi_l1b, hi_l1c, hi_l2 from imap_processing.hit.l1a.hit_l1a import hit_l1a from imap_processing.hit.l1b.hit_l1b import hit_l1b from imap_processing.hit.l2.hit_l2 import hit_l2 @@ -62,6 +64,7 @@ from imap_processing.idex.idex_l1b import idex_l1b from imap_processing.idex.idex_l2a import idex_l2a from imap_processing.idex.idex_l2b import idex_l2b +from imap_processing.lo.constants import LoConstants from imap_processing.lo.l1a import lo_l1a from imap_processing.lo.l1b import lo_l1b from imap_processing.lo.l1c import lo_l1c @@ -84,6 +87,10 @@ from imap_processing.ultra.l1b import ultra_l1b from imap_processing.ultra.l1c import ultra_l1c from imap_processing.ultra.l2 import ultra_l2 +from imap_processing.utils import ( + check_epochs_within_day_offsets, + filter_day_boundary_data, +) logger = logging.getLogger(__name__) @@ -198,15 +205,7 @@ def _parse_args() -> argparse.Namespace: action="store_const", dest="loglevel", const=logging.DEBUG, - default=logging.WARNING, - ) - parser.add_argument( - "-v", - "--verbose", - help="Add verbose output", - action="store_const", - dest="loglevel", - const=logging.INFO, + default=logging.INFO, ) parser.add_argument("--instrument", type=str, required=True, help=instrument_help) parser.add_argument("--data-level", type=str, required=True, help=level_help) @@ -260,6 +259,14 @@ def _parse_args() -> argparse.Namespace: ) args = parser.parse_args() + # Set the basic logging configuration for all users + # of the CLI tool. + logging.basicConfig( + format="%(asctime)s - %(levelname)s:%(name)s:%(message)s", + level=args.loglevel, + datefmt="%Y-%m-%d %H:%M:%S", + ) + # If the dependency argument was passed in as a json file, read it into a string if args.dependency.endswith(".json"): logger.info( @@ -407,32 +414,23 @@ def upload_products(self, products: list[Path]) -> None: A list of file paths to upload to the SDC. """ if self.upload_to_sdc: - # Validate that the files don't already exist - for filename in products: - file_path = ScienceFilePath(filename) - existing_file = imap_data_access.query( - instrument=file_path.instrument, - data_level=file_path.data_level, - descriptor=file_path.descriptor, - start_date=file_path.start_date, - end_date=file_path.start_date, - repointing=file_path.repointing, - version=file_path.version, - extension="cdf", - table="science", - ) - if existing_file: - raise ProcessInstrument.ImapFileExistsError( - f"File {filename} already exists in the IMAP SDC. " - "No files were uploaded." - f"Generated files: {products}." - ) - - if len(products) == 0: + if not products: logger.info("No files to upload.") + return + for filename in products: - logger.info(f"Uploading file: {filename}") - imap_data_access.upload(filename) + try: + logger.info(f"Uploading file: {filename}") + imap_data_access.upload(filename) + except IMAPDataAccessError as e: + msg = str(e) + if "FileAlreadyExists" in msg and "409" in msg: + logger.warning("Skipping upload of existing file, %s", filename) + continue + else: + logger.error(f"Upload failed with error: {msg}") + except Exception as e: + logger.error(f"Upload failed unknown error: {e}") @final def process(self) -> None: @@ -622,14 +620,10 @@ def do_processing( datasets: list[xr.Dataset] = [] if self.data_level == "l1a": - science_files = dependencies.get_file_paths(source="codice") - if len(science_files) != 1: - raise ValueError( - f"CoDICE L1A requires exactly one input science file, received: " - f"{science_files}." - ) # process data - datasets = codice_l1a.process_codice_l1a(science_files[0]) + datasets = codice_l1a.process_l1a(dependencies) + for i, ds in enumerate(datasets): + datasets[i] = filter_day_boundary_data(ds, self.start_date) if self.data_level == "l1b": science_files = dependencies.get_file_paths(source="codice") @@ -642,13 +636,7 @@ def do_processing( datasets = [codice_l1b.process_codice_l1b(science_files[0])] if self.data_level == "l2": - science_files = dependencies.get_file_paths(source="codice") - if len(science_files) != 1: - raise ValueError( - f"CoDICE L2 requires exactly one input science file, received: " - f"{science_files}." - ) - datasets = [codice_l2.process_codice_l2(science_files[0])] + datasets = [codice_l2.process_codice_l2(self.descriptor, dependencies)] return datasets @@ -676,7 +664,7 @@ def do_processing( datasets: list[xr.Dataset] = [] if self.data_level == "l1a": - science_files = dependencies.get_file_paths(source="glows") + science_files = dependencies.get_file_paths(source="glows", data_type="l0") if len(science_files) != 1: raise ValueError( f"GLOWS L1A requires exactly one input science file, received: " @@ -685,33 +673,21 @@ def do_processing( datasets = glows_l1a(science_files[0]) if self.data_level == "l1b": - science_files = dependencies.get_file_paths(source="glows") + science_files = dependencies.get_file_paths(source="glows", data_type="l1a") if len(science_files) != 1: raise ValueError( f"GLOWS L1B requires exactly one input science file, received: " f"{science_files}." ) input_dataset = load_cdf(science_files[0]) - # TODO: Replace this by reading from AWS/ProcessingInputs - glows_ancillary_dir = Path(__file__).parent / "glows" / "ancillary" + # Load conversion table (needed for both hist and DE) + conversion_table_file = dependencies.get_processing_inputs( + descriptor="l1b-conversion-table-for-anc-data" + )[0] - # Create file lists for each ancillary type - excluded_regions_files = [ - glows_ancillary_dir - / "imap_glows_map-of-excluded-regions_20250923_v002.dat" - ] - uv_sources_files = [ - glows_ancillary_dir / "imap_glows_map-of-uv-sources_20250923_v002.dat" - ] - suspected_transients_files = [ - glows_ancillary_dir - / "imap_glows_suspected-transients_20250923_v002.dat" - ] - exclusions_by_instr_team_files = [ - glows_ancillary_dir - / "imap_glows_exclusions-by-instr-team_20250923_v002.dat" - ] + with open(conversion_table_file.imap_file_paths[0].construct_path()) as f: + conversion_table_dict = json.load(f) # Use end date buffer for ancillary data current_day = np.datetime64( @@ -719,37 +695,86 @@ def do_processing( ) day_buffer = current_day + np.timedelta64(3, "D") - # Create combiners for each ancillary dataset - excluded_regions_combiner = GlowsAncillaryCombiner( - excluded_regions_files, day_buffer - ) - uv_sources_combiner = GlowsAncillaryCombiner(uv_sources_files, day_buffer) - suspected_transients_combiner = GlowsAncillaryCombiner( - suspected_transients_files, day_buffer - ) - exclusions_by_instr_team_combiner = GlowsAncillaryCombiner( - exclusions_by_instr_team_files, day_buffer - ) + if "hist" in self.descriptor: + # Create file lists for each ancillary type + excluded_regions_files = dependencies.get_processing_inputs( + descriptor="l1b-map-of-excluded-regions" + )[0] + uv_sources_files = dependencies.get_processing_inputs( + descriptor="l1b-map-of-uv-sources" + )[0] + suspected_transients_files = dependencies.get_processing_inputs( + descriptor="l1b-suspected-transients" + )[0] + exclusions_by_instr_team_files = dependencies.get_processing_inputs( + descriptor="l1b-exclusions-by-instr-team" + )[0] + pipeline_settings = dependencies.get_processing_inputs( + descriptor="pipeline-settings" + )[0] - datasets = [ - glows_l1b( - input_dataset, - excluded_regions_combiner.combined_dataset, - uv_sources_combiner.combined_dataset, - suspected_transients_combiner.combined_dataset, - exclusions_by_instr_team_combiner.combined_dataset, + # Create combiners for each ancillary dataset + excluded_regions_combiner = GlowsAncillaryCombiner( + excluded_regions_files, day_buffer ) - ] + uv_sources_combiner = GlowsAncillaryCombiner( + uv_sources_files, day_buffer + ) + suspected_transients_combiner = GlowsAncillaryCombiner( + suspected_transients_files, day_buffer + ) + exclusions_by_instr_team_combiner = GlowsAncillaryCombiner( + exclusions_by_instr_team_files, day_buffer + ) + pipeline_settings_combiner = GlowsAncillaryCombiner( + pipeline_settings, day_buffer + ) + + datasets = [ + glows_l1b( + input_dataset, + excluded_regions_combiner.combined_dataset, + uv_sources_combiner.combined_dataset, + suspected_transients_combiner.combined_dataset, + exclusions_by_instr_team_combiner.combined_dataset, + pipeline_settings_combiner.combined_dataset, + conversion_table_dict, + ) + ] + else: + # Direct events + datasets = [glows_l1b_de(input_dataset, conversion_table_dict)] if self.data_level == "l2": - science_files = dependencies.get_file_paths(source="glows") + science_files = dependencies.get_file_paths(source="glows", data_type="l1b") if len(science_files) != 1: raise ValueError( - f"GLOWS L1A requires exactly one input science file, received: " - f"{science_files}." + f"GLOWS L2 requires exactly one input science file, " + f"received: {science_files}." ) input_dataset = load_cdf(science_files[0]) - datasets = glows_l2(input_dataset) + + # Load pipeline settings for L2 processing + current_day = np.datetime64( + f"{self.start_date[:4]}-{self.start_date[4:6]}-{self.start_date[6:]}" + ) + day_buffer = current_day + np.timedelta64(3, "D") + pipeline_settings_input = dependencies.get_processing_inputs( + descriptor="pipeline-settings" + )[0] + pipeline_settings_combiner = GlowsAncillaryCombiner( + pipeline_settings_input, day_buffer + ) + calibration_input = dependencies.get_processing_inputs( + descriptor="l2-calibration" + )[0] + calibration_combiner = GlowsAncillaryCombiner(calibration_input, day_buffer) + + datasets = glows_l2( + input_dataset, + pipeline_settings_combiner.combined_dataset, + calibration_combiner.combined_dataset, + ) return datasets @@ -757,7 +782,7 @@ def do_processing( class Hi(ProcessInstrument): """Process IMAP-Hi.""" - def do_processing( + def do_processing( # noqa: PLR0912 self, dependencies: ProcessingInputCollection ) -> list[xr.Dataset]: """ @@ -788,6 +813,57 @@ def do_processing( l0_files = dependencies.get_file_paths(source="hi", descriptor="raw") if l0_files: datasets = hi_l1b.housekeeping(l0_files[0]) + elif "goodtimes" in self.descriptor: + # Check self.repointing is not None (for mypy type checking) + if self.repointing is None: + raise ValueError( + "Repointing must be provided for Hi Goodtimes processing." + ) + + # Goodtimes processing + l1b_de_paths = dependencies.get_file_paths( + source="hi", data_type="l1b", descriptor="de" + ) + if not l1b_de_paths: + raise ValueError("No L1B DE files found for goodtimes processing") + + l1b_hk_paths = dependencies.get_file_paths( + source="hi", data_type="l1b", descriptor="hk" + ) + if len(l1b_hk_paths) != 1: + raise ValueError( + f"Expected one L1B HK file, got {len(l1b_hk_paths)}" + ) + + cal_prod_paths = dependencies.get_file_paths( + data_type="ancillary", descriptor="cal-prod" + ) + if len(cal_prod_paths) != 1: + raise ValueError( + f"Expected one cal-prod ancillary file, " + f"got {len(cal_prod_paths)}" + ) + + l1a_diagfee_paths = dependencies.get_file_paths( + source="hi", data_type="l1a", descriptor="diagfee" + ) + if len(l1a_diagfee_paths) != 1: + raise ValueError( + f"Expected one L1A DIAG_FEE file, got {len(l1a_diagfee_paths)}" + ) + + # Load CDFs before passing to hi_goodtimes + l1b_de_datasets = [load_cdf(path) for path in l1b_de_paths] + l1b_hk = load_cdf(l1b_hk_paths[0]) + l1a_diagfee = load_cdf(l1a_diagfee_paths[0]) + + datasets = hi_goodtimes.hi_goodtimes( + self.repointing, + l1b_de_datasets, + l1b_hk, + l1a_diagfee, + cal_prod_paths[0], + ) else: l1a_de_file = dependencies.get_file_paths( source="hi", data_type="l1a", descriptor="de" @@ -800,26 +876,84 @@ def do_processing( load_cdf(l1a_de_file), load_cdf(l1b_hk_file), esa_energies_csv ) elif self.data_level == "l1c": - science_paths = dependencies.get_file_paths(source="hi", data_type="l1b") - if len(science_paths) != 1: - raise ValueError( - f"Expected only one science dependency. Got {science_paths}" + if "pset" in self.descriptor: + # L1C PSET processing + l1b_de_paths = dependencies.get_file_paths( + source="hi", data_type="l1b", descriptor="de" ) - anc_paths = dependencies.get_file_paths(data_type="ancillary") - if len(anc_paths) != 1: - raise ValueError( - f"Expected only one ancillary dependency. Got {anc_paths}" + if len(l1b_de_paths) != 1: + raise ValueError( + f"Expected exactly one DE science dependency. " + f"Got {l1b_de_paths}" + ) + + # Get ancillary dependencies + anc_dependencies = dependencies.get_processing_inputs( + data_type="ancillary" + ) + if len(anc_dependencies) != 2: + raise ValueError( + f"Expected two ancillary dependencies (cal-prod and " + f"backgrounds). Got " + f"{[anc_dep.descriptor for anc_dep in anc_dependencies]}" + ) + + # Create mapping from descriptor to path + anc_path_dict = { + dep.descriptor.split("-", 1)[1]: dep.imap_file_paths[ + 0 + ].construct_path() + for dep in anc_dependencies + } + + # Verify we have both required ancillary files + if ( + "cal-prod" not in anc_path_dict + or "backgrounds" not in anc_path_dict + ): + raise ValueError( + f"Missing required ancillary files. Expected 'cal-prod' and " + f"'backgrounds', got {list(anc_path_dict.keys())}" + ) + + # Load goodtimes dependency + goodtimes_paths = dependencies.get_file_paths( + source="hi", data_type="l1b", descriptor="goodtimes" + ) + if len(goodtimes_paths) != 1: + raise ValueError( + f"Expected exactly one goodtimes dependency. " + f"Got {goodtimes_paths}" + ) + + datasets = hi_l1c.hi_l1c( + load_cdf(l1b_de_paths[0]), + anc_path_dict["cal-prod"], + load_cdf(goodtimes_paths[0]), + anc_path_dict["backgrounds"], ) - datasets = hi_l1c.hi_l1c(load_cdf(science_paths[0]), anc_paths[0]) elif self.data_level == "l2": science_paths = dependencies.get_file_paths(source="hi", data_type="l1c") - # TODO get ancillary paths - geometric_factors_path = "" - esa_energies_path = "" + anc_dependencies = dependencies.get_processing_inputs(data_type="ancillary") + if len(anc_dependencies) != 3: + raise ValueError( + f"Expected three ancillary dependencies for L2 processing including" + f"cal-prod, esa-energies, and esa-eta-fit-factors." + f"Got {[anc_dep.descriptor for anc_dep in anc_dependencies]}" + "." + ) + # Get individual L2 ancillary dependencies + # Strip the "45sensor" or "90sensor" off the ancillary descriptor and + # create a mapping from descriptor to path + l2_ancillary_path_dict = { + "-".join(dep.descriptor.split("-")[1:]): dep.imap_file_paths[ + 0 + ].construct_path() + for dep in anc_dependencies + } datasets = hi_l2.hi_l2( science_paths, - geometric_factors_path, - esa_energies_path, + l2_ancillary_path_dict, self.descriptor, ) else: @@ -861,7 +995,10 @@ def do_processing( f"L0 and time kernels." ) # process data to L1A products - science_files = dependencies.get_file_paths(source="hit", descriptor="raw") + # TODO: revert to 'raw' in issue #3215 work + science_files = dependencies.get_file_paths( + source="hit", descriptor="pha-telemetry-corrected" + ) datasets = hit_l1a(science_files[0], self.start_date) elif self.data_level == "l1b": @@ -945,16 +1082,30 @@ def do_processing( science_files = dependencies.get_file_paths(source="idex") datasets = PacketParser(science_files[0]).data elif self.data_level == "l1b": - if len(dependency_list) != 3: + n_expected_deps = 3 if self.descriptor == "sci-1week" else 1 + if len(dependency_list) != n_expected_deps: raise ValueError( - f"Unexpected dependencies found for IDEX L1B:" - f"{dependency_list}. Expected only three dependencies." + f"Unexpected dependencies found for IDEX L1B {self.descriptor}:" + f"{dependency_list}. Expected only {n_expected_deps} dependencies." ) - # get CDF file science_files = dependencies.get_file_paths(source="idex") + if not science_files: + raise ValueError("No science files found for IDEX L1B processing.") + # IDEX l1b requires spice kernels and since there may be events that occur + # before the start date of the job, there is a buffer added to the upstream + # dependency query. This means that there may be multiple l1a science files + # that are returned but we only want to process the file with the same + # start date. + l1a_file = [f for f in science_files if self.start_date in f.name] + if not l1a_file: + raise ValueError( + f"No L1A science file found for IDEX L1B processing with start " + f"date {self.start_date}. Out of science files: {science_files}" + ) + l1a_file = l1a_file[0] + logger.info(f"Processing IDEX l1b using l1a file: {l1a_file.name}") # process data - dependency = load_cdf(science_files[0]) - datasets = [idex_l1b(dependency)] + datasets = [idex_l1b(load_cdf(l1a_file), self.descriptor)] elif self.data_level == "l2a": if len(dependency_list) != 3: raise ValueError( @@ -978,9 +1129,13 @@ def do_processing( source="idex", descriptor="sci-1week" ) sci_dependencies = [load_cdf(f) for f in sci_files] - hk_files = dependencies.get_file_paths(source="idex", descriptor="evt") + # sort science files by the first epoch value + sci_dependencies.sort(key=lambda ds: ds["epoch"].values[0]) + hk_files = dependencies.get_file_paths(source="idex", descriptor="msg") # Remove duplicate housekeeping files hk_dependencies = [load_cdf(dep) for dep in list(set(hk_files))] + # sort housekeeping files by the first epoch value + hk_dependencies.sort(key=lambda ds: ds["epoch"].values[0]) datasets = idex_l2b(sci_dependencies, hk_dependencies) return datasets @@ -988,6 +1143,53 @@ def do_processing( class Lo(ProcessInstrument): """Process IMAP-Lo.""" + def pre_processing(self) -> ProcessingInputCollection: + """ + Complete pre-processing. + + Extends the base pre-processing by filtering Lo PSET science inputs to + only those whose ``pivot_angle`` is within + ``LoConstants.PSET_PIVOT_ANGLE_TOLERANCE`` of + ``LoConstants.PSET_PIVOT_ANGLE``. PSET files that fall outside this + range are dropped before processing begins. + + Returns + ------- + dependencies : ProcessingInputCollection + Object containing dependencies to process. + """ + datasets = super().pre_processing() + new_datasets = ProcessingInputCollection() + + for processing_input in datasets.get_processing_inputs(): + if ( + processing_input.source == "lo" + and processing_input.descriptor == "pset" + ): + valid_filenames = [] + for imap_file_path in processing_input.imap_file_paths: + pset = load_cdf(imap_file_path.construct_path()) + if "pivot_angle" in pset: + if ( + abs( + pset["pivot_angle"].item() + - LoConstants.PSET_PIVOT_ANGLE + ) + < LoConstants.PSET_PIVOT_ANGLE_TOLERANCE + ): + valid_filenames.append(str(imap_file_path.filename)) + else: + logger.info( + f"Dropping pset {imap_file_path.filename} because " + f"pivot angle is not in range." + ) + if valid_filenames: + new_datasets.add(type(processing_input)(*valid_filenames)) + else: + new_datasets.add(processing_input) + + return new_datasets + def do_processing( self, dependencies: ProcessingInputCollection ) -> list[xr.Dataset]: @@ -1020,18 +1222,29 @@ def do_processing( elif self.data_level == "l1b": data_dict = {} science_files = dependencies.get_file_paths(source="lo", data_type="l1a") + science_files += dependencies.get_file_paths(source="lo", data_type="l1b") + + ancillary_files = dependencies.get_file_paths( + source="lo", data_type="ancillary" + ) logger.info(f"Science files for L1B: {science_files}") for file in science_files: dataset = load_cdf(file) data_dict[dataset.attrs["Logical_source"]] = dataset - datasets = lo_l1b.lo_l1b(data_dict) + datasets = lo_l1b.lo_l1b(data_dict, ancillary_files, self.descriptor) elif self.data_level == "l1c": data_dict = {} anc_dependencies: list = dependencies.get_file_paths( - source="lo", descriptor="goodtimes" + source="lo", data_type="ancillary" ) science_files = dependencies.get_file_paths(source="lo", descriptor="de") + science_files += dependencies.get_file_paths( + source="lo", data_type="l1b", descriptor="goodtimes" + ) + science_files += dependencies.get_file_paths( + source="lo", data_type="l1b", descriptor="bgrates" + ) for file in science_files: dataset = load_cdf(file) data_dict[dataset.attrs["Logical_source"]] = dataset @@ -1039,13 +1252,15 @@ def do_processing( elif self.data_level == "l2": data_dict = {} - # TODO: Add ancillary descriptors when maps using them are - # implemented. - anc_dependencies = [] science_files = dependencies.get_file_paths(source="lo", descriptor="pset") - psets = [] - for file in science_files: - psets.append(load_cdf(file)) + anc_dependencies = dependencies.get_file_paths(data_type="ancillary") + + # Load all pset files into datasets + if not science_files: + logger.info("No valid psets found for L2 processing.") + return datasets + + psets = [load_cdf(file) for file in science_files] data_dict[psets[0].attrs["Logical_source"]] = psets datasets = lo_l2.lo_l2(data_dict, anc_dependencies, self.descriptor) return datasets @@ -1127,9 +1342,9 @@ def do_processing( # noqa: PLR0912 input_data = [load_cdf(dep) for dep in science_files] # Input datasets can be in any order, and are validated within mag_l1c if len(input_data) == 1: - datasets = [mag_l1c(input_data[0])] + datasets = [mag_l1c(input_data[0], current_day)] elif len(input_data) == 2: - datasets = [mag_l1c(input_data[0], input_data[1])] + datasets = [mag_l1c(input_data[0], current_day, input_data[1])] else: raise ValueError( f"Invalid dependencies found for MAG L1C:" @@ -1202,11 +1417,87 @@ def do_processing( # noqa: PLR0912 if "raw" not in ds.attrs["Logical_source"] and not np.all( ds["epoch"].values[1:] > ds["epoch"].values[:-1] ): - raise ValueError( - "Timestamps for output file are not monotonically increasing." + logger.warning( + f"Timestamps for output file {ds.attrs['Logical_source']} are not " + f"monotonically increasing." ) + + # Will raise an error if any timestamps are outside the current day + check_epochs_within_day_offsets(datasets, current_day) + return datasets + def post_processing( + self, + processed_data: list[xr.Dataset | Path], + dependencies: ProcessingInputCollection, + ) -> list[Path]: + """ + Override the post-processing method to handle ancillary file upload. + + This will retrieve any datasets with Logical_source matching + ancillary_identifiers, and write them out to filenames, which will then be + passed to super().post_processing(). This means write_cdf will be skipped for + ancillary files ONLY. + + Parameters + ---------- + processed_data : list[xarray.Dataset | Path] + A list of datasets (products) and paths produced by the do_processing + method. + dependencies : ProcessingInputCollection + Object containing dependencies to process. + + Returns + ------- + list[Path] + List of paths to CDF files produced. + """ + ancillary_identifiers = [ + "imap_mag_l1d_gradiometry-offsets-burst", + "imap_mag_l1d_gradiometry-offsets-norm", + "imap_mag_l1d_spin-offsets", + ] + + for index, dataset in enumerate(processed_data): + if isinstance(dataset, xr.Dataset): + logical_source = dataset.attrs["Logical_source"] + if logical_source in ancillary_identifiers: + # Skip write_cdf + instrument, _data_level, descriptor = dataset.attrs[ + "Logical_source" + ].split("_")[1:] + start_date = self.start_date + version = self.version + + output_filepath = ( + imap_data_access.AncillaryFilePath.generate_from_inputs( + instrument=instrument, + descriptor=descriptor, + version=version, + extension="cdf", + start_time=start_date, + end_time=start_date, + ).filename + ) + + try: + # write file to CDF + xarray_to_cdf( + dataset, + output_filepath, + terminate_on_warning=False, + istp=False, + ) + # update the dataset in processed_data to point to a path + processed_data[index] = output_filepath + except (ValueError, TypeError, ISTPError) as e: + # Don't fail for any reason for ancillary files + logger.warning(f"Hit error {e} when creating {output_filepath}") + continue + + return super().post_processing(processed_data, dependencies) + class Spacecraft(ProcessInstrument): """Process Spacecraft data.""" @@ -1228,8 +1519,8 @@ def do_processing( The list of processed products. """ print(f"Processing Spacecraft {self.data_level}") - - if self.data_level == "l1a": + processed_dataset = [] + if self.descriptor == "quaternions": # File path is expected output file path input_files = dependencies.get_file_paths(source="spacecraft") if len(input_files) > 1: @@ -1238,26 +1529,21 @@ def do_processing( f"{input_files}. Expected only one dependency." ) datasets = list(quaternions.process_quaternions(input_files[0])) - return datasets - elif self.data_level == "spice": + processed_dataset.extend(datasets) + elif self.descriptor == "pointing-attitude": spice_inputs = dependencies.get_file_paths( data_type=SPICESource.SPICE.value ) ah_paths = [path for path in spice_inputs if ".ah" in path.suffixes] - if len(ah_paths) != 1: - raise ValueError( - f"Unexpected spice dependencies found for Spacecraft " - f"pointing_kernel: {ah_paths}. Expected exactly one " - f"attitude history file." - ) pointing_kernel_paths = pointing_frame.generate_pointing_attitude_kernel( - ah_paths[0] + ah_paths ) - return pointing_kernel_paths + processed_dataset.extend(pointing_kernel_paths) else: raise NotImplementedError( f"Spacecraft processing not implemented for level {self.data_level}" ) + return processed_dataset class Swapi(ProcessInstrument): @@ -1300,7 +1586,9 @@ def do_processing( ) # process science or housekeeping data - datasets = swapi_l1(dependencies) + datasets = swapi_l1(dependencies, descriptor=self.descriptor) + for i, ds in enumerate(datasets): + datasets[i] = filter_day_boundary_data(ds, self.start_date) elif self.data_level == "l2": if len(dependency_list) != 3: raise ValueError( @@ -1357,6 +1645,8 @@ def do_processing( ) science_files = dependencies.get_file_paths(source="swe") datasets = swe_l1a(str(science_files[0])) + for i, ds in enumerate(datasets): + datasets[i] = filter_day_boundary_data(ds, self.start_date) # Right now, we only process science data. Therefore, # we expect only one dataset to be returned. @@ -1435,7 +1725,7 @@ def do_processing( f"Unexpected science_files found for ULTRA L1A:" f"{science_files}. Expected only one dependency." ) - datasets = ultra_l1a.ultra_l1a(science_files[0]) + datasets = ultra_l1a.ultra_l1a(science_files[0], create_derived_l1b=True) elif self.data_level == "l1b": science_files = dependencies.get_file_paths(source="ultra", data_type="l1a") l1a_dict = { @@ -1461,7 +1751,10 @@ def do_processing( } science_files = dependencies.get_file_paths(source="ultra", data_type="l1b") l1b_dict = { - dataset.attrs["Logical_source"]: dataset + # TODO remove + dataset.attrs["Logical_source"].replace( + "cullingmask", "goodtimes" + ): dataset for dataset in [load_cdf(sci_file) for sci_file in science_files] } combined = {**l1a_dict, **l1b_dict} @@ -1469,16 +1762,17 @@ def do_processing( ancillary_files = {} for path in anc_paths: ancillary_files[path.stem.split("_")[2]] = path - spice_paths = dependencies.get_file_paths(data_type="spice") - if spice_paths: - has_spice = True - else: - has_spice = False - datasets = ultra_l1c.ultra_l1c(combined, ancillary_files, has_spice) + datasets = ultra_l1c.ultra_l1c(combined, ancillary_files, self.descriptor) elif self.data_level == "l2": all_pset_filepaths = dependencies.get_file_paths( source="ultra", descriptor="pset" ) + energy_ancilary_files = dependencies.get_file_paths( + data_type="ancillary", descriptor="l2-energy-bin-group-sizes" + ) + energy_bin_edges_file = ( + None if energy_ancilary_files == [] else energy_ancilary_files[0] + ) # There can be many PSET files, so avoid reading them all in. # The filename stem (logical_file_id) contains # all the information needed in the key. @@ -1489,6 +1783,7 @@ def do_processing( datasets = ultra_l2.ultra_l2( data_dict, descriptor=self.descriptor, + energy_bin_edges_file=energy_bin_edges_file, ) return datasets diff --git a/imap_processing/codice/codice_l0.py b/imap_processing/codice/codice_l0.py deleted file mode 100644 index 757874ddf1..0000000000 --- a/imap_processing/codice/codice_l0.py +++ /dev/null @@ -1,54 +0,0 @@ -""" -Perform CoDICE L0 processing. - -This module contains a function to decommutate CoDICE CCSDS packets using -XTCE packet definitions. - -For more information on this process and the latest versions of the packet -definitions, see https://lasp.colorado.edu/galaxy/display/IMAP/CoDICE. - -Notes ------ - from imap_processing.codice.codice_l0 import decom_packets - packet_file = '/path/to/raw_ccsds_20230822_122700Z_idle.bin' - packet_list = decom_packets(packet_file) -""" - -from pathlib import Path - -import xarray as xr - -from imap_processing import imap_module_directory -from imap_processing.utils import packet_file_to_datasets - - -def decom_packets(packet_file: Path) -> dict[int, xr.Dataset]: - """ - Decom CoDICE data packets using CoDICE packet definition. - - Parameters - ---------- - packet_file : pathlib.Path - Path to data packet path with filename. - - Returns - ------- - datasets : dict[int, xarray.Dataset] - Mapping from apid to ``xarray`` dataset, one dataset per apid. - """ - # TODO: Currently need to use the 'old' packet definition for housekeeping - # because the simulated housekeeping data being used has various - # mis-matches from the telemetry definition. This may be updated - # once new simulated housekeeping data are acquired. - if "hskp" in str(packet_file): - xtce_filename = "P_COD_NHK.xml" - else: - xtce_filename = "codice_packet_definition.xml" - xtce_packet_definition = Path( - f"{imap_module_directory}/codice/packet_definitions/{xtce_filename}" - ) - datasets: dict[int, xr.Dataset] = packet_file_to_datasets( - packet_file, xtce_packet_definition - ) - - return datasets diff --git a/imap_processing/codice/codice_l1a.py b/imap_processing/codice/codice_l1a.py index f95460a548..794c09730d 100644 --- a/imap_processing/codice/codice_l1a.py +++ b/imap_processing/codice/codice_l1a.py @@ -1,1663 +1,162 @@ -""" -Perform CoDICE l1a processing. - -This module processes CoDICE L0 files and creates L1a data products. - -Notes ------ - from imap_processing.codice.codice_l1a import process_codice_l1a - processed_datasets = process_codice_l1a(path_to_l0_file) -""" - -from __future__ import annotations +"""CoDICE L1A processing functions.""" +import datetime import logging -from pathlib import Path -from typing import Any +import os -import numpy as np -import pandas as pd import xarray as xr -from numpy.typing import NDArray +from imap_data_access import ProcessingInputCollection from imap_processing import imap_module_directory from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes -from imap_processing.codice import constants -from imap_processing.codice.codice_l0 import decom_packets -from imap_processing.codice.decompress import decompress -from imap_processing.codice.utils import CODICEAPID, CoDICECompression -from imap_processing.spice.time import met_to_ttj2000ns +from imap_processing.codice.codice_l1a_de import l1a_direct_event +from imap_processing.codice.codice_l1a_hi_counters_aggregated import ( + l1a_hi_counters_aggregated, +) +from imap_processing.codice.codice_l1a_hi_counters_singles import ( + l1a_hi_counters_singles, +) +from imap_processing.codice.codice_l1a_hi_omni import l1a_hi_omni +from imap_processing.codice.codice_l1a_hi_priority import l1a_hi_priority +from imap_processing.codice.codice_l1a_hi_sectored import l1a_hi_sectored +from imap_processing.codice.codice_l1a_lo_counters_aggregated import ( + l1a_lo_counters_aggregated, +) +from imap_processing.codice.codice_l1a_lo_counters_singles import ( + l1a_lo_counters_singles, +) +from imap_processing.codice.codice_l1a_lo_priority import l1a_lo_priority +from imap_processing.codice.codice_l1a_lo_species import l1a_lo_species +from imap_processing.codice.utils import ( + CODICEAPID, + process_by_table_id, +) +from imap_processing.utils import packet_file_to_datasets logger = logging.getLogger(__name__) -logger.setLevel(logging.INFO) -class CoDICEL1aPipeline: +def process_l1a( # noqa: PLR0912 + dependency: ProcessingInputCollection, +) -> list[xr.Dataset]: """ - Contains methods for processing L0 data and creating L1a data products. + Process L1A data based on descriptor and dependencies. Parameters ---------- - table_id : int - A unique ID assigned to a specific table configuration. This field is - used to link the overall acquisition and processing settings to a - specific table configuration. - plan_id : int - The plan table that was in use. In conjunction with ``plan_step``, - describes which counters are included in the data packet. - plan_step : int - Plan step that was active when the data was acquired and processed. In - conjunction with ``plan_id``, describes which counters are included - in the data packet. - view_id : int - Provides information about how data was collapsed and/or compressed. + dependency : ProcessingInputCollection + Collection of processing inputs required for L1A processing. - Methods + Returns ------- - apply_despinning() - Apply the despinning algorithm to lo- angular and priority products. - decompress_data(science_values) - Perform decompression on the data. - define_coordinates() - Create ``xr.DataArrays`` for the coords needed in the final dataset. - define_data_variables() - Define and add the appropriate data variables to the dataset. - define_dimensions() - Define the dimensions of the data arrays for the final dataset. - define_energy_bins() - Define/add variables to the dataset that correspond to the energy bins. - define_support_variables() - Define and add 'support' CDF data variables to the dataset. - get_acquisition_times() - Retrieve the acquisition times via the Lo stepping table. - get_energy_table() - Retrieve the ESA sweep values. - get_hi_energy_table_data(species) - Retrieve energy table data for CoDICE-Hi products - reshape_binned_data(dataset) - Reshape data arrays for binned datasets. - reshape_data() - Reshape the data arrays based on the data product being made. - set_data_product_config() - Set the various settings for defining the data products. - """ - - def __init__(self, table_id: int, plan_id: int, plan_step: int, view_id: int): - """Initialize a ``CoDICEL1aPipeline`` class instance.""" - self.table_id = table_id - self.plan_id = plan_id - self.plan_step = plan_step - self.view_id = view_id - - def apply_despinning(self) -> None: - """ - Apply the despinning algorithm to lo- angular and priority products. - - This only applies to CoDICE-Lo angular and priority data products. See - sections 9.3.4 and 9.3.5 of the algorithm document for more details. - """ - # Determine the appropriate dimensions for the despun data - num_energies = self.config["dims"]["esa_step"] - num_spin_sectors = self.config["dims"]["spin_sector"] - num_spins = num_spin_sectors * 2 - num_counters = self.config["num_counters"] - num_positions = self.config["dims"].get( - "inst_az" - ) # Defaults to None if not present + list[xarray.Dataset] + List of processed L1A datasets generated from available APIDs. + """ + # Get science data which is L0 packet file + science_file = dependency.get_file_paths(data_type="l0")[0] + # TODO get the exact time the FSW changed on january 29 and relabel the xml file + # On January 29, 2026, the CoDICE flight software was updated to a new version. + # This update included changes to the packet definitions. + start_date = datetime.datetime.strptime( + os.path.basename(science_file).split("_")[4], "%Y%m%d" + ) # Extract the date from the filename + path = imap_module_directory / "codice/packet_definitions/" + if start_date >= datetime.datetime(2026, 1, 29): + xtce_file = path / "imap_codice_packet-definition_20260129_v001.xml" + else: + xtce_file = path / "imap_codice_packet-definition_20250101_v001.xml" - # The dimensions are dependent on the specific data product - if "angular" in self.config["dataset_name"]: - despun_dims: tuple[int, ...] = ( - num_energies, - num_positions, - num_spins, - num_counters, + datasets_by_apid = packet_file_to_datasets( + science_file, + xtce_file, + ) + datasets = [] + for apid in datasets_by_apid: + if apid not in [CODICEAPID.COD_LO_PHA, CODICEAPID.COD_HI_PHA]: + # Get LUT file. Direct events do not need LUT + lut_file = dependency.get_file_paths(descriptor="l1a-sci-lut") + lut_file = lut_file[0] + + if apid == CODICEAPID.COD_LO_SW_SPECIES_COUNTS: + logger.info("Processing Lo SW Species Counts") + datasets.append( + process_by_table_id(datasets_by_apid[apid], lut_file, l1a_lo_species) ) - elif "priority" in self.config["dataset_name"]: - despun_dims = (num_energies, num_spins, num_counters) - - # Placeholder for finalized despun data - self.data: list[np.ndarray] # Needed to appease mypy - despun_data = [np.zeros(despun_dims) for _ in range(len(self.data))] - - # Iterate over the energy and spin sector indices, and determine the - # appropriate pixel orientation. The combination of the pixel - # orientation and the azimuth determine which spin sector the data - # gets stored in. - # TODO: All these nested for-loops are bad. Try to find a better - # solution. - for i, epoch_data in enumerate(self.data): - for energy_index in range(num_energies): - pixel_orientation = constants.PIXEL_ORIENTATIONS[energy_index] - for spin_sector_index in range(num_spin_sectors): - for azimuth_index in range(num_spins): - if pixel_orientation == "A" and azimuth_index < 12: - despun_spin_sector = spin_sector_index - elif pixel_orientation == "A" and azimuth_index >= 12: - despun_spin_sector = spin_sector_index + 12 - elif pixel_orientation == "B" and azimuth_index < 12: - despun_spin_sector = spin_sector_index + 12 - elif pixel_orientation == "B" and azimuth_index >= 12: - despun_spin_sector = spin_sector_index - - if "angular" in self.config["dataset_name"]: - spin_data = epoch_data[ - energy_index, :, spin_sector_index, : - ] # (5, 4) - despun_data[i][energy_index, :, despun_spin_sector, :] = ( - spin_data - ) - elif "priority" in self.config["dataset_name"]: - spin_data = epoch_data[energy_index, spin_sector_index, :] - despun_data[i][energy_index, despun_spin_sector, :] = ( - spin_data - ) - - # Replace original data - self.data = despun_data - - def decompress_data(self, science_values: list[NDArray[str]] | list[str]) -> None: - """ - Perform decompression on the data. - - The science data within the packet is a compressed byte string of - values. Apply the appropriate decompression algorithm to get an array - of decompressed values. - - Parameters - ---------- - science_values : list[NDArray[str]] | list[str] - A list of byte strings (or bit strings, in the case of I-ALiRT) - representing the science values of the data for each packet. - """ - # The compression algorithm depends on the instrument and view ID - if self.config["instrument"] == "lo": - compression_algorithm = constants.LO_COMPRESSION_ID_LOOKUP[self.view_id] - elif self.config["instrument"] == "hi": - compression_algorithm = constants.HI_COMPRESSION_ID_LOOKUP[self.view_id] - - self.raw_data = [] - - # I-ALiRT data already has byte count cut-off applied, so treat - # it slightly differently - if "ialirt" in self.config["dataset_name"]: - for packet_data in science_values: - # Convert from bit string to byte object - values = int(packet_data, 2).to_bytes( - len(packet_data) // 8, byteorder="big" - ) - decompressed_values = decompress(values, compression_algorithm) - self.raw_data.append(decompressed_values) - - else: - for packet_data, byte_count in zip( - science_values, self.dataset.byte_count.data, strict=False - ): - # Convert from numpy array to byte object - values = packet_data[()] - - # Only use the values up to the byte count. Bytes after this are - # used as padding and are not needed - values = values[:byte_count] - - decompressed_values = decompress(values, compression_algorithm) - self.raw_data.append(decompressed_values) - - def define_coordinates(self) -> None: # noqa: PLR0912 (too many branches) - """ - Create ``xr.DataArrays`` for the coords needed in the final dataset. - - The coordinates for the dataset depend on the data product being made. - - # TODO: Split this function up or simplify it to avoid too many branches - # error. - """ - self.coords = {} - - coord_names = [ - *self.config["dims"].keys(), - *[key + "_label" for key in self.config["dims"].keys()], - ] - - # Define epoch coordinates - epochs, epoch_delta_minus, epoch_delta_plus = calculate_epoch_values( - self.dataset.acq_start_seconds, self.dataset.acq_start_subseconds - ) - for name, var in [ - ("epoch", epochs), - ("epoch_delta_minus", epoch_delta_minus), - ("epoch_delta_plus", epoch_delta_plus), - ]: - coord = xr.DataArray( - var, - name=name, - dims=[name], - attrs=self.cdf_attrs.get_variable_attributes(name, check_schema=False), + elif apid == CODICEAPID.COD_HI_OMNI_SPECIES_COUNTS: + datasets.append( + process_by_table_id(datasets_by_apid[apid], lut_file, l1a_hi_omni) ) - self.coords[name] = coord - - # Define the values for the coordinates - for name in coord_names: - if name in [ - "esa_step", - "inst_az", - "spin_sector_pairs", - "spin_sector_index", - "ssd_index", - ]: - values = np.arange(self.config["dims"][name]) - dims = [name] - elif name == "spin_sector": - if self.config["dataset_name"] in constants.REQUIRES_DESPINNING: - values = np.arange(24) - else: - values = np.arange(self.config["dims"][name]) - dims = [name] - elif name == "spin_sector_pairs_label": - values = np.array( - [ - "0-30 deg", - "30-60 deg", - "60-90 deg", - "90-120 deg", - "120-150 deg", - "150-180 deg", - ] - ) - dims = [name] - elif name == "inst_az_label": - if self.config["dataset_name"] == "imap_codice_l1a_lo-nsw-angular": - values = [str(x) for x in range(4, 23)] - elif self.config["dataset_name"] == "imap_codice_l1a_lo-sw-angular": - values = ["1", "2", "3", "23", "24"] - else: - values = np.arange(self.config["dims"]["inst_az"]).astype(str) - dims = ["inst_az"] - elif name in [ - "esa_step_label", - "spin_sector_index_label", - "ssd_index_label", - ]: - key = name.removesuffix("_label") - values = np.arange(self.config["dims"][key]).astype(str) - dims = [key] - elif name == "spin_sector_label": - key = name.removesuffix("_label") - dims = [key] - if self.config["dataset_name"] in constants.REQUIRES_DESPINNING: - values = np.arange(24).astype(str) - else: - values = np.arange(self.config["dims"][key]).astype(str) - - coord = xr.DataArray( - values, - name=name, - dims=dims, - attrs=self.cdf_attrs.get_variable_attributes(name, check_schema=False), + elif apid == CODICEAPID.COD_HI_SECT_SPECIES_COUNTS: + logger.info("Processing Hi Sectored Species Counts") + datasets.append( + process_by_table_id(datasets_by_apid[apid], lut_file, l1a_hi_sectored) ) - - self.coords[name] = coord - - def define_data_variables(self) -> xr.Dataset: - """ - Define and add the appropriate data variables to the dataset. - - The data variables included in the dataset depend on the data product - being made. The method returns the ``xarray.Dataset`` object that can - then be written to a CDF file. - - Returns - ------- - processed_dataset : xarray.Dataset - The 'final' ``xarray`` dataset. - """ - # Create the main dataset to hold all the variables - dataset = xr.Dataset( - coords=self.coords, - attrs=self.cdf_attrs.get_global_attributes(self.config["dataset_name"]), - ) - - # Stack the data so that it is easier to reshape and iterate over - all_data = np.stack(self.data) - - # The dimension of all_data is something like (epoch, num_energy_steps, - # num_positions, num_spin_sectors, num_counters) (or may be slightly - # different depending on the data product). In any case, iterate over - # the num_counters dimension to isolate the data for each counter so - # each counter's data can be placed in a separate CDF data variable. - for counter, variable_name in zip( - range(all_data.shape[-1]), self.config["variable_names"], strict=False - ): - # Extract the counter data - counter_data = all_data[..., counter] - - # Get the CDF attributes - descriptor = self.config["dataset_name"].split("imap_codice_l1a_")[-1] - cdf_attrs_key = f"{descriptor}-{variable_name}" - attrs = self.cdf_attrs.get_variable_attributes(cdf_attrs_key) - - # For most products, the final CDF dimensions always has "epoch" as - # the first dimension followed by the dimensions for the specific - # data product - dims = ["epoch", *list(self.config["dims"].keys())] - - # However, CoDICE-Hi products use specific energy bins for the - # energy dimension - # TODO: This bit of code may no longer be needed once I can figure - # out how to run hi-sectored product through the - # create_binned_dataset function - if self.config["dataset_name"] == "imap_codice_l1a_hi-sectored": - dims = [ - f"energy_{variable_name}" if item == "esa_step" else item - for item in dims - ] - - # Create the CDF data variable - dataset[variable_name] = xr.DataArray( - counter_data, - name=variable_name, - dims=dims, - attrs=attrs, + elif apid == CODICEAPID.COD_HI_PHA: + logger.info("Processing Direct Events for Hi") + datasets.append(l1a_direct_event(datasets_by_apid[apid], apid=apid)) + elif apid == CODICEAPID.COD_LO_PHA: + logger.info("Processing Direct Events for Lo") + datasets.append(l1a_direct_event(datasets_by_apid[apid], apid=apid)) + elif apid in [ + CODICEAPID.COD_LO_SW_PRIORITY_COUNTS, + CODICEAPID.COD_LO_NSW_PRIORITY_COUNTS, + ]: + logger.info(f"Processing {apid} Priority Counts") + datasets.append( + process_by_table_id(datasets_by_apid[apid], lut_file, l1a_lo_priority) ) - - # Add support data variables based on data product - dataset = self.define_support_variables(dataset) - - # For CoDICE-Hi products, since energy dimension was replaced, we no - # longer need the "esa_step" coordinate - # TODO: This bit of code may no longer be needed once I can figure - # out how to run hi-sectored product through the - # create_binned_dataset function - if self.config["dataset_name"] == "imap_codice_l1a_hi-sectored": - for species in self.config["energy_table"]: - dataset = self.define_energy_bins(dataset, species) - dataset = dataset.drop_vars(["esa_step", "esa_step_label"]) - - return dataset - - def define_energy_bins(self, dataset: xr.Dataset, species: str) -> xr.Dataset: - """ - Define/add variables to the dataset that correspond to the energy bins. - - For hi-omni and hi-sectored data products specifically, the L1a data - product contains the energy bin centers and deltas. This method - handles adding these bins as CDF variables and their attributes. - - Parameters - ---------- - dataset : xarray.Dataset - ``xarray`` dataset for the data product. - species : str - The species for which to add the energy bins (e.g. "he3"). - - Returns - ------- - dataset : xarray.Dataset - ``xarray`` dataset for the data product, with added energy variables. - """ - energy_bin_name = f"energy_{species}" - centers, deltas_minus, deltas_plus = self.get_hi_energy_table_data( - energy_bin_name.split("energy_")[-1] - ) - - # Add bin centers and deltas to the dataset - dataset[energy_bin_name] = xr.DataArray( - centers, - dims=[energy_bin_name], - attrs=self.cdf_attrs.get_variable_attributes( - f"{self.config['dataset_name'].split('_')[-1]}-{energy_bin_name}", - check_schema=False, - ), - ) - dataset[f"{energy_bin_name}_minus"] = xr.DataArray( - deltas_minus, - dims=[f"{energy_bin_name}_minus"], - attrs=self.cdf_attrs.get_variable_attributes( - f"{self.config['dataset_name'].split('_')[-1]}-{energy_bin_name}_minus", - check_schema=False, - ), - ) - dataset[f"{energy_bin_name}_plus"] = xr.DataArray( - deltas_plus, - dims=[f"{energy_bin_name}_plus"], - attrs=self.cdf_attrs.get_variable_attributes( - f"{self.config['dataset_name'].split('_')[-1]}-{energy_bin_name}_plus", - check_schema=False, - ), - ) - - return dataset - - def define_support_variables(self, dataset: xr.Dataset) -> xr.Dataset: - """ - Define and add 'support' CDF data variables to the dataset. - - These variables include instrument metadata, energies, times, etc. that - help further define the L1a CDF data product. The variables included - depend on the data product being made. - - Parameters - ---------- - dataset : xarray.Dataset - ``xarray`` dataset for the data product. - - Returns - ------- - dataset : xarray.Dataset - ``xarray`` dataset for the data product, with added support variables. - """ - # These variables can be gathered from the packet data - packet_data_variables = [ - "rgfo_half_spin", - "nso_half_spin", - "sw_bias_gain_mode", - "st_bias_gain_mode", - ] - - for variable_name in self.config["support_variables"]: - # These variables require reading in external tables - if variable_name == "energy_table": - variable_data = self.get_energy_table() - dims = ["esa_step"] - attrs = self.cdf_attrs.get_variable_attributes( - "energy_table", check_schema=False - ) - - elif variable_name == "acquisition_time_per_step": - variable_data = self.get_acquisition_times() - dims = ["esa_step"] - attrs = self.cdf_attrs.get_variable_attributes( - "acquisition_time_per_step", check_schema=False - ) - - # These variables can be gathered straight from the packet data - elif variable_name in packet_data_variables: - variable_data = self.dataset[variable_name].data - dims = ["epoch"] - attrs = self.cdf_attrs.get_variable_attributes(variable_name) - - # Data quality is named differently in packet data and needs to be - # treated slightly differently - elif variable_name == "data_quality": - if "hi-omni" in self.config["dataset_name"]: - continue - variable_data = self.dataset.suspect.data - dims = ["epoch"] - attrs = self.cdf_attrs.get_variable_attributes("data_quality") - - # Spin period requires the application of a conversion factor - # See Table B.5 in the algorithm document - elif variable_name == "spin_period": - if "hi-omni" in self.config["dataset_name"]: - continue - variable_data = ( - self.dataset.spin_period.data * constants.SPIN_PERIOD_CONVERSION - ).astype(np.float32) - dims = ["epoch"] - attrs = self.cdf_attrs.get_variable_attributes("spin_period") - - # The k-factor is a constant that maps voltages to energies - elif variable_name == "k_factor": - variable_data = np.array([constants.K_FACTOR], dtype=np.float32) - dims = [""] - attrs = self.cdf_attrs.get_variable_attributes("k_factor") - - # Add variable to the dataset - dataset[variable_name] = xr.DataArray( - variable_data, - dims=dims, - attrs=attrs, + elif apid == CODICEAPID.COD_HI_INST_COUNTS_PRIORITIES: + logger.info("Processing Hi Priority Counts") + datasets.append( + process_by_table_id(datasets_by_apid[apid], lut_file, l1a_hi_priority) ) - - return dataset - - def get_acquisition_times(self) -> list[float]: - """ - Retrieve the acquisition times via the Lo stepping table. - - Get the acquisition times from the lookup table based on the values of - ``plan_id`` and ``plan_step`` - - The Lo stepping table defines how many voltage steps and which steps are - used during each spacecraft spin. A full cycle takes 16 spins. The table - provides the "acquisition time", which is the acquisition time, in - milliseconds, for the energy step. - - Returns - ------- - acquisition_times : list[float] - The list of acquisition times from the Lo stepping table. - """ - # Determine which Lo stepping table is needed - lo_stepping_table_id = constants.LO_STEPPING_TABLE_ID_LOOKUP[ - (self.plan_id, self.plan_step) - ] - - acquisition_times: list[float] = constants.ACQUISITION_TIMES[ - lo_stepping_table_id - ] - - return acquisition_times - - def get_energy_table(self) -> NDArray[float]: - """ - Retrieve the ESA sweep values. - - Get the ElectroStatic Analyzer (ESA) sweep values from the data file - based on the values of ``plan_id`` and ``plan_step`` - - CoDICE-Lo measures ions between ~0.5 and 80 keV/q that enter the - aperture and are selected and focused according to their E/q into the - Time of Flight (TOF) assembly. The E/q sweeping steps up to the max - voltage for the next stepping cycle when solar wind count rate exceed a - predefined threshold rate. - - The ESA sweep table defines the voltage steps that are used to cover the - full energy per charge range. - - Returns - ------- - energy_table : NDArray[float] - The list of ESA sweep values (i.e. voltage steps). - """ - # Read in the ESA sweep data table - esa_sweep_data_file = Path( - f"{imap_module_directory}/codice/data/esa_sweep_values.csv" - ) - sweep_data = pd.read_csv(esa_sweep_data_file) - - # Determine which ESA sweep table is needed - sweep_table_id = constants.ESA_SWEEP_TABLE_ID_LOOKUP[ - (self.plan_id, self.plan_step) - ] - - # Get the appropriate values - sweep_table = sweep_data[sweep_data["table_idx"] == sweep_table_id] - energy_table: NDArray[float] = sweep_table["esa_v"].values - - return energy_table - - def get_hi_energy_table_data( - self, species: str - ) -> tuple[NDArray[float], NDArray[float], NDArray[float]]: - """ - Retrieve energy table data for CoDICE-Hi products. - - This includes the centers and deltas of the energy bins for a given - species. These data eventually get included in the CoDICE-Hi CDF data - products. - - Parameters - ---------- - species : str - The species of interest, which determines which lookup table to - use (e.g. ``h``). - - Returns - ------- - centers : NDArray[float] - An array whose values represent the centers of the energy bins. - deltas_minus : NDArray[float] - An array whose values represent the minus deltas of the energy bins. - deltas_plus : NDArray[float] - An array whose values represent the plus deltas of the energy bins. - """ - data_product = self.config["dataset_name"].split("-")[-1].upper() - energy_table = np.array( - getattr(constants, f"{data_product}_ENERGY_TABLE")[species] - ) - - # Find the geometric centers and deltas of the energy bins - # The delta minus is the difference between the center of the bin - # and the 'left edge' of the bin. The delta plus is the difference - # between the 'right edge' of the bin and the center of the bin - centers = np.sqrt(energy_table[:-1] * energy_table[1:]) - deltas_minus = centers - energy_table[:-1] - deltas_plus = energy_table[1:] - centers - - return centers, deltas_minus, deltas_plus - - def reshape_binned_data(self, dataset: xr.Dataset) -> dict[str, list]: - """ - Reshape data arrays for binned datasets. - - Binned datasets get reshaped based on the number of species and their - corresponding number of energy bins. Additionally, the number of spins - during data acquisition are collapsed/summed which also needs to be taken - into account when reshaping into the correct dimensions. - - Parameters - ---------- - dataset : xarray.Dataset - ``xarray`` dataset for the data product. - - Returns - ------- - data : dict[str, list] - Data arrays for each species. - """ - # This will hold all of the data per-species and support variables, - # ready to be put in a CDF file - data: dict[str, list] = {} - for species in self.config["energy_table"]: - data[species] = [] - data["epoch"] = [] - data["spin_period"] = [] - data["data_quality"] = [] - - # Get the number of spins per species - num_spins = self.config["num_spins"] - - # Iterate through each epoch's data and pull out the data for each - # species - stacked_data = np.array(self.raw_data, dtype=np.uint32) - for i, epoch in enumerate(stacked_data): - current_epoch = dataset.epoch.data[i] - position = 0 - for species in self.config["energy_table"]: - # Subtracting one here since the table includes endpoints - num_bins = len(self.config["energy_table"][species]) - 1 - species_data = ( - epoch[position : position + num_bins * self.config["num_spins"]] - .reshape(num_bins, num_spins) - .T + elif apid == CODICEAPID.COD_HI_INST_COUNTS_AGGREGATED: + logger.info("Processing Hi Counters aggregated") + datasets.append( + process_by_table_id( + datasets_by_apid[apid], lut_file, l1a_hi_counters_aggregated ) - - # Now pull out the data for each spin within the species data - for spin_data in species_data: - data[species].append(spin_data) - - # We only need one set of support variables in the CDF, - # so just iterate using one species for these - if species == "h": - # For each spin, we add * to the - # epoch value - spin_period = ( - dataset.spin_period.data[i] - * constants.SPIN_PERIOD_CONVERSION - ) - epoch_value = current_epoch + np.int64( - (spin_period * num_spins) * 1e9 # Convert from s to ns - ) - data["epoch"].append(epoch_value) - current_epoch = epoch_value - - # Other support variables - data["spin_period"].append(spin_period) - data["data_quality"].append(dataset.suspect.data[i]) - - position += num_bins * num_spins - - return data - - def reshape_data(self) -> None: - """ - Reshape the data arrays based on the data product being made. - - These data need to be divided up by species or priorities (or - what I am calling "counters" as a general term), and re-arranged into - multidimensional arrays representing dimensions such as time, - spin sectors, positions, and energies (depending on the data product). - - However, the existence and order of these dimensions can vary depending - on the specific data product, so we define this in the "dims" key of the - configuration dictionary. - """ - # This will contain the reshaped data for all counters - self.data = [] - - # Reshape the data based on how it is written to the data array of - # the packet data. The number of counters is the last dimension / axis. - reshape_dims = ( - *self.config["dims"].values(), - self.config["num_counters"], - ) - for packet_data in self.raw_data: - reshaped_packet_data = np.array(packet_data, dtype=np.uint32).reshape( - reshape_dims ) - self.data.append(reshaped_packet_data) - - # Apply despinning if necessary - if self.config["dataset_name"] in constants.REQUIRES_DESPINNING: - self.apply_despinning() - - # No longer need to keep the raw data around - del self.raw_data - - def set_data_product_config(self, apid: int, dataset: xr.Dataset) -> None: - """ - Set the various settings for defining the data products. - - Parameters - ---------- - apid : int - The APID of interest. - dataset : xarray.Dataset - The dataset for the APID of interest. - """ - # Set the packet dataset so that it can be easily called from various - # methods - self.dataset = dataset - - # Set various configurations of the data product - self.config: dict[str, Any] = constants.DATA_PRODUCT_CONFIGURATIONS[apid] - - # Gather and set the CDF attributes - self.cdf_attrs = ImapCdfAttributes() - self.cdf_attrs.add_instrument_global_attrs("codice") - self.cdf_attrs.add_instrument_variable_attrs("codice", "l1a") - - -def calculate_epoch_values( - acq_start_seconds: xr.DataArray, acq_start_subseconds: xr.DataArray -) -> tuple[NDArray[int], NDArray[int], NDArray[int]]: - """ - Calculate and return the values to be used for `epoch`. - - On CoDICE, the epoch values are derived from the `acq_start_seconds` and - `acq_start_subseconds` fields in the packet. - - Note that the `acq_start_subseconds` field needs to be converted from - microseconds to seconds. - - Parameters - ---------- - acq_start_seconds : xarray.DataArray - The acquisition times to calculate the epoch values from. - acq_start_subseconds : xarray.DataArray - The subseconds portion of the acquisition times. - - Returns - ------- - epoch : NDArray[int] - List of centered epoch values. - epoch_delta_minus: NDArray[int] - List of values that represent the length of time from acquisition - start to the center of the acquisition time bin. - epoch_delta_plus: NDArray[int] - List of values that represent the length of time from the center of - the acquisition time bin to the end of acquisition. - """ - # First calculate an epoch value based on the acquisition start - acq_start = met_to_ttj2000ns(acq_start_seconds + acq_start_subseconds / 1e6) - - # Apply correction to center the epoch bin - epoch = (acq_start[:-1] + acq_start[1:]) // 2 - epoch_delta_minus = epoch - acq_start[:-1] - epoch_delta_plus = acq_start[1:] - epoch - - # Since the centers and deltas are determined by averaging sequential bins, - # the last elements must be calculated differently. For this, we just use - # the last acquisition start and the previous deltas - epoch = np.concatenate([epoch, [acq_start[-1]]]) - epoch_delta_minus = np.concatenate([epoch_delta_minus, [epoch_delta_minus[-1]]]) - epoch_delta_plus = np.concatenate([epoch_delta_plus, [epoch_delta_plus[-1]]]) - - return epoch, epoch_delta_minus, epoch_delta_plus - - -def group_ialirt_data( - packets: xr.Dataset, data_field_range: range, prefix: str -) -> list[bytearray]: - """ - Group together the individual I-ALiRT data fields. - - Parameters - ---------- - packets : xarray.Dataset - The dataset containing the I-ALiRT data packets. - data_field_range : range - The range of the individual data fields (15 or lo, 6 for hi). - prefix : str - The prefix used to index the data (i.e. ``cod_lo`` or ``cod_hi``). - - Returns - ------- - grouped_data : list[bytearray] - The list of grouped I-ALiRT data. - """ - current_data_stream = bytearray() - grouped_data = [] - - # Workaround to get this function working for both I-ALiRT spacecraft - # data and CoDICE-specific I-ALiRT test data from Joey - # TODO: Once CoDICE I-ALiRT processing is more established, we can probably - # do away with processing the test data from Joey and just use the - # I-ALiRT data that is constructed closer to what we expect in-flight. - if hasattr(packets, "acquisition_time"): - time_key = "acquisition_time" - counter_key = "counter" - data_key = "data" - else: - time_key = f"{prefix}_acq" - counter_key = f"{prefix}_counter" - data_key = f"{prefix}_data" - - # When a counter value of 255 is encountered, this signifies the - # end of the data stream - for packet_num in range(0, len(packets[time_key].data)): - counter = packets[counter_key].data[packet_num] - if counter != 255: - for field in data_field_range: - current_data_stream.extend( - bytearray([packets[f"{data_key}_{field:02}"].data[packet_num]]) + elif apid == CODICEAPID.COD_HI_INST_COUNTS_SINGLES: + logger.info("Processing Hi Counters singles") + datasets.append( + process_by_table_id( + datasets_by_apid[apid], lut_file, l1a_hi_counters_singles ) - else: - # At this point, if there are data, the data stream is ready - # to be processed like an SW Species product (for lo) or an - # Omni Species product (for hi) - if len(current_data_stream) > 0: - grouped_data.append(current_data_stream) - current_data_stream = bytearray() - - return grouped_data - - -def create_binned_dataset( - apid: int, dataset: xr.Dataset, science_values: list[str] -) -> xr.Dataset: - """ - Create dataset for data that is binned by energy. - - This applies to the ``hi-omni`` and ``hi-sectored`` datasets. In addition to - data for species (e.g. ``h``, ``c``, ``o``, etc.), we add CDF variables - for their respective energy bin centers and deltas (e.g. ``energy_h``, - ``energy_h_delta``, etc.) - - Parameters - ---------- - apid : int - The APID of the packet. - dataset : xarray.Dataset - The packets to process. - science_values : list[str] - The values of the "data" field of the dataset. - - Returns - ------- - dataset : xarray.Dataset - Xarray dataset containing the final processed dataset. - """ - # TODO: hi-sectored data product should be processed similar to hi-omni, - # so I should be able to use this method. - - # Get the four "main" parameters for processing - table_id, plan_id, plan_step, view_id = get_params(dataset) - - # Run some of the pipeline methods to set configs and decompress - # the data - pipeline = CoDICEL1aPipeline(table_id, plan_id, plan_step, view_id) - pipeline.set_data_product_config(apid, dataset) - pipeline.decompress_data(science_values) - - data = pipeline.reshape_binned_data(dataset) - - # Create the main dataset to hold all the variables - coord = xr.DataArray( - np.array(data["epoch"], dtype=np.uint64), - name="epoch", - dims=["epoch"], - attrs=pipeline.cdf_attrs.get_variable_attributes("epoch", check_schema=False), - ) - # TODO: Figure out how to calculate epoch centers and deltas and store them - # in variables here - dataset = xr.Dataset( - coords={"epoch": coord}, - attrs=pipeline.cdf_attrs.get_global_attributes(pipeline.config["dataset_name"]), - ) - - # Add the data variables - descriptor = pipeline.config["dataset_name"].removeprefix("imap_codice_l1a_") - for species in pipeline.config["energy_table"]: - # Add the species data to the dataset - values = np.array(data[species], dtype=np.uint32) - attrs = pipeline.cdf_attrs.get_variable_attributes(f"{descriptor}-{species}") - dims = ["epoch", f"energy_{species}"] - dataset[species] = xr.DataArray( - values, - name=species, - dims=dims, - attrs=attrs, - ) - - # Add the energy bins to the dataset - dataset = pipeline.define_energy_bins(dataset, species) - - # Add support variables to the dataset - dataset["spin_period"] = xr.DataArray( - np.array(data["spin_period"]), - name="spin_period", - dims=["epoch"], - attrs=pipeline.cdf_attrs.get_variable_attributes("spin_period"), - ) - dataset["data_quality"] = xr.DataArray( - np.array(data["data_quality"]), - name="data_quality", - dims=["epoch"], - attrs=pipeline.cdf_attrs.get_variable_attributes("data_quality"), - ) - - return dataset - - -def create_direct_event_dataset(apid: int, packets: xr.Dataset) -> xr.Dataset: - """ - Create dataset for direct event data. - - For direct event data, the raw data from the spacecraft is organized first - by epoch, then by priority, then by events. For example, for a CoDICE-Lo - dataset with 10 epochs, we expect the length of the `event_data` field to - be (10 epochs * 8 priorities) = 80 items, with each item being a compressed - byte object representing a variable number of events (up to 10000 events). - Each compressed byte object is comprised of several fields with specific - bit lengths/positions, described by the constants.[LO|HI]_DE_BIT_STRUCTURE - dictionary. Padding is added to any fields that have less than 10000 events. - - In order to process these data, we must take the decommed raw data, group - the packets appropriately based on their `seq_flgs`, decompress the data, - then arrange the data into CDF data variables for each priority and bit - field. For example, P2_SpinAngle represents the spin angles for the 2nd - priority data. - - Parameters - ---------- - apid : int - The APID of the packet. - packets : xarray.Dataset - The packets to process. - - Returns - ------- - dataset : xarray.Dataset - Xarray dataset containing the direct event data. - """ - # Group and decompress the data - grouped_data = group_data(packets) - decompressed_data = [ - decompress(group, CoDICECompression.LOSSLESS) for group in grouped_data - ] - - # Reshape the packet data into CDF-ready variables - data = reshape_de_data(packets, decompressed_data, apid) - - # Gather the CDF attributes - cdf_attrs = ImapCdfAttributes() - cdf_attrs.add_instrument_global_attrs("codice") - cdf_attrs.add_instrument_variable_attrs("codice", "l1a") - - # Determine the epochs to use in the dataset, which are the epochs whenever - # there is a start of a segment and the priority is 0 - epoch_indices = np.where( - ((packets.seq_flgs.data == 3) | (packets.seq_flgs.data == 1)) - & (packets.priority.data == 0) - )[0] - acq_start_seconds = packets.acq_start_seconds[epoch_indices] - acq_start_subseconds = packets.acq_start_subseconds[epoch_indices] - - # Calculate epoch variables - epochs, epochs_delta_minus, epochs_delta_plus = calculate_epoch_values( - acq_start_seconds, acq_start_subseconds - ) - - # Define coordinates - epoch = xr.DataArray( - epochs, - name="epoch", - dims=["epoch"], - attrs=cdf_attrs.get_variable_attributes("epoch", check_schema=False), - ) - epoch_delta_minus = xr.DataArray( - epochs_delta_minus, - name="epoch_delta_minus", - dims=["epoch_delta_minus"], - attrs=cdf_attrs.get_variable_attributes( - "epoch_delta_minus", check_schema=False - ), - ) - epoch_delta_plus = xr.DataArray( - epochs_delta_plus, - name="epoch_delta_plus", - dims=["epoch_delta_plus"], - attrs=cdf_attrs.get_variable_attributes("epoch_delta_plus", check_schema=False), - ) - event_num = xr.DataArray( - np.arange(10000), - name="event_num", - dims=["event_num"], - attrs=cdf_attrs.get_variable_attributes("event_num", check_schema=False), - ) - event_num_label = xr.DataArray( - np.arange(10000).astype(str), - name="event_num_label", - dims=["event_num"], - attrs=cdf_attrs.get_variable_attributes("event_num_label", check_schema=False), - ) - - # Create the dataset to hold the data variables - if apid == CODICEAPID.COD_LO_PHA: - attrs = cdf_attrs.get_global_attributes("imap_codice_l1a_lo-direct-events") - elif apid == CODICEAPID.COD_HI_PHA: - attrs = cdf_attrs.get_global_attributes("imap_codice_l1a_hi-direct-events") - dataset = xr.Dataset( - coords={ - "epoch": epoch, - "epoch_delta_minus": epoch_delta_minus, - "epoch_delta_plus": epoch_delta_plus, - "event_num": event_num, - "event_num_label": event_num_label, - }, - attrs=attrs, - ) - - # Create the CDF data variables for each Priority and Field - for i in range(constants.DE_DATA_PRODUCT_CONFIGURATIONS[apid]["num_priorities"]): - for field in constants.DE_DATA_PRODUCT_CONFIGURATIONS[apid]["cdf_fields"]: - variable_name = f"p{i}_{field}" - attrs = cdf_attrs.get_variable_attributes(variable_name) - if field in ["num_events", "data_quality"]: - dims = ["epoch"] - else: - dims = ["epoch", "event_num"] - dataset[variable_name] = xr.DataArray( - np.array(data[variable_name]), - name=variable_name, - dims=dims, - attrs=attrs, ) - - return dataset - - -def create_hskp_dataset(packet: xr.Dataset) -> xr.Dataset: - """ - Create dataset for each metadata field for housekeeping data. - - Parameters - ---------- - packet : xarray.Dataset - The packet to process. - - Returns - ------- - dataset : xarray.Dataset - Xarray dataset containing the metadata. - """ - cdf_attrs = ImapCdfAttributes() - cdf_attrs.add_instrument_global_attrs("codice") - cdf_attrs.add_instrument_variable_attrs("codice", "l1a") - - epoch = xr.DataArray( - packet.epoch, - name="epoch", - dims=["epoch"], - attrs=cdf_attrs.get_variable_attributes("epoch", check_schema=False), - ) - - dataset = xr.Dataset( - coords={"epoch": epoch}, - attrs=cdf_attrs.get_global_attributes("imap_codice_l1a_hskp"), - ) - - # These variables don't need to carry over from L0 to L1a - exclude_variables = [ - "spare_1", - "spare_2", - "spare_3", - "spare_4", - "spare_5", - "spare_6", - "spare_62", - "spare_68", - "chksum", - ] - - for variable in packet: - if variable in exclude_variables: - continue - - # The housekeeping spin_period variable has different values than - # the spin_value attribute in other datasets, so it gets special - # treatment - if variable == "spin_period": - attrs = cdf_attrs.get_variable_attributes("spin_period_hskp") - else: - attrs = cdf_attrs.get_variable_attributes(variable) - - dataset[variable] = xr.DataArray( - packet[variable].data, dims=["epoch"], attrs=attrs - ) - - return dataset - - -def create_ialirt_dataset(apid: int, packets: xr.Dataset) -> xr.Dataset: - """ - Create dataset for lo- and hi-ialirt data. - - I-ALiRT data are packed identically to regular science data - (``lo-sw-species`` for CoDICE-lo, and ``hi-omni`` for CoDICE-hi), except - for some slight differences in the metadata that are transmitted. - Additionally, data are transmitted in separate, individual single-byte - fields (there are 15 of these for CoDICE-lo and 6 for CoDICE-hi). - - This function will process these I-ALiRT data while using some of the same - code used for processing the ``lo-sw-species`` and ``hi-omni`` L1a data - products. - - Parameters - ---------- - apid : int - The APID of the packet. - packets : xarray.Dataset - The packets to process. - - Returns - ------- - dataset : xarray.Dataset - Xarray dataset containing the direct event data. - - References - ---------- - See section 9.4 of the CoDICE algorithm document for further details. - """ - # I-ALiRT packet data gets split up into multiple data fields, - # specific to lo- and hi- - # See sections 10.4.1 and 10.4.2 in the algorithm document - if apid == CODICEAPID.COD_LO_IAL: - data_field_range = range(0, 15) - prefix = "cod_lo" - elif apid == CODICEAPID.COD_HI_IAL: - data_field_range = range(0, 5) - prefix = "cod_hi" - - # Group together packets of I-ALiRT data to form complete data sets - grouped_data = group_ialirt_data(packets, data_field_range, prefix) - - if grouped_data: - # Process each group to get the science data and corresponding metadata - science_values, metadata_values = process_ialirt_data_streams(grouped_data) - - # How data are processed is different for lo-iarlirt and hi-ialirt - if apid == CODICEAPID.COD_HI_IAL: - # Set some necessary values and process as a binned dataset similar to - # a hi-omni data product - metadata_for_processing = [ - "table_id", - "plan_id", - "plan_step", - "view_id", - "spin_period", - "suspect", - ] - for var in metadata_for_processing: - packets[var] = metadata_values[var.upper()] - dataset = create_binned_dataset(apid, packets, science_values) - - elif apid == CODICEAPID.COD_LO_IAL: - # Create a nominal instance of the pipeline and process similar to a - # lo-sw-species data product - pipeline = CoDICEL1aPipeline( - metadata_values["TABLE_ID"][0], - metadata_values["PLAN_ID"][0], - metadata_values["PLAN_STEP"][0], - metadata_values["VIEW_ID"][0], - ) - pipeline.set_data_product_config(apid, packets) - pipeline.decompress_data(science_values) - pipeline.reshape_data() - - # The calculate_epoch_values method needs acq_start_seconds and - # acq_start_subseconds attributes on the dataset - pipeline.dataset["acq_start_seconds"] = ( - "_", - metadata_values["ACQ_START_SECONDS"], - ) - pipeline.dataset["acq_start_subseconds"] = ( - "_", - metadata_values["ACQ_START_SUBSECONDS"], - ) - - pipeline.define_coordinates() - - # The dataset also needs the metadata that will be carried through - # to the final data product - for field in [ - "spin_period", - "suspect", - "st_bias_gain_mode", - "sw_bias_gain_mode", - "rgfo_half_spin", - "nso_half_spin", - ]: - pipeline.dataset[field] = ("_", metadata_values[field.upper()]) - - dataset = pipeline.define_data_variables() - - return dataset - - else: - logger.warning("No I-ALiRT data found") - return None - - -def get_de_metadata(packets: xr.Dataset, segment: int) -> bytes: - """ - Gather and return packet metadata (From packet_version through byte_count). - - Extract the metadata in the segmented direct event packet, which is then - used to construct the full data of the group of segments. - - Parameters - ---------- - packets : xarray.Dataset - The segmented direct event packet data. - segment : int - The index of the segment of interest. - - Returns - ------- - metadata : bytes - The compressed metadata for the segmented packet. - """ - # String together the metadata fields and convert the data to a bytes obj - metadata_str = "" - for field, num_bits in constants.DE_METADATA_FIELDS.items(): - metadata_str += f"{packets[field].data[segment]:0{num_bits}b}" - metadata_chunks = [metadata_str[i : i + 8] for i in range(0, len(metadata_str), 8)] - metadata_ints = [int(item, 2) for item in metadata_chunks] - metadata = bytes(metadata_ints) - - return metadata - - -def get_params(dataset: xr.Dataset) -> tuple[int, int, int, int]: - """ - Return the four 'main' parameters used for l1a processing. - - The combination of these parameters largely determines what steps/values - are used to create CoDICE L1a data products and what steps are needed in - the pipeline algorithm. - - Parameters - ---------- - dataset : xarray.Dataset - The dataset for the APID of interest. We expect each packet in the - dataset to have the same values for the four main parameters, so the - first index of the dataset can be used to determine them. - - Returns - ------- - table_id : int - A unique ID assigned to a specific table configuration. This field is - used to link the overall acquisition and processing settings to a - specific table configuration. - plan_id : int - The plan table that was in use. In conjunction with ``plan_step``, - describes which counters are included in the data packet. - plan_step : int - Plan step that was active when the data was acquired and processed. In - conjunction with ``plan_id``, describes which counters are included - in the data packet. - view_id : int - Provides information about how data was collapsed and/or compressed. - """ - table_id = int(dataset.table_id.data[0]) - plan_id = int(dataset.plan_id.data[0]) - plan_step = int(dataset.plan_step.data[0]) - view_id = int(dataset.view_id.data[0]) - - return table_id, plan_id, plan_step, view_id - - -def group_data(packets: xr.Dataset) -> list[bytes]: - """ - Organize continuation packets into appropriate groups. - - Some packets are continuation packets, as in, they are packets that are - part of a group of packets. These packets are marked by the `seq_flgs` field - in the CCSDS header of the packet. For CoDICE, the values are defined as - follows: - - 3 = Packet is not part of a group - 1 = Packet is the first packet of the group - 0 = Packet is in the middle of the group - 2 = Packet is the last packet of the group - - For packets that are part of a group, the byte count associated with the - first packet of the group signifies the byte count for the entire group. - - Parameters - ---------- - packets : xarray.Dataset - Dataset containing the packets to group. - - Returns - ------- - grouped_data : list[bytes] - The packet data, converted to bytes and grouped appropriately. - """ - grouped_data = [] # Holds the properly grouped data to be decompressed - current_group = bytearray() # Temporary storage for current group - group_byte_count = None # Temporary storage for current group byte count - - for segment in range(len(packets.event_data.data)): - packet_data = packets.event_data.data[segment] - group_code = packets.seq_flgs.data[segment] - byte_count = packets.byte_count.data[segment] - - # If the group code is 3, this means the data is not part of a group - # and can be decompressed as-is - if group_code == 3: - grouped_data.append(packet_data[:byte_count]) - - # If the group code is 1, this means the data is the first data in a - # group. Also, set the byte count for the group - elif group_code == 1: - group_byte_count = byte_count - current_group += packet_data - - # If the group code is 0, this means the data is part of the middle of - # the group. - elif group_code == 0: - current_group += get_de_metadata(packets, segment) - current_group += packet_data - - # If the group code is 2, this means the data is the last data in the - # group - elif group_code == 2: - current_group += get_de_metadata(packets, segment) - current_group += packet_data - - # The grouped data is now ready to be decompressed - values_to_decompress = current_group[:group_byte_count] - grouped_data.append(values_to_decompress) - - # Reset the current group - current_group = bytearray() - group_byte_count = None - - return grouped_data - - -def log_dataset_info(datasets: dict[int, xr.Dataset]) -> None: - """ - Log info about the input data to help with tracking and/or debugging. - - Parameters - ---------- - datasets : dict[int, xarray.Dataset] - Mapping from apid to ``xarray`` dataset, one dataset per apid. - """ - launch_time = np.datetime64("2010-01-01T00:01:06.184", "ns") - logger.info("\nThis input file contains the following APIDs:\n") - for apid, ds in datasets.items(): - num_packets = len(ds.epoch.data) - time_deltas = [np.timedelta64(item, "ns") for item in ds.epoch.data] - times = [launch_time + delta for delta in time_deltas] - start = np.datetime_as_string(times[0]) - end = np.datetime_as_string(times[-1]) - logger.info( - f"{CODICEAPID(apid).name}: {num_packets} packets spanning {start} to {end}" - ) - - -def process_ialirt_data_streams( - grouped_data: list[bytearray], -) -> tuple[list[str], dict[str, list[int]]]: - """ - Process each I-ALiRT science data stream to extract individual data fields. - - Each data stream is converted to binary so that each metadata and science - data field and their values can be separated out. These fields and values - eventually will be stored in CDF data/support variables. - - Parameters - ---------- - grouped_data : list[bytearray] - A list of grouped I-ALiRT data. - - Returns - ------- - science_values : list[str] - The science values / data array portion of the I-ALiRT data in the form - of a binary string. - metadata_values : dict[str, list[int]] - The extracted metadata fields and their values. - """ - # Initialize placeholders for the processed data - science_values = [] - metadata_values: dict[str, list[int]] = {} - for field in constants.IAL_BIT_STRUCTURE: - metadata_values[field] = [] - - # Process each complete data stream - for data_stream in grouped_data: - try: - # Convert the data to binary - bit_string = "".join(f"{byte:08b}" for byte in data_stream) - - # Separate the data into its individual fields - bit_position = 0 - for field in constants.IAL_BIT_STRUCTURE: - # Convert from binary to integer - value = int( - bit_string[ - bit_position : bit_position + constants.IAL_BIT_STRUCTURE[field] - ], - 2, + elif apid == CODICEAPID.COD_LO_INST_COUNTS_AGGREGATED: + logger.info("Processing Lo Counters aggregated") + datasets.append( + process_by_table_id( + datasets_by_apid[apid], lut_file, l1a_lo_counters_aggregated ) - - # If we encounter an SHCOARSE of 0, the packet is bad - if field == "SHCOARSE" and value == 0: - raise ValueError("Bad packet encountered") - - metadata_values[field].append(value) - bit_position += constants.IAL_BIT_STRUCTURE[field] - if field == "BYTE_COUNT": - byte_count = value * 8 # Convert from bytes to number of bits - - # The rest is the data field, up to the byte count - data_field = bit_string[bit_position : bit_position + byte_count] - science_values.append(data_field) - except ValueError: - pass - - return science_values, metadata_values - - -def reshape_de_data( - packets: xr.Dataset, decompressed_data: list[list[int]], apid: int -) -> dict[str, np.ndarray]: - """ - Reshape the decompressed direct event data into CDF-ready arrays. - - Parameters - ---------- - packets : xarray.Dataset - Dataset containing the packets, needed to determine priority order - and data quality. - decompressed_data : list[list[int]] - The decompressed data to reshape, in the format [[]]. - apid : int - The APID of the packet, used primarily to determine if the data are from - CoDICE-Lo or CoDICE-Hi. - - Returns - ------- - data : dict[str, numpy.ndarray] - The reshaped, CDF-ready arrays. The keys of the dictionary represent the - CDF variable names, and the values represent the data. - """ - # Dictionary to hold all the (soon to be restructured) direct event data - data: dict[str, np.ndarray] = {} - - # Extract some useful variables - num_priorities = constants.DE_DATA_PRODUCT_CONFIGURATIONS[apid]["num_priorities"] - bit_structure = constants.DE_DATA_PRODUCT_CONFIGURATIONS[apid]["bit_structure"] - - # Determine the number of epochs to help with data array initialization - # There is one epoch per set of priorities - num_epochs = len(decompressed_data) // num_priorities - - # Get num_events, data quality, and priorities data for beginning of segments - segment_starts = np.where( - (packets.seq_flgs.data == 3) | (packets.seq_flgs.data == 1) - )[0] - num_events_arr = packets.num_events.data[segment_starts] - data_quality_arr = packets.suspect.data[segment_starts] - priorities_arr = packets.priority.data[segment_starts] - - # Initialize data arrays for each priority and field to store the data - # We also need arrays to hold number of events and data quality - for priority_num in range(num_priorities): - for field in bit_structure: - if field not in ["Priority", "Spare"]: - data[f"p{priority_num}_{field}"] = np.full( - (num_epochs, 10000), - bit_structure[field]["fillval"], - dtype=bit_structure[field]["dtype"], - ) - data[f"p{priority_num}_num_events"] = np.full( - num_epochs, 65535, dtype=np.uint16 - ) - data[f"p{priority_num}_data_quality"] = np.full(num_epochs, 255, dtype=np.uint8) - - # decompressed_data is one large list of values of length - # ( * ) - # Chunk the data into each epoch - for epoch_index in range(num_epochs): - # Determine the starting and ending indices of the epoch - epoch_start = epoch_index * num_priorities - epoch_end = epoch_start + num_priorities - - # Extract the data for the epoch - epoch_data = decompressed_data[epoch_start:epoch_end] - - # The order of the priorities and data quality flags are unique to each - # epoch and can be gathered from the packet data - priority_order = priorities_arr[epoch_start:epoch_end] - data_quality = data_quality_arr[epoch_start:epoch_end] - - # For each epoch/priority combo, iterate over each event - for i, priority_num in enumerate(priority_order): - priority_data = epoch_data[i] - - # Number of events and data quality can be determined at this stage - num_events = num_events_arr[epoch_start:epoch_end][i] - data[f"p{priority_num}_num_events"][epoch_index] = num_events - data[f"p{priority_num}_data_quality"][epoch_index] = data_quality[i] - - # Iterate over each event - for event_index in range(num_events): - event_start = event_index * 8 # The 8 is for 8 bytes - event_end = event_start + 8 - event = priority_data[event_start:event_end] - - # Separate out each individual field from the bit string - # The fields are packed into the bit string in reverse order, so - # we need to back them out in reverse order - bit_string = ( - f"{int.from_bytes(event, byteorder='big'):0{len(event) * 8}b}" + ) + elif apid == CODICEAPID.COD_LO_INST_COUNTS_SINGLES: + logger.info("Processing Lo Counters singles") + datasets.append( + process_by_table_id( + datasets_by_apid[apid], lut_file, l1a_lo_counters_singles ) - - bit_position = 0 - for field_name, field_components in reversed(bit_structure.items()): - # We don't need to carry Priority and Spare fields through - if field_name in ["Priority", "Spare"]: - bit_position += field_components["bit_length"] - continue - - # Convert from binary to integer - value = int( - bit_string[ - bit_position : bit_position + field_components["bit_length"] - ], - 2, - ) - - # Set the value into the data array - data[f"p{priority_num}_{field_name}"][epoch_index, event_index] = ( - value - ) - bit_position += field_components["bit_length"] - - return data - - -def process_codice_l1a(file_path: Path) -> list[xr.Dataset]: - """ - Will process CoDICE l0 data to create l1a data products. - - Parameters - ---------- - file_path : pathlib.Path | str - Path to the CoDICE L0 file to process. - - Returns - ------- - processed_datasets : list[xarray.Dataset] - A list of the ``xarray`` datasets containing the science data and - supporting metadata. - """ - # Decom the packets, group data by APID, and sort by time - datasets = decom_packets(file_path) - - # Log some information about the contents of the data - log_dataset_info(datasets) - - # Placeholder to hold the final, processed datasets - processed_datasets = [] - - # Process each APID separately - for apid in datasets: - dataset = datasets[apid] - logger.info(f"\nProcessing {CODICEAPID(apid).name} packet") - - # Housekeeping data - if apid == CODICEAPID.COD_NHK: - processed_dataset = create_hskp_dataset(dataset) - logger.info(f"\nFinal data product:\n{processed_dataset}\n") - - # Event data - elif apid in [CODICEAPID.COD_LO_PHA, CODICEAPID.COD_HI_PHA]: - processed_dataset = create_direct_event_dataset(apid, dataset) - logger.info(f"\nFinal data product:\n{processed_dataset}\n") - - # I-ALiRT data - elif apid in [CODICEAPID.COD_LO_IAL, CODICEAPID.COD_HI_IAL]: - processed_dataset = create_ialirt_dataset(apid, dataset) - logger.info(f"\nFinal data product:\n{processed_dataset}\n") - - # hi-omni data - elif apid == CODICEAPID.COD_HI_OMNI_SPECIES_COUNTS: - science_values = [packet.data for packet in dataset.data] - processed_dataset = create_binned_dataset(apid, dataset, science_values) - logger.info(f"\nFinal data product:\n{processed_dataset}\n") - - # Everything else - elif apid in constants.APIDS_FOR_SCIENCE_PROCESSING: - # Extract the data - science_values = [packet.data for packet in dataset.data] - - # Get the four "main" parameters for processing - table_id, plan_id, plan_step, view_id = get_params(dataset) - - # Run the pipeline to create a dataset for the product - pipeline = CoDICEL1aPipeline(table_id, plan_id, plan_step, view_id) - pipeline.set_data_product_config(apid, dataset) - pipeline.decompress_data(science_values) - pipeline.reshape_data() - pipeline.define_coordinates() - processed_dataset = pipeline.define_data_variables() - - logger.info(f"\nFinal data product:\n{processed_dataset}\n") - - # For APIDs that don't require processing - else: - logger.info(f"\t{apid} does not require processing") - continue - - processed_datasets.append(processed_dataset) - - return processed_datasets + ) + elif apid == CODICEAPID.COD_NHK: + logger.info("Processing l1a housekeeping data") + cdf_attrs = ImapCdfAttributes() + cdf_attrs.add_instrument_global_attrs("codice") + l1a_ds = datasets_by_apid[apid] + l1a_ds.attrs.update(cdf_attrs.get_global_attributes("imap_codice_l1a_hskp")) + datasets.append(l1a_ds) + + # l1b processing need to re-run packet file to datasets to do the + # housekeeping engineering unit conversions based on the packet definitions + # We only do this if there are any housekeeping packets that need it so we + # don't process unnecessarily here. + logger.info("Processing l1b housekeeping data") + l1b_ds = packet_file_to_datasets( + science_file, + xtce_file, + use_derived_value=True, + )[apid] + l1b_ds.attrs.update(cdf_attrs.get_global_attributes("imap_codice_l1b_hskp")) + datasets.append(l1b_ds) + + return datasets diff --git a/imap_processing/codice/codice_l1a_de.py b/imap_processing/codice/codice_l1a_de.py new file mode 100644 index 0000000000..25e437594e --- /dev/null +++ b/imap_processing/codice/codice_l1a_de.py @@ -0,0 +1,590 @@ +"""Processing functions for CoDICE L1A Direct Event data.""" + +import logging + +import numpy as np +import xarray as xr + +from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes +from imap_processing.codice import constants +from imap_processing.codice.decompress import decompress +from imap_processing.codice.utils import ( + CODICEAPID, + CoDICECompression, + ViewTabInfo, + apply_replacements_to_attrs, + get_codice_epoch_time, +) +from imap_processing.spice.time import met_to_ttj2000ns +from imap_processing.utils import combine_segmented_packets + +logger = logging.getLogger(__name__) + + +def extract_initial_items_from_combined_packets( + packets: xr.Dataset, +) -> xr.Dataset: + """ + Extract fields from the beginning of combined event_data packets. + + Extracts bit fields from the first 20 bytes of each event_data array + and add them as new variables to the dataset. + + This was previously done in XTCE, but we can't do that because of + segmented packets that need to be combined. Each segmented packet + has its own (SHCOARSE, EVENTDATA, CHKSUM) fields, so we need to + only combine along the EVENTDATA field and extract data that way. + + Parameters + ---------- + packets : xarray.Dataset + Dataset containing combined packets with event_data. + + Returns + ------- + xarray.Dataset + Dataset with extracted metadata fields added. + """ + # Initialize arrays for extracted fields + n_packets = len(packets.epoch) + + # Preallocate arrays + packet_version: np.ndarray = np.zeros(n_packets, dtype=np.uint16) + spin_period: np.ndarray = np.zeros(n_packets, dtype=np.uint16) + acq_start_seconds: np.ndarray = np.zeros(n_packets, dtype=np.uint32) + acq_start_subseconds: np.ndarray = np.zeros(n_packets, dtype=np.uint32) + spare_1: np.ndarray = np.zeros(n_packets, dtype=np.uint8) + st_bias_gain_mode: np.ndarray = np.zeros(n_packets, dtype=np.uint8) + sw_bias_gain_mode: np.ndarray = np.zeros(n_packets, dtype=np.uint8) + suspect: np.ndarray = np.zeros(n_packets, dtype=np.uint8) + priority: np.ndarray = np.zeros(n_packets, dtype=np.uint8) + compressed: np.ndarray = np.zeros(n_packets, dtype=np.uint8) + rgfo_half_spin: np.ndarray = np.zeros(n_packets, dtype=np.uint8) + rgfo_esa_step: np.ndarray = np.zeros(n_packets, dtype=np.uint8) + rgfo_spin_sector: np.ndarray = np.zeros(n_packets, dtype=np.uint8) + nso_half_spin: np.ndarray = np.zeros(n_packets, dtype=np.uint8) + nso_spin_sector: np.ndarray = np.zeros(n_packets, dtype=np.uint8) + nso_esa_step: np.ndarray = np.zeros(n_packets, dtype=np.uint8) + spare_2: np.ndarray = np.zeros(n_packets, dtype=np.uint16) + num_events: np.ndarray = np.zeros(n_packets, dtype=np.uint32) + byte_count: np.ndarray = np.zeros(n_packets, dtype=np.uint32) + + # Extract fields from each packet + for pkt_idx in range(n_packets): + event_data = packets.event_data.data[pkt_idx] + + # Byte-aligned fields using int.from_bytes + packet_version[pkt_idx] = int.from_bytes(event_data[0:2], byteorder="big") + spin_period[pkt_idx] = int.from_bytes(event_data[2:4], byteorder="big") + acq_start_seconds[pkt_idx] = int.from_bytes(event_data[4:8], byteorder="big") + + # Non-byte-aligned fields (bytes 8-12 contain mixed bit fields) + # Extract 4 bytes and unpack bit fields + mixed_bytes = int.from_bytes(event_data[8:12], byteorder="big") + + # acq_start_subseconds: 20 bits (MSB) + acq_start_subseconds[pkt_idx] = (mixed_bytes >> 12) & 0xFFFFF + # spare_1: 2 bits + spare_1[pkt_idx] = (mixed_bytes >> 10) & 0x3 + # st_bias_gain_mode: 2 bits + st_bias_gain_mode[pkt_idx] = (mixed_bytes >> 8) & 0x3 + # sw_bias_gain_mode: 2 bits + sw_bias_gain_mode[pkt_idx] = (mixed_bytes >> 6) & 0x3 + # priority: 4 bits + priority[pkt_idx] = (mixed_bytes >> 2) & 0xF + # suspect: 1 bit + suspect[pkt_idx] = (mixed_bytes >> 1) & 0x1 + # compressed: 1 bit (LSB) + compressed[pkt_idx] = mixed_bytes & 0x1 + # After packet version 1, the fields below are present in event_data + if packet_version[pkt_idx] > 1: + # All of the fields below are single byte fields + rgfo_half_spin[pkt_idx] = event_data[12] + rgfo_spin_sector[pkt_idx] = event_data[13] + rgfo_esa_step[pkt_idx] = event_data[14] + nso_half_spin[pkt_idx] = event_data[15] + nso_spin_sector[pkt_idx] = event_data[16] + nso_esa_step[pkt_idx] = event_data[17] + + # spare_2 is 16 bits + spare_2[pkt_idx] = int.from_bytes(event_data[18:20], byteorder="big") + # Remaining byte-aligned fields + num_events[pkt_idx] = int.from_bytes(event_data[20:24], byteorder="big") + byte_count[pkt_idx] = int.from_bytes(event_data[24:28], byteorder="big") + # Header is 28 bytes total for version > 1 + len_header = 28 + else: + # Remaining byte-aligned fields + num_events[pkt_idx] = int.from_bytes(event_data[12:16], byteorder="big") + byte_count[pkt_idx] = int.from_bytes(event_data[16:20], byteorder="big") + # Header is 20 bytes total for version 1 + len_header = 20 + + # Remove the first len_header bytes from event_data (header fields from above) + # Then trim to the number of bytes indicated by byte_count + if byte_count[pkt_idx] > len(event_data) - len_header: + raise ValueError( + f"Byte count {byte_count[pkt_idx]} exceeds available " + f"data length {len(event_data) - len_header} for packet index" + f" {pkt_idx}." + ) + + packets.event_data.data[pkt_idx] = event_data[ + len_header : byte_count[pkt_idx] + len_header + ] + if compressed[pkt_idx]: + packets.event_data.data[pkt_idx] = decompress( + packets.event_data.data[pkt_idx], + CoDICECompression.LOSSLESS, + ) + + # Add extracted fields to dataset + packets["packet_version"] = xr.DataArray(packet_version, dims=["epoch"]) + packets["spin_period"] = xr.DataArray(spin_period, dims=["epoch"]) + packets["acq_start_seconds"] = xr.DataArray(acq_start_seconds, dims=["epoch"]) + packets["acq_start_subseconds"] = xr.DataArray(acq_start_subseconds, dims=["epoch"]) + packets["spare_1"] = xr.DataArray(spare_1, dims=["epoch"]) + packets["st_bias_gain_mode"] = xr.DataArray(st_bias_gain_mode, dims=["epoch"]) + packets["sw_bias_gain_mode"] = xr.DataArray(sw_bias_gain_mode, dims=["epoch"]) + packets["priority"] = xr.DataArray(priority, dims=["epoch"]) + packets["suspect"] = xr.DataArray(suspect, dims=["epoch"]) + packets["compressed"] = xr.DataArray(compressed, dims=["epoch"]) + packets["rgfo_half_spin"] = xr.DataArray(rgfo_half_spin, dims=["epoch"]) + packets["rgfo_spin_sector"] = xr.DataArray(rgfo_spin_sector, dims=["epoch"]) + packets["rgfo_esa_step"] = xr.DataArray(rgfo_esa_step, dims=["epoch"]) + packets["nso_half_spin"] = xr.DataArray(nso_half_spin, dims=["epoch"]) + packets["nso_spin_sector"] = xr.DataArray(nso_spin_sector, dims=["epoch"]) + packets["nso_esa_step"] = xr.DataArray(nso_esa_step, dims=["epoch"]) + packets["spare_2"] = xr.DataArray(spare_2, dims=["epoch"]) + packets["num_events"] = xr.DataArray(num_events, dims=["epoch"]) + packets["byte_count"] = xr.DataArray(byte_count, dims=["epoch"]) + + return packets + + +def unpack_bits(bit_structure: dict, de_data: np.ndarray) -> dict: + """ + Unpack 64-bit values into separate fields based on bit structure. + + Parameters + ---------- + bit_structure : dict + Dictionary mapping variable names to their bit lengths. + de_data : np.ndarray + 1D array of 64-bit values to unpack. + + Returns + ------- + dict + Dictionary of field_name -> unpacked values array. + """ + unpacked = {} + # Data need to be unpacked in right to left order (LSB). Eg. + # binary string - 0x03 β†’ 00000011 + # bit read order - Bit 7 β†’ 0 + # Bit 6 β†’ 0 + # Bit 5 β†’ 0 + # Bit 4 β†’ 0 + # Bit 3 β†’ 0 + # Bit 2 β†’ 0 + # Bit 1 β†’ 1 + # Bit 0 (LSB) β†’ 1 + # bits chunks - [5, 1, ...., 7, 3, 16] + # vars - ['gain', 'apd_id', ...., 'energy_step', 'priority', 'spare'] + # unpack data - [3, 0, 0, ....., 0, 0] + + # convert data into int type for bitwise operations + de_data = de_data.astype(np.uint64) + + for name, data in bit_structure.items(): + mask = (1 << data["bit_length"]) - 1 + unpacked[name] = de_data & mask + # Shift the data to the right for the next iteration + de_data = de_data >> data["bit_length"] + + return unpacked + + +def _create_dataset_coords( + packets: xr.Dataset, + apid: int, + num_priorities: int, + cdf_attrs: ImapCdfAttributes, +) -> xr.Dataset: + """ + Create the output dataset with coordinates. + + Parameters + ---------- + packets : xarray.Dataset + Combined packets with extracted header fields. + apid : int + APID for sensor type. + num_priorities : int + Number of priorities for this APID. + cdf_attrs : ImapCdfAttributes + CDF attributes manager. + + Returns + ------- + xarray.Dataset + Dataset with coordinates defined. + """ + # Get timing info from the first packet of each epoch + epoch_slice = slice(None, None, num_priorities) + + view_tab_info = ViewTabInfo( + apid=apid, + sensor=1 if apid == CODICEAPID.COD_HI_PHA else 0, + collapse_table=0, + three_d_collapsed=0, + view_id=0, + compression=CoDICECompression.LOSSLESS.value, # DE data is always lossless + ) + epochs, epochs_delta = get_codice_epoch_time( + packets["acq_start_seconds"].isel(epoch=epoch_slice), + packets["acq_start_subseconds"].isel(epoch=epoch_slice), + packets["spin_period"].isel(epoch=epoch_slice), + view_tab_info, + ) + + # Convert to numpy arrays + epochs_data = np.asarray(epochs) + epochs_delta_data = np.asarray(epochs_delta) + epoch_values = met_to_ttj2000ns(epochs_data) + + dataset = xr.Dataset( + coords={ + "epoch": ( + "epoch", + epoch_values, + cdf_attrs.get_variable_attributes("epoch", check_schema=False), + ), + "epoch_delta_minus": ( + "epoch", + epochs_delta_data, + cdf_attrs.get_variable_attributes( + "epoch_delta_minus", check_schema=False + ), + ), + "epoch_delta_plus": ( + "epoch", + epochs_delta_data, + cdf_attrs.get_variable_attributes( + "epoch_delta_plus", check_schema=False + ), + ), + "event_num": ( + "event_num", + np.arange(constants.MAX_DE_EVENTS_PER_PACKET), + cdf_attrs.get_variable_attributes("event_num", check_schema=False), + ), + "event_num_label": ( + "event_num", + np.arange(constants.MAX_DE_EVENTS_PER_PACKET).astype(str), + cdf_attrs.get_variable_attributes( + "event_num_label", check_schema=False + ), + ), + "priority": ( + "priority", + np.arange(num_priorities), + cdf_attrs.get_variable_attributes("priority", check_schema=False), + ), + "priority_label": ( + "priority", + np.arange(num_priorities).astype(str), + cdf_attrs.get_variable_attributes("priority_label", check_schema=False), + ), + } + ) + + return dataset + + +def _unpack_and_store_events( + de_data: xr.Dataset, + packets: xr.Dataset, + num_priorities: int, + bit_structure: dict, + event_fields: list[str], +) -> xr.Dataset: + """ + Unpack all event data and store directly into the dataset arrays. + + Parameters + ---------- + de_data : xarray.Dataset + Dataset to store unpacked events into (modified in place). + packets : xarray.Dataset + Combined packets with extracted header fields. + num_priorities : int + Number of priorities per epoch. + bit_structure : dict + Bit structure defining how to unpack 64-bit event values. + event_fields : list[str] + List of field names to unpack (excludes priority/spare). + + Returns + ------- + xarray.Dataset + The dataset with unpacked events stored. + """ + # Extract arrays from packets dataset + num_events_arr = packets.num_events.values + priorities_arr = packets.priority.values + event_data_arr = packets.event_data.values + + total_events = int(np.sum(num_events_arr)) + if total_events == 0: + return de_data + + num_packets = len(num_events_arr) + + # Preallocate arrays for concatenated events and their destination indices + all_event_bytes: np.ndarray = np.zeros((total_events, 8), dtype=np.uint8) + event_epoch_idx: np.ndarray = np.zeros(total_events, dtype=np.int32) + event_priority_idx: np.ndarray = np.zeros(total_events, dtype=np.int32) + event_position_idx: np.ndarray = np.zeros(total_events, dtype=np.int32) + + # Build concatenated event array and index mappings + offset = 0 + for pkt_idx in range(num_packets): + n_events = int(num_events_arr[pkt_idx]) + if n_events == 0: + continue + # Extract and byte-reverse events for LSB unpacking + pkt_bytes = np.asarray(event_data_arr[pkt_idx], dtype=np.uint8) + pkt_bytes = pkt_bytes.reshape(n_events, 8)[:, ::-1] + all_event_bytes[offset : offset + n_events] = pkt_bytes + + # Record destination indices for later array-based assignments + event_epoch_idx[offset : offset + n_events] = pkt_idx // num_priorities + event_priority_idx[offset : offset + n_events] = priorities_arr[pkt_idx] + event_position_idx[offset : offset + n_events] = np.arange(n_events) + + offset += n_events + + # Convert bytes to 64-bit values and unpack all fields at once + all_64bits = all_event_bytes.view(np.uint64).ravel() + unpacked = unpack_bits(bit_structure, all_64bits) + + # Place unpacked values directly into the dataset arrays + for field in event_fields: + de_data[field].values[ + event_epoch_idx, event_priority_idx, event_position_idx + ] = unpacked[field] + + return de_data + + +def process_de_data( + packets: xr.Dataset, + apid: int, + cdf_attrs: ImapCdfAttributes, +) -> xr.Dataset: + """ + Process direct event data into a complete CDF-ready dataset. + + Parameters + ---------- + packets : xarray.Dataset + Dataset containing the combined packets with extracted header fields. + apid : int + The APID identifying CoDICE-Lo or CoDICE-Hi. + cdf_attrs : ImapCdfAttributes + The CDF attributes manager. + + Returns + ------- + xarray.Dataset + Complete processed Direct Event dataset with coordinates and attributes. + """ + # Get configuration for this APID + config = constants.DE_DATA_PRODUCT_CONFIGURATIONS[apid] + num_priorities = config["num_priorities"] + bit_structure = config["bit_structure"] + + # Identify complete priority groups by acq_start_seconds + # Each priority group should have exactly num_priorities packets + # with the same acq_start_seconds value + acq_start_seconds = packets["acq_start_seconds"].values + unique_times, counts = np.unique(acq_start_seconds, return_counts=True) + + # Find incomplete groups (not exactly num_priorities packets) + incomplete_mask = counts != num_priorities + if np.any(incomplete_mask): + incomplete_times = unique_times[incomplete_mask] + incomplete_counts = counts[incomplete_mask] + logger.warning( + f"Found {len(incomplete_times)} incomplete priority group(s) " + f"for APID {apid}. Expected {num_priorities} packets per group. " + f"Incomplete groups at acq_start_seconds {incomplete_times.tolist()} " + f"with counts {incomplete_counts.tolist()}. Padding with zeros." + ) + + # Create a list of groups with padding if any priorities are missing + padded_groups = [] + for time, count in zip(unique_times, counts, strict=False): + # Get the packets for this group + group_ids = np.where(acq_start_seconds == time)[0] + group = packets.isel(epoch=group_ids) + if count < num_priorities: + # Find missing priorities + existing_priorities = set(group["priority"].values) + missing_priorities = sorted( + set(range(num_priorities)) - existing_priorities + ) + num_missing_priorities = len(missing_priorities) + # Use first packet as a template and expand along the epoch dimension + # for the number of missing priorities. + pad_packet = group.isel(epoch=[0] * num_missing_priorities).copy() + # Set padding values to zero + pad_packet["num_events"].values = np.full(num_missing_priorities, 0) + pad_packet["byte_count"].values = np.full(num_missing_priorities, 0) + pad_packet["priority"].values = missing_priorities + # Set event_data to empty object arrays for padding packets + for i in range(num_missing_priorities): + pad_packet["event_data"].data[i] = np.array([], dtype=np.uint8) + # Concatenate the existing priorities with the zeros priority groups + group = xr.concat([group, pad_packet], dim="epoch") + # Sort by priority + sort_idx = np.argsort(group["priority"].values) + group = group.isel(epoch=sort_idx) + elif count > num_priorities: + # TODO is this possible? + # Sort by priority + sort_idx = np.argsort(group["priority"].values) + group = group.isel(epoch=sort_idx) + # Keep only the first num_priorities packets + group = group.isel(epoch=slice(0, num_priorities)) + padded_groups.append(group) + + # Concatenate all groups + packets = xr.concat(padded_groups, dim="epoch") + + # Calculate number of epochs + num_epochs = len(unique_times) + + # Create dataset with coordinates + de_data = _create_dataset_coords(packets, apid, num_priorities, cdf_attrs) + + # Set global attributes based on APID + if apid == CODICEAPID.COD_LO_PHA: + de_data.attrs = cdf_attrs.get_global_attributes( + "imap_codice_l1a_lo-direct-events" + ) + de_data["k_factor"] = xr.DataArray( + np.array([constants.K_FACTOR]), + dims=["k_factor"], + attrs=cdf_attrs.get_variable_attributes("k_factor", check_schema=False), + ) + else: + de_data.attrs = cdf_attrs.get_global_attributes( + "imap_codice_l1a_hi-direct-events" + ) + + # Add per-epoch metadata from first packet of each epoch + epoch_slice = slice(None, None, num_priorities) + for var in [ + "sw_bias_gain_mode", + "st_bias_gain_mode", + "rgfo_esa_step", + "rgfo_half_spin", + "rgfo_spin_sector", + "nso_esa_step", + "nso_half_spin", + "nso_spin_sector", + ]: + de_data[var] = xr.DataArray( + packets[var].isel(epoch=epoch_slice).values, + dims=["epoch"], + attrs=cdf_attrs.get_variable_attributes(var), + ) + + # Initialize 3D event data arrays with fill values + event_fields = [f for f in bit_structure if f not in ["priority"]] + for field in event_fields: + info = bit_structure[field] + attrs = apply_replacements_to_attrs( + cdf_attrs.get_variable_attributes("de_3d_attrs"), + {"num_digits": len(str(info["fillval"])), "valid_max": info["fillval"]}, + ) + de_data[field] = xr.DataArray( + np.full( + (num_epochs, num_priorities, constants.MAX_DE_EVENTS_PER_PACKET), + info["fillval"], + dtype=info["dtype"], + ), + dims=["epoch", "priority", "event_num"], + attrs=attrs, + ) + + # Initialize 2D per-priority metadata arrays + for var in ["num_events", "data_quality"]: + de_data[var] = xr.DataArray( + np.full((num_epochs, num_priorities), 65535, dtype=np.uint16), + dims=["epoch", "priority"], + attrs=cdf_attrs.get_variable_attributes("de_2d_attrs"), + ) + # Reshape packet arrays for validation and assignment + priorities_2d = packets.priority.values.reshape(num_epochs, num_priorities) + num_events_2d = packets.num_events.values.reshape(num_epochs, num_priorities) + data_quality_2d = packets.suspect.values.reshape(num_epochs, num_priorities) + + # Validate each epoch has all unique priorities + unique_counts = np.array([len(np.unique(row)) for row in priorities_2d]) + if np.any(unique_counts != num_priorities): + bad_epoch = np.argmax(unique_counts != num_priorities) + raise ValueError( + f"Priority array for epoch {bad_epoch} contains " + f"non-unique values: {priorities_2d[bad_epoch]}" + ) + + # Assign num_events and data_quality using priorities as column indices + epoch_idx = np.arange(num_epochs)[:, np.newaxis] + de_data["num_events"].values[epoch_idx, priorities_2d] = num_events_2d + de_data["data_quality"].values[epoch_idx, priorities_2d] = data_quality_2d + + # Unpack all events and store directly into dataset arrays + de_data = _unpack_and_store_events( + de_data, + packets, + num_priorities, + bit_structure, + event_fields, + ) + + return de_data + + +def l1a_direct_event(unpacked_dataset: xr.Dataset, apid: int) -> xr.Dataset: + """ + Process CoDICE L1A Direct Event data. + + Parameters + ---------- + unpacked_dataset : xarray.Dataset + Input L1A Direct Event dataset. + apid : int + APID to process. + + Returns + ------- + xarray.Dataset + Processed L1A Direct Event dataset. + """ + # Combine segmented packets and extract header fields + packets = combine_segmented_packets( + unpacked_dataset, binary_field_name="event_data" + ) + + packets = extract_initial_items_from_combined_packets(packets) + + # Gather the CDF attributes + cdf_attrs = ImapCdfAttributes() + cdf_attrs.add_instrument_global_attrs("codice") + cdf_attrs.add_instrument_variable_attrs("codice", "l1a") + + # Process packets into complete CDF-ready dataset + return process_de_data(packets, apid, cdf_attrs) diff --git a/imap_processing/codice/codice_l1a_hi_counters_aggregated.py b/imap_processing/codice/codice_l1a_hi_counters_aggregated.py new file mode 100644 index 0000000000..b694bab4fc --- /dev/null +++ b/imap_processing/codice/codice_l1a_hi_counters_aggregated.py @@ -0,0 +1,166 @@ +"""CoDICE L1A Hi Counters aggregated processing functions.""" + +import logging +from pathlib import Path + +import numpy as np +import xarray as xr + +from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes +from imap_processing.codice import constants +from imap_processing.codice.decompress import decompress +from imap_processing.codice.utils import ( + CoDICECompression, + get_codice_epoch_time, + get_counters_aggregated_pattern, + get_view_tab_obj, +) +from imap_processing.spice.time import met_to_ttj2000ns + +logger = logging.getLogger(__name__) + + +def l1a_hi_counters_aggregated( + group_ds: xr.Dataset, + lut_file: Path, + table_id: str, + view_id: int, + apid: int, + plan_id: int, + plan_step: int, +) -> xr.Dataset: + """ + Process a single table-ID group of CoDICE Hi Counters Aggregated L1A data. + + Parameters + ---------- + group_ds : xarray.Dataset + Dataset filtered to a single table_id. + lut_file : Path + Path to the LUT file for processing. + table_id : str + The table ID for this group. + view_id : int + View ID (uniform across the product). + apid : int + APID (uniform across the product). + plan_id : int + Plan ID (uniform across the product). + plan_step : int + Plan step (uniform across the product). + + Returns + ------- + xarray.Dataset + Processed L1A dataset for input table-ID group. + """ + logger.info( + f"Processing species with - APID: {apid} / 0x{apid:X}, View ID: {view_id}, " + f"Table ID: {table_id}, Plan ID: {plan_id}, Plan Step: {plan_step}" + ) + # ========== Get LUT Data =========== + sci_lut_data, view_tab_obj = get_view_tab_obj(lut_file, table_id, view_id, apid) + + if view_tab_obj.sensor != 1: + raise ValueError("Unsupported sensor ID for Hi processing.") + + # ========= Decompress and Reshape Data =========== + logical_source_id = "imap_codice_l1a_hi-counters-aggregated" + # Counters is little bit different in how CDF variables are derived. + # For singles, CDF variables are coming from 'product' tab. But for + # counters aggregated, it's coming from 'collapsed' tab in JSON LUT. + # In addition, for Lo, we include other inactive variables as zeros + # in the CDF. For Hi, all variables except 'reserved{x}' are active, + # so reserved variables are excluded unless it changes. This change + # will affect CoDICE team and here. + non_reserved_variables = get_counters_aggregated_pattern( + sci_lut_data, view_tab_obj.sensor, view_tab_obj.collapse_table + ).keys() + + # For Hi aggregated, the spin sector is 1. Therefore, only use size + # of active variables to reshape decompressed data. + num_variables = len(non_reserved_variables) + # Decompress data using byte count information from decommed data + binary_data_list = group_ds["data"].values + byte_count_list = group_ds["byte_count"].values + + compression_algorithm = CoDICECompression(view_tab_obj.compression) + + # The decompressed data in the shape of (epoch, n). Then reshape later. + decompressed_data = [ + decompress( + packet_data[:byte_count], + compression_algorithm, + ) + for (packet_data, byte_count) in zip( + binary_data_list, byte_count_list, strict=False + ) + ] + counters_data = np.array(decompressed_data, dtype=np.uint32).reshape( + -1, num_variables + ) + # Convert counters data to float + counters_data = counters_data.astype(np.float64) + + # ========= Get Epoch Time Data =========== + # Epoch center time and delta + epoch_center, deltas = get_codice_epoch_time( + group_ds["acq_start_seconds"].values, + group_ds["acq_start_subseconds"].values, + group_ds["spin_period"].values, + view_tab_obj, + ) + + # ========== Initialize CDF Dataset with Coordinates =========== + cdf_attrs = ImapCdfAttributes() + cdf_attrs.add_instrument_global_attrs("codice") + cdf_attrs.add_instrument_variable_attrs("codice", "l1a") + + l1a_dataset = xr.Dataset( + coords={ + "epoch": xr.DataArray( + met_to_ttj2000ns(epoch_center), + dims=("epoch",), + attrs=cdf_attrs.get_variable_attributes("epoch", check_schema=False), + ), + "epoch_delta_minus": xr.DataArray( + deltas, + dims=("epoch",), + attrs=cdf_attrs.get_variable_attributes( + "epoch_delta_minus", check_schema=False + ), + ), + "epoch_delta_plus": xr.DataArray( + deltas, + dims=("epoch",), + attrs=cdf_attrs.get_variable_attributes( + "epoch_delta_plus", check_schema=False + ), + ), + }, + attrs=cdf_attrs.get_global_attributes(logical_source_id), + ) + + # Add first few unique variables + l1a_dataset["spin_period"] = xr.DataArray( + group_ds["spin_period"].values * constants.SPIN_PERIOD_CONVERSION, + dims=("epoch",), + attrs=cdf_attrs.get_variable_attributes("spin_period"), + ) + l1a_dataset["data_quality"] = xr.DataArray( + group_ds["suspect"].values, + dims=("epoch",), + attrs=cdf_attrs.get_variable_attributes("data_quality"), + ) + + # Finally, add data variables + for idx, variable in enumerate(non_reserved_variables): + # We don't store reserved variables in CDF + attrs = cdf_attrs.get_variable_attributes(f"hi-{variable}") + + l1a_dataset[variable] = xr.DataArray( + counters_data[:, idx], dims=("epoch",), attrs=attrs + ) + # No uncertainty needed for Hi counters data + + return l1a_dataset diff --git a/imap_processing/codice/codice_l1a_hi_counters_singles.py b/imap_processing/codice/codice_l1a_hi_counters_singles.py new file mode 100644 index 0000000000..a33288ce47 --- /dev/null +++ b/imap_processing/codice/codice_l1a_hi_counters_singles.py @@ -0,0 +1,173 @@ +"""CoDICE L1A Hi Singles processing functions.""" + +import logging +from pathlib import Path + +import numpy as np +import xarray as xr + +from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes +from imap_processing.codice import constants +from imap_processing.codice.decompress import decompress +from imap_processing.codice.utils import ( + CoDICECompression, + get_codice_epoch_time, + get_collapse_pattern_shape, + get_view_tab_obj, +) +from imap_processing.spice.time import met_to_ttj2000ns + +logger = logging.getLogger(__name__) + + +def l1a_hi_counters_singles( + group_ds: xr.Dataset, + lut_file: Path, + table_id: str, + view_id: int, + apid: int, + plan_id: int, + plan_step: int, +) -> xr.Dataset: + """ + Process a single table-ID group of CoDICE Hi Counters Singles L1A data. + + Parameters + ---------- + group_ds : xarray.Dataset + Dataset filtered to a single table_id. + lut_file : Path + Path to the LUT file for processing. + table_id : str + The table ID for this group. + view_id : int + View ID (uniform across the product). + apid : int + APID (uniform across the product). + plan_id : int + Plan ID (uniform across the product). + plan_step : int + Plan step (uniform across the product). + + Returns + ------- + xarray.Dataset + Processed L1A dataset for input table-ID group. + """ + logger.info( + f"Processing species with - APID: {apid} / 0x{apid:X}, View ID: {view_id}, " + f"Table ID: {table_id}, Plan ID: {plan_id}, Plan Step: {plan_step}" + ) + # ========== Get LUT Data =========== + sci_lut_data, view_tab_obj = get_view_tab_obj(lut_file, table_id, view_id, apid) + + if view_tab_obj.sensor != 1: + raise ValueError("Unsupported sensor ID for Hi processing.") + + # ========= Decompress and Reshape Data =========== + logical_source_id = "imap_codice_l1a_hi-counters-singles" + + # Counters is little bit different in how CDF variables are derived. + # For singles, CDF variables are coming from 'product' tab. But for + # counters aggregated, it's coming from 'collapsed' tab in JSON LUT. + variable_names = sci_lut_data["data_product_hi_tab"]["0"]["counters-singles"].keys() + collapse_shape = get_collapse_pattern_shape( + sci_lut_data, view_tab_obj.sensor, view_tab_obj.collapse_table + ) + # Use inst_az dimension to reshape decompressed data since + # spin sector size is 1. + inst_az = collapse_shape[1] + + compression_algorithm = CoDICECompression(view_tab_obj.compression) + # Decompress data using byte count information from decommed data + binary_data_list = group_ds["data"].values + byte_count_list = group_ds["byte_count"].values + + # The decompressed data in the shape of (epoch, n). Then reshape later. + decompressed_data = [ + decompress( + packet_data[:byte_count], + compression_algorithm, + ) + for (packet_data, byte_count) in zip( + binary_data_list, byte_count_list, strict=False + ) + ] + counters_data = np.array(decompressed_data, dtype=np.uint32).reshape( + -1, len(variable_names), inst_az + ) + # Convert counters data to float + counters_data = counters_data.astype(np.float64) + # ========= Get Epoch Time Data =========== + # Epoch center time and delta + epoch_center, deltas = get_codice_epoch_time( + group_ds["acq_start_seconds"].values, + group_ds["acq_start_subseconds"].values, + group_ds["spin_period"].values, + view_tab_obj, + ) + + # ========== Initialize CDF Dataset with Coordinates =========== + cdf_attrs = ImapCdfAttributes() + cdf_attrs.add_instrument_global_attrs("codice") + cdf_attrs.add_instrument_variable_attrs("codice", "l1a") + + l1a_dataset = xr.Dataset( + coords={ + "epoch": xr.DataArray( + met_to_ttj2000ns(epoch_center), + dims=("epoch",), + attrs=cdf_attrs.get_variable_attributes("epoch", check_schema=False), + ), + "epoch_delta_minus": xr.DataArray( + deltas, + dims=("epoch",), + attrs=cdf_attrs.get_variable_attributes( + "epoch_delta_minus", check_schema=False + ), + ), + "epoch_delta_plus": xr.DataArray( + deltas, + dims=("epoch",), + attrs=cdf_attrs.get_variable_attributes( + "epoch_delta_plus", check_schema=False + ), + ), + "inst_az": xr.DataArray( + np.arange(inst_az, dtype=np.uint8), + dims=("inst_az",), + attrs=cdf_attrs.get_variable_attributes("inst_az", check_schema=False), + ), + "inst_az_label": xr.DataArray( + np.arange(inst_az, dtype=np.uint8).astype(str), + dims=("inst_az",), + attrs=cdf_attrs.get_variable_attributes( + "inst_az_label", check_schema=False + ), + ), + }, + attrs=cdf_attrs.get_global_attributes(logical_source_id), + ) + + # Add first few unique variables + l1a_dataset["spin_period"] = xr.DataArray( + group_ds["spin_period"].values * constants.SPIN_PERIOD_CONVERSION, + dims=("epoch",), + attrs=cdf_attrs.get_variable_attributes("spin_period"), + ) + l1a_dataset["data_quality"] = xr.DataArray( + group_ds["suspect"].values, + dims=("epoch",), + attrs=cdf_attrs.get_variable_attributes("data_quality"), + ) + + # Finally, add species data variables and their uncertainties + for idx, species in enumerate(variable_names): + l1a_dataset[species] = xr.DataArray( + counters_data[:, idx], + dims=("epoch", "inst_az"), + attrs=cdf_attrs.get_variable_attributes(f"hi-{species}"), + ) + # No uncertainty needed for Hi counters data + + return l1a_dataset diff --git a/imap_processing/codice/codice_l1a_hi_omni.py b/imap_processing/codice/codice_l1a_hi_omni.py new file mode 100644 index 0000000000..a2bd2e1833 --- /dev/null +++ b/imap_processing/codice/codice_l1a_hi_omni.py @@ -0,0 +1,273 @@ +"""CoDICE Hi Omni L1A processing functions.""" + +import logging +from pathlib import Path + +import numpy as np +import xarray as xr + +from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes +from imap_processing.codice import constants +from imap_processing.codice.decompress import decompress +from imap_processing.codice.utils import ( + CoDICECompression, + apply_replacements_to_attrs, + get_codice_epoch_time, + get_energy_info, + get_view_tab_obj, +) +from imap_processing.spice.time import met_to_ttj2000ns + +logger = logging.getLogger(__name__) + + +def l1a_hi_omni( + group_ds: xr.Dataset, + lut_file: Path, + table_id: str, + view_id: int, + apid: int, + plan_id: int, + plan_step: int, +) -> xr.Dataset: + """ + Process a single table-ID group of CoDICE Hi Omni L1A data. + + Parameters + ---------- + group_ds : xarray.Dataset + Dataset filtered to a single table_id. + lut_file : Path + Path to the LUT file for processing. + table_id : str + The table ID for this group. + view_id : int + View ID (uniform across the product). + apid : int + APID (uniform across the product). + plan_id : int + Plan ID (uniform across the product). + plan_step : int + Plan step (uniform across the product). + + Returns + ------- + xarray.Dataset + Processed L1A dataset for input table-ID group. + """ + logger.info( + f"Processing species with - APID: {apid} / 0x{apid:X}, View ID: {view_id}, " + f"Table ID: {table_id}, Plan ID: {plan_id}, Plan Step: {plan_step}" + ) + + # ========== Get LUT Data =========== + sci_lut_data, view_tab_obj = get_view_tab_obj(lut_file, table_id, view_id, apid) + + if view_tab_obj.sensor != 1: + raise ValueError("Unsupported sensor ID for Hi processing.") + + # ========= Decompress and Reshape Data =========== + species_data = sci_lut_data["data_product_hi_tab"]["0"]["omni"] + species_names = species_data.keys() + logical_source_id = "imap_codice_l1a_hi-omni" + + compression_algorithm = CoDICECompression(view_tab_obj.compression) + # Decompress data using byte count information from decommed data + binary_data_list = group_ds["data"].values + byte_count_list = group_ds["byte_count"].values + + # The decompressed data in the shape of (epoch, n). Then reshape later. + decompressed_data = [ + decompress( + packet_data[:byte_count], + compression_algorithm, + ) + for (packet_data, byte_count) in zip( + binary_data_list, byte_count_list, strict=False + ) + ] + + # ========= Get Epoch Time Data =========== + # Epoch center time and delta + epoch_center, deltas = get_codice_epoch_time( + group_ds["acq_start_seconds"].values, + group_ds["acq_start_subseconds"].values, + group_ds["spin_period"].values, + view_tab_obj, + ) + + three_d_collapsed = view_tab_obj.three_d_collapsed + num_packets = len(binary_data_list) + + # Repeat deltas n_spins times to match new num_epochs + n_spins = int(16 / three_d_collapsed) + repeated_deltas = np.tile(deltas, n_spins) + # Calculate center of new epoch times using this + # formula: + # epoch_time = epoch_center + (i * delta) + # where i = 0 to n_spins. + # We are repeating each center time 'n_spins' times to + # get new epochs and then multiply by factor. Final and new epoch shape + # is (num_packets * n_spins). It's in seconds. + # TODO: why multiply by 2? + epoch_times = ( + np.repeat(epoch_center, n_spins) + + np.tile(np.arange(n_spins), num_packets) + * np.repeat(deltas, n_spins) + / 1e9 + * 2 + ) + + # ========== Initialize CDF Dataset with Coordinates =========== + cdf_attrs = ImapCdfAttributes() + cdf_attrs.add_instrument_global_attrs("codice") + cdf_attrs.add_instrument_variable_attrs("codice", "l1a") + + l1a_dataset = xr.Dataset( + coords={ + "epoch": xr.DataArray( + met_to_ttj2000ns(epoch_times), + dims=("epoch",), + attrs=cdf_attrs.get_variable_attributes("epoch", check_schema=False), + ), + "epoch_delta_minus": xr.DataArray( + repeated_deltas, + dims=("epoch",), + attrs=cdf_attrs.get_variable_attributes( + "epoch_delta_minus", check_schema=False + ), + ), + "epoch_delta_plus": xr.DataArray( + repeated_deltas, + dims=("epoch",), + attrs=cdf_attrs.get_variable_attributes( + "epoch_delta_plus", check_schema=False + ), + ), + }, + attrs=cdf_attrs.get_global_attributes(logical_source_id), + ) + + # Reshape decompressed data to: + # decompressed_data -> (9, 480) + # Then we will parse 480 data into species below for looping. + decompressed_data = np.array(decompressed_data, dtype=np.uint32).reshape( + num_packets, n_spins * 120 + ) + + # Use chunks of (energy_x) to put data in its energy bins as done below. + # Eg. [15, 15, 15, 18, 18, 15, 18, 5, 1] + # where each number is energy dimension for species 'x'. + species_chunk_sizes = [ + len(species_data[species]["min_energy"]) for species in species_names + ] + start_idx = 0 + for index, (species_name, data) in enumerate(species_data.items()): + # Add coordinate for 'energy_{species_name}' + centers, energy_minus, energy_plus = get_energy_info(data) + energy_attrs = cdf_attrs.get_variable_attributes( + "hi-energy-attrs", check_schema=False + ) + energy_attrs = apply_replacements_to_attrs( + energy_attrs, {"species": species_name} + ) + l1a_dataset = l1a_dataset.assign_coords( + { + f"energy_{species_name}": xr.DataArray( + np.array(centers), + dims=(f"energy_{species_name}",), + attrs=energy_attrs, + ) + } + ) + species_label_attrs = cdf_attrs.get_variable_attributes( + "energy_species_label", check_schema=False + ) + species_label_attrs = apply_replacements_to_attrs( + species_label_attrs, {"species": species_name} + ) + l1a_dataset[f"energy_{species_name}_label"] = xr.DataArray( + np.array(centers).astype("str"), + dims=(f"energy_{species_name}"), + attrs=species_label_attrs, + ) + # Add energy minus variables + delta_attrs = cdf_attrs.get_variable_attributes("hi-energy-delta-attrs") + delta_attrs = apply_replacements_to_attrs( + delta_attrs, {"species": species_name, "operation": "minus"} + ) + l1a_dataset[f"energy_{species_name}_minus"] = xr.DataArray( + energy_minus, dims=(f"energy_{species_name}",), attrs=delta_attrs + ) + # Add energy plus variable + delta_attrs = apply_replacements_to_attrs( + delta_attrs, {"species": species_name, "operation": "plus"} + ) + l1a_dataset[f"energy_{species_name}_plus"] = xr.DataArray( + energy_plus, dims=(f"energy_{species_name}",), attrs=delta_attrs + ) + + # Now, we put species data into its energy bins using indices like this: + # Eg. species h's 4 spins data are in these indices: + # All h energy data of first spin = [0,4,8,12,… 56]. + # All h energy data of second spin = [1,5,9,…,57]. + # All h energy data of third spin = [2,6,10,…,58]. + # All h energy data of fourth spin = [3,7,11,…,59]. + # In other words, H - [0 - 59] contains 4 spins data of h's 15 energy bins + # and repeated this pattern for other species in order. + # Eg. He3 - [60 - 119] and so on. + + chunk_size = species_chunk_sizes[index] + # Now parse the decompressed data into species as mentioned in above comment + # using start and end indices. + # End indices is start + (chunk size * n_spins) + end_idx = start_idx + chunk_size * n_spins + # Get specie's data by (num_epochs, start_idx:end_idx) + # Eg. (9, 60) for H + species_data = decompressed_data[:, start_idx:end_idx] + # Reshape the data to (num_epochs, species_chunk_size, n_spins) to begin + # getting data into it's final state. + # Eg. (9, 15, 4) + species_data = species_data.reshape(-1, chunk_size, n_spins) + # Then transpose into (num_epochs, n_spins, species_chunk_size) and reshape + # into (num_epochs * n_spins, species_chunk_size) to get final state. + # Eg. (36, 15) + species_data = species_data.transpose(0, 2, 1).reshape(-1, chunk_size) + species_attrs = cdf_attrs.get_variable_attributes("hi-species-attrs") + species_attrs = apply_replacements_to_attrs( + species_attrs, {"species": species_name} + ) + # Convert to float + species_data = species_data.astype(np.float64) + l1a_dataset[species_name] = xr.DataArray( + species_data, + dims=("epoch", f"energy_{species_name}"), + attrs=species_attrs, + ) + species_unc_attrs = cdf_attrs.get_variable_attributes("hi-species-unc-attrs") + species_unc_attrs = apply_replacements_to_attrs( + species_unc_attrs, {"species": species_name} + ) + l1a_dataset[f"unc_{species_name}"] = xr.DataArray( + np.sqrt(species_data), + dims=("epoch", f"energy_{species_name}"), + attrs=species_unc_attrs, + ) + # Increment start index + start_idx = end_idx + + # ========= Add Additional Variables =========== + # Repeat spin_period and data_quality to match new epoch shape (num_epochs) + l1a_dataset["spin_period"] = xr.DataArray( + np.repeat(group_ds["spin_period"].values, n_spins) + * constants.SPIN_PERIOD_CONVERSION, + dims=("epoch",), + attrs=cdf_attrs.get_variable_attributes("spin_period"), + ) + l1a_dataset["data_quality"] = xr.DataArray( + np.repeat(group_ds["suspect"].values, n_spins), + dims=("epoch",), + attrs=cdf_attrs.get_variable_attributes("data_quality"), + ) + + return l1a_dataset diff --git a/imap_processing/codice/codice_l1a_hi_priority.py b/imap_processing/codice/codice_l1a_hi_priority.py new file mode 100644 index 0000000000..f990aa6932 --- /dev/null +++ b/imap_processing/codice/codice_l1a_hi_priority.py @@ -0,0 +1,180 @@ +"""CoDICE L1A Hi priority processing functions.""" + +import logging +from pathlib import Path + +import numpy as np +import xarray as xr + +from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes +from imap_processing.codice import constants +from imap_processing.codice.decompress import decompress +from imap_processing.codice.utils import ( + CoDICECompression, + get_codice_epoch_time, + get_collapse_pattern_shape, + get_view_tab_obj, +) +from imap_processing.spice.time import met_to_ttj2000ns + +logger = logging.getLogger(__name__) + + +def l1a_hi_priority( + group_ds: xr.Dataset, + lut_file: Path, + table_id: str, + view_id: int, + apid: int, + plan_id: int, + plan_step: int, +) -> xr.Dataset: + """ + Process a single table-ID group of CoDICE Hi Priority L1A data. + + Parameters + ---------- + group_ds : xarray.Dataset + Dataset filtered to a single table_id. + lut_file : Path + Path to the LUT file for processing. + table_id : str + The table ID for this group. + view_id : int + View ID (uniform across the product). + apid : int + APID (uniform across the product). + plan_id : int + Plan ID (uniform across the product). + plan_step : int + Plan step (uniform across the product). + + Returns + ------- + xarray.Dataset + Processed L1A dataset for input table-ID group. + """ + logger.info( + f"Processing species with - APID: {apid} / 0x{apid:X}, View ID: {view_id}, " + f"Table ID: {table_id}, Plan ID: {plan_id}, Plan Step: {plan_step}" + ) + + # ========== Get LUT Data =========== + sci_lut_data, view_tab_obj = get_view_tab_obj(lut_file, table_id, view_id, apid) + + if view_tab_obj.sensor != 1: + raise ValueError("Unsupported sensor ID for Hi priority processing.") + + # ========= Get Epoch Time Data =========== + # Epoch center time and delta + epoch_center, deltas = get_codice_epoch_time( + group_ds["acq_start_seconds"].values, + group_ds["acq_start_subseconds"].values, + group_ds["spin_period"].values, + view_tab_obj, + ) + + # ========= Decompress and Calculate Reshape information =========== + species_data = sci_lut_data["data_product_hi_tab"]["0"]["priority"] + species_names = species_data.keys() + logical_source_id = "imap_codice_l1a_hi-priority" + compression_algorithm = CoDICECompression(view_tab_obj.compression) + # Decompress data using byte count information from decommed data + binary_data_list = group_ds["data"].values + byte_count_list = group_ds["byte_count"].values + packet_version = group_ds["packet_version"].values[0] + # The decompressed data in the shape of (epoch, n). Then reshape later. + decompressed_data = [ + np.frombuffer( + bytes( + decompress( + packet_data[:byte_count], + compression_algorithm, + ) + ), + dtype=">u4", + # '>' means big-endian, 'u4' means unsigned 4-byte integer (uint32) + ) + # For newer packet versions, the decompressed data needs to be converted to + # uint32 + if packet_version > 1 + else decompress( + packet_data[:byte_count], + compression_algorithm, + ) + for (packet_data, byte_count) in zip( + binary_data_list, byte_count_list, strict=False + ) + ] + + num_packets = len(binary_data_list) + + # Reshape decompressed data to in below for loop: + # (num_packets, collapse_shape[1](inst_az)) + collapse_shape = get_collapse_pattern_shape( + sci_lut_data, + view_tab_obj.sensor, + view_tab_obj.collapse_table, + ) + species_data = np.array(decompressed_data, dtype=np.uint32).reshape( + num_packets, collapse_shape[1] + ) + species_data = species_data.astype(np.float64) + # ========== Create CDF Dataset with Metadata =========== + cdf_attrs = ImapCdfAttributes() + cdf_attrs.add_instrument_global_attrs("codice") + cdf_attrs.add_instrument_variable_attrs("codice", "l1a") + + l1a_dataset = xr.Dataset( + coords={ + "epoch": xr.DataArray( + met_to_ttj2000ns(epoch_center), + dims=("epoch",), + attrs=cdf_attrs.get_variable_attributes("epoch", check_schema=False), + ), + "epoch_delta_minus": xr.DataArray( + deltas, + dims=("epoch",), + attrs=cdf_attrs.get_variable_attributes( + "epoch_delta_minus", check_schema=False + ), + ), + "epoch_delta_plus": xr.DataArray( + deltas, + dims=("epoch",), + attrs=cdf_attrs.get_variable_attributes( + "epoch_delta_plus", check_schema=False + ), + ), + }, + attrs=cdf_attrs.get_global_attributes(logical_source_id), + ) + # Add first few unique variables + l1a_dataset["spin_period"] = xr.DataArray( + group_ds["spin_period"].values * constants.SPIN_PERIOD_CONVERSION, + dims=("epoch",), + attrs=cdf_attrs.get_variable_attributes("spin_period"), + ) + l1a_dataset["data_quality"] = xr.DataArray( + group_ds["suspect"].values, + dims=("epoch",), + attrs=cdf_attrs.get_variable_attributes("data_quality"), + ) + + # Finally, add species data variables and their uncertainties + for idx, species in enumerate(species_names): + l1a_dataset[species] = xr.DataArray( + species_data[ + :, + idx, + ], + dims=("epoch",), + attrs=cdf_attrs.get_variable_attributes(species), + ) + l1a_dataset[f"unc_{species}"] = xr.DataArray( + np.sqrt(l1a_dataset[species].values), + dims=("epoch",), + attrs=cdf_attrs.get_variable_attributes(species), + ) + + return l1a_dataset diff --git a/imap_processing/codice/codice_l1a_hi_sectored.py b/imap_processing/codice/codice_l1a_hi_sectored.py new file mode 100644 index 0000000000..b4fce45c28 --- /dev/null +++ b/imap_processing/codice/codice_l1a_hi_sectored.py @@ -0,0 +1,284 @@ +"""CoDICE Hi Sectored L1A processing functions.""" + +import logging +from pathlib import Path + +import numpy as np +import xarray as xr + +from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes +from imap_processing.codice import constants +from imap_processing.codice.decompress import decompress +from imap_processing.codice.utils import ( + CoDICECompression, + apply_replacements_to_attrs, + get_codice_epoch_time, + get_collapse_pattern_shape, + get_energy_info, + get_view_tab_obj, +) +from imap_processing.spice.time import met_to_ttj2000ns + +logger = logging.getLogger(__name__) + + +def l1a_hi_sectored( + group_ds: xr.Dataset, + lut_file: Path, + table_id: str, + view_id: int, + apid: int, + plan_id: int, + plan_step: int, +) -> xr.Dataset: + """ + Process a single table-ID group of CoDICE Hi Sectored L1A data. + + Parameters + ---------- + group_ds : xarray.Dataset + Dataset filtered to a single table_id. + lut_file : Path + Path to the LUT file for processing. + table_id : str + The table ID for this group. + view_id : int + View ID (uniform across the product). + apid : int + APID (uniform across the product). + plan_id : int + Plan ID (uniform across the product). + plan_step : int + Plan step (uniform across the product). + + Returns + ------- + xarray.Dataset + Processed L1A dataset for input table-ID group. + """ + logger.info( + f"Processing species with - APID: {apid} / 0x{apid:X}, View ID: {view_id}, " + f"Table ID: {table_id}, Plan ID: {plan_id}, Plan Step: {plan_step}" + ) + + # ========== Get LUT Data =========== + sci_lut_data, view_tab_obj = get_view_tab_obj(lut_file, table_id, view_id, apid) + + if view_tab_obj.sensor != 1: + raise ValueError("Unsupported sensor ID for Hi Sectored processing.") + + # ========= Get Epoch Time Data =========== + # Epoch center time and delta + epoch_center, deltas = get_codice_epoch_time( + group_ds["acq_start_seconds"].values, + group_ds["acq_start_subseconds"].values, + group_ds["spin_period"].values, + view_tab_obj, + ) + + # ========= Decompress and Calculate Reshape information =========== + species_data = sci_lut_data["data_product_hi_tab"]["0"]["sectored"] + species_names = species_data.keys() + logical_source_id = "imap_codice_l1a_hi-sectored" + + compression_algorithm = CoDICECompression(view_tab_obj.compression) + # Decompress data using byte count information from decommed data + binary_data_list = group_ds["data"].values + byte_count_list = group_ds["byte_count"].values + + # The decompressed data in the shape of (epoch, n). Then reshape later. + decompressed_data = [ + decompress( + packet_data[:byte_count], + compression_algorithm, + ) + for (packet_data, byte_count) in zip( + binary_data_list, byte_count_list, strict=False + ) + ] + + num_packets = len(binary_data_list) + + # Use chunks of (energy_x) to put data in its energy bins as done below. + # Eg. [15, 15, 15, 18, 18, 15, 18, 5, 1] + # where each number is energy dimension for species 'x'. + species_chunk_sizes = [ + len(species_data[species]["min_energy"]) for species in species_names + ] + + # Reshape decompressed data to in below for loop: + # (num_packets, num_species, energy_bins, spin_sector, inst_az) + num_species = len(species_names) + energy_bins = 8 + collapse_shape = get_collapse_pattern_shape( + sci_lut_data, + view_tab_obj.sensor, + view_tab_obj.collapse_table, + ) + if np.unique(species_chunk_sizes) != [energy_bins]: + raise ValueError("Expected energy bins to be 8 for Hi Sectored data.") + + # Calculate collapsed size + decompressed_data = np.array(decompressed_data, dtype=np.uint32).reshape( + num_packets, num_species, energy_bins, *collapse_shape + ) + + # ========== Create Dataset =========== + cdf_attrs = ImapCdfAttributes() + cdf_attrs.add_instrument_global_attrs("codice") + cdf_attrs.add_instrument_variable_attrs("codice", "l1a") + + l1a_dataset = xr.Dataset( + coords={ + "epoch": xr.DataArray( + met_to_ttj2000ns(epoch_center), + dims=("epoch",), + attrs=cdf_attrs.get_variable_attributes("epoch", check_schema=False), + ), + "epoch_delta_minus": xr.DataArray( + deltas, + dims=("epoch",), + attrs=cdf_attrs.get_variable_attributes( + "epoch_delta_minus", check_schema=False + ), + ), + "epoch_delta_plus": xr.DataArray( + deltas, + dims=("epoch",), + attrs=cdf_attrs.get_variable_attributes( + "epoch_delta_plus", check_schema=False + ), + ), + "spin_sector": xr.DataArray( + np.arange(collapse_shape[0]), + dims=("spin_sector",), + attrs=cdf_attrs.get_variable_attributes( + "spin_sector", check_schema=False + ), + ), + "spin_sector_label": xr.DataArray( + np.arange(collapse_shape[0]).astype(str), + dims=("spin_sector",), + attrs=cdf_attrs.get_variable_attributes( + "spin_sector_label", check_schema=False + ), + ), + "inst_az": xr.DataArray( + np.arange(collapse_shape[1]), + dims=("inst_az",), + attrs=cdf_attrs.get_variable_attributes("inst_az", check_schema=False), + ), + "inst_az_label": xr.DataArray( + np.arange(collapse_shape[1]).astype(str), + dims=("inst_az",), + attrs=cdf_attrs.get_variable_attributes( + "inst_az_label", check_schema=False + ), + ), + }, + attrs=cdf_attrs.get_global_attributes(logical_source_id), + ) + + # Final data shape of each species is (epoch, energy_h, spin_sector, inst_az) + for species_index, (species_name, data) in enumerate(species_data.items()): + # Add coordinate for 'energy_{species_name}' + energy_centers, energy_minus, energy_plus = get_energy_info(data) + coord_attrs = cdf_attrs.get_variable_attributes( + "hi-energy-attrs", check_schema=False + ) + coord_attrs = apply_replacements_to_attrs( + coord_attrs, {"species": species_name} + ) + l1a_dataset = l1a_dataset.assign_coords( + { + f"energy_{species_name}": xr.DataArray( + np.array(energy_centers), + dims=(f"energy_{species_name}",), + attrs=coord_attrs, + ) + } + ) + species_label_attrs = cdf_attrs.get_variable_attributes( + "energy_species_label", check_schema=False + ) + species_label_attrs = apply_replacements_to_attrs( + species_label_attrs, {"species": species_name} + ) + l1a_dataset[f"energy_{species_name}_label"] = xr.DataArray( + np.array(energy_centers).astype("str"), + dims=(f"energy_{species_name}"), + attrs=species_label_attrs, + ) + # Add energy plus and minus variables + minus_attrs = cdf_attrs.get_variable_attributes("hi-energy-delta-attrs") + minus_attrs = apply_replacements_to_attrs( + minus_attrs, {"species": species_name, "operation": "minus"} + ) + l1a_dataset[f"energy_{species_name}_minus"] = xr.DataArray( + energy_minus, + dims=(f"energy_{species_name}",), + attrs=minus_attrs, + ) + plus_attrs = cdf_attrs.get_variable_attributes("hi-energy-delta-attrs") + plus_attrs = apply_replacements_to_attrs( + plus_attrs, {"species": species_name, "operation": "plus"} + ) + l1a_dataset[f"energy_{species_name}_plus"] = xr.DataArray( + energy_plus, + dims=(f"energy_{species_name}",), + attrs=plus_attrs, + ) + + # Extract species data from decompressed data: + # - (num_packets, energy_bins, spin_sector, inst_az) + # Unpacked data is in this order: + # (epoch, number_species, energy_{species}, inst_az, spin_sector) + species_data = decompressed_data[:, species_index, :, :, :] + # Now transpose to put data in the correct order for writing to CDF: + # (epoch, energy_{species}, spin_sector, inst_az) + species_data = np.transpose(species_data, [0, 1, 3, 2]) + + species_attrs = cdf_attrs.get_variable_attributes("hi-species-attrs") + species_attrs = apply_replacements_to_attrs( + species_attrs, {"species": species_name} + ) + species_data = species_data.astype(np.float64) + # Add DEPEND_2, DEPEND_3 + species_attrs["DEPEND_2"] = "spin_sector" + species_attrs["LABL_PTR_2"] = "spin_sector_label" + species_attrs["DEPEND_3"] = "inst_az" + species_attrs["LABL_PTR_3"] = "inst_az_label" + l1a_dataset[species_name] = xr.DataArray( + species_data, + dims=("epoch", f"energy_{species_name}", "spin_sector", "inst_az"), + attrs=species_attrs, + ) + # Uncertainty is sqrt of counts + species_unc_attrs = cdf_attrs.get_variable_attributes("hi-species-unc-attrs") + species_unc_attrs = apply_replacements_to_attrs( + species_unc_attrs, {"species": species_name} + ) + # Add DEPEND_2, DEPEND_3 + species_unc_attrs["DEPEND_2"] = "spin_sector" + species_unc_attrs["LABL_PTR_2"] = "spin_sector_label" + species_unc_attrs["DEPEND_3"] = "inst_az" + species_unc_attrs["LABL_PTR_3"] = "inst_az_label" + l1a_dataset[f"unc_{species_name}"] = xr.DataArray( + np.sqrt(species_data), + dims=("epoch", f"energy_{species_name}", "spin_sector", "inst_az"), + attrs=species_unc_attrs, + ) + + # ========= Add Additional Variables =========== + l1a_dataset["spin_period"] = xr.DataArray( + group_ds["spin_period"].values * constants.SPIN_PERIOD_CONVERSION, + dims=("epoch",), + attrs=cdf_attrs.get_variable_attributes("spin_period"), + ) + l1a_dataset["data_quality"] = xr.DataArray( + group_ds["suspect"].values, + dims=("epoch",), + attrs=cdf_attrs.get_variable_attributes("data_quality"), + ) + + return l1a_dataset diff --git a/imap_processing/codice/codice_l1a_ialirt_hi.py b/imap_processing/codice/codice_l1a_ialirt_hi.py new file mode 100644 index 0000000000..a5dfcc1f32 --- /dev/null +++ b/imap_processing/codice/codice_l1a_ialirt_hi.py @@ -0,0 +1,180 @@ +"""CoDICE Hi I-ALiRT L1A processing functions.""" + +import logging +from pathlib import Path + +import numpy as np +import xarray as xr + +from imap_processing.codice import constants +from imap_processing.codice.decompress import decompress +from imap_processing.codice.utils import ( + CoDICECompression, + ViewTabInfo, + get_codice_epoch_time, + get_collapse_pattern_shape, + get_energy_info, + get_view_tab_info, + read_sci_lut, +) +from imap_processing.spice.time import met_to_ttj2000ns + +logger = logging.getLogger(__name__) + + +def l1a_ialirt_hi(unpacked_dataset: xr.Dataset, lut_file: Path) -> xr.Dataset: + """ + Process CoDICE Hi I-ALiRT L1A data. + + Parameters + ---------- + unpacked_dataset : xarray.Dataset + Unpacked dataset from L0 packet file. + lut_file : Path + Path to the LUT file for processing. + + Returns + ------- + xarray.Dataset + Processed L1A dataset for Hi Omni data. + """ + table_id = unpacked_dataset["table_id"].values[0] + view_id = unpacked_dataset["view_id"].values[0] + apid = unpacked_dataset["pkt_apid"].values[0] + plan_id = unpacked_dataset["plan_id"].values[0] + plan_step = unpacked_dataset["plan_step"].values[0] + + logger.info( + f"Processing species with - APID: {apid} / 0x{apid:X}, " + f"View ID: {view_id}, Table ID: {table_id}, " + f"Plan ID: {plan_id}, Plan Step: {plan_step}" + ) + + # ========== Get LUT Data =========== + sci_lut_data = read_sci_lut(lut_file, table_id) + view_tab_info = get_view_tab_info(sci_lut_data, view_id, apid) + + view_tab_obj = ViewTabInfo( + apid=apid, + view_id=view_id, + sensor=view_tab_info["sensor"], + three_d_collapsed=view_tab_info["3d_collapse"], + collapse_table=view_tab_info["collapse_table"], + compression=view_tab_info["compression"], + ) + + species_data = sci_lut_data["data_product_hi_tab"]["0"]["ialirt"] + first_species = next(iter(species_data)) + centers, energy_minus, energy_plus = get_energy_info(species_data[first_species]) + + compression_algorithm = CoDICECompression(view_tab_obj.compression) + + binary_data_list = unpacked_dataset["data"].values + byte_count_list = unpacked_dataset["byte_count"].values + + decompressed_data = [ + decompress(packet_data[:byte_count], compression_algorithm) + for packet_data, byte_count in zip( + binary_data_list, byte_count_list, strict=False + ) + ] + + epoch_center, deltas = get_codice_epoch_time( + unpacked_dataset["acq_start_seconds"].values, + unpacked_dataset["acq_start_subseconds"].values, + unpacked_dataset["spin_period"].values, + view_tab_obj, + ) + + three_d_collapsed = view_tab_obj.three_d_collapsed + num_packets = len(binary_data_list) + n_spins = int(16 / three_d_collapsed) + repeated_deltas = np.tile(deltas, n_spins) + + epoch_times = ( + np.repeat(epoch_center, n_spins) + + np.tile(np.arange(n_spins), num_packets) + * np.repeat(deltas, n_spins) + / 1e9 + * 2 + ) + + l1a_dataset = xr.Dataset( + coords={ + "epoch": xr.DataArray( + met_to_ttj2000ns(epoch_times), + dims=("epoch",), + ), + "epoch_delta_minus": xr.DataArray( + repeated_deltas, + dims=("epoch",), + ), + "epoch_delta_plus": xr.DataArray( + repeated_deltas, + dims=("epoch",), + ), + f"energy_{first_species}_minus": xr.DataArray( + energy_minus, + dims=(f"energy_{first_species}",), + ), + f"energy_{first_species}_plus": xr.DataArray( + energy_plus, + dims=(f"energy_{first_species}",), + ), + }, + ) + + energy_bins = 15 + collapse_shape = get_collapse_pattern_shape( + sci_lut_data, + view_tab_obj.sensor, + view_tab_obj.collapse_table, + ) + + # Reshape data into (epoch, energy, n_spins, spin_sector, inst_az) + decompressed_data = np.array(decompressed_data, dtype=np.uint32).reshape( + num_packets, + energy_bins, + n_spins, + *collapse_shape, + ) + + # Number of energy chunks. + num_energy_chunk = [len(species_data[first_species]["min_energy"])] + + l1a_dataset = l1a_dataset.assign_coords( + {f"energy_{first_species}": (f"energy_{first_species}", np.array(centers))} + ) + + chunk_size = num_energy_chunk[0] + + # This is rearranging data from (epoch, energy, n_spins, spin_sector, inst_az) + # -> (epoch, n_spins, energy, spin_sector, inst_az) -> + # finally (epoch * n_spins, energy, + # spin_sector, inst_az) + decompressed_data = decompressed_data.transpose(0, 2, 1, 4, 3).reshape( + -1, chunk_size, *collapse_shape + ) + + l1a_dataset[first_species] = xr.DataArray( + decompressed_data, + dims=("epoch", f"energy_{first_species}", "spin_sector", "inst_az"), + ) + + l1a_dataset[f"unc_{first_species}"] = xr.DataArray( + np.sqrt(decompressed_data), + dims=("epoch", f"energy_{first_species}", "spin_sector", "inst_az"), + ) + + l1a_dataset["spin_period"] = xr.DataArray( + np.repeat(unpacked_dataset["spin_period"].values, n_spins) + * constants.SPIN_PERIOD_CONVERSION, + dims=("epoch",), + ) + + l1a_dataset["data_quality"] = xr.DataArray( + np.repeat(unpacked_dataset["suspect"].values, n_spins), + dims=("epoch",), + ) + + return l1a_dataset diff --git a/imap_processing/codice/codice_l1a_lo_counters_aggregated.py b/imap_processing/codice/codice_l1a_lo_counters_aggregated.py new file mode 100644 index 0000000000..1bd323bccd --- /dev/null +++ b/imap_processing/codice/codice_l1a_lo_counters_aggregated.py @@ -0,0 +1,319 @@ +"""CoDICE L1A Lo Counters aggregated processing functions.""" + +import logging +from pathlib import Path + +import numpy as np +import xarray as xr + +from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes +from imap_processing.codice import constants +from imap_processing.codice.constants import HALF_SPIN_FILLVAL +from imap_processing.codice.decompress import decompress +from imap_processing.codice.utils import ( + CoDICECompression, + calculate_acq_time_per_step, + get_codice_epoch_time, + get_counters_aggregated_pattern, + get_view_tab_obj, +) +from imap_processing.spice.time import met_to_ttj2000ns + +logger = logging.getLogger(__name__) + + +def l1a_lo_counters_aggregated( + group_ds: xr.Dataset, + lut_file: Path, + table_id: str, + view_id: int, + apid: int, + plan_id: int, + plan_step: int, +) -> xr.Dataset: + """ + Process a single table-ID group of CoDICE Lo Counters Aggregated L1A data. + + Parameters + ---------- + group_ds : xarray.Dataset + Dataset filtered to a single table_id. + lut_file : Path + Path to the LUT file for processing. + table_id : str + The table ID for this group. + view_id : int + View ID (uniform across the product). + apid : int + APID (uniform across the product). + plan_id : int + Plan ID (uniform across the product). + plan_step : int + Plan step (uniform across the product). + + Returns + ------- + xarray.Dataset + Processed L1A dataset for input table-ID group. + """ + logger.info( + f"Processing aggregated with - APID: {apid} / 0x{apid:X}, View ID: {view_id}, " + f"Table ID: {table_id}, Plan ID: {plan_id}, Plan Step: {plan_step}" + ) + # ========== Get LUT Data =========== + sci_lut_data, view_tab_obj = get_view_tab_obj(lut_file, table_id, view_id, apid) + + if view_tab_obj.sensor != 0: + raise ValueError("Unsupported sensor ID for Lo processing.") + + # ========== Get Voltage Data from LUT =========== + # Use plan id and plan step to get voltage data's table_number in ESA sweep table. + # Voltage data is (128,) + esa_table_number = sci_lut_data["plan_tab"][f"({plan_id}, {plan_step})"][ + "lo_stepping" + ] + voltage_data = sci_lut_data["esa_sweep_tab"][f"{esa_table_number}"] + + # ========= Decompress and Reshape Data =========== + logical_source_id = "imap_codice_l1a_lo-counters-aggregated" + # Counters is little bit different in how CDF variables are derived. + # For singles, CDF variables are coming from 'product' tab. But for + # counters aggregated, it's coming from 'collapsed' tab in JSON LUT. + # In addition, for Lo, we include other inactive variables as zeros + # in the CDF. For Hi, all variables except 'reserved{x}' are active, + # so reserved variables are excluded unless it changes. This change + # will affect CoDICE team and here. + non_reserved_variables = get_counters_aggregated_pattern( + sci_lut_data, view_tab_obj.sensor, view_tab_obj.collapse_table + ) + non_reserved_keys = non_reserved_variables.keys() + all_keys = sci_lut_data["collapse_lo"]["1"]["variables"].keys() + # Dimensions + num_variables = len(non_reserved_keys) + spin_sector_pairs = non_reserved_variables["tcr"] + esa_step = constants.NUM_ESA_STEPS + # Decompress data using byte count information from decommed data + binary_data_list = group_ds["data"].values + byte_count_list = group_ds["byte_count"].values + + compression_algorithm = CoDICECompression(view_tab_obj.compression) + + # The decompressed data in the shape of (epoch, n). Then reshape later. + decompressed_data = [ + decompress( + packet_data[:byte_count], + compression_algorithm, + ) + for (packet_data, byte_count) in zip( + binary_data_list, byte_count_list, strict=False + ) + ] + + counters_data = np.array(decompressed_data, dtype=np.uint32).reshape( + -1, esa_step, num_variables, spin_sector_pairs + ) + + # If data size is less than 128, pad with fillval to make it 128 + half_spin_per_esa_step = sci_lut_data["lo_stepping_tab"]["row_number"].get("data") + if len(half_spin_per_esa_step) < constants.NUM_ESA_STEPS: + pad_size = constants.NUM_ESA_STEPS - len(half_spin_per_esa_step) + half_spin_per_esa_step = np.concatenate( + (np.array(half_spin_per_esa_step), np.full(pad_size, HALF_SPIN_FILLVAL)) + ) + # Each group shares the same table_id, so all epochs use the same LUT values. + half_spin_per_esa_step = np.tile( + np.asarray(half_spin_per_esa_step).astype(np.uint8), + (len(group_ds["acq_start_seconds"]), 1), + ) + # Get acquisition time per esa step + acquisition_time_per_step = calculate_acq_time_per_step( + sci_lut_data["lo_stepping_tab"] + ) + acquisition_time_per_step = np.tile( + np.asarray(acquisition_time_per_step), + (len(group_ds["acq_start_seconds"]), 1), + ) + # For every energy after nso_half_spin, set data to fill values + nso_half_spin = group_ds["nso_half_spin"].values + nso_mask = (half_spin_per_esa_step >= nso_half_spin[:, np.newaxis]) | ( + half_spin_per_esa_step == HALF_SPIN_FILLVAL + ) + counters_mask = nso_mask[:, :, np.newaxis, np.newaxis] + counters_mask = np.broadcast_to(counters_mask, counters_data.shape) + counters_data = counters_data.astype(np.float64) + counters_data[counters_mask] = np.nan + # Set half_spin_per_esa_step to (fillval) where nso_mask is True + half_spin_per_esa_step[nso_mask] = HALF_SPIN_FILLVAL + # Set acquisition_time_per_step to nan where nso_mask is True + acquisition_time_per_step[nso_mask] = np.nan + + # ========= Get Epoch Time Data =========== + # Epoch center time and delta + epoch_center, deltas = get_codice_epoch_time( + group_ds["acq_start_seconds"].values, + group_ds["acq_start_subseconds"].values, + group_ds["spin_period"].values, + view_tab_obj, + ) + + # ========== Initialize CDF Dataset with Coordinates =========== + cdf_attrs = ImapCdfAttributes() + cdf_attrs.add_instrument_global_attrs("codice") + cdf_attrs.add_instrument_variable_attrs("codice", "l1a") + + l1a_dataset = xr.Dataset( + coords={ + "epoch": xr.DataArray( + met_to_ttj2000ns(epoch_center), + dims=("epoch",), + attrs=cdf_attrs.get_variable_attributes("epoch", check_schema=False), + ), + "epoch_delta_minus": xr.DataArray( + deltas, + dims=("epoch",), + attrs=cdf_attrs.get_variable_attributes( + "epoch_delta_minus", check_schema=False + ), + ), + "epoch_delta_plus": xr.DataArray( + deltas, + dims=("epoch",), + attrs=cdf_attrs.get_variable_attributes( + "epoch_delta_plus", check_schema=False + ), + ), + "esa_step": xr.DataArray( + np.arange(esa_step, dtype=np.uint8), + dims=("esa_step",), + attrs=cdf_attrs.get_variable_attributes("esa_step", check_schema=False), + ), + "half_spin_per_esa_step": xr.DataArray( + half_spin_per_esa_step, + dims=( + "epoch", + "esa_step", + ), + attrs=cdf_attrs.get_variable_attributes( + "half_spin_per_esa_step", check_schema=False + ), + ), + "esa_step_label": xr.DataArray( + np.arange(esa_step, dtype=np.uint8).astype(str), + dims=("esa_step",), + attrs=cdf_attrs.get_variable_attributes( + "esa_step_label", check_schema=False + ), + ), + "spin_sector_pairs": xr.DataArray( + np.arange(spin_sector_pairs, dtype=np.uint8), + dims=("spin_sector_pairs",), + attrs=cdf_attrs.get_variable_attributes( + "spin_sector_pairs", check_schema=False + ), + ), + "spin_sector_pairs_label": xr.DataArray( + np.arange(spin_sector_pairs, dtype=np.uint8).astype(str), + dims=("spin_sector_pairs",), + attrs=cdf_attrs.get_variable_attributes( + "spin_sector_pairs_label", check_schema=False + ), + ), + }, + attrs=cdf_attrs.get_global_attributes(logical_source_id), + ) + + # Add first few unique variables + l1a_dataset["spin_period"] = xr.DataArray( + group_ds["spin_period"].values * constants.SPIN_PERIOD_CONVERSION, + dims=("epoch",), + attrs=cdf_attrs.get_variable_attributes("spin_period"), + ) + l1a_dataset["k_factor"] = xr.DataArray( + np.array([constants.K_FACTOR]), + dims=("k_factor",), + attrs=cdf_attrs.get_variable_attributes("k_factor_attrs", check_schema=False), + ) + l1a_dataset["voltage_table"] = xr.DataArray( + np.array(voltage_data), + dims=("esa_step",), + attrs=cdf_attrs.get_variable_attributes("voltage_table", check_schema=False), + ) + l1a_dataset["data_quality"] = xr.DataArray( + group_ds["suspect"].values, + dims=("epoch",), + attrs=cdf_attrs.get_variable_attributes("data_quality"), + ) + l1a_dataset["acquisition_time_per_esa_step"] = xr.DataArray( + acquisition_time_per_step, + dims=("epoch", "esa_step"), + attrs=cdf_attrs.get_variable_attributes( + "acquisition_time_per_esa_step", check_schema=False + ), + ) + # Rename vars + group_ds = group_ds.rename( + { + k: v + for k, v in [ + ("rgfo_energy_step", "rgfo_esa_step"), + ("nso_energy_step", "nso_esa_step"), + ] + if k in group_ds + } + ) + # These variables were added to the packet definition after 20260129, so they only + # exist in the dataset if packet_version > 1. + # If they don't exist, initialize them with fill val arrays since they won't be + # used in the NSO/RGFO masking logic but should still exist in l1a for SPDF + # compliance/consistency. + l1a_additional_vars = [ + "rgfo_spin_sector", + "rgfo_esa_step", + "nso_spin_sector", + "nso_esa_step", + ] + for var in l1a_additional_vars: + if var not in group_ds: + group_ds[var] = np.full(group_ds.sizes["epoch"], fill_value=np.nan) + + # Carry over these variables from unpacked data to l1a_dataset + l1a_carryover_vars = [ + "sw_bias_gain_mode", + "st_bias_gain_mode", + "rgfo_half_spin", + "nso_half_spin", + *l1a_additional_vars, + ] + # Loop through them since we need to set their attrs too + for var in l1a_carryover_vars: + l1a_dataset[var] = xr.DataArray( + group_ds[var].values, + dims=("epoch",), + attrs=cdf_attrs.get_variable_attributes(var), + ) + # Finally, add data variables + for idx, variable in enumerate(non_reserved_variables): + # We don't store reserved variables in CDF + attrs = cdf_attrs.get_variable_attributes(f"lo-{variable}") + + l1a_dataset[variable] = xr.DataArray( + counters_data[:, :, idx, :], + dims=("epoch", "esa_step", "spin_sector_pairs"), + attrs=attrs, + ) + + for variable in all_keys: + if variable in non_reserved_keys or variable.startswith("reserved"): + continue + attrs = cdf_attrs.get_variable_attributes(f"lo-{variable}") + l1a_dataset[variable] = xr.DataArray( + np.full( + l1a_dataset["tcr"].shape, + np.iinfo(np.uint32).max, + dtype=np.uint32, + ), + dims=("epoch", "esa_step", "spin_sector_pairs"), + attrs=attrs, + ) + # No uncertainty needed for Lo counters data + return l1a_dataset diff --git a/imap_processing/codice/codice_l1a_lo_counters_singles.py b/imap_processing/codice/codice_l1a_lo_counters_singles.py new file mode 100644 index 0000000000..b0b29c8b60 --- /dev/null +++ b/imap_processing/codice/codice_l1a_lo_counters_singles.py @@ -0,0 +1,382 @@ +"""CoDICE L1A Lo Singles processing functions.""" + +import logging +from pathlib import Path + +import numpy as np +import xarray as xr + +from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes +from imap_processing.codice import constants +from imap_processing.codice.constants import HALF_SPIN_FILLVAL +from imap_processing.codice.decompress import decompress +from imap_processing.codice.utils import ( + CoDICECompression, + calculate_acq_time_per_step, + get_codice_epoch_time, + get_collapse_pattern_shape, + get_view_tab_obj, +) +from imap_processing.spice.time import met_to_ttj2000ns + +logger = logging.getLogger(__name__) + + +def l1a_lo_counters_singles( + group_ds: xr.Dataset, + lut_file: Path, + table_id: str, + view_id: int, + apid: int, + plan_id: int, + plan_step: int, +) -> xr.Dataset: + """ + Process a single table-ID group of CoDICE Lo Counters Singles L1A data. + + Parameters + ---------- + group_ds : xarray.Dataset + Dataset filtered to a single table_id. + lut_file : Path + Path to the LUT file for processing. + table_id : str + The table ID for this group. + view_id : int + View ID (uniform across the product). + apid : int + APID (uniform across the product). + plan_id : int + Plan ID (uniform across the product). + plan_step : int + Plan step (uniform across the product). + + Returns + ------- + xarray.Dataset + Processed L1A dataset for input table-ID group. + """ + logger.info( + f"Processing species with - APID: {apid} / 0x{apid:X}, View ID: {view_id}, " + f"Table ID: {table_id}, Plan ID: {plan_id}, Plan Step: {plan_step}" + ) + # ========== Get LUT Data =========== + sci_lut_data, view_tab_obj = get_view_tab_obj(lut_file, table_id, view_id, apid) + + if view_tab_obj.sensor != 0: + raise ValueError("Unsupported sensor ID for Hi processing.") + + # ========== Get Voltage Data from LUT =========== + # Use plan id and plan step to get voltage data's table_number in ESA sweep table. + # Voltage data is (128,) + esa_table_number = sci_lut_data["plan_tab"][f"({plan_id}, {plan_step})"][ + "lo_stepping" + ] + voltage_data = sci_lut_data["esa_sweep_tab"][f"{esa_table_number}"] + # ========= Decompress and Reshape Data =========== + logical_source_id = "imap_codice_l1a_lo-counters-singles" + + # Counters is little bit different in how CDF variables are derived. + # For singles, CDF variables are coming from 'product' tab. But for + # counters aggregated, it's coming from 'collapsed' tab in JSON LUT. + # But since lo counters singles only has one variable, we are skipping + # variable_names extraction here. + collapse_shape = get_collapse_pattern_shape( + sci_lut_data, view_tab_obj.sensor, view_tab_obj.collapse_table + ) + # Dimensions to reshape decompressed data + spin_sector_pairs = collapse_shape[0] + inst_az = collapse_shape[1] + esa_step = len(voltage_data) + + compression_algorithm = CoDICECompression(view_tab_obj.compression) + # Decompress data using byte count information from decommed data + binary_data_list = group_ds["data"].values + byte_count_list = group_ds["byte_count"].values + + # The decompressed data in the shape of (epoch, n). Then reshape later. + decompressed_data = [ + decompress( + packet_data[:byte_count], + compression_algorithm, + ) + for (packet_data, byte_count) in zip( + binary_data_list, byte_count_list, strict=False + ) + ] + + counters_data = ( + np.array(decompressed_data, dtype=np.uint32) + .reshape(-1, esa_step, inst_az, spin_sector_pairs) + .transpose(0, 1, 3, 2) + ) + + # If data size is less than 128, pad with fillval to make it 128 + half_spin_per_esa_step = sci_lut_data["lo_stepping_tab"]["row_number"].get("data") + if len(half_spin_per_esa_step) < constants.NUM_ESA_STEPS: + pad_size = constants.NUM_ESA_STEPS - len(half_spin_per_esa_step) + half_spin_per_esa_step = np.concatenate( + (np.array(half_spin_per_esa_step), np.full(pad_size, HALF_SPIN_FILLVAL)) + ) + # Each group shares the same table_id, so all epochs use the same LUT values. + half_spin_per_esa_step = np.tile( + np.asarray(half_spin_per_esa_step).astype(np.uint8), + (len(group_ds["acq_start_seconds"]), 1), + ) + # Get acquisition time per esa step + acquisition_time_per_step = calculate_acq_time_per_step( + sci_lut_data["lo_stepping_tab"] + ) + acquisition_time_per_step = np.tile( + np.asarray(acquisition_time_per_step), + (len(group_ds["acq_start_seconds"]), 1), + ) + # ========== Apply NSO/RGFO Masking =========== + # After FSW changes on 20260129, The Lo L1A product contains variables that + # indicate the esa step and spin sector during which the RGFO or NSO limits are + # triggered. The spin sector variable ranges from 0-23 (normalized to 0-11) and is + # the instrument reported spin sector. The following algorithm defines when to + # assign NaN to the counters data product due to NSO operation: + # 1. For half_spin > nso_half_spin a set all data to NaN + # 2. For half_spin = nso_half_spin + # a. For spin_sector > nso_spin_sector a set all data to NaN + # b. For spin_sector = nso_spin_sector + # i. For esa_step > nso_esa_step a set all data to NaN + # For every energy after nso_half_spin, set data to fill values + # For data before 20260129 ( packet_version <=1 ) set all data to NaN where + # half_spin > nso_half_spin + packet_versions = group_ds["packet_version"].values + nso_half_spin = group_ds["nso_half_spin"].values + # TODO handle boundary days where the FSW changed halfway through the dataset. E.g + # Some packet_version = 1 and some = 2 + if packet_versions[0] <= 1: + # For half_spin > NSO_half_spin, set to NaN + half_spin_mask = (half_spin_per_esa_step > nso_half_spin[:, np.newaxis]) | ( + half_spin_per_esa_step == HALF_SPIN_FILLVAL + ) + counters_mask = half_spin_mask[:, :, np.newaxis, np.newaxis] + counters_mask = np.broadcast_to(counters_mask, counters_data.shape) + else: + # nso_spin_sector and nso_esa_step for comparison. Shape (epoch, 1, 1) + # to broadcast + nso_spin_sector = ( + group_ds["nso_spin_sector"].values[:, np.newaxis, np.newaxis] % 12 + ) # Mod 12 since spin sector is reported as 0-23 but we want to compare to + # 0-11 bins in the data. + # After modulo 12, we need to floor divide by 2 since the counters data has 6 + # spin sector bins (2 spin sectors per bin). + nso_spin_sector = nso_spin_sector // 2 + # compare it to the 0-5 spin sector bins in the data + nso_esa_step = group_ds["nso_energy_step"].values[:, np.newaxis, np.newaxis] + num_esa_steps = counters_data.shape[1] + num_spin_sectors = counters_data.shape[2] + # Create arrays for spin sectors and esa steps to compare with nso values. + # Shape (1, 1, spin_sector) and (1, esa_step, 1) + spin_sectors = np.arange(num_spin_sectors)[np.newaxis, np.newaxis, :] + esa_steps = np.arange(num_esa_steps)[np.newaxis, :, np.newaxis] + # Create a mask for half_spin > nso_half_spin. Shape (epoch, esa_step)) + # This will be used below to set half_spin_per_esa_step to fillval and + # acquisition_time_per_step to NaN for those steps. + half_spin_mask = (half_spin_per_esa_step > nso_half_spin[:, np.newaxis]) | ( + half_spin_per_esa_step == HALF_SPIN_FILLVAL + ) + # Create a mask for the boundary condition where half_spin == nso_half_spin. + at_boundary = ( + half_spin_per_esa_step[:, :, np.newaxis] + == nso_half_spin[:, np.newaxis, np.newaxis] + ) + boundary_half_spin_mask = ( + at_boundary + & + # For spin_sector > nso_spin_sector, set to NaN + ( + (spin_sectors > nso_spin_sector) + | + # For spin_sector = nso_spin_sector and esa_step > nso_esa_step, + # set to NaN + ((spin_sectors == nso_spin_sector) & (esa_steps > nso_esa_step)) + ) + ) + + # Combine masks. Shape (epoch, esa_step, spin_sector). This mask is True + # where data should be set to NaN + nso_mask = half_spin_mask[:, :, np.newaxis] | boundary_half_spin_mask + # Expand nso_mask to (epoch, 1, esa_step, spin_sector, 1) to apply to + # counters_data. + counters_mask = np.broadcast_to( + nso_mask[:, :, :, np.newaxis], counters_data.shape + ) + + counters_data = counters_data.astype(np.float64) + counters_data[counters_mask] = np.nan + # Set half_spin_per_esa_step to (fillval) where half_spin mask is True + half_spin_per_esa_step[half_spin_mask] = HALF_SPIN_FILLVAL + # Set acquisition_time_per_step to nan where half_spin_mask is True + acquisition_time_per_step[half_spin_mask] = np.nan + + # ========= Get Epoch Time Data =========== + # Epoch center time and delta + epoch_center, deltas = get_codice_epoch_time( + group_ds["acq_start_seconds"].values, + group_ds["acq_start_subseconds"].values, + group_ds["spin_period"].values, + view_tab_obj, + ) + + # ========== Initialize CDF Dataset with Coordinates =========== + cdf_attrs = ImapCdfAttributes() + cdf_attrs.add_instrument_global_attrs("codice") + cdf_attrs.add_instrument_variable_attrs("codice", "l1a") + + l1a_dataset = xr.Dataset( + coords={ + "epoch": xr.DataArray( + met_to_ttj2000ns(epoch_center), + dims=("epoch",), + attrs=cdf_attrs.get_variable_attributes("epoch", check_schema=False), + ), + "epoch_delta_minus": xr.DataArray( + deltas, + dims=("epoch",), + attrs=cdf_attrs.get_variable_attributes( + "epoch_delta_minus", check_schema=False + ), + ), + "epoch_delta_plus": xr.DataArray( + deltas, + dims=("epoch",), + attrs=cdf_attrs.get_variable_attributes( + "epoch_delta_plus", check_schema=False + ), + ), + "esa_step": xr.DataArray( + np.arange(esa_step, dtype=np.uint8), + dims=("esa_step",), + attrs=cdf_attrs.get_variable_attributes("esa_step", check_schema=False), + ), + "half_spin_per_esa_step": xr.DataArray( + half_spin_per_esa_step, + dims=( + "epoch", + "esa_step", + ), + attrs=cdf_attrs.get_variable_attributes( + "half_spin_per_esa_step", check_schema=False + ), + ), + "esa_step_label": xr.DataArray( + np.arange(esa_step, dtype=np.uint8).astype(str), + dims=("esa_step",), + attrs=cdf_attrs.get_variable_attributes( + "esa_step_label", check_schema=False + ), + ), + "inst_az": xr.DataArray( + np.arange(inst_az, dtype=np.uint8), + dims=("inst_az",), + attrs=cdf_attrs.get_variable_attributes("inst_az", check_schema=False), + ), + "inst_az_label": xr.DataArray( + (np.arange(inst_az, dtype=np.uint8) + 1).astype(str), + dims=("inst_az",), + attrs=cdf_attrs.get_variable_attributes( + "inst_az_label", check_schema=False + ), + ), + "spin_sector_pairs": xr.DataArray( + np.arange(spin_sector_pairs, dtype=np.uint8), + dims=("spin_sector_pairs",), + attrs=cdf_attrs.get_variable_attributes( + "spin_sector_pairs", check_schema=False + ), + ), + "spin_sector_pairs_label": xr.DataArray( + np.arange(spin_sector_pairs, dtype=np.uint8).astype(str), + dims=("spin_sector_pairs",), + attrs=cdf_attrs.get_variable_attributes( + "spin_sector_pairs_label", check_schema=False + ), + ), + }, + attrs=cdf_attrs.get_global_attributes(logical_source_id), + ) + + # Add first few unique variables + l1a_dataset["spin_period"] = xr.DataArray( + group_ds["spin_period"].values * constants.SPIN_PERIOD_CONVERSION, + dims=("epoch",), + attrs=cdf_attrs.get_variable_attributes("spin_period"), + ) + l1a_dataset["k_factor"] = xr.DataArray( + np.array([constants.K_FACTOR]), + dims=("k_factor",), + attrs=cdf_attrs.get_variable_attributes("k_factor_attrs", check_schema=False), + ) + l1a_dataset["voltage_table"] = xr.DataArray( + np.array(voltage_data), + dims=("esa_step",), + attrs=cdf_attrs.get_variable_attributes("voltage_table", check_schema=False), + ) + l1a_dataset["data_quality"] = xr.DataArray( + group_ds["suspect"].values, + dims=("epoch",), + attrs=cdf_attrs.get_variable_attributes("data_quality"), + ) + l1a_dataset["acquisition_time_per_esa_step"] = xr.DataArray( + acquisition_time_per_step, + dims=("epoch", "esa_step"), + attrs=cdf_attrs.get_variable_attributes( + "acquisition_time_per_esa_step", check_schema=False + ), + ) + # Rename vars + group_ds = group_ds.rename( + { + k: v + for k, v in [ + ("rgfo_energy_step", "rgfo_esa_step"), + ("nso_energy_step", "nso_esa_step"), + ] + if k in group_ds + } + ) + # These variables were added to the packet definition after 20260129, so they only + # exist in the dataset if packet_version > 1. + # If they don't exist, initialize them with fill val arrays since they won't be + # used in the NSO/RGFO masking logic but should still exist in l1a for SPDF + # compliance/consistency. + l1a_additional_vars = [ + "rgfo_spin_sector", + "rgfo_esa_step", + "nso_spin_sector", + "nso_esa_step", + ] + for var in l1a_additional_vars: + if var not in group_ds: + group_ds[var] = np.full(group_ds.sizes["epoch"], fill_value=np.nan) + + # Carry over these variables from unpacked data to l1a_dataset + l1a_carryover_vars = [ + "sw_bias_gain_mode", + "st_bias_gain_mode", + "rgfo_half_spin", + "nso_half_spin", + *l1a_additional_vars, + ] + # Loop through them since we need to set their attrs too + for var in l1a_carryover_vars: + l1a_dataset[var] = xr.DataArray( + group_ds[var].values, + dims=("epoch",), + attrs=cdf_attrs.get_variable_attributes(var), + ) + # Finally, add counters data variables and their uncertainties. + # Since singles only has one variable, we can directly add it here. + l1a_dataset["apd_singles"] = xr.DataArray( + counters_data, + dims=("epoch", "esa_step", "spin_sector_pairs", "inst_az"), + attrs=cdf_attrs.get_variable_attributes("lo_counters_singles"), + ) + # No uncertainty needed for Lo counters data + + return l1a_dataset diff --git a/imap_processing/codice/codice_l1a_lo_priority.py b/imap_processing/codice/codice_l1a_lo_priority.py new file mode 100644 index 0000000000..34a32349a9 --- /dev/null +++ b/imap_processing/codice/codice_l1a_lo_priority.py @@ -0,0 +1,402 @@ +"""CoDICE L1A Lo priority processing functions.""" + +import logging +from pathlib import Path + +import numpy as np +import xarray as xr + +from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes +from imap_processing.codice import constants +from imap_processing.codice.constants import HALF_SPIN_FILLVAL +from imap_processing.codice.decompress import decompress +from imap_processing.codice.utils import ( + CODICEAPID, + CoDICECompression, + calculate_acq_time_per_step, + get_codice_epoch_time, + get_collapse_pattern_shape, + get_view_tab_obj, +) +from imap_processing.spice.time import met_to_ttj2000ns + +logger = logging.getLogger(__name__) + + +def l1a_lo_priority( + group_ds: xr.Dataset, + lut_file: Path, + table_id: str, + view_id: int, + apid: int, + plan_id: int, + plan_step: int, +) -> xr.Dataset: + """ + Process a single table-ID group of CoDICE Lo Priority L1A data. + + Parameters + ---------- + group_ds : xarray.Dataset + Dataset filtered to a single table_id. + lut_file : Path + Path to the LUT file for processing. + table_id : str + The table ID for this group. + view_id : int + View ID (uniform across the product). + apid : int + APID (uniform across the product). + plan_id : int + Plan ID (uniform across the product). + plan_step : int + Plan step (uniform across the product). + + Returns + ------- + xarray.Dataset + Processed L1A dataset for input table-ID group. + """ + logger.info( + f"Processing species with - APID: {apid} / 0x{apid:X}, View ID: {view_id}, " + f"Table ID: {table_id}, Plan ID: {plan_id}, Plan Step: {plan_step}" + ) + + # ========== Get LUT Data =========== + sci_lut_data, view_tab_obj = get_view_tab_obj(lut_file, table_id, view_id, apid) + + if view_tab_obj.sensor != 0: + raise ValueError("Unsupported sensor ID for Lo priority processing.") + + # ========== Get Voltage Data from LUT =========== + # Use plan id and plan step to get voltage data's table_number in ESA sweep table. + # Voltage data is (128,) + esa_table_number = sci_lut_data["plan_tab"][f"({plan_id}, {plan_step})"][ + "lo_stepping" + ] + voltage_data = sci_lut_data["esa_sweep_tab"][f"{esa_table_number}"] + + # ========= Get Epoch Time Data =========== + # Epoch center time and delta + epoch_center, deltas = get_codice_epoch_time( + group_ds["acq_start_seconds"].values, + group_ds["acq_start_subseconds"].values, + group_ds["spin_period"].values, + view_tab_obj, + ) + + # ========= Decompress and Calculate Reshape information =========== + # Set needed metadata for Hi and Lo's different priority products + if apid == CODICEAPID.COD_LO_SW_PRIORITY_COUNTS: + species_names = sci_lut_data["data_product_lo_tab"]["0"]["priority"]["sw"][ + "species_names" + ] + logical_source_id = "imap_codice_l1a_lo-sw-priority" + compression_algorithm = CoDICECompression(view_tab_obj.compression) + elif apid == CODICEAPID.COD_LO_NSW_PRIORITY_COUNTS: + species_names = sci_lut_data["data_product_lo_tab"]["0"]["priority"]["nsw"][ + "species_names" + ] + logical_source_id = "imap_codice_l1a_lo-nsw-priority" + compression_algorithm = CoDICECompression(view_tab_obj.compression) + else: + raise ValueError("Unsupported APID for Lo priority processing.") + + # Decompress data using byte count information from decommed data + binary_data_list = group_ds["data"].values + byte_count_list = group_ds["byte_count"].values + + packet_version = group_ds["packet_version"].values[0] + # The decompressed data in the shape of (epoch, n). Then reshape later. + decompressed_data = [ + np.frombuffer( + bytes( + decompress( + packet_data[:byte_count], + compression_algorithm, + ) + ), + dtype=">u4", # Big endian + ) + # For newer packet versions, the decompressed data needs to be converted to + # uint32 + if packet_version > 1 + else decompress( + packet_data[:byte_count], + compression_algorithm, + ) + for (packet_data, byte_count) in zip( + binary_data_list, byte_count_list, strict=False + ) + ] + + num_packets = len(binary_data_list) + + # Reshape decompressed data to in below for loop: + # (num_packets, num_species, esa_steps, collapse_shape[0](spin_sector)) + num_species = len(species_names) + num_esa_steps = constants.NUM_ESA_STEPS + collapse_shape = get_collapse_pattern_shape( + sci_lut_data, + view_tab_obj.sensor, + view_tab_obj.collapse_table, + ) + num_spin_sectors = collapse_shape[0] + species_data = np.array(decompressed_data, dtype=np.uint32).reshape( + num_packets, num_species, num_esa_steps, num_spin_sectors + ) + + # If data size is less than 128, pad with fillval to make it 128 + half_spin_per_esa_step = sci_lut_data["lo_stepping_tab"]["row_number"].get("data") + if len(half_spin_per_esa_step) < num_esa_steps: + pad_size = num_esa_steps - len(half_spin_per_esa_step) + half_spin_per_esa_step = np.concatenate( + (np.array(half_spin_per_esa_step), np.full(pad_size, HALF_SPIN_FILLVAL)) + ) + + # Each group shares the same table_id, so all epochs use the same LUT values. + half_spin_per_esa_step = np.tile( + np.asarray(half_spin_per_esa_step).astype(np.uint8), + (len(group_ds["acq_start_seconds"]), 1), + ) + # Get acquisition time per esa step + acquisition_time_per_step = calculate_acq_time_per_step( + sci_lut_data["lo_stepping_tab"] + ) + acquisition_time_per_step = np.tile( + np.asarray(acquisition_time_per_step), + (len(group_ds["acq_start_seconds"]), 1), + ) + # ========== Apply NSO/RGFO Masking =========== + # After FSW changes on 20260129, The Lo L1A product contains variables that + # indicate the esa step and spin sector during which the RGFO or NSO limits are + # triggered. The spin sector variable ranges from 0-11 and is the instrument + # reported spin sector. The following algorithm defines when to assign NaN to the + # priority data product due to NSO + # operation: + # 1. For half_spin > nso_half_spin a set all data to NaN + # 2. For half_spin = nso_half_spin + # a. For spin_sector > nso_spin_sector a set all data to NaN + # b. For spin_sector = nso_spin_sector + # i. For esa_step > nso_esa_step a set all data to NaN + # For every energy after nso_half_spin, set data to fill values + # For data before 20260129 ( packet_version <=1 ) set all data to NaN where + # half_spin > nso_half_spin + packet_versions = group_ds["packet_version"].values + nso_half_spin = group_ds["nso_half_spin"].values + # TODO handle boundary days where the FSW changed halfway through the dataset. E.g + # Some packet_version = 1 and some = 2 + if packet_versions[0] <= 1: + # For half_spin >= NSO_half_spin, set to NaN + half_spin_mask = (half_spin_per_esa_step >= nso_half_spin[:, np.newaxis]) | ( + half_spin_per_esa_step == HALF_SPIN_FILLVAL + ) + species_mask = half_spin_mask[:, np.newaxis, :, np.newaxis] + species_mask = np.broadcast_to(species_mask, species_data.shape) + else: + # nso_spin_sector and nso_esa_step for comparison. Shape (epoch, 1, 1) + # to broadcast + # Packet nso_spin_sector spans the full spin (0-23), but this product's + # spin_sector dimension is half-spin indexed (0-11), so modulo 12 is + # intentional to align packet NSO metadata with the data coordinates. + nso_spin_sector = ( + group_ds["nso_spin_sector"].values[:, np.newaxis, np.newaxis] % 12 + ) + nso_esa_step = group_ds["nso_energy_step"].values[:, np.newaxis, np.newaxis] + # Create arrays for spin sectors and esa steps to compare with nso values. + # Shape (1, 1, spin_sector) and (1, esa_step, 1) + spin_sectors = np.arange(num_spin_sectors)[np.newaxis, np.newaxis, :] + esa_steps = np.arange(num_esa_steps)[np.newaxis, :, np.newaxis] + # Create a mask for half_spin > nso_half_spin. Shape (epoch, esa_step)) + # This will be used below to set half_spin_per_esa_step to fillval and + # acquisition_time_per_step to NaN for those steps. + half_spin_mask = (half_spin_per_esa_step > nso_half_spin[:, np.newaxis]) | ( + half_spin_per_esa_step == HALF_SPIN_FILLVAL + ) + # Create a mask for the boundary condition where half_spin == nso_half_spin. + at_boundary = ( + half_spin_per_esa_step[:, :, np.newaxis] + == nso_half_spin[:, np.newaxis, np.newaxis] + ) + boundary_half_spin_mask = ( + at_boundary + & + # For spin_sector > nso_spin_sector, set to NaN + ( + (spin_sectors > nso_spin_sector) + | + # For spin_sector = nso_spin_sector and esa_step > nso_esa_step, + # set to NaN + ((spin_sectors == nso_spin_sector) & (esa_steps > nso_esa_step)) + ) + ) + # Combine masks. Shape (epoch, esa_step, spin_sector). This mask is True + # where data should be set to NaN + nso_mask = half_spin_mask[:, :, np.newaxis] | boundary_half_spin_mask + # Expand nso_mask to (epoch, 1, esa_step, spin_sector) to apply to species_data. + species_mask = np.broadcast_to( + nso_mask[:, np.newaxis, :, :], species_data.shape + ) + + species_data = species_data.astype(np.float64) + species_data[species_mask] = np.nan + # Set half_spin_per_esa_step to (fillval) where nso_mask is True + half_spin_per_esa_step[half_spin_mask] = HALF_SPIN_FILLVAL + # Set acquisition_time_per_step to nan where nso_mask is True + acquisition_time_per_step[half_spin_mask] = np.nan + + # ========== Create CDF Dataset with Metadata =========== + cdf_attrs = ImapCdfAttributes() + cdf_attrs.add_instrument_global_attrs("codice") + cdf_attrs.add_instrument_variable_attrs("codice", "l1a") + + l1a_dataset = xr.Dataset( + coords={ + "epoch": xr.DataArray( + met_to_ttj2000ns(epoch_center), + dims=("epoch",), + attrs=cdf_attrs.get_variable_attributes("epoch", check_schema=False), + ), + "epoch_delta_minus": xr.DataArray( + deltas, + dims=("epoch",), + attrs=cdf_attrs.get_variable_attributes( + "epoch_delta_minus", check_schema=False + ), + ), + "epoch_delta_plus": xr.DataArray( + deltas, + dims=("epoch",), + attrs=cdf_attrs.get_variable_attributes( + "epoch_delta_plus", check_schema=False + ), + ), + "esa_step": xr.DataArray( + np.arange(128), + dims=("esa_step",), + attrs=cdf_attrs.get_variable_attributes("esa_step", check_schema=False), + ), + "half_spin_per_esa_step": xr.DataArray( + half_spin_per_esa_step, + dims=( + "epoch", + "esa_step", + ), + attrs=cdf_attrs.get_variable_attributes( + "half_spin_per_esa_step", check_schema=False + ), + ), + "esa_step_label": xr.DataArray( + np.arange(128).astype(str), + dims=("esa_step",), + attrs=cdf_attrs.get_variable_attributes( + "esa_step_label", check_schema=False + ), + ), + "k_factor": xr.DataArray( + np.array([constants.K_FACTOR]), + dims=("k_factor",), + attrs=cdf_attrs.get_variable_attributes( + "k_factor_attrs", check_schema=False + ), + ), + "spin_sector": xr.DataArray( + np.arange(collapse_shape[0], dtype=np.uint8), + dims=("spin_sector",), + attrs=cdf_attrs.get_variable_attributes( + "spin_sector", check_schema=False + ), + ), + "spin_sector_label": xr.DataArray( + np.arange(collapse_shape[0]).astype(str), + dims=("spin_sector",), + attrs=cdf_attrs.get_variable_attributes( + "spin_sector_label", check_schema=False + ), + ), + }, + attrs=cdf_attrs.get_global_attributes(logical_source_id), + ) + # Add first few unique variables + l1a_dataset["spin_period"] = xr.DataArray( + group_ds["spin_period"].values * constants.SPIN_PERIOD_CONVERSION, + dims=("epoch",), + attrs=cdf_attrs.get_variable_attributes("spin_period"), + ) + l1a_dataset["k_factor"] = xr.DataArray( + np.array([constants.K_FACTOR]), + dims=("k_factor",), + attrs=cdf_attrs.get_variable_attributes("k_factor_attrs", check_schema=False), + ) + l1a_dataset["voltage_table"] = xr.DataArray( + np.array(voltage_data), + dims=("esa_step",), + attrs=cdf_attrs.get_variable_attributes("voltage_table", check_schema=False), + ) + l1a_dataset["data_quality"] = xr.DataArray( + group_ds["suspect"].values, + dims=("epoch",), + attrs=cdf_attrs.get_variable_attributes("data_quality"), + ) + l1a_dataset["acquisition_time_per_esa_step"] = xr.DataArray( + acquisition_time_per_step, + dims=("epoch", "esa_step"), + attrs=cdf_attrs.get_variable_attributes( + "acquisition_time_per_esa_step", check_schema=False + ), + ) + # Rename vars + group_ds = group_ds.rename( + { + k: v + for k, v in [ + ("rgfo_energy_step", "rgfo_esa_step"), + ("nso_energy_step", "nso_esa_step"), + ] + if k in group_ds + } + ) + # These variables were added to the packet definition after 20260129, so they only + # exist in the dataset if packet_version > 1. + # If they don't exist, initialize them with fill val arrays since they won't be + # used in the NSO/RGFO masking logic but should still exist in l1a for SPDF + # compliance/consistency. + l1a_additional_vars = [ + "rgfo_spin_sector", + "rgfo_esa_step", + "nso_spin_sector", + "nso_esa_step", + ] + for var in l1a_additional_vars: + if var not in group_ds: + group_ds[var] = np.full(group_ds.sizes["epoch"], fill_value=np.nan) + + # Carry over these variables from unpacked data to l1a_dataset + l1a_carryover_vars = [ + "sw_bias_gain_mode", + "st_bias_gain_mode", + "rgfo_half_spin", + "nso_half_spin", + *l1a_additional_vars, + ] + # Loop through them since we need to set their attrs too + for var in l1a_carryover_vars: + l1a_dataset[var] = xr.DataArray( + group_ds[var].values, + dims=("epoch",), + attrs=cdf_attrs.get_variable_attributes(var), + ) + # Finally, add species data variables and their uncertainties + for idx, species in enumerate(species_names): + l1a_dataset[species] = xr.DataArray( + species_data[:, idx, :, :], + dims=("epoch", "esa_step", "spin_sector"), + attrs=cdf_attrs.get_variable_attributes(species), + ) + l1a_dataset[f"unc_{species}"] = xr.DataArray( + np.sqrt(l1a_dataset[species].values), + dims=("epoch", "esa_step", "spin_sector"), + attrs=cdf_attrs.get_variable_attributes(species), + ) + + return l1a_dataset diff --git a/imap_processing/codice/codice_l1a_lo_species.py b/imap_processing/codice/codice_l1a_lo_species.py new file mode 100644 index 0000000000..d5f9fbeef2 --- /dev/null +++ b/imap_processing/codice/codice_l1a_lo_species.py @@ -0,0 +1,377 @@ +"""CoDICE Lo Species L1A processing functions.""" + +import logging +from pathlib import Path + +import numpy as np +import xarray as xr + +from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes +from imap_processing.codice import constants +from imap_processing.codice.constants import ( + HALF_SPIN_FILLVAL, + LO_IALIRT_VARIABLE_NAMES, + LO_SW_SPECIES_VARIABLE_NAMES, +) +from imap_processing.codice.decompress import decompress +from imap_processing.codice.utils import ( + CODICEAPID, + CoDICECompression, + calculate_acq_time_per_step, + get_codice_epoch_time, + get_collapse_pattern_shape, + get_view_tab_obj, +) +from imap_processing.spice.time import met_to_ttj2000ns + +logger = logging.getLogger(__name__) + + +def l1a_lo_species( + group_ds: xr.Dataset, + lut_file: Path, + table_id: str, + view_id: int, + apid: int, + plan_id: int, + plan_step: int, +) -> xr.Dataset: + """ + Process a single table-ID group of CoDICE Lo Species L1A data. + + Parameters + ---------- + group_ds : xarray.Dataset + Dataset filtered to a single table_id. + lut_file : Path + Path to the LUT file for processing. + table_id : str + The table ID for this group. + view_id : int + View ID (uniform across the product). + apid : int + APID (uniform across the product). + plan_id : int + Plan ID (uniform across the product). + plan_step : int + Plan step (uniform across the product). + + Returns + ------- + xarray.Dataset + The processed L1A dataset for input table-ID group. + """ + logger.info( + f"Processing species with - APID: {apid} / 0x{apid:X}, View ID: {view_id}, " + f"Table ID: {table_id}, Plan ID: {plan_id}, Plan Step: {plan_step}" + ) + + # ========== Get LUT Data =========== + sci_lut_data, view_tab_obj = get_view_tab_obj(lut_file, table_id, view_id, apid) + if view_tab_obj.sensor != 0: + raise ValueError("Unsupported sensor ID for Lo species processing.") + + # ========= Decompress and Reshape Data =========== + # Lookup SW species based on APID + if view_tab_obj.apid == CODICEAPID.COD_LO_SW_SPECIES_COUNTS: + actual_species_names = sci_lut_data["data_product_lo_tab"]["0"]["species"][ + "sw" + ]["species_names"] + desired_species_names = set( + sci_lut_data["data_product_lo_tab"]["0"]["species"]["sw"][ + "desired_species_names" + ] + + LO_SW_SPECIES_VARIABLE_NAMES + ) + logical_source_id = "imap_codice_l1a_lo-sw-species" + elif view_tab_obj.apid == CODICEAPID.COD_LO_IAL: + actual_species_names = sci_lut_data["data_product_lo_tab"]["0"]["ialirt"]["sw"][ + "species_names" + ] + desired_species_names = set( + sci_lut_data["data_product_lo_tab"]["0"]["ialirt"]["sw"][ + "desired_species_names" + ] + + LO_IALIRT_VARIABLE_NAMES + ) + # Note: ialirt does not produce a cdf for l1a so this is arbitrary. + logical_source_id = "imap_codice_l1a_lo-sw-species" + else: + raise ValueError(f"Unknown apid {view_tab_obj.apid} in Lo species processing.") + + compression_algorithm = CoDICECompression(view_tab_obj.compression) + # Decompress data using byte count information from decommed data + binary_data_list = group_ds["data"].values + byte_count_list = group_ds["byte_count"].values + decompressed_data = [ + decompress( + packet_data[:byte_count], + compression_algorithm, + ) + for (packet_data, byte_count) in zip( + binary_data_list, byte_count_list, strict=False + ) + ] + + # Look up collapse pattern using LUT table. This should return collapsed shape. + # For Lo species, it will be (1,) + collapsed_shape = get_collapse_pattern_shape( + sci_lut_data, view_tab_obj.sensor, view_tab_obj.collapse_table + ) + + # Reshape decompressed data to: + # (num_packets, num_species, esa_steps, *collapsed_shape) + # where collapsed_shape is usually (1,) for Lo species. + num_packets = len(binary_data_list) + num_species = len(actual_species_names) + esa_steps = constants.NUM_ESA_STEPS + species_data = np.array(decompressed_data, dtype=np.uint32).reshape( + num_packets, num_species, esa_steps, *collapsed_shape + ) + + # If data size is less than 128, pad with fillval to make it 128 + half_spin_per_esa_step = sci_lut_data["lo_stepping_tab"]["row_number"].get("data") + if len(half_spin_per_esa_step) < constants.NUM_ESA_STEPS: + pad_size = constants.NUM_ESA_STEPS - len(half_spin_per_esa_step) + half_spin_per_esa_step = np.concatenate( + (np.array(half_spin_per_esa_step), np.full(pad_size, HALF_SPIN_FILLVAL)) + ) + + acquisition_time_per_step = calculate_acq_time_per_step( + sci_lut_data["lo_stepping_tab"] + ) + # Get acquisition time per esa step. Each group shares the same table_id, so + # all epochs within the group use the same LUT values. + half_spin_per_esa_step = np.tile( + np.asarray( + half_spin_per_esa_step, + ).astype(np.uint8), + (len(group_ds["acq_start_seconds"]), 1), + ) + acquisition_time_per_step = np.tile( + np.asarray(acquisition_time_per_step), + (len(group_ds["acq_start_seconds"]), 1), + ) + # For every energy after nso_half_spin, set data to fill values + nso_half_spin = group_ds["nso_half_spin"].values + nso_mask = (half_spin_per_esa_step >= nso_half_spin[:, np.newaxis]) | ( + half_spin_per_esa_step == HALF_SPIN_FILLVAL + ) + species_mask = nso_mask[:, np.newaxis, :, np.newaxis] + species_mask = np.repeat(species_mask, num_species, 1) + species_data = species_data.astype(np.float64) + species_data[species_mask] = np.nan + # Set half_spin_per_esa_step to (fillval) where nso_mask is True + half_spin_per_esa_step[nso_mask] = HALF_SPIN_FILLVAL + # Set acquisition_time_per_step to nan where nso_mask is True + acquisition_time_per_step[nso_mask] = np.nan + + # ========== Get Voltage Data from LUT =========== + # Use plan id and plan step to get voltage data's table_number in ESA sweep table. + # Voltage data is (128,) + esa_table_number = sci_lut_data["plan_tab"][f"({plan_id}, {plan_step})"][ + "lo_stepping" + ] + voltage_data = sci_lut_data["esa_sweep_tab"][f"{esa_table_number}"] + + # ========= Get Epoch Time Data =========== + # Epoch center time and delta + epoch_center, deltas = get_codice_epoch_time( + group_ds["acq_start_seconds"].values, + group_ds["acq_start_subseconds"].values, + group_ds["spin_period"].values, + view_tab_obj, + ) + + # ========== Create CDF Dataset with Metadata =========== + cdf_attrs = ImapCdfAttributes() + cdf_attrs.add_instrument_global_attrs("codice") + cdf_attrs.add_instrument_variable_attrs("codice", "l1a") + + l1a_dataset = xr.Dataset( + coords={ + "epoch": xr.DataArray( + met_to_ttj2000ns(epoch_center), + dims=("epoch",), + attrs=cdf_attrs.get_variable_attributes("epoch", check_schema=False), + ), + "epoch_delta_minus": xr.DataArray( + deltas, + dims=("epoch",), + attrs=cdf_attrs.get_variable_attributes( + "epoch_delta_minus", check_schema=False + ), + ), + "epoch_delta_plus": xr.DataArray( + deltas, + dims=("epoch",), + attrs=cdf_attrs.get_variable_attributes( + "epoch_delta_plus", check_schema=False + ), + ), + "esa_step": xr.DataArray( + np.arange(128), + dims=("esa_step",), + attrs=cdf_attrs.get_variable_attributes("esa_step", check_schema=False), + ), + "half_spin_per_esa_step": xr.DataArray( + half_spin_per_esa_step, + dims=( + "epoch", + "esa_step", + ), + attrs=cdf_attrs.get_variable_attributes( + "half_spin_per_esa_step", check_schema=False + ), + ), + "esa_step_label": xr.DataArray( + np.arange(128).astype(str), + dims=("esa_step",), + attrs=cdf_attrs.get_variable_attributes( + "esa_step_label", check_schema=False + ), + ), + "k_factor": xr.DataArray( + np.array([constants.K_FACTOR]), + dims=("k_factor",), + attrs=cdf_attrs.get_variable_attributes( + "k_factor_attrs", check_schema=False + ), + ), + "spin_sector": xr.DataArray( + np.array([0], dtype=np.uint8), + dims=("spin_sector",), + attrs=cdf_attrs.get_variable_attributes( + "spin_sector", check_schema=False + ), + ), + "spin_sector_label": xr.DataArray( + np.array(["0"]).astype(str), + dims=("spin_sector",), + attrs=cdf_attrs.get_variable_attributes( + "spin_sector_label", check_schema=False + ), + ), + }, + attrs=cdf_attrs.get_global_attributes(logical_source_id), + ) + # Add first few unique variables + l1a_dataset["spin_period"] = xr.DataArray( + group_ds["spin_period"].values * constants.SPIN_PERIOD_CONVERSION, + dims=("epoch",), + attrs=cdf_attrs.get_variable_attributes("spin_period"), + ) + l1a_dataset["k_factor"] = xr.DataArray( + np.array([constants.K_FACTOR]), + dims=("k_factor",), + attrs=cdf_attrs.get_variable_attributes("k_factor_attrs", check_schema=False), + ) + l1a_dataset["voltage_table"] = xr.DataArray( + np.array(voltage_data), + dims=("esa_step",), + attrs=cdf_attrs.get_variable_attributes("voltage_table", check_schema=False), + ) + l1a_dataset["data_quality"] = xr.DataArray( + group_ds["suspect"].values, + dims=("epoch",), + attrs=cdf_attrs.get_variable_attributes("data_quality"), + ) + l1a_dataset["acquisition_time_per_esa_step"] = xr.DataArray( + acquisition_time_per_step, + dims=("epoch", "esa_step"), + attrs=cdf_attrs.get_variable_attributes( + "acquisition_time_per_esa_step", check_schema=False + ), + ) + # Rename vars + group_ds = group_ds.rename( + { + k: v + for k, v in [ + ("rgfo_energy_step", "rgfo_esa_step"), + ("nso_energy_step", "nso_esa_step"), + ] + if k in group_ds + } + ) + # These variables were added to the packet definition after 20260129, so they only + # exist in the unpacked dataset if packet_version > 1 + # If they don't exist, initialize them with fill val arrays since they won't be + # used in the NSO/RGFO masking logic but should still exist in l1a for SPDF + # compliance/consistency. + l1a_additional_vars = [ + "rgfo_spin_sector", + "rgfo_esa_step", + "nso_spin_sector", + "nso_esa_step", + ] + for var in l1a_additional_vars: + if var not in group_ds: + group_ds[var] = np.full(group_ds.sizes["epoch"], fill_value=np.nan) + + # Carry over these variables from unpacked data to l1a_dataset + l1a_carryover_vars = [ + "sw_bias_gain_mode", + "st_bias_gain_mode", + "rgfo_half_spin", + "nso_half_spin", + "packet_version", + *l1a_additional_vars, + ] + # Loop through them since we need to set their attrs too + for var in l1a_carryover_vars: + l1a_dataset[var] = xr.DataArray( + group_ds[var].values, + dims=("epoch",), + attrs=cdf_attrs.get_variable_attributes(var), + ) + # Finally, add species data variables and their uncertainties + # Loop through the species we want in the final dataset (desired_species_names) and + # add them if they exist in the actual species names from the LUT. + # This is to handle the bug in which the spacecraft was sending data down "off by + # one" and getting mislabeled. + for species in desired_species_names: + if species not in actual_species_names: + logger.warning( + f"Desired species {species} not found in actual species names from " + f"LUT. This species will be filled with fill values in the final " + f"dataset. Actual species names: {actual_species_names}" + ) + species_data_individual = np.full(species_data[:, 0, :, :].shape, np.nan) + else: + species_idx = actual_species_names.index(species) + species_data_individual = species_data[:, species_idx, :, :] + + species_attrs = cdf_attrs.get_variable_attributes("lo-species-attrs") + unc_attrs = cdf_attrs.get_variable_attributes("lo-species-unc-attrs") + + direction = ( + "Sunward" + if view_tab_obj.apid == CODICEAPID.COD_LO_SW_SPECIES_COUNTS + else "Non-Sunward" + ) + # Replace {species} and {direction} in attrs + species_attrs["CATDESC"] = species_attrs["CATDESC"].format( + species=species, direction=direction + ) + species_attrs["FIELDNAM"] = species_attrs["FIELDNAM"].format( + species=species, direction=direction + ) + l1a_dataset[species] = xr.DataArray( + species_data_individual, + dims=("epoch", "esa_step", "spin_sector"), + attrs=species_attrs, + ) + # Uncertainty data + unc_attrs["CATDESC"] = unc_attrs["CATDESC"].format( + species=species, direction=direction + ) + unc_attrs["FIELDNAM"] = unc_attrs["FIELDNAM"].format( + species=species, direction=direction + ) + l1a_dataset[f"unc_{species}"] = xr.DataArray( + np.sqrt(l1a_dataset[species].values), + dims=("epoch", "esa_step", "spin_sector"), + attrs=unc_attrs, + ) + return l1a_dataset diff --git a/imap_processing/codice/codice_l1b.py b/imap_processing/codice/codice_l1b.py index 6e569d829f..644f59a3b9 100644 --- a/imap_processing/codice/codice_l1b.py +++ b/imap_processing/codice/codice_l1b.py @@ -9,9 +9,6 @@ dataset = process_codice_l1b(l1a_filenanme) """ -# TODO: Figure out how to convert hi-priority data product. Need an updated -# algorithm document that describes this. - import logging from pathlib import Path @@ -23,12 +20,9 @@ from imap_processing.codice import constants logger = logging.getLogger(__name__) -logger.setLevel(logging.INFO) -def convert_to_rates( - dataset: xr.Dataset, descriptor: str, variable_name: str -) -> np.ndarray: +def convert_to_rates(dataset: xr.Dataset, descriptor: str) -> np.ndarray: """ Apply a conversion from counts to rates. @@ -41,35 +35,88 @@ def convert_to_rates( The L1b dataset containing the data to convert. descriptor : str The descriptor of the data product of interest. - variable_name : str - The variable name to apply the conversion to. Returns ------- rates_data : np.ndarray The converted data array. """ - # TODO: Temporary workaround to create CDFs for SIT-4. Revisit after SIT-4. - acq_times = 1 + # No uncertainty calculation for diagnostic counters products + calculate_unc = False if "counters" in descriptor else True + # Variables to convert based on descriptor + variables_to_convert = getattr( + constants, f"{descriptor.upper().replace('-', '_')}_VARIABLE_NAMES" + ) + if descriptor.startswith("lo-"): + # Calculate energy_per_charge using voltage_table and k_factor + energy_attrs = dataset["voltage_table"].attrs | { + "UNITS": "keV/e", + "LABLAXIS": "E/q", + "CATDESC": "Energy per charge", + "FIELDNAM": "Energy per charge", + } + # 1e3 is to convert eV to keV + dataset["energy_per_charge"] = xr.DataArray( + dataset["voltage_table"].values * dataset["k_factor"].values * 1e-3, + dims=[ + "esa_step", + ], + attrs=energy_attrs, + ) if descriptor in [ "lo-counters-aggregated", "lo-counters-singles", - "lo-nsw-angular", - "lo-sw-angular", "lo-nsw-priority", "lo-sw-priority", - "lo-nsw-species", + ]: + # Denominator to convert counts to rates + denominator = ( + dataset.acquisition_time_per_esa_step + * constants.L1B_DATA_PRODUCT_CONFIGURATIONS[descriptor]["num_spin_sectors"] + ) + + # Do not carry these variable attributes from L1a to L1b for above products + drop_variables = [ + "k_factor", + "nso_half_spin", + "sw_bias_gain_mode", + "st_bias_gain_mode", + "spin_period", + "voltage_table", + "nso_esa_step", + "nso_spin_sector", + # TODO: undo this when I get new validation file from Joey + # "acquisition_time_per_esa_step", + ] + dataset = dataset.drop_vars(drop_variables) + elif descriptor in [ "lo-sw-species", "lo-ialirt", ]: - # Applying rate calculation described in section 10.2 of the algorithm - # document - rates_data = dataset[variable_name].data / ( - acq_times - * 1e-6 # Converting from microseconds to seconds - * constants.L1B_DATA_PRODUCT_CONFIGURATIONS[descriptor]["num_spin_sectors"] + # Create n_sector with 'epoch' and 'esa_step' dimension. This is done by + # xr.full_like with input dataset.acquisition_time_per_esa_step. This ensures + # that the resulting n_sector has the same dimensions as + # acquisition_time_per_esa_step. Per CoDICE, fill first 127 with default value + # of 12. Then fill last with 11. In your SDC processing + n_sector = xr.full_like( + dataset.acquisition_time_per_esa_step, 12.0, dtype=np.float64 ) + n_sector[:, -1] = 11.0 + + # Denominator to convert counts to rates + denominator = dataset.acquisition_time_per_esa_step * n_sector + # Do not carry these variable attributes from L1a to L1b for above products + drop_variables = [ + "k_factor", + "nso_half_spin", + "sw_bias_gain_mode", + "st_bias_gain_mode", + "spin_period", + "voltage_table", + ] + dataset = dataset.drop_vars(drop_variables) + elif descriptor in [ "hi-counters-aggregated", "hi-counters-singles", @@ -78,17 +125,32 @@ def convert_to_rates( "hi-sectored", "hi-ialirt", ]: - # Applying rate calculation described in section 10.1 of the algorithm - # document - rates_data = dataset[variable_name].data / ( + # Denominator to convert counts to rates + denominator = ( constants.L1B_DATA_PRODUCT_CONFIGURATIONS[descriptor]["num_spin_sectors"] * constants.L1B_DATA_PRODUCT_CONFIGURATIONS[descriptor]["num_spins"] - * acq_times + * constants.HI_ACQUISITION_TIME ) - elif descriptor == "hskp": - rates_data = dataset[variable_name].data / acq_times - return rates_data + # For each variable, convert counts and uncertainty to rates + for variable in variables_to_convert: + dataset[variable].data = dataset[variable].astype(np.float64) / denominator + # Carry over attrs and update as needed + dataset[variable].attrs["UNITS"] = "counts/s" + + if calculate_unc: + # Uncertainty calculation + unc_variable = f"unc_{variable}" + dataset[unc_variable].data = ( + dataset[unc_variable].astype(np.float64) / denominator + ) + dataset[unc_variable].attrs["UNITS"] = "1/s" + + # Drop spin_period + if "spin_period" in dataset.variables: + dataset = dataset.drop_vars("spin_period") + + return dataset def process_codice_l1b(file_path: Path) -> xr.Dataset: @@ -115,52 +177,17 @@ def process_codice_l1b(file_path: Path) -> xr.Dataset: dataset_name = l1a_dataset.attrs["Logical_source"].replace("_l1a_", "_l1b_") descriptor = dataset_name.removeprefix("imap_codice_l1b_") - # Direct event data products do not have a level L1B - if descriptor in ["lo-direct-events", "hi-direct-events"]: - logger.warning("Encountered direct event data product. Skipping L1b processing") - return None - # Get the L1b CDF attributes cdf_attrs = ImapCdfAttributes() cdf_attrs.add_instrument_global_attrs("codice") - cdf_attrs.add_instrument_variable_attrs("codice", "l1b") # Use the L1a data product as a starting point for L1b - l1b_dataset = l1a_dataset.copy() + l1b_dataset = l1a_dataset.copy(deep=True) # Update the global attributes l1b_dataset.attrs = cdf_attrs.get_global_attributes(dataset_name) - # Determine which variables need to be converted from counts to rates - # TODO: Figure out exactly which hskp variables need to be converted - # Housekeeping and binned datasets are treated a bit differently since - # not all variables need to be converted - if descriptor == "hskp": - # TODO: Check with Joey if any housekeeping data needs to be converted - variables_to_convert = [] - elif descriptor == "hi-sectored": - variables_to_convert = ["h", "he3he4", "cno", "fe"] - elif descriptor == "hi-omni": - variables_to_convert = ["h", "he3", "he4", "c", "o", "ne_mg_si", "fe", "uh"] - elif descriptor == "hi-ialirt": - variables_to_convert = ["h"] - else: - variables_to_convert = getattr( - constants, f"{descriptor.upper().replace('-', '_')}_VARIABLE_NAMES" - ) - - # Apply the conversion to rates - for variable_name in variables_to_convert: - l1b_dataset[variable_name].data = convert_to_rates( - l1b_dataset, descriptor, variable_name - ) - - # Set the variable attributes - cdf_attrs_key = f"{descriptor}-{variable_name}" - l1b_dataset[variable_name].attrs = cdf_attrs.get_variable_attributes( - cdf_attrs_key, check_schema=False - ) - - logger.info(f"\nFinal data product:\n{l1b_dataset}\n") - - return l1b_dataset + return convert_to_rates( + l1b_dataset, + descriptor, + ) diff --git a/imap_processing/codice/codice_l2.py b/imap_processing/codice/codice_l2.py index ce008d2027..0a7998ee91 100644 --- a/imap_processing/codice/codice_l2.py +++ b/imap_processing/codice/codice_l2.py @@ -9,50 +9,1395 @@ dataset = process_codice_l2(l1_filename) """ +import datetime import logging from pathlib import Path +import numpy as np +import pandas as pd import xarray as xr +from imap_data_access import ProcessingInputCollection, ScienceFilePath +from numpy.typing import NDArray from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes from imap_processing.cdf.utils import load_cdf +from imap_processing.codice.constants import ( + GAIN_ID_TO_STR, + HALF_SPIN_FILLVAL, + HI_L2_ELEVATION_ANGLE, + HI_OMNI_VARIABLE_NAMES, + HI_SECTORED_VARIABLE_NAMES, + L2_HI_SECTORED_ANGLE, + LO_POSITION_TO_ELEVATION_ANGLE, + LO_SW_PICKUP_ION_SPECIES_VARIABLE_NAMES, + LO_SW_SOLAR_WIND_SPECIES_VARIABLE_NAMES, + PUI_POSITIONS, + SOLAR_WIND_POSITIONS, + SSD_ID_TO_ELEVATION, + SSD_ID_TO_SPIN_ANGLE, +) +from imap_processing.codice.utils import apply_replacements_to_attrs logger = logging.getLogger(__name__) -logger.setLevel(logging.INFO) -def process_codice_l2(file_path: Path) -> xr.Dataset: +def get_lo_de_energy_luts( + dependencies: ProcessingInputCollection, +) -> tuple[NDArray, NDArray]: + """ + Get the LO DE lookup tables for energy conversions. + + Parameters + ---------- + dependencies : ProcessingInputCollection + The collection of processing input files. + + Returns + ------- + energy_lut : np.ndarray + An array of energy in keV for each energy table index. + energy_bins_lut : np.ndarray + An array of energy bins. + """ + # Get lookup tables + energy_table_file = dependencies.get_file_paths( + descriptor="l2-lo-onboard-energy-table" + )[0] + energy_bins_file = dependencies.get_file_paths( + descriptor="l2-lo-onboard-energy-bins" + )[0] + energy_lut = pd.read_csv(energy_table_file, header=None, skiprows=1).to_numpy() + energy_bins_lut = pd.read_csv(energy_bins_file, header=None, skiprows=1).to_numpy()[ + :, 1 + ] + + return energy_lut, energy_bins_lut + + +def get_mpq_calc_energy_conversion_vals( + dependencies: ProcessingInputCollection, +) -> np.ndarray: + """ + Get the mass per charge (MPQ) esa step to energy kev conversion lookup table values. + + Parameters + ---------- + dependencies : ProcessingInputCollection + The collection of processing input files. + + Returns + ------- + esa_kev : np.ndarray + An array of energy in keV for each esa step. + """ + mpq_calc_lut_file = dependencies.get_file_paths(descriptor="l2-lo-onboard-mpq-cal")[ + 0 + ] + mpq_df = pd.read_csv(mpq_calc_lut_file, header=None) + k_factor = float(mpq_df.loc[0, 10]) + esa_v = mpq_df.loc[4, 4:].to_numpy().astype(np.float64) + # Calculate the energy in keV for each esa step + esa_kev = esa_v * k_factor / 1000 + return esa_kev + + +def get_mpq_calc_tof_conversion_vals( + dependencies: ProcessingInputCollection, +) -> np.ndarray: + """ + Get the MPQ calculation tof to ns conversion lookup table values. + + Parameters + ---------- + dependencies : ProcessingInputCollection + The collection of processing input files. + + Returns + ------- + tof_ns : np.ndarray + Tof in ns for each TOF bit. + """ + mpq_calc_lut_file = dependencies.get_file_paths(descriptor="l2-lo-onboard-mpq-cal")[ + 0 + ] + mpq_df = pd.read_csv(mpq_calc_lut_file, header=None) + ns_channel_sq = float(mpq_df.loc[2, 1]) + ns_channel = float(mpq_df.loc[3, 1]) + tof_offset = float(mpq_df.loc[4, 1]) + # Get the TOF bit to ns lookup + tof_bits = mpq_df.loc[6:, 0].to_numpy().astype(np.int64) + # Calculate the TOF in ns for each TOF bit + tof_ns = tof_bits**2 * ns_channel_sq + tof_bits * ns_channel + tof_offset + + return tof_ns + + +def get_hi_de_luts( + dependencies: ProcessingInputCollection | None, +) -> tuple[np.ndarray, np.ndarray]: + """ + Load lookup tables for hi direct-event processing. + + Parameters + ---------- + dependencies : ProcessingInputCollection + The collection of processing input files. + + Returns + ------- + energy_table : np.ndarray + 2D array of energy lookup table with shape (ssd_energy, col). + tof_table : np.ndarray + 2D array of tof lookup table with shape (tof_index, col). + """ + energy_table_file_path = dependencies.get_file_paths( + descriptor="l2-hi-energy-table" + )[0] + tof_table_file_path = dependencies.get_file_paths(descriptor="l2-hi-tof-table")[0] + # Read TOF CSV, skip first column which is an index + # Each row corresponds to a tof index and the columns are tof (ns) and E/n (MeV/n) + tof_table = ( + pd.read_csv(tof_table_file_path, header=None, skiprows=1).iloc[:, 1:].to_numpy() + ) + # Read energy table CSV, skip first column which is an index + # Each row corresponds to an ssd energy index and the columns map to a combination + # of gain and ssd id + energy_table = ( + pd.read_csv(energy_table_file_path, header=None, skiprows=1) + .iloc[:, 1:] + .to_numpy() + ) + return energy_table, tof_table + + +def get_geometric_factor_lut( + dependencies: ProcessingInputCollection | None, + path: Path | None = None, +) -> dict: + """ + Get the geometric factor lookup table. + + Parameters + ---------- + dependencies : ProcessingInputCollection + The collection of processing input files. + path : pathlib.Path + Optional path used for I-ALiRT. + + Returns + ------- + geometric_factor_lut : dict + A dict with a full and reduced mode array with shape (esa_steps, position). + """ + if path is not None: + csv_path = path + else: + csv_path = Path(dependencies.get_file_paths(descriptor="l2-lo-gfactor")[0]) + + geometric_factors = pd.read_csv(csv_path) + # sort by esa step. They should already be sorted, but just in case + full = geometric_factors[geometric_factors["mode"] == "full"].sort_values( + by="esa_step" + ) + reduced = geometric_factors[geometric_factors["mode"] == "reduced"].sort_values( + by="esa_step" + ) + + # Sort position columns to ensure the correct order + position_names_sorted = sorted( + [col for col in full if col.startswith("position")], + key=lambda x: int(x.split("_")[-1]), + ) + + return { + "full": full[position_names_sorted].to_numpy(), + "reduced": reduced[position_names_sorted].to_numpy(), + } + + +def get_efficiency_lut( + dependencies: ProcessingInputCollection | None, + path: Path | None = None, +) -> pd.DataFrame: + """ + Get the efficiency lookup table. + + Parameters + ---------- + dependencies : ProcessingInputCollection + The collection of processing input files. + path : pathlib.Path + Optional path used for I-ALiRT. + + Returns + ------- + efficiency_lut : pandas.DataFrame + Contains the efficiency lookup table. Columns are: + species, product, esa_step, position_1, position_2, ..., position_24. + """ + if path is not None: + csv_path = path + else: + csv_path = Path(dependencies.get_file_paths(descriptor="l2-lo-efficiency")[0]) + return pd.read_csv(csv_path) + + +def get_species_efficiency(species: str, efficiency: pd.DataFrame) -> xr.DataArray: + """ + Get the efficiency values for a given species. + + Parameters + ---------- + species : str + The species name. + efficiency : pandas.DataFrame + The efficiency lookup table. + + Returns + ------- + efficiency : xarray.DataArray + A 2D array of efficiencies with shape (epoch, esa_steps). + """ + species_efficiency = efficiency[efficiency["species"] == species].sort_values( + by="esa_step" + ) + # Sort position columns to ensure the correct order + position_names_sorted = sorted( + [col for col in species_efficiency if col.startswith("position")], + key=lambda x: int(x.split("_")[-1]), + ) + # Shape: (esa_step, inst_az) + return xr.DataArray( + species_efficiency[position_names_sorted].to_numpy(), + dims=("esa_step", "inst_az"), + ) + + +def compute_geometric_factors( + dataset: xr.Dataset, geometric_factor_lookup: dict, angular_product: bool = False +) -> xr.DataArray: + """ + Calculate geometric factors needed for intensity calculations. + + Geometric factors are determined by comparing the half-spin values per + esa_step in the HALF_SPIN_LUT to the rgfo_half_spin values in the provided + L2 dataset. + + If the half-spin value is less than the corresponding rgfo_half_spin value, + the geometric factor is set to 0.75 (full mode); otherwise, it is set to 0.5 + (reduced mode). If the data is from after November 24th 2025, then reduced + mode is no longer applied and the geometric factor is always set to full mode. + + NOTE: Half spin values are associated with ESA steps which corresponds to the + index of the energy_per_charge dimension that is between 0 and 127. + + NOTE: If packet_version = 2, the Lo L1B product now contains variables that indicate + the esa step and spin sector during which the RGFO or NSO limits are triggered. + The spin sector variable ranges from 0-11 and is the instrument reported spin + sector. In the following algorithm, spin_angle refers to the L1B angular bin + (0 – 23) which is despun and spin_sector refers to the non-despun spin sector + reported from the instrument (0-11). + + Parameters + ---------- + dataset : xarray.Dataset + The L2 dataset containing rgfo_half_spin data variable. + geometric_factor_lookup : dict + A dict with a full and reduced mode array with shape (esa_steps, position). + angular_product : bool + Whether the product being processed is an angular product. If True, then + the geometric factor calculation has additional steps to determine the exact + rgfo boundary. + + Returns + ------- + geometric_factors : xarray.DataArray + A 3D array of geometric factors with shape (epoch, esa_steps, positions). + """ + # Get half spin values per esa step from the dataset + # Add a new dim for spin_sector + half_spin_per_esa_step = dataset.half_spin_per_esa_step.values[:, :, np.newaxis] + # Expand dimensions to compare each rgfo_half_spin value against + # all half_spin_values and spin_sectors. Shape: (epoch, 1, 1) + rgfo_half_spin = dataset.rgfo_half_spin.data[:, np.newaxis, np.newaxis] + # After November 24th 2025 we need to do this step a different way. + start_date = dataset.attrs.get("Logical_file_id", None) + if start_date is None: + raise ValueError("Dataset is missing Logical_file_id attribute.") + processing_date = datetime.datetime.strptime(start_date.split("_")[4], "%Y%m%d") + date_switch = datetime.datetime(2025, 11, 24) + fsw_switch_date = datetime.datetime(2026, 1, 29) + # Only consider valid half spins + valid_half_spin = half_spin_per_esa_step != HALF_SPIN_FILLVAL + # TODO: Fix this calculation on days when the sci Lut changes. There may be + # different packet versions in the same dataset. + # Perform the comparison and calculate modes + if angular_product and dataset.packet_version.data[0] > 1: + # For angular products with packet version > 1, we have spin sector information + # to determine the exact boundary of the RGFO mode. Shape: (epoch, 1, 1) + # Mod by 12 to convert rgfo_spin_sector to half spin sector range of 0-11 + rgfo_spin_sector = dataset.rgfo_spin_sector.data[:, np.newaxis, np.newaxis] % 12 + rgfo_esa_step = dataset.rgfo_esa_step.data[:, np.newaxis, np.newaxis] + # Shape: (1, 1, spin_sector (24)) + spin_sector = dataset.spin_sector.data[np.newaxis, np.newaxis, :] + # Shape: (1, esa_step (128), 1) + esa_step = dataset.esa_step.data[np.newaxis, :, np.newaxis] + at_boundary = half_spin_per_esa_step == rgfo_half_spin + + modes = ( + # Reduced mode (True) is applied where: + # 1. Half spin is valid. + valid_half_spin + & ( + # 2. Half spin is greater than rgfo_half_spin. + (half_spin_per_esa_step > rgfo_half_spin) + | ( + # 3. Where half_spin_per_esa_step equals rgfo_half_spin AND + at_boundary + & ( + # a. The spin sector mod 12 is greater than rgfo_spin_sector + ((spin_sector % 12) > rgfo_spin_sector) + | + # b. OR the spin sector mod 12 equals rgfo_spin_sector AND the + # esa step is greater than rgfo_esa_step + ( + ((spin_sector % 12) == rgfo_spin_sector) + & (esa_step > rgfo_esa_step) + ) + ) + ) + ) + ) + elif (processing_date < date_switch) | (processing_date >= fsw_switch_date): + # Modes will be true (reduced mode) anywhere half_spin > rgfo_half_spin + # otherwise false (full mode) + modes = valid_half_spin & (half_spin_per_esa_step > rgfo_half_spin) + else: + # After November 24th, 2025, we no longer apply reduced geometric factors; + # always use the full geometric factor lookup. + modes = np.zeros_like(half_spin_per_esa_step, dtype=bool) + + # If the last dimension of modes is 24, we have spin sector information and + # need to apply the geometric factor lookup differently + if modes.shape[-1] == 24: + # Get the geometric factors based on the modes + # expand the mode array to include a dimension for "inst_az" (also shape=24) + modes = modes[:, :, :, np.newaxis] # Shape (epoch, esa_step, 24, 1) + gf = np.where( + modes, # Shape (epoch, esa_step, 24, 1) + geometric_factor_lookup["reduced"][:, np.newaxis, :], # (esa_step, 1, 24) + geometric_factor_lookup["full"][:, np.newaxis, :], # (esa_step, 1, 24) + ) # Shape: (epoch, esa_step, spin_sector, inst_az) + return xr.DataArray(gf, dims=("epoch", "esa_step", "spin_sector", "inst_az")) + else: + # Get the geometric factors based on the modes + gf = np.where( + modes, # Shape (epoch, esa_step, 1) + geometric_factor_lookup["reduced"], # (esa_step, 24) + geometric_factor_lookup["full"], # (esa_step, 24) + ) # Shape: (epoch, esa_step, inst_az) + return xr.DataArray(gf, dims=("epoch", "esa_step", "inst_az")) + + +def calculate_intensity( + dataset: xr.Dataset, + species_list: list, + geometric_factors: xr.DataArray, + efficiency: pd.DataFrame, + positions: list, + average_across_positions: bool = False, +) -> xr.Dataset: + """ + Calculate species or angular intensities. + + Parameters + ---------- + dataset : xarray.Dataset + The L2 dataset to process. + species_list : list + List of species variable names to calculate intensity. + geometric_factors : np.ndarray + The geometric factors array with shape (epoch, esa_steps). + efficiency : pandas.DataFrame + The efficiency lookup table. + positions : list + A list of position indices to select from the geometric factor and + efficiency lookup tables. + average_across_positions : bool + Whether to average the efficiencies and geometric factors across the selected + positions. Default is False. + + Returns + ------- + xarray.Dataset + The updated L2 dataset with species intensities calculated. + """ + # Select the relevant positions from the geometric factors + # TODO revisit gfactor calculation. For pickup ions, only position 0 is used + # Eventually, the CoDICE team wants to standardize this. + if species_list == LO_SW_PICKUP_ION_SPECIES_VARIABLE_NAMES: + geometric_factors = geometric_factors.isel(inst_az=[0]) + else: + geometric_factors = geometric_factors.isel(inst_az=positions) + if average_across_positions: + # take the mean geometric factor across positions + geometric_factors = geometric_factors.mean(dim="inst_az") + scalar = len(positions) + else: + scalar = 1 + # Calculate the angular intensities using the provided geometric factors and + # efficiency. + # intensity = species_rate / (gm * eff * esa_step) for position and spin angle + for species in species_list: + # Shape: (epoch, esa_step, inst_az) + species_eff = get_species_efficiency(species, efficiency).isel( + inst_az=positions + ) + if species_eff.size == 0: + logger.warning(f"No efficiency data found for species {species}. Skipping.") + continue + + if average_across_positions: + # Take the mean efficiency across positions + species_eff = species_eff.mean(dim="inst_az") + # Shape: (epoch, esa_step, inst_az) or + # (epoch, esa_step) if averaged + denominator = ( + scalar * geometric_factors * species_eff * dataset["energy_per_charge"] + ) + if species not in dataset: + raise ValueError(f"Species {species} not found in dataset.") + else: + # Only replace the data with calculated intensity to keep the attributes + dataset[species].data = (dataset[species] / denominator).data + + # Also calculate uncertainty if available + species_uncertainty = f"unc_{species}" + if species_uncertainty not in dataset: + logger.warning( + f"Uncertainty {species_uncertainty} not found in dataset." + f" Filling with NaNS." + ) + dataset[species_uncertainty] = np.full( + dataset["esa_step"].data.shape, np.nan + ) + else: + dataset[species_uncertainty].data = ( + dataset[species_uncertainty] / denominator + ).data + + return dataset + + +def process_lo_species_intensity( + dataset: xr.Dataset, + species_list: list, + geometric_factors: xr.DataArray, + efficiency: pd.DataFrame, + positions: list, +) -> xr.Dataset: + """ + Process the lo-species L2 dataset to calculate species intensities. + + Parameters + ---------- + dataset : xarray.Dataset + The L2 dataset to process. + species_list : list + List of species variable names to calculate intensity. + geometric_factors : xarray.DataArray + The geometric factors array with shape (epoch, esa_steps). + efficiency : pandas.DataFrame + The efficiency lookup table. + positions : list + A list of position indices to select from the geometric factor and + efficiency lookup tables. + + Returns + ------- + xarray.Dataset + The updated L2 dataset with species intensities calculated. + """ + # Calculate the species intensities using the provided geometric factors and + # efficiency. + dataset = calculate_intensity( + dataset, + species_list, + geometric_factors, + efficiency, + positions, + average_across_positions=True, + ) + cdf_attrs = ImapCdfAttributes() + cdf_attrs.add_instrument_variable_attrs("codice", "l2-lo-species") + if positions == SOLAR_WIND_POSITIONS: + species_attrs = cdf_attrs.get_variable_attributes("lo-sw-species-attrs") + unc_attrs = cdf_attrs.get_variable_attributes("lo-sw-species-unc-attrs") + elif positions == PUI_POSITIONS: + species_attrs = cdf_attrs.get_variable_attributes("lo-pui-species-attrs") + unc_attrs = cdf_attrs.get_variable_attributes("lo-pui-species-unc-attrs") + else: + species_attrs = cdf_attrs.get_variable_attributes("lo-species-attrs") + unc_attrs = cdf_attrs.get_variable_attributes("lo-species-unc-attrs") + + # add uncertainties to species list + species_list = species_list + [f"unc_{var}" for var in species_list] + # update species attrs + for species in species_list: + attrs = unc_attrs if "unc" in species else species_attrs + # Replace {species} and {direction} in attrs + attrs = apply_replacements_to_attrs(attrs, {"species": species}) + dataset[species].attrs.update(attrs) + + # Since the RGFO mode is implemented within a half-spin at a given esa step and + # spin sector and since the species data is summed over all spin sectors, the data + # during this half spin cannot be de-convolved. Thus, the intensity during the + # half_spin = RGFO_half_spin should be set to fill values. + half_spin_boundary = ( + dataset.half_spin_per_esa_step.data + == dataset.rgfo_half_spin.data[:, np.newaxis] + ) + # Add an extra dimension to match the species data shape (361, 128, 1) + half_spin_boundary = half_spin_boundary[:, :, np.newaxis] + + for species in species_list: + dataset[species].data[half_spin_boundary] = np.nan + + return dataset + + +def process_hi_omni(dependencies: ProcessingInputCollection) -> xr.Dataset: + """ + Process the hi-omni L1B dataset to calculate omni-directional intensities. + + See section 11.1.3 of the CoDICE algorithm document for details. + + The formula for omni-directional intensities is:: + + l1B species data / ( + geometric_factor * number_of_ssd * efficiency * energy_passband + ) + + Geometric factor is constant for all species which is 0.013. + Number of SSD is constant for all species which is 12. + Efficiency is provided in a CSV file for each species and energy bin. + Energy passband is calculated from L1B variables energy_bin_minus + energy_bin_plus + + Parameters + ---------- + dependencies : ProcessingInputCollection + The collection of processing input files. + + Returns + ------- + xarray.Dataset + The updated L2 dataset with omni-directional intensities calculated. + """ + l1b_file = dependencies.get_file_paths(descriptor="hi-omni")[0] + l1b_dataset = load_cdf(l1b_file) + + # Read the efficiencies data from the CSV file + efficiencies_file = dependencies.get_file_paths(descriptor="l2-hi-omni-efficiency")[ + 0 + ] + efficiencies_df = pd.read_csv(efficiencies_file) + # Omni product has 8 species and each species has different shape. + # Eg. + # h - (epoch, 15) + # c - (epoch, 18) + # uh - (epoch, 5) + # etc. + # Because of that, we need to loop over each species and calculate + # omni-directional intensities separately. + # Read geometric factor. It is labeled as GF in the CSV file + geometric_factor = efficiencies_df[efficiencies_df["species"] == "GF"].values[0][-1] + for species in HI_OMNI_VARIABLE_NAMES: + # replace '_' with '-' to match CSV species naming + species_csv_name = species.replace("_", "-") + species_data = efficiencies_df[efficiencies_df["species"] == species_csv_name] + # Read current species' efficiency + species_efficiencies = species_data["average_efficiency"].values[np.newaxis, :] + # Calculate energy passband from L1B data + energy_passbands = ( + l1b_dataset[f"energy_{species}_plus"] + + l1b_dataset[f"energy_{species}_minus"] + ).values[np.newaxis, :] + # Calculate omni-directional intensities + omni_direction_intensities = l1b_dataset[species] / ( + geometric_factor * species_efficiencies * energy_passbands + ) + # Store by replacing existing species data with omni-directional intensities + l1b_dataset[species].values = omni_direction_intensities + + # Calculate uncertainty if available + species_uncertainty = f"unc_{species}" + if species_uncertainty in l1b_dataset: + omni_uncertainties = l1b_dataset[species_uncertainty] / ( + geometric_factor * species_efficiencies * energy_passbands + ) + # Store by replacing existing uncertainty data with omni-directional + # uncertainties + l1b_dataset[species_uncertainty].values = omni_uncertainties + + # TODO: this may go away once Joey and I fix L1B CDF + # Update global CDF attributes + cdf_attrs = ImapCdfAttributes() + cdf_attrs.add_instrument_global_attrs("codice") + cdf_attrs.add_instrument_variable_attrs("codice", "l2-hi-omni") + l1b_dataset.attrs = cdf_attrs.get_global_attributes("imap_codice_l2_hi-omni") + + # TODO: ask Joey to add attrs for epoch_delta_plus and epoch_delta_minus + # and update dimension to be 'epoch' in L1B data + for variable in l1b_dataset.data_vars: + if variable in ["epoch_delta_plus", "epoch_delta_minus", "data_quality"]: + l1b_dataset[variable].attrs = cdf_attrs.get_variable_attributes( + variable, check_schema=False + ) + else: + l1b_dataset[variable].attrs = cdf_attrs.get_variable_attributes( + variable, check_schema=False + ) + + # Add these new coordinates + new_coords = { + "energy_h": xr.DataArray( + l1b_dataset["energy_h"].values, + dims=("energy_h",), + attrs=cdf_attrs.get_variable_attributes("energy_h", check_schema=False), + ), + "energy_h_label": xr.DataArray( + l1b_dataset["energy_h"].values.astype(str), + dims=("energy_h",), + attrs=cdf_attrs.get_variable_attributes( + "energy_h_label", check_schema=False + ), + ), + "energy_he3": xr.DataArray( + l1b_dataset["energy_he3"].values, + dims=("energy_he3",), + attrs=cdf_attrs.get_variable_attributes("energy_he3", check_schema=False), + ), + "energy_he3_label": xr.DataArray( + l1b_dataset["energy_he3"].values.astype(str), + dims=("energy_he3",), + attrs=cdf_attrs.get_variable_attributes( + "energy_he3_label", check_schema=False + ), + ), + "energy_he4": xr.DataArray( + l1b_dataset["energy_he4"].values, + dims=("energy_he4",), + attrs=cdf_attrs.get_variable_attributes("energy_he4", check_schema=False), + ), + "energy_he4_label": xr.DataArray( + l1b_dataset["energy_he4"].values.astype(str), + dims=("energy_he4",), + attrs=cdf_attrs.get_variable_attributes( + "energy_he4_label", check_schema=False + ), + ), + "energy_c": xr.DataArray( + l1b_dataset["energy_c"].values, + dims=("energy_c",), + attrs=cdf_attrs.get_variable_attributes("energy_c", check_schema=False), + ), + "energy_c_label": xr.DataArray( + l1b_dataset["energy_c"].values.astype(str), + dims=("energy_c",), + attrs=cdf_attrs.get_variable_attributes( + "energy_c_label", check_schema=False + ), + ), + "energy_o": xr.DataArray( + l1b_dataset["energy_o"].values, + dims=("energy_o",), + attrs=cdf_attrs.get_variable_attributes("energy_o", check_schema=False), + ), + "energy_o_label": xr.DataArray( + l1b_dataset["energy_o"].values.astype(str), + dims=("energy_o",), + attrs=cdf_attrs.get_variable_attributes( + "energy_o_label", check_schema=False + ), + ), + "energy_ne_mg_si": xr.DataArray( + l1b_dataset["energy_ne_mg_si"].values, + dims=("energy_ne_mg_si",), + attrs=cdf_attrs.get_variable_attributes( + "energy_ne_mg_si", check_schema=False + ), + ), + "energy_ne_mg_si_label": xr.DataArray( + l1b_dataset["energy_ne_mg_si"].values.astype(str), + dims=("energy_ne_mg_si",), + attrs=cdf_attrs.get_variable_attributes( + "energy_ne_mg_si_label", check_schema=False + ), + ), + "energy_fe": xr.DataArray( + l1b_dataset["energy_fe"].values, + dims=("energy_fe",), + attrs=cdf_attrs.get_variable_attributes("energy_fe", check_schema=False), + ), + "energy_fe_label": xr.DataArray( + l1b_dataset["energy_fe"].values.astype(str), + dims=("energy_fe",), + attrs=cdf_attrs.get_variable_attributes( + "energy_fe_label", check_schema=False + ), + ), + "energy_uh": xr.DataArray( + l1b_dataset["energy_uh"].values, + dims=("energy_uh",), + attrs=cdf_attrs.get_variable_attributes("energy_uh", check_schema=False), + ), + "energy_uh_label": xr.DataArray( + l1b_dataset["energy_uh"].values.astype(str), + dims=("energy_uh",), + attrs=cdf_attrs.get_variable_attributes( + "energy_uh_label", check_schema=False + ), + ), + "energy_junk": xr.DataArray( + l1b_dataset["energy_junk"].values, + dims=("energy_junk",), + attrs=cdf_attrs.get_variable_attributes("energy_junk", check_schema=False), + ), + "energy_junk_label": xr.DataArray( + l1b_dataset["energy_junk"].values.astype(str), + dims=("energy_junk",), + attrs=cdf_attrs.get_variable_attributes( + "energy_junk_label", check_schema=False + ), + ), + "epoch": xr.DataArray( + l1b_dataset["epoch"].data, + dims=("epoch",), + attrs=cdf_attrs.get_variable_attributes("epoch", check_schema=False), + ), + "epoch_delta_plus": l1b_dataset["epoch_delta_plus"], + "epoch_delta_minus": l1b_dataset["epoch_delta_minus"], + } + + l1b_dataset["epoch"].attrs["DELTA_MINUS_VAR"] = "epoch_delta_minus" + l1b_dataset["epoch"].attrs["DELTA_PLUS_VAR"] = "epoch_delta_plus" + + l1b_dataset = l1b_dataset.assign_coords(new_coords) + + return l1b_dataset + + +def process_hi_sectored(dependencies: ProcessingInputCollection) -> xr.Dataset: + """ + Process the hi-omni L1B dataset to calculate omni-directional intensities. + + See section 11.1.2 of the CoDICE algorithm document for details. + + The formula for omni-directional intensities is:: + + l1b species data / (geometric_factor * efficiency * energy_passband) + + Geometric factor is constant for all species and is 0.013. + Efficiency is provided in a CSV file for each species and energy bin and + position. + Energy passband is calculated from energy_bin_minus + energy_bin_plus + + Parameters + ---------- + dependencies : ProcessingInputCollection + The collection of processing input files. + + Returns + ------- + xarray.Dataset + The updated L2 dataset with omni-directional intensities calculated. + """ + file_path = dependencies.get_file_paths(descriptor="hi-sectored")[0] + l1b_dataset = load_cdf(file_path) + + # Update global CDF attributes + cdf_attrs = ImapCdfAttributes() + cdf_attrs.add_instrument_global_attrs("codice") + cdf_attrs.add_instrument_variable_attrs("codice", "l2-hi-sectored") + + # Overwrite L1B variable attributes with L2 variable attributes + l2_dataset = xr.Dataset( + coords={ + "spin_sector": l1b_dataset["spin_sector"], + "spin_sector_label": xr.DataArray( + l1b_dataset["spin_sector"].values.astype(str), + dims=("spin_sector",), + attrs=cdf_attrs.get_variable_attributes( + "spin_sector_label", check_schema=False + ), + ), + "energy_h": xr.DataArray( + l1b_dataset["energy_h"].values, + dims=("energy_h",), + attrs=cdf_attrs.get_variable_attributes("energy_h", check_schema=False), + ), + "energy_h_label": xr.DataArray( + l1b_dataset["energy_h"].values.astype(str), + dims=("energy_h",), + attrs=cdf_attrs.get_variable_attributes( + "energy_h_label", check_schema=False + ), + ), + "energy_he3he4": xr.DataArray( + l1b_dataset["energy_he3he4"].values, + dims=("energy_he3he4",), + attrs=cdf_attrs.get_variable_attributes( + "energy_he3he4", check_schema=False + ), + ), + "energy_he3he4_label": xr.DataArray( + l1b_dataset["energy_he3he4"].values.astype(str), + dims=("energy_he3he4",), + attrs=cdf_attrs.get_variable_attributes( + "energy_he3he4_label", check_schema=False + ), + ), + "energy_cno": xr.DataArray( + l1b_dataset["energy_cno"].values, + dims=("energy_cno",), + attrs=cdf_attrs.get_variable_attributes( + "energy_cno", check_schema=False + ), + ), + "energy_cno_label": xr.DataArray( + l1b_dataset["energy_cno"].values.astype(str), + dims=("energy_cno",), + attrs=cdf_attrs.get_variable_attributes( + "energy_cno_label", check_schema=False + ), + ), + "energy_fe": xr.DataArray( + l1b_dataset["energy_fe"].values, + dims=("energy_fe",), + attrs=cdf_attrs.get_variable_attributes( + "energy_fe", check_schema=False + ), + ), + "energy_fe_label": xr.DataArray( + l1b_dataset["energy_fe"].values.astype(str), + dims=("energy_fe",), + attrs=cdf_attrs.get_variable_attributes( + "energy_fe_label", check_schema=False + ), + ), + "epoch": l1b_dataset["epoch"], + "epoch_delta_plus": l1b_dataset["epoch_delta_plus"], + "epoch_delta_minus": l1b_dataset["epoch_delta_minus"], + "elevation_angle": xr.DataArray( + HI_L2_ELEVATION_ANGLE, + dims=("elevation_angle",), + attrs=cdf_attrs.get_variable_attributes( + "elevation_angle", check_schema=False + ), + ), + "elevation_angle_label": xr.DataArray( + HI_L2_ELEVATION_ANGLE.astype(str), + dims=("elevation_angle",), + attrs=cdf_attrs.get_variable_attributes( + "elevation_angle_label", check_schema=False + ), + ), + }, + attrs=cdf_attrs.get_global_attributes("imap_codice_l2_hi-sectored"), + ) + + l1b_dataset["epoch"].attrs["DELTA_MINUS_VAR"] = "epoch_delta_minus" + l1b_dataset["epoch"].attrs["DELTA_PLUS_VAR"] = "epoch_delta_plus" + + efficiencies_file = dependencies.get_file_paths( + descriptor="l2-hi-sectored-efficiency" + )[0] + + # Calculate sectored intensities + efficiencies_df = pd.read_csv(efficiencies_file) + # Similar to hi-omni, each species has different shape. + # Because of that, we need to loop over each species and calculate + # sectored intensities separately. + for species in HI_SECTORED_VARIABLE_NAMES: + # Efficiencies from dataframe maps to different dimension in L1B data. + # For example: + # l1b species 'h' has shape: + # (epoch, 8, 12, 12) -> (time, energy, spin_sector, inst_az) + # efficiencies 'h' has shape after reading from CSV: + # (8, 12) -> (energy, inst_az) + # NOTE: 12 here maps to last 12 in above l1b dimension. + # Because of this, it's easier to work with the data in xarray. + # Xarray automatically aligns dimensions and coordinates, making it easier + # to work with multi-dimensional data. Thus, we convert the efficiencies + # to xarray.DataArray with dimensions (energy, inst_az) + species_data = efficiencies_df[efficiencies_df["species"] == species].values + species_efficiencies = xr.DataArray( + species_data[:, 2:].astype( + float + ), # Skip first two columns (species, energy_bin) + dims=(f"energy_{species}", "inst_az"), + coords=l1b_dataset[[f"energy_{species}", "inst_az"]], + ) + # Read geometric factor. It is labeled as GF in the CSV file + geometric_factor = efficiencies_df[efficiencies_df["species"] == "GF"].values + geometric_factor_da = xr.DataArray( + geometric_factor[0, 2:].astype( + np.float64 + ), # Skip first two columns (species, energy_bin) + dims="inst_az", + coords=l1b_dataset[["inst_az"]], + ) + # energy_passbands has shape: + # (8,) -> (energy) + energy_passbands = xr.DataArray( + l1b_dataset[f"energy_{species}_minus"] + + l1b_dataset[f"energy_{species}_plus"], + dims=(f"energy_{species}",), + coords=l2_dataset[[f"energy_{species}"]], + name="passband", + ) + + sectored_intensities = l1b_dataset[species] / ( + geometric_factor_da * species_efficiencies * energy_passbands + ) + + # Replace existing species data with omni-directional intensities + species_attrs = cdf_attrs.get_variable_attributes(species, check_schema=False) + # Replace {species} in attributes with actual species name + species_attrs = apply_replacements_to_attrs(species_attrs, {"species": species}) + + l2_dataset[species] = xr.DataArray( + sectored_intensities.data, + dims=("epoch", f"energy_{species}", "spin_sector", "elevation_angle"), + attrs=species_attrs, + ) + # Calculate uncertainty if available + species_uncertainty = f"unc_{species}" + if species_uncertainty in l1b_dataset: + sectored_uncertainties = l1b_dataset[species_uncertainty] / ( + geometric_factor_da * species_efficiencies * energy_passbands + ) + unc_species_attrs = cdf_attrs.get_variable_attributes( + species_uncertainty, check_schema=False + ) + # Replace {species} in attributes with actual species name + unc_species_attrs = apply_replacements_to_attrs( + unc_species_attrs, {"species": species} + ) + + l2_dataset[species_uncertainty] = xr.DataArray( + sectored_uncertainties.data, + dims=("epoch", f"energy_{species}", "spin_sector", "elevation_angle"), + attrs=unc_species_attrs, + ) + + # Calculate spin angle + # Formula: + # ΞΈ_(k,n) = (ΞΈ_(k,0)+30Β°* n) mod 360Β° + # where + # n is size of L2_HI_SECTORED_ANGLE, 0 to 11, + # k is size of inst_az from l1b, 0 to 11, + # Calculate spin angle by adding a base angle from L2_HI_SECTORED_ANGLE + # for each SSD index and then adding multiple of 30 degrees for each elevation. + # Then mod by 360 to keep it within 0-360 range. + # Determine number of bins from dataset dimensions + n_spin = l2_dataset.sizes["spin_sector"] + n_elev = l2_dataset.sizes["elevation_angle"] + + # Elevation-dependent offset: 0, 30, 60, ... for each elevation bin + elevation_offsets = np.arange(n_elev, dtype=float).reshape(1, n_elev) * 30.0 + + # Base spin angle per spin sector, broadcast across elevation_angle + base_angles = np.asarray(L2_HI_SECTORED_ANGLE, dtype=float).reshape(n_spin, 1) + + spin_angle = (base_angles + elevation_offsets) % 360.0 + # We need to transpose spin_angle to put spin_angle data into correct + # dimensions. Eg. + # spin_angle[0,0] - 285 + # spin_angle[1,0] - 315 + # .... + # This is expected behavior per CoDICE because the spin angle should increments + # at 30 degree spin angle per elevation angle. Due to that, in the example, the + # column remained same but spin angle incremented by 30 degrees for each + # elevation angle. + spin_angle = spin_angle.T + # Add spin angle variable using the new elevation_angle dimension + l2_dataset["spin_angle"] = (("spin_sector", "elevation_angle"), spin_angle) + l2_dataset["spin_angle"].attrs = cdf_attrs.get_variable_attributes( + "spin_angle", check_schema=False + ) + + # Now carry over other variables from L1B to L2 dataset + for variable in l1b_dataset.data_vars: + if variable.startswith("epoch_") and variable != "epoch": + # get attrs with just that name + l2_dataset[variable] = xr.DataArray( + l1b_dataset[variable].data, + dims=("epoch",), + attrs=cdf_attrs.get_variable_attributes(variable, check_schema=False), + ) + elif variable.startswith("energy_"): + l2_dataset[variable] = xr.DataArray( + l1b_dataset[variable].data, + dims=(f"energy_{variable.split('_')[1]}",), + attrs=cdf_attrs.get_variable_attributes(variable, check_schema=False), + ) + elif variable == "data_quality": + l2_dataset[variable] = l1b_dataset[variable] + l2_dataset[variable].attrs.update( + cdf_attrs.get_variable_attributes(variable, check_schema=False) + ) + + l2_dataset["epoch"].attrs.update( + cdf_attrs.get_variable_attributes("epoch", check_schema=False) + ) + return l2_dataset + + +def process_lo_direct_events(dependencies: ProcessingInputCollection) -> xr.Dataset: + """ + Process the lo-direct-events L1A dataset to convert variables to physical units. + + See section 11.2.1 of the CoDICE algorithm document for details. + + Parameters + ---------- + dependencies : ProcessingInputCollection + The collection of processing input files. + + Returns + ------- + xarray.Dataset + The updated L2 dataset with variables converted to physical units. + """ + file_path = dependencies.get_file_paths(descriptor="lo-direct-events")[0] + l1a_dataset = load_cdf(file_path) + + # Update global CDF attributes + cdf_attrs = ImapCdfAttributes() + cdf_attrs.add_instrument_global_attrs("codice") + cdf_attrs.add_instrument_variable_attrs("codice", "l2-lo-direct-events") + energy_table, energy_bins = get_lo_de_energy_luts(dependencies) + # Convert from position to elevation angle in degrees relative to the spacecraft + # axis + l2_dataset = l1a_dataset + # Create a new coordinate for elevation_angle based on inst_az + pos_to_els = ( + LO_POSITION_TO_ELEVATION_ANGLE["sw"] | LO_POSITION_TO_ELEVATION_ANGLE["nsw"] + ) + elevation_angle_shape = l2_dataset["position"].shape + elevation_angle = np.array( + [pos_to_els.get(pos, np.nan) for pos in l2_dataset["position"].values.flat] + ).reshape(elevation_angle_shape) + l2_dataset["elevation_angle"] = ( + l2_dataset["position"].dims, + elevation_angle.astype(np.float32), + ) + # Convert spin_sector to spin_angle in degrees + # Use equation from section 11.2.2 of algorithm document + # Shift all spin sectors for all positions 13 - 24 adding 12 and mod 24 + original_spin_sector = l2_dataset["spin_sector"].values + l2_dataset["spin_sector"] = xr.where( + (l2_dataset["position"] >= 13) & (l2_dataset["position"] <= 24), + (l2_dataset["spin_sector"] + 12) % 24, + l2_dataset["spin_sector"], + ) + l2_dataset["spin_angle"] = l2_dataset["spin_sector"].astype(np.float32) * 15.0 + 7.5 + + # Set spin angle and sector to NaN for invalid positions (>23) + l2_dataset["spin_angle"] = xr.where( + (original_spin_sector > 23), np.nan, l2_dataset["spin_angle"] + ) + l2_dataset["spin_sector"] = xr.where( + (original_spin_sector > 23), np.nan, l2_dataset["spin_sector"] + ) + # convert apd energy to physical units + # Set the gain labels based on gain values + gains = l2_dataset["gain"].values.ravel() + apd_ids = l2_dataset["apd_id"].values.ravel() + apd_energy = l2_dataset["apd_energy"].values.ravel() + apd_energy_shape = l2_dataset["apd_energy"].shape + + # The energy table lookup columns are ordered by apd_id and gain + # E.g. APD-1-LG, APD-1-HG, ..., APD-29-LG + # So we can get the col index like so: ind = apd_id * 2 + gain + col_inds = apd_ids * 2 + gains + # Get a mask of valid indices + valid_mask = ( + (apd_energy < energy_table.shape[0]) + & (col_inds < energy_table.shape[1]) + & (apd_ids > 0) + ) + # Initialize output array with NaNs + energy_bins_inds = np.full(apd_energy.shape, np.nan) + energy_kev = np.full(apd_energy.shape, np.nan) + # The rows are apd_energy bins + energy_bins_inds[valid_mask] = energy_table[ + apd_energy[valid_mask], col_inds[valid_mask] + ] + energy_kev[valid_mask] = energy_bins[energy_bins_inds[valid_mask].astype(int)] + + l2_dataset["apd_energy"].data = ( + np.array(energy_kev).astype(np.float32).reshape(apd_energy_shape) + ) + + # Calculate TOF in nanoseconds + tof_bit_to_ns = get_mpq_calc_tof_conversion_vals(dependencies) + tof_bits = l2_dataset["tof"].values.flatten() + # Create output array + tof_ns = np.full(tof_bits.shape, np.nan, dtype=np.float64) + # Get only valid TOF bits between 0 and 1023 + valid_mask = (tof_bits >= 0) & (tof_bits < 1024) + tof_ns[valid_mask] = tof_bit_to_ns[tof_bits[valid_mask]] + # Reshape back to original shape + l2_dataset["tof"].data = tof_ns.astype(np.float32).reshape(l2_dataset["tof"].shape) + + # Convert energy step to energy in keV + esa_kev = get_mpq_calc_energy_conversion_vals(dependencies) + energy_steps = l2_dataset["energy_step"].values.flatten() + # Create output array + kev = np.full(energy_steps.shape, np.nan, dtype=np.float64) + # Get only valid energy_steps between 0 and 128 + valid_mask = (energy_steps >= 0) & (energy_steps < 128) + kev[valid_mask] = esa_kev[energy_steps[valid_mask]] + # Reshape back to original shape + l2_dataset["energy_per_charge"] = ( + l2_dataset["energy_step"].dims, + kev.astype(np.float32).reshape(l2_dataset["energy_step"].shape), + ) + # Drop unused variables + vars_to_drop = ["spare", "sw_bias_gain_mode", "st_bias_gain_mode", "k_factor"] + l2_dataset = l2_dataset.drop_vars(vars_to_drop) + # Update variable attributes + l2_dataset.attrs.update( + cdf_attrs.get_global_attributes("imap_codice_l2_lo-direct-events") + ) + for var in l2_dataset.data_vars: + if "nso" in var or "rgfo" in var: + # skip adding attributes for these variables. They should already + # have attrs carried over from l1a. + continue + l2_dataset[var].attrs.update(cdf_attrs.get_variable_attributes(var)) + # Update coord attributes + l2_dataset["priority"].attrs.update( + cdf_attrs.get_variable_attributes("priority", check_schema=False) + ) + l2_dataset["event_num"].attrs.update( + cdf_attrs.get_variable_attributes("event_num", check_schema=False) + ) + l2_dataset["epoch"] = xr.DataArray( + l2_dataset["epoch"].data, + dims="epoch", + attrs=cdf_attrs.get_variable_attributes("epoch", check_schema=False), + ) + # Add labels + l2_dataset["event_num_label"] = xr.DataArray( + l2_dataset["event_num"].values.astype(str).astype(" xr.Dataset: + """ + Process the hi-direct-events L1A dataset to convert variables to physical units. + + See section 11.2.1 of the CoDICE algorithm document for details. + + Parameters + ---------- + dependencies : ProcessingInputCollection + The collection of processing input files. + + Returns + ------- + xarray.Dataset + The updated L2 dataset with variables converted to physical units. + """ + file_path = dependencies.get_file_paths(descriptor="hi-direct-events")[0] + l1a_dataset = load_cdf(file_path) + + # Update global CDF attributes + cdf_attrs = ImapCdfAttributes() + cdf_attrs.add_instrument_global_attrs("codice") + cdf_attrs.add_instrument_variable_attrs("codice", "l2-hi-direct-events") + + l2_dataset = l1a_dataset + # Load energy table and tof table needed for conversions + energy_table, tof_table = get_hi_de_luts(dependencies) + # Initialize nan array for calculations + nan_array = np.full(l2_dataset["ssd_id"].shape, np.nan) + # Convert from position to elevation angle in degrees relative to the spacecraft + # axis + ssd_id = l2_dataset["ssd_id"].values + valid_ssd = (ssd_id <= 15) & (ssd_id >= 0) + + elevation = nan_array.copy() + elevation[valid_ssd] = SSD_ID_TO_ELEVATION[ssd_id[valid_ssd]] + l2_dataset["elevation_angle"] = xr.DataArray( + data=elevation.astype(np.float32), dims=l2_dataset["ssd_id"].dims + ) + # Calculate ssd energy in meV + gain = l2_dataset["gain"].values + ssd_energy = l2_dataset["ssd_energy"].values + valid_mask = ( + (np.isin(gain, list(GAIN_ID_TO_STR.keys()))) + & valid_ssd + & (ssd_energy != len(energy_table)) + ) + # The columns are organized in order of id and gains + # E.g. ssd 0 - LG, ssd 0 - MG, ssd 0 - HG, ssd 1 - LG, ssd 1 - MG, ssd 1 - HG, ... + cols = ssd_id * 3 + (gain - 1) + ssd_energy_converted = nan_array.copy() + ssd_energy_converted[valid_mask] = energy_table[ + ssd_energy[valid_mask], cols[valid_mask] + ] + l2_dataset["ssd_energy"].data = ssd_energy_converted.astype(np.float32) + + # Convert spin_sector to spin_angle in degrees + theta_angles = nan_array.copy() + theta_angles[valid_ssd] = SSD_ID_TO_SPIN_ANGLE[ssd_id[valid_ssd]] + l2_dataset["spin_angle"] = ( + (theta_angles + 15.0 * l2_dataset["spin_sector"]) % 360.0 + ).astype(np.float32) + + # Calculate TOF in ns + tof = l2_dataset["tof"].values + # Get valid TOF indices for lookup + valid_tof_mask = tof < tof_table.shape[0] + tof_ns = nan_array.copy() + # Get tof values in ns from first column of tof_table + tof_ns[valid_tof_mask] = tof_table[tof[valid_tof_mask], 0] + l2_dataset["tof"] = xr.DataArray( + data=tof_ns, + dims=l2_dataset["tof"].dims, + ).astype(np.float32) + + # Calculate energy per nuc + energy_nuc = nan_array.copy() + # Get value from second column of tof_table (E/n (MeV/n)) + energy_nuc[valid_tof_mask] = tof_table[tof[valid_tof_mask], 1] + l2_dataset["energy_per_nuc"] = xr.DataArray( + data=energy_nuc, + dims=l2_dataset["tof"].dims, + ).astype(np.float32) + # Drop unused variables + vars_to_drop = [ + "spare", + "sw_bias_gain_mode", + "st_bias_gain_mode", + "rgfo_esa_step", + "rgfo_spin_sector", + "rgfo_half_spin", + "nso_esa_step", + "nso_spin_sector", + "nso_half_spin", + ] + l2_dataset = l2_dataset.drop_vars(vars_to_drop) + # Update variable attributes + l2_dataset.attrs.update( + cdf_attrs.get_global_attributes("imap_codice_l2_hi-direct-events") + ) + for var in l2_dataset.data_vars: + l2_dataset[var].attrs.update(cdf_attrs.get_variable_attributes(var)) + # Update coord attributes + l2_dataset["priority"].attrs.update( + cdf_attrs.get_variable_attributes("priority", check_schema=False) + ) + l2_dataset["event_num"].attrs.update( + cdf_attrs.get_variable_attributes("event_num", check_schema=False) + ) + l2_dataset["epoch"] = xr.DataArray( + l2_dataset["epoch"].data, + dims="epoch", + attrs=cdf_attrs.get_variable_attributes("epoch", check_schema=False), + ) + # Add labels + l2_dataset["event_num_label"] = xr.DataArray( + l2_dataset["event_num"].values.astype(str).astype(" xr.Dataset: """ Will process CoDICE l1 data to create l2 data products. Parameters ---------- - file_path : pathlib.Path - Path to the CoDICE L1 file to process. + descriptor : str + The descriptor for the CoDICE L1 file to process. + dependencies : ProcessingInputCollection + Collection of processing inputs such as ancillary data files. Returns ------- l2_dataset : xarray.Dataset The``xarray`` dataset containing the science data and supporting metadata. """ - logger.info(f"Processing {file_path}") - - # Open the l1 file - l1_dataset = load_cdf(file_path) + # This should get science files since ancillary or spice doesn't have data_type + # as data level. + file_path = dependencies.get_file_paths(descriptor=descriptor)[0] + # Now form product name from descriptor + descriptor = ScienceFilePath(file_path).descriptor + dataset_name = f"imap_codice_l2_{descriptor}" + # TODO: update list of datasets that need geometric factors (if needed) + # Compute geometric factors needed for intensity calculations + if dataset_name in [ + "imap_codice_l2_lo-sw-species", + ]: + cdf_attrs = ImapCdfAttributes() + cdf_attrs.add_instrument_global_attrs("codice") - # Use the logical source as a way to distinguish between data products and - # set some useful distinguishing variables - # TODO: Could clean this up by using imap-data-access methods? - dataset_name = l1_dataset.attrs["Logical_source"] - data_level = dataset_name.removeprefix("imap_codice_").split("_")[0] - dataset_name = dataset_name.replace(data_level, "l2") + l2_dataset = load_cdf(file_path).copy() - # Use the L1 data product as a starting point for L2 - l2_dataset = l1_dataset.copy() + geometric_factor_lookup = get_geometric_factor_lut(dependencies) + efficiency_lookup = get_efficiency_lut(dependencies) - # Get the L2 CDF attributes - cdf_attrs = ImapCdfAttributes() - l2_dataset = add_dataset_attributes(l2_dataset, dataset_name, cdf_attrs) + if dataset_name == "imap_codice_l2_lo-sw-species": + geometric_factors = compute_geometric_factors( + l2_dataset, geometric_factor_lookup + ) + # Filter the efficiency lookup table for solar wind efficiencies + efficiencies = efficiency_lookup[efficiency_lookup["product"] == "sw"] + # Calculate the pickup ion sunward solar wind intensities using equation + # described in section 11.2.3 of algorithm document. + l2_dataset = process_lo_species_intensity( + l2_dataset, + LO_SW_PICKUP_ION_SPECIES_VARIABLE_NAMES, + geometric_factors, + efficiencies, + PUI_POSITIONS, + ) + # Calculate the sunward solar wind species intensities using equation + # described in section 11.2.3 of algorithm document. + l2_dataset = process_lo_species_intensity( + l2_dataset, + LO_SW_SOLAR_WIND_SPECIES_VARIABLE_NAMES, + geometric_factors, + efficiencies, + SOLAR_WIND_POSITIONS, + ) + l2_dataset.attrs.update( + cdf_attrs.get_global_attributes("imap_codice_l2_lo-sw-species") + ) if dataset_name in [ "imap_codice_l2_hi-counters-singles", @@ -63,6 +1408,7 @@ def process_codice_l2(file_path: Path) -> xr.Dataset: "imap_codice_l2_lo-nsw-priority", ]: # No changes needed. Just save to an L2 CDF file. + # TODO: May not even need L2 files for these products pass elif dataset_name == "imap_codice_l2_hi-direct-events": @@ -75,18 +1421,18 @@ def process_codice_l2(file_path: Path) -> xr.Dataset: # These converted variables are *in addition* to the existing L1 variables # The other data variables require no changes # See section 11.1.2 of algorithm document - pass + l2_dataset = process_hi_direct_events(dependencies) elif dataset_name == "imap_codice_l2_hi-sectored": # Convert the sectored count rates using equation described in section # 11.1.3 of algorithm document. - pass + l2_dataset = process_hi_sectored(dependencies) elif dataset_name == "imap_codice_l2_hi-omni": # Calculate the omni-directional intensity for each species using # equation described in section 11.1.4 of algorithm document # hopefully this can also apply to hi-ialirt - pass + l2_dataset = process_hi_omni(dependencies) elif dataset_name == "imap_codice_l2_lo-direct-events": # Convert the following data variables to physical units using @@ -99,82 +1445,21 @@ def process_codice_l2(file_path: Path) -> xr.Dataset: # These converted variables are *in addition* to the existing L1 variables # The other data variables require no changes # See section 11.1.2 of algorithm document - pass - - elif dataset_name == "imap_codice_l2_lo-sw-angular": - # Calculate the sunward angular intensities using equation described in - # section 11.2.3 of algorithm document. - pass - - elif dataset_name == "imap_codice_l2_lo-nsw-angular": - # Calculate the non-sunward angular intensities using equation described - # in section 11.2.3 of algorithm document. - pass - - elif dataset_name == "imap_codice_l2_lo-sw-species": - # Calculate the sunward solar wind species intensities using equation - # described in section 11.2.4 of algorithm document. - # Calculate the pickup ion sunward solar wind intensities using equation - # described in section 11.2.4 of algorithm document. - # Hopefully this can also apply to lo-ialirt - pass + l2_dataset = process_lo_direct_events(dependencies) - elif dataset_name == "imap_codice_l2_lo-nsw-species": - # Calculate the non-sunward solar wind species intensities using - # equation described in section 11.2.4 of algorithm document. - # Calculate the pickup ion non-sunward solar wind intensities using - # equation described in section 11.2.4 of algorithm document. - pass + # make sure we drop vars not needed in l2 products + vars_to_drop = [ + "acquisition_time_per_esa_step", + "rgfo_half_spin", + "half_spin_per_esa_step", + "rgfo_esa_step", + "rgfo_spin_sector", + "packet_version", + ] + for var in vars_to_drop: + if var in l2_dataset.data_vars: + l2_dataset = l2_dataset.drop_vars(var) logger.info(f"\nFinal data product:\n{l2_dataset}\n") return l2_dataset - - -def add_dataset_attributes( - l2_dataset: xr.Dataset, dataset_name: str, cdf_attrs: ImapCdfAttributes -) -> xr.Dataset: - """ - Add the global and variable attributes to the dataset. - - Parameters - ---------- - l2_dataset : xarray.Dataset - The dataset to update. - dataset_name : str - The name of the dataset. - cdf_attrs : ImapCdfAttributes - The attribute manager for CDF attributes. - - Returns - ------- - xarray.Dataset - The updated dataset. - """ - cdf_attrs.add_instrument_global_attrs("codice") - cdf_attrs.add_instrument_variable_attrs("codice", "l2") - - # Update the global attributes - l2_dataset.attrs = cdf_attrs.get_global_attributes(dataset_name) - - # Set the variable attributes - for variable_name in l2_dataset.data_vars.keys(): - try: - l2_dataset[variable_name].attrs = cdf_attrs.get_variable_attributes( - variable_name, check_schema=False - ) - except KeyError: - # Some variables may have a product descriptor prefix in the - # cdf attributes key if they are common to multiple products. - descriptor = dataset_name.split("imap_codice_l2_")[-1] - cdf_attrs_key = f"{descriptor}-{variable_name}" - try: - l2_dataset[variable_name].attrs = cdf_attrs.get_variable_attributes( - f"{cdf_attrs_key}", check_schema=False - ) - except KeyError: - logger.error( - f"Field '{variable_name}' and '{cdf_attrs_key}' not found in " - f"attribute manager." - ) - return l2_dataset diff --git a/imap_processing/codice/constants.py b/imap_processing/codice/constants.py index ced1f486d3..c2a53aff9a 100644 --- a/imap_processing/codice/constants.py +++ b/imap_processing/codice/constants.py @@ -17,90 +17,45 @@ import numpy as np -from imap_processing.codice.utils import CODICEAPID, CoDICECompression - -# Grouping of APIDs used to signify similar L1a processing -APIDS_FOR_SCIENCE_PROCESSING = [ - CODICEAPID.COD_HI_INST_COUNTS_AGGREGATED, - CODICEAPID.COD_HI_INST_COUNTS_PRIORITIES, - CODICEAPID.COD_HI_INST_COUNTS_SINGLES, - CODICEAPID.COD_HI_SECT_SPECIES_COUNTS, - CODICEAPID.COD_LO_INST_COUNTS_AGGREGATED, - CODICEAPID.COD_LO_INST_COUNTS_SINGLES, - CODICEAPID.COD_LO_SW_ANGULAR_COUNTS, - CODICEAPID.COD_LO_NSW_ANGULAR_COUNTS, - CODICEAPID.COD_LO_SW_PRIORITY_COUNTS, - CODICEAPID.COD_LO_NSW_PRIORITY_COUNTS, - CODICEAPID.COD_LO_SW_SPECIES_COUNTS, - CODICEAPID.COD_LO_NSW_SPECIES_COUNTS, -] - -# Mapping between descriptors and APID -CODICEAPID_MAPPING = { - "hskp": CODICEAPID.COD_NHK, - "lo-ialirt": CODICEAPID.COD_LO_IAL, - "lo-direct-events": CODICEAPID.COD_LO_PHA, - "lo-sw-priority": CODICEAPID.COD_LO_SW_PRIORITY_COUNTS, - "lo-sw-species": CODICEAPID.COD_LO_SW_SPECIES_COUNTS, - "lo-nsw-species": CODICEAPID.COD_LO_NSW_SPECIES_COUNTS, - "lo-sw-angular": CODICEAPID.COD_LO_SW_ANGULAR_COUNTS, - "lo-nsw-angular": CODICEAPID.COD_LO_NSW_ANGULAR_COUNTS, - "lo-nsw-priority": CODICEAPID.COD_LO_NSW_PRIORITY_COUNTS, - "lo-counters-aggregated": CODICEAPID.COD_LO_INST_COUNTS_AGGREGATED, - "lo-counters-singles": CODICEAPID.COD_LO_INST_COUNTS_SINGLES, - "hi-ialirt": CODICEAPID.COD_HI_IAL, - "hi-direct-events": CODICEAPID.COD_HI_PHA, - "hi-counters-aggregated": CODICEAPID.COD_HI_INST_COUNTS_AGGREGATED, - "hi-counters-singles": CODICEAPID.COD_HI_INST_COUNTS_SINGLES, - "hi-omni": CODICEAPID.COD_HI_OMNI_SPECIES_COUNTS, - "hi-sectored": CODICEAPID.COD_HI_SECT_SPECIES_COUNTS, - "hi-priority": CODICEAPID.COD_HI_INST_COUNTS_PRIORITIES, -} +from imap_processing.codice.utils import CODICEAPID +# -------L1A Constants------- # Numerical constants SPIN_PERIOD_CONVERSION = 0.00032 K_FACTOR = 5.76 # This is used to convert voltages to energies in L2 +NUM_ESA_STEPS = 128 +LO_DESPIN_SPIN_SECTORS = 24 +MAX_DE_EVENTS_PER_PACKET = 10000 + +# Define the packet fields needed to be stored in segmented data and their +# corresponding bit lengths for I-ALiRT data products +IAL_BIT_STRUCTURE = { + "SHCOARSE": 32, + "PACKET_VERSION": 16, + "SPIN_PERIOD": 16, + "ACQ_START_SECONDS": 32, + "ACQ_START_SUBSECONDS": 20, + "SPARE_00": 8, + "ST_BIAS_GAIN_MODE": 2, + "SW_BIAS_GAIN_MODE": 2, + "TABLE_ID": 32, + "PLAN_ID": 16, + "PLAN_STEP": 4, + "VIEW_ID": 4, + "SPARE_01": 8, + "RGFO_HALF_SPIN": 8, + "RGFO_SPIN_SECTOR": 8, + "RGFO_ENERGY_STEP": 8, + "NSO_HALF_SPIN": 8, + "NSO_SPIN_SECTOR": 8, + "NSO_ENERGY_STEP": 8, + "SPARE_02": 16, + "SPARE_03": 5, + "SUSPECT": 1, + "COMPRESSION": 3, + "BYTE_COUNT": 23, +} -# CDF variable names used for lo data products -LO_COUNTERS_SINGLES_VARIABLE_NAMES = ["apd_singles"] -LO_SW_ANGULAR_VARIABLE_NAMES = ["hplus", "heplusplus", "oplus6", "fe_loq"] -LO_NSW_ANGULAR_VARIABLE_NAMES = ["heplusplus"] -LO_SW_PRIORITY_VARIABLE_NAMES = [ - "p0_tcrs", - "p1_hplus", - "p2_heplusplus", - "p3_heavies", - "p4_dcrs", -] -LO_NSW_PRIORITY_VARIABLE_NAMES = ["p5_heavies", "p6_hplus_heplusplus"] -LO_SW_SPECIES_VARIABLE_NAMES = [ - "hplus", - "heplusplus", - "cplus4", - "cplus5", - "cplus6", - "oplus5", - "oplus6", - "oplus7", - "oplus8", - "ne", - "mg", - "si", - "fe_loq", - "fe_hiq", - "heplus", - "cnoplus", -] -LO_NSW_SPECIES_VARIABLE_NAMES = [ - "hplus", - "heplusplus", - "c", - "o", - "ne_si_mg", - "fe", - "heplus", - "cnoplus", -] LO_IALIRT_VARIABLE_NAMES = [ "heplusplus", "cplus5", @@ -109,621 +64,58 @@ "oplus7", "oplus8", "mg", - "fe_loq", "fe_hiq", + "fe_loq", ] - -# CDF variable names used for hi data products -HI_COUNTERS_SINGLES_VARIABLE_NAMES = ["tcr", "ssdo", "stssd"] -HI_OMNI_VARIABLE_NAMES = ["h", "he3", "he4", "c", "o", "ne_mg_si", "fe", "uh", "junk"] -HI_PRIORITY_VARIABLE_NAMES = [ - "Priority0", - "Priority1", - "Priority2", - "Priority3", - "Priority4", - "Priority5", -] -HI_SECTORED_VARIABLE_NAMES = ["h", "he3he4", "cno", "fe"] HI_IALIRT_VARIABLE_NAMES = ["h"] - -# CDF variable names used for direct event data products -HI_DE_CDF_FIELDS = [ - "num_events", - "data_quality", - "ssd_energy", - "tof", - "ssd_id", - "gain", - "multi_flag", - "type", - "spin_sector", - "spin_number", -] -HI_DIRECT_EVENTS_VARIABLE_NAMES = [ - f"p{n}_{field}" for n in range(6) for field in HI_DE_CDF_FIELDS -] -LO_DE_CDF_FIELDS = [ - "num_events", - "data_quality", - "gain", - "apd_id", - "apd_energy", - "tof", - "multi_flag", - "type", - "spin_sector", - "energy_step", -] -LO_DIRECT_EVENTS_VARIABLE_NAMES = [ - f"p{n}_{field}" for n in range(8) for field in LO_DE_CDF_FIELDS -] - -# Final I-ALiRT data product fields -CODICE_LO_IAL_DATA_FIELDS = [ - "c_over_o_abundance", - "mg_over_o_abundance", - "fe_over_o_abundance", - "c_plus_6_over_c_plus_5_ratio", - "o_plus_7_over_o_plus_6_ratio", - "fe_low_over_fe_high_ratio", -] -CODICE_HI_IAL_DATA_FIELDS = ["h"] - -# lo- and hi-counters-aggregated data product variables are dynamically -# determined based on the number of active counters -# TODO: Try to convince Joey to move to lower case variable names with -# underscores? -LO_COUNTERS_AGGREGATED_ACTIVE_VARIABLES = { - "tcr": True, - "dcr": True, - "tof_plus_apd": False, - "tof_only": False, - "position_plus_apd": False, - "position_only": False, - "sta_or_stb_plus_apd": False, - "sta_or_stb_only": False, - "reserved1": False, - "reserved2": False, - "sp_only": False, - "apd_only": False, - "low_tof_cutoff": False, - "sta": True, - "stb": True, - "sp": True, - "total_position_count": True, - "invalid_position_count": False, - "asic1_flag_invalid": False, - "asic2_flag_invalid": False, - "asic1_channel_invalid": False, - "asic2_channel_invalid": False, - "tec4_timeout_tof_no_pos": False, - "tec4_timeout_pos_no_tof": False, - "tec4_timeout_no_pos_tof": False, - "tec5_timeout_tof_no_pos": False, - "tec5_timeout_pos_no_tof": False, - "tec5_timeout_no_pos_tof": False, -} -LO_COUNTERS_AGGREGATED_VARIABLE_NAMES = [ - name - for name, is_active in LO_COUNTERS_AGGREGATED_ACTIVE_VARIABLES.items() - if is_active -] -HI_COUNTERS_AGGREGATED_ACTIVE_VARIABLES = { - "dcr": True, - "sto": True, - "spo": True, - "reserved1": False, - "mst": True, - "reserved2": False, - "reserved3": False, - "reserved4": False, - "reserved5": False, - "low_tof_cutoff": False, - "reserved6": False, - "reserved7": False, - "asic1_flag_invalid": True, - "asic2_flag_invalid": True, - "asic1_channel_invalid": False, - "asic_2_channel_invalid": False, -} -HI_COUNTERS_AGGREGATED_VARIABLE_NAMES = [ - name - for name, is_active in HI_COUNTERS_AGGREGATED_ACTIVE_VARIABLES.items() - if is_active -] - -# List of data products that require application of despinning algorithm -REQUIRES_DESPINNING = [ - "imap_codice_l1a_lo-sw-angular", - "imap_codice_l1a_lo-nsw-angular", - "imap_codice_l1a_lo-sw-priority", - "imap_codice_l1a_lo-nsw-priority", -] - -# Energy tables for CoDICE-Hi data products. These values represent the edges -# of the bins, and are used in the CoDICE L1a pipeline to compute the centers -# and deltas of the bins, which then get stored in the CDF files for future use. -# These are defined in the "Data Products - Hi" tab of the "*-SCI-LUT-*.xml" -# spreadsheet that largely defines CoDICE processing. -IALIRT_ENERGY_TABLE = { - "h": [ - 0.05, - 0.070710678, - 0.1, - 0.141421356, - 0.2, - 0.282842712, - 0.4, - 0.565685425, - 0.8, - 1.13137085, - 1.6, - 2.2627417, - 3.2, - 4.5254834, - 6.4, - 9.050966799, - ], +# Mass over charge (AMU/e) +# Section 13.2 of Algorithm Document. +LO_IALIRT_M_OVER_Q = { + "heplusplus": 2.0, + "cplus5": 2.4, + "cplus6": 2.0, + "oplus6": 2.7, + "oplus7": 2.28, + "oplus8": 2.0, + "mg": 3.5, + "fe_loq": 7.25, + "fe_hiq": 3.85, } -OMNI_ENERGY_TABLE = { - "h": [ - 0.05, - 0.070710678, - 0.1, - 0.141421356, - 0.2, - 0.282842712, - 0.4, - 0.565685425, - 0.8, - 1.13137085, - 1.6, - 2.2627417, - 3.2, - 4.5254834, - 6.4, - 9.050966799, - ], - "he3": [ - 0.035355339, - 0.05, - 0.070710678, - 0.1, - 0.141421356, - 0.2, - 0.282842712, - 0.4, - 0.565685425, - 0.8, - 1.13137085, - 1.6, - 2.2627417, - 3.2, - 4.5254834, - 6.4, - ], - "he4": [ - 0.035355339, - 0.05, - 0.070710678, - 0.1, - 0.141421356, - 0.2, - 0.282842712, - 0.4, - 0.565685425, - 0.8, - 1.13137085, - 1.6, - 2.2627417, - 3.2, - 4.5254834, - 6.4, +HI_IALIRT_ELEVATION_ANGLE = np.array( + [ + 132.8, + 65.7, + 47.1, + 114.3, ], - "c": [ - 0.025, - 0.035355339, - 0.05, - 0.070710678, - 0.1, - 0.141421356, - 0.2, - 0.282842712, - 0.4, - 0.565685425, - 0.8, - 1.13137085, - 1.6, - 2.2627417, - 3.2, - 4.5254834, - 6.4, - 9.050966799, - 12.8, + dtype=np.float32, +) +HI_IALIRT_REF_SPIN_ANGLE = np.array( + [ + 286.85, + 264.55, + 343.16, + 5.44, ], - "o": [ - 0.025, - 0.035355339, - 0.05, - 0.070710678, - 0.1, - 0.141421356, - 0.2, - 0.282842712, - 0.4, - 0.565685425, - 0.8, - 1.13137085, - 1.6, - 2.2627417, - 3.2, - 4.5254834, - 6.4, - 9.050966799, - 12.8, - ], - "ne_mg_si": [ - 0.01767767, - 0.025, - 0.035355339, - 0.05, - 0.070710678, - 0.1, - 0.141421356, - 0.2, - 0.282842712, - 0.4, - 0.565685425, - 0.8, - 1.13137085, - 1.6, - 2.2627417, - 3.2, - ], - "fe": [ - 0.01767767, - 0.025, - 0.035355339, - 0.05, - 0.070710678, - 0.1, - 0.141421356, - 0.2, - 0.282842712, - 0.4, - 0.565685425, - 0.8, - 1.13137085, - 1.6, - 2.2627417, - 3.2, - 4.5254834, - 6.4, - 9.050966799, - ], - "uh": [0.01767767, 0.025, 0.035355339, 0.05, 0.070710678, 0.1], - "junk": [0.05, 0.070710678], -} - -SECTORED_ENERGY_TABLE = { - "h": [0.05, 0.1, 0.2, 0.4, 0.8, 1.6, 3.2, 6.4, 12.8], - "he3he4": [0.025, 0.05, 0.1, 0.2, 0.4, 0.8, 1.6, 3.2, 6.4], - "cno": [0.025, 0.05, 0.1, 0.2, 0.4, 0.8, 1.6, 3.2, 6.4], - "fe": [0.0125, 0.025, 0.05, 0.1, 0.2, 0.4, 0.8, 1.6, 3.2], -} - -# Various configurations to support processing of individual data products -# Much of these are described in the algorithm document in chapter 10 ("Data -# Level 1A") -DATA_PRODUCT_CONFIGURATIONS: dict[CODICEAPID | int, dict] = { - CODICEAPID.COD_HI_IAL: { - "dataset_name": "imap_codice_l1a_hi-ialirt", - "energy_table": IALIRT_ENERGY_TABLE, - "dims": {"esa_step": 15, "inst_az": 4}, - "instrument": "hi", - "num_counters": 1, - "num_spins": 4, - "support_variables": [ - "data_quality", - "spin_period", - "energy_h", - ], - "variable_names": HI_IALIRT_VARIABLE_NAMES, - }, - CODICEAPID.COD_HI_INST_COUNTS_AGGREGATED: { - "dataset_name": "imap_codice_l1a_hi-counters-aggregated", - "dims": {}, - "instrument": "hi", - "num_counters": len( - HI_COUNTERS_AGGREGATED_VARIABLE_NAMES - ), # The number of counters depends on the number of active counters - "support_variables": ["data_quality", "spin_period"], - "variable_names": HI_COUNTERS_AGGREGATED_VARIABLE_NAMES, - }, - CODICEAPID.COD_HI_INST_COUNTS_SINGLES: { - "dataset_name": "imap_codice_l1a_hi-counters-singles", - "dims": { - "ssd_index": 12, - }, - "instrument": "hi", - "num_counters": 3, - "support_variables": ["data_quality", "spin_period"], - "variable_names": HI_COUNTERS_SINGLES_VARIABLE_NAMES, - }, - CODICEAPID.COD_HI_INST_COUNTS_PRIORITIES: { - "dataset_name": "imap_codice_l1a_hi-priority", - "dims": {}, - "instrument": "hi", - "num_counters": 6, - "support_variables": ["data_quality", "spin_period"], - "variable_names": HI_PRIORITY_VARIABLE_NAMES, - }, - CODICEAPID.COD_HI_OMNI_SPECIES_COUNTS: { - "dataset_name": "imap_codice_l1a_hi-omni", - "energy_table": OMNI_ENERGY_TABLE, - "dims": {"esa_step": 15, "inst_az": 4}, - "instrument": "hi", - "num_counters": 8, - "num_spins": 4, - "support_variables": [ - "data_quality", - "spin_period", - "energy_h", - "energy_he3", - "energy_he4", - "energy_c", - "energy_o", - "energy_ne_mg_si", - "energy_fe", - "energy_uh", - "energy_junk", - ], - "variable_names": HI_OMNI_VARIABLE_NAMES, - }, - CODICEAPID.COD_HI_SECT_SPECIES_COUNTS: { - "dataset_name": "imap_codice_l1a_hi-sectored", - "energy_table": SECTORED_ENERGY_TABLE, - "dims": { - "esa_step": 8, - "ssd_index": 12, - "spin_sector_index": 12, - }, - "instrument": "hi", - "num_counters": 4, - "num_spins": 16, - "support_variables": [ - "data_quality", - "spin_period", - "energy_h", - "energy_he3he4", - "energy_cno", - "energy_fe", - ], - "variable_names": HI_SECTORED_VARIABLE_NAMES, - }, - CODICEAPID.COD_LO_IAL: { - "dataset_name": "imap_codice_l1a_lo-ialirt", - "dims": {"esa_step": 128, "spin_sector": 1}, - "instrument": "lo", - "num_counters": 9, - "support_variables": [ - "energy_table", - "acquisition_time_per_step", - "rgfo_half_spin", - "nso_half_spin", - "sw_bias_gain_mode", - "st_bias_gain_mode", - "data_quality", - "spin_period", - "k_factor", - ], - "variable_names": LO_IALIRT_VARIABLE_NAMES, - }, - CODICEAPID.COD_LO_INST_COUNTS_AGGREGATED: { - "dataset_name": "imap_codice_l1a_lo-counters-aggregated", - "dims": {"esa_step": 128, "spin_sector_pairs": 6}, - "instrument": "lo", - "num_counters": len( - LO_COUNTERS_AGGREGATED_VARIABLE_NAMES - ), # The number of counters depends on the number of active counters - "support_variables": [ - "energy_table", - "acquisition_time_per_step", - "rgfo_half_spin", - "nso_half_spin", - "sw_bias_gain_mode", - "st_bias_gain_mode", - "data_quality", - "spin_period", - "k_factor", - ], - "variable_names": LO_COUNTERS_AGGREGATED_VARIABLE_NAMES, - }, - CODICEAPID.COD_LO_INST_COUNTS_SINGLES: { - "dataset_name": "imap_codice_l1a_lo-counters-singles", - "dims": {"esa_step": 128, "inst_az": 24, "spin_sector_pairs": 6}, - "instrument": "lo", - "num_counters": 1, - "support_variables": [ - "energy_table", - "acquisition_time_per_step", - "rgfo_half_spin", - "nso_half_spin", - "sw_bias_gain_mode", - "st_bias_gain_mode", - "data_quality", - "spin_period", - "k_factor", - ], - "variable_names": LO_COUNTERS_SINGLES_VARIABLE_NAMES, - }, - CODICEAPID.COD_LO_SW_ANGULAR_COUNTS: { - "dataset_name": "imap_codice_l1a_lo-sw-angular", - "dims": {"esa_step": 128, "inst_az": 5, "spin_sector": 12}, - "instrument": "lo", - "num_counters": 4, - "support_variables": [ - "energy_table", - "acquisition_time_per_step", - "rgfo_half_spin", - "nso_half_spin", - "sw_bias_gain_mode", - "st_bias_gain_mode", - "data_quality", - "spin_period", - "k_factor", - ], - "variable_names": LO_SW_ANGULAR_VARIABLE_NAMES, - }, - CODICEAPID.COD_LO_NSW_ANGULAR_COUNTS: { - "dataset_name": "imap_codice_l1a_lo-nsw-angular", - "dims": {"esa_step": 128, "inst_az": 19, "spin_sector": 12}, - "instrument": "lo", - "num_counters": 1, - "support_variables": [ - "energy_table", - "acquisition_time_per_step", - "rgfo_half_spin", - "nso_half_spin", - "sw_bias_gain_mode", - "st_bias_gain_mode", - "data_quality", - "spin_period", - "k_factor", - ], - "variable_names": LO_NSW_ANGULAR_VARIABLE_NAMES, - }, - CODICEAPID.COD_LO_SW_PRIORITY_COUNTS: { - "dataset_name": "imap_codice_l1a_lo-sw-priority", - "dims": {"esa_step": 128, "spin_sector": 12}, - "instrument": "lo", - "num_counters": 5, - "support_variables": [ - "energy_table", - "acquisition_time_per_step", - "rgfo_half_spin", - "nso_half_spin", - "sw_bias_gain_mode", - "st_bias_gain_mode", - "data_quality", - "spin_period", - "k_factor", - ], - "variable_names": LO_SW_PRIORITY_VARIABLE_NAMES, - }, - CODICEAPID.COD_LO_NSW_PRIORITY_COUNTS: { - "dataset_name": "imap_codice_l1a_lo-nsw-priority", - "dims": {"esa_step": 128, "spin_sector": 12}, - "instrument": "lo", - "num_counters": 2, - "support_variables": [ - "energy_table", - "acquisition_time_per_step", - "rgfo_half_spin", - "nso_half_spin", - "sw_bias_gain_mode", - "st_bias_gain_mode", - "data_quality", - "spin_period", - "k_factor", - ], - "variable_names": LO_NSW_PRIORITY_VARIABLE_NAMES, - }, - CODICEAPID.COD_LO_SW_SPECIES_COUNTS: { - "dataset_name": "imap_codice_l1a_lo-sw-species", - "dims": {"esa_step": 128, "spin_sector": 1}, - "instrument": "lo", - "num_counters": 16, - "support_variables": [ - "energy_table", - "acquisition_time_per_step", - "rgfo_half_spin", - "nso_half_spin", - "sw_bias_gain_mode", - "st_bias_gain_mode", - "data_quality", - "spin_period", - "k_factor", - ], - "variable_names": LO_SW_SPECIES_VARIABLE_NAMES, - }, - CODICEAPID.COD_LO_NSW_SPECIES_COUNTS: { - "dataset_name": "imap_codice_l1a_lo-nsw-species", - "dims": {"esa_step": 128, "spin_sector": 1}, - "instrument": "lo", - "num_counters": 8, - "support_variables": [ - "energy_table", - "acquisition_time_per_step", - "rgfo_half_spin", - "nso_half_spin", - "sw_bias_gain_mode", - "st_bias_gain_mode", - "data_quality", - "spin_period", - "k_factor", - ], - "variable_names": LO_NSW_SPECIES_VARIABLE_NAMES, - }, -} + dtype=float, +) -# Various configurations to support L1b processing of individual data products -# Much of these are described in the algorithm document in chapter 11 ("Data -# Level 1B") -L1B_DATA_PRODUCT_CONFIGURATIONS: dict[str, dict] = { - "hi-counters-aggregated": { - "num_spin_sectors": 24, - "num_spins": 16, - }, - "hi-counters-singles": { - "num_spin_sectors": 24, - "num_spins": 16, - }, - "hi-ialirt": { - "num_spin_sectors": 24, - "num_spins": 4, - }, - "hi-omni": { - "num_spin_sectors": 24, - "num_spins": 4, - }, - "hi-priority": { # TODO: Ask Joey to define these - "num_spin_sectors": 1, - "num_spins": 1, - }, - "hi-sectored": { - "num_spin_sectors": 2, - "num_spins": 16, - }, - "lo-counters-aggregated": { - "num_spin_sectors": 2, - }, - "lo-counters-singles": { - "num_spin_sectors": 2, - }, - "lo-nsw-angular": { - "num_spin_sectors": 1, - }, - "lo-sw-angular": { - "num_spin_sectors": 1, - }, - "lo-nsw-priority": { - "num_spin_sectors": 1, - }, - "lo-sw-priority": { - "num_spin_sectors": 1, - }, - "lo-nsw-species": { - "num_spin_sectors": 12, - }, - "lo-sw-species": { - "num_spin_sectors": 12, - }, - "lo-ialirt": { - "num_spin_sectors": 12, - }, +# Define the packet fields needed to be stored in segmented data and their +# corresponding bit lengths for direct event data products +DE_METADATA_FIELDS = { + "packet_version": 16, + "spin_period": 16, + "acq_start_seconds": 32, + "acq_start_subseconds": 20, + "spare_1": 2, + "st_bias_gain_mode": 2, + "sw_bias_gain_mode": 2, + "priority": 4, + "suspect": 1, + "compressed": 1, + "num_events": 32, + "byte_count": 32, } # Various configurations to support processing of direct events data products @@ -772,18 +164,17 @@ "dtype": np.uint8, "fillval": np.iinfo(np.uint8).max, }, - "Priority": { + "priority": { "bit_length": 3, "dtype": np.uint8, "fillval": np.iinfo(np.uint8).max, }, - "Spare": { + "spare": { "bit_length": 22, "dtype": np.uint8, "fillval": np.iinfo(np.uint8).max, }, }, - "cdf_fields": HI_DE_CDF_FIELDS, }, CODICEAPID.COD_LO_PHA: { "num_priorities": 8, @@ -833,170 +224,20 @@ "dtype": np.uint8, "fillval": np.iinfo(np.uint8).max, }, - "Priority": { + "priority": { "bit_length": 3, "dtype": np.uint8, "fillval": np.iinfo(np.uint8).max, }, - "Spare": { + "spare": { "bit_length": 16, "dtype": np.uint8, "fillval": np.iinfo(np.uint8).max, }, }, - "cdf_fields": LO_DE_CDF_FIELDS, }, } -# Define the packet fields needed to be stored in segmented data and their -# corresponding bit lengths for direct event data products -IAL_BIT_STRUCTURE = { - "SHCOARSE": 32, - "PACKET_VERSION": 16, - "SPIN_PERIOD": 16, - "ACQ_START_SECONDS": 32, - "ACQ_START_SUBSECONDS": 20, - "SPARE_00": 8, - "ST_BIAS_GAIN_MODE": 2, - "SW_BIAS_GAIN_MODE": 2, - "TABLE_ID": 32, - "PLAN_ID": 16, - "PLAN_STEP": 4, - "VIEW_ID": 4, - "RGFO_HALF_SPIN": 6, - "NSO_HALF_SPIN": 6, - "SPARE_01": 1, - "SUSPECT": 1, - "COMPRESSION": 3, - "BYTE_COUNT": 23, -} - -# Define the packet fields needed to be stored in segmented data and their -# corresponding bit lengths for direct event data products -DE_METADATA_FIELDS = { - "packet_version": 16, - "spin_period": 16, - "acq_start_seconds": 32, - "acq_start_subseconds": 20, - "spare_1": 2, - "st_bias_gain_mode": 2, - "sw_bias_gain_mode": 2, - "priority": 4, - "suspect": 1, - "compressed": 1, - "num_events": 32, - "byte_count": 32, -} - -# Compression ID lookup tables -# The key is the view_id and the value is the ID for the compression algorithm -# (see utils.CoDICECompression to see how the values correspond) -# These are defined in the "Views" tab of the "*-SCI-LUT-*.xml" spreadsheet that -# largely defines CoDICE processing. -LO_COMPRESSION_ID_LOOKUP = { - 0: CoDICECompression.PACK_24_BIT, - 1: CoDICECompression.LOSSY_B_LOSSLESS, - 2: CoDICECompression.LOSSY_B_LOSSLESS, - 3: CoDICECompression.LOSSY_A_LOSSLESS, - 4: CoDICECompression.LOSSY_A_LOSSLESS, - 5: CoDICECompression.LOSSY_A_LOSSLESS, - 6: CoDICECompression.LOSSY_A_LOSSLESS, - 7: CoDICECompression.LOSSY_A_LOSSLESS, - 8: CoDICECompression.LOSSY_A_LOSSLESS, -} -HI_COMPRESSION_ID_LOOKUP = { - 0: CoDICECompression.LOSSY_A, - 1: CoDICECompression.LOSSY_A, - 2: CoDICECompression.LOSSY_A, - 3: CoDICECompression.LOSSY_B_LOSSLESS, - 4: CoDICECompression.LOSSY_B_LOSSLESS, - 5: CoDICECompression.LOSSY_A_LOSSLESS, - 6: CoDICECompression.LOSSY_A_LOSSLESS, - 7: CoDICECompression.LOSSY_A_LOSSLESS, - 8: CoDICECompression.LOSSY_A_LOSSLESS, - 9: CoDICECompression.LOSSY_A_LOSSLESS, -} - -# ESA Sweep table ID lookup table -# The combination of plan_id and plan_step determine the ESA sweep Table to use -# Currently, ESA sweep table 0 is used for every plan_id/plan_step combination, -# but may change in the future. These are defined in the "ESA Sweep" tab of the -# "*-SCI-LUT-*.xml" spreadsheet that largely defines CoDICE processing. -ESA_SWEEP_TABLE_ID_LOOKUP = { - (0, 0): 0, - (0, 1): 0, - (0, 2): 0, - (0, 3): 0, - (1, 0): 0, - (1, 1): 0, - (1, 2): 0, - (1, 3): 0, - (2, 0): 0, - (2, 1): 0, - (2, 2): 0, - (2, 3): 0, - (3, 0): 0, - (3, 1): 0, - (3, 2): 0, - (3, 3): 0, - (4, 0): 0, - (4, 1): 0, - (4, 2): 0, - (4, 3): 0, - (5, 0): 0, - (5, 1): 0, - (5, 2): 0, - (5, 3): 0, - (6, 0): 0, - (6, 1): 0, - (6, 2): 0, - (6, 3): 0, - (7, 0): 0, - (7, 1): 0, - (7, 2): 0, - (7, 3): 0, -} - -# Lo Stepping table ID lookup table -# The combination of plan_id and plan_step determine the Lo Stepping Table to -# use. Currently, LO Stepping table 0 is used for every plan_id/plan_step -# combination, but may change in the future. These are defined in the "Lo -# Stepping" tab of the "*-SCI-LUT-*.xml" spreadsheet that largely defines CoDICE -# processing. -LO_STEPPING_TABLE_ID_LOOKUP = { - (0, 0): 0, - (0, 1): 0, - (0, 2): 0, - (0, 3): 0, - (1, 0): 0, - (1, 1): 0, - (1, 2): 0, - (1, 3): 0, - (2, 0): 0, - (2, 1): 0, - (2, 2): 0, - (2, 3): 0, - (3, 0): 0, - (3, 1): 0, - (3, 2): 0, - (3, 3): 0, - (4, 0): 0, - (4, 1): 0, - (4, 2): 0, - (4, 3): 0, - (5, 0): 0, - (5, 1): 0, - (5, 2): 0, - (5, 3): 0, - (6, 0): 0, - (6, 1): 0, - (6, 2): 0, - (6, 3): 0, - (7, 0): 0, - (7, 1): 0, - (7, 2): 0, - (7, 3): 0, -} # Lookup tables for Lossy decompression algorithms "A" and "B" # These were provided by Greg Dunn via his sohis_cdh_utils.v script and then @@ -1520,662 +761,257 @@ 255: 2151415807, } -# Lookup table for CoDICE-Lo despinning pixel orientations -# See section 9.3.4 of the algorithm document for further information -PIXEL_ORIENTATIONS = { - 0: "A", - 1: "B", - 2: "A", - 3: "B", - 4: "A", - 5: "A", - 6: "B", - 7: "B", - 8: "A", - 9: "A", - 10: "B", - 11: "B", - 12: "A", - 13: "A", - 14: "A", - 15: "B", - 16: "B", - 17: "B", - 18: "A", - 19: "A", - 20: "A", - 21: "B", - 22: "B", - 23: "B", - 24: "A", - 25: "A", - 26: "A", - 27: "A", - 28: "B", - 29: "B", - 30: "B", - 31: "B", - 32: "A", - 33: "A", - 34: "A", - 35: "A", - 36: "B", - 37: "B", - 38: "B", - 39: "B", - 40: "A", - 41: "A", - 42: "A", - 43: "A", - 44: "A", - 45: "B", - 46: "B", - 47: "B", - 48: "B", - 49: "B", - 50: "A", - 51: "A", - 52: "A", - 53: "A", - 54: "A", - 55: "B", - 56: "B", - 57: "B", - 58: "B", - 59: "B", - 60: "A", - 61: "A", - 62: "A", - 63: "A", - 64: "A", - 65: "B", - 66: "B", - 67: "B", - 68: "B", - 69: "B", - 70: "A", - 71: "A", - 72: "A", - 73: "A", - 74: "A", - 75: "B", - 76: "B", - 77: "B", - 78: "B", - 79: "B", - 80: "A", - 81: "A", - 82: "A", - 83: "A", - 84: "A", - 85: "A", - 86: "B", - 87: "B", - 88: "B", - 89: "B", - 90: "B", - 91: "B", - 92: "A", - 93: "A", - 94: "A", - 95: "A", - 96: "A", - 97: "A", - 98: "B", - 99: "B", - 100: "B", - 101: "B", - 102: "B", - 103: "B", - 104: "A", - 105: "A", - 106: "A", - 107: "A", - 108: "A", - 109: "A", - 110: "B", - 111: "B", - 112: "B", - 113: "B", - 114: "B", - 115: "B", - 116: "A", - 117: "A", - 118: "A", - 119: "A", - 120: "A", - 121: "A", - 122: "B", - 123: "B", - 124: "B", - 125: "B", - 126: "B", - 127: "B", +# ------L1B Constants------ +HI_ACQUISITION_TIME = 0.59916 + +# TODO: in the future, read from sci-lut +LO_SW_ANGULAR_VARIABLE_NAMES = ["hplus", "heplusplus", "oplus6", "fe_loq", "heplus"] +LO_NSW_ANGULAR_VARIABLE_NAMES = ["heplusplus", "heplus"] +LO_SW_PRIORITY_VARIABLE_NAMES = [ + "p0_tcrs", + "p1_hplus", + "p2_heplusplus", + "p3_heavies", + "p4_dcrs", +] +LO_NSW_PRIORITY_VARIABLE_NAMES = ["p5_heavies", "p6_hplus_heplusplus"] +LO_SW_SPECIES_VARIABLE_NAMES = [ + "hplus", + "heplusplus", + "cplus4", + "cplus5", + "cplus6", + "oplus5", + "oplus6", + "oplus7", + "oplus8", + "ne", + "mg", + "si", + "fe_loq", + "fe_hiq", + "heplus", + "cnoplus", +] +LO_COUNTERS_AGGREGATED_VARIABLE_NAMES = [ + "tcr", + "dcr", + "sta", + "stb", + "sp", + "total_position_count", +] +HI_COUNTERS_AGGREGATED_VARIABLE_NAMES = [ + "dcr", + "mst", + "starts_only", + "stops_only", + "singles_starts", + "singles_stops", + "low_tof_cutoff", +] +LO_COUNTERS_SINGLES_VARIABLE_NAMES = ["apd_singles"] +HI_COUNTERS_SINGLES_VARIABLE_NAMES = ["tcr", "ssdo", "stssd"] +# Various configurations to support L1b processing of individual data products +# Much of these are described in the algorithm document in chapter 11 ("Data +# Level 1B") +L1B_DATA_PRODUCT_CONFIGURATIONS: dict[str, dict] = { + "hi-counters-aggregated": { + "num_spin_sectors": 24, + "num_spins": 16, + }, + "hi-counters-singles": { + "num_spin_sectors": 24, + "num_spins": 16, + }, + "hi-ialirt": { + "num_spin_sectors": 6, + "num_spins": 4, + }, + "hi-omni": { + "num_spin_sectors": 24, + "num_spins": 4, + }, + "hi-priority": { + "num_spin_sectors": 24, + "num_spins": 16, + }, + "hi-sectored": { + "num_spin_sectors": 2, + "num_spins": 16, + }, + "lo-counters-aggregated": { + "num_spin_sectors": 2, + }, + "lo-counters-singles": { + "num_spin_sectors": 2, + }, + "lo-nsw-priority": { + "num_spin_sectors": 1, + }, + "lo-sw-priority": { + "num_spin_sectors": 1, + }, + "lo-sw-species": { + "num_spin_sectors": 12, + }, + "lo-ialirt": { + "num_spin_sectors": 12, + }, } -# Derived acquisition times that get stored in CDF data variables in L1a -# processing. These are taken from the "Acq Time" column in the "Lo Stepping" -# tab of the "*-SCI-LUT-*.xml" spreadsheet that largely defines CoDICE -# processing. -ACQUISITION_TIMES = { - 0: [ - 578.70833333, - 578.70833333, - 578.70833333, - 578.70833333, - 289.35416667, - 289.35416667, - 289.35416667, - 289.35416667, - 289.35416667, - 289.35416667, - 289.35416667, - 289.35416667, - 192.90277778, - 192.90277778, - 192.90277778, - 192.90277778, - 192.90277778, - 192.90277778, - 192.90277778, - 192.90277778, - 192.90277778, - 192.90277778, - 192.90277778, - 192.90277778, - 144.67708333, - 144.67708333, - 144.67708333, - 144.67708333, - 144.67708333, - 144.67708333, - 144.67708333, - 144.67708333, - 144.67708333, - 144.67708333, - 144.67708333, - 144.67708333, - 144.67708333, - 144.67708333, - 144.67708333, - 144.67708333, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - ], - 1: [ - 578.70833333, - 578.70833333, - 578.70833333, - 578.70833333, - 289.35416667, - 289.35416667, - 289.35416667, - 289.35416667, - 289.35416667, - 289.35416667, - 289.35416667, - 289.35416667, - 192.90277778, - 192.90277778, - 192.90277778, - 192.90277778, - 192.90277778, - 192.90277778, - 192.90277778, - 192.90277778, - 192.90277778, - 192.90277778, - 192.90277778, - 192.90277778, - 144.67708333, - 144.67708333, - 144.67708333, - 144.67708333, - 144.67708333, - 144.67708333, - 144.67708333, - 144.67708333, - 144.67708333, - 144.67708333, - 144.67708333, - 144.67708333, - 144.67708333, - 144.67708333, - 144.67708333, - 144.67708333, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - ], - 2: [ - 578.70833333, - 578.70833333, - 578.70833333, - 578.70833333, - 289.35416667, - 289.35416667, - 289.35416667, - 289.35416667, - 289.35416667, - 289.35416667, - 289.35416667, - 289.35416667, - 192.90277778, - 192.90277778, - 192.90277778, - 192.90277778, - 192.90277778, - 192.90277778, - 192.90277778, - 192.90277778, - 192.90277778, - 192.90277778, - 192.90277778, - 192.90277778, - 144.67708333, - 144.67708333, - 144.67708333, - 144.67708333, - 144.67708333, - 144.67708333, - 144.67708333, - 144.67708333, - 144.67708333, - 144.67708333, - 144.67708333, - 144.67708333, - 144.67708333, - 144.67708333, - 144.67708333, - 144.67708333, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - ], - 3: [ - 578.70833333, - 578.70833333, - 578.70833333, - 578.70833333, - 289.35416667, - 289.35416667, - 289.35416667, - 289.35416667, - 289.35416667, - 289.35416667, - 289.35416667, - 289.35416667, - 192.90277778, - 192.90277778, - 192.90277778, - 192.90277778, - 192.90277778, - 192.90277778, - 192.90277778, - 192.90277778, - 192.90277778, - 192.90277778, - 192.90277778, - 192.90277778, - 144.67708333, - 144.67708333, - 144.67708333, - 144.67708333, - 144.67708333, - 144.67708333, - 144.67708333, - 144.67708333, - 144.67708333, - 144.67708333, - 144.67708333, - 144.67708333, - 144.67708333, - 144.67708333, - 144.67708333, - 144.67708333, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 115.74166667, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, - 96.45138889, +# ------L2 Constants------ +LO_SW_SOLAR_WIND_SPECIES_VARIABLE_NAMES = [ + "hplus", + "heplusplus", + "cplus4", + "cplus5", + "cplus6", + "oplus5", + "oplus6", + "oplus7", + "oplus8", + "ne", + "mg", + "si", + "fe_hiq", + "fe_loq", +] +LO_SW_PICKUP_ION_SPECIES_VARIABLE_NAMES = [ + "heplus", + "cnoplus", +] +HI_OMNI_VARIABLE_NAMES = ["h", "he3", "he4", "c", "o", "ne_mg_si", "fe", "uh", "junk"] +HI_SECTORED_VARIABLE_NAMES = ["h", "he3he4", "cno", "fe"] +HI_PRIORITY_VARIABLE_NAMES = [ + "priority0", + "priority1", + "priority2", + "priority3", + "priority4", + "priority5", +] + +NSW_POSITIONS = [x for x in range(3, 22)] +SW_POSITIONS = [0, 1, 2, 22, 23] +SOLAR_WIND_POSITIONS = [0] +PUI_POSITIONS = SW_POSITIONS +IALIRT_HI_NUMBER_OF_SSD_PER_GROUP = 3.0 + +L2_HI_SECTORED_ANGLE = np.array( + [ + 285.00, + 244.11, + 228.69, + 225.00, + 228.69, + 244.11, + 285.00, + 325.89, + 341.31, + 345.00, + 341.31, + 325.89, + ] +) + +HI_L2_ELEVATION_ANGLE = np.array( + [ + 150.0, + 138.6, + 115.7, + 90.0, + 64.3, + 41.4, + 30.0, + 41.4, + 64.3, + 90.0, + 115.7, + 138.6, ], + dtype=float, +) + + +LO_POSITION_TO_ELEVATION_ANGLE = { + "sw": { + 1: 0, + 2: 15, + 24: 15, + 3: 30, + 23: 30, + }, + "nsw": { + 4: 45, + 22: 45, + 5: 60, + 21: 60, + 6: 75, + 20: 75, + 7: 90, + 19: 90, + 8: 105, + 18: 105, + 9: 120, + 17: 120, + 10: 135, + 16: 135, + 11: 150, + 15: 150, + 12: 165, + 14: 165, + 13: 180, + }, } + +# SSD ID to Elevation Angle +# The index corresponds to the SSD ID. Missing SSD IDs are represented with np.nan. +SSD_ID_TO_ELEVATION = np.array( + [ + 150.0, + 138.6, + np.nan, + 115.7, + 90.0, + 64.3, + np.nan, + 41.4, + 30.0, + 41.4, + np.nan, + 64.3, + 90.0, + 115.7, + np.nan, + 138.6, + ] +) + +# gain lookup table +GAIN_ID_TO_STR = {1: "LG", 2: "MG", 3: "HG"} + +# SSD ID to Spin Angle (degrees) +# The index corresponds to the SSD ID. Missing SSD IDs are represented with np.nan. +SSD_ID_TO_SPIN_ANGLE = np.array( + [ + 277.50, + 236.61, + np.nan, + 221.19, + 217.5, + 221.19, + np.nan, + 236.61, + 277.50, + 318.39, + np.nan, + 333.81, + 337.50, + 333.81, + np.nan, + 318.39, + ] +) + +HALF_SPIN_FILLVAL = 63 diff --git a/imap_processing/codice/data/lo_stepping_values.csv b/imap_processing/codice/data/lo_stepping_values.csv index 196ff40c88..79605fab9a 100644 --- a/imap_processing/codice/data/lo_stepping_values.csv +++ b/imap_processing/codice/data/lo_stepping_values.csv @@ -1,4 +1,4 @@ -table_num,row_num,num_reps,store_data,e1,e2,e3,e4,e5,e6,e7,e8,acq_time +table_num,half_spin_num,num_reps,store_data,e1,e2,e3,e4,e5,e6,e7,e8,acq_time 0,0,1,12,0,-,-,-,-,-,-,-,578.708333 0,1,1,12,1,-,-,-,-,-,-,-,578.708333 0,2,1,12,2,-,-,-,-,-,-,-,578.708333 diff --git a/imap_processing/codice/packet_definitions/codice_packet_definition.xml b/imap_processing/codice/packet_definitions/imap_codice_packet-definition_20250101_v001.xml similarity index 93% rename from imap_processing/codice/packet_definitions/codice_packet_definition.xml rename to imap_processing/codice/packet_definitions/imap_codice_packet-definition_20250101_v001.xml index a50eb3d4b6..47bf7415a5 100644 --- a/imap_processing/codice/packet_definitions/codice_packet_definition.xml +++ b/imap_processing/codice/packet_definitions/imap_codice_packet-definition_20250101_v001.xml @@ -1,6 +1,6 @@ - + @@ -45,7 +45,7 @@ - + @@ -297,8 +297,17 @@ + + + + + + + + + - + @@ -358,7 +367,7 @@ - + @@ -439,7 +448,8 @@ - + + @@ -567,46 +577,28 @@ - - - - - - - + - - - - - - - + - - - - - - - + - - - - - - - + - + + + + + + + @@ -615,7 +607,8 @@ - + + @@ -624,7 +617,8 @@ - + + @@ -633,7 +627,8 @@ - + + @@ -688,7 +683,7 @@ - + @@ -697,8 +692,7 @@ - - + @@ -707,8 +701,7 @@ - - + @@ -717,7 +710,7 @@ - + @@ -726,7 +719,7 @@ - + @@ -796,19 +789,19 @@ - + - + - + - + - + @@ -835,15 +828,55 @@ - + - + + + + + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1115,7 +1148,7 @@ - + @@ -1145,7 +1178,13 @@ - + + + + + + + @@ -1154,7 +1193,13 @@ - + + + + + + + @@ -1163,7 +1208,13 @@ - + + + + + + + @@ -1172,7 +1223,13 @@ - + + + + + + + @@ -1181,7 +1238,13 @@ - + + + + + + + @@ -1474,74 +1537,12 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -1737,7 +1738,6 @@ - @@ -2422,74 +2422,12 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -3104,6 +3042,12 @@ + + INDICATES THE CURRENT OPERATIONAL STATE OF THE LO ESA SWEEP: +- NORMAL - BOTH ESAS ARE TRACKING TOGETHER +- RGFO - REDUCED GAIN FACTOR OPERATION; ESA-A IS REDUCED IN ORDER TO REDUCE THE GAIN FACTOR AND ALLOW FEWER IONS INTO THE DETECTOR +- NSO - NO SCAN OPERATION; BOTH ESAS ARE RETURNED TO A HIGH-ENERGY SETTING AND NO SCANNING IS DONE FOR THE REMAINDER OF THE ESA SWEEP + @@ -3127,17 +3071,27 @@ - + - - - - - - - - - + + ALARM PERSISTENCE = 3 IN OASIS + + + ALARM PERSISTENCE = 3 IN OASIS + + + ALARM PERSISTENCE = 3 IN OASIS + + + ALARM PERSISTENCE = 3 IN OASIS + + + ALARM PERSISTENCE = 3 IN OASIS + + + + + @@ -3159,11 +3113,13 @@ - - - - - + + + + + + EACH BIT INDICATES WHETHER THE CORRESPONDING MACRO IS CURRENTLY RUNNING (E.G. BIT 1 WILL BE SET IF MACRO 1 IS RUNNING) + INDICATES WHETHER ANY CATEGORY 1 LIMITS HAVE TRIGGERED. @@ -3194,7 +3150,7 @@ INDICATES WHETHER THE MOST RECENT TRIGGER WAS A MINIMUM OR MAXIMUM LIMIT - INDICATES THE ID OF THE MOST RECENT FDC TRIGGER + INDICATES THE TABLE INDEX OF THE MOST RECENT FDC TRIGGER INDICATES THE ACTION THAT WAS TAKEN FOR THE MOST RECENT FDC TRIGGER @@ -3208,7 +3164,7 @@ INDICATES WHETHER FSW CONTROL OF THE OPERATIONAL HEATER IS ENABLED - + INDICATES THE CURRENT STATE OF THE PHYSICAL HEATER OUTPUT @@ -3313,60 +3269,28 @@ SECONDARY HEADER - WHOLE-SECONDS PART OF SCLK - - PACKET VERSION - THIS WILL BE INCREMENTED EACH TIME THE FORMAT OF THE PACKET CHANGESCOD_LO_PHA. - - - SPIN PERIOD REPORTED BY THE SPACECRAFT IN THE TIME AND STATUS MESSAGE. REPORTED PERIOD IS THE PERIOD THAT WAS ACTIVE WHEN THE 16-SPIN ACQUISITION CYCLE STARTED. - - - FULL-SECONDS PORTION OF THE TIME AT WHICH THE 16-SPIN CYCLE STARTED - - - SUB-SECONDS PORTION OF THE TIME AT WHICH THE 16-SPIN CYCLE STARTED - - - SPARE FOR ALIGNMENT - - - BIAS GAIN MODE FOR THE SUPRATHERMAL SECTOR - - - BIAS GAIN MODE FOR THE SOLARWIND SECTOR - - - - INDICATES THAT THERE WAS SOME ERROR DETECTED DURING ACQUISITION OR PROCESSING OF THE DATA. ERRORS COULD INCLUDE CORRUPTED ACQUISITION MEMORY (I.E. EDAC ERRORS), TIMING VIOLATIONS, OR OTHER EVENTS THAT INTERRUPTED OR OTHERWISE AFFECTED DATA COLLECTION. - - - WHETHER THE EVENT DATA IS COMPRESSED. IF 1/YES, EVENT_DATA ARRAY IS COMPRESSED USING THE LZMA COMPRESSION ALGORITHM. - - - NUMBER OF EVENTS SELECTED FOR DOWNLINK (I.E. NUMBER OF EVENTS IN THE EVENT_DATA ARRAY) - - - NUMBER OF BYTES IN THE EVENT_DATA ARRAY. IF COMPRESSED, THIS VALUE REPRESENTS THE LENGTH OF THE COMPRESSED DATA. - - OPTIONALLY COMPRESSED ARRAY OF EVENT DATA + + OPTIONALLY COMPRESSED ARRAY OF EVENT DATA -FORMAT IS TBD; SOME CONSIDERATIONS/OPTIONS: -- FULL EVENTS HAVE A LOT OF REDUNDANT DATA (E.G. WILL HAVE MANY EVENTS WITH THE SAME PRIORITY/E-STEP/SPIN PHASE INFORMATION). HOW WELL DOES COMPRESSION TO DEAL WITH THE REDUNDANCY? -- COULD INCLUDE MINI-HEADERS FOR EACH (PRIORITY,E-STEP, SPIN-PHASE) GROUP AND STRIP THE REDUNDANT DATA FROM THE EVENTS -- SHOULD EVENTS BE TIGHTLY PACKED, OR CAN WE PAD OUT TO 64-BIT WORD BOUNDARIES? HOW WELL DOES COMPRESSION COMPENSATE FOR THE EXTRA BITS? + FORMAT IS TBD; SOME CONSIDERATIONS/OPTIONS: + - FULL EVENTS HAVE A LOT OF REDUNDANT DATA (E.G. WILL HAVE MANY EVENTS WITH THE SAME PRIORITY/E-STEP/SPIN PHASE INFORMATION). HOW WELL DOES COMPRESSION TO DEAL WITH THE REDUNDANCY? + - COULD INCLUDE MINI-HEADERS FOR EACH (PRIORITY,E-STEP, SPIN-PHASE) GROUP AND STRIP THE REDUNDANT DATA FROM THE EVENTS + - SHOULD EVENTS BE TIGHTLY PACKED, OR CAN WE PAD OUT TO 64-BIT WORD BOUNDARIES? HOW WELL DOES COMPRESSION COMPENSATE FOR THE EXTRA BITS? -EACH EVENT CONSISTS OF: -- 7-BIT E-STEP -- 10-BIT TOF -- 9-BIT APD ENERGY -- 7-BIT SPIN ANGLE -- 5-BIT POSITION -- 5-BIT APD-ID -- 1-BIT APD-GAIN -- 2-BIT PHA TYPE -- 3-BIT PRIORITY RANGE + EACH EVENT CONSISTS OF: + - 7-BIT E-STEP + - 10-BIT TOF + - 9-BIT APD ENERGY + - 7-BIT SPIN ANGLE + - 5-BIT POSITION + - 5-BIT APD-ID + - 1-BIT APD-GAIN + - 2-BIT PHA TYPE + - 3-BIT PRIORITY RANGE -TBD: EVENTS MAY BE TIGHTLY PACKED, OR MAY HAVE SPARES ADDED TO KEEP EACH EVENT BYTE-ALIGNED. IN EITHER CASE, THERE MAY BE UP TO 1 BYTE OF PADDING TO KEEP THE TOTAL SIZE OF THE PACKET EVEN. + TBD: EVENTS MAY BE TIGHTLY PACKED, OR MAY HAVE SPARES ADDED TO KEEP EACH EVENT BYTE-ALIGNED. IN EITHER CASE, THERE MAY BE UP TO 1 BYTE OF PADDING TO KEEP THE TOTAL SIZE OF THE PACKET EVEN. + PACKET CHECKSUM @@ -3999,58 +3923,26 @@ WHEN THIS ARRAY IS TOO LARGE FOR A SINGLE CCSDS PACKET, CODICE WILL UTILIZE THE SECONDARY HEADER - WHOLE-SECONDS PART OF SCLK - - PACKET VERSION - THIS WILL BE INCREMENTED EACH TIME THE FORMAT OF THE PACKET CHANGESCOD_LO_PHA. - - - SPIN PERIOD REPORTED BY THE SPACECRAFT IN THE TIME AND STATUS MESSAGE. REPORTED PERIOD IS THE PERIOD THAT WAS ACTIVE WHEN THE 16-SPIN ACQUISITION CYCLE STARTED. - - - FULL-SECONDS PORTION OF THE TIME AT WHICH THE 16-SPIN CYCLE STARTED - - - SUB-SECONDS PORTION OF THE TIME AT WHICH THE 16-SPIN CYCLE STARTED - - - SPARE FOR ALIGNMENT - - - BIAS GAIN MODE FOR THE SUPRATHERMAL SECTOR - - - BIAS GAIN MODE FOR THE SOLARWIND SECTOR - - - - INDICATES THAT THERE WAS SOME ERROR DETECTED DURING ACQUISITION OR PROCESSING OF THE DATA. ERRORS COULD INCLUDE CORRUPTED ACQUISITION MEMORY (I.E. EDAC ERRORS), TIMING VIOLATIONS, OR OTHER EVENTS THAT INTERRUPTED OR OTHERWISE AFFECTED DATA COLLECTION. - - - WHETHER THE EVENT DATA IS COMPRESSED. IF 1/YES, EVENT_DATA ARRAY IS COMPRESSED USING THE RICE COMPRESSION ALGORITHM. - - - NUMBER OF EVENTS SELECTED FOR DOWNLINK (I.E. NUMBER OF EVENTS IN THE EVENT_DATA ARRAY) - - - NUMBER OF BYTES IN THE EVENT_DATA ARRAY. IF COMPRESSED, THIS VALUE REPRESENTS THE LENGTH OF THE COMPRESSED DATA. - - OPTIONALLY COMPRESSED ARRAY OF EVENT DATA + + OPTIONALLY COMPRESSED ARRAY OF EVENT DATA -FORMAT IS TBD; SOME CONSIDERATIONS/OPTIONS: -- FULL EVENTS HAVE A LOT OF REDUNDANT DATA (E.G. WILL HAVE MANY EVENTS WITH THE SAME PRIORITY/SPIN/SPIN PHASE INFORMATION). HOW WELL DOES COMPRESSION TO DEAL WITH THE REDUNDANCY? -- COULD INCLUDE MINI-HEADERS FOR EACH (PRIORITY,SPIN, SPIN-PHASE) GROUP AND STRIP THE REDUNDANT DATA FROM THE EVENTS -- SHOULD EVENTS BE TIGHTLY PACKED, OR CAN WE PAD OUT TO 64-BIT WORD BOUNDARIES? HOW WELL DOES COMPRESSION COMPENSATE FOR THE EXTRA BITS? + FORMAT IS TBD; SOME CONSIDERATIONS/OPTIONS: + - FULL EVENTS HAVE A LOT OF REDUNDANT DATA (E.G. WILL HAVE MANY EVENTS WITH THE SAME PRIORITY/SPIN/SPIN PHASE INFORMATION). HOW WELL DOES COMPRESSION TO DEAL WITH THE REDUNDANCY? + - COULD INCLUDE MINI-HEADERS FOR EACH (PRIORITY,SPIN, SPIN-PHASE) GROUP AND STRIP THE REDUNDANT DATA FROM THE EVENTS + - SHOULD EVENTS BE TIGHTLY PACKED, OR CAN WE PAD OUT TO 64-BIT WORD BOUNDARIES? HOW WELL DOES COMPRESSION COMPENSATE FOR THE EXTRA BITS? -EACH EVENT CONSISTS OF: -- 10-BIT TOF -- 9-BIT SSD ENERGY -- 2-BIT ENERGY RANGE -- 7-BIT SPIN ANGLE -- 4-BIT SSD POSITION -- 4-BIT SPIN NUMBER -- 2-BIT PHA TYPE + EACH EVENT CONSISTS OF: + - 10-BIT TOF + - 9-BIT SSD ENERGY + - 2-BIT ENERGY RANGE + - 7-BIT SPIN ANGLE + - 4-BIT SSD POSITION + - 4-BIT SPIN NUMBER + - 2-BIT PHA TYPE -TBD: EVENTS MAY BE TIGHTLY PACKED, OR MAY HAVE SPARES ADDED TO KEEP EACH EVENT BYTE-ALIGNED. IN EITHER CASE, THERE MAY BE UP TO 1 BYTE OF PADDING TO KEEP THE TOTAL SIZE OF THE PACKET EVEN. + TBD: EVENTS MAY BE TIGHTLY PACKED, OR MAY HAVE SPARES ADDED TO KEEP EACH EVENT BYTE-ALIGNED. IN EITHER CASE, THERE MAY BE UP TO 1 BYTE OF PADDING TO KEEP THE TOTAL SIZE OF THE PACKET EVEN. + PACKET CHECKSUM @@ -4491,6 +4383,7 @@ WHEN THIS ARRAY IS TOO LARGE FOR A SINGLE CCSDS PACKET, CODICE WILL UTILIZE THE + @@ -4546,11 +4439,11 @@ WHEN THIS ARRAY IS TOO LARGE FOR A SINGLE CCSDS PACKET, CODICE WILL UTILIZE THE - - - - - + + + + + @@ -4565,7 +4458,7 @@ WHEN THIS ARRAY IS TOO LARGE FOR A SINGLE CCSDS PACKET, CODICE WILL UTILIZE THE - + @@ -4632,18 +4525,6 @@ WHEN THIS ARRAY IS TOO LARGE FOR A SINGLE CCSDS PACKET, CODICE WILL UTILIZE THE - - - - - - - - - - - - @@ -4908,18 +4789,6 @@ WHEN THIS ARRAY IS TOO LARGE FOR A SINGLE CCSDS PACKET, CODICE WILL UTILIZE THE - - - - - - - - - - - - diff --git a/imap_processing/codice/packet_definitions/imap_codice_packet-definition_20260129_v001.xml b/imap_processing/codice/packet_definitions/imap_codice_packet-definition_20260129_v001.xml new file mode 100644 index 0000000000..c6e0646b26 --- /dev/null +++ b/imap_processing/codice/packet_definitions/imap_codice_packet-definition_20260129_v001.xml @@ -0,0 +1,5231 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + CCSDS Packet Version Number (always 0) + + + CCSDS Packet Type Indicator (0=telemetry) + + + CCSDS Packet Secondary Header Flag (always 1) + + + CCSDS Packet Application Process ID + + + CCSDS Packet Grouping Flags (3=not part of group) + + + CCSDS Packet Sequence Count (increments with each new packet) + + + CCSDS Packet Length (number of bytes after Packet length minus 1) + + + EUROPA CLIPPER SECONDARY HEADER - WHOLE-SECONDS PART OF SCLK + + + PACKET VERSION - THIS WILL BE INCREMENTED EACH TIME THE FORMAT OF THE PACKET CHANGES. + + + NUMBER OF COMMANDS THAT HAVE BEEN EXECUTED. COUNTS 0-255, THEN ROLLS OVER TO 0. RESET VIA CLR_LATCHED_SINGLE(COMMAND_COUNTS) [ALSO RESETS CMDJRCT, CMDACC, ITF_ERROR COUNTS) + + + NUMBER OF COMMANDS THAT HAVE BEEN REJECTED. COUNTS 0-255, THEN ROLLS OVER TO 0. RESET VIA CLR_LATCHED_SINGLE(COMMAND_COUNTS) [ALSO RESETS CMDEXE, CMDACC, ITF_ERROR COUNTS) + + + OPCODE OF THE LAST EXECUTED COMMAND + + + CURRENT OPERATING MODE + + + STATE OF THE MEMORY-OPERATIONS HANDLER + + + STATE OF THE MEMORY-DUMP HANDLER (BUSY/IDLE) + + + NUMBER OF ITF ERRORS THAT HAVE BEEN DETECTED; COUNTS 0-3, THEN ROLLS OVER TO 0. RESET VIA CLR_LATCHED_SINGLE(COMMAND_COUNTS) [ALSO RESETS CMDEXE, CMDJRCT, CMDACC COUNTS) + + + NUMBER OF SPIN PULSES RECEIVED + + + NUMBER OF MISSED PPS PULSES. COUNTS 0-3, THEN FREEZES AT 3. RESET VIA CLR_LATCHED_SINGLE(PPS_STATS) + + + NUMBER OF TIMES THE WATCHDOG HAS TIMED OUT. + + + CURRENT STATUS OF THE HV SAFE/DISABLE PLUGS: +- SAFE: ALL HVPS OUTPUTS PROVIDE 1/10 THE COMMANDED VOLTAGE +- DIS: ALL HVPS OUTPUTS PROVIDE 0V, REGARDLESS OF COMMANDED VOLTAGE +- FULL: HVPS OUTPUTS PROVIDE THE FULL COMMANDED VOLTAGE + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + INDICATES THE CURRENT OPERATIONAL STATE OF THE LO ESA SWEEP: +- NORMAL - BOTH ESAS ARE TRACKING TOGETHER +- RGFO - REDUCED GAIN FACTOR OPERATION; ESA-A IS REDUCED IN ORDER TO REDUCE THE GAIN FACTOR AND ALLOW FEWER IONS INTO THE DETECTOR +- NSO - NO SCAN OPERATION; BOTH ESAS ARE RETURNED TO A HIGH-ENERGY SETTING AND NO SCANNING IS DONE FOR THE REMAINDER OF THE ESA SWEEP + + + + + + + + + + + + + + + + + + + + + + + + + + + + ALARM PERSISTENCE = 3 IN OASIS + + + ALARM PERSISTENCE = 3 IN OASIS + + + ALARM PERSISTENCE = 3 IN OASIS + + + ALARM PERSISTENCE = 3 IN OASIS + + + ALARM PERSISTENCE = 3 IN OASIS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + EACH BIT INDICATES WHETHER THE CORRESPONDING MACRO IS CURRENTLY RUNNING (E.G. BIT 1 WILL BE SET IF MACRO 1 IS RUNNING) + + + INDICATES WHETHER ANY CATEGORY 1 LIMITS HAVE TRIGGERED. + + 2 BITS: 0: NO TRIGGERS; 1: ONE TRIGGER, 2: TWO TRIGGERS, 3: MORE THAN TWO TRIGGERS + + + INDICATES WHETHER ANY CATEGORY 2 LIMITS HAVE TRIGGERED + + + INDICATES WHETHER ANY CATEGORY 3 LIMITS HAVE TRIGGERED + + + INDICATES WHETHER ANY CATEGORY 4 LIMITS HAVE TRIGGERED + + + INDICATES WHETHER ANY CATEGORY 5 LIMITS HAVE TRIGGERED + + + INDICATES WHETHER ANY CATEGORY 6 LIMITS HAVE TRIGGERED + + + INDICATES WHETHER ANY CATEGORY 7 LIMITS HAVE TRIGGERED + + + INDICATES WHETHER ANY CATEGORY 8 LIMITS HAVE TRIGGERED + + + INDICATES WHETHER THE MOST RECENT TRIGGER WAS A MINIMUM OR MAXIMUM LIMIT + + + INDICATES THE TABLE INDEX OF THE MOST RECENT FDC TRIGGER + + + INDICATES THE ACTION THAT WAS TAKEN FOR THE MOST RECENT FDC TRIGGER + + + CURRENT INDEX FOR THE ROUND ROBIN PARAMETER REPORTING. THE ROUND ROBIN MECHANISM REPORTS ONE VALUE FROM THE PARAMETER TABLE EACH TIME THIS PACKET IS GENERATED. + + + PARAMETER VALUE CORRESPONDING TO THE CURRENT ROUND_ROBIN_INDEX VALUE. + + + INDICATES WHETHER FSW CONTROL OF THE OPERATIONAL HEATER IS ENABLED + + + INDICATES THE CURRENT STATE OF THE PHYSICAL HEATER OUTPUT + + + INDICATES THE CURRENT STATE OF THE PHYSICAL HEATER OUTPUT + + + SPARE FOR ALIGNMENT + + + CPU PERCENT IDLE TIME. BASED ON THE MEMORY SCRUB TASK PERCENT, SINCE IT CONSUMES ALL IDLE CYCLES. + + + + + + + + + + + + + + + + + + + + + + + + SPARE FOR ALIGNMENT + + + PACKET CHECKSUM + + + SECONDARY HEADER - WHOLE-SECONDS PART OF SCLK + + + OPTIONALLY COMPRESSED ARRAY OF EVENT DATA + +FORMAT IS TBD; SOME CONSIDERATIONS/OPTIONS: +- FULL EVENTS HAVE A LOT OF REDUNDANT DATA (E.G. WILL HAVE MANY EVENTS WITH THE SAME PRIORITY/E-STEP/SPIN PHASE INFORMATION). HOW WELL DOES COMPRESSION TO DEAL WITH THE REDUNDANCY? +- COULD INCLUDE MINI-HEADERS FOR EACH (PRIORITY,E-STEP, SPIN-PHASE) GROUP AND STRIP THE REDUNDANT DATA FROM THE EVENTS +- SHOULD EVENTS BE TIGHTLY PACKED, OR CAN WE PAD OUT TO 64-BIT WORD BOUNDARIES? HOW WELL DOES COMPRESSION COMPENSATE FOR THE EXTRA BITS? + +EACH EVENT CONSISTS OF: +- 7-BIT E-STEP +- 10-BIT TOF +- 9-BIT APD ENERGY +- 7-BIT SPIN ANGLE +- 5-BIT POSITION +- 5-BIT APD-ID +- 1-BIT APD-GAIN +- 2-BIT PHA TYPE +- 3-BIT PRIORITY RANGE + +TBD: EVENTS MAY BE TIGHTLY PACKED, OR MAY HAVE SPARES ADDED TO KEEP EACH EVENT BYTE-ALIGNED. IN EITHER CASE, THERE MAY BE UP TO 1 BYTE OF PADDING TO KEEP THE TOTAL SIZE OF THE PACKET EVEN. + + + PACKET CHECKSUM + + + SECONDARY HEADER - WHOLE-SECONDS PART OF SCLK + + + PACKET VERSION - THIS WILL BE INCREMENTED EACH TIME THE FORMAT OF THE PACKET CHANGES. + + + SPIN PERIOD REPORTED BY THE SPACECRAFT IN THE TIME AND STATUS MESSAGE. REPORTED PERIOD IS THE PERIOD THAT WAS ACTIVE WHEN THE 16-SPIN ACQUISITION CYCLE STARTED. + + + FULL-SECONDS PORTION OF THE TIME AT WHICH THE 16-SPIN CYCLE STARTED + + + SUB-SECONDS PORTION OF THE TIME AT WHICH THE 16-SPIN CYCLE STARTED (MICROSECONDS) + + + SPARE FOR ALIGNMENT + + + BIAS GAIN MODE FOR THE SUPRATHERMAL SECTOR + + + BIAS GAIN MODE FOR THE SOLARWIND SECTOR + + + UNIQUE ID ASSIGNED TO A SPECIFIC TABLE CONFIGURATION. THIS FIELD IS USED TO LINK THE OVERALL ACQUISITION AND PROCESSING SETTINGS TO A SPECIFIC TABLE CONFIGURATION. + + + PLAN TABLE THAT WAS IN USE + + + PLAN STEP THAT WAS ACTIVE WHEN THIS DATA WAS ACQUIRED AND PROCESSED. + + + VIEW ID PROVIDES INFORMATION ABOUT HOW DATA WAS COLLAPSED AND/OR COMPRESSED. + + + SPARE FOR ALIGNMENT + + + INDICATES THE POINT WHEN REDUCED GAIN FACTOR OPERATION (RGFO) WAS ACTIVED. IN RGFO, THE ENTRANCE ESA VOLTAGE IS REDUCED IN ORDER TO LIMIT THE NUMBER OF IONS THAT REACH THE DETECTORS. + + + INDICATES THE POINT WHEN REDUCED GAIN FACTOR OPERATION (RGFO) WAS ACTIVED. IN RGFO, THE ENTRANCE ESA VOLTAGE IS REDUCED IN ORDER TO LIMIT THE NUMBER OF IONS THAT REACH THE DETECTORS. + + + INDICATES THE POINT WHEN REDUCED GAIN FACTOR OPERATION (RGFO) WAS ACTIVED. IN RGFO, THE ENTRANCE ESA VOLTAGE IS REDUCED IN ORDER TO LIMIT THE NUMBER OF IONS THAT REACH THE DETECTORS. + + + INDICATES THE POINT WHEN NO-SCAN OPERATION (NSO) WAS ACTIVED. IN NSO, THE ESA VOLTAGE IS SET TO THE FIRST STEP IN THE SCAN AND REMAINS FIXED UNTIL THE NEXT CYCLE BOUNDARY. + + + INDICATES THE POINT WHEN NO-SCAN OPERATION (NSO) WAS ACTIVED. IN NSO, THE ESA VOLTAGE IS SET TO THE FIRST STEP IN THE SCAN AND REMAINS FIXED UNTIL THE NEXT CYCLE BOUNDARY. + + + INDICATES THE POINT WHEN NO-SCAN OPERATION (NSO) WAS ACTIVED. IN NSO, THE ESA VOLTAGE IS SET TO THE FIRST STEP IN THE SCAN AND REMAINS FIXED UNTIL THE NEXT CYCLE BOUNDARY. + + + SPARE FOR ALIGNMENT + + + SPARE FOR ALIGNMENT + + + INDICATES THAT THERE WAS SOME ERROR DETECTED DURING ACQUISITION OR PROCESSING OF THE DATA. ERRORS COULD INCLUDE CORRUPTED ACQUISITION MEMORY (I.E. EDAC ERRORS), TIMING VIOLATIONS, OR OTHER EVENTS THAT INTERRUPTED OR OTHERWISE AFFECTED DATA COLLECTION. + + + WHETHER/HOW THE DATA IS COMPRESSED. + + + NUMBER OF BYTES IN THE DATA ARRAY. IF COMPRESSED, THIS VALUE REPRESENTS THE LENGTH OF THE COMPRESSED DATA. + + + COUNTER DATA + +VARIABLE LENGTH; MAXIMUM (BASED ON UNCOLLAPSED, UNCOMPRESSED DATA, AND ASSUMING ALL 8 PRIORITY-COUNTERS INCLUDED): + +128 ENERGIES X 24 POSITIONS X 12 SPIN-ANGLES X 32 BITS X 8 COUNTERS = 9,437,184 BITS (1,179,648 BYTES) + +REALISTICALLY, DATA IS AGGRESSIVELY COLLAPSED AND COMPRESSED, AND ONLY A SUBSET OF THE 32 SPECIES COUNTERS WILL BE INCLUDED, SO THIS DATA FIELD WILL BE MUCH SMALLER THAN THE MAXIMUM. + +DATA FORMAT IS A SERIES OF SPIN-ANGLE X POSITION X ENERGY DATA CUBES COLLAPSED PER THE SCI_LUT COLLAPSE TABLE SELECTED BY THE VIEW_ID. WHICH COUNTERS ARE INCLUDED IS DETERMINED BY USING THE PLAN_ID AND PLAN_STEP TO INDEX INTO THE SCI_LUT DATA PRODUCTS HI/LO TABLES TO FIND ALL THE COUNTERS THAT ARE ASSOCIATED WITH THE VIEW_ID. + +THE COLLAPSED DATA CUBES ARE ALSO OPTIONALLY COMPRESSED USING LOSSY AND/OR LOSSLESS COMPRESSION. LOSSY COMPRESSION IS A TABLE-BASED 24->8 BIT COMPRESSION APPLIED TO EACH COUNTER VALUE. LOSSLESS COMPRESSION USES THE LZMA COMPRESSION ALGORITHM AND IS APPLIED TO THE FULL DATA FIELD AS A SINGLE UNIT. + +FIELD WILL ADDITIONALLY BE PADDED IN ORDER TO MEET THE REQUIREMENT OF PACKETS BEING A MULTIPLE OF 16 BITS; ANY PAD BITS WILL BE ACCOUNTED FOR IN THE CCSDS HEADER LENGTH FIELD, BUT WILL *NOT* BE INCLUDED IN THE BYTE_COUNT FIELD + +WHEN THIS ARRAY IS TOO LARGE FOR A SINGLE CCSDS PACKET, CODICE WILL UTILIZE THE CCSDS GROUPING FLAGS TO PROVIDE THE FULL DATA PACKET OVER SEVERAL CCSDS PACKETS. + + + PACKET CHECKSUM + + + SECONDARY HEADER - WHOLE-SECONDS PART OF SCLK + + + PACKET VERSION - THIS WILL BE INCREMENTED EACH TIME THE FORMAT OF THE PACKET CHANGES. + + + SPIN PERIOD REPORTED BY THE SPACECRAFT IN THE TIME AND STATUS MESSAGE. REPORTED PERIOD IS THE PERIOD THAT WAS ACTIVE WHEN THE 16-SPIN ACQUISITION CYCLE STARTED. + + + FULL-SECONDS PORTION OF THE TIME AT WHICH THE 16-SPIN CYCLE STARTED + + + SUB-SECONDS PORTION OF THE TIME AT WHICH THE 16-SPIN CYCLE STARTED (MICROSECONDS) + + + SPARE FOR ALIGNMENT + + + BIAS GAIN MODE FOR THE SUPRATHERMAL SECTOR + + + BIAS GAIN MODE FOR THE SOLARWIND SECTOR + + + UNIQUE ID ASSIGNED TO A SPECIFIC TABLE CONFIGURATION. THIS FIELD IS USED TO LINK THE OVERALL ACQUISITION AND PROCESSING SETTINGS TO A SPECIFIC TABLE CONFIGURATION. + + + PLAN TABLE THAT WAS IN USE + + + PLAN STEP THAT WAS ACTIVE WHEN THIS DATA WAS ACQUIRED AND PROCESSED. + + + VIEW ID PROVIDES INFORMATION ABOUT HOW DATA WAS COLLAPSED AND/OR COMPRESSED. + + + SPARE FOR ALIGNMENT + + + INDICATES THE POINT WHEN REDUCED GAIN FACTOR OPERATION (RGFO) WAS ACTIVED. IN RGFO, THE ENTRANCE ESA VOLTAGE IS REDUCED IN ORDER TO LIMIT THE NUMBER OF IONS THAT REACH THE DETECTORS. + + + INDICATES THE POINT WHEN REDUCED GAIN FACTOR OPERATION (RGFO) WAS ACTIVED. IN RGFO, THE ENTRANCE ESA VOLTAGE IS REDUCED IN ORDER TO LIMIT THE NUMBER OF IONS THAT REACH THE DETECTORS. + + + INDICATES THE POINT WHEN REDUCED GAIN FACTOR OPERATION (RGFO) WAS ACTIVED. IN RGFO, THE ENTRANCE ESA VOLTAGE IS REDUCED IN ORDER TO LIMIT THE NUMBER OF IONS THAT REACH THE DETECTORS. + + + INDICATES THE POINT WHEN NO-SCAN OPERATION (NSO) WAS ACTIVED. IN NSO, THE ESA VOLTAGE IS SET TO THE FIRST STEP IN THE SCAN AND REMAINS FIXED UNTIL THE NEXT CYCLE BOUNDARY. + + + INDICATES THE POINT WHEN NO-SCAN OPERATION (NSO) WAS ACTIVED. IN NSO, THE ESA VOLTAGE IS SET TO THE FIRST STEP IN THE SCAN AND REMAINS FIXED UNTIL THE NEXT CYCLE BOUNDARY. + + + INDICATES THE POINT WHEN NO-SCAN OPERATION (NSO) WAS ACTIVED. IN NSO, THE ESA VOLTAGE IS SET TO THE FIRST STEP IN THE SCAN AND REMAINS FIXED UNTIL THE NEXT CYCLE BOUNDARY. + + + SPARE FOR ALIGNMENT + + + SPARE FOR ALIGNMENT + + + INDICATES THAT THERE WAS SOME ERROR DETECTED DURING ACQUISITION OR PROCESSING OF THE DATA. ERRORS COULD INCLUDE CORRUPTED ACQUISITION MEMORY (I.E. EDAC ERRORS), TIMING VIOLATIONS, OR OTHER EVENTS THAT INTERRUPTED OR OTHERWISE AFFECTED DATA COLLECTION. + + + WHETHER/HOW THE DATA IS COMPRESSED. + + + NUMBER OF BYTES IN THE DATA ARRAY. IF COMPRESSED, THIS VALUE REPRESENTS THE LENGTH OF THE COMPRESSED DATA. + + + COUNTER DATA + +VARIABLE LENGTH; MAXIMUM (BASED ON UNCOLLAPSED, UNCOMPRESSED DATA, AND ASSUMING ALL 32 SPECIES-COUNTERS INCLUDED): + +128 ENERGIES X 24 POSITIONS X 12 SPIN-ANGLES X 32 BITS X 32 COUNTERS = 37,748,736 BITS (4,718,592 BYTES) + +REALISTICALLY, DATA IS AGGRESSIVELY COLLAPSED AND COMPRESSED, AND ONLY A SUBSET OF THE 32 SPECIES COUNTERS WILL BE INCLUDED, SO THIS DATA FIELD WILL BE MUCH SMALLER THAN THE MAXIMUM. + +DATA FORMAT IS A SERIES OF SPIN-ANGLE X POSITION X ENERGY DATA CUBES COLLAPSED PER THE SCI_LUT COLLAPSE TABLE SELECTED BY THE VIEW_ID. WHICH COUNTERS ARE INCLUDED IS DETERMINED BY USING THE PLAN_ID AND PLAN_STEP TO INDEX INTO THE SCI_LUT DATA PRODUCTS HI/LO TABLES TO FIND ALL THE COUNTERS THAT ARE ASSOCIATED WITH THE VIEW_ID. + +THE COLLAPSED DATA CUBES ARE ALSO OPTIONALLY COMPRESSED USING LOSSY AND/OR LOSSLESS COMPRESSION. LOSSY COMPRESSION IS A TABLE-BASED 24->8 BIT COMPRESSION APPLIED TO EACH COUNTER VALUE. LOSSLESS COMPRESSION USES THE LZMA COMPRESSION ALGORITHM AND IS APPLIED TO THE FULL DATA FIELD AS A SINGLE UNIT. + +FIELD WILL ADDITIONALLY BE PADDED IN ORDER TO MEET THE REQUIREMENT OF PACKETS BEING A MULTIPLE OF 16 BITS; ANY PAD BITS WILL BE ACCOUNTED FOR IN THE CCSDS HEADER LENGTH FIELD, BUT WILL *NOT* BE INCLUDED IN THE BYTE_COUNT FIELD + +WHEN THIS ARRAY IS TOO LARGE FOR A SINGLE CCSDS PACKET, CODICE WILL UTILIZE THE CCSDS GROUPING FLAGS TO PROVIDE THE FULL DATA PACKET OVER SEVERAL CCSDS PACKETS. + + + PACKET CHECKSUM + + + SECONDARY HEADER - WHOLE-SECONDS PART OF SCLK + + + PACKET VERSION - THIS WILL BE INCREMENTED EACH TIME THE FORMAT OF THE PACKET CHANGES. + + + SPIN PERIOD REPORTED BY THE SPACECRAFT IN THE TIME AND STATUS MESSAGE. REPORTED PERIOD IS THE PERIOD THAT WAS ACTIVE WHEN THE 16-SPIN ACQUISITION CYCLE STARTED. + + + FULL-SECONDS PORTION OF THE TIME AT WHICH THE 16-SPIN CYCLE STARTED + + + SUB-SECONDS PORTION OF THE TIME AT WHICH THE 16-SPIN CYCLE STARTED (MICROSECONDS) + + + SPARE FOR ALIGNMENT + + + BIAS GAIN MODE FOR THE SUPRATHERMAL SECTOR + + + BIAS GAIN MODE FOR THE SOLARWIND SECTOR + + + UNIQUE ID ASSIGNED TO A SPECIFIC TABLE CONFIGURATION. THIS FIELD IS USED TO LINK THE OVERALL ACQUISITION AND PROCESSING SETTINGS TO A SPECIFIC TABLE CONFIGURATION. + + + PLAN TABLE THAT WAS IN USE + + + PLAN STEP THAT WAS ACTIVE WHEN THIS DATA WAS ACQUIRED AND PROCESSED. + + + VIEW ID PROVIDES INFORMATION ABOUT HOW DATA WAS COLLAPSED AND/OR COMPRESSED. + + + SPARE FOR ALIGNMENT + + + INDICATES THE POINT WHEN REDUCED GAIN FACTOR OPERATION (RGFO) WAS ACTIVED. IN RGFO, THE ENTRANCE ESA VOLTAGE IS REDUCED IN ORDER TO LIMIT THE NUMBER OF IONS THAT REACH THE DETECTORS. + + + INDICATES THE POINT WHEN REDUCED GAIN FACTOR OPERATION (RGFO) WAS ACTIVED. IN RGFO, THE ENTRANCE ESA VOLTAGE IS REDUCED IN ORDER TO LIMIT THE NUMBER OF IONS THAT REACH THE DETECTORS. + + + INDICATES THE POINT WHEN REDUCED GAIN FACTOR OPERATION (RGFO) WAS ACTIVED. IN RGFO, THE ENTRANCE ESA VOLTAGE IS REDUCED IN ORDER TO LIMIT THE NUMBER OF IONS THAT REACH THE DETECTORS. + + + INDICATES THE POINT WHEN NO-SCAN OPERATION (NSO) WAS ACTIVED. IN NSO, THE ESA VOLTAGE IS SET TO THE FIRST STEP IN THE SCAN AND REMAINS FIXED UNTIL THE NEXT CYCLE BOUNDARY. + + + INDICATES THE POINT WHEN NO-SCAN OPERATION (NSO) WAS ACTIVED. IN NSO, THE ESA VOLTAGE IS SET TO THE FIRST STEP IN THE SCAN AND REMAINS FIXED UNTIL THE NEXT CYCLE BOUNDARY. + + + INDICATES THE POINT WHEN NO-SCAN OPERATION (NSO) WAS ACTIVED. IN NSO, THE ESA VOLTAGE IS SET TO THE FIRST STEP IN THE SCAN AND REMAINS FIXED UNTIL THE NEXT CYCLE BOUNDARY. + + + SPARE FOR ALIGNMENT + + + SPARE FOR ALIGNMENT + + + INDICATES THAT THERE WAS SOME ERROR DETECTED DURING ACQUISITION OR PROCESSING OF THE DATA. ERRORS COULD INCLUDE CORRUPTED ACQUISITION MEMORY (I.E. EDAC ERRORS), TIMING VIOLATIONS, OR OTHER EVENTS THAT INTERRUPTED OR OTHERWISE AFFECTED DATA COLLECTION. + + + WHETHER/HOW THE DATA IS COMPRESSED. + + + NUMBER OF BYTES IN THE DATA ARRAY. IF COMPRESSED, THIS VALUE REPRESENTS THE LENGTH OF THE COMPRESSED DATA. + + + COUNTER DATA + +VARIABLE LENGTH; MAXIMUM (BASED ON UNCOLLAPSED, UNCOMPRESSED DATA, AND ASSUMING ALL 32 SPECIES-COUNTERS INCLUDED): + +128 ENERGIES X 24 POSITIONS X 12 SPIN-ANGLES X 32 BITS X 32 COUNTERS = 37,748,736 BITS (4,718,592 BYTES) + +REALISTICALLY, DATA IS AGGRESSIVELY COLLAPSED AND COMPRESSED, AND ONLY A SUBSET OF THE 32 SPECIES COUNTERS WILL BE INCLUDED, SO THIS DATA FIELD WILL BE MUCH SMALLER THAN THE MAXIMUM. + +DATA FORMAT IS A SERIES OF SPIN-ANGLE X POSITION X ENERGY DATA CUBES COLLAPSED PER THE SCI_LUT COLLAPSE TABLE SELECTED BY THE VIEW_ID. WHICH COUNTERS ARE INCLUDED IS DETERMINED BY USING THE PLAN_ID AND PLAN_STEP TO INDEX INTO THE SCI_LUT DATA PRODUCTS HI/LO TABLES TO FIND ALL THE COUNTERS THAT ARE ASSOCIATED WITH THE VIEW_ID. + +THE COLLAPSED DATA CUBES ARE ALSO OPTIONALLY COMPRESSED USING LOSSY AND/OR LOSSLESS COMPRESSION. LOSSY COMPRESSION IS A TABLE-BASED 24->8 BIT COMPRESSION APPLIED TO EACH COUNTER VALUE. LOSSLESS COMPRESSION USES THE LZMA COMPRESSION ALGORITHM AND IS APPLIED TO THE FULL DATA FIELD AS A SINGLE UNIT. + +FIELD WILL ADDITIONALLY BE PADDED IN ORDER TO MEET THE REQUIREMENT OF PACKETS BEING A MULTIPLE OF 16 BITS; ANY PAD BITS WILL BE ACCOUNTED FOR IN THE CCSDS HEADER LENGTH FIELD, BUT WILL *NOT* BE INCLUDED IN THE BYTE_COUNT FIELD + +WHEN THIS ARRAY IS TOO LARGE FOR A SINGLE CCSDS PACKET, CODICE WILL UTILIZE THE CCSDS GROUPING FLAGS TO PROVIDE THE FULL DATA PACKET OVER SEVERAL CCSDS PACKETS. + + + PACKET CHECKSUM + + + SECONDARY HEADER - WHOLE-SECONDS PART OF SCLK + + + PACKET VERSION - THIS WILL BE INCREMENTED EACH TIME THE FORMAT OF THE PACKET CHANGES. + + + SPIN PERIOD REPORTED BY THE SPACECRAFT IN THE TIME AND STATUS MESSAGE. REPORTED PERIOD IS THE PERIOD THAT WAS ACTIVE WHEN THE 16-SPIN ACQUISITION CYCLE STARTED. + + + FULL-SECONDS PORTION OF THE TIME AT WHICH THE 16-SPIN CYCLE STARTED + + + SUB-SECONDS PORTION OF THE TIME AT WHICH THE 16-SPIN CYCLE STARTED (MICROSECONDS) + + + SPARE FOR ALIGNMENT + + + BIAS GAIN MODE FOR THE SUPRATHERMAL SECTOR + + + BIAS GAIN MODE FOR THE SOLARWIND SECTOR + + + UNIQUE ID ASSIGNED TO A SPECIFIC TABLE CONFIGURATION. THIS FIELD IS USED TO LINK THE OVERALL ACQUISITION AND PROCESSING SETTINGS TO A SPECIFIC TABLE CONFIGURATION. + + + PLAN TABLE THAT WAS IN USE + + + PLAN STEP THAT WAS ACTIVE WHEN THIS DATA WAS ACQUIRED AND PROCESSED. + + + VIEW ID PROVIDES INFORMATION ABOUT HOW DATA WAS COLLAPSED AND/OR COMPRESSED. + + + SPARE FOR ALIGNMENT + + + INDICATES THE POINT WHEN REDUCED GAIN FACTOR OPERATION (RGFO) WAS ACTIVED. IN RGFO, THE ENTRANCE ESA VOLTAGE IS REDUCED IN ORDER TO LIMIT THE NUMBER OF IONS THAT REACH THE DETECTORS. + + + INDICATES THE POINT WHEN REDUCED GAIN FACTOR OPERATION (RGFO) WAS ACTIVED. IN RGFO, THE ENTRANCE ESA VOLTAGE IS REDUCED IN ORDER TO LIMIT THE NUMBER OF IONS THAT REACH THE DETECTORS. + + + INDICATES THE POINT WHEN REDUCED GAIN FACTOR OPERATION (RGFO) WAS ACTIVED. IN RGFO, THE ENTRANCE ESA VOLTAGE IS REDUCED IN ORDER TO LIMIT THE NUMBER OF IONS THAT REACH THE DETECTORS. + + + INDICATES THE POINT WHEN NO-SCAN OPERATION (NSO) WAS ACTIVED. IN NSO, THE ESA VOLTAGE IS SET TO THE FIRST STEP IN THE SCAN AND REMAINS FIXED UNTIL THE NEXT CYCLE BOUNDARY. + + + INDICATES THE POINT WHEN NO-SCAN OPERATION (NSO) WAS ACTIVED. IN NSO, THE ESA VOLTAGE IS SET TO THE FIRST STEP IN THE SCAN AND REMAINS FIXED UNTIL THE NEXT CYCLE BOUNDARY. + + + INDICATES THE POINT WHEN NO-SCAN OPERATION (NSO) WAS ACTIVED. IN NSO, THE ESA VOLTAGE IS SET TO THE FIRST STEP IN THE SCAN AND REMAINS FIXED UNTIL THE NEXT CYCLE BOUNDARY. + + + SPARE FOR ALIGNMENT + + + SPARE FOR ALIGNMENT + + + INDICATES THAT THERE WAS SOME ERROR DETECTED DURING ACQUISITION OR PROCESSING OF THE DATA. ERRORS COULD INCLUDE CORRUPTED ACQUISITION MEMORY (I.E. EDAC ERRORS), TIMING VIOLATIONS, OR OTHER EVENTS THAT INTERRUPTED OR OTHERWISE AFFECTED DATA COLLECTION. + + + WHETHER/HOW THE DATA IS COMPRESSED. + + + NUMBER OF BYTES IN THE DATA ARRAY. IF COMPRESSED, THIS VALUE REPRESENTS THE LENGTH OF THE COMPRESSED DATA. + + + COUNTER DATA + +VARIABLE LENGTH; MAXIMUM (BASED ON UNCOLLAPSED, UNCOMPRESSED DATA, AND ASSUMING ALL 32 SPECIES-COUNTERS INCLUDED): + +128 ENERGIES X 24 POSITIONS X 12 SPIN-ANGLES X 32 BITS X 32 COUNTERS = 37,748,736 BITS (4,718,592 BYTES) + +REALISTICALLY, DATA IS AGGRESSIVELY COLLAPSED AND COMPRESSED, AND ONLY A SUBSET OF THE 32 SPECIES COUNTERS WILL BE INCLUDED, SO THIS DATA FIELD WILL BE MUCH SMALLER THAN THE MAXIMUM. + +DATA FORMAT IS A SERIES OF SPIN-ANGLE X POSITION X ENERGY DATA CUBES COLLAPSED PER THE SCI_LUT COLLAPSE TABLE SELECTED BY THE VIEW_ID. WHICH COUNTERS ARE INCLUDED IS DETERMINED BY USING THE PLAN_ID AND PLAN_STEP TO INDEX INTO THE SCI_LUT DATA PRODUCTS HI/LO TABLES TO FIND ALL THE COUNTERS THAT ARE ASSOCIATED WITH THE VIEW_ID. + +THE COLLAPSED DATA CUBES ARE ALSO OPTIONALLY COMPRESSED USING LOSSY AND/OR LOSSLESS COMPRESSION. LOSSY COMPRESSION IS A TABLE-BASED 24->8 BIT COMPRESSION APPLIED TO EACH COUNTER VALUE. LOSSLESS COMPRESSION USES THE LZMA COMPRESSION ALGORITHM AND IS APPLIED TO THE FULL DATA FIELD AS A SINGLE UNIT. + +FIELD WILL ADDITIONALLY BE PADDED IN ORDER TO MEET THE REQUIREMENT OF PACKETS BEING A MULTIPLE OF 16 BITS; ANY PAD BITS WILL BE ACCOUNTED FOR IN THE CCSDS HEADER LENGTH FIELD, BUT WILL *NOT* BE INCLUDED IN THE BYTE_COUNT FIELD + +WHEN THIS ARRAY IS TOO LARGE FOR A SINGLE CCSDS PACKET, CODICE WILL UTILIZE THE CCSDS GROUPING FLAGS TO PROVIDE THE FULL DATA PACKET OVER SEVERAL CCSDS PACKETS. + + + PACKET CHECKSUM + + + SECONDARY HEADER - WHOLE-SECONDS PART OF SCLK + + + PACKET VERSION - THIS WILL BE INCREMENTED EACH TIME THE FORMAT OF THE PACKET CHANGES. + + + SPIN PERIOD REPORTED BY THE SPACECRAFT IN THE TIME AND STATUS MESSAGE. REPORTED PERIOD IS THE PERIOD THAT WAS ACTIVE WHEN THE 16-SPIN ACQUISITION CYCLE STARTED. + + + FULL-SECONDS PORTION OF THE TIME AT WHICH THE 16-SPIN CYCLE STARTED + + + SUB-SECONDS PORTION OF THE TIME AT WHICH THE 16-SPIN CYCLE STARTED (MICROSECONDS) + + + SPARE FOR ALIGNMENT + + + BIAS GAIN MODE FOR THE SUPRATHERMAL SECTOR + + + BIAS GAIN MODE FOR THE SOLARWIND SECTOR + + + UNIQUE ID ASSIGNED TO A SPECIFIC TABLE CONFIGURATION. THIS FIELD IS USED TO LINK THE OVERALL ACQUISITION AND PROCESSING SETTINGS TO A SPECIFIC TABLE CONFIGURATION. + + + PLAN TABLE THAT WAS IN USE + + + PLAN STEP THAT WAS ACTIVE WHEN THIS DATA WAS ACQUIRED AND PROCESSED. + + + VIEW ID PROVIDES INFORMATION ABOUT HOW DATA WAS COLLAPSED AND/OR COMPRESSED. + + + SPARE FOR ALIGNMENT + + + INDICATES THE POINT WHEN REDUCED GAIN FACTOR OPERATION (RGFO) WAS ACTIVED. IN RGFO, THE ENTRANCE ESA VOLTAGE IS REDUCED IN ORDER TO LIMIT THE NUMBER OF IONS THAT REACH THE DETECTORS. + + + INDICATES THE POINT WHEN REDUCED GAIN FACTOR OPERATION (RGFO) WAS ACTIVED. IN RGFO, THE ENTRANCE ESA VOLTAGE IS REDUCED IN ORDER TO LIMIT THE NUMBER OF IONS THAT REACH THE DETECTORS. + + + INDICATES THE POINT WHEN REDUCED GAIN FACTOR OPERATION (RGFO) WAS ACTIVED. IN RGFO, THE ENTRANCE ESA VOLTAGE IS REDUCED IN ORDER TO LIMIT THE NUMBER OF IONS THAT REACH THE DETECTORS. + + + INDICATES THE POINT WHEN NO-SCAN OPERATION (NSO) WAS ACTIVED. IN NSO, THE ESA VOLTAGE IS SET TO THE FIRST STEP IN THE SCAN AND REMAINS FIXED UNTIL THE NEXT CYCLE BOUNDARY. + + + INDICATES THE POINT WHEN NO-SCAN OPERATION (NSO) WAS ACTIVED. IN NSO, THE ESA VOLTAGE IS SET TO THE FIRST STEP IN THE SCAN AND REMAINS FIXED UNTIL THE NEXT CYCLE BOUNDARY. + + + INDICATES THE POINT WHEN NO-SCAN OPERATION (NSO) WAS ACTIVED. IN NSO, THE ESA VOLTAGE IS SET TO THE FIRST STEP IN THE SCAN AND REMAINS FIXED UNTIL THE NEXT CYCLE BOUNDARY. + + + SPARE FOR ALIGNMENT + + + SPARE FOR ALIGNMENT + + + INDICATES THAT THERE WAS SOME ERROR DETECTED DURING ACQUISITION OR PROCESSING OF THE DATA. ERRORS COULD INCLUDE CORRUPTED ACQUISITION MEMORY (I.E. EDAC ERRORS), TIMING VIOLATIONS, OR OTHER EVENTS THAT INTERRUPTED OR OTHERWISE AFFECTED DATA COLLECTION. + + + WHETHER/HOW THE DATA IS COMPRESSED. + + + NUMBER OF BYTES IN THE DATA ARRAY. IF COMPRESSED, THIS VALUE REPRESENTS THE LENGTH OF THE COMPRESSED DATA. + + + COUNTER DATA + +VARIABLE LENGTH; MAXIMUM (BASED ON UNCOLLAPSED, UNCOMPRESSED DATA, AND ASSUMING ALL 32 SPECIES-COUNTERS INCLUDED): + +128 ENERGIES X 24 POSITIONS X 12 SPIN-ANGLES X 32 BITS X 32 COUNTERS = 37,748,736 BITS (4,718,592 BYTES) + +REALISTICALLY, DATA IS AGGRESSIVELY COLLAPSED AND COMPRESSED, AND ONLY A SUBSET OF THE 32 SPECIES COUNTERS WILL BE INCLUDED, SO THIS DATA FIELD WILL BE MUCH SMALLER THAN THE MAXIMUM. + +DATA FORMAT IS A SERIES OF SPIN-ANGLE X POSITION X ENERGY DATA CUBES COLLAPSED PER THE SCI_LUT COLLAPSE TABLE SELECTED BY THE VIEW_ID. WHICH COUNTERS ARE INCLUDED IS DETERMINED BY USING THE PLAN_ID AND PLAN_STEP TO INDEX INTO THE SCI_LUT DATA PRODUCTS HI/LO TABLES TO FIND ALL THE COUNTERS THAT ARE ASSOCIATED WITH THE VIEW_ID. + +THE COLLAPSED DATA CUBES ARE ALSO OPTIONALLY COMPRESSED USING LOSSY AND/OR LOSSLESS COMPRESSION. LOSSY COMPRESSION IS A TABLE-BASED 24->8 BIT COMPRESSION APPLIED TO EACH COUNTER VALUE. LOSSLESS COMPRESSION USES THE LZMA COMPRESSION ALGORITHM AND IS APPLIED TO THE FULL DATA FIELD AS A SINGLE UNIT. + +FIELD WILL ADDITIONALLY BE PADDED IN ORDER TO MEET THE REQUIREMENT OF PACKETS BEING A MULTIPLE OF 16 BITS; ANY PAD BITS WILL BE ACCOUNTED FOR IN THE CCSDS HEADER LENGTH FIELD, BUT WILL *NOT* BE INCLUDED IN THE BYTE_COUNT FIELD + +WHEN THIS ARRAY IS TOO LARGE FOR A SINGLE CCSDS PACKET, CODICE WILL UTILIZE THE CCSDS GROUPING FLAGS TO PROVIDE THE FULL DATA PACKET OVER SEVERAL CCSDS PACKETS. + + + PACKET CHECKSUM + + + SECONDARY HEADER - WHOLE-SECONDS PART OF SCLK + + + PACKET VERSION - THIS WILL BE INCREMENTED EACH TIME THE FORMAT OF THE PACKET CHANGES. + + + SPIN PERIOD REPORTED BY THE SPACECRAFT IN THE TIME AND STATUS MESSAGE. REPORTED PERIOD IS THE PERIOD THAT WAS ACTIVE WHEN THE 16-SPIN ACQUISITION CYCLE STARTED. + + + FULL-SECONDS PORTION OF THE TIME AT WHICH THE 16-SPIN CYCLE STARTED + + + SUB-SECONDS PORTION OF THE TIME AT WHICH THE 16-SPIN CYCLE STARTED (MICROSECONDS) + + + SPARE FOR ALIGNMENT + + + BIAS GAIN MODE FOR THE SUPRATHERMAL SECTOR + + + BIAS GAIN MODE FOR THE SOLARWIND SECTOR + + + UNIQUE ID ASSIGNED TO A SPECIFIC TABLE CONFIGURATION. THIS FIELD IS USED TO LINK THE OVERALL ACQUISITION AND PROCESSING SETTINGS TO A SPECIFIC TABLE CONFIGURATION. + + + PLAN TABLE THAT WAS IN USE + + + PLAN STEP THAT WAS ACTIVE WHEN THIS DATA WAS ACQUIRED AND PROCESSED. + + + VIEW ID PROVIDES INFORMATION ABOUT HOW DATA WAS COLLAPSED AND/OR COMPRESSED. + + + SPARE FOR ALIGNMENT + + + INDICATES THE POINT WHEN REDUCED GAIN FACTOR OPERATION (RGFO) WAS ACTIVED. IN RGFO, THE ENTRANCE ESA VOLTAGE IS REDUCED IN ORDER TO LIMIT THE NUMBER OF IONS THAT REACH THE DETECTORS. + + + INDICATES THE POINT WHEN REDUCED GAIN FACTOR OPERATION (RGFO) WAS ACTIVED. IN RGFO, THE ENTRANCE ESA VOLTAGE IS REDUCED IN ORDER TO LIMIT THE NUMBER OF IONS THAT REACH THE DETECTORS. + + + INDICATES THE POINT WHEN REDUCED GAIN FACTOR OPERATION (RGFO) WAS ACTIVED. IN RGFO, THE ENTRANCE ESA VOLTAGE IS REDUCED IN ORDER TO LIMIT THE NUMBER OF IONS THAT REACH THE DETECTORS. + + + INDICATES THE POINT WHEN NO-SCAN OPERATION (NSO) WAS ACTIVED. IN NSO, THE ESA VOLTAGE IS SET TO THE FIRST STEP IN THE SCAN AND REMAINS FIXED UNTIL THE NEXT CYCLE BOUNDARY. + + + INDICATES THE POINT WHEN NO-SCAN OPERATION (NSO) WAS ACTIVED. IN NSO, THE ESA VOLTAGE IS SET TO THE FIRST STEP IN THE SCAN AND REMAINS FIXED UNTIL THE NEXT CYCLE BOUNDARY. + + + INDICATES THE POINT WHEN NO-SCAN OPERATION (NSO) WAS ACTIVED. IN NSO, THE ESA VOLTAGE IS SET TO THE FIRST STEP IN THE SCAN AND REMAINS FIXED UNTIL THE NEXT CYCLE BOUNDARY. + + + SPARE FOR ALIGNMENT + + + SPARE FOR ALIGNMENT + + + INDICATES THAT THERE WAS SOME ERROR DETECTED DURING ACQUISITION OR PROCESSING OF THE DATA. ERRORS COULD INCLUDE CORRUPTED ACQUISITION MEMORY (I.E. EDAC ERRORS), TIMING VIOLATIONS, OR OTHER EVENTS THAT INTERRUPTED OR OTHERWISE AFFECTED DATA COLLECTION. + + + WHETHER/HOW THE DATA IS COMPRESSED. + + + NUMBER OF BYTES IN THE DATA ARRAY. IF COMPRESSED, THIS VALUE REPRESENTS THE LENGTH OF THE COMPRESSED DATA. + + + COUNTER DATA + +VARIABLE LENGTH; MAXIMUM (BASED ON UNCOLLAPSED, UNCOMPRESSED DATA, AND ASSUMING ALL 8 PRIORITY-COUNTERS INCLUDED): + +128 ENERGIES X 24 POSITIONS X 12 SPIN-ANGLES X 32 BITS X 8 COUNTERS = 9,437,184 BITS (1,179,648 BYTES) + +REALISTICALLY, DATA IS AGGRESSIVELY COLLAPSED AND COMPRESSED, AND ONLY A SUBSET OF THE 32 SPECIES COUNTERS WILL BE INCLUDED, SO THIS DATA FIELD WILL BE MUCH SMALLER THAN THE MAXIMUM. + +DATA FORMAT IS A SERIES OF SPIN-ANGLE X POSITION X ENERGY DATA CUBES COLLAPSED PER THE SCI_LUT COLLAPSE TABLE SELECTED BY THE VIEW_ID. WHICH COUNTERS ARE INCLUDED IS DETERMINED BY USING THE PLAN_ID AND PLAN_STEP TO INDEX INTO THE SCI_LUT DATA PRODUCTS HI/LO TABLES TO FIND ALL THE COUNTERS THAT ARE ASSOCIATED WITH THE VIEW_ID. + +THE COLLAPSED DATA CUBES ARE ALSO OPTIONALLY COMPRESSED USING LOSSY AND/OR LOSSLESS COMPRESSION. LOSSY COMPRESSION IS A TABLE-BASED 24->8 BIT COMPRESSION APPLIED TO EACH COUNTER VALUE. LOSSLESS COMPRESSION USES THE LZMA COMPRESSION ALGORITHM AND IS APPLIED TO THE FULL DATA FIELD AS A SINGLE UNIT. + +FIELD WILL ADDITIONALLY BE PADDED IN ORDER TO MEET THE REQUIREMENT OF PACKETS BEING A MULTIPLE OF 16 BITS; ANY PAD BITS WILL BE ACCOUNTED FOR IN THE CCSDS HEADER LENGTH FIELD, BUT WILL *NOT* BE INCLUDED IN THE BYTE_COUNT FIELD + +WHEN THIS ARRAY IS TOO LARGE FOR A SINGLE CCSDS PACKET, CODICE WILL UTILIZE THE CCSDS GROUPING FLAGS TO PROVIDE THE FULL DATA PACKET OVER SEVERAL CCSDS PACKETS. + + + PACKET CHECKSUM + + + SECONDARY HEADER - WHOLE-SECONDS PART OF SCLK + + + PACKET VERSION - THIS WILL BE INCREMENTED EACH TIME THE FORMAT OF THE PACKET CHANGES. + + + SPIN PERIOD REPORTED BY THE SPACECRAFT IN THE TIME AND STATUS MESSAGE. REPORTED PERIOD IS THE PERIOD THAT WAS ACTIVE WHEN THE 16-SPIN ACQUISITION CYCLE STARTED. + + + FULL-SECONDS PORTION OF THE TIME AT WHICH THE 16-SPIN CYCLE STARTED + + + SUB-SECONDS PORTION OF THE TIME AT WHICH THE 16-SPIN CYCLE STARTED (MICROSECONDS) + + + SPARE FOR ALIGNMENT + + + BIAS GAIN MODE FOR THE SUPRATHERMAL SECTOR + + + BIAS GAIN MODE FOR THE SOLARWIND SECTOR + + + UNIQUE ID ASSIGNED TO A SPECIFIC TABLE CONFIGURATION. THIS FIELD IS USED TO LINK THE OVERALL ACQUISITION AND PROCESSING SETTINGS TO A SPECIFIC TABLE CONFIGURATION. + + + PLAN TABLE THAT WAS IN USE + + + PLAN STEP THAT WAS ACTIVE WHEN THIS DATA WAS ACQUIRED AND PROCESSED. + + + VIEW ID PROVIDES INFORMATION ABOUT HOW DATA WAS COLLAPSED AND/OR COMPRESSED. + + + SPARE FOR ALIGNMENT + + + INDICATES THE POINT WHEN REDUCED GAIN FACTOR OPERATION (RGFO) WAS ACTIVED. IN RGFO, THE ENTRANCE ESA VOLTAGE IS REDUCED IN ORDER TO LIMIT THE NUMBER OF IONS THAT REACH THE DETECTORS. + + + INDICATES THE POINT WHEN REDUCED GAIN FACTOR OPERATION (RGFO) WAS ACTIVED. IN RGFO, THE ENTRANCE ESA VOLTAGE IS REDUCED IN ORDER TO LIMIT THE NUMBER OF IONS THAT REACH THE DETECTORS. + + + INDICATES THE POINT WHEN REDUCED GAIN FACTOR OPERATION (RGFO) WAS ACTIVED. IN RGFO, THE ENTRANCE ESA VOLTAGE IS REDUCED IN ORDER TO LIMIT THE NUMBER OF IONS THAT REACH THE DETECTORS. + + + INDICATES THE POINT WHEN NO-SCAN OPERATION (NSO) WAS ACTIVED. IN NSO, THE ESA VOLTAGE IS SET TO THE FIRST STEP IN THE SCAN AND REMAINS FIXED UNTIL THE NEXT CYCLE BOUNDARY. + + + INDICATES THE POINT WHEN NO-SCAN OPERATION (NSO) WAS ACTIVED. IN NSO, THE ESA VOLTAGE IS SET TO THE FIRST STEP IN THE SCAN AND REMAINS FIXED UNTIL THE NEXT CYCLE BOUNDARY. + + + INDICATES THE POINT WHEN NO-SCAN OPERATION (NSO) WAS ACTIVED. IN NSO, THE ESA VOLTAGE IS SET TO THE FIRST STEP IN THE SCAN AND REMAINS FIXED UNTIL THE NEXT CYCLE BOUNDARY. + + + SPARE FOR ALIGNMENT + + + SPARE FOR ALIGNMENT + + + INDICATES THAT THERE WAS SOME ERROR DETECTED DURING ACQUISITION OR PROCESSING OF THE DATA. ERRORS COULD INCLUDE CORRUPTED ACQUISITION MEMORY (I.E. EDAC ERRORS), TIMING VIOLATIONS, OR OTHER EVENTS THAT INTERRUPTED OR OTHERWISE AFFECTED DATA COLLECTION. + + + WHETHER/HOW THE DATA IS COMPRESSED. + + + NUMBER OF BYTES IN THE DATA ARRAY. IF COMPRESSED, THIS VALUE REPRESENTS THE LENGTH OF THE COMPRESSED DATA. + + + COUNTER DATA + +VARIABLE LENGTH; MAXIMUM (BASED ON UNCOLLAPSED, UNCOMPRESSED DATA, AND ASSUMING ALL 22 INSTRUMENT RATE COUNTERS INCLUDED): + +128 ENERGIES X 24 POSITIONS X 12 SPIN-ANGLES X 32 BITS X 22 COUNTERS = 25,952,256 BITS (3,244,032 BYTES) + +REALISTICALLY, DATA IS AGGRESSIVELY COLLAPSED AND COMPRESSED, AND ONLY A SUBSET OF THE 32 SPECIES COUNTERS WILL BE INCLUDED, SO THIS DATA FIELD WILL BE MUCH SMALLER THAN THE MAXIMUM. + +DATA FORMAT IS A SERIES OF SPIN-ANGLE X POSITION X ENERGY DATA CUBES COLLAPSED PER THE SCI_LUT COLLAPSE TABLE SELECTED BY THE VIEW_ID. WHICH COUNTERS ARE INCLUDED IS DETERMINED BY USING THE PLAN_ID AND PLAN_STEP TO INDEX INTO THE SCI_LUT DATA PRODUCTS HI/LO TABLES TO FIND ALL THE COUNTERS THAT ARE ASSOCIATED WITH THE VIEW_ID. + +THE COLLAPSED DATA CUBES ARE ALSO OPTIONALLY COMPRESSED USING LOSSY AND/OR LOSSLESS COMPRESSION. LOSSY COMPRESSION IS A TABLE-BASED 24->8 BIT COMPRESSION APPLIED TO EACH COUNTER VALUE. LOSSLESS COMPRESSION USES THE LZMA COMPRESSION ALGORITHM AND IS APPLIED TO THE FULL DATA FIELD AS A SINGLE UNIT. + +FIELD WILL ADDITIONALLY BE PADDED IN ORDER TO MEET THE REQUIREMENT OF PACKETS BEING A MULTIPLE OF 16 BITS; ANY PAD BITS WILL BE ACCOUNTED FOR IN THE CCSDS HEADER LENGTH FIELD, BUT WILL *NOT* BE INCLUDED IN THE BYTE_COUNT FIELD + +WHEN THIS ARRAY IS TOO LARGE FOR A SINGLE CCSDS PACKET, CODICE WILL UTILIZE THE CCSDS GROUPING FLAGS TO PROVIDE THE FULL DATA PACKET OVER SEVERAL CCSDS PACKETS. + + + PACKET CHECKSUM + + + SECONDARY HEADER - WHOLE-SECONDS PART OF SCLK + + + PACKET VERSION - THIS WILL BE INCREMENTED EACH TIME THE FORMAT OF THE PACKET CHANGES. + + + SPIN PERIOD REPORTED BY THE SPACECRAFT IN THE TIME AND STATUS MESSAGE. REPORTED PERIOD IS THE PERIOD THAT WAS ACTIVE WHEN THE 16-SPIN ACQUISITION CYCLE STARTED. + + + FULL-SECONDS PORTION OF THE TIME AT WHICH THE 16-SPIN CYCLE STARTED + + + SUB-SECONDS PORTION OF THE TIME AT WHICH THE 16-SPIN CYCLE STARTED (MICROSECONDS) + + + SPARE FOR ALIGNMENT + + + BIAS GAIN MODE FOR THE SUPRATHERMAL SECTOR + + + BIAS GAIN MODE FOR THE SOLARWIND SECTOR + + + UNIQUE ID ASSIGNED TO A SPECIFIC TABLE CONFIGURATION. THIS FIELD IS USED TO LINK THE OVERALL ACQUISITION AND PROCESSING SETTINGS TO A SPECIFIC TABLE CONFIGURATION. + + + PLAN TABLE THAT WAS IN USE + + + PLAN STEP THAT WAS ACTIVE WHEN THIS DATA WAS ACQUIRED AND PROCESSED. + + + VIEW ID PROVIDES INFORMATION ABOUT HOW DATA WAS COLLAPSED AND/OR COMPRESSED. + + + SPARE FOR ALIGNMENT + + + INDICATES THE POINT WHEN REDUCED GAIN FACTOR OPERATION (RGFO) WAS ACTIVED. IN RGFO, THE ENTRANCE ESA VOLTAGE IS REDUCED IN ORDER TO LIMIT THE NUMBER OF IONS THAT REACH THE DETECTORS. + + + INDICATES THE POINT WHEN REDUCED GAIN FACTOR OPERATION (RGFO) WAS ACTIVED. IN RGFO, THE ENTRANCE ESA VOLTAGE IS REDUCED IN ORDER TO LIMIT THE NUMBER OF IONS THAT REACH THE DETECTORS. + + + INDICATES THE POINT WHEN REDUCED GAIN FACTOR OPERATION (RGFO) WAS ACTIVED. IN RGFO, THE ENTRANCE ESA VOLTAGE IS REDUCED IN ORDER TO LIMIT THE NUMBER OF IONS THAT REACH THE DETECTORS. + + + INDICATES THE POINT WHEN NO-SCAN OPERATION (NSO) WAS ACTIVED. IN NSO, THE ESA VOLTAGE IS SET TO THE FIRST STEP IN THE SCAN AND REMAINS FIXED UNTIL THE NEXT CYCLE BOUNDARY. + + + INDICATES THE POINT WHEN NO-SCAN OPERATION (NSO) WAS ACTIVED. IN NSO, THE ESA VOLTAGE IS SET TO THE FIRST STEP IN THE SCAN AND REMAINS FIXED UNTIL THE NEXT CYCLE BOUNDARY. + + + INDICATES THE POINT WHEN NO-SCAN OPERATION (NSO) WAS ACTIVED. IN NSO, THE ESA VOLTAGE IS SET TO THE FIRST STEP IN THE SCAN AND REMAINS FIXED UNTIL THE NEXT CYCLE BOUNDARY. + + + SPARE FOR ALIGNMENT + + + SPARE FOR ALIGNMENT + + + INDICATES THAT THERE WAS SOME ERROR DETECTED DURING ACQUISITION OR PROCESSING OF THE DATA. ERRORS COULD INCLUDE CORRUPTED ACQUISITION MEMORY (I.E. EDAC ERRORS), TIMING VIOLATIONS, OR OTHER EVENTS THAT INTERRUPTED OR OTHERWISE AFFECTED DATA COLLECTION. + + + WHETHER/HOW THE DATA IS COMPRESSED. + + + NUMBER OF BYTES IN THE DATA ARRAY. IF COMPRESSED, THIS VALUE REPRESENTS THE LENGTH OF THE COMPRESSED DATA. + + + COUNTER DATA + +VARIABLE LENGTH; MAXIMUM (BASED ON UNCOLLAPSED, UNCOMPRESSED DATA, AND ASSUMING ALL 22 INSTRUMENT RATE COUNTERS INCLUDED): + +128 ENERGIES X 24 POSITIONS X 12 SPIN-ANGLES X 32 BITS X 22 COUNTERS = 25,952,256 BITS (3,244,032 BYTES) + +REALISTICALLY, DATA IS AGGRESSIVELY COLLAPSED AND COMPRESSED, AND ONLY A SUBSET OF THE 32 SPECIES COUNTERS WILL BE INCLUDED, SO THIS DATA FIELD WILL BE MUCH SMALLER THAN THE MAXIMUM. + +DATA FORMAT IS A SERIES OF SPIN-ANGLE X POSITION X ENERGY DATA CUBES COLLAPSED PER THE SCI_LUT COLLAPSE TABLE SELECTED BY THE VIEW_ID. WHICH COUNTERS ARE INCLUDED IS DETERMINED BY USING THE PLAN_ID AND PLAN_STEP TO INDEX INTO THE SCI_LUT DATA PRODUCTS HI/LO TABLES TO FIND ALL THE COUNTERS THAT ARE ASSOCIATED WITH THE VIEW_ID. + +THE COLLAPSED DATA CUBES ARE ALSO OPTIONALLY COMPRESSED USING LOSSY AND/OR LOSSLESS COMPRESSION. LOSSY COMPRESSION IS A TABLE-BASED 24->8 BIT COMPRESSION APPLIED TO EACH COUNTER VALUE. LOSSLESS COMPRESSION USES THE LZMA COMPRESSION ALGORITHM AND IS APPLIED TO THE FULL DATA FIELD AS A SINGLE UNIT. + +FIELD WILL ADDITIONALLY BE PADDED IN ORDER TO MEET THE REQUIREMENT OF PACKETS BEING A MULTIPLE OF 16 BITS; ANY PAD BITS WILL BE ACCOUNTED FOR IN THE CCSDS HEADER LENGTH FIELD, BUT WILL *NOT* BE INCLUDED IN THE BYTE_COUNT FIELD + +WHEN THIS ARRAY IS TOO LARGE FOR A SINGLE CCSDS PACKET, CODICE WILL UTILIZE THE CCSDS GROUPING FLAGS TO PROVIDE THE FULL DATA PACKET OVER SEVERAL CCSDS PACKETS. + + + PACKET CHECKSUM + + + SECONDARY HEADER - WHOLE-SECONDS PART OF SCLK + + + OPTIONALLY COMPRESSED ARRAY OF EVENT DATA + +FORMAT IS TBD; SOME CONSIDERATIONS/OPTIONS: +- FULL EVENTS HAVE A LOT OF REDUNDANT DATA (E.G. WILL HAVE MANY EVENTS WITH THE SAME PRIORITY/SPIN/SPIN PHASE INFORMATION). HOW WELL DOES COMPRESSION TO DEAL WITH THE REDUNDANCY? +- COULD INCLUDE MINI-HEADERS FOR EACH (PRIORITY,SPIN, SPIN-PHASE) GROUP AND STRIP THE REDUNDANT DATA FROM THE EVENTS +- SHOULD EVENTS BE TIGHTLY PACKED, OR CAN WE PAD OUT TO 64-BIT WORD BOUNDARIES? HOW WELL DOES COMPRESSION COMPENSATE FOR THE EXTRA BITS? + +EACH EVENT CONSISTS OF: +- 10-BIT TOF +- 9-BIT SSD ENERGY +- 2-BIT ENERGY RANGE +- 7-BIT SPIN ANGLE +- 4-BIT SSD POSITION +- 4-BIT SPIN NUMBER +- 2-BIT PHA TYPE + +TBD: EVENTS MAY BE TIGHTLY PACKED, OR MAY HAVE SPARES ADDED TO KEEP EACH EVENT BYTE-ALIGNED. IN EITHER CASE, THERE MAY BE UP TO 1 BYTE OF PADDING TO KEEP THE TOTAL SIZE OF THE PACKET EVEN. + + + PACKET CHECKSUM + + + SECONDARY HEADER - WHOLE-SECONDS PART OF SCLK + + + PACKET VERSION - THIS WILL BE INCREMENTED EACH TIME THE FORMAT OF THE PACKET CHANGES. + + + SPIN PERIOD REPORTED BY THE SPACECRAFT IN THE TIME AND STATUS MESSAGE. REPORTED PERIOD IS THE PERIOD THAT WAS ACTIVE WHEN THE 16-SPIN ACQUISITION CYCLE STARTED. + + + FULL-SECONDS PORTION OF THE TIME AT WHICH THE 16-SPIN CYCLE STARTED + + + SUB-SECONDS PORTION OF THE TIME AT WHICH THE 16-SPIN CYCLE STARTED (MICROSECONDS) + + + SPARE FOR ALIGNMENT + + + BIAS GAIN MODE FOR THE SUPRATHERMAL SECTOR + + + BIAS GAIN MODE FOR THE SOLARWIND SECTOR + + + UNIQUE ID ASSIGNED TO A SPECIFIC TABLE CONFIGURATION. THIS FIELD IS USED TO LINK THE OVERALL ACQUISITION AND PROCESSING SETTINGS TO A SPECIFIC TABLE CONFIGURATION. + + + PLAN TABLE THAT WAS IN USE + + + PLAN STEP THAT WAS ACTIVE WHEN THIS DATA WAS ACQUIRED AND PROCESSED. + + + VIEW ID PROVIDES INFORMATION ABOUT HOW DATA WAS COLLAPSED AND/OR COMPRESSED. + + + SPARE FOR ALIGNMENT + + + INDICATES THE POINT WHEN REDUCED GAIN FACTOR OPERATION (RGFO) WAS ACTIVED. IN RGFO, THE ENTRANCE ESA VOLTAGE IS REDUCED IN ORDER TO LIMIT THE NUMBER OF IONS THAT REACH THE DETECTORS. + + + INDICATES THE POINT WHEN REDUCED GAIN FACTOR OPERATION (RGFO) WAS ACTIVED. IN RGFO, THE ENTRANCE ESA VOLTAGE IS REDUCED IN ORDER TO LIMIT THE NUMBER OF IONS THAT REACH THE DETECTORS. + + + INDICATES THE POINT WHEN REDUCED GAIN FACTOR OPERATION (RGFO) WAS ACTIVED. IN RGFO, THE ENTRANCE ESA VOLTAGE IS REDUCED IN ORDER TO LIMIT THE NUMBER OF IONS THAT REACH THE DETECTORS. + + + INDICATES THE POINT WHEN NO-SCAN OPERATION (NSO) WAS ACTIVED. IN NSO, THE ESA VOLTAGE IS SET TO THE FIRST STEP IN THE SCAN AND REMAINS FIXED UNTIL THE NEXT CYCLE BOUNDARY. + + + INDICATES THE POINT WHEN NO-SCAN OPERATION (NSO) WAS ACTIVED. IN NSO, THE ESA VOLTAGE IS SET TO THE FIRST STEP IN THE SCAN AND REMAINS FIXED UNTIL THE NEXT CYCLE BOUNDARY. + + + INDICATES THE POINT WHEN NO-SCAN OPERATION (NSO) WAS ACTIVED. IN NSO, THE ESA VOLTAGE IS SET TO THE FIRST STEP IN THE SCAN AND REMAINS FIXED UNTIL THE NEXT CYCLE BOUNDARY. + + + SPARE FOR ALIGNMENT + + + SPARE FOR ALIGNMENT + + + INDICATES THAT THERE WAS SOME ERROR DETECTED DURING ACQUISITION OR PROCESSING OF THE DATA. ERRORS COULD INCLUDE CORRUPTED ACQUISITION MEMORY (I.E. EDAC ERRORS), TIMING VIOLATIONS, OR OTHER EVENTS THAT INTERRUPTED OR OTHERWISE AFFECTED DATA COLLECTION. + + + WHETHER/HOW THE DATA IS COMPRESSED. + + + NUMBER OF BYTES IN THE DATA ARRAY. IF COMPRESSED, THIS VALUE REPRESENTS THE LENGTH OF THE COMPRESSED DATA. + + + COUNTER DATA + +VARIABLE LENGTH; + +MAXIMUM (BASED ON UNCOLLAPSED, UNCOMPRESSED DATA, AND ASSUMING ALL COUNTERS INCLUDED): + +16 SPINS X 16 POSITIONS X 24 SPIN-ANGLES X 32 BITS X 22 COUNTERS = 4,325,376 BITS (540,672 BYTES) + +NOMINAL (BASED ON CURRENT PLAN FOR COUNTER SELECTION, COLLAPSING, AND COMPRESSION): 840 BITS (105 BYTES) + +DATA FORMAT IS A SERIES OF SPIN-ANGLE X POSITION X SPIN NUMBER DATA CUBES COLLAPSED PER THE SCI_LUT COLLAPSE TABLE SELECTED BY THE VIEW_ID. WHICH COUNTERS ARE INCLUDED IS DETERMINED BY USING THE PLAN_ID AND PLAN_STEP TO INDEX INTO THE SCI_LUT DATA PRODUCTS HI/LO TABLES TO FIND ALL THE COUNTERS THAT ARE ASSOCIATED WITH THE VIEW_ID. + +THE COLLAPSED DATA CUBES ARE ALSO OPTIONALLY COMPRESSED USING LOSSY AND/OR LOSSLESS COMPRESSION. LOSSY COMPRESSION IS A TABLE-BASED 24->8 BIT COMPRESSION APPLIED TO EACH COUNTER VALUE. LOSSLESS COMPRESSION USES THE LZMA COMPRESSION ALGORITHM AND IS APPLIED TO THE FULL DATA FIELD AS A SINGLE UNIT. + +FIELD WILL ADDITIONALLY BE PADDED IN ORDER TO MEET THE REQUIREMENT OF PACKETS BEING A MULTIPLE OF 16 BITS; ANY PAD BITS WILL BE ACCOUNTED FOR IN THE CCSDS HEADER LENGTH FIELD, BUT WILL *NOT* BE INCLUDED IN THE BYTE_COUNT FIELD + +WHEN THIS ARRAY IS TOO LARGE FOR A SINGLE CCSDS PACKET, CODICE WILL UTILIZE THE CCSDS GROUPING FLAGS TO PROVIDE THE FULL DATA PACKET OVER SEVERAL CCSDS PACKETS. + + + PACKET CHECKSUM + + + SECONDARY HEADER - WHOLE-SECONDS PART OF SCLK + + + PACKET VERSION - THIS WILL BE INCREMENTED EACH TIME THE FORMAT OF THE PACKET CHANGES. + + + SPIN PERIOD REPORTED BY THE SPACECRAFT IN THE TIME AND STATUS MESSAGE. REPORTED PERIOD IS THE PERIOD THAT WAS ACTIVE WHEN THE 16-SPIN ACQUISITION CYCLE STARTED. + + + FULL-SECONDS PORTION OF THE TIME AT WHICH THE 16-SPIN CYCLE STARTED + + + SUB-SECONDS PORTION OF THE TIME AT WHICH THE 16-SPIN CYCLE STARTED (MICROSECONDS) + + + SPARE FOR ALIGNMENT + + + BIAS GAIN MODE FOR THE SUPRATHERMAL SECTOR + + + BIAS GAIN MODE FOR THE SOLARWIND SECTOR + + + UNIQUE ID ASSIGNED TO A SPECIFIC TABLE CONFIGURATION. THIS FIELD IS USED TO LINK THE OVERALL ACQUISITION AND PROCESSING SETTINGS TO A SPECIFIC TABLE CONFIGURATION. + + + PLAN TABLE THAT WAS IN USE + + + PLAN STEP THAT WAS ACTIVE WHEN THIS DATA WAS ACQUIRED AND PROCESSED. + + + VIEW ID PROVIDES INFORMATION ABOUT HOW DATA WAS COLLAPSED AND/OR COMPRESSED. + + + SPARE FOR ALIGNMENT + + + INDICATES THE POINT WHEN REDUCED GAIN FACTOR OPERATION (RGFO) WAS ACTIVED. IN RGFO, THE ENTRANCE ESA VOLTAGE IS REDUCED IN ORDER TO LIMIT THE NUMBER OF IONS THAT REACH THE DETECTORS. + + + INDICATES THE POINT WHEN REDUCED GAIN FACTOR OPERATION (RGFO) WAS ACTIVED. IN RGFO, THE ENTRANCE ESA VOLTAGE IS REDUCED IN ORDER TO LIMIT THE NUMBER OF IONS THAT REACH THE DETECTORS. + + + INDICATES THE POINT WHEN REDUCED GAIN FACTOR OPERATION (RGFO) WAS ACTIVED. IN RGFO, THE ENTRANCE ESA VOLTAGE IS REDUCED IN ORDER TO LIMIT THE NUMBER OF IONS THAT REACH THE DETECTORS. + + + INDICATES THE POINT WHEN NO-SCAN OPERATION (NSO) WAS ACTIVED. IN NSO, THE ESA VOLTAGE IS SET TO THE FIRST STEP IN THE SCAN AND REMAINS FIXED UNTIL THE NEXT CYCLE BOUNDARY. + + + INDICATES THE POINT WHEN NO-SCAN OPERATION (NSO) WAS ACTIVED. IN NSO, THE ESA VOLTAGE IS SET TO THE FIRST STEP IN THE SCAN AND REMAINS FIXED UNTIL THE NEXT CYCLE BOUNDARY. + + + INDICATES THE POINT WHEN NO-SCAN OPERATION (NSO) WAS ACTIVED. IN NSO, THE ESA VOLTAGE IS SET TO THE FIRST STEP IN THE SCAN AND REMAINS FIXED UNTIL THE NEXT CYCLE BOUNDARY. + + + SPARE FOR ALIGNMENT + + + SPARE FOR ALIGNMENT + + + INDICATES THAT THERE WAS SOME ERROR DETECTED DURING ACQUISITION OR PROCESSING OF THE DATA. ERRORS COULD INCLUDE CORRUPTED ACQUISITION MEMORY (I.E. EDAC ERRORS), TIMING VIOLATIONS, OR OTHER EVENTS THAT INTERRUPTED OR OTHERWISE AFFECTED DATA COLLECTION. + + + WHETHER/HOW THE DATA IS COMPRESSED. + + + NUMBER OF BYTES IN THE DATA ARRAY. IF COMPRESSED, THIS VALUE REPRESENTS THE LENGTH OF THE COMPRESSED DATA. + + + COUNTER DATA + +VARIABLE LENGTH; + +MAXIMUM (BASED ON UNCOLLAPSED, UNCOMPRESSED DATA, AND ASSUMING ALL COUNTERS INCLUDED): + +16 SPINS X 16 POSITIONS X 24 SPIN-ANGLES X 32 BITS X 22 COUNTERS = 4,325,376 BITS (540,672 BYTES) + +NOMINAL (BASED ON CURRENT PLAN FOR COUNTER SELECTION, COLLAPSING, AND COMPRESSION): 840 BITS (105 BYTES) + +DATA FORMAT IS A SERIES OF SPIN-ANGLE X POSITION X SPIN NUMBER DATA CUBES COLLAPSED PER THE SCI_LUT COLLAPSE TABLE SELECTED BY THE VIEW_ID. WHICH COUNTERS ARE INCLUDED IS DETERMINED BY USING THE PLAN_ID AND PLAN_STEP TO INDEX INTO THE SCI_LUT DATA PRODUCTS HI/LO TABLES TO FIND ALL THE COUNTERS THAT ARE ASSOCIATED WITH THE VIEW_ID. + +THE COLLAPSED DATA CUBES ARE ALSO OPTIONALLY COMPRESSED USING LOSSY AND/OR LOSSLESS COMPRESSION. LOSSY COMPRESSION IS A TABLE-BASED 24->8 BIT COMPRESSION APPLIED TO EACH COUNTER VALUE. LOSSLESS COMPRESSION USES THE LZMA COMPRESSION ALGORITHM AND IS APPLIED TO THE FULL DATA FIELD AS A SINGLE UNIT. + +FIELD WILL ADDITIONALLY BE PADDED IN ORDER TO MEET THE REQUIREMENT OF PACKETS BEING A MULTIPLE OF 16 BITS; ANY PAD BITS WILL BE ACCOUNTED FOR IN THE CCSDS HEADER LENGTH FIELD, BUT WILL *NOT* BE INCLUDED IN THE BYTE_COUNT FIELD + +WHEN THIS ARRAY IS TOO LARGE FOR A SINGLE CCSDS PACKET, CODICE WILL UTILIZE THE CCSDS GROUPING FLAGS TO PROVIDE THE FULL DATA PACKET OVER SEVERAL CCSDS PACKETS. + + + PACKET CHECKSUM + + + SECONDARY HEADER - WHOLE-SECONDS PART OF SCLK + + + PACKET VERSION - THIS WILL BE INCREMENTED EACH TIME THE FORMAT OF THE PACKET CHANGES. + + + SPIN PERIOD REPORTED BY THE SPACECRAFT IN THE TIME AND STATUS MESSAGE. REPORTED PERIOD IS THE PERIOD THAT WAS ACTIVE WHEN THE 16-SPIN ACQUISITION CYCLE STARTED. + + + FULL-SECONDS PORTION OF THE TIME AT WHICH THE 16-SPIN CYCLE STARTED + + + SUB-SECONDS PORTION OF THE TIME AT WHICH THE 16-SPIN CYCLE STARTED (MICROSECONDS) + + + SPARE FOR ALIGNMENT + + + BIAS GAIN MODE FOR THE SUPRATHERMAL SECTOR + + + BIAS GAIN MODE FOR THE SOLARWIND SECTOR + + + UNIQUE ID ASSIGNED TO A SPECIFIC TABLE CONFIGURATION. THIS FIELD IS USED TO LINK THE OVERALL ACQUISITION AND PROCESSING SETTINGS TO A SPECIFIC TABLE CONFIGURATION. + + + PLAN TABLE THAT WAS IN USE + + + PLAN STEP THAT WAS ACTIVE WHEN THIS DATA WAS ACQUIRED AND PROCESSED. + + + VIEW ID PROVIDES INFORMATION ABOUT HOW DATA WAS COLLAPSED AND/OR COMPRESSED. + + + SPARE FOR ALIGNMENT + + + INDICATES THE POINT WHEN REDUCED GAIN FACTOR OPERATION (RGFO) WAS ACTIVED. IN RGFO, THE ENTRANCE ESA VOLTAGE IS REDUCED IN ORDER TO LIMIT THE NUMBER OF IONS THAT REACH THE DETECTORS. + + + INDICATES THE POINT WHEN REDUCED GAIN FACTOR OPERATION (RGFO) WAS ACTIVED. IN RGFO, THE ENTRANCE ESA VOLTAGE IS REDUCED IN ORDER TO LIMIT THE NUMBER OF IONS THAT REACH THE DETECTORS. + + + INDICATES THE POINT WHEN REDUCED GAIN FACTOR OPERATION (RGFO) WAS ACTIVED. IN RGFO, THE ENTRANCE ESA VOLTAGE IS REDUCED IN ORDER TO LIMIT THE NUMBER OF IONS THAT REACH THE DETECTORS. + + + INDICATES THE POINT WHEN NO-SCAN OPERATION (NSO) WAS ACTIVED. IN NSO, THE ESA VOLTAGE IS SET TO THE FIRST STEP IN THE SCAN AND REMAINS FIXED UNTIL THE NEXT CYCLE BOUNDARY. + + + INDICATES THE POINT WHEN NO-SCAN OPERATION (NSO) WAS ACTIVED. IN NSO, THE ESA VOLTAGE IS SET TO THE FIRST STEP IN THE SCAN AND REMAINS FIXED UNTIL THE NEXT CYCLE BOUNDARY. + + + INDICATES THE POINT WHEN NO-SCAN OPERATION (NSO) WAS ACTIVED. IN NSO, THE ESA VOLTAGE IS SET TO THE FIRST STEP IN THE SCAN AND REMAINS FIXED UNTIL THE NEXT CYCLE BOUNDARY. + + + SPARE FOR ALIGNMENT + + + SPARE FOR ALIGNMENT + + + INDICATES THAT THERE WAS SOME ERROR DETECTED DURING ACQUISITION OR PROCESSING OF THE DATA. ERRORS COULD INCLUDE CORRUPTED ACQUISITION MEMORY (I.E. EDAC ERRORS), TIMING VIOLATIONS, OR OTHER EVENTS THAT INTERRUPTED OR OTHERWISE AFFECTED DATA COLLECTION. + + + WHETHER/HOW THE DATA IS COMPRESSED. + + + NUMBER OF BYTES IN THE DATA ARRAY. IF COMPRESSED, THIS VALUE REPRESENTS THE LENGTH OF THE COMPRESSED DATA. + + + COUNTER DATA + +VARIABLE LENGTH; MAXIMUM (BASED ON UNCOLLAPSED, UNCOMPRESSED DATA, AND ASSUMING ALL 146 SQRT(2) SPECEIS COUNTERS INCLUDED): + +16 SPINS X 16 POSITIONS X 24 SPIN-ANGLES X 32 BITS X 146 COUNTERS = 28,704,768 BITS (3,588,096 BYTES) + +NOMINAL (BASED ON CURRENT PLAN FOR COUNTER SELECTION, COLLAPSING, AND COMPRESSION): 42,240 BITS (5,281 BYTES) + +DATA FORMAT IS A SERIES OF SPIN-ANGLE X POSITION X SPIN NUMBER DATA CUBES COLLAPSED PER THE SCI_LUT COLLAPSE TABLE SELECTED BY THE VIEW_ID. WHICH COUNTERS ARE INCLUDED IS DETERMINED BY USING THE PLAN_ID AND PLAN_STEP TO INDEX INTO THE SCI_LUT DATA PRODUCTS HI/LO TABLES TO FIND ALL THE COUNTERS THAT ARE ASSOCIATED WITH THE VIEW_ID. + +THE COLLAPSED DATA CUBES ARE ALSO OPTIONALLY COMPRESSED USING LOSSY AND/OR LOSSLESS COMPRESSION. LOSSY COMPRESSION IS A TABLE-BASED 24->8 BIT COMPRESSION APPLIED TO EACH COUNTER VALUE. LOSSLESS COMPRESSION USES THE LZMA COMPRESSION ALGORITHM AND IS APPLIED TO THE FULL DATA FIELD AS A SINGLE UNIT. + +FIELD WILL ADDITIONALLY BE PADDED IN ORDER TO MEET THE REQUIREMENT OF PACKETS BEING A MULTIPLE OF 16 BITS; ANY PAD BITS WILL BE ACCOUNTED FOR IN THE CCSDS HEADER LENGTH FIELD, BUT WILL *NOT* BE INCLUDED IN THE BYTE_COUNT FIELD + +WHEN THIS ARRAY IS TOO LARGE FOR A SINGLE CCSDS PACKET, CODICE WILL UTILIZE THE CCSDS GROUPING FLAGS TO PROVIDE THE FULL DATA PACKET OVER SEVERAL CCSDS PACKETS. + + + PACKET CHECKSUM + + + SECONDARY HEADER - WHOLE-SECONDS PART OF SCLK + + + PACKET VERSION - THIS WILL BE INCREMENTED EACH TIME THE FORMAT OF THE PACKET CHANGES. + + + SPIN PERIOD REPORTED BY THE SPACECRAFT IN THE TIME AND STATUS MESSAGE. REPORTED PERIOD IS THE PERIOD THAT WAS ACTIVE WHEN THE 16-SPIN ACQUISITION CYCLE STARTED. + + + FULL-SECONDS PORTION OF THE TIME AT WHICH THE 16-SPIN CYCLE STARTED + + + SUB-SECONDS PORTION OF THE TIME AT WHICH THE 16-SPIN CYCLE STARTED (MICROSECONDS) + + + SPARE FOR ALIGNMENT + + + BIAS GAIN MODE FOR THE SUPRATHERMAL SECTOR + + + BIAS GAIN MODE FOR THE SOLARWIND SECTOR + + + UNIQUE ID ASSIGNED TO A SPECIFIC TABLE CONFIGURATION. THIS FIELD IS USED TO LINK THE OVERALL ACQUISITION AND PROCESSING SETTINGS TO A SPECIFIC TABLE CONFIGURATION. + + + PLAN TABLE THAT WAS IN USE + + + PLAN STEP THAT WAS ACTIVE WHEN THIS DATA WAS ACQUIRED AND PROCESSED. + + + VIEW ID PROVIDES INFORMATION ABOUT HOW DATA WAS COLLAPSED AND/OR COMPRESSED. + + + SPARE FOR ALIGNMENT + + + INDICATES THE POINT WHEN REDUCED GAIN FACTOR OPERATION (RGFO) WAS ACTIVED. IN RGFO, THE ENTRANCE ESA VOLTAGE IS REDUCED IN ORDER TO LIMIT THE NUMBER OF IONS THAT REACH THE DETECTORS. + + + INDICATES THE POINT WHEN REDUCED GAIN FACTOR OPERATION (RGFO) WAS ACTIVED. IN RGFO, THE ENTRANCE ESA VOLTAGE IS REDUCED IN ORDER TO LIMIT THE NUMBER OF IONS THAT REACH THE DETECTORS. + + + INDICATES THE POINT WHEN REDUCED GAIN FACTOR OPERATION (RGFO) WAS ACTIVED. IN RGFO, THE ENTRANCE ESA VOLTAGE IS REDUCED IN ORDER TO LIMIT THE NUMBER OF IONS THAT REACH THE DETECTORS. + + + INDICATES THE POINT WHEN NO-SCAN OPERATION (NSO) WAS ACTIVED. IN NSO, THE ESA VOLTAGE IS SET TO THE FIRST STEP IN THE SCAN AND REMAINS FIXED UNTIL THE NEXT CYCLE BOUNDARY. + + + INDICATES THE POINT WHEN NO-SCAN OPERATION (NSO) WAS ACTIVED. IN NSO, THE ESA VOLTAGE IS SET TO THE FIRST STEP IN THE SCAN AND REMAINS FIXED UNTIL THE NEXT CYCLE BOUNDARY. + + + INDICATES THE POINT WHEN NO-SCAN OPERATION (NSO) WAS ACTIVED. IN NSO, THE ESA VOLTAGE IS SET TO THE FIRST STEP IN THE SCAN AND REMAINS FIXED UNTIL THE NEXT CYCLE BOUNDARY. + + + SPARE FOR ALIGNMENT + + + SPARE FOR ALIGNMENT + + + INDICATES THAT THERE WAS SOME ERROR DETECTED DURING ACQUISITION OR PROCESSING OF THE DATA. ERRORS COULD INCLUDE CORRUPTED ACQUISITION MEMORY (I.E. EDAC ERRORS), TIMING VIOLATIONS, OR OTHER EVENTS THAT INTERRUPTED OR OTHERWISE AFFECTED DATA COLLECTION. + + + WHETHER/HOW THE DATA IS COMPRESSED. + + + NUMBER OF BYTES IN THE DATA ARRAY. IF COMPRESSED, THIS VALUE REPRESENTS THE LENGTH OF THE COMPRESSED DATA. + + + COUNTER DATA + +VARIABLE LENGTH; MAXIMUM (BASED ON UNCOLLAPSED, UNCOMPRESSED DATA, AND ASSUMING ALL X2 SPECEIS COUNTERS INCLUDED): + +16 SPINS X 16 POSITIONS X 24 SPIN-ANGLES X 32 BITS X 46 COUNTERS = 9,043,968 BITS (1,130,496 BYTES) + +NOMINAL (BASED ON CURRENT PLAN FOR COUNTER SELECTION, COLLAPSING, AND COMPRESSION): 4672 BITS (584 BYTES) + +DATA FORMAT IS A SERIES OF SPIN-ANGLE X POSITION X SPIN NUMBER DATA CUBES COLLAPSED PER THE SCI_LUT COLLAPSE TABLE SELECTED BY THE VIEW_ID. WHICH COUNTERS ARE INCLUDED IS DETERMINED BY USING THE PLAN_ID AND PLAN_STEP TO INDEX INTO THE SCI_LUT DATA PRODUCTS HI/LO TABLES TO FIND ALL THE COUNTERS THAT ARE ASSOCIATED WITH THE VIEW_ID. + +THE COLLAPSED DATA CUBES ARE ALSO OPTIONALLY COMPRESSED USING LOSSY AND/OR LOSSLESS COMPRESSION. LOSSY COMPRESSION IS A TABLE-BASED 24->8 BIT COMPRESSION APPLIED TO EACH COUNTER VALUE. LOSSLESS COMPRESSION USES THE LZMA COMPRESSION ALGORITHM AND IS APPLIED TO THE FULL DATA FIELD AS A SINGLE UNIT. + +FIELD WILL ADDITIONALLY BE PADDED IN ORDER TO MEET THE REQUIREMENT OF PACKETS BEING A MULTIPLE OF 16 BITS; ANY PAD BITS WILL BE ACCOUNTED FOR IN THE CCSDS HEADER LENGTH FIELD, BUT WILL *NOT* BE INCLUDED IN THE BYTE_COUNT FIELD + +WHEN THIS ARRAY IS TOO LARGE FOR A SINGLE CCSDS PACKET, CODICE WILL UTILIZE THE CCSDS GROUPING FLAGS TO PROVIDE THE FULL DATA PACKET OVER SEVERAL CCSDS PACKETS. + + + PACKET CHECKSUM + + + SECONDARY HEADER - WHOLE-SECONDS PART OF SCLK + + + PACKET VERSION - THIS WILL BE INCREMENTED EACH TIME THE FORMAT OF THE PACKET CHANGES. + + + SPIN PERIOD REPORTED BY THE SPACECRAFT IN THE TIME AND STATUS MESSAGE. REPORTED PERIOD IS THE PERIOD THAT WAS ACTIVE WHEN THE 16-SPIN ACQUISITION CYCLE STARTED. + + + FULL-SECONDS PORTION OF THE TIME AT WHICH THE 16-SPIN CYCLE STARTED + + + SUB-SECONDS PORTION OF THE TIME AT WHICH THE 16-SPIN CYCLE STARTED (MICROSECONDS) + + + SPARE FOR ALIGNMENT + + + BIAS GAIN MODE FOR THE SUPRATHERMAL SECTOR + + + BIAS GAIN MODE FOR THE SOLARWIND SECTOR + + + UNIQUE ID ASSIGNED TO A SPECIFIC TABLE CONFIGURATION. THIS FIELD IS USED TO LINK THE OVERALL ACQUISITION AND PROCESSING SETTINGS TO A SPECIFIC TABLE CONFIGURATION. + + + PLAN TABLE THAT WAS IN USE + + + PLAN STEP THAT WAS ACTIVE WHEN THIS DATA WAS ACQUIRED AND PROCESSED. + + + VIEW ID PROVIDES INFORMATION ABOUT HOW DATA WAS COLLAPSED AND/OR COMPRESSED. + + + SPARE FOR ALIGNMENT + + + INDICATES THE POINT WHEN REDUCED GAIN FACTOR OPERATION (RGFO) WAS ACTIVED. IN RGFO, THE ENTRANCE ESA VOLTAGE IS REDUCED IN ORDER TO LIMIT THE NUMBER OF IONS THAT REACH THE DETECTORS. + + + INDICATES THE POINT WHEN REDUCED GAIN FACTOR OPERATION (RGFO) WAS ACTIVED. IN RGFO, THE ENTRANCE ESA VOLTAGE IS REDUCED IN ORDER TO LIMIT THE NUMBER OF IONS THAT REACH THE DETECTORS. + + + INDICATES THE POINT WHEN REDUCED GAIN FACTOR OPERATION (RGFO) WAS ACTIVED. IN RGFO, THE ENTRANCE ESA VOLTAGE IS REDUCED IN ORDER TO LIMIT THE NUMBER OF IONS THAT REACH THE DETECTORS. + + + INDICATES THE POINT WHEN NO-SCAN OPERATION (NSO) WAS ACTIVED. IN NSO, THE ESA VOLTAGE IS SET TO THE FIRST STEP IN THE SCAN AND REMAINS FIXED UNTIL THE NEXT CYCLE BOUNDARY. + + + INDICATES THE POINT WHEN NO-SCAN OPERATION (NSO) WAS ACTIVED. IN NSO, THE ESA VOLTAGE IS SET TO THE FIRST STEP IN THE SCAN AND REMAINS FIXED UNTIL THE NEXT CYCLE BOUNDARY. + + + INDICATES THE POINT WHEN NO-SCAN OPERATION (NSO) WAS ACTIVED. IN NSO, THE ESA VOLTAGE IS SET TO THE FIRST STEP IN THE SCAN AND REMAINS FIXED UNTIL THE NEXT CYCLE BOUNDARY. + + + SPARE FOR ALIGNMENT + + + SPARE FOR ALIGNMENT + + + INDICATES THAT THERE WAS SOME ERROR DETECTED DURING ACQUISITION OR PROCESSING OF THE DATA. ERRORS COULD INCLUDE CORRUPTED ACQUISITION MEMORY (I.E. EDAC ERRORS), TIMING VIOLATIONS, OR OTHER EVENTS THAT INTERRUPTED OR OTHERWISE AFFECTED DATA COLLECTION. + + + WHETHER/HOW THE DATA IS COMPRESSED. + + + NUMBER OF BYTES IN THE DATA ARRAY. IF COMPRESSED, THIS VALUE REPRESENTS THE LENGTH OF THE COMPRESSED DATA. + + + COUNTER DATA + +VARIABLE LENGTH; + +MAXIMUM (BASED ON UNCOLLAPSED, UNCOMPRESSED DATA, AND ASSUMING ALL COUNTERS INCLUDED): + +16 SPINS X 16 POSITIONS X 24 SPIN-ANGLES X 32 BITS X 22 COUNTERS = 4,325,376 BITS (540,672 BYTES) + +NOMINAL (BASED ON CURRENT PLAN FOR COUNTER SELECTION, COLLAPSING, AND COMPRESSION): 840 BITS (105 BYTES) + +DATA FORMAT IS A SERIES OF SPIN-ANGLE X POSITION X SPIN NUMBER DATA CUBES COLLAPSED PER THE SCI_LUT COLLAPSE TABLE SELECTED BY THE VIEW_ID. WHICH COUNTERS ARE INCLUDED IS DETERMINED BY USING THE PLAN_ID AND PLAN_STEP TO INDEX INTO THE SCI_LUT DATA PRODUCTS HI/LO TABLES TO FIND ALL THE COUNTERS THAT ARE ASSOCIATED WITH THE VIEW_ID. + +THE COLLAPSED DATA CUBES ARE ALSO OPTIONALLY COMPRESSED USING LOSSY AND/OR LOSSLESS COMPRESSION. LOSSY COMPRESSION IS A TABLE-BASED 24->8 BIT COMPRESSION APPLIED TO EACH COUNTER VALUE. LOSSLESS COMPRESSION USES THE LZMA COMPRESSION ALGORITHM AND IS APPLIED TO THE FULL DATA FIELD AS A SINGLE UNIT. + +FIELD WILL ADDITIONALLY BE PADDED IN ORDER TO MEET THE REQUIREMENT OF PACKETS BEING A MULTIPLE OF 16 BITS; ANY PAD BITS WILL BE ACCOUNTED FOR IN THE CCSDS HEADER LENGTH FIELD, BUT WILL *NOT* BE INCLUDED IN THE BYTE_COUNT FIELD + +WHEN THIS ARRAY IS TOO LARGE FOR A SINGLE CCSDS PACKET, CODICE WILL UTILIZE THE CCSDS GROUPING FLAGS TO PROVIDE THE FULL DATA PACKET OVER SEVERAL CCSDS PACKETS. + + + PACKET CHECKSUM + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/imap_processing/codice/utils.py b/imap_processing/codice/utils.py index 23daed6543..0a38b34b53 100644 --- a/imap_processing/codice/utils.py +++ b/imap_processing/codice/utils.py @@ -5,7 +5,45 @@ other CoDICE processing modules. """ +import json +from collections.abc import Callable +from dataclasses import dataclass from enum import IntEnum +from pathlib import Path + +import numpy as np +import xarray as xr + +from imap_processing.codice import constants + + +@dataclass +class ViewTabInfo: + """ + Class to hold view table information. + + Attributes + ---------- + apid : int + The APID for the packet. + collapse_table : int + Collapse table id used to determine the collapse pattern. + compression : int + Compression algorithm used for the packet. + sensor : int + Sensor id (0 for LO, 1 for HI). + three_d_collapsed : int + The 3D collapsed value from the LUT. + view_id : int + The view identifier from the packet. + """ + + apid: int + collapse_table: int + compression: int + sensor: int + three_d_collapsed: int + view_id: int class CODICEAPID(IntEnum): @@ -57,3 +95,494 @@ class CoDICECompression(IntEnum): LOSSY_A_LOSSLESS = 4 LOSSY_B_LOSSLESS = 5 PACK_24_BIT = 6 + + +class SegmentedPacketOrder(IntEnum): + """ENUM for segmented packet order.""" + + UNSEGMENTED = 3 + FIRST_SEGMENT = 1 + CONTINUATION_SEGMENT = 0 + LAST_SEGMENT = 2 + + +def read_sci_lut(file_path: Path, table_id: str) -> dict: + """ + Read the SCI-LUT JSON file for a specific table ID. + + Parameters + ---------- + file_path : pathlib.Path + Path to the SCI-LUT JSON file. + table_id : str + Table identifier to extract from the JSON. + + Returns + ------- + dict + The SCI-LUT data for the specified table id. + """ + sci_lut_data = json.loads(file_path.read_text()).get(f"{table_id}") + if sci_lut_data is None: + raise ValueError(f"SCI-LUT file does not have data for table ID {table_id}.") + return sci_lut_data + + +def get_view_tab_info(json_data: dict, view_id: int, apid: int) -> dict: + """ + Get the view table information for a specific view and APID. + + Parameters + ---------- + json_data : dict + The JSON data loaded from the SCI-LUT file. + view_id : int + The view ID from the packet. + apid : int + The APID from the packet. + + Returns + ------- + dict + The view table information containing details like sensor, + collapse_table, data_product, etc. + """ + apid_hex = f"0x{apid:X}" + # This is how we get view information that will be used to get + # collapse pattern: + # table_id -> view_tab -> (view_id, apid) -> sensor -> collapse_table ->compression + # 'view_tab': {'(0, 0x480)': {'collapse_table': 0, '3d_collapse': 1, 'sensor': 0, + # 'compression':0} + view_tab = json_data.get("view_tab").get(f"({view_id}, {apid_hex})") + return view_tab + + +def get_view_tab_obj( + lut_file: Path, table_id: str, view_id: int, apid: int +) -> tuple[dict, "ViewTabInfo"]: + """ + Read the SCI-LUT and build a ViewTabInfo for the given table ID. + + Parameters + ---------- + lut_file : pathlib.Path + Path to the SCI-LUT JSON file. + table_id : str + Table identifier to extract from the JSON. + view_id : int + The view ID from the packet. + apid : int + The APID from the packet. + + Returns + ------- + tuple[dict, ViewTabInfo] + The SCI-LUT data dict and a populated ViewTabInfo for the given table ID. + """ + sci_lut_data = read_sci_lut(lut_file, table_id) + view_tab_info = get_view_tab_info(sci_lut_data, view_id, apid) + view_tab_obj = ViewTabInfo( + apid=apid, + view_id=view_id, + sensor=view_tab_info["sensor"], + three_d_collapsed=view_tab_info["3d_collapse"], + collapse_table=view_tab_info["collapse_table"], + compression=view_tab_info["compression"], + ) + return sci_lut_data, view_tab_obj + + +def process_by_table_id( + unpacked_dataset: xr.Dataset, + lut_file: Path, + process_fn: Callable[..., xr.Dataset], +) -> xr.Dataset: + """ + Split dataset by unique table_id values, process each group, and recombine. + + This is the shared wrapper logic used by all non-DE/NHK L1A processing + functions. It extracts the fields that are uniform across a packet stream + (``view_id``, ``apid``, ``plan_id``, ``plan_step``), iterates over every + unique ``table_id`` found in the dataset, filters to that group via + ``isel``, calls *process_fn* for each group, and finally concatenates the + results sorted by epoch. + + Parameters + ---------- + unpacked_dataset : xarray.Dataset + Full unpacked dataset from the L0 packet file. + lut_file : pathlib.Path + Path to the SCI-LUT JSON file passed through to *process_fn*. + process_fn : Callable + The private ``_process_xxx`` function to call for each table_id group. + It must accept the signature + ``(group_ds, lut_file, table_id, view_id, apid, plan_id, plan_step)`` + and return an ``xr.Dataset``. + + Returns + ------- + xarray.Dataset + Combined L1A dataset sorted by epoch. + """ + view_id = unpacked_dataset["view_id"].values[0] + apid = unpacked_dataset["pkt_apid"].values[0] + plan_id = unpacked_dataset["plan_id"].values[0] + plan_step = unpacked_dataset["plan_step"].values[0] + + unique_table_ids = np.unique(unpacked_dataset["table_id"].values) + processed = [ + process_fn( + unpacked_dataset.isel( + epoch=unpacked_dataset["table_id"].values == table_id + ), + lut_file, + table_id, + view_id, + apid, + plan_id, + plan_step, + ) + for table_id in unique_table_ids + ] + if len(processed) == 1: + return processed[0] + return xr.concat(processed, dim="epoch").sortby("epoch") + + +def get_collapse_pattern_shape( + json_data: dict, sensor_id: int, collapse_table_id: int +) -> tuple[int, ...]: + """ + Get the collapse pattern for a specific sensor id and collapse table id. + + Parameters + ---------- + json_data : dict + The JSON data loaded from the SCI-LUT file. + sensor_id : int + Sensor identifier (0 for LO, 1 for HI). + collapse_table_id : int + Collapse table id to look up in the SCI-LUT. + + Returns + ------- + tuple[int, int] + () describing the collapsed pattern. Examples: + ``(1,)`` for a fully collapsed 1-D pattern or ``(N, M)`` for a + reduced 2-D pattern. + """ + sensor = "lo" if sensor_id == 0 else "hi" + collapse_matrix = np.array( + json_data[f"collapse_{sensor}"][f"{collapse_table_id}"]["matrix"] + ) + + # Analyze the collapse pattern matrix to determine its reduced shape. + # Steps: + # - Extract non-zero elements from the matrix. + # - Reshape to group unique non-zero rows and columns. + # - If all non-zero values are identical, return (1,) for a fully collapsed pattern. + # - Otherwise, compute the number of unique rows and columns to describe the + # reduced shape. + non_zero_data = np.where(collapse_matrix != 0) + non_zero_reformatted = collapse_matrix[non_zero_data].reshape( + np.unique(non_zero_data[0]).size, np.unique(non_zero_data[1]).size + ) + + if np.unique(non_zero_reformatted).size == 1: + # all non-zero values are identical means -> fully collapsed + return (1,) + + # If not fully collapsed, find repeated patterns in rows and columns + # to reduce shape further. + unique_rows = np.unique(non_zero_reformatted, axis=0) + unique_columns = np.unique(non_zero_reformatted, axis=1) + # Unique spin sectors and instrument azimuths to unpack data + unique_spin_sectors = unique_columns.shape[1] + unique_inst_azs = unique_rows.shape[0] + return (unique_spin_sectors, unique_inst_azs) + + +def get_counters_aggregated_pattern( + json_data: dict, sensor_id: int, collapse_table_id: int +) -> dict: + """ + Return the aggregated counters pattern from the SCI-LUT JSON. + + The counters aggregated pattern is stored as {key: list} in the SCI-LUT JSON. + Each variable can be turned on and off in-flight. Because of that, we need to + be flexible. If any variable is turned off, its corresponding row in the + matrix will be all zeros and fill CDF variable for that row with zeros. + + Parameters + ---------- + json_data : dict + The JSON data loaded from the SCI-LUT file. + sensor_id : int + Sensor identifier (0 for LO, 1 for HI). + collapse_table_id : int + Collapse table id to look up in the SCI-LUT. + + Returns + ------- + dict + The counters key and its corresponding collapse pattern. + """ + sensor = "lo" if sensor_id == 0 else "hi" + full_matrix = json_data[f"collapse_{sensor}"][f"{collapse_table_id}"]["variables"] + # Filter non-zero rows only + non_zero_rows = { + k: data_list for k, data_list in full_matrix.items() if 0 not in data_list + } + # Sort keys in order of unique num of their list. + # Eg. CoDICE Hi's counters-aggregated is not collapsed + # in the order of row by row. It could have collected in this order: + # [ + # [1....1], + # [2....2], + # [3....3], + # [4....4], + # [7....7], + # [8....8], + # [11....11], + # [5....5], + # [6....6], + # [9....9], + # [10....10], + # ] + # Sort to get: + # [ + # [1....1], + # [2....2], + # ... + # [11....11], + in_order_rows = dict(sorted(non_zero_rows.items(), key=lambda item: item[1][0])) + # Now get collapse pattern for all variables by finding + # collapse pattern for the first key. Then replace all key's + # with that because it should be same. If not, + # that will effect these remaining logic. + first_key = next(iter(in_order_rows)) + collapse_patterns = np.array(in_order_rows[first_key]) + # We only look for collapse pattern of columns because each variable + # are rows in the collapse pattern matrix. + unique_columns = np.unique(collapse_patterns, axis=0) + unique_spin_sectors = unique_columns.shape[0] + for key in in_order_rows: + in_order_rows[key] = unique_spin_sectors + return in_order_rows + + +def index_to_position( + json_data: dict, sensor_id: int, collapse_table_id: int +) -> np.ndarray: + """ + Get the indices of non-zero unique rows in the collapse pattern matrix. + + Parameters + ---------- + json_data : dict + The JSON data loaded from the SCI-LUT file. + sensor_id : int + Sensor identifier (0 for LO, 1 for HI). + collapse_table_id : int + Collapse table id to look up in the SCI-LUT. + + Returns + ------- + np.ndarray + Array of indices corresponding to non-zero unique rows. + """ + sensor = "lo" if sensor_id == 0 else "hi" + collapse_matrix = np.array( + json_data[f"collapse_{sensor}"][f"{collapse_table_id}"]["matrix"] + ) + + # Find unique non-zero rows and their original indices + non_zero_row_mask = np.any(collapse_matrix != 0, axis=1) + non_zero_rows = collapse_matrix[non_zero_row_mask] + _, unique_indices = np.unique(non_zero_rows, axis=0, return_index=True) + non_zero_row_indices = np.flatnonzero(non_zero_row_mask)[unique_indices] + return non_zero_row_indices + + +def get_codice_epoch_time( + acq_start_seconds: np.ndarray, + acq_start_subseconds: np.ndarray, + spin_period: np.ndarray, + view_tab_obj: ViewTabInfo, +) -> tuple[np.ndarray, np.ndarray]: + """ + Calculate center time and delta. + + Parameters + ---------- + acq_start_seconds : np.ndarray + Array of acquisition start seconds. + acq_start_subseconds : np.ndarray + Array of acquisition start subseconds. + spin_period : np.ndarray + Array of spin periods. + view_tab_obj : ViewTabInfo + The view table information object. It contains information such as sensor ID + and three_d_collapsed value and others. + + Returns + ------- + tuple[np.ndarray, np.ndarray] + (center_times (s), delta_times (ns)). center_times is converted to + nanoseconds at CDF write time. + """ + # If Lo sensor + if view_tab_obj.sensor == 0: + # Lo sensor, we need to set spins to be constant. + # 32 half spins makes full 16 spins for all non direct event products. + # But Lo direct event's spins is also 16 spins. Because of that, we can use + # the same calculation for all Lo products. + num_spins = 16.0 + # If Hi sensor and Direct Event product + elif view_tab_obj.sensor == 1 and view_tab_obj.apid == CODICEAPID.COD_HI_PHA: + # Use constant 16 spins for Hi PHA + num_spins = 16.0 + # If Non-Direct Event Hi product + else: + # Use 3d_collapsed value from LUT for other Hi products + num_spins = view_tab_obj.three_d_collapsed + + # Units of 'spin ticks', where one 'spin tick' equals 320 microseconds. + # It takes multiple spins to collect data for a view. + spin_period_ns = spin_period.astype(np.float64) * 320 * 1e3 # Convert to ns + delta_times = (num_spins * spin_period_ns) / 2 + # subseconds need to converted to seconds using this formula per CoDICE team: + # subseconds / 65536 gives seconds + center_times_seconds = ( + acq_start_seconds + acq_start_subseconds / 65536 + (delta_times / 1e9) + ) + + return center_times_seconds, delta_times + + +def calculate_acq_time_per_step( + low_stepping_tab: dict, esa_step_dim: int = 128 +) -> np.ndarray: + """ + Calculate acquisition time per step from low stepping table. + + Parameters + ---------- + low_stepping_tab : dict + The low stepping table from the SCI-LUT JSON. + esa_step_dim : int + The ESA step dimension size. + + Returns + ------- + np.ndarray + Array of acquisition times per step of shape (num_esa_steps,). + """ + # These tunable values are used to calculate acquisition time per step + tunable_values = low_stepping_tab["tunable_values"] + + # pre-calculate values + sector_time = tunable_values["spin_time_ms"] / tunable_values["num_sectors_ms"] + sector_margin_ms = tunable_values["sector_margin_ms"] + dwell_fraction = tunable_values["dwell_fraction_percentage"] + min_hv_settle_ms = tunable_values["min_hv_settle_ms"] + max_hv_settle_ms = tunable_values["max_hv_settle_ms"] + num_steps_data = np.array( + low_stepping_tab["num_steps"].get("data"), dtype=np.float64 + ) + # If num_steps_data is less than 128, pad with nan + if len(num_steps_data) < constants.NUM_ESA_STEPS: + pad_size = esa_step_dim - len(num_steps_data) + num_steps_data = np.concatenate((num_steps_data, np.full(pad_size, np.nan))) + # Total non-acquisition time is in column (BD) of science LUT + dwell_fraction_percentage = float(sector_time) * (100.0 - dwell_fraction) / 100.0 + + # Calculate HV settle time per step not adjusted for Min/Max. + # It's in column (BF) of science LUT. + non_adjusted_hv_settle_per_step = ( + dwell_fraction_percentage - sector_margin_ms + ) / num_steps_data + hv_settle_per_step = np.minimum( + np.maximum(non_adjusted_hv_settle_per_step, min_hv_settle_ms), max_hv_settle_ms + ) + # initialize array of nans for acquisition time per step + acq_time_per_step: np.ndarray = np.full(esa_step_dim, np.nan, dtype=np.float64) + # acquisition time per step in milliseconds + # sector_time - sector_margin_ms / num_steps - hv_settle_per_step + acq_time_per_step[: len(num_steps_data)] = ( + (sector_time - sector_margin_ms) / num_steps_data + ) - hv_settle_per_step + # Convert to seconds + return acq_time_per_step / 1e3 + + +def get_energy_info( + energy_table: np.ndarray, +) -> tuple[np.ndarray, np.ndarray, np.ndarray]: + """ + Calculate energy bin centers and deltas from energy table. + + Parameters + ---------- + energy_table : np.ndarray + The species plus and minus energy array. + + Returns + ------- + centers : np.ndarray + The geometric centers of the energy bins. + deltas_minus : np.ndarray + The delta minus values of the energy bins. + deltas_plus : np.ndarray + The delta plus values of the energy bins. + """ + # Find the geometric centers and deltas of the energy bins + # The delta minus is the difference between the center of the bin + # and the 'left edge' of the bin. The delta plus is the difference + # between the 'right edge' of the bin and the center of the bin + min_energy = np.array(energy_table["min_energy"], dtype=np.float64) + max_energy = np.array(energy_table["max_energy"], dtype=np.float64) + + centers = np.sqrt(min_energy * max_energy) + deltas_minus = centers - min_energy + deltas_plus = max_energy - centers + + return centers, deltas_minus, deltas_plus + + +def apply_replacements_to_attrs(attrs: dict, replacements: dict) -> dict: + """ + Return a shallow-copied attrs dict with placeholders replaced. + + This helper replaces occurrences of placeholders like '{species}' and + '{direction}' in string values using simple str.replace calls. It does + not use str.format to avoid errors when templates contain braces for + other reasons. + + Parameters + ---------- + attrs : dict + The attributes dictionary to process (string values may contain + placeholders). + replacements : dict + Mapping of placeholder names (without braces) to replacement values. + + Returns + ------- + dict + New attributes dict with replacements applied to string values. + """ + if not isinstance(attrs, dict): + return attrs + new = {} + for k, v in attrs.items(): + if isinstance(v, str): + s = v + for name, val in replacements.items(): + if val is None: + continue + s = s.replace(f"{{{name}}}", str(val)) + new[k] = s + else: + new[k] = v + return new diff --git a/imap_processing/decom.py b/imap_processing/decom.py deleted file mode 100644 index ffd81cb02e..0000000000 --- a/imap_processing/decom.py +++ /dev/null @@ -1,36 +0,0 @@ -""" -Decommutate a packet file using a given packet definition. - -This module contains a common function that can be used by multiple instruments -to decommutate CCSDS packet data using a given XTCE packet definition. -""" - -from pathlib import Path - -from space_packet_parser import definitions - - -def decom_packets(packet_file: str | Path, xtce_packet_definition: str | Path) -> list: - """ - Unpack CCSDS data packet. - - In this function, we unpack and return data - as it is. Data modification will not be done at this step. - - Parameters - ---------- - packet_file : str - Path to data packet path with filename. - xtce_packet_definition : str - Path to XTCE file with filename. - - Returns - ------- - list - List of all the unpacked data. - """ - packet_definition = definitions.XtcePacketDefinition(xtce_packet_definition) - - with open(packet_file, "rb") as binary_data: - packet_generator = packet_definition.packet_generator(binary_data) - return list(packet_generator) diff --git a/imap_processing/ena_maps/ena_maps.py b/imap_processing/ena_maps/ena_maps.py index d6ba8c60c5..ec6fd41d82 100644 --- a/imap_processing/ena_maps/ena_maps.py +++ b/imap_processing/ena_maps/ena_maps.py @@ -7,7 +7,7 @@ from abc import ABC, abstractmethod from enum import Enum from pathlib import Path -from typing import TypeVar +from typing import ClassVar, TypeVar import astropy_healpix.healpy as hp import numpy as np @@ -16,13 +16,13 @@ from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes from imap_processing.cdf.utils import load_cdf -from imap_processing.ena_maps.utils import map_utils, spatial_utils +from imap_processing.ena_maps.utils import map_utils, naming, spatial_utils # The coordinate names can vary between L1C and L2 data (e.g. azimuth vs longitude), # so we define an enum to handle the coordinate names. from imap_processing.ena_maps.utils.coordinates import CoordNames from imap_processing.spice import geometry -from imap_processing.spice.time import ttj2000ns_to_et +from imap_processing.spice.time import met_to_ttj2000ns, ttj2000ns_to_et logger = logging.getLogger(__name__) @@ -73,7 +73,7 @@ def match_coords_to_indices( input_object: PointingSet | AbstractSkyMap, output_object: PointingSet | AbstractSkyMap, event_et: float | None = None, -) -> NDArray: +) -> NDArray | xr.DataArray: """ Find the output indices corresponding to each input coord between 2 spatial objects. @@ -87,7 +87,7 @@ def match_coords_to_indices( This function always "pushes" the pixels of the input object to corresponding pixels in the output object's unwrapped rectangular grid or healpix tessellation; however, by swapping the input and output objects, one can apply the "pull" method - of index matching. + of index matching. At present, the allowable inputs are either: - A PointingSet object and a SkyMap object, in either order of input/output. @@ -97,7 +97,7 @@ def match_coords_to_indices( Parameters ---------- input_object : PointingSet | AbstractSkyMap - An object containing 1D spatial pixel centers in azimuth and elevation, + An object containing spatial pixel centers in azimuth and elevation, which will be matched to 1D indices of spatial pixels in the output frame. Must contain the Spice frame in which the pixel centers are defined. output_object : PointingSet | AbstractSkyMap @@ -114,11 +114,13 @@ def match_coords_to_indices( Returns ------- - flat_indices_input_grid_output_frame : NDArray - 1D array of pixel indices of the output object corresponding to each pixel in - the input object. The length of the array is equal to the number of pixels in - the input object, and may contain 0, 1, or multiple occurrences of the same - output index. + flat_indices_input_grid_output_frame : xr.DataArray + Array of pixel indices mapping each input object pixel center to a pixel + in the output object. The output xr.DataArray will have the same leading + dimension labels preserved. The shape of the output array is (..., n) + where ... matches the non-spatial dimensions of the input object, and n + is the number of spatial pixels in the input object. Output indices may + contain 0, 1, or multiple occurrences of the same output index. Raises ------ @@ -134,14 +136,15 @@ def match_coords_to_indices( if isinstance(input_object, PointingSet) and isinstance(output_object, PointingSet): raise ValueError("Cannot match indices between two PointingSet objects.") - # If event_et is not specified, use epoch of the PointingSet, if present. + # If event_et is not specified, use the midpoint of the PointingSet, if + # present. # The epoch will be in units of terrestrial time (TT) J2000 nanoseconds, # which must be converted to ephemeris time (ET) for SPICE. if event_et is None: if isinstance(input_object, PointingSet): - event_et = ttj2000ns_to_et(input_object.epoch) + event_et = input_object.midpoint_j2000_et elif isinstance(output_object, PointingSet): - event_et = ttj2000ns_to_et(output_object.epoch) + event_et = output_object.midpoint_j2000_et else: raise ValueError( "Event time must be specified if both objects are SkyMaps." @@ -166,14 +169,14 @@ def match_coords_to_indices( # use ravel_multi_index to get the 1D indices of the pixels in the output frame. az_indices = ( np.digitize( - input_obj_az_el_output_frame[:, 0], + input_obj_az_el_output_frame[..., 0], output_object.sky_grid.az_bin_edges, ) - 1 ) el_indices = ( np.digitize( - input_obj_az_el_output_frame[:, 1], + input_obj_az_el_output_frame[..., 1], output_object.sky_grid.el_bin_edges, ) - 1 @@ -191,8 +194,8 @@ def match_coords_to_indices( # which directly returns the index on the output frame's Healpix tessellation. flat_indices_input_grid_output_frame = hp.ang2pix( nside=output_object.nside, - theta=input_obj_az_el_output_frame[:, 0], # Lon in degrees - phi=input_obj_az_el_output_frame[:, 1], # Lat in degrees + theta=input_obj_az_el_output_frame[..., 0], # Lon in degrees + phi=input_obj_az_el_output_frame[..., 1], # Lat in degrees nest=output_object.nested, lonlat=True, ) @@ -202,6 +205,14 @@ def match_coords_to_indices( f"Received: {output_object.tiling_type}" ) + # Wrap the output indices in a DataArray with the same leading dimensions as + # the input object az_el_points to preserve broadcasting information + input_dims = input_obj_az_el_input_frame.dims[:-1] + flat_indices_input_grid_output_frame = xr.DataArray( + flat_indices_input_grid_output_frame, + dims=input_dims, + ) + return flat_indices_input_grid_output_frame @@ -236,9 +247,10 @@ class PointingSet(ABC): spice_reference_frame: geometry.SpiceFrame # ======== Attributes required to be set in a subclass ======== - # Azimuth and elevation coordinates of each spatial pixel. The ndarray should - # have the shape (n, 2) where n is the number of spatial pixels - az_el_points: np.ndarray + # Azimuth and elevation coordinates of each spatial pixel. Must be an + # xr.DataArray with dimensions (..., spatial_dim, az_el_coord) to preserve + # dimension labels + az_el_points: xr.DataArray # Tuple containing the names of each spatial coordinate of the xarray.Dataset # stored in the data attribute spatial_coords: tuple[str, ...] @@ -274,7 +286,9 @@ def num_points(self) -> int: num_points: int The number of spatial pixels in the pointing set. """ - return self.az_el_points.shape[0] + # Last dimension is az/el vector, the second to last dimension is + # the number of pixels. + return self.az_el_points.shape[-2] @property def epoch(self) -> int: @@ -288,6 +302,19 @@ def epoch(self) -> int: """ return self.data["epoch"].values[0] + @property + def midpoint_j2000_et(self) -> float: + """ + The midpoint of the pointing in ET. + + Returns + ------- + midpoint: int + The midpoint value [J2000 ET] of the pointing set. + """ + epoch_delta = self.data["epoch_delta"].values[0] + return float(ttj2000ns_to_et(self.epoch + epoch_delta / 2)) + @property def unwrapped_dims_dict(self) -> dict[str, tuple[str, ...]]: """ @@ -430,11 +457,12 @@ def __init__( # into shape (number of points in tiling of the sky, 2) where # column 0 (az_el_points[:, 0]) is the azimuth of that point and # column 1 (az_el_points[:, 1]) is the elevation of that point. - self.az_el_points = np.column_stack( - ( - self.sky_grid.az_grid.ravel(), - self.sky_grid.el_grid.ravel(), - ) + self.az_el_points = xr.DataArray( + np.stack( + (self.sky_grid.az_grid.ravel(), self.sky_grid.el_grid.ravel()), + axis=-1, + ), + dims=[CoordNames.GENERIC_PIXEL.value, CoordNames.AZ_EL_VECTOR.value], ) @@ -540,9 +568,12 @@ def __init__( # The coordinates of the healpix pixel centers are stored as a 2D array # of shape (num_points, 2) where column 0 is the lon/az # and column 1 is the lat/el. - self.az_el_points = np.column_stack( - (azimuth_pixel_center, elevation_pixel_center) + self.az_el_points = xr.DataArray( + np.stack((azimuth_pixel_center, elevation_pixel_center), axis=-1), + dims=[CoordNames.GENERIC_PIXEL.value, CoordNames.AZ_EL_VECTOR.value], ) + # downsample counts variable to match the nside of the pointing set + self.downsample_counts() @property def num_points(self) -> int: @@ -585,8 +616,131 @@ def __repr__(self) -> str: f"num_points={self.num_points})" ) + def downsample_counts(self) -> None: + """ + Downsample the counts variable to match the pset nside. -class HiPointingSet(PointingSet): + Counts at l1c are sampled at a finer resolution to help maintain the + pointing accuracy for each event. Since count maps are a binned integral + quantity, they necessarily require a non-spun approach per Pointing, unlike + exposure time and sensitivities. We need to downsample the counts from the + nside of the input pset counts variable (e.g. 128) to the nside of the pset. + """ + pset_data = self.data + # TODO remove this check once we reprocess all psets + # going forward, all psets should have counts_pixel_index as a coordinate. + if "counts_pixel_index" not in pset_data.dims: + logger.info( + "No counts_pixel_index found in the dataset. Skipping counts " + "downsampling." + ) + return + counts_n_pix = pset_data.sizes["counts_pixel_index"] + pset_n_pix = hp.nside2npix(self.nside) + if counts_n_pix != pset_n_pix: + # Raise an error if the nside the counts were sampled at is lower than the + # nside of the output map. We never want counts to be upsampled. + if counts_n_pix < pset_n_pix: + raise ValueError( + f"Counts in the input PSET are sampled at nside " + f"{hp.npix2nside(counts_n_pix)}, and the pset is {self.nside}. " + f"This would require upsampling the counts, which we do not want." + ) + counts_nside = hp.npix2nside(counts_n_pix) + n_energy_bins = pset_data.sizes["energy_bin_geometric_mean"] + order_diff = int(np.log2(counts_nside // self.nside)) + counts = pset_data["counts"].values[ + 0 + ] # shape: (n_energy_bins, counts_n_pix) + # Get counts in nested ordering. In nested ordering, the + # pixels that need to be binned together to go from the counts nside to + # the pset nside are contiguous in the array. + # Use nest2ring to get the indices to convert from ring to nest ordering if + # necessary. + if not self.nested: + counts_n = counts[ + :, hp.nest2ring(counts_nside, np.arange(counts_n_pix)) + ] + else: + counts_n = counts + + # reshape the counts by the amount pixels to bin together which is + # 4**order_diff because each step in order multiplies the pixel count + # by 4 + # Shape: (n_energy_bins, pset_n_pix, 4**order_diff) -> + # (n_energy_bins, pset_n_pix) + binned_counts_n = counts_n.reshape( + (n_energy_bins, pset_n_pix, 4**order_diff) + ).sum(axis=-1) + + if not self.nested: + # convert back to ring ordering if necessary and store in the + # downsampled counts array + binned_counts_n = binned_counts_n[ + :, hp.ring2nest(self.nside, np.arange(pset_n_pix)) + ] + + self.data["counts"] = xr.DataArray( + binned_counts_n[np.newaxis, :, :], + dims=( + *self.data["counts"].dims[:-1], + CoordNames.HEALPIX_INDEX.value, + ), + ) + logger.info( + f"Counts variable with nside = {counts_nside} downsampled to " + f"nside {self.nside}." + ) + else: + # Update the counts variable with the correct dims + self.data["counts"] = self.data["counts"].rename( + {CoordNames.COUNTS_HEALPIX_INDEX.value: CoordNames.HEALPIX_INDEX.value} + ) + + +class LoHiBasePointingSet(PointingSet): + """ + Base class for Lo and Hi pointing sets with HAE coordinate data. + + This class provides common functionality for pointing sets that contain + hae_longitude and hae_latitude coordinates in the dataset. + """ + + tiling_type: SkyTilingType = SkyTilingType.RECTANGULAR + + def update_az_el_points(self) -> None: + """ + Update the az_el_points instance variable with new az/el coordinates. + + The values stored in the "hae_longitude" and "hae_latitude" variables + are used to construct the azimuth and elevation coordinates. + """ + logger.debug( + "Updating az/el points based on data in hae_longitude and" + "hae_latitude variables." + ) + # Get lon/lat coordinates, squeeze the epoch dimension and stack along + # the spatial dimensions. xarray.stack() takes possibly multiple spatial + # dimensions and reshapes those into a single dimension. + az_stacked = ( + self.data["hae_longitude"] + .squeeze("epoch") + .stack({CoordNames.GENERIC_PIXEL.value: self.spatial_coords}) + ) + el_stacked = ( + self.data["hae_latitude"] + .squeeze("epoch") + .stack({CoordNames.GENERIC_PIXEL.value: self.spatial_coords}) + ) + + # Stack lon/lat along last axis to create shape (..., 2) + self.az_el_points = xr.DataArray( + np.stack([az_stacked.values, el_stacked.values], axis=-1), + dims=[*az_stacked.dims, CoordNames.AZ_EL_VECTOR.value], + ) + + +class HiPointingSet(LoHiBasePointingSet): """ PointingSet object specific to Hi L1C PSet data. @@ -594,53 +748,34 @@ class HiPointingSet(PointingSet): ---------- dataset : xarray.Dataset | str | Path Hi L1C pointing set data loaded in a xarray.DataArray. - spin_phase : str - Include ENAs from "full", "ram" or "anti-ram" phases of the spin. """ - def __init__(self, dataset: xr.Dataset | str | Path, spin_phase: str): - super().__init__(dataset, spice_reference_frame=geometry.SpiceFrame.ECLIPJ2000) - - # Filter out ENAs from non-selected portions of the spin. - if spin_phase not in ["full", "ram", "anti-ram"]: - raise ValueError(f"Unrecognized spin_phase value: {spin_phase}.") - # ram only includes spin-phase interval [0, 0.5) - # which is the first half of the spin_angle_bins - elif spin_phase == "ram": - self.data = self.data.isel( - spin_angle_bin=slice(0, self.data["spin_angle_bin"].data.size // 2) - ) - # anti-ram includes spin-phase interval [0.5, 1) - # which is the second half of the spin_angle_bins - elif spin_phase == "anti-ram": - self.data = self.data.isel( - spin_angle_bin=slice(self.data["spin_angle_bin"].data.size // 2, None) - ) - - # Rename some PSET vars to match L2 variables - self.data = self.data.rename( - { - "exposure_times": "exposure_factor", - "background_rates": "bg_rates", - "background_rates_uncertainty": "bg_rates_unc", - } - ) + # class variable that stores the mapping of variables that need to be + # renamed to match L2 variables + l1c_to_l2_var_mapping: ClassVar[dict[str, str]] = { + "exposure_times": "exposure_factor", + "background_rates": "bg_rate", + "background_rates_uncertainty": "bg_rate_sys_err", + } - # Add obs_date variable to be used in determining a map mean obs_date - self.data["obs_date"] = xr.full_like( - self.data["exposure_factor"], self.data["epoch"].values[0] - ) + def __init__(self, dataset: xr.Dataset | str | Path): + super().__init__(dataset, spice_reference_frame=geometry.SpiceFrame.IMAP_HAE) - self.az_el_points = np.column_stack( - ( - np.squeeze(self.data["hae_longitude"]), - np.squeeze(self.data["hae_latitude"]), - ) - ) self.spatial_coords = ("spin_angle_bin",) + # Rename some PSET vars to match L2 variables (if necessary) + rename_dict = { + key: value + for key, value in self.l1c_to_l2_var_mapping.items() + if key in self.data + } + self.data = self.data.rename(rename_dict) + + # Update az_el_points using the base class method + self.update_az_el_points() + -class LoPointingSet(PointingSet): +class LoPointingSet(LoHiBasePointingSet): """ PointingSet object specific to Lo L1C PSet data. @@ -653,15 +788,26 @@ class LoPointingSet(PointingSet): def __init__(self, dataset: xr.Dataset): super().__init__(dataset, spice_reference_frame=geometry.SpiceFrame.IMAP_HAE) - # The HAE centers are stored in the pset as (1, 3600, 40) arrays - self.az_el_points = np.column_stack( - ( - np.squeeze(self.data["hae_longitude"]).values.ravel(), - np.squeeze(self.data["hae_latitude"]).values.ravel(), - ) - ) self.spatial_coords = ("spin_angle", "off_angle") + # Update az_el_points using the base class method + self.update_az_el_points() + + @property + def midpoint_j2000_et(self) -> float: + """ + The midpoint of the pointing in ET. + + Returns + ------- + midpoint: int + The midpoint value [J2000 ET] of the pointing set. + """ + epoch_delta = met_to_ttj2000ns( + self.data["pointing_end_met"].item() + ) - met_to_ttj2000ns(self.data["pointing_start_met"].item()) + return float(ttj2000ns_to_et(self.epoch + epoch_delta / 2)) + # Define the Map classes class AbstractSkyMap(ABC): @@ -694,9 +840,10 @@ class AbstractSkyMap(ABC): max_epoch: int # ======== Attributes required to be set in a subclass ======== - # Azimuth and elevation coordinates of each spatial pixel. The ndarray should - # have the shape (n, 2) where n is the number of spatial pixels - az_el_points: np.ndarray + # Azimuth and elevation coordinates of each spatial pixel. The xarray.DataArray + # should have the shape (n, 2) where n is the number of spatial pixels. + # Always a simple numpy array for maps (no need for multi-dimensional coords). + az_el_points: xr.DataArray # Type of sky tiling tiling_type: SkyTilingType # Dictionary of xr.DataArray objects for each non-spatial coordinate in the SkyMap @@ -763,11 +910,12 @@ def num_points(self) -> int: """ return self.az_el_points.shape[0] - def project_pset_values_to_map( + def project_pset_values_to_map( # noqa: PLR0912 self, pointing_set: PointingSet, value_keys: list[str] | None = None, index_match_method: IndexMatchMethod = IndexMatchMethod.PUSH, + pset_valid_mask: NDArray | xr.DataArray | None = None, ) -> None: """ Project a pointing set's values to the map grid. @@ -789,6 +937,10 @@ def project_pset_values_to_map( index_match_method : IndexMatchMethod, optional The method of index matching to use for all values. Default is IndexMatchMethod.PUSH. + pset_valid_mask : xarray.DataArray or NDArray, optional + A boolean mask of shape (number of pointing set pixels,) indicating + which pixels in the pointing set should be considered valid for projection. + If None, all pixels are considered valid. Default is None. Raises ------ @@ -797,9 +949,13 @@ def project_pset_values_to_map( """ if value_keys is None: value_keys = list(pointing_set.data.data_vars.keys()) - for value_key in value_keys: - if value_key not in pointing_set.data.data_vars: - raise ValueError(f"Value key {value_key} not found in pointing set.") + + if missing_keys := set(value_keys) - set(pointing_set.data.data_vars): + raise KeyError(f"Value keys not found in pointing set: {missing_keys}") + + if pset_valid_mask is None: + logger.debug("No pset_valid_mask provided, using all pixels as valid.") + pset_valid_mask = np.ones(pointing_set.num_points, dtype=bool) if index_match_method is IndexMatchMethod.PUSH: # Determine the indices of the sky map grid that correspond to @@ -821,19 +977,14 @@ def project_pset_values_to_map( ) for value_key in value_keys: - pset_values = pointing_set.data[value_key] + if value_key not in pointing_set.data.data_vars: + raise ValueError(f"Value key {value_key} not found in pointing set.") # If multiple spatial axes present # (i.e (az, el) for rectangular coordinate PSET), - # flatten them in the values array to match the raveled indices - non_spatial_axes_shape = tuple( - size - for key, size in pset_values.sizes.items() - if key not in pointing_set.spatial_coords - ) - raveled_pset_data = pset_values.data.reshape( - *non_spatial_axes_shape, - pointing_set.num_points, + # stack them into a single coordinate to match the raveled indices + raveled_pset_data = pointing_set.data[value_key].stack( + {CoordNames.GENERIC_PIXEL.value: pointing_set.spatial_coords} ) if value_key not in self.data_1d.data_vars: @@ -856,26 +1007,47 @@ def project_pset_values_to_map( if index_match_method is IndexMatchMethod.PUSH: # Bin the values at the matched indices. There may be multiple # pointing set pixels that correspond to the same sky map pixel. + # Broadcast all arrays together using xarray dimension alignment + data_bc, indices_bc = xr.broadcast( + raveled_pset_data, matched_indices_push + ) + # If the valid mask is a xr.DataArray, broadcast it to the same shape + if isinstance(pset_valid_mask, xr.DataArray): + stacked_valid_mask = pset_valid_mask.stack( + {CoordNames.GENERIC_PIXEL.value: pointing_set.spatial_coords} + ) + _, pset_valid_mask_bc = xr.broadcast(data_bc, stacked_valid_mask) + pset_valid_mask_values = pset_valid_mask_bc.values + else: + pset_valid_mask_values = pset_valid_mask + + # Extract numpy arrays for bincount operation pointing_projected_values = map_utils.bin_single_array_at_indices( - value_array=raveled_pset_data, + value_array=data_bc.values, projection_grid_shape=self.binning_grid_shape, - projection_indices=matched_indices_push, + projection_indices=indices_bc.values, + input_valid_mask=pset_valid_mask_values, ) + # TODO: we may need to allow for unweighted/weighted means here by + # dividing pointing_projected_values by some binned weights. + # For unweighted means, we could use the number of pointing set pixels + # that correspond to each map pixel as the weights. + self.data_1d[value_key] += pointing_projected_values elif index_match_method is IndexMatchMethod.PULL: + valid_map_mask = pset_valid_mask[matched_indices_pull] # We know that there will only be one value per sky map pixel, # so we can use the matched indices directly - pointing_projected_values = raveled_pset_data[..., matched_indices_pull] - else: - raise NotImplementedError( - "Only PUSH and PULL index matching methods are supported." + pointing_projected_values = raveled_pset_data.values[ + ..., matched_indices_pull[valid_map_mask] + ] + # TODO: we may need to allow for unweighted/weighted means here by + # dividing pointing_projected_values by some binned weights. + # For unweighted means, we could use the number of pointing set pixels + # that correspond to each map pixel as the weights. + self.data_1d[value_key].values[..., valid_map_mask] += ( + pointing_projected_values ) - # TODO: we may need to allow for unweighted/weighted means here by - # dividing pointing_projected_values by some binned weights. - # For unweighted means, we could use the number of pointing set pixels - # that correspond to each map pixel as the weights. - self.data_1d[value_key] += pointing_projected_values - # TODO: The max epoch needs to include the pset duration. Right now it # is just capturing the start epoch. See issue #1747 self.min_epoch = min(self.min_epoch, pointing_set.epoch) @@ -1102,7 +1274,10 @@ def __init__( el_points = self.sky_grid.el_grid.ravel() # Stack so axis 0 is different pixels, and axis 1 is (az, el) of the pixel - self.az_el_points = np.column_stack((az_points, el_points)) + self.az_el_points = xr.DataArray( + np.column_stack((az_points, el_points)), + dims=[CoordNames.GENERIC_PIXEL.value, CoordNames.AZ_EL_VECTOR.value], + ) # Calculate solid angles of each pixel in the map grid in units of steradians self.solid_angle_grid = spatial_utils.build_solid_angle_map( @@ -1169,6 +1344,10 @@ def to_dataset(self) -> xr.Dataset: # Rewrap each data array in the data_1d to the original 2D grid shape rewrapped_data = {} for key in self.data_1d.data_vars: + # Don't rewrap non-spatial variables + if CoordNames.GENERIC_PIXEL.value not in self.data_1d[key].coords: + rewrapped_data[key] = self.data_1d[key] + continue # drop pixel dim from the end, and add the spatial coords as dims rewrapped_dims = [ dim @@ -1196,13 +1375,14 @@ def to_dataset(self) -> xr.Dataset: coords={**self.non_spatial_coords, **self.spatial_coords}, ) - def build_cdf_dataset( + def build_cdf_dataset( # noqa: PLR0912 self, instrument: str, level: str, - frame: str, descriptor: str, sensor: str | None = None, + drop_vars_with_no_attributes: bool = True, + external_map_dataset: xr.Dataset | None = None, ) -> xr.Dataset: """ Format the data into a xarray.Dataset and add required CDF variables. @@ -1213,12 +1393,22 @@ def build_cdf_dataset( Instrument name. "hi", "lo", "ultra". level : str Product level. "l2" or "l3". - frame : str - Map frame. "sf", "hf" or "hk". descriptor : str Descriptor for filename. sensor : str, optional Sensor number "45" or "90". + drop_vars_with_no_attributes : bool, optional + Default behavior is to drop any dataset variables that don't have + attributes defined in the CDF attribute manager. This ensures that + the output CDF doesn't have any of the intermedeiate variables left + over from computations. Sometimes, it is useful to output the + intermedeiate variables. To do so, set this to False. + external_map_dataset : xarray.Dataset, optional + If provided, this dataset will be used as the base dataset to + build the CDF dataset from, instead of using the internal map data. + This is useful if additional processing has been done to the map data + after projection, and those results need to be included in the CDF. + Default is None. Returns ------- @@ -1234,7 +1424,10 @@ def build_cdf_dataset( logger.info("Building CDF ready dataset from RectangularSkyMap data.") - cdf_ds = self.to_dataset() + if external_map_dataset is not None: + cdf_ds = external_map_dataset + else: + cdf_ds = self.to_dataset() # Set the value of the epoch coord cdf_ds = cdf_ds.assign_coords(**{CoordNames.TIME.value: [self.min_epoch]}) @@ -1248,7 +1441,7 @@ def build_cdf_dataset( if ("L2" in name) ] l2_coords.append(CoordNames.TIME.value) - for map_coord in cdf_ds.dims.keys(): + for map_coord in cdf_ds.dims: if map_coord not in l2_coords: cdf_ds = cdf_ds.drop_dims(map_coord) @@ -1261,31 +1454,37 @@ def build_cdf_dataset( name=f"{coord_name}_label", dims=[coord_name], ) - # We can set the correct delta value of the spatial coordinates + # Set the correct delta values for the time coordinate if coord_name == CoordNames.TIME.value: + # Delta minus is always zero because epoch is the start time + cdf_ds[f"{coord_name}_delta_minus"] = xr.DataArray( + xr.zeros_like(cdf_ds[coord_name]), + name=f"{coord_name}_delta_minus", + dims=[coord_name], + ) cdf_ds[f"{coord_name}_delta"] = xr.DataArray( xr.full_like(cdf_ds[coord_name], self.max_epoch - self.min_epoch), name=f"{coord_name}_delta", dims=[coord_name], ) + # Set the correct delta values of the spatial coordinates elif coord_name in self.spatial_coords: cdf_ds[f"{coord_name}_delta"] = xr.DataArray( xr.full_like(cdf_ds[coord_name], self.spacing_deg / 2), name=f"{coord_name}_delta", dims=[coord_name], ) - # Add energy delta_minus and delta_plus variables elif coord_name == CoordNames.ENERGY_L2.value: - cdf_ds[f"{coord_name}_delta_minus"] = xr.DataArray( - xr.full_like(cdf_ds[coord_name], np.nan), - name=f"{coord_name}_delta", - dims=[coord_name], - ) - cdf_ds[f"{coord_name}_delta_plus"] = xr.DataArray( - xr.full_like(cdf_ds[coord_name], np.nan), - name=f"{coord_name}_delta", - dims=[coord_name], - ) + if f"{coord_name}_delta_minus" not in cdf_ds: + raise KeyError( + f"Required variable '{coord_name}_delta_minus' " + f"not found in cdf Dataset." + ) + if f"{coord_name}_delta_plus" not in cdf_ds: + raise KeyError( + f"Required variable '{coord_name}_delta_plus' " + f"not found in cdf Dataset." + ) # Object which holds CDF attributes for the map cdf_attrs = ImapCdfAttributes() @@ -1297,16 +1496,14 @@ def build_cdf_dataset( ) # Now set global attributes - map_attrs = cdf_attrs.get_global_attributes( - f"imap_{instrument}_{level}_enamap-{frame}" - ) + map_attrs = cdf_attrs.get_global_attributes(f"imap_{instrument}_{level}_enamap") map_attrs["Spacing_degrees"] = str(self.spacing_deg) for key in ["Data_type", "Logical_source", "Logical_source_description"]: map_attrs[key] = map_attrs[key].format( descriptor=descriptor, sensor=sensor, ) - # Always add the following attributes to the map + # Always add the following attributes to the map map_attrs.update( { "Sky_tiling_type": self.tiling_type.value, @@ -1315,25 +1512,39 @@ def build_cdf_dataset( ) cdf_ds.attrs.update(map_attrs) - # Set the variable attributes - for var in [*cdf_ds.data_vars, *cdf_ds.coords]: + # Set the variable and coordinate attributes + for name, data_array in {**cdf_ds.data_vars, **cdf_ds.coords}.items(): try: - # Don't check schema on label or delta variables - ignore_schema_substrings = ["_label", "_delta"] - check_schema = ( - False if any(s in var for s in ignore_schema_substrings) else True - ) + # We only check the schema on data variables that include "epoch" + # in their list of dimensions (But not epoch itself). + check_schema = name != "epoch" and "epoch" in data_array.dims var_attrs = cdf_attrs.get_variable_attributes( - variable_name=var, + variable_name=name, check_schema=check_schema, ) - except KeyError as e: - raise KeyError( - f"Attributes for variable {var} not found in " - f"loaded variable attributes." - ) from e + cdf_ds[name].attrs.update(var_attrs) + except KeyError: + if drop_vars_with_no_attributes: + logger.debug( + f"Dropping variable '{name}' that has no attributes defined." + ) + cdf_ds = cdf_ds.drop_vars(name) + else: + logger.debug( + f"Variable '{name}' has no attributes defined. It will " + f"be included in the output dataset with no attributes." + ) + + # Manually adjust epoch attributes + cdf_ds["epoch"].attrs.update( + {"DELTA_PLUS_VAR": "epoch_delta", "BIN_LOCATION": 0} + ) - cdf_ds[var].attrs.update(var_attrs) + # And CATDESC for principal data + md = naming.MapDescriptor.from_string(descriptor) + principal_data = md.principal_data_var + if principal_data in cdf_ds: + cdf_ds[principal_data].attrs["CATDESC"] = md.to_catdesc() return cdf_ds @@ -1412,7 +1623,10 @@ def __init__( nside=nside, ipix=np.arange(hp.nside2npix(nside)), nest=nested, lonlat=True ) # Stack so axis 0 is different pixels, and axis 1 is (az, el) of the pixel - self.az_el_points = np.column_stack((pixel_az, pixel_el)) + self.az_el_points = xr.DataArray( + np.column_stack((pixel_az, pixel_el)), + dims=[CoordNames.GENERIC_PIXEL.value, CoordNames.AZ_EL_VECTOR.value], + ) self.spatial_coords = { CoordNames.HEALPIX_INDEX.value: xr.DataArray( @@ -1544,13 +1758,6 @@ def calculate_rect_pixel_value_from_healpix_map_n_subdivisions( + subpix_spacing / 2 ) - # We must weight by solid angle, which is not exactly equal for all subpixels - # Calculate the solid angle of the full rectangular pixel (sterad) - full_rect_pixel_solid_angle = np.deg2rad(rect_pix_spacing_deg) * ( - np.sin(np.deg2rad(bottom_edge_lat + rect_pix_spacing_deg)) - - np.sin(np.deg2rad(bottom_edge_lat)) - ) - # Calculate solid angle of each subpix from the rect_subpix_lat_ctrs (sterad) all_edges_lat = bottom_edge_lat + np.arange(n_subpix_side + 1) * subpix_spacing sine_all_edges_lat = np.sin(np.deg2rad(all_edges_lat)) @@ -1580,14 +1787,22 @@ def calculate_rect_pixel_value_from_healpix_map_n_subdivisions( # Get the healpix values at the rectangular subpixel centers hp_vals_at_rect_pix_ctrs = value_array.values[..., hp_pix_at_rect_subpix_ctrs] + valid_pixel_mask = np.isfinite(hp_vals_at_rect_pix_ctrs) + # Weighted mean (weighted by solid angle) of these values over the pixel axis, # which is the last axis of this array - weighted_hp_vals_at_rect_pix_ctrs = ( - hp_vals_at_rect_pix_ctrs * rect_subpix_solid_angle_by_lat + valid_pixel_weights = np.where( + valid_pixel_mask, rect_subpix_solid_angle_by_lat, 0 ) - mean_pixel_value = ( - weighted_hp_vals_at_rect_pix_ctrs.sum(axis=-1) / full_rect_pixel_solid_angle + weighted_hp_vals_at_rect_pix_ctrs = ( + np.where(valid_pixel_mask, hp_vals_at_rect_pix_ctrs, 0) + * valid_pixel_weights ) + + with np.errstate(invalid="ignore"): + mean_pixel_value = weighted_hp_vals_at_rect_pix_ctrs.sum(axis=-1) / np.sum( + valid_pixel_weights, axis=-1 + ) # Log the mean pixel value and the number of subdivisions for debugging logger.debug( f" Mean pixel value at Number of subdivisions: {num_subdivisions}: " @@ -1748,7 +1963,7 @@ def to_rectangular_skymap( value_array=healpix_values_array, max_subdivision_depth=max_subdivision_depth, ) - for lon_lat in rect_map.az_el_points + for lon_lat in rect_map.az_el_points.values ] # Separate the best value and the recursion depth for each pixel diff --git a/imap_processing/ena_maps/utils/coordinates.py b/imap_processing/ena_maps/utils/coordinates.py index eebebcc003..4ad217f2fb 100644 --- a/imap_processing/ena_maps/utils/coordinates.py +++ b/imap_processing/ena_maps/utils/coordinates.py @@ -12,9 +12,15 @@ class CoordNames(Enum): ENERGY_ULTRA_L1C = "energy_bin_geometric_mean" ENERGY_L2 = "energy" HEALPIX_INDEX = "pixel_index" + COUNTS_HEALPIX_INDEX = "counts_pixel_index" # The names of the az/el angular coordinates may differ between L1C and L2 data AZIMUTH_L1C = "longitude" ELEVATION_L1C = "latitude" AZIMUTH_L2 = "longitude" ELEVATION_L2 = "latitude" + + # Common name for dimension along azimuth/elevation vector + AZ_EL_VECTOR = "az_el" + # Commoon name for dimension along Cartesian vector + CARTESIAN_VECTOR = "x_y_z" diff --git a/imap_processing/ena_maps/utils/corrections.py b/imap_processing/ena_maps/utils/corrections.py new file mode 100644 index 0000000000..0663b62ef4 --- /dev/null +++ b/imap_processing/ena_maps/utils/corrections.py @@ -0,0 +1,1021 @@ +"""L2 corrections common to multiple IMAP ENA instruments.""" + +import logging +from pathlib import Path +from typing import TypeVar + +import numpy as np +import pandas as pd +import xarray as xr +from numpy.polynomial import Polynomial +from scipy.constants import electron_volt, erg, proton_mass + +from imap_processing.ena_maps.ena_maps import ( + LoHiBasePointingSet, +) +from imap_processing.ena_maps.utils.coordinates import CoordNames +from imap_processing.spice import geometry +from imap_processing.spice.time import ttj2000ns_to_et + +logger = logging.getLogger(__name__) + +# Tell ruff to ignore ambiguous Greek letters in formulas in this file +# ruff: noqa: RUF003 + +# Create a TypeVar to represent the specific class being passed in +# Bound to LoHiBasePointingSet, meaning it must be LoHiBasePointingSet +# or a subclass of it +LoHiBasePsetSubclass = TypeVar("LoHiBasePsetSubclass", bound=LoHiBasePointingSet) + +# Physical constants for Compton-Getting correction +# Units: electron_volt = [J / eV] +# erg = [J / erg] +# To get [erg / eV], => electron_volt [J / eV] / erg [J / erg] = erg_per_ev [erg / eV] +ERG_PER_EV = electron_volt / erg # erg per eV - unit conversion factor +# Units: proton_mass = [kg] +# Here, we convert proton_mass to grams +PROTON_MASS_GRAMS = proton_mass * 1e3 # proton mass in grams + + +class PowerLawFluxCorrector: + """ + IMAP-Lo flux correction algorithm implementation. + + Based on Section 5 of the Mapping Algorithm Document. Applies corrections for + ESA transmission integration over energy bandpass using iterative + predictor-corrector scheme to estimate source fluxes from observed fluxes. + + Parameters + ---------- + coeffs_file : str or Path + Location of CSV file containing ESA transmission coefficients. + """ + + def __init__(self, coeffs_file: str | Path): + """Initialize PowerLawFluxCorrector.""" + # Load the csv file + eta_coeffs_df = pd.read_csv(coeffs_file, index_col="esa_step") + # Create a lookup dictionary to get the correct np.polynomial.Polynomial + # for a given esa_step + coeff_columns = ["M0", "M1", "M2", "M3", "M4", "M5"] + self.polynomial_lookup = { + row.name: Polynomial(row[coeff_columns].values) + for _, row in eta_coeffs_df.iterrows() + } + + def eta_esa(self, k: np.ndarray, gamma: np.ndarray) -> np.ndarray: + """ + Calculate ESA transmission scale factor Ξ·_esa,k(Ξ³) for each energy level. + + Parameters + ---------- + k : np.ndarray + Energy levels (1D array of ESA steps). + gamma : np.ndarray + Power-law slopes. Can be 1D (n_energy,) or multi-dimensional + (n_energy, ...spatial_dims...). + + Returns + ------- + np.ndarray + ESA transmission scale factors. Shape matches gamma. + """ + k = np.atleast_1d(k) + gamma = np.atleast_1d(gamma) + eta = np.empty_like(gamma) + + # Loop over energy levels only (first axis) + for i, esa_step in enumerate(k): + # Evaluate polynomial for all spatial pixels at this energy level + eta[i] = self.polynomial_lookup[esa_step](gamma[i]) + # Negative transmissions get set to 1 + eta[i] = np.where(eta[i] < 0, 1.0, eta[i]) + + return eta + + @staticmethod + def estimate_power_law_slope( + fluxes: np.ndarray, + energies: np.ndarray, + uncertainties: np.ndarray | None = None, + ) -> tuple[np.ndarray, np.ndarray | None]: + """ + Estimate power-law slopes Ξ³_k for each energy level using vectorized operations. + + Implements equations (36)-(41) from the Mapping Algorithm Document v7 + with proper boundary handling. Uses extended arrays with repeated + endpoints for unified calculation, and handles zero fluxes by falling + back to linear differencing or returning NaN where both central and + linear differencing fail. + + Parameters + ---------- + fluxes : np.ndarray + Array of differential fluxes with shape (n_energy, n_pixels). + energies : np.ndarray + Array of energy levels [E_1, E_2, ..., E_7]. Must be 1D. + uncertainties : np.ndarray, optional + Array of flux uncertainties. Shape must match fluxes. + + Returns + ------- + gamma : np.ndarray + Array of power-law slopes. Shape (n_energy, n_pixels). + delta_gamma : np.ndarray or None + Array of uncertainty slopes (if uncertainties provided). Shape + (n_energy, n_pixels). + """ + # Compute logs, setting non-positive fluxes to NaN + log_fluxes = np.log(np.where(fluxes > 0, fluxes, np.nan)) + log_energies = np.log(energies) + + # Pad with NaN so central differencing naturally falls back to one-sided + # Interior points use central differencing equation: + # gamma_k = ln(J_{k+1}/J_{k-1}) / ln(E_{k+1}/E_{k-1}) + # Left boundary uses linear forward differencing: + # gamma_k = ln(J_{k+1}/J_{k}) / ln(E_{k+1}/E_{k}) + # Right boundary uses linear backward differencing: + # gamma_k = ln(J_{k}/J_{k-1}) / ln(E_{k}/E_{k-1}) + + # Pad along energy axis (first axis) with NaN + # fluxes has shape (n_energy, n_pixels) + log_extended_fluxes = np.pad( + log_fluxes, ((1, 1), (0, 0)), constant_values=np.nan + ) + log_extended_energies = np.pad(log_energies, (1, 1), constant_values=np.nan) + + # Broadcast energies to match flux shape: + # (n_energy + 2,) -> (n_energy + 2, n_pixels) + log_extended_energies_broadcast = np.broadcast_to( + log_extended_energies[:, np.newaxis], + log_extended_fluxes.shape, + ) + + # Create index arrays with same shape as fluxes + # Start with central differencing indices: left=k-1, right=k+1 + # In the extended array, original index k corresponds to extended index k+1 + n_energies = energies.shape[0] + left_indices = np.broadcast_to( + np.arange(n_energies)[:, np.newaxis], fluxes.shape + ).copy() + right_indices = np.broadcast_to( + (np.arange(n_energies) + 2)[:, np.newaxis], fluxes.shape + ).copy() + + # Check if central differencing is valid + central_invalid = ~( + np.isfinite(np.take_along_axis(log_extended_fluxes, left_indices, axis=0)) + & np.isfinite( + np.take_along_axis(log_extended_fluxes, right_indices, axis=0) + ) + ) + + # For invalid central differencing, try forward differencing: left=k, right=k+1 + left_indices[central_invalid] += 1 + + # Check if forward differencing is valid + forward_invalid = ~( + np.isfinite(np.take_along_axis(log_extended_fluxes, left_indices, axis=0)) + & np.isfinite( + np.take_along_axis(log_extended_fluxes, right_indices, axis=0) + ) + ) + + # For invalid forward differencing, try backward: left=k-1, right=k + need_backward = central_invalid & forward_invalid + left_indices[need_backward] -= 1 # Back to k-1 + right_indices[need_backward] -= 1 # Change from k+1 to k + + # Extract final flux and energy values using the computed indices + left_log_fluxes = np.take_along_axis(log_extended_fluxes, left_indices, axis=0) + right_log_fluxes = np.take_along_axis( + log_extended_fluxes, right_indices, axis=0 + ) + left_log_energies = np.take_along_axis( + log_extended_energies_broadcast, left_indices, axis=0 + ) + right_log_energies = np.take_along_axis( + log_extended_energies_broadcast, right_indices, axis=0 + ) + + # Compute power-law slopes + valid = np.isfinite(left_log_fluxes) & np.isfinite(right_log_fluxes) + with np.errstate(divide="ignore", invalid="ignore"): + gamma = np.where( + valid, + (right_log_fluxes - left_log_fluxes) + / (right_log_energies - left_log_energies), + 0.0, + ) + + # Compute uncertainty slopes + delta_gamma = np.zeros_like(fluxes, dtype=float) + if uncertainties is not None: + with np.errstate(divide="ignore", invalid="ignore"): + rel_unc_sq = (uncertainties / fluxes) ** 2 + extended_rel_unc_sq = np.pad( + rel_unc_sq, ((1, 1), (0, 0)), constant_values=np.nan + ) + + left_rel_unc_sq = np.take_along_axis( + extended_rel_unc_sq, left_indices, axis=0 + ) + right_rel_unc_sq = np.take_along_axis( + extended_rel_unc_sq, right_indices, axis=0 + ) + + delta_gamma = np.where( + valid, + np.sqrt(left_rel_unc_sq + right_rel_unc_sq) + / (right_log_energies - left_log_energies), + 0.0, + ) + + return gamma, delta_gamma + + def predictor_corrector_iteration( + self, + observed_fluxes: np.ndarray, + observed_uncertainties: np.ndarray, + energies: np.ndarray, + max_iterations: int = 20, + convergence_threshold: float = 0.005, + ) -> tuple[np.ndarray, np.ndarray, np.ndarray]: + """ + Estimate source fluxes using iterative predictor-corrector scheme. + + Implements the algorithm from Appendix A of the Mapping Algorithm Document. + Fully vectorized to process all spatial pixels simultaneously, with + per-pixel convergence tracking. + + Parameters + ---------- + observed_fluxes : np.ndarray + Array of observed fluxes. Shape (n_energy,) or + (n_energy, ...spatial_dims...). + observed_uncertainties : numpy.ndarray + Array of observed uncertainties. Shape must match observed_fluxes. + energies : np.ndarray + Array of energy levels (1D). + max_iterations : int, optional + Maximum number of iterations, by default 20. + convergence_threshold : float, optional + RMS convergence criterion, by default 0.005 (0.5%). + + Returns + ------- + source_fluxes : np.ndarray + Final estimate of source fluxes. Shape matches observed_fluxes. + source_uncertainties : np.ndarray + Final estimate of source uncertainties. Shape matches observed_fluxes. + n_iterations : np.ndarray + Number of iterations run for each pixel. Shape matches spatial dims + of input. + """ + n_levels = observed_fluxes.shape[0] + energy_levels: np.ndarray = np.arange(n_levels) + 1 + + # Initial power-law estimate from observed fluxes + gamma_initial, _ = self.estimate_power_law_slope(observed_fluxes, energies) + + # Initial source flux estimate + eta_initial = self.eta_esa(energy_levels, gamma_initial) + source_fluxes_n = observed_fluxes / eta_initial + source_uncertainties = observed_uncertainties / eta_initial + + # Track which pixels have converged and iteration count per pixel + converged = np.zeros(observed_fluxes.shape[1:], dtype=bool) + n_iterations = np.zeros(observed_fluxes.shape[1:], dtype=int) + + # Mark pixels that are all zeros or all NaNs as already converged + # These pixels have no meaningful data to iterate on + all_zero_or_nan = np.all( + (observed_fluxes == 0) | ~np.isfinite(observed_fluxes), axis=0 + ) + converged[all_zero_or_nan] = True + + for iteration in range(max_iterations): + # Get mask for unconverged pixels + not_converged = ~converged + + # Only process unconverged pixels + source_fluxes_active = source_fluxes_n[:, not_converged] + observed_fluxes_active = observed_fluxes[:, not_converged] + observed_uncertainties_active = observed_uncertainties[:, not_converged] + gamma_initial_active = gamma_initial[:, not_converged] + + # Store previous iteration for unconverged pixels + source_fluxes_prev = source_fluxes_active.copy() + + # Predictor step - only for unconverged pixels + gamma_pred, _ = self.estimate_power_law_slope( + source_fluxes_active, energies + ) + gamma_half = 0.5 * (gamma_initial_active + gamma_pred) + + # Predictor source flux estimate + eta_half = self.eta_esa(energy_levels, gamma_half) + source_fluxes_half = observed_fluxes_active / eta_half + + # Corrector step + gamma_corr, _ = self.estimate_power_law_slope(source_fluxes_half, energies) + gamma_n = 0.5 * (gamma_pred + gamma_corr) + + # Final source flux estimate for this iteration + eta_final = self.eta_esa(energy_levels, gamma_n) + source_fluxes_new = observed_fluxes_active / eta_final + source_uncertainties_new = observed_uncertainties_active / eta_final + + # Check convergence for unconverged pixels + with np.errstate(divide="ignore", invalid="ignore"): + ratios_sq = (source_fluxes_new / source_fluxes_prev) ** 2 + # Compute chi per pixel (mean over energy axis) + chi_n = np.abs(np.sqrt(np.nanmean(ratios_sq, axis=0)) - 1) + + # Determine which pixels converged this iteration + # Start with all False, then set True for newly converged pixels + newly_converged = np.zeros_like(converged) + newly_converged[not_converged] = chi_n < convergence_threshold + n_iterations[newly_converged] = iteration + 1 + + # Update source fluxes and uncertainties for unconverged pixels + source_fluxes_n[:, not_converged] = source_fluxes_new + source_uncertainties[:, not_converged] = source_uncertainties_new + + # Update converged mask + converged |= newly_converged + + # If all pixels have converged, exit early + if np.all(converged): + break + + # Set iteration count for pixels that didn't converge + n_iterations[~converged] = max_iterations + + return source_fluxes_n, source_uncertainties, n_iterations + + def apply_flux_correction( + self, + flux: xr.DataArray, + flux_stat_unc: xr.DataArray, + energies: xr.DataArray, + ) -> tuple[xr.DataArray, xr.DataArray]: + """ + Apply flux correction to observed fluxes. + + Iterative predictor-corrector scheme is applied to all spatial pixels + simultaneously using vectorized operations to correct fluxes and + statistical uncertainties. + + Parameters + ---------- + flux : xarray.DataArray + Input flux. Must have "energy" dimension corresponding to energies. + Can have arbitrary additional spatial dimensions. + flux_stat_unc : xarray.DataArray + Statistical uncertainty for input fluxes. Shape and dimensions must + match flux. + energies : xarray.DataArray + Array of energy levels in units of eV or keV. Must be 1D with + "energy" dimension. + + Returns + ------- + tuple[xarray.DataArray, xarray.DataArray] + Corrected fluxes and flux uncertainties with same shape and dimensions + as input. + """ + # Stack all non-energy dimensions into a single "pixel" dimension + # This converts to shape (energy, pixel) for processing + spatial_dims = [d for d in flux.dims if "energy" not in d] + + if spatial_dims: + flux_stacked = flux.stack(flux_pixel=spatial_dims) + flux_stat_unc_stacked = flux_stat_unc.stack(flux_pixel=spatial_dims) + else: + # If only energy dimension exists, add a dummy pixel dimension + flux_stacked = flux.expand_dims("flux_pixel") + flux_stat_unc_stacked = flux_stat_unc.expand_dims("flux_pixel") + + # Call vectorized predictor-corrector iteration on 2D arrays + corrected_flux_stacked, corrected_unc_stacked, _ = ( + self.predictor_corrector_iteration( + flux_stacked.values, + flux_stat_unc_stacked.values, + energies.values, + ) + ) + + # Convert back to DataArrays with stacked dimensions + corrected_flux_da = xr.DataArray( + corrected_flux_stacked, + dims=flux_stacked.dims, + coords=flux_stacked.coords, + ) + corrected_unc_da = xr.DataArray( + corrected_unc_stacked, + dims=flux_stat_unc_stacked.dims, + coords=flux_stat_unc_stacked.coords, + ) + + # Unstack back to original dimensions + if spatial_dims: + corrected_flux_da = corrected_flux_da.unstack("flux_pixel") + corrected_unc_da = corrected_unc_da.unstack("flux_pixel") + + # Ensure dimension order matches input + corrected_flux_da = corrected_flux_da.transpose(*flux.dims) + corrected_unc_da = corrected_unc_da.transpose(*flux_stat_unc.dims) + else: + # Remove dummy pixel dimension + corrected_flux_da = corrected_flux_da.squeeze("flux_pixel") + corrected_unc_da = corrected_unc_da.squeeze("flux_pixel") + + return corrected_flux_da, corrected_unc_da + + +def add_spacecraft_position_and_velocity_to_pset( + pset: xr.Dataset, +) -> xr.Dataset: + """ + Calculate and add spacecraft position and velocity data to pointing set dataset. + + Parameters + ---------- + pset : xr.Dataset + Pointing set dataset to be updated. Must contain "epoch" coordinate + and "epoch_delta" data variable or "pointing_start_met" and + "pointing_end_met" data variables to compute. + + Returns + ------- + pset_processed : xarray.Dataset + Pointing set dataset with spacecraft position and velocity data added. + These values are calculated at the midpoint time of the pointing. + + Notes + ----- + Adds the following DataArrays to input dataset: + - "sc_velocity": Spacecraft velocity vector (km/s) with dims ["x_y_z"] + - "sc_position": Spacecraft position vector (km) with dims ["x_y_z"] + """ + # Hi and Lo need to use different methods for computing the Pointing + # midpoint time. + if pset.attrs["Logical_source"].startswith("imap_hi"): + # Compute ephemeris time (J2000 seconds) of PSET midpoint + # epoch contains Pointing start time, and epoch_delta indicates the total + # duration of the Pointing + # For Hi, epoch_delta is the duration of the Pointing in nanoseconds + pointing_duration_ns = pset["epoch_delta"].values[0] + elif pset.attrs["Logical_source"].startswith("imap_lo"): + # For Lo, compute the pointing duration using pointing start/end MET times + pointing_duration_ns = ( + pset["pointing_end_met"].values[0] - pset["pointing_start_met"].values[0] + ) * 1e9 + else: + raise NotImplementedError( + f"add_spacecraft_position_and_velocity_to_pset does not support PSETs with " + f"Logical_source: {pset.attrs['Logical_source']}" + ) + + # Handle case where pointing duration is zero or negative to avoid invalid + # ephemeris time (this is used, for example, for empty psets due to + # goodtimes filtering) + if pointing_duration_ns <= 0: + logger.warning( + "Pointing duration is zero or negative. " + "Setting spacecraft position and velocity to zero." + ) + sc_position_vector = np.zeros(3) # Zero position vector + sc_velocity_vector = np.zeros(3) # Zero velocity vector + else: + # Compute ephemeris time (J2000 seconds) of PSET midpoint + et = ttj2000ns_to_et(pset["epoch"].values[0] + pointing_duration_ns / 2) + + # Get spacecraft state in HAE frame + sc_state = geometry.imap_state(et, ref_frame=geometry.SpiceFrame.IMAP_HAE) + sc_position_vector = sc_state[0:3] + sc_velocity_vector = sc_state[3:6] + + # Store spacecraft position as DataArray + pset["sc_position"] = xr.DataArray( + sc_position_vector, dims=[CoordNames.CARTESIAN_VECTOR.value] + ) + + # Store spacecraft velocity as DataArray + pset["sc_velocity"] = xr.DataArray( + sc_velocity_vector, dims=[CoordNames.CARTESIAN_VECTOR.value] + ) + + return pset + + +def _add_cartesian_look_direction(pset: xr.Dataset) -> xr.Dataset: + """ + Calculate and add look direction vectors to pointing set dataset. + + Parameters + ---------- + pset : xarray.Dataset + Pointing set dataset to be updated. Must contain "hae_longitude" and + "hae_latitude" data variables. + + Returns + ------- + pset_processed : xarray.Dataset + Pointing set dataset with look direction vectors added. + + Notes + ----- + Adds the following DataArray to input dataset: + - "look_direction": Cartesian unit vectors with dims [...spatial_dims, "x_y_z"] + """ + longitudes = pset["hae_longitude"] + latitudes = pset["hae_latitude"] + + # Stack spherical coordinates (r=1 for unit vectors, azimuth, elevation) + spherical_coords = np.stack( + [ + np.ones_like(longitudes), # r = 1 for unit vectors + longitudes, # azimuth = longitude + latitudes, # elevation = latitude + ], + axis=-1, + ) + + # Convert to Cartesian coordinates and store as DataArray + pset["look_direction"] = xr.DataArray( + geometry.spherical_to_cartesian(spherical_coords), + dims=[*longitudes.dims, CoordNames.CARTESIAN_VECTOR.value], + ) + + return pset + + +def _calculate_compton_getting_transform( + pset: xr.Dataset, + energy_hf: xr.DataArray, +) -> xr.Dataset: + """ + Apply Compton-Getting transformation to compute ENA source directions. + + This implements the Compton-Getting velocity transformation to correct + for the motion of the spacecraft through the heliosphere. The transformation + accounts for the Doppler shift of ENA energies and the aberration of + arrival directions. + + All calculations are performed using xarray DataArrays to preserve + dimension information throughout the computation. + + Parameters + ---------- + pset : xarray.Dataset + Pointing set dataset with sc_velocity, sc_direction_vector, and + look_direction already added. + energy_hf : xr.DataArray + ENA energies in the heliosphere frame in eV. + + Returns + ------- + pset : xarray.Dataset + Pointing set dataset with Compton-Getting related variables added. + + Notes + ----- + The algorithm is based on the "Appendix A. The IMAP-Lo Mapping Algorithms" + document. + Adds the following DataArrays to input dataset: + - "energy_sc": ENA energies in spacecraft frame (eV) + - "energy_hf": ENA energies in the heliosphere frame (eV) + - "ram_mask": Mask indicating whether ENA source direction is from the ram + direction. + Updates the following DataArrays in input dataset: + - "hae_longitude": ENA source longitudes in heliosphere frame (degrees) + - "hae_latitude": ENA source latitudes in heliosphere frame (degrees) + """ + # Store heliosphere frame energies + pset["energy_hf"] = energy_hf + + # Calculate spacecraft speed + sc_velocity_km_per_sec = np.linalg.norm(pset["sc_velocity"], axis=-1, keepdims=True) + + # Calculate dot product between look directions and spacecraft direction vector + # Use Einstein summation for efficient vectorized dot product + sc_direction_vector = pset["sc_velocity"] / sc_velocity_km_per_sec + dot_product = xr.DataArray( + np.einsum( + "...i,...i->...", + pset["look_direction"], + sc_direction_vector, + ), + dims=pset["look_direction"].dims[:-1], + ) + + # Calculate the kinetic energy of a hydrogen ENA traveling at spacecraft velocity + # E_u = (1/2) * m * U_sc^2 (convert km/s to cm/s with 1.0e5 factor) + energy_u = ( + 0.5 * PROTON_MASS_GRAMS * (sc_velocity_km_per_sec * 1e5) ** 2 / ERG_PER_EV + ) + + # Note: Tim thinks that this approach seems backwards. Here, we are assuming + # that ENAs are observed in the heliosphere frame at the ESA energy levels. + # We then calculate the velocity that said ENAs would have in the spacecraft + # frame as well as the CG corrected energy level in the spacecraft frame. + # We then use this velocity to calculate and the velocity of the spacecraft + # to do the vector math which determines the ENA source direction in the + # heliosphere frame. + # The ENAs are in fact observed in the spacecraft frame at a known energy + # level in the spacecraft frame. Why don't we use that energy level to + # calculate the source direction in the spacecraft frame and then do the + # vector math to find the source direction in the heliosphere frame? We + # would also need to calculate the CG corrected ENA energy in the heliosphere + # frame and keep track of that when binning. + + # Calculate y values for each energy level (Equation 61) + # y_k = sqrt(E^h_k / E^u) + y = np.sqrt(pset["energy_hf"] / energy_u) + + # Velocity magnitude factor calculation (Equation 62) + # x_k = (-Γͺβ‚› Β· Γ»_sc) + sqrt(yΒ² + (Γͺβ‚› Β· Γ»_sc)Β² - 1) + # dot_product = look_hat dot usc_hat = (-Γͺβ‚› Β· Γ»_sc) + x = dot_product + np.sqrt(y**2 + dot_product**2 - 1) + # Get the dimensions in the right order so that spatial is last + x = x.transpose(dot_product.dims[0], y.dims[0], *dot_product.dims[1:]) + + # Calculate ENA speed in the spacecraft frame + # |vβƒ—_sc| = x_k * U_sc + velocity_sc = x * sc_velocity_km_per_sec + + # Calculate the kinetic energy of the spacecraft + # E_sc = (1/2) * M_p * v_scΒ² (convert km/s to cm/s with 1.0e5 factor) + pset["energy_sc"] = 0.5 * PROTON_MASS_GRAMS * (velocity_sc * 1e5) ** 2 / ERG_PER_EV + + # Calculate the velocity vector in the spacecraft frame + # vβƒ—_sc = -|v_sc| * Γͺβ‚› (velocity direction is opposite to look direction) + velocity_vector_sc = -1 * velocity_sc * pset["look_direction"] + + # Calculate the ENA velocity vector in the heliosphere frame + # vβƒ—_helio = vβƒ—_sc + Uβƒ—_sc (simple velocity addition) + velocity_vector_helio = velocity_vector_sc + pset["sc_velocity"] + + # Convert to spherical coordinates to get ENA source directions + # Look direction is opposite of ENA direction + ena_source_direction_helio = geometry.cartesian_to_spherical( + -1 * velocity_vector_helio.data + ) + + # Update the PSET hae_longitude and hae_latitude variables with the new + # energy-dependent values. + pset["hae_longitude"] = ( + pset["energy_sc"].dims, + ena_source_direction_helio[..., 1], + ) + pset["hae_latitude"] = ( + pset["energy_sc"].dims, + ena_source_direction_helio[..., 2], + ) + + return pset + + +def calculate_ram_mask(pset: xr.Dataset) -> xr.Dataset: + """ + Calculate the RAM mask using the input spacecraft velocity vector. + + The RAM mask is a boolean array with the same dimensions as what is stored + in the "hae_longitude" and "hae_latitude" variables of the dataset. + + Parameters + ---------- + pset : xarray.Dataset + Pointing set dataset. The pset dataset is assumed to have valid + "hae_longitude", "hae_latitude", and "sc_velocity" variables. + + Returns + ------- + pset : xarray.Dataset + Pointing set dataset with ram_mask variable added. + """ + logger.debug( + f"Calculating the RAM mask using input spacecraft direction " + f"vector: {pset['sc_velocity'].values} and hae coordinates in " + f"the dataset hae_longitude and hae_latitude variables." + ) + longitude = pset["hae_longitude"] + latitude = pset["hae_latitude"] + spacecraft_velocity = pset["sc_velocity"].values + spherical_coords = np.stack( + [ + np.ones_like(longitude.values), + longitude.values, + latitude.values, + ], + axis=-1, + ) + cartesian_source_direction = xr.DataArray( + geometry.spherical_to_cartesian(spherical_coords), + dims=[*longitude.dims, CoordNames.CARTESIAN_VECTOR.value], + ) + # For ram/anti-ram filtering we can use the sign of the scalar projection + # of the ENA source direction vector (-vβƒ—_ena) onto the spacecraft velocity + # vector. + # ram_mask = (-vβƒ—_ena Β· Γ»_sc) >= 0 + # Use Einstein summation for efficient vectorized dot product + ram_mask = ( + np.einsum("...i,...i->...", spacecraft_velocity, cartesian_source_direction) + >= 0 + ) + pset["ram_mask"] = xr.DataArray( + ram_mask, + dims=longitude.dims, + ) + + return pset + + +def apply_compton_getting_correction( + pset: xr.Dataset, + energy_hf: xr.DataArray, +) -> xr.Dataset: + """ + Apply Compton-Getting correction to a pointing set dataset. + + This function performs the Compton-Getting velocity transformation to correct + ENA observations for the motion of the spacecraft through the heliosphere. + The corrected coordinates represent the true source directions of the ENAs + in the heliosphere frame. + + New variables are added to the dataset for the corrected coordinates and + energies. + + All calculations are performed using xarray DataArrays to preserve dimension + information throughout the computation. + + Parameters + ---------- + pset : xarray.Dataset + Pointing set dataset. Must contain the following coordinates: + - epoch: start time of the pointing + Must contain the following variables: + - sc_velocity: velocity vector of the spacecraft in the HAE frame at + the midpoint time of the pointing [km/s]. See the + `add_spacecraft_position_and_velocity_to_pset` function. + - hae_longitude: PSET bin longitudes in the HAE frame (degrees) + - hae_latitude: PSET bin latitudes in the HAE frame (degrees) + energy_hf : xr.DataArray + ENA energies in the heliosphere frame in eV. Must be 1D with an + energy dimension. + + Returns + ------- + processed_dataset : xarray.Dataset + Updated dataset object with Compton-Getting related variables added and + hae_longitude and hae_latitude variables updated to contain energy-dependent + cg-corrected values. + + Notes + ----- + This function adds the following variables to the dataset: + - "look_direction": Cartesian unit vectors of observation directions + - "energy_hf": ENA energies in heliosphere frame (eV) + - "energy_sc": ENA energies in spacecraft frame (eV) + This function modifies the following variables in the dataset: + - "hae_longitude": ENA source longitudes in heliosphere frame (degrees) + - "hae_latitude": ENA source latitudes in heliosphere frame (degrees) + """ + # Step 1: Calculate and add look direction vectors to pset + processed_dataset = _add_cartesian_look_direction(pset) + + # Step 2: Apply Compton-Getting transformation + processed_dataset = _calculate_compton_getting_transform( + processed_dataset, energy_hf + ) + + return processed_dataset + + +def interpolate_map_flux_to_helio_frame( + map_ds: xr.Dataset, + esa_energies: xr.DataArray, + helio_energies: xr.DataArray, + vars_to_interpolate: list[str], + update_sys_err: bool = True, +) -> xr.Dataset: + """ + Interpolate flux from spacecraft frame to heliocentric frame energies. + + This implements the Compton-Getting interpolation step that transforms + flux measurements from the spacecraft frame to the heliocentric frame. + The algorithm follows these steps: + 1. For each spatial pixel and energy step, get the spacecraft energy + 2. Find bounding ESA energy channels for interpolation + 3. Perform power-law interpolation between bounding channels to spacecraft energy + 4. Apply energy scaling transformation to heliocentric frame + + Parameters + ---------- + map_ds : xarray.Dataset + Map dataset with `energy_sc` data variable containing the spacecraft + frame energies for each spatial pixel and ESA energy step. + esa_energies : xarray.DataArray + The ESA nominal central energies. Any energy unit is acceptable as long + as it is consistent with `helio_energies`. + helio_energies : xarray.DataArray + The heliocentric frame energies to interpolate to. Any energy unit is + acceptable as long as it is consistent with `esa_energies`. + In practice, these are the same as esa_energies. + vars_to_interpolate : list[str] + List of variables to perform interpolation on. This is just the base + flux/intensity variable. It is assumed that the associated statistical + uncertainty and systematic error variables are also present in the input + dataset and will be interpolated as well. For example, if ["ena_intensity"] + is input, then the variables "ena_intensity", "ena_intensity_stat_uncert", + and "ena_intensity_sys_err" will be interpolated. + update_sys_err : bool, optional + Flag indicating whether to update the systematic error variables as part + of the flux interpolation. Defaults to True. + + Returns + ------- + map_ds : xarray.Dataset + Updated map dataset with interpolated heliocentric frame fluxes. + """ + logger.info("Performing Compton-Getting interpolation to heliocentric frame") + + # Work with xarray DataArrays to handle arbitrary spatial dimensions + energy_sc = map_ds["energy_sc"] + + # Step 1: Find bounding ESA energy indices for each position + # Use np.searchsorted on flattened array, then reshape back + esa_energy_vals = esa_energies.values + energy_sc_flat = energy_sc.values.ravel() + + # Find right bound index for each element (vectorized) + right_idx_flat = np.searchsorted(esa_energy_vals, energy_sc_flat, side="right") + right_idx_flat = np.clip(right_idx_flat, 1, len(esa_energy_vals) - 1) + left_idx_flat = right_idx_flat - 1 + + # Reshape indices back to match energy_sc shape + right_idx = right_idx_flat.reshape(energy_sc.shape) + left_idx = left_idx_flat.reshape(energy_sc.shape) + + # Create DataArrays for indices with same dims as energy_sc + # Note: we need to avoid coordinate name conflicts when using isel() + # The energy dimension should be present in dims but not as a coordinate + # since we're using these as indices into the energy dimension + # Create coordinates dict without the energy coordinate + coords_without_energy = {k: v for k, v in energy_sc.coords.items() if k != "energy"} + + right_idx_da = xr.DataArray( + right_idx, dims=energy_sc.dims, coords=coords_without_energy + ) + left_idx_da = xr.DataArray( + left_idx, dims=energy_sc.dims, coords=coords_without_energy + ) + + # Get energy values at boundaries - select from esa_energies using indices + energy_left = esa_energies.isel({"energy": left_idx_da}) + energy_right = esa_energies.isel({"energy": right_idx_da}) + + for var_name in vars_to_interpolate: + logger.debug( + f"Interpolating {var_name}, {var_name}_stat_uncert, and " + f"{var_name}_sys_err to heliocentric frame energies" + ) + # Step 2: Extract flux values at bounding energy channels + # Use xarray's advanced indexing to get fluxes at left and right indices + intensity = map_ds[var_name] + stat_unc = map_ds[f"{var_name}_stat_uncert"] + sys_err = map_ds[f"{var_name}_sys_err"] + flux_left = intensity.isel({"energy": left_idx_da}) + flux_right = intensity.isel({"energy": right_idx_da}) + stat_unc_left = stat_unc.isel({"energy": left_idx_da}) + stat_unc_right = stat_unc.isel({"energy": right_idx_da}) + sys_err_left = sys_err.isel({"energy": left_idx_da}) + sys_err_right = sys_err.isel({"energy": right_idx_da}) + + # Step 3: Perform interpolation to spacecraft energy + # Use power-law interpolation when both bounding fluxes are positive, + # otherwise fall back to linear interpolation to avoid log(0) issues. + + # Interpolation fraction for linear fallback + interp_fraction = (energy_sc - energy_left) / (energy_right - energy_left) + + # Determine which pixels need linear interpolation (zero/negative flux) + use_linear = (flux_left <= 0) | (flux_right <= 0) + + with np.errstate(divide="ignore", invalid="ignore"): + # === Power-law interpolation (Equations 72-76) === + # slope = log(f_right/f_left) / log(e_right/e_left) + # flux_sc = f_left * (energy_sc / e_left)^slope + slope = np.log(flux_right / flux_left) / np.log(energy_right / energy_left) + flux_sc_powerlaw = flux_left * ((energy_sc / energy_left) ** slope) + + # Interpolation factor for uncertainty propagation (Equations 75 & 76) + unc_factor = np.log(energy_sc / energy_left) / np.log( + energy_right / energy_left + ) + + # Statistical uncertainty propagation (Equation 75): + # Ξ΄J = J * sqrt((Ξ΄J_left/J_left)^2 * (1 + unc_factor^2) + # + unc_factor^2 * (Ξ΄J_right/J_right)^2) + stat_unc_sc_powerlaw = flux_sc_powerlaw * np.sqrt( + (stat_unc_left / flux_left) ** 2 * (1.0 + unc_factor**2) + + unc_factor**2 * (stat_unc_right / flux_right) ** 2 + ) + + # Systematic uncertainty propagation (Equation 76): + # ΟƒJ^g = ΟƒJ^src_kref * (⟨E^s_kref⟩ / E^ESA_kref)^Ξ³_kref * (E^h / ⟨E^s_kref⟩) + # Systematic error scales proportionally with flux during power-law + # interpolation + sys_err_sc_powerlaw = sys_err_left * ((energy_sc / energy_left) ** slope) + + # === Linear interpolation (fallback for zero/negative flux) === + # flux_sc = flux_left + (flux_right - flux_left) * f + # where f = (energy_sc - energy_left) / (energy_right - energy_left) + flux_sc_linear = flux_left + (flux_right - flux_left) * interp_fraction + + # Statistical uncertainty: sqrt((1-f)^2 * Οƒ_left^2 + f^2 * Οƒ_right^2) + stat_unc_sc_linear = np.sqrt( + (1 - interp_fraction) ** 2 * stat_unc_left**2 + + interp_fraction**2 * stat_unc_right**2 + ) + + # Systematic error: linear interpolation + sys_err_sc_linear = ( + sys_err_left + (sys_err_right - sys_err_left) * interp_fraction + ) + + # Merge: use linear where needed, power-law otherwise + flux_sc = xr.where(use_linear, flux_sc_linear, flux_sc_powerlaw) + stat_unc_sc = xr.where(use_linear, stat_unc_sc_linear, stat_unc_sc_powerlaw) + sys_err_sc = xr.where(use_linear, sys_err_sc_linear, sys_err_sc_powerlaw) + + # Step 4: Energy scaling transformation (Liouville theorem) + # flux_helio = flux_sc * (helio_energy / energy_sc) + # Using xarray broadcasting, helio_energies will broadcast + # along esa_energy_step + with np.errstate(divide="ignore", invalid="ignore"): + energy_ratio = helio_energies / energy_sc + flux_helio = flux_sc * energy_ratio + stat_unc_helio = stat_unc_sc * energy_ratio + sys_err_helio = sys_err_sc * energy_ratio + + # Clamp negative fluxes to zero (can occur from linear extrapolation) + flux_helio = xr.where(flux_helio < 0, 0.0, flux_helio) + + # Set any location where the value is not finite to NaN (converts +/-inf to NaN) + flux_helio = flux_helio.where(np.isfinite(flux_helio), np.nan) + stat_unc_helio = stat_unc_helio.where(np.isfinite(stat_unc_helio), np.nan) + sys_err_helio = sys_err_helio.where(np.isfinite(sys_err_helio), np.nan) + + # Update the dataset with interpolated values + map_ds[var_name] = flux_helio + map_ds[f"{var_name}_stat_uncert"] = stat_unc_helio + if update_sys_err: + map_ds[f"{var_name}_sys_err"] = sys_err_helio + + return map_ds + + +def get_pset_directional_mask( + pset_ds: xr.Dataset, direction: str +) -> xr.DataArray | None: + """ + Get the boolean mask appropriate for the indicated ena direction. + + Parameters + ---------- + pset_ds : xarray.Dataset + PSET dataset. If spin_phase is "ram" or "anti", the dataset must contain + a "ram_mask" variable. + direction : str + Map spin phase. Must be "ram", "anti", or "full". + + Returns + ------- + pset_bin_mask : xarray.DataArray | None + Boolean mask indicating which bins are in the indicated direction. If + direction is "full", then None is returned. + """ + if direction not in ["ram", "anti", "full"]: + raise ValueError( + f"Invalid direction string: {direction}. Must be 'ram', 'anti', or 'full'." + ) + # Set the mask used to filter ram/anti-ram pixels + pset_valid_mask = None # Default to no mask (full spin) + if direction == "ram": + pset_valid_mask = pset_ds["ram_mask"] + logger.debug( + f"Using ram mask with shape: {pset_valid_mask.shape} " + f"containing {np.prod(pset_valid_mask.shape)} pixels," + f"{np.sum(pset_valid_mask.values)} of which are True." + ) + elif direction == "anti": + pset_valid_mask = ~pset_ds["ram_mask"] + logger.debug( + f"Using anti-ram mask with shape: {pset_valid_mask.shape} " + f"containing {np.prod(pset_valid_mask.shape)} pixels," + f"{np.sum(pset_valid_mask.values)} of which are True." + ) + return pset_valid_mask diff --git a/imap_processing/ena_maps/utils/map_utils.py b/imap_processing/ena_maps/utils/map_utils.py index a4cd488756..dd7b84208a 100644 --- a/imap_processing/ena_maps/utils/map_utils.py +++ b/imap_processing/ena_maps/utils/map_utils.py @@ -10,11 +10,95 @@ logger = logging.getLogger(__name__) +def vectorized_bincount( + indices: NDArray, weights: NDArray | None = None, minlength: int = 0 +) -> NDArray: + """ + Vectorized version of np.bincount for multi-dimensional arrays. + + This function applies np.bincount across multi-dimensional input arrays by + adding offsets to the indices and flattening, then reshaping the result. + This approach allows broadcasting between indices and weights. + + Parameters + ---------- + indices : NDArray + Array of non-negative integers to be binned. Can be multi-dimensional. + If multi-dimensional, bincount is applied independently along each + leading dimension. + weights : NDArray, optional + Array of weights that is broadcastable with indices. If provided, each + weight is accumulated into its corresponding bin. If None (default), + each index contributes a count of 1. + minlength : int, optional + Minimum number of bins in the output array. Applied to each independent + bincount operation. Default is 0. + + Returns + ------- + NDArray + Array of binned values with the same leading dimensions as the input + arrays, and a final dimension of size minlength (or the maximum index + 1, + whichever is larger). + + See Also + -------- + numpy.bincount : The underlying function being vectorized. + + Examples + -------- + >>> indices = np.array([[0, 1, 1], [2, 2, 3]]) + >>> vectorized_bincount(indices, minlength=4) + array([[1., 2., 0., 0.], + [0., 0., 2., 1.]]) + """ + # Handle 1D case directly + if indices.ndim == 1 and (weights is None or weights.ndim == 1): + return np.bincount(indices, weights=weights, minlength=minlength) + + # For multi-dimensional arrays, broadcast indices and weights + if weights is not None: + indices_bc, weights_bc = np.broadcast_arrays(indices, weights) + weights_flat = weights_bc.ravel() + else: + indices_bc = indices + weights_flat = None + + # Get the shape for reshaping output + non_spatial_shape = indices_bc.shape[:-1] + n_binsets = np.prod(non_spatial_shape) + + # Determine actual minlength if not specified + if minlength == 0: + minlength = int(np.max(indices_bc)) + 1 + + # We want to flatten the multi-dimensional bincount problem into a 1D problem. + # This can be done by offsetting the indices for each element of each additional + # dimension by an integer multiple of the number of bins. Doing so gives + # each element in the additional dimensions its own set of 1D bins: index 0 + # uses bins [0, minlength), index 1 uses bins [minlength, 2*minlength), etc. + offsets: NDArray = np.arange(n_binsets).reshape(*non_spatial_shape, 1) * minlength + indices_flat = (indices_bc + offsets).ravel() + + # Single bincount call with flattened data + binned_flat = np.bincount( + indices_flat, weights=weights_flat, minlength=n_binsets * minlength + ) + + # Reshape to separate each sample's bins + binned_values = binned_flat.reshape(n_binsets, -1)[:, :minlength].reshape( + *non_spatial_shape, minlength + ) + + return binned_values + + def bin_single_array_at_indices( value_array: NDArray, projection_grid_shape: tuple[int, ...], projection_indices: NDArray, input_indices: NDArray | None = None, + input_valid_mask: NDArray | None = None, ) -> NDArray: """ Bin an array of values at the given indices. @@ -24,7 +108,7 @@ def bin_single_array_at_indices( Parameters ---------- value_array : NDArray - Array of values to bin. The final axis be the one and only spatial axis. + Array of values to bin. The final axis is the one and only spatial axis. If other axes are present, they will be binned independently along the spatial axis. projection_grid_shape : tuple[int, ...] @@ -33,61 +117,89 @@ def bin_single_array_at_indices( or just (number of bins,) if the grid is 1D. projection_indices : NDArray Ordered indices for projection grid, corresponding to indices in input grid. - 1 dimensional. May be non-unique, depending on the projection method. + Can be 1-dimensional or multi-dimensional. If multi-dimensional, must be + broadcastable with value_array. May contain non-unique indices, depending + on the projection method. input_indices : NDArray Ordered indices for input grid, corresponding to indices in projection grid. 1 dimensional. May be non-unique, depending on the projection method. - If None (default), an arange of the same length as the - final axis of value_array is used. + If None (default), an numpy.arange of the same length as the final axis of + value_array is used. + input_valid_mask : NDArray, optional + Boolean mask array for valid values in input grid. + If None, all pixels are considered valid. Default is None. + Must be broadcastable with value_array and projection_indices. Returns ------- NDArray - Binned values on the projection grid. + Binned values on the projection grid. The output shape depends on the + input shapes after broadcasting: + - If value_array is 1D: returns 1D array of shape (num_projection_indices,) + - If value_array is multi-dimensional: returns array with shape + (*value_array.shape[:-1], num_projection_indices), where the leading + dimensions match value_array's non-spatial dimensions and the final + dimension contains the binned values for each projection grid position. + - If projection_indices is multi-dimensional and broadcasts with value_array, + the output shape will be (broadcasted_shape[:-1], num_projection_indices). Raises ------ ValueError - If the input and projection indices are not 1D arrays - with the same number of elements. - NotImplementedError - If the input value_array has dimensionality less than 1. + If input_indices is not a 1D array, or if the arrays cannot be + broadcast together. """ + # Set and check input_indices if input_indices is None: input_indices = np.arange(value_array.shape[-1]) - - # Both sets of indices must be 1D with the same number of elements - if input_indices.ndim != 1 or projection_indices.ndim != 1: + # input_indices must be 1D + if input_indices.ndim != 1: raise ValueError( - "Indices must be 1D arrays. " + "input_indices must be a 1D array. " "If using a rectangular grid, the indices must be unwrapped." ) - if input_indices.size != projection_indices.size: - raise ValueError( - "The number of input and projection indices must be the same. \n" - f"Received {input_indices.size} input indices and {projection_indices.size}" - " projection indices." + + # Verify projection_indices is broadcastable with value_array + try: + broadcasted_shape = np.broadcast_shapes( + projection_indices.shape, value_array.shape ) + except ValueError as e: + raise ValueError( + f"projection_indices shape {projection_indices.shape} must be " + f"broadcastable with value_array shape {value_array.shape}" + ) from e - num_projection_indices = np.prod(projection_grid_shape) + # Set and check input_valid_mask + if input_valid_mask is None: + input_valid_mask = np.ones(value_array.shape[-1], dtype=bool) + else: + input_valid_mask = np.asarray(input_valid_mask, dtype=bool) + # Verify input_valid_mask is broadcastable with value_array + try: + np.broadcast_shapes(input_valid_mask.shape, value_array.shape) + except ValueError as e: + raise ValueError( + f"input_valid_mask shape {input_valid_mask.shape} must be " + f"broadcastable with value_array shape {value_array.shape}" + ) from e + + # Broadcast input_valid_mask to match value_array shape if needed + input_valid_mask_bc = np.broadcast_to(input_valid_mask, broadcasted_shape) + + # Select values at input_indices positions along the spatial axis + values = value_array[..., input_indices] + + # Apply mask: set invalid values to 0 + values_masked = np.where(input_valid_mask_bc, values, 0) + + num_projection_indices = int(np.prod(projection_grid_shape)) + + # Use vectorized_bincount to handle arbitrary dimensions + binned_values = vectorized_bincount( + projection_indices, weights=values_masked, minlength=num_projection_indices + ) - if value_array.ndim == 1: - binned_values = np.bincount( - projection_indices, - weights=value_array[input_indices], - minlength=num_projection_indices, - ) - elif value_array.ndim >= 2: - # Apply bincount to each row independently - binned_values = np.apply_along_axis( - lambda x: np.bincount( - projection_indices, - weights=x[..., input_indices], - minlength=num_projection_indices, - ), - axis=-1, - arr=value_array, - ) return binned_values @@ -96,6 +208,7 @@ def bin_values_at_indices( projection_grid_shape: tuple[int, ...], projection_indices: NDArray, input_indices: NDArray | None = None, + input_valid_mask: NDArray | None = None, ) -> dict[str, NDArray]: """ Project values from input grid to projection grid based on matched indices. @@ -118,6 +231,9 @@ def bin_values_at_indices( Ordered indices for input grid, corresponding to indices in projection grid. 1 dimensional. May be non-unique, depending on the projection method. If None (default), behavior is determined by bin_single_array_at_indices. + input_valid_mask : NDArray, optional + Boolean mask array for valid values in input grid. + If None, all pixels are considered valid. Default is None. Returns ------- @@ -137,6 +253,7 @@ def bin_values_at_indices( projection_grid_shape=projection_grid_shape, projection_indices=projection_indices, input_indices=input_indices, + input_valid_mask=input_valid_mask, ) return binned_values_dict diff --git a/imap_processing/ena_maps/utils/naming.py b/imap_processing/ena_maps/utils/naming.py index 1d5379c77e..d8aa7b6d9e 100644 --- a/imap_processing/ena_maps/utils/naming.py +++ b/imap_processing/ena_maps/utils/naming.py @@ -33,7 +33,7 @@ class MappableInstrumentShortName(Enum): # Must be specified separately for purpose of type checking vs comparison valid_spice_frame_strings = ["sf", "hf", "hk"] _spice_frame_str_types = Literal["sf", "hf", "hk"] -_coord_frame_str_types = Literal["hae", "hre", "hnu", "gcs"] +_coord_frame_str_types = Literal["hae", "hre", "hnu", "gcs", "hrc"] # Mapping of inertial frames to their longer names used in logical source descriptors INERTIAL_FRAME_LONG_NAMES = { @@ -173,6 +173,87 @@ def to_string(self) -> str: ] ) + def to_catdesc(self) -> str: + """ + Convert the MapDescriptor instance to a human-readable CATDESC string. + + Returns + ------- + str + Information in descriptor converted to SPDF CATDESC attribute. This + is normally used for plot titles and should be under about 80 characters. + """ + instrument = self.instrument.name.split("_")[0] + if instrument not in ("IDEX", "GLOWS"): + instrument = instrument.title() + sensor = " Combined" if self.sensor == "combined" else self.sensor + species = "UV" if self.species == "uv" else self.species.title() + m = re.match( + r"^(drt|ena|int|isn|spx)(?:(?<=spx)\d+)?([^-_\s]*)$", self.principal_data + ) + quantity = { + "drt": "Rate", + "ena": "Inten", + "int": "Inten", + "isn": "Rate", + "spx": "Spectral", + }[m.group(1)] + if m.group(1) == "isn": + species = "ISN " + species + extras = m.group(2) + coord = self.coordinate_system.upper() + frame = { + "hf": "Helio", + "hk": "Helio Kin", + "sf": "SC", + }[self.frame_descriptor] + survival = "Surv Corr" if self.survival_corrected == "sp" else "No Surv Corr" + spin_phase = self.spin_phase.title() + if spin_phase == "Full": + spin_phase = "Full Spin" + m = re.match(r"^(\d+)deg|nside(\d+)", self.resolution_str) + resolution = f"{m.group(1)} deg" if m.group(1) else f"NSide {m.group(2)}" + if isinstance(self.duration, int): + duration = f"{self.duration} Day" + else: + m = re.match(r"^(\d+)(.*)$", self.duration) + duration = f"{m.group(1)} {m.group(2).title()}" + if duration.endswith("Mo"): + duration += "n" + catdesc = ( + f"IMAP {instrument}{sensor} {species} {quantity}, {coord} " + f"{frame} Frame, {survival}, {spin_phase}, {resolution}, {duration}" + ) + possible_extras = [ + ("nbs", "No sputter/bootstrap"), + ("nbkgnd", "No bkgnd sub"), + ] + for extra, long_description in possible_extras: + if extras.startswith(extra): + catdesc += f", {long_description}" + break + return catdesc + + @property + def principal_data_var(self) -> str: + """ + The name of the variable containing the principal data for the map. + + Returns + ------- + principal_data_var : str + CDF (dataset) variable name expected to contain the principal data. + """ + if self.principal_data.startswith("isnnbkgnd"): + return "isn_rate" + return { + "drt": "dust_rate", + "ena": "ena_intensity", + "int": "glows_rate", + "isn": "isn_rate_bg_subtracted", + "spx": "ena_spectral_index", + }[self.principal_data[:3]] + # Methods for parsing and building parts of the map descriptor string @staticmethod def get_instrument_descriptor( @@ -333,16 +414,13 @@ def get_map_coord_frame(frame_str: _coord_frame_str_types) -> SpiceFrame: NotImplementedError If the frame string is not recognized. """ - if frame_str == "hae": - return SpiceFrame.IMAP_HAE - elif frame_str == "hre": - return SpiceFrame.IMAP_HRE - elif frame_str == "hnu": - return SpiceFrame.IMAP_HNU - elif frame_str == "gcs": - return SpiceFrame.IMAP_GCS - else: - raise NotImplementedError("Coordinate frame is not yet implemented.") + try: + return SpiceFrame[f"IMAP_{frame_str.upper()}"] + except KeyError as err: + raise KeyError( + f"Coordinate frame {frame_str} which translates to " + f"SPICE frame IMAP_{frame_str.upper()} is not recognized." + ) from err def to_empty_map( self, diff --git a/imap_processing/glows/ancillary/imap_glows_pipeline_settings_20250923_v002.json b/imap_processing/glows/ancillary/imap_glows_pipeline-settings_20250923_v002.json similarity index 100% rename from imap_processing/glows/ancillary/imap_glows_pipeline_settings_20250923_v002.json rename to imap_processing/glows/ancillary/imap_glows_pipeline-settings_20250923_v002.json diff --git a/imap_processing/glows/l0/decom_glows.py b/imap_processing/glows/l0/decom_glows.py index 7782d68a00..7dabd256bc 100644 --- a/imap_processing/glows/l0/decom_glows.py +++ b/imap_processing/glows/l0/decom_glows.py @@ -3,12 +3,11 @@ from enum import Enum from pathlib import Path -from space_packet_parser import definitions - from imap_processing import imap_module_directory from imap_processing.ccsds.ccsds_data import CcsdsData from imap_processing.glows import __version__ from imap_processing.glows.l0.glows_l0_data import DirectEventL0, HistogramL0 +from imap_processing.utils import packet_generator, separate_ccsds_header_userdata class GlowsParams(Enum): @@ -49,32 +48,27 @@ def decom_packets( f"{imap_module_directory}/glows/packet_definitions/GLX_COMBINED.xml" ) - packet_definition = definitions.XtcePacketDefinition(xtce_document) - histdata = [] dedata = [] filename = packet_file_path.name - with open(packet_file_path, "rb") as binary_data: - glows_packets = packet_definition.packet_generator(binary_data) - - for packet in glows_packets: - apid = packet["PKT_APID"] - # Do something with the packet data - if apid == GlowsParams.HIST_APID.value: - values = [item.raw_value for item in packet.user_data.values()] - hist_l0 = HistogramL0( - __version__, filename, CcsdsData(packet.header), *values - ) - histdata.append(hist_l0) - - if apid == GlowsParams.DE_APID.value: - values = [item.raw_value for item in packet.user_data.values()] - - de_l0 = DirectEventL0( - __version__, filename, CcsdsData(packet.header), *values - ) - dedata.append(de_l0) - - return histdata, dedata + for packet in packet_generator(packet_file_path, xtce_document): + apid = packet["PKT_APID"] + # Do something with the packet data + if apid == GlowsParams.HIST_APID.value: + header, userdata = separate_ccsds_header_userdata(packet) + hist_l0 = HistogramL0( + __version__, filename, CcsdsData(header), *list(userdata.values()) + ) + histdata.append(hist_l0) + + if apid == GlowsParams.DE_APID.value: + values = [item.raw_value for i, item in enumerate(packet.values()) if i > 6] + header = { + key: value for i, (key, value) in enumerate(packet.items()) if i <= 6 + } + de_l0 = DirectEventL0(__version__, filename, CcsdsData(header), *values) + dedata.append(de_l0) + + return histdata, dedata diff --git a/imap_processing/glows/l0/glows_l0_data.py b/imap_processing/glows/l0/glows_l0_data.py index a8965df689..40f0733541 100644 --- a/imap_processing/glows/l0/glows_l0_data.py +++ b/imap_processing/glows/l0/glows_l0_data.py @@ -160,6 +160,28 @@ def __post_init__(self) -> None: int(self.DE_DATA, 2).to_bytes(len(self.DE_DATA) // 8, "big") ) + # Sort by SEQ + def __lt__(self, other: "DirectEventL0") -> bool: + """ + Define less-than comparison for DirectEventL0. + + This is used when sorting lists of DirectEvents. + The L0 values should be sorted according to SEQ, which is the official + sequencing value for packets. + + Parameters + ---------- + other : DirectEventL0 + Another DirectEventL0 object for comparison. + + Returns + ------- + bool: + If the current object's SEQ is less than the other object's SEQ (i.e. + sorts SEQ in traditional ascending order). + """ + return self.SEQ < other.SEQ + def within_same_sequence(self, other: "DirectEventL0") -> bool: """ Compare fields for L0 which should be the same for packets within one sequence. diff --git a/imap_processing/glows/l1a/glows_l1a.py b/imap_processing/glows/l1a/glows_l1a.py index 1f799e4d64..051b6f6667 100644 --- a/imap_processing/glows/l1a/glows_l1a.py +++ b/imap_processing/glows/l1a/glows_l1a.py @@ -1,5 +1,7 @@ """Methods for GLOWS Level 1A processing and CDF writing.""" +import logging +from itertools import groupby from pathlib import Path import numpy as np @@ -9,10 +11,13 @@ from imap_processing.glows.l0.decom_glows import decom_packets from imap_processing.glows.l0.glows_l0_data import DirectEventL0 from imap_processing.glows.l1a.glows_l1a_data import DirectEventL1A, HistogramL1A +from imap_processing.glows.utils.constants import GlowsConstants from imap_processing.spice.time import ( met_to_ttj2000ns, ) +logger = logging.getLogger(__name__) + def create_glows_attr_obj() -> ImapCdfAttributes: """ @@ -57,18 +62,17 @@ def glows_l1a(packet_filepath: Path) -> list[xr.Dataset]: # Decompose packet file into histogram, and direct event data. hist_l0, de_l0 = decom_packets(packet_filepath) - l1a_de = process_de_l0(de_l0) - l1a_hists = [] - for hist in hist_l0: - l1a_hists.append(HistogramL1A(hist)) - # Generate CDF files for each day output_datasets = [] - dataset = generate_histogram_dataset(l1a_hists, glows_attrs) - output_datasets.append(dataset) + if hist_l0: + l1a_hists = [HistogramL1A(hist) for hist in hist_l0] + dataset = generate_histogram_dataset(l1a_hists, glows_attrs) + output_datasets.append(dataset) - dataset = generate_de_dataset(l1a_de, glows_attrs) - output_datasets.append(dataset) + if de_l0: + l1a_de = process_de_l0(de_l0) + dataset = generate_de_dataset(l1a_de, glows_attrs) + output_datasets.append(dataset) return output_datasets @@ -93,18 +97,48 @@ def process_de_l0( Dictionary with keys of days and values of lists of DirectEventL1A objects. Each day has one CDF file associated with it. """ - de_list: list[DirectEventL1A] = [] - - for de in de_l0: - # Putting not first data int o last direct event list. - if de.SEQ != 0: - # If the direct event is part of a sequence and is not the first, - # add it to the last direct event in the list - de_list[-1].merge_de_packets(de) - else: - de_list.append(DirectEventL1A(de)) + l1a_output: list[DirectEventL1A] = [] - return de_list + # Sort by SEC, so groupby only has one instance of each SEC + sorted_l0 = sorted(de_l0, key=lambda x: x.SEC) + + for sec, de in groupby(sorted_l0, lambda x: x.SEC): + de_list = list(de) + if len(de_list) == 1: + # Only one seq found + new_de = DirectEventL1A(de_list[0]) + if new_de.l0.LEN != 1: + # We're missing packets off the end + new_de.finish_incomplete_packet() + + l1a_output.append(new_de) + else: + sorted_des = sorted(de_list) + if sorted_des[0].SEQ != 0: + logger.warning(f"GLOWS: First SEQ not found for DE SEC {sec}") + # Processing cannot be run on this packet. + continue + first_de = DirectEventL1A(sorted_des[0]) + for each_de in sorted_des[1:]: + try: + first_de.merge_de_packets(each_de) + except (ValueError, IndexError) as e: + # We don't want to stop processing for DE errors + logger.warning( + f"ERROR ENCOUNTERED in GLOWS DE processing. " + f"Excluding packet from output. Error: {e}" + ) + continue + + if sorted_des[-1].SEQ != first_de.l0.LEN: + first_de.finish_incomplete_packet() + + l1a_output.append(first_de) + + # Filter out DE records with no direct_events (incomplete packet sequences) + l1a_output = [de for de in l1a_output if de.direct_events] + + return l1a_output def generate_de_dataset( @@ -129,7 +163,7 @@ def generate_de_dataset( # TODO: Block header per second, or global attribute? # Store timestamps for each DirectEventL1a object. - time_data = np.zeros(len(de_l1a_list), dtype=np.int64) + time_data: np.ndarray = np.zeros(len(de_l1a_list), dtype=np.int64) # Each DirectEventL1A class covers 1 second of direct events data direct_events = np.zeros((len(de_l1a_list), len(de_l1a_list[0].direct_events), 4)) @@ -137,7 +171,6 @@ def generate_de_dataset( # First variable is the output data type, second is the list of values support_data: dict = { - # "flight_software_version": [], "seq_count_in_pkts_file": [np.uint16, []], "number_of_de_packets": [np.uint32, []], } @@ -291,16 +324,51 @@ def generate_histogram_dataset( output : xarray.Dataset Dataset containing the GLOWS L1A histogram CDF output. """ + # Filter out empty histogram objects (those with no bins). + hist_l1a_list = [ + hist for hist in hist_l1a_list if hist.number_of_bins_per_histogram > 0 + ] + + # Filter out histograms with imap_start_time == 0 (invalid timing data). + valid_hists = [hist for hist in hist_l1a_list if hist.imap_start_time.seconds != 0] + if len(valid_hists) < len(hist_l1a_list): + logger.warning( + f"GLOWS: Filtered out {len(hist_l1a_list) - len(valid_hists)} " + f"histogram(s) with imap_start_time == 0." + ) + hist_l1a_list = valid_hists + + # Deduplicate by (imap_start_time, imap_time_offset), keeping the first occurrence. + seen_times: dict = {} + for hist in hist_l1a_list: + key = ( + hist.imap_start_time.seconds, + hist.imap_start_time.subseconds, + hist.imap_time_offset.seconds, + hist.imap_time_offset.subseconds, + ) + if key not in seen_times: + seen_times[key] = hist + dedup_hists = list(seen_times.values()) + if len(dedup_hists) < len(hist_l1a_list): + logger.warning( + f"GLOWS: Filtered out {len(hist_l1a_list) - len(dedup_hists)} " + f"duplicate histogram(s) by imap_start_time and imap_time_offset." + ) + hist_l1a_list = dedup_hists + # Store timestamps for each HistogramL1A object. - time_data = np.zeros(len(hist_l1a_list), dtype=np.int64) - # TODO Add daily average of histogram counts + time_data: np.ndarray = np.zeros(len(hist_l1a_list), dtype=np.int64) # Data in lists, for each of the 25 time varying datapoints in HistogramL1A - hist_data = np.zeros((len(hist_l1a_list), 3600), dtype=np.uint16) + hist_data: np.ndarray = np.full( + (len(hist_l1a_list), GlowsConstants.STANDARD_BIN_COUNT), + GlowsConstants.HISTOGRAM_FILLVAL, + dtype=np.uint16, + ) # First variable is the output data type, second is the list of values support_data: dict = { - "flight_software_version": [np.uint32, []], "seq_count_in_pkts_file": [np.uint16, []], "first_spin_id": [np.uint32, []], "last_spin_id": [np.uint32, []], @@ -326,8 +394,12 @@ def generate_histogram_dataset( } for index, hist in enumerate(hist_l1a_list): - epoch_time = met_to_ttj2000ns(hist.imap_start_time.to_seconds()) - hist_data[index] = hist.histogram + epoch_time = met_to_ttj2000ns( + hist.imap_start_time.to_seconds() + hist.imap_time_offset.to_seconds() / 2 + ) + # Assign histogram data, padding with zeros if shorter than max_bins + hist_len = len(hist.histogram) + hist_data[index, :hist_len] = hist.histogram support_data["flags_set_onboard"][1].append(hist.flags["flags_set_onboard"]) support_data["is_generated_on_ground"][1].append( @@ -349,7 +421,8 @@ def generate_histogram_dataset( dims=["epoch"], attrs=glows_cdf_attributes.get_variable_attributes("epoch", check_schema=False), ) - bin_count = 3600 # TODO: Is it always 3600 bins? + + bin_count = GlowsConstants.STANDARD_BIN_COUNT bins = xr.DataArray( np.arange(bin_count), @@ -388,6 +461,11 @@ def generate_histogram_dataset( output["histogram"] = hist + # These attributes are the same for each record, so we don't + # need to store them per epoch like most of the other fields + # Instead, we store them as global attributes + output.attrs["flight_software_version"] = hist_l1a_list[0].flight_software_version + for key, value in support_data.items(): output[key] = xr.DataArray( np.array(value[1], dtype=value[0]), diff --git a/imap_processing/glows/l1a/glows_l1a_data.py b/imap_processing/glows/l1a/glows_l1a_data.py index 0ebad91c5c..164d4d832e 100644 --- a/imap_processing/glows/l1a/glows_l1a_data.py +++ b/imap_processing/glows/l1a/glows_l1a_data.py @@ -1,12 +1,14 @@ """Data classes to support GLOWS L1A processing.""" +import logging import struct from dataclasses import InitVar, dataclass, field -from imap_processing.glows import __version__ from imap_processing.glows.l0.glows_l0_data import DirectEventL0, HistogramL0 from imap_processing.glows.utils.constants import DirectEvent, TimeTuple +logger = logging.getLogger(__name__) + @dataclass class StatusData: @@ -149,8 +151,6 @@ class HistogramL1A: List of histogram data values flight_software_version: int Version of the flight software used to generate the data. Part of block header. - ground_software_version: str - Version of the ground software used to process the data. Part of block header. pkts_file_name: str Name of the packet file used to generate the data. Part of block header. seq_count_in_pkts_file: int @@ -198,10 +198,9 @@ class HistogramL1A: l0: InitVar[HistogramL0] histogram: list[int] = field(init=False) - # next four are in block header flight_software_version: int = field(init=False) - ground_software_version: str = field(init=False) - pkts_file_name: str = field(init=False) + pkts_file_name: str = "" + # next four are in block header seq_count_in_pkts_file: int = field(init=False) first_spin_id: int = field(init=False) last_spin_id: int = field(init=False) @@ -238,7 +237,6 @@ def __post_init__(self, l0: HistogramL0) -> None: self.histogram = list(l0.HISTOGRAM_DATA) self.flight_software_version = l0.SWVER - self.ground_software_version = __version__ self.pkts_file_name = l0.packet_file_name # note: packet number is seq_count (per apid!) field in CCSDS header self.seq_count_in_pkts_file = l0.ccsds_header.SRC_SEQ_CTR @@ -261,8 +259,7 @@ def __post_init__(self, l0: HistogramL0) -> None: self.glows_time_offset = TimeTuple(l0.GLXOFFSEC, l0.GLXOFFSUBSEC) # In L1a, these are left as unit encoded values. - # TODO: This is plus one in validation code, why? - self.number_of_spins_per_block = l0.SPINS + 1 + self.number_of_spins_per_block = l0.SPINS self.number_of_bins_per_histogram = l0.NBINS self.number_of_events = l0.EVENTS self.filter_temperature_average = l0.TEMPAVG @@ -280,6 +277,16 @@ def __post_init__(self, l0: HistogramL0) -> None: "is_generated_on_ground": False, } + # Remove the extra byte from some packets (if there are an odd number of bins) + if self.number_of_bins_per_histogram % 2 == 1: + self.histogram = self.histogram[:-1] + + if self.number_of_bins_per_histogram != len(self.histogram): + logger.warning( + f"Number of bins {self.number_of_bins_per_histogram} does not match " + f"processed number of bins {len(self.histogram)}!" + ) + @dataclass class DirectEventL1A: @@ -290,14 +297,6 @@ class DirectEventL1A: so this class may span multiple packets. This is determined by the SEQ and LEN, by each packet having an incremental SEQ until LEN number of packets. - Block header information is retrieved from l0: - { - "flight_software_version" = l0.ccsds_header.VERSION - "ground_software_version" = __version__ - "pkts_file_name" = l0.packet_file_name - "seq_count_in_pkts_file" = l0.ccsds_header.SRC_SEQ_CTR - } - Parameters ---------- level0 : DirectEventL0 @@ -323,11 +322,14 @@ class DirectEventL1A: direct_events : list[DirectEvent] List of DirectEvent objects, which is created when the final level 0 packet in the sequence is added to de_data. Defaults to None. + pkts_file_name : str + Name of the L0 CCSDS packets file used to generate this dataset Methods ------- merge_de_packets Add another Level0 instance. + finish_incomplete_packet """ l0: DirectEventL0 @@ -336,6 +338,7 @@ class DirectEventL1A: missing_seq: list[int] status_data: StatusData = field(init=False) direct_events: list[DirectEvent] = field(init=False, default=None) # type: ignore[arg-type] + pkts_file_name: str = " " def __init__(self, level0: DirectEventL0): self.l0 = level0 @@ -343,6 +346,8 @@ def __init__(self, level0: DirectEventL0): self.de_data = bytearray(level0.DE_DATA) self.missing_seq = [] + self.pkts_file_name = level0.packet_file_name + if level0.LEN == 1: self._process_de_data() @@ -370,7 +375,8 @@ def merge_de_packets(self, second_l0: DirectEventL0) -> None: raise ValueError( f"Sequence for direct event L1A is out of order or " f"incorrect. Attempted to append sequence counter " - f"{second_l0.SEQ} after {self.most_recent_seq}." + f"{second_l0.SEQ} after {self.most_recent_seq}. " + f"New DE time: {second_l0.SEC}, current time: {self.l0.SEC}." ) # Track any missing sequence counts @@ -380,11 +386,10 @@ def merge_de_packets(self, second_l0: DirectEventL0) -> None: # Determine if new L0 packet matches existing L0 packet match = self.l0.within_same_sequence(second_l0) - # TODO: Should this raise an error? Log? something else? if not match: raise ValueError( f"While attempting to merge L0 packet {second_l0} " - f"with {self.l0} mismatched values" + f"with {self.l0} mismatched values " f"were found. " ) @@ -392,10 +397,19 @@ def merge_de_packets(self, second_l0: DirectEventL0) -> None: self.most_recent_seq = second_l0.SEQ # if this is the last packet in the sequence, process the DE data - # TODO: What if the last packet never arrives? if self.l0.LEN == self.most_recent_seq + 1: self._process_de_data() + def finish_incomplete_packet(self) -> None: + """ + Finish an incomplete packet. + + This will fill out the missing sequences and status data, but no DEs. This can + only run with at least the first packet. + """ + self.missing_seq += [i for i in range(self.most_recent_seq + 1, self.l0.LEN)] + self.status_data = StatusData(self.de_data[:40]) + def _process_de_data(self) -> None: """ Will process direct event bytes. @@ -427,6 +441,14 @@ def _generate_direct_events(self, direct_events: bytearray) -> list[DirectEvent] An array containing DirectEvent objects. """ # read the first direct event, which is always uncompressed + + if len(direct_events) < 8: + logger.warning( + "GLOWS: Direct event data is too short to contain any events " + f"(got {len(direct_events)} bytes, need at least 8). " + "Returning empty event list." + ) + return [] current_event = self._build_uncompressed_event(direct_events[:8]) processed_events = [current_event] @@ -512,7 +534,7 @@ def _build_compressed_event( else: raise ValueError( - f"Incorrect length {len(raw)} for {raw}, expecting 2 or 3" + f"Incorrect length {len(raw)} for {raw}, expecting 2 or 3 " f"bit compressed direct event data" ) diff --git a/imap_processing/glows/l1b/glows_l1b.py b/imap_processing/glows/l1b/glows_l1b.py index 56d1c92d00..6166f10490 100644 --- a/imap_processing/glows/l1b/glows_l1b.py +++ b/imap_processing/glows/l1b/glows_l1b.py @@ -1,8 +1,7 @@ """Methods for processing GLOWS L1B data.""" import dataclasses -import json -from pathlib import Path +import logging import numpy as np import xarray as xr @@ -14,7 +13,11 @@ AncillaryParameters, DirectEventL1B, HistogramL1B, + PipelineSettings, ) +from imap_processing.spice.time import et_to_datetime64, ttj2000ns_to_et + +logger = logging.getLogger(__name__) def glows_l1b( @@ -23,14 +26,16 @@ def glows_l1b( uv_sources: xr.Dataset, suspected_transients: xr.Dataset, exclusions_by_instr_team: xr.Dataset, + pipeline_settings_dataset: xr.Dataset, + conversion_table_dict: dict, ) -> xr.Dataset: """ - Will process the GLOWS L1B data and format the output datasets. + Will process the histogram GLOWS L1B data and format the output datasets. Parameters ---------- input_dataset : xr.Dataset - Dataset of input values. + Dataset of input values for L1A histogram data. excluded_regions : xr.Dataset Dataset containing excluded sky regions with ecliptic coordinates. This is the output from GlowsAncillaryCombiner. @@ -43,6 +48,11 @@ def glows_l1b( exclusions_by_instr_team : xr.Dataset Dataset containing manual exclusions by instrument team with time-based masks. This is the output from GlowsAncillaryCombiner. + pipeline_settings_dataset : xr.Dataset + Dataset containing pipeline settings and other ancillary parameters. + conversion_table_dict : dict + Dict containing the L1B conversion table for decoding ancillary parameters. + This is read directly out of the JSON file. Returns ------- @@ -53,6 +63,8 @@ def glows_l1b( cdf_attrs.add_instrument_global_attrs("glows") cdf_attrs.add_instrument_variable_attrs("glows", "l1b") + day = et_to_datetime64(ttj2000ns_to_et(input_dataset["epoch"].data[0])) + # Create ancillary exclusions object from passed-in datasets ancillary_exclusions = AncillaryExclusions( excluded_regions=excluded_regions, @@ -60,37 +72,73 @@ def glows_l1b( suspected_transients=suspected_transients, exclusions_by_instr_team=exclusions_by_instr_team, ) + pipeline_settings = PipelineSettings( + pipeline_settings_dataset.sel(epoch=day, method="nearest"), + ) - with open( - Path(__file__).parents[1] / "ancillary" / "l1b_conversion_table_v001.json" - ) as f: - ancillary_parameters = AncillaryParameters(json.loads(f.read())) + ancillary_parameters = AncillaryParameters(conversion_table_dict) - logical_source = ( - input_dataset.attrs["Logical_source"][0] - if isinstance(input_dataset.attrs["Logical_source"], list) - else input_dataset.attrs["Logical_source"] + output_dataarrays = process_histogram( + input_dataset, ancillary_exclusions, ancillary_parameters, pipeline_settings + ) + output_dataset = create_l1b_hist_output( + output_dataarrays, + output_dataarrays[0].coords["epoch"], + input_dataset["bins"], + cdf_attrs, ) - if "hist" in logical_source: - output_dataset = create_l1b_hist_output( - input_dataset, cdf_attrs, ancillary_parameters, ancillary_exclusions - ) + output_dataset.attrs["flight_software_version"] = input_dataset.attrs[ + "flight_software_version" + ] + parents = input_dataset.attrs.get("Parents", "") + output_dataset.attrs["pkts_file_name"] = [ + parent for parent in parents if parent.endswith("pkts") + ] - elif "de" in logical_source: - output_dataset = create_l1b_de_output(input_dataset, cdf_attrs) + return output_dataset - else: - raise ValueError( - f"Logical_source {input_dataset.attrs['Logical_source']} for input file " - f"does not match histogram " - "('hist') or direct event ('de')." - ) + +def glows_l1b_de( + input_dataset: xr.Dataset, + conversion_table_dict: dict, +) -> xr.Dataset: + """ + Process GLOWS L1B direct events data. + + Parameters + ---------- + input_dataset : xr.Dataset + The input dataset to process. + conversion_table_dict : dict + Dict containing the L1B conversion table for decoding ancillary parameters. + + Returns + ------- + xr.Dataset + The processed L1B direct events dataset. + """ + cdf_attrs = ImapCdfAttributes() + cdf_attrs.add_instrument_global_attrs("glows") + cdf_attrs.add_instrument_variable_attrs("glows", "l1b") + + ancillary_parameters = AncillaryParameters(conversion_table_dict) + + output_dataset = create_l1b_de_output( + input_dataset, cdf_attrs, ancillary_parameters + ) + + parents = input_dataset.attrs.get("Parents", "") + output_dataset.attrs["pkts_file_name"] = [ + parent for parent in parents if parent.endswith("pkts") + ] return output_dataset -def process_de(l1a: xr.Dataset) -> tuple[xr.DataArray]: +def process_de( + l1a: xr.Dataset, ancillary_parameters: AncillaryParameters +) -> tuple[xr.DataArray]: """ Will process the direct event data from the L1A dataset and return the L1B dataset. @@ -104,6 +152,8 @@ def process_de(l1a: xr.Dataset) -> tuple[xr.DataArray]: ---------- l1a : xr.Dataset The L1A dataset to process. + ancillary_parameters : AncillaryParameters + The ancillary parameters for decoding DE data. Returns ------- @@ -142,8 +192,29 @@ def process_de(l1a: xr.Dataset) -> tuple[xr.DataArray]: # (input) variable. input_dims[0] = ["within_the_second", "direct_event_components"] + # Create a closure that captures the ancillary parameters + def create_direct_event_l1b(*args) -> tuple: # type: ignore[no-untyped-def] + """ + Create DirectEventL1B object with captured ancillary parameters. + + Parameters + ---------- + *args + Variable arguments passed from xr.apply_ufunc containing L1A data. + + Returns + ------- + tuple + Tuple of values from DirectEventL1B dataclass. + """ + return tuple( + dataclasses.asdict( + DirectEventL1B(*args, ancillary_parameters) # type: ignore[call-arg] + ).values() + ) + l1b_fields: tuple = xr.apply_ufunc( - lambda *args: tuple(dataclasses.asdict(DirectEventL1B(*args)).values()), + create_direct_event_l1b, *dataarrays, input_core_dims=input_dims, output_core_dims=output_dims, @@ -158,6 +229,7 @@ def process_histogram( l1a: xr.Dataset, ancillary_exclusions: AncillaryExclusions, ancillary_parameters: AncillaryParameters, + pipeline_settings: PipelineSettings, ) -> xr.Dataset: """ Will process the histogram data from the L1A dataset and return the L1B dataset. @@ -176,6 +248,8 @@ def process_histogram( The ancillary exclusions data for bad-angle flag processing. ancillary_parameters : AncillaryParameters The ancillary parameters for decoding histogram data. + pipeline_settings : PipelineSettings + The pipeline settings including flag activation. Returns ------- @@ -183,6 +257,16 @@ def process_histogram( The DataArrays for each variable in the L1B dataset. These can be assembled directly into a DataSet with the appropriate attributes. """ + invalid_mask = l1a["imap_start_time"].values == 0.0 + if invalid_mask.any(): + logger.warning( + "GLOWS L1B: Skipping %d histogram(s) with imap_start_time=0.0 " + "(invalid timing data) at epochs: %s", + invalid_mask.sum(), + l1a["epoch"].values[invalid_mask], + ) + l1a = l1a.isel(epoch=~invalid_mask) + dataarrays = [l1a[i] for i in l1a.keys()] input_dims: list = [[] for i in l1a.keys()] @@ -211,8 +295,7 @@ def process_histogram( ] # histograms is the only multi dimensional input variable, so we set the non-epoch - # dimension ("bins"). - # The rest of the input vars are epoch only, so they have an empty list. + # dimension ("bins"). Also, the three scalar inputs only have a non-epoch dimension. input_dims[0] = ["bins"] # Create a closure that captures the ancillary objects @@ -231,7 +314,7 @@ def create_histogram_l1b(*args) -> tuple: # type: ignore[no-untyped-def] Tuple of processed L1B data arrays from HistogramL1B.output_data(). """ return HistogramL1B( # type: ignore[call-arg] - *args, ancillary_exclusions, ancillary_parameters + *args, ancillary_exclusions, ancillary_parameters, pipeline_settings ).output_data() l1b_fields = xr.apply_ufunc( @@ -248,37 +331,39 @@ def create_histogram_l1b(*args) -> tuple: # type: ignore[no-untyped-def] def create_l1b_hist_output( - input_dataset: xr.Dataset, + l1b_dataarrays: tuple[xr.DataArray], + epoch: xr.DataArray, + bin_coord: xr.DataArray, cdf_attrs: ImapCdfAttributes, - ancillary_parameters: AncillaryParameters, - ancillary_exclusions: AncillaryExclusions, ) -> xr.Dataset: """ Create the output dataset for the L1B histogram data. - This function processes the input dataset and creates a new dataset with the - appropriate attributes and data variables. It uses the `process_histogram` function - to process the histogram data. + This function takes in the output from `process_histogram`, which is a tuple of + DataArrays matching the output L1B data variables, and assembles them into a + Dataset with the appropriate coordinates. Parameters ---------- - input_dataset : xr.Dataset - The input L1A GLOWS Histogram dataset to process. + l1b_dataarrays : tuple[xr.DataArray] + The DataArrays for each variable in the L1B dataset. These align with the + fields in the HistogramL1B dataclass, which also describes each variable. + epoch : xr.DataArray + The epoch DataArray to use as a coordinate in the output dataset. Generally + equal to the L1A epoch, except when values are dropped for no data. + bin_coord : xr.DataArray + An arange DataArray for the bins coordinate. Nominally expected to be equal to + `xr.DataArray(np.arange(number_of_bins_per_histogram), name="bins", + dims=["bins"])`. Pulled up from L1A. cdf_attrs : ImapCdfAttributes The CDF attributes to use for the output dataset. - ancillary_parameters : AncillaryParameters - The ancillary parameters to use for the output dataset. Generated from the - l1b conversion table and pipeline setting ancillary files. - ancillary_exclusions : AncillaryExclusions - The ancillary exclusions to use for the output dataset. Generated from - ancillary files. Returns ------- output_dataset : xr.Dataset The output dataset with the processed histogram data and all attributes. """ - data_epoch = input_dataset["epoch"] + data_epoch = epoch data_epoch.attrs = cdf_attrs.get_variable_attributes("epoch", check_schema=False) flag_data = xr.DataArray( @@ -318,7 +403,7 @@ def create_l1b_hist_output( ) bin_data = xr.DataArray( - input_dataset["bins"].data, + bin_coord.data, name="bins", dims=["bins"], attrs=cdf_attrs.get_variable_attributes("bins_attrs", check_schema=False), @@ -331,10 +416,6 @@ def create_l1b_hist_output( attrs=cdf_attrs.get_variable_attributes("bins_label", check_schema=False), ) - output_dataarrays = process_histogram( - input_dataset, ancillary_exclusions, ancillary_parameters - ) - output_dataset = xr.Dataset( coords={ "epoch": data_epoch, @@ -349,22 +430,25 @@ def create_l1b_hist_output( ) # Since we know the output_dataarrays are in the same order as the fields in the - # HistogramL1B dataclass, we can use dataclasses.fields to get the field names. - + # HistogramL1B dataclass, we can use dataclasses.fields to get the field names, + # with the exception of the global attributes. fields = dataclasses.fields(HistogramL1B) - for index, dataarray in enumerate(output_dataarrays): - # Dataarray is already an xr.DataArray type, so we can just assign it - output_dataset[fields[index].name] = dataarray - output_dataset[fields[index].name].attrs = cdf_attrs.get_variable_attributes( - fields[index].name - ) + for index, dataarray in enumerate(l1b_dataarrays): + if fields[index].name not in ["flight_software_version", "pkts_file_name"]: + # Dataarray is already an xr.DataArray type, so we can just assign it + output_dataset[fields[index].name] = dataarray + output_dataset[ + fields[index].name + ].attrs = cdf_attrs.get_variable_attributes(fields[index].name) output_dataset["bins"] = bin_data return output_dataset def create_l1b_de_output( - input_dataset: xr.Dataset, cdf_attrs: ImapCdfAttributes + input_dataset: xr.Dataset, + cdf_attrs: ImapCdfAttributes, + ancillary_parameters: AncillaryParameters, ) -> xr.Dataset: """ Create the output dataset for the L1B direct event data. @@ -375,6 +459,8 @@ def create_l1b_de_output( The input dataset to process. cdf_attrs : ImapCdfAttributes The CDF attributes to use for the output dataset. + ancillary_parameters : AncillaryParameters + The ancillary parameters for decoding DE data. Returns ------- @@ -384,7 +470,7 @@ def create_l1b_de_output( data_epoch = input_dataset["epoch"] data_epoch.attrs = cdf_attrs.get_variable_attributes("epoch", check_schema=False) - output_dataarrays = process_de(input_dataset) + output_dataarrays = process_de(input_dataset, ancillary_parameters) within_the_second_data = xr.DataArray( input_dataset["within_the_second"], name="within_the_second", diff --git a/imap_processing/glows/l1b/glows_l1b_data.py b/imap_processing/glows/l1b/glows_l1b_data.py index 8242ee371d..7fcb18331c 100644 --- a/imap_processing/glows/l1b/glows_l1b_data.py +++ b/imap_processing/glows/l1b/glows_l1b_data.py @@ -1,9 +1,7 @@ """Module for GLOWS L1B data products.""" import dataclasses -import json from dataclasses import InitVar, dataclass, field -from pathlib import Path import numpy as np import xarray as xr @@ -11,8 +9,15 @@ from imap_processing.glows import FLAG_LENGTH from imap_processing.glows.utils.constants import TimeTuple +from imap_processing.quality_flags import GLOWSL1bFlags from imap_processing.spice import geometry -from imap_processing.spice.geometry import SpiceBody, SpiceFrame +from imap_processing.spice.geometry import ( + SpiceBody, + SpiceFrame, + frame_transform, + get_instrument_mounting_az_el, + spherical_to_cartesian, +) from imap_processing.spice.spin import ( get_instrument_spin_phase, get_spin_angle, @@ -60,6 +65,10 @@ class PipelineSettings: # numpydoc ignore=PR02 Offset in hours to adjust sunset time relative to onboard settings for fine-tuning the day/night boundary determination. + spin_offset_correction : float + Constant spin angle offset [degrees] applied to fix a constant + spin offset observed for stars as seen by GLOWS. + processing_thresholds : dict Various thresholds and parameters for ground processing pipeline that control sensitivity and quality criteria for L1B data processing. @@ -89,6 +98,7 @@ class PipelineSettings: # numpydoc ignore=PR02 active_bad_time_flags: list[bool] = field(init=False) sunrise_offset: float = field(init=False) sunset_offset: float = field(init=False) + spin_offset_correction: float = field(init=False) processing_thresholds: dict = field(init=False) def __post_init__(self, pipeline_dataset: xr.Dataset) -> None: @@ -101,33 +111,103 @@ def __post_init__(self, pipeline_dataset: xr.Dataset) -> None: Dataset containing pipeline settings data variables. """ # Extract active bad-angle flags (default to all True if not present) + _angle_flag_names = [ + "is_close_to_uv_source", + "is_inside_excluded_region", + "is_excluded_by_instr_team", + "is_suspected_transient", + ] if "active_bad_angle_flags" in pipeline_dataset.data_vars: self.active_bad_angle_flags = list( pipeline_dataset["active_bad_angle_flags"].values ) + elif any( + f"active_bad_angle_flags_{n}" in pipeline_dataset.data_vars + for n in _angle_flag_names + ): + # Flattened format from convert_json_to_dataset + self.active_bad_angle_flags = [ + bool(pipeline_dataset[f"active_bad_angle_flags_{name}"].values) + for name in _angle_flag_names + ] else: # Default: all 4 bad-angle flags are active self.active_bad_angle_flags = [True, True, True, True] # Extract active bad-time flags (default to all True if not present) + _time_flag_names = [ + "is_pps_missing", + "is_time_status_missing", + "is_phase_missing", + "is_spin_period_missing", + "is_overexposed", + "is_direct_event_non_monotonic", + "is_night", + "is_hv_test_in_progress", + "is_test_pulse_in_progress", + "is_memory_error_detected", + "is_generated_on_ground", + "is_beyond_daily_statistical_error", + "is_temperature_std_dev_beyond_threshold", + "is_hv_voltage_std_dev_beyond_threshold", + "is_spin_period_std_dev_beyond_threshold", + "is_pulse_length_std_dev_beyond_threshold", + "is_spin_period_difference_beyond_threshold", + ] if "active_bad_time_flags" in pipeline_dataset.data_vars: self.active_bad_time_flags = list( pipeline_dataset["active_bad_time_flags"].values ) + elif any( + f"active_bad_time_flags_{n}" in pipeline_dataset.data_vars + for n in _time_flag_names + ): + # Flattened format from convert_json_to_dataset + self.active_bad_time_flags = [ + bool(pipeline_dataset[f"active_bad_time_flags_{name}"].values) + for name in _time_flag_names + ] else: # Default: assume all bad-time flags are active - self.active_bad_time_flags = [True] * 16 # Typical number of bad-time flags + self.active_bad_time_flags = [True] * FLAG_LENGTH # Extract sunrise/sunset offsets (default to 0.0 if not present) self.sunrise_offset = float(pipeline_dataset.get("sunrise_offset", 0.0)) self.sunset_offset = float(pipeline_dataset.get("sunset_offset", 0.0)) + # Extract spin-offset correction in deg units (default to 0.0 if not present) + self.spin_offset_correction = float( + pipeline_dataset.get("spin_offset_correction", 0.0) + ) + # Extract processing thresholds (collect all threshold-related variables) self.processing_thresholds = {} for var_name in pipeline_dataset.data_vars: if "threshold" in var_name.lower() or "limit" in var_name.lower(): self.processing_thresholds[var_name] = pipeline_dataset[var_name].item() + def get_threshold(self, suffix: str) -> float | None: + """ + Return the threshold value whose key ends with the given suffix. + + Parameters + ---------- + suffix : str + The suffix to match against threshold keys. + + Returns + ------- + return_value : float or None + The matching threshold value, or None if no match is found. + """ + return_value = None + for descriptor, value in self.processing_thresholds.items(): + if descriptor.endswith(suffix): + return_value = float(value) + break + + return return_value + @dataclass class AncillaryExclusions: @@ -231,13 +311,15 @@ class AncillaryParameters: """ GLOWS L1B Ancillary Parameters for decoding ancillary histogram data points. - This class reads from a JSON file input which defines ancillary parameters. - It validates to ensure the input file has all the required parameters. + This class reads from either a dict (JSON input) or an xarray Dataset (from + GlowsAncillaryCombiner) which defines ancillary parameters. It validates to + ensure the input has all the required parameters. Parameters ---------- input_table : dict - Dictionary generated from input JSON file. + Dictionary generated from input JSON file, or xarray Dataset from + GlowsAncillaryCombiner containing conversion table data. Attributes ---------- @@ -258,14 +340,28 @@ class AncillaryParameters: "p01", "p02", "p03", "p04"] """ - def __init__(self, input_table: dict): + def __init__(self, input_table: dict) -> None: """ Generate ancillary parameters from the given input. Validates parameters and will throw a KeyError if input data is incorrect. + + Parameters + ---------- + input_table : dict + Dictionary containing conversion parameters. """ - full_keys = ["min", "max", "n_bits", "p01", "p02", "p03", "p04"] - spin_keys = ["min", "max", "n_bits"] + full_keys = [ + "min", + "max", + "n_bits", + "p01", + "p02", + "p03", + "p04", + "physical_unit", + ] + spin_keys = ["min", "max", "n_bits", "physical_unit"] try: self.version = input_table["version"] @@ -425,6 +521,8 @@ class DirectEventL1B: Flag for pulse test in progress, ends up in flags array memory_error_detected: InitVar[np.double] Flag for memory error detected, ends up in flags array + ancillary_parameters: InitVar[AncillaryParameters] + The ancillary parameters for decoding DE data flags: ndarray array of flags for extra information, per histogram. This is assembled from L1A variables. @@ -433,6 +531,8 @@ class DirectEventL1B: float. From direct_events. direct_event_pulse_lengths: ndarray array of pulse lengths [ΞΌs] for direct events. From direct_events + pkts_file_name + Name of the input CCSDS packets file """ direct_events: InitVar[np.ndarray] @@ -460,6 +560,7 @@ class DirectEventL1B: hv_test_in_progress: InitVar[np.double] pulse_test_in_progress: InitVar[np.double] memory_error_detected: InitVar[np.double] + ancillary_parameters: InitVar[AncillaryParameters] # The following variables are created from the InitVar data de_flags: np.ndarray | None = field(init=False, default=None) # TODO: First two values of DE are sec/subsec @@ -483,6 +584,7 @@ def __post_init__( hv_test_in_progress: np.double, pulse_test_in_progress: np.double, memory_error_detected: np.double, + ancillary_parameters: AncillaryParameters, ) -> None: """ Generate the L1B data for direct events using the inputs from InitVar. @@ -515,6 +617,8 @@ def __post_init__( Flag indicating if a pulse test is in progress. memory_error_detected : np.double Flag indicating if a memory error is detected. + ancillary_parameters : AncillaryParameters + The ancillary parameters for decoding DE data. """ self.direct_event_glows_times, self.direct_event_pulse_lengths = ( self.process_direct_events(direct_events) @@ -530,22 +634,14 @@ def __post_init__( int(self.glows_time_last_pps), glows_ssclk_last_pps ).to_seconds() - with open( - Path(__file__).parents[1] / "ancillary" / "l1b_conversion_table_v001.json" - ) as f: - self.ancillary_parameters = AncillaryParameters(json.loads(f.read())) - - self.filter_temperature = self.ancillary_parameters.decode( + # Use passed-in ancillary parameters instead of loading from file + self.filter_temperature = ancillary_parameters.decode( "filter_temperature", self.filter_temperature ) - self.hv_voltage = self.ancillary_parameters.decode( - "hv_voltage", self.hv_voltage - ) - self.spin_period = self.ancillary_parameters.decode( - "spin_period", self.spin_period - ) + self.hv_voltage = ancillary_parameters.decode("hv_voltage", self.hv_voltage) + self.spin_period = ancillary_parameters.decode("spin_period", self.spin_period) - self.spin_phase_at_next_pps = self.ancillary_parameters.decode( + self.spin_phase_at_next_pps = ancillary_parameters.decode( "spin_phase", self.spin_phase_at_next_pps ) @@ -607,7 +703,6 @@ class HistogramL1B: ---------- histogram array of block-accumulated count numbers - flight_software_version: str seq_count_in_pkts_file: int first_spin_id: int The start ID @@ -679,9 +774,7 @@ class HistogramL1B: """ histogram: np.ndarray - flight_software_version: str seq_count_in_pkts_file: int - # ancillary_data_files: np.ndarray TODO Add this first_spin_id: int last_spin_id: int flags_set_onboard: int # TODO: this should be renamed in L1B @@ -705,9 +798,7 @@ class HistogramL1B: imap_time_offset: np.double # No conversion needed from l1a->l1b glows_start_time: np.double # No conversion needed from l1a->l1b glows_time_offset: np.double # No conversion needed from l1a->l1b - # unique_block_identifier: str = field( - # init=False - # ) # Could be datetime TODO: Can't put a string in data + unique_block_identifier: str = field(init=False) imap_spin_angle_bin_cntr: np.ndarray = field(init=False) # Same size as bins histogram_flag_array: np.ndarray = field(init=False) # These two are retrieved from spin data @@ -724,10 +815,9 @@ class HistogramL1B: flags: np.ndarray = field(init=False) ancillary_exclusions: InitVar[AncillaryExclusions] ancillary_parameters: InitVar[AncillaryParameters] + pipeline_settings: InitVar[PipelineSettings] # TODO: # - Determine a good way to output flags as "human readable" - # - Add spice pieces - # - also unique identifiers # - Bad angle algorithm using SPICE locations # - Move ancillary file to AWS @@ -739,6 +829,7 @@ def __post_init__( pulse_length_variance: np.double, ancillary_exclusions: AncillaryExclusions, ancillary_parameters: AncillaryParameters, + pipeline_settings: PipelineSettings, ) -> None: """ Will process data. @@ -759,14 +850,18 @@ def __post_init__( Ancillary exclusions data for bad-angle flag processing. ancillary_parameters : AncillaryParameters Ancillary parameters for decoding histogram data. + pipeline_settings : PipelineSettings + Pipeline settings for processing thresholds and flags. """ # self.histogram_flag_array = np.zeros((2,)) day = met_to_datetime64(self.imap_start_time) # Add SPICE related variables - self.update_spice_parameters() - # Will require some additional inputs - self.imap_spin_angle_bin_cntr = np.zeros((3600,)) + self.update_spice_parameters(pipeline_settings.spin_offset_correction) + # Calculate the spin angle bin center using actual histogram length from L1A + n_bins = len(self.histogram) + phi = (np.arange(n_bins, dtype=np.float64) + 0.5) / n_bins + self.imap_spin_angle_bin_cntr = phi * 360.0 # TODO: This should probably be an AWS file # TODO Pass in AncillaryParameters object instead of reading here. @@ -800,21 +895,29 @@ def __post_init__( # get the data for the correct day day_exclusions = ancillary_exclusions.limit_by_day(day) + # Generate ISO datetime string using SPICE functions + datetime64_time = met_to_datetime64(self.imap_start_time) + self.unique_block_identifier = np.datetime_as_string(datetime64_time, "s") # Initialize histogram flag array: [is_close_to_uv_source, # is_inside_excluded_region, is_excluded_by_instr_team, # is_suspected_transient] x 3600 bins self.histogram_flag_array = self._compute_histogram_flag_array(day_exclusions) - # self.unique_block_identifier = np.datetime_as_string( - # np.datetime64(int(self.imap_start_time), "ns"), "s" - # ) - self.flags = np.ones((FLAG_LENGTH,), dtype=np.uint8) + self.flags = self.compute_flags(pipeline_settings) + + def update_spice_parameters(self, spin_offset_correction: float = 0.0) -> None: + """ + Update SPICE parameters based on the current state. - def update_spice_parameters(self) -> None: - """Update SPICE parameters based on the current state.""" + Parameters + ---------- + spin_offset_correction : float + Constant spin angle offset [degrees] from pipeline settings, added + to position_angle_offset_average to correct a systematic bias in + observed star positions. Default: 0.0. + """ data_start_met = self.imap_start_time - # use of imap_start_time and glows_time_offset is correct. data_end_met = np.double(self.imap_start_time) + np.double( - self.glows_time_offset + self.imap_time_offset ) data_start_time_et = sct_to_et(met_to_sclkticks(data_start_met)) data_end_time_et = sct_to_et(met_to_sclkticks(data_end_met)) @@ -841,28 +944,33 @@ def update_spice_parameters(self) -> None: ), degrees=True, ) - self.position_angle_offset_average = np.double(angle_offset) + self.position_angle_offset_average = np.double(angle_offset) + np.double( + spin_offset_correction + ) self.position_angle_offset_std_dev = np.double( 0.0 ) # Set to zero per algorithm document # Calculate spin axis orientation - spin_axis_all_times = geometry.cartesian_to_latitudinal( + spin_axis_all_times = geometry.cartesian_to_spherical( geometry.frame_transform( time_range, np.array([0, 0, 1]), - SpiceFrame.IMAP_DPS, + SpiceFrame.IMAP_SPACECRAFT, SpiceFrame.ECLIPJ2000, - ) + ), ) # Calculate circular statistics for longitude (wraps around) - lon_mean = circmean(spin_axis_all_times[..., 1], low=-np.pi, high=np.pi) - lon_std = circstd(spin_axis_all_times[..., 1], low=-np.pi, high=np.pi) + # Convert to radians for use with circular statistics methods + spin_axis_all_times = np.radians(spin_axis_all_times) + lon_mean = circmean(spin_axis_all_times[..., 1], low=0, high=2 * np.pi) + lon_std = circstd(spin_axis_all_times[..., 1], low=0, high=2 * np.pi) lat_mean = circmean(spin_axis_all_times[..., 2], low=-np.pi, high=np.pi) lat_std = circstd(spin_axis_all_times[..., 2], low=-np.pi, high=np.pi) - self.spin_axis_orientation_average = np.array([lon_mean, lat_mean]) - self.spin_axis_orientation_std_dev = np.array([lon_std, lat_std]) + # Convert circular statistics to degrees and store + self.spin_axis_orientation_average = np.degrees(np.array([lon_mean, lat_mean])) + self.spin_axis_orientation_std_dev = np.degrees(np.array([lon_std, lat_std])) # Calculate spacecraft location and velocity # ------------------------------------------ @@ -873,7 +981,7 @@ def update_spice_parameters(self) -> None: ) position = imap_state[:, :3] velocity = imap_state[:, 3:] - # averange and standard deviation over time (rows) + # average and standard deviation over time (rows) self.spacecraft_location_average = np.average(position, axis=0) self.spacecraft_location_std_dev = np.std(position, axis=0) self.spacecraft_velocity_average = np.average(velocity, axis=0) @@ -916,6 +1024,225 @@ def deserialize_flags(raw: int) -> np.ndarray[int]: return flags + def compute_flags(self, pipeline_settings: PipelineSettings) -> np.ndarray: + """ + Compute the 17 bad-time flags for this histogram. + + Parameters + ---------- + pipeline_settings : PipelineSettings + Pipeline settings containing processing thresholds. + + Returns + ------- + flags : numpy.ndarray + Array of shape (FLAG_LENGTH,) with dtype uint8. 1 = good, 0 = bad. + """ + # Section 12.3.1 of the Algorithm Document: onboard generated bad-time flags. + # Flags are "stored in a 16-bit integer field. + onboard_flags: np.ndarray = ( + 1 - self.deserialize_flags(int(self.flags_set_onboard)) + ).astype(np.uint8) + + # Section 12.3.2 of the Algorithm Document: ground processing flags: flag 1. + # Informs if the histogram was generated on-board or on the ground. + # Flag 1 = onboard. + is_generated_on_ground = np.uint8(1 - int(self.is_generated_on_ground)) + + # Section 12.3.2 of the Algorithm Document: ground processing flags: flag 2. + # Checks if total count in a given histogram is far from the daily average. + # Placeholder until daily histogram is available in glows_l1b.py. + # TODO: this equation needs to be clarified. + is_beyond_daily_statistical_error = np.uint8(1) + + # Section 12.3.2 of the Algorithm Document: ground processing flags: flag 3-7. + # (1=good, 0=bad). + temp_threshold = pipeline_settings.get_threshold( + "std_dev_threshold__celsius_deg" + ) + hv_threshold = pipeline_settings.get_threshold("std_dev_threshold__volt") + spin_std_threshold = pipeline_settings.get_threshold("std_dev_threshold__sec") + pulse_threshold = pipeline_settings.get_threshold("std_dev_threshold__usec") + + is_temp_ok = np.uint8(self.filter_temperature_std_dev <= temp_threshold) + is_hv_ok = np.uint8(self.hv_voltage_std_dev <= hv_threshold) + is_spin_std_ok = np.uint8(self.spin_period_std_dev <= spin_std_threshold) + is_pulse_ok = np.uint8(self.pulse_length_std_dev <= pulse_threshold) + + # TODO: listed as TBC in Algorithm Document. + # Placeholder for now. + is_beyond_background_error = np.uint8(1) + + ground_flags = np.array( + [ + is_generated_on_ground, + is_beyond_daily_statistical_error, + is_temp_ok, + is_hv_ok, + is_spin_std_ok, + is_pulse_ok, + is_beyond_background_error, + ], + dtype=np.uint8, + ) + + return np.concatenate([onboard_flags, ground_flags]) + + @staticmethod + def calculate_look_vectors_dps( + imap_spin_angle_bin_cntr: np.ndarray, position_angle_offset_average: np.double + ) -> np.ndarray: + """ + Calculate the look direction vectors in DPS frame for a histogramming block. + + Parameters + ---------- + imap_spin_angle_bin_cntr : numpy.ndarray + Array of shape (3600) representing the centers of the spin angle bins. + position_angle_offset_average : float + Effective offset angle defined in section 10.6 of the algorithm document, + i.e. Angle from GLOWS instrument to spin angle 0 in DPS frame. + + Returns + ------- + look_vecs_dps : numpy.ndarray + Array of shape (nbin, 3) representing the look directions in DPS frame + for each of the bins. + """ + azimuth = ( + imap_spin_angle_bin_cntr - position_angle_offset_average + 360.0 + ) % 360.0 + + # Instrument pointing direction in the DPS frame. + az_el = get_instrument_mounting_az_el(SpiceFrame.IMAP_GLOWS) + elevation = az_el[1] + + spherical = np.stack( + [np.ones_like(azimuth), azimuth, np.full_like(azimuth, elevation)], + axis=-1, + ) # (nbin, 3) + + # Convert to unit cartesian vectors. + look_vecs_dps = spherical_to_cartesian(spherical) # (nbin, 3) + + return look_vecs_dps + + def flag_uv_and_excluded(self, exclusions: AncillaryExclusions) -> tuple: + """ + Create boolean mask where True means bin is within radius of UV source. + + Parameters + ---------- + exclusions : AncillaryExclusions + Ancillary exclusions data filtered for the current day. + + Returns + ------- + close_to_uv_source : np.ndarray + Boolean mask for uv source. + inside_excluded_region : np.ndarray + Boolean mask for inside excluded region. + """ + data_start_time_et = sct_to_et(met_to_sclkticks(self.imap_start_time)) + + # Calculate unit cartesian vectors in DPS. + look_vecs_dps = self.calculate_look_vectors_dps( + self.imap_spin_angle_bin_cntr, self.position_angle_offset_average + ) + + # Transform unit cartesian vectors to ECLIPJ2000 frame. + look_vecs_ecl = frame_transform( + data_start_time_et, + look_vecs_dps, + SpiceFrame.IMAP_DPS, + SpiceFrame.ECLIPJ2000, + # This is for cases in which a histogram falls in a 2-min ck gap. + # DPS CK coverage intentionally doesn't include the + # repointing transition period. + allow_spice_noframeconnect=True, + ) + + # UV source vectors. + uv_longitude = exclusions.uv_sources[ + "ecliptic_longitude_deg" + ].values # (n_src,) + uv_latitude = exclusions.uv_sources["ecliptic_latitude_deg"].values # (n_src,) + uv_radius = np.deg2rad( + exclusions.uv_sources["angular_radius_for_masking"].values + ) + + uv_spherical = np.stack( + [np.ones_like(uv_longitude), uv_longitude, uv_latitude], + axis=-1, + ) # (n_src, 3): (r, azimuth, elevation) in degrees + + uv_vecs = spherical_to_cartesian(uv_spherical) # (n_src, 3) + + # Dot product of unit vectors gives cos(separation_angle) for each + # histogram bin vs. each UV source -> shape (nbin, n_src). + # (nbin, 3) @ (3, n_src) -> (nbin, n_src) + # If dot product -> 1 the two vectors point in almost + # the same direction and needs mask. + # If dot product -> 0 the two directions are perpendicular on the sky. + uv_cos_sep = look_vecs_ecl @ uv_vecs.T # (nbin, n_src) + # Determine if the pixel is too close to any of the source radii. + close_to_uv_source = np.any( + uv_cos_sep >= np.cos(uv_radius)[None, :], axis=1 + ) # (nbin,) + + # Excluded region pixel centers. + region_longitude = exclusions.excluded_regions[ + "ecliptic_longitude_deg" + ].values # (n_region,) + region_latitude = exclusions.excluded_regions[ + "ecliptic_latitude_deg" + ].values # (n_region,) + + region_spherical = np.stack( + [np.ones_like(region_longitude), region_longitude, region_latitude], + axis=-1, + ) # (n_region, 3) + + region_vecs = spherical_to_cartesian(region_spherical) # (n_region, 3) + + # (nbin, 3) @ (3, n_region) -> (nbin, n_region) + region_cos_sep = look_vecs_ecl @ region_vecs.T + + # Flag any bin whose pointing direction falls within half a bin width + # (0.1Β° / 2 = 0.05Β°) of an excluded sky direction. + half_bin_rad = np.deg2rad(0.1 / 2) + + inside_excluded_region = np.any( + region_cos_sep >= np.cos(half_bin_rad), axis=1 + ) # (nbin,) + + return close_to_uv_source, inside_excluded_region + + def flag_from_mask_dataset(self, mask_dataset: xr.Dataset) -> np.ndarray: + """ + Look up the per-bin boolean mask for this histogram block. + + Parameters + ---------- + mask_dataset : xr.Dataset + Dataset with ``l1b_unique_block_identifier`` and + ``histogram_mask_array`` variables indexed by ``time_block``. + + Returns + ------- + mask : np.ndarray + Boolean array of shape (n_bins,). True where the bin is flagged. + """ + identifiers = mask_dataset["l1b_unique_block_identifier"].values + match = np.where(identifiers == self.unique_block_identifier)[0] + if not match.size: + return np.zeros(len(self.histogram), dtype=bool) + mask_str = mask_dataset["histogram_mask_array"].values[match[0]] + + # Parse the "0"/"1" character string into a boolean array + mask = np.array(list(mask_str)) == "1" + return mask + def _compute_histogram_flag_array( self, exclusions: AncillaryExclusions ) -> np.ndarray: @@ -938,5 +1265,40 @@ def _compute_histogram_flag_array( np.ndarray Array of shape (4, 3600) with bad-angle flags for each bin. """ - # TODO: fill out once spice data is available - return np.zeros((4, 3600), dtype=np.uint8) + histogram_flags: np.ndarray = np.full( + (4, len(self.histogram)), + GLOWSL1bFlags.NONE.value, + dtype=np.uint8, + ) + + close_to_uv_source, inside_excluded_region = self.flag_uv_and_excluded( + exclusions + ) + + # close if within radius of any UV source + histogram_flags[0][close_to_uv_source] |= ( + GLOWSL1bFlags.IS_CLOSE_TO_UV_SOURCE.value + ) + + # inside if within half bin width of any excluded region center + histogram_flags[1][inside_excluded_region] |= ( + GLOWSL1bFlags.IS_INSIDE_EXCLUDED_REGION.value + ) + + # bins excluded by the instrument team for the matching histogram block + excluded_by_instr = self.flag_from_mask_dataset( + exclusions.exclusions_by_instr_team + ) + histogram_flags[2][excluded_by_instr] |= ( + GLOWSL1bFlags.IS_EXCLUDED_BY_INSTR_TEAM.value + ) + + # bins flagged as suspected transients for the matching histogram block + suspected_transient = self.flag_from_mask_dataset( + exclusions.suspected_transients + ) + histogram_flags[3][suspected_transient] |= ( + GLOWSL1bFlags.IS_SUSPECTED_TRANSIENT.value + ) + + return histogram_flags diff --git a/imap_processing/glows/l2/glows_l2.py b/imap_processing/glows/l2/glows_l2.py index e0a330cfa7..e6f08e0e9b 100644 --- a/imap_processing/glows/l2/glows_l2.py +++ b/imap_processing/glows/l2/glows_l2.py @@ -1,142 +1,81 @@ """Module for GLOWS Level 2 processing.""" import dataclasses +import logging import numpy as np import xarray as xr -from numpy.typing import NDArray from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes from imap_processing.glows import FLAG_LENGTH -from imap_processing.glows.l1b.glows_l1b_data import HistogramL1B -from imap_processing.glows.l2.glows_l2_data import DailyLightcurve, HistogramL2 - - -def glows_l2(input_dataset: xr.Dataset) -> list[xr.Dataset]: +from imap_processing.glows.l1b.glows_l1b_data import ( + PipelineSettings, +) +from imap_processing.glows.l2.glows_l2_data import HistogramL2 +from imap_processing.glows.utils.constants import GlowsConstants +from imap_processing.spice.time import ( + et_to_datetime64, + met_to_utc, + ttj2000ns_to_et, + ttj2000ns_to_met, +) + +logger = logging.getLogger(__name__) + + +def glows_l2( + input_dataset: xr.Dataset, + pipeline_settings_dataset: xr.Dataset, + calibration_dataset: xr.Dataset, +) -> list[xr.Dataset]: """ - Will process GLoWS L2 data from L1 data. + Will process GLOWS L2 data from L1 data. Parameters ---------- input_dataset : xarray.Dataset Input L1B dataset. + pipeline_settings_dataset : xarray.Dataset + Dataset containing pipeline settings from + GlowsAncillaryCombiner. + calibration_dataset : xarray.Dataset + Dataset containing calibration data from + GlowsAncillaryCombiner. Returns ------- - xarray.Dataset - Glows L2 Dataset. + list[xarray.Dataset] + Glows L2 Dataset. """ cdf_attrs = ImapCdfAttributes() cdf_attrs.add_instrument_global_attrs("glows") cdf_attrs.add_instrument_variable_attrs("glows", "l2") - l2 = generate_l2(input_dataset) - - return [create_l2_dataset(l2, cdf_attrs)] - - -# TODO: filter good times out -def generate_l2(l1b_dataset: xr.Dataset) -> HistogramL2: - """ - Generate L2 data from L1B data. - - Returns L2 data in the form of a HistogramL2 dataclass. - - Parameters - ---------- - l1b_dataset : xarray.Dataset - Input L1B dataset. - - Returns - ------- - HistogramL2 - L2 data in the form of a HistogramL2 dataclass. - """ - # most of the values from L1B are averaged over a day - good_data = l1b_dataset.isel( - epoch=return_good_times(l1b_dataset["flags"], np.ones((FLAG_LENGTH,))) + # Select pipeline settings for the day matching + # the first epoch in the L1B data. Convert from + # TT J2000 nanoseconds to datetime64 for indexing. + day = et_to_datetime64(ttj2000ns_to_et(input_dataset["epoch"].data[0])) + pipeline_settings = PipelineSettings( + pipeline_settings_dataset.sel(epoch=day, method="nearest") ) - # todo: bad angle filter - # TODO filter bad bins out. Needs to happen here while everything is still - # per-timestamp. - - # one dataset collects multiple epoch values which need to be averaged down into - # one value. - all_variables = dataclasses.fields(HistogramL1B) - - daily_lightcurve = DailyLightcurve(good_data) - - var_outputs = { - "total_l1b_inputs": len(good_data["epoch"]), - "number_of_good_l1b_inputs": len(good_data["epoch"]), - # TODO replace post-filter - "identifier": 100, # TODO: retrieve from spin table - # TODO fill this in - "bad_time_flag_occurrences": np.zeros((1, FLAG_LENGTH)), - # Accumulate all the histograms from good times from the day into one - "daily_lightcurve": daily_lightcurve, - } - - if len(good_data["epoch"]) != 0: - # Generate outputs that are passed in directly from L1B - var_outputs["start_time"] = good_data["epoch"].data[0] - var_outputs["end_time"] = good_data["epoch"].data[-1] + l2 = HistogramL2(input_dataset, pipeline_settings, calibration_dataset) + if l2.number_of_good_l1b_inputs == 0: + logger.warning("No good data found in L1B dataset. Returning empty list.") + return [] + elif ( + np.all(l2.daily_lightcurve.photon_flux == 0) + and np.all(l2.daily_lightcurve.flux_uncertainties == 0) + and np.all(l2.daily_lightcurve.exposure_times == 0) + ): + logger.warning("All flux and exposure times are zero. Returning empty list.") + return [] else: - # No good times in the file - var_outputs["start_time"] = l1b_dataset["imap_start_time"].data[0] - var_outputs["end_time"] = ( - l1b_dataset["imap_start_time"].data[0] - + l1b_dataset["imap_time_offset"].data[0] - ) - - for field in all_variables: - var_name = field.name - if "average" in var_name: - # This results in a scalar value, so `keepdims=True` ensures we keep the - # epoch dimension. - var_outputs[var_name] = ( - l1b_dataset[var_name].mean(dim="epoch", keepdims=True).data - ) - - var_outputs[var_name.replace("average", "std_dev")] = ( - l1b_dataset[var_name].std(dim="epoch", keepdims=True).data - ) - - # l1b stuff is done - output = HistogramL2(**var_outputs) - - return output - - -def filter_bad_bins(histograms: NDArray, bin_exclusions: NDArray) -> NDArray: - """ - Filter out bad bins from the histogram. - - Parameters - ---------- - histograms : numpy.ndarray - Histogram data, with shape (n_timestamps, n_bins). - bin_exclusions : numpy.ndarray - Array of bin exclusions. This 2d array has a timestamp and bin filter array - pair. The bin filter array indicates "1" if a bin is to be excluded. - - Returns - ------- - numpy.ndarray - Histogram data with bad bins marked with -1. - """ - # TODO: will need ancillary file imap_glows_exclusions_by_instr_team - # TODO: complete once unique_block_identifier is implemented - # file contains timestamp & bin filter array pairs. For the timestamp, the - # filter should be applied such that 1 excludes the bin. - - # excluded bins can be marked with -1 - return histograms + return [create_l2_dataset(l2, cdf_attrs, input_dataset.attrs)] def create_l2_dataset( - histogram_l2: HistogramL2, attrs: ImapCdfAttributes + histogram_l2: HistogramL2, attrs: ImapCdfAttributes, input_attrs: dict ) -> xr.Dataset: """ Create a xarray dataset from a HistogramL2 dataclass. @@ -149,17 +88,18 @@ def create_l2_dataset( L2 data. attrs : ImapCdfAttributes CDF attributes for GLOWS L2. + input_attrs : dict + Global attributes from the input L1B dataset to propagate. Returns ------- xarray.Dataset L2 dataset for output to CDF file. """ - # Each L2 file only has one timestamp. - # TODO: If we want this to point to the start time, we need to set the attribute - # variable BIN_LOCATION to 0. Otherwise, we need this to be halfway between start - # time and end time. - time_data = np.array([histogram_l2.start_time], dtype=np.float64) + # Each L2 file only has one timestamp: the midpoint between start and end time. + time_data = np.array( + [(histogram_l2.start_time + histogram_l2.end_time) / 2], dtype=np.float64 + ) # TODO: Create CDF attributes epoch_time = xr.DataArray( time_data, @@ -169,7 +109,7 @@ def create_l2_dataset( ) bins = xr.DataArray( - np.arange(histogram_l2.daily_lightcurve.number_of_bins, dtype=np.uint32), + np.arange(GlowsConstants.STANDARD_BIN_COUNT, dtype=np.uint32), name="bins", dims=["bins"], attrs=attrs.get_variable_attributes("bins_dim", check_schema=False), @@ -211,6 +151,11 @@ def create_l2_dataset( attrs=attrs.get_global_attributes("imap_glows_l2_hist"), ) + output.attrs["flight_software_version"] = input_attrs.get( + "flight_software_version", "" + ) + output.attrs["pkts_file_name"] = input_attrs.get("pkts_file_name", []) + ecliptic_variables = [ "spacecraft_location_average", "spacecraft_location_std_dev", @@ -223,6 +168,8 @@ def create_l2_dataset( "spin_axis_orientation_std_dev", ] + utc_time_variables = ["start_time", "end_time"] + for key, value in dataclasses.asdict(histogram_l2).items(): if key in ecliptic_variables: output[key] = xr.DataArray( @@ -242,7 +189,12 @@ def create_l2_dataset( dims=["epoch", "flags"], attrs=attrs.get_variable_attributes(key), ) - + elif key in utc_time_variables: + # Convert time to UTC + utc_string = [met_to_utc(ttj2000ns_to_met(value))] + output[key] = xr.DataArray( + utc_string, dims=["epoch"], attrs=attrs.get_variable_attributes(key) + ) elif key != "daily_lightcurve": val = value if type(value) is not np.ndarray: @@ -253,47 +205,27 @@ def create_l2_dataset( attrs=attrs.get_variable_attributes(key), ) + n_bins = histogram_l2.daily_lightcurve.number_of_bins for key, value in dataclasses.asdict(histogram_l2.daily_lightcurve).items(): if key == "number_of_bins": - # number_of_bins does not have n_bins dimensions. + # number_of_bins does not have a bins dimension. output[key] = xr.DataArray( np.array([value]), dims=["epoch"], attrs=attrs.get_variable_attributes(key), ) else: + # Bin arrays are chopped to number_of_bins in DailyLightcurve to + # avoid operating on FILLVAL data. Re-expand to STANDARD_BIN_COUNT + # here, filling unused bins with the variable's CDF FILLVAL. + var_attrs = attrs.get_variable_attributes(key) + fillval = var_attrs["FILLVAL"] + padded = np.full(GlowsConstants.STANDARD_BIN_COUNT, fillval) + padded[:n_bins] = value output[key] = xr.DataArray( - np.array([value]), + np.array([padded]), dims=["epoch", "bins"], - attrs=attrs.get_variable_attributes(key), + attrs=var_attrs, ) return output - - -def return_good_times(flags: xr.DataArray, active_flags: NDArray) -> NDArray: - """ - Return the good times based on the input flags. - - Parameters - ---------- - flags : xarray.DataArray - Flags dataset with shape (n_timestamps, n_flags). If a flag is active and set - to 1, the timestamp is considered good. - - active_flags : numpy.ndarray - Array of active flags. If the flag is set to 1, it is considered active. - - Returns - ------- - numpy.ndarray - An array of indices for good times. - """ - if len(active_flags) != flags.shape[1]: - print("Active flags don't matched expected length") - - # A good time is where all the active flags are equal to one. - # Here, we mask the active indices using active_flags, and then return the times - # where all the active indices == 1. - good_times = np.where(np.all(flags[:, active_flags == 1] == 1, axis=1))[0] - return good_times diff --git a/imap_processing/glows/l2/glows_l2_data.py b/imap_processing/glows/l2/glows_l2_data.py index c55f6b7e33..f08eff6cca 100644 --- a/imap_processing/glows/l2/glows_l2_data.py +++ b/imap_processing/glows/l2/glows_l2_data.py @@ -5,6 +5,23 @@ import numpy as np import xarray as xr from numpy.typing import NDArray +from scipy.stats import circmean, circstd + +from imap_processing.glows import FLAG_LENGTH +from imap_processing.glows.l1b.glows_l1b_data import PipelineSettings +from imap_processing.glows.utils.constants import GlowsConstants +from imap_processing.quality_flags import GLOWSL1bFlags +from imap_processing.spice.geometry import ( + SpiceFrame, + frame_transform_az_el, + get_instrument_mounting_az_el, +) +from imap_processing.spice.time import ( + et_to_datetime64, + met_to_sclkticks, + sct_to_et, + ttj2000ns_to_et, +) @dataclass @@ -36,6 +53,8 @@ class DailyLightcurve: number of bins in lightcurve l1b_data : xarray.Dataset L1B data filtered by good times, good angles, and good bins. + calibration_factor : float | None + Rayleigh calibration factor used for flux calculations. """ # All variables should have n_bin elements @@ -44,15 +63,20 @@ class DailyLightcurve: raw_histograms: np.ndarray = field(init=False) exposure_times: np.ndarray = field(init=False) flux_uncertainties: np.ndarray = field(init=False) - # TODO: flag array histogram_flag_array: np.ndarray = field(init=False) - # TODO: ecliptic coordinates ecliptic_lon: np.ndarray = field(init=False) ecliptic_lat: np.ndarray = field(init=False) number_of_bins: int = field(init=False) l1b_data: InitVar[xr.Dataset] + position_angle: InitVar[float] + calibration_factor: InitVar[float | None] - def __post_init__(self, l1b_data: xr.Dataset) -> None: + def __post_init__( + self, + l1b_data: xr.Dataset, + position_angle: float, + calibration_factor: float | None, + ) -> None: """ Compute all the daily lightcurve variables from L1B data. @@ -61,78 +85,172 @@ def __post_init__(self, l1b_data: xr.Dataset) -> None: l1b_data : xarray.Dataset L1B data filtered by good times, good angles, and good bins for one observation day. + position_angle : float + The offset angle of the GLOWS instrument from the north spin point - this + is used in spin angle calculations. + calibration_factor : float + Calibration factor used for flux calculations, in units of counts per second + per Rayleigh. This is used to convert from raw histograms and exposure times + to physical photon flux units. """ - self.raw_histograms = self.calculate_histogram_sums(l1b_data["histogram"].data) + # number_of_bins_per_histogram is the count of valid (non-FILLVAL) bins. + # Histogram arrays from L1B are always GlowsConstants.STANDARD_BIN_COUNT + # (3600) long, with unused bins filled with GlowsConstants.HISTOGRAM_FILLVAL. + # All bin-dimensioned arrays here are chopped to number_of_bins so that + # computations only operate on valid data. glows_l2.py is responsible for + # re-expanding these arrays back to STANDARD_BIN_COUNT, filling unused bins + # with the appropriate CDF FILLVAL before writing to output. - exposure_times_per_timestamp = ( - l1b_data["spin_period_average"] - * l1b_data["number_of_spins_per_block"] - / 3600 + self.number_of_bins = ( + l1b_data["number_of_bins_per_histogram"].data[0] + if len(l1b_data["number_of_bins_per_histogram"].data) != 0 + else 0 ) - self.exposure_times = self.calculate_exposure_times( - l1b_data, exposure_times_per_timestamp + self.raw_histograms = self.calculate_histogram_sums(l1b_data["histogram"].data)[ + : self.number_of_bins + ] + + exposure_per_epoch = ( + l1b_data["spin_period_average"].data + * l1b_data["number_of_spins_per_block"].data + / self.number_of_bins ) + + # Exposure is uniform across bins; sum over all good-time epochs + self.exposure_times = np.full(self.number_of_bins, np.sum(exposure_per_epoch)) + raw_uncertainties = np.sqrt(self.raw_histograms) - self.photon_flux = np.zeros(len(self.raw_histograms)) - self.flux_uncertainties = np.zeros(len(self.raw_histograms)) + self.photon_flux = np.zeros(self.number_of_bins) + self.flux_uncertainties = np.zeros(self.number_of_bins) - # TODO: Only where exposure counts != 0 - if len(self.exposure_times) != 0: - self.photon_flux = self.raw_histograms / self.exposure_times - self.flux_uncertainties = raw_uncertainties / self.exposure_times + if ( + self.number_of_bins > 0 + and self.exposure_times[0] > 0 + and calibration_factor + ): + self.photon_flux = ( + self.raw_histograms / self.exposure_times + ) / calibration_factor + self.flux_uncertainties = ( + raw_uncertainties / self.exposure_times + ) / calibration_factor - # TODO: Average this, or should they all be the same? - self.spin_angle = np.average(l1b_data["imap_spin_angle_bin_cntr"].data, axis=0) + self.spin_angle = np.zeros(0) - # TODO: is the first number here ok? Would it change mid-obs day? - self.number_of_bins = len(self.spin_angle) + # Apply 'OR' operation to histogram_flag_array across all + # good-time L1B blocks per bin. + # Per Section 12.3.4: a flag is True in L2 if it is True in any L1B block. + # flags shape: (n_epochs, 4, n_bins) + flags = l1b_data["histogram_flag_array"].data + if flags.size > 0: + # Flatten epochs and flag rows into one axis: (n_epochs * 4, n_bins) + flags_2d = flags.reshape(-1, self.number_of_bins) + # Apply binary 'OR' operation across all rows per bin: (n_bins,) + self.histogram_flag_array = np.bitwise_or.reduce(flags_2d, axis=0).astype( + np.uint8 + ) + else: + self.histogram_flag_array = np.zeros(self.number_of_bins, dtype=np.uint8) - self.histogram_flag_array = np.zeros(self.number_of_bins) - self.ecliptic_lon = np.zeros(self.number_of_bins) - self.ecliptic_lat = np.zeros(self.number_of_bins) + if self.number_of_bins: + # imap_spin_angle_bin_cntr is the raw IMAP spin angle ψ (0 - 360Β°, + # bin midpoints). + spin_angle_bin_cntr = l1b_data["imap_spin_angle_bin_cntr"].data[0][ + : self.number_of_bins + ] + # Convert ψ β†’ ψPA (Eq. 29): position angle measured from the + # northernmost point of the scanning circle. + self.spin_angle = (spin_angle_bin_cntr - position_angle + 360.0) % 360.0 + + # Roll all bin arrays so bin 0 corresponds to the northernmost + # point (minimum ψPA). + roll = -np.argmin(self.spin_angle) + self.spin_angle = np.roll(self.spin_angle, roll) + self.raw_histograms = np.roll(self.raw_histograms, roll) + self.photon_flux = np.roll(self.photon_flux, roll) + self.exposure_times = np.roll(self.exposure_times, roll) + self.flux_uncertainties = np.roll(self.flux_uncertainties, roll) + self.histogram_flag_array = np.roll(self.histogram_flag_array, roll) + + # Get the midpoint start time covered by repointing kernels + # needed to compute ecliptic coordinates + mid_idx = len(l1b_data["imap_start_time"]) // 2 + pointing_midpoint_time_et = sct_to_et( + met_to_sclkticks(l1b_data["imap_start_time"][mid_idx].data) + ) + self.ecliptic_lon, self.ecliptic_lat = ( + self.compute_ecliptic_coords_of_bin_centers( + pointing_midpoint_time_et, self.spin_angle + ) + ) @staticmethod - def calculate_exposure_times( - good_times: xr.Dataset, exposure_count: xr.DataArray - ) -> NDArray: + def calculate_histogram_sums(histograms: NDArray) -> NDArray: """ - Calculate exposure times for each bin across all the timestamps. + Calculate the sum of histograms across all timestamps. Parameters ---------- - good_times : xarray.Dataset - Dataset with only good times. - exposure_count : float - Exposure count for each valid timestamp and bin. + histograms : numpy.ndarray + Array of histograms across all timestamps. Returns ------- numpy.ndarray - Array of summed exposure times for each bin. + Sum of valid histograms across all timestamps. """ - weighted_sum = (good_times["histogram"].data != -1) * exposure_count.data[ - :, np.newaxis - ] - return np.sum(weighted_sum, axis=0) + histograms = histograms.copy() + # Zero out areas where HISTOGRAM_FILLVAL (i.e. unused bins) + histograms[histograms == GlowsConstants.HISTOGRAM_FILLVAL] = 0 + return np.sum(histograms, axis=0, dtype=np.int64) @staticmethod - def calculate_histogram_sums(histograms: NDArray) -> NDArray: + def compute_ecliptic_coords_of_bin_centers( + data_time_et: float, spin_angle_bin_centers: NDArray + ) -> tuple[np.ndarray, np.ndarray]: """ - Calculate the sum of histograms across all timestamps. + Compute the ecliptic coordinates of the histogram bin centers. + + This method transforms the instrument pointing direction for each bin + center from the IMAP Pointing frame (IMAP_DPS) to the ECLIPJ2000 frame. Parameters ---------- - histograms : numpy.ndarray - Array of histograms across all timestamps. + data_time_et : float + Ephemeris time corresponding to the midpoint of the histogram accumulation. + + spin_angle_bin_centers : numpy.ndarray + Spin angle bin centers for the histogram bins, measured in the IMAP frame, + with shape (n_bins,), and already corrected for the northernmost point of + the scanning circle. Returns ------- - numpy.ndarray - Sum of valid histograms across all timestamps. + tuple[numpy.ndarray, numpy.ndarray] + Longitude and latitudes in the ECLIPJ2000 frame representing the pointing + direction of each histogram bin center, with shape (n_bins,). """ - histograms[histograms == -1] = 0 - return np.sum(histograms, axis=0, dtype=np.int64) + # In the IMAP frame, the azimuth corresponds to the spin angle bin centers + azimuth = spin_angle_bin_centers + + # Get elevation from instrument pointing direction in the DPS frame. + az_el_instrument_mounting = get_instrument_mounting_az_el(SpiceFrame.IMAP_GLOWS) + elevation = az_el_instrument_mounting[1] + + # Create array of azimuth, elevation coordinates in the DPS frame (n_bins, 2) + az_el = np.stack((azimuth, np.full_like(azimuth, elevation)), axis=-1) + + # Transform coordinates to ECLIPJ2000 frame using SPICE transformations. + ecliptic_coords = frame_transform_az_el( + data_time_et, + az_el, + SpiceFrame.IMAP_DPS, + SpiceFrame.ECLIPJ2000, + ) + + # Return ecliptic longitudes and latitudes as separate arrays. + return ecliptic_coords[:, 0], ecliptic_coords[:, 1] @dataclass @@ -142,6 +260,15 @@ class HistogramL2: This class collects multiple HistogramL1B classes into one L2 per observational day. + Parameters + ---------- + l1b_dataset : xr.Dataset + GLOWS histogram L1B dataset, as produced by glows_l1b.py. + pipeline_settings : PipelineSettings + Pipeline settings object read from ancillary file. + calibration_dataset : xr.Dataset + The cps-to-Rayleigh calibration dataset needed for flux calculations. + Attributes ---------- number_of_good_l1b_inputs : int @@ -200,7 +327,7 @@ class HistogramL2: number_of_good_l1b_inputs: int total_l1b_inputs: int - identifier: int # TODO: Should be the official pointing number + identifier: int start_time: np.double end_time: np.double daily_lightcurve: DailyLightcurve @@ -214,8 +341,8 @@ class HistogramL2: pulse_length_std_dev: np.ndarray[np.double] spin_period_ground_average: np.ndarray[np.double] spin_period_ground_std_dev: np.ndarray[np.double] - position_angle_offset_average: np.ndarray[np.double] - position_angle_offset_std_dev: np.ndarray[np.double] + position_angle_offset_average: np.double + position_angle_offset_std_dev: np.double spin_axis_orientation_std_dev: np.ndarray[np.double] spacecraft_location_average: np.ndarray[np.double] spacecraft_location_std_dev: np.ndarray[np.double] @@ -223,3 +350,389 @@ class HistogramL2: spacecraft_velocity_std_dev: np.ndarray[np.double] spin_axis_orientation_average: np.ndarray[np.double] bad_time_flag_occurrences: np.ndarray + + def __init__( + self, + l1b_dataset: xr.Dataset, + pipeline_settings: PipelineSettings, + calibration_dataset: xr.Dataset, + ) -> None: + """ + Given an L1B dataset, process data into an output HistogramL2 object. + + Parameters + ---------- + l1b_dataset : xr.Dataset + GLOWS histogram L1B dataset, as produced by glows_l1b.py. + pipeline_settings : PipelineSettings + Pipeline settings object read from ancillary file. + calibration_dataset : xr.Dataset + cps-to-Rayleigh calibration dataset used for flux calculations. + coords: start_time_utc, data_vars: cps_per_r + """ + active_flags = np.array(pipeline_settings.active_bad_time_flags, dtype=float) + + # Apply sunrise/sunset offsets to extend the night region around + # is_night transitions before selecting good blocks. + flags = self.apply_is_night_offsets( + l1b_dataset["flags"].data, + is_night_idx=GlowsConstants.IS_NIGHT_FLAG_IDX, + sunrise_offset=int(pipeline_settings.sunrise_offset), + sunset_offset=int(pipeline_settings.sunset_offset), + ) + flags_da = xr.DataArray(flags, dims=l1b_dataset["flags"].dims) + + # Select the good blocks (i.e. epoch values) according to the flags. Drop any + # bad blocks before processing. + good_data = l1b_dataset.isel( + epoch=self.return_good_times(flags_da, active_flags) + ) + # Exclude histograms where all bins have is_excluded_by_instr_team set. + # Per cbk implementation: GLOWS team marks such histograms as entirely bad; + # they are dropped here and do not contribute to the L2 histogram_flag_array. + excl_flag_val = GLOWSL1bFlags.IS_EXCLUDED_BY_INSTR_TEAM.value + excl_row = good_data["histogram_flag_array"].data[:, 2, :] # (n_epochs, n_bins) + not_all_excl = ~np.all(excl_row == excl_flag_val, axis=1) + good_data = good_data.isel(epoch=np.where(not_all_excl)[0]) + + # TODO: bad angle filter + # TODO: filter bad bins out. Needs to happen here while everything is still + # per-timestamp. + + self.total_l1b_inputs = len(l1b_dataset["epoch"]) + self.number_of_good_l1b_inputs = len(good_data["epoch"]) + repointing = l1b_dataset.attrs.get("Repointing") + self.identifier = int(repointing.replace("repoint", "")) + # TODO fill this in + self.bad_time_flag_occurrences = np.zeros((1, FLAG_LENGTH), dtype=np.uint16) + + if len(good_data["epoch"]) != 0: + # Generate outputs that are passed in directly from L1B + self.start_time = good_data["epoch"].data[0] + self.end_time = good_data["epoch"].data[-1] + else: + # No good times in the file + self.start_time = l1b_dataset["imap_start_time"].data[0] + self.end_time = ( + l1b_dataset["imap_start_time"].data[0] + + l1b_dataset["imap_time_offset"].data[0] + ) + + self.filter_temperature_average = ( + good_data["filter_temperature_average"] + .mean(dim="epoch", keepdims=True) + .data + ) + self.filter_temperature_std_dev = ( + good_data["filter_temperature_average"].std(dim="epoch", keepdims=True).data + ) + self.hv_voltage_average = ( + good_data["hv_voltage_average"].mean(dim="epoch", keepdims=True).data + ) + self.hv_voltage_std_dev = ( + good_data["hv_voltage_average"].std(dim="epoch", keepdims=True).data + ) + self.spin_period_average = ( + good_data["spin_period_average"].mean(dim="epoch", keepdims=True).data + ) + self.spin_period_std_dev = ( + good_data["spin_period_average"].std(dim="epoch", keepdims=True).data + ) + self.pulse_length_average = ( + good_data["pulse_length_average"].mean(dim="epoch", keepdims=True).data + ) + self.pulse_length_std_dev = ( + good_data["pulse_length_average"].std(dim="epoch", keepdims=True).data + ) + self.spin_period_ground_average = ( + good_data["spin_period_ground_average"] + .mean(dim="epoch", keepdims=True) + .data + ) + self.spin_period_ground_std_dev = ( + good_data["spin_period_ground_average"].std(dim="epoch", keepdims=True).data + ) + + position_angle = self.compute_position_angle( + pipeline_settings.spin_offset_correction + ) + self.position_angle_offset_average: np.double = np.double(position_angle) + + # Always zero - per algorithm doc 10.6 + self.position_angle_offset_std_dev = np.double(0.0) + self.spacecraft_location_average = ( + good_data["spacecraft_location_average"] + .mean(dim="epoch") + .data[np.newaxis, :] + ) + self.spacecraft_location_std_dev = ( + good_data["spacecraft_location_average"] + .std(dim="epoch") + .data[np.newaxis, :] + ) + self.spacecraft_velocity_average = ( + good_data["spacecraft_velocity_average"] + .mean(dim="epoch") + .data[np.newaxis, :] + ) + self.spacecraft_velocity_std_dev = ( + good_data["spacecraft_velocity_average"] + .std(dim="epoch") + .data[np.newaxis, :] + ) + spin_axis_data = good_data[ + "spin_axis_orientation_average" + ].data # (n_epochs, 2) + if spin_axis_data.shape[0] > 0: + # Use circular statistics for longitude since it will be near the 0->360 + # boundary. Latitude will never be near the pole, so standard mean and + # std functions are appropriate + lon_avg = circmean(np.radians(spin_axis_data[:, 0]), low=0, high=2 * np.pi) + lon_std = circstd(np.radians(spin_axis_data[:, 0]), low=0, high=360) + lat_avg = float(np.mean(spin_axis_data[:, 1])) + lat_std = float(np.std(spin_axis_data[:, 1])) + else: + lon_avg = lon_std = lat_avg = lat_std = np.nan + self.spin_axis_orientation_average = np.array([[np.degrees(lon_avg), lat_avg]]) + self.spin_axis_orientation_std_dev = np.array([[np.degrees(lon_std), lat_std]]) + + # Select calibration factor corresponding to the mid-epoch in the L1B data. + if len(good_data["epoch"].data) != 0: + calibration_factor = self.get_calibration_factor( + good_data["epoch"].data, calibration_dataset + ) + else: + calibration_factor = None # No good data available. Still proceed + + self.daily_lightcurve = DailyLightcurve( + good_data, position_angle, calibration_factor + ) + + def filter_bad_bins(self, histograms: NDArray, bin_exclusions: NDArray) -> NDArray: + """ + Filter out bad bins from the histogram. + + Parameters + ---------- + histograms : numpy.ndarray + Histogram data, with shape (n_timestamps, n_bins). + bin_exclusions : numpy.ndarray + Array of bin exclusions. This 2d array has a timestamp and bin filter array + pair. The bin filter array indicates "1" if a bin is to be excluded. + + Returns + ------- + numpy.ndarray + Histogram data with bad bins marked with -1. + """ + # TODO: will need ancillary file imap_glows_exclusions_by_instr_team + # TODO: complete once unique_block_identifier is implemented + # file contains timestamp & bin filter array pairs. For the timestamp, the + # filter should be applied such that 1 excludes the bin. + + # excluded bins can be marked with -1 + return histograms + + @staticmethod + def return_good_times(flags: xr.DataArray, active_flags: NDArray) -> NDArray: + """ + Return the good times based on the input flags. + + Parameters + ---------- + flags : xarray.DataArray + Flags dataset with shape (n_timestamps, n_flags). If a flag is active and + set to 1, the timestamp is considered good. + + active_flags : numpy.ndarray + Array of active flags. If the flag is set to 1, it is considered active. + + Returns + ------- + numpy.ndarray + An array of indices for good times. + """ + if len(active_flags) != flags.shape[1]: + print("Active flags don't match expected length") + + # A good time is where all the active flags are equal to one. + # Here, we mask the active indices using active_flags, and then return the times + # where all the active indices == 1. + good_times = np.where(np.all(flags[:, active_flags == 1] == 1, axis=1))[0] + return good_times + + @staticmethod + def apply_is_night_offsets( + flags: np.ndarray, + is_night_idx: int, + sunrise_offset: int, + sunset_offset: int, + ) -> np.ndarray: + """ + Apply sunrise/sunset offsets to is_night transitions. + + Per algorithm doc v4.4.7, Sec. 3.9.1, item 2 (raw is_night: 1=night, 0=day): + + sunset_offset applies at both transitions: + >0: night shortens by N at each end (first N night epochs at sunset become + day; last N night epochs before sunrise become day) + <0: night extends by |N| at each end + + sunrise_offset is an additional adjustment at sunrise (is_night 1->0) only: + >0: night extends N histograms past the raw sunrise transition + <0: night shortens by |N| before the raw sunrise transition + + In the processed flags array: 0 = bad (night), 1 = good (day). + + Parameters + ---------- + flags : numpy.ndarray + Flags array with shape (n_epochs, FLAG_LENGTH), 0=bad, 1=good. + is_night_idx : int + Column index of the is_night flag in the flags array. + sunrise_offset : int + Additional histogram shift at the sunrise (is_night 1->0) transition. + sunset_offset : int + Histogram shift applied at both the sunset and sunrise transitions. + + Returns + ------- + numpy.ndarray + Returns the original flags array if no offsets are applied, + otherwise returns a modified copy. + + Notes + ----- + Algorithm doc v4.4.7, Sec. 3.9.1, item 2 + is_night: 1 = daytime (good), 0 = night (bad) + """ + # If sunrise_offset=0 and sunset_offset=0 then no corrections are needed + # relative to is_night transition set onboard. + if sunrise_offset == 0 and sunset_offset == 0: + return flags + + flags_with_offsets = flags.copy() + + is_night_col = flags[:, is_night_idx] + n = flags.shape[0] + diff = np.diff(is_night_col.astype(int)) + sunset_index = np.where(diff == -1)[0] + sunrise_index = np.where(diff == 1)[0] + + if sunrise_offset > 0: + # Night (flag = 0) extends by sunrise_offset relative + # to is_night 0 -> 1 transition. + for i in sunrise_index: + flags_with_offsets[ + i + 1 : min(n, i + 1 + sunrise_offset), is_night_idx + ] = 0 + + elif sunrise_offset < 0: + # Night (flag = 0) shortens by sunrise_offset relative + # to is_night 0 -> 1 transition. + for i in sunrise_index: + flags_with_offsets[ + max(0, i + 1 + sunrise_offset) : i + 1, is_night_idx + ] = 1 + + if sunset_offset > 0: + # Night (flag = 0) shortens by sunset_offset relative + # to is_night 1 -> 0 transition. + for i in sunset_index: + flags_with_offsets[ + i + 1 : min(n, i + 1 + sunset_offset), is_night_idx + ] = 1 + + elif sunset_offset < 0: + # Night (flag = 0) extends by sunset_offset relative + # to is_night 1 -> 0 transition. + for i in sunset_index: + flags_with_offsets[ + max(0, i + 1 + sunset_offset) : i + 1, is_night_idx + ] = 0 + + return flags_with_offsets + + def compute_position_angle(self, spin_offset_correction: float = 0.0) -> float: + """ + Compute the position angle based on the instrument mounting. + + This number is not expected to change significantly. It is the same for all L1B + blocks (epoch values). + + Parameters + ---------- + spin_offset_correction : float + Constant spin angle offset [degrees] from pipeline settings, applied + to correct a systematic bias in observed star positions. Default: 0.0. + + Returns + ------- + float + The GLOWS mounting position angle, including spin offset correction. + """ + # Calculation described in algorithm doc 10.6 (Eq. 30): + # psi_G_eff = 360 - psi_GLOWS + # where psi_GLOWS is the azimuth of the GLOWS boresight in the + # IMAP spacecraft frame, measured from the spacecraft x-axis. + # This angle does not change with time, as it is in the spinning IMAP frame. + # It basically defines the angle between x=0 in the IMAP frame and x=0 in the + # GLOWS instrument frame, and is defined by the physical mounting location of + # the instrument. + # delta_psi_G_eff is assumed to be 0 per instrument team decision (aka this + # doesn't move from the SPICE determined mounting angle. + glows_mounting_azimuth, _ = get_instrument_mounting_az_el(SpiceFrame.IMAP_GLOWS) + return (360.0 - glows_mounting_azimuth + spin_offset_correction) % 360.0 + + @staticmethod + def get_calibration_factor( + epoch_values: np.ndarray, calibration_dataset: xr.Dataset + ) -> float: + """ + Select calibration factor for an observational day. + + The calibration factor is needed to compute flux in Rayleigh units. + There is a strong assumption that the calibration is constant for + a given observational day. + + Parameters + ---------- + epoch_values : np.ndarray + Array of epoch values from the L1B dataset, in TT J2000 nanoseconds. + calibration_dataset : xr.Dataset + Dataset containing calibration data with the following structure: + Coords: epoch (datetime64[s]) + Dims: epoch, cps_per_r_dim_0, start_time_utc_dim_0 + Data vars: "cps_per_r" and "start_time_utc" are 2D (epoch, *_dim_0) + + Note: epoch and start_time_utc do not necessarily match in size or + values + - epoch contains timestamps in the calibration data up to a defined + day buffer and start_time_utc are the timestamps for all the + calibration data entries. + - epoch is used for selecting the time block, and start_time_utc is + used for selecting the calibration value within that block. + + Returns + ------- + float + The calibration factor needed to compute flux in Rayleigh units. + """ + # Use the midpoint epoch for the observation day + mid_idx = len(epoch_values) // 2 + mid_epoch_utc = et_to_datetime64(ttj2000ns_to_et(epoch_values[mid_idx].item())) + + # Select calibration data before or equal to mid_epoch_utc using "pad" to find + # the nearest preceding entry in the calibration dataset's epoch + # coordinate which is in UTC datetime64 format. + cal_at_epoch = calibration_dataset.sel(epoch=mid_epoch_utc, method="pad") + + # start_time_utc is a data variable with its own index dimension. + # Use searchsorted to find the last entry whose start_time_utc <= mid_epoch_utc. + start_times = np.array( + cal_at_epoch["start_time_utc"].values, dtype="datetime64[ns]" + ) + nearest_idx = np.searchsorted(start_times, mid_epoch_utc, side="right") - 1 + + # Select the calibration value at the nearest index. + return float(cal_at_epoch["cps_per_r"].isel(cps_per_r_dim_0=nearest_idx)) diff --git a/imap_processing/glows/packet_definitions/GLX_COMBINED.xml b/imap_processing/glows/packet_definitions/GLX_COMBINED.xml index ebca7a4e48..e86bc8e229 100644 --- a/imap_processing/glows/packet_definitions/GLX_COMBINED.xml +++ b/imap_processing/glows/packet_definitions/GLX_COMBINED.xml @@ -35,10 +35,14 @@ P_GLX_TMSCDE.xml and P_GLX_TMSHIST.xml to process both packet APIDs --> - + - 28800 + + + + + @@ -172,9 +176,9 @@ P_GLX_TMSCDE.xml and P_GLX_TMSHIST.xml to process both packet APIDs --> Number of events Number of event in all bins (sum) of this histogram. - + Histogram Counts - Total histogram data counts. Each bin has 8 bits of data, with 3600 total bins. + Total histogram data counts. Each bin has 8 bits of data. Number of bins is dynamically determined from packet length. diff --git a/imap_processing/glows/utils/constants.py b/imap_processing/glows/utils/constants.py index 357535ace7..08714e3637 100644 --- a/imap_processing/glows/utils/constants.py +++ b/imap_processing/glows/utils/constants.py @@ -61,10 +61,19 @@ class GlowsConstants: IMAP clock) SCAN_CIRCLE_ANGULAR_RADIUS: float angular radius of IMAP/GLOWS scanning circle [deg] + HISTOGRAM_FILLVAL: int + Fill value for histogram bins (65535 for uint16) + STANDARD_BIN_COUNT: int + Standard number of bins per histogram (3600) + IS_NIGHT_FLAG_IDX: int + Index of the is_night flag in the bad-time flags array (0-indexed) """ SUBSECOND_LIMIT: int = 2_000_000 SCAN_CIRCLE_ANGULAR_RADIUS: float = 75.0 + HISTOGRAM_FILLVAL: int = 65535 + STANDARD_BIN_COUNT: int = 3600 + IS_NIGHT_FLAG_IDX: int = 6 @dataclass diff --git a/imap_processing/hi/hi_goodtimes.py b/imap_processing/hi/hi_goodtimes.py new file mode 100644 index 0000000000..2d17d554a5 --- /dev/null +++ b/imap_processing/hi/hi_goodtimes.py @@ -0,0 +1,2359 @@ +"""IMAP-HI Goodtimes processing module.""" + +import logging +from enum import IntEnum +from pathlib import Path + +import numpy as np +import pandas as pd +import xarray as xr +from scipy.ndimage import convolve1d + +from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes +from imap_processing.hi.utils import ( + CalibrationProductConfig, + CoincidenceBitmap, + HiConstants, + compute_qualified_event_mask, + parse_sensor_number, +) +from imap_processing.quality_flags import ImapHiL1bDeFlags +from imap_processing.spice.repoint import get_repoint_data +from imap_processing.spice.time import met_to_ttj2000ns + +logger = logging.getLogger(__name__) + +# Structured dtype for good time intervals +INTERVAL_DTYPE: np.dtype = np.dtype( + [ + ("met_start", np.float64), + ("met_end", np.float64), + ("spin_bin_low", np.uint8), + ("spin_bin_high", np.uint8), + ("n_bins", np.uint8), + ("esa_step_mask", np.uint16), # Bitmask for ESA steps 1-10 (bit i = step i+1) + ("cull_value", np.uint8), + ] +) + + +class CullCode(IntEnum): + """Cull reason codes for good/bad time classification (bit flags).""" + + GOOD = 0 + INCOMPLETE_SPIN = 1 << 0 # 1 + DRF = 1 << 1 # 2 + BAD_TDC_CAL = 1 << 2 # 4 + OVERFLOW = 1 << 3 # 8 + STAT_FILTER_0 = 1 << 4 # 16 + STAT_FILTER_1 = 1 << 5 # 32 + STAT_FILTER_2 = 1 << 6 # 64 + BAD_ESA_VOLTAGE = 1 << 7 # 128 + + +def hi_goodtimes( + current_repointing: str, + l1b_de_datasets: list[xr.Dataset], + l1b_hk: xr.Dataset, + l1a_diagfee: xr.Dataset, + cal_product_config_path: Path, +) -> list[xr.Dataset]: + """ + Generate goodtimes dataset for IMAP-Hi L1B processing. + + This is the top-level function that orchestrates all goodtimes culling + operations for a single pointing. It applies the following filters in order: + + 0. mark_bad_esa_voltage - Remove times with invalid ESA voltage configuration + 1. mark_incomplete_spin_sets - Remove incomplete 8-spin histogram periods + 2. mark_drf_times - Remove times during spacecraft drift restabilization + 3. mark_bad_tdc_cal - Remove times with failed TDC calibration + 4. mark_overflow_packets - Remove times when DE packets overflow + 5. mark_statistical_filter_0 - Detect drastic penetrating background changes + 6. mark_statistical_filter_1 - Detect isotropic count rate increases + 7. mark_statistical_filter_2 - Detect short-lived event pulses + + Parameters + ---------- + current_repointing : str + Repointing identifier for the current pointing (e.g., "repoint00001"). + Used to identify which dataset in l1b_de_datasets is the current one. + l1b_de_datasets : list[xr.Dataset] + L1B DE datasets for surrounding pointings. Typically includes + current plus 3 preceding and 3 following pointings (7 total). + Statistical filters 0 and 1 use all datasets; other filters use + only the current pointing. + l1b_hk : xr.Dataset + L1B housekeeping dataset containing DRF status. + l1a_diagfee : xr.Dataset + L1A DIAG_FEE dataset containing TDC calibration status. + cal_product_config_path : Path + Path to calibration product configuration CSV file. + + Returns + ------- + list[xr.Dataset] + List containing the goodtimes dataset ready for CDF writing, + or an empty list if processing cannot proceed yet. + + Notes + ----- + See IMAP-Hi Algorithm Document Sections 2.2.4 and 2.3.2 for details + on each culling algorithm. + + Processing requires that repointing + 3 has occurred (so that statistical + filters can use surrounding pointings). Due to challenges with dependency + management in the batch starter, it was decided to design the Hi goodtimes + to set the L1B DE dependencies as not required and handle the final logic for + checking L1B DE dependencies in this function. If repointing + 3 has not yet + completed, an empty list is returned. If repointing + 3 has occurred but + not all 7 DE files are available, all times are marked as bad. + """ + logger.info("Starting Hi goodtimes processing") + + # Parse the current repoint ID and check if we can process yet + current_repoint_id = int(current_repointing.replace("repoint", "")) + future_repoint_id = current_repoint_id + 3 + + # Check if the future repointing has finished by checking that the next + # repoint is in the repoint dataframe. + repoint_df = get_repoint_data() + required_repoints_complete = ( + future_repoint_id + 1 in repoint_df["repoint_id"].values + ) + + if not required_repoints_complete: + raise ValueError( + f"Goodtimes cannot yet be processed for {current_repointing}: " + f"repoint{future_repoint_id:05d} has not yet been completed " + f"according to the repoint table." + ) + + # Find the current pointing index in the datasets + current_index = _find_current_pointing_index(l1b_de_datasets, current_repointing) + current_l1b_de = l1b_de_datasets[current_index] + + # Create the goodtimes dataset from the current pointing + goodtimes_ds = create_goodtimes_dataset(current_l1b_de) + + # Check if we have the full set of 7 DE files for nominal processing + if len(l1b_de_datasets) == 7: + _apply_goodtimes_filters( + goodtimes_ds, + l1b_de_datasets, + current_index, + l1b_hk, + l1a_diagfee, + cal_product_config_path, + ) + else: + # Incomplete DE file set - mark all times as bad + logger.warning( + f"Incomplete DE file set for {current_repointing}: " + f"expected 7 files, got {len(l1b_de_datasets)}. " + "Marking all times as bad." + ) + goodtimes_ds["cull_flags"][:, :] = CullCode.INCOMPLETE_SPIN + + # Log final statistics + stats = goodtimes_ds.goodtimes.get_cull_statistics() + logger.info( + f"Final statistics: {stats['good_bins']}/{stats['total_bins']} good " + f"({stats['fraction_good'] * 100:.1f}%)" + ) + if stats["cull_code_counts"]: + logger.info(f"Cull code counts: {stats['cull_code_counts']}") + + # Finalize dataset for CDF output + logger.info("Finalizing goodtimes dataset for CDF output") + cdf_ready_ds = goodtimes_ds.goodtimes.finalize_dataset() + + logger.info("Hi goodtimes processing complete") + return [cdf_ready_ds] + + +def _find_current_pointing_index( + l1b_de_datasets: list[xr.Dataset], + current_repointing: str, +) -> int: + """ + Find the index of the current pointing in the datasets list. + + Parameters + ---------- + l1b_de_datasets : list[xr.Dataset] + L1B DE datasets. + current_repointing : str + Repointing identifier for the current pointing. + + Returns + ------- + current_index : int + Index of the current pointing in the datasets list. + + Raises + ------ + ValueError + If the current repointing is not found in the datasets. + """ + for i, ds in enumerate(l1b_de_datasets): + if ds.attrs.get("Repointing") == current_repointing: + logger.info(f"Current pointing index: {i} of {len(l1b_de_datasets)}") + return i + + raise ValueError( + f"Could not find current repointing {current_repointing} " + f"in L1B DE datasets. Available repointings: " + f"{[ds.attrs.get('Repointing') for ds in l1b_de_datasets]}" + ) + + +def _apply_goodtimes_filters( + goodtimes_ds: xr.Dataset, + l1b_de_datasets: list[xr.Dataset], + current_index: int, + l1b_hk: xr.Dataset, + l1a_diagfee: xr.Dataset, + cal_product_config_path: Path, +) -> None: + """ + Apply all goodtimes culling filters to the dataset. + + Modifies goodtimes_ds in place by applying filters 0-7. + + Parameters + ---------- + goodtimes_ds : xr.Dataset + Goodtimes dataset to modify. + l1b_de_datasets : list[xr.Dataset] + All L1B DE datasets (current + surrounding pointings). + current_index : int + Index of the current pointing in l1b_de_datasets. + l1b_hk : xr.Dataset + L1B housekeeping dataset. + l1a_diagfee : xr.Dataset + L1A DIAG_FEE dataset containing TDC calibration status. + cal_product_config_path : Path + Path to calibration product configuration CSV file. + """ + current_l1b_de = l1b_de_datasets[current_index] + + # Load calibration product config + logger.info(f"Loading cal product config: {cal_product_config_path}") + cal_product_config = CalibrationProductConfig.from_csv(cal_product_config_path) + + # Log initial statistics + stats = goodtimes_ds.goodtimes.get_cull_statistics() + logger.info(f"Initial good bins: {stats['good_bins']}/{stats['total_bins']}") + + # Pre-compute qualified event masks for each dataset + # These masks check BOTH coincidence_type AND TOF windows + for l1b_de in l1b_de_datasets: + ccsds_index = l1b_de["ccsds_index"].values + + # Handle invalid events (FILLVAL trigger_id) to avoid IndexError + # For pointings with no valid events, trigger_id will be at FILLVAL + trigger_id_fillval = l1b_de["trigger_id"].attrs.get("FILLVAL", 65535) + valid_events = l1b_de["trigger_id"].values != trigger_id_fillval + + # Initialize with -1 (won't match any config row since ESA energy steps > 0) + esa_energy_steps: np.ndarray = np.full(len(ccsds_index), -1, dtype=np.int32) + if np.any(valid_events): + esa_energy_steps[valid_events] = l1b_de["esa_energy_step"].values[ + ccsds_index[valid_events] + ] + + l1b_de["qualified_mask"] = xr.DataArray( + compute_qualified_event_mask(l1b_de, cal_product_config, esa_energy_steps), + dims=["event_met"], + ) + logger.info("Pre-computed qualified event masks for all datasets") + + # === Apply culling filters === + + # 0. Mark bad ESA voltage times + logger.info("Applying filter: mark_bad_esa_voltage") + mark_bad_esa_voltage(goodtimes_ds, current_l1b_de) + + # 1. Mark incomplete spin sets + logger.info("Applying filter: mark_incomplete_spin_sets") + mark_incomplete_spin_sets(goodtimes_ds, current_l1b_de) + + # 2. Mark DRF times (drift restabilization) + logger.info("Applying filter: mark_drf_times") + mark_drf_times(goodtimes_ds, l1b_hk) + + # 3. Mark bad TDC calibration times + logger.info("Applying filter: mark_bad_tdc_cal") + mark_bad_tdc_cal(goodtimes_ds, l1a_diagfee) + + # 4. Mark overflow packets + logger.info("Applying filter: mark_overflow_packets") + mark_overflow_packets(goodtimes_ds, current_l1b_de, cal_product_config) + + # 5. Statistical Filter 0 - drastic background changes + logger.info("Applying filter: mark_statistical_filter_0") + mark_statistical_filter_0(goodtimes_ds, l1b_de_datasets, current_index) + + # 6. Statistical Filter 1 - isotropic count rate increases + logger.info("Applying filter: mark_statistical_filter_1") + mark_statistical_filter_1( + goodtimes_ds, + l1b_de_datasets, + current_index, + ) + + # 7. Statistical Filter 2 - short-lived event pulses + logger.info("Applying filter: mark_statistical_filter_2") + mark_statistical_filter_2( + goodtimes_ds, + current_l1b_de, + ) + + +def create_goodtimes_dataset(l1b_de: xr.Dataset) -> xr.Dataset: + """ + Create goodtimes dataset from L1B Direct Event data. + + Initializes all times and spin bins as good (cull_flags=0). The goodtimes + dataset is created with one entry per unique MET timestamp found in the + L1B DE data. Culling functions (e.g., mark_incomplete_spin_sets) should be + called after creation to identify and flag bad times. + + Parameters + ---------- + l1b_de : xarray.Dataset + L1B direct event data for this pointing. Used to extract MET timestamps + for each 8-spin interval. + + Returns + ------- + xarray.Dataset + Initialized goodtimes dataset with cull_flags set to 0 (all good). + Access goodtimes methods via the .goodtimes accessor + (e.g., dataset.goodtimes.remove_times()). + """ + logger.info("Creating Goodtimes from L1B Direct Event data") + + # Extract MET times from esa_step_met + # Each MET represents one 8-spin histogram packet interval + met_all = l1b_de["esa_step_met"] + logger.debug(f"Extracted {len(met_all)} total MET entries from L1B DE data") + + # Find unique MET values and indices of first occurrences + unique_mets, first_indices = np.unique(met_all.values, return_index=True) + logger.info(f"Found {len(unique_mets)} unique MET values") + + # Extract data for unique METs (use first occurrence of each) + met = met_all.isel(epoch=first_indices) + esa_step = l1b_de["esa_step"].isel(epoch=first_indices) + + # Create coordinates + coords = { + "met": met.values, + "spin_bin": np.arange(90), + } + + # Create data variables + # Initialize cull_flags - all good (0) by default + # Shape: (n_met_timestamps, 90 spin_bins) + # Per alg doc Section 2.3.2: 90-element arrays, one per histogram packet + # Culling functions will set non-zero cull codes for bad times + data_vars = { + "cull_flags": xr.DataArray( + np.zeros((len(met), 90), dtype=np.uint8), + dims=["met", "spin_bin"], + ), + "esa_step": xr.DataArray(esa_step.values, dims=["met"]), + } + + # Create attributes + sensor_number = parse_sensor_number(l1b_de.attrs["Logical_source"]) + repointing = l1b_de.attrs.get("Repointing", "repoint-9999") + attrs = { + "Sensor": f"{sensor_number}sensor", + "Repointing": repointing, + } + + return xr.Dataset(data_vars, coords, attrs) + + +@xr.register_dataset_accessor("goodtimes") +class GoodtimesAccessor: + """ + Extend xarray.Dataset with accessor for IMAP-Hi Good Times operations. + + Provides methods to track and manage good/bad time intervals for a single + Pointing based on validation checks defined in the IMAP-Hi Algorithm + Document Section 2.2.4 and 2.3.2. + + The accessor operates on xr.Dataset objects created by create_goodtimes_dataset(). + The dataset maintains a cull_flags array initialized to all zeros (good). + As bad times are identified by validation algorithms, they are flagged via + the `remove_times()` method with a non-zero cull code. + + Cull Codes: + * 0 : Good time (default) + * 1-N : Bad time, with specific cull reason code + + Expected xarray.Dataset structure: + * Dimensions: + * met : int + Number of MET timestamps (one per 8-spin histogram packet, ~90 per pointing) + * spin_bin : int + Number of spin angle bins (90 bins covering 0-360 degrees) + * Coordinates + * met : numpy.ndarray + Mission Elapsed Time values for each 8-spin interval + * spin_bin : numpy.ndarray + Spin bin indices (0-89) + * Data Variables + * cull_flags : xarray.DataArray (met, spin_bin) + Cull flags where 0=good time, non-zero=bad time with cull reason code + * esa_step : xarray.DataArray (met,) + ESA step for each MET timestamp + * Attributes + * sensor : str + Sensor identifier ('45sensor' or '90sensor') + * pointing : int + Pointing number for this dataset + + Parameters + ---------- + xarray_obj : xarray.Dataset + The xarray Dataset to wrap with goodtimes accessor functionality. + + Examples + -------- + >>> gt_dataset = create_goodtimes_dataset(l1b_de) + >>> gt_dataset.goodtimes.mark_bad_times(met=1000.5, cull=CullCode.LOOSE) + >>> intervals = gt_dataset.goodtimes.get_good_intervals() + """ + + def __init__(self, xarray_obj: xr.Dataset) -> None: + """Initialize the accessor with an xarray Dataset.""" + self._obj = xarray_obj + + def mark_bad_times( + self, + met: np.ndarray | float | tuple[float, float], + bins: np.ndarray | int | None = None, + cull: int = 1, + ) -> None: + """ + Flag specific MET times and spin bins as bad times with a cull code. + + This method is called by external validation algorithms when bad times + are identified. It sets the cull_flags to the specified non-zero cull code + for the given MET timestamps and spin bins. + + Parameters + ---------- + met : numpy.ndarray, float, or tuple of (float, float) + MET timestamp(s) to flag as bad. Can be: + - Single float: one MET timestamp + - Tuple of (start, end): time range (inclusive) + - Array of floats: multiple MET timestamps + bins : numpy.ndarray, int, or None + Spin bin(s) to flag as bad. Can be: + - None: flag all spin bins (0-89) for the given MET(s) + - Single int: one spin bin + - Array of ints: multiple spin bins + cull : int + Cull reason code (non-zero). Different validation checks can use + different codes to identify the reason for culling: + - 1: Loose criterion + - etc. + + Notes + ----- + If a time/bin is already flagged with a different cull code, this method + will overwrite it with the new cull code. Consider implementing logic to + preserve or combine cull codes if needed. + + Examples + -------- + >>> # Flag all spin bins for MET=1000.5 as loose (cull=1) + >>> goodtimes.mark_bad_times(met=1000.5, bins=None, cull=CullCode.LOOSE) + + >>> # Flag spin bins 0-10 for MET=1000.5 + >>> goodtimes.mark_bad_times( + ... met=1000.5, bins=np.arange(11), cull=CullCode.LOOSE + ... ) + + >>> # Flag time range around a repoint (240s before/after) + >>> repoint_time = 1000.0 + >>> goodtimes.mark_bad_times( + ... met=(repoint_time - 240, repoint_time + 240), + ... cull=CullCode.LOOSE + ... ) + + >>> # Flag multiple specific METs, all bins + >>> goodtimes.mark_bad_times( + ... met=np.array([1000.5, 1001.5]), bins=None, cull=CullCode.LOOSE + ... ) + """ + if cull == 0: + raise ValueError("Cull code must be non-zero. Use 0 only for good times.") + + # Handle bins parameter + if bins is None: + # Flag all spin bins (0-89) + bins_array = np.arange(90) + else: + # Convert to array for consistent handling + bins_array = np.atleast_1d(bins) + + # Validate bin indices + if np.any((bins_array < 0) | (bins_array >= 90)): + raise ValueError("Spin bins must be in range [0, 89]") + + met_values = self._obj.coords["met"].values + + # check for met times out of range + met_array = np.atleast_1d(met) + # Add the difference between the last two MET values to the valid range + # to get the time of the last MET + 8_spins + if len(met_values) >= 2: + met_interval = np.diff(met_values[-2:])[0] + elif len(met_values) == 1: + # Only one MET value - use a default interval (120 seconds) + met_interval = 120.0 + else: + # No MET values - can't validate range + met_interval = 0.0 + + valid_met_range = (met_values[0], met_values[-1] + met_interval) + invalid_met_mask = (met_array < valid_met_range[0]) | ( + met_array > valid_met_range[-1] + ) + if np.any(invalid_met_mask): + raise ValueError( + f"MET value(s) {met_array[invalid_met_mask]} are " + f"outside valid range: {valid_met_range}" + ) + + # Handle time range input (tuple of start, end) + if isinstance(met, tuple) and len(met) == 2: + met_start, met_end = met + # Find all MET indices within the range + in_range = (met_values >= met_start) & (met_values <= met_end) + met_indices = np.nonzero(in_range)[0] + else: + # Find indices of largest MET that is <= each met_val (vectorized) + # searchsorted with side='right' gives first index where value would go + # Subtract 1 to get the largest value <= met_val + met_indices = np.searchsorted(met_values, met_array, side="right") - 1 + + # Set cull_flags for all indices using bitwise OR to combine flags + n_times = len(met_indices) + n_bins = len(bins_array) + logger.debug( + f"Flagging {n_times} MET time(s) x {n_bins} spin bin(s) with " + f"cull code {cull}" + ) + self._obj["cull_flags"].values[np.ix_(met_indices, bins_array)] |= np.uint8( + cull + ) + + def get_good_intervals(self) -> np.ndarray: + """ + Extract good time intervals grouped by ESA sweep cull patterns. + + Groups consecutive ESA sweeps with identical cull patterns. For each group: + 1. Writes one interval for fully-good ESA steps (all 90 bins good) spanning + bins 0-89, with cull_value indicating the cull code from any bad ESAs. + 2. Writes additional intervals for each good bin region of partially-good + ESA steps, with cull_value indicating the cull code that removed bad bins. + + Returns + ------- + numpy.ndarray + Structured array with dtype INTERVAL_DTYPE containing: + - met_start: First MET timestamp of interval + - met_end: Start of next interval (or last MET for final interval) + - spin_bin_low: Lowest spin bin in this contiguous region + - spin_bin_high: Highest spin bin in this contiguous region + - n_bins: Number of bins in this region + - esa_step_mask: Bitmask of good ESA steps (1-10) for this interval + - cull_value: Cull code for ESA steps/bins not included (0 if all good) + + Notes + ----- + This is used for generating the Good Times output files per algorithm + document Section 2.3.2.5. + """ + logger.debug("Extracting good time intervals") + + # Determine which dimension is present (epoch for CDF, met for in-memory) + time_dim = "epoch" if "epoch" in self._obj.dims else "met" + + # Get met values + met_values = self._obj["met"].values + if len(met_values) == 0: + logger.warning("No MET values found, returning empty intervals array") + return np.array([], dtype=INTERVAL_DTYPE) + + # Add sweep indices as a coordinate + ds = _add_sweep_indices(self._obj) + + # Compare consecutive sweeps using xarray groupby + grouped = list(ds["cull_flags"].groupby("esa_sweep")) + + # Determine pattern changes by comparing each sweep to the next + # Start with False for first sweep (no previous sweep) + pattern_changes = [False] + for i in range(len(grouped) - 1): + # The grouped list contains tuples (sweep_idx, cull_flags_ds). + # Grab just the cull_flags_ds values for comparison. + cull_curr = grouped[i][1] + cull_next = grouped[i + 1][1] + + # Compare shapes first (different lengths = different pattern) + # In a nominal Pointing, the final ESA sweep will get cut short by + # the repoint maneuver. This causes a difference in shape. + if cull_curr.shape != cull_next.shape: + pattern_changes.append(True) + else: + # Compare cull_flag values only (not coordinates) + pattern_changes.append( + not np.array_equal(cull_curr.values, cull_next.values) + ) + + # Convert to numpy array and create group IDs + pattern_changes = np.array(pattern_changes, dtype=bool) + + # Use cumsum to create group IDs + group_ids = pattern_changes.cumsum().astype(int) + + # Map group IDs to all time points using the correct dimension + group_coord = np.array([group_ids[int(s)] for s in ds["esa_sweep"].values]) + ds = ds.assign_coords(pattern_group=(time_dim, group_coord)) + + # Group by pattern_group (consecutive identical sweeps only) + intervals: list[tuple] = [] + pattern_groups = list(ds.groupby("pattern_group")) + + for i, (_, pattern_ds) in enumerate(pattern_groups): + # Get met values from the pattern dataset + pattern_met = pattern_ds["met"].values + met_start = float(pattern_met.min()) + + # met_end is start of next group, or max MET of this group if last + if i + 1 < len(pattern_groups): + next_met = pattern_groups[i + 1][1]["met"].values + met_end = float(next_met.min()) + else: + met_end = float(pattern_met.max()) + + # Get first sweep as representative (all sweeps in pattern are identical) + first_sweep_idx = pattern_ds["esa_sweep"].values[0] + first_sweep = pattern_ds.sel( + {time_dim: (pattern_ds["esa_sweep"] == first_sweep_idx)} + ) + + # Generate interval elements for this pattern + intervals.extend( + self._generate_intervals_for_pattern(first_sweep, met_start, met_end) + ) + + logger.info(f"Extracted {len(intervals)} good time intervals") + return np.array(intervals, dtype=INTERVAL_DTYPE) + + def _generate_intervals_for_pattern( + self, sweep_ds: xr.Dataset, met_start: float, met_end: float + ) -> list[tuple]: + """ + Generate interval elements for a sweep pattern. + + Parameters + ---------- + sweep_ds : xarray.Dataset + Representative sweep. + met_start : float + Start MET for this interval group. + met_end : float + End MET for this interval group. + + Returns + ------- + list[tuple] + List of interval tuples matching INTERVAL_DTYPE. + """ + all_good_mask = 0 + partial_regions = [] + bad_cull_value = 0 + + # Process each unique ESA step + for esa_step in np.unique(sweep_ds["esa_step"].values): + esa_mask = sweep_ds["esa_step"] == esa_step + cull_pattern = sweep_ds["cull_flags"].values[esa_mask.values][0] + esa_bit = 1 << (int(esa_step) - 1) + + if np.all(cull_pattern == 0): + all_good_mask |= esa_bit + else: + bad_vals = cull_pattern[cull_pattern > 0] + if len(bad_vals) > 0: + # Aggregate all non-zero cull codes for this ESA step so that + # the region cull value reflects every flag that contributed. + region_cull = int(np.bitwise_or.reduce(bad_vals)) + bad_cull_value |= region_cull + else: + region_cull = 0 + + for bin_low, bin_high in self._find_good_bin_regions(cull_pattern): + partial_regions.append( + { + "esa_bit": esa_bit, + "bin_low": bin_low, + "bin_high": bin_high, + "cull_value": region_cull, + } + ) + + # Generate interval elements + elements = [] + + if all_good_mask > 0: + elements.append( + (met_start, met_end, 0, 89, 90, all_good_mask, bad_cull_value) + ) + + for region in partial_regions: + n_bins = region["bin_high"] - region["bin_low"] + 1 + elements.append( + ( + met_start, + met_end, + region["bin_low"], + region["bin_high"], + n_bins, + region["esa_bit"], + region["cull_value"], + ) + ) + + return elements + + @staticmethod + def _find_good_bin_regions(cull_pattern: np.ndarray) -> list[tuple[int, int]]: + """ + Find contiguous regions where cull_pattern == 0. + + Parameters + ---------- + cull_pattern : np.ndarray + Array of cull values for 90 spin bins. + + Returns + ------- + list[tuple[int, int]] + List of (start_bin, end_bin) tuples for good regions. + """ + regions: list[tuple[int, int]] = [] + in_good_region = False + start_bin = 0 + + for i, val in enumerate(cull_pattern): + if val == 0 and not in_good_region: + start_bin = i + in_good_region = True + elif val != 0 and in_good_region: + regions.append((start_bin, i - 1)) + in_good_region = False + + if in_good_region: + regions.append((start_bin, 89)) + + return regions + + def get_cull_statistics(self) -> dict: + """ + Calculate statistics on cull codes for diagnostics. + + Returns + ------- + dict + Dictionary with cull code statistics: + - total_bins: Total number of MET Γ— spin_bin combinations + - good_bins: Number of bins with cull_flags=0 + - culled_bins: Number of bins with cull_flags>0 + - fraction_good: Fraction of bins that are good + - cull_code_counts: Dict mapping cull codes to counts + """ + total_bins = self._obj["cull_flags"].size + culled_bins = np.count_nonzero(self._obj["cull_flags"]) + good_bins = total_bins - culled_bins + + # Count occurrences of each cull code + unique_codes, counts = np.unique( + self._obj["cull_flags"].values[self._obj["cull_flags"].values > 0], + return_counts=True, + ) + cull_code_counts = dict( + zip(unique_codes.tolist(), counts.tolist(), strict=False) + ) + + return { + "total_bins": int(total_bins), + "good_bins": int(good_bins), + "culled_bins": int(culled_bins), + "fraction_good": good_bins / total_bins if total_bins > 0 else 0.0, + "cull_code_counts": cull_code_counts, + } + + def write_txt(self, output_path: Path) -> Path: + """ + Write time intervals to text file in the format specified by algorithm document. + + Format per Section 2.3.2.5: + pointing MET_start MET_end spin_bin_low spin_bin_high sensor + esa_steps[10] cull_value + + The esa_steps field consists of 10 binary values (0 or 1) indicating whether + each ESA step (1-10) is included in this interval. + + Parameters + ---------- + output_path : pathlib.Path + Path where the text file should be written. + + Returns + ------- + pathlib.Path + Path to the created file. + """ + logger.info(f"Writing intervals to file: {output_path}") + pointing = int(self._obj.attrs["Repointing"].replace("repoint", "")) + sensor = ( + parse_sensor_number(self._obj.attrs["Logical_source"]) + if "Logical_source" in self._obj.attrs + else self._obj.attrs["Sensor"].replace("sensor", "") + ) + + intervals = self.get_good_intervals() + + with open(output_path, "w") as f: + # Write header info + file_id = self._obj.attrs.get("Logical_file_id") + if file_id is not None: + f.write( + f"# Goodtimes txt file generated for input CDF: {file_id}" + "\n" + ) + for interval in intervals: + # Convert esa_step_mask bitmask to 10 binary values + # Bit i represents ESA step i+1, so check bits 0-9 + esa_step_mask = int(interval["esa_step_mask"]) + esa_step_flags = " ".join( + "1" if (esa_step_mask >> i) & 1 else "0" for i in range(10) + ) + + # Format: + # pointing met_start met_end spin_bin_low spin_bin_high sensor + # esa_steps[10] cull_value + line = ( + f"{pointing:05d} " + f"{interval['met_start']:0.1f} " + f"{interval['met_end']:0.1f} " + f"{interval['spin_bin_low']:2d} " + f"{interval['spin_bin_high']:2d} " + f"{sensor} " + f"{esa_step_flags} " + f"{interval['cull_value']:3d}" + ) + + # TODO: Add rate/sigma values for each ESA step + + f.write(line + "\n") + + logger.info(f"Wrote {len(intervals)} intervals to {output_path}") + return output_path + + def finalize_dataset(self) -> xr.Dataset: + """ + Finalize the goodtimes dataset for CDF output. + + Converts the dataset from using MET as the primary dimension to using + epoch (TT2000 nanoseconds), and adds all CDF attributes required for + L1B CDF file writing. + + Returns + ------- + xarray.Dataset + CDF-ready dataset with epoch dimension and all CDF attributes. + + Notes + ----- + This method should be called after all goodtimes filtering is complete, + just before writing to CDF. + + Requires SPICE kernels to be loaded for MET to epoch conversion. + """ + logger.info("Finalizing goodtimes dataset for CDF output") + + # Initialize CDF attribute manager + attr_mgr = ImapCdfAttributes() + attr_mgr.add_instrument_global_attrs("hi") + attr_mgr.add_instrument_variable_attrs("hi") + + # Convert MET coordinate to epoch coordinate (TT2000 nanoseconds) + met_values = self._obj.coords["met"].values + epoch_values = met_to_ttj2000ns(met_values) + + # Rename met dimension to epoch and assign new epoch coordinate values + ds = self._obj.rename({"met": "epoch"}) + ds = ds.assign_coords(epoch=epoch_values) + + # Move met from coordinate to data variable + ds["met"] = xr.DataArray(met_values, dims=["epoch"]) + + # Add spin_bin_label coordinate + spin_bin_label = np.array([f"{i}" for i in ds.coords["spin_bin"].values]) + ds = ds.assign_coords(spin_bin_label=("spin_bin", spin_bin_label)) + + # Add coordinate attributes + ds["epoch"].attrs = attr_mgr.get_variable_attributes( + "epoch", check_schema=False + ) + for coord_name in ds.coords: + attr_mgr_key = ( + f"hi_goodtimes_{coord_name}" if coord_name != "epoch" else "epoch" + ) + ds[coord_name].attrs = attr_mgr.get_variable_attributes( + attr_mgr_key, check_schema=False + ) + + # Add variable attributes + for var_name in ds.data_vars: + ds[var_name].attrs.update( + attr_mgr.get_variable_attributes(f"hi_goodtimes_{var_name}") + ) + + # Update global attributes + sensor_str = ds.attrs.pop("Sensor") + ds.attrs = attr_mgr.get_global_attributes("imap_hi_l1b_goodtimes_attrs") + + # Update Logical_source with sensor string + ds.attrs["Logical_source"] = ds.attrs["Logical_source"].format( + sensor=sensor_str + ) + + return ds + + +# ============================================================================== +# Culling/Filtering Functions +# Based on culling.c - Reference: IMAP-Hi Algorithm Document Sections 2.2.4, 2.3.2 +# ============================================================================== + + +def mark_bad_esa_voltage( + goodtimes_ds: xr.Dataset, + l1b_de: xr.Dataset, + cull_code: int = CullCode.BAD_ESA_VOLTAGE, +) -> None: + """ + Mark times when ESA voltages don't match expected values. + + Filters out 8-spin periods where the ESA energy step is invalid, indicating + either calibration mode (esa_energy_step=0) or an ESA voltage mismatch + (esa_energy_step=FILLVAL). The voltage validation is performed during L1B + processing by matching measured inner/outer ESA voltages against the ESA + energies lookup table. + + Algorithm Document Reference: + Section 2.3.2: Good times selection requiring valid ESA configuration + + Parameters + ---------- + goodtimes_ds : xarray.Dataset + Goodtimes dataset to update with cull flags. + l1b_de : xarray.Dataset + L1B Direct Event data containing esa_energy_step field. + cull_code : int, optional + Cull code to use for marking bad times (default: CullCode.BAD_ESA_VOLTAGE). + + Notes + ----- + This function modifies goodtimes_ds in place by calling mark_bad_times() + for MET timestamps with invalid ESA energy steps. + + Invalid ESA energy steps: + - esa_energy_step = 0: Calibration mode (ESA stepping but not science data) + - esa_energy_step = FILLVAL (255): ESA voltage mismatch - measured voltages + didn't match any known energy step in the lookup table + """ + logger.info("Running mark_bad_esa_voltage culling") + + # Get FILLVAL from attributes (should be 255 for uint8) + fillval = l1b_de["esa_energy_step"].attrs.get("FILLVAL", 255) + + esa_step_met = l1b_de["esa_step_met"].values + esa_energy_step = l1b_de["esa_energy_step"].values + + # Find packets with invalid ESA energy steps + invalid_mask = (esa_energy_step == 0) | (esa_energy_step == fillval) + + if not np.any(invalid_mask): + logger.info("No invalid ESA energy steps found") + return + + # Get unique METs of invalid packets + invalid_mets = np.unique(esa_step_met[invalid_mask]) + + # Mark all identified times as bad (all spin bins) + goodtimes_ds.goodtimes.mark_bad_times(met=invalid_mets, cull=cull_code) + + # Log statistics + n_invalid_0: int = np.sum(esa_energy_step == 0) + n_invalid_fillval: int = np.sum(esa_energy_step == fillval) + logger.info( + f"Found {n_invalid_0} packets with esa_energy_step=0 (calibration), " + f"{n_invalid_fillval} with esa_energy_step=FILLVAL (voltage mismatch). " + f"Marked {len(invalid_mets)} 8-spin period(s) as bad." + ) + + +def mark_incomplete_spin_sets( + goodtimes_ds: xr.Dataset, + l1b_de: xr.Dataset, + cull_code: int = CullCode.INCOMPLETE_SPIN, +) -> None: + """ + Filter out incomplete 8-spin histogram periods. + + Ensures data completeness by removing histogram packets that don't represent + complete 8-spin periods. Histogram packets are the fundamental time unit for + IMAP-Hi science data, and incomplete periods indicate data gaps or telemetry + issues that would compromise scientific analysis. + + Algorithm Document Reference: + Section 2.3.2: Good times selection requiring complete data coverage + + Background: + Direct Event (DE) packets contain the "last_spin_num" field indicating + which spin number (1-8) was the last spin included in that packet. The + instrument can operate in different cadences: + - Every 4th spin: last_spin_num values of 4 and 8 only + - Every 2nd spin: last_spin_num values of 2, 4, 6, 8 + - Every spin: last_spin_num values of 1-8 + + For a complete 8-spin period, we must see all the expected last_spin_num values + with no gaps. The cadence cannot change during HVSCI mode. + + Parameters + ---------- + goodtimes_ds : xarray.Dataset + Goodtimes dataset to update with cull flags. + l1b_de : xarray.Dataset + L1B Direct Event data containing DE packets with last_spin_num field + and ccsds_qf quality flag. + cull_code : int, optional + Cull code to use for marking bad times (default: CullCode.LOOSE). + + Notes + ----- + This function modifies goodtimes_ds in place by calling mark_bad_times() + for MET timestamps with incomplete spin coverage. + """ + logger.info("Running mark_incomplete_spin_sets culling") + + met_values = goodtimes_ds.coords["met"].values + + # Get DE packet MET times directly from esa_step_met + de_met = l1b_de["esa_step_met"] + + # Assign each DE packet to nearest goodtimes MET using searchsorted + # This maps each DE packet to a MET index + met_indices = np.searchsorted(met_values, de_met.values, side="right") - 1 + + # Clip to valid range + met_indices = np.clip(met_indices, 0, len(met_values) - 1) + + # Calculate actual distance to assigned MET + time_slop = 10.0 # seconds tolerance + distances = np.abs(de_met.values - met_values[met_indices]) + valid_assignment = distances <= time_slop + + # Create a new coordinate in l1b_de for grouping + l1b_de_with_group = l1b_de.assign_coords(met_group=("epoch", met_indices)) + + # Only keep packets with valid time assignment + l1b_de_valid = l1b_de_with_group.isel(epoch=valid_assignment) + + # Valid pattern bitmasks + valid_pattern_1 = 0b10001000 # bits 3,7: every 4th spin (last_spin_num 4,8) + valid_pattern_2 = 0b10101010 # bits 1,3,5,7: every 2nd spin (2,4,6,8) + valid_pattern_3 = 0b11111111 # bits 0-7: every spin (1-8) + valid_patterns = [valid_pattern_1, valid_pattern_2, valid_pattern_3] + + # Group by MET and validate each group + bad_mets = [] + + for met_idx, group in l1b_de_valid.groupby("met_group"): + met_time = met_values[met_idx] + + # Check for invalid spins flag (bit 1 in ccsds_qf) + if np.any((group["ccsds_qf"].values & ImapHiL1bDeFlags.BADSPIN) != 0): + bad_mets.append(met_time) + continue + + # Get last_spin_num values for this group + last_spin_num_values = group["last_spin_num"].values + + # Count occurrences of each last_spin_num value (1-8) + last_spin_num_counts = np.bincount( + last_spin_num_values, + minlength=9, + )[1:9] # bins 1-8, ignore 0 + + # Check if we have exactly one of each expected last_spin_num value + # has_exactly_one[i] corresponds to last_spin_num i+1 + # bit i in pattern_bits represents last_spin_num i+1 + has_exactly_one = last_spin_num_counts == 1 + pattern_bits = np.packbits(has_exactly_one, bitorder="little")[0] + + if pattern_bits not in valid_patterns: + bad_mets.append(met_time) + + # Also mark MET times with no DE packets as bad + mets_with_packets = np.unique(met_indices[valid_assignment]) + all_met_indices = np.arange(len(met_values)) + mets_without_packets = np.setdiff1d(all_met_indices, mets_with_packets) + bad_mets.extend(met_values[mets_without_packets]) + + # Remove all bad times at once + if bad_mets: + goodtimes_ds.goodtimes.mark_bad_times(met=np.array(bad_mets), cull=cull_code) + + logger.info(f"Dropped {len(bad_mets)} incomplete 8-spin period(s)") + + +def mark_drf_times( + goodtimes_ds: xr.Dataset, + hk: xr.Dataset, + cull_code: int = CullCode.DRF, +) -> None: + """ + Remove times during spacecraft drift restabilization. + + Filters out data collected during and immediately after Drift Restabilization + Flag (DRF) periods. When the spacecraft drift rate exceeds acceptable limits, + the DRF is asserted and the spacecraft performs a restabilization maneuver. + During restabilization, the spacecraft pointing is unstable, making the data + unsuitable for science. + + Algorithm Document Reference: + Section 2.2.4: Housekeeping checks for spacecraft attitude and pointing + Section 2.2.7: Bad times during spacecraft maneuvers + + Background: + The spacecraft must maintain precise pointing for Hi sensors to correctly + measure ENA arrival directions. When DRF is asserted, the spacecraft is + performing active stabilization, and pointing may be off-nominal for up to + 30 minutes after DRF deasserts. This implementation conservatively removes + all times within 30 minutes following DRF deassertion. + + Parameters + ---------- + goodtimes_ds : xarray.Dataset + Goodtimes dataset to update with cull flags. + hk : xarray.Dataset + Housekeeping data containing DRF status in fsw_thruster_warn field. + cull_code : int, optional + Cull code to use for marking bad times (default: CullCode.LOOSE). + + Notes + ----- + This function modifies goodtimes_ds in place. If no housekeeping data is + available, a warning is logged but no times are removed. + """ + logger.info("Running mark_drf_times culling") + + if len(hk.epoch) == 0: + logger.warning("No NHK loaded to check for DRF times") + return + + # Get HK times and DRF status from fsw_thruster_warn + hk_met = hk["shcoarse"] + drf_status = hk["fsw_thruster_warn"].values != 0 + + # Find transitions from DRF active (1) to inactive (0) using numpy.diff + drf_diff = np.diff(drf_status.astype(int)) + # Transition from 1->0 shows as -1 in diff + # diff[i] = status[i+1] - status[i], so add 1 to get index where it became 0 + transition_indices = np.nonzero(drf_diff == -1)[0] + 1 + # Ensure transition_indices is always iterable, even if a scalar is returned + transition_indices = np.atleast_1d(transition_indices) + + # For each DRF deactivation, remove times in 30-minute window before + for idx in transition_indices: + drf_end_time = hk_met.values[idx] + window_start = drf_end_time - 30 * 60 # 30 minutes before + + # Remove time range using tuple input + goodtimes_ds.goodtimes.mark_bad_times( + met=(window_start, drf_end_time), cull=cull_code + ) + + logger.info( + f"Dropped times during {len(transition_indices)} DRF restabilization period(s)" + ) + + +def mark_overflow_packets( + goodtimes_ds: xr.Dataset, + l1b_de: xr.Dataset, + config_df: pd.DataFrame, + cull_code: int = CullCode.OVERFLOW, +) -> None: + """ + Remove times when DE packets overflow with qualified events. + + Filters out 8-spin periods where a Direct Event packet contains the maximum + number of events (664) and the final event qualifies for a calibration product. + When a packet is full and ends with a qualified event, additional events may + have been lost, making the count data incomplete. + + Algorithm Document Reference: + Section 2.3.2.2: Good Times Exclusions due to High Count Rate + + Background: + Each DE packet can hold a maximum of 664 direct events. When a packet fills + completely, any additional events that occur are lost. If the final event + in a full packet has a coincidence type that is part of a defined calibration + product, the packet is considered to have potentially lost science-quality + events, and the entire 8-spin period should be excluded from analysis. + + Parameters + ---------- + goodtimes_ds : xarray.Dataset + Goodtimes dataset to update with cull flags. + l1b_de : xarray.Dataset + L1B Direct Event data containing: + - ccsds_index: Index mapping each event to its packet + - coincidence_type: Coincidence type bitmap for each event + - event_met: MET timestamp for each event + config_df : pandas.DataFrame + Calibration product configuration DataFrame with coincidence_type_values + column containing tuples of valid coincidence type integers for each + calibration product. Use CalibrationProductConfig.from_csv() to load. + cull_code : int, optional + Cull code to use for marking bad times (default: CullCode.LOOSE). + + Notes + ----- + This function modifies goodtimes_ds in place by calling mark_bad_times() + for MET timestamps with overflow packets containing qualified final events. + + The check for qualified events uses the coincidence_type_values from the + calibration product configuration, which defines which coincidence types + are considered valid for science analysis. + """ + logger.info("Running mark_overflow_packets culling") + + ccsds_indices = l1b_de["ccsds_index"].values + coincidence_types = l1b_de["coincidence_type"].values + event_mets = l1b_de["event_met"].values + + if len(ccsds_indices) == 0: + logger.info("No events in L1B DE data") + return + + # Maximum number of DEs per packet + max_des_per_packet = 664 + + # Count events per packet using bincount + # bincount[i] = number of events with ccsds_index == i + packet_event_counts = np.bincount(ccsds_indices) + + # Find packets that are full (have exactly 664 events) + full_packet_indices = np.nonzero(packet_event_counts == max_des_per_packet)[0] + + if len(full_packet_indices) == 0: + logger.info("No full packets found") + return + + # Use DEBUG level for per-packet logging if more than 10 full packets + log_per_packet = logger.info if len(full_packet_indices) <= 10 else logger.debug + + # Build set of all valid coincidence types from calibration products + all_valid_coin_types = set() + for coin_types in config_df["coincidence_type_values"]: + all_valid_coin_types.update(coin_types) + + # Find the last event index for each packet (vectorized) + # We need to find, for each full packet, the index of its final event. + # Since events within a packet appear consecutively in the array, the + # "last" event for packet P is the event with the largest array index + # where ccsds_indices == P. + # + # We use np.maximum.at to efficiently compute this: + # - last_event_per_packet[P] will hold the max event index for packet P + # - np.maximum.at updates last_event_per_packet[ccsds_indices[i]] with + # event_indices[i] if it's larger than the current value + # - After processing all events, last_event_per_packet[P] contains the + # index of the last event belonging to packet P + max_packet_idx = int(np.max(ccsds_indices)) + last_event_per_packet: np.ndarray = np.full(max_packet_idx + 1, -1, dtype=np.intp) + event_indices = np.arange(len(ccsds_indices)) + np.maximum.at(last_event_per_packet, ccsds_indices, event_indices) + + # Get the final event indices for full packets + final_event_indices = last_event_per_packet[full_packet_indices] + + # Get coincidence types for final events + final_coin_types = coincidence_types[final_event_indices] + + # Log each full packet + for i, packet_idx in enumerate(full_packet_indices): + log_per_packet( + f"Packet {packet_idx} is full with final event " + f"(coincidence_type={final_coin_types[i]})" + ) + + # Check which final events are qualified (in a calibration product) + qualified_mask = np.isin(final_coin_types, list(all_valid_coin_types)) + + # Get METs for qualified packets + mets_to_cull = event_mets[final_event_indices[qualified_mask]] + + # Mark all identified times as bad (all spin bins) + if len(mets_to_cull) > 0: + goodtimes_ds.goodtimes.mark_bad_times(met=mets_to_cull, cull=cull_code) + + logger.info( + f"Found {len(full_packet_indices)} full packet(s), " + f"dropped {len(mets_to_cull)} 8-spin period(s) due to overflow packets" + ) + + +def mark_bad_tdc_cal( + goodtimes_ds: xr.Dataset, + diagfee: xr.Dataset, + cull_code: int = CullCode.BAD_TDC_CAL, + check_tdc_3: bool = False, +) -> None: + """ + Remove times with failed TDC calibration (DIAG_FEE method). + + Based on C reference: drop_bad_tdc_diagfee in culling_v2.c provided by + IMAP-Hi team. + + This function scans DIAG_FEE packets chronologically and checks the TDC + calibration status for each packet. If any TDC has failed calibration, + all times from that DIAG_FEE packet until the next DIAG_FEE packet are + marked as bad. + + Parameters + ---------- + goodtimes_ds : xr.Dataset + Goodtimes dataset to update with cull flags. + diagfee : xr.Dataset + DIAG_FEE dataset containing TDC calibration status fields: + - shcoarse: Mission Elapsed Time (MET) + - tdc1_cal_ctrl_stat: TDC1 calibration status (bit 1 = success) + - tdc2_cal_ctrl_stat: TDC2 calibration status (bit 1 = success) + - tdc3_cal_ctrl_stat: TDC3 calibration status (bit 1 = success) + cull_code : int, optional + Cull code to use for marking bad times. Default is CullCode.LOOSE. + check_tdc_3 : bool, optional + Whether to check TDC3 calibration status in addition to TDC1 and TDC2. + Default is False to match original C code behavior. + + Notes + ----- + This function modifies goodtimes_ds in place. + + Quirk: Two DIAG_FEE packets are generated when entering HVSCI mode. + The first packet is skipped if two packets appear within 10 seconds. + """ + logger.info("Running mark_bad_tdc_cal culling") + + # Based on sample code in culling_v2.c, skip this check if we have fewer + # than two diag_fee packets. + if len(diagfee.epoch) < 2: + logger.warning( + f"Insufficient DIAG_FEE packets to select good times " + f"(found {len(diagfee.epoch)}, need at least 2)" + ) + return + + diagfee_met = diagfee["shcoarse"].values + goodtimes_met = goodtimes_ds.coords["met"].values + + # Identify duplicate packets: skip if followed by another within 10 seconds + time_gaps = np.diff(diagfee_met) + is_duplicate = np.concatenate([time_gaps < 10, [False]]) + + # Identify any packets where any of the three TDC calibrations failed. + # TDC failure check (bit 1: 1=good, 0=bad) + tdc_failed = ((diagfee["tdc1_cal_ctrl_stat"].values & 2) == 0) | ( + (diagfee["tdc2_cal_ctrl_stat"].values & 2) == 0 + ) + if check_tdc_3: + tdc_failed |= (diagfee["tdc3_cal_ctrl_stat"].values & 2) == 0 + + # Only loop over non-duplicate packets with TDC failures + tdc_failed_indices = np.nonzero(~is_duplicate & tdc_failed)[0] + + n_times_removed = 0 + for i in tdc_failed_indices: + # Remove times from this DIAG_FEE packet until next. We are skipping the + # first packet of a duplicate pair, so determining the window based on the + # current packet met and next packet met covers the time window between + # non-duplicate DIAG_FEE packets. We can ignore the ~10 seconds of slop + # around duplicate packets because these packets should only be produced + # when IMAP-Hi is transitioning to HVSCI mode which means that there will + # be no DE packets being produced. + df_time = diagfee_met[i] + next_df_time = diagfee_met[i + 1] if i < len(diagfee_met) - 1 else np.inf + + in_window = (goodtimes_met >= df_time) & (goodtimes_met < next_df_time) + mets_to_cull = goodtimes_met[in_window] + + if len(mets_to_cull) > 0: + goodtimes_ds.goodtimes.mark_bad_times(met=mets_to_cull, cull=cull_code) + n_times_removed += len(mets_to_cull) + + logger.info(f"Dropped {n_times_removed} time(s) due to bad TDC calibration") + + +def _get_sweep_indices(esa_step: np.ndarray) -> np.ndarray: + """ + Assign sweep indices to each MET based on ESA step transitions. + + A new sweep starts when ESA step transitions from high to low + (e.g., 9 -> 1), detected using np.diff(). + + Parameters + ---------- + esa_step : numpy.ndarray + ESA step values for each MET (epoch dimension). + + Returns + ------- + sweep_indices : numpy.ndarray + Sweep index for each MET. First sweep is index 0. + """ + if len(esa_step) == 0: + return np.array([], dtype=np.int32) + + # Find sweep boundaries where ESA step transitions from high to low + esa_diff = np.diff(esa_step.astype(np.int32)) + # Negative diff indicates high-to-low transition (e.g., 9 -> 1 = -8) + sweep_boundaries = esa_diff < 0 + + # Create sweep indices using cumsum on boundaries + # Prepend False so first MET is in sweep 0 + sweep_indices = ( + np.concatenate([[False], sweep_boundaries]).cumsum().astype(np.int32) + ) + + return sweep_indices + + +def _add_sweep_indices(l1b_de: xr.Dataset) -> xr.Dataset: + """ + Add esa_sweep coordinate to the dataset based on ESA step transitions. + + Parameters + ---------- + l1b_de : xarray.Dataset + L1B Direct Event dataset or goodtimes dataset. + + Returns + ------- + xarray.Dataset + Dataset with esa_sweep coordinate added on the time dimension + (either 'epoch' or 'met'). + """ + sweep_indices = _get_sweep_indices(l1b_de["esa_step"].values) + # Determine which dimension to use (epoch for CDF data, met for in-memory) + time_dim = "epoch" if "epoch" in l1b_de.dims else "met" + return l1b_de.assign_coords(esa_sweep=(time_dim, sweep_indices)) + + +def _compute_normalized_counts_per_sweep( + l1b_de: xr.Dataset, + tof_ab_limit_ns: int, +) -> xr.Dataset: + """ + Compute normalized AB coincidence counts per ESA sweep and reshape dataset. + + This function: + 1. Computes normalized AB coincidence counts per sweep + 2. Removes all data associated with the event_met coordinate + 3. Reshapes the dataset so esa_sweep becomes a dimension (removing epoch) + 4. Returns the updated dataset with all epoch-based variables + + Parameters + ---------- + l1b_de : xarray.Dataset + L1B Direct Event dataset with esa_sweep coordinate on epoch dimension. + tof_ab_limit_ns : int + Maximum absolute value of tof_ab in nanoseconds. + + Returns + ------- + xarray.Dataset + Reshaped dataset with esa_sweep as a dimension containing: + - normalized_count: normalized AB coincidence counts per sweep + - All other variables from the input dataset (first value per sweep) + """ + if "esa_sweep" not in l1b_de.coords: + raise ValueError("Dataset must have esa_sweep coordinate") + + # Filter to valid AB coincidences + tof_ab = l1b_de["tof_ab"] + coincidence_type = l1b_de["coincidence_type"] + ccsds_index = l1b_de["ccsds_index"] + + ab_coincidence_type = CoincidenceBitmap.detector_hit_str_to_int("AB") + is_valid_ab = (coincidence_type == ab_coincidence_type) & ( + np.abs(tof_ab) <= tof_ab_limit_ns + ) + + # Map events to sweeps via ccsds_index -> esa_sweep + event_epoch_idx = ccsds_index.values + event_sweep_idx = l1b_de["esa_sweep"].values[event_epoch_idx] + + # Count valid AB events per sweep + n_sweeps = int(l1b_de["esa_sweep"].max().values) + 1 + counts_per_sweep: np.ndarray = np.zeros(n_sweeps, dtype=np.int64) + np.add.at(counts_per_sweep, event_sweep_idx[is_valid_ab.values], 1) + + # Normalize by number of unique ESA energy steps + n_unique_esa_energy_steps = len(np.unique(l1b_de["esa_energy_step"].values)) + normalized_counts = counts_per_sweep / n_unique_esa_energy_steps + + # Remove all variables that depend on event_met dimension + ds = l1b_de.drop_dims("event_met", errors="ignore") + + # Set esa_sweep and esa_energy_step as a multi-index on epoch dimension + ds = ds.set_index(epoch=["esa_sweep", "esa_energy_step"]) + + # Drop duplicates, keeping first occurrence of each (esa_sweep, esa_energy_step) + # pair. This handles cases where multiple packets have the same esa_sweep + # and esa_energy_step. + ds = ds.drop_duplicates(dim="epoch", keep="first") + + # Unstack to make esa_sweep and esa_energy_step into separate dimensions + # This creates a 2D array with dimensions (esa_sweep, esa_energy_step) + ds_reshaped = ds.unstack("epoch") + + # Add normalized_count as a new variable + # It only has esa_sweep dimension (no esa_energy_step variation within a sweep) + ds_reshaped["normalized_count"] = xr.DataArray( + normalized_counts, + dims=["esa_sweep"], + coords={"esa_sweep": np.arange(n_sweeps)}, + ) + + return ds_reshaped + + +def mark_statistical_filter_0( + goodtimes_ds: xr.Dataset, + l1b_de_datasets: list[xr.Dataset], + current_index: int, + threshold_factor: float = HiConstants.STAT_FILTER_0_THRESHOLD_FACTOR, + tof_ab_limit_ns: int = HiConstants.STAT_FILTER_0_TOF_AB_LIMIT_NS, + cull_code: int = CullCode.STAT_FILTER_0, + min_pointings: int = HiConstants.STAT_FILTER_MIN_POINTINGS, +) -> None: + """ + Apply Statistical Filter 0 to detect drastic penetrating background changes. + + Statistical Filter 0 from Algorithm Document Section 2.3.2.3 detects when + the penetrating background rate has changed drastically, compromising + background subtraction accuracy. For each ESA sweep across all input + Pointings, it computes the normalized AB coincidence count (total count + divided by number of ESA steps). It then marks ESA sweeps in the current + Pointing where the normalized count exceeds 150% of the median. + + Parameters + ---------- + goodtimes_ds : xarray.Dataset + Goodtimes dataset for the current Pointing to update. + l1b_de_datasets : list[xarray.Dataset] + List of L1B DE datasets for surrounding Pointings. Typically includes + current plus preceding and following Pointings + (e.g., [P-3, P-2, P-1, P(current), P+1, P+2, P+3]). + current_index : int + Index of the current Pointing in l1b_de_datasets. + threshold_factor : float, optional + Multiplier for median comparison. + Default is HiConstants.STAT_FILTER_0_THRESHOLD_FACTOR. + tof_ab_limit_ns : int, optional + Maximum |tof_ab| in nanoseconds for AB coincidences. + Default is HiConstants.STAT_FILTER_0_TOF_AB_LIMIT_NS. + cull_code : int, optional + Cull code to use for marking bad times. Default is CullCode.LOOSE. + min_pointings : int, optional + Minimum number of Pointings required. + Default is HiConstants.STAT_FILTER_MIN_POINTINGS. + + Raises + ------ + ValueError + If current_index is out of range or if fewer than min_pointings + datasets are provided. + + Notes + ----- + This function modifies goodtimes_ds in place. Only ESA sweeps in the + current Pointing where the normalized count exceeds `threshold_factor * + median` are marked as bad. Other sweeps remain unaffected. + + Algorithm: + 1. For each complete ESA sweep across all Pointings, count AB coincidences + where |tof_ab| <= tof_ab_limit_ns and divide by number of ESA steps + 2. Calculate median of all normalized sweep counts + 3. For each sweep in current Pointing, mark all METs in that sweep as bad + if normalized count > threshold_factor * median + """ + logger.info("Running mark_statistical_filter_0 culling") + + # Validate current_index is in range + if current_index < 0 or current_index >= len(l1b_de_datasets): + raise ValueError( + f"current_index {current_index} out of range for list of " + f"length {len(l1b_de_datasets)}" + ) + + # Validate that we have the minimum number of datasets + if len(l1b_de_datasets) < min_pointings: + raise ValueError( + f"At least {min_pointings} valid Pointings required, " + f"got {len(l1b_de_datasets)}" + ) + + # Add esa_sweep coordinate, reshape, and compute normalized_count for each dataset + all_normalized_counts: list[np.ndarray] = [] + reshaped_datasets: dict[int, xr.Dataset] = {} + + for i, l1b_de in enumerate(l1b_de_datasets): + # Add esa_sweep coordinate + l1b_de_with_sweep = _add_sweep_indices(l1b_de) + + # Compute normalized counts and reshape dataset. This removes epoch + # dimension, adds esa_sweep dimension, and includes normalized_count. + reshaped_ds = _compute_normalized_counts_per_sweep( + l1b_de_with_sweep, tof_ab_limit_ns + ) + + # Store reshaped dataset and normalized counts + reshaped_datasets[i] = reshaped_ds + all_normalized_counts.append(reshaped_ds["normalized_count"].values) + + offset = i - current_index + logger.debug( + f"Pointing {offset:+d}: " + f"{len(reshaped_ds['normalized_count'])} complete ESA sweeps" + ) + + current_ds = reshaped_datasets[current_index] + + # Calculate median from all sweep counts + all_counts = np.concatenate(all_normalized_counts) + median_count = float(np.median(all_counts)) + threshold = median_count * threshold_factor + + logger.info( + f"Statistical Filter 0: median={median_count:.2f}, " + f"threshold={threshold:.2f} ({len(all_counts)} sweeps)" + ) + + # Find and mark bad sweeps in current dataset + bad_sweep_mask = current_ds["normalized_count"] > threshold + n_bad_sweeps = int(bad_sweep_mask.sum()) + + # Get MET time ranges for bad sweeps using xarray boolean indexing + # Select only the bad sweeps using the mask + bad_sweeps_ds = current_ds.isel(esa_sweep=bad_sweep_mask) + + # For each bad sweep, mark the time range from first to last ccsds_met + for sweep_idx in range(len(bad_sweeps_ds["esa_sweep"])): + # Get all ccsds_met values for this sweep across all esa_energy_steps + sweep_mets = bad_sweeps_ds["ccsds_met"].isel(esa_sweep=sweep_idx).values + + # Get min and max MET values, ignoring NaNs + met_start: float = float(np.nanmin(sweep_mets)) + met_end: float = float(np.nanmax(sweep_mets)) + + # Mark the entire time range for this sweep as bad + goodtimes_ds.goodtimes.mark_bad_times( + met=(met_start, met_end), bins=None, cull=cull_code + ) + + if n_bad_sweeps > 0: + logger.info( + f"Statistical Filter 0: Marked {n_bad_sweeps}/" + f"{len(current_ds['normalized_count'])} ESA sweeps as bad" + ) + else: + logger.info("No bad ESA sweeps identified by Statistical Filter 0") + + +def _compute_qualified_counts_per_sweep( + l1b_de: xr.Dataset, + qualified_mask: np.ndarray, +) -> xr.Dataset: + """ + Compute qualified calibration product counts per 8-spin interval and reshape. + + Uses the (esa_sweep, esa_energy_step) multi-index to identify unique 8-spin sets, + following the same pattern as _compute_normalized_counts_per_sweep. + + Parameters + ---------- + l1b_de : xarray.Dataset + L1B Direct Event dataset with esa_sweep coordinate on epoch dimension. + qualified_mask : np.ndarray + Boolean mask indicating which events qualify for calibration products. + This mask should check BOTH coincidence_type AND TOF windows. + + Returns + ------- + xarray.Dataset + Reshaped dataset with dimensions (esa_sweep, esa_energy_step) containing: + - qualified_count: total qualified counts per 8-spin interval + - ccsds_met: first MET for each 8-spin interval + """ + if "esa_sweep" not in l1b_de.coords: + raise ValueError("Dataset must have esa_sweep coordinate") + + # Get values needed for counting + ccsds_index = l1b_de["ccsds_index"].values + esa_sweep = l1b_de.coords["esa_sweep"].values + esa_energy_step = l1b_de["esa_energy_step"].values + + # Use pre-computed qualified mask + is_qualified = qualified_mask + + # Map qualified events to their packet's (esa_sweep, esa_energy_step) + qualified_packet_idx = ccsds_index[is_qualified] + qualified_sweep = esa_sweep[qualified_packet_idx] + qualified_energy_step = esa_energy_step[qualified_packet_idx] + + # Count qualified events per (esa_sweep, esa_energy_step) using 2D array + n_sweeps = int(esa_sweep.max()) + 1 + n_esa_energy_steps = int(esa_energy_step.max()) + 1 + counts_2d: np.ndarray = np.zeros((n_sweeps, n_esa_energy_steps), dtype=np.float64) + np.add.at(counts_2d, (qualified_sweep, qualified_energy_step), 1) + + # Remove event_met dimension and reshape using multi-index + ds = l1b_de.drop_dims("event_met", errors="ignore") + ds = ds.set_index(epoch=["esa_sweep", "esa_energy_step"]) + ds = ds.drop_duplicates(dim="epoch", keep="first") + ds_reshaped = ds.unstack("epoch") + + # Add qualified_count - aligns with (esa_sweep, esa_energy_step) coordinates + ds_reshaped["qualified_count"] = xr.DataArray( + counts_2d, + dims=["esa_sweep", "esa_energy_step"], + coords={ + "esa_sweep": np.arange(n_sweeps), + "esa_energy_step": np.arange(n_esa_energy_steps), + }, + ) + + # Set missing (sweep, energy_step) pairs to NaN so they don't affect statistics + missing_mask = ds_reshaped["ccsds_met"].isnull() + ds_reshaped["qualified_count"] = ds_reshaped["qualified_count"].where(~missing_mask) + + return ds_reshaped + + +def _build_per_sweep_datasets( + l1b_de_datasets: list[xr.Dataset], +) -> dict[int, xr.Dataset]: + """ + Build per-sweep datasets with qualified counts for each Pointing. + + Parameters + ---------- + l1b_de_datasets : list[xarray.Dataset] + List of L1B DE datasets for multiple Pointings. Each dataset must + contain a "qualified_mask" DataArray indicating which events qualify + for calibration products. + + Returns + ------- + dict[int, xarray.Dataset] + Dictionary mapping dataset index to 2D Dataset with + (esa_sweep, esa_energy_step) dims. + """ + per_sweep_datasets: dict[int, xr.Dataset] = {} + + for i, l1b_de in enumerate(l1b_de_datasets): + # Add esa_sweep coordinate and compute counts per 8-spin interval + l1b_de_with_sweep = _add_sweep_indices(l1b_de) + per_sweep = _compute_qualified_counts_per_sweep( + l1b_de_with_sweep, l1b_de["qualified_mask"].values + ) + per_sweep_datasets[i] = per_sweep + + return per_sweep_datasets + + +def _compute_median_and_sigma_per_esa( + per_sweep_datasets: dict[int, xr.Dataset], +) -> tuple[xr.DataArray, xr.DataArray]: + """ + Compute median and sigma for each ESA energy step using xarray. + + Combines all per-sweep datasets and computes the median qualified count + per ESA energy step across all sweeps and pointings. + + Parameters + ---------- + per_sweep_datasets : dict[int, xarray.Dataset] + Dictionary mapping dataset index to 2D Dataset with + (esa_sweep, esa_energy_step) dims. + + Returns + ------- + tuple[xarray.DataArray, xarray.DataArray] + Tuple of (median_per_esa, sigma_per_esa) DataArrays with esa_energy_step + coordinate. ESA energy steps with zero/nan median or esa_energy_step=0 + are set to NaN/0. + """ + if not per_sweep_datasets: + empty = xr.DataArray( + [], dims=["esa_energy_step"], coords={"esa_energy_step": []} + ) + return empty, empty.astype(int) + + # Concatenate datasets along esa_sweep dimension using xarray. This handles + # different esa_energy_step coordinates by aligning and filling with NaN. + combined = xr.concat( + [ds["qualified_count"] for ds in per_sweep_datasets.values()], + dim="esa_sweep", + ) + + # Compute median along esa_sweep dimension using xarray + median_per_esa = combined.median(dim="esa_sweep", skipna=True) + + # Compute sigma: sigma β‰ˆ √(median + 1) rounded to closest integer + sigma_per_esa = np.sqrt(median_per_esa + 1).round().astype(int) + + # Set invalid ESA energy steps (zero/nan median or esa_energy_step=0) to NaN/0 + esa_energy_step_coords = median_per_esa.coords["esa_energy_step"] + invalid_mask = ( + (esa_energy_step_coords == 0) | (median_per_esa <= 0) | median_per_esa.isnull() + ) + median_per_esa = median_per_esa.where(~invalid_mask) + sigma_per_esa = sigma_per_esa.where(~invalid_mask, 0) + + # Log warnings for invalid ESA energy steps (excluding esa_energy_step=0) + invalid_esa_energy_steps = esa_energy_step_coords.values[ + (esa_energy_step_coords != 0).values & invalid_mask.values + ] + for esa in invalid_esa_energy_steps: + logger.warning( + f"Statistical Filter 1: Median is zero/nan for ESA energy step {esa}, " + "skipping this ESA energy step" + ) + + # Log valid ESA energy steps + valid_esa_energy_steps = esa_energy_step_coords.values[~invalid_mask.values] + for esa in valid_esa_energy_steps: + logger.debug( + f"Statistical Filter 1: ESA {esa}: " + f"median={median_per_esa.sel(esa_energy_step=esa).values:.2f}, " + f"sigma={sigma_per_esa.sel(esa_energy_step=esa).values}" + ) + + return median_per_esa, sigma_per_esa + + +def _identify_cull_pattern( + current_counts: xr.DataArray, + median_per_esa: xr.DataArray, + sigma_per_esa: xr.DataArray, + consecutive_threshold_sigma: float = HiConstants.STAT_FILTER_1_CONSECUTIVE_SIGMA, + extreme_threshold_sigma: float = HiConstants.STAT_FILTER_1_EXTREME_SIGMA, + min_consecutive: int = HiConstants.STAT_FILTER_1_MIN_CONSECUTIVE, +) -> xr.DataArray: + """ + Identify 2D cull pattern for statistical filter 1 using convolution. + + Detects three patterns: + 1. Consecutive runs: 3+ consecutive sweeps exceeding threshold with ESA neighbor + confirmation (isotropic excursion pattern from C implementation) + 2. Isolated intervals: Good intervals surrounded by bad on both sides in time + 3. Extreme outliers: Any position exceeding 5-sigma threshold + + Parameters + ---------- + current_counts : xr.DataArray + 2D array of qualified counts with dims (esa_sweep, esa_energy_step). + median_per_esa : xr.DataArray + Median counts per ESA energy step. + sigma_per_esa : xr.DataArray + Sigma values per ESA energy step. + consecutive_threshold_sigma : float + Sigma multiplier for consecutive interval check. + Default is HiConstants.STAT_FILTER_1_CONSECUTIVE_SIGMA. + extreme_threshold_sigma : float + Sigma multiplier for extreme outlier check. + Default is HiConstants.STAT_FILTER_1_EXTREME_SIGMA. + min_consecutive : int + Minimum consecutive intervals above threshold. + Default is HiConstants.STAT_FILTER_1_MIN_CONSECUTIVE. + + Returns + ------- + xr.DataArray + Boolean mask with dims (esa_sweep, esa_energy_step) where + True = cull this position. + """ + # Compute thresholds using xarray broadcasting + consecutive_threshold = median_per_esa + consecutive_threshold_sigma * sigma_per_esa + extreme_threshold = median_per_esa + extreme_threshold_sigma * sigma_per_esa + + # Compute exceeds masks - handle NaN by treating as False + exceeds_consecutive = (current_counts > consecutive_threshold).fillna(False) + exceeds_extreme = (current_counts > extreme_threshold).fillna(False) + + # Get underlying numpy arrays for convolution (dims: esa_sweep x esa_energy_step) + exceeds_arr = exceeds_consecutive.values.astype(int) + + # Initialize cull mask + cull_arr = np.zeros_like(exceeds_arr, dtype=bool) + + # === Pass 1: Find consecutive runs with ESA neighbor confirmation === + # Use convolution to find runs of min_consecutive in time (axis=0 = esa_sweep) + time_kernel = np.ones(min_consecutive) + consecutive_sum = convolve1d(exceeds_arr, time_kernel, axis=0, mode="constant") + + # Dilate the consecutive detection to mark all positions in runs + # convolve1d centers the kernel, so we dilate to capture run edges + run_kernel = np.ones(min_consecutive) + run_positions = convolve1d( + (consecutive_sum >= min_consecutive).astype(int), + run_kernel, + axis=0, + mode="constant", + ) + in_consecutive_run = (run_positions >= 1) & exceeds_arr.astype(bool) + + # Check ESA neighbors at same time position using convolution along ESA axis + # Kernel [1, 0, 1] sums neighbors without counting self + # Use cval=1 so edges pass the neighbor check (matches C implementation where + # edges are treated as "not good", i.e., the check passes at boundaries) + esa_neighbor_kernel = np.array([1, 0, 1]) + esa_neighbor_exceeds = convolve1d( + exceeds_arr, esa_neighbor_kernel, axis=1, mode="constant", cval=1 + ) + has_esa_neighbor = esa_neighbor_exceeds >= 1 + + # Combine: in a consecutive run AND has ESA neighbor exceeding at same time + cull_arr |= in_consecutive_run & has_esa_neighbor + + # === Pass 2: Mark isolated good intervals (orphans) === + # Pattern: [bad, good, bad] in time dimension + # Sum neighbors in time - if both neighbors are bad (in cull_arr), sum = 2 + # Kernel [1, 0, 1] sums neighbors without counting self + neighbor_kernel = np.array([1, 0, 1]) + bad_neighbor_sum = convolve1d( + cull_arr.astype(int), neighbor_kernel, axis=0, mode="constant" + ) + # Current position is good (not in cull_arr) but both time neighbors are bad + isolated = ~cull_arr & (bad_neighbor_sum == 2) + cull_arr |= isolated + + # Log isolated intervals found + n_isolated = int(isolated.sum()) + if n_isolated > 0: + logger.debug(f"Statistical Filter 1: Found {n_isolated} isolated intervals") + + # === Pass 3: Mark extreme outliers (5-sigma) === + extreme_arr = exceeds_extreme.values + n_extreme = int((extreme_arr & ~cull_arr).sum()) + if n_extreme > 0: + logger.debug(f"Statistical Filter 1: Found {n_extreme} extreme outliers") + cull_arr |= extreme_arr + + # Convert back to xarray DataArray with same coordinates + cull_mask = xr.DataArray( + cull_arr, + dims=current_counts.dims, + coords=current_counts.coords, + ) + + return cull_mask + + +def mark_statistical_filter_1( + goodtimes_ds: xr.Dataset, + l1b_de_datasets: list[xr.Dataset], + current_index: int, + consecutive_threshold_sigma: float = HiConstants.STAT_FILTER_1_CONSECUTIVE_SIGMA, + extreme_threshold_sigma: float = HiConstants.STAT_FILTER_1_EXTREME_SIGMA, + min_consecutive_intervals: int = HiConstants.STAT_FILTER_1_MIN_CONSECUTIVE, + cull_code: int = CullCode.STAT_FILTER_1, + min_pointings: int = HiConstants.STAT_FILTER_MIN_POINTINGS, +) -> None: + """ + Apply Statistical Filter 1 to detect isotropic count rate increases. + + Statistical Filter 1 from Algorithm Document Section 2.3.2.3 detects times + when qualified calibration product counts increase fairly isotropically for + a limited time. It operates per sensor, per ESA energy step, per 8-spin + interval, summing counts over all angles. + + The filter applies three passes: + 1. Mark intervals where counts exceed median + consecutive_threshold_sigma + for at least min_consecutive_intervals AND in at least one adjacent ESA step. + 2. Remove isolated good intervals (good sandwiched between two bad). + 3. Mark remaining intervals where counts exceed median + extreme_threshold_sigma. + + Parameters + ---------- + goodtimes_ds : xarray.Dataset + Goodtimes dataset for the current Pointing to update. + l1b_de_datasets : list[xarray.Dataset] + List of L1B DE datasets for surrounding Pointings. Typically includes + current plus 3 preceding and 3 following Pointings. Each dataset must + contain a "qualified_mask" DataArray indicating which events qualify + for calibration products (checking both coincidence_type AND TOF). + current_index : int + Index of the current Pointing in l1b_de_datasets. + consecutive_threshold_sigma : float, optional + Sigma multiplier for consecutive interval check. + Default is HiConstants.STAT_FILTER_1_CONSECUTIVE_SIGMA. + extreme_threshold_sigma : float, optional + Sigma multiplier for extreme outlier check. + Default is HiConstants.STAT_FILTER_1_EXTREME_SIGMA. + min_consecutive_intervals : int, optional + Minimum consecutive intervals above threshold. + Default is HiConstants.STAT_FILTER_1_MIN_CONSECUTIVE. + cull_code : int, optional + Cull code to use for marking bad times. Default is CullCode.LOOSE. + min_pointings : int, optional + Minimum number of Pointings required. + Default is HiConstants.STAT_FILTER_MIN_POINTINGS. + + Raises + ------ + ValueError + If current_index is out of range or if fewer than min_pointings + datasets are provided. + + Notes + ----- + This function modifies goodtimes_ds in place. Should be called after + Statistical Filter 0 and other angle-independent filters. + """ + logger.info("Running mark_statistical_filter_1 culling") + + # Validate inputs + if current_index < 0 or current_index >= len(l1b_de_datasets): + raise ValueError( + f"current_index {current_index} out of range for list of " + f"length {len(l1b_de_datasets)}" + ) + + if len(l1b_de_datasets) < min_pointings: + raise ValueError( + f"At least {min_pointings} valid Pointings required, " + f"got {len(l1b_de_datasets)}" + ) + + # Step 1: Build per-sweep datasets with qualified counts for each Pointing + per_sweep_datasets = _build_per_sweep_datasets(l1b_de_datasets) + + # Step 2: Compute median and sigma per ESA energy step using xarray + median_per_esa, sigma_per_esa = _compute_median_and_sigma_per_esa( + per_sweep_datasets + ) + + if np.all(np.isnan(median_per_esa.values)): + logger.warning( + "Statistical Filter 1: No valid ESA energy steps " + "with non-zero median, skipping" + ) + return + + # Get current Pointing's per-sweep data (2D: esa_sweep x esa_energy_step) + current_ds = per_sweep_datasets[current_index] + current_counts = current_ds["qualified_count"] + + # Identify cull pattern using convolution-based detection + cull_mask = _identify_cull_pattern( + current_counts, + median_per_esa, + sigma_per_esa, + consecutive_threshold_sigma=consecutive_threshold_sigma, + extreme_threshold_sigma=extreme_threshold_sigma, + min_consecutive=min_consecutive_intervals, + ) + + # Apply culling to goodtimes - get METs where cull_mask is True + if cull_mask.any(): + # Use xarray's where to get METs for culled intervals, then flatten + mets_to_cull = current_ds["ccsds_met"].where(cull_mask).values.ravel() + # Remove NaN values + mets_to_cull = mets_to_cull[~np.isnan(mets_to_cull)] + + if len(mets_to_cull) > 0: + goodtimes_ds.goodtimes.mark_bad_times(met=mets_to_cull, cull=cull_code) + + logger.info( + f"Statistical Filter 1: Marked {len(mets_to_cull)} 8-spin intervals as bad" + ) + else: + logger.info("Statistical Filter 1: No bad intervals identified") + + +def _find_event_clusters( + event_times: np.ndarray, + min_events: int, + max_time_delta: float, +) -> list[tuple[int, int]]: + """ + Find clusters of events that occur within a maximum time window. + + Uses vectorized numpy operations to find groups of min_events or more + events that all occur within max_time_delta seconds of each other. + + Parameters + ---------- + event_times : np.ndarray + Sorted array of event times (event_met values in seconds). + min_events : int + Minimum number of events to form a cluster. + max_time_delta : float + Maximum time span in seconds for events to be considered clustered. + + Returns + ------- + list[tuple[int, int]] + List of (start_idx, end_idx) tuples marking cluster boundaries + in the input array. Indices are inclusive. + """ + if len(event_times) < min_events: + return [] + + # Compute time span for each window of min_events consecutive events + # window_spans[i] = event_times[i + min_events - 1] - event_times[i] + window_spans = event_times[min_events - 1 :] - event_times[: -(min_events - 1)] + + # Mask where windows fit within max_time_delta + cluster_mask = window_spans <= max_time_delta + + if not np.any(cluster_mask): + return [] + + # Find contiguous regions of True in the mask. Each contiguous region + # [i, j] in the mask corresponds to cluster [i, j + min_events - 1] + + # Pad with False to handle edge cases + padded = np.concatenate(([False], cluster_mask, [False])) + + # Find transitions: +1 = start of group, -1 = end of group + diff = np.diff(padded.astype(int)) + starts = np.flatnonzero(diff == 1) + # We need to adjust ends for the shortening from diffs performed. + # The window_spans array has length = n_events - min_events + 1 + # The contiguous diff adds two padding elements and np.diff shortens by 1. + # The result is that we need to add min_events and subtract 2 to get the + # correct end index. + ends = np.flatnonzero(diff == -1) + min_events - 2 # Adjust for window size + + return list(zip(starts.tolist(), ends.tolist(), strict=False)) + + +def _compute_bins_for_cluster( + nominal_bins: np.ndarray, + cluster_start: int, + cluster_end: int, + bin_padding: int, + n_bins: int = 90, +) -> np.ndarray: + """ + Compute the spin bins to cull for a cluster of events, with wrapping. + + Parameters + ---------- + nominal_bins : np.ndarray + Array of nominal_bin values for events. + cluster_start : int + Start index of cluster in nominal_bins array. + cluster_end : int + End index of cluster (inclusive). + bin_padding : int + Number of bins to add on each side. + n_bins : int + Total number of spin bins (default 90). + + Returns + ------- + np.ndarray + Array of bin indices to cull, with wrapping handled. + For example, if cluster spans bins 88-91 with n_bins=90, + returns [87, 88, 89, 0, 1, 2] (with padding=1). + """ + cluster_bins: np.ndarray = nominal_bins[cluster_start : cluster_end + 1].astype( + np.int32 + ) + + # Unwrap to handle clusters spanning the 0/n_bins boundary + unwrapped = np.unwrap(cluster_bins, period=n_bins) + bin_min = int(np.min(unwrapped)) + bin_max = int(np.max(unwrapped)) + + # Add padding + bin_low = bin_min - bin_padding + bin_high = bin_max + bin_padding + + # Generate bin indices with wrapping using modulo + bins_to_mark: np.ndarray = np.arange(bin_low, bin_high + 1) % n_bins + + logger.debug(f"Cluster {cluster_start} to {cluster_end} bins: {bins_to_mark}") + + return bins_to_mark + + +def mark_statistical_filter_2( + goodtimes_ds: xr.Dataset, + l1b_de: xr.Dataset, + min_events: int = HiConstants.STAT_FILTER_2_MIN_EVENTS, + max_time_delta: float = HiConstants.STAT_FILTER_2_MAX_TIME_DELTA, + bin_padding: int = HiConstants.STAT_FILTER_2_BIN_PADDING, + cull_code: int = CullCode.STAT_FILTER_2, +) -> None: + """ + Apply Statistical Filter 2 to detect short-lived event pulses. + + Statistical Filter 2 from Algorithm Document Section 2.3.2.3 removes + occasional short-lived "pulses" of qualified counts that may be + temporally correlated between sensors. These pulses are usually visible + only at the highest few energy steps and are not caught by Filter 1. + + For each 8-spin set (grouped by esa_sweep and esa_step), this filter: + 1. Keeps only events qualifying as calibration product 1 or 2 + 2. Sorts events by event_met + 3. Finds time ranges where min_events or more events occur within + max_time_delta seconds + 4. Marks the angle range covered by each pulse (plus bin_padding bins + on each side, with wrapping) as not good for all METs in that 8-spin set + + Parameters + ---------- + goodtimes_ds : xr.Dataset + Goodtimes dataset for the current Pointing to update. + l1b_de : xr.Dataset + L1B Direct Event dataset for the current Pointing containing: + - ccsds_index: packet index for each event + - ccsds_met: MET timestamp for each packet + - event_met: MET timestamp for each event + - coincidence_type: detector coincidence bitmap + - nominal_bin: spacecraft spin bin (0-89) + - esa_step: ESA energy step for each packet + - qualified_mask: boolean mask indicating which events qualify for + calibration products (checking both coincidence_type AND TOF windows) + min_events : int, optional + Minimum events to form a pulse cluster. + Default is HiConstants.STAT_FILTER_2_MIN_EVENTS. + max_time_delta : float, optional + Maximum time span in seconds for events to be considered clustered. + Default is HiConstants.STAT_FILTER_2_MAX_TIME_DELTA. + bin_padding : int, optional + Number of 4-degree bins to add on each side of the pulse angle range. + Default is HiConstants.STAT_FILTER_2_BIN_PADDING. + cull_code : int, optional + Cull code to use for marking bad times. Default is CullCode.LOOSE. + + Notes + ----- + This function modifies goodtimes_ds in place. It marks specific spin + bins as bad, unlike Filters 0 and 1 which mark entire time intervals. + Bin marking wraps around (e.g., bin 91 becomes bin 1). + + The default parameters (min_events=6, + max_time_delta=HiConstants.STAT_FILTER_2_MAX_TIME_DELTA β‰ˆ 9.995 s) + imply that seeing 6+ qualified events in an approximately 10-second + window has probability < 0.06% under normal conditions + (background rate ~0.1/s). + """ + logger.info("Running mark_statistical_filter_2 culling") + + # Add esa_sweep coordinate to group packets into 8-spin sets + l1b_de_with_sweep = _add_sweep_indices(l1b_de) + + # Get packet-level arrays + ccsds_index = l1b_de_with_sweep["ccsds_index"].values + esa_sweep = l1b_de_with_sweep.coords["esa_sweep"].values + esa_step = l1b_de_with_sweep["esa_step"].values + + # Add event-level coordinates for grouping + l1b_de_with_sweep = l1b_de_with_sweep.assign_coords( + event_sweep=("event_met", esa_sweep[ccsds_index]), + event_step=("event_met", esa_step[ccsds_index]), + ) + + # Get qualified mask from the dataset + qualified_mask = l1b_de["qualified_mask"].values + + if not np.any(qualified_mask): + logger.info("Statistical Filter 2: No qualified events found") + return + + qualified_events = l1b_de_with_sweep.isel(event_met=qualified_mask) + + n_clusters_found = 0 + n_bins_marked = 0 + + # Process each 8-spin set using xarray groupby + for (sweep_idx, step_idx), group in qualified_events.groupby( + ["event_sweep", "event_step"] + ): + # Sort by event_met + sorted_group = group.sortby("event_met") + sorted_mets = sorted_group["event_met"].values + sorted_bins = sorted_group["nominal_bin"].values + + # Find clusters + clusters = _find_event_clusters(sorted_mets, min_events, max_time_delta) + + if not clusters: + continue + + # Get all METs for this 8-spin set (to mark all packets in the set) + set_mets = l1b_de_with_sweep["ccsds_met"].values[ + (esa_sweep == sweep_idx) & (esa_step == step_idx) + ] + + # Mark bins for each cluster + for cluster_start, cluster_end in clusters: + bins_to_mark = _compute_bins_for_cluster( + sorted_bins, cluster_start, cluster_end, bin_padding + ) + + # Mark the bins as bad for all METs in this 8-spin set + for met in set_mets: + goodtimes_ds.goodtimes.mark_bad_times( + met=met, bins=bins_to_mark, cull=cull_code + ) + + n_clusters_found += 1 + n_bins_marked += len(bins_to_mark) * len(set_mets) + + logger.debug( + f"Statistical Filter 2: ESA sweep={sweep_idx}, step={step_idx}, " + f"cluster of {cluster_end - cluster_start + 1} events, " + f"marking {len(bins_to_mark)} bins across {len(set_mets)} METs" + ) + + if n_clusters_found > 0: + logger.info( + f"Statistical Filter 2: Found {n_clusters_found} pulse cluster(s), " + f"marked {n_bins_marked} bin-intervals as bad" + ) + else: + logger.info("Statistical Filter 2: No pulse clusters identified") diff --git a/imap_processing/hi/hi_l1a.py b/imap_processing/hi/hi_l1a.py index 3b7843d087..0d32cf775d 100644 --- a/imap_processing/hi/hi_l1a.py +++ b/imap_processing/hi/hi_l1a.py @@ -11,19 +11,10 @@ from imap_processing import imap_module_directory from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes -from imap_processing.hi.utils import HIAPID +from imap_processing.hi.utils import HIAPID, HiConstants from imap_processing.spice.time import met_to_ttj2000ns from imap_processing.utils import packet_file_to_datasets -# TODO: read DE_CLOCK_TICK_US from -# instrument status summary later. This value -# is rarely change but want to be able to change -# it if needed. It stores information about how -# fast the time was ticking. It is in microseconds. -DE_CLOCK_TICK_US = 1999 -DE_CLOCK_TICK_S = DE_CLOCK_TICK_US / 1e6 -HALF_CLOCK_TICK_S = DE_CLOCK_TICK_S / 2 - MILLISECOND_TO_S = 1e-3 # define the names of the 24 counter arrays @@ -57,23 +48,23 @@ # This is a mapping of variable name to index when the dump_data in the # HVSCI MEMDMP packet is interpreted as an array of uint32 values. MEMDMP_DATA_INDS = { - "lastbin_shorten": 9, + "lastbin_shorten": 10, "coinc_length": 60, "de_timetag": 65, - "ab_min": 67, - "ab_max": 68, - "ac_min": 69, - "ac_max": 70, - "ba_min": 71, - "ba_max": 72, - "bc_min": 73, - "bc_max": 74, - "ca_min": 75, - "ca_max": 76, - "cb_min": 77, - "cb_max": 78, - "cc_min": 79, - "cc_max": 80, + "ab_max": 67, + "ab_min": 68, + "ac_max": 69, + "ac_min": 70, + "ba_max": 71, + "ba_min": 72, + "bc_max": 73, + "bc_min": 74, + "ca_max": 75, + "ca_min": 76, + "cb_max": 77, + "cb_min": 78, + "cc_max": 79, + "cc_min": 80, "cfd_dac_a": 82, "cfd_dac_b": 83, "cfd_dac_c": 84, @@ -264,25 +255,40 @@ def create_de_dataset(de_data_dict: dict[str, npt.ArrayLike]) -> xr.Dataset: attrs=epoch_attrs, ) - event_met_attrs = attr_mgr.get_variable_attributes( - "hi_de_event_met", check_schema=False - ) - # For L1A DE, event_met is its own dimension, so we remove the DEPEND_0 attribute - _ = event_met_attrs.pop("DEPEND_0") - # Compute the meta-event MET in seconds meta_event_met = ( np.array(de_data_dict["esa_step_seconds"]).astype(np.float64) + np.array(de_data_dict["esa_step_milliseconds"]) * MILLISECOND_TO_S ) - # Compute the MET of each event in seconds - # event MET = meta_event_met + de_clock - # See Hi Algorithm Document section 2.2.5 - event_met_array = np.array( - meta_event_met[de_data_dict["ccsds_index"]] - + np.array(de_data_dict["de_tag"]) * DE_CLOCK_TICK_S, - dtype=event_met_attrs.pop("dtype"), + + event_met_attrs = attr_mgr.get_variable_attributes( + "hi_de_event_met", check_schema=False ) + # For L1A DE, event_met is its own dimension, so we remove the DEPEND_0 attribute + _ = event_met_attrs.pop("DEPEND_0") + event_met_dtype = event_met_attrs.pop("dtype") + + # If there are no events, add a single event with fill values + if len(de_data_dict["de_tag"]) == 0: + logger.warning( + "No direct events found in SCIDE packets. " + "Creating a false DE entry with fill values." + ) + for key in ["de_tag", "trigger_id", "tof_1", "tof_2", "tof_3", "ccsds_index"]: + attrs = attr_mgr.get_variable_attributes(f"hi_de_{key}", check_schema=False) + de_data_dict[key] = [attrs["FILLVAL"]] + event_met_array = np.array([event_met_attrs["FILLVAL"]], dtype=event_met_dtype) + else: + # Compute the MET of each event in seconds + # event MET = meta_event_met + de_clock + # See Hi Algorithm Document section 2.2.5 + event_met_array = np.array( + meta_event_met[de_data_dict["ccsds_index"]] + + np.array(de_data_dict["de_tag"]) * HiConstants.DE_CLOCK_TICK_S, + dtype=event_met_dtype, + ) + + # Create the event_met coordinate event_met = xr.DataArray( event_met_array, name="event_met", @@ -290,10 +296,12 @@ def create_de_dataset(de_data_dict: dict[str, npt.ArrayLike]) -> xr.Dataset: attrs=event_met_attrs, ) + # Create a dataset with only coordinates dataset = xr.Dataset( coords={"epoch": epoch, "event_met": event_met}, ) + # Add variable to the dataset for var_name, data in de_data_dict.items(): attrs = attr_mgr.get_variable_attributes( f"hi_de_{var_name}", check_schema=False @@ -357,7 +365,7 @@ def parse_direct_events(de_data: bytes) -> dict[str, npt.ArrayLike]: # word_0: full 16-bits is the de_tag # word_1: 2-bits of Trigger ID, 10-bits tof_1, upper 4-bits of tof_2 # word_2: lower 6-bits of tof_2, 10-bits of tof_3 - data_uint16 = np.reshape( + data_uint16: np.ndarray = np.reshape( np.frombuffer(de_data, dtype=">u2"), (3, -1), order="F" ).astype(np.uint16) @@ -396,11 +404,11 @@ def finish_hist_dataset(input_ds: xr.Dataset) -> xr.Dataset: dataset = input_ds.rename_vars({"shcoarse": "ccsds_met"}) dataset.epoch.attrs.update( - attr_mgr.get_variable_attributes("epoch"), + attr_mgr.get_variable_attributes("epoch", check_schema=False), ) # Add the hist_angle coordinate # Histogram data is binned in 90, 4-degree bins - attrs = attr_mgr.get_variable_attributes("hi_hist_angle") + attrs = attr_mgr.get_variable_attributes("hi_hist_angle", check_schema=False) dataset.coords.update( { "angle": xr.DataArray( @@ -527,7 +535,7 @@ def finish_memdmp_dataset(input_ds: xr.Dataset) -> xr.Dataset: dataset = dataset.rename_vars({"shcoarse": "ccsds_met"}) dataset.epoch.attrs.update( - attr_mgr.get_variable_attributes("epoch"), + attr_mgr.get_variable_attributes("epoch", check_schema=False), ) # Update existing variable attributes @@ -557,9 +565,12 @@ def finish_memdmp_dataset(input_ds: xr.Dataset) -> xr.Dataset: # offset index with a stride of the number of bytes in the dump # data divided by 4 (32-bit values). new_vars[new_var] = xr.DataArray( - data=full_uint32_data[offset::index_stride], + data=full_uint32_data[offset::index_stride].astype(np.uint32), dims=["epoch"], ) + # Need to add one to de_timetag value + if new_var == "de_timetag": + new_vars[new_var].data += 1 # Remove binary memory dump data and add parsed variables dataset = dataset.drop("dump_data") diff --git a/imap_processing/hi/hi_l1b.py b/imap_processing/hi/hi_l1b.py index 32ef811043..a7a648eb53 100644 --- a/imap_processing/hi/hi_l1b.py +++ b/imap_processing/hi/hi_l1b.py @@ -11,7 +11,7 @@ from imap_processing import imap_module_directory from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes from imap_processing.cdf.utils import parse_filename_like -from imap_processing.hi.hi_l1a import HALF_CLOCK_TICK_S +from imap_processing.hi.hi_l1a import MILLISECOND_TO_S from imap_processing.hi.utils import ( HIAPID, CoincidenceBitmap, @@ -20,6 +20,7 @@ create_dataset_variables, parse_sensor_number, ) +from imap_processing.quality_flags import ImapHiL1bDeFlags from imap_processing.spice.geometry import ( SpiceFrame, instrument_pointing, @@ -133,11 +134,12 @@ def annotate_direct_events( att_manager_lookup_str="hi_de_{0}", ) ) + l1b_de_dataset.update(de_esa_step_met(l1b_de_dataset)) + l1b_de_dataset.update(de_ccsds_qf(l1b_de_dataset)) l1b_de_dataset = l1b_de_dataset.drop_vars( [ "src_seq_ctr", "pkt_len", - "last_spin_num", "spin_invalids", "esa_step_seconds", "esa_step_milliseconds", @@ -158,6 +160,27 @@ def annotate_direct_events( return [l1b_de_dataset] +def any_good_direct_events(dataset: xr.Dataset) -> bool: + """ + Test dataset to see if there are any good direct events. + + Datasets can have no good direct events when there were no DEs in a pointing. + In this case, due to restrictions with cdflib, we have to write a single + bad DE in the CDF. + + Parameters + ---------- + dataset : xarray.Dataset + Run the check on this dataset. + + Returns + ------- + any_good_events : bool + True if there is at least one good direct event. False otherwise. + """ + return bool(np.any(dataset["trigger_id"] != dataset["trigger_id"].attrs["FILLVAL"])) + + def compute_coincidence_type_and_tofs( dataset: xr.Dataset, ) -> dict[str, xr.DataArray]: @@ -190,6 +213,9 @@ def compute_coincidence_type_and_tofs( len(dataset.event_met), att_manager_lookup_str="hi_de_{0}", ) + # Check for no valid direct events. + if not any_good_direct_events(dataset): + return new_vars # compute masks needed for coincidence type and ToF calculations a_first = dataset.trigger_id.values == TriggerId.A @@ -301,12 +327,15 @@ def de_nominal_bin_and_spin_phase(dataset: xr.Dataset) -> dict[str, xr.DataArray len(dataset.event_met), att_manager_lookup_str="hi_de_{0}", ) + # Check for no valid direct events. + if not any_good_direct_events(dataset): + return new_vars # nominal_bin is the index number of the 90 4-degree bins that each DE would # be binned into in the histogram packet. The Hi histogram data is binned by # spacecraft spin-phase, not instrument spin-phase, so the same is done here. # We have to add 1/2 clock tick to MET time before getting spin phase - met_seconds = dataset.event_met.values + HALF_CLOCK_TICK_S + met_seconds = dataset.event_met.values + HiConstants.HALF_CLOCK_TICK_S imap_spin_phase = get_spacecraft_spin_phase(met_seconds) new_vars["nominal_bin"].values = np.asarray(imap_spin_phase * 360 / 4).astype( np.uint8 @@ -345,9 +374,15 @@ def compute_hae_coordinates(dataset: xr.Dataset) -> dict[str, xr.DataArray]: len(dataset.event_met), att_manager_lookup_str="hi_de_{0}", ) + # Check for no valid direct events. + if not any_good_direct_events(dataset): + return new_vars + # Per Section 2.2.5 of Algorithm Document, add 1/2 of tick duration # to MET before computing pointing. - sclk_ticks = met_to_sclkticks(dataset.event_met.values + HALF_CLOCK_TICK_S) + sclk_ticks = met_to_sclkticks( + dataset.event_met.values + HiConstants.HALF_CLOCK_TICK_S + ) et = sct_to_et(sclk_ticks) sensor_number = parse_sensor_number(dataset.attrs["Logical_source"]) # TODO: For now, we are using SPICE to compute the look direction for each @@ -387,6 +422,9 @@ def de_esa_energy_step( len(l1b_de_ds.epoch), att_manager_lookup_str="hi_de_{0}", ) + # Check for no valid direct events. + if not any_good_direct_events(l1b_de_ds): + return new_vars # Get the LUT object using the HK data and esa-energies ancillary csv esa_energies_lut = pd.read_csv(esa_energies_anc, comment="#") @@ -497,3 +535,92 @@ def get_esa_to_esa_energy_step_lut( matching_esa_energy["esa_energy_step"].values[0], ) return esa_energy_step_lut + + +def de_esa_step_met(dataset: xr.Dataset) -> dict[str, xr.DataArray]: + """ + Compute esa_step_met for each CCSDS packet. + + The esa_step_met is the MET time when the ESA was stepped, computed from + esa_step_seconds and esa_step_milliseconds. + + Parameters + ---------- + dataset : xarray.Dataset + The L1A/B dataset containing esa_step_seconds and esa_step_milliseconds. + + Returns + ------- + new_vars : dict[str, xarray.DataArray] + Dictionary with "esa_step_met" key and float64 DataArray value. + """ + new_vars = create_dataset_variables( + ["esa_step_met"], + len(dataset.epoch), + att_manager_lookup_str="hi_de_{0}", + ) + + # Compute esa_step_met from esa_step_seconds and esa_step_milliseconds + new_vars["esa_step_met"].values = ( + dataset["esa_step_seconds"].values.astype(np.float64) + + dataset["esa_step_milliseconds"].values * MILLISECOND_TO_S + ) + + return new_vars + + +def de_ccsds_qf(dataset: xr.Dataset) -> dict[str, xr.DataArray]: + """ + Compute ccsds_qf quality flag for each CCSDS packet. + + The ccsds_qf is a quality flag bitmask indicating packet characteristics. + + Parameters + ---------- + dataset : xarray.Dataset + The L1A/B dataset containing ccsds_index for mapping events to packets. + + Returns + ------- + new_vars : dict[str, xarray.DataArray] + Dictionary with "ccsds_qf" key and uint8 DataArray value. + """ + max_events_per_packet = 664 + + new_vars = create_dataset_variables( + ["ccsds_qf"], + len(dataset.epoch), + att_manager_lookup_str="hi_de_{0}", + ) + + # Initialize all values to 0 (no flags set) + new_vars["ccsds_qf"].values[:] = 0 + + # Count events per CCSDS packet + # ccsds_index maps each event to its originating packet + ccsds_indices = dataset["ccsds_index"].values + n_packets = len(dataset.epoch) + + # Filter out fill/out-of-range indices (e.g., uint16 FILLVAL 65535) + valid_mask = (ccsds_indices >= 0) & (ccsds_indices < n_packets) + + # Set BADSPIN flag for packets with nonzero spin_invalids + spin_invalid_mask = dataset["spin_invalids"].values != 0 + new_vars["ccsds_qf"].values[spin_invalid_mask] |= np.uint8(ImapHiL1bDeFlags.BADSPIN) + + # If there are no valid events, skip the PACKET_FULL check + if not np.any(valid_mask): + return new_vars + + # Compute event counts per valid CCSDS packet + event_counts = np.bincount( + ccsds_indices[valid_mask].astype(np.int64), + minlength=n_packets, + ) + # Set PACKET_FULL flag for packets with 664 events + full_packet_mask = event_counts == max_events_per_packet + new_vars["ccsds_qf"].values[full_packet_mask] |= np.uint8( + ImapHiL1bDeFlags.PACKET_FULL + ) + + return new_vars diff --git a/imap_processing/hi/hi_l1c.py b/imap_processing/hi/hi_l1c.py index fe53198172..9a60235a52 100644 --- a/imap_processing/hi/hi_l1c.py +++ b/imap_processing/hi/hi_l1c.py @@ -4,36 +4,36 @@ import logging from pathlib import Path -from typing import NamedTuple import numpy as np import pandas as pd import xarray as xr from numpy import typing as npt -from numpy._typing import NDArray from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes from imap_processing.cdf.utils import parse_filename_like -from imap_processing.hi.hi_l1a import ( - DE_CLOCK_TICK_S, - HALF_CLOCK_TICK_S, -) from imap_processing.hi.utils import ( - CoincidenceBitmap, + BackgroundConfig, + CalibrationProductConfig, + HiConstants, create_dataset_variables, full_dataarray, + iter_background_events_by_config, + iter_qualified_events_by_config, parse_sensor_number, ) from imap_processing.spice.geometry import ( SpiceFrame, frame_transform, frame_transform_az_el, + get_spacecraft_to_instrument_spin_phase_offset, ) +from imap_processing.spice.repoint import get_pointing_times from imap_processing.spice.spin import ( - get_instrument_spin_phase, + get_spacecraft_spin_phase, get_spin_data, ) -from imap_processing.spice.time import ttj2000ns_to_et +from imap_processing.spice.time import met_to_ttj2000ns, ttj2000ns_to_et N_SPIN_BINS = 3600 SPIN_PHASE_BIN_EDGES = np.linspace(0, 1, N_SPIN_BINS + 1) @@ -43,22 +43,24 @@ def hi_l1c( - de_dataset: xr.Dataset, calibration_prod_config_path: Path + de_dataset: xr.Dataset, + calibration_prod_config_path: Path, + goodtimes_ds: xr.Dataset, + background_config_path: Path, ) -> list[xr.Dataset]: """ High level IMAP-Hi l1c processing function. - This function will be expanded once the l1c processing is better defined. It - will need to add inputs such as Ephemerides, Goodtimes inputs, and - instrument status summary and will output a Pointing Set CDF as well as a - Goodtimes list (CDF?). - Parameters ---------- de_dataset : xarray.Dataset IMAP-Hi l1b de product. calibration_prod_config_path : pathlib.Path Calibration product configuration file. + goodtimes_ds : xarray.Dataset + Goodtimes dataset with cull_flags. + background_config_path : pathlib.Path + Background configuration file. Returns ------- @@ -67,15 +69,18 @@ def hi_l1c( """ logger.info("Running Hi l1c processing") - # TODO: I am not sure what the input for Goodtimes will be so for now, - # If the input is an xarray Dataset, do pset processing - l1c_dataset = generate_pset_dataset(de_dataset, calibration_prod_config_path) + l1c_dataset = generate_pset_dataset( + de_dataset, calibration_prod_config_path, goodtimes_ds, background_config_path + ) return [l1c_dataset] def generate_pset_dataset( - de_dataset: xr.Dataset, calibration_prod_config_path: Path + de_dataset: xr.Dataset, + calibration_prod_config_path: Path, + goodtimes_ds: xr.Dataset, + background_config_path: Path, ) -> xr.Dataset: """ Generate IMAP-Hi l1c pset xarray dataset from l1b product. @@ -86,6 +91,10 @@ def generate_pset_dataset( IMAP-Hi l1b de product. calibration_prod_config_path : pathlib.Path Calibration product configuration file. + goodtimes_ds : xarray.Dataset + Goodtimes dataset with cull_flags. + background_config_path : pathlib.Path + Background configuration file. Returns ------- @@ -99,41 +108,61 @@ def generate_pset_dataset( logical_source_parts = parse_filename_like(de_dataset.attrs["Logical_source"]) # read calibration product configuration file config_df = CalibrationProductConfig.from_csv(calibration_prod_config_path) + # read background configuration file + background_df = BackgroundConfig.from_csv(background_config_path) pset_dataset = empty_pset_dataset( - de_dataset.epoch.data[0], - de_dataset.esa_energy_step.data, - config_df.cal_prod_config.number_of_products, + de_dataset.ccsds_met.data.mean(), + de_dataset.esa_energy_step, + config_df.cal_prod_config.calibration_product_numbers, logical_source_parts["sensor"], ) - pset_et = ttj2000ns_to_et(pset_dataset.epoch.data[0]) # Calculate and add despun_z, hae_latitude, and hae_longitude variables to # the pset_dataset - pset_dataset.update(pset_geometry(pset_et, logical_source_parts["sensor"])) + pset_midpoint_et = ttj2000ns_to_et( + pset_dataset.epoch.data[0] + pset_dataset.epoch_delta.data[0] / 2 + ) + pset_dataset.update(pset_geometry(pset_midpoint_et, logical_source_parts["sensor"])) # Bin the counts into the spin-bins - pset_dataset.update(pset_counts(pset_dataset.coords, config_df, de_dataset)) + pset_dataset.update( + pset_counts(pset_dataset.coords, config_df, de_dataset, goodtimes_ds) + ) # Calculate and add the exposure time to the pset_dataset - pset_dataset.update(pset_exposure(pset_dataset.coords, de_dataset)) - # Get the backgrounds - pset_dataset.update(pset_backgrounds(pset_dataset.coords)) + pset_dataset.update(pset_exposure(pset_dataset.coords, de_dataset, goodtimes_ds)) + + # Compute backgrounds (background counts computed internally) + pset_dataset.update( + pset_backgrounds( + pset_dataset.coords, + background_df, + de_dataset, + goodtimes_ds, + pset_dataset["exposure_times"], + ) + ) return pset_dataset def empty_pset_dataset( - epoch_val: int, l1b_energy_steps: np.ndarray, n_cal_prods: int, sensor_str: str + l1b_met: float, + l1b_energy_steps: xr.DataArray, + cal_prod_numbers: npt.NDArray[np.int_], + sensor_str: str, ) -> xr.Dataset: """ Allocate an empty xarray.Dataset with appropriate pset coordinates. Parameters ---------- - epoch_val : int - The starting epoch in J2000 TT nanoseconds for data in the PSET. - l1b_energy_steps : np.ndarray + l1b_met : float + Any met from the input L1B DE dataset. This is used to query the + repoint-table data to get the start and end times of the pointing. + l1b_energy_steps : xarray.DataArray The array of esa_energy_step data from the L1B DE product. - n_cal_prods : int - Number of calibration products to allocate. + cal_prod_numbers : numpy.ndarray + Array of calibration product numbers from the configuration file. + These can be arbitrary integers, not necessarily starting at 0. sensor_str : str '45sensor' or '90sensor'. @@ -148,13 +177,18 @@ def empty_pset_dataset( # preallocate coordinates xr.DataArrays coords = dict() + + # Get the Pointing start and end times + pointing_mets = get_pointing_times(l1b_met) + epochs = met_to_ttj2000ns(np.asarray(pointing_mets)) + # epoch coordinate has only 1 entry for pointing set epoch_attrs = attr_mgr.get_variable_attributes("epoch", check_schema=False) epoch_attrs.update( attr_mgr.get_variable_attributes("hi_pset_epoch", check_schema=False) ) coords["epoch"] = xr.DataArray( - np.array([epoch_val], dtype=np.int64), # TODO: get dtype from cdf attrs? + np.array([epochs[0]], dtype=np.int64), name="epoch", dims=["epoch"], attrs=epoch_attrs, @@ -164,8 +198,12 @@ def empty_pset_dataset( "hi_pset_esa_energy_step", check_schema=False ).copy() dtype = attrs.pop("dtype") - # Find the unique, non-zero esa_energy_steps from the L1B data - esa_energy_steps = np.array(sorted(set(l1b_energy_steps) - {0}), dtype=dtype) + # Find the unique esa_energy_steps from the L1B data + # Exclude 0 and FILLVAL + esa_energy_steps = np.array( + sorted(set(l1b_energy_steps.values) - {0, l1b_energy_steps.attrs["FILLVAL"]}), + dtype=dtype, + ) coords["esa_energy_step"] = xr.DataArray( esa_energy_steps, name="esa_energy_step", @@ -178,7 +216,7 @@ def empty_pset_dataset( ).copy() dtype = attrs.pop("dtype") coords["calibration_prod"] = xr.DataArray( - np.arange(n_cal_prods, dtype=dtype), + cal_prod_numbers.astype(dtype), name="calibration_prod", dims=["calibration_prod"], attrs=attrs, @@ -197,6 +235,15 @@ def empty_pset_dataset( # Allocate the coordinate label variables data_vars = dict() + # Generate the epoch_delta variable + data_vars["epoch_delta"] = xr.DataArray( + np.diff(epochs), + name="epoch_delta", + dims=["epoch"], + attrs=attr_mgr.get_variable_attributes( + "hi_pset_epoch_delta", check_schema=False + ), + ) # Generate label variables data_vars["esa_energy_step_label"] = xr.DataArray( coords["esa_energy_step"].values.astype(str), @@ -253,7 +300,7 @@ def pset_geometry(pset_et: float, sensor_str: str) -> dict[str, xr.DataArray]: Returns ------- geometry_vars : dict[str, xarray.DataArray] - Keys are variable names and values are data arrays. + Keys are variable names, and values are data arrays. """ geometry_vars = create_dataset_variables( ["despun_z"], (1, 3), att_manager_lookup_str="hi_pset_{0}" @@ -300,6 +347,7 @@ def pset_counts( pset_coords: dict[str, xr.DataArray], config_df: pd.DataFrame, l1b_de_dataset: xr.Dataset, + goodtimes_ds: xr.Dataset, ) -> dict[str, xr.DataArray]: """ Bin direct events into PSET spin-bins. @@ -312,14 +360,15 @@ def pset_counts( The calibration product configuration dataframe. l1b_de_dataset : xarray.Dataset The L1B dataset for the pointing being processed. + goodtimes_ds : xarray.Dataset + Goodtimes dataset with cull_flags. Returns ------- dict[str, xarray.DataArray] - Dictionary containing new exposure_times DataArray to be added to the PSET - dataset. + Dictionary containing counts DataArray. """ - # Generate exposure time variable filled with zeros + # Generate counts variable filled with zeros counts_var = create_dataset_variables( ["counts"], coords=pset_coords, @@ -327,148 +376,317 @@ def pset_counts( fill_value=0, ) - # Convert list of DEs to pandas dataframe for ease indexing/filtering - de_df = l1b_de_dataset.drop_dims("epoch").to_pandas() + # Create mapping from calibration product numbers to array indices + cal_prod_to_index = { + cal_prod: idx + for idx, cal_prod in enumerate(pset_coords["calibration_prod"].values) + } + + # Drop events with FILLVAL for trigger_id. This should only occur for a + # pointing with no events that gets a single fill event + de_ds = l1b_de_dataset.drop_dims("epoch") + + # Remove DEs with invalid trigger_id. This should only occur for a + # pointing with no events that gets a single fill event + good_mask = de_ds["trigger_id"].data != de_ds["trigger_id"].attrs["FILLVAL"] + if not np.any(good_mask): + return counts_var # Remove DEs not in Goodtimes/angles - good_mask = good_time_and_phase_mask( - l1b_de_dataset.event_met.values, l1b_de_dataset.spin_phase.values + # For direct events, use nominal_bin (spacecraft spin bin 0-89) to look up goodtimes + goodtimes_mask = good_time_and_phase_mask( + de_ds.event_met.values, + de_ds.nominal_bin.values, + goodtimes_ds, ) - de_df = de_df[good_mask] + de_ds = de_ds.isel(event_met=goodtimes_mask) + + # Get esa_energy_step for each event (recorded per packet, use ccsds_index) + esa_energy_steps = l1b_de_dataset["esa_energy_step"].data[de_ds["ccsds_index"].data] # The calibration product configuration potentially has different coincidence # types for each ESA and different TOF windows for each calibration product, - # esa energy step combination. Because of this we need to filter DEs that - # belong to each combo individually. - # Loop over the esa_energy_step values first - for esa_energy, esa_df in config_df.groupby(level="esa_energy_step"): - # Create a mask for all DEs at the current esa_energy_step. - # esa_energy_step is recorded for each packet rather than for each DE, - # so we use ccsds_index to get the esa_energy_step for each DE - esa_mask = ( - l1b_de_dataset["esa_energy_step"].data[de_df["ccsds_index"].to_numpy()] - == esa_energy + # esa energy step combination. Use the shared generator to iterate over all + # config combinations and get qualified event masks. + for esa_energy, config_row, qualified_mask in iter_qualified_events_by_config( + de_ds, config_df, esa_energy_steps + ): + # Filter events using the qualified mask + filtered_de_ds = de_ds.isel(event_met=qualified_mask) + + # Bin remaining DEs into spin-bins + i_esa = np.flatnonzero(pset_coords["esa_energy_step"].data == esa_energy)[0] + # spin_phase is in the range [0, 1). Multiplying by N_SPIN_BINS and + # truncating to an integer gives the correct bin index + spin_bin_indices = (filtered_de_ds["spin_phase"].data * N_SPIN_BINS).astype(int) + # When iterating over rows of a dataframe, the names of the multi-index + # are not preserved. Below, `config_row.Index[0]` gets the + # calibration_prod value from the namedtuple representing the + # dataframe row. We map this to the array index using cal_prod_to_index. + i_cal_prod = cal_prod_to_index[config_row.Index[0]] + np.add.at( + counts_var["counts"].data[0, i_esa, i_cal_prod], + spin_bin_indices, + 1, ) - # Now loop over the calibration products for the current ESA energy - for config_row in esa_df.itertuples(): - # Remove DEs that are not at the current ESA energy and in the list - # of coincidence types for the current calibration product - type_mask = de_df["coincidence_type"].isin( - config_row.coincidence_type_values - ) - filtered_de_df = de_df[(esa_mask & type_mask)] - - # Use the TOF window mask to remove DEs with TOFs outside the allowed range - tof_fill_vals = { - f"tof_{detector_pair}": l1b_de_dataset[f"tof_{detector_pair}"].attrs[ - "FILLVAL" - ] - for detector_pair in CalibrationProductConfig.tof_detector_pairs - } - tof_in_window_mask = get_tof_window_mask( - filtered_de_df, config_row, tof_fill_vals - ) - filtered_de_df = filtered_de_df[tof_in_window_mask] - - # Bin remaining DEs into spin-bins - i_esa = np.flatnonzero(pset_coords["esa_energy_step"].data == esa_energy)[0] - # spin_phase is in the range [0, 1). Multiplying by N_SPIN_BINS and - # truncating to an integer gives the correct bin index - spin_bin_indices = ( - filtered_de_df["spin_phase"].to_numpy() * N_SPIN_BINS - ).astype(int) - # When iterating over rows of a dataframe, the names of the multi-index - # are not preserved. Below, `config_row.Index[0]` gets the cal_prod_num - # value from the namedtuple representing the dataframe row. - np.add.at( - counts_var["counts"].data[0, i_esa, config_row.Index[0]], - spin_bin_indices, - 1, - ) + return counts_var -def get_tof_window_mask( - de_df: pd.DataFrame, prod_config_row: NamedTuple, fill_vals: dict -) -> NDArray[bool]: +def _compute_background_counts( + pset_coords: dict[str, xr.DataArray], + background_config_df: pd.DataFrame, + l1b_de_dataset: xr.Dataset, + goodtimes_ds: xr.Dataset, +) -> xr.DataArray: """ - Generate a mask indicating which DEs to keep based on TOF windows. + Compute background counts by filtering and binning direct events. + + Background counts are computed across all esa_energy_steps and spin_angle_bins + since backgrounds are isotropic and do not depend on ESA energy step or spin angle. Parameters ---------- - de_df : pandas.DataFrame - The Direct Event dataframe for the DEs to filter based on the TOF - windows. - prod_config_row : NamedTuple - A single row of the prod config dataframe represented as a named tuple. - fill_vals : dict - A dictionary containing the fill values used in the input DE TOF - dataframe values. This value should be derived from the L1B DE CDF - TOF variable attributes. + pset_coords : dict[str, xarray.DataArray] + The PSET coordinates from the xarray.Dataset. + background_config_df : pandas.DataFrame + Background configuration DataFrame with MultiIndex + (calibration_prod, background_index, esa_energy_step). + l1b_de_dataset : xarray.Dataset + The L1B dataset for the pointing being processed. + goodtimes_ds : xarray.Dataset + Goodtimes dataset with cull_flags. Returns ------- - window_mask : np.ndarray - A mask with one entry per DE in the input `de_df` indicating which DEs - contain TOF values within the windows specified by `prod_config_row`. - The mask is intended to directly filter the DE dataframe. + xarray.DataArray + Background counts with dims (epoch, calibration_prod, background_index). """ - detector_pairs = CalibrationProductConfig.tof_detector_pairs - tof_in_window_mask = np.empty((len(detector_pairs), len(de_df)), dtype=bool) - for i_pair, detector_pair in enumerate(detector_pairs): - low_limit = getattr(prod_config_row, f"tof_{detector_pair}_low") - high_limit = getattr(prod_config_row, f"tof_{detector_pair}_high") - tof_array = de_df[f"tof_{detector_pair}"].to_numpy() - # The TOF in window mask contains True wherever the TOF is within - # the configuration low/high bounds OR the FILLVAL is present. The - # FILLVAL indicates that the detector pair was not hit. DEs with - # the incorrect coincidence_type are already filtered out and this - # implementation simplifies combining the tof_in_window_masks in - # the next step. - tof_in_window_mask[i_pair] = np.logical_or( - np.logical_and(low_limit <= tof_array, tof_array <= high_limit), - tof_array == fill_vals[f"tof_{detector_pair}"], - ) - return np.all(tof_in_window_mask, axis=0) + # Create background_counts as xarray DataArray with proper coordinates + # Note: esa_energy_step and spin_angle_bin are NOT included since backgrounds + # are isotropic and computed across all ESA steps and spin angles + background_indices = ( + background_config_df.index.get_level_values("background_index") + .unique() + .sort_values() + .values + ) + + bg_coords = { + "epoch": pset_coords["epoch"], + "calibration_prod": pset_coords["calibration_prod"], + "background_index": background_indices, + } + + background_counts = xr.DataArray( + np.zeros( + ( + len(bg_coords["epoch"]), + len(bg_coords["calibration_prod"]), + len(bg_coords["background_index"]), + ), + ), + dims=[ + "epoch", + "calibration_prod", + "background_index", + ], + coords=bg_coords, + ) + + # Process direct events + de_ds = l1b_de_dataset.drop_dims("epoch") + + good_mask = de_ds["trigger_id"].data != de_ds["trigger_id"].attrs["FILLVAL"] + if not np.any(good_mask): + return background_counts + + # Remove DEs not in Goodtimes/angles + goodtimes_mask = good_time_and_phase_mask( + de_ds.event_met.values, + de_ds.nominal_bin.values, + goodtimes_ds, + ) + de_ds = de_ds.isel(event_met=goodtimes_mask) + + n_events = len(de_ds["event_met"]) + if n_events == 0: + return background_counts + + # Get TOF configuration (one row per calibration_prod, background_index) + # TOF windows are the same across ESA steps, so we use get_tof_config() + tof_config = background_config_df.background_config.get_tof_config() + + for cal_prod in pset_coords["calibration_prod"].values: + # Check that cal_prod exists in tof_config + if cal_prod not in tof_config.index.get_level_values("calibration_prod"): + raise ValueError( + f"Calibration product {cal_prod} not found in background " + f"configuration. Available calibration products: " + f"{sorted(tof_config.index.get_level_values('calibration_prod').unique().tolist())}" + ) + + # Take a cross-section of the TOF configuration DataFrame + # to get rows relevant to the current calibration product + cal_prod_rows = tof_config.xs(cal_prod, level="calibration_prod") + + # Use iter_background_events_by_config to get filtered events + for config_row, filtered_de_ds in iter_background_events_by_config( + de_ds, cal_prod_rows + ): + background_idx = config_row.Index + + if len(filtered_de_ds["event_met"]) == 0: + continue + + # Count all filtered events + # (no binning by spin angle since backgrounds are isotropic) + count = len(filtered_de_ds["event_met"]) + + background_counts.loc[ + dict( + epoch=pset_coords["epoch"].values[0], + calibration_prod=cal_prod, + background_index=background_idx, + ) + ] += count + + return background_counts -def pset_backgrounds(pset_coords: dict[str, xr.DataArray]) -> dict[str, xr.DataArray]: +def pset_backgrounds( + pset_coords: dict[str, xr.DataArray], + background_config_df: pd.DataFrame, + l1b_de_dataset: xr.Dataset, + goodtimes_ds: xr.Dataset, + exposure_times: xr.DataArray, +) -> dict[str, xr.DataArray]: """ - Calculate pointing set backgrounds and background uncertainties. + Calculate pointing set backgrounds from direct events. + + Computes background counts internally by filtering and binning events + according to the background configuration, then calculates background + rates and uncertainties. Scaling factors and uncertainties are applied + per ESA energy step. Parameters ---------- pset_coords : dict[str, xarray.DataArray] The PSET coordinates from the xarray.Dataset. + background_config_df : pandas.DataFrame + Background configuration DataFrame with MultiIndex + (calibration_prod, background_index, esa_energy_step). + l1b_de_dataset : xarray.Dataset + The L1B dataset for the pointing being processed. + goodtimes_ds : xarray.Dataset + Goodtimes dataset with cull_flags. + exposure_times : xarray.DataArray + Exposure times with dims (epoch, esa_energy_step, spin_angle_bin). Returns ------- dict[str, xarray.DataArray] - Dictionary containing background_rates and background_rates_unc DataArrays - to be added to the PSET dataset. + Dictionary containing background_rates and background_rates_uncertainty + DataArrays to be added to the PSET dataset. """ - # TODO: This is just a placeholder setting backgrounds to zero. The background - # algorithm will be determined in flight. attr_mgr = ImapCdfAttributes() attr_mgr.add_instrument_global_attrs("hi") attr_mgr.add_instrument_variable_attrs(instrument="hi", level=None) - return { + # Create output arrays + output_vars = { var_name: full_dataarray( var_name, attr_mgr.get_variable_attributes(f"hi_pset_{var_name}", check_schema=False), pset_coords, - fill_value=fill_val, ) - for var_name, fill_val in [ - ("background_rates", 0), - ("background_rates_uncertainty", 1), - ] + for var_name in ["background_rates", "background_rates_uncertainty"] } + # Get total exposure time + total_exposure_time = float(exposure_times.sum()) + + if total_exposure_time <= 0: + output_vars["background_rates"].values[:] = 0 + output_vars["background_rates_uncertainty"].values[:] = 0 + return output_vars + + # Compute background counts: shape (epoch, calibration_prod, background_index) + background_counts = _compute_background_counts( + pset_coords, background_config_df, l1b_de_dataset, goodtimes_ds + ) + + # Compute count rates: shape (epoch, calibration_prod, background_index) + count_rates = background_counts / total_exposure_time + + # Convert background config DataFrame to xarray Dataset + # Config now has dims: (calibration_prod, background_index, esa_energy_step) + config_ds = background_config_df.to_xarray() + + # Validate calibration products match (compare values, not DataArray metadata) + if not np.array_equal( + config_ds["calibration_prod"].values, pset_coords["calibration_prod"].values + ): + raise ValueError( + f"Calibration products in pset_coords and background_config_df " + f"do not match. pset_coords: {pset_coords['calibration_prod'].values}, " + f"background_config_df: {config_ds['calibration_prod'].values}" + ) + + # Validate ESA energy steps match (compare values, not DataArray metadata) + if not np.array_equal( + config_ds["esa_energy_step"].values, pset_coords["esa_energy_step"].values + ): + raise ValueError( + f"ESA energy steps in pset_coords and background_config_df " + f"do not match. pset_coords: {pset_coords['esa_energy_step'].values}, " + f"background_config_df: {config_ds['esa_energy_step'].values}" + ) + + # scaling_factors_da: (calibration_prod, background_index, esa_energy_step) + scaling_factors_da = config_ds["scaling_factor"] + uncertainties_da = config_ds["uncertainty"] + + # Compute scaled rates + # count_rates: (epoch, calibration_prod, background_index) + # scaling_factors_da: (calibration_prod, background_index, esa_energy_step) + # scaled_rates: (epoch, calibration_prod, background_index, esa_energy_step) + scaled_rates = count_rates * scaling_factors_da + + # Compute uncertainties (Poisson + scaling factor, combined in quadrature) + poisson_unc = ( + np.sqrt(background_counts) / total_exposure_time + ) * scaling_factors_da + scaling_unc = count_rates * uncertainties_da + combined_unc = np.sqrt(poisson_unc**2 + scaling_unc**2) + + # Sum over background_index dimension to get final rates + # total_rates: (epoch, calibration_prod, esa_energy_step) + total_rates = scaled_rates.sum(dim="background_index", skipna=True) + total_unc = np.sqrt((combined_unc**2).sum(dim="background_index", skipna=True)) + + # Broadcast to output variable dimensions (e.g., epoch, esa_energy_step, + # calibration_prod, spin_angle_bin). Backgrounds are isotropic, so we + # broadcast across the last dimension (spin_angle_bin). + # Get the output dimension order from the output variable (excluding last dim) + output_dims = output_vars["background_rates"].dims[:-1] + total_rates_transposed = total_rates.transpose(*output_dims) + total_unc_transposed = total_unc.transpose(*output_dims) + + output_vars["background_rates"].values[:] = total_rates_transposed.values[ + ..., np.newaxis + ] + output_vars["background_rates_uncertainty"].values[:] = total_unc_transposed.values[ + ..., np.newaxis + ] + + return output_vars + def pset_exposure( - pset_coords: dict[str, xr.DataArray], l1b_de_dataset: xr.Dataset + pset_coords: dict[str, xr.DataArray], + l1b_de_dataset: xr.Dataset, + goodtimes_ds: xr.Dataset, ) -> dict[str, xr.DataArray]: """ Calculate PSET exposure time. @@ -479,6 +697,8 @@ def pset_exposure( The PSET coordinates from the xarray.Dataset. l1b_de_dataset : xarray.Dataset The L1B dataset for the pointing being processed. + goodtimes_ds : xarray.Dataset + Goodtimes dataset with cull_flags. Returns ------- @@ -499,7 +719,7 @@ def pset_exposure( # Get a subset of the l1b_de_dataset that contains only the second # of each pair of packets at an ESA step. - data_subset = find_second_de_packet_data(l1b_de_dataset) + data_subset = find_last_de_packet_data(l1b_de_dataset) # Get the pandas dataframe with spin data spin_df = get_spin_data() @@ -515,15 +735,26 @@ def pset_exposure( # Clock tick MET times are accumulation "edges". To get the mean spin-phase # for a given clock tick, add 1/2 clock tick and compute spin-phase. - spin_phases = np.atleast_1d( - get_instrument_spin_phase( - clock_tick_mets + HALF_CLOCK_TICK_S, - SpiceFrame[f"IMAP_HI_{sensor_number}"], - ) - ) + mid_tick_mets = clock_tick_mets + HiConstants.HALF_CLOCK_TICK_S + + # Compute spacecraft spin phase first (used for goodtimes filtering) + spacecraft_spin_phase = np.atleast_1d(get_spacecraft_spin_phase(mid_tick_mets)) + + # Convert spacecraft spin phase to nominal_bins (0-89) for goodtimes lookup + nominal_bins = (spacecraft_spin_phase * 90).astype(np.int32) + nominal_bins = np.clip(nominal_bins, 0, 89) + + # Compute instrument spin phase from spacecraft spin phase + # This implementation is identical to spin.get_instrument_spin_phase and + # is replicated here to avoid querying the spin dataframe again. + instrument_frame = SpiceFrame[f"IMAP_HI_{sensor_number}"] + phase_offset = get_spacecraft_to_instrument_spin_phase_offset(instrument_frame) + spin_phases = (spacecraft_spin_phase + phase_offset) % 1.0 # Remove ticks not in good times/angles - good_mask = good_time_and_phase_mask(clock_tick_mets, spin_phases) + good_mask = good_time_and_phase_mask( + clock_tick_mets, nominal_bins, goodtimes_ds + ) spin_phases = spin_phases[good_mask] clock_tick_weights = clock_tick_weights[good_mask] @@ -541,14 +772,14 @@ def pset_exposure( exposure_var["exposure_times"].values[:, i_esa] += new_exposure_times # Convert exposure clock ticks to seconds - exposure_var["exposure_times"].values *= DE_CLOCK_TICK_S + exposure_var["exposure_times"].values *= HiConstants.DE_CLOCK_TICK_S return exposure_var -def find_second_de_packet_data(l1b_dataset: xr.Dataset) -> xr.Dataset: +def find_last_de_packet_data(l1b_dataset: xr.Dataset) -> xr.Dataset: """ - Find the telemetry entries for the second packet at an ESA step. + Find the telemetry entries for the last packet at an ESA step. Parameters ---------- @@ -558,35 +789,38 @@ def find_second_de_packet_data(l1b_dataset: xr.Dataset) -> xr.Dataset: Returns ------- reduced_dataset : xarray.Dataset - A dataset containing only the entries for the second packet at an ESA step. + A dataset containing only the entries for the last packet at an ESA step. """ epoch_dataset = l1b_dataset.drop_dims("event_met") - # We should get two CCSDS packets per 8-spin ESA step. + # We should get 2, 4, or 8 CCSDS packets per 8-spin ESA step. # Get the indices of the packet before each ESA change. esa_step = epoch_dataset["esa_step"].values - second_esa_packet_idx = np.append( - np.flatnonzero(np.diff(esa_step) != 0), len(esa_step) - 1 - ) - # Remove esa steps at 0 - these are calibrations - second_esa_packet_idx = second_esa_packet_idx[esa_step[second_esa_packet_idx] != 0] - # Remove indices where we don't have two consecutive packets at the same ESA - if second_esa_packet_idx[0] == 0: - logger.warning( - f"Removing packet 0 with ESA step: {esa_step[0]} from" - f"calculation of exposure time due to missing matched pair." - ) - second_esa_packet_idx = second_esa_packet_idx[1:] - missing_esa_pair_mask = ( - esa_step[second_esa_packet_idx - 1] != esa_step[second_esa_packet_idx] - ) - if missing_esa_pair_mask.any(): - logger.warning( - f"Removing {missing_esa_pair_mask.sum()} packets from exposure " - f"time calculation due to missing ESA step DE packet pairs." - ) - second_esa_packet_idx = second_esa_packet_idx[~missing_esa_pair_mask] - # Reduce the dataset to just the second packet entries - data_subset = epoch_dataset.isel(epoch=second_esa_packet_idx) + esa_energy_step = epoch_dataset["esa_energy_step"].values + # A change in esa_step should indicate the location of the last packet in + # each pair of DE packets at an esa_energy_step. In practice, during some + # calibration activities, it was observed that the esa_energy_step can change + # when the esa_step did not. So, we look for either to change and use the + # indices of those changes to identify the last packet in each set. We + # also need to add the final packet index and assume an energy step change + # occurs after the final packet. + last_esa_packet_idx = np.append( + np.flatnonzero((np.diff(esa_step) != 0) | (np.diff(esa_energy_step) != 0)), + len(esa_step) - 1, + ) + # Remove esa energy steps at 0 - these are calibrations + keep_mask = esa_energy_step[last_esa_packet_idx] != 0 + # Remove esa energy steps at FILLVAL - these are unidentified + keep_mask &= ( + esa_energy_step[last_esa_packet_idx] + != l1b_dataset["esa_energy_step"].attrs["FILLVAL"] + ) + last_esa_packet_idx = last_esa_packet_idx[keep_mask] + + # We don't need to worry about checking that the right number of packets + # is present for each ESA step because that is done in the Goodtimes processing. + + # Reduce the dataset to just the last packet entries + data_subset = epoch_dataset.isel(epoch=last_esa_packet_idx) return data_subset @@ -622,9 +856,11 @@ def get_de_clock_ticks_for_esa_step( # ESA step group so this match is the end time. The start time is # 8-spins earlier. spin_start_mets = spin_df.spin_start_met.to_numpy() - # CCSDS MET has one second resolution, add one to it to make sure it is - # greater than the spin start time it ended on. - end_time_ind = np.flatnonzero(ccsds_met + 1 >= spin_start_mets).max() + # CCSDS MET has one second resolution, add two to it to make sure it is + # greater than the spin start time it ended on. Theotretically, adding + # one second should be sufficeint, but in practice, with flight data, adding + # two seconds was found to be necessary. + end_time_ind = np.flatnonzero(ccsds_met + 2 >= spin_start_mets).max() # If the minimum absolute difference is greater than 1/2 the spin-phase # we have a problem. @@ -645,10 +881,10 @@ def get_de_clock_ticks_for_esa_step( f"The CCSDS MET time {ccsds_met} " "is less than 8 spins from the loaded spin table data." ) - clock_tick_mets = np.arange( + clock_tick_mets: np.ndarray = np.arange( spin_start_mets[end_time_ind - 8], spin_start_mets[end_time_ind], - DE_CLOCK_TICK_S, + HiConstants.DE_CLOCK_TICK_S, dtype=float, ) # The final clock-tick bin has less exposure time because the next spin @@ -660,133 +896,45 @@ def get_de_clock_ticks_for_esa_step( clock_tick_weights = np.ones_like(clock_tick_mets, dtype=float) clock_tick_weights[-1] = ( spin_start_mets[end_time_ind] - clock_tick_mets[-1] - ) / DE_CLOCK_TICK_S + ) / HiConstants.DE_CLOCK_TICK_S return clock_tick_mets, clock_tick_weights def good_time_and_phase_mask( - tick_mets: np.ndarray, spin_phases: np.ndarray -) -> npt.NDArray: + mets: np.ndarray, + nominal_bins: np.ndarray, + goodtimes_ds: xr.Dataset, +) -> npt.NDArray[np.bool_]: """ - Filter out the clock tick times that are not in good times and angles. + Filter out times that are not in good times based on the goodtimes dataset. Parameters ---------- - tick_mets : np.ndarray - Clock-tick MET times. - spin_phases : np.ndarray - Spin phases for each clock tick. + mets : np.ndarray + MET times for each event or clock tick. + nominal_bins : np.ndarray + Spacecraft spin bins (0-89) for each event or clock tick. + goodtimes_ds : xarray.Dataset + Goodtimes dataset with cull_flags variable dimensioned (met, spin_bin). Returns ------- keep_mask : np.ndarray - Boolean mask indicating which clock ticks are in good times/phases. + Boolean mask indicating which events/ticks are in good times. """ - # TODO: Implement this once we have Goodtimes data product defined. - return np.full_like(tick_mets, True, dtype=bool) + gt_mets = goodtimes_ds["met"].values + cull_flags = goodtimes_ds["cull_flags"].values + # Map each event/tick to the nearest goodtimes MET interval + # searchsorted with side='right' - 1 gives the largest MET <= query MET + met_indices = np.searchsorted(gt_mets, mets, side="right") - 1 + met_indices = np.clip(met_indices, 0, len(gt_mets) - 1) -@pd.api.extensions.register_dataframe_accessor("cal_prod_config") -class CalibrationProductConfig: - """ - Register custom accessor for calibration product configuration DataFrames. + # Convert nominal_bins to int32 for indexing + spin_bins: npt.NDArray[np.int32] = nominal_bins.astype(np.int32) - Parameters - ---------- - pandas_obj : pandas.DataFrame - Object to run validation and use accessor functions on. - """ + # Look up cull_flags for each event/tick + # Events are good if cull_flags == 0 + event_cull_flags = cull_flags[met_indices, spin_bins] - index_columns = ( - "cal_prod_num", - "esa_energy_step", - ) - tof_detector_pairs = ("ab", "ac1", "bc1", "c1c2") - required_columns = ( - "coincidence_type_list", - *[ - f"tof_{det_pair}_{limit}" - for det_pair in tof_detector_pairs - for limit in ["low", "high"] - ], - ) - - def __init__(self, pandas_obj: pd.DataFrame) -> None: - self._validate(pandas_obj) - self._obj = pandas_obj - self._add_coincidence_values_column() - - def _validate(self, df: pd.DataFrame) -> None: - """ - Validate the current configuration. - - Parameters - ---------- - df : pandas.DataFrame - Object to validate. - - Raises - ------ - AttributeError : If the dataframe does not pass validation. - """ - for index_name in self.index_columns: - if index_name in df.index: - raise AttributeError( - f"Required index {index_name} not present in dataframe." - ) - # Verify that the Dataframe has all the required columns - for col in self.required_columns: - if col not in df.columns: - raise AttributeError(f"Required column {col} not present in dataframe.") - # TODO: Verify that the same ESA energy steps exist in all unique calibration - # product numbers - - def _add_coincidence_values_column(self) -> None: - """Generate and add the coincidence_type_values column to the dataframe.""" - # Add a column that consists of the coincidence type strings converted - # to integer values - self._obj["coincidence_type_values"] = self._obj.apply( - lambda row: tuple( - CoincidenceBitmap.detector_hit_str_to_int(entry) - for entry in row["coincidence_type_list"] - ), - axis=1, - ) - - @classmethod - def from_csv(cls, path: Path) -> pd.DataFrame: - """ - Read configuration CSV file into a pandas.DataFrame. - - Parameters - ---------- - path : pathlib.Path - Location of the Calibration Product configuration CSV file. - - Returns - ------- - dataframe : pandas.DataFrame - Validated calibration product configuration data frame. - """ - df = pd.read_csv( - path, - index_col=cls.index_columns, - converters={"coincidence_type_list": lambda s: tuple(s.split("|"))}, - comment="#", - ) - # Force the _init_ method to run by using the namespace - _ = df.cal_prod_config.number_of_products - return df - - @property - def number_of_products(self) -> int: - """ - Get the number of calibration products in the current configuration. - - Returns - ------- - number_of_products : int - The maximum number of calibration products defined in the list of - calibration product definitions. - """ - return len(self._obj.index.unique(level="cal_prod_num")) + return event_cull_flags == 0 diff --git a/imap_processing/hi/hi_l2.py b/imap_processing/hi/hi_l2.py index eb3c8225f8..c047ece1f0 100644 --- a/imap_processing/hi/hi_l2.py +++ b/imap_processing/hi/hi_l2.py @@ -7,87 +7,127 @@ import pandas as pd import xarray as xr +from imap_processing.cdf.utils import load_cdf from imap_processing.ena_maps.ena_maps import ( - AbstractSkyMap, HiPointingSet, RectangularSkyMap, ) +from imap_processing.ena_maps.utils.corrections import ( + PowerLawFluxCorrector, + add_spacecraft_position_and_velocity_to_pset, + apply_compton_getting_correction, + calculate_ram_mask, + get_pset_directional_mask, + interpolate_map_flux_to_helio_frame, +) from imap_processing.ena_maps.utils.naming import MapDescriptor +from imap_processing.hi.utils import CalibrationProductConfig logger = logging.getLogger(__name__) +SC_FRAME_VARS_TO_PROJECT = { + "counts", + "exposure_factor", + "bg_rate", + "obs_date", +} +HELIO_FRAME_VARS_TO_PROJECT = SC_FRAME_VARS_TO_PROJECT | {"energy_sc"} # TODO: is an exposure time weighted average for obs_date appropriate? -VARS_TO_EXPOSURE_TIME_AVERAGE = ["bg_rates", "bg_rates_unc", "obs_date"] +FULL_EXPOSURE_TIME_AVERAGE_SET = {"bg_rate", "obs_date", "energy_sc"} + + +# ============================================================================= +# MAIN ENTRY POINT +# ============================================================================= def hi_l2( psets: list[str | Path], - geometric_factors_path: str | Path, - esa_energies_path: str | Path, + l2_ancillary_path_dict: dict[str, Path], descriptor: str, ) -> list[xr.Dataset]: """ - High level IMAP-Hi L2 processing function. + Process IMAP-Hi L1C data into L2 CDF data products. + + This is the main entry point for L2 processing. It orchestrates the entire + processing pipeline from L1C pointing sets to L2 sky maps with intensities. Parameters ---------- psets : list of str or pathlib.Path List of input PSETs to make a map from. - geometric_factors_path : str or pathlib.Path - Where to get the geometric factors from. - esa_energies_path : str or pathlib.Path - Where to get the energies from. + l2_ancillary_path_dict : dict[str, pathlib.Path] + Mapping containing ancillary file descriptors as keys and file paths as + values. Required keys are: ["cal-prod", "esa-energies", "esa-eta-fit-factors"]. descriptor : str - Output filename descriptor. Contains full configuration for the options - of how to generate the map. + The map descriptor to be produced + (e.g., "h90-ena-h-sf-nsp-full-hae-6deg-3mo"). Returns ------- - l2_dataset : list[xarray.Dataset] - Level 2 IMAP-Hi dataset ready to be written to a CDF file. + list[xarray.Dataset] + List containing the processed L2 dataset with rates, intensities, + and uncertainties. + + Raises + ------ + ValueError + If map_descriptor sensor attribute is invalid. + NotImplementedError + If HEALPix map output is requested (only rectangular maps supported). """ - cg_corrected = False - map_descriptor = MapDescriptor.from_string(descriptor) - - sky_map = generate_hi_map( - psets, - geometric_factors_path, - esa_energies_path, - spin_phase=map_descriptor.spin_phase, - output_map=map_descriptor.to_empty_map(), - cg_corrected=cg_corrected, - ) + logger.info("Starting IMAP-Hi L2 processing pipeline") + logger.info(f"Descriptor: {descriptor}") + logger.info(f"Processing {len(psets)} pointing sets") - # Get the map dataset with variables/coordinates in the correct shape - # TODO get the correct descriptor and frame - - if not isinstance(sky_map, RectangularSkyMap): - raise NotImplementedError("HEALPix map output not supported for Hi") + # Parse the map descriptor + map_descriptor = MapDescriptor.from_string(descriptor) if not isinstance(map_descriptor.sensor, str): raise ValueError( "Invalid map_descriptor. Sensor attribute must be of type str " "and be either '45' or '90'" ) - l2_ds = sky_map.build_cdf_dataset( + logger.info(f"Step 1: Creating sky map from {len(psets)} pointing sets") + sky_maps = create_sky_map_from_psets( + psets, + l2_ancillary_path_dict, + map_descriptor, + ) + + logger.info("Step 2: Calculating rates and intensities") + for sky_map in sky_maps.values(): + sky_map.data_1d = calculate_all_rates_and_intensities( + sky_map.data_1d, + l2_ancillary_path_dict, + map_descriptor, + ) + + logger.info("Step 3: Combining maps (if needed)") + final_map = combine_maps(sky_maps) + + logger.info("Step 4: Finalizing dataset with attributes") + l2_ds = final_map.build_cdf_dataset( "hi", "l2", - map_descriptor.frame_descriptor, descriptor, sensor=map_descriptor.sensor, ) + logger.info("IMAP-Hi L2 processing pipeline completed successfully") return [l2_ds] -def generate_hi_map( +# ============================================================================= +# SKY MAP CREATION PIPELINE +# ============================================================================= + + +def create_sky_map_from_psets( psets: list[str | Path], - geometric_factors_path: str | Path, - esa_energies_path: str | Path, - output_map: AbstractSkyMap, - cg_corrected: bool = False, - spin_phase: str = "full", -) -> AbstractSkyMap: + l2_ancillary_path_dict: dict[str, Path], + descriptor: MapDescriptor, +) -> dict[str, RectangularSkyMap]: """ Project Hi PSET data into a sky map. @@ -95,98 +135,269 @@ def generate_hi_map( ---------- psets : list of str or pathlib.Path List of input PSETs to make a map from. - geometric_factors_path : str or pathlib.Path - Where to get the geometric factors from. - esa_energies_path : str or pathlib.Path - Where to get the energies from. - output_map : AbstractSkyMap - The map object to collect data into. Determines pixel spacing, - coordinate system, etc. - cg_corrected : bool, Optional - Whether to apply Compton-Getting correction to the energies. Defaults to - False. - spin_phase : str, Optional - Apply filtering to PSET data include ram or anti-ram or full spin data. - Defaults to "full". + l2_ancillary_path_dict : dict[str, pathlib.Path] + Mapping containing ancillary file descriptors as keys and file paths as + values. Require keys are: ["cal-prod", "esa-energies", "esa-eta-fit-factors"]. + descriptor : imap_processing.ena_maps.utils.naming.MapDescriptor + Output filename descriptor. Contains full configuration for the options + of how to generate the map. Returns ------- - sky_map : AbstractSkyMap - The sky map with all the PSET data projected into the map. + sky_maps : dict[str, RectangularSkyMap] + Dictionary mapping spin phase keys ("ram", "anti", or "full") + to sky maps with all the PSET data projected. Includes + an energy coordinate and energy_delta_minus and energy_delta_plus + variables from ESA energy calibration data. For helioframe full-spin + maps, contains "ram" and "anti" keys; otherwise contains a single key + matching the descriptor's spin_phase. """ - # TODO: Implement Compton-Getting correction - if cg_corrected: - raise NotImplementedError - - for pset_path in psets: - logger.info(f"Processing {pset_path}") - pset = HiPointingSet(pset_path, spin_phase=spin_phase) - - # Background rate and uncertainty are exposure time weighted means in - # the map. - for var in VARS_TO_EXPOSURE_TIME_AVERAGE: - pset.data[var] *= pset.data["exposure_factor"] - - # Project (bin) the PSET variables into the map pixels - output_map.project_pset_values_to_map( - pset, - ["counts", "exposure_factor", "bg_rates", "bg_rates_unc", "obs_date"], - ) + if len(psets) == 0: + raise ValueError("No PSETs provided for map creation") + + # If we are making a full-spin, helio-frame map, we need to make one ram + # and one anti-ram map that get combined at the final L2 step. + if descriptor.frame_descriptor == "hf" and descriptor.spin_phase == "full": + # The spin-phase of the descriptor has no effect on the output map, so + # we can just use descriptor.to_empty_map() to generate both. + output_maps = { + "ram": descriptor.to_empty_map(), + "anti": descriptor.to_empty_map(), + } + else: + output_maps = {descriptor.spin_phase: descriptor.to_empty_map()} + + if not all([isinstance(map, RectangularSkyMap) for map in output_maps.values()]): + raise NotImplementedError("Healpix map output not supported for Hi") + # Needed for mypy type narrowing + rect_maps: dict[str, RectangularSkyMap] = { + k: v for k, v in output_maps.items() if isinstance(v, RectangularSkyMap) + } - # Finish the exposure time weighted mean calculation of backgrounds - # Allow divide by zero to fill set pixels with zero exposure time to NaN - with np.errstate(divide="ignore"): - for var in VARS_TO_EXPOSURE_TIME_AVERAGE: - output_map.data_1d[var] /= output_map.data_1d["exposure_factor"] + vars_to_bin = ( + HELIO_FRAME_VARS_TO_PROJECT + if descriptor.frame_descriptor == "hf" + else SC_FRAME_VARS_TO_PROJECT + ) + vars_to_exposure_time_average = FULL_EXPOSURE_TIME_AVERAGE_SET & vars_to_bin + + for i_pset, pset_path in enumerate(psets): + logger.debug(f"Processing {pset_path}") + pset_ds = load_cdf(pset_path) + + # Store the first PSET esa_energy_step values and make sure every PSET + # contains the same set of esa_energy_step values. + # TODO: Correctly handle PSETs with different esa_energy_step values. + if i_pset == 0: + cached_esa_steps = pset_ds["esa_energy_step"].values.copy() + esa_ds = esa_energy_df( + l2_ancillary_path_dict["esa-energies"], + pset_ds["esa_energy_step"].values, + ).to_xarray() + energy_kev = esa_ds["nominal_central_energy"] + if not np.array_equal(cached_esa_steps, pset_ds["esa_energy_step"].values): + raise ValueError( + "All PSETs must have the same set of esa_energy_step values." + ) + + pset_processed = process_single_pset( + pset_ds, + energy_kev, + descriptor, + vars_to_exposure_time_average, + ) - output_map.data_1d.update(calculate_ena_signal_rates(output_map.data_1d)) - output_map.data_1d.update( - calculate_ena_intensity( - output_map.data_1d, geometric_factors_path, esa_energies_path + hi_pset = HiPointingSet(pset_processed) + + for spin_phase, map in rect_maps.items(): + # Project (bin) the PSET variables into the map pixels + directional_mask = get_pset_directional_mask(pset_processed, spin_phase) + map.project_pset_values_to_map( + hi_pset, list(vars_to_bin), pset_valid_mask=directional_mask + ) + + for map in rect_maps.values(): + # Finish the exposure time weighted mean calculation of backgrounds + # Allow divide by zero to fill set pixels with zero exposure time to NaN + with np.errstate(divide="ignore"): + map.data_1d[vars_to_exposure_time_average] /= map.data_1d["exposure_factor"] + + # Add ESA energy data to the map dataset for use in rate/intensity calculations + energy_delta = esa_ds["bandpass_fwhm"] / 2 + map.data_1d["energy_delta_minus"] = energy_delta + map.data_1d["energy_delta_plus"] = energy_delta + # Add energy as an auxiliary coordinate (keV values indexed by esa_energy_step) + map.data_1d = map.data_1d.assign_coords( + energy=("esa_energy_step", esa_ds["nominal_central_energy"].values) ) + + return rect_maps + + +# ============================================================================= +# PSET PROCESSING +# ============================================================================= + + +def process_single_pset( + pset: xr.Dataset, + energy_kev: xr.DataArray, + descriptor: MapDescriptor, + vars_to_exposure_time_average: set[str], +) -> xr.Dataset: + """ + Process a single pointing set for projection to the sky map. + + Parameters + ---------- + pset : xarray.Dataset + Single pointing set dataset to process. + energy_kev : xarray.DataArray + Central energy values in keV for the ESA energy steps. + descriptor : imap_processing.ena_maps.utils.naming.MapDescriptor + Map descriptor containing processing configuration. + vars_to_exposure_time_average : set of str + Set of variable names that need to be multiplied by exposure factor + for weighted averaging. + + Returns + ------- + xarray.Dataset + Processed pointing set ready for projection. + """ + # Step 1: Rename some PSET vars to match L2 variables + pset_processed = pset.rename(HiPointingSet.l1c_to_l2_var_mapping) + + # Step 2: Add obs_date variable to be used in determining a map mean obs_date + mid_time = ( + pset_processed["epoch"].values[0] + pset_processed["epoch_delta"].values[0] / 2 + ) + pset_processed["obs_date"] = xr.full_like( + pset_processed["exposure_factor"], float(mid_time) ) - output_map.data_1d["obs_date"].data = output_map.data_1d["obs_date"].data.astype( - np.int64 + # Step 3: Add spacecraft position and velocity + pset_processed = add_spacecraft_position_and_velocity_to_pset(pset_processed) + + # Step 4: Optionally apply Compton-Getting correction for heliocentric frame + if descriptor.frame_descriptor == "hf": + # convert esa nominal central energy from keV to eV + esa_energy_ev = energy_kev * 1000 + pset_processed = apply_compton_getting_correction(pset_processed, esa_energy_ev) + + # Step 5: Calculate ram mask + pset_processed = calculate_ram_mask(pset_processed) + + # Step 6: Multiply variables that need to be exposure time weighted average by + # exposure factor. + for var in vars_to_exposure_time_average: + if var in pset_processed: + pset_processed[var] *= pset_processed["exposure_factor"] + + return pset_processed + + +# ============================================================================= +# RATES AND INTENSITIES CALCULATIONS +# ============================================================================= + + +def calculate_all_rates_and_intensities( + map_ds: xr.Dataset, + l2_ancillary_path_dict: dict[str, Path], + descriptor: MapDescriptor, +) -> xr.Dataset: + """ + Calculate rates and intensities with proper error propagation. + + This function orchestrates the full rate and intensity calculation pipeline + including signal rates, intensities, coordinate transformations, and optional + Compton-Getting corrections for heliocentric frame maps. + + Parameters + ---------- + map_ds : xarray.Dataset + Map dataset with projected PSET data (counts, exposure_factor, bg_rate, + energy_delta_minus, energy_delta_plus, etc.) and an `energy` coordinate + containing the ESA nominal central energies in keV. + l2_ancillary_path_dict : dict[str, pathlib.Path] + Mapping containing ancillary file descriptors as keys and file paths as + values. Required keys are: ["cal-prod", "esa-energies", "esa-eta-fit-factors"]. + descriptor : imap_processing.ena_maps.utils.naming.MapDescriptor + Map descriptor containing processing configuration. + + Returns + ------- + map_ds : xarray.Dataset + Map dataset with calculated rates, intensities, and uncertainties. + """ + # Step 1: Calculate ENA signal rates + logger.debug("Calculating ENA signal rates") + map_ds = calculate_ena_signal_rates(map_ds) + + # Step 2: Calculate ENA intensities + logger.debug("Calculating ENA intensities") + map_ds = calculate_ena_intensity(map_ds, l2_ancillary_path_dict, descriptor) + + # Step 3: Handle obs_date variable type conversion + # TODO: Handle variable types correctly in RectangularSkyMap.build_cdf_dataset + obs_date = map_ds["obs_date"] + # Replace non-finite values with the int64 sentinel before casting + map_ds["obs_date"] = xr.where( + np.isfinite(obs_date), + obs_date.astype("int64"), + np.int64(-9223372036854775808), ) - # TODO: Figure out how to compute obs_date_range (stddev of obs_date) - output_map.data_1d["obs_date_range"] = xr.zeros_like(output_map.data_1d["obs_date"]) + map_ds["obs_date_range"] = xr.zeros_like(map_ds["obs_date"]) - # Rename and convert coordinate from esa_energy_step energy - esa_energies = esa_energy_lookup( - esa_energies_path, output_map.data_1d["esa_energy_step"].data + # Step 4: Swap esa_energy_step dimension for energy coordinate + map_ds = map_ds.swap_dims({"esa_energy_step": "energy"}) + map_ds = map_ds.drop_vars( + ["esa_energy_step", "esa_energy_step_label"], errors="ignore" ) - output_map.data_1d = output_map.data_1d.rename({"esa_energy_step": "energy"}) - output_map.data_1d = output_map.data_1d.assign_coords(energy=esa_energies) - # Set the energy_step_delta values - # TODO: get the correct energy delta values (they are set to NaN) in - # output_map.build_cdf_dataset() - output_map.data_1d = output_map.data_1d.drop("esa_energy_step_label") + # Step 5: Apply Compton-Getting interpolation for heliocentric frame maps + if descriptor.frame_descriptor == "hf": + logger.debug("Applying Compton-Getting interpolation for heliocentric frame") + # Convert energy coordinate from keV to eV for interpolation + esa_energy_ev = map_ds["energy"] * 1000 + + # Hi does not want to apply the flux correction to the systematic error. + map_ds = interpolate_map_flux_to_helio_frame( + map_ds, + esa_energy_ev, # ESA energies in eV + esa_energy_ev, # heliocentric energies (same as ESA energies) + ["ena_intensity"], + update_sys_err=False, # Hi does not update the systematic error + ) + # Drop any esa_energy_step_label that may have been re-added + map_ds = map_ds.drop_vars(["esa_energy_step_label"], errors="ignore") + + # Step 6: Clean up intermediate variables + map_ds = cleanup_intermediate_variables(map_ds) - return output_map + return map_ds -def calculate_ena_signal_rates(map_ds: xr.Dataset) -> dict[str, xr.DataArray]: +def calculate_ena_signal_rates(map_ds: xr.Dataset) -> xr.Dataset: """ Calculate the ENA signal rates. Parameters ---------- map_ds : xarray.Dataset - Map dataset that has counts, exposure_times, and background_rates calculated. + Map dataset that has counts, exposure_factor, and bg_rate calculated. Returns ------- - signal_rates : dict[str, xarray.DataArray] - ENA signal rates computed from the binned PSET data. + map_ds : xarray.Dataset + Map dataset with new variables: ena_signal_rates, ena_signal_rate_stat_unc. """ - signal_rate_vars = {} # Allow divide by zero to set pixels with zero exposure time to NaN with np.errstate(divide="ignore"): # Calculate the ENA Signal Rate - signal_rate_vars["ena_signal_rates"] = ( - map_ds["counts"] / map_ds["exposure_factor"] - map_ds["bg_rates"] + map_ds["ena_signal_rates"] = ( + map_ds["counts"] / map_ds["exposure_factor"] - map_ds["bg_rate"] ) # Calculate the ENA Signal Rate Uncertainties # The minimum count uncertainty is 1 for any pixel that has non-zero @@ -195,24 +406,23 @@ def calculate_ena_signal_rates(map_ds: xr.Dataset) -> dict[str, xr.DataArray]: # minimum count uncertainty because division by zero exposure time results # in the correct NaN value. min_counts_unc = xr.ufuncs.maximum(map_ds["counts"], 1) - signal_rate_vars["ena_signal_rate_stat_unc"] = ( + map_ds["ena_signal_rate_stat_unc"] = ( np.sqrt(min_counts_unc) / map_ds["exposure_factor"] ) # Statistical fluctuations may result in a negative ENA signal rate after # background subtraction. A negative signal rate is nonphysical. See IMAP Hi # Algorithm Document section 3.1.1 - signal_rate_vars["ena_signal_rates"].values[ - signal_rate_vars["ena_signal_rates"].values < 0 - ] = 0 - return signal_rate_vars + map_ds["ena_signal_rates"].values[map_ds["ena_signal_rates"].values < 0] = 0 + + return map_ds def calculate_ena_intensity( map_ds: xr.Dataset, - geometric_factors_path: str | Path, - esa_energies_path: str | Path, -) -> dict[str, xr.DataArray]: + l2_ancillary_path_dict: dict[str, Path], + descriptor: MapDescriptor, +) -> xr.Dataset: """ Calculate the ena intensities. @@ -220,56 +430,365 @@ def calculate_ena_intensity( ---------- map_ds : xarray.Dataset Map dataset that has ena_signal_rate fields calculated. - geometric_factors_path : str or pathlib.Path - Where to get the geometric factors from. - esa_energies_path : str or pathlib.Path - Where to get the energies from. + l2_ancillary_path_dict : dict[str, pathlib.Path] + Mapping containing ancillary file descriptors as keys and file paths as + values. Require keys are: ["cal-prod", "esa-energies", "esa-eta-fit-factors"]. + descriptor : imap_processing.ena_maps.utils.naming.MapDescriptor + Output filename descriptor. Contains full configuration for the options + of how to generate the map. For this function, the principal data string + is used to determine if a flux correction should be applied. Returns ------- - intensity_vars : dict[str, xarray.DataArray] - ENA Intensity with statistical and systematic uncertainties. + map_ds : xarray.Dataset + Map dataset with new variables: ena_intensity, ena_intensity_stat_uncert, + ena_intensity_sys_err. """ - # TODO: Implement geometric factor lookup - if geometric_factors_path: - raise NotImplementedError - geometric_factor = xr.DataArray( - np.ones((map_ds["esa_energy_step"].size, map_ds["calibration_prod"].size)), - coords=[map_ds["esa_energy_step"], map_ds["calibration_prod"]], + # read calibration product configuration file + cal_prod_df = CalibrationProductConfig.from_csv(l2_ancillary_path_dict["cal-prod"]) + # reindex_like removes esa_energy_steps and calibration products not in the + # map_ds esa_energy_step and calibration_product coordinates + geometric_factor = cal_prod_df.to_xarray().reindex_like(map_ds)["geometric_factor"] + geometric_factor = geometric_factor.transpose( + *[coord for coord in map_ds.coords if coord in geometric_factor.coords] ) - - esa_energy = esa_energy_lookup(esa_energies_path, map_ds["esa_energy_step"].data) + energy_df = esa_energy_df( + l2_ancillary_path_dict["esa-energies"], map_ds["esa_energy_step"].data + ) + esa_energy = energy_df.to_xarray()["nominal_central_energy"] # Convert ENA Signal Rate to Flux - flux_conversion_divisor = geometric_factor * esa_energy[:, np.newaxis] - intensity_vars = { - "ena_intensity": map_ds["ena_signal_rates"] / flux_conversion_divisor, - "ena_intensity_stat_unc": map_ds["ena_signal_rate_stat_unc"] - / flux_conversion_divisor, - "ena_intensity_sys_err": map_ds["bg_rates_unc"] / flux_conversion_divisor, - } + flux_conversion_divisor = geometric_factor * esa_energy + map_ds["ena_intensity"] = map_ds["ena_signal_rates"] / flux_conversion_divisor + map_ds["ena_intensity_stat_uncert"] = ( + map_ds["ena_signal_rate_stat_unc"] / flux_conversion_divisor + ) - # TODO: Correctly implement combining of calibration products. For now, just sum - # Hi groups direct events into distinct calibration products based on coincidence - # type. (See L1B processing and Hi Algorithm Document section 6.1.2) When adding - # together different calibration products, a different weighting must be used - # than exposure time. (See Hi Algorithm Document Section 3.1.2) - intensity_vars["ena_intensity"] = intensity_vars["ena_intensity"].sum( - dim="calibration_prod" + # Ignore numpy divide by zero and zero/zero warnings. Setting pixels with + # zero exposure time to NaN is the correct behavior. + with np.errstate(divide="ignore", invalid="ignore"): + map_ds["ena_intensity_sys_err"] = ( + np.sqrt(map_ds["bg_rate"] * map_ds["exposure_factor"]) + / map_ds["exposure_factor"] + / flux_conversion_divisor + ) + + # Combine calibration products using proper weighted averaging + # as described in Hi Algorithm Document Section 3.1.2 + map_ds = combine_calibration_products( + map_ds, + geometric_factor, + esa_energy, ) - intensity_vars["ena_intensity_stat_unc"] = np.sqrt( - (intensity_vars["ena_intensity_stat_unc"] ** 2).sum(dim="calibration_prod") + + if "raw" not in descriptor.principal_data: + # Flux correction + corrector = PowerLawFluxCorrector(l2_ancillary_path_dict["esa-eta-fit-factors"]) + # Apply flux correction with xarray inputs + map_ds["ena_intensity"], map_ds["ena_intensity_stat_uncert"] = ( + corrector.apply_flux_correction( + map_ds["ena_intensity"], + map_ds["ena_intensity_stat_uncert"], + esa_energy, + ) + ) + + return map_ds + + +def combine_calibration_products( + map_ds: xr.Dataset, + geometric_factors: xr.DataArray, + esa_energies: xr.DataArray, +) -> xr.Dataset: + """ + Combine calibration products using weighted averaging. + + Implements the algorithm described in Hi Algorithm Document Section 3.1.2 + for properly combining data from multiple calibration products. + + Parameters + ---------- + map_ds : xarray.Dataset + Map dataset that has preliminary intensity variables computed for each + calibration product. + geometric_factors : xarray.DataArray + Geometric factors for each calibration product and energy step. + esa_energies : xarray.DataArray + Central energies for each energy step. + + Returns + ------- + map_ds : xarray.Dataset + Map dataset with updated variables: ena_intensity, ena_intensity_stat_uncert, + ena_intensity_sys_err now combined across calibration products at each + energy level. + """ + ena_flux = map_ds["ena_intensity"] + sys_err = map_ds["ena_intensity_sys_err"] + + # Calculate improved statistical variance estimates using geometric factor + # ratios to reduce bias from Poisson uncertainty estimation + improved_stat_variance = _calculate_improved_stat_variance( + map_ds, geometric_factors, esa_energies + ) + + # Perform inverse-variance weighted averaging + # Handle divide by zero and invalid values + with np.errstate(divide="ignore", invalid="ignore"): + # Use total variance weights for flux combination + flux_weights = 1.0 / improved_stat_variance + weighted_flux_sum = (ena_flux * flux_weights).sum(dim="calibration_prod") + combined_flux = weighted_flux_sum / flux_weights.sum(dim="calibration_prod") + + map_ds["ena_intensity"] = combined_flux + # Statistical uncertainty + map_ds["ena_intensity_stat_uncert"] = np.sqrt( + 1 + / (1 / (map_ds["ena_intensity_stat_uncert"] ** 2)).sum( + dim="calibration_prod", skipna=True, min_count=1 + ) + ) + # For systematic error, just do quadrature sum over the systematic error for + # each calibration product. + map_ds["ena_intensity_sys_err"] = np.sqrt( + (sys_err**2).sum(dim="calibration_prod", skipna=True, min_count=1) + ) + + return map_ds + + +def combine_maps(sky_maps: dict[str, RectangularSkyMap]) -> RectangularSkyMap: + """ + Combine ram and anti-ram sky maps using appropriate weighting. + + For full-spin heliocentric frame maps, ram and anti-ram maps are processed + separately through the CG correction pipeline, then combined here using + inverse-variance weighting for intensity and appropriate methods for other + variables. + + Parameters + ---------- + sky_maps : dict[str, RectangularSkyMap] + Dictionary of sky maps to combine. Expected to contain either 1 map + (no combination needed) or 2 maps with "ram" and "anti" keys. + + Returns + ------- + RectangularSkyMap + Combined sky map. + """ + if len(sky_maps) not in [1, 2]: + raise ValueError(f"Expected 1 or 2 sky maps, got {len(sky_maps)}") + if len(sky_maps) == 1: + logger.debug("Only one sky map provided, returning it unchanged") + return next(iter(sky_maps.values())) + if "ram" not in sky_maps or "anti" not in sky_maps: + raise ValueError( + f"Expected sky maps with 'ram' and 'anti' keys." + f"Instead got: {sky_maps.keys()}" + ) + + logger.info("Combining ram and anti-ram maps using inverse-variance weighting.") + + ram_ds = sky_maps["ram"].data_1d + anti_ds = sky_maps["anti"].data_1d + + # Use the ram sky map as the base for the combined result + combined_map = sky_maps["ram"] + combined = ram_ds.copy() + + # Additive variables: counts and exposure_factor + combined["counts"] = ram_ds["counts"] + anti_ds["counts"] + combined["exposure_factor"] = ram_ds["exposure_factor"] + anti_ds["exposure_factor"] + + # Compute weights for ram and anti-ram based on the inverse of the variance + # (uncertainty squared). Zero weights where the variance is zero or where + # ena_intensity is not finite. The latter prevents NaNs, which get replaced + # with zeros for the sum below, from contributing to the weighted average. + ram_valid_mask = np.logical_and( + ram_ds["ena_intensity_stat_uncert"] > 0, np.isfinite(ram_ds["ena_intensity"]) + ) + weight_ram = xr.where( + ram_valid_mask, + 1 / ram_ds["ena_intensity_stat_uncert"] ** 2, + 0, ) - intensity_vars["ena_intensity_sys_err"] = np.sqrt( - (intensity_vars["ena_intensity_sys_err"] ** 2).sum(dim="calibration_prod") + anti_valid_mask = np.logical_and( + anti_ds["ena_intensity_stat_uncert"] > 0, np.isfinite(anti_ds["ena_intensity"]) ) + weight_anti = xr.where( + anti_valid_mask, + 1 / anti_ds["ena_intensity_stat_uncert"] ** 2, + 0, + ) + total_weight = weight_ram + weight_anti + + with np.errstate(divide="ignore", invalid="ignore"): + # Inverse-variance weighted average for ena_intensity + combined["ena_intensity"] = ( + ram_ds["ena_intensity"].fillna(0) * weight_ram + + anti_ds["ena_intensity"].fillna(0) * weight_anti + ) / total_weight + # ena_intensity_stat_uncertainty is combined using inverse quadrature sum + combined["ena_intensity_stat_uncert"] = np.sqrt(1 / total_weight) + + # Exposure-weighted average for systematic error + total_exp = combined["exposure_factor"] + combined["ena_intensity_sys_err"] = ( + ram_ds["ena_intensity_sys_err"] * ram_ds["exposure_factor"] + + anti_ds["ena_intensity_sys_err"] * anti_ds["exposure_factor"] + ) / total_exp + + # Exposure-weighted average for obs_date + with np.errstate(divide="ignore", invalid="ignore"): + combined["obs_date"] = ( + ram_ds["obs_date"] * ram_ds["exposure_factor"] + + anti_ds["obs_date"] * anti_ds["exposure_factor"] + ) / total_exp + + # Combined obs_date_range accounts for within-group and between-group variance + # var_combined = (w1*var1 + w2*var2)/(w1+w2) + w1*w2*(mean1-mean2)^2/(w1+w2)^2 + within_variance = ( + ram_ds["exposure_factor"] * ram_ds["obs_date_range"] ** 2 + + anti_ds["exposure_factor"] * anti_ds["obs_date_range"] ** 2 + ) / total_exp + between_variance = ( + ram_ds["exposure_factor"] + * anti_ds["exposure_factor"] + * (ram_ds["obs_date"] - anti_ds["obs_date"]) ** 2 + ) / (total_exp**2) + combined["obs_date_range"] = np.sqrt(within_variance + between_variance) + + # Re-cast obs_date and obs_date_range back to int64 after float arithmetic. + # Replace non-finite values with the int64 sentinel value. + # TODO: Handle variable types correctly in RectangularSkyMap.build_cdf_dataset + int64_sentinel = np.int64(-9223372036854775808) + combined["obs_date"] = xr.where( + np.isfinite(combined["obs_date"]), + combined["obs_date"].astype("int64"), + int64_sentinel, + ) + combined["obs_date_range"] = xr.where( + np.isfinite(combined["obs_date_range"]), + combined["obs_date_range"].astype("int64"), + int64_sentinel, + ) + + combined_map.data_1d = combined + return combined_map + + +def _calculate_improved_stat_variance( + map_ds: xr.Dataset, + geometric_factors: xr.DataArray, + esa_energies: xr.DataArray, +) -> xr.DataArray: + """ + Calculate improved statistical variances using geometric factor ratios. + + This implements the algorithm from Hi Algorithm Document Section 3.1.2: + For calibration product X, replace N_X in the uncertainty calculation with + an improved estimate using geometric factor ratios from all calibration products. + + The key insight is that we can vectorize this by first computing a geometric + factor normalized signal rate, then scaling it back for each calibration product. + + Parameters + ---------- + map_ds : xarray.Dataset + Map dataset. + geometric_factors : xr.DataArray + Geometric factors for each calibration product. + esa_energies : xarray.DataArray + Central energies for each energy step. + + Returns + ------- + improved_variance : xr.DataArray + Improved statistical variance estimates. + """ + n_calib_prods = map_ds["ena_intensity"].sizes.get("calibration_prod", 1) + + if n_calib_prods <= 1: + # No improvement possible with single calibration product + return map_ds["ena_intensity_stat_uncert"] ** 2 + + logger.debug("Computing geometric factor normalized signal rates") + + # signal_rates = counts / exposure_factor - bg_rate + # signal_rates shape is: (n_epoch, n_energy, n_cal_prod, n_spatial_pixels) + signal_rates = map_ds["ena_signal_rates"] + + # Compute geometric factor normalized signal rate (vectorized approach) + # This represents the weighted average signal rate per unit geometric factor + # geometric_factor_norm_signal_rates shape is: (n_epoch, n_energy, n_spatial_pixels) + geometric_factor_norm_signal_rates = signal_rates.sum( + dim="calibration_prod" + ) / geometric_factors.sum(dim="calibration_prod") + + # For each calibration product, the averaged signal rate estimate is: + # averaged_signal_rate_i = geometric_factor_norm_signal_rates * geometric_factor_i + # averaged_signal_rates shape is: (n_epoch, n_energy, n_cal_prod, n_spatial_pixels) + averaged_signal_rates = geometric_factor_norm_signal_rates * geometric_factors + + logger.debug("Including background rates in uncertainty calculation") + # Convert averaged signal rates back to flux uncertainties + # Total count rates for Poisson uncertainty calculation + total_count_rates_for_uncertainty = map_ds["bg_rate"] + averaged_signal_rates + + logger.debug("Computing improved flux uncertainties") + # Statistical variance: + with np.errstate(divide="ignore", invalid="ignore"): + improved_variance = total_count_rates_for_uncertainty / ( + map_ds["exposure_factor"] * (geometric_factors * esa_energies) + ) + + # Handle invalid cases by falling back to original uncertainties + improved_variance = xr.where( + ~np.isfinite(improved_variance) | (geometric_factors == 0), + map_ds["ena_intensity_stat_uncert"], + improved_variance, + ) + + return improved_variance + + +def cleanup_intermediate_variables(dataset: xr.Dataset) -> xr.Dataset: + """ + Remove intermediate variables that were only needed for calculations. + + Parameters + ---------- + dataset : xarray.Dataset + Dataset containing intermediate calculation variables. + + Returns + ------- + xarray.Dataset + Cleaned dataset with intermediate variables removed. + """ + # Remove the intermediate variables from the map + potential_vars = [ + "bg_rate", + "energy_sc", + "ena_signal_rates", + "ena_signal_rate_stat_unc", + ] + + vars_to_remove = [var for var in potential_vars if var in dataset.data_vars] + + return dataset.drop_vars(vars_to_remove) + - return intensity_vars +# ============================================================================= +# SETUP AND INITIALIZATION HELPERS +# ============================================================================= -def esa_energy_lookup( - esa_energies_path: str | Path, esa_energy_steps: np.ndarray -) -> np.ndarray: +def esa_energy_df( + esa_energies_path: str | Path, esa_energy_steps: np.ndarray | slice | None = None +) -> pd.DataFrame: """ Lookup the nominal central energy values for given esa energy steps. @@ -277,18 +796,19 @@ def esa_energy_lookup( ---------- esa_energies_path : str or pathlib.Path Location of the calibration csv file containing the lookup data. - esa_energy_steps : numpy.ndarray - The ESA energy steps to get energies for. + esa_energy_steps : numpy.ndarray, slice, or None + The ESA energy steps to get energies for. If not provided (default is None), + the full dataframe is returned. Returns ------- - esa_energies: numpy.ndarray - The nominal central energy for the given esa energy steps. + esa_energies_df: pandas.DataFrame + Full data frame from the csv file filtered to only include the + esa_energy_steps input. """ + if esa_energy_steps is None: + esa_energy_steps = slice(None) esa_energies_lut = pd.read_csv( esa_energies_path, comment="#", index_col="esa_energy_step" ) - esa_energies = esa_energies_lut.loc[esa_energy_steps][ - "nominal_central_energy" - ].values - return esa_energies + return esa_energies_lut.loc[esa_energy_steps] diff --git a/imap_processing/hi/utils.py b/imap_processing/hi/utils.py index 70006ee5ff..69738ff97c 100644 --- a/imap_processing/hi/utils.py +++ b/imap_processing/hi/utils.py @@ -1,13 +1,19 @@ """IMAP-Hi utils functions.""" +from __future__ import annotations + import re -from collections.abc import Iterable, Sequence +from collections.abc import Generator, Iterable, Sequence from dataclasses import dataclass from enum import IntEnum +from pathlib import Path +from typing import IO, Any import numpy as np import pandas as pd import xarray as xr +from numpy import typing as npt +from numpy.typing import NDArray from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes @@ -47,6 +53,16 @@ class HiConstants: Attributes ---------- + DE_CLOCK_TICK_US : int + Duration of Direct Event clock tick in microseconds. This is the time + resolution of the Direct Event time tags. See IMAP-Hi Algorithm Document + Section 2.2.5 Annotated Direct Events for more details. + DE_CLOCK_TICK_S : float + Duration of Direct Event clock tick in seconds. + This is derived from DE_CLOCK_TICK_US. + HALF_CLOCK_TICK_S : float + Half of the Direct Event clock tick duration in seconds. This is derived + from DE_CLOCK_TICK_S. TOF1_TICK_DUR : int Duration of Time-of-Flight 1 clock tick in nanoseconds. TOF2_TICK_DUR : int @@ -59,8 +75,37 @@ class HiConstants: Tuple of values indicating TOF2 does not contain a valid time. TOF3_BAD_VALUES : tuple[int] Tuple of values indicating TOF3 does not contain a valid time. + STAT_FILTER_MIN_POINTINGS : int + Minimum number of Pointings required for statistical filters. + STAT_FILTER_0_THRESHOLD_FACTOR : float + Multiplier for median comparison in Statistical Filter 0. + Values exceeding threshold_factor * median are culled. + STAT_FILTER_0_TOF_AB_LIMIT_NS : int + Maximum abs(tof_ab) in nanoseconds for AB coincidences in Filter 0. + STAT_FILTER_1_CONSECUTIVE_SIGMA : float + Sigma multiplier for consecutive interval check in Filter 1. + STAT_FILTER_1_EXTREME_SIGMA : float + Sigma multiplier for extreme outlier check in Filter 1. + STAT_FILTER_1_MIN_CONSECUTIVE : int + Minimum consecutive intervals above threshold in Filter 1. + STAT_FILTER_2_MIN_EVENTS : int + Minimum events to form a pulse cluster in Filter 2. + STAT_FILTER_2_MAX_TIME_DELTA : float + Maximum time span in seconds for events to be considered clustered + in Filter 2. + STAT_FILTER_2_BIN_PADDING : int + Number of bins to add on each side of pulse angle range in Filter 2. """ + # TODO: read DE_CLOCK_TICK_US from + # instrument status summary later. This value + # is rarely change but want to be able to change + # it if needed. It stores information about how + # fast the time was ticking. It is in microseconds. + DE_CLOCK_TICK_US = 1999 + DE_CLOCK_TICK_S = DE_CLOCK_TICK_US / 1e6 + HALF_CLOCK_TICK_S = DE_CLOCK_TICK_S / 2 + TOF1_TICK_DUR = 1 # 1 ns TOF2_TICK_DUR = 1 # 1 ns TOF3_TICK_DUR = 0.5 # 0.5 ns @@ -72,6 +117,18 @@ class HiConstants: TOF2_BAD_VALUES = (511,) TOF3_BAD_VALUES = (1023,) + # Statistical Filter tuning parameters + # See IMAP-Hi Algorithm Document Section 2.3.2.3 + STAT_FILTER_MIN_POINTINGS = 4 + STAT_FILTER_0_THRESHOLD_FACTOR = 1.5 + STAT_FILTER_0_TOF_AB_LIMIT_NS = 15 + STAT_FILTER_1_CONSECUTIVE_SIGMA = 1.8 + STAT_FILTER_1_EXTREME_SIGMA = 5.0 + STAT_FILTER_1_MIN_CONSECUTIVE = 3 + STAT_FILTER_2_MIN_EVENTS = 6 + STAT_FILTER_2_MAX_TIME_DELTA = 5000 * DE_CLOCK_TICK_S + STAT_FILTER_2_BIN_PADDING = 1 + def parse_sensor_number(full_string: str) -> int: """ @@ -256,7 +313,12 @@ class EsaEnergyStepLookupTable: def __init__(self) -> None: self.df = pd.DataFrame( - columns=["start_met", "end_met", "esa_step", "esa_energy_step"] + { + "start_met": pd.Series(dtype="float64"), + "end_met": pd.Series(dtype="float64"), + "esa_step": pd.Series(dtype="int64"), + "esa_energy_step": pd.Series(dtype="int64"), + } ) self._indexed = False @@ -392,3 +454,632 @@ def query( return results.astype(self._esa_energy_step_dtype)[0] else: return results.astype(self._esa_energy_step_dtype) + + +class _BaseConfigAccessor: + """ + Base class for configuration DataFrame accessors. + + Provides common functionality for validating and processing configuration + DataFrames with coincidence types and TOF windows. + + Parameters + ---------- + pandas_obj : pandas.DataFrame + Object to run validation and use accessor functions on. + """ + + # Subclasses must define these + index_columns: tuple[str, ...] + required_columns: tuple[str, ...] + tof_detector_pairs = ("ab", "ac1", "bc1", "c1c2") + + def __init__(self, pandas_obj: pd.DataFrame) -> None: + self._validate(pandas_obj) + self._obj = pandas_obj + self._add_coincidence_values_column() + + def _validate(self, df: pd.DataFrame) -> None: + """ + Validate the current configuration. + + Parameters + ---------- + df : pandas.DataFrame + Object to validate. + + Raises + ------ + AttributeError : If the dataframe does not pass validation. + """ + for index_name in self.index_columns: + if index_name not in df.index.names: + raise AttributeError( + f"Required index {index_name} not present in dataframe." + ) + # Verify that the Dataframe has all the required columns + for col in self.required_columns: + if col not in df.columns: + raise AttributeError(f"Required column {col} not present in dataframe.") + + def _add_coincidence_values_column(self) -> None: + """Generate and add the coincidence_type_values column to the dataframe.""" + # Add a column that consists of the coincidence type strings converted + # to integer values + self._obj["coincidence_type_values"] = self._obj.apply( + lambda row: tuple( + CoincidenceBitmap.detector_hit_str_to_int(entry) + for entry in row["coincidence_type_list"] + ), + axis=1, + ) + + @property + def calibration_product_numbers(self) -> npt.NDArray[np.int_]: + """ + Get the calibration product numbers from the current configuration. + + Returns + ------- + cal_prod_numbers : numpy.ndarray + Array of calibration product numbers from the configuration. + These are sorted in ascending order and can be arbitrary integers. + """ + return ( + self._obj.index.get_level_values("calibration_prod") + .unique() + .sort_values() + .values + ) + + +@pd.api.extensions.register_dataframe_accessor("cal_prod_config") +class CalibrationProductConfig(_BaseConfigAccessor): + """Register custom accessor for calibration product configuration DataFrames.""" + + index_columns = ( + "calibration_prod", + "esa_energy_step", + ) + required_columns = ( + "coincidence_type_list", + *[ + f"tof_{det_pair}_{limit}" + for det_pair in _BaseConfigAccessor.tof_detector_pairs + for limit in ["low", "high"] + ], + ) + + @classmethod + def from_csv(cls, path: str | Path | IO[str]) -> pd.DataFrame: + """ + Read calibration product configuration CSV file into a pandas.DataFrame. + + Parameters + ---------- + path : str or pathlib.Path or file-like object + Location of the calibration product configuration CSV file. + + Returns + ------- + dataframe : pandas.DataFrame + Validated calibration product configuration DataFrame with + coincidence_type_values column added. + """ + df = pd.read_csv( + path, + index_col=cls.index_columns, + converters={"coincidence_type_list": lambda s: tuple(s.split("|"))}, + comment="#", + ) + # Trigger the accessor to run validation and add coincidence_type_values + _ = df.cal_prod_config.number_of_products + return df + + @property + def number_of_products(self) -> int: + """ + Get the number of calibration products in the current configuration. + + Returns + ------- + number_of_products : int + The maximum number of calibration products defined in the list of + calibration product definitions. + """ + return len(self._obj.index.unique(level="calibration_prod")) + + +@pd.api.extensions.register_dataframe_accessor("background_config") +class BackgroundConfig(_BaseConfigAccessor): + """Register custom accessor for background configuration DataFrames.""" + + index_columns = ( + "calibration_prod", + "background_index", + "esa_energy_step", + ) + # Columns that must be consistent across esa_energy_step for each + # (calibration_prod, background_index) combination + tof_columns = tuple( + f"tof_{det_pair}_{limit}" + for det_pair in _BaseConfigAccessor.tof_detector_pairs + for limit in ["low", "high"] + ) + + required_columns = ( + "coincidence_type_list", + *tof_columns, + "scaling_factor", + "uncertainty", + ) + + def _validate(self, df: pd.DataFrame) -> None: + """ + Validate the background configuration. + + Extends base validation to verify: + 1. TOF windows and coincidence types are consistent across esa_energy_step + for each (calibration_prod, background_index) combination. + 2. All required columns (coincidence_type_list, TOF windows, scaling_factor, + uncertainty) are non-null for every row. + + Parameters + ---------- + df : pandas.DataFrame + DataFrame to validate. + + Raises + ------ + AttributeError + If required columns or index are missing. + ValueError + If TOF windows or coincidence types differ across ESA energy steps, + or if any required values are null/missing. + """ + super()._validate(df) + + # Check that all required columns have non-null values for every row + # This catches cases where forward-fill didn't populate values + # (e.g., missing first row in a group) or where scaling_factor/uncertainty + # are missing for some ESA steps + required_non_null = [ + "coincidence_type_list", + *self.tof_columns, + "scaling_factor", + "uncertainty", + ] + + for col in required_non_null: + null_mask = df[col].isna() + if null_mask.any(): + # Get the index values of rows with null values + null_rows = df.index[null_mask].tolist() + raise ValueError( + f"Null values found in required column '{col}' for rows: " + f"{null_rows}. All background configuration rows must have " + f"non-null values for coincidence_type_list, TOF windows, " + f"scaling_factor, and uncertainty." + ) + + # Columns that must be consistent across ESA steps + consistency_columns = [*self.tof_columns, "coincidence_type_list"] + + # Group by (calibration_prod, background_index) and check consistency + grouped = df.groupby(level=["calibration_prod", "background_index"]) + + for (cal_prod, bg_idx), group in grouped: + for col in consistency_columns: + unique_values = group[col].unique() + if len(unique_values) > 1: + raise ValueError( + f"Inconsistent {col} values across esa_energy_step for " + f"calibration_prod={cal_prod}, background_index={bg_idx}. " + f"Found values: {unique_values.tolist()}. " + f"TOF windows and coincidence types must be identical " + f"across all ESA energy steps." + ) + + def get_tof_config(self) -> pd.DataFrame: + """ + Get TOF window configuration with one row per background. + + Returns one row per (calibration_prod, background_index) combination. + Since TOF windows are validated to be consistent across esa_energy_step, + this returns the first row for each (calibration_prod, background_index) + combination containing only the TOF-related columns. + + Returns + ------- + tof_config : pandas.DataFrame + DataFrame indexed by (calibration_prod, background_index) with + coincidence_type_list, coincidence_type_values, and TOF window columns. + """ + tof_cols = [ + "coincidence_type_list", + "coincidence_type_values", + *self.tof_columns, + ] + return self._obj.groupby(level=["calibration_prod", "background_index"])[ + tof_cols + ].first() + + @classmethod + def from_csv(cls, path: str | Path | IO[str]) -> pd.DataFrame: + """ + Read background configuration CSV file into a pandas.DataFrame. + + TOF window columns and coincidence_type_list can be specified only on + the first row of each (calibration_prod, background_index) group and + will be forward-filled to subsequent rows. This reduces redundancy in + the CSV file since these values must be identical across ESA energy + steps. + + Parameters + ---------- + path : str or pathlib.Path or file-like object + Location of the background configuration CSV file. + + Returns + ------- + dataframe : pandas.DataFrame + Validated background configuration DataFrame with + coincidence_type_values column added. + """ + + def parse_coincidence_list(s: str) -> tuple | None: + """ + Parse coincidence type list, returning None for empty strings. + + Parameters + ---------- + s : str + Pipe-delimited string of coincidence types. + + Returns + ------- + tuple or None + Tuple of coincidence type strings, or None if input is empty. + """ + if pd.isna(s) or s == "": + return None + return tuple(s.split("|")) + + df = pd.read_csv( + path, + index_col=cls.index_columns, + converters={"coincidence_type_list": parse_coincidence_list}, + comment="#", + ) + + # Forward-fill TOF columns and coincidence_type_list within each + # (calibration_prod, background_index) group. This allows the CSV to + # specify these values only on the first row of each group. + fill_columns = ["coincidence_type_list", *cls.tof_columns] + df[fill_columns] = df.groupby(level=["calibration_prod", "background_index"])[ + fill_columns + ].ffill() + + # Trigger the accessor to run validation and add coincidence_type_values + _ = df.background_config.calibration_product_numbers + return df + + +def get_tof_window_mask( + de_ds: xr.Dataset, + tof_windows: dict[str, tuple[float, float]], + tof_fill_vals: dict[str, float], +) -> NDArray[np.bool_]: + """ + Generate mask indicating which DEs pass TOF window checks. + + An event passes the TOF window check for a given detector pair if its TOF value + is within the (low, high) bounds OR equals the fill value (indicating the detector + pair was not hit). + + Parameters + ---------- + de_ds : xarray.Dataset + Direct Event Dataset with TOF variables (tof_ab, tof_ac1, tof_bc1, tof_c1c2). + tof_windows : dict[str, tuple[float, float]] + Dictionary mapping TOF field names to (low, high) tuples defining the + acceptable window for each TOF measurement. + tof_fill_vals : dict[str, float] + Fill values for each TOF field - events with fill values pass the check. + If not provided, fill value handling is disabled. + + Returns + ------- + mask : numpy.ndarray + Boolean mask where True = event passes all specified TOF window checks. + """ + # Start with all True mask + n_events = len(de_ds["event_met"]) if "event_met" in de_ds.dims else 0 + if n_events == 0: + return np.array([], dtype=bool) + + combined_mask: np.ndarray = np.ones(n_events, dtype=bool) + + for tof_field, (low, high) in tof_windows.items(): + tof_array = de_ds[tof_field].values + # TOF is in window if between low/high bounds OR equals fill value + in_window = (low <= tof_array) & (tof_array <= high) + in_window |= tof_array == tof_fill_vals[tof_field] + + combined_mask &= in_window + + return combined_mask + + +def filter_events_by_coincidence( + de_ds: xr.Dataset, + coincidence_types: Sequence[int], +) -> NDArray[np.bool_]: + """ + Filter events by coincidence type. + + Parameters + ---------- + de_ds : xarray.Dataset + Direct Event Dataset with coincidence_type variable. + coincidence_types : Sequence[int] + Sequence of coincidence type integers to match. + + Returns + ------- + mask : np.ndarray + Boolean mask where True = event's coincidence_type is in the provided list. + """ + if "coincidence_type" not in de_ds: + raise ValueError("Dataset must have 'coincidence_type' variable") + + coincidence_array = de_ds["coincidence_type"].values + return np.isin(coincidence_array, list(coincidence_types)) + + +def get_bin_range_with_wrap( + first_bin: int, last_bin: int, n_bins: int, extend_by: int +) -> np.ndarray: + """ + Get bin range with wraparound and optional extension. + + Computes a range of bin indices from first_bin to last_bin, optionally + extending by a padding amount on each side, with proper wraparound + handling for circular bin structures (e.g., spin bins). + + Parameters + ---------- + first_bin : int + First bin index in the range. + last_bin : int + Last bin index in the range (may be less than first_bin if wrapping). + n_bins : int + Total number of bins (bins are 0 to n_bins-1). + extend_by : int + Number of bins to add on each side of the range. + + Returns + ------- + bins : np.ndarray + Array of bin indices in the range, with wrapping handled. + """ + # Apply extension + bot = (first_bin - extend_by) % n_bins + top = (last_bin + extend_by) % n_bins + + # Check if we need to wrap + if top >= bot: + # No wrap needed + return np.arange(bot, top + 1) + else: + # Wrap around: bins from bot to n_bins-1, then 0 to top + return np.concatenate([np.arange(bot, n_bins), np.arange(0, top + 1)]) + + +def _build_tof_fill_vals(de_ds: xr.Dataset) -> dict[str, float]: + """ + Build TOF fill values dictionary from dataset attributes. + + Parameters + ---------- + de_ds : xarray.Dataset + Direct Event dataset with TOF variables containing FILLVAL attributes. + + Returns + ------- + dict[str, float] + Dictionary mapping TOF variable names to their fill values. + """ + tof_fill_vals = {} + for pair in CalibrationProductConfig.tof_detector_pairs: + tof_var = f"tof_{pair}" + tof_fill_vals[tof_var] = de_ds[tof_var].attrs.get("FILLVAL", np.nan) + return tof_fill_vals + + +def iter_qualified_events_by_config( + de_ds: xr.Dataset, + cal_product_config: pd.DataFrame, + esa_energy_steps: NDArray[np.int_], +) -> Generator[tuple[Any, Any, NDArray[np.bool_]], None, None]: + """ + Iterate over calibration config, yielding masks for qualified events. + + For each (esa_energy_step, calibration_prod) combination in the config, + yields a mask indicating which events qualify based on BOTH coincidence_type + AND TOF window checks. + + Parameters + ---------- + de_ds : xarray.Dataset + Direct Event dataset with coincidence_type and TOF variables. + TOF variables must have FILLVAL attribute for fill value handling. + cal_product_config : pandas.DataFrame + Config DataFrame with multi-index (calibration_prod, esa_energy_step). + Must have coincidence_type_values column and TOF window columns. + esa_energy_steps : np.ndarray + ESA energy step for each event in de_ds. + + Yields + ------ + esa_energy : Any + The ESA energy step value. + config_row : namedtuple + The config row from itertuples() containing calibration product settings. + qualified_mask : np.ndarray + Boolean mask where True = event qualifies for this (esa, cal_prod). + """ + n_events = len(de_ds["event_met"]) if "event_met" in de_ds.dims else 0 + + # Build TOF fill values from dataset attributes + tof_fill_vals = _build_tof_fill_vals(de_ds) + + for esa_energy, esa_df in cal_product_config.groupby(level="esa_energy_step"): + # Mask for events at this ESA energy step + esa_mask = esa_energy_steps == esa_energy if n_events > 0 else np.array([]) + + for config_row in esa_df.itertuples(): + if n_events == 0 or not np.any(esa_mask): + yield esa_energy, config_row, np.zeros(n_events, dtype=bool) + continue + + # Apply common filtering logic + filter_mask = _filter_events_by_config_row(de_ds, config_row, tof_fill_vals) + + yield esa_energy, config_row, esa_mask & filter_mask + + +def _filter_events_by_config_row( + de_ds: xr.Dataset, + config_row: Any, + tof_fill_vals: dict[str, float], +) -> NDArray[np.bool_]: + """ + Filter events by coincidence type and TOF windows for a single config row. + + Helper function to apply common filtering logic used by both + iter_qualified_events_by_config and iter_background_events_by_config. + + Parameters + ---------- + de_ds : xarray.Dataset + Direct Event dataset with coincidence_type and TOF variables. + config_row : namedtuple + Config row from DataFrame.itertuples() containing: + - coincidence_type_values: tuple of int coincidence types + - tof__low, tof__high: TOF window bounds + tof_fill_vals : dict[str, float] + Dictionary mapping TOF variable names to their fill values. + + Returns + ------- + filter_mask : numpy.ndarray + Boolean mask where True = event matches the filter criteria. + """ + # Check coincidence type + coin_mask = filter_events_by_coincidence(de_ds, config_row.coincidence_type_values) + + # Build TOF windows dict from config row + tof_windows = { + f"tof_{pair}": ( + getattr(config_row, f"tof_{pair}_low"), + getattr(config_row, f"tof_{pair}_high"), + ) + for pair in CalibrationProductConfig.tof_detector_pairs + } + + # Check TOF windows + tof_mask = get_tof_window_mask(de_ds, tof_windows, tof_fill_vals) + + return coin_mask & tof_mask + + +def iter_background_events_by_config( + de_ds: xr.Dataset, + background_config: pd.DataFrame, +) -> Generator[tuple[Any, xr.Dataset], None, None]: + """ + Iterate over background config, yielding filtered event datasets. + + For each (calibration_prod, background_index) combination in the config, + yields the filtered dataset containing only events that match BOTH + coincidence_type AND TOF window checks. + + Unlike iter_qualified_events_by_config, this does NOT filter by ESA energy + step, as background counts are accumulated across all ESA steps. + + Parameters + ---------- + de_ds : xarray.Dataset + Direct Event dataset with coincidence_type and TOF variables. + TOF variables must have FILLVAL attribute for fill value handling. + background_config : pandas.DataFrame + Config DataFrame with multi-index (calibration_prod, background_index). + Must have coincidence_type_values column and TOF window columns. + + Yields + ------ + config_row : namedtuple + The config row from itertuples() containing background settings. + filtered_ds : xarray.Dataset + Filtered dataset containing only events matching the criteria. + """ + n_events = len(de_ds["event_met"]) + + # Build TOF fill values from dataset attributes + tof_fill_vals = _build_tof_fill_vals(de_ds) + + for config_row in background_config.itertuples(): + if n_events == 0: + # Return empty dataset + yield config_row, de_ds.isel(event_met=slice(0, 0)) + continue + + # Apply common filtering logic + filter_mask = _filter_events_by_config_row(de_ds, config_row, tof_fill_vals) + + # Return filtered dataset (no ESA energy filtering) + filtered_ds = de_ds.isel(event_met=filter_mask) + yield config_row, filtered_ds + + +def compute_qualified_event_mask( + de_ds: xr.Dataset, + cal_product_config: pd.DataFrame, + esa_energy_steps: NDArray[np.int_], +) -> NDArray[np.bool_]: + """ + Compute mask of events qualifying for ANY calibration product. + + An event qualifies if it passes BOTH coincidence_type AND TOF window + checks for ANY (calibration_prod, esa_energy_step) combination in the + configuration. + + Parameters + ---------- + de_ds : xarray.Dataset + Direct Event dataset with coincidence_type and TOF variables. + TOF variables must have FILLVAL attribute for fill value handling. + cal_product_config : pandas.DataFrame + Config DataFrame with multi-index (calibration_prod, esa_energy_step). + Must have coincidence_type_values column and TOF window columns. + esa_energy_steps : np.ndarray + ESA energy step for each event in de_ds. + + Returns + ------- + qualified_mask : np.ndarray + Boolean mask - True if event qualifies for at least one cal product. + """ + n_events = len(de_ds["event_met"]) + if n_events == 0: + return np.array([], dtype=bool) + + qualified_mask: np.ndarray = np.zeros(n_events, dtype=bool) + + for _, _, mask in iter_qualified_events_by_config( + de_ds, cal_product_config, esa_energy_steps + ): + qualified_mask |= mask + + return qualified_mask diff --git a/imap_processing/hit/hit_utils.py b/imap_processing/hit/hit_utils.py index af131f53cc..55f8b92a7b 100644 --- a/imap_processing/hit/hit_utils.py +++ b/imap_processing/hit/hit_utils.py @@ -368,7 +368,7 @@ def add_energy_variables( """ updated_ds = dataset.copy() - energy_mean = np.round( + energy_mean: np.ndarray = np.round( np.mean(np.array([energy_min_values, energy_max_values]), axis=0), 3 ).astype(np.float32) @@ -424,8 +424,8 @@ def add_summed_particle_data_to_dataset( ) # Initialize arrays for energy values - energy_min = np.zeros(len(energy_ranges), dtype=np.float32) - energy_max = np.zeros(len(energy_ranges), dtype=np.float32) + energy_min: np.ndarray = np.zeros(len(energy_ranges), dtype=np.float32) + energy_max: np.ndarray = np.zeros(len(energy_ranges), dtype=np.float32) # Compute summed data and update the dataset for i, energy_range_dict in enumerate(energy_ranges): diff --git a/imap_processing/hit/l0/decom_hit.py b/imap_processing/hit/l0/decom_hit.py index 88fee0319d..357765c08a 100644 --- a/imap_processing/hit/l0/decom_hit.py +++ b/imap_processing/hit/l0/decom_hit.py @@ -286,9 +286,9 @@ def assemble_science_frames(sci_dataset: xr.Dataset) -> xr.Dataset: f"{starting_indices[0]} packets at start of file belong to science frame " f"from previous day's ccsds file" ) - last_index_of_last_frame = starting_indices[-1] + FRAME_SIZE + last_index_of_last_frame = int(starting_indices[-1]) + FRAME_SIZE if last_index_of_last_frame: - remaining_packets = total_packets - last_index_of_last_frame + remaining_packets = int(total_packets) - last_index_of_last_frame if 0 < remaining_packets < FRAME_SIZE: print( f"{remaining_packets} packets at end of file belong to science frame " diff --git a/imap_processing/hit/l1a/hit_l1a.py b/imap_processing/hit/l1a/hit_l1a.py index 3ac84b4f52..7930195642 100644 --- a/imap_processing/hit/l1a/hit_l1a.py +++ b/imap_processing/hit/l1a/hit_l1a.py @@ -150,7 +150,9 @@ def subcom_sectorates(sci_dataset: xr.Dataset) -> xr.Dataset: # Update counts for science frames where data is available for i, mod_10 in enumerate(hdr_min_count_mod_10): - data_by_species_and_energy_range[mod_10]["counts"][i] = updated_dataset[ + # NOTE: this ignore is needed to avoid a mypy error in Git + # tests. + data_by_species_and_energy_range[mod_10]["counts"][i] = updated_dataset[ # type: ignore[index] "sectorates" ].values[i] @@ -389,8 +391,6 @@ def subset_sectored_counts( A dataset of complete sectored counts and corresponding livetime values for the processing day. """ - # TODO: Update to use fill values for partial frames rather than drop them - # Modify livetime_counter to use a new epoch coordinate # that is aligned with the original epoch dimension. This # ensures that livetime doesn't get filtered when the original @@ -427,7 +427,7 @@ def subset_sectored_counts( ) complete_sectored_counts_dataset = sectored_counts_dataset.isel(epoch=data_indices) - epoch_per_complete_set = np.repeat( + epoch_per_complete_set: np.ndarray = np.repeat( [ complete_sectored_counts_dataset.epoch[idx : idx + bin_size].mean().item() for idx in range(0, len(complete_sectored_counts_dataset.epoch), 10) @@ -612,10 +612,10 @@ def process_science( sci_dataset = decom_hit(dataset) # Create dataset for sectored data organized by species type - sectored_dataset = subcom_sectorates(sci_dataset) + # sectored_dataset = subcom_sectorates(sci_dataset) # Subset sectored data for complete sets (10 min intervals covering all species) - sectored_dataset = subset_sectored_counts(sectored_dataset, packet_date) + # sectored_dataset = subset_sectored_counts(sectored_dataset, packet_date) # TODO: # - headers are values per packet rather than per frame. Do these need to align @@ -637,11 +637,11 @@ def process_science( # Calculate uncertainties for count rates count_rates_dataset = calculate_uncertainties(count_rates_dataset) - sectored_count_rates_dataset = calculate_uncertainties(sectored_dataset) + # sectored_count_rates_dataset = calculate_uncertainties(sectored_dataset) l1a_datasets: dict = { "imap_hit_l1a_counts-standard": count_rates_dataset, - "imap_hit_l1a_counts-sectored": sectored_count_rates_dataset, + # "imap_hit_l1a_counts-sectored": sectored_count_rates_dataset, "imap_hit_l1a_direct-events": pha_raw_dataset, } diff --git a/imap_processing/hit/l1b/hit_l1b.py b/imap_processing/hit/l1b/hit_l1b.py index b170a1799a..cd6344ce2a 100644 --- a/imap_processing/hit/l1b/hit_l1b.py +++ b/imap_processing/hit/l1b/hit_l1b.py @@ -16,7 +16,6 @@ from imap_processing.hit.l1b.constants import ( FILLVAL_FLOAT32, FILLVAL_INT64, - LIVESTIM_PULSES, SECTORS, SUMMED_PARTICLE_ENERGY_RANGE_MAPPING, ) @@ -108,8 +107,7 @@ def process_science_data( logical_source = None # Calculate fractional livetime from the livetime counter - livetime = l1a_counts_dataset["livetime_counter"] / LIVESTIM_PULSES - livetime = livetime.rename("livetime") + livetime = livetime_fraction_calculation(l1a_counts_dataset["livetime_counter"]) # Process counts data to an L1B dataset based on the descriptor if descriptor == "standard-rates": @@ -302,7 +300,7 @@ def sum_livetime_10min(livetime: xr.DataArray) -> xr.DataArray: livetime_10min_sum = [ livetime[i : i + 10].sum().item() for i in range(0, len(livetime) - 9, 10) ] - livetime_expanded = np.repeat(livetime_10min_sum, 10) + livetime_expanded: np.ndarray = np.repeat(livetime_10min_sum, 10) return xr.DataArray(livetime_expanded, dims=livetime.dims, coords=livetime.coords) @@ -465,3 +463,31 @@ def process_sectored_rates_data( l1b_sectored_rates_dataset = l1b_sectored_rates_dataset.rename(rename_map) return l1b_sectored_rates_dataset + + +def livetime_fraction_calculation(livetime_counter: xr.DataArray) -> xr.DataArray: + """ + Calculate livetime fraction from the livetime counter. + + Parameters + ---------- + livetime_counter : xr.DataArray + 1D array of livetime counter values. + + Returns + ------- + xr.DataArray + 1D array of livetime fraction values. + """ + livetime_fraction = xr.zeros_like(livetime_counter, dtype=np.float32) + + # Equation 8 in section 6.2 of the algorithm document + livetime1 = livetime_counter <= 4101 + livetime2 = (livetime_counter > 4101) & (livetime_counter <= 16000) + livetime3 = livetime_counter > 16000 + + livetime_fraction[livetime1] = livetime_counter[livetime1] * 3.41e-5 + 0.14 + livetime_fraction[livetime2] = livetime_counter[livetime2] * 6.827e-5 + livetime_fraction[livetime3] = livetime_counter[livetime3] * 1.04e-9 + + return livetime_fraction diff --git a/imap_processing/hit/l2/hit_l2.py b/imap_processing/hit/l2/hit_l2.py index 57ae2daf45..8c2230b214 100644 --- a/imap_processing/hit/l2/hit_l2.py +++ b/imap_processing/hit/l2/hit_l2.py @@ -315,7 +315,7 @@ def calculate_intensities_for_a_species( dynamic_threshold_states = updated_ds["dynamic_threshold_state"].values unique_states = np.unique(dynamic_threshold_states) species_name = ( - species_variable.split("_")[0] + species_variable.split("_", maxsplit=1)[0] if "_uncert_" in species_variable else species_variable ) diff --git a/imap_processing/hit/packet_definitions/hit_packet_definitions.xml b/imap_processing/hit/packet_definitions/hit_packet_definitions.xml index 4fd5514cfc..535fe626c0 100644 --- a/imap_processing/hit/packet_definitions/hit_packet_definitions.xml +++ b/imap_processing/hit/packet_definitions/hit_packet_definitions.xml @@ -1,6 +1,6 @@ - + @@ -141,18 +141,19 @@ + + + - + - + + - - - @@ -178,6 +179,9 @@ + + + @@ -2363,7 +2367,7 @@ CCSDS Packet Sec Header - + 262 byte chunks of science data diff --git a/imap_processing/ialirt/calculate_ingest.py b/imap_processing/ialirt/calculate_ingest.py index 75a7b547f8..e173c03748 100644 --- a/imap_processing/ialirt/calculate_ingest.py +++ b/imap_processing/ialirt/calculate_ingest.py @@ -1,133 +1,79 @@ -"""Packet ingest and tcp connection times for each station.""" +"""Packet ingest times and rates for each station.""" import logging from datetime import datetime, timedelta, timezone from typing import Any -from imap_processing.ialirt.constants import STATIONS - logger = logging.getLogger(__name__) +STATIONS = ["Kiel", "UKSA", "tlmrelay"] + -def find_tcp_connections( - start_file_creation: datetime, - end_file_creation: datetime, - lines: list, - realtime_summary: dict, -) -> dict: +def packets_created(start_file_creation: datetime, lines: list) -> dict: """ - Find tcp connection time ranges for ground station from log lines. + Find timestamps and rates when packets were ingested based on log lines. Parameters ---------- start_file_creation : datetime File creation time of last file minus 48 hrs. - end_file_creation : datetime - File creation time of last file. lines : list All lines of log files. - realtime_summary : dict - Input dictionary containing ingest parameters. Returns ------- - realtime_summary : dict - Output dictionary with tcp connection info. + station_dict : dict + Timestamps and rates when packets were ingested. """ - current_starts: dict[str, datetime | None] = {} + station_dict: dict[str, dict[str, list[Any]]] = { + station: {"last_data_received": [], "rate_kbps": []} + for station in list(STATIONS) + } + + station_year: dict[str, int] = { + station: start_file_creation.year for station in station_dict + } + prev_doy: dict[str, int | None] = {station: None for station in station_dict} for line in lines: - if "antenna partner connection is" not in line: - continue - - timestamp_str = line.split(" ")[0] - msg = " ".join(line.split(" ")[1:]) - station = msg.split(" antenna")[0] - - if station not in realtime_summary["connection_times"]: - realtime_summary["connection_times"][station] = [] - if station not in realtime_summary["stations"]: - realtime_summary["stations"].append(station) - - timestamp = datetime.strptime(timestamp_str, "%Y/%j-%H:%M:%S.%f") - - if f"{station} antenna partner connection is up." in line: - current_starts[station] = timestamp - - elif f"{station} antenna partner connection is down!" in line: - start = current_starts.get(station) - if start is not None: - realtime_summary["connection_times"][station].append( - { - "start": datetime.isoformat(start), - "end": datetime.isoformat(timestamp), - } + # If line begins with a digit and the station is present. + if line.split()[0].isdigit() and line.split()[1] in STATIONS: + # Get bps rate. + rate = float(line.split()[-1]) + # Get last data received. + data_last_received = line.split()[2] + # Get day of year. + doy = int(data_last_received[:3]) + # Get station. + station = line.split()[1] + + # Handle end of year rollover + prev = prev_doy[station] + + if prev is not None and doy < prev and prev > 300 and doy < 30: + station_year[station] += 1 + + prev_doy[station] = doy + + dt = ( + datetime.strptime( + f"{station_year[station]}/{data_last_received}", + "%Y/%j-%H:%M:%S", ) - current_starts[station] = None - else: - # No matching "up" - realtime_summary["connection_times"][station].append( - { - "start": datetime.isoformat(start_file_creation), - "end": datetime.isoformat(timestamp), - } - ) - current_starts[station] = None - - # Handle hanging "up" at the end of file - for station, start in current_starts.items(): - if start is not None: - realtime_summary["connection_times"][station].append( - { - "start": datetime.isoformat(start), - "end": datetime.isoformat(end_file_creation), - } + .replace(tzinfo=timezone.utc) + .isoformat() + .replace("+00:00", "Z") ) + if dt not in station_dict[station]["last_data_received"]: + station_dict[station]["last_data_received"].append(dt) + station_dict[station]["rate_kbps"].append(rate) - # Filter out connection windows that are completely outside the time window - for station in realtime_summary["connection_times"]: - realtime_summary["connection_times"][station] = [ - window - for window in realtime_summary["connection_times"][station] - if datetime.fromisoformat(window["end"]) >= start_file_creation - and datetime.fromisoformat(window["start"]) <= end_file_creation - ] - - return realtime_summary - - -def packets_created(start_file_creation: datetime, lines: list) -> list: - """ - Find timestamps when packets were created based on log lines. - - Parameters - ---------- - start_file_creation : datetime - File creation time of last file minus 48 hrs. - lines : list - All lines of log files. - - Returns - ------- - packet_times : list - List of datetime objects when packets were created. - """ - packet_times = [] - - for line in lines: - if "Renamed iois_1_packets" in line: - timestamp_str = line.split(" ")[0] - timestamp = datetime.strptime(timestamp_str, "%Y/%j-%H:%M:%S.%f") - # Possible that data extends further than 48 hrs in the past. - if timestamp >= start_file_creation: - packet_times.append(timestamp) - - return packet_times + return station_dict def format_ingest_data(last_filename: str, log_lines: list) -> dict: """ - Format TCP connection and packet ingest data from multiple log files. + Format packet ingest times and rates from log file. Parameters ---------- @@ -139,8 +85,7 @@ def format_ingest_data(last_filename: str, log_lines: list) -> dict: Returns ------- realtime_summary : dict - Structured output with TCP connection windows per station - and global packet ingest timestamps. + Structured output with packet receipt info per station. Notes ----- @@ -149,34 +94,13 @@ def format_ingest_data(last_filename: str, log_lines: list) -> dict: "summary": "I-ALiRT Real-time Ingest Summary", "generated": "2025-08-07T21:36:09Z", "time_format": "UTC (ISOC)", - "stations": [ - "Kiel" - ], "time_range": [ - "2025-07-30T23:00:00", - "2025-07-31T02:00:00" - ], - "packet_ingest": [ - "2025-07-31T00:00:00", - "2025-07-31T02:01:00" + "2025-01-21T09:50:58Z", + "2025-01-21T09:55:58Z" ], - "connection_times": { - "Kiel": [ - { - "start": "2025-07-30T23:00:00", - "end": "2025-07-31T00:15:00" - }, - { - "start": "2025-07-31T02:00:00", - "end": "2025-07-31T02:00:00" - } - ] - } + "Kiel": {"last_data_received": ["2025-01-21T09:50:58Z", "2025-01-21T09:51:58Z"], + "rate_kbps": [2.0, 2.0]} } - - where time_range is the overall time range of the data, - packet_ingest contains timestamps when packets were finalized, - and tcp contains connection windows for each station. """ # File creation time. last_timestamp_str = last_filename.split(".")[2] @@ -188,32 +112,21 @@ def format_ingest_data(last_filename: str, log_lines: list) -> dict: hours=48 ) + # Parse file. + station_dict = packets_created(start_of_time, log_lines) + realtime_summary: dict[str, Any] = { "summary": "I-ALiRT Real-time Ingest Summary", "generated": datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ"), "time_format": "UTC (ISOC)", - "stations": list(STATIONS), "time_range": [ start_of_time.isoformat(), end_of_time.isoformat(), ], # Overall time range of the data - "packet_ingest": [], # Global packet ingest times - "connection_times": { - station: [] for station in list(STATIONS) - }, # Per-station TCP connection windows + "stations": list(STATIONS), + **station_dict, } - # TCP connection data for each station - realtime_summary = find_tcp_connections( - start_of_time, end_of_time, log_lines, realtime_summary - ) - - # Global packet ingest timestamps - packet_times = packets_created(start_of_time, log_lines) - realtime_summary["packet_ingest"] = [ - pkt_time.isoformat() for pkt_time in packet_times - ] - logger.info(f"Created ingest files for {realtime_summary['time_range']}") return realtime_summary diff --git a/imap_processing/ialirt/constants.py b/imap_processing/ialirt/constants.py index 9c1d527f11..898df1c41f 100644 --- a/imap_processing/ialirt/constants.py +++ b/imap_processing/ialirt/constants.py @@ -1,6 +1,7 @@ """Module for constants and useful shared classes used in I-ALiRT processing.""" from dataclasses import dataclass +from datetime import time from typing import NamedTuple import numpy as np @@ -40,6 +41,13 @@ class IalirtSwapiConstants: e_charge = 1.602176634e-19 # electronic charge, [C] speed_coeff = np.sqrt(2 * e_charge / prot_mass) / 1e3 + # temporary correction factor based on WIND data available + # overlapping with the first ~month of SWAPI data. + # to be replaced once SWAPI's L3 processing pipeline is finalized + # this will increase the model count by a factor of e^1, + # changing the output density by a factor of e^-1. + temporary_density_factor = np.exp(1) + class StationProperties(NamedTuple): """Class that represents properties of ground stations.""" @@ -48,22 +56,48 @@ class StationProperties(NamedTuple): latitude: float # latitude in degrees altitude: float # altitude in kilometers min_elevation_deg: float # minimum elevation angle in degrees + schedule_start: time | None = None # station schedule start + schedule_end: time | None = None # station schedule end -# Verified by Kiel and KSWC Observatory staff. -# Notes: the KSWC station is not yet operational, -# but will have the following properties: -# "KSWC": StationProperties( -# longitude=126.2958, # degrees East -# latitude=33.4273, # degrees North -# altitude=0.1, # approx 100 meters -# min_elevation_deg=5, # 5 degrees is the requirement -# ), +# Verified by Observatory staff. STATIONS = { + "Formosa": StationProperties( + longitude=-47.256408, # degrees East (negative = West) + latitude=-15.578032, # degrees North (negative = South) + altitude=0.968, # kilometers (~968 meters) + min_elevation_deg=5, # 5 degrees is the requirement + ), "Kiel": StationProperties( longitude=10.1808, # degrees East latitude=54.2632, # degrees North altitude=0.1, # approx 100 meters min_elevation_deg=5, # 5 degrees is the requirement - ) + schedule_start=None, + schedule_end=None, + ), + "Korea": StationProperties( + longitude=126.2958, # degrees East + latitude=33.4273, # degrees North + altitude=0.1, # approx 100 meters + min_elevation_deg=5, # 5 degrees is the requirement + schedule_start=None, + schedule_end=None, + ), + "Manaus": StationProperties( + longitude=-59.969319, # degrees East (negative = West) + latitude=-2.891215, # degrees North (negative = South) + altitude=0.9578, # approx 957.8 meters + min_elevation_deg=5, # 5 degrees is the requirement + schedule_start=None, + schedule_end=None, + ), + "SANSA": StationProperties( + longitude=27.714, # degrees East (negative = West) + latitude=-25.888, # degrees North (negative = South) + altitude=1.542, # approx 1542 meters + min_elevation_deg=2, # 5 degrees is the requirement + schedule_start=None, + schedule_end=None, + ), } diff --git a/imap_processing/ialirt/generate_coverage.py b/imap_processing/ialirt/generate_coverage.py index 4122b73a39..99bbc699d9 100644 --- a/imap_processing/ialirt/generate_coverage.py +++ b/imap_processing/ialirt/generate_coverage.py @@ -4,7 +4,7 @@ import numpy as np -from imap_processing.ialirt.constants import STATIONS +from imap_processing.ialirt.constants import STATIONS, StationProperties from imap_processing.ialirt.process_ephemeris import calculate_azimuth_and_elevation from imap_processing.spice.time import et_to_utc, str_to_et @@ -12,7 +12,7 @@ logger = logging.getLogger(__name__) ALL_STATIONS = [ - *STATIONS.keys(), + "Kiel", "DSS-24", "DSS-25", "DSS-26", @@ -25,13 +25,64 @@ "DSS-56", "DSS-74", "DSS-75", + "DSS-43", ] -def generate_coverage( +def create_schedule_mask( + station: StationProperties, time_range: np.ndarray +) -> np.ndarray: + """ + Create a boolean mask based on the static daily operating schedule. + + Parameters + ---------- + station : StationProperties + Ground station configuration. + time_range : np.ndarray + Array of ephemeris time (ET) values corresponding to the + coverage time. + + Returns + ------- + schedule_mask : np.ndarray + Boolean array True is operating window. + """ + if station.schedule_start is None and station.schedule_end is None: + return np.ones(time_range.shape, dtype=bool) + + utc_times = et_to_utc(time_range, format_str="ISOC") + utc_dt = utc_times.astype("datetime64[s]") + + # seconds since midnight (UTC), vectorized + sec_of_day = (utc_dt - utc_dt.astype("datetime64[D]")) / np.timedelta64(1, "s") + + schedule_mask = np.ones(time_range.shape, dtype=bool) + + if station.schedule_start is not None: + start_sec = ( + station.schedule_start.hour * 3600 + + station.schedule_start.minute * 60 + + station.schedule_start.second + ) + schedule_mask &= sec_of_day >= start_sec + + if station.schedule_end is not None: + end_sec = ( + station.schedule_end.hour * 3600 + + station.schedule_end.minute * 60 + + station.schedule_end.second + ) + schedule_mask &= sec_of_day <= end_sec + + return schedule_mask + + +def generate_coverage( # noqa: PLR0912 start_time: str, outages: dict | None = None, dsn: dict | None = None, + uksa: list | None = None, ) -> tuple[dict, dict]: """ Build the output dictionary containing coverage and outage time for each station. @@ -44,6 +95,8 @@ def generate_coverage( Dictionary of outages for each station. dsn : dict, optional Dictionary of Deep Space Network (DSN) stations. + uksa : list, optional + List of UKSA contacts. Returns ------- @@ -53,7 +106,7 @@ def generate_coverage( Outage times per station. """ duration_seconds = 24 * 60 * 60 # 86400 seconds in 24 hours - time_step = 3600 # 1 hr in seconds + time_step = 5 * 60 # 5 min in seconds stations = { "Kiel": STATIONS["Kiel"], @@ -65,10 +118,10 @@ def generate_coverage( stop_et_input = start_et_input + duration_seconds time_range = np.arange(start_et_input, stop_et_input, time_step) - total_visible_mask = np.zeros(time_range.shape, dtype=bool) + total_visible_mask: np.ndarray = np.zeros(time_range.shape, dtype=bool) # Precompute DSN outage mask for non-DSN stations - dsn_outage_mask = np.zeros(time_range.shape, dtype=bool) + dsn_outage_mask: np.ndarray = np.zeros(time_range.shape, dtype=bool) if dsn: for dsn_contacts in dsn.values(): for start, end in dsn_contacts: @@ -76,11 +129,20 @@ def generate_coverage( end_et = str_to_et(end) dsn_outage_mask |= (time_range >= start_et) & (time_range <= end_et) - for station_name, (lon, lat, alt, min_elevation) in stations.items(): - azimuth, elevation = calculate_azimuth_and_elevation(lon, lat, alt, time_range) - visible = elevation > min_elevation + for station_name, station in stations.items(): + _azimuth, elevation = calculate_azimuth_and_elevation( + station.longitude, + station.latitude, + station.altitude, + time_range, + obsref="IAU_EARTH", + ) + visible = elevation > station.min_elevation_deg - outage_mask = np.zeros(time_range.shape, dtype=bool) + schedule_mask = create_schedule_mask(station, time_range) + visible &= schedule_mask + + outage_mask: np.ndarray = np.zeros(time_range.shape, dtype=bool) if outages and station_name in outages: for start, end in outages[station_name]: start_et = str_to_et(start) @@ -100,7 +162,7 @@ def generate_coverage( # --- DSN Stations --- if dsn: for dsn_station, contacts in dsn.items(): - dsn_visible_mask = np.zeros(time_range.shape, dtype=bool) + dsn_visible_mask: np.ndarray = np.zeros(time_range.shape, dtype=bool) for start, end in contacts: start_et = str_to_et(start) end_et = str_to_et(end) @@ -123,6 +185,16 @@ def generate_coverage( outage_dict[f"{dsn_station}"] = et_to_utc( time_range[outage_mask], format_str="ISOC" ) + if uksa: + uksa_visible_mask: np.ndarray = np.zeros(time_range.shape, dtype=bool) + for start, end in uksa: + start_et = str_to_et(start) + end_et = str_to_et(end) + uksa_visible_mask |= (time_range >= start_et) & (time_range <= end_et) + total_visible_mask |= uksa_visible_mask + coverage_dict["UKSA"] = et_to_utc( + time_range[uksa_visible_mask], format_str="ISOC" + ) # Total coverage percentage total_coverage_percent = ( @@ -131,9 +203,9 @@ def generate_coverage( coverage_dict["total_coverage_percent"] = total_coverage_percent # Ensure all stations are present in both dicts - for station in ALL_STATIONS: - coverage_dict.setdefault(station, np.array([], dtype=" NDArray: """ @@ -98,7 +102,7 @@ def get_x_y_axes(z_axis: NDArray) -> NDArray: # Take the cross product to get the X-axis. x_axis = np.cross(y_axis, z_axis) - frames = np.stack([x_axis, y_axis, z_axis], axis=1) + frames = np.stack([x_axis, y_axis, z_axis], axis=-1) return frames @@ -123,7 +127,7 @@ def compute_total_rotation( total_rotations : NDArray Instrument to inertial rotation matrices (N, 3, 3). """ - total_rotations = mount_matrix @ spin_rotations @ inertial_frames + total_rotations = inertial_frames @ spin_rotations @ mount_matrix return total_rotations @@ -133,7 +137,7 @@ def transform_instrument_vectors_to_inertial( spin_phase: NDArray, sc_inertial_right: NDArray, sc_inertial_decline: NDArray, - instrument_frame: SpiceFrame = SpiceFrame.IMAP_MAG, + instrument_frame: SpiceFrame, spacecraft_frame: SpiceFrame = SpiceFrame.IMAP_SPACECRAFT, ) -> NDArray: """ @@ -169,11 +173,13 @@ def transform_instrument_vectors_to_inertial( # Build inertial S/C frames inertial_frames = get_x_y_axes(inertial_z_axis) + spin_phase_corrected = spin_phase + SPIN_PHASE_OFFSET_DEG + # Get spin rotation matrices (around Z) in the spacecraft frame # The spin rotation happens in the spacecraft frame, not in inertial frame. # In the spacecraft frame, the spin axis is always exactly [0, 0, 1] spin_rotations = get_rotation_matrix( - np.tile([0, 0, 1], (len(spin_phase), 1)), spin_phase + np.tile([0, 0, 1], (len(spin_phase_corrected), 1)), spin_phase_corrected ) # Get static mount matrix @@ -187,7 +193,7 @@ def transform_instrument_vectors_to_inertial( # Apply to instrument vectors vectors = np.array( [ - spice.mxv(rot.T.copy(), vec) + spice.mxv(rot, vec) for rot, vec in zip(total_rotations, instrument_vectors, strict=False) ] ) diff --git a/imap_processing/ialirt/l0/parse_mag.py b/imap_processing/ialirt/l0/parse_mag.py index c51d1d12e5..04efeeb56b 100644 --- a/imap_processing/ialirt/l0/parse_mag.py +++ b/imap_processing/ialirt/l0/parse_mag.py @@ -5,6 +5,7 @@ import numpy as np import xarray as xr +from scipy.interpolate import CubicSpline from imap_processing.ialirt.l0.ialirt_spice import ( transform_instrument_vectors_to_inertial, @@ -15,7 +16,10 @@ Packet2, Packet3, ) -from imap_processing.ialirt.utils.grouping import find_groups +from imap_processing.ialirt.utils.grouping import ( + _populate_instrument_header_items, + find_groups, +) from imap_processing.ialirt.utils.time import calculate_time from imap_processing.mag.l1a.mag_l1a_data import TimeTuple from imap_processing.mag.l1b.mag_l1b import ( @@ -23,14 +27,14 @@ shift_time, ) from imap_processing.mag.l1d.mag_l1d_data import MagL1d -from imap_processing.mag.l2.mag_l2_data import MagL2L1dBase +from imap_processing.mag.l2.mag_l2_data import MagL2L1dBase, ValidFrames from imap_processing.spice.geometry import ( SpiceFrame, cartesian_to_spherical, frame_transform, spherical_to_cartesian, ) -from imap_processing.spice.time import met_to_ttj2000ns, met_to_utc, ttj2000ns_to_et +from imap_processing.spice.time import met_to_ttj2000ns, ttj2000ns_to_et logger = logging.getLogger(__name__) @@ -83,7 +87,7 @@ def get_status_data(status_values: xr.DataArray, pkt_counters: xr.DataArray) -> for pkt_num, decoder in decoders.items(): status_subset = status_values[pkt_counters == pkt_num] - decoded_packet = decoder(int(status_subset)) + decoded_packet = decoder(int(status_subset.item())) combined_packets.update(vars(decoded_packet)) return combined_packets @@ -212,13 +216,12 @@ def get_time( primary_time = TimeTuple(int(pri_coarsetm.item()), int(pri_fintm.item())) secondary_time = TimeTuple(int(sec_coarsetm.item()), int(sec_fintm.item())) - time_data_pri_met = primary_time.to_seconds() - time_data_primary_ttj2000ns = met_to_ttj2000ns(time_data_pri_met) + + time_data_primary_ttj2000ns = primary_time.to_j2000ns() time_data["primary_epoch"] = shift_time( time_data_primary_ttj2000ns, time_shift_mago ) - time_data_sec_met = secondary_time.to_seconds() - time_data_secondary_ttj2000ns = met_to_ttj2000ns(time_data_sec_met) + time_data_secondary_ttj2000ns = secondary_time.to_j2000ns() time_data["secondary_epoch"] = shift_time( time_data_secondary_ttj2000ns, time_shift_magi ) @@ -268,6 +271,9 @@ def calculate_l1b( retrieve_matrix_from_single_l1b_calibration(calibration_dataset, is_mago=False) ) + logger.info(f"calibration_matrix_mago shape: {calibration_matrix_mago.shape}.") + logger.info(f"calibration_matrix_magi shape: {calibration_matrix_magi.shape}.") + # Get time values for each group. time_data = get_time( grouped_data, group, pkt_counter, time_shift_mago, time_shift_magi @@ -385,6 +391,81 @@ def apply_gradiometry_correction( return mago_corrected, magnitude +def interpolate_spherical( + sc_inertial_right: np.ndarray, + sc_inertial_decline: np.ndarray, + sc_spin_phase: np.ndarray, + attitude_time: np.ndarray, + target_time: float, +) -> tuple: + """ + Interpolate spherical coordinates. + + Parameters + ---------- + sc_inertial_right : numpy.ndarray + Inertial right ascension for 4 packets 0 to 360 degrees, shape (4). + sc_inertial_decline : numpy.ndarray + Inertial declination for 4 packets -45 to 45 degrees, shape (4). + sc_spin_phase : numpy.ndarray + Spin phase for 4 packets 0 to 360 degrees, shape (4). + attitude_time : np.ndarray + Timestamps for all packets in ttj2000ns. + target_time : float + Time at which to apply the transformation. + Will be primary_epoch (mago vector) or secondary_epoch (magi vector). + Example: time_data['primary_epoch']. + + Returns + ------- + ra_deg np.ndarray + Interpolated right ascension based on time (deg). + dec_deg np.ndarray + Interpolated declination based on time (deg). + spin_phase_deg np.ndarray + Interpolated spin-phase based on time (deg). + """ + # Interpolate spin phase, RA, and Dec at target_time + # Convert RA/Dec to unit cartesian vectors + spherical_coords = np.stack( + [ + np.ones_like(sc_inertial_right), + sc_inertial_right, + sc_inertial_decline, + ], + axis=-1, + ) + vecs = spherical_to_cartesian(spherical_coords) + + # This was chosen instead of linear interpolation + # to account for the vector moving along a curved + # arc on the unit sphere. + spline_x = CubicSpline(attitude_time, vecs[:, 0]) + spline_y = CubicSpline(attitude_time, vecs[:, 1]) + spline_z = CubicSpline(attitude_time, vecs[:, 2]) + + # Interpolate in Cartesian space + vx = float(spline_x(target_time)) + vy = float(spline_y(target_time)) + vz = float(spline_z(target_time)) + + v_interp = np.array([vx, vy, vz]) + # Normalize vector so that its magnitude is 1. + v_interp /= np.linalg.norm(v_interp) + + # Convert back to spherical + ra_dec = cartesian_to_spherical(v_interp) + ra_deg = ra_dec[1] + dec_deg = ra_dec[2] + + # Account for discontinuities in spin phase. + spin_phase_unwrapped = np.unwrap(np.radians(sc_spin_phase)) + spin_phase_interp = np.interp(target_time, attitude_time, spin_phase_unwrapped) + spin_phase_deg = np.degrees(spin_phase_interp) % 360 + + return ra_deg, dec_deg, spin_phase_deg + + def transform_to_inertial( sc_spin_phase_rad: np.ndarray, sc_inertial_right: np.ndarray, @@ -392,6 +473,7 @@ def transform_to_inertial( attitude_time: np.ndarray, target_time: float, mag_vector: np.ndarray, + instrument_frame: SpiceFrame, ) -> np.ndarray: """ Transform vector to ECLIPJ2000. @@ -405,16 +487,15 @@ def transform_to_inertial( sc_inertial_decline : numpy.ndarray Inertial declination for 4 packets -Ο€/2 to Ο€/2 radians, shape (4). attitude_time : np.ndarray - Timestamps for the 4 packets. - Example: test_met = grouped_data["met"][ - (grouped_data["group"] == group).values]. - ttj2000ns = met_to_ttj2000ns(test_met.values). + Timestamps for all packets in ttj2000ns. target_time : float Time at which to apply the transformation. Will be primary_epoch (mago vector) or secondary_epoch (magi vector). Example: time_data['primary_epoch']. mag_vector : numpy.ndarray Vector, shape (3). + instrument_frame : SpiceFrame + SPICE frame of the instrument. Returns ------- @@ -442,35 +523,13 @@ def transform_to_inertial( sc_inertial_right = sc_inertial_right[sort_idx] sc_inertial_decline = sc_inertial_decline[sort_idx] - # Interpolate spin phase, RA, and Dec at target_time - # Convert RA/Dec to unit cartesian vectors - spherical_coords = np.stack( - [ - np.ones_like(sc_inertial_right), - np.degrees(sc_inertial_right), - np.degrees(sc_inertial_decline), - ], - axis=-1, + ra_deg, dec_deg, spin_phase_deg = interpolate_spherical( + np.degrees(sc_inertial_right), + np.degrees(sc_inertial_decline), + np.degrees(sc_spin_phase_rad), + attitude_time, + target_time, ) - vecs = spherical_to_cartesian(spherical_coords) - - # Interpolate in Cartesian space - vx = np.interp(target_time, attitude_time, vecs[:, 0]) - vy = np.interp(target_time, attitude_time, vecs[:, 1]) - vz = np.interp(target_time, attitude_time, vecs[:, 2]) - v_interp = np.array([vx, vy, vz]) - # Normalize vector so that its magnitude is 1. - v_interp /= np.linalg.norm(v_interp) - - # Convert back to spherical - ra_dec = cartesian_to_spherical(v_interp) - ra_deg = ra_dec[1] - dec_deg = ra_dec[2] - - # Account for discontinuities in spin phase. - spin_phase_unwrapped = np.unwrap(sc_spin_phase_rad) - spin_phase_interp = np.interp(target_time, attitude_time, spin_phase_unwrapped) - spin_phase_deg = np.degrees(spin_phase_interp) % 360 # Transform each into ECLIPJ2000 inertial_vector = transform_instrument_vectors_to_inertial( @@ -478,6 +537,7 @@ def transform_to_inertial( np.array([spin_phase_deg]), np.array([ra_deg]), np.array([dec_deg]), + instrument_frame, )[0] return inertial_vector @@ -561,6 +621,19 @@ def process_packet( pkt_counter = get_pkt_counter(accumulated_data["mag_status"]) accumulated_data["pkt_counter"] = pkt_counter + # Convert from incrementing uint16 (0-65535) to radians. + sc_spin_phase_rad = accumulated_data["sc_spin_phase"].astype(float) * ( + 2 * np.pi / 65535.0 + ) + sc_inertial_right = accumulated_data["sc_inertial_right"].astype(float) * ( + 0.0055 * np.pi / 180 + ) + sc_inertial_decline = accumulated_data["sc_inertial_decline"].astype(float) * ( + 0.0027 * np.pi / 180 + ) + + attitude_time = met_to_ttj2000ns(accumulated_data["met"]) + grouped_data = find_groups(accumulated_data, (0, 3), "pkt_counter", "met") unique_groups = np.unique(grouped_data["group"]) @@ -570,6 +643,7 @@ def process_packet( mago_times_all = [] magi_vectors_all = [] magi_times_all = [] + incomplete_groups = [] for group in unique_groups: # Get status values for each group. @@ -581,10 +655,7 @@ def process_packet( ] if not np.array_equal(pkt_counter, np.arange(4)): - logger.info( - f"Group {group} does not contain all values from 0 to " - f"3 without duplicates." - ) + incomplete_groups.append(group) continue # Get decoded status data. @@ -616,9 +687,9 @@ def process_packet( if status_data["sec_isvalid"] == 0: updated_vector_magi = np.full(4, -32768) - mago_calibration = l1d_calibration_dataset["URFTOORFO"][0] - magi_calibration = l1d_calibration_dataset["URFTOORFI"][0] - offsets = l1d_calibration_dataset["offsets"][0] + mago_calibration = l1d_calibration_dataset["URFTOORFO"] + magi_calibration = l1d_calibration_dataset["URFTOORFI"] + offsets = l1d_calibration_dataset["offsets"] mago_out = calibrate_and_offset_vectors( updated_vector_mago, mago_calibration, offsets, is_magi=False @@ -626,19 +697,6 @@ def process_packet( magi_out = calibrate_and_offset_vectors( updated_vector_magi, magi_calibration, offsets, is_magi=True ) - sc_spin_phase_rad = grouped_data["sc_spin_phase"][ - (grouped_data["group"] == group).values - ] - sc_inertial_right = grouped_data["sc_inertial_right"][ - (grouped_data["group"] == group).values - ] - sc_inertial_decline = grouped_data["sc_inertial_decline"][ - (grouped_data["group"] == group).values - ] - - attitude_time = met_to_ttj2000ns( - grouped_data["met"][(grouped_data["group"] == group).values] - ) # Convert to ECLIPJ2000 frame. mago_inertial_vector = transform_to_inertial( @@ -648,6 +706,7 @@ def process_packet( attitude_time, time_data["primary_epoch"], mago_out, + ValidFrames.MAGO.spice_frame, ) magi_inertial_vector = transform_to_inertial( sc_spin_phase_rad.values, @@ -656,21 +715,29 @@ def process_packet( attitude_time, time_data["secondary_epoch"], magi_out, + ValidFrames.MAGI.spice_frame, ) met = grouped_data["met"][(grouped_data["group"] == group).values] - met_all.append(met.values[0]) + met_all.append(met) mago_times_all.append(time_data["primary_epoch"]) mago_vectors_all.append(mago_inertial_vector) magi_vectors_all.append(magi_inertial_vector) magi_times_all.append(time_data["secondary_epoch"]) + if incomplete_groups: + logger.info( + f"The following mag groups were skipped due to " + f"missing or duplicate pkt_counter values: " + f"{incomplete_groups}" + ) + mago_corrected, magnitude = apply_gradiometry_correction( np.array(mago_vectors_all), np.array(mago_times_all), np.array(magi_vectors_all), np.array(magi_times_all), - l1d_calibration_dataset["gradiometer_factor"].values.squeeze(), + l1d_calibration_dataset["gradiometer_factor"].squeeze(), ) gse_vector, gsm_vector, rtn_vector = transform_to_frames( @@ -691,20 +758,51 @@ def process_packet( continue mag_data.append( - { - "apid": 478, - "met": int(met_all[i]), - "met_in_utc": met_to_utc(met_all[i]).split(".")[0], - "ttj2000ns": int(met_to_ttj2000ns(met_all[i])), + _populate_instrument_header_items(met_all[i]) + | { + "instrument": "mag", "mag_epoch": int(mago_times_all[i]), - "mag_B_GSE": [Decimal(str(v)) for v in gse_vector[i]], - "mag_B_GSM": [Decimal(str(v)) for v in gsm_vector[i]], - "mag_B_RTN": [Decimal(str(v)) for v in rtn_vector[i]], - "mag_B_magnitude": Decimal(str(magnitude[i])), - "mag_phi_B_GSM": Decimal(str(phi_gsm[i])), - "mag_theta_B_GSM": Decimal(str(theta_gsm[i])), - "mag_phi_B_GSE": Decimal(str(phi_gse[i])), - "mag_theta_B_GSE": Decimal(str(theta_gse[i])), + "mag_B_GSE": [Decimal(f"{v:.3f}") for v in gse_vector[i]], + "mag_B_GSM": [Decimal(f"{v:.3f}") for v in gsm_vector[i]], + "mag_B_RTN": [Decimal(f"{v:.3f}") for v in rtn_vector[i]], + "mag_B_magnitude": Decimal(f"{magnitude[i]:.3f}"), + "mag_phi_B_GSM": Decimal(f"{phi_gsm[i]:.3f}"), + "mag_theta_B_GSM": Decimal(f"{theta_gsm[i]:.3f}"), + "mag_phi_B_GSE": Decimal(f"{phi_gse[i]:.3f}"), + "mag_theta_B_GSE": Decimal(f"{theta_gse[i]:.3f}"), + "mag_hk_status": { + "hk1v5_warn": bool(status_data["hk1v5_warn"]), + "hk1v5_danger": bool(status_data["hk1v5_danger"]), + "hk1v5c_warn": bool(status_data["hk1v5c_warn"]), + "hk1v5c_danger": bool(status_data["hk1v5c_danger"]), + "hk1v8_warn": bool(status_data["hk1v8_warn"]), + "hk1v8_danger": bool(status_data["hk1v8_danger"]), + "hk1v8c_warn": bool(status_data["hk1v8c_warn"]), + "hk1v8c_danger": bool(status_data["hk1v8c_danger"]), + "fob_saturated": bool(status_data["fob_saturated"]), + "fib_saturated": bool(status_data["fib_saturated"]), + "mode": int(status_data["mode"]), + "icu_temp": int(status_data["icu_temp"]), + "hk2v5_warn": bool(status_data["hk2v5_warn"]), + "hk2v5_danger": bool(status_data["hk2v5_danger"]), + "hk2v5c_warn": bool(status_data["hk2v5c_warn"]), + "hk2v5c_danger": bool(status_data["hk2v5c_danger"]), + "hk3v3": int(status_data["hk3v3"]), + "hk3v3_current": int(status_data["hk3v3_current"]), + "pri_isvalid": bool(status_data["pri_isvalid"]), + "hkp8v5_warn": bool(status_data["hkp8v5_warn"]), + "hkp8v5_danger": bool(status_data["hkp8v5_danger"]), + "hkp8v5c_warn": bool(status_data["hkp8v5c_warn"]), + "hkp8v5c_danger": bool(status_data["hkp8v5c_danger"]), + "hkn8v5": int(status_data["hkn8v5"]), + "hkn8v5_current": int(status_data["hkn8v5_current"]), + "fob_temp": int(status_data["fob_temp"]), + "fib_temp": int(status_data["fib_temp"]), + "fob_range": int(status_data["fob_range"]), + "fib_range": int(status_data["fib_range"]), + "multbit_errs": bool(status_data["multbit_errs"]), + "sec_isvalid": bool(status_data["sec_isvalid"]), + }, } ) diff --git a/imap_processing/ialirt/l0/process_codice.py b/imap_processing/ialirt/l0/process_codice.py index 64df429f84..1675acd664 100644 --- a/imap_processing/ialirt/l0/process_codice.py +++ b/imap_processing/ialirt/l0/process_codice.py @@ -1,19 +1,408 @@ """Functions to support I-ALiRT CoDICE processing.""" +import datetime import logging +from collections import namedtuple from decimal import Decimal -from typing import Any +from pathlib import Path +from typing import Any, cast +import numpy as np +import pandas as pd import xarray as xr +from numpy.typing import NDArray + +from imap_processing.codice import constants +from imap_processing.codice.codice_l1a_ialirt_hi import l1a_ialirt_hi +from imap_processing.codice.codice_l1a_lo_species import l1a_lo_species +from imap_processing.codice.codice_l1b import convert_to_rates +from imap_processing.codice.codice_l2 import ( + compute_geometric_factors, + get_efficiency_lut, + get_geometric_factor_lut, + process_lo_species_intensity, +) +from imap_processing.codice.utils import process_by_table_id +from imap_processing.ialirt.utils.grouping import ( + _populate_instrument_header_items, + find_groups, +) +from imap_processing.ialirt.utils.time import calculate_time +from imap_processing.spice.time import ( + et_to_utc, + ttj2000ns_to_et, +) logger = logging.getLogger(__name__) -FILLVAL_FLOAT32 = Decimal(str(-1.0e31)) +COD_LO_COUNTER = 232 +COD_HI_COUNTER = 199 +COD_LO_RANGE = range(0, 15) +COD_HI_RANGE = range(0, 5) + +COD_LO_L2 = namedtuple( + "COD_LO_L2", + [ + "c_over_o_abundance", + "mg_over_o_abundance", + "fe_over_o_abundance", + "c_plus_6_over_c_plus_5", + "o_plus_7_over_o_plus_6", + "fe_low_over_fe_high", + ], +) + + +def process_ialirt_data_streams( + grouped_data: list[bytearray], +) -> tuple[list[str], dict[str, list[int]]]: + """ + Process each I-ALiRT science data stream to extract individual data fields. + + Each data stream is converted to binary so that each metadata and science + data field and their values can be separated out. These fields and values + eventually will be stored in CDF data/support variables. + + Parameters + ---------- + grouped_data : list[bytearray] + A list of grouped I-ALiRT data. + + Returns + ------- + science_values : list[str] + The science values / data array portion of the I-ALiRT data in the form + of a binary string. + metadata_values : dict[str, list[int]] + The extracted metadata fields and their values. + """ + # Initialize placeholders for the processed data + science_values = [] + metadata_values: dict[str, list[int]] = {} + for field in constants.IAL_BIT_STRUCTURE: + metadata_values[field] = [] + + # Process each complete data stream + for data_stream in grouped_data: + try: + # Convert the data to binary + bit_string = "".join(f"{byte:08b}" for byte in data_stream) + + # Separate the data into its individual fields + bit_position = 0 + for field in constants.IAL_BIT_STRUCTURE: + # Convert from binary to integer + value = int( + bit_string[ + bit_position : bit_position + constants.IAL_BIT_STRUCTURE[field] + ], + 2, + ) + + # If we encounter an SHCOARSE of 0, the packet is bad + if field == "SHCOARSE" and value == 0: + raise ValueError("Bad packet encountered") + + metadata_values[field].append(value) + bit_position += constants.IAL_BIT_STRUCTURE[field] + if field == "BYTE_COUNT": + byte_count = value * 8 # Convert from bytes to number of bits + + # The rest is the data field, up to the byte count + data_field = bit_string[bit_position : bit_position + byte_count] + science_values.append(data_field) + except ValueError: + pass + + return science_values, metadata_values + + +def concatenate_bytes(grouped_data: xr.Dataset, group: int, sensor: str) -> bytearray: + """ + Concatenate all data fields for a specific group into a single bytearray. + + Parameters + ---------- + grouped_data : xr.Dataset + The grouped CoDICE dataset containing cod_{sensor}_data_XX variables. + group : int + The group number to extract. + sensor : str + The sensor type, either 'lo' or 'hi'. + + Returns + ------- + current_data_stream: bytearray + The concatenated data stream for the selected group. + """ + current_data_stream = bytearray() + group_mask = (grouped_data["group"] == group).values + + cod_ranges = { + "lo": COD_LO_RANGE, + "hi": COD_HI_RANGE, + } + + # Stack all cod_* fields into a 2D NumPy array [n_rows, n_fields] + arrays = [ + grouped_data[f"cod_{sensor}_data_{field:02}"].values[group_mask] + for field in cod_ranges[sensor] + ] + + # Shape β†’ (n_fields, n_rows) + stacked = np.vstack(arrays) + + # Transpose to get (n_rows, n_fields), then flatten row-wise + flattened = stacked.T.flatten() + + # Convert to bytes and extend the stream + current_data_stream.extend(np.uint8(flattened).tobytes()) + + return current_data_stream + + +def create_xarray_dataset( + science_values: list, + metadata_values: dict, + sensor: str, +) -> xr.Dataset: + """ + Create a xarray Dataset from science and metadata values. + + Parameters + ---------- + science_values : list + List of binary strings (bit representations) for each species. + metadata_values : dict + Dictionary of metadata values. + sensor : str + The sensor type, either 'lo' or 'hi'. + + Returns + ------- + xr.Dataset + The constructed xarray Dataset compatible with l1a_lo_species(). + """ + apid = {"lo": 1152, "hi": 1168} + + packet_bytes = [ + int(bits, 2).to_bytes(len(bits) // 8, byteorder="big") + for bits in science_values + ] + + # Fake epoch time. + num_epochs = len(np.array(metadata_values["ACQ_START_SECONDS"])) + epoch = np.arange(num_epochs) + + epoch_time = xr.DataArray(epoch, name="epoch", dims=["epoch"]) + dataset = xr.Dataset(coords={"epoch": epoch_time}) + + # Metadata value for each field + for key, value in metadata_values.items(): + data = np.array(value) + dataset[key.lower()] = xr.DataArray(data, dims=["epoch"]) + + dataset["data"] = xr.DataArray(np.array(packet_bytes, dtype=object), dims=["epoch"]) + dataset["pkt_apid"] = xr.DataArray( + np.full(len(epoch), apid[sensor]), dims=["epoch"] + ) + + return dataset + + +def convert_to_intensities( + cod_hi_l1b_data: xr.Dataset, l2_lut_path: Path, species: str +) -> NDArray: + """ + Calculate intensities. + + Parameters + ---------- + cod_hi_l1b_data : xr.Dataset + L1b data. + l2_lut_path : Path + L2 LUT path. + species : str + CoDICE Hi species. + + Returns + ------- + intensity : np.array + L2 CoDICE-Hi intensities. + + Notes + ----- + Equation from section 13.1 in the CoDICE Algorithm Document. + """ + # Average of the hydrogen efficiencies. + efficiencies_df = pd.read_csv(l2_lut_path) + species_efficiency = efficiencies_df.sort_values(by="energy_bin")[ + efficiencies_df["species"] != "GF" + ] + eps_ig = species_efficiency[["group_0", "group_1", "group_2", "group_3"]].to_numpy( + float + ) + + # For omni over 3 SSDs: + g_g = efficiencies_df[efficiencies_df["species"] == "GF"][ + ["group_0", "group_1", "group_2", "group_3"] + ].to_numpy(float) + + # Calculate energy passband from L1B data + energy_passbands = ( + cod_hi_l1b_data[f"energy_{species}_plus"] + + cod_hi_l1b_data[f"energy_{species}_minus"] + ).values[:, np.newaxis] + + denom = g_g * eps_ig * energy_passbands # (15, 4) + # reshape to broadcast along h's first and third dimensions + denom = denom[None, :, None, :] + + # Rates in shape (n_spins, energy, spin_sector, inst_az - this is group) + h = cod_hi_l1b_data[species].values + + # Final intensities with same shape as h + intensity = h / denom # shape (4, 15, 4, 4); units #/(cm^2 sr s MeV/nuc) + + return intensity + + +def calculate_ratios( + cod_lo_l1b_data: xr.Dataset, + l2_lut_path: Path, + l2_geometric_factor_path: Path | None, +) -> COD_LO_L2: + """ + Calculate CoDICE-Lo L2 data products. + + Parameters + ---------- + cod_lo_l1b_data : xarray.Dataset + Data in xarray format. + l2_lut_path : Path + Efficiency lookup table. + l2_geometric_factor_path : Path + Geometric factor lookup table. + + Returns + ------- + c_over_o_abundance : float + Ratio of C over O. + mg_over_o_abundance : float + Ratio of Mg over O. + fe_over_o_abundance : float + Ratio of Fe over O. + c_plus_6_over_c_plus_5 : np.array + Ratio of C+6 over C+5. + o_plus_7_over_o_plus_6 : np.array + Ratio of O+7 over O+6. + fe_low_over_fe_high : np.array + Ratio of Fe low over Fe high. + """ + geometric_factor_lookup = get_geometric_factor_lut(None, l2_geometric_factor_path) + geometric_factors = compute_geometric_factors( + cod_lo_l1b_data, geometric_factor_lookup + ) + + efficiency_lookup = get_efficiency_lut(None, l2_lut_path) + efficiencies = efficiency_lookup[efficiency_lookup["product"] == "sw"] + intensity = process_lo_species_intensity( + cod_lo_l1b_data, + constants.LO_IALIRT_VARIABLE_NAMES, + geometric_factors, + efficiencies, + constants.SOLAR_WIND_POSITIONS, + ) + pseudo_density_dict = {} + + for species in constants.LO_IALIRT_VARIABLE_NAMES: + pseudo_density = ( + intensity[species] + * np.sqrt(cod_lo_l1b_data["energy_per_charge"]) + * np.sqrt(constants.LO_IALIRT_M_OVER_Q[species]) + ) # (epoch, esa_step, spin_sector) + + summed_pseudo_density = pseudo_density.sum(dim="esa_step").squeeze( + "spin_sector" + ) # (epoch,) + pseudo_density_dict[species] = summed_pseudo_density.values.item() + + # Denominator. + # Note that outside of this test a zero value denominator + # will lead to a null value. + # The use of zeros here is only to match the test data as + # confirmed by the instrument team. + o_abundance_denom = ( + pseudo_density_dict["oplus6"] + + pseudo_density_dict["oplus7"] + + pseudo_density_dict["oplus8"] + ) + + c_over_o_abundance_num = ( + pseudo_density_dict["cplus5"] + pseudo_density_dict["cplus6"] + ) + mg_over_o_abundance_num = pseudo_density_dict["mg"] + fe_over_o_abundance_num = ( + pseudo_density_dict["fe_loq"] + pseudo_density_dict["fe_hiq"] + ) + + if float(o_abundance_denom) != 0: + c_over_o_abundance = c_over_o_abundance_num / o_abundance_denom + mg_over_o_abundance = mg_over_o_abundance_num / o_abundance_denom + fe_over_o_abundance = fe_over_o_abundance_num / o_abundance_denom + + c_over_o_abundance = Decimal(f"{float(c_over_o_abundance):.6f}") + mg_over_o_abundance = Decimal(f"{float(mg_over_o_abundance):.6f}") + fe_over_o_abundance = Decimal(f"{float(fe_over_o_abundance):.6f}") + else: + c_over_o_abundance, mg_over_o_abundance, fe_over_o_abundance = ( + None, + None, + None, + ) + + if float(pseudo_density_dict["cplus5"]) != 0: + c_plus_6_over_c_plus_5 = ( + pseudo_density_dict["cplus6"] / pseudo_density_dict["cplus5"] + ) + + c_plus_6_over_c_plus_5 = Decimal(f"{float(c_plus_6_over_c_plus_5):.6f}") + else: + c_plus_6_over_c_plus_5 = None + + if float(pseudo_density_dict["oplus6"]) != 0: + o_plus_7_over_o_plus_6 = ( + pseudo_density_dict["oplus7"] / pseudo_density_dict["oplus6"] + ) + o_plus_7_over_o_plus_6 = Decimal(f"{float(o_plus_7_over_o_plus_6):.6f}") + else: + o_plus_7_over_o_plus_6 = None + + if float(pseudo_density_dict["fe_hiq"]) != 0: + fe_low_over_fe_high = ( + pseudo_density_dict["fe_loq"] / pseudo_density_dict["fe_hiq"] + ) + fe_low_over_fe_high = Decimal(f"{float(fe_low_over_fe_high):.6f}") + else: + fe_low_over_fe_high = None + + return COD_LO_L2( + c_over_o_abundance=c_over_o_abundance, + mg_over_o_abundance=mg_over_o_abundance, + fe_over_o_abundance=fe_over_o_abundance, + c_plus_6_over_c_plus_5=c_plus_6_over_c_plus_5, + o_plus_7_over_o_plus_6=o_plus_7_over_o_plus_6, + fe_low_over_fe_high=fe_low_over_fe_high, + ) def process_codice( dataset: xr.Dataset, -) -> tuple[list[dict[str, Any]], list[dict[str, Any]]]: + l1a_lut_path: Path, + l2_lut_path: Path, + sensor: str, + l2_geometric_factor_path: Path | None = None, +) -> tuple: """ Create final data products. @@ -21,10 +410,20 @@ def process_codice( ---------- dataset : xr.Dataset Decommed L0 data. + l1a_lut_path : Path + L1A LUT path. + l2_lut_path : Path + L2 LUT path. + sensor : str + Sensor (codice_hi or codice_lo). + l2_geometric_factor_path : Path + Optional geometric factor path based on the sensor (required by Lo). Returns ------- - codice_data : tuple[list[dict[str, Any]], list[dict[str, Any]]]: + cod_lo_data : dict + Dictionary of final data product. + codice_hi_data : dict Dictionary of final data product. Notes @@ -35,27 +434,111 @@ def process_codice( - Calculate L2 CoDICE pseudodensities (pg 37 of Algorithm Document) - Calculate the public data products """ - # For I-ALiRT SIT, the test data being used has all zeros and thus no - # groups can be found, thus there is no data to process - # TODO: Once I-ALiRT test data is acquired that actually has data in it, - # this can be turned back on - # codicelo_data = create_ialirt_dataset(CODICEAPID.COD_LO_IAL, dataset) - # codicehi_data = create_ialirt_dataset(CODICEAPID.COD_HI_IAL, dataset) + logger.info("Processing CoDICE.") + + codice_lo_data: list[dict[str, Any]] = [] + codice_hi_data: list[dict[str, Any]] = [] + + # Subsecond time conversion specified in 7516-9054 GSW-FSW ICD. + # Value of SCLK subseconds, unsigned, (LSB = 1/256 sec) + met = calculate_time(dataset["sc_sclk_sec"], dataset["sc_sclk_sub_sec"], 256) + # Add required parameters. + dataset["met"] = met + + if sensor == "codice_lo": + logger.info("Processing CoDICE-Lo.") + grouped_cod_lo_data = find_groups( + dataset, (0, COD_LO_COUNTER), "cod_lo_counter", "cod_lo_acq" + ) + unique_cod_lo_groups = np.unique(grouped_cod_lo_data["group"]) + + if sensor == "codice_hi": + logger.info("Processing CoDICE-Hi.") + grouped_cod_hi_data = find_groups( + dataset, (0, COD_HI_COUNTER), "cod_hi_counter", "cod_hi_acq" + ) + unique_cod_hi_groups = np.unique(grouped_cod_hi_data["group"]) + + if sensor == "codice_lo" and unique_cod_lo_groups.size > 0: + for group in unique_cod_lo_groups: + cod_lo_data_stream = concatenate_bytes(grouped_cod_lo_data, group, "lo") + + # Decompress binary stream + met = grouped_cod_lo_data["met"][ + (grouped_cod_lo_data["group"] == group).values + ] + + cod_lo_science_values, cod_lo_metadata_values = process_ialirt_data_streams( + [cod_lo_data_stream] + ) + cod_lo_dataset = create_xarray_dataset( + cod_lo_science_values, cod_lo_metadata_values, "lo" + ) + l1a_lo = process_by_table_id(cod_lo_dataset, l1a_lut_path, l1a_lo_species) + l1b_lo = cast( + xr.Dataset, + convert_to_rates( + l1a_lo, + "lo-ialirt", + ), + ) + mid_measurement = int((l1b_lo["epoch"][0] + l1b_lo["epoch"][-1]) // 2) + yyyymmdd = datetime.datetime.strptime( + et_to_utc(ttj2000ns_to_et(mid_measurement)), "%Y-%m-%dT%H:%M:%S.%f" + ).strftime("%Y%m%d") + l1b_lo.attrs["Logical_file_id"] = ( + f"imap_ialirt_l1_realtime_{yyyymmdd}_v000.cdf" + ) + + l2_lo = calculate_ratios(l1b_lo, l2_lut_path, l2_geometric_factor_path) + + codice_lo_data.append( + _populate_instrument_header_items(met) + | { + "instrument": f"{sensor}", + "codice_lo_epoch": int(l1a_lo["epoch"].item()), + f"{sensor}_c_over_o_abundance": l2_lo.c_over_o_abundance, + f"{sensor}_mg_over_o_abundance": l2_lo.mg_over_o_abundance, + f"{sensor}_fe_over_o_abundance": l2_lo.fe_over_o_abundance, + f"{sensor}_c_plus_6_over_c_plus_5": l2_lo.c_plus_6_over_c_plus_5, + f"{sensor}_o_plus_7_over_o_plus_6": l2_lo.o_plus_7_over_o_plus_6, + f"{sensor}_fe_low_over_fe_high": l2_lo.fe_low_over_fe_high, + } + ) - # TODO: calculate rates - # This will be done in codice.codice_l1b + if sensor == "codice_hi" and unique_cod_hi_groups.size > 0: + for group in unique_cod_hi_groups: + cod_hi_data_stream = concatenate_bytes(grouped_cod_hi_data, group, "hi") - # TODO: calculate L2 CoDICE pseudodensities - # This will be done in codice.codice_l2 + # Decompress binary stream + met = grouped_cod_hi_data["met"][ + (grouped_cod_hi_data["group"] == group).values + ] - # TODO: calculate the public data products - # This will be done in this module + cod_hi_science_values, cod_hi_metadata_values = process_ialirt_data_streams( + [cod_hi_data_stream] + ) + cod_hi_dataset = create_xarray_dataset( + cod_hi_science_values, cod_hi_metadata_values, "hi" + ) + l1a_hi = l1a_ialirt_hi(cod_hi_dataset, l1a_lut_path) + l1b_hi = convert_to_rates( + l1a_hi, + "hi-ialirt", + ) + l2_hi = convert_to_intensities(l1b_hi, l2_lut_path, "h") + # Put in Decimal format so DynamoDB can read it. + dec_l2_hi = np.vectorize(lambda x: Decimal(f"{float(x):.4f}"))( + l2_hi + ).tolist() - # Create mock dataset for I-ALiRT SIT - # TODO: Once I-ALiRT test data is acquired that actually has data in it, - # we should be able to properly populate the I-ALiRT data, but for - # now, just create lists of dicts. - cod_lo_data: list[dict[str, Any]] = [] - cod_hi_data: list[dict[str, Any]] = [] + codice_hi_data.append( + _populate_instrument_header_items(met) + | { + "instrument": f"{sensor}", + f"{sensor}_epoch": [int(epoch) for epoch in l1b_hi["epoch"]], + f"{sensor}_h": dec_l2_hi, + } + ) - return cod_lo_data, cod_hi_data + return codice_lo_data, codice_hi_data diff --git a/imap_processing/ialirt/l0/process_hit.py b/imap_processing/ialirt/l0/process_hit.py index e72a9c6633..c76e43374e 100644 --- a/imap_processing/ialirt/l0/process_hit.py +++ b/imap_processing/ialirt/l0/process_hit.py @@ -1,13 +1,17 @@ """Functions to support HIT processing.""" import logging +from decimal import Decimal import numpy as np import xarray as xr -from imap_processing.ialirt.utils.grouping import find_groups +from imap_processing.ialirt.utils.grouping import ( + _populate_instrument_header_items, + find_groups, +) from imap_processing.ialirt.utils.time import calculate_time -from imap_processing.spice.time import met_to_ttj2000ns, met_to_utc +from imap_processing.spice.time import met_to_ttj2000ns logger = logging.getLogger(__name__) @@ -127,6 +131,8 @@ def process_hit(xarray_data: xr.Dataset) -> list[dict]: Dictionary final data product. """ hit_data = [] + incomplete_groups = [] + status_groups = [] # Subsecond time conversion specified in 7516-9054 GSW-FSW ICD. # Value of SCLK subseconds, unsigned, (LSB = 1/256 sec) @@ -141,6 +147,13 @@ def process_hit(xarray_data: xr.Dataset) -> list[dict]: unique_groups = np.unique(grouped_data["group"]) for group in unique_groups: + status_values = grouped_data["hit_status"][ + (grouped_data["group"] == group).values + ] + + if np.any(status_values == 0): + status_groups.append(group) + # Subcom values for the group should be 0-59 with no duplicates. subcom_values = grouped_data["hit_subcom"][ (grouped_data["group"] == group).values @@ -148,12 +161,13 @@ def process_hit(xarray_data: xr.Dataset) -> list[dict]: # Ensure no duplicates and all values from 0 to 59 are present if not np.array_equal(subcom_values, np.arange(60)): - logger.warning( - f"Group {group} does not contain all values from 0 to " - f"59 without duplicates." - ) + incomplete_groups.append(group) continue + hit_met = int( + grouped_data["hit_met"][(grouped_data["group"] == group).values].values[0] + ) + fast_rate_1 = grouped_data["hit_fast_rate_1"][ (grouped_data["group"] == group).values ] @@ -163,28 +177,47 @@ def process_hit(xarray_data: xr.Dataset) -> list[dict]: slow_rate = grouped_data["hit_slow_rate"][ (grouped_data["group"] == group).values ] - met = int(grouped_data["met"][(grouped_data["group"] == group).values][0]) + met = grouped_data["met"][(grouped_data["group"] == group).values] l1 = create_l1(fast_rate_1, fast_rate_2, slow_rate) hit_data.append( - { - "apid": 478, - "met": int(met), - "met_in_utc": met_to_utc(met).split(".")[0], - "ttj2000ns": int(met_to_ttj2000ns(met)), - "hit_e_a_side_low_en": int(l1["IALRT_RATE_1"] + l1["IALRT_RATE_2"]), - "hit_e_a_side_med_en": int(l1["IALRT_RATE_5"] + l1["IALRT_RATE_6"]), - "hit_e_a_side_high_en": int(l1["IALRT_RATE_7"]), - "hit_e_b_side_low_en": int(l1["IALRT_RATE_11"] + l1["IALRT_RATE_12"]), - "hit_e_b_side_med_en": int(l1["IALRT_RATE_15"] + l1["IALRT_RATE_16"]), - "hit_e_b_side_high_en": int(l1["IALRT_RATE_17"]), - "hit_h_omni_med_en": int(l1["H_12_15"] + l1["H_15_70"]), - "hit_h_a_side_high_en": int(l1["IALRT_RATE_8"]), - "hit_h_b_side_high_en": int(l1["IALRT_RATE_18"]), - "hit_he_omni_low_en": int(l1["HE4_06_08"]), - "hit_he_omni_high_en": int(l1["HE4_15_70"]), + _populate_instrument_header_items(met) + | { + "instrument": "hit", + "hit_epoch": int(met_to_ttj2000ns(hit_met)), + "hit_e_a_side_low_en": Decimal( + f"{l1['IALRT_RATE_1'] + l1['IALRT_RATE_2']:.3f}" + ), + "hit_e_a_side_med_en": Decimal( + f"{l1['IALRT_RATE_5'] + l1['IALRT_RATE_6']:.3f}" + ), + "hit_e_a_side_high_en": Decimal(f"{l1['IALRT_RATE_7']:.3f}"), + "hit_e_b_side_low_en": Decimal( + f"{l1['IALRT_RATE_11'] + l1['IALRT_RATE_12']:.3f}" + ), + "hit_e_b_side_med_en": Decimal( + f"{l1['IALRT_RATE_15'] + l1['IALRT_RATE_16']:.3f}" + ), + "hit_e_b_side_high_en": Decimal(f"{l1['IALRT_RATE_17']:.3f}"), + "hit_h_omni_low_en": Decimal(f"{l1['H_06_08']:.3f}"), + "hit_h_omni_med_en": Decimal(f"{l1['H_12_15']:.3f}"), + "hit_h_a_side_high_en": Decimal(f"{l1['IALRT_RATE_8']:.3f}"), + "hit_h_b_side_high_en": Decimal(f"{l1['IALRT_RATE_18']:.3f}"), + "hit_he_omni_low_en": Decimal(f"{l1['HE4_06_08']:.3f}"), + "hit_he_omni_high_en": Decimal(f"{l1['HE4_15_70']:.3f}"), } ) + if incomplete_groups: + logger.info( + f"The following hit groups were skipped due to " + f"missing or duplicate pkt_counter values: " + f"{incomplete_groups}" + ) + if status_groups: + logger.warning( + f"The following hit groups have zero status values: {status_groups}" + ) + return hit_data diff --git a/imap_processing/ialirt/l0/process_status.py b/imap_processing/ialirt/l0/process_status.py new file mode 100644 index 0000000000..f32007c16e --- /dev/null +++ b/imap_processing/ialirt/l0/process_status.py @@ -0,0 +1,77 @@ +"""Functions to support status processing.""" + +import logging + +import xarray as xr + +from imap_processing.ialirt.utils.grouping import ( + _populate_instrument_header_items, +) +from imap_processing.ialirt.utils.time import calculate_time +from imap_processing.spice.time import met_to_ttj2000ns + +logger = logging.getLogger(__name__) + + +def process_status(xarray_data: xr.Dataset) -> list[dict]: + """ + Create L1 data dictionary. + + Parameters + ---------- + xarray_data : xr.Dataset + Parsed data. + + Returns + ------- + status_data : list[dict] + Dictionary final data product. + """ + status_data = [] + + # Subsecond time conversion specified in 7516-9054 GSW-FSW ICD. + # Value of SCLK subseconds, unsigned, (LSB = 1/256 sec) + met = calculate_time( + xarray_data["sc_sclk_sec"], xarray_data["sc_sclk_sub_sec"], 256 + ) + + # Add required parameters. + xarray_data["met"] = met + + sc_swapi_status = xarray_data["sc_swapi_status"] + sc_mag_status = xarray_data["sc_mag_status"] + sc_hit_status = xarray_data["sc_hit_status"] + sc_codice_status = xarray_data["sc_codice_status"] + sc_lo_status = xarray_data["sc_lo_status"] + sc_hi_45_status = xarray_data["sc_hi_45_status"] + sc_hi_90_status = xarray_data["sc_hi_90_status"] + sc_ultra_45_status = xarray_data["sc_ultra_45_status"] + sc_ultra_90_status = xarray_data["sc_ultra_90_status"] + sc_swe_status = xarray_data["sc_swe_status"] + sc_idex_status = xarray_data["sc_idex_status"] + sc_glows_status = xarray_data["sc_glows_status"] + sc_autonomy_status = xarray_data["sc_autonomy"] + + for i in range(len(xarray_data["met"])): + status_data.append( + _populate_instrument_header_items(met) + | { + "instrument": "spacecraft_status", + "status_epoch": int(met_to_ttj2000ns(met[i])), + "sc_swapi_status": int(sc_swapi_status[i]), + "sc_mag_status": int(sc_mag_status[i]), + "sc_hit_status": int(sc_hit_status[i]), + "sc_codice_status": int(sc_codice_status[i]), + "sc_lo_status": int(sc_lo_status[i]), + "sc_hi_45_status": int(sc_hi_45_status[i]), + "sc_hi_90_status": int(sc_hi_90_status[i]), + "sc_ultra_45_status": int(sc_ultra_45_status[i]), + "sc_ultra_90_status": int(sc_ultra_90_status[i]), + "sc_swe_status": int(sc_swe_status[i]), + "sc_idex_status": int(sc_idex_status[i]), + "sc_glows_status": int(sc_glows_status[i]), + "sc_autonomy_status": int(sc_autonomy_status[i]), + } + ) + + return status_data diff --git a/imap_processing/ialirt/l0/process_swapi.py b/imap_processing/ialirt/l0/process_swapi.py index 4666e02510..1be0277d38 100644 --- a/imap_processing/ialirt/l0/process_swapi.py +++ b/imap_processing/ialirt/l0/process_swapi.py @@ -10,14 +10,19 @@ from scipy.special import erf from imap_processing.ialirt.constants import IalirtSwapiConstants as Consts -from imap_processing.ialirt.utils.grouping import find_groups +from imap_processing.ialirt.utils.grouping import ( + _populate_instrument_header_items, + find_groups, +) from imap_processing.ialirt.utils.time import calculate_time -from imap_processing.spice.time import met_to_ttj2000ns, met_to_utc +from imap_processing.spice.time import met_to_ttj2000ns from imap_processing.swapi.l1.swapi_l1 import process_sweep_data from imap_processing.swapi.l2.swapi_l2 import SWAPI_LIVETIME logger = logging.getLogger(__name__) +NUM_IALIRT_ENERGY_STEPS = 63 + def count_rate( energy_pass: float, speed: float, density: float, temp: float @@ -52,6 +57,9 @@ def count_rate( speed = speed * 1000 # convert km/s to m/s density = density * 1e6 # convert 1/cm**3 to 1/m**3 + # see comment on Consts.temporary_density_factor + density = density * Consts.temporary_density_factor + return ( (density * Consts.eff_area * (beta / np.pi) ** (3 / 2)) * (np.exp(-beta * (center_speed**2 + speed**2 - 2 * center_speed * speed))) @@ -69,7 +77,7 @@ def optimize_pseudo_parameters( count_rates: np.ndarray, count_rate_error: np.ndarray, energy_passbands: np.ndarray, -) -> (dict)[str, list[float]]: +) -> np.ndarray: """ Find the pseudo speed (u), density (n) and temperature (T) of solar wind particles. @@ -86,47 +94,114 @@ def optimize_pseudo_parameters( Returns ------- - solution_dict : dict - Dictionary containing the optimized speed, density, and temperature values for - each sweep included in the input count_rates array. + pseudo_params : np.ndarray + Pseudo speed, pseudo density, pseudo temperature. """ - solution_dict = { # type: ignore - "pseudo_speed": [], - "pseudo_density": [], - "pseudo_temperature": [], - } - - for sweep in np.arange(count_rates.shape[0]): - current_sweep_count_rates = count_rates[sweep, :] - current_sweep_count_rate_errors = count_rate_error[sweep, :] - # Find the max count rate, and use the 5 points surrounding it - max_index = np.argmax(current_sweep_count_rates) - initial_speed_guess = np.sqrt(energy_passbands[max_index]) * Consts.speed_coeff - initial_param_guess = np.array( - [ - initial_speed_guess, - 5 * (400 / initial_speed_guess) ** 2, - 60000 * (initial_speed_guess / 400) ** 2, - ] - ) - sol = curve_fit( + # Find the max count rate, and use the 5 points surrounding it + max_index = np.argmax(count_rates) + initial_speed_guess = np.sqrt(energy_passbands[max_index]) * Consts.speed_coeff + initial_param_guess = np.array( + [ + initial_speed_guess, + 5 * (400 / initial_speed_guess) ** 2, + 60000 * (initial_speed_guess / 400) ** 2, + ] + ) + + sol = None + + try: + five_point_range = range(max_index - 2, max_index + 2 + 1) + xdata: np.ndarray = energy_passbands.take(five_point_range, mode="clip") + ydata: np.ndarray = count_rates.take(five_point_range, mode="clip") + sigma: np.ndarray = count_rate_error.take(five_point_range, mode="clip") + curve_fit_output = curve_fit( f=count_rate, - xdata=energy_passbands.take( - range(max_index - 3, max_index + 3), mode="wrap" - ), - ydata=current_sweep_count_rates.take( - range(max_index - 3, max_index + 3), mode="wrap" - ), - sigma=current_sweep_count_rate_errors.take( - range(max_index - 3, max_index + 3), mode="wrap" - ), + xdata=xdata, + ydata=ydata, + sigma=sigma, p0=initial_param_guess, ) - solution_dict["pseudo_speed"].append(sol[0][0]) - solution_dict["pseudo_density"].append(sol[0][1]) - solution_dict["pseudo_temperature"].append(sol[0][2]) - return solution_dict + # If covariance matrix is not finite, scipy failed to converge to a + # solution and could just be reporting the initial guess + covariance_matrix_is_finite = np.all(np.isfinite(curve_fit_output[1])) + + # fit has failed if R^2 < 0.7 + yfit = count_rate(xdata, *curve_fit_output[0]) # type: ignore[arg-type] + r2 = 1 - np.sum((ydata - yfit) ** 2) / np.sum((ydata - ydata.mean()) ** 2) + r2_is_acceptable = r2 >= 0.7 + + if covariance_matrix_is_finite and r2_is_acceptable: + sol = curve_fit_output[0] + except RuntimeError: + logger.error("curve_fit failed") + sol = None + + # report speed only if fit fails + if sol is None: + sol = initial_param_guess.copy() + sol[1:] = np.nan + + return sol + + +def geometric_mean( + swapi_met_list: list, + pseudo_speed_list: list, + pseudo_proton_density_list: list, + pseudo_proton_temperature_list: list, +) -> tuple: + """ + Find moving geometric mean of SWAPI data. + + Parameters + ---------- + swapi_met_list : list + Mission elapsed time for first time measurement of SWAPI sweep. + pseudo_speed_list : list + Pseudo speed for SWAPI sweep. + pseudo_proton_density_list : list + Pseudo proton density for SWAPI sweep. + pseudo_proton_temperature_list : list + Pseudo proton temperature for SWAPI sweep. + + Returns + ------- + avg_swapi_met : float + Average swapi met value. + avg_proton_density : float + Average proton density value. + avg_pseudo_speed : float + Average pseudo speed value. + avg_proton_temperature : float + Average proton temperature value. + """ + met_arr = np.asarray(swapi_met_list) + + # If any of the values are equal to nan then do not include that index. + valid = ( + ~np.isnan(pseudo_speed_list) + & ~np.isnan(pseudo_proton_density_list) + & ~np.isnan(pseudo_proton_temperature_list) + ) + + if not np.any(valid): + avg_swapi_met = np.mean(met_arr) + return avg_swapi_met, np.nan, np.nan, np.nan + + pseudo_speed_arr = np.asarray(pseudo_speed_list)[valid] + avg_pseudo_speed = np.exp(np.mean(np.log(pseudo_speed_arr))) + + density_arr = np.asarray(pseudo_proton_density_list)[valid] + avg_proton_density = np.exp(np.mean(np.log(density_arr))) + + temperature_arr = np.asarray(pseudo_proton_temperature_list)[valid] + avg_proton_temperature = np.exp(np.mean(np.log(temperature_arr))) + + avg_swapi_met = np.mean(met_arr[valid]) + + return avg_swapi_met, avg_proton_density, avg_pseudo_speed, avg_proton_temperature def process_swapi_ialirt( @@ -157,7 +232,17 @@ def process_swapi_ialirt( # Add required parameters. sci_dataset["met"] = met - met_values = [] + incomplete_groups = [] + swapi_data = [] + pseudo_proton_speed_list = [] + pseudo_proton_density_list = [] + pseudo_proton_temperature_list = [] + swapi_met_list = [] + + # Extract energy values from the calibration lookup table file + calibration_lut_table["timestamp"] = pd.to_datetime( + calibration_lut_table["timestamp"] + ) grouped_dataset = find_groups(sci_dataset, (0, 11), "swapi_seq_number", "met") @@ -172,63 +257,112 @@ def process_swapi_ialirt( seq_values = grouped_dataset["swapi_seq_number"][ (grouped_dataset["group"] == group) ] + met = grouped_dataset["met"][(grouped_dataset["group"] == group).values] - met_values.append( - int(grouped_dataset["met"][(grouped_dataset["group"] == group).values][0]) - ) + swapi_met = grouped_dataset["swapi_acq"][ + (grouped_dataset["group"] == group).values + ] + mid_measurement = int((swapi_met[0] + swapi_met[-1]) // 2) # Ensure no duplicates and all values from 0 to 11 are present - if not np.array_equal(seq_values.astype(int), np.arange(12)): - logger.info( - f"SWAPI group {group} does not contain all sequence values from 0 to " - f"11 without duplicates." - ) + if not np.array_equal(seq_values.values.astype(int), np.arange(12)): + incomplete_groups.append(group) continue - raw_coin_count = process_sweep_data(grouped_dataset, "swapi_coin_cnt") - raw_coin_rate = raw_coin_count / SWAPI_LIVETIME - count_rate_error = np.sqrt(raw_coin_count) / SWAPI_LIVETIME + grouped_subset = grouped_dataset.sel(epoch=grouped_dataset.group == group) + + raw_coin_count = process_sweep_data(grouped_subset, "swapi_coin_cnt") + # I-ALiRT packets have counts compressed by a factor of 16. + # Add 8 to avoid having counts truncated to 0 and to avoid + # counts being systematically too low + raw_coin_count = raw_coin_count * 16 + 8 + # Subset to only the relevant I-ALiRT energy steps + raw_coin_count = raw_coin_count[:, :NUM_IALIRT_ENERGY_STEPS] + raw_coin_rate = raw_coin_count / SWAPI_LIVETIME + count_rate_error = np.sqrt(raw_coin_count) / SWAPI_LIVETIME + + sweep_id = int(grouped_subset["swapi_version"].values[0]) + subset_sweep = calibration_lut_table[ + calibration_lut_table["Sweep #"] == sweep_id + ] - # Extract energy values from the calibration lookup table file - calibration_lut_table["timestamp"] = pd.to_datetime( - calibration_lut_table["timestamp"], format="%m/%d/%Y %H:%M" - ) - calibration_lut_table["timestamp"] = calibration_lut_table["timestamp"].to_numpy( - dtype="datetime64[ns]" - ) + # Find the sweep's energy data for the latest time + subset = subset_sweep[ + (subset_sweep["timestamp"] == subset_sweep["timestamp"].max()) + ] + if subset.empty: + raise ValueError( + f"No esa unit conversion available for sweep {sweep_id}. " + f"Check lookup table?" + ) + else: + subset = subset.sort_values(["timestamp", "ESA Step #"]) + energy_passbands = ( + subset["Energy"][:NUM_IALIRT_ENERGY_STEPS].to_numpy().astype(float) + ) - # Find the sweep's energy data for the latest time, where sweep_id == 2 - subset = calibration_lut_table[ - (calibration_lut_table["timestamp"] == calibration_lut_table["timestamp"].max()) - & (calibration_lut_table["Sweep #"] == 2) - ] - if subset.empty: - energy_passbands = np.full(63, np.nan, dtype=np.float64) - else: - subset = subset.sort_values(["timestamp", "ESA Step #"]) - energy_passbands = subset["Energy"][0:63].to_numpy().astype(float) - - solution = optimize_pseudo_parameters( - raw_coin_rate, count_rate_error, energy_passbands - ) + pseudo_speed, pseudo_density, pseudo_temperature = optimize_pseudo_parameters( + raw_coin_rate.squeeze(), count_rate_error.squeeze(), energy_passbands + ) - swapi_data = [] + pseudo_proton_speed_list.append(pseudo_speed) + pseudo_proton_density_list.append(pseudo_density) + pseudo_proton_temperature_list.append(pseudo_temperature) + swapi_met_list.append(mid_measurement) + + # Begin averaging after 1 minute has passed (5 sweeps) and make certain that + # the data is sequential (~12 s cadence). + if len(swapi_met_list) >= 5 and np.all( + np.isclose(np.diff(swapi_met_list[-5:]), 12.0, atol=0.05) + ): + ( + avg_swapi_met, + avg_pseudo_proton_density, + avg_pseudo_proton_speed, + avg_pseudo_proton_temperature, + ) = geometric_mean( + swapi_met_list[-5:], + pseudo_proton_speed_list[-5:], + pseudo_proton_density_list[-5:], + pseudo_proton_temperature_list[-5:], + ) - for entry in np.arange(0, len(solution["pseudo_speed"])): - swapi_data.append( - { - "apid": 478, - "met": int(met_values[entry]), - "met_in_utc": met_to_utc(met_values[entry]).split(".")[0], - "ttj2000ns": int(met_to_ttj2000ns(met_values[entry])), - "swapi_pseudo_proton_speed": Decimal(solution["pseudo_speed"][entry]), - "swapi_pseudo_proton_density": Decimal( - solution["pseudo_density"][entry] - ), - "swapi_pseudo_proton_temperature": Decimal( - solution["pseudo_temperature"][entry] - ), - } + avg_pseudo_proton_speed = ( + Decimal(f"{avg_pseudo_proton_speed:.3f}") + if avg_pseudo_proton_speed is not None + and np.isfinite(avg_pseudo_proton_speed) + else None + ) + + avg_pseudo_proton_density = ( + Decimal(f"{avg_pseudo_proton_density:.3f}") + if avg_pseudo_proton_density is not None + and np.isfinite(avg_pseudo_proton_density) + else None + ) + + avg_pseudo_proton_temperature = ( + Decimal(f"{avg_pseudo_proton_temperature:.3f}") + if avg_pseudo_proton_temperature is not None + and np.isfinite(avg_pseudo_proton_temperature) + else None + ) + + swapi_data.append( + _populate_instrument_header_items(met) + | { + "instrument": "swapi", + "swapi_epoch": int(met_to_ttj2000ns(avg_swapi_met)), + "swapi_pseudo_proton_speed": avg_pseudo_proton_speed, + "swapi_pseudo_proton_density": avg_pseudo_proton_density, + "swapi_pseudo_proton_temperature": avg_pseudo_proton_temperature, + } + ) + if incomplete_groups: + logger.info( + f"The following swapi groups were skipped due to " + f"missing or duplicate pkt_counter values: " + f"{incomplete_groups}" ) return swapi_data diff --git a/imap_processing/ialirt/l0/process_swe.py b/imap_processing/ialirt/l0/process_swe.py index 9d3eae94d9..3ae639ae5e 100644 --- a/imap_processing/ialirt/l0/process_swe.py +++ b/imap_processing/ialirt/l0/process_swe.py @@ -3,13 +3,15 @@ import logging import numpy as np -import pandas as pd import xarray as xr from numpy.typing import NDArray -from imap_processing.ialirt.utils.grouping import find_groups +from imap_processing.ialirt.utils.grouping import ( + _populate_instrument_header_items, + find_groups, +) from imap_processing.ialirt.utils.time import calculate_time -from imap_processing.spice.time import met_to_ttj2000ns, met_to_utc +from imap_processing.spice.time import met_to_ttj2000ns from imap_processing.swe.l1a.swe_science import decompressed_counts from imap_processing.swe.l1b.swe_l1b import ( deadtime_correction, @@ -102,7 +104,7 @@ def prepare_raw_counts(grouped: xr.Dataset, cem_number: int = N_CEMS) -> NDArray - 7 corresponds to the 7 CEM detectors. - 30 corresponds to the 30 phi bins. """ - raw_counts = np.zeros((8, cem_number, 30), dtype=np.uint8) + raw_counts: np.ndarray = np.zeros((8, cem_number, 30), dtype=np.uint8) # Compute phi values and their corresponding bins # Example: energy steps 0-1 have the same phi; @@ -155,7 +157,7 @@ def get_ialirt_energies() -> list: return energy -def normalize_counts(counts: NDArray, latest_cal: pd.Series) -> NDArray: +def normalize_counts(counts: NDArray, interp_cal: NDArray) -> NDArray: """ Normalize the counts using the latest calibration factor. @@ -163,18 +165,16 @@ def normalize_counts(counts: NDArray, latest_cal: pd.Series) -> NDArray: ---------- counts : np.ndarray Array of counts. - latest_cal : pd.Series - Array of latest calibration factors. + interp_cal : np.ndarray + Array of calibration factors. Returns ------- norm_counts : np.ndarray Array of normalized counts. """ - latest_cal = latest_cal.to_numpy() - # Norm counts where counts are non-negative - norm_counts = counts * (latest_cal / GEOMETRIC_FACTORS)[:, np.newaxis] + norm_counts = counts * (interp_cal / GEOMETRIC_FACTORS)[:, np.newaxis] norm_counts[norm_counts < 0] = 0 return norm_counts @@ -473,11 +473,20 @@ def process_swe(accumulated_data: xr.Dataset, in_flight_cal_files: list) -> list # Add required parameters. accumulated_data["met"] = met + # Drop any off-nominal SWE groups + nominal_data = accumulated_data.where( + accumulated_data["swe_nom_flag"] != 0, + drop=True, + ) + # Get total full cycle data available for processing. # There are 60 packets in a set so (0, 59) is the range. - grouped_data = find_groups(accumulated_data, (0, 59), "swe_seq", "time_seconds") + grouped_data = find_groups( + nominal_data, (0, 59), "swe_seq", "met", check_src_seq_ctr=False + ) unique_groups = np.unique(grouped_data["group"]) swe_data: list[dict] = [] + incomplete_groups = [] for group in unique_groups: # Sequence values for the group should be 0-59 with no duplicates. @@ -485,10 +494,7 @@ def process_swe(accumulated_data: xr.Dataset, in_flight_cal_files: list) -> list # Ensure no duplicates and all values from 0 to 59 are present if not np.array_equal(seq_values, np.arange(60)): - logger.info( - f"Group {group} does not contain all values from 0 to " - f"59 without duplicates." - ) + incomplete_groups.append(group) continue # Prepare raw counts array just for this group # (8 energy steps, 7 CEMs, 30 phi bins) @@ -512,12 +518,47 @@ def process_swe(accumulated_data: xr.Dataset, in_flight_cal_files: list) -> list corrected_first_half = deadtime_correction(counts_first_half, 80 * 10**3) corrected_second_half = deadtime_correction(counts_second_half, 80 * 10**3) - # Grab the latest calibration factor + # Interpolate to find the correct calibration factor in_flight_cal_df = read_in_flight_cal_data(in_flight_cal_files) - latest_cal = in_flight_cal_df.sort_values("met_time").iloc[-1][1::] + # Get names of all 7 cems in the calibration file + cal_cols = [f"cem{i}" for i in range(1, 8)] + cal_met = in_flight_cal_df["met_time"].to_numpy() - normalized_first_half = normalize_counts(corrected_first_half, latest_cal) - normalized_second_half = normalize_counts(corrected_second_half, latest_cal) + # Find the middle timestamp of the first group + group_time_first_half = ( + grouped["time_seconds"].where(grouped["swe_seq"] < 30, drop=True).values + ) + group_time_first_half_mid = ( + group_time_first_half[0] + group_time_first_half[-1] + ) // 2 + + # Interpolate to the appropriate calibration factor + idx = np.searchsorted(cal_met, group_time_first_half_mid, side="right") - 1 + + interp_cal_first_half = np.array( + [in_flight_cal_df[cem].iloc[idx] for cem in cal_cols], + dtype=np.float64, + ) + # Find the middle timestamp of the second group + group_time_second_half = ( + grouped["time_seconds"].where(grouped["swe_seq"] >= 30, drop=True).values + ) + group_time_second_half_mid = ( + group_time_second_half[0] + group_time_second_half[-1] + ) // 2 + idx = np.searchsorted(cal_met, group_time_second_half_mid, side="right") - 1 + + interp_cal_second_half = np.array( + [in_flight_cal_df[cem].iloc[idx] for cem in cal_cols], + dtype=np.float64, + ) + + normalized_first_half = normalize_counts( + corrected_first_half, interp_cal_first_half + ) + normalized_second_half = normalize_counts( + corrected_second_half, interp_cal_second_half + ) # Sum over the 7 detectors summed_first_half_cem = np.sum(normalized_first_half, axis=1) @@ -525,7 +566,7 @@ def process_swe(accumulated_data: xr.Dataset, in_flight_cal_files: list) -> list bde_first_search = azimuthal_check_counterstreaming( summed_first_half_cem, summed_second_half_cem ) - # Sum over azimuth. + # Sum over azimuth summed_first_half_az = np.sum(normalized_first_half, axis=2) summed_second_half_az = np.sum(normalized_second_half, axis=2) bde_second_search = polar_check_counterstreaming( @@ -542,32 +583,35 @@ def process_swe(accumulated_data: xr.Dataset, in_flight_cal_files: list) -> list summed_first = normalized_first_half.sum(axis=(1, 2)) summed_second = normalized_second_half.sum(axis=(1, 2)) - met_first_half = int( - grouped["met"].where(grouped["swe_seq"] == 0, drop=True).values[0] - ) - met_second_half = int( - grouped["met"].where(grouped["swe_seq"] == 30, drop=True).values[0] + met_first_half = grouped["met"].where(grouped["swe_seq"] == 0, drop=True).values + met_second_half = ( + grouped["met"].where(grouped["swe_seq"] == 30, drop=True).values ) swe_data.append( - { - "apid": 478, - "met": met_first_half, - "met_in_utc": met_to_utc(met_first_half).split(".")[0], - "ttj2000ns": int(met_to_ttj2000ns(met_first_half)), + _populate_instrument_header_items(met_first_half) + | { + "instrument": "swe", + "swe_epoch": int(met_to_ttj2000ns(group_time_first_half_mid)), "swe_normalized_counts": [int(val) for val in summed_first], "swe_counterstreaming_electrons": bde_first_half, }, ) swe_data.append( - { - "apid": 478, - "met": met_second_half, - "met_in_utc": met_to_utc(met_second_half).split(".")[0], - "ttj2000ns": int(met_to_ttj2000ns(met_second_half)), + _populate_instrument_header_items(met_second_half) + | { + "instrument": "swe", + "swe_epoch": int(met_to_ttj2000ns(group_time_second_half_mid)), "swe_normalized_counts": [int(val) for val in summed_second], "swe_counterstreaming_electrons": bde_second_half, }, ) + if incomplete_groups: + logger.info( + f"The following swe groups were skipped due to " + f"missing or duplicate pkt_counter values: " + f"{incomplete_groups}" + ) + return swe_data diff --git a/imap_processing/ialirt/packet_definitions/ialirt.xml b/imap_processing/ialirt/packet_definitions/ialirt.xml index 10dbe72b5d..d9a779ea80 100644 --- a/imap_processing/ialirt/packet_definitions/ialirt.xml +++ b/imap_processing/ialirt/packet_definitions/ialirt.xml @@ -141,6 +141,9 @@ + + + @@ -296,7 +299,7 @@ Inertial Right Ascension of system angular momentum vector - + Inertial Declination of system angular momentum vector diff --git a/imap_processing/ialirt/process_ephemeris.py b/imap_processing/ialirt/process_ephemeris.py index 3ce67122b6..8ae2e390e3 100644 --- a/imap_processing/ialirt/process_ephemeris.py +++ b/imap_processing/ialirt/process_ephemeris.py @@ -72,6 +72,7 @@ def calculate_azimuth_and_elevation( altitude: float, observation_time: float | np.ndarray, target: str = SpiceBody.IMAP.name, + obsref: str = "ITRF93", ) -> tuple: """ Calculate azimuth and elevation. @@ -91,6 +92,9 @@ def calculate_azimuth_and_elevation( is to be computed. Expressed as ephemeris time, seconds past J2000 TDB. target : str (Optional) The target body. Default is "IMAP". + obsref : str (Optional) + Body-fixed, body-centered reference frame wrt + observer's center. Returns ------- @@ -120,7 +124,7 @@ def calculate_azimuth_and_elevation( elplsz=True, # Elevation increases from the XY plane toward +Z obspos=ground_station_position_ecef, # observer pos. to center of motion obsctr="EARTH", # Name of the center of motion - obsref="IAU_EARTH", # Body-fixed, body-centered reference frame wrt + obsref=obsref, # Body-fixed, body-centered reference frame wrt # observer's center ) azimuth.append(np.rad2deg(azel_results[0][1])) @@ -223,7 +227,7 @@ def build_output( # For now, assume that kernel management will be handled by ensure_spice azimuth, elevation = calculate_azimuth_and_elevation( - longitude, latitude, altitude, time_range + longitude, latitude, altitude, time_range, obsref="ITRF93" ) output_dict["time"] = et_to_utc(time_range, format_str="ISOC") diff --git a/imap_processing/ialirt/utils/constants.py b/imap_processing/ialirt/utils/constants.py index a8264be80c..90c60cd3de 100644 --- a/imap_processing/ialirt/utils/constants.py +++ b/imap_processing/ialirt/utils/constants.py @@ -1,68 +1,197 @@ """Keys for I-ALiRT data products.""" -IALIRT_KEYS = [ +import numpy as np + +from imap_processing.codice.constants import ( + HI_IALIRT_REF_SPIN_ANGLE, +) + +IALIRT_DIMS = { # H intensities in 15 energy ranges and binned into 4 azimuths and 4 spin angle bins - "codice_hi_h", + "codice_hi_h": [ + "codice_hi_epoch", + "codice_hi_energy_center", + "codice_hi_spin_sector", + "codice_hi_polar", + ], # C/O abundance ratio - "codice_lo_c_over_o_abundance", + "codice_lo_c_over_o_abundance": ["codice_lo_epoch"], # Mg/O abundance ratio - "codice_lo_mg_over_o_abundance", + "codice_lo_mg_over_o_abundance": ["codice_lo_epoch"], # Fe/O abundance ratio - "codice_lo_fe_over_o_abundance", + "codice_lo_fe_over_o_abundance": ["codice_lo_epoch"], # C+6/C+5 charge state ratio - "codice_lo_c_plus_6_over_c_plus_5_ratio", + "codice_lo_c_plus_6_over_c_plus_5": ["codice_lo_epoch"], # O+7/O+6 charge state ratio - "codice_lo_o_plus_7_over_o_plus_6_ratio", + "codice_lo_o_plus_7_over_o_plus_6": ["codice_lo_epoch"], # Fe low/Fe high charge state ratio - "codice_lo_fe_low_over_fe_high_ratio", - # Low energy (~300 keV) electrons (A-side) - "hit_e_a_side_low_en", - # Medium energy (~3 MeV) electrons (A-side) - "hit_e_a_side_med_en", - # High energy (>3 MeV) electrons (A-side) - "hit_e_a_side_high_en", - # Low energy (~300 keV) electrons (B-side) - "hit_e_b_side_low_en", - # Medium energy (~3 MeV) electrons (B-side) - "hit_e_b_side_med_en", - # High energy (>3 MeV) electrons (B-side) - "hit_e_b_side_high_en", - # Medium energy (12 to 70 MeV) protons (Omnidirectional) - "hit_h_omni_med_en", - # High energy (>70 MeV) protons (A-side) - "hit_h_a_side_high_en", - # High energy (>70 MeV) protons (B-side) - "hit_h_b_side_high_en", + "codice_lo_fe_low_over_fe_high": ["codice_lo_epoch"], + # Medium energy (<1 MeV) electrons (A-side) + "hit_e_a_side_med_en": ["hit_epoch"], + # Medium energy (<1 MeV) electrons (B-side) + "hit_e_b_side_med_en": ["hit_epoch"], + # Low energy (6 to 8 MeV) protons (Omnidirectional) + "hit_h_omni_low_en": ["hit_epoch"], + # Medium energy (12 to 15 MeV) protons (Omnidirectional) + "hit_h_omni_med_en": ["hit_epoch"], # Low energy (6 to 8 MeV/nuc) He (Omnidirectional) - "hit_he_omni_low_en", + "hit_he_omni_low_en": ["hit_epoch"], # High energy (15 to 70 MeV/nuc) He (Omnidirectional) - "hit_he_omni_high_en", - # MAG instrument epoch - "mag_epoch", + "hit_he_omni_high_en": ["hit_epoch"], + # Magnitude of the magnetic field vector + "mag_B_magnitude": ["mag_epoch"], + # Elevation angle (ΞΈ) of the magnetic field in GSE coordinates + "mag_theta_B_GSE": ["mag_epoch"], + # Azimuth angle (Ο†) of the magnetic field in GSE coordinates + "mag_phi_B_GSE": ["mag_epoch"], + # Elevation angle (ΞΈ) of the magnetic field in GSM coordinates + "mag_theta_B_GSM": ["mag_epoch"], + # Azimuth angle (Ο†) of the magnetic field in GSM coordinates + "mag_phi_B_GSM": ["mag_epoch"], # Magnetic field vector in GSE coordinates - "mag_B_GSE", + "mag_B_GSE": ["mag_epoch", "B_GSE_labels"], # Magnetic field vector in GSM coordinates - "mag_B_GSM", + "mag_B_GSM": ["mag_epoch", "B_GSM_labels"], # Magnetic field vector in RTN coordinates - "mag_B_RTN", - # Magnitude of the magnetic field vector - "mag_B_magnitude", - # Azimuth angle (Ο†) of the magnetic field in GSM coordinates - "mag_phi_B_GSM", - # Elevation angle (ΞΈ) of the magnetic field in GSM coordinates - "mag_theta_B_GSM", - # Azimuth angle (Ο†) of the magnetic field in GSE coordinates - "mag_phi_B_GSE", - # Elevation angle (ΞΈ) of the magnetic field in GSE coordinates - "mag_theta_B_GSE", + "mag_B_RTN": ["mag_epoch", "B_RTN_labels"], # Pseudo density of solar wind protons - "swapi_pseudo_proton_density", + "swapi_pseudo_proton_density": ["swapi_epoch"], # Pseudo speed of solar wind protons in solar inertial frame - "swapi_pseudo_proton_speed", + "swapi_pseudo_proton_speed": ["swapi_epoch"], # Pseudo temperature of solar wind protons in plasma frame - "swapi_pseudo_proton_temperature", + "swapi_pseudo_proton_temperature": ["swapi_epoch"], # SWE Normalized Counts - "swe_normalized_counts", + "swe_normalized_counts": ["swe_epoch", "swe_electron_energy"], # SWE Counterstreaming flag - "swe_counterstreaming_electrons", + "swe_counterstreaming_electrons": ["swe_epoch"], + # Spacecraft position in GSE coordinates + "sc_position_GSE": ["ephemeris_epoch", "sc_GSE_position_labels"], + # Spacecraft velocity in GSE coordinates + "sc_velocity_GSE": ["ephemeris_epoch", "sc_GSE_velocity_labels"], + # Spacecraft position in GSM coordinates + "sc_position_GSM": ["ephemeris_epoch", "sc_GSM_position_labels"], + # Spacecraft velocity in GSM coordinates + "sc_velocity_GSM": ["ephemeris_epoch", "sc_GSM_velocity_labels"], +} + +IALIRT_DTYPES = { + # H intensities in 15 energy ranges and binned into 4 azimuths and 4 spin angle bins + "codice_hi_h": np.float32, + # CoDICE-Lo abundance / ratios + "codice_lo_c_over_o_abundance": np.float32, + "codice_lo_mg_over_o_abundance": np.float32, + "codice_lo_fe_over_o_abundance": np.float32, + "codice_lo_c_plus_6_over_c_plus_5": np.float32, + "codice_lo_o_plus_7_over_o_plus_6": np.float32, + "codice_lo_fe_low_over_fe_high": np.float32, + # HIT scalars + "hit_e_a_side_med_en": np.float32, + "hit_e_b_side_med_en": np.float32, + "hit_h_omni_low_en": np.float32, + "hit_h_omni_med_en": np.float32, + "hit_he_omni_low_en": np.float32, + "hit_he_omni_high_en": np.float32, + # MAG + "mag_B_magnitude": np.float32, + "mag_B_RTN": np.float32, + "mag_B_GSE": np.float32, + "mag_theta_B_GSE": np.float32, + "mag_phi_B_GSE": np.float32, + "mag_B_GSM": np.float32, + "mag_theta_B_GSM": np.float32, + "mag_phi_B_GSM": np.float32, + # SWAPI + "swapi_pseudo_proton_density": np.float32, + "swapi_pseudo_proton_speed": np.float32, + "swapi_pseudo_proton_temperature": np.float32, + # SWE + "swe_normalized_counts": np.int64, + "swe_counterstreaming_electrons": np.uint8, + # Spacecraft vectors + "sc_position_GSM": np.float32, + "sc_velocity_GSM": np.float32, + "sc_position_GSE": np.float32, + "sc_velocity_GSE": np.float32, +} + +hit_restricted_fields = { + "hit_e_a_side_high_en", + "hit_e_b_side_high_en", + "hit_h_a_side_high_en", + "hit_h_b_side_high_en", + "hit_e_a_side_low_en", + "hit_e_b_side_low_en", +} + +codice_hi_energy_center = [ + 0.02378414, + 0.03363586, + 0.04756828, + 0.06727171, + 0.09513657, + 0.13454343, + 0.19027314, + 0.26908685, + 0.38054628, + 0.53817371, + 0.76109255, + 1.07634741, + 1.52218511, + 2.15269482, + 3.04437021, +] +codice_hi_energy_minus = [ + 0.00378414, + 0.00535159, + 0.00756828, + 0.01070317, + 0.01513657, + 0.02140634, + 0.03027314, + 0.04281268, + 0.06054628, + 0.08562537, + 0.12109255, + 0.17125073, + 0.24218511, + 0.34250146, + 0.48437021, +] +codice_hi_energy_plus = [ + 0.00450013, + 0.00636414, + 0.00900026, + 0.01272829, + 0.01800052, + 0.02545657, + 0.03600103, + 0.05091315, + 0.07200206, + 0.10182629, + 0.14400413, + 0.20365259, + 0.28800825, + 0.40730518, + 0.57601651, +] + +# Calculate spin angle +# Formula: +# ΞΈ_(g,n) = (ΞΈ_(g,0)+90Β°* n) mod 360Β° +# where +# n is number of sectored angles, 0 to 3, +# g is size of the group (inst_az), 0 to 3, +HI_IALIRT_SPIN_ANGLE = ( + HI_IALIRT_REF_SPIN_ANGLE[:, np.newaxis] + np.array([0, 1, 2, 3]) * 90 +) % 360.0 + +swe_energy = [ + 100.4, + 140.0, + 194.0, + 270.0, + 376.0, + 523.0, + 727.0, + 1011.0, ] diff --git a/imap_processing/ialirt/utils/create_xarray.py b/imap_processing/ialirt/utils/create_xarray.py index 6c8fc3ae12..f5a2fa1e56 100644 --- a/imap_processing/ialirt/utils/create_xarray.py +++ b/imap_processing/ialirt/utils/create_xarray.py @@ -1,10 +1,25 @@ """Creates xarray based on structure of queried DynamoDB.""" +from collections import defaultdict +from datetime import datetime, timedelta + import numpy as np import xarray as xr +from cdflib.epochs import CDFepoch from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes -from imap_processing.ialirt.utils.constants import IALIRT_KEYS +from imap_processing.codice.constants import ( + HI_IALIRT_ELEVATION_ANGLE, +) +from imap_processing.ialirt.utils.constants import ( + IALIRT_DIMS, + IALIRT_DTYPES, + codice_hi_energy_center, + codice_hi_energy_minus, + codice_hi_energy_plus, + hit_restricted_fields, + swe_energy, +) def create_xarray_from_records(records: list[dict]) -> xr.Dataset: # noqa: PLR0912 @@ -25,134 +40,324 @@ def create_xarray_from_records(records: list[dict]) -> xr.Dataset: # noqa: PLR0 cdf_manager.add_instrument_global_attrs("ialirt") cdf_manager.add_instrument_variable_attrs("ialirt", "l1") - instrument_keys: set[str] = set(IALIRT_KEYS) - n = len(records) - attrs = cdf_manager.get_variable_attributes("default_int64_attrs") - fillval = attrs.get("FILLVAL") - ttj2000ns_values = np.full(n, fillval, dtype=np.int64) + one_epoch = {"codice_lo", "hit", "swapi", "swe", "spacecraft", "mag"} + multi_epoch = {"codice_hi"} + + epochs: dict[str, list[int]] = {inst: [] for inst in (one_epoch | multi_epoch)} + by_inst: dict[str, list[dict]] = defaultdict(list) + + # Get the start and end ttj2000ns. + date = records[0]["time_utc"] # e.g. "2025-06-20T08:00:00Z" + + # Parse as UTC + dt = datetime.fromisoformat(date) + + # Start and end of that UTC day + start_dt = dt.replace(hour=0, minute=0, second=0, microsecond=0) + end_dt = start_dt + timedelta(days=1) + + start_ttj2000 = int( + CDFepoch.compute_tt2000( + [ + start_dt.year, + start_dt.month, + start_dt.day, + start_dt.hour, + start_dt.minute, + start_dt.second, + 0, + 0, + 0, # ms, us, ns + ] + ) + ) + end_ttj2000 = int( + CDFepoch.compute_tt2000( + [ + end_dt.year, + end_dt.month, + end_dt.day, + end_dt.hour, + end_dt.minute, + end_dt.second, + 0, + 0, + 0, # ms, us, ns + ] + ) + ) + + for record in records: + inst = record.get("instrument") + by_inst[record["instrument"]].append(record) + if inst == "spacecraft": + epochs[inst].append(record["ttj2000ns"]) + elif inst in one_epoch: + epochs[inst].append(record[f"{inst}_epoch"]) + elif inst in multi_epoch: + epochs[inst].extend(record[f"{inst}_epoch"]) + + epoch_arrays = {} + + for inst, arr in epochs.items(): + if inst == "spacecraft": + coord = "ephemeris_epoch" + attr = cdf_manager.get_variable_attributes( + "ephemeris_epoch", check_schema=False + ) + else: + coord = f"{inst}_epoch" + attr = cdf_manager.get_variable_attributes( + f"{inst}_epoch", check_schema=False + ) + epoch_arrays[coord] = xr.DataArray( + data=np.array(arr, dtype=np.int64), name=coord, dims=[coord], attrs=attr + ) + + sc_gsm_position_component = xr.DataArray( + ["sc X (GSM)", "sc Y (GSM)", "sc Z (GSM)"], + name="sc_GSM_position_labels", + dims=["sc_GSM_position_labels"], + attrs=cdf_manager.get_variable_attributes( + "sc_GSM_position_labels", check_schema=False + ), + ) + sc_gsm_velocity_component = xr.DataArray( + ["sc Vx (GSM)", "sc Vy (GSM)", "sc Vz (GSM)"], + name="sc_GSM_velocity_labels", + dims=["sc_GSM_velocity_labels"], + attrs=cdf_manager.get_variable_attributes( + "sc_GSM_velocity_labels", check_schema=False + ), + ) - # Collect all keys that start with the instrument prefixes. - for i, record in enumerate(records): - ttj2000ns_values[i] = record["ttj2000ns"] + sc_gse_position_component = xr.DataArray( + ["sc X (GSE)", "sc Y (GSE)", "sc Z (GSE)"], + name="sc_GSE_position_labels", + dims=["sc_GSE_position_labels"], + attrs=cdf_manager.get_variable_attributes( + "sc_GSE_position_labels", check_schema=False + ), + ) + sc_gse_velocity_component = xr.DataArray( + ["sc Vx (GSE)", "sc Vy (GSE)", "sc Vz (GSE)"], + name="sc_GSE_velocity_labels", + dims=["sc_GSE_velocity_labels"], + attrs=cdf_manager.get_variable_attributes( + "sc_GSE_velocity_labels", check_schema=False + ), + ) - epoch = xr.DataArray( - data=ttj2000ns_values, - name="epoch", - dims=["epoch"], - attrs=cdf_manager.get_variable_attributes("epoch", check_schema=False), + gsm_component = xr.DataArray( + ["Bx (GSM)", "By (GSM)", "Bz (GSM)"], + name="B_GSM_labels", + dims=["B_GSM_labels"], + attrs=cdf_manager.get_variable_attributes("B_GSM_labels", check_schema=False), ) - component = xr.DataArray( - ["x", "y", "z"], - name="component", - dims=["component"], - attrs=cdf_manager.get_variable_attributes("component", check_schema=False), + + gse_component = xr.DataArray( + ["Bx (GSE)", "By (GSE)", "Bz (GSE)"], + name="B_GSE_labels", + dims=["B_GSE_labels"], + attrs=cdf_manager.get_variable_attributes("B_GSE_labels", check_schema=False), ) rtn_component = xr.DataArray( - ["radial", "tangential", "normal"], - name="RTN_component", - dims=["RTN_component"], - attrs=cdf_manager.get_variable_attributes("RTN_componentt", check_schema=False), + ["B radial (RTN)", "B tangential (RTN)", "B normal (RTN)"], + name="B_RTN_labels", + dims=["B_RTN_labels"], + attrs=cdf_manager.get_variable_attributes("B_RTN_labels", check_schema=False), + ) + + swe_electron_energy = xr.DataArray( + data=np.float32(swe_energy), + name="swe_electron_energy", + dims=["swe_electron_energy"], + attrs=cdf_manager.get_variable_attributes( + "swe_electron_energy", check_schema=False + ), ) - esa_step = xr.DataArray( - data=np.arange(8, dtype=np.uint8), - name="esa_step", - dims=["esa_step"], - attrs=cdf_manager.get_variable_attributes("esa_step", check_schema=False), + codice_hi_energy_centers = xr.DataArray( + data=np.array(codice_hi_energy_center, dtype=np.float32), + name="codice_hi_energy_center", + dims=["codice_hi_energy_center"], + attrs=cdf_manager.get_variable_attributes( + "codice_hi_energy_center", check_schema=False + ), ) - energy_ranges = xr.DataArray( - data=np.arange(15, dtype=np.uint8), - name="codice_hi_h_energy_ranges", - dims=["codice_hi_h_energy_ranges"], + codice_energy_minus = xr.DataArray( + data=np.array(codice_hi_energy_minus, dtype=np.float32), + name="codice_hi_energy_minus", + dims=["codice_hi_energy_center"], attrs=cdf_manager.get_variable_attributes( - "codice_hi_h_energy_ranges", check_schema=False + "codice_hi_energy_minus", check_schema=False ), ) - elevation = xr.DataArray( - data=np.arange(4, dtype=np.uint8), - name="codice_hi_h_elevation", - dims=["codice_hi_h_elevation"], + codice_energy_plus = xr.DataArray( + data=np.array(codice_hi_energy_plus, dtype=np.float32), + name="codice_hi_energy_plus", + dims=["codice_hi_energy_center"], attrs=cdf_manager.get_variable_attributes( - "codice_hi_h_elevation", check_schema=False + "codice_hi_energy_plus", check_schema=False ), ) - spin_angle = xr.DataArray( + polar = xr.DataArray( + HI_IALIRT_ELEVATION_ANGLE, + name="codice_hi_polar", + dims=["codice_hi_polar"], + attrs=cdf_manager.get_variable_attributes( + "codice_hi_polar", check_schema=False + ), + ) + + polar_labels = xr.DataArray( + [f"{float(v):.1f}deg" for v in polar.values], + name="codice_hi_polar_labels", + dims=["codice_hi_polar"], + attrs=cdf_manager.get_variable_attributes( + "codice_hi_polar_labels", check_schema=False + ), + ) + + spin_sector = xr.DataArray( data=np.arange(4, dtype=np.uint8), - name="codice_hi_h_spin_angle", - dims=["codice_hi_h_spin_angle"], + name="codice_hi_spin_sector", + dims=["codice_hi_spin_sector"], + attrs=cdf_manager.get_variable_attributes( + "codice_hi_spin_sector", check_schema=False + ), + ) + + spin_sector_labels = xr.DataArray( + [ + "0", + "1", + "2", + "3", + ], + name="codice_hi_spin_sector_labels", + dims=["codice_hi_spin_sector"], attrs=cdf_manager.get_variable_attributes( - "codice_hi_h_spin_anglen", check_schema=False + "codice_hi_spin_sector_labels", check_schema=False ), ) coords = { - "epoch": epoch, - "component": component, - "RTN_component": rtn_component, - "esa_step": esa_step, - "codice_hi_h_energy_ranges": energy_ranges, - "codice_hi_h_elevation": elevation, - "codice_hi_h_spin_angle": spin_angle, + "codice_hi_epoch": epoch_arrays["codice_hi_epoch"], + "codice_lo_epoch": epoch_arrays["codice_lo_epoch"], + "hit_epoch": epoch_arrays["hit_epoch"], + "mag_epoch": epoch_arrays["mag_epoch"], + "swapi_epoch": epoch_arrays["swapi_epoch"], + "swe_epoch": epoch_arrays["swe_epoch"], + "ephemeris_epoch": epoch_arrays["ephemeris_epoch"], + "B_GSM_labels": gsm_component, + "B_GSE_labels": gse_component, + "B_RTN_labels": rtn_component, + "sc_GSM_position_labels": sc_gsm_position_component, + "sc_GSM_velocity_labels": sc_gsm_velocity_component, + "sc_GSE_position_labels": sc_gse_position_component, + "sc_GSE_velocity_labels": sc_gse_velocity_component, + "codice_hi_energy_center": codice_hi_energy_centers, + "codice_hi_energy_minus": codice_energy_minus, + "codice_hi_energy_plus": codice_energy_plus, + "codice_hi_polar": polar, + "codice_hi_polar_labels": polar_labels, + "codice_hi_spin_sector": spin_sector, + "codice_hi_spin_sector_labels": spin_sector_labels, + "swe_electron_energy": swe_electron_energy, } dataset = xr.Dataset( coords=coords, attrs=cdf_manager.get_global_attributes("imap_ialirt_l1_realtime"), ) - # Create empty dataset for each key. - for key in instrument_keys: + # Create variables with fill values. + for key in IALIRT_DIMS: + dims = IALIRT_DIMS[key] attrs = cdf_manager.get_variable_attributes(key, check_schema=False) - fillval = attrs.get("FILLVAL") - if key in ["mag_B_GSE", "mag_B_GSM"]: - data = np.full((n, 3), fillval, dtype=np.float32) - dims = ["epoch", "component"] - dataset[key] = xr.DataArray(data, dims=dims, attrs=attrs) - elif key == "mag_B_RTN": - data = np.full((n, 3), fillval, dtype=np.float32) - dims = ["epoch", "RTN_component"] - dataset[key] = xr.DataArray(data, dims=dims, attrs=attrs) - elif key.startswith("codice_hi"): - data = np.full((n, 15, 4, 4), fillval, dtype=np.float32) - dims = [ - "epoch", - "codice_hi_h_energy_ranges", - "codice_hi_h_elevation", - "codice_hi_h_spin_angle", - ] - dataset[key] = xr.DataArray(data, dims=dims, attrs=attrs) - elif key == "swe_counterstreaming_electrons": - data = np.full(n, fillval, dtype=np.uint8) - dims = ["epoch"] - dataset[key] = xr.DataArray(data, dims=dims, attrs=attrs) - elif key.startswith("swe"): - data = np.full((n, 8), fillval, dtype=np.uint32) - dims = ["epoch", "esa_step"] - dataset[key] = xr.DataArray(data, dims=dims, attrs=attrs) - elif key.startswith("hit"): - data = np.full(n, fillval, dtype=np.uint32) - dims = ["epoch"] - dataset[key] = xr.DataArray(data, dims=dims, attrs=attrs) + fill = attrs["FILLVAL"] + dtype = IALIRT_DTYPES[key] + + shape = [dataset.dims[d] for d in dims] + + data: np.ndarray = np.full(shape, fill, dtype=dtype) + dataset[key] = xr.DataArray(data, dims=dims, attrs=attrs) + + for i, record in enumerate(by_inst.get("mag", [])): + for key in IALIRT_DIMS.keys(): + if key in ["mag_B_GSE", "mag_B_GSM", "mag_B_RTN"]: + dataset[key].data[i, :] = record[key] + + if key in [ + "mag_B_magnitude", + "mag_theta_B_GSE", + "mag_phi_B_GSE", + "mag_theta_B_GSM", + "mag_phi_B_GSM", + ]: + dataset[key].data[i] = np.float32(record[key]) + + for i, record in enumerate(by_inst.get("codice_hi", [])): + # 4 codice-hi epochs per record + t0 = 4 * i + t1 = t0 + 4 + hi = np.asarray(record["codice_hi_h"], dtype=np.float32) + dataset["codice_hi_h"].data[t0:t1, :, :, :] = hi + + for i, record in enumerate(by_inst.get("codice_lo", [])): + for key in IALIRT_DIMS.keys(): + val = record.get(key) + if ( + key.startswith("codice_lo_") + and key != "codice_lo_epoch" + and val is not None + ): + dataset[key].data[i] = np.float32(val) + + for i, record in enumerate(by_inst.get("hit", [])): + for key in IALIRT_DIMS.keys(): + val = record.get(key) + if ( + key.startswith("hit_") + and key != "hit_epoch" + and val is not None + and key not in hit_restricted_fields + ): + dataset[key].data[i] = np.float32(val) + + for i, record in enumerate(by_inst.get("swapi", [])): + for key in IALIRT_DIMS.keys(): + val = record.get(key) + if key.startswith("swapi_") and key != "swapi_epoch" and val is not None: + dataset[key].data[i] = np.float32(val) + + for i, record in enumerate(by_inst.get("swe", [])): + dataset["swe_normalized_counts"].data[i, :] = np.asarray( + record["swe_normalized_counts"], dtype=np.int64 + ) + dataset["swe_counterstreaming_electrons"].data[i] = np.uint8( + record["swe_counterstreaming_electrons"] + ) + + for i, record in enumerate(by_inst.get("spacecraft", [])): + for key in IALIRT_DIMS.keys(): + if key.startswith("sc_"): + dataset[key].data[i, :] = np.asarray(record[key], dtype=np.float32) + + # Trim data that does not fit within the UTC day. + for inst in epochs.keys(): + if inst == "spacecraft": + dim = "ephemeris_epoch" else: - data = np.full(n, fillval, dtype=np.float32) - dims = ["epoch"] - dataset[key] = xr.DataArray(data, dims=dims, attrs=attrs) - - # Populate the dataset variables - for i, record in enumerate(records): - for key, val in record.items(): - if key in ["apid", "met", "met_in_utc", "ttj2000ns"]: - continue - elif key in ["mag_B_GSE", "mag_B_GSM", "mag_B_RTN"]: - dataset[key].data[i, :] = val - elif key.startswith("swe_normalized_counts"): - dataset[key].data[i, :] = val - elif key.startswith("codice_hi"): - dataset[key].data[i, :, :, :] = val - else: - dataset[key].data[i] = val + dim = f"{inst}_epoch" + + if dim in dataset.coords: + dataset = dataset.sel( + {dim: (dataset[dim] >= start_ttj2000) & (dataset[dim] < end_ttj2000)} + ) return dataset diff --git a/imap_processing/ialirt/utils/grouping.py b/imap_processing/ialirt/utils/grouping.py index 27bf3fcbca..30fdf5a009 100644 --- a/imap_processing/ialirt/utils/grouping.py +++ b/imap_processing/ialirt/utils/grouping.py @@ -5,6 +5,8 @@ import numpy as np import xarray as xr +from imap_processing.spice.time import met_to_ttj2000ns, met_to_utc + logger = logging.getLogger(__name__) @@ -50,6 +52,7 @@ def find_groups( sequence_range: tuple, sequence_name: str, time_name: str, + check_src_seq_ctr: bool = True, ) -> xr.Dataset: """ Group data based on time and sequence number values. @@ -64,6 +67,8 @@ def find_groups( Name of the sequence variable. time_name : str Name of the time variable. + check_src_seq_ctr : bool | True + Check for incrementing src_seq_ctr. Returns ------- @@ -114,7 +119,34 @@ def find_groups( # group (epoch) int64 7kB 1 1 1 1 1 1 1 1 1 ... 15 15 15 15 15 15 15 15 15 grouped_data = grouped_data.assign_coords(group=("epoch", group_labels)) - # Filter out groups with non-sequential src_seq_ctr values. - filtered_data = filter_valid_groups(grouped_data) + if check_src_seq_ctr: + # Filter out groups with non-sequential src_seq_ctr values. + filtered_data = filter_valid_groups(grouped_data) + else: + filtered_data = grouped_data return filtered_data + + +def _populate_instrument_header_items(met: np.ndarray) -> dict: + """ + Create header values. + + Parameters + ---------- + met : np.ndarray + Mission elapsed time. + + Returns + ------- + header : dict + Header for each instrument. + """ + sc_met = (met[0] + met[-1]) // 2 + header = { + "apid": 478, + "met": int(sc_met), + "met_in_utc": met_to_utc(sc_met).split(".")[0], + "ttj2000ns": int(met_to_ttj2000ns(sc_met)), + } + return header diff --git a/imap_processing/idex/evt_msg_decode_utils.py b/imap_processing/idex/evt_msg_decode_utils.py new file mode 100644 index 0000000000..ec3dff8828 --- /dev/null +++ b/imap_processing/idex/evt_msg_decode_utils.py @@ -0,0 +1,82 @@ +"""Helper functions for decoding event messages.""" + +import re + +# Regex to match spaces where we need to embed params in the event message templates, +# e.g. {p0}, {p1+2}, {p3:dict}, {p4+1|dict} +EMBEDDED_PARAM_RE = re.compile(r"\{p(\d+)(?:\+(\d+))?(?::[\w]+)?(?:\|(\w+))?\}") + + +def render_event_template( + event_description_template: str, params_bytes: list, msg_json_data: dict +) -> str: + """ + Produce an event message string by replacing placeholders with parameter values. + + Example template: + "Event {p0} occurred with value {p1+2|dictName}" + + This would replace {p0} with the hex value of params[0], and replace {p1+2:dictName} + with the combined hex value of params[1] and params[2] (treated as big-endian bytes) + looked up in the dictionary named "dictName" for a human-readable string, or + rendered as hex if not found in the dictionary. + + Parameters + ---------- + event_description_template : str + The event message template containing placeholders like {p0}, {p1+2}, + {p3:dict}, {p4+1|dict}. + params_bytes : list + The list of parameter values to substitute into the template. + msg_json_data : dict + Mapping of parameter values to human-readable strings for decoding event + messages. + + Returns + ------- + str + The rendered event message with placeholders replaced by parameter values. + """ + + def replace(m: re.Match[str]) -> str: + """ + Replace a single placeholder match with the corresponding parameter value. + + Parameters + ---------- + m : re.Match[str] + A regex match object for a placeholder in the template. + + Returns + ------- + str + The string to replace the placeholder with. + """ + # We are parsing the placeholder value here to determine which parameter + # to substitute and how to format them. + # group one is the parameter index e.g. p0-3 + idx = int(m.group(1)) + # group two is the optional byte length e.g. +2 (so we know how many params + # to combine) + n_bytes = int(m.group(2)) if m.group(2) else 1 + # group three is an optional dictionary name to use for decoding this parameter + dict_name = m.group(3) + value = 0 + for i in range(n_bytes): + # combine the next n_bytes params into a single integer value, treating + # them as big-endian bytes + value = (value << 8) | ( + params_bytes[idx + i] if idx + i < len(params_bytes) else 0 + ) + # If a dictionary name is provided use it to decode the value, otherwise just + # render as hex. + if dict_name: + resolved = msg_json_data.get(dict_name, {}).get( + value, f"0x{value:0{2 * n_bytes}X}" + ) + return f"{dict_name}({resolved})" # wrap with dict name + + return f"{value:02x}" + + # Replace all placeholders in the template using the replace function defined above. + return EMBEDDED_PARAM_RE.sub(replace, event_description_template) diff --git a/imap_processing/idex/idex_constants.py b/imap_processing/idex/idex_constants.py index 0f6d0e8f1f..8d50ddcd99 100644 --- a/imap_processing/idex/idex_constants.py +++ b/imap_processing/idex/idex_constants.py @@ -46,10 +46,17 @@ class IdexConstants: # Microseconds to seconds conversion US_TO_S = 1e-6 +# Low-rate timing constants +LOW_SAMPLE_RATE_HZ: float = 4.0625e6 +SAMPLES_PER_BLOCK: int = 8 +DT_BLOCK: float = SAMPLES_PER_BLOCK / LOW_SAMPLE_RATE_HZ + # Seconds in a day SECONDS_IN_DAY = 86400 # Nanoseconds in day NANOSECONDS_IN_DAY = SECONDS_IN_DAY * int(1e9) +# Picocoulombs to coulombs conversion factor +PICOCOULOMB_TO_COULOMB = 1e-12 # fg to kg conversion factor FG_TO_KG = 1e-15 @@ -62,7 +69,7 @@ class ConversionFactors(float, Enum): """Conversion factor values (DN to picocoulombs) for each of the six waveforms.""" TOF_High = 2.89e-4 - TOF_Low = 5.14e-4 + TOF_Low = 5.14e-1 TOF_Mid = 1.13e-2 Target_Low = 1.58e1 Target_High = 1.63e-1 @@ -88,11 +95,3 @@ class ConversionFactors(float, Enum): # Define the pointing reference frame for IDEX IDEX_EVENT_REFERENCE_FRAME = SpiceFrame.ECLIPJ2000 - - -class IDEXEvtAcquireCodes(IntEnum): - """Create ENUM for event message ints that signify science acquire events.""" - - ACQSETUP = 2 - ACQ = 3 - CHILL = 5 diff --git a/imap_processing/idex/idex_evt_msg_parsing_dictionaries.json b/imap_processing/idex/idex_evt_msg_parsing_dictionaries.json new file mode 100644 index 0000000000..be721d716e --- /dev/null +++ b/imap_processing/idex/idex_evt_msg_parsing_dictionaries.json @@ -0,0 +1,1377 @@ +{ + "logEntryIdDictionary": { + "0": "EMPTY", + "8": "PMLOG_INIT", + "10": "TASK_START", + "11": "SLICE_ERR", + "12": "PERF_PARAM_ERR", + "13": "PERF_DURR_ERR", + "14": "TASK_OVERRUN", + "15": "TASK_DONE", + "17": "EXEC_CMD", + "18": "GOT_RX_DATA", + "19": "GOOD_CCSDS", + "20": "EXEC_TIME", + "21": "DUAL_EXPIRED", + "30": "START_TX_PKT", + "32": "RX_CKSUM_ERR", + "36": "CCSDS_RX_ERR", + "37": "CMD_LEN_INVLD", + "38": "CMD_UNKNOWN", + "39": "CMD_RJCT_UNARM", + "40": "CMD_RJCT_ENGINE", + "41": "CMD_RJCT_ARGNUM", + "42": "CMD_RJCT_NULL", + "43": "CMD_RJCT_RANGE", + "44": "CMD_RJCT_MODE", + "45": "CMD_RJCT_BUSY", + "46": "CMD_NO_CMD_YET", + "48": "QBOOT_ST_CHANGE", + "49": "QBOOT_HALTED", + "50": "QBOOT_ALRDY_IDLE", + "51": "QBOOT_MEM_BUSY", + "58": "REGION_OFF_DIE", + "59": "INIT_FLASH_FOUND", + "60": "LOAD_OFF_DIE", + "61": "MEMINIT_OBJ_MISS", + "63": "INIT_CKSUM_MISMT", + "64": "UERR_SCI_DATA", + "65": "LISTED_CATALOGS", + "66": "MAKE_CATALOG_ERR", + "67": "SCI_DATA_DROPPED", + "68": "FEWER_SCI_BLOCKS", + "69": "COPYTO_NO_HALT", + "70": "AUTOSAVE_ERR", + "71": "RECOVR_MODE_RST", + "72": "RECOVR_OPER_RST", + "73": "ANALYZE_ERROR", + "74": "BOTH_MIRROR_BAD", + "75": "FOUND_SCI_DATA", + "76": "MEM_QUEUE_RJCT", + "77": "MEM_COLLAB_START", + "78": "MEM_COLLAB_SUCC", + "79": "MEM_COLLAB_FAIL", + "80": "REBUILD_SUMMARY", + "81": "CKSUM_MISMATCH", + "82": "MISMATCH_REBUILT", + "83": "FLASH_DIE_UNUSED", + "84": "NO_CHANGE_NVFSW3", + "85": "FLASH_DRIVER_ERR", + "86": "OPERATION_FAILED", + "87": "FOUND_BAD_BLOCK", + "88": "FLASH_UERR", + "89": "FLASH_CERR", + "90": "BAD_MEM_CLEANUP", + "91": "FLASH_DRIVER_ERR", + "92": "MEM_OBJ_MISSING", + "93": "BAD_MODE_EXIT", + "94": "BAD_OPER_EXIT", + "95": "SHUFFLE_ERROR", + "96": "MEM_OP_QUEUED", + "97": "MEM_FLASH_FOUND", + "98": "MEM_OP_HALTED", + "99": "MEM_OP_START", + "100": "MEM_OP_DONE", + "101": "MEM_OP_WORKING", + "102": "MEM_OP_SETUP", + "103": "MEM_OP_RUNNING", + "104": "DIR_RD_DONE", + "105": "DIR_WR_DONE", + "106": "MEM_STATE_CHG", + "107": "MEM_ALRDY_IDLE", + "108": "LOAD_SPILLOVER", + "109": "MEM_GOT_PARAM", + "110": "CKSUM_MATCH", + "111": "SHUFFLE_STATE", + "112": "SHUFFLE_DONE", + "113": "FAIL_ADD_FETCH", + "114": "POP_FETCH_TBL", + "115": "RECONCILED_FT", + "116": "DATASET_FOUND", + "117": "DATASET_NOTFOUND", + "128": "IBRAM_WDOG", + "129": "DBRAM_WDOG", + "130": "SRAM_WDOG", + "131": "EXCEPTION_WDOG", + "132": "PROC_RST_WDOG", + "133": "DECON_AUTO_DIS", + "135": "HV_CURRENT_FAULT", + "136": "HV_STATE_CHANGE", + "137": "HV_STATE_TOF_ON", + "138": "HV_VOTING_FAILED", + "139": "HV_MMR_MISMATCH", + "140": "HV_BAD_STPT_MAX", + "141": "ANA_HK_FAULTLO", + "142": "ANA_HK_FAULTHI", + "143": "HV_OSCIL_FAULT", + "144": "BOOT2OPER", + "145": "POR_RST", + "146": "CMD_RST", + "147": "BOOT_HELLO", + "148": "OPER_HELLO", + "152": "MODE_CHANGE", + "153": "TOOK_DWELL_DATA", + "154": "DWELL_COMPLETE", + "155": "STIM_COMPLETE", + "159": "HAPPY_GOODBYE", + "160": "DUBIOUS_GOODBYE", + "161": "UPK_PROC_RST", + "162": "UPK_WDOG_RST", + "163": "UPK_UNKWN_RST", + "164": "UPK_BOOT_ERR", + "192": "SCI_STATE", + "193": "MEM_COLLAB_DONE", + "194": "CATALOG_MATCH", + "196": "SCI_DONE", + "197": "SCI_PEAK_CNT", + "198": "SCI_EVENT_ID", + "199": "SCI_CAT_FULL", + "200": "SCI_PROCESS_EVT", + "203": "SCI_TRANSMIT", + "204": "SCI_DATA", + "206": "SCI_SNDEVT_AID", + "207": "SCI_SPI_READ", + "208": "SCI_CLK_FAIL", + "209": "SCI_TASK_STATE", + "211": "SCI_PARSE_SIZE", + "212": "SCI_PARSE_HDR", + "213": "SCI_PARSE_END", + "214": "SCI_PARSE_EVT", + "215": "SCI_SND_ST_ERR", + "216": "SCI_SND_CH_ERR", + "217": "SCI_PWR_ERR", + "219": "ALLOC_EXHAUSTED", + "220": "SCI_AID_PREV_USE", + "221": "PROCESS_FIRST", + "224": "SEQ_STATE_CHANGE", + "225": "SEQ_RESUME", + "226": "SEQ_TERM_AT_IDLE", + "227": "SEQ_PAUSE_IDLE", + "228": "SEQ_PAUSE_STALE", + "229": "SEQ_BUF_VERIFIED", + "230": "SEQ_ABRT_UNCLEAN", + "232": "SEQ_ERROR_STOP", + "233": "SUBSEQ_CALL_SUB", + "234": "SEQ_BAD_STATE", + "235": "SEQ_ERR_NO_SEQ", + "236": "SEQ_RECURSE_CALL", + "237": "SEQ_BUF_NOT_LOAD", + "238": "SEQ_BAD_CKSUM", + "239": "SEQ_CMD_SUCC", + "240": "FAULT_EXCESS", + "241": "FAULT_RESP_STRT", + "242": "FAULT_INTERRUPT", + "243": "FAULT_FAIL", + "244": "FAULT_IGNORED", + "245": "MODE_RESP_STRT", + "246": "MODE_RESP_FAIL", + "247": "MODE_RESP_BUSY", + "248": "SUSPEND_DONE", + "249": "ALREADY_ERASED", + "255": "ENTRY_ID_INVAL" + }, + "eventMsgDictionary": { + "8": "DES postmortem log initialized", + "10": "DES task execution started", + "11": "DES INVALID DES SLICE, INVALID ID=0x{p0:02x}{p1:02x}{p2:02x}{p3:02x}", + "12": "DES PERFMON ASKED TO ADD INVALID ENTRY, TASK ID=0x{p0:02x}{p1:02x}, SLICE=0x{p2:02x}{p3:02x}", + "13": "DES PERFMON SUSPICIOUS DURATION, TASK=0x{p0:02x}{p1:02x}, SLICE=0x{p2:02x}{p3:02x}", + "14": "DES TASK OVERRUN, START:END SLICE=0x{p0:02x}:{p1:02x}, TASK ID={p2:02x}", + "15": "DES task execution completed", + "17": "CMD success (apid=0x{p0:02x}{p1:02x}, {p2+2|opCodeLCDictionary})", + "18": "CMD received itf, byte length=0x{p0:02x}{p1:02x}{p2:02x}{p3:02x}", + "19": "CMD rx itf and ccsds pkt good, vc=0x{p0:02x}{p1:02x}, byte length=0x{p2:02x}{p3:02x}", + "20": "CMD processed spacecraft time message", + "21": "CMD engine arm state expired", + "30": "TLM started tlm pkt tx", + "32": "CMD CRC MISMATCH (DISCARDING), P=0x{p0:02x}{p1:02x}{p2:02x}{p3:02x}", + "36": "CMD ERROR WITH CCSDS HDR IN RX PKT (DISCARDING), CCSDS1=0x{p0:02x}{p1:02x}{p2:02x}{p3:02x}", + "37": "CMD OUT OF BOUNDS LENGTH, hdr field=0x{p0:02x}{p1:02x}{p2:02x}{p3:02x}", + "38": "CMD UNKNOWN, ENG={p0+2|cmdEngineDictionary}, OPCODE=0x{p2:02x}{p3:02x}", + "39": "CMD RJCT UNARM, ENG={p0+1|cmdEngineDictionary}, {p1+1|idexModeDictionary}, {p2+2|opCodeDictionary}", + "40": "CMD RJCT ENGINE, ENG={p0+1|cmdEngineDictionary}, {p1+1|idexModeDictionary}, {p2+2|opCodeDictionary}", + "41": "CMD RJCT ARG#, ENG={p0+1|cmdEngineDictionary}, {p1+1|idexModeDictionary}, {p2+2|opCodeDictionary}", + "42": "CMD RJCT NULL, ENG={p0+1|cmdEngineDictionary}, {p1+1|idexModeDictionary}, {p2+2|opCodeDictionary}", + "43": "CMD RJCT RANGE, ENG={p0+1|cmdEngineDictionary}, {p1+1|idexModeDictionary}, {p2+2|opCodeDictionary}", + "44": "CMD RJCT MODE, ENG={p0+1|cmdEngineDictionary}, {p1+1|idexModeDictionary}, {p2+2|opCodeDictionary}", + "45": "CMD RJCT BUSY, PARAM=0x{p0:02x}{p1:02x}{p2:02x}{p3:02x}", + "46": "CMD REDUCED VALIDATION CRITERIA, CCSDS=0x{p0:02x}{p1:02x}, CRC=0x{p2:02x}{p3:02x}", + "48": "QBT state change: {p0+2|qbootStateDictionary}==>{p2+2|qbootStateDictionary}", + "49": "QBT quickboot halted", + "50": "QBT quickboot halted, but already idle", + "51": "QBT unexpected memory busy state while quickbooting", + "58": "QBT FT REPORTS OBJECT IN OFF DIE, PARAM=0x{p0:02x}{p1:02x}{p2:02x}{p3:02x}", + "59": "QBT loaded {p0+2|regionLCDictionary} from block 0x{p2:02x}{p3:02x}", + "60": "QBT LOADED {p0+2|regionDictionary} FROM OFF DIE, BLOCK=0x{p2:02x}{p3:02x}", + "61": "QBT OBJECT MISSING INIT! PARAM={p0:02x}{p1:02x}{p2:02x}{p3:02x}", + "63": "MEM CKSUM MISMATCH FOUND DURING INIT, PARAM=0x{p0:02x}{p1:02x}{p2:02x}{p3:02x}", + "64": "MEM UNCORRECTABLE EDAC ERR IN SCI DATA, BLOCK=0x{p0:02x}{p1:02x} PAGE=0x{p2:02x}{p3:02x}", + "65": "MEM listed catalogs done, catalog count=0x{p0:02x}{p1:02x}{p2:02x}{p3:02x}", + "66": "MEM ERROR CREATING OR SAVING CATALOG, PARAM=0x{p0:02x}{p1:02x}{p2:02x}{p3:02x}", + "67": "MEM SCI DATA FILLED RESERVED MEMORY, REST DROPPED, ErrStatReg=0x{p0:02x}{p1:02x}{p2:02x}", + "68": "MEM only 0x{p0:02x}{p1:02x} blocks reserved out of 0x{p2:02x}{p3:02x} requested", + "69": "MEM allowing copyto glash operation to complete before halting, param=0x{p0:02x}{p1:02x}{p2:02x}{p3:02x}", + "70": "MEM AUTO-SAVE ERROR {p0+1|memOpDictionary} {p1+1|regionDictionary} PARAM=0x{p2:02x} CODE=0x{p3:02x}", + "71": "MEM FOUND RESET DURING CORRUPTION SENSITIVE MODE, P=0x{p0:02x}{p1:02x}{p2:02x}{p3:02x}", + "72": "MEM FOUND RESET DURING CORRUPTION SENSITIVE MEM OPER, P=0x{p0:02x}{p1:02x}{p2:02x}{p3:02x}", + "73": "MEM FLASH BLOCK ANALYSIS FAILURE, Block=0x{p0:02x}{p1:02x} ERROR=0x{p2:02x}{p3:02x}", + "74": "MEM BOTH MIRRORED BLOCKS FOUND BAD AT SAME TIME, PARAM=0x{p0:02x}{p1:02x}{p2:02x}{p3:02x}", + "75": "MEM cleanup found sci data, blocks empty=0x{p0:02x}{p1:02x}, blocks w/data=0x{p2:02x}{p3:02x}", + "76": "MEM QUEUED MEM CMD REJECTED, PARAM=0x{p0:02x}{p1:02x}{p2:02x}{p3:02x}", + "77": "MEM collaboration started, {p0+1|memCollabDictionary}, param=0x{p1:02x}{p2:02x}{p3:02x}", + "78": "MEM collaboration succeeded, {p0+1|memCollabDictionary}, param=0x{p1:02x}{p2:02x}{p3:02x}", + "79": "MEM MEMORY COLLABORATION FAILED, {p0+1|memCollabCAPSDictionary}, PARAM=0x{p1:02x}{p2:02x}{p3:02x}", + "80": "MEM REBUILD ERROR SUMMARY, PARAM=0x{p0:02x}{p1:02x}{p2:02x}{p3:02x}", + "81": "MEM CKSUM MISMATCH FOR OBJECT, PARAM=0x{p0:02x}{p1:02x}{p2:02x}{p3:02x}", + "82": "MEM REBUILT MISMATCHED FT ENTRY, PARAM=0x{p0:02x}{p1:02x}{p2:02x}{p3:02x}", + "83": "MEM FLASH DIE UNPOWERED, PARAM=0x{p0:02x}{p1:02x}{p2:02x}{p3:02x}", + "84": "MEM REJECT MODIFY NVFSW3, PARAM=0x{p0:02x}{p1:02x}{p2:02x}{p3:02x}", + "85": "MEM UNEXPECTED FLASH ERROR, PARAM=0x{p0:02x}{p1:02x}{p2:02x}{p3:02x}", + "86": "MEM OPERATION FAILED, PARAM=0x{p0:02x}{p1:02x}{p2:02x}{p3:02x}", + "87": "MEM FOUND BAD BLOCK, BLOCK=0x{p0:02x}{p1:02x} ERRTYPE={p2:02x} OLDSTATE={p3:02x}", + "88": "MEM FLASH UErr FOUND, PARAM=0x{p0:02x}{p1:02x}{p2:02x}{p3:02x}", + "89": "MEM FLASH CErr FOUND, PARAM=0x{p0:02x}{p1:02x}{p2:02x}{p3:02x}", + "90": "MEM BAD CLEANUP STATE P={p0:02x}{p1:02x}{p2:02x}{p3:02x}", + "91": "MEM FLASH DRIVER ERROR P={p0:02x}{p1:02x}{p2:02x}{p3:02x}", + "92": "MEM OBJECT MISSING! REGION={p0+2|regionDictionary}, BLOCK={p2:02x}{p3:02x}", + "93": "MEM FOUND CORRUPTION-SENSITIVE MODE EXITED ABNORMALLY", + "94": "MEM FOUND CORRUPTION-SENSITIVE MEM OPER EXITED ABNORMALLY", + "95": "MEM SHUFFLE OPER ERROR, STATE=0x{p0:02x}{p1:02x} BLOCK=0x{p2:02x}{p3:02x}", + "96": "MEM operation queued, {p0+2|memOpLCDictionary} {p2+2|regionLCDictionary}", + "97": "MEM found {p0+2|regionLCDictionary} in block 0x{p2:02x}{p3:02x}", + "98": "MEM operation halted", + "99": "MEM memory operation started", + "100": "MEM {p0+1|memOpLCDictionary} {p1+1|regionLCDictionary} complete, duration=0x{p2:02x}{p3:02x}", + "101": "MEM operation working P=0x{p0:02x}{p1:02x}{p2:02x}{p3:02x}", + "102": "MEM operation setup P=0x{p0:02x}{p1:02x}{p2:02x}{p3:02x}", + "103": "MEM operation running P=0x{p0:02x}{p1:02x}{p2:02x}{p3:02x}", + "104": "MEM exec raw read, value=0x{p0:02x}{p1:02x}{p2:02x}{p3:02x}", + "105": "MEM exec raw write, addr=0x{p0:02x}{p1:02x}{p2:02x}{p3:02x}", + "106": "MEM state change: Transition {p0+2|memStateLCDictionary} <== {p2+2|memStateLCDictionary}", + "107": "MEM got halt but already idle", + "108": "MEM load command spillover, Offset8=0x{p0:02x} Len8={p1:02x}", + "109": "MEM got param cmd received and executed, param=0x{p0:02x}{p1:02x}{p2:02x}{p3:02x}", + "110": "MEM checksum matched expected", + "111": "MEM shuffle state change: Transition 0x{p0:02x}{p1:02x} <== 0x{p2:02x}{p3:02x}", + "112": "MEM shuffle complete, param=0x{p0:02x}{p1:02x}{p2:02x}{p3:02x}", + "113": "MEM FETCH TABLE FAILED TO ADD, param=0x{p0:02x}{p1:02x}{p2:02x}{p3:02x}", + "114": "MEM popped fetch table entry, param=0x{p0:02x}{p1:02x}{p2:02x}{p3:02x}", + "115": "MEM reconciled Flash Table, number entries fixed=0x{p0:02x}{p1:02x}{p2:02x}{p3:02x}", + "116": "MEM Science dataset with AID 0x{p0:02x}{p1:02x}{p2:02x}{p3:02x} found", + "117": "MEM SCIENCE DATASET WITH AID 0x{p0:02x}{p1:02x}{p2:02x}{p3:02x} NOT FOUND", + "128": "AUT IBRAM EDAC MERR DETECTED (WDOG RESET LIKELY), P=0x{p0:02x}{p1:02x}{p2:02x}{p3:02x}", + "129": "AUT DBRAM EDAC MERR DETECTED (WDOG RESET LIKELY), P=0x{p0:02x}{p1:02x}{p2:02x}{p3:02x}", + "130": "AUT SRAM EDAC MERR DETECTED (WDOG RESET LIKELY), P=0x{p0:02x}{p1:02x}{p2:02x}{p3:02x}", + "131": "AUT CAUSING WDOG RESET DUE TO PROCESSOR EXCEPTION, P=0x{p0:02x}{p1:02x}{p2:02x}{p3:02x}", + "132": "AUT CAUSING WDOG RESET DUE TO PROCESSOR-ONLY RESET, P=0x{p0:02x}{p1:02x}{p2:02x}{p3:02x}", + "133": "AUT DECON ENABLED OUTSIDE MODE, DISABLING, P=0x{p0:02x}{p1:02x}{p2:02x}{p3:02x}", + "135": "AUT HVPS DET CURRENT TOO HIGH FAULT I=0x{p0:02x}{p1:02x} Limit=0x{p2:02x}{p3:02x}", + "136": "AUT hvps state changed to {p0+4|hvStateDictionary}", + "137": "AUT TOF ADCS ON BUT HVPS CHANGED {p0+1|hvStateDictionary} TO {p1+1|hvStateDictionary}, ADC0=0x{p2:02x}, ADC1=0x{p3:02x}", + "138": "AUT HVPS TRIPLE-VOTING FAILED, {p0+4|hvMmrMismatchDictionary}", + "139": "AUT HVPS FPGA MMR FAILS LAST WRITTEN VALUE CHECK, P=0x{p0:02x}{p1:02x} {p2+2|hvMmrMismatchDictionary}", + "140": "AUT HVPS SETPOINT (0x{p0:02x}{p1:02x}) GREATER THAN MAX (0x{p2:02x}{p3:02x})", + "141": "AUT ANALOG HK(0x{p0:02x}{p1:02x}) 0x{p2:02x}{p3:02x} IS FAULT LO", + "142": "AUT ANALOG HK(0x{p0:02x}{p1:02x}) 0x{p2:02x}{p3:02x} IS FAULT HI", + "143": "AUT HVPS SENSOR OSCILLATOR FAULT, P=0x{p0:02x}{p1:02x}{p2:02x}{p3:02x}", + "144": "UPK transition from {p0:02x} {p1+1|idexModeLCDictionary} to {p2:02x} {p3+1|idexModeLCDictionary}", + "145": "UPK power-on reset, P=0x{p0:02x}{p1:02x}{p2:02x}{p3:02x}", + "146": "UPK commanded reset, P=0x{p0:02x}{p1:02x}{p2:02x}{p3:02x}", + "147": "UPK boot fsw says hello, version={p0:02x}.{p1:02x}.{p2:02x}{p3:02x}", + "148": "UPK oper fsw says hello, version={p0:02x}.{p1:02x}.{p2:02x}{p3:02x}", + "152": "UPK mode changed from {p0+2|idexModeLCDictionary} to {p2+2|idexModeLCDictionary}", + "153": "UPK analog dwell measurement recorded", + "154": "UPK analog dwell completed", + "155": "UPK stim pulser operation completed, , PulserSel=0x{p0:02x}{p1:02x}{p2:02x}{p3:02x}", + "159": "UPK csci change imminent to {p0+4|idexModeLCDictionary} - goodbye", + "160": "UPK RESET IMMINENT TO {p0+4|idexModeDictionary} - DUBIOUS GOODBYE!", + "161": "UPK PROCESSOR ONLY RESET, P=0x{p0:02x}{p1:02x}{p2:02x}{p3:02x}", + "162": "UPK WATCHDOG RESET, P=0x{p0:02x}{p1:02x}{p2:02x}{p3:02x}", + "163": "UPK UNKNOWN RESET, P=0x{p0:02x}{p1:02x}{p2:02x}{p3:02x}", + "164": "UPK BOOT STATUS ERROR, P=0x{p0:02x}{p1:02x}{p2:02x}{p3:02x}", + "192": "SCI state change: {p0+2|sciState16Dictionary} ==> {p2+2|sciState16Dictionary}", + "193": "SCI collab {p0+2|memCollabDictionary} is {p2+2|memCollabStatLCDictionary}", + "194": "SCI event ID 0x{p0:02x}{p1:02x} found matching category 0x{p2:02x}{p3:02x}", + "196": "SCI science activity completed: {p0+4|sciState16Dictionary}", + "197": "SCI process channel: {p0+2|sciChannel16Dictionary}, peak cnt (0x{p2:02x}{p3:02x})", + "198": "SCI event trigger (0x{p0:02x}{p1:02x}) id (0x{p2:02x}{p3:02x})", + "199": "SCI process cat full AID (0x{p0:02x}{p1:02x}) count (0x{p2:02x}{p3:02x})", + "200": "SCI process event id (0x{p0:02x}{p1:02x}) Category (0x{p2:02x}{p3:02x})", + "203": "SCI transmit: id (0x{p0:02x}{p1:02x}) cat (0x{p2:02x}) content (0x{p3:02x})", + "204": "SCI data: (0x{p0:02x}{p1:02x}{p2:02x}{p3:02x})", + "206": "SCI sending event with aid (0x{p0:02x}{p1:02x}) and evt num (0x{p2:02x}{p3:02x})", + "207": "SCI spi read: adc (0x{p0:02x}) addr (0x{p1:02x}) value (0x{p2:02x}{p3:02x})", + "208": "SCI CLOCK TRAINING FAILED: Size (0x{p0:02x}{p1:02x}) retry (0x{p2:02x}{p3:02x})", + "209": "SCI TASK STATE ERROR: {p0+2|sciState16Dictionary} ==> {p2+2|sciState16Dictionary}", + "211": "SCI PARSE SIZE ERROR: channel (0x{p0:02x}{p1:02x}) size (0x{p2:02x}{p3:02x})", + "212": "SCI PARSE HEADER SIZE ERROR: packetlen (0x{p0:02x}{p1:02x}) block size (0x{p2:02x}{p3:02x})", + "213": "SCI PARSE END ERROR: STATE {p0+2|sciState16Dictionary} root (0x{p2:02x}{p3:02x})", + "214": "SCI PARSE EVENT ERROR: page (0x{p0:02x}{p1:02x}) id (0x{p2:02x}{p3:02x})", + "215": "SCI SEND STATE ERROR: STATE (0x{p0:02x}{p1:02x}{p2:02x}{p3:02x})", + "216": "SCI SEND CHANNEL ERROR: CHANNEL (0x{p0:02x}{p1:02x}{p2:02x}{p3:02x})", + "217": "SCI ADC POWER ERROR: exp {p0+1|enaDis32Dictionary} act {p1+1|enaDis32Dictionary} chan {p2+2|sciChannel16Dictionary}", + "219": "SCI BDS ALLOCATION EXHAUSTED: REMAINING={p0:02x}", + "220": "SCI AID ALREADY PRESENT: AID=0x{p0:02x}{p1:02x}{p2:02x}{p3:02x}", + "221": "SCI DATASET NEEDS PROCESSING BEFORE TRANSMIT", + "224": "SEQ engine has changed state, eng=seqEngineDictionary(0x{p0:02x}) was={p1+1|seqEngineStateDictionary} is={p2+1|seqEngineStateDictionary} 0x{p3:02x}", + "225": "SEQ got resume command when not paused, eng={p0+2|seqEngineDictionary} state={p2+2|seqEngineStateDictionary}", + "226": "SEQ got terminate command when already idle, eng={p0+2|seqEngineDictionary} state={p2+2|seqEngineStateDictionary}", + "227": "SEQ got pause command when already idle, eng={p0+2|seqEngineDictionary} state={p2+2|seqEngineStateDictionary}", + "228": "SEQ GOT PAUSE COMMAND WHEN STALE, eng={p0+2|seqEngineDictionary} state={p2+2|seqEngineStateDictionary}", + "229": "SEQ buffer successfully verified, buf={p0+4|seqBufferDictionary}", + "230": "SEQ ABORTED BUT CANNOT CLEANUP, ENG={p0+2|seqEngineDictionary} BUF={p2+2|seqBufferDictionary}", + "232": "SEQ ENGINE STOPPED DUE TO ERROR, ENG={p0+1|seqEngineDictionary} STATE={p1+1|seqEngineStateDictionary} STOPCODE={p2+1|seqEngStopCodeDictionary} 0x{p3:02x}", + "233": "SEQ ATTEMPTED TO CALL SUBSEQ WHILE ALREADY IN SUBSEQ, eng={p0+2|seqEngineDictionary} state={p2+2|seqEngineStateDictionary}", + "234": "SEQ STATE IS UNDEFINED, STOPPING AND GOING TO IDLE, ENG={p0+2|seqEngineDictionary} STATE={p2+2|seqEngineStateDictionary}", + "235": "SEQ ATTEMPTING WORK ON SEQUENCE THAT IS NOT LOADED, ENG={p0+2|seqEngineDictionary} STATE={p2+2|seqEngineStateDictionary}", + "236": "SEQ ATTEMPTED SUBSEQ CALL FROM ONE BUF TO SAME BUF, ENG={p0+2|seqEngineDictionary} STATE={p2+2|seqEngineStateDictionary}", + "237": "SEQ ATTEMPTED OPERATION ON UNLOADED BUF, BUF={p0+4|seqBufferDictionary}", + "238": "SEQ BUF'S CALCULATED CKSUM DOES NOT MATCH HDR, BUF={p0+4|seqBufferDictionary}", + "239": "SEQ success (len=0x{p0:02x}{p1:02x}, {p2+2|opCodeLCDictionary})", + "240": "SEQ EXCESS FAULT RESPONSE COUNT: FAULT={p0+1|faultSeqDictionary} STATE={p1+1|seqState3Dictionary} ENG={p2+1|seqEngineStateDictionary} BUFID=0x{p3:02x}", + "241": "SEQ Start Fault Resp: FAULT={p0+1|faultSeqDictionary} STATE={p1+1|seqState3Dictionary} ENG={p2+1|seqEngineStateDictionary} BUFID=0x{p3:02x}", + "242": "SEQ Higher Priority Fault: FAULT={p0+1|faultSeqDictionary} STATE={p1+1|seqState3Dictionary} ENG={p2+1|seqEngineStateDictionary} BUFID=0x{p3:02x}", + "243": "SEQ Fault Verify Fail: FAULT={p0+1|faultSeqDictionary} STATE={p1+1|seqState3Dictionary} ENG={p2+1|seqEngineStateDictionary} BUFID=0x{p3:02x}", + "244": "SEQ Fault Lower Priority Ignored: FAULT={p0+1|faultSeqDictionary} STATE={p1+1|seqState3Dictionary} ENG={p2+1|seqEngineStateDictionary} BUFID=0x{p3:02x}", + "245": "SEQ mode trans started: modetrans={p0+1|modeTransDictionary} state={p1+1|seqEngineStateDictionary} eng={p2+1|seqEngineDictionary} BUFID=0x{p3:02x}", + "246": "SEQ TRANS VERIFY FAIL: MODE={p0+1|modeTransDictionary} STATE={p1+1|seqEngineStateDictionary} ENG={p2+1|seqEngineDictionary} BUFID=0x{p3:02x}", + "247": "SEQ TRANS IGNORED NOT IDLE: MODE={p0+1|modeTransDictionary} STATE={p1+1|seqEngineStateDictionary} ENG={p2+1|seqEngineDictionary} BUFID=0x{p3:02x}", + "248": "SEQ suspend complete, eng={p0+2|seqEngineDictionary}, reason={p2+2|seqSuspendEndDictionary}", + "249": "SEQ attempted to erase seq but already empty, BUF={p0+4|seqBufferDictionary}", + "254": "??? INVALID FE, P=0x{p0:02x}{p1:02x}{p2:02x}{p3:02x}", + "255": "??? INVALID FF, P=0x{p0:02x}{p1:02x}{p2:02x}{p3:02x}" + }, + "busyStateTypeDictionary": { + "1": "BUSY", + "0": "OK" + }, + "idexModeDictionary": { + "0": "NONE", + "1": "BOOT", + "2": "SAFE", + "3": "IDLE", + "4": "DECON", + "5": "SCIENCE", + "6": "TRANSMIT" + }, + "idexModeLCDictionary": { + "0": "none", + "1": "boot", + "2": "safe", + "3": "idle", + "4": "decon", + "5": "science", + "6": "transmit" + }, + "chgModeInputType32Dictionary": { + "2": "SAFE", + "3": "IDLE", + "4": "DECON", + "5": "SCIENCE", + "6": "TRANSMIT" + }, + "ovrflwStateTypeDictionary": { + "1": "ERR", + "0": "OK" + }, + "regionDictionary": { + "0": "SCISTART", + "1": "NVFSW1", + "2": "NVFSW2", + "3": "NVFSW3", + "4": "NVPT", + "5": "SCICONT", + "6": "NVPERST", + "7": "NVFT", + "8": "NVPM", + "9": "NVSCIT", + "10": "SCIRSVP", + "11": "NVFETCHT", + "12": "NVSCS", + "13": "NVCATALOG", + "14": "REG14", + "15": "USER", + "16": "SCRATCH", + "17": "ACTFSW", + "18": "PT", + "19": "FT", + "20": "PERST", + "21": "SCIT", + "22": "SCS", + "24": "CATALOG", + "25": "FETCHT", + "51": "BLOCK", + "63": "NONE" + }, + "regionLCDictionary": { + "0": "scistart", + "1": "nvfsw1", + "2": "nvfsw2", + "3": "nvfsw3", + "4": "nvpt", + "5": "scicont", + "6": "nvperst", + "7": "nvft", + "8": "nvpm", + "9": "nvscit", + "10": "scirsvp", + "11": "nvfetcht", + "12": "nvscs", + "13": "nvcatalog", + "14": "reg14", + "15": "user", + "16": "scratch", + "17": "actfsw", + "18": "pt", + "19": "ft", + "20": "perst", + "21": "scit", + "22": "scs", + "24": "catalog", + "25": "fetcht", + "51": "block", + "63": "none" + }, + "qbootRegion2Dictionary": { + "0": "NONE", + "1": "NVFSW1", + "2": "NVFSW2", + "3": "NVFSW3" + }, + "qbootRegion8Dictionary": { + "0": "NONE", + "1": "NVFSW1", + "2": "NVFSW2", + "3": "NVFSW3", + "63": "NONE" + }, + "memRegionDumpDictionary": { + "1": "NVFSW1", + "2": "NVFSW2", + "3": "NVFSW3", + "4": "NVPT", + "6": "NVPERST", + "7": "NVFT", + "8": "NVPM", + "9": "NVSCIT", + "11": "NVFETCHT", + "12": "NVSCS", + "13": "NVCATALOG", + "16": "SCRATCH", + "17": "ACTFSW", + "18": "PT", + "19": "FT", + "20": "PERST", + "21": "SCIT", + "22": "SCS", + "24": "CATALOG", + "25": "FETCHT", + "51": "BLOCK" + }, + "memRegionCksumDictionary": { + "1": "NVFSW1", + "2": "NVFSW2", + "3": "NVFSW3", + "4": "NVPT", + "6": "NVPERST", + "7": "NVFT", + "9": "NVSCIT", + "11": "NVFETCHT", + "12": "NVSCS", + "13": "NVCATALOG", + "16": "SCRATCH", + "17": "ACTFSW", + "18": "PT", + "19": "FT", + "20": "PERST", + "21": "SCIT", + "22": "SCS", + "24": "CATALOG", + "25": "FETCHT" + }, + "memRegionCopyToDictionary": { + "1": "NVFSW1", + "2": "NVFSW2", + "4": "NVPT", + "6": "NVPERST", + "7": "NVFT", + "9": "NVSCIT", + "11": "NVFETCHT", + "12": "NVSCS", + "13": "NVCATALOG", + "17": "ACTFSW", + "18": "PT", + "19": "FT", + "20": "PERST", + "21": "SCIT", + "22": "SCS", + "24": "CATALOG", + "25": "FETCHT", + "51": "BLOCK" + }, + "memRegionCopyFromDictionary": { + "1": "NVFSW1", + "2": "NVFSW2", + "3": "NVFSW3", + "4": "NVPT", + "6": "NVPERST", + "7": "NVFT", + "8": "NVPM", + "9": "NVSCIT", + "11": "NVFETCHT", + "12": "NVSCS", + "13": "NVCATALOG", + "17": "ACTFSW", + "18": "PT", + "19": "FT", + "20": "PERST", + "21": "SCIT", + "22": "SCS", + "24": "CATALOG", + "25": "FETCHT", + "51": "BLOCK" + }, + "memRegionEraseDictionary": { + "8": "NVPM", + "16": "SCRATCH", + "17": "ACTFSW", + "24": "CATALOG", + "25": "FETCHT", + "51": "BLOCK" + }, + "memRegionRebuildDictionary": { + "51": "BLOCK" + }, + "memRegionShuffleDictionary": { + "51": "BLOCK" + }, + "memRegionSetHdrDictionary": { + "1": "NVFSW1", + "2": "NVFSW2", + "3": "NVFSW3", + "51": "BLOCK" + }, + "memOpDictionary": { + "0": "NONE", + "1": "DUMP", + "2": "CKSUM", + "4": "ERASE", + "8": "CPYTO", + "16": "CPYFROM", + "32": "REBUILD", + "64": "SHUFFLE" + }, + "memOpLCDictionary": { + "0": "none", + "1": "dump", + "2": "cksum", + "4": "erase", + "8": "cpyto", + "16": "cpyfrom", + "32": "rebuild", + "64": "shuffle" + }, + "memStateDictionary": { + "1": "NOTINIT", + "2": "IDLE", + "4": "DUMPSRAM", + "5": "CKSUMSRAM", + "6": "ERASESRAM", + "7": "CPY2SRAM", + "8": "CPYSRAM", + "9": "SETUPSCI", + "10": "CLEANSCI", + "11": "COPYFLASH", + "12": "COPY2FLASH", + "13": "ERASEFLASH", + "14": "DUMPFLASH", + "15": "CKSUMFLASH", + "16": "REBUILD", + "17": "SHUFFLE", + "18": "CLEANUP", + "19": "FETCHSCI", + "20": "ERASESCI" + }, + "memStateLCDictionary": { + "1": "notinit", + "2": "idle", + "4": "dumpsram", + "5": "cksumsram", + "6": "erasesram", + "7": "copy2sram", + "8": "cpysram", + "9": "setupsci", + "10": "cleansci", + "11": "copyflash", + "12": "copy2flash", + "13": "eraseflash", + "14": "dumpflash", + "15": "cksumflash", + "16": "rebuild", + "17": "shuffle", + "18": "cleanup", + "19": "fetchsci", + "20": "erasesci" + }, + "memCollabCAPSDictionary": { + "0": "SAVEPMLOG", + "1": "SCISETUP", + "2": "SCICLEANUP", + "3": "SCIFIND", + "4": "SCICOPY", + "5": "SCIFETCH", + "6": "GETCATALOG", + "7": "SAVECATALOG", + "8": "ERASESCI" + }, + "memCollabDictionary": { + "0": "savepmlog", + "1": "scisetup", + "2": "scicleanup", + "3": "scifind", + "4": "scicopy", + "5": "scifetch", + "6": "getcatalog", + "7": "savecatalog", + "8": "erasesci" + }, + "memCollabStatLCDictionary": { + "0": "busy", + "1": "success", + "2": "FAIL", + "3": "NEVER" + }, + "adpMetaControlDictionary": { + "1": "START", + "2": "END" + }, + "setAllocType32Dictionary": { + "0": "SET", + "1": "ADD" + }, + "deconSelDictionary": { + "0": "THERM0", + "1": "THERM1" + }, + "logSel8Dictionary": { + "0": "EVT", + "1": "PM", + "2": "CMD" + }, + "catalogSelDictionary": { + "0": "ALL", + "1": "HDR", + "2": "PAGE2", + "3": "PAGE3", + "4": "PAGE4", + "5": "PAGE5", + "6": "PAGE6", + "7": "PAGE7", + "8": "PAGE8", + "9": "PAGE9", + "10": "PAGE10", + "11": "PAGE11", + "12": "PAGE12", + "13": "PAGE13", + "14": "PAGE14", + "15": "PAGE15", + "16": "PAGE16", + "17": "PAGE17", + "18": "PAGE18", + "19": "PAGE19", + "20": "PAGE20", + "21": "PAGE21", + "22": "PAGE22", + "23": "PAGE23", + "24": "PAGE24", + "25": "PAGE25", + "26": "PAGE26", + "27": "PAGE27", + "28": "PAGE28", + "29": "PAGE29", + "30": "PAGE30", + "31": "PAGE31", + "32": "PAGE32", + "33": "PAGE33", + "34": "PAGE34", + "35": "PAGE35", + "36": "PAGE36", + "37": "PAGE37", + "38": "PAGE38", + "39": "PAGE39", + "40": "PAGE40", + "41": "PAGE41", + "42": "PAGE42", + "43": "PAGE43", + "44": "PAGE44", + "45": "PAGE45", + "46": "PAGE46", + "47": "PAGE47", + "48": "PAGE48", + "49": "PAGE49", + "50": "PAGE50", + "51": "PAGE51", + "52": "PAGE52", + "53": "PAGE53", + "54": "PAGE54", + "55": "PAGE55", + "56": "PAGE56", + "57": "PAGE57", + "58": "PAGE58", + "59": "PAGE59", + "60": "PAGE60", + "61": "PAGE61", + "62": "PAGE62", + "63": "PAGE63" + }, + "flagSel32Dictionary": { + "1": "PWRCYC", + "2": "PANIC", + "3": "BUSY", + "4": "PWRDOWN", + "5": "SAFE", + "6": "WDOG", + "7": "SPARE0", + "8": "SPARE1", + "9": "SPARE2", + "10": "MODEINTR", + "11": "OPERINTR", + "12": "BDSALLOC" + }, + "panicStateTypeDictionary": { + "1": "PANIC", + "0": "OK" + }, + "resetTypeDictionary": { + "0": "UNKWN", + "1": "POR", + "2": "WDOG", + "3": "CMD", + "4": "PROC", + "5": "BOOT" + }, + "irqOrdinalDictionary": { + "0": "WDOG", + "1": "BRAMINST", + "2": "BRAMDATA", + "3": "SRAM", + "4": "TIMER", + "5": "WISHBONE", + "6": "TIMEMSG", + "7": "PLL", + "8": "FLASHDONE", + "15": "NONE" + }, + "injectingErrorDictionary": { + "0": "OKAY", + "1": "BADBLOCK", + "2": "CERR", + "3": "BBCERR", + "4": "MERR", + "5": "BBMERR", + "6": "INVLD", + "7": "INVLD" + }, + "triggerModeDictionary": { + "0": "None", + "1": "THOLD", + "2": "PULSE1", + "3": "PULSE2" + }, + "triggerPolarityDictionary": { + "0": "ABOVE", + "1": "BELOW" + }, + "externTriggerDictionary": { + "0": "FALL", + "1": "RISE" + }, + "sciState16Dictionary": { + "0": "IDLE", + "1": "ACQCLEANUP", + "2": "ACQSETUP", + "3": "ACQ", + "4": "CAL", + "5": "CHILL", + "6": "CLKPATTERN", + "7": "CLK", + "8": "DUMPADCSPI", + "9": "MEMCOPY", + "10": "FETCHEVT", + "11": "MEMFIND", + "12": "MEMGETCAT", + "13": "MEMSAVCAT", + "14": "PARSE", + "15": "PROCESS", + "16": "SEND", + "17": "READSPI", + "18": "TRANSMIT", + "19": "ADCINIT" + }, + "sciChannel16Dictionary": { + "0": "HS_HIGH_GAIN", + "1": "HS_LOW_GAIN", + "2": "HS_MID_GAIN", + "3": "LS_TLR", + "4": "LS_THR", + "5": "LS_ION", + "6": "MAX_CHANNEL" + }, + "sciSndEvtSt16Dictionary": { + "0": "HEADER_RDY", + "1": "HEADER_SNT", + "2": "CHANNEL_COMP_ZERO", + "3": "CHANNEL_COMP_RDY", + "4": "CHANNEL_COMP_SNT", + "5": "CHANNEL_PACK_RDY", + "6": "CHANNEL_PACK_SNT", + "7": "CHANNEL_RDY", + "8": "CHANNEL_SNT", + "9": "EVT_SEND_DONE", + "10": "EVT_MAX_STATE" + }, + "sciChanOneHotDictionary": { + "0": "NONE", + "1": "EVTHDR", + "2": "TOFHG", + "4": "TOFLG", + "8": "TOFMG", + "16": "TLR", + "32": "THR", + "64": "ION", + "127": "ALL" + }, + "depthSelTypeDictionary": { + "0": "B10", + "1": "B12" + }, + "cmdEngineDictionary": { + "0": "AUTO", + "1": "OPER", + "2": "RT" + }, + "setSeqStateDictionary": { + "1": "PAUSE", + "2": "RESUME", + "3": "TERM" + }, + "seqEngineDictionary": { + "0": "AUTO", + "1": "OPER" + }, + "seqBufferDictionary": { + "0": "BUF0", + "1": "BUF1", + "2": "BUF2", + "3": "BUF3", + "4": "BUF4", + "5": "BUF5", + "6": "BUF6", + "7": "BUF7", + "8": "BUF8", + "9": "BUF9", + "10": "BUF10", + "11": "BUF11", + "12": "BUF12", + "13": "BUF13", + "14": "BUF14", + "15": "BUF15", + "16": "BUF16", + "17": "BUF17", + "18": "BUF18", + "19": "BUF19", + "20": "BUF20", + "21": "BUF21", + "22": "BUF22", + "23": "BUF23", + "24": "BUF24", + "25": "BUF25", + "26": "BUF26", + "27": "BUF27", + "28": "BUF28", + "29": "BUF29", + "30": "BUF30", + "31": "BUF31", + "32": "BUF32", + "33": "NONE" + }, + "seqEngineStateDictionary": { + "0": "IDLE", + "1": "ACTIV", + "2": "SUSPN", + "3": "PAUSE", + "4": "STALE" + }, + "seqEngStopCodeDictionary": { + "0": "NOM", + "1": "CMD", + "2": "VRFY", + "3": "RJCT", + "4": "STALE", + "5": "ZERO" + }, + "seqEngWaitTypeDictionary": { + "0": "None", + "1": "Abs", + "2": "Rel", + "3": "Cond" + }, + "seqSuspendEndDictionary": { + "0": "None", + "1": "Abs", + "2": "Rel", + "3": "Cond", + "4": "SciIdle", + "5": "Timeout" + }, + "seqState3Dictionary": { + "0": "Clear", + "1": "Start", + "2": "Done", + "3": "FAIL", + "4": "Intr" + }, + "cmdExecStatusDictionary": { + "0": "NONE", + "1": "OKAY", + "2": "BUSY", + "3": "LENGTH", + "4": "ID", + "5": "PROT", + "6": "RANGE", + "7": "MODE", + "8": "SRC", + "9": "ARGNUM", + "10": "NULL", + "11": "CRC", + "12": "OKAY2", + "13": "TIMEMSG", + "14": "CCSDS" + }, + "opCodeDictionary": { + "0": "NONE", + "4353": "NOOP", + "34561": "RST", + "34563": "SHUTDWN", + "36352": "SETAIDBIN", + "52416": "SETFLAG", + "52417": "CLRFLAG", + "52418": "LISTCATALOGS", + "52419": "CHGMODE", + "52420": "DUMPLOG", + "52421": "DWELL", + "52422": "CFGHTR", + "52423": "DSHTR", + "52424": "HALTQB", + "52425": "DUALCMD", + "52426": "CLRCMDST", + "52427": "LOADMEM", + "52428": "RAWWRT", + "52429": "RAWREAD", + "52430": "RAWCPY", + "52431": "SETPRM", + "52432": "GETPRM", + "52433": "WRFTBL", + "52434": "DUMPFTBL", + "52436": "SETMEMHDR", + "52437": "ERASEMEM", + "52438": "CKSUMMEM", + "52439": "DUMPMEM", + "52440": "COPYTOMEM", + "52441": "COPYFROMMEM", + "52445": "ACQUIRE", + "52446": "PROCESS_XMIT", + "52447": "WRSPI", + "52448": "ERASESCI", + "52449": "SETSCIPRM", + "52450": "INITSEQ", + "52451": "STRTSEQ", + "52452": "SETSEQST", + "52453": "SUSPABS", + "52454": "SUSPREL", + "52455": "CLSUB", + "52456": "VERSEQ", + "52457": "CLRFAULTCNT", + "52458": "SHUTDWNHV", + "52459": "CLRTLMST", + "52460": "CLRMEM", + "52461": "CLRSCI", + "52462": "REBUILD", + "52463": "SHUFFLE", + "52464": "DUMPADC", + "52465": "HALTSCI", + "52466": "HALTMEM", + "52467": "CLRUK", + "52468": "PTSEQ", + "52469": "STUFFSEQ", + "52470": "ERASESEQ", + "52480": "PWRADC", + "52481": "CFGADCTOF", + "52482": "CFGADCTAR", + "52483": "CFGSCIACQ", + "52484": "CFGTRG", + "52485": "INITADC", + "52486": "CALADC", + "52487": "TRAINADCCLK", + "52488": "SETHVPWR", + "52490": "DSHVOSC", + "52491": "SETHVSETPT", + "52492": "SETHVMAX", + "52493": "CLRATN", + "52494": "CLRSEQ", + "52495": "READSPI", + "52496": "FETCHONE", + "52506": "FETCH", + "52507": "TRANSMIT", + "52508": "SENDCATALOG", + "52509": "SUSPIDLESCI", + "52510": "SETALLOC", + "52511": "ADDTOFETCH", + "52512": "CFGSTIM", + "52513": "ENSTIM", + "52514": "HALTSTIM", + "48059": "DEPLOYDOOR", + "61166": "ENAHVOSC" + }, + "opCodeLCDictionary": { + "0": "none", + "4353": "noop", + "34561": "rst", + "34563": "shutdwn", + "36352": "setaidbin", + "52416": "setflag", + "52417": "clrflag", + "52418": "listcatalogs", + "52419": "chgmode", + "52420": "dumplog", + "52421": "dwell", + "52422": "cfghtr", + "52423": "dshtr", + "52424": "haltqb", + "52425": "dualcmd", + "52426": "clrcmdst", + "52427": "loadmem", + "52428": "rawwrt", + "52429": "rawread", + "52430": "rawcpy", + "52431": "setprm", + "52432": "getprm", + "52433": "wrftbl", + "52434": "dumpftbl", + "52436": "setmemhdr", + "52437": "erasemem", + "52438": "cksummem", + "52439": "dumpmem", + "52440": "copytomem", + "52441": "copyfrommem", + "52445": "acquire", + "52446": "process_xmit", + "52447": "wrspi", + "52448": "erasesci", + "52449": "setsciprm", + "52450": "initseq", + "52451": "strtseq", + "52452": "setseqst", + "52453": "suspabs", + "52454": "susprel", + "52455": "clsub", + "52456": "verseq", + "52457": "clrfaultcnt", + "52458": "shutdwnhv", + "52459": "clrtlmst", + "52460": "clrmem", + "52461": "clrsci", + "52462": "rebuild", + "52463": "shuffle", + "52464": "dumpadc", + "52465": "haltsci", + "52466": "haltmem", + "52467": "clruk", + "52468": "ptseq", + "52469": "stuffseq", + "52470": "eraseseq", + "52480": "pwradc", + "52481": "cfgadctof", + "52482": "cfgadctar", + "52483": "cfgsciacq", + "52484": "cfgtrg", + "52485": "initadc", + "52486": "caladc", + "52487": "trainadcclk", + "52488": "sethvpwr", + "52490": "dshvosc", + "52491": "sethvsetpt", + "52492": "sethvmax", + "52493": "clratn", + "52494": "clrseq", + "52495": "readspi", + "52496": "fetchone", + "52506": "fetch", + "52507": "transmit", + "52508": "sendcatalog", + "52509": "suspidlesci", + "52510": "setalloc", + "52511": "addtofetch", + "52512": "cfgstim", + "52513": "enstim", + "52514": "haltstim", + "48059": "deploydoor", + "61166": "enahvosc" + }, + "tlmApIdLsbDictionary": { + "128": "EVTMSG", + "129": "ALIVE", + "130": "EVTLOG", + "131": "PMLOG", + "132": "CMDLOG", + "133": "HWPKT", + "134": "SWPKT", + "135": "DUMP", + "136": "DWELL" + }, + "qbootStateDictionary": { + "0": "NOATTEMPT", + "1": "UNINIT", + "2": "STARTED", + "6": "STOPPED", + "7": "WAITING", + "8": "PENDING" + }, + "qbootStateLCDictionary": { + "0": "noattempt", + "1": "uninit", + "2": "started", + "6": "stopped", + "7": "waiting", + "8": "pending" + }, + "qbootReason8Dictionary": { + "0": "NO_STOP", + "1": "FT_FAIL", + "2": "PERST_FAIL", + "3": "PT_FAIL", + "4": "NVFSW_FAIL", + "5": "SAFE_ENTRY", + "6": "PANICKING", + "7": "REBOOT_RST", + "8": "MEM_FAIL", + "9": "BYCMD", + "11": "NO_TIME", + "12": "WDOGCNT", + "13": "NONE" + }, + "blockState8Dictionary": { + "0": "UNKWN", + "16": "BAD", + "32": "EMPTY", + "48": "SCISTRT", + "49": "NVFSW1", + "50": "NVFSW2", + "51": "NVFSW3", + "52": "NVPT", + "53": "SCICONT", + "54": "NVPERST", + "55": "NVFT", + "56": "NVPMLOG", + "57": "NVSCIT", + "58": "SCIRSVD", + "59": "NVFETCHT", + "60": "NVSCS", + "61": "NVCATALOG", + "62": "SPAREE", + "63": "USER" + }, + "blockState32Dictionary": { + "0": "UNKWN", + "16": "BAD", + "32": "EMPTY", + "48": "SCISTRT", + "49": "NVFSW1", + "50": "NVFSW2", + "51": "NVFSW3", + "52": "NVPT", + "53": "SCICONT", + "54": "NVPERST", + "55": "NVFT", + "56": "NVPMLOG", + "57": "NVSCIT", + "58": "SCIRSVD", + "59": "NVFETCHT", + "60": "NVSCS", + "61": "NVCATALOG", + "62": "REG14", + "63": "USER" + }, + "hvOscillatorDictionary": { + "1": "DETECT", + "0": "SENSOR" + }, + "hvPolarityDictionary": { + "1": "NEG", + "0": "POS" + }, + "hvOutputDictionary": { + "0": "SENSOR", + "1": "RJCTN", + "2": "TARGET", + "3": "DETECT" + }, + "hvOutputOnlyDSDictionary": { + "0": "SENSOR", + "3": "DETECT" + }, + "hvOutputOnlyTRDictionary": { + "1": "RJCTN", + "2": "TARGET" + }, + "hvStateDictionary": { + "0": "OFF", + "1": "STANDBY", + "2": "RAMPUP", + "3": "ACTIVE", + "4": "RAMPDOWN" + }, + "hvMmrMismatchDictionary": { + "0": "POW_ENA", + "1": "SEN_ENA", + "2": "DET_ENA", + "3": "POL_ENA", + "4": "DET_SPT", + "5": "SEN_SPT", + "6": "TAR_SPT", + "7": "REF_SPT", + "8": "DET_MAX", + "9": "SEN_MAX", + "10": "TAR_MAX", + "11": "REF_MAX" + }, + "faultDictionary": { + "1": "ANAHKFLAG", + "4": "HVPSOSCERR", + "8": "HVPSCURR", + "16": "ANAHKLIMIT", + "64": "SPARE", + "128": "DECON0", + "256": "DECON1", + "512": "REPOINT", + "1023": "ALLFAULTS" + }, + "faultSeqDictionary": { + "0": "ABORTED_SEQ_FAULT", + "1": "HV_SEN_OSC_FAULT", + "2": "HV_DET_CUR_FAULT", + "3": "ANA_HK_FAULT", + "4": "COMM_LOSS_FAULT", + "5": "SPARE_FAULT", + "6": "DECON0_FAULT", + "7": "DECON1_FAULT", + "8": "REPOINT_FAULT", + "9": "FPGA_CLK_FAULT", + "10": "SHUTDOWN_RESET" + }, + "disEnaDictionary": { + "1": "DIS", + "0": "ENA" + }, + "enaDisDictionary": { + "1": "ENA", + "0": "DIS" + }, + "enaDis3Dictionary": { + "7": "ENA", + "0": "DIS" + }, + "enaDis8Dictionary": { + "1": "ENA", + "0": "DIS" + }, + "enaDis32Dictionary": { + "1": "ENA", + "0": "DIS" + }, + "busyIdleDictionary": { + "1": "BUSY", + "0": "IDLE" + }, + "onOffDictionary": { + "1": "ON", + "0": "OFF" + }, + "onOff32Dictionary": { + "1": "ON", + "0": "OFF" + }, + "errOkayDictionary": { + "1": "ERR", + "0": "OK" + }, + "okayErrDictionary": { + "1": "OK", + "0": "ERR" + }, + "yesNoDictionary": { + "1": "YES", + "0": "NO" + }, + "noYesDictionary": { + "1": "NO", + "0": "YES" + }, + "inOutDictionary": { + "1": "IN", + "0": "OUT" + }, + "openClosedDictionary": { + "1": "OPEN", + "0": "CLOSED" + }, + "closedOpenDictionary": { + "1": "CLOSED", + "0": "OPEN" + }, + "highLowDictionary": { + "1": "HI", + "0": "LO" + }, + "redPriDictionary": { + "1": "RED", + "0": "PRI" + }, + "deconHtrStateDictionary": { + "0": "DIS", + "1": "THERM0", + "2": "THERM1", + "3": "BOTH" + }, + "boardIdDictionary": { + "1": "EM", + "4": "EMULATOR", + "8": "FM", + "9": "SP" + }, + "nandOwnDictionary": { + "0": "FSW", + "1": "FPGA" + }, + "hvpsBoardPwrDictionary": { + "0": "DIS", + "1": "ERR", + "2": "ERR", + "3": "ERR", + "4": "ERR", + "5": "ERR", + "6": "ERR", + "7": "ENA" + }, + "modeTransDictionary": { + "0": "BOOT_TO_IDLE", + "1": "IDLE_TO_DECON", + "2": "IDLE_TO_SCIENCE", + "3": "IDLE_TO_TRANSMIT", + "4": "DECON_TO_IDLE", + "5": "SCIENCE_TO_IDLE", + "6": "TRANSMIT_TO_IDLE", + "7": "ANY_TO_SAFE", + "8": "SAFE_TO_IDLE" + } +} diff --git a/imap_processing/idex/idex_l0.py b/imap_processing/idex/idex_l0.py index c66a207755..6ffe119a84 100644 --- a/imap_processing/idex/idex_l0.py +++ b/imap_processing/idex/idex_l0.py @@ -6,8 +6,8 @@ from xarray import Dataset -from imap_processing import decom, imap_module_directory -from imap_processing.utils import packet_file_to_datasets +from imap_processing import imap_module_directory +from imap_processing.utils import packet_file_to_datasets, packet_generator logger = logging.getLogger(__name__) @@ -39,7 +39,7 @@ def decom_packets( science_xtce_file = f"{xtce_base_path}/idex_science_packet_definition.xml" hk_xtce_file = f"{xtce_base_path}/idex_housekeeping_packet_definition.xml" - science_decom_packet_list = decom.decom_packets(packet_file, science_xtce_file) + science_decom_packet_list = list(packet_generator(packet_file, science_xtce_file)) raw_datasets_by_apid = packet_file_to_datasets( packet_file, hk_xtce_file, use_derived_value=False ) diff --git a/imap_processing/idex/idex_l1a.py b/imap_processing/idex/idex_l1a.py index a15db110aa..2e68afc0be 100644 --- a/imap_processing/idex/idex_l1a.py +++ b/imap_processing/idex/idex_l1a.py @@ -14,6 +14,7 @@ l1a_data.write_l1a_cdf() """ +import json import logging from enum import IntEnum from pathlib import Path @@ -24,7 +25,9 @@ import xarray as xr from xarray import Dataset +from imap_processing import imap_module_directory from imap_processing.idex.decode import rice_decode +from imap_processing.idex.evt_msg_decode_utils import render_event_template from imap_processing.idex.idex_constants import IDEXAPID from imap_processing.idex.idex_l0 import decom_packets from imap_processing.idex.idex_utils import get_idex_attrs @@ -86,35 +89,142 @@ def __init__(self, packet_file: str | Path) -> None: if science_packets: logger.info("Processing IDEX L1A Science data.") self.data.append(self._create_science_dataset(science_packets)) - datasets_by_level = {"l1a": raw_datset_by_apid, "l1b": derived_datasets_by_apid} for level, dataset in datasets_by_level.items(): - if IDEXAPID.IDEX_EVT in dataset: - logger.info(f"Processing IDEX {level} Event Message data") + # Only produce l1a products for event messages. L1b will be processed in a + # another job. + if IDEXAPID.IDEX_EVT in dataset and level == "l1a": + logger.info("Processing IDEX L1A Event Message data") data = dataset[IDEXAPID.IDEX_EVT] - data.attrs = self.idex_attrs.get_global_attributes( - f"imap_idex_{level}_evt" - ) - data["epoch"] = calculate_idex_epoch_time( - data["shcoarse"], data["shfine"] - ) - data["epoch"].attrs = epoch_attrs - self.data.append(data) + processed_data = self._create_evt_msg_data(data) + processed_data["epoch"].attrs = epoch_attrs + self.data.append(processed_data) if IDEXAPID.IDEX_CATLST in dataset: - logger.info(f"Processing IDEX {level} Catalog List Summary data.") + logger.info(f"Processing IDEX {level} CATLST data") data = dataset[IDEXAPID.IDEX_CATLST] data.attrs = self.idex_attrs.get_global_attributes( f"imap_idex_{level}_catlst" ) - data["epoch"] = calculate_idex_epoch_time( - data["shcoarse"], data["shfine"] + data["epoch"] = calculate_idex_event_time( + data["shcoarse"].data, data["shfine"].data ) data["epoch"].attrs = epoch_attrs self.data.append(data) logger.info("IDEX L1A data processing completed.") + def _create_evt_msg_data(self, data: xr.Dataset) -> xr.Dataset: + """ + Process IDEX message data into a more usable format. + + Parameters + ---------- + data : xarray.Dataset + The raw message data to process. + + Returns + ------- + xarray.Dataset + The processed message data. + """ + # Convert the time to epoch time in nanoseconds since J2000 in the TT timescale + # elsec_evtpkt is the coarse time in seconds, elssec_evtpkt is the fine time in + # 20-microsecond intervals. We need to combine these to get the actual event + # time. + epoch = calculate_idex_event_time( + data["elsec_evtpkt"].data, data["elssec_evtpkt"].data + ) + # initialize dataset with time variables + l1a_msg_ds = xr.Dataset( + data_vars={ + "epoch": xr.DataArray(epoch, name="epoch", dims=["epoch"]), + "elsec_evtpkt": xr.DataArray( + data["elsec_evtpkt"].data, + dims=["epoch"], + attrs=self.idex_attrs.get_variable_attributes("elsec_evtpkt"), + ), + "elssec_evtpkt": xr.DataArray( + data["elssec_evtpkt"].data, + dims=["epoch"], + attrs=self.idex_attrs.get_variable_attributes("elssec_evtpkt"), + ), + }, + attrs=self.idex_attrs.get_global_attributes("imap_idex_l1a_msg"), + ) + # Load the event decoding dictionaries + with open( + f"{imap_module_directory}/idex/idex_evt_msg_parsing_dictionaries.json" + ) as f: + msg_dicts = json.load(f) + + # restore integer keys since JSON stringifies them + msg_json_data = { + dict_name: {int(k): v for k, v in pairs.items()} + for dict_name, pairs in msg_dicts.items() + } + # Get the event message templates and log entry name dictionaries + # These are used to decode the raw event messages into human-readable formats + # during rendering. + event_description_templates = msg_json_data.get("eventMsgDictionary", {}) + log_entry_names = msg_json_data.get("logEntryIdDictionary", {}) + + # Get the event id - this will tell us what event happened. + # The following parameter values will tell us additional details about the event + # For example the event may be a science state change and the parameters will + # tell us what state it changed to (e.g. on or off). + event_ids = data["elid_evtpkt"].data + # Stack the parameter bytes into a single array of shape (num_events, 4) for + # easier access during rendering. + params_bytes = np.stack( + [ + data["el1par_evtpkt"].data, + data["el2par_evtpkt"].data, + data["el3par_evtpkt"].data, + data["el4par_evtpkt"].data, + ], + axis=-1, + ) + + # initialize an empty list for messages + messages = [] + for idx in range(len(event_ids)): + # Look up the string format using the event_id. + event_id = event_ids[idx] + current_desc_template = event_description_templates.get(event_id) + current_param_bytes = params_bytes[idx].tolist() + event_name = log_entry_names.get(event_id, f"EVENT_0x{event_id:02X}") + # Render the event message using the template if available. + if current_desc_template: + try: + message = render_event_template( + current_desc_template, current_param_bytes, msg_json_data + ) + except Exception as exc: + message = ( + f"{event_name} [template_render_error={exc}] " + f"params=" + f"({', '.join(f'0x{x:02X}' for x in current_param_bytes)})" + ) + else: + # If no template exists for an event ID, fall back to a message + # that still preserves the event name and raw parameter bytes. + phex = ", ".join(f"0x{x:02X}" for x in current_param_bytes) + message = f"{event_name} ({phex})" + + messages.append(message) + + l1a_msg_ds["messages"] = xr.DataArray( + messages, + name="messages", + dims=["epoch"], + attrs=self.idex_attrs.get_variable_attributes( + "messages", check_schema=False + ), + ) + l1a_msg_ds.attrs = self.idex_attrs.get_global_attributes("imap_idex_l1a_msg") + return l1a_msg_ds + def _create_science_dataset(self, science_decom_packet_list: list) -> xr.Dataset: """ Process IDEX science packets into an xarray Dataset. @@ -248,25 +358,24 @@ def _read_waveform_bits(waveform_raw: str, high_sample: bool = True) -> list[int return ints -def calculate_idex_epoch_time( - shcoarse_time: float | np.ndarray, shfine_time: float | np.ndarray +def calculate_idex_event_time( + coarse_time_sec: np.ndarray, + fine_time_subs: np.ndarray, ) -> npt.NDArray[np.int64]: """ Calculate the epoch time from the FPGA header time variables. - We are given the MET seconds, we need to convert it to nanoseconds in j2000. IDEX - epoch is calculated with shcoarse and shfine time values. The shcoarse time counts - the number of whole seconds elapsed since the epoch (Jan 1st 2010), while shfine - time counts the number of additional 20-microsecond intervals beyond the whole - seconds. Together, these time measurements establish when a dust event took place. + Coarse_time_sec counts the number of whole seconds elapsed since the epoch + (Jan 1st 2010), while fine_time_subs counts the number of additional 20-microsecond + intervals beyond the whole seconds. Together, these time measurements establish + when a dust event took place. Parameters ---------- - shcoarse_time : float, numpy.ndarray - The coarse time value from the FPGA header. Number of seconds since epoch. - shfine_time : float, numpy.ndarray - The fine time value from the FPGA header. Number of 20 microsecond "ticks" since - the last second. + coarse_time_sec : numpy.ndarray + The coarse event time (seconds). + fine_time_subs : numpy.ndarray + The fine event time in 20-microsecond intervals. Returns ------- @@ -274,9 +383,9 @@ def calculate_idex_epoch_time( The mission elapsed time converted to nanoseconds since the J2000 epoch in the terrestrial time (TT) timescale. """ - # Get met time in seconds including shfine (number of 20 microsecond ticks) - met = shcoarse_time + shfine_time * 20e-6 - return met_to_ttj2000ns(met) + # Calculate the fine event time in seconds + fine_event_time = fine_time_subs * 20e-6 + return met_to_ttj2000ns(coarse_time_sec + fine_event_time) class RawDustEvent: @@ -288,7 +397,7 @@ class RawDustEvent: Parameters ---------- - header_packet : space_packet_parser.packets.CCSDSPacket + header_packet : space_packet_parser.SpacePacket The FPGA metadata event header. Attributes @@ -340,7 +449,7 @@ class RawDustEvent: MAX_HIGH_BLOCKS = 16 MAX_LOW_BLOCKS = 64 - def __init__(self, header_packet: space_packet_parser.packets.CCSDSPacket) -> None: + def __init__(self, header_packet: space_packet_parser.SpacePacket) -> None: """ Initialize a raw dust event, with an FPGA Header Packet from IDEX. @@ -352,14 +461,22 @@ def __init__(self, header_packet: space_packet_parser.packets.CCSDSPacket) -> No Parameters ---------- - header_packet : space_packet_parser.packets.CCSDSPacket + header_packet : space_packet_parser.SpacePacket The FPGA metadata event header. """ # Calculate the impact time in seconds since epoch self.impact_time = 0 - self.impact_time = calculate_idex_epoch_time( - header_packet["SHCOARSE"], header_packet["SHFINE"] + # The elapsed seconds are stored as a 32-bit unsigned integer that is split + # across two 16-bit words for packetization. As a result, idx__txhdrtimesec1 + # represents multiples of 2^16 seconds, while idx_txhdrtimesec2 represents the + # remaining seconds within that range. This necessitates bit shifting the upper + # word by 16 bits when reconstructing the full seconds counter. + self.impact_time = calculate_idex_event_time( + (header_packet["IDX__TXHDRTIMESEC1"] << 16) + + header_packet["IDX__TXHDRTIMESEC2"], + header_packet["IDX__TXHDRTIMESUBS"], ) + self.event_number = header_packet["IDX__SCI0EVTNUM"] # The actual trigger time for the low and high sample rate in @@ -371,8 +488,8 @@ def __init__(self, header_packet: space_packet_parser.packets.CCSDSPacket) -> No # Iterate through every telemetry item not in the header and pull out the values self.telemetry_items = { key.lower(): val - for key, val in header_packet.items() - if key not in header_packet.header.keys() + for i, (key, val) in enumerate(header_packet.items()) + if i > 6 # Skip first 7 header items } logger.debug( @@ -420,7 +537,7 @@ def _append_raw_data(self, scitype: Scitype, bits: str) -> None: logger.warning("Unknown science type received: [%s]", scitype) def _set_sample_trigger_times( - self, packet: space_packet_parser.packets.CCSDSPacket + self, packet: space_packet_parser.SpacePacket ) -> None: """ Calculate the actual sample trigger time. @@ -430,7 +547,7 @@ def _set_sample_trigger_times( Parameters ---------- - packet : space_packet_parser.packets.CCSDSPacket + packet : space_packet_parser.SpacePacket The IDEX FPGA header packet info. Notes @@ -451,14 +568,36 @@ def _set_sample_trigger_times( """ # Retrieve the number of samples for high gain delay - # packet['IDX__TXHDRSAMPDELAY'] is a 32-bit value, with the last 10 bits - # representing the high gain sample delay and the first 2 bits used for padding. - # To extract the high gain bits, the bitwise right shift (>> 20) moves the bits - # 20 positions to the right, and the mask (0b1111111111) keeps only the least - # significant 10 bits. - # TODO use the delay corresponding to the trigger - high_gain_delay = (packet["IDX__TXHDRSAMPDELAY"] >> 22) & 0b1111111111 + # packet['IDX__TXHDRSAMPDELAY'] is a 32-bit value: + # bits0-9: high-gain delay, + # bits10-19: mid-gain delay, + # bits20-29: low-gain delay. + # bits30-31 are padding/reserved. + # Each delay is extracted by right-shifting to align the field, + # then masking with #0b1111111111 (10 bits). + n_blocks = packet["IDX__TXHDRBLOCKS"] + trigger_item = packet["IDX__TXHDRTRIGID"] + + tof_delay = packet["IDX__TXHDRSAMPDELAY"] # last two bits are padding + + # mask to extract 10-bit values + tof_mask = 0b1111111111 + + # Determine the delay based on the trigger id. + hg_delay = tof_delay & tof_mask # first 10 bits (0-9) + mg_delay = (tof_delay >> 10) & tof_mask # next 10 bits (10-19) + lg_delay = (tof_delay >> 20) & tof_mask # next 10 bits (20-29) + + u10 = trigger_item & 0x3FF + if (u10 >> 0) & 1: + delay = hg_delay + elif (u10 >> 1) & 1: + delay = lg_delay + elif (u10 >> 2) & 1: + delay = mg_delay + else: + delay = hg_delay # Retrieve number of low/high sample pre-trigger blocks @@ -478,11 +617,10 @@ def _set_sample_trigger_times( * (num_low_sample_pretrigger_blocks + 1) * self.NUMBER_SAMPLES_PER_LOW_SAMPLE_BLOCK ) - self.high_sample_trigger_time = ( - self.HIGH_SAMPLE_RATE - * (num_high_sample_pretrigger_blocks + 1) - * self.NUMBER_SAMPLES_PER_HIGH_SAMPLE_BLOCK - - self.HIGH_SAMPLE_RATE * high_gain_delay + self.high_sample_trigger_time = self.HIGH_SAMPLE_RATE * ( + num_high_sample_pretrigger_blocks + 1 + ) * self.NUMBER_SAMPLES_PER_HIGH_SAMPLE_BLOCK - self.HIGH_SAMPLE_RATE * ( + delay - 1 ) def _parse_high_sample_waveform(self, waveform_raw: str) -> list[int]: @@ -556,7 +694,7 @@ def _calc_low_sample_resolution(self, num_samples: int) -> npt.NDArray: time_low_sample_rate_data : numpy.ndarray Low time sample data array. """ - time_low_sample_rate_init = np.linspace(0, num_samples, num_samples) + time_low_sample_rate_init: np.ndarray = np.arange(num_samples, dtype=np.float64) time_low_sample_rate_data = ( self.LOW_SAMPLE_RATE * time_low_sample_rate_init - self.low_sample_trigger_time @@ -583,22 +721,22 @@ def _calc_high_sample_resolution(self, num_samples: int) -> npt.NDArray: time_high_sample_rate_data : numpy.ndarray High sample time data array. """ - time_high_sample_rate_init = np.linspace(0, num_samples, num_samples) + time_high_sample_rate_init: np.ndarray = np.arange( + num_samples, dtype=np.float64 + ) time_high_sample_rate_data = ( self.HIGH_SAMPLE_RATE * time_high_sample_rate_init - self.high_sample_trigger_time ) return time_high_sample_rate_data - def _populate_bit_strings( - self, packet: space_packet_parser.packets.CCSDSPacket - ) -> None: + def _populate_bit_strings(self, packet: space_packet_parser.SpacePacket) -> None: """ Parse IDEX data packets to populate bit strings. Parameters ---------- - packet : space_packet_parser.packets.CCSDSPacket + packet : space_packet_parser.SpacePacket A single science data packet for one of the 6. IDEX observables. """ @@ -625,8 +763,15 @@ def process(self) -> Dataset | None: # Gather the huge amount of metadata info trigger_vars = {} for var, value in self.telemetry_items.items(): - trigger_vars[var] = xr.DataArray( - name=var, + # SCI0AID is not updated properly. To this end, TXHDRFSWAIDCOPY must be + # used as the proper AID. + if var == "idx__sci0aid": + continue + # rename idx__txhdrfswaidcopy to aid for better readability in the final + # dataset + var_name = "aid" if var == "idx__txhdrfswaidcopy" else var + trigger_vars[var_name] = xr.DataArray( + name=var_name, data=[value], dims=("epoch"), attrs=idex_attrs.get_variable_attributes(var), diff --git a/imap_processing/idex/idex_l1b.py b/imap_processing/idex/idex_l1b.py index a11cfb9ecb..2b767dd675 100644 --- a/imap_processing/idex/idex_l1b.py +++ b/imap_processing/idex/idex_l1b.py @@ -15,14 +15,18 @@ """ import logging -from enum import Enum +from enum import Enum, IntEnum +import numpy as np import pandas as pd import xarray as xr +from numpy.typing import NDArray +from xarray import DataArray from imap_processing import imap_module_directory from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes from imap_processing.idex.idex_constants import ( + DT_BLOCK, IDEX_EVENT_REFERENCE_FRAME, ConversionFactors, ) @@ -42,6 +46,40 @@ logger = logging.getLogger(__name__) +class EventMessage(Enum): + """Enum class for event messages.""" + + PULSER_ON = "SEQ success (len=0x0580, opCodeLCDictionary(enstim))" + PULSER_OFF = "UPK stim pulser operation completed, , PulserSel=0x00000007" + SCIENCE_ON = ( + "SCI state change: sciState16Dictionary(ACQSETUP) ==> sciState16Dictionary(ACQ)" + ) + SCIENCE_OFF = ( + "SCI state change: sciState16Dictionary(ACQ) ==> sciState16Dictionary(CHILL)" + ) + + +class TriggerOrigin(IntEnum): + """Enum class for event trigger origins.""" + + HS_ADC0I_TOF_HG = 0 + HS_ADC0Q_TOF_LG = 1 + HS_ADC1Q_TOF_MG = 2 + LS_ADC1_TARGET_HG = 3 + SW_TRIGGER = 4 + EXTERNAL_TRIGGER = 5 + + +TRIGGER_LABELS = { + TriggerOrigin.HS_ADC0I_TOF_HG: "HS ADC0I trigger (TOF HG)", + TriggerOrigin.HS_ADC0Q_TOF_LG: "HS ADC0Q trigger (TOF LG)", + TriggerOrigin.HS_ADC1Q_TOF_MG: "HS ADC1Q trigger (TOF MG)", + TriggerOrigin.LS_ADC1_TARGET_HG: "LS ADC1 trigger (Target HG / low range)", + TriggerOrigin.SW_TRIGGER: "SW trigger", + TriggerOrigin.EXTERNAL_TRIGGER: "external trigger", +} + + class TriggerMode(Enum): """ Enum class for data collection trigger Modes. @@ -80,9 +118,106 @@ def get_mode_label(mode: int, channel: str) -> str: return f"{channel.upper()}{TriggerMode(mode).name}" -def idex_l1b(l1a_dataset: xr.Dataset) -> xr.Dataset: +def idex_l1b(l1a_dataset: xr.Dataset, descriptor: str) -> xr.Dataset | None: + """ + Process IDEX l1a data to create l1b data products based on the descriptor. + + Parameters + ---------- + l1a_dataset : xarray.Dataset + IDEX L1a dataset to process. + descriptor : str + Descriptor to determine the type of l1b processing to perform. E.g. "sci-1week" + or "msg". + + Returns + ------- + l1b_dataset : xarray.Dataset + The``xarray`` dataset containing the processed data and supporting metadata. + """ + if descriptor.startswith("sci"): + return idex_l1b_science(l1a_dataset) + elif descriptor.startswith("msg"): + return idex_l1b_msg(l1a_dataset) + else: + raise ValueError(f"Unsupported descriptor: {descriptor}") + + +def idex_l1b_msg(l1a_dataset: xr.Dataset) -> xr.Dataset | None: + """ + Will process IDEX l1a msg data. + + Parameters + ---------- + l1a_dataset : xarray.Dataset + IDEX L1a dataset to process. + + Returns + ------- + l1b_dataset : xarray.Dataset + The``xarray`` dataset containing the msg housekeeping data and + supporting metadata. """ - Will process IDEX l1a data to create l1b data products. + logger.info( + f"Running IDEX L1B MSG processing on dataset: " + f"{l1a_dataset.attrs['Logical_source']}" + ) + # create the attribute manager for this data level + idex_attrs = get_idex_attrs("l1b") + # set up a dataset with only epoch. + l1b_dataset = setup_dataset(l1a_dataset, [], idex_attrs, data_vars=None) + l1b_dataset.attrs = idex_attrs.get_global_attributes("imap_idex_l1b_msg") + # Compute science_on and pulser_on variables based on the event message. The + # "science_on" variable indicates when the science data collection is turned on or + # off and the "pulser_on" variable indicates when the pulser is turned on or off. + # The following logic is applied to determine the pulser_on status. + # enstim β†’ set pulser_on = 1 + # susprel AND the previous message was enstim β†’ set pulser_on = 0 + # susprel but previous message was NOT enstim β†’ pulser_on stays whatever it was + l1a_messages = l1a_dataset.messages.values + # Set science_on to 1 when science is on and 0 when it is off. 255 otherwise. + science_on = np.where(l1a_messages == EventMessage.SCIENCE_ON.value, 1, 255) + science_on[l1a_messages == EventMessage.SCIENCE_OFF.value] = 0 + # Find indices where there are consecutive PULSER_ON followed by PULSER_OFF + # messages. These are the only cases where we should set pulser_on to 1 and 0. + # Compare the messages by shifting the pulser off messages back by one and looking + # for matching overlaps. + consecutive_pulser_on_off = np.where( + (l1a_messages[:-1] == EventMessage.PULSER_ON.value) + & (l1a_messages[1:] == EventMessage.PULSER_OFF.value) + )[0] + pulser_on = np.full(len(l1a_messages), 255) # initialize with 255 (unknown) + pulser_on[consecutive_pulser_on_off] = 1 + pulser_on[consecutive_pulser_on_off + 1] = 0 + l1b_dataset["pulser_on"] = xr.DataArray( + data=pulser_on, + dims="epoch", + name="pulser_on", + attrs=idex_attrs.get_variable_attributes("pulser_on"), + ) + l1b_dataset["science_on"] = xr.DataArray( + data=science_on, + dims="epoch", + name="science_on", + attrs=idex_attrs.get_variable_attributes("science_on"), + ) + + # Filter dataset to only include rows where there is an event + # (either science or pulser) + null_event = (pulser_on == 255) & (science_on == 255) + l1b_dataset = l1b_dataset.isel(epoch=~null_event) + if len(l1b_dataset["epoch"]) == 0: + logger.warning( + "No science or pulser events found. No l1b dataset will be created." + ) + return None + logger.info("IDEX L1B MSG data processing completed.") + return l1b_dataset + + +def idex_l1b_science(l1a_dataset: xr.Dataset) -> xr.Dataset: + """ + Will process IDEX l1a science data. Parameters ---------- @@ -111,27 +246,30 @@ def idex_l1b(l1a_dataset: xr.Dataset) -> xr.Dataset: l1a_dataset, var_information_df, idex_attrs ) + dead_time = get_event_dead_time(l1a_dataset, idex_attrs) + waveforms_converted = convert_waveforms(l1a_dataset, idex_attrs) # Get spice data and save them as xr.DataArrays in the output. Spice data is not # used for calculations yet but are saved in the CDF for reference. spice_data = get_spice_data(l1a_dataset, idex_attrs) - trigger_settings = get_trigger_mode_and_level(l1a_dataset) - if trigger_settings: - trigger_settings["triggerlevel"].attrs = idex_attrs.get_variable_attributes( - "trigger_level" - ) - trigger_settings["triggermode"].attrs = idex_attrs.get_variable_attributes( - "trigger_mode" - ) - + trigger_settings = get_trigger_mode_and_level(l1a_dataset, idex_attrs) + trigger_origin = get_trigger_origin( + l1a_dataset["idx__txhdrtrigid"].data, idex_attrs + ) # Create l1b Dataset - prefixes = ["shcoarse", "shfine", "time_high_sample", "time_low_sample"] - data_vars = processed_vars | waveforms_converted | trigger_settings | spice_data + prefixes = ["shcoarse", "shfine", "time_high_sample", "time_low_sample", "aid"] + data_vars = ( + processed_vars + | dead_time + | waveforms_converted + | trigger_settings + | spice_data + | trigger_origin + ) l1b_dataset = setup_dataset(l1a_dataset, prefixes, idex_attrs, data_vars) l1b_dataset.attrs = idex_attrs.get_global_attributes("imap_idex_l1b_sci") - # Convert variables l1b_dataset = convert_raw_to_eu( l1b_dataset, @@ -225,6 +363,7 @@ def convert_waveforms( def get_trigger_mode_and_level( l1a_dataset: xr.Dataset, + idex_attrs: ImapCdfAttributes, ) -> dict[str, xr.DataArray] | dict: """ Determine the trigger mode and threshold level for each event. @@ -233,6 +372,8 @@ def get_trigger_mode_and_level( ---------- l1a_dataset : xarray.Dataset IDEX L1a dataset containing the six waveform arrays and instrument settings. + idex_attrs : ImapCdfAttributes + CDF attribute manager object. Returns ------- @@ -243,8 +384,8 @@ def get_trigger_mode_and_level( channels = ["lg", "mg", "hg"] # 10 bit mask mask = 0b1111111111 - trigger_modes = [] - trigger_levels = [] + # Initialize a dict to hold the mode labels and threshold levels for each channel + data_dict = {} def compute_trigger_values( trigger_mode: int, trigger_controls: int, gain_channel: str @@ -302,28 +443,114 @@ def compute_trigger_values( vectorize=True, output_dtypes=[object, float], ) - trigger_modes.append(mode_array.rename("trigger_mode")) - trigger_levels.append(level_array.rename("trigger_level")) - - try: # There should be an array of modes and threshold levels for each channel. - # At each index (event) only one of the three arrays should have a value that is - # not 'None' because each event can only be triggered by one channel. - # By merging the three arrays, we get value for each event. - merged_modes = xr.merge([trigger_modes[0], xr.merge(trigger_modes[1:])]) - merged_levels = xr.merge([trigger_levels[0], xr.merge(trigger_levels[1:])]) - - return { - "triggermode": merged_modes.trigger_mode, - "triggerlevel": merged_levels.trigger_level, - } - - except xr.MergeError as e: - raise ValueError( - f"Only one channel can trigger a dust event. Please make sure " - f"there is only one valid trigger value per event. This " - f"caused Merge Error: {e}" - ) from e + # write each of them out as separate variables because there may be + # multiple channels that can trigger an event. The trigger origin variable + # can be used to determine which channel(s) triggered the event. + mode_array.attrs = idex_attrs.get_variable_attributes(f"trigger_mode_{channel}") + data_dict[f"trigger_mode_{channel}"] = mode_array + level_array.attrs = idex_attrs.get_variable_attributes( + f"trigger_level_{channel}" + ) + data_dict[f"trigger_level_{channel}"] = level_array + + return data_dict + + +def get_trigger_origin( + trigger_id: NDArray, idex_attrs: ImapCdfAttributes +) -> dict[str, DataArray]: + """ + Determine the trigger origin for each event. + + Parameters + ---------- + trigger_id : numpy.ndarray + Array of raw trigger ID values from the l1a dataset. The trigger ID is a 32-bit + integer where the lower 10 bits contain information about the trigger origin. + idex_attrs : ImapCdfAttributes + CDF attribute manager object. + + Returns + ------- + dict[str, xarray.DataArray] + A dictionary containing the trigger_origin DataArray with the trigger + origin info for each event. + """ + # extract the lower 10 bits of the trigger ID to get the trigger origin information + trigger_bits = trigger_id & 0x3FF + # For each event, determine which bits are set and get the corresponding trigger + # origin labels + origin_labels = np.array( + [ + ", ".join( + [TRIGGER_LABELS[TriggerOrigin(i)] for i in range(6) if (bits >> i) & 1] + ) + for bits in trigger_bits + ], + dtype=object, + ) + # Update any events with no trigger bits set to "unknown trigger origin" + origin_labels[origin_labels == ""] = "Unknown trigger origin" + return { + "trigger_origin": xr.DataArray( + name="trigger_origin", + data=np.squeeze(origin_labels), + dims="epoch", + attrs=idex_attrs.get_variable_attributes("trigger_origin"), + ) + } + + +def get_event_dead_time( + l1a_dataset: xr.Dataset, + idex_attrs: ImapCdfAttributes, +) -> dict[str, xr.DataArray]: + """ + Compute event dead time (in seconds) from packed txhdrblocks. + + The dead time is encoded via two bitfields: + - dead_blocks_base (6 bits) + - dead_blocks_shift (4 bits) + + Dead time is computed as: + dead_time = dead_blocks_base * 2**dead_blocks_shift * DT_BLOCK + + where DT_BLOCK is the duration of a single low-rate block. + + Parameters + ---------- + l1a_dataset : xarray.Dataset + IDEX L1A dataset containing the packed `idx__txhdrblocks` variable. + idex_attrs : ImapCdfAttributes + CDF attribute manager object. + + Returns + ------- + dict[str, xarray.DataArray] + Dictionary containing the `dead_time` DataArray (seconds). + """ + txhdrblocks = l1a_dataset["idx__txhdrblocks"].data + + # Extract bitfields + dead_blocks_shift = (txhdrblocks >> 20) & 0b1111 + dead_blocks_base = (txhdrblocks >> 24) & 0b111111 + + # Convert to float once + base = dead_blocks_base.astype(np.float64) + shift = dead_blocks_shift.astype(np.float64) + + # Compute dead time + dead_time_array: NDArray[np.float64] = base * np.power(2.0, shift) * DT_BLOCK + + return { + "dead_time": xr.DataArray( + name="dead_time", + data=dead_time_array, + dims="epoch", + attrs=idex_attrs.get_variable_attributes("dead_time"), + ) + } def get_spice_data( diff --git a/imap_processing/idex/idex_l2a.py b/imap_processing/idex/idex_l2a.py index 97e933a39e..3c564a343a 100644 --- a/imap_processing/idex/idex_l2a.py +++ b/imap_processing/idex/idex_l2a.py @@ -70,10 +70,10 @@ def load_calibration_files(ancillary_files: dict) -> tuple[NDArray, NDArray]: """ # Load calibration coefficients from ancillary files t_rise_params = pd.read_csv( - ancillary_files["l2a-calibration-curve-yield-params"], skiprows=1, header=None + ancillary_files["l2a-calibration-curve-t-rise"], skiprows=1, header=None ).values.flatten()[:8] yield_params = pd.read_csv( - ancillary_files["l2a-calibration-curve-t-rise"], skiprows=1, header=None + ancillary_files["l2a-calibration-curve-yield-params"], skiprows=1, header=None ).values.flatten()[:8] return t_rise_params, yield_params @@ -118,7 +118,7 @@ def idex_l2a(l1b_dataset: xr.Dataset, ancillary_files: dict) -> xr.Dataset: atomic_masses_path = f"{imap_module_directory}/idex/atomic_masses.csv" atomic_masses = pd.read_csv(atomic_masses_path) masses = atomic_masses["Mass"] - stretches, shifts, mass_scales = time_to_mass(tof_high.data, hs_time.data, masses) + _stretches, _shifts, mass_scales = time_to_mass(tof_high.data, hs_time.data, masses) # TODO use correct fillval mass_scales_da = xr.DataArray( @@ -205,6 +205,7 @@ def idex_l2a(l1b_dataset: xr.Dataset, ancillary_files: dict) -> xr.Dataset: vectorize=True, output_dtypes=[np.float64] * 6, keep_attrs=True, + kwargs={"waveform_name": waveform}, ) # Calculate mass and velocity estimates velocity_mass_results = xr.apply_ufunc( @@ -299,6 +300,48 @@ def idex_l2a(l1b_dataset: xr.Dataset, ancillary_files: dict) -> xr.Dataset: "target_fit_parameter_labels", check_schema=False ), ) + + # We're inserting a NaN block here for the 2026 June release while the + # IDEX science team works through validating the fitting routines and + # derived values. + + # Ion Grid Fitting: + l2a_dataset["ion_grid_dust_mass_estimate"].data = np.full( + l2a_dataset["ion_grid_dust_mass_estimate"].shape, np.nan + ) + + l2a_dataset["ion_grid_velocity_estimate"].data = np.full( + l2a_dataset["ion_grid_velocity_estimate"].shape, np.nan + ) + + # TOF / Mass-spec Fitting + l2a_dataset["tof_peak_area_under_fit"].data = np.full( + l2a_dataset["tof_peak_area_under_fit"].shape, np.nan + ) + + l2a_dataset["tof_peak_chi_square"].data = np.full( + l2a_dataset["tof_peak_chi_square"].shape, np.nan + ) + + l2a_dataset["tof_peak_fit_parameters"].data = np.full( + l2a_dataset["tof_peak_fit_parameters"].shape, np.nan + ) + + l2a_dataset["tof_peak_kappa"].data = np.full( + l2a_dataset["tof_peak_kappa"].shape, np.nan + ) + + l2a_dataset["tof_peak_reduced_chi_square"].data = np.full( + l2a_dataset["tof_peak_reduced_chi_square"].shape, np.nan + ) + + l2a_dataset["tof_snr"].data = np.full(l2a_dataset["tof_snr"].shape, np.nan) + + l2a_dataset["mass"].data = np.full(l2a_dataset["mass"].shape, np.nan) + + l2a_dataset["mass_scale"].data = np.full(l2a_dataset["mass_scale"].shape, np.nan) + # End NaN block + logger.info("IDEX L2A science data processing completed.") l2a_dataset.attrs.update(idex_attrs.get_global_attributes("imap_idex_l2a_sci")) return l2a_dataset @@ -318,11 +361,11 @@ def calculate_velocity_and_mass( Parameters ---------- sig_amp : float - Signal amplitude. + Signal amplitude (pC). t_rise : float - T_rise fit parameter from the target fit. + T_rise fit parameter from the target fit (us). t_rise_params : np.ndarray - Calibration parameters for rise time. + Calibration parameters for rise time (us). yield_params : np.ndarray Calibration parameters for yield. @@ -333,57 +376,104 @@ def calculate_velocity_and_mass( mass_est : float Estimated mass. """ - log_a_t: float = np.log10(t_rise_params[0]) + v_est = invert_rise_time_to_velocity(t_rise, t_rise_params) + if not np.isfinite(v_est): + return np.nan, np.nan + + log_a_y: float = float(yield_params[0]) + yield_val = 10 ** log_smooth_powerlaw(np.log10(v_est), log_a_y, yield_params[1:]) + sig_amp_coulombs = sig_amp * idex_constants.PICOCOULOMB_TO_COULOMB + mass_est = sig_amp_coulombs / yield_val + + return v_est, mass_est + + +def invert_rise_time_to_velocity(t_rise: float, t_rise_params: np.ndarray) -> float: + """ + Invert the rise-time calibration to estimate impact velocity. + + The rise-time calibration is defined in the forward direction as + rise_time = f(velocity). This helper numerically inverts that relation to recover + velocity from a fitted rise time. + + Parameters + ---------- + t_rise : float + Fitted target rise time in microseconds. + t_rise_params : np.ndarray + Calibration parameters for the forward rise-time curve + [A, a1, a2, a3, vb, vc, k, m]. + + Returns + ------- + float + Estimated impact velocity in km/s, or NaN if the inversion fails. + """ + if not np.isfinite(t_rise) or t_rise <= 0.0: + logger.error( + "Unable to calculate velocity estimate from rise time %.6g. " + "Rise time must be finite and positive. Returning nan.", + t_rise, + ) + return np.nan + + log_a_t: float = float(t_rise_params[0]) + target_log_t_rise = np.log10(t_rise) try: root = root_scalar( - lambda lv: log_smooth_powerlaw(lv, log_a_t, t_rise_params[1:]) - - np.log10(t_rise), + lambda log_v: ( + log_smooth_powerlaw(log_v, log_a_t, t_rise_params[1:]) + - target_log_t_rise + ), bracket=[-1, 2], + method="brentq", ) - v_est = 10**root.root + return 10**root.root except Exception: logger.error( - "Unable to calculate velocity and mass estimate. " - "The root finding failed for power law function. " - "Returning nans for the estimate." + "Unable to calculate velocity estimate from rise time %.6g. " + "The rise-time calibration inversion failed. Returning nan.", + t_rise, ) - return np.nan, np.nan - - log_a_y: float = np.log10(yield_params[0]) - yield_val = 10 ** log_smooth_powerlaw(np.log10(v_est), log_a_y, yield_params[1:]) - mass_est = sig_amp / yield_val - - return v_est, mass_est + return np.nan def log_smooth_powerlaw(log_v: float, log_a: float, params: np.ndarray) -> float: """ - Define a smoothly transitioning power law to fit the calibration curve to. + Define a smoothly transitioning power law used by the IDEX calibration curves. + + This helper is used in two ways: + - rise-time calibration: log10(velocity [km/s]) to log10(rise_time [us]) + - yield calibration: log10(velocity [km/s]) to log10(charge_yield [C/kg]) Parameters ---------- log_v : float - Velocity. + The log10 input to the calibration curve. + This is log10(velocity [km/s]) for both the rise-time and yield cases. log_a : float - Scale factor. + Log10 of the calibration scale factor A. params : np.ndarray - Calibration parameters for the power law. + Calibration parameters for the power law + [a1, a2, a3, vb, vc, k, m]. Returns ------- float - The value of the power law at the given velocity. + The calibrated log10 output. + This is either log10(rise_time [us]) for the rise-time case or + log10(charge_yield [C/kg]) for the yield case. """ # Unpack the rest of the calibration parameters # a1, a2, and a3 are the power law exponents for the low, medium, and high-velocity # segments. # vb and vc are the characteristic speeds where the slope transition happens, and k # setting the sharpness of the transitions. - a1, a2, a3, vb, vc, k, m = params + a1, a2, a3, vb, vc, k, _m = params v = 10**log_v base = log_a + a1 * log_v - transition1 = (1 + (v / vb) ** m) ** ((a2 - a1) / m) - transition2 = (1 + (v / vc) ** m) ** ((a3 - a2) / m) + transition1 = (1 + (v / vb) ** k) ** ((a2 - a1) / k) + transition2 = (1 + (v / vc) ** k) ** ((a3 - a2) / k) return base + np.log10(transition1 * transition2) @@ -748,7 +838,8 @@ def calculate_area_under_emg(time_slice: np.ndarray, param: np.ndarray) -> float def estimate_dust_mass( low_sampling_time: xr.DataArray, target_signal: xr.DataArray, - remove_noise: bool = True, + remove_noise: bool = False, + waveform_name: str = "", ) -> tuple[NDArray, float, float, float, NDArray]: """ Filter and fit the target or ion grid signals to get the total dust impact charge. @@ -756,12 +847,14 @@ def estimate_dust_mass( Parameters ---------- low_sampling_time : xarray.DataArray - The low sampling time array. + The low sampling time array in microseconds. target_signal : xarray.DataArray Target signal data. remove_noise : bool If true, attempt to remove background noise, otherwise fit on the unfiltered signal. + waveform_name : str + Channel name used to select channel-specific fit bounds. Returns ------- @@ -781,34 +874,62 @@ def estimate_dust_mass( """ signal = np.array(target_signal.data) time = np.array(low_sampling_time.data) - good_mask = np.logical_and( - time >= BaselineNoiseTime.START, - time <= BaselineNoiseTime.STOP, - ) + # window_start = float(np.min(time)) + window_stop = float(np.min(time)) + 5.0 + # good_mask = np.logical_and(time >= window_start, time <= window_stop) + good_mask = time <= window_stop if not np.any(good_mask): logger.warning( "Unable to find baseline noise. " - f"There is no signal from {BaselineNoiseTime.START} to " - f"{BaselineNoiseTime.STOP} ns." + f"There is no signal in the first 5 microseconds of the waveform " + f"(Beginning to {window_stop} us)." ) if remove_noise: - # Remove noise due to "microphonics" - signal = remove_signal_noise(time, signal, good_mask) - # Time before image charge - pre = -2.0 - # Get signal values where the time is before the image charge - signal_before_imapact = signal[time < pre] - # Center the baseline signal around zero - signal_baseline = signal_before_imapact - np.mean(signal_before_imapact) + logger.debug( + "estimate_dust_mass fits the raw low-rate waveform directly; " + "remove_noise is ignored for this fit path." + ) + signal_before_impact = signal[good_mask] + baseline_mean = float(np.mean(signal_before_impact)) + channel_name = waveform_name or str(getattr(target_signal, "name", "")) # Initial Guess for the parameters of the ion grid signal time_of_impact = 0.0 # Time of dust hit - constant_offset = 0.0 # Initial baseline - amplitude: float = np.max(signal) # Signal height - rise_time = 0.371 # How fast the signal rises (s) - discharge_time = 0.371 # How fast signal decays (s) - - p0 = [time_of_impact, constant_offset, amplitude, rise_time, discharge_time] + constant_offset = baseline_mean + signal_relative_to_baseline = np.asarray(signal - baseline_mean, dtype=float) + if np.any(np.isfinite(signal_relative_to_baseline)): + amplitude = float( + signal_relative_to_baseline[ + np.nanargmax(np.abs(signal_relative_to_baseline)) + ] + ) + else: + amplitude = float("nan") + if channel_name != "Ion_Grid" and (not np.isfinite(amplitude) or amplitude <= 0.0): + amplitude = float(np.max(signal) - baseline_mean) + if not np.isfinite(amplitude): + amplitude = float(np.max(signal)) + if channel_name != "Ion_Grid" and amplitude <= 0.0: + amplitude = float(np.max(signal)) + + rise_time_0 = 0.371 # How fast the signal rises (us) + discharge_time_0 = 37.1 # How fast signal decays (us) + + p0 = [time_of_impact, constant_offset, amplitude, rise_time_0, discharge_time_0] + positive_min = float(np.finfo(float).eps) + amplitude_lower_bound: float = positive_min + amplitude_upper_bound: float = float(np.inf) + if channel_name == "Ion_Grid": + if np.isfinite(amplitude) and amplitude < 0.0: + amplitude_lower_bound = float(-np.inf) + amplitude_upper_bound = -positive_min + else: + amplitude_lower_bound = positive_min + amplitude_upper_bound = float(np.inf) + bounds = ( + [-np.inf, -np.inf, amplitude_lower_bound, positive_min, positive_min], + [np.inf, np.inf, amplitude_upper_bound, np.inf, np.inf], + ) try: with np.errstate(invalid="ignore", over="ignore"): @@ -817,6 +938,7 @@ def estimate_dust_mass( time, signal, p0=p0, + bounds=bounds, maxfev=100_000, # , epsfcn=1e-10 ) except RuntimeError as e: @@ -835,8 +957,11 @@ def estimate_dust_mass( ) impact_fit = fit_impact(time, *param) - # Calculate the resulting signal amplitude after removing baseline noise - sig_amp = max(impact_fit) - np.mean(signal_baseline) + # Evaluate the analytic extremum of the fitted pulse instead of relying on the + # discrete sample grid. + t_max = param[0] + param[3] * np.log((param[4] / param[3]) + 1.0) + y_max = float(fit_impact(np.asarray([t_max], dtype=float), *param)[0]) + sig_amp = abs(float(y_max - param[1])) chisqr, redchi = chi_square(signal, impact_fit, len(p0)) return param, float(sig_amp), chisqr, redchi, impact_fit @@ -856,13 +981,13 @@ def fit_impact( Parameters ---------- time : np.ndarray - Time values for the signal. + Time values for the signal (us). time_of_impact : float - Time of dust impact. + Time of dust impact (us). constant_offset : float Initial baseline noise. amplitude : float - Signal height. + Signal height (pC). rise_time : float How fast the signal rises (s). discharge_time : float diff --git a/imap_processing/idex/idex_l2b.py b/imap_processing/idex/idex_l2b.py index 2e209d5dfc..d16aff0660 100644 --- a/imap_processing/idex/idex_l2b.py +++ b/imap_processing/idex/idex_l2b.py @@ -12,12 +12,13 @@ l0_file = "imap_processing/tests/idex/imap_idex_l0_raw_20231218_v001.pkts" l0_file_hk = "imap_processing/tests/idex/imap_idex_l0_raw_20250108_v001.pkts" - l1a_data = PacketParser(l0_file).data[0] - evt_data = PacketParser(l0_file_hk).data[0] - l1a_data, l1a_evt_data, l1b_evt_data = PacketParser(l0_file) - l1b_data = idex_l1b(l1a_data) + l1a_data, _ = PacketParser(l0_file) + _, l1a_msg_data = PacketParser(l0_file_hk) + msg_data_l1b = idex_l1b(msg_data_l1a, "msg") + l1b_data = idex_l1b(l1a_data, "sci-1week") + l1a_data = idex_l2a(l1b_data) - l2b_and_l2c_datasets = idex_l2b(l2a_data, [evt_data]) + l2b_and_l2c_datasets = idex_l2b(l2a_data, [msg_data_l1b]) write_cdf(l2b_and_l2c_datasets[0]) write_cdf(l2b_and_l2c_datasets[1]) """ @@ -29,6 +30,7 @@ import numpy as np import xarray as xr +from numpy._typing import NDArray from imap_processing.ena_maps.ena_maps import SkyTilingType from imap_processing.ena_maps.utils.spatial_utils import AzElSkyGrid @@ -37,7 +39,6 @@ IDEX_EVENT_REFERENCE_FRAME, IDEX_SPACING_DEG, SECONDS_IN_DAY, - IDEXEvtAcquireCodes, ) from imap_processing.idex.idex_utils import get_idex_attrs from imap_processing.spice.time import epoch_to_doy, et_to_datetime64, ttj2000ns_to_et @@ -83,7 +84,7 @@ def idex_l2b( - l2a_datasets: list[xr.Dataset], evt_datasets: list[xr.Dataset] + l2a_datasets: list[xr.Dataset], msg_data_l1b: list[xr.Dataset] ) -> list[xr.Dataset]: """ Will process IDEX l2a data to create l2b and l2c data products. @@ -95,8 +96,8 @@ def idex_l2b( ---------- l2a_datasets : list[xarray.Dataset] IDEX L2a datasets to process. - evt_datasets : list[xarray.Dataset] - List of IDEX housekeeping event message datasets. + msg_data_l1b : list[xarray.Dataset] + List of IDEX L1B event message datasets. Returns ------- @@ -112,11 +113,17 @@ def idex_l2b( # create the attribute manager for this data level idex_l2b_attrs = get_idex_attrs("l2b") idex_l2c_attrs = get_idex_attrs("l2c") - evt_dataset = xr.concat(evt_datasets, dim="epoch") - + msg_ds = ( + xr.concat(msg_data_l1b, dim="epoch").sortby("epoch").drop_duplicates("epoch") + ) # Concat all the l2a datasets together l2a_dataset = xr.concat(l2a_datasets, dim="epoch") - epoch_doy_unique = np.unique(epoch_to_doy(l2a_dataset["epoch"].data)) + epoch_doy = epoch_to_doy(l2a_dataset["epoch"].data) + # Use dict.fromkeys to preserve order while getting unique DOYs. We want to make + # sure the order of DOYs stays the same in case we are dealing with data that + # spans over the new year. E.g., we want 365 to come before 1 if we have data from + # Dec and Jan. + epoch_doy_unique = np.array(list(dict.fromkeys(epoch_doy))) ( counts_by_charge, counts_by_mass, @@ -124,8 +131,14 @@ def idex_l2b( counts_by_mass_map, daily_epoch, ) = compute_counts_by_charge_and_mass(l2a_dataset, epoch_doy_unique) + # Filter the message dataset to only include science acquisition on/off events. + # (ignore fill vals) + science_on_msg_ds = msg_ds.isel(epoch=np.isin(msg_ds.science_on, [0, 1])) + msg_time = science_on_msg_ds["epoch"].data + msg_values = science_on_msg_ds["science_on"].data + # Get science acquisition percentage for each day - daily_on_percentage = get_science_acquisition_on_percentage(evt_dataset) + daily_on_percentage = get_science_acquisition_on_percentage(msg_time, msg_values) ( rate_by_charge, rate_by_mass, @@ -144,7 +157,8 @@ def idex_l2b( charge_bin_means = np.sqrt(CHARGE_BIN_EDGES[:-1] * CHARGE_BIN_EDGES[1:]) mass_bin_means = np.sqrt(MASS_BIN_EDGES[:-1] * MASS_BIN_EDGES[1:]) spin_phase_means = (SPIN_PHASE_BIN_EDGES[:-1] + SPIN_PHASE_BIN_EDGES[1:]) / 2 - + # convert to integers + spin_phase_means = spin_phase_means.astype(np.uint16) # Define xarrays that are shared between l2b and l2c epoch = xr.DataArray( name="epoch", @@ -152,8 +166,23 @@ def idex_l2b( dims="epoch", attrs=idex_l2b_attrs.get_variable_attributes("epoch", check_schema=False), ) - common_vars = { + "on_off_times": xr.DataArray( + name="on_off_times", + data=msg_time, + dims="on_off_times", + attrs=idex_l2b_attrs.get_variable_attributes( + "on_off_times", check_schema=False + ), + ), + "on_off_events": xr.DataArray( + name="on_off_events", + data=np.asarray(msg_values, dtype=np.uint8), + dims="on_off_times", + attrs=idex_l2b_attrs.get_variable_attributes( + "on_off_events", check_schema=False + ), + ), "impact_day_of_year": xr.DataArray( name="impact_day_of_year", data=epoch_doy_unique, @@ -319,7 +348,6 @@ def idex_l2b( attrs=idex_l2c_attrs.get_variable_attributes("rate_by_mass_map"), ), } - l2b_dataset = xr.Dataset( coords={"epoch": epoch}, data_vars=l2b_vars, @@ -338,8 +366,39 @@ def idex_l2b( l2c_dataset.attrs.update(map_attrs) - logger.info("IDEX L2B and L2C science data processing completed.") + # We're inserting a NaN block here for the 2026 June release while the + # IDEX science team works through validating the fitting routines and + # derived values. + + # L2B Block + l2b_dataset["counts_by_mass"].data = np.full( + l2b_dataset["counts_by_mass"].shape, np.nan + ) + l2b_dataset["counts_by_charge"].data = np.full( + l2b_dataset["counts_by_charge"].shape, np.nan + ) + l2b_dataset["rate_by_mass"].data = np.full( + l2b_dataset["rate_by_mass"].shape, np.nan + ) + l2b_dataset["rate_by_charge"].data = np.full( + l2b_dataset["rate_by_charge"].shape, np.nan + ) + + # L2C Block + l2c_dataset["counts_by_mass_map"].data = np.full( + l2c_dataset["counts_by_mass_map"].shape, np.nan + ) + l2c_dataset["counts_by_charge_map"].data = np.full( + l2c_dataset["counts_by_charge_map"].shape, np.nan + ) + l2c_dataset["rate_by_mass_map"].data = np.full( + l2c_dataset["rate_by_mass_map"].shape, np.nan + ) + l2c_dataset["rate_by_charge_map"].data = np.full( + l2c_dataset["rate_by_charge_map"].shape, np.nan + ) + logger.info("IDEX L2B and L2C science data processing completed.") return [l2b_dataset, l2c_dataset] @@ -368,7 +427,7 @@ def compute_counts_by_charge_and_mass( counts_by_mass = [] counts_by_charge_map = [] counts_by_mass_map = [] - daily_epoch = np.zeros(len(epoch_doy_unique), dtype=np.float64) + daily_epoch: np.ndarray = np.zeros(len(epoch_doy_unique), dtype=np.float64) for i in range(len(epoch_doy_unique)): doy = epoch_doy_unique[i] # Get the indices for the current day @@ -567,76 +626,18 @@ def bin_spin_phases(spin_phases: xr.DataArray) -> np.ndarray: return np.asarray(bin_indices) -def get_science_acquisition_timestamps( - evt_dataset: xr.Dataset, -) -> tuple[np.ndarray, np.ndarray, np.ndarray]: - """ - Get the science acquisition start and stop times and messages from the event data. - - Parameters - ---------- - evt_dataset : xarray.Dataset - Contains IDEX event message data. - - Returns - ------- - event_logs : np.ndarray - Array containing science acquisition start and stop events messages. - event_timestamps : np.ndarray - Array containing science acquisition start and stop timestamps. - event_values : np.ndarray - Array containing values indicating if the event is a start (1) or - stop (0). - """ - # Sort the event dataset by the epoch time. Drop duplicates - evt_dataset = evt_dataset.sortby("epoch").drop_duplicates("epoch") - # First find indices of the state change events - sc_indices = np.where(evt_dataset["elid_evtpkt"].data == "SCI_STE")[0] - event_logs = [] - event_timestamps = [] - event_values = [] - # Get the values of the state change events - val1 = ( - evt_dataset["el1par_evtpkt"].data[sc_indices] << 8 - | evt_dataset["el2par_evtpkt"].data[sc_indices] - ) - val2 = ( - evt_dataset["el3par_evtpkt"].data[sc_indices] << 8 - | evt_dataset["el4par_evtpkt"].data[sc_indices] - ) - epochs = evt_dataset["epoch"][sc_indices].data - # Now the state change values and check if it is either a science - # acquisition start or science acquisition stop event. - for v1, v2, epoch in zip(val1, val2, epochs, strict=False): - # An "acquire" start will have val1=ACQSETUP and val2=ACQ - # An "acquire" stop will have val1=ACQ and val2=CHILL - if (v1, v2) == (IDEXEvtAcquireCodes.ACQSETUP, IDEXEvtAcquireCodes.ACQ): - event_logs.append("SCI state change: ACQSETUP to ACQ") - event_timestamps.append(epoch) - event_values.append(1) - elif (v1, v2) == (IDEXEvtAcquireCodes.ACQ, IDEXEvtAcquireCodes.CHILL): - event_logs.append("SCI state change: ACQ to CHILL") - event_timestamps.append(epoch) - event_values.append(0) - - logger.info( - f"Found science acquisition events: {event_logs} at times: {event_timestamps}" - ) - return ( - np.asarray(event_logs), - np.asarray(event_timestamps), - np.asarray(event_values), - ) - - -def get_science_acquisition_on_percentage(evt_dataset: xr.Dataset) -> dict: +def get_science_acquisition_on_percentage( + msg_time: NDArray, msg_values: NDArray +) -> dict: """ Calculate the percentage of time science acquisition was occurring for each day. Parameters ---------- - evt_dataset : xarray.Dataset - Contains IDEX event message data. + msg_time : np.ndarray + Array of timestamps for science acquisition start and stop events. + msg_values : np.ndarray + Array of values indicating if the event is a start (1) or stop (0). Returns ------- @@ -644,9 +645,7 @@ def get_science_acquisition_on_percentage(evt_dataset: xr.Dataset) -> dict: Percentages of time the instrument was in science acquisition mode for each day of year. """ - # Get science acquisition start and stop times - evt_logs, evt_time, evt_values = get_science_acquisition_timestamps(evt_dataset) - if len(evt_time) == 0: + if len(msg_time) == 0: logger.warning( "No science acquisition events found in event dataset. Returning empty " "uptime percentages. All rate variables will be set to -1." @@ -656,17 +655,17 @@ def get_science_acquisition_on_percentage(evt_dataset: xr.Dataset) -> dict: daily_totals: collections.defaultdict = defaultdict(timedelta) daily_on: collections.defaultdict = defaultdict(timedelta) # Convert epoch event times to datetime - dates = et_to_datetime64(ttj2000ns_to_et(evt_time)).astype(datetime) + dates = et_to_datetime64(ttj2000ns_to_et(msg_time)).astype(datetime) # Simulate an event at the start of the first day. start_of_first_day = dates[0].replace(hour=0, minute=0, second=0, microsecond=0) # Assume that the state at the start of the day is the opposite of what the first # state is. - state_at_start = 0 if evt_values[0] == 1 else 1 + state_at_start = 0 if msg_values[0] == 1 else 1 dates = np.insert(dates, 0, start_of_first_day) - evt_values = np.insert(evt_values, 0, state_at_start) + msg_values = np.insert(msg_values, 0, state_at_start) for i in range(len(dates)): start = dates[i] - state = evt_values[i] + state = msg_values[i] if i == len(dates) - 1: # If this is the last event, set the "end" value the end of the day. end = (start + timedelta(days=1)).replace( diff --git a/imap_processing/idex/idex_variable_unpacking_and_eu_conversion.csv b/imap_processing/idex/idex_variable_unpacking_and_eu_conversion.csv index 793897ef64..80927ecbe2 100644 --- a/imap_processing/idex/idex_variable_unpacking_and_eu_conversion.csv +++ b/imap_processing/idex/idex_variable_unpacking_and_eu_conversion.csv @@ -10,8 +10,8 @@ 9,detector_voltage,idx__txhdrhvpshkch01,4,4,12,V,0,1.4652,0,0,0,0,0,0,UNSEGMENTED_POLY,IDEX_SCI 10,sensor_voltage,idx__txhdrhvpshkch01,20,4,12,V,0,1.4652,0,0,0,0,0,0,UNSEGMENTED_POLY,IDEX_SCI 11,target_voltage,idx__txhdrhvpshkch23,4,4,12,V,0,1.4652,0,0,0,0,0,0,UNSEGMENTED_POLY,IDEX_SCI -12,reflectron_voltage,idx__txhdrhvpshkch23,20,4,12,V,0,1.4652,0,0,0,0,0,0,UNSEGMENTED_POLY,IDEX_SCI -13,rejection_voltage,idx__txhdrhvpshkch45,4,4,12,V,0,1.4652,0,0,0,0,0,0,UNSEGMENTED_POLY,IDEX_SCI +12,rejection_voltage,idx__txhdrhvpshkch23,20,4,12,V,0,1.4652,0,0,0,0,0,0,UNSEGMENTED_POLY,IDEX_SCI +13,reflectron_voltage,idx__txhdrhvpshkch45,4,4,12,V,0,1.4652,0,0,0,0,0,0,UNSEGMENTED_POLY,IDEX_SCI 14,current_hvps_sensor,idx__txhdrhvpshkch45,20,4,12,mA,0,0.000007326,0,0,0,0,0,0,UNSEGMENTED_POLY,IDEX_SCI 15,positive_current_hvps,idx__txhdrhvpshkch67,4,4,12,mA,0,0.000024339,0,0,0,0,0,0,UNSEGMENTED_POLY,IDEX_SCI 16,negative_current_hvps,idx__txhdrhvpshkch67,20,4,12,mA,0,0.000024339,0,0,0,0,0,0,UNSEGMENTED_POLY,IDEX_SCI diff --git a/imap_processing/lo/ancillary_data/imap_lo_bootstrap-correction-factors_v001.csv b/imap_processing/lo/ancillary_data/imap_lo_bootstrap-correction-factors_v001.csv new file mode 100644 index 0000000000..5039d8aba2 --- /dev/null +++ b/imap_processing/lo/ancillary_data/imap_lo_bootstrap-correction-factors_v001.csv @@ -0,0 +1,20 @@ +esa_step_i,esa_step_k,bootstrap_factor +1,2,0.03 +1,3,0.01 +2,3,0.05 +2,4,0.02 +2,5,0.01 +3,4,0.09 +3,5,0.03 +3,6,0.016 +3,7,0.01 +4,5,0.16 +4,6,0.068 +4,7,0.016 +4,8,0.01 +5,6,0.29 +5,7,0.068 +5,8,0.016 +6,7,0.52 +6,8,0.061 +7,8,0.75 diff --git a/imap_processing/lo/ancillary_data/imap_lo_hydrogen-geometric-factor_v001.csv b/imap_processing/lo/ancillary_data/imap_lo_hydrogen-geometric-factor_v001.csv new file mode 100644 index 0000000000..3c4b9996de --- /dev/null +++ b/imap_processing/lo/ancillary_data/imap_lo_hydrogen-geometric-factor_v001.csv @@ -0,0 +1,75 @@ +ο»Ώincident_E-Step,Observed_E-Step,Cntr_E,Cntr_E_unc,GF_Dbl_all,GF_Dbl_all_unc,GF_Trpl_all,GF_Trpl_all_unc,GF_Dbl_H,GF_Dbl_H_unc,GF_Trpl_H,GF_Trpl_H_unc +Hi_Res,,[keV],[keV],[cm^2sr keV/keV],[cm^2sr keV/keV],[cm^2sr keV/keV],[cm^2sr keV/keV],[cm^2sr keV/keV],[cm^2sr keV/keV],[cm^2sr keV/keV],[cm^2sr keV/keV] +1,1,0.01633,0.00028,5.35E-05,4.82E-06,2.20E-05,1.87E-06,5.32E-05,4.26E-06,7.00E-05,4.90E-05 +2,1,0.01633,0.00028,3.10E-05,2.79E-06,1.25E-05,1.06E-06,3.09E-05,2.47E-06,1.27E-05,1.08E-06 +2,2,0.03047,0.00043,1.04E-04,9.36E-06,4.27E-05,3.63E-06,1.03E-04,8.26E-06,7.90E-05,5.50E-05 +3,1,0.01633,0.00028,4.13E-05,3.72E-06,1.68E-05,1.43E-06,4.16E-05,3.33E-06,1.71E-05,1.45E-06 +3,2,0.03047,0.00043,1.28E-04,1.15E-05,5.02E-05,4.26E-06,1.30E-04,1.04E-05,5.35E-05,4.55E-06 +3,3,0.05576,0.00089,1.59E-04,1.43E-05,6.54E-05,5.56E-06,1.59E-04,1.27E-05,9.70E-05,6.80E-05 +4,1,0.01633,0.00028,9.85E-06,8.86E-07,3.73E-06,3.17E-07,7.97E-06,6.38E-07,3.28E-06,2.79E-07 +4,2,0.03047,0.00043,1.71E-05,1.54E-06,6.54E-06,5.56E-07,1.68E-05,1.34E-06,6.89E-06,5.86E-07 +4,3,0.05576,0.00089,6.72E-05,6.05E-06,2.58E-05,2.19E-06,6.92E-05,5.53E-06,2.84E-05,2.42E-06 +4,4,0.1063,0.0019,1.79E-04,1.61E-05,7.36E-05,6.25E-06,1.78E-04,1.42E-05,1.12E-04,3.00E-05 +5,1,0.01633,0.00028,1.62E-05,1.46E-06,5.05E-06,4.29E-07,7.86E-06,6.29E-07,3.23E-06,2.75E-07 +5,2,0.03047,0.00043,1.57E-05,1.41E-06,5.16E-06,4.39E-07,9.72E-06,7.77E-07,3.99E-06,3.39E-07 +5,3,0.05576,0.00089,1.45E-05,1.31E-06,4.98E-06,4.24E-07,1.49E-05,1.20E-06,6.14E-06,5.22E-07 +5,4,0.1063,0.0019,5.81E-05,5.23E-06,2.15E-05,1.83E-06,6.00E-05,4.80E-06,2.47E-05,2.10E-06 +5,5,0.2,0.0034,1.77E-04,1.59E-05,7.26E-05,6.17E-06,1.76E-04,1.41E-05,1.40E-04,4.50E-05 +6,1,0.01633,0.00028,1.34E-05,1.21E-06,4.33E-06,3.68E-07,9.40E-06,7.52E-07,3.86E-06,3.28E-07 +6,2,0.03047,0.00043,1.61E-05,1.45E-06,4.64E-06,3.94E-07,1.11E-05,8.92E-07,4.58E-06,3.89E-07 +6,3,0.05576,0.00089,1.74E-05,1.57E-06,5.02E-06,4.27E-07,1.42E-05,1.14E-06,5.84E-06,4.96E-07 +6,4,0.1063,0.0019,1.45E-05,1.30E-06,4.28E-06,3.64E-07,1.56E-05,1.25E-06,6.40E-06,5.44E-07 +6,5,0.2,0.0034,5.81E-05,5.23E-06,2.06E-05,1.75E-06,6.01E-05,4.81E-06,2.47E-05,2.10E-06 +6,6,0.405,0.0073,2.06E-04,1.85E-05,8.46E-05,7.19E-06,2.06E-04,1.64E-05,1.77E-04,2.00E-05 +7,1,0.01633,0.00028,5.32E-06,4.79E-07,1.51E-06,1.29E-07,5.05E-06,4.04E-07,2.08E-06,1.76E-07 +7,2,0.03047,0.00043,1.61E-05,1.45E-06,5.15E-06,4.38E-07,1.39E-05,1.11E-06,5.70E-06,4.85E-07 +7,3,0.05576,0.00089,1.96E-05,1.77E-06,6.10E-06,5.19E-07,1.42E-05,1.14E-06,5.84E-06,4.96E-07 +7,4,0.1063,0.0019,2.08E-05,1.87E-06,6.43E-06,5.46E-07,1.65E-05,1.32E-06,6.78E-06,5.77E-07 +7,5,0.2,0.0034,2.52E-05,2.27E-06,8.69E-06,7.39E-07,2.61E-05,2.09E-06,1.07E-05,9.11E-07 +7,6,0.405,0.0073,1.93E-04,1.74E-05,6.94E-05,5.90E-06,1.98E-04,1.59E-05,8.15E-05,6.93E-06 +7,7,0.7873,0.022,3.82E-04,3.44E-05,1.57E-04,1.33E-05,3.82E-04,3.05E-05,2.25E-04,1.40E-05 +8,1,0.01633,0.00028,5.28E-05,4.75E-06,2.25E-05,1.91E-06,4.10E-05,3.28E-06,1.68E-05,1.43E-06 +8,2,0.03047,0.00043,6.14E-06,5.53E-07,1.96E-06,1.66E-07,5.25E-06,4.20E-07,2.16E-06,1.83E-07 +8,3,0.05576,0.00089,1.13E-05,1.02E-06,3.39E-06,2.88E-07,9.37E-06,7.50E-07,3.85E-06,3.27E-07 +8,4,0.1063,0.0019,1.16E-05,1.04E-06,3.83E-06,3.25E-07,8.69E-06,6.95E-07,3.57E-06,3.03E-07 +8,5,0.2,0.0034,1.09E-05,9.78E-07,3.55E-06,3.02E-07,8.41E-06,6.73E-07,3.46E-06,2.94E-07 +8,6,0.405,0.0073,3.29E-05,2.96E-06,1.28E-05,1.08E-06,3.28E-05,2.62E-06,1.35E-05,1.15E-06 +8,7,0.7873,0.022,3.95E-04,3.56E-05,1.44E-04,1.23E-05,4.04E-04,3.23E-05,1.66E-04,1.41E-05 +8,8,1.821,0.16389,5.41E-04,4.87E-05,2.22E-04,1.89E-05,5.41E-04,4.33E-05,2.22E-04,1.89E-05 +Hi_Thr,,,,,,,,,,, +1,1,0.01719,0.00022,8.92E-05,8.03E-06,3.67E-05,3.12E-06,8.87E-05,7.10E-06,1.66E-04,1.01E-04 +2,1,0.01719,0.00022,5.16E-05,4.65E-06,2.08E-05,1.76E-06,5.15E-05,4.12E-06,2.12E-05,1.80E-06 +2,2,0.03236,0.00036,1.73E-04,1.56E-05,7.12E-05,6.06E-06,1.72E-04,1.38E-05,1.92E-04,1.17E-04 +3,1,0.01719,0.00022,6.88E-05,6.19E-06,2.80E-05,2.38E-06,6.94E-05,5.55E-06,2.85E-05,2.42E-06 +3,2,0.03236,0.00036,2.13E-04,1.91E-05,8.36E-05,7.11E-06,2.17E-04,1.74E-05,8.92E-05,7.58E-06 +3,3,0.05948,0.00077,2.65E-04,2.39E-05,1.09E-04,9.26E-06,2.64E-04,2.11E-05,2.27E-04,1.38E-04 +4,1,0.01719,0.00022,1.64E-05,1.48E-06,6.22E-06,5.29E-07,1.33E-05,1.06E-06,5.46E-06,4.64E-07 +4,2,0.03236,0.00036,2.84E-05,2.56E-06,1.09E-05,9.27E-07,2.80E-05,2.24E-06,1.15E-05,9.77E-07 +4,3,0.05948,0.00077,1.12E-04,1.01E-05,4.30E-05,3.66E-06,1.15E-04,9.22E-06,4.74E-05,4.03E-06 +4,4,0.1144,0.0013,2.98E-04,2.68E-05,1.23E-04,1.04E-05,2.96E-04,2.37E-05,2.73E-04,9.80E-05 +5,1,0.01719,0.00022,2.70E-05,2.43E-06,8.42E-06,7.15E-07,1.31E-05,1.05E-06,5.38E-06,4.58E-07 +5,2,0.03236,0.00036,2.61E-05,2.35E-06,8.61E-06,7.31E-07,1.62E-05,1.30E-06,6.65E-06,5.66E-07 +5,3,0.05948,0.00077,2.42E-05,2.18E-06,8.30E-06,7.06E-07,2.49E-05,1.99E-06,1.02E-05,8.70E-07 +5,4,0.1144,0.0013,9.69E-05,8.72E-06,3.58E-05,3.04E-06,1.00E-04,8.00E-06,4.11E-05,3.49E-06 +5,5,0.2137,0.003,2.94E-04,2.65E-05,1.21E-04,1.03E-05,2.93E-04,2.34E-05,3.38E-04,9.50E-05 +6,1,0.01719,0.00022,2.24E-05,2.01E-06,7.22E-06,6.14E-07,1.57E-05,1.25E-06,6.44E-06,5.47E-07 +6,2,0.03236,0.00036,2.68E-05,2.41E-06,7.73E-06,6.57E-07,1.86E-05,1.49E-06,7.64E-06,6.49E-07 +6,3,0.05948,0.00077,2.91E-05,2.61E-06,8.37E-06,7.12E-07,2.37E-05,1.89E-06,9.73E-06,8.27E-07 +6,4,0.1144,0.0013,2.41E-05,2.17E-06,7.13E-06,6.06E-07,2.60E-05,2.08E-06,1.07E-05,9.07E-07 +6,5,0.2137,0.003,9.68E-05,8.71E-06,3.44E-05,2.92E-06,1.00E-04,8.02E-06,4.12E-05,3.50E-06 +6,6,0.4374,0.0053,3.43E-04,3.09E-05,1.41E-04,1.20E-05,3.43E-04,2.74E-05,4.44E-04,4.90E-05 +7,1,0.01719,0.00022,8.87E-06,7.98E-07,2.52E-06,2.14E-07,8.42E-06,6.73E-07,3.46E-06,2.94E-07 +7,2,0.03236,0.00036,2.68E-05,2.41E-06,8.59E-06,7.30E-07,2.31E-05,1.85E-06,9.50E-06,8.08E-07 +7,3,0.05948,0.00077,3.27E-05,2.95E-06,1.02E-05,8.64E-07,2.37E-05,1.89E-06,9.73E-06,8.27E-07 +7,4,0.1144,0.0013,3.47E-05,3.12E-06,1.07E-05,9.10E-07,2.75E-05,2.20E-06,1.13E-05,9.61E-07 +7,5,0.2137,0.003,4.20E-05,3.78E-06,1.45E-05,1.23E-06,4.35E-05,3.48E-06,1.79E-05,1.52E-06 +7,6,0.4374,0.0053,3.21E-04,2.89E-05,1.16E-04,9.84E-06,3.31E-04,2.65E-05,1.36E-04,1.16E-05 +7,7,0.8389,0.00117,6.36E-04,5.73E-05,2.61E-04,2.22E-05,6.36E-04,5.09E-05,5.69E-04,2.90E-05 +8,1,0.01719,0.00022,8.79E-05,7.91E-06,3.75E-05,3.19E-06,6.83E-05,5.46E-06,2.81E-05,2.39E-06 +8,2,0.03236,0.00036,1.02E-05,9.21E-07,3.26E-06,2.77E-07,8.75E-06,7.00E-07,3.60E-06,3.06E-07 +8,3,0.05948,0.00077,1.88E-05,1.70E-06,5.65E-06,4.80E-07,1.56E-05,1.25E-06,6.42E-06,5.46E-07 +8,4,0.1144,0.0013,1.93E-05,1.73E-06,6.38E-06,5.42E-07,1.45E-05,1.16E-06,5.95E-06,5.06E-07 +8,5,0.2137,0.003,1.81E-05,1.63E-06,5.92E-06,5.03E-07,1.40E-05,1.12E-06,5.76E-06,4.90E-07 +8,6,0.4374,0.0053,5.48E-05,4.93E-06,2.13E-05,1.81E-06,5.46E-05,4.37E-06,2.25E-05,1.91E-06 +8,7,0.8389,0.00117,6.59E-04,5.93E-05,2.40E-04,2.04E-05,6.74E-04,5.39E-05,2.77E-04,2.35E-05 +8,8,1.822,0.16398,9.01E-04,8.11E-05,3.70E-04,3.15E-05,9.01E-04,7.21E-05,3.70E-04,3.15E-05 \ No newline at end of file diff --git a/imap_processing/lo/ancillary_data/imap_lo_oxygen-geometric-factor_v001.csv b/imap_processing/lo/ancillary_data/imap_lo_oxygen-geometric-factor_v001.csv new file mode 100644 index 0000000000..a72e122e47 --- /dev/null +++ b/imap_processing/lo/ancillary_data/imap_lo_oxygen-geometric-factor_v001.csv @@ -0,0 +1,75 @@ +ο»Ώincident_E-Step,Observed_E-Step,Cntr_E,Cntr_E_unc,GF_Dbl_all,GF_Dbl_all_unc,GF_Trpl_all,GF_Trpl_all_unc,GF_Dbl_O,GF_Dbl_O_unc,GF_Trpl_O,GF_Trpl_O_unc +Hi_Res,,[keV],[keV],[cm^2sr keV/keV],[cm^2sr keV/keV],[cm^2sr keV/keV],[cm^2sr keV/keV],[cm^2sr keV/keV],[cm^2sr keV/keV],[cm^2sr keV/keV],[cm^2sr keV/keV] +1,1,0.016,0.00144,3.8700E-04,3.4400E-04,8.9100E-05,8.0200E-05,4.2600E-04,3.4100E-04,1.0600E-04,9.1500E-05 +2,1,0.016,0.00144,2.8700E-04,2.5600E-04,6.6100E-05,5.9500E-05,2.7700E-04,2.2100E-04,6.9200E-05,5.9500E-05 +2,2,0.032,0.00288,4.4800E-04,3.9900E-04,9.6700E-05,8.7000E-05,4.7800E-04,3.8200E-04,1.2000E-04,1.0300E-04 +3,1,0.016,0.00144,5.2900E-04,4.7100E-04,1.3200E-04,1.1900E-04,4.1800E-04,3.3400E-04,1.0400E-04,8.9800E-05 +3,2,0.032,0.00288,5.9300E-04,5.2800E-04,1.4100E-04,1.2700E-04,6.3000E-04,5.0400E-04,1.5800E-04,1.3600E-04 +3,3,0.065,0.00585,6.9900E-04,6.2200E-04,1.6600E-04,1.5000E-04,7.6400E-04,6.1100E-04,1.9100E-04,1.6400E-04 +4,1,0.016,0.00144,6.6400E-04,5.9100E-04,1.7700E-04,1.5900E-04,4.1600E-04,3.3300E-04,1.0400E-04,8.9400E-05 +4,2,0.032,0.00288,1.1500E-03,1.0200E-03,2.6900E-04,2.4200E-04,1.0900E-03,8.7300E-04,2.7300E-04,2.3500E-04 +4,3,0.065,0.00585,2.3600E-03,2.1000E-03,5.1700E-04,4.6500E-04,2.5200E-03,2.0100E-03,6.2900E-04,5.4100E-04 +4,4,0.135,0.01215,8.1500E-04,7.2600E-04,1.9100E-04,1.7200E-04,8.7400E-04,7.0000E-04,2.1900E-04,1.8800E-04 +5,1,0.016,0.00144,2.8100E-04,2.5000E-04,8.8400E-05,7.9600E-05,1.2500E-04,9.9900E-05,3.1200E-05,2.6800E-05 +5,2,0.032,0.00288,3.8100E-04,3.4000E-04,1.0800E-04,9.7300E-05,2.0800E-04,1.6600E-04,5.1900E-05,4.4600E-05 +5,3,0.065,0.00585,5.8000E-04,5.1600E-04,1.3800E-04,1.2400E-04,5.7100E-04,4.5700E-04,1.4300E-04,1.2300E-04 +5,4,0.135,0.01215,5.4100E-04,4.8100E-04,1.2100E-04,1.0800E-04,5.6900E-04,4.5500E-04,1.4200E-04,1.2200E-04 +5,5,0.279,0.02511,8.4100E-04,7.4900E-04,2.0500E-04,1.8500E-04,8.6900E-04,6.9500E-04,2.1700E-04,1.8700E-04 +6,1,0.016,0.00144,2.2100E-04,1.9700E-04,7.1000E-05,6.3900E-05,4.7600E-05,3.8100E-05,1.1900E-05,1.0200E-05 +6,2,0.032,0.00288,3.1900E-04,2.8400E-04,9.7800E-05,8.8000E-05,1.3800E-04,1.1100E-04,3.4600E-05,2.9800E-05 +6,3,0.065,0.00585,4.4900E-04,4.0000E-04,1.2400E-04,1.1100E-04,1.7000E-04,1.3600E-04,4.2500E-05,3.6500E-05 +6,4,0.135,0.01215,6.7700E-04,6.0300E-04,1.5400E-04,1.3800E-04,5.1000E-04,4.0800E-04,1.2700E-04,1.1000E-04 +6,5,0.279,0.02511,1.2800E-03,1.1400E-03,2.9100E-04,2.6200E-04,1.1700E-03,9.3300E-04,2.9100E-04,2.5100E-04 +6,6,0.601,0.05409,8.3600E-04,7.4400E-04,1.9800E-04,1.7800E-04,8.2700E-04,6.6100E-04,2.0700E-04,1.7800E-04 +7,1,0.016,0.00144,1.8500E-04,1.6500E-04,5.9600E-05,5.3700E-05,5.6700E-05,4.5400E-05,1.4200E-05,1.2200E-05 +7,2,0.032,0.00288,2.3400E-04,2.0800E-04,7.3700E-05,6.6300E-05,9.2100E-05,7.3700E-05,2.3000E-05,1.9800E-05 +7,3,0.065,0.00585,3.2000E-04,2.8500E-04,9.2000E-05,8.2800E-05,1.0600E-04,8.5000E-05,2.6600E-05,2.2800E-05 +7,4,0.135,0.01215,4.4900E-04,4.0000E-04,1.2000E-04,1.0800E-04,1.7800E-04,1.4200E-04,4.4400E-05,3.8200E-05 +7,5,0.279,0.02511,7.1800E-04,6.3900E-04,1.7600E-04,1.5800E-04,6.1600E-04,4.9300E-04,1.5400E-04,1.3200E-04 +7,6,0.601,0.05409,1.0300E-03,9.1800E-04,2.4500E-04,2.2000E-04,9.9900E-04,7.9900E-04,2.5000E-04,2.1500E-04 +7,7,1.206,0.10854,9.6000E-04,8.5400E-04,2.4400E-04,2.1900E-04,9.6100E-04,7.6900E-04,2.4000E-04,2.0700E-04 +8,1,0.016,0.00144,2.8900E-04,2.5800E-04,9.1800E-05,8.2700E-05,4.4800E-05,3.5800E-05,1.1200E-05,9.6300E-06 +8,2,0.032,0.00288,3.4200E-04,3.0500E-04,1.0500E-04,9.4300E-05,6.8300E-05,5.4600E-05,1.7100E-05,1.4700E-05 +8,3,0.065,0.00585,1.9300E-04,1.7200E-04,5.6900E-05,5.1200E-05,4.9700E-05,3.9800E-05,1.2400E-05,1.0700E-05 +8,4,0.135,0.01215,2.7000E-04,2.4000E-04,7.2300E-05,6.5000E-05,6.1300E-05,4.9000E-05,1.5300E-05,1.3200E-05 +8,5,0.279,0.02511,3.7600E-04,3.3500E-04,9.7400E-05,8.7700E-05,1.5500E-04,1.2400E-04,3.8800E-05,3.3300E-05 +8,6,0.601,0.05409,7.3600E-04,6.5500E-04,1.8400E-04,1.6600E-04,6.0000E-04,4.8000E-04,1.5000E-04,1.2900E-04 +8,7,1.206,0.10854,1.0600E-03,9.4100E-04,2.5600E-04,2.3100E-04,9.7300E-04,7.7900E-04,2.4300E-04,2.0900E-04 +8,8,2.361,0.21249,9.8400E-04,8.7500E-04,2.5500E-04,2.2900E-04,9.3600E-04,7.4900E-04,2.3400E-04,2.0100E-04 +Hi_Thr,,,,,,,,,,, +1,1,0.017,0.00153,6.4500E-04,5.7400E-04,1.4900E-04,1.3400E-04,7.1000E-04,5.6800E-04,1.7700E-04,1.5300E-04 +2,1,0.017,0.00153,4.7900E-04,4.2600E-04,1.1000E-04,9.9200E-05,4.6100E-04,3.6900E-04,1.1500E-04,9.9200E-05 +2,2,0.033,0.00297,7.4600E-04,6.6400E-04,1.6100E-04,1.4500E-04,7.9700E-04,6.3700E-04,1.9900E-04,1.7100E-04 +3,1,0.017,0.00153,8.8200E-04,7.8500E-04,2.2000E-04,1.9800E-04,6.9600E-04,5.5700E-04,1.7400E-04,1.5000E-04 +3,2,0.033,0.00297,9.8800E-04,8.7900E-04,2.3500E-04,2.1100E-04,1.0500E-03,8.4100E-04,2.6300E-04,2.2600E-04 +3,3,0.066,0.00594,1.1700E-03,1.0400E-03,2.7700E-04,2.4900E-04,1.2700E-03,1.0200E-03,3.1800E-04,2.7400E-04 +4,1,0.017,0.00153,1.1100E-03,9.8600E-04,2.9500E-04,2.6600E-04,6.9300E-04,5.5400E-04,1.7300E-04,1.4900E-04 +4,2,0.033,0.00297,1.9200E-03,1.7100E-03,4.4800E-04,4.0300E-04,1.8200E-03,1.4600E-03,4.5500E-04,3.9100E-04 +4,3,0.066,0.00594,3.9300E-03,3.4900E-03,8.6100E-04,7.7500E-04,4.1900E-03,3.3500E-03,1.0500E-03,9.0100E-04 +4,4,0.136,0.01224,1.3600E-03,1.2100E-03,3.1800E-04,2.8600E-04,1.4600E-03,1.1700E-03,3.6400E-04,3.1300E-04 +5,1,0.017,0.00153,4.6800E-04,4.1700E-04,1.4700E-04,1.3300E-04,2.0800E-04,1.6700E-04,5.2000E-05,4.4700E-05 +5,2,0.033,0.00297,6.3600E-04,5.6600E-04,1.8000E-04,1.6200E-04,3.4600E-04,2.7700E-04,8.6500E-05,7.4400E-05 +5,3,0.066,0.00594,9.6600E-04,8.6000E-04,2.3000E-04,2.0700E-04,9.5100E-04,7.6100E-04,2.3800E-04,2.0400E-04 +5,4,0.136,0.01224,9.0100E-04,8.0200E-04,2.0100E-04,1.8100E-04,9.4800E-04,7.5800E-04,2.3700E-04,2.0400E-04 +5,5,0.28,0.0252,1.4000E-03,1.2500E-03,3.4200E-04,3.0800E-04,1.4500E-03,1.1600E-03,3.6200E-04,3.1100E-04 +6,1,0.017,0.00153,3.6800E-04,3.2800E-04,1.1800E-04,1.0700E-04,7.9400E-05,6.3500E-05,1.9800E-05,1.7100E-05 +6,2,0.033,0.00297,5.3200E-04,4.7300E-04,1.6300E-04,1.4700E-04,2.3100E-04,1.8500E-04,5.7700E-05,4.9600E-05 +6,3,0.066,0.00594,7.4800E-04,6.6600E-04,2.0600E-04,1.8500E-04,2.8300E-04,2.2600E-04,7.0800E-05,6.0900E-05 +6,4,0.136,0.01224,1.1300E-03,1.0000E-03,2.5600E-04,2.3000E-04,8.4900E-04,6.8000E-04,2.1200E-04,1.8300E-04 +6,5,0.28,0.0252,2.1400E-03,1.9100E-03,4.8500E-04,4.3700E-04,1.9400E-03,1.5500E-03,4.8600E-04,4.1800E-04 +6,6,0.602,0.05418,1.3900E-03,1.2400E-03,3.3000E-04,2.9700E-04,1.3800E-03,1.1000E-03,3.4400E-04,2.9600E-04 +7,1,0.017,0.00153,3.0900E-04,2.7500E-04,9.9400E-05,8.9500E-05,9.4500E-05,7.5600E-05,2.3600E-05,2.0300E-05 +7,2,0.033,0.00297,3.9000E-04,3.4700E-04,1.2300E-04,1.1100E-04,1.5400E-04,1.2300E-04,3.8400E-05,3.3000E-05 +7,3,0.066,0.00594,5.3400E-04,4.7500E-04,1.5300E-04,1.3800E-04,1.7700E-04,1.4200E-04,4.4300E-05,3.8100E-05 +7,4,0.136,0.01224,7.4900E-04,6.6700E-04,2.0000E-04,1.8000E-04,2.9600E-04,2.3700E-04,7.4000E-05,6.3700E-05 +7,5,0.28,0.0252,1.2000E-03,1.0700E-03,2.9300E-04,2.6400E-04,1.0300E-03,8.2100E-04,2.5700E-04,2.2100E-04 +7,6,0.602,0.05418,1.7200E-03,1.5300E-03,4.0800E-04,3.6700E-04,1.6700E-03,1.3300E-03,4.1600E-04,3.5800E-04 +7,7,1.207,0.10863,1.6000E-03,1.4200E-03,4.0600E-04,3.6500E-04,1.6000E-03,1.2800E-03,4.0000E-04,3.4400E-04 +8,1,0.017,0.00153,4.8200E-04,4.2900E-04,1.5300E-04,1.3800E-04,7.4700E-05,5.9700E-05,1.8700E-05,1.6100E-05 +8,2,0.033,0.00297,5.7000E-04,5.0800E-04,1.7500E-04,1.5700E-04,1.1400E-04,9.1100E-05,2.8500E-05,2.4500E-05 +8,3,0.066,0.00594,3.2100E-04,2.8600E-04,9.4800E-05,8.5300E-05,8.2900E-05,6.6300E-05,2.0700E-05,1.7800E-05 +8,4,0.136,0.01224,4.5000E-04,4.0100E-04,1.2000E-04,1.0800E-04,1.0200E-04,8.1700E-05,2.5500E-05,2.2000E-05 +8,5,0.28,0.0252,6.2700E-04,5.5800E-04,1.6200E-04,1.4600E-04,2.5800E-04,2.0700E-04,6.4600E-05,5.5600E-05 +8,6,0.602,0.05418,1.2300E-03,1.0900E-03,3.0700E-04,2.7600E-04,1.0000E-03,8.0000E-04,2.5000E-04,2.1500E-04 +8,7,1.207,0.10863,1.7600E-03,1.5700E-03,4.2700E-04,3.8400E-04,1.6200E-03,1.3000E-03,4.0600E-04,3.4900E-04 +8,8,2.362,0.21258,1.6400E-03,1.4600E-03,4.2500E-04,3.8200E-04,1.5600E-03,1.2500E-03,3.9000E-04,3.3500E-04 \ No newline at end of file diff --git a/imap_processing/lo/ancillary_data/imap_lo_sputter-correction-factors_v001.csv b/imap_processing/lo/ancillary_data/imap_lo_sputter-correction-factors_v001.csv new file mode 100644 index 0000000000..fb99d38dcc --- /dev/null +++ b/imap_processing/lo/ancillary_data/imap_lo_sputter-correction-factors_v001.csv @@ -0,0 +1,3 @@ +source_species,target_species,esa_step,sputter_factor,sputter_factor_uncertainty +o,h,5,0.15,0.05 +o,h,6,0.01,0.008 diff --git a/imap_processing/lo/constants.py b/imap_processing/lo/constants.py new file mode 100644 index 0000000000..25cea7b722 --- /dev/null +++ b/imap_processing/lo/constants.py @@ -0,0 +1,77 @@ +"""Constants for IMAP-Lo.""" + +from dataclasses import dataclass +from typing import ClassVar + + +@dataclass(frozen=True) +class LoConstants: + """Constants for Lo which can be used across different levels.""" + + # Expected pivot angle [degrees] for pointing sets for generating map products. + PSET_PIVOT_ANGLE: float = 90.0 + # Absolute tolerance [degrees] for accepting a pset's pivot angle + # as sufficiently close to the required value. + PSET_PIVOT_ANGLE_TOLERANCE: float = 45.0 + + # Ion species tracked. "H" is mandatory (and should be the first element); + # any others for which we have histrates may be added here. + ELEMS = ("H", "O") + + # Hours into the day (UTC) for HK data to calculate median for pivot angle + # estimation. + PIVOT_HK_HOUR_RANGE: tuple[float, float] = (0.5, 22.5) + + N_CYCLE_SUM: int = 1 # Granularity of goodtime boundaries + N_CYCLE_AVE: int = 7 # Cycles to average over when estimating background rates + N_ESA_LEVELS: int = 7 # Total number of ESA levels + N_SPINS_PER_ESA_LEVEL: int = 4 # Spins per ESA step within one histogram cycle + N_SPIN_ANGLE_BINS: int = 60 # Number of angular bins within a spin + + # Nominal spin period [s]. True spin duration is NOT 15 seconds. + NOMINAL_SPIN_PERIOD_SEC: float = 15.0 + + # One histogram accumulation cycle duration [s] + HISTOGRAM_CYCLE_EPOCHS: int = ( + N_ESA_LEVELS * N_SPINS_PER_ESA_LEVEL * int(NOMINAL_SPIN_PERIOD_SEC) + ) + RAM_ESA_LEVELS: tuple[int, ...] = ( + 6, + 7, + ) # ESA levels for RAM estimation (1-indexed) + + # Histogram angular bins (0-indexed) corresponding to the RAM and anti-RAM look + # directions + RAM_HISTOGRAM_BINS: tuple[slice, ...] = (slice(0, 20), slice(50, 60)) + ANTI_RAM_HISTOGRAM_BINS: tuple[slice, ...] = (slice(20, 50),) + + # Nominal background rates [counts/s] for each species + BG_RATES: ClassVar[dict[str, float]] = {"H": 0.0014925, "O": 0.000136635} + # When no exposure is available, scale the nominal rate down as a conservative + # estimate. + BG_RATE_FALLBACK_SCALE: ClassVar[dict[str, float]] = {"H": 1.0, "O": 0.3} + # Minimum non-zero background rate floor = nominal / divisor + BG_RATE_FLOOR_DIVISOR: ClassVar[dict[str, float]] = {"H": 50.0, "O": 150.0} + + # Background-rate thresholds [counts/s] by pivot-angle range (low, high) [deg]. + # Each value is (ram_threshold, anti_ram_threshold). + # The first matching open interval (low < pivot < high) is used; if none matches, + # THRESHOLD_BG_RATE_RAM_DEFAULT / THRESHOLD_BG_RATE_ANTI_RAM_DEFAULT apply. + PIVOT_ANGLE_THRESHOLDS: ClassVar[dict[tuple[float, float], tuple[float, float]]] = { + (88.0, 92.0): (0.014, 0.007), + (73.0, 77.0): (0.0175, 0.00875), + (103.0, 107.0): (0.0112, 0.0056), + } + + # Default background-rate thresholds [counts/s] when no pivot range matches. + THRESHOLD_BG_RATE_RAM_DEFAULT: float = 0.0175 + THRESHOLD_BG_RATE_ANTI_RAM_DEFAULT: float = 0.00875 + + # Maximum time gap [s] between consecutive histogram epochs before treating them as + # separate intervals. + DELAY_MAX: int = 100 + # Fraction of each cycle duration that contributes actual exposure. + EXPOSURE_FACTOR: float = 0.5 + # Padding [s] added to begin/end of each goodtime interval to ensure complete + # cycles are covered at interval edges. + GOODTIME_PADDING: float = 2.0 diff --git a/imap_processing/lo/l0/lo_science.py b/imap_processing/lo/l0/lo_science.py index 97b0103943..43f2aeca40 100644 --- a/imap_processing/lo/l0/lo_science.py +++ b/imap_processing/lo/l0/lo_science.py @@ -24,7 +24,6 @@ from imap_processing.utils import convert_to_binary_string logger = logging.getLogger(__name__) -logger.setLevel(logging.INFO) HistPacking = namedtuple( "HistPacking", @@ -167,10 +166,14 @@ def parse_events(dataset: xr.Dataset, attr_mgr: ImapCdfAttributes) -> xr.Dataset """ Parse and decompress binary direct event data for Lo. + This function works directly with raw bytes instead of converting to binary strings, + resulting in significant performance improvements. + Parameters ---------- dataset : xr.Dataset Lo science direct events from packets_to_dataset function. + Should contain raw bytes data in 'data' field. attr_mgr : ImapCdfAttributes CDF attribute manager for Lo L1A. @@ -184,8 +187,14 @@ def parse_events(dataset: xr.Dataset, attr_mgr: ImapCdfAttributes) -> xr.Dataset # parse the count and passes fields. These fields only occur once # at the beginning of each packet group and are not part of the # compressed direct event data + + # Extract DE counts from raw bytes + de_counts = [ + extract_bits_from_bytes(raw_data, 0, 16) for raw_data in dataset["data"].values + ] + dataset["de_count"] = xr.DataArray( - [int(pkt[0:16], 2) for pkt in dataset["events"].values], + de_counts, dims="epoch", attrs=attr_mgr.get_variable_attributes("de_count"), ) @@ -198,174 +207,171 @@ def parse_events(dataset: xr.Dataset, attr_mgr: ImapCdfAttributes) -> xr.Dataset + list(FIXED_FIELD_BITS._asdict().keys()) + list(VARIABLE_FIELD_BITS._asdict().keys()) ) + # Initialize all Direct Event fields with their fill value # L1A Direct event data will not be tied to an epoch # data will use a direct event index for the # pointing as its coordinate/dimension for field in de_fields: + attrs = attr_mgr.get_variable_attributes(field, check_schema=False) dataset[field] = xr.DataArray( - np.full(num_de, attr_mgr.get_variable_attributes(field)["FILLVAL"]), + np.full(num_de, attrs["FILLVAL"]), dims="direct_events", - attrs=attr_mgr.get_variable_attributes(field), + attrs=attrs, ) dataset["passes"] = xr.DataArray( np.full( - len(dataset["events"].values), + len(dataset["data"].values), attr_mgr.get_variable_attributes("passes")["FILLVAL"], ), dims="epoch", attrs=attr_mgr.get_variable_attributes("passes"), ) - # The DE index for the entire pointing - pointing_de = 0 - # for each direct event packet in the pointing - for pkt_idx, de_count in enumerate(dataset["de_count"].values): - # initialize the bit position for the packet - # after the counts field - dataset.attrs["bit_pos"] = 16 - # Parse the passes field for the packet - dataset["passes"].values[pkt_idx] = parse_de_bin(dataset, pkt_idx, 32) - dataset.attrs["bit_pos"] = dataset.attrs["bit_pos"] + 32 - - # for each direct event in the packet - for _ in range(de_count): - # Parse the fixed fields for the direct event - # Coincidence Type, Time, ESA Step, Mode - dataset = parse_fixed_fields(dataset, pkt_idx, pointing_de) - # Parse the variable fields for the direct event - # TOF0, TOF1, TOF2, TOF3, Checksum, Position - dataset = parse_variable_fields(dataset, pkt_idx, pointing_de) - - pointing_de += 1 - - del dataset.attrs["bit_pos"] - logger.info("\n Returning Lo L1A Direct Events Dataset") - return dataset - + # Pre-extract numpy arrays for all fields to avoid xarray overhead + field_arrays = {} + for field in de_fields: + field_arrays[field] = dataset[field].values -def parse_fixed_fields( - dataset: xr.Dataset, pkt_idx: int, pointing_de: int -) -> xr.Dataset: - """ - Parse the fixed fields for a direct event. + data_values = dataset["data"].values + de_count_values = dataset["de_count"].values + passes_values = dataset["passes"].values - Fixed fields are the fields that are always transmitted for - a direct event. These fields are the Coincidence Type, - Time, ESA Step, and Mode. + # Process each packet + pointing_de = 0 - Parameters - ---------- - dataset : xr.Dataset - Lo science direct events from packets_to_dataset function. - pkt_idx : int - Index of the packet for the pointing. - pointing_de : int - Index of the total direct event for the pointing. + for pkt_idx, de_count in enumerate(de_count_values): + logger.debug( + f"Parsing packet {pkt_idx} of {len(de_count_values)} " + f"with {de_count} direct events" + ) + raw_data = data_values[pkt_idx] - Returns - ------- - dataset : xr.Dataset - Updated dataset with the fixed fields parsed. - """ - for field, bit_length in FIXED_FIELD_BITS._asdict().items(): - dataset[field].values[pointing_de] = parse_de_bin(dataset, pkt_idx, bit_length) - dataset.attrs["bit_pos"] += bit_length + # Parse all direct events in this packet using bytewise operations + pointing_de, passes_value = parse_packet_events( + raw_data, de_count, pointing_de, field_arrays + ) + passes_values[pkt_idx] = passes_value + logger.info("\n Returning Lo L1A Direct Events Dataset") return dataset -def parse_variable_fields( - dataset: xr.Dataset, pkt_idx: int, pointing_de: int -) -> xr.Dataset: +def parse_packet_events( + raw_data: bytes, de_count: int, pointing_de: int, field_arrays: dict +) -> tuple[int, int]: """ - Parse the variable fields for a direct event. - - Variable fields are the fields that are not always transmitted. - Which fields are transmitted is determined by the Coincidence - type and Mode. These fields are TOF0, TOF1, TOF2, TOF3, Checksum, - and Position. All of these fields except for Position are bit - shifted to the right by 1 when packed into the CCSDS packets. + Parse all direct events in a single packet using bitwise operations on raw bytes. Parameters ---------- - dataset : xr.Dataset - Lo science direct events from packets_to_dataset function. - pkt_idx : int - Index of the packet for the pointing. + raw_data : bytes + Raw packet data as bytes. + de_count : int + Number of direct events in this packet. pointing_de : int - Index of the total direct event for the pointing. + Starting index for direct events in the pointing. + field_arrays : dict + Dictionary of field names to pre-extracted numpy arrays. Returns ------- - dataset : xr.Dataset - Updated dataset with the fixed fields parsed. + int, int + Updated pointing_de index after processing all events in packet. + Passes value for this packet. """ - # The decoder defines which TOF fields are - # transmitted for this case and mode - case_decoder = CASE_DECODER[ - ( - dataset["coincidence_type"].values[pointing_de], - dataset["mode"].values[pointing_de], - ) - ] + # Parse passes field (bits 16-47) + passes_value = extract_bits_from_bytes(raw_data, 16, 32) + + bit_offset = 48 # Start after count (16 bits) + passes (32 bits) + + # Process all direct events in this packet + for de_idx in range(de_count): + current_de_idx = pointing_de + de_idx - for field, field_exists in case_decoder._asdict().items(): - # Check which TOF fields should have been transmitted for this - # case number / mode combination and decompress them. - if field_exists: - bit_length = VARIABLE_FIELD_BITS._asdict()[field] - dataset[field].values[pointing_de] = parse_de_bin( - dataset, pkt_idx, bit_length, DE_BIT_SHIFT[field] + # Parse fixed fields using bitwise operations + for field, bit_length in FIXED_FIELD_BITS._asdict().items(): + field_arrays[field][current_de_idx] = extract_bits_from_bytes( + raw_data, bit_offset, bit_length ) - dataset.attrs["bit_pos"] += bit_length + bit_offset += bit_length + + # Parse variable fields based on coincidence type and mode + # Variable fields are the fields that are not always transmitted. + # Which fields are transmitted is determined by the Coincidence + # type and Mode. These fields are TOF0, TOF1, TOF2, TOF3, Checksum, + # and Position. All of these fields except for Position are bit + # shifted to the right by 1 when packed into the CCSDS packets. + case_decoder = CASE_DECODER[ + ( + field_arrays["coincidence_type"][current_de_idx], + field_arrays["mode"][current_de_idx], + ) + ] - return dataset + for field, field_exists in case_decoder._asdict().items(): + if field_exists: + bit_length = VARIABLE_FIELD_BITS._asdict()[field] + bit_shift = DE_BIT_SHIFT.get(field, 0) + field_arrays[field][current_de_idx] = extract_bits_from_bytes( + raw_data, bit_offset, bit_length, bit_shift + ) + bit_offset += bit_length + return pointing_de + de_count, passes_value -def parse_de_bin( - dataset: xr.Dataset, pkt_idx: int, bit_length: int, bit_shift: int = 0 + +def extract_bits_from_bytes( + data: bytes, bit_offset: int, bit_length: int, bit_shift: int = 0 ) -> int: """ - Parse a binary string for a direct event field. + Extract bits from raw bytes using bitwise operations. + + This is much faster than converting to binary strings and doing string slicing. Parameters ---------- - dataset : xr.Dataset - Lo science direct events from packets_to_dataset function. - pkt_idx : int - Index of the packet for the pointing. + data : bytes + Raw byte data. + bit_offset : int + Starting bit position (0-based). bit_length : int - Length of the field in bits. + Number of bits to extract. bit_shift : int - Number of bits to shift the field to the left. + Number of bits to shift result left (for unpacking compressed data). Returns ------- int - Parsed integer for the direct event field. + Extracted value. """ - bit_pos = dataset.attrs["bit_pos"] + # Convert bytes to a big integer for bit manipulation + total_bits = len(data) * 8 + value = int.from_bytes(data, byteorder="big") - parsed_int = ( - int( - dataset["events"].values[pkt_idx][bit_pos : bit_pos + bit_length], - 2, - ) - << bit_shift - ) - return parsed_int + # Create a mask for the desired bits + mask = (1 << bit_length) - 1 + + # Shift to align the desired bits to the right, then apply mask + shift_amount = total_bits - bit_offset - bit_length + extracted = (value >> shift_amount) & mask + + # Apply any additional bit shift for decompression + return extracted << bit_shift def combine_segmented_packets(dataset: xr.Dataset) -> xr.Dataset: """ - Combine segmented packets. + Combine segmented packets and set MET field. If the number of bits needed to pack the direct events exceeds the maximum number of bits allowed in a packet, the direct events will be spread across multiple packets. This function will combine the segmented binary into a single binary string for each epoch. + This function also sets the MET field based on segment start times, + even when no segmentation is present. + Parameters ---------- dataset : xr.Dataset @@ -374,7 +380,7 @@ def combine_segmented_packets(dataset: xr.Dataset) -> xr.Dataset: Returns ------- dataset : xr.Dataset - Updated dataset with any segmented direct events combined. + Updated dataset with any segmented direct events combined and MET field set. """ seq_flgs = dataset.seq_flgs.values seq_ctrs = dataset.src_seq_ctr.values @@ -385,6 +391,7 @@ def combine_segmented_packets(dataset: xr.Dataset) -> xr.Dataset: # 3 = unsegmented packet seg_starts = np.nonzero((seq_flgs == 1) | (seq_flgs == 3))[0] seg_ends = np.nonzero((seq_flgs == 2) | (seq_flgs == 3))[0] + # Swap the epoch dimension for the shcoarse # the epoch dimension will be reduced to the # first epoch in each segment @@ -392,26 +399,31 @@ def combine_segmented_packets(dataset: xr.Dataset) -> xr.Dataset: dataset = dataset.swap_dims({"epoch": "shcoarse"}) # Find the valid groups of segmented packets - # returns a list of booleans for each group of segmented packets - # where true means the group is valid valid_groups = find_valid_groups(seq_ctrs, seg_starts, seg_ends) - # Combine the segmented packets into a single binary string - dataset["events"] = [ - "".join(dataset["data"].values[start : end + 1]) - for start, end in zip(seg_starts, seg_ends, strict=False) - ] + # Combine the segmented packets into raw bytes directly + combined_data_list = [] + for start, end in zip(seg_starts, seg_ends, strict=False): + combined_bytes = b"".join(dataset["data"].values[start : end + 1]) + combined_data_list.append(combined_bytes) - # drop any group of segmented packets that aren't sequential - dataset["events"] = dataset["events"].values[valid_groups] + # Drop any group of segmented packets that aren't sequential + valid_combined_data = [ + combined_data_list[i] for i, valid in enumerate(valid_groups) if valid + ] # Update the epoch to the first epoch in the segment dataset.coords["epoch"] = dataset["epoch"].values[seg_starts] - # drop any group of segmented epochs that aren't sequential + # Drop any group of segmented epochs that aren't sequential dataset.coords["epoch"] = dataset["epoch"].values[valid_groups] - # Set met to the first segment start times for the valid groups. - # shcoarse will be retained as a per packet coordinate and met - # is used as the mission elapsed time for each segment + + # Create the data DataArray with combined raw bytes + dataset["data"] = xr.DataArray( + valid_combined_data, + dims=["epoch"], + coords={"epoch": dataset.coords["epoch"]}, + ) + # Set met to the first segment start times for the valid groups dataset["met"] = xr.DataArray( dataset["shcoarse"].values[seg_starts][valid_groups], dims="epoch" ) diff --git a/imap_processing/lo/l0/lo_star_sensor.py b/imap_processing/lo/l0/lo_star_sensor.py index 7db2fdba2d..c5284463f2 100644 --- a/imap_processing/lo/l0/lo_star_sensor.py +++ b/imap_processing/lo/l0/lo_star_sensor.py @@ -11,7 +11,6 @@ ) logger = logging.getLogger(__name__) -logger.setLevel(logging.INFO) def process_star_sensor(ds: xr.Dataset) -> xr.Dataset: diff --git a/imap_processing/lo/l1a/lo_l1a.py b/imap_processing/lo/l1a/lo_l1a.py index 737616d40c..6c24c7998d 100644 --- a/imap_processing/lo/l1a/lo_l1a.py +++ b/imap_processing/lo/l1a/lo_l1a.py @@ -16,10 +16,9 @@ parse_histogram, ) from imap_processing.lo.l0.lo_star_sensor import process_star_sensor -from imap_processing.utils import convert_to_binary_string, packet_file_to_datasets +from imap_processing.utils import packet_file_to_datasets logger = logging.getLogger(__name__) -logger.setLevel(logging.INFO) def lo_l1a(dependency: Path) -> list[xr.Dataset]: @@ -85,14 +84,11 @@ def lo_l1a(dependency: Path) -> list[xr.Dataset]: ) logical_source = "imap_lo_l1a_de" ds = datasets_by_apid[LoAPID.ILO_SCI_DE] - # Process the "data" array into a string - ds["data"] = xr.DataArray( - [convert_to_binary_string(data) for data in ds["data"].values], - dims=ds["data"].dims, - attrs=ds["data"].attrs, - ) + # For segmented packets, combine raw bytes directly + # Always call combine_segmented_packets to set MET field ds = combine_segmented_packets(ds) + ds = parse_events(ds, attr_mgr) ds = add_dataset_attrs(ds, attr_mgr, logical_source) datasets_to_return.append(ds) @@ -145,6 +141,15 @@ def lo_l1a(dependency: Path) -> list[xr.Dataset]: ds = datasets_by_apid_derived[LoAPID.ILO_APP_SHK] ds = add_dataset_attrs(ds, attr_mgr, logical_source) datasets_to_return.append(ds) + if any( + apid in datasets_by_apid + for apid in [LoAPID.ILO_APP_NHK, LoAPID.ILO_APP_SHK, LoAPID.ILO_DIAG_PCC] + ): + logger.info("\nCreating instrument state vector") + logical_source = "imap_lo_l1b_instrument-status-summary" + combined_ds = instrument_status_summary(datasets_by_apid_derived) + combined_ds = add_dataset_attrs(combined_ds, attr_mgr, logical_source) + datasets_to_return.append(combined_ds) logger.info(f"Returning [{len(datasets_to_return)}] datasets") return datasets_to_return @@ -175,21 +180,25 @@ def add_dataset_attrs( # Get global attributes dataset.attrs.update(attr_mgr.get_global_attributes(logical_source)) # Get attributes for shcoarse and epoch - dataset.shcoarse.attrs.update(attr_mgr.get_variable_attributes("shcoarse")) - dataset.epoch.attrs.update(attr_mgr.get_variable_attributes("epoch")) + dataset.shcoarse.attrs.update( + attr_mgr.get_variable_attributes("shcoarse", check_schema=False) + ) + dataset.epoch.attrs.update( + attr_mgr.get_variable_attributes("epoch", check_schema=False) + ) if logical_source == "imap_lo_l1a_spin": spin = xr.DataArray( data=np.arange(0, 28, dtype=np.uint8), name="spin", dims=["spin"], - attrs=attr_mgr.get_variable_attributes("spin"), + attrs=attr_mgr.get_variable_attributes("spin", check_schema=False), ) spin_label = xr.DataArray( data=spin.values.astype(str), name="spin_label", dims=["spin_label"], - attrs=attr_mgr.get_variable_attributes("spin_label"), + attrs=attr_mgr.get_variable_attributes("spin_label", check_schema=False), ) dataset = dataset.assign_coords(spin=spin, spin_label=spin_label) @@ -221,11 +230,6 @@ def add_dataset_attrs( "chksum", ] ) - # An empty DEPEND_0 is being added to support_data - # variables that should only have DEPEND_1 - # Removing Depend_0 here. - # TODO: Should look for a fix to this issue - del dataset["spin"].attrs["DEPEND_0"] elif logical_source == "imap_lo_l1a_histogram": # Create coordinates for the dataset @@ -233,38 +237,46 @@ def add_dataset_attrs( data=np.arange(0, 6, dtype=np.uint8), name="azimuth_60", dims=["azimuth_60"], - attrs=attr_mgr.get_variable_attributes("azimuth_60"), + attrs=attr_mgr.get_variable_attributes("azimuth_60", check_schema=False), ) azimuth_60_label = xr.DataArray( data=azimuth_60.values.astype(str), name="azimuth_60_label", dims=["azimuth_60_label"], - attrs=attr_mgr.get_variable_attributes("azimuth_60_label"), + attrs=attr_mgr.get_variable_attributes( + "azimuth_60_label", check_schema=False + ), ) azimuth_6 = xr.DataArray( data=np.arange(0, 60, dtype=np.uint8), name="azimuth_6", dims=["azimuth_6"], - attrs=attr_mgr.get_variable_attributes("azimuth_6"), + attrs=attr_mgr.get_variable_attributes("azimuth_6", check_schema=False), ) azimuth_6_label = xr.DataArray( data=azimuth_6.values.astype(str), name="azimuth_6_label", dims=["azimuth_6_label"], - attrs=attr_mgr.get_variable_attributes("azimuth_6_label"), + attrs=attr_mgr.get_variable_attributes( + "azimuth_6_label", check_schema=False + ), ) esa_step = xr.DataArray( data=np.arange(1, 8, dtype=np.uint8), name="esa_step", dims=["esa_step"], - attrs=attr_mgr.get_variable_attributes("esa_step_coord"), + attrs=attr_mgr.get_variable_attributes( + "esa_step_coord", check_schema=False + ), ) esa_step_label = xr.DataArray( esa_step.values.astype(str), name="esa_step_label", dims=["esa_step_label"], - attrs=attr_mgr.get_variable_attributes("esa_step_label"), + attrs=attr_mgr.get_variable_attributes( + "esa_step_label", check_schema=False + ), ) dataset = dataset.assign_coords( @@ -289,13 +301,6 @@ def add_dataset_attrs( "pkt_len", ] ) - # An empty DEPEND_0 is being added to support_data - # variables that should only have DEPEND_1 - # Removing Depend_0 here. - # TODO: Should look for a fix to this issue - del dataset["azimuth_60"].attrs["DEPEND_0"] - del dataset["azimuth_6"].attrs["DEPEND_0"] - del dataset["esa_step"].attrs["DEPEND_0"] elif logical_source == "imap_lo_l1a_de": # Create the coordinates for the dataset @@ -303,16 +308,23 @@ def add_dataset_attrs( data=np.arange(sum(dataset["de_count"].values), dtype=np.uint16), name="direct_events", dims=["direct_events"], - attrs=attr_mgr.get_variable_attributes("direct_events"), + attrs=attr_mgr.get_variable_attributes("direct_events", check_schema=False), ) direct_events_label = xr.DataArray( direct_events.values.astype(str), name="direct_events_label", dims=["direct_events_label"], - attrs=attr_mgr.get_variable_attributes("direct_events_label"), + attrs=attr_mgr.get_variable_attributes( + "direct_events_label", check_schema=False + ), ) + # For DEs, shcoarse applies to each ASC group and is not per individual epoch + # so we can't depend on epoch in the attributes + dataset["shcoarse"].attrs.pop("DEPEND_0") + dataset["shcoarse"].attrs["DEPEND_1"] = "shcoarse" + dataset = dataset.assign_coords( direct_events=direct_events, direct_events_label=direct_events_label, @@ -328,26 +340,78 @@ def add_dataset_attrs( "src_seq_ctr", "pkt_len", "data", - "events", ] ) - # An empty DEPEND_0 is being added to support_data - # variables that should only have DEPEND_1 - # Removing Depend_0 here. - # TODO: Should look for a fix to this issue - for var in [ - "direct_events", - "coincidence_type", - "de_time", - "mode", - "esa_step", - "tof0", - "tof1", - "tof2", - "tof3", - "pos", - "cksm", - ]: - dataset[var].attrs.pop("DEPEND_0") return dataset + + +def instrument_status_summary(datasets_by_apid_derived: dict) -> xr.Dataset: + """ + Combine relevant datasets to create instrument status summary. + + This is from section 9.1.1 of the IMAP-Lo Algorithm Document. We + combine the NHK, SHK, and PCC datasets to create a single data + product containing the instrument status summary. These are not + all aligned in time, so we simply merge them and fill NaNs where + the times are not aligned across data products. + + Parameters + ---------- + datasets_by_apid_derived : dict + Dictionary of datasets keyed by APID with derived values. + + Returns + ------- + xr.Dataset + Combined dataset containing the instrument state vector. + """ + datasets_to_merge = [ + ds + for apid, ds in datasets_by_apid_derived.items() + if apid in [LoAPID.ILO_APP_NHK, LoAPID.ILO_APP_SHK, LoAPID.ILO_DIAG_PCC] + ] + combined_ds = xr.merge(datasets_to_merge, compat="override") + # Only keep the desired keys for the state vector + status_summary_keys = [ + "shcoarse", + "op_mode", + "pac_vset", + "mcp_vset", + "tof_mcp_v", + "bhv_def_neg_dac", + "bhv_def_pos_dac", + "bhv_pmt_dac", + "fsw_version_str", + "eng_lut_version_str", + "sci_lut_version_str", + "an_a_thr", + "an_b0_thr", + "an_b3_thr", + "an_c_thr", + "tof3_thr", + "tof2_thr", + "tof1_thr", + "tof0_thr", + "ifb_hot_spot_t", + "coarse_pot_pri", + "fine_pot_pri", + ] + vars_present = set(status_summary_keys).intersection( + set(combined_ds.data_vars.keys()) + ) + combined_ds = combined_ds[list(vars_present)] + # Add variables that are missing but expected to be in the state vector + for key in status_summary_keys: + if key not in combined_ds: + if key in ["fsw_version_str", "eng_lut_version_str", "sci_lut_version_str"]: + combined_ds[key] = xr.DataArray( + data=np.full(combined_ds["epoch"].shape, "", dtype=str), + dims=["epoch"], + ) + else: + combined_ds[key] = xr.DataArray( + data=np.full(combined_ds["epoch"].shape, np.nan, dtype=float), + dims=["epoch"], + ) + return combined_ds diff --git a/imap_processing/lo/l1b/lo_l1b.py b/imap_processing/lo/l1b/lo_l1b.py index cc73fb5d23..2d5150f581 100644 --- a/imap_processing/lo/l1b/lo_l1b.py +++ b/imap_processing/lo/l1b/lo_l1b.py @@ -2,34 +2,196 @@ import logging from dataclasses import Field +from datetime import timedelta from pathlib import Path -from typing import Any import numpy as np +import spiceypy import xarray as xr from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes +from imap_processing.lo import lo_ancillary +from imap_processing.lo.constants import LoConstants as c # noqa: N813 from imap_processing.lo.l1b.tof_conversions import ( TOF0_CONV, TOF1_CONV, TOF2_CONV, TOF3_CONV, ) -from imap_processing.spice.geometry import SpiceFrame, instrument_pointing -from imap_processing.spice.time import met_to_ttj2000ns, ttj2000ns_to_et +from imap_processing.spice.geometry import ( + SpiceFrame, + cartesian_to_latitudinal, + frame_transform, + get_spacecraft_to_instrument_spin_phase_offset, + lo_instrument_pointing, +) +from imap_processing.spice.repoint import ( + get_pointing_mid_time, + get_pointing_times, + interpolate_repoint_data, +) +from imap_processing.spice.spin import ( + get_spin_data, + get_spin_number, + interpolate_spin_data, +) +from imap_processing.spice.time import ( + epoch_to_fractional_doy, + et_to_utc, + met_to_ttj2000ns, + ttj2000ns_to_et, + ttj2000ns_to_met, +) logger = logging.getLogger(__name__) -logger.setLevel(logging.INFO) - -def lo_l1b(dependencies: dict) -> list[Path]: +# ------------------------------------------------------------------- +# Centralized field definitions to avoid repetition across functions +# ------------------------------------------------------------------- +# spin-bin fields (count fields used in multiple places) +SPIN_BIN_6_FIELDS = [ + "h_counts", + "o_counts", + "tof0_tof1_counts", + "tof0_tof2_counts", + "tof1_tof2_counts", + "silver_triple_counts", +] + +SPIN_BIN_60_FIELDS = [ + "start_a_counts", + "start_c_counts", + "stop_b0_counts", + "stop_b3_counts", + "tof0_counts", + "tof1_counts", + "tof2_counts", + "tof3_counts", + "disc_tof0_counts", + "disc_tof1_counts", + "disc_tof2_counts", + "disc_tof3_counts", + "pos0_counts", + "pos1_counts", + "pos2_counts", + "pos3_counts", +] + +# Mapping from L1A field names to L1B count field names used in initialize_all_rates +SPIN_BIN_6_L1A_TO_L1B = { + "hydrogen": "h_counts", + "oxygen": "o_counts", + "tof0_tof1": "tof0_tof1_counts", + "tof0_tof2": "tof0_tof2_counts", + "tof1_tof2": "tof1_tof2_counts", + "silver": "silver_triple_counts", +} + +SPIN_BIN_60_L1A_TO_L1B = { + "start_a": "start_a_counts", + "start_c": "start_c_counts", + "stop_b0": "stop_b0_counts", + "stop_b3": "stop_b3_counts", + "tof0_count": "tof0_counts", + "tof1_count": "tof1_counts", + "tof2_count": "tof2_counts", + "tof3_count": "tof3_counts", + "disc_tof0": "disc_tof0_counts", + "disc_tof1": "disc_tof1_counts", + "disc_tof2": "disc_tof2_counts", + "disc_tof3": "disc_tof3_counts", + "pos0": "pos0_counts", + "pos1": "pos1_counts", + "pos2": "pos2_counts", + "pos3": "pos3_counts", +} + +# Count-field -> rate-field mappings used by calculate_histogram_rates +SPIN_BIN_6_COUNT_TO_RATE = { + "h_counts": "h_rates", + "o_counts": "o_rates", + "tof0_tof1_counts": "tof0_tof1_rates", + "tof0_tof2_counts": "tof0_tof2_rates", + "tof1_tof2_counts": "tof1_tof2_rates", + "silver_triple_counts": "silver_triple_rates", +} + +SPIN_BIN_60_COUNT_TO_RATE = { + "start_a_counts": "start_a_rates", + "start_c_counts": "start_c_rates", + "stop_b0_counts": "stop_b0_rates", + "stop_b3_counts": "stop_b3_rates", + "tof0_counts": "tof0_rates", + "tof1_counts": "tof1_rates", + "tof2_counts": "tof2_rates", + "tof3_counts": "tof3_rates", + "disc_tof0_counts": "disc_tof0_rates", + "disc_tof1_counts": "disc_tof1_rates", + "disc_tof2_counts": "disc_tof2_rates", + "disc_tof3_counts": "disc_tof3_rates", + "pos0_counts": "pos0_rates", + "pos1_counts": "pos1_rates", + "pos2_counts": "pos2_rates", + "pos3_counts": "pos3_rates", +} + +# Fields to include in the split hist/monitor rate datasets +HIST_RATE_FIELDS = [ + "h_rates", + "o_rates", + "h_counts", + "o_counts", + "esa_mode", + "exposure_time_6deg", + "spin_cycle", +] +MONITOR_RATE_FIELDS = [ + "tof0_tof1_rates", + "tof0_tof2_rates", + "tof1_tof2_rates", + "silver_triple_rates", + "start_a_rates", + "start_c_rates", + "stop_b0_rates", + "stop_b3_rates", + "tof0_rates", + "tof1_rates", + "tof2_rates", + "tof3_rates", + "disc_tof0_rates", + "disc_tof1_rates", + "disc_tof2_rates", + "disc_tof3_rates", + "pos0_rates", + "pos1_rates", + "pos2_rates", + "pos3_rates", + "esa_mode", + "exposure_time_60deg", + "exposure_time_6deg", + "spin_cycle", +] + +GOODTIMES_FIELDS = ["gt_start_met", "gt_end_met", "pivot", "pivot_de"] + +# ------------------------------------------------------------------- +DE_CLOCK_TICK_S = 4.096e-3 # seconds per DE clock tick + + +def lo_l1b( + sci_dependencies: dict, anc_dependencies: list, descriptor: str +) -> list[Path]: """ Will process IMAP-Lo L1A data into L1B CDF data products. Parameters ---------- - dependencies : dict + sci_dependencies : dict Dictionary of datasets needed for L1B data product creation in xarray Datasets. + anc_dependencies : list + List of ancillary file paths needed for L1B data product creation. + descriptor : str + Determines which datasets are produced. Returns ------- @@ -43,60 +205,182 @@ def lo_l1b(dependencies: dict) -> list[Path]: # create the attribute manager to access L1A fillval attributes attr_mgr_l1a = ImapCdfAttributes() attr_mgr_l1a.add_instrument_variable_attrs(instrument="lo", level="l1a") - logger.info(f"\n Dependencies: {list(dependencies.keys())}\n") + logger.info(f"\n Dependencies: {list(sci_dependencies.keys())}\n") + + datasets_to_return = [] + + if descriptor == "badtimes": + logger.info("\nProcessing IMAP-Lo L1B Bad Times...") + badtimes_ds = create_badtimes_dataset() + badtimes_ds.attrs = attr_mgr_l1b.get_global_attributes("imap_lo_l1b_badtimes") + if len(badtimes_ds["epoch"]) > 0: + # Only add the dataset if there are bad times added + datasets_to_return.append(badtimes_ds) + # if the dependencies are used to create Annotated Direct Events - if "imap_lo_l1a_de" in dependencies and "imap_lo_l1a_spin" in dependencies: + elif descriptor == "de": logger.info("\nProcessing IMAP-Lo L1B Direct Events...") - logical_source = "imap_lo_l1b_de" - # get the dependency dataset for l1b direct events - l1a_de = dependencies["imap_lo_l1a_de"] - spin_data = dependencies["imap_lo_l1a_spin"] - - # Initialize the L1B DE dataset - l1b_de = initialize_l1b_de(l1a_de, attr_mgr_l1b, logical_source) - # Get the start and end times for each spin epoch - acq_start, acq_end = convert_start_end_acq_times(spin_data) - # Get the average spin durations for each epoch - avg_spin_durations_per_cycle = get_avg_spin_durations_per_cycle( - acq_start, acq_end - ) - # get spin angle (0 - 360 degrees) for each DE - spin_angle = get_spin_angle(l1a_de) - # calculate and set the spin bin based on the spin angle - # spin bins are 0 - 60 bins - l1b_de = set_spin_bin(l1b_de, spin_angle) - # set the spin cycle for each direct event - l1b_de = set_spin_cycle(l1a_de, l1b_de) - # get spin start times for each event - spin_start_time = get_spin_start_times(l1a_de, l1b_de, spin_data, acq_end) - # get the absolute met for each event - l1b_de = set_event_met( - l1a_de, l1b_de, spin_start_time, avg_spin_durations_per_cycle - ) - # set the epoch for each event - l1b_de = set_each_event_epoch(l1b_de) - # Set the average spin duration for each direct event - l1b_de = set_avg_spin_durations_per_event( - l1a_de, l1b_de, avg_spin_durations_per_cycle - ) - # calculate the TOF1 for golden triples - # store in the l1a dataset to use in l1b calculations - l1a_de = calculate_tof1_for_golden_triples(l1a_de) - # set the coincidence type string for each direct event - l1b_de = set_coincidence_type(l1a_de, l1b_de, attr_mgr_l1a) - # convert the TOFs to engineering units - l1b_de = convert_tofs_to_eu(l1a_de, l1b_de, attr_mgr_l1a, attr_mgr_l1b) - # set the species for each direct event - l1b_de = identify_species(l1b_de) - # set the badtimes - l1b_de = set_bad_times(l1b_de) - # set the pointing direction for each direct event - l1b_de = set_pointing_direction(l1b_de) - # calculate and set the pointing bin based on the spin phase - # pointing bin is 3600 x 40 bins - l1b_de = set_pointing_bin(l1b_de) - - return [l1b_de] + ds = l1b_de(sci_dependencies, anc_dependencies, attr_mgr_l1b, attr_mgr_l1a) + datasets_to_return.append(ds) + + # If dependencies are used to create Histogram Rates + elif descriptor == "all-rates": + logger.info("\nProcessing IMAP-Lo L1B Hist and Monitor Rates...") + ds = l1b_allrates(sci_dependencies, anc_dependencies, attr_mgr_l1b) + datasets_to_return.extend(ds) + + elif descriptor == "derates": + logger.info("\nProcessing IMAP-Lo L1B DE Rates...") + ds = calculate_de_rates(sci_dependencies, anc_dependencies, attr_mgr_l1b) + datasets_to_return.append(ds) + + elif descriptor == "prostar": + logger.info("\nProcessing IMAP-Lo L1B Star Sensor Profile...") + ds = l1b_star(sci_dependencies, attr_mgr_l1b) + datasets_to_return.append(ds) + + elif descriptor == "goodtimes": + logger.info("\nProcessing IMAP-Lo L1B Background Rates and Goodtimes...") + ds = l1b_bgrates_and_goodtimes(sci_dependencies, anc_dependencies, attr_mgr_l1b) + datasets_to_return.extend(ds) + + else: + logger.warning(f"Unexpected descriptor: {descriptor!r}") + + return datasets_to_return + + +def l1b_de( + sci_dependencies: dict, + anc_dependencies: list, + attr_mgr_l1b: ImapCdfAttributes, + attr_mgr_l1a: ImapCdfAttributes, +) -> xr.Dataset: + """ + Create the IMAP-Lo L1B Direct Events dataset. + + Parameters + ---------- + sci_dependencies : dict + Dictionary of datasets needed for L1B data product creation in xarray Datasets. + anc_dependencies : list + List of ancillary file paths needed for L1B data product creation. + attr_mgr_l1b : ImapCdfAttributes + Attribute manager used to get the global attributes. + attr_mgr_l1a : ImapCdfAttributes + Attribute manager used to get the variable attributes. + + Returns + ------- + l1b_de : xr.Dataset + The IMAP-Lo L1B Direct Events dataset. + """ + logical_source = "imap_lo_l1b_de" + # get the dependency dataset for l1b direct events + l1a_de = sci_dependencies["imap_lo_l1a_de"] + spin_data = sci_dependencies["imap_lo_l1a_spin"] + l1b_nhk = sci_dependencies["imap_lo_l1b_nhk"] + + # Initialize the L1B DE dataset + l1b_de = initialize_l1b_de(l1a_de, attr_mgr_l1b, logical_source) + # Get the pivot angle from the housekeeping dataset + pivot_angle = get_pivot_angle_from_nhk(l1b_nhk) + l1b_de["pivot_angle"] = xr.DataArray([pivot_angle], dims=["pivot_angle"]) + + pointing_start_met, pointing_end_met = get_pointing_times( + l1a_de["met"].values[0].item() + ) + + # Get the average spin durations for each epoch + avg_spin_durations_per_cycle = get_avg_spin_durations_per_cycle(spin_data) + # set the spin cycle for each direct event + l1b_de = set_spin_cycle(pointing_start_met, l1a_de, l1b_de) + + # get the absolute met for each event + l1b_de = set_event_met(l1a_de, l1b_de) + # set the epoch for each event + l1b_de = set_each_event_epoch(l1b_de) + # Set the ESA mode for each direct event + l1b_de = set_esa_mode( + pointing_start_met, pointing_end_met, anc_dependencies, l1b_de + ) + # Set the average spin duration for each direct event + l1b_de = set_avg_spin_durations_per_event( + l1a_de, l1b_de, avg_spin_durations_per_cycle + ) + # calculate the TOF1 for golden triples + # store in the l1a dataset to use in l1b calculations + l1a_de = calculate_tof1_for_golden_triples(l1a_de) + # set the coincidence type string for each direct event + l1b_de = set_coincidence_type(l1a_de, l1b_de, attr_mgr_l1a) + # convert the TOFs to engineering units + l1b_de = convert_tofs_to_eu(l1a_de, l1b_de, attr_mgr_l1a, attr_mgr_l1b) + # set the species for each direct event + l1b_de = identify_species(l1b_de) + # set the pointing direction for each direct event + l1b_de = set_pointing_direction(l1b_de) + # calculate and set the pointing bin based on the spin phase + # pointing bin is 3600 x 40 bins + l1b_de = set_pointing_bin(l1b_de) + return l1b_de + + +def l1b_allrates( + sci_dependencies: dict, anc_dependencies: list, attr_mgr_l1b: ImapCdfAttributes +) -> xr.Dataset: + """ + Create the IMAP-Lo L1B Histogram Rates dataset. + + Parameters + ---------- + sci_dependencies : dict + Dictionary of datasets needed for L1B data product creation in xarray Datasets. + anc_dependencies : list + List of ancillary file paths needed for L1B data product creation. + attr_mgr_l1b : ImapCdfAttributes + Attribute manager used to get the global attributes. + + Returns + ------- + [xr.Dataset, xr.Dataset] + The IMAP-Lo L1B Histogram and Monitor Rates datasets. + """ + datasets_to_return = [] + # get the dependency dataset for l1b histogram rates + l1a_hist = sci_dependencies["imap_lo_l1a_histogram"] + spin_data = sci_dependencies["imap_lo_l1a_spin"] + # initialize the L1B Histogram Rates dataset from the L1A Histogram Rates + # This carries over the epoch and count fields from L1A + l1b_all_rates = initialize_all_rates(l1a_hist, attr_mgr_l1b) + # set spin cycle and remove invalid spin ASCs + l1b_all_rates = set_spin_cycle_from_spin_data(l1a_hist, l1b_all_rates, spin_data) + + pointing_start_met, pointing_end_met = get_pointing_times( + ttj2000ns_to_met(l1a_hist["epoch"].values[0].item()) + ) + l1b_all_rates = set_esa_mode( + pointing_start_met, pointing_end_met, anc_dependencies, l1b_all_rates + ) + # resweep the histogram data + l1b_all_rates, exposure_factor = resweep_histogram_data( + l1b_all_rates, anc_dependencies + ) + # Get the start and end times for each spin epoch + acq_start, acq_end = convert_start_end_acq_times(spin_data) + # Get the average spin durations for each epoch + avg_spin_durations_per_cycle = get_avg_spin_durations_per_cycle(spin_data) + l1b_all_rates = calculate_histogram_rates( + l1b_all_rates, + acq_start, + acq_end, + avg_spin_durations_per_cycle, + exposure_factor, + ) + + l1b_hist_rates, l1b_monitor_rates = split_rate_dataset(l1b_all_rates, attr_mgr_l1b) + datasets_to_return.extend([l1b_hist_rates, l1b_monitor_rates]) + + return datasets_to_return def initialize_l1b_de( @@ -133,7 +417,7 @@ def initialize_l1b_de( # TODO: Add pos to YAML file # attrs=attr_mgr.get_variable_attributes("pos"), ) - l1b_de["mode"] = xr.DataArray( + l1b_de["mode_bit"] = xr.DataArray( l1a_de["mode"].values, dims=["epoch"], # TODO: Add mode to YAML file @@ -151,10 +435,75 @@ def initialize_l1b_de( # TODO: Add esa_step to YAML file # attrs=attr_mgr.get_variable_attributes("esa_step"), ) + l1b_de["shcoarse"] = xr.DataArray( + np.repeat(l1a_de["met"].values, l1a_de["de_count"].values), + dims=["epoch"], + # TODO: Add shcoarse to YAML file + # attrs=attr_mgr.get_variable_attributes("shcoarse"), + ) return l1b_de +def set_esa_mode( + pointing_start_met: float, + pointing_end_met: float, + anc_dependencies: list, + l1b_science: xr.Dataset, +) -> xr.Dataset: + """ + Set the ESA mode for each direct event or histogram. + + The ESA mode is determined from the sweep table for the time period of the pointing. + + Parameters + ---------- + pointing_start_met : float + Start time for the pointing in MET seconds. + pointing_end_met : float + End time for the pointing in MET seconds. + anc_dependencies : list + List of ancillary file paths. + l1b_science : xarray.Dataset + The L1B science dataset. + + Returns + ------- + l1b_science : xr.Dataset + The L1B science dataset with the ESA mode added. + """ + # Read the sweep table from the ancillary files + sweep_df = lo_ancillary.read_ancillary_file( + next(str(s) for s in anc_dependencies if "sweep-table" in str(s)) + ) + + # Get the sweep table rows that correspond to the time period of the pointing + pointing_sweep_df = sweep_df[ + (sweep_df["GoodTime_start"] >= pointing_start_met) + & (sweep_df["GoodTime_end"] <= pointing_end_met) + ] + + # Check that there is only one ESA mode in the sweep table for the pointing + if len(pointing_sweep_df["ESA_Mode"].unique()) == 1: + # Update the ESA mode strings to be 0 for HiRes and 1 for HiThr + sweep_df["esa_mode"] = sweep_df["ESA_Mode"].map({"HiRes": 0, "HiThr": 1}) + # Get the ESA mode for the pointing + esa_mode = sweep_df["esa_mode"].values[0] + # Repeat the ESA mode for each direct event in the pointing + esa_mode_array: np.ndarray = np.repeat(esa_mode, len(l1b_science["epoch"])) + else: + raise ValueError("Multiple ESA modes found in sweep table for pointing.") + + l1b_science["esa_mode"] = xr.DataArray( + esa_mode_array, + dims=["epoch"], + # TODO: Add esa_mode to YAML file + # attrs=attr_mgr.get_variable_attributes("esa_mode"), + ) + + return l1b_science + + def convert_start_end_acq_times( spin_data: xr.Dataset, ) -> tuple[xr.DataArray, xr.DataArray]: @@ -181,78 +530,33 @@ def convert_start_end_acq_times( def get_avg_spin_durations_per_cycle( - acq_start: xr.DataArray, acq_end: xr.DataArray + spin_data: xr.Dataset, ) -> xr.DataArray: """ - Get the average spin duration for each spin epoch. + Get the average spin duration for each aggregated science cycle. Parameters ---------- - acq_start : xarray.DataArray - The start acquisition times for each spin epoch. - acq_end : xarray.DataArray - The end acquisition times for each spin epoch. + spin_data : xarray.Dataset + The L1A Spin dataset. Returns ------- avg_spin_durations : xarray.DataArray - The average spin duration for each spin epoch. + The average spin duration for each ASC. """ + acq_start = spin_data["acq_start_sec"] + spin_data["acq_start_subsec"] * 1e-6 + acq_end = spin_data["acq_end_sec"] + spin_data["acq_end_subsec"] * 1e-6 # Get the avg spin duration for each spin epoch - # There are 28 spins per epoch (1 aggregated science cycle) - avg_spin_durations_per_cycle = (acq_end - acq_start) / 28 + # We need to use the number of spins that were actually in the ASC + # because there may be partial ASCs where only some of the spins were completed + avg_spin_durations_per_cycle = (acq_end - acq_start) / spin_data["num_completed"] return avg_spin_durations_per_cycle -def get_spin_angle(l1a_de: xr.Dataset) -> np.ndarray[np.float64] | Any: - """ - Get the spin angle (0 - 360 degrees) for each DE. - - Parameters - ---------- - l1a_de : xarray.Dataset - The L1A DE dataset. - - Returns - ------- - spin_angle : np.ndarray - The spin angle for each DE. - """ - de_times = l1a_de["de_time"].values - # DE Time is 12 bit DN. The max possible value is 4096 - spin_angle = np.array(de_times / 4096 * 360, dtype=np.float64) - return spin_angle - - -def set_spin_bin(l1b_de: xr.Dataset, spin_angle: np.ndarray) -> xr.Dataset: - """ - Set the spin bin (0 - 60 bins) for each Direct Event where each bin is 6 degrees. - - Parameters - ---------- - l1b_de : xarray.Dataset - The L1B Direct Event dataset. - spin_angle : np.ndarray - The spin angle (0-360 degrees) for each Direct Event. - - Returns - ------- - l1b_de : xarray.Dataset - The L1B DE dataset with the spin bin added. - """ - # Get the spin bin for each DE - # Spin bins are 0 - 60 where each bin is 6 degrees - spin_bin = (spin_angle // 6).astype(int) - l1b_de["spin_bin"] = xr.DataArray( - spin_bin, - dims=["epoch"], - # TODO: Add spin angle to YAML file - # attrs=attr_mgr.get_variable_attributes("spin_bin"), - ) - return l1b_de - - -def set_spin_cycle(l1a_de: xr.Dataset, l1b_de: xr.Dataset) -> xr.Dataset: +def set_spin_cycle( + pointing_start_met: float, l1a_de: xr.Dataset, l1b_de: xr.Dataset +) -> xr.Dataset: """ Set the spin cycle for each direct event. @@ -265,6 +569,8 @@ def set_spin_cycle(l1a_de: xr.Dataset, l1b_de: xr.Dataset) -> xr.Dataset: Parameters ---------- + pointing_start_met : float + The start time of the pointing in MET seconds. l1a_de : xarray.Dataset The L1A DE dataset. l1b_de : xarray.Dataset @@ -275,19 +581,18 @@ def set_spin_cycle(l1a_de: xr.Dataset, l1b_de: xr.Dataset) -> xr.Dataset: l1b_de : xarray.Dataset The L1B DE dataset with the spin cycle added for each direct event. """ + spin_start_num = get_spin_number(pointing_start_met) counts = l1a_de["de_count"].values # split the esa_steps into ASC groups de_asc_groups = np.split(l1a_de["esa_step"].values, np.cumsum(counts)[:-1]) spin_cycle = [] - for i, esa_asc_group in enumerate(de_asc_groups): - # TODO: Spin Number does not reset for each pointing. Need to figure out - # how to retain this information across days - # increment the spin_start by 28 after each aggregated science cycle - spin_start = i * 28 + for esa_asc_group in de_asc_groups: # calculate the spin cycle for each DE in the ASC group # TODO: Add equation number in algorithm document when new version is - # available. Add to docstring as well - spin_cycle.extend(spin_start + 7 + (esa_asc_group - 1) * 2) + # available. Add to docstring as well + spin_cycle.extend(spin_start_num + 7 + (esa_asc_group - 1) * 2) + # increment the spin start number by 28 for the next ASC + spin_start_num += 28 l1b_de["spin_cycle"] = xr.DataArray( spin_cycle, @@ -299,8 +604,194 @@ def set_spin_cycle(l1a_de: xr.Dataset, l1b_de: xr.Dataset) -> xr.Dataset: return l1b_de +# TODO: The spin cycle function above needs to be updated for DEs. We cannot assume +# there are 28 spins per ASC and we should calculate the spin start number based on the +# corresponding L1A spin data Acq Start for the ASC. The implementation below should be +# should be used for the DE rather than the above function, but in the interest of time +# the below function is only hooked up to the histogram rates processing and should be +# integrated into the DE processing in a later PR. +# TODO: Break up the invalid spin ASC removal and the code to find the closest DE/Hist +# and spin ASCs into their own functions. +def set_spin_cycle_from_spin_data( + l1a_science: xr.Dataset, l1b_science: xr.Dataset, spin_data: xr.Dataset +) -> xr.Dataset: + """ + Set the spin cycle for each direct event using the L1A spin data. + + The spin cycle is the average spin for a given Aggregated Science Cycle + in a given ESA Step. + + Parameters + ---------- + l1a_science : xr.Dataset + The L1A Histogram or Direct Event dataset. + l1b_science : xr.Dataset + The L1B Histogram Rate or Direct Event dataset. + spin_data : xr.Dataset + The L1A Spin dataset. + + Returns + ------- + l1b_science : xr.Dataset + The L1B science dataset with the spin cycle added for each direct event. + """ + acq_start, _acq_end = convert_start_end_acq_times(spin_data) + + spin_met_per_asc = spin_data["shcoarse"].values.astype(np.float64) + science_met_per_asc = ttj2000ns_to_met(l1a_science["epoch"]).astype(np.float64) + + science_to_spin_indices = match_science_to_spin_asc( + science_met_per_asc, spin_met_per_asc + ) + + # Add a flag for invalid ASCs + valid_mask = find_valid_asc(science_to_spin_indices, spin_data) + l1b_science["incomplete_asc"] = xr.DataArray(~valid_mask, dims=["epoch"]) + + # Use the closest indices to get the corresponding acq_start rows + closest_start_acq_per_asc = acq_start.isel(epoch=science_to_spin_indices) + + # compute spin start number for each remaining ASC + spin_start_num_per_asc = np.atleast_1d(get_spin_number(closest_start_acq_per_asc)) + spin_start_num_per_asc = spin_start_num_per_asc[:, None] # (n_valid, 1) + + logical_src = l1a_science.attrs.get("Logical_source", "") + if logical_src == "imap_lo_l1a_de": + # For DE: expand per-event across ESA steps within each (valid) ASC + counts = l1a_science["de_count"].values + spin_cycle = [] + for asc_idx, _count in enumerate(counts): + esa_steps = l1a_science["esa_step"].values[ + sum(counts[:asc_idx]) : sum(counts[: asc_idx + 1]) + ] + spin_cycle.extend( + spin_start_num_per_asc[asc_idx, 0] + 7 + (esa_steps - 1) * 2 + ) + spin_cycle = np.array(spin_cycle) + l1b_science["spin_cycle"] = xr.DataArray(spin_cycle, dims=["epoch"]) + elif logical_src == "imap_lo_l1a_histogram": + # For histogram: keep 2D array (n_valid_epochs, esa_step) + esa_steps = l1b_science["esa_step"].values # shape: (7,) + spin_cycle = spin_start_num_per_asc + 7 + (esa_steps - 1) * 2 + l1b_science["spin_cycle"] = xr.DataArray(spin_cycle, dims=["epoch", "esa_step"]) + else: + raise ValueError( + "set spin cycle called with unsupported dataset with " + "Logical_source: {logical_src}" + ) + + return l1b_science + + +def match_science_to_spin_asc( + science_met_per_asc: xr.DataArray, spin_met_per_asc: xr.DataArray +) -> np.ndarray: + """ + Compute the indices of the closest spin acquisition times for each science event. + + This function matches science data acquisition epochs to spin data acquisition + epochs by finding the closest spin acquisition indices for each science data + acquisition epoch. The result is an array where each element corresponds to the + index of the closest spin data acquisition time for a given science event. + + Parameters + ---------- + science_met_per_asc : xr.DataArray + An array of science acquisition epochs in MET seconds. + spin_met_per_asc : xr.DataArray + An array of spin acquisition epochs in MET seconds. + + Returns + ------- + science_to_spin_indices : np.ndarray + Index of closest prior spin ASC for each science ASC. + Set to -1 if no valid prior spin exists. + """ + # Find the closest spin shcoarse for each science ASC + # computes the index of the closest spin_met_per_asc for each science_met_per_asc + # so the resulting array will be of length len(science_met_per_asc), one index per + # ASC, but the value of each index will be the index of the closest spin data. + science_to_spin_indices = np.abs( + science_met_per_asc[:, None] - spin_met_per_asc + ).argmin(axis=1) + + return science_to_spin_indices + + +def find_valid_asc( + science_to_spin_indices: np.ndarray, + spin_data: xr.Dataset, +) -> np.ndarray: + """ + Find valid Aggregated Science Cycles by filtering invalid spin data. + + Parameters + ---------- + science_to_spin_indices : np.ndarray + Indices of closest spin acquisitions. + spin_data : xr.Dataset + The L1A Spin dataset. + + Returns + ------- + valid_mask : np.ndarray + Boolean mask indicating valid ASCs. + """ + # Apply each validation check independently on full arrays + valid_indices = _check_valid_indices(science_to_spin_indices) + valid_spin_count = _check_sufficient_spins(spin_data)[science_to_spin_indices] + + # Combine these two masks + valid_mask = valid_indices & valid_spin_count + + return valid_mask + + +def _check_valid_indices(science_to_spin_indices: np.ndarray) -> np.ndarray: + """ + Check that all matched spin indices are valid (non-negative). + + Parameters + ---------- + science_to_spin_indices : np.ndarray + Indices of closest spin acquisitions. + + Returns + ------- + valid_mask : np.ndarray + Boolean mask where True indicates a valid index. + """ + invalid_indices = science_to_spin_indices < 0 + if invalid_indices.any(): + logger.warning(f"Found {invalid_indices.sum()} ASCs with invalid spin indices") + return ~invalid_indices + + +def _check_sufficient_spins(spin_data: xr.Dataset) -> np.ndarray: + """ + Check that matched spin cycles have sufficient spins (28 completed). + + Parameters + ---------- + spin_data : xr.Dataset + The L1A Spin dataset containing num_completed field. + + Returns + ------- + valid_mask : np.ndarray + Boolean mask where True indicates sufficient spins. + """ + # Check if corresponding spin cycle has 28 spins + valid_mask = spin_data["num_completed"].values == 28 + + if (~valid_mask).any(): + logger.warning(f"Found {(~valid_mask).sum()} ASCs with fewer than 28 spins") + + return valid_mask + + def get_spin_start_times( - l1a_de: xr.Dataset, l1b_de: xr.Dataset, spin_data: xr.Dataset, acq_end: xr.DataArray + l1a_de: xr.Dataset, ) -> xr.DataArray: """ Get the start time for the spin that each direct event is in. @@ -313,54 +804,32 @@ def get_spin_start_times( ---------- l1a_de : xr.Dataset The L1A DE dataset. - l1b_de : xr.Dataset - The L1B DE dataset. - spin_data : xr.Dataset - The L1A Spin dataset. - acq_end : xr.DataArray - The end acquisition times for each spin ASC. Returns ------- - spin_start_time : xr.DataArray + spin_start_time : np.ndarray The start time for the spin that each direct event is in. """ - met = l1a_de["met"].values - # Find the closest stop_acq for each shcoarse - closest_stop_acq_indices = np.abs(met[:, None] - acq_end.values).argmin(axis=1) - # There are 28 spins per epoch (1 aggregated science cycle) - # Set the spin_cycle_num to the spin number relative to the - # start of the ASC - spin_cycle_num = l1b_de["spin_cycle"] % 28 - # Get the seconds portion of the start time for each spin - start_sec_spins = spin_data["start_sec_spin"].values[ - closest_stop_acq_indices, spin_cycle_num - ] - # Get the subseconds portion of the spin start time and convert from - # microseconds to seconds - start_subsec_spins = ( - spin_data["start_subsec_spin"].values[closest_stop_acq_indices, spin_cycle_num] - * 1e-6 - ) + # Get the actual spin start times from the spin data + # Use the individual spin start times rather than calculating from ASC averages + spin_start_times = interpolate_spin_data(l1a_de["met"].values)[ + "spin_start_met" + ].values + spin_start_times = np.repeat(spin_start_times, l1a_de["de_count"].values) - # Combine the seconds and subseconds to get the start time for each spin - spin_start_time = start_sec_spins + start_subsec_spins - return xr.DataArray(spin_start_time) + return spin_start_times def set_event_met( l1a_de: xr.Dataset, l1b_de: xr.Dataset, - spin_start_time: xr.DataArray, - avg_spin_durations: xr.DataArray, ) -> xr.Dataset: """ Get the event MET for each direct event. Each direct event is converted from a data number to engineering unit in seconds. - de_eu_time de_dn_time / 4096 * avg_spin_duration - where de_time is the direct event time Data Number (DN) and avg_spin_duration - is the average spin duration for the ASC that the event was measured in. + time_from_start_of_spin = de_time * DE_CLOCK_TICK_S + where de_time is the direct event time Data Number (DN). The direct event time is the time of direct event relative to the start of the spin. The event MET is the sum of the start time of the spin and the @@ -372,26 +841,18 @@ def set_event_met( The L1A DE dataset. l1b_de : xr.Dataset The L1B DE dataset. - spin_start_time : np.ndarray - The start time for the spin that each direct event is in. - avg_spin_durations : xr.DataArray - The average spin duration for each epoch. Returns ------- l1b_de : xr.Dataset The L1B DE dataset with the event MET. """ - counts = l1a_de["de_count"].values - de_time_asc_groups = np.split(l1a_de["de_time"].values, np.cumsum(counts)[:-1]) - de_times_eu = [] - for i, de_time_asc in enumerate(de_time_asc_groups): - # DE Time is 12 bit DN. The max possible value is 4095 - # divide by 4096 to get fraction of a spin duration - de_times_eu.extend(de_time_asc / 4096 * avg_spin_durations[i].values) + # get spin start times for each event + spin_start_times = get_spin_start_times(l1a_de) + # spin start + offset based on de_time ticks l1b_de["event_met"] = xr.DataArray( - spin_start_time + de_times_eu, + spin_start_times + l1a_de["de_time"].values * DE_CLOCK_TICK_S, dims=["epoch"], # attrs=attr_mgr.get_variable_attributes("epoch") ) @@ -478,7 +939,8 @@ def calculate_tof1_for_golden_triples(l1a_de: xr.Dataset) -> xr.Dataset: The L1A DE dataset with the TOF1 calculated for golden triples. """ for idx, coin_type in enumerate(l1a_de["coincidence_type"].values): - if coin_type == 0 and l1a_de["mode"][idx] == 0: + # NOTE: mode bit of 1 is used to identify golden triple (event was compressed) + if coin_type == 0 and l1a_de["mode"][idx] == 1: # Calculate TOF1 # TOF1 equation requires values to be right bit shifted. These values were # originally right bit shifted when packed in the telemetry packet, but were @@ -660,34 +1122,6 @@ def identify_species(l1b_de: xr.Dataset) -> xr.Dataset: return l1b_de -def set_bad_times(l1b_de: xr.Dataset) -> xr.Dataset: - """ - Set the bad times for each direct event. - - Parameters - ---------- - l1b_de : xarray.Dataset - The L1B DE dataset. - - Returns - ------- - l1b_de : xarray.Dataset - The L1B DE dataset with the bad times added. - """ - # Initialize all times as not bad for now - # TODO: Update to set badtimes based on criteria that - # will be defined in the algorithm document - # 1 = badtime, 0 = not badtime - l1b_de["badtimes"] = xr.DataArray( - np.zeros(len(l1b_de["epoch"]), dtype=int), - dims=["epoch"], - # TODO: Add to yaml - # attrs=attr_mgr.get_variable_attributes("bad_times"), - ) - - return l1b_de - - def set_pointing_direction(l1b_de: xr.Dataset) -> xr.Dataset: """ Set the pointing direction for each direct event. @@ -708,22 +1142,32 @@ def set_pointing_direction(l1b_de: xr.Dataset) -> xr.Dataset: """ # Get the pointing bin for each DE et = ttj2000ns_to_et(l1b_de["epoch"]) + # get the direction in HAE coordinates + direction = lo_instrument_pointing( + et, l1b_de["pivot_angle"].values[0], SpiceFrame.IMAP_HAE, cartesian=True + ) - direction = instrument_pointing(et, SpiceFrame.IMAP_LO_BASE, SpiceFrame.IMAP_DPS) # TODO: Need to ask Lo what to do if a latitude is outside of the # +/-2 degree range. Is that possible? - l1b_de["direction_lon"] = xr.DataArray( + l1b_de["hae_x"] = xr.DataArray( direction[:, 0], dims=["epoch"], # TODO: Add direction_lon to YAML file - # attrs=attr_mgr.get_variable_attributes("direction_lon"), + # attrs=attr_mgr.get_variable_attributes("hae_x"), ) - l1b_de["direction_lat"] = xr.DataArray( + l1b_de["hae_y"] = xr.DataArray( direction[:, 1], dims=["epoch"], # TODO: Add direction_lat to YAML file - # attrs=attr_mgr.get_variable_attributes("direction_lat"), + # attrs=attr_mgr.get_variable_attributes("hae_y"), + ) + + l1b_de["hae_z"] = xr.DataArray( + direction[:, 2], + dims=["epoch"], + # TODO: Add direction_lat to YAML file + # attrs=attr_mgr.get_variable_attributes("hae_z"), ) return l1b_de @@ -733,7 +1177,7 @@ def set_pointing_bin(l1b_de: xr.Dataset) -> xr.Dataset: """ Set the pointing bin for each direct event. - The pointing bins are defined as 3600 bins for longitude and 40 bins for latitude. + The pointing bins are defined as 3600 bins for spin and 40 bins for off angle. Each bin is 0.1 degrees. The bins are defined as follows: Longitude bins: -180 to 180 degrees Latitude bins: -2 to 2 degrees @@ -748,14 +1192,38 @@ def set_pointing_bin(l1b_de: xr.Dataset) -> xr.Dataset: l1b_de : xarray.Dataset The L1B DE dataset with the pointing bins added. """ - # First column: latitudes - lats = l1b_de["direction_lat"] - # Second column: longitudes - lons = l1b_de["direction_lon"] + x = l1b_de["hae_x"] + y = l1b_de["hae_y"] + z = l1b_de["hae_z"] + # Convert from HAE to DPS coordinates + dps_xyz = frame_transform( + ttj2000ns_to_et(l1b_de["epoch"]), + np.column_stack((x, y, z)), + SpiceFrame.IMAP_HAE, + SpiceFrame.IMAP_DPS, + allow_spice_noframeconnect=True, + ) + # convert the pointing direction to latitudinal coordinates + direction = cartesian_to_latitudinal(dps_xyz) + # first column: radius (Not needed) + # second column: longitude + lons = direction[:, 1] + # shift to 0-360 range (spin-phase 0 should be in bin 0) + lons = (lons + 360) % 360 + # third column: latitude + lats = direction[:, 2] + # we want this relative to the pivot angle + # i.e. the off_angle is +/- 2 degrees from the pivot angle + lats = lats - (90 - l1b_de["pivot_angle"].values[0]) + if np.any(lats < -2) or np.any(lats > 2): + logger.warning( + "Some latitude values are outside of the +/-2 degree range " + f"for off-angle binning. Range: ({np.min(lats)}, {np.max(lats)})" + ) # Define bin edges # 3600 bins, 0.1Β° each - lon_bins = np.linspace(-180, 180, 3601) + lon_bins = np.linspace(0, 360, 3601) # 40 bins, 0.1Β° each lat_bins = np.linspace(-2, 2, 41) @@ -764,18 +1232,18 @@ def set_pointing_bin(l1b_de: xr.Dataset) -> xr.Dataset: lon_bins = np.digitize(lons, lon_bins) - 1 lat_bins = np.digitize(lats, lat_bins) - 1 - l1b_de["pointing_bin_lon"] = xr.DataArray( + l1b_de["spin_bin"] = xr.DataArray( lon_bins, dims=["epoch"], # TODO: Add pointing_bin_lon to YAML file - # attrs=attr_mgr.get_variable_attributes("pointing_bin_lon"), + # attrs=attr_mgr.get_variable_attributes("spin_bin"), ) - l1b_de["pointing_bin_lat"] = xr.DataArray( + l1b_de["off_angle_bin"] = xr.DataArray( lat_bins, dims=["epoch"], # TODO: Add point_bin_lat to YAML file - # attrs=attr_mgr.get_variable_attributes("pointing_bin_lat"), + # attrs=attr_mgr.get_variable_attributes("spin_bin"), ) return l1b_de @@ -817,7 +1285,7 @@ def create_datasets( data=epoch_converted_time, name="epoch", dims=["epoch"], - attrs=attr_mgr.get_variable_attributes("epoch"), + attrs=attr_mgr.get_variable_attributes("epoch", check_schema=False), ) if logical_source == "imap_lo_l1b_de": @@ -880,3 +1348,1447 @@ def create_datasets( ) return dataset + + +def create_badtimes_dataset() -> xr.Dataset: + """ + Create a badtimes dataset using the spin products. + + Returns + ------- + dataset : xarray.Dataset + Dataset with all badtimes data product fields in xr.DataArray. + """ + logger.info("Creating badtimes dataset") + try: + spin_df = get_spin_data() + except ValueError: + logger.warning("No spin data found. Skipping badtimes dataset creation.") + # Return an empty dataset with the expected badtimes fields (zero-length) + empty_epoch = xr.DataArray( + data=np.array([], dtype=np.int64), name="epoch", dims=["epoch"] + ) + empty_ds = xr.Dataset(coords={"epoch": empty_epoch}) + + empty_ds["yyyymmdd"] = xr.DataArray( + data=np.array([], dtype=np.int32), dims=["epoch"] + ) + empty_ds["BadTime_start"] = xr.DataArray( + data=np.array([], dtype=np.int64), dims=["epoch"] + ) + empty_ds["BadTime_end"] = xr.DataArray( + data=np.array([], dtype=np.int64), dims=["epoch"] + ) + empty_ds["bin_start"] = xr.DataArray( + data=np.array([], dtype=np.uint8), dims=["epoch"] + ) + empty_ds["bin_end"] = xr.DataArray( + data=np.array([], dtype=np.uint8), dims=["epoch"] + ) + + empty_ds["esa_step"] = xr.DataArray( + data=np.arange(1, 8, dtype=np.uint8), + name="esa_step", + dims=["esa_step"], + ) + empty_ds["badtime_flag"] = xr.DataArray( + data=np.empty((0, len(empty_ds["esa_step"])), dtype=np.uint8), + dims=["epoch", "esa_step"], + ) + + empty_ds["Comment"] = xr.DataArray( + data=np.array([], dtype=object), dims=["epoch"] + ) + + return empty_ds + + # All spins with thruster firings are bad times + thruster_data = spin_df[spin_df["thruster_firing"]] + logger.info("Number of thruster firings found: %d", len(thruster_data)) + thruster_ds = xr.Dataset( + coords={ + "epoch": xr.DataArray( + data=met_to_ttj2000ns(thruster_data["spin_start_met"]), + name="epoch", + dims=["epoch"], + ) + }, + ) + thruster_ds["yyyymmdd"] = xr.DataArray( + data=thruster_data["spin_start_utc"] + .str.replace("-", "") + .str.slice(0, 8) + .values.astype(int), + dims=["epoch"], + ) + thruster_ds["BadTime_start"] = xr.DataArray( + data=thruster_data["spin_start_sec_sclk"].values, + dims=["epoch"], + ) + thruster_ds["BadTime_end"] = thruster_ds["BadTime_start"] + thruster_data[ + "spin_period_sec" + ].values.astype(int) + thruster_ds["bin_start"] = xr.DataArray( + data=np.zeros(len(thruster_ds["epoch"]), dtype=np.uint8), + dims=["epoch"], + ) + thruster_ds["bin_end"] = xr.DataArray( + data=np.full(len(thruster_ds["epoch"]), 59, dtype=np.uint8), + dims=["epoch"], + ) + thruster_ds["esa_step"] = xr.DataArray( + data=np.arange(1, 8, dtype=np.uint8), + name="esa_step", + dims=["esa_step"], + ) + thruster_ds["badtime_flag"] = xr.DataArray( + data=np.ones( + (len(thruster_ds["epoch"]), len(thruster_ds["esa_step"])), dtype=np.uint8 + ), + dims=["epoch", "esa_step"], + ) + thruster_ds["Comment"] = xr.DataArray( + data=np.full(len(thruster_ds["epoch"]), "Thruster Firing", dtype=object), + dims=["epoch"], + ) + + # TODO: Merge with other datasets if/when those are created + return thruster_ds + + +def initialize_all_rates( + l1a_hist: xr.Dataset, attr_mgr_l1b: ImapCdfAttributes +) -> xr.Dataset: + """ + Initialize the L1B histogram rates dataset. + + Parameters + ---------- + l1a_hist : xr.Dataset + The L1A histogram rates dataset. + attr_mgr_l1b : ImapCdfAttributes + Attribute manager used to get the L1B histogram rates dataset attributes. + + Returns + ------- + l1b_all_rates : xr.Dataset + The initialized L1B histogram and monitor rates dataset. + """ + l1b_all_rates = xr.Dataset( + coords={ + "epoch": xr.DataArray(l1a_hist["epoch"].values, dims=["epoch"]), + "esa_step": l1a_hist["esa_step"], + "spin_bin_6": xr.DataArray( + l1a_hist["azimuth_6"].values, + dims=["spin_bin_6"], + ), + "spin_bin_60": xr.DataArray( + l1a_hist["azimuth_60"].values, + dims=["spin_bin_60"], + ), + }, + ) + # Use centralized mappings for field definitions + for l1a_field, l1b_field in SPIN_BIN_6_L1A_TO_L1B.items(): + l1b_all_rates[l1b_field] = xr.DataArray( + l1a_hist[l1a_field].values, + dims=["epoch", "esa_step", "spin_bin_6"], + ) + + for l1a_field, l1b_field in SPIN_BIN_60_L1A_TO_L1B.items(): + l1b_all_rates[l1b_field] = xr.DataArray( + l1a_hist[l1a_field].values, + dims=["epoch", "esa_step", "spin_bin_60"], + ) + + return l1b_all_rates + + +def resweep_histogram_data( + l1b_histrates: xr.Dataset, + anc_dependencies: list, +) -> tuple[xr.Dataset, dict[str, np.ndarray]]: + """ + Correct energy steps in histogram data based on sweep and LUT tables. + + Returns the updated dataset and a 3D array of reswept counts + (epoch, azimuth, esa_step) indicating how many original steps were reswept into + each final step. + + Parameters + ---------- + l1b_histrates : xr.Dataset + The L1B histogram rates dataset. + anc_dependencies : list + List of ancillary file paths. + + Returns + ------- + l1b_histrates : xr.Dataset + The updated L1B histogram rates dataset with reswept counts. + exposure_factor : dict[str, np.ndarray] + Dictionary mapping bin types to their 3D exposure factor arrays + (epoch, esa_step, azimuth) indicating how many ESA steps were + reswept during resweeping. + """ + epochs = l1b_histrates["epoch"].values + energy_mapping = _get_esa_level_indices(epochs, anc_dependencies=anc_dependencies) + + # initialize the reswept counts arrays + for field in SPIN_BIN_6_FIELDS + SPIN_BIN_60_FIELDS: + reswept = np.zeros_like(l1b_histrates[field].values) + # Place potentially multiple esa_steps into the same energy level bin + np.add.at( + reswept, + (slice(None), energy_mapping, slice(None)), + l1b_histrates[field].values, + ) + l1b_histrates[field].values = reswept + + # Calculate exposure factors for each bin type + exposure_factor_6deg = np.zeros_like(l1b_histrates["h_counts"].values, dtype=int) + exposure_factor_60deg = np.zeros_like( + l1b_histrates["start_a_counts"].values, dtype=int + ) + # We have N_SPINS_PER_ESA_LEVEL spins per ESA step in an ASC, so we need to place + # N_SPINS_PER_ESA_LEVEL spins into each bin as our multiplication factor + np.add.at( + exposure_factor_6deg, + (slice(None), energy_mapping, slice(None)), + c.N_SPINS_PER_ESA_LEVEL, + ) + np.add.at( + exposure_factor_60deg, + (slice(None), energy_mapping, slice(None)), + c.N_SPINS_PER_ESA_LEVEL, + ) + + # Create a dictionary to hold exposure factors for both bin types + exposure_factors = {} + exposure_factors["6deg"] = exposure_factor_6deg + exposure_factors["60deg"] = exposure_factor_60deg + + return l1b_histrates, exposure_factors + + +def calculate_histogram_rates( + l1b_histrates: xr.Dataset, + acq_start: xr.DataArray, + acq_end: xr.DataArray, + avg_spin_durations_per_cycle: xr.DataArray, + exposure_factors: dict[str, np.ndarray], +) -> xr.Dataset: + """ + Calculate histogram rates by dividing reswept counts by exposure time. + + For each epoch in l1b_histrates, this function finds the corresponding + spin interval, calculates the exposure time for each bin type, + and divides the counts by the exposure time. The exposure time is scaled + by the number of ESA steps that were reswept during resweeping. + + Parameters + ---------- + l1b_histrates : xr.Dataset + The L1B histogram rates dataset containing reswept counts. + acq_start : xr.DataArray + Start times for each spin cycle in MET seconds. + acq_end : xr.DataArray + End times for each spin cycle in MET seconds. + avg_spin_durations_per_cycle : xr.DataArray + Average spin duration for each cycle in seconds. + exposure_factors : dict[str, np.ndarray] + Dictionary mapping bin types to their 3D exposure factor arrays + (epoch, esa_step, azimuth) indicating how many ESA steps were + reswept during resweeping. + + Returns + ------- + l1b_histrates : xr.Dataset + The L1B histogram rates dataset with rates calculated. + """ + epochs_ttj2000 = l1b_histrates["epoch"].values + epochs_met = ttj2000ns_to_met(epochs_ttj2000) + + # Match each histogram epoch to its corresponding spin cycle + closest_spin_idx = np.abs(epochs_met[:, None] - acq_start.values).argmin(axis=1) + + # Get spin durations for each epoch + spin_durations = avg_spin_durations_per_cycle.values[closest_spin_idx] + + # Calculate exposure time for 6-degree bins (60 bins per spin) + exposure_time_6deg = spin_durations / 60 + # Calculate effective exposure time with broadcasting + effective_exposure_6deg = ( + exposure_time_6deg[:, None, None] * exposure_factors["6deg"] + ) + + # Calculate exposure time for 60-degree bins (6 bins per spin) + exposure_time_60deg = spin_durations / 6 + effective_exposure_60deg = ( + exposure_time_60deg[:, None, None] * exposure_factors["60deg"] + ) + + # Process all fields + # Process 6-degree bin fields + for count_field, rate_field in SPIN_BIN_6_COUNT_TO_RATE.items(): + counts = l1b_histrates[count_field].values # (epoch, esa_step, spin_bin_6) + + # Avoid division by zero + with np.errstate(divide="ignore", invalid="ignore"): + rates = np.where( + effective_exposure_6deg > 0, counts / effective_exposure_6deg, 0 + ) + + l1b_histrates[rate_field] = xr.DataArray( + rates, + dims=l1b_histrates[count_field].dims, + ) + + l1b_histrates["exposure_time_6deg"] = xr.DataArray( + effective_exposure_6deg, + dims=["epoch", "esa_step", "spin_bin_6"], + ) + + # Process 60-degree bin fields + for count_field, rate_field in SPIN_BIN_60_COUNT_TO_RATE.items(): + counts = l1b_histrates[count_field].values # (epoch, esa_step, spin_bin_60) + + # Avoid division by zero + with np.errstate(divide="ignore", invalid="ignore"): + rates = np.where( + effective_exposure_60deg > 0, counts / effective_exposure_60deg, 0 + ) + + l1b_histrates[rate_field] = xr.DataArray( + rates, + dims=l1b_histrates[count_field].dims, + ) + + l1b_histrates["exposure_time_60deg"] = xr.DataArray( + effective_exposure_60deg, + dims=["epoch", "esa_step", "spin_bin_60"], + ) + + return l1b_histrates + + +def calculate_de_rates( + sci_dependencies: dict, + anc_dependencies: list, + attr_mgr_l1b: ImapCdfAttributes, +) -> xr.Dataset: + """ + Calculate direct event rates histograms. + + The histograms are per ASC (28 spins), so we need to + regroup the individual DEs from the l1b_de dataset into + their associated ASC and then bin them by ESA / spin bin. + + Parameters + ---------- + sci_dependencies : dict + The science dependencies for the derates product. + anc_dependencies : list + List of ancillary file paths. + attr_mgr_l1b : ImapCdfAttributes + Attribute manager used to get the L1B derates dataset attributes. + + Returns + ------- + l1b_derates : xr.Dataset + Dataset containing DE rates histograms. + """ + l1b_de = sci_dependencies["imap_lo_l1b_de"] + l1a_spin = sci_dependencies["imap_lo_l1a_spin"] + # Set the asc_start for each DE by removing the average spin cycle + # which is a function of esa_step (see set_spin_cycle function) + # spin_cycle is an average over esa steps and spins per asc, so finding + # the "average" spin that an esa step occurred at. + asc_start = l1b_de["spin_cycle"] - (7 + (l1b_de["esa_step"] - 1) * 2) + + # Get unique ASC values and create a mapping from asc_start to index + unique_asc, unique_idx, asc_idx = np.unique( + asc_start.values, return_index=True, return_inverse=True + ) + num_asc = len(unique_asc) + + # Pre-extract arrays for faster access (avoid repeated xarray indexing) + esa_step_idx = l1b_de["esa_step"].values - 1 # Convert to 0-based index + # Convert spin_bin from 0.1 degree bins to 6 degree bins for coarse histograms + spin_bin = l1b_de["spin_bin"].values // 60 + species = l1b_de["species"].values + coincidence_type = l1b_de["coincidence_type"].values + + if len(anc_dependencies) == 0: + logger.warning("No ancillary dependencies provided, using linear stepping.") + energy_step_mapping = np.arange(7) + else: + # An array mapping esa step index to esa level for resweeping + energy_step_mapping = _get_esa_level_indices( + l1b_de["epoch"].values[asc_idx], anc_dependencies + ) + + # exposure time shape: (num_asc, num_esa_steps) + exposure_time: np.ndarray = np.zeros((num_asc, c.N_ESA_LEVELS), dtype=float) + # exposure_time_6deg = N_SPINS_PER_ESA_LEVEL * avg_spin_per_asc / 60 + # N_SPINS_PER_ESA_LEVEL sweeps per ASC (28 / 7) in 60 bins + asc_avg_spin_durations = ( + c.N_SPINS_PER_ESA_LEVEL * l1b_de["avg_spin_durations"].data[unique_idx] / 60 + ) + np.add.at( + exposure_time, + (slice(None), energy_step_mapping), + asc_avg_spin_durations[:, np.newaxis], + ) + + # Create output arrays + output_shape = (num_asc, c.N_ESA_LEVELS, c.N_SPIN_ANGLE_BINS) + h_counts = np.zeros(output_shape) + o_counts = np.zeros(output_shape) + triple_counts = np.zeros(output_shape) + double_counts = np.zeros(output_shape) + + # Species masks + h_mask = species == "H" + o_mask = species == "O" + + # Coincidence type masks + triple_types = ["111111", "111100", "111000"] + double_types = [ + "110100", + "110000", + "101101", + "101100", + "101000", + "100100", + "100101", + "100000", + "011100", + "011000", + "010100", + "010101", + "010000", + "001100", + "001101", + "001000", + ] + triple_mask = np.isin(coincidence_type, triple_types) + double_mask = np.isin(coincidence_type, double_types) + + # Vectorized histogramming using np.add.at with full index arrays + np.add.at(h_counts, (asc_idx[h_mask], esa_step_idx[h_mask], spin_bin[h_mask]), 1) + np.add.at(o_counts, (asc_idx[o_mask], esa_step_idx[o_mask], spin_bin[o_mask]), 1) + np.add.at( + triple_counts, + (asc_idx[triple_mask], esa_step_idx[triple_mask], spin_bin[triple_mask]), + 1, + ) + np.add.at( + double_counts, + (asc_idx[double_mask], esa_step_idx[double_mask], spin_bin[double_mask]), + 1, + ) + + ds = xr.Dataset( + coords={ + # ASC start time in TTJ2000ns + "epoch": l1a_spin["epoch"], + "esa_step": np.arange(7), + "spin_bin": np.arange(60), + }, + ) + ds["h_counts"] = xr.DataArray( + h_counts, + dims=["epoch", "esa_step", "spin_bin"], + ) + ds["o_counts"] = xr.DataArray( + o_counts, + dims=["epoch", "esa_step", "spin_bin"], + ) + ds["triple_counts"] = xr.DataArray( + triple_counts, + dims=["epoch", "esa_step", "spin_bin"], + ) + ds["double_counts"] = xr.DataArray( + double_counts, + dims=["epoch", "esa_step", "spin_bin"], + ) + ds["exposure_time"] = xr.DataArray( + exposure_time, + dims=["epoch", "esa_step"], + ) + ds["h_rates"] = ds["h_counts"] / ds["exposure_time"] + ds["o_rates"] = ds["o_counts"] / ds["exposure_time"] + ds["triple_rates"] = ds["triple_counts"] / ds["exposure_time"] + ds["double_rates"] = ds["double_counts"] / ds["exposure_time"] + + # (N, 7) + unique_asc = xr.DataArray(unique_asc, dims=["epoch"]) + ds["spin_cycle"] = unique_asc + 7 + (ds["esa_step"] - 1) * 2 + + # TODO: Add badtimes + ds["badtime"] = xr.zeros_like(ds["epoch"], dtype=int) + + ds["pivot_angle"] = l1b_de["pivot_angle"] + + pointing_start_met, pointing_end_met = get_pointing_times( + ttj2000ns_to_met(ds["epoch"].values[0].item()) + ) + ds = set_esa_mode(pointing_start_met, pointing_end_met, anc_dependencies, ds) + + ds.attrs = attr_mgr_l1b.get_global_attributes("imap_lo_l1b_derates") + ds["epoch"].attrs = attr_mgr_l1b.get_variable_attributes( + "epoch", check_schema=False + ) + + return ds + + +def get_pivot_angle_from_nhk(ds_nhk: xr.Dataset) -> float: + """ + Get the middle pivot angle from the NHK dataset. + + The pivot platform moves at the beginning of each pointing period, so we + don't want to be near one of the start/end times, so just grab the middle value. + + Parameters + ---------- + ds_nhk : xr.Dataset + The NHK dataset containing pivot angle information. + + Returns + ------- + pivot_angle : float + The nearest pivot angle for the given epoch. + """ + nitems = len(ds_nhk["pcc_cumulative_cnt_pri"]) + return ds_nhk["pcc_cumulative_cnt_pri"].isel(epoch=nitems // 2).item() + + +def _get_esa_level_indices(epochs: np.ndarray, anc_dependencies: list) -> np.ndarray: + """ + Get the ESA level indices (reswept indices) for the given epochs. + + This will always return a 7-element array mapping the original ESA step + indices (0-6) to the true ESA levels after resweeping. i.e. we could have + taken two measurements in a row at the same energy level, so the mapping + would be [0, 0, 1, 1, 2, 2, 3] potentially. The nominal stepping is + [0, 1, 2, 3, 4, 5, 6]. + + Parameters + ---------- + epochs : np.ndarray + Array of epochs in TTJ2000ns format. + anc_dependencies : list + List of ancillary file paths. + + Returns + ------- + esa_level_indices : np.ndarray + Array of ESA level indices for each epoch. + """ + # The sweep table contains the mapping of dates to the LUT table which shows how + # the ESA steps should be reswept. + sweep_df = lo_ancillary.read_ancillary_file( + next(str(s) for s in anc_dependencies if "sweep-table" in str(s)) + ) + lut_df = lo_ancillary.read_ancillary_file( + next(str(s) for s in anc_dependencies if "esa-mode-lut" in str(s)) + ) + + # Get the time information to compare the epochs to the sweep table dates + sweep_dates = sweep_df["Date"].astype(str) + # Get only the date portion of the epoch string for comparison with the sweep table + # NOTE: We only use the first epoch here since the LUT mapping should be + # constant through the entire dataset + epoch_date_only = et_to_utc(ttj2000ns_to_et(epochs[0])).split("T")[0] + + # Get the matching sweep table entry for the epoch date and its LUT table index + matching_sweep = sweep_df[sweep_dates == epoch_date_only] + # if the epoch date is not in the sweep table, raise an error + if len(matching_sweep) == 0: + raise ValueError(f"No sweep table entry found for date {epoch_date_only}") + + unique_lut_tables = matching_sweep["LUT_table"].unique() + + # There should only be one unique LUT table for each date + if len(unique_lut_tables) != 1: + logger.warning( + f"Multiple LUT tables found for epoch {epoch_date_only}, " + f"but found tables {unique_lut_tables}." + ) + + # Get the LUT entries for the identified LUT index + lut_table_idx = unique_lut_tables[0] + lut_entries = lut_df[lut_df["Tbl_Idx"] == lut_table_idx].copy() + + # If there are no LUT entries for the identified LUT table, log a warning + # and return the default mapping + if len(lut_entries) == 0: + logger.warning( + f"No LUT entries for epoch {epoch_date_only}. Looking" + f"for table index {lut_table_idx}." + ) + return np.arange(7) + + # Sort the LUT entries by E-Step_Idx to ensure correct mapping order + lut_entries = lut_entries.sort_values("E-Step_Idx") + + # TODO: It seems like this is also given to us in the main sweep table + # Can we just take the last 7 entries of the sweep table for that + # date and use those values instead of this extra work with the + # separate LUT ancillary file? + energy_step_mapping: np.ndarray = np.zeros(7, dtype=int) + # Loop through the LUT entries and populate the mapping + for _, row in lut_entries.iterrows(): + # Original ESA step index is 1-based, convert to 0-based + esa_idx = int(row["E-Step_Idx"]) - 1 + true_esa_step = int(row["E-Step_lvl"]) - 1 + # Populate the mapping + energy_step_mapping[esa_idx] = true_esa_step + + return energy_step_mapping + + +def split_rate_dataset( + l1b_all_rates: xr.Dataset, attr_mgr_l1b: ImapCdfAttributes +) -> tuple[xr.Dataset, xr.Dataset]: + """ + Split the L1B all rates dataset into histogram rates and monitor rates datasets. + + Parameters + ---------- + l1b_all_rates : xr.Dataset + The L1B all rates dataset containing both histogram and monitor rates. + attr_mgr_l1b : ImapCdfAttributes + Attribute manager used to get the L1B histogram and monitor rates dataset + attributes. + + Returns + ------- + l1b_hist_rates : xr.Dataset + The L1B histogram rates dataset. + l1b_monitor_rates : xr.Dataset + The L1B monitor rates dataset. + """ + # Use centralized lists for fields to include in split datasets + l1b_hist_rates = l1b_all_rates[HIST_RATE_FIELDS] + l1b_hist_rates.attrs = attr_mgr_l1b.get_global_attributes("imap_lo_l1b_histrates") + l1b_monitor_rates = l1b_all_rates[MONITOR_RATE_FIELDS] + l1b_monitor_rates.attrs = attr_mgr_l1b.get_global_attributes( + "imap_lo_l1b_monitorrates" + ) + + return l1b_hist_rates, l1b_monitor_rates + + +# ============================================================================ +# Star Sensor L1B Processing Functions +# ============================================================================ + + +def filter_valid_star_records( + l1a_star: xr.Dataset, + min_count: int = 700, + time_window_offset: float = 0.0, + time_window_duration: float | None = None, +) -> np.ndarray: + """ + Create boolean mask for valid star sensor records. + + Records are valid if: + 1. COUNT >= min_count (default 700, per algorithm Section 5) + 2. Within specified time window (if provided) + 3. Not during a repoint maneuver + + Parameters + ---------- + l1a_star : xr.Dataset + L1A star sensor dataset containing 'shcoarse' (MET seconds) and 'count'. + min_count : int + Minimum acceptable COUNT value (default: 700). + time_window_offset : float + Time offset in seconds from first record (default: 0.0). + time_window_duration : float | None + Duration of valid time window in seconds (None = no filter, default). + + Returns + ------- + valid_mask : np.ndarray + Boolean array indicating valid records. + """ + # Section 5: Acceptance Criteria - COUNT >= 700 + count_mask = l1a_star["count"].values >= min_count + + # shcoarse is already in MET seconds + shcoarse_sec = l1a_star["shcoarse"].values.astype(np.float64) + + # Section 2.2: Time window filter (if specified) + if time_window_duration is not None: + t0 = shcoarse_sec[0] + time_mask = (shcoarse_sec >= (t0 + time_window_offset)) & ( + shcoarse_sec <= (t0 + time_window_offset + time_window_duration) + ) + valid_mask = count_mask & time_mask + else: + valid_mask = count_mask + + # Filter out repoint maneuvers + repoint_df = interpolate_repoint_data(shcoarse_sec) + # Exclude times where repoint_in_progress is True + repoint_mask = ~repoint_df["repoint_in_progress"].values + valid_mask = valid_mask & repoint_mask + + n_valid = valid_mask.sum() + n_total = len(valid_mask) + logger.info( + f"Star sensor valid records: {n_valid}/{n_total} " + f"({100 * n_valid / n_total:.1f}%)" + ) + + return valid_mask + + +def calculate_star_sensor_profile_for_group( + data: np.ndarray, + counts: np.ndarray, + end_bins_to_exclude: int = 2, +) -> tuple[np.ndarray, np.ndarray]: + """ + Calculate averaged star sensor amplitude profile for a group of records. + + Parameters + ---------- + data : np.ndarray + Star sensor data array, shape (n_records, 720). + counts : np.ndarray + Count values for each record, shape (n_records,). + end_bins_to_exclude : int + Number of bins to exclude from end of each row of data (default: 2). + + Returns + ------- + avg_amplitude : np.ndarray + Average amplitude in mV per bin, shape (720,). + count_per_bin : np.ndarray + Number of samples accumulated per bin, shape (720,). + """ + if len(data) == 0: + return np.full(720, np.nan, dtype=np.float64), np.zeros(720, dtype=np.int32) + + # Determine valid bin ranges for each record + use_edge_exclusion = (end_bins_to_exclude > 0) & (counts > end_bins_to_exclude) + end_bins = np.where( + use_edge_exclusion, + np.minimum(counts - end_bins_to_exclude, 720), + np.minimum(counts, 720), + ) + + # Create mask for valid bins: shape (n_records, 720) + bin_indices = np.arange(720) + valid_bin_mask = bin_indices[None, :] < end_bins[:, None] + + # Apply mask and sum across all records + masked_data = np.where(valid_bin_mask, data, 0) + sum_array = masked_data.sum(axis=0).astype(np.float64) + count_array = valid_bin_mask.sum(axis=0).astype(np.int32) + + # Compute average amplitude per bin + avg_amplitude: np.ndarray = np.full(720, np.nan, dtype=np.float64) + mask = count_array > 0 + avg_amplitude[mask] = sum_array[mask] / count_array[mask] + + return avg_amplitude, count_array + + +def calculate_star_sensor_profiles_by_group( + l1a_star: xr.Dataset, + sampling_cadence: float, + spin_period: float, + group_size: int = 64, + start_angle_offset: float = 62.0, + end_bins_to_exclude: int = 2, + min_count_threshold: int = 700, +) -> tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray]: + """ + Calculate averaged star sensor amplitude profiles for groups of records. + + Groups L1A star sensor records into chunks of `group_size` and calculates + an averaged profile for each group. + + Parameters + ---------- + l1a_star : xr.Dataset + L1A star sensor data. + sampling_cadence : float + Sampling period in milliseconds (ifb_data_interval). + spin_period : float + Spin period in seconds. + group_size : int + Number of records per group (default: 64). + start_angle_offset : float + Starting angle offset in degrees (default: 62.0 = 90Β° - 28Β°). + end_bins_to_exclude : int + Number of ending bins to exclude from each average (default: 2). + min_count_threshold : int + Minimum COUNT value for valid record (default: 700). + + Returns + ------- + spin_angle : np.ndarray + Spin angles in degrees [0-360], shape (720,). + group_mets : np.ndarray + Start MET for each group, shape (n_groups,). + avg_amplitudes : np.ndarray + Average amplitude in mV per bin per group, shape (n_groups, 720). + counts_per_bin : np.ndarray + Number of samples accumulated per bin per group, shape (n_groups, 720). + """ + # Get valid record mask + valid_mask = filter_valid_star_records( + l1a_star, min_count_threshold, time_window_offset=0.0, time_window_duration=None + ) + + valid_indices = np.where(valid_mask)[0] + n_valid = len(valid_indices) + + # Calculate spin angles (same for all groups) + deg_per_bin = 360.0 * (sampling_cadence / 1000.0) / spin_period + bin_indices = np.arange(720) + sample_centers = (bin_indices + 0.5) * deg_per_bin + spin_angle = (start_angle_offset + sample_centers) % 360.0 + + if n_valid == 0: + logger.warning( + "No valid star sensor records found. Returning empty profile with FILLVAL." + ) + return ( + spin_angle, + np.array([], dtype=np.int64), + np.empty((0, 720), dtype=np.float64), + np.empty((0, 720), dtype=np.int32), + ) + + # Keep valid data using xarray selection + l1a_star = l1a_star.isel(epoch=valid_indices) + + # Calculate number of groups (include partial groups) + n_groups = (n_valid + group_size - 1) // group_size + last_group_size = n_valid % group_size + + logger.info( + f"Processing {n_valid} valid records into {n_groups} groups of {group_size}" + ) + if last_group_size != 0: + logger.debug(f"Last group contains {last_group_size} records (partial group)") + + # Assign group labels to the dataset for xarray groupby operations + group_labels: np.ndarray = np.repeat(np.arange(n_groups), group_size)[:n_valid] + l1a_star = l1a_star.assign_coords(group=("epoch", group_labels)) + + # Extract first MET for each group using xarray groupby + group_mets = l1a_star["shcoarse"].groupby("group").first().values.astype(np.int64) + + # Initialize output arrays + avg_amplitudes: np.ndarray = np.zeros((n_groups, 720), dtype=np.float64) + counts_per_bin: np.ndarray = np.zeros((n_groups, 720), dtype=np.int32) + + # Process each group using xarray groupby + for group_label, group_data in l1a_star.groupby("group"): + # Calculate profile for this group + avg_amp, count_arr = calculate_star_sensor_profile_for_group( + group_data["data"].values, group_data["count"].values, end_bins_to_exclude + ) + + avg_amplitudes[group_label] = avg_amp + counts_per_bin[group_label] = count_arr + + return spin_angle, group_mets, avg_amplitudes, counts_per_bin + + +def get_sampling_cadence_from_nhk(l1b_nhk: xr.Dataset) -> float: + """ + Extract ifb_data_interval from NHK dataset. + + The sampling cadence is already in engineering units after L1B processing. + Formula applied in XTCE: ifb_data_interval = 13.3344 + 0.06945 * DN + + Parameters + ---------- + l1b_nhk : xr.Dataset + L1B NHK dataset with derived values (engineering units). + + Returns + ------- + sampling_cadence : float + Average sampling cadence in milliseconds. + """ + if "ifb_data_interval" not in l1b_nhk: + raise KeyError( + "ifb_data_interval field not found in L1B NHK dataset. " + "Cannot calculate sampling cadence." + ) + + # Get mean value across all epochs (should be relatively constant) + sampling_cadence = float(l1b_nhk["ifb_data_interval"].values.mean()) + + logger.info(f"Star sensor sampling cadence from NHK: {sampling_cadence:.3f} ms") + return sampling_cadence + + +def l1b_star( + sci_dependencies: dict, + attr_mgr_l1b: ImapCdfAttributes, + group_size: int = 64, +) -> xr.Dataset: + """ + Create the IMAP-Lo L1B Star Sensor dataset. + + Creates averaged spin profiles from L1A star sensor data, computing + the average amplitude per spin angle bin for each group of records. + Each group contains `group_size` consecutive valid records. + + Parameters + ---------- + sci_dependencies : dict + Dictionary of datasets needed for L1B data product creation in xarray Datasets. + attr_mgr_l1b : ImapCdfAttributes + Attribute manager for L1B dataset metadata. + group_size : int + Number of records to average per group (default: 64). + + Returns + ------- + l1b_star_ds : xr.Dataset + L1B star sensor dataset with spin_angle, avg_amplitude, count_per_bin, + and time range metadata. Each epoch corresponds to a group of records. + """ + logical_source = "imap_lo_l1b_prostar" + l1a_star = sci_dependencies["imap_lo_l1a_star"] + l1b_nhk = sci_dependencies["imap_lo_l1b_nhk"] + spin_data = sci_dependencies["imap_lo_l1a_spin"] + + # L1A files have a coordinate of shcoarse due to DEPEND_0 issue. + # This is a temporary fix for that. + # TODO: Fix L1A shcoarse DEPEND_0 and then remove this + if "shcoarse" in l1a_star.dims: + var_shcoarse = xr.DataArray(l1a_star["shcoarse"].values, dims=("epoch",)) + l1a_star = l1a_star.drop_vars("shcoarse") + l1a_star["shcoarse"] = var_shcoarse + + # Get sampling cadence from NHK + sampling_cadence = get_sampling_cadence_from_nhk(l1b_nhk) + + # Get spin duration from spin data + avg_spin_durations = get_avg_spin_durations_per_cycle(spin_data) + spin_duration = float(avg_spin_durations.mean().values) + logger.info(f"Using spin duration from spin data: {spin_duration:.6f} s") + + # TODO: Read from ancillary config file when available + lo_angle_offset = 2.0 + sc_to_inst_angle_offset = ( + 360 * get_spacecraft_to_instrument_spin_phase_offset(SpiceFrame.IMAP_LO) + + lo_angle_offset + ) + end_bins_to_exclude = 2 + min_count_threshold = 700 + + # Calculate profiles for each 64-spin group + ( + spin_angle, + group_mets, + avg_amplitudes, + counts_per_bin, + ) = calculate_star_sensor_profiles_by_group( + l1a_star, + sampling_cadence, + spin_duration, + group_size=group_size, + start_angle_offset=sc_to_inst_angle_offset, + end_bins_to_exclude=end_bins_to_exclude, + min_count_threshold=min_count_threshold, + ) + + # Get global epoch times from L1A data for start_doy and end_doy + global_start_epoch = l1a_star["epoch"].values[0] + global_end_epoch = l1a_star["epoch"].values[-1] + + # Create dataset with spin_angle as coordinate and multiple epochs + group_epochs = met_to_ttj2000ns(group_mets) + l1b_star_ds = xr.Dataset( + coords={ + "epoch": xr.DataArray( + group_epochs, + dims=["epoch"], + attrs=attr_mgr_l1b.get_variable_attributes("epoch", check_schema=False), + ), + "spin_angle": xr.DataArray( + spin_angle, + dims=["spin_angle"], + attrs=attr_mgr_l1b.get_variable_attributes( + "spin_angle", check_schema=False + ), + ), + }, + attrs=attr_mgr_l1b.get_global_attributes(logical_source), + ) + + # Add spin_angle_bin as a variable (original bin indices) + l1b_star_ds["spin_angle_bin"] = xr.DataArray( + np.arange(720, dtype=np.uint16), + dims=["spin_angle"], + attrs=attr_mgr_l1b.get_variable_attributes( + "spin_angle_bin", check_schema=False + ), + ) + + l1b_star_ds["met"] = xr.DataArray( + group_mets, + dims=["epoch"], + attrs=attr_mgr_l1b.get_variable_attributes("met"), + ) + + l1b_star_ds["avg_amplitude"] = xr.DataArray( + avg_amplitudes, + dims=["epoch", "spin_angle"], + attrs=attr_mgr_l1b.get_variable_attributes("avg_amplitude"), + ) + + l1b_star_ds["count_per_bin"] = xr.DataArray( + counts_per_bin, + dims=["epoch", "spin_angle"], + attrs=attr_mgr_l1b.get_variable_attributes("count_per_bin"), + ) + + # Sort the dataset by spin_angle + l1b_star_ds = l1b_star_ds.sortby("spin_angle") + + # Add pointing mid time (MET) as a scalar value + # Use the first epoch to determine which pointing we're in + first_met = l1a_star["shcoarse"].values[0] + pointing_mid_met = get_pointing_mid_time(first_met) + + # Add global start and end day of year as scalar values + start_doy = epoch_to_fractional_doy(global_start_epoch) + end_doy = epoch_to_fractional_doy(global_end_epoch) + + # Add processing parameters as metadata + l1b_star_ds.attrs["start_doy"] = start_doy + l1b_star_ds.attrs["end_doy"] = end_doy + l1b_star_ds.attrs["pointing_mid_met"] = pointing_mid_met + l1b_star_ds.attrs["sampling_cadence_ms"] = sampling_cadence + l1b_star_ds.attrs["spin_duration_sec"] = spin_duration + l1b_star_ds.attrs["lo_angle_offset_deg"] = lo_angle_offset + l1b_star_ds.attrs["end_bins_excluded"] = end_bins_to_exclude + l1b_star_ds.attrs["min_count_threshold"] = min_count_threshold + l1b_star_ds.attrs["group_size"] = group_size + + logger.info( + f"L1B star sensor dataset created successfully with {len(group_epochs)} groups" + ) + + return l1b_star_ds + + +def l1b_bgrates_and_goodtimes( # noqa: PLR0912 + sci_dependencies: dict, + anc_dependencies: list, + attr_mgr_l1b: ImapCdfAttributes, + delay_max: int | None = None, +) -> xr.Dataset: + """ + Create the IMAP-Lo L1B Background dataset. + + Creates a Background dataset from the L1B Histogram Rates dataset. + + Parameters + ---------- + sci_dependencies : dict + Dictionary of datasets needed for L1B data product creation in xarray Datasets. + anc_dependencies : list + List of ancillary file paths. + attr_mgr_l1b : ImapCdfAttributes + Attribute manager for L1B dataset metadata. + delay_max : int | None + Maximum time gap [s] between consecutive histogram epochs before treating them + as separate intervals. If None, the default value of 100 is used. + + Returns + ------- + l1b_bgrates_ds : xr.Dataset + L1B bgrates dataset with ESA flags per epoch and bin. + Each dataset also includes a background rate. + """ + if delay_max is None: + delay_max = c.DELAY_MAX + + elems = c.ELEMS # shortcut + + pivot_de: float = 0.0 + cdf_de = sci_dependencies.get("imap_lo_l1b_de") + if cdf_de is not None: + pivot_de = cdf_de["pivot_angle"].item() if "pivot_angle" in cdf_de else 0.0 + + pivot: float = 90.0 + cdf_hk = sci_dependencies.get("imap_lo_l1b_nhk") + if cdf_hk is not None and "pcc_coarse_pot_pri" in cdf_hk: + hk_epoch_ets = ttj2000ns_to_et(cdf_hk["epoch"]) + start_et_hk = ( + hk_epoch_ets[0] + timedelta(hours=c.PIVOT_HK_HOUR_RANGE[0]).total_seconds() + ) + end_et_hk = ( + hk_epoch_ets[0] + timedelta(hours=c.PIVOT_HK_HOUR_RANGE[1]).total_seconds() + ) + + coarse_pot_pri = cdf_hk["pcc_coarse_pot_pri"].values + pivot = np.nanmedian( # type: ignore + coarse_pot_pri[(hk_epoch_ets >= start_et_hk) & (hk_epoch_ets <= end_et_hk)] + ) + if np.isnan(pivot): + pivot = 90.0 + + cdf_hist = sci_dependencies["imap_lo_l1b_histrates"] + epoch_ttj2000 = cdf_hist["epoch"].values + n_epochs = epoch_ttj2000.shape[0] + met = ttj2000ns_to_met(epoch_ttj2000) + + # Get year and day-of-year for the anti-RAM threshold override lookup + epoch_start_dt = spiceypy.et2datetime(ttj2000ns_to_et(epoch_ttj2000[0])) + epoch_year = epoch_start_dt.year + epoch_doy = epoch_start_dt.timetuple().tm_yday + + # Choose background rate thresholds based on pivot orientation. + bg_rate_ram_nominal = c.THRESHOLD_BG_RATE_RAM_DEFAULT + bg_rate_anti_ram_nominal = c.THRESHOLD_BG_RATE_ANTI_RAM_DEFAULT + for (low, high), (ram_thresh, anti_ram_thresh) in c.PIVOT_ANGLE_THRESHOLDS.items(): + if low < pivot < high: + bg_rate_ram_nominal = ram_thresh + bg_rate_anti_ram_nominal = anti_ram_thresh + break + + # Manual overrides of the anti-RAM threshold for anomalous days. + overrides_anc_files = [ + s for s in anc_dependencies if "bg-rates-anti-ram-overrides" in str(s) + ] + if overrides_anc_files: + overrides = lo_ancillary.read_ancillary_file(str(overrides_anc_files[0])) + overrides = overrides.set_index(["year", "doy"])["counts/s"].to_dict() + else: + overrides = {} + + bg_rate_anti_ram_nominal = overrides.get( + (epoch_year, epoch_doy), bg_rate_anti_ram_nominal + ) + + ram_esa_indices = [i - 1 for i in c.RAM_ESA_LEVELS] # Convert to 0-indexed + + # Sum histogram counts over the relevant angular bins for each species and + # direction. RAM counts use only certain ESA steps; anti-RAM counts use all. + elem_ram_counts = {} + elem_anti_ram_counts = {} + for elem in elems: + if f"{elem.lower()}_counts" in cdf_hist.data_vars: + elem_counts = cdf_hist[f"{elem.lower()}_counts"].values + else: + elem_counts = np.zeros_like(cdf_hist["h_counts"].values) + elem_ram_counts[elem] = sum( + np.sum(elem_counts[:, ram_esa_indices, b], axis=(1, 2)) + for b in c.RAM_HISTOGRAM_BINS + ) + elem_anti_ram_counts[elem] = sum( + np.sum(elem_counts[:, :, b], axis=(1, 2)) for b in c.ANTI_RAM_HISTOGRAM_BINS + ) + + # Pre-compute expected exposure times [s] for the averaging and summing windows. + # Exposure is tied to the histogram cadence rather than the total pointing duration. + exposure = c.HISTOGRAM_CYCLE_EPOCHS * c.N_CYCLE_AVE * c.EXPOSURE_FACTOR + exposure_ram = exposure * len(c.RAM_ESA_LEVELS) / c.N_ESA_LEVELS + exposure_sum = c.HISTOGRAM_CYCLE_EPOCHS * c.N_CYCLE_SUM * c.EXPOSURE_FACTOR + + # Walk through histogram epochs one N_CYCLE_SUM block at a time. + begin = end = 0.0 + interval = c.HISTOGRAM_CYCLE_EPOCHS * c.N_CYCLE_SUM + synthetic_floors = {e: 0.0 for e in elems} # Accumulated model-predicted BG counts + proxy_floors = { + e: 0.0 for e in elems + } # Accumulated measured anti-RAM counts (BG proxy) + goodtime_exposure_avg = goodtime_exposure_sum = 0.0 + goodtime_rows = [] + + for i in range(0, n_epochs, c.N_CYCLE_SUM): + measured_interval = interval + if i + c.N_CYCLE_SUM < n_epochs: + measured_interval = met[i + c.N_CYCLE_SUM] - met[i] + + if measured_interval > (interval + delay_max): + if begin > 0.0: + end = met[i - 1] + goodtime_rows.append( + ( + begin, + end, + bg_rate_anti_ram_nominal, + goodtime_exposure_avg, + goodtime_exposure_sum, + ) + ) + begin = end = 0.0 + continue + + # A large gap (missing data) forces the current good-time interval to close. + delta_time = 0.0 + if i > 0: + delta_time = met[i] - (met[i - 1] + c.HISTOGRAM_CYCLE_EPOCHS) + + if (delta_time > c.DELAY_MAX) and (begin > 0.0): + end = met[i - 1] + goodtime_rows.append( + ( + begin, + end, + bg_rate_anti_ram_nominal, + goodtime_exposure_avg, + goodtime_exposure_sum, + ) + ) + begin = end = 0.0 + + # Sliding window centered on epoch i for rate averaging + window_avg_start = max(int(i - c.N_CYCLE_AVE // 2), 0) + window_avg_end = min(n_epochs, window_avg_start + c.N_CYCLE_AVE) + if (window_avg_end - window_avg_start) < c.N_CYCLE_AVE: + window_avg_start = max(window_avg_end - c.N_CYCLE_AVE, 0) + + # Sliding window centered on epoch i for accumulating counts + window_sum_start = max(int(i - c.N_CYCLE_SUM // 2), 0) + window_sum_end = min(n_epochs, window_sum_start + c.N_CYCLE_SUM) + if (window_sum_end - window_sum_start) < c.N_CYCLE_SUM: + window_sum_start = max(window_avg_end - c.N_CYCLE_SUM, 0) + + # Estimate background rates from the averaged H counts + ram_rate = ( + np.sum(elem_ram_counts["H"][window_avg_start:window_avg_end]) / exposure_ram + ) + anti_ram_rate = ( + np.sum(elem_anti_ram_counts["H"][window_avg_start:window_avg_end]) + / exposure + ) + + # good-time = intervals where background rates are below threshold + if (ram_rate < bg_rate_ram_nominal) and ( + anti_ram_rate < bg_rate_anti_ram_nominal + ): + if begin == 0.0: + begin = met[i] # Start a new good-time interval + + for elem in elems: + synthetic_floors[elem] += c.BG_RATES.get(elem, 0) * exposure + proxy_floors[elem] += np.sum( + elem_anti_ram_counts[elem][window_sum_start:window_sum_end] + ) + + goodtime_exposure_avg += exposure + goodtime_exposure_sum += exposure_sum + + elif begin > 0.0: + # Background exceeded threshold; close the current good-time interval. + end = met[i - 1] + goodtime_rows.append( + ( + begin, + end, + bg_rate_anti_ram_nominal, + goodtime_exposure_avg, + goodtime_exposure_sum, + ) + ) + begin = end = 0.0 + + if (end == 0.0) and (begin > 0.0): + end = met[n_epochs - 1] + if end > begin: + goodtime_rows.append( + ( + begin, + end, + bg_rate_anti_ram_nominal, + goodtime_exposure_avg, + goodtime_exposure_sum, + ) + ) + + # Compute background rates per species + bg_rates_out = {} + sigma_bg_rates_out = {} + for elem in elems: + if goodtime_exposure_avg == 0: + bg_rate = bg_rate_anti_ram_nominal * c.BG_RATE_FALLBACK_SCALE.get(elem, 0) + sigma_bg_rate = bg_rate + else: + bg_rate = synthetic_floors[elem] / goodtime_exposure_avg + sigma_bg_rate = np.sqrt(synthetic_floors[elem]) / goodtime_exposure_avg + + if bg_rate == 0.0: + bg_rate = bg_rate_anti_ram_nominal / c.BG_RATE_FLOOR_DIVISOR.get(elem, 1) + sigma_bg_rate = bg_rate + if sigma_bg_rate == 0.0: + sigma_bg_rate = bg_rate + + bg_rates_out[elem] = bg_rate + sigma_bg_rates_out[elem] = sigma_bg_rate + + # Final adjustment - add padding to each goodtime interval + for i, (begin, end, *other) in enumerate(goodtime_rows): + goodtime_rows[i] = ( + begin - c.GOODTIME_PADDING, + end + c.GOODTIME_PADDING, + *other, + ) + + if len(goodtime_rows) == 0: + goodtime_rows = [(0, 0, 0, 0, 0)] + + # Initialize the dataset + datasets_to_return = [] + l1b_combined_ds = xr.Dataset() + + epoch_values = met_to_ttj2000ns(np.array([r[0] for r in goodtime_rows])) + + l1b_combined_ds["epoch"] = xr.DataArray( + data=epoch_values, + name="epoch", + dims=["epoch"], + attrs=attr_mgr_l1b.get_variable_attributes("epoch", check_schema=False), + ) + + # esa_step is a coordinate in this dataset, so pop the DEPEND_0 attribute + esa_step_attrs = attr_mgr_l1b.get_variable_attributes("esa_step") + esa_step_attrs.pop("DEPEND_0") + l1b_combined_ds["esa_step"] = xr.DataArray( + data=np.arange(c.N_ESA_LEVELS, dtype=np.uint8) + 1, + name="esa_step", + dims=["esa_step"], + attrs=esa_step_attrs, + ) + l1b_combined_ds = l1b_combined_ds.set_coords(["epoch", "esa_step"]) + + l1b_combined_ds["pivot"] = xr.DataArray( + data=np.float32(pivot), + name="pivot", + attrs=attr_mgr_l1b.get_variable_attributes("pivot", check_schema=False), + ) + l1b_combined_ds["pivot_de"] = xr.DataArray( + data=np.float32(pivot_de), + name="pivot_de", + attrs=attr_mgr_l1b.get_variable_attributes("pivot_de", check_schema=False), + ) + + l1b_combined_ds["gt_start_met"] = xr.DataArray( + data=np.array([r[0] for r in goodtime_rows], dtype=np.float64), + name="Goodtime_start", + dims=["epoch"], + attrs=attr_mgr_l1b.get_variable_attributes("gt_start_met"), + ) + l1b_combined_ds["gt_end_met"] = xr.DataArray( + data=np.array([r[1] for r in goodtime_rows], dtype=np.float64), + name="Goodtime_end", + dims=["epoch"], + attrs=attr_mgr_l1b.get_variable_attributes("gt_end_met"), + ) + + # Per-species scalar variables + for elem in elems: + elem_lower = elem.lower() + # For *_background_rates, and *_background_variance for each species, + # we return a (N_ESA_LEVELS) array of identical values to be backward + # compatible with an old implementation of the algorithm. + l1b_combined_ds[f"{elem_lower}_background_rates"] = xr.DataArray( + data=np.full(c.N_ESA_LEVELS, bg_rates_out[elem]), + name=f"{elem_lower}_background_rates", + attrs=attr_mgr_l1b.get_variable_attributes( + f"{elem_lower}_background_rates", + check_schema=False, + ), + dims=["esa_step"], + ) + l1b_combined_ds[f"{elem_lower}_background_variance"] = xr.DataArray( + data=np.full(c.N_ESA_LEVELS, sigma_bg_rates_out[elem]), + name=f"{elem_lower}_background_variance", + attrs=attr_mgr_l1b.get_variable_attributes( + f"{elem_lower}_background_variance", + check_schema=False, + ), + dims=["esa_step"], + ) + l1b_combined_ds[f"{elem_lower}_synthetic_floor"] = xr.DataArray( + data=np.float32(synthetic_floors[elem]), + name=f"{elem_lower}_synthetic_floor", + attrs=attr_mgr_l1b.get_variable_attributes( + f"{elem_lower}_synthetic_floor", check_schema=False + ), + ) + l1b_combined_ds[f"{elem_lower}_proxy_floor"] = xr.DataArray( + data=np.float32(proxy_floors[elem]), + name=f"{elem_lower}_proxy_floor", + attrs=attr_mgr_l1b.get_variable_attributes( + f"{elem_lower}_proxy_floor", check_schema=False + ), + ) + + logger.info("L1B Background Rates and Bettertimes created successfully") + + l1b_bgrates_ds, l1b_goodtimes_ds = split_backgrounds_and_goodtimes_dataset( + l1b_combined_ds, attr_mgr_l1b + ) + datasets_to_return.extend([l1b_bgrates_ds, l1b_goodtimes_ds]) + + return datasets_to_return + + +def split_backgrounds_and_goodtimes_dataset( + l1b_backgrounds_and_goodtimes_ds: xr.Dataset, attr_mgr_l1b: ImapCdfAttributes +) -> tuple[xr.Dataset, xr.Dataset]: + """ + Separate the L1B backgrounds and goodtimes dataset. + + Parameters + ---------- + l1b_backgrounds_and_goodtimes_ds : xr.Dataset + The L1B all backgrounds and goodtimes dataset containing + both background rates and goodtimes. + attr_mgr_l1b : ImapCdfAttributes + Attribute manager used to get the L1B background rates and + goodtimes dataset attributes. + + Returns + ------- + l1b_bgrates : xr.Dataset + The L1B background rates dataset. + l1b_goodtimes_rates : xr.Dataset + The L1B goodtimes rates dataset. + """ + l1b_goodtimes_ds = l1b_backgrounds_and_goodtimes_ds[GOODTIMES_FIELDS] + l1b_goodtimes_ds.attrs = attr_mgr_l1b.get_global_attributes("imap_lo_l1b_goodtimes") + + # Suffixes for fields that we accept as belonging to `l1b_bgrates`. + background_rate_field_suffixes = [ + "_background_rates", + "_background_variance", + "_synthetic_floor", + "_proxy_floor", + ] + background_rate_fields = sorted( + [ + data_var + for data_var in l1b_backgrounds_and_goodtimes_ds.data_vars + if any( + data_var.endswith(suffix) for suffix in background_rate_field_suffixes + ) + ] + ) + + l1b_bgrates_ds = l1b_backgrounds_and_goodtimes_ds[background_rate_fields] + l1b_bgrates_ds["epoch"] = l1b_backgrounds_and_goodtimes_ds["epoch"] + l1b_bgrates_ds.attrs = attr_mgr_l1b.get_global_attributes("imap_lo_l1b_bgrates") + + return l1b_bgrates_ds, l1b_goodtimes_ds diff --git a/imap_processing/lo/l1b/tof_conversions.py b/imap_processing/lo/l1b/tof_conversions.py index 420fe8225a..9f2751e134 100644 --- a/imap_processing/lo/l1b/tof_conversions.py +++ b/imap_processing/lo/l1b/tof_conversions.py @@ -4,8 +4,9 @@ tof_conv = namedtuple("tof_conv", ["C0", "C1"]) # TOF conversion coefficients from Lo's TOF Conversion_annotated.docx +# TOF3_CONV was updated in March 2026 per email from Nathan # TODO: Ask Lo to put these in the algorithm document for better reference TOF0_CONV = tof_conv(C0=5.52524e-01, C1=1.68374e-01) TOF1_CONV = tof_conv(C0=-7.20181e-01, C1=1.65124e-01) TOF2_CONV = tof_conv(C0=3.74422e-01, C1=1.66409e-01) -TOF3_CONV = tof_conv(C0=4.41970e-01, C1=1.72024e-01) +TOF3_CONV = tof_conv(C0=4.6726e-01, C1=1.7144e-01) diff --git a/imap_processing/lo/l1c/lo_l1c.py b/imap_processing/lo/l1c/lo_l1c.py index 4ffb855dd1..2eb43c99da 100644 --- a/imap_processing/lo/l1c/lo_l1c.py +++ b/imap_processing/lo/l1c/lo_l1c.py @@ -1,17 +1,28 @@ """IMAP-Lo L1C Data Processing.""" +import logging from dataclasses import Field from enum import Enum import numpy as np +import pandas as pd import xarray as xr -from scipy.stats import binned_statistic_dd from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes -from imap_processing.lo import lo_ancillary +from imap_processing.ena_maps.utils.corrections import ( + add_spacecraft_position_and_velocity_to_pset, +) +from imap_processing.spice.geometry import ( + SpiceFrame, + frame_transform_az_el, + lo_instrument_pointing, +) from imap_processing.spice.repoint import get_pointing_times -from imap_processing.spice.spin import get_spin_number -from imap_processing.spice.time import met_to_ttj2000ns, ttj2000ns_to_met +from imap_processing.spice.spin import get_spin_data, get_spin_number +from imap_processing.spice.time import ( + met_to_ttj2000ns, + ttj2000ns_to_et, +) N_ESA_ENERGY_STEPS = 7 N_SPIN_ANGLE_BINS = 3600 @@ -19,12 +30,22 @@ # 1 time, 7 energy steps, 3600 spin angle bins, and 40 off angle bins PSET_SHAPE = (1, N_ESA_ENERGY_STEPS, N_SPIN_ANGLE_BINS, N_OFF_ANGLE_BINS) PSET_DIMS = ["epoch", "esa_energy_step", "spin_angle", "off_angle"] -ESA_ENERGY_STEPS = np.arange(N_ESA_ENERGY_STEPS) + 1 # 1 to 7 inclusive +ESA_ENERGY_STEPS: np.ndarray = ( + np.arange(N_ESA_ENERGY_STEPS) + 1 # 1 to 7 inclusive +) SPIN_ANGLE_BIN_EDGES = np.linspace(0, 360, N_SPIN_ANGLE_BINS + 1) SPIN_ANGLE_BIN_CENTERS = (SPIN_ANGLE_BIN_EDGES[:-1] + SPIN_ANGLE_BIN_EDGES[1:]) / 2 OFF_ANGLE_BIN_EDGES = np.linspace(-2, 2, N_OFF_ANGLE_BINS + 1) OFF_ANGLE_BIN_CENTERS = (OFF_ANGLE_BIN_EDGES[:-1] + OFF_ANGLE_BIN_EDGES[1:]) / 2 +# Constants for statistical exposure time calculation +# Number of time samples per spin to capture all potential timesteps +N_SAMPLES_PER_SPIN = 4096 +# Default number of representative spins to sample across the pointing +DEFAULT_N_REPRESENTATIVE_SPINS = 5 +# Nominal Lo pivot angle in degrees +LO_NOMINAL_PIVOT_ANGLE = 90.0 + class FilterType(str, Enum): """ @@ -66,15 +87,54 @@ def lo_l1c(sci_dependencies: dict, anc_dependencies: list) -> list[xr.Dataset]: if "imap_lo_l1b_de" in sci_dependencies: logical_source = "imap_lo_l1c_pset" l1b_de = sci_dependencies["imap_lo_l1b_de"] - l1b_goodtimes_only = filter_goodtimes(l1b_de, anc_dependencies) - pset = initialize_pset(l1b_goodtimes_only, attr_mgr, logical_source) - full_counts = create_pset_counts(l1b_goodtimes_only) + l1b_goodtimes_only = filter_goodtimes( + l1b_de, sci_dependencies["imap_lo_l1b_goodtimes"] + ) + + # Handle case where no good times are found after filtering, + # which would lead to an empty dataset + if len(l1b_goodtimes_only["epoch"]) == 0: + logging.warning( + "No good times found in L1B DE dataset after filtering. " + "Creating empty PSET dataset with zero counts and exposure time." + ) + # Set dummy pointing start and end METs + pointing_start_met = 0.0 + pointing_end_met = 0.0 + else: + pointing_start_met, pointing_end_met = get_pointing_times( + float( + sci_dependencies["imap_lo_l1b_goodtimes"]["gt_start_met"].values[0] + ) + ) - # Set the pointing start and end times based on the first epoch - pointing_start_met, pointing_end_met = get_pointing_times( - ttj2000ns_to_met(l1b_goodtimes_only["epoch"][0].item()) + pset = xr.Dataset( + coords={"epoch": np.array([met_to_ttj2000ns(pointing_start_met)])}, + attrs=attr_mgr.get_global_attributes(logical_source), ) + # pass-through of the pivot_angle from L1B DE + pset["pivot_angle"] = l1b_de["pivot_angle"] + + # ESA mode needs to be added to L1B DE. Adding try statement + # to avoid error until it's available in the dataset + if "esa_mode" not in l1b_de: + logging.debug( + "ESA mode not found in L1B DE dataset. \ + Setting to default value of 0 for Hi-Res." + ) + pset["esa_mode"] = xr.DataArray( + np.array([0]), + dims=["epoch"], + attrs=attr_mgr.get_variable_attributes("esa_mode"), + ) + else: + pset["esa_mode"] = xr.DataArray( + np.array([l1b_de["esa_mode"].values[0]]), + dims=["epoch"], + attrs=attr_mgr.get_variable_attributes("esa_mode"), + ) + pset["pointing_start_met"] = xr.DataArray( np.array([pointing_start_met]), dims="epoch", @@ -86,20 +146,20 @@ def lo_l1c(sci_dependencies: dict, anc_dependencies: list) -> list[xr.Dataset]: attrs=attr_mgr.get_variable_attributes("pointing_end_met"), ) - # Set the epoch to the start of the pointing - pset["epoch"] = xr.DataArray( - met_to_ttj2000ns(pset["pointing_start_met"].values), - attrs=attr_mgr.get_variable_attributes("epoch"), - ) - # Get the start and end spin numbers based on the pointing start and end MET + if 0 == pointing_start_met: + start_spin_number = 0 + end_spin_number = 0 + else: + start_spin_number = get_spin_number(pset["pointing_start_met"].item()) + end_spin_number = get_spin_number(pset["pointing_end_met"].item()) pset["start_spin_number"] = xr.DataArray( - [get_spin_number(pset["pointing_start_met"].item())], + [start_spin_number], dims="epoch", attrs=attr_mgr.get_variable_attributes("start_spin_number"), ) pset["end_spin_number"] = xr.DataArray( - [get_spin_number(pset["pointing_end_met"].item())], + [end_spin_number], dims="epoch", attrs=attr_mgr.get_variable_attributes("end_spin_number"), ) @@ -114,10 +174,39 @@ def lo_l1c(sci_dependencies: dict, anc_dependencies: list) -> list[xr.Dataset]: pset["h_counts"] = create_pset_counts(l1b_goodtimes_only, FilterType.HYDROGEN) pset["o_counts"] = create_pset_counts(l1b_goodtimes_only, FilterType.OXYGEN) - # Set the exposure time + # Set the exposure time using statistical off-pointing sampling + # with good-times filtering applied pset["exposure_time"] = calculate_exposure_times( - full_counts, l1b_goodtimes_only + pointing_start_met, + pointing_end_met, + sci_dependencies["imap_lo_l1b_goodtimes"], + ) + + # Set backgrounds + ( + pset["h_background_rates"], + pset["h_background_rates_stat_uncert"], + pset["h_background_rates_sys_err"], + ) = set_background_rates( + FilterType.HYDROGEN, + sci_dependencies, + attr_mgr, ) + + ( + pset["o_background_rates"], + pset["o_background_rates_stat_uncert"], + pset["o_background_rates_sys_err"], + ) = set_background_rates( + FilterType.OXYGEN, + sci_dependencies, + attr_mgr, + ) + + pset["hae_longitude"], pset["hae_latitude"] = set_pointing_directions( + pset["epoch"].item(), attr_mgr, pset["pivot_angle"].values[0].item() + ) + pset.attrs = attr_mgr.get_global_attributes(logical_source) pset = pset.assign_coords( @@ -128,88 +217,223 @@ def lo_l1c(sci_dependencies: dict, anc_dependencies: list) -> list[xr.Dataset]: } ) + # Get the spacecraft position and velocity and direction + pset = add_spacecraft_position_and_velocity_to_pset(pset) + + # Update the attributes for the spacecraft position and velocity variables + pset["sc_position"].attrs.update(attr_mgr.get_variable_attributes("sc_position")) + pset["sc_velocity"].attrs.update(attr_mgr.get_variable_attributes("sc_velocity")) + pset["label_vector_HAE"] = xr.DataArray( + np.array(["x HAE", "y HAE", "z HAE"], dtype=str), + name="label_vector_HAE", + dims=[" "], + attrs=attr_mgr.get_variable_attributes("label_vector_HAE", check_schema=False), + ) + return [pset] -def initialize_pset( - l1b_de: xr.Dataset, attr_mgr: ImapCdfAttributes, logical_source: str -) -> xr.Dataset: +def filter_goodtimes(l1b_de: xr.Dataset, goodtimes_ds: xr.Dataset) -> xr.Dataset: """ - Initialize the PSET dataset and set the Epoch. + Filter the L1B Direct Event dataset to only include good times. - The Epoch time is set to the first of the L1B - Direct Event times. There is one Epoch per PSET file. + The good times are read from the L1B goodtimes dataset produced by + l1b_bgrates_and_goodtimes. Parameters ---------- l1b_de : xarray.Dataset L1B Direct Event dataset. - attr_mgr : ImapCdfAttributes - Attribute manager used to get the L1C attributes. - logical_source : str - The logical source of the pset. + goodtimes_ds : xarray.Dataset + L1B goodtimes dataset containing gt_start_met and gt_end_met variables + that define good time windows in MET seconds. Returns ------- - pset : xarray.Dataset - Initialized PSET dataset. + xarray.Dataset + Filtered L1B Direct Event dataset containing only events within good + time windows. """ - pset = xr.Dataset( - attrs=attr_mgr.get_global_attributes(logical_source), + epochs = l1b_de["epoch"].values + gt_starts = met_to_ttj2000ns(goodtimes_ds["gt_start_met"].values) + gt_ends = met_to_ttj2000ns(goodtimes_ds["gt_end_met"].values) + + # Keep events that fall within any goodtime window + in_goodtime = np.any( + (epochs[:, np.newaxis] >= gt_starts) & (epochs[:, np.newaxis] <= gt_ends), + axis=1, ) - # TODO: Need to create utility to get start of repointing to use - # for the pset epoch time. Setting to first DE for now - pset_epoch = l1b_de["epoch"][0].item() - pset["epoch"] = xr.DataArray( - np.array([pset_epoch]), - dims=["epoch"], - attrs=attr_mgr.get_variable_attributes("epoch"), + + return l1b_de.isel(epoch=in_goodtime) + + +def get_triple_coincidences(de: xr.Dataset) -> xr.Dataset: + """ + Get only the triple coincidence events from the L1B Direct Event dataset. + + Parameters + ---------- + de : xarray.Dataset + L1B Direct Event dataset. + + Returns + ------- + de_triples : xarray.Dataset + L1B Direct Event dataset with only triple coincidence events. + """ + triple_types = ["111111", "111100", "111000"] + triple_idx = np.nonzero(np.isin(de["coincidence_type"], triple_types))[0] + de_triples = de.isel(epoch=triple_idx) + + return de_triples + + +def get_double_coincidences(de: xr.Dataset) -> xr.Dataset: + """ + Get only the double coincidence events from the L1B Direct Event dataset. + + Parameters + ---------- + de : xarray.Dataset + L1B Direct Event dataset. + + Returns + ------- + de_doubles : xarray.Dataset + L1B Direct Event dataset with only double coincidence events. + """ + double_types = [ + "110100", + "110000", + "101101", + "101100", + "101000", + "100100", + "100101", + "100000", + "011100", + "011000", + "010100", + "010101", + "010000", + "001100", + "001101", + "001000", + ] + double_idx = np.nonzero(np.isin(de["coincidence_type"], double_types))[0] + de_doubles = de.isel(epoch=double_idx) + + return de_doubles + + +def _get_peak_mask( + de: xr.Dataset, peak_lows: list[int], peak_highs: list[int] +) -> np.ndarray: + """ + Get a boolean mask for events within specified peak ranges. + + Parameters + ---------- + de : xarray.Dataset + L1B Direct Event dataset. + peak_lows : list[int] + List of low peak values for each TOF. + peak_highs : list[int] + List of high peak values for each TOF. + + Returns + ------- + peak_mask : numpy.ndarray + Boolean mask indicating events within the specified peak ranges. + """ + tof0_s = de["tof0"] + 0.5 * de["tof3"] + tof1_s = de["tof1"] - 0.5 * de["tof3"] + + peak_mask = ( + (tof0_s >= peak_lows[0]) + & (tof0_s <= peak_highs[0]) + & (tof1_s >= peak_lows[1]) + & (tof1_s <= peak_highs[1]) + & (de["tof2"] >= peak_lows[2]) + & (de["tof2"] <= peak_highs[2]) ) - return pset + return peak_mask -def filter_goodtimes(l1b_de: xr.Dataset, anc_dependencies: list) -> xr.Dataset: +def _get_golden_triple_mask(de: xr.Dataset) -> np.ndarray: """ - Filter the L1B Direct Event dataset to only include good times. + Get a boolean mask for events within the golden triple coincidence types. - The good times are read from the sweep table ancillary file. + A golden triple coincidence is only one of the possible triples-types, so + we need to subset it separately from just triples. Parameters ---------- - l1b_de : xarray.Dataset + de : xarray.Dataset L1B Direct Event dataset. - anc_dependencies : list - Ancillary files needed for L1C data product creation. + Returns + ------- + golden_triple_mask : numpy.ndarray + Boolean mask indicating events within the golden triple coincidence types. + """ + return de["coincidence_type"] == "111111" + + +def get_h_species(de: xr.Dataset) -> xr.Dataset: + """ + Get only the hydrogen species from the L1B Direct Event dataset. + + Parameters + ---------- + de : xarray.Dataset + L1B Direct Event dataset. Returns ------- - l1b_de : xarray.Dataset - Filtered L1B Direct Event dataset. + de_h : xarray.Dataset + L1B Direct Event dataset with only hydrogen species. """ - # the goodtimes are currently the only ancillary file needed for L1C processing - goodtimes_table_df = lo_ancillary.read_ancillary_file(anc_dependencies[0]) + h_peak_low = [20, 10, 10] + h_peak_high = [70, 50, 40] - # convert goodtimes from MET to TTJ2000 - goodtimes_start = met_to_ttj2000ns(goodtimes_table_df["GoodTime_strt"]) - goodtimes_end = met_to_ttj2000ns(goodtimes_table_df["GoodTime_end"]) + golden_triple_mask = _get_golden_triple_mask(de) + h_peak_mask = _get_peak_mask(de, h_peak_low, h_peak_high) - # Create a mask for epochs within any of the start/end time ranges - goodtimes_mask = np.zeros_like(l1b_de["epoch"], dtype=bool) + h_idx = np.nonzero((golden_triple_mask & h_peak_mask).values)[0] - # Iterate over the good times and create a mask - for start, end in zip(goodtimes_start, goodtimes_end, strict=False): - goodtimes_mask |= (l1b_de["epoch"] >= start) & (l1b_de["epoch"] < end) + de_h = de.isel(epoch=h_idx) + return de_h - # Filter the dataset using the mask - filtered_epochs = l1b_de.sel(epoch=goodtimes_mask) - return filtered_epochs +def get_o_species(de: xr.Dataset) -> xr.Dataset: + """ + Get only the oxygen species from the L1B Direct Event dataset. + + Parameters + ---------- + de : xarray.Dataset + L1B Direct Event dataset. + + Returns + ------- + de_o : xarray.Dataset + L1B Direct Event dataset with only oxygen species. + """ + co_peak_low = [100, 60, 60] + co_peak_high = [270, 150, 150] + + golden_triple_mask = _get_golden_triple_mask(de) + o_peak_mask = _get_peak_mask(de, co_peak_low, co_peak_high) + o_idx = np.nonzero((golden_triple_mask & o_peak_mask).values)[0] + + de_o = de.isel(epoch=o_idx) + return de_o def create_pset_counts( - de: xr.Dataset, filter: FilterType = FilterType.NONE + de: xr.Dataset, filter_type: FilterType = FilterType.NONE ) -> xr.DataArray: """ Create the PSET counts for the L1B Direct Event dataset. @@ -222,7 +446,7 @@ def create_pset_counts( ---------- de : xarray.Dataset L1B Direct Event dataset. - filter : FilterType, optional + filter_type : FilterType, optional The event type to include in the counts. Can be "triples", "doubles", "h", or "o". @@ -231,63 +455,33 @@ def create_pset_counts( counts : xarray.DataArray The counts for the specified filter. """ - filter_options = { - # triples coincidence types - FilterType.TRIPLES: ["111111", "111100", "111000"], - # doubles coincidence types - FilterType.DOUBLES: [ - "110100", - "110000", - "101101", - "101100", - "101000", - "100100", - "100101", - "100000", - "011100", - "011000", - "010100", - "010101", - "010000", - "001100", - "001101", - "001000", - ], - # hydrogen species identifier - FilterType.HYDROGEN: "h", - # oxygen species identifier - FilterType.OXYGEN: "o", - } - - # if the filter string is triples or doubles, filter using the coincidence type - if filter in {FilterType.TRIPLES, FilterType.DOUBLES}: - filter_idx = np.where(np.isin(de["coincidence_type"], filter_options[filter]))[ - 0 - ] - # if the filter is h or o, filter using the species - elif filter in {FilterType.HYDROGEN, FilterType.OXYGEN}: - filter_idx = np.where(np.isin(de["species"], filter_options[filter]))[0] - else: - # if no filter is specified, use all data - filter_idx = np.arange(len(de["epoch"])) - - # Filter the dataset using the filter index - de_filtered = de.isel(epoch=filter_idx) + match filter_type: + case FilterType.TRIPLES: + de_filtered = get_triple_coincidences(de) + case FilterType.DOUBLES: + de_filtered = get_double_coincidences(de) + case FilterType.HYDROGEN: + de_filtered = get_h_species(de) + case FilterType.OXYGEN: + de_filtered = get_o_species(de) + case _: + # if no filter is specified, use all data + de_filtered = de # stack the filtered data into the 3D array data = np.column_stack( ( de_filtered["esa_step"], - de_filtered["pointing_bin_lon"], - de_filtered["pointing_bin_lat"], + de_filtered["spin_bin"], + de_filtered["off_angle_bin"], ) ) # Create the histogram with 3600 longitude bins, 40 latitude bins, and 7 energy bins lon_edges = np.arange(3601) lat_edges = np.arange(41) - energy_edges = np.arange(8) + energy_edges = np.arange(1, 9) - hist, edges = np.histogramdd( + hist, _edges = np.histogramdd( data, bins=[energy_edges, lon_edges, lat_edges], ) @@ -303,50 +497,393 @@ def create_pset_counts( return counts -def calculate_exposure_times(counts: xr.DataArray, l1b_de: xr.Dataset) -> xr.DataArray: +def get_representative_spin_times( + pointing_start_met: float, + pointing_end_met: float, + n_spins: int = DEFAULT_N_REPRESENTATIVE_SPINS, +) -> pd.DataFrame: """ - Calculate the exposure times for the L1B Direct Event dataset. + Get evenly-spaced representative spin times from the pointing period. - The exposure times are calculated by binning the data into 3600 longitude bins, - 40 latitude bins, and 7 energy bins. If more than one exposure time is in a bin, - the average is taken. + Selects N spins distributed evenly across the middle 80% of the pointing + duration (skipping the first and last 10%) by querying the spin table for + spins at evenly-spaced MET times. Parameters ---------- - counts : xarray.DataArray - An event counts array with dimensions (epoch, lon_bins, lat_bins, energy_bins). - l1b_de : xarray.Dataset - L1B Direct Event dataset. This data contains the average spin durations. + pointing_start_met : float + The start MET time of the pointing. + pointing_end_met : float + The end MET time of the pointing. + n_spins : int, optional + Number of representative spins to select. Default is 5. + + Returns + ------- + representative_spins : pandas.DataFrame + DataFrame containing the spin table data for the selected representative + spins, including columns: spin_number, spin_start_met, actual_spin_period. + """ + spin_df = get_spin_data() + + # Filter spin table to only spins within the pointing period + pointing_spins = spin_df[ + (spin_df["spin_start_met"] >= pointing_start_met) + & (spin_df["spin_start_met"] < pointing_end_met) + ] + + if len(pointing_spins) == 0: + raise ValueError( + f"No spins found in spin table for pointing period " + f"[{pointing_start_met}, {pointing_end_met}]." + ) + + # Select evenly-spaced indices from the middle 80% of available spins + # Skip first 10% and last 10% to avoid boundary effects + total_spins = len(pointing_spins) + start_fraction = 0.1 + end_fraction = 0.9 + start_idx = int(total_spins * start_fraction) + end_idx = int(total_spins * end_fraction) - 1 + + # Ensure we have valid indices + start_idx = max(0, start_idx) + end_idx = max(start_idx, min(end_idx, total_spins - 1)) + + available_spins = end_idx - start_idx + 1 + if available_spins <= n_spins: + # Use all available spins in the middle 80% if fewer than requested + selected_indices = np.arange(start_idx, end_idx + 1) + else: + # Select evenly-spaced indices from the middle 80% + selected_indices = np.linspace(start_idx, end_idx, n_spins, dtype=int) + + representative_spins = pointing_spins.iloc[selected_indices] + + logging.debug( + f"Selected {len(representative_spins)} representative spins from " + f"{total_spins} total spins in pointing period (using middle 80%)." + ) + + return representative_spins + + +def sample_boresight_bins( + spin_start_met: float, + spin_period: float, + n_samples: int = N_SAMPLES_PER_SPIN, +) -> tuple[np.ndarray, np.ndarray]: + """ + Sample the Lo boresight look direction throughout a single spin. + + Generates evenly-spaced time samples within a spin period, computes the + Lo boresight pointing direction in the IMAP_DPS frame, and returns the + spin_angle and off_angle for each sample. + + Parameters + ---------- + spin_start_met : float + The MET time at the start of the spin. + spin_period : float + The duration of the spin in seconds. + n_samples : int, optional + Number of time samples within the spin. Default is 4096. + + Returns + ------- + spin_angles : numpy.ndarray + Array of spin angles (0-360 degrees) for each sample time. + off_angles : numpy.ndarray + Array of off angles (elevation from DPS equatorial plane) for each sample. + """ + # Generate evenly-spaced sample times within the spin + # Use the center of each time bin for sampling + sample_fractions = (np.arange(n_samples) + 0.5) / n_samples + sample_mets = spin_start_met + sample_fractions * spin_period + + # Convert MET times to ephemeris time for SPICE + sample_ttj2000ns = met_to_ttj2000ns(sample_mets) + sample_ets = ttj2000ns_to_et(sample_ttj2000ns) + + # Get the Lo boresight pointing in the DPS frame + # lo_instrument_pointing returns (longitude, latitude) in degrees + # longitude corresponds to spin_angle, latitude corresponds to off_angle + # Use nominal pivot angle of 90 degrees which rotates boresight to point + # approximately in the spacecraft spin plane (near-zero off-pointing) + pointing = lo_instrument_pointing( + sample_ets, LO_NOMINAL_PIVOT_ANGLE, SpiceFrame.IMAP_DPS + ) + + # Extract spin_angle (longitude) and off_angle (latitude) + spin_angles = pointing[:, 0] + off_angles = pointing[:, 1] + + # Ensure spin angles are in [0, 360) range + spin_angles = np.mod(spin_angles, 360) + + return spin_angles, off_angles + + +def calculate_bin_weights(off_angles: np.ndarray) -> np.ndarray: + """ + Calculate the probability weight for each off_angle bin. + + Bins all sampled off angles into the 40-bin grid and normalizes + the counts to get probability weights that sum to 1. These weights + are applied uniformly across all spin_angle bins since the spacecraft + rotates evenly and we want smooth exposure across spin angles. + + Parameters + ---------- + off_angles : numpy.ndarray + Array of off angles (degrees) from all sampled times. + + Returns + ------- + bin_weights : numpy.ndarray + 1D array of shape (N_OFF_ANGLE_BINS,) containing the probability + weight for each off_angle bin. Weights sum to 1.0. + """ + # Create 1D histogram of off_angles only + bin_counts, _ = np.histogram(off_angles, bins=OFF_ANGLE_BIN_EDGES) + + # Normalize to get probability weights + total_samples = len(off_angles) + if total_samples > 0: + bin_weights = bin_counts / total_samples + else: + # If no samples, return zero weights + bin_weights = np.zeros(N_OFF_ANGLE_BINS, dtype=np.float32) + + return bin_weights + + +def create_goodtimes_fraction( + goodtimes_ds: xr.Dataset, + pointing_start_met: float, + pointing_end_met: float, +) -> np.ndarray: + """ + Create fractional weights for spin_angle bins and ESA steps based on good-times. + + The good-times ancillary file specifies which spin angle bins (in 6-degree + resolution) and ESA energy steps are valid during specific time periods. + This function calculates the fraction of the pointing duration that is + covered by good-times for each (ESA step, spin_angle bin) combination. + + Parameters + ---------- + goodtimes_ds : xarray.Dataset + Dataset containing the good-times data with variables: + gt_start_met, gt_end_met. + pointing_start_met : float + The start MET time of the pointing. + pointing_end_met : float + The end MET time of the pointing. + + Returns + ------- + goodtimes_fraction : numpy.ndarray + 2D array of shape (N_ESA_ENERGY_STEPS, N_SPIN_ANGLE_BINS) containing + the fraction of pointing duration covered by good-times for each + ESA step and spin angle bin. Values range from 0.0 to 1.0. + """ + total_pointing_duration = pointing_end_met - pointing_start_met + + # Initialize as all zeros (no good time) + goodtimes_fraction: np.ndarray = np.zeros( + (N_ESA_ENERGY_STEPS, N_SPIN_ANGLE_BINS), dtype=np.float32 + ) + + if total_pointing_duration <= 0: + logging.warning("Pointing duration is zero or negative.") + return goodtimes_fraction + + # Filter good-times to only those overlapping with the pointing period + pointing_goodtimes_mask = ( + (goodtimes_ds["gt_start_met"] < pointing_end_met) + & (goodtimes_ds["gt_end_met"] > pointing_start_met) + ).values + + if not pointing_goodtimes_mask.any(): + logging.warning( + f"No good-times found for pointing period " + f"[{pointing_start_met}, {pointing_end_met}]. " + "All exposure times will be zero." + ) + return goodtimes_fraction + + pointing_goodtimes = goodtimes_ds.isel(epoch=pointing_goodtimes_mask) + + # Process each good-time row and accumulate fractional coverage + for i in range(len(pointing_goodtimes["epoch"])): + row = pointing_goodtimes.isel(epoch=i) + + # Calculate the overlap between this good-time period and the pointing + goodtime_start = max(float(row["gt_start_met"]), pointing_start_met) + goodtime_end = min(float(row["gt_end_met"]), pointing_end_met) + overlap_duration = goodtime_end - goodtime_start + + if overlap_duration <= 0: + continue + + # Calculate fraction of pointing duration covered by this good-time + time_fraction = overlap_duration / total_pointing_duration + + # For each ESA step, accumulate the fractional coverage. + # Add this time fraction to the affected bins. + # Note that all ESA Levels and all N_SPIN_ANGLE_BINS currently get the + # same increment, pending algorithmic changes in the future. + goodtimes_fraction += time_fraction + + # Clip to [0, 1] in case of overlapping good-time periods + goodtimes_fraction = np.clip(goodtimes_fraction, 0.0, 1.0) + + # Calculate average coverage for logging + avg_coverage = goodtimes_fraction.mean() + logging.debug( + f"Good-times coverage: average={100 * avg_coverage:.1f}%, " + f"min={100 * goodtimes_fraction.min():.1f}%, " + f"max={100 * goodtimes_fraction.max():.1f}%" + ) + + return goodtimes_fraction + + +def calculate_exposure_times( + pointing_start_met: float, + pointing_end_met: float, + goodtimes_ds: xr.Dataset | None = None, + n_representative_spins: int = DEFAULT_N_REPRESENTATIVE_SPINS, +) -> xr.DataArray: + """ + Calculate exposure times using statistical off-pointing sampling. + + Samples the Lo boresight look direction across representative spins to + determine which spin_angle Γ— off_angle bins are observed. The total + pointing duration is then distributed across bins proportionally to + the observed probability weights. If good-times data is provided, + exposure times are zeroed for invalid spin_angle/ESA step combinations. + + Parameters + ---------- + pointing_start_met : float + The start MET time of the pointing. + pointing_end_met : float + The end MET time of the pointing. + goodtimes_ds : xarray.Dataset, optional + Dataset containing the good-times data. If provided, + exposure times will be zeroed for invalid spin_angle bins and ESA steps. + n_representative_spins : int, optional + Number of representative spins to sample. Default is 5. Returns ------- exposure_time : xarray.DataArray - The exposure times for the L1B Direct Event dataset. + The exposure times for each (esa_energy_step, spin_angle, off_angle) bin. + Shape is (1, N_ESA_ENERGY_STEPS, N_SPIN_ANGLE_BINS, N_OFF_ANGLE_BINS). """ - data = np.column_stack( - (l1b_de["esa_step"], l1b_de["pointing_bin_lon"], l1b_de["pointing_bin_lat"]) + # Calculate total pointing duration in seconds + total_pointing_duration = pointing_end_met - pointing_start_met + + if total_pointing_duration <= 0: + logging.warning( + "Pointing duration is zero or negative. Exposure times will be zero." + ) + # Return zero exposure times with correct shape and dimensions + zero_exposure: np.ndarray = np.zeros(PSET_SHAPE, dtype=np.float32) + return xr.DataArray( + data=zero_exposure, + dims=PSET_DIMS, + ) + + # Get representative spins from the pointing period + representative_spins = get_representative_spin_times( + pointing_start_met, pointing_end_met, n_representative_spins ) - result = binned_statistic_dd( - data, - # exposure time equation from Lo Alg Document 10.1.1.4 - 4 * l1b_de["avg_spin_durations"].to_numpy() / 3600, - statistic="mean", - # NOTE: The l1b pointing_bin_lon is bin number, not actual angle - bins=[ - np.arange(N_ESA_ENERGY_STEPS + 1), - np.arange(N_SPIN_ANGLE_BINS + 1), - np.arange(N_OFF_ANGLE_BINS + 1), - ], + # Collect all sampled spin angles and off angles across representative spins + all_spin_angles = [] + all_off_angles = [] + + for _, spin_row in representative_spins.iterrows(): + spin_start_met = spin_row["spin_start_met"] + spin_period = spin_row["actual_spin_period"] + + spin_angles, off_angles = sample_boresight_bins(spin_start_met, spin_period) + all_spin_angles.append(spin_angles) + all_off_angles.append(off_angles) + + # Concatenate all samples + all_spin_angles = np.concatenate(all_spin_angles) + all_off_angles = np.concatenate(all_off_angles) + + # Log statistics about the sampled angles for debugging + logging.debug( + f"Sampled angles - spin_angle: min={all_spin_angles.min():.2f}, " + f"max={all_spin_angles.max():.2f}, mean={all_spin_angles.mean():.2f}" + ) + logging.debug( + f"Sampled angles - off_angle: min={all_off_angles.min():.2f}, " + f"max={all_off_angles.max():.2f}, mean={all_off_angles.mean():.2f}" ) - stat = result.statistic[np.newaxis, :, :, :] + # Calculate bin probability weights for off_angle only + # We use 1D histogram on off_angle because discrete spin sampling creates + # artifacts, but the spacecraft rotates evenly so spin_angle exposure + # should be uniform + off_angle_weights = calculate_bin_weights(all_off_angles) + + # Calculate exposure time per ESA step + # Divide by N_ESA_ENERGY_STEPS because each ESA step is only active + # for 1/7 of the total pointing duration + # Divide by N_SPIN_ANGLE_BINS to distribute uniformly across spin angles + exposure_per_esa_step = total_pointing_duration / N_ESA_ENERGY_STEPS + exposure_per_spin_bin = exposure_per_esa_step / N_SPIN_ANGLE_BINS + + # Apply off_angle weights: each spin_angle bin gets the same off_angle distribution + # Shape: (N_SPIN_ANGLE_BINS, N_OFF_ANGLE_BINS) + exposure_per_bin = exposure_per_spin_bin * off_angle_weights[np.newaxis, :] + + # Broadcast exposure across ESA energy steps (each ESA step has the same + # geometric exposure pattern, but only 1/7 of the total time) + # Need to make a copy since we may modify it with good-times mask + exposure_3d = np.broadcast_to( + exposure_per_bin[np.newaxis, :, :], + (N_ESA_ENERGY_STEPS, N_SPIN_ANGLE_BINS, N_OFF_ANGLE_BINS), + ).copy() + + # Apply good-times fraction if provided + if goodtimes_ds is not None: + goodtimes_fraction = create_goodtimes_fraction( + goodtimes_ds, pointing_start_met, pointing_end_met + ) + # Expand fraction to include off_angle dimension + # (fraction is same for all off_angles) + # goodtimes_fraction shape: (N_ESA_ENERGY_STEPS, N_SPIN_ANGLE_BINS) + # exposure_3d shape: (N_ESA_ENERGY_STEPS, N_SPIN_ANGLE_BINS, N_OFF_ANGLE_BINS) + exposure_3d = exposure_3d * goodtimes_fraction[:, :, np.newaxis] + + logging.debug( + f"Applied good-times mask: exposure sum reduced from " + f"{(exposure_per_bin.sum() * N_ESA_ENERGY_STEPS):.1f}s to " + f"{exposure_3d.sum():.1f}s" + ) + + # Add epoch dimension + exposure_4d = exposure_3d[np.newaxis, :, :, :] exposure_time = xr.DataArray( - data=stat.astype(np.float16), + data=exposure_4d.astype(np.float32), dims=PSET_DIMS, ) + logging.debug( + f"Calculated exposure times: total duration={total_pointing_duration:.1f}s, " + f"sampled {len(representative_spins)} spins x {N_SAMPLES_PER_SPIN} samples, " + f"exposure sum={exposure_per_bin.sum():.1f}s" + ) + return exposure_time @@ -484,3 +1021,171 @@ def create_datasets( ) return dataset + + +def set_background_rates( + species: FilterType, + sci_dependencies: dict, + attr_mgr: ImapCdfAttributes, +) -> tuple[xr.DataArray, xr.DataArray, xr.DataArray]: + """ + Set the background rates for the specified species. + + Background rates and statistical uncertainties are read from the + ``imap_lo_l1b_bgrates`` dataset in ``sci_dependencies``. Each species + provides a 1-D array of shape ``(N_ESA_ENERGY_STEPS,)`` that is broadcast + uniformly across all spin-angle and off-angle bins. If the bgrates dataset + is absent, all arrays default to zero. + + Parameters + ---------- + species : FilterType + The species to set the background rates for. Can be "h" or "o". + sci_dependencies : dict + Science dependency datasets. Expected to contain the key + ``"imap_lo_l1b_bgrates"`` with variables + ``"{species}_background_rates"`` and ``"{species}_background_variance"``. + attr_mgr : ImapCdfAttributes + Attribute manager used to get the L1C attributes. + + Returns + ------- + background_rates : tuple[xr.DataArray, xr.DataArray, xr.DataArray] + Tuple containing: + - The background rates for the specified species. + - The statistical uncertainties for the background rates. + - The systematic errors for the background rates. + """ + if species not in {FilterType.HYDROGEN, FilterType.OXYGEN}: + raise ValueError(f"Species must be 'h' or 'o', but got {species.value}.") + + bg_rates: np.ndarray = np.zeros( + (N_ESA_ENERGY_STEPS, N_SPIN_ANGLE_BINS, N_OFF_ANGLE_BINS), + dtype=np.float16, + ) + bg_stat_uncert: np.ndarray = np.zeros( + (N_ESA_ENERGY_STEPS, N_SPIN_ANGLE_BINS, N_OFF_ANGLE_BINS), + dtype=np.float16, + ) + bg_sys_err: np.ndarray = np.zeros( + (N_ESA_ENERGY_STEPS, N_SPIN_ANGLE_BINS, N_OFF_ANGLE_BINS), + dtype=np.float16, + ) + + bgrates_ds = sci_dependencies.get("imap_lo_l1b_bgrates") + if bgrates_ds is not None: + species_key = species.value + rate_field = f"{species_key}_background_rates" + variance_field = f"{species_key}_background_variance" + + if rate_field in bgrates_ds: + rates_per_esa = bgrates_ds[ + rate_field + ].values # shape: (N_ESA_ENERGY_STEPS,) + bg_rates = np.broadcast_to( + rates_per_esa[:, np.newaxis, np.newaxis], + (N_ESA_ENERGY_STEPS, N_SPIN_ANGLE_BINS, N_OFF_ANGLE_BINS), + ).astype(np.float16) + + if variance_field in bgrates_ds: + var_per_esa = bgrates_ds[ + variance_field + ].values # shape: (N_ESA_ENERGY_STEPS,) + bg_stat_uncert = np.broadcast_to( + var_per_esa[:, np.newaxis, np.newaxis], + (N_ESA_ENERGY_STEPS, N_SPIN_ANGLE_BINS, N_OFF_ANGLE_BINS), + ).astype(np.float16) + + bg_rates_data = xr.DataArray( + data=bg_rates[np.newaxis, :, :, :], + dims=["epoch", "esa_energy_step", "spin_angle", "off_angle"], + attrs=attr_mgr.get_variable_attributes(f"{species.value}_background_rates"), + ) + bg_stat_uncert_data = xr.DataArray( + data=bg_stat_uncert[np.newaxis, :, :, :], + dims=["epoch", "esa_energy_step", "spin_angle", "off_angle"], + attrs=attr_mgr.get_variable_attributes( + f"{species.value}_background_rates_stat_uncert" + ), + ) + bg_sys_err_data = xr.DataArray( + data=bg_sys_err[np.newaxis, :, :, :], + dims=["epoch", "esa_energy_step", "spin_angle", "off_angle"], + attrs=attr_mgr.get_variable_attributes( + f"{species.value}_background_rates_sys_err" + ), + ) + + return bg_rates_data, bg_stat_uncert_data, bg_sys_err_data + + +def set_pointing_directions( + epoch: float, + attr_mgr: ImapCdfAttributes, + pivot_angle: float, +) -> tuple[xr.DataArray, xr.DataArray]: + """ + Set the pointing directions for the given epoch. + + The pointing directions are calculated by transforming Spin and off angles + to HAE longitude and latitude using SPICE. This returns the HAE longitude and + latitude as (3600, 40) arrays for each the latitude and longitude. + + Parameters + ---------- + epoch : float + The epoch time in TTJ2000ns. + attr_mgr : ImapCdfAttributes + Attribute manager used to get the L1C attributes. + pivot_angle : float + The pivot angle in degrees. + Off-angles are adjusted relative to this pivot angle before transformation. + + Returns + ------- + hae_longitude : xr.DataArray + The HAE longitude for each spin and off angle bin. + hae_latitude : xr.DataArray + The HAE latitude for each spin and off angle bin. + """ + # Handle case where epoch is empty + if epoch == met_to_ttj2000ns(0): + return xr.DataArray( + data=np.zeros( + (1, len(SPIN_ANGLE_BIN_CENTERS), len(OFF_ANGLE_BIN_CENTERS)), + dtype=np.float64, + ), + dims=["epoch", "spin_angle", "off_angle"], + attrs=attr_mgr.get_variable_attributes("hae_longitude"), + ), xr.DataArray( + data=np.zeros( + (1, len(SPIN_ANGLE_BIN_CENTERS), len(OFF_ANGLE_BIN_CENTERS)), + dtype=np.float64, + ), + dims=["epoch", "spin_angle", "off_angle"], + attrs=attr_mgr.get_variable_attributes("hae_latitude"), + ) + + et = ttj2000ns_to_et(epoch) + # create a meshgrid of spin and off angles using the bin centers + spin, off = np.meshgrid( + SPIN_ANGLE_BIN_CENTERS, OFF_ANGLE_BIN_CENTERS, indexing="ij" + ) + # off_angles need to account for the pivot_angle + off += 90 - pivot_angle + dps_az_el = np.stack([spin, off], axis=-1) + + # Transform from DPS Az/El to HAE lon/lat + hae_az_el = frame_transform_az_el( + et, dps_az_el, SpiceFrame.IMAP_DPS, SpiceFrame.IMAP_HAE, degrees=True + ) + + return xr.DataArray( + data=hae_az_el[np.newaxis, :, :, 0].astype(np.float64), + dims=["epoch", "spin_angle", "off_angle"], + attrs=attr_mgr.get_variable_attributes("hae_longitude"), + ), xr.DataArray( + data=hae_az_el[np.newaxis, :, :, 1].astype(np.float64), + dims=["epoch", "spin_angle", "off_angle"], + attrs=attr_mgr.get_variable_attributes("hae_latitude"), + ) diff --git a/imap_processing/lo/l2/lo_l2.py b/imap_processing/lo/l2/lo_l2.py index 3e808df7d6..b6af437d98 100644 --- a/imap_processing/lo/l2/lo_l2.py +++ b/imap_processing/lo/l2/lo_l2.py @@ -1,213 +1,1414 @@ """IMAP-Lo L2 data processing.""" +import logging +from pathlib import Path +from typing import cast + import numpy as np +import pandas as pd import xarray as xr from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes from imap_processing.ena_maps import ena_maps from imap_processing.ena_maps.ena_maps import AbstractSkyMap, RectangularSkyMap +from imap_processing.ena_maps.utils.corrections import ( + PowerLawFluxCorrector, + apply_compton_getting_correction, + calculate_ram_mask, + get_pset_directional_mask, + interpolate_map_flux_to_helio_frame, +) from imap_processing.ena_maps.utils.naming import MapDescriptor +from imap_processing.lo import lo_ancillary +from imap_processing.spice.time import et_to_datetime64, ttj2000ns_to_et + +logger = logging.getLogger(__name__) + +# ============================================================================= +# MAIN ENTRY POINT +# ============================================================================= def lo_l2( sci_dependencies: dict, anc_dependencies: list, descriptor: str ) -> list[xr.Dataset]: """ - Will process IMAP-Lo L1C data into Le CDF data products. + Process IMAP-Lo L1C data into L2 CDF data products. + + This is the main entry point for L2 processing. It orchestrates the entire + processing pipeline from L1C pointing sets to L2 sky maps with intensities. Parameters ---------- sci_dependencies : dict Dictionary of datasets needed for L2 data product creation in xarray Datasets. + Must contain "imap_lo_l1c_pset" key with list of pointing set datasets. + anc_dependencies : list + List of ancillary file paths needed for L2 data product creation. + Should include efficiency factor files. + descriptor : str + The map descriptor to be produced + (e.g., "ilo90-ena-h-sf-nsp-full-hae-6deg-3mo"). + + Returns + ------- + list[xr.Dataset] + List containing the processed L2 dataset with rates, intensities, + and uncertainties. + + Raises + ------ + ValueError + If no pointing set data found in science dependencies. + NotImplementedError + If HEALPix map output is requested (only rectangular maps supported). + """ + logger.info("Starting IMAP-Lo L2 processing pipeline") + if "imap_lo_l1c_pset" not in sci_dependencies: + raise ValueError("No pointing set data found in science dependencies") + psets = sci_dependencies["imap_lo_l1c_pset"] + + # Parse the map descriptor to get species and other attributes + map_descriptor = MapDescriptor.from_string(descriptor) + logger.info(f"Processing map for species: {map_descriptor.species}") + + # Determine if corrections are needed and prepare oxygen data if required + ( + sputtering_correction, + bootstrap_correction, + flux_correction, + o_map_dataset, + flux_factors, + cg_correction, + ) = _prepare_corrections( + map_descriptor, descriptor, sci_dependencies, anc_dependencies + ) + + logger.info("Step 1: Loading ancillary data") + efficiency_data = load_efficiency_data(anc_dependencies) + + logger.info(f"Step 2: Creating sky map from {len(psets)} pointing sets") + sky_map = create_sky_map_from_psets( + psets, map_descriptor, efficiency_data, cg_correction + ) + + logger.info("Step 3: Converting to dataset and adding geometric factors") + dataset = sky_map.to_dataset() + dataset = add_geometric_factors(dataset, map_descriptor.species) + + logger.info("Step 4: Calculating rates and intensities") + dataset = calculate_all_rates_and_intensities( + dataset, + sputtering_correction=sputtering_correction, + bootstrap_correction=bootstrap_correction, + flux_correction=flux_correction, + o_map_dataset=o_map_dataset, + flux_factors=flux_factors, + cg_correction=cg_correction, + ) + + logger.info("Step 5: Finalizing dataset with attributes") + dataset = cast(RectangularSkyMap, sky_map).build_cdf_dataset( + instrument="lo", level="l2", descriptor=descriptor, external_map_dataset=dataset + ) + + logger.info("IMAP-Lo L2 processing pipeline completed successfully") + return [dataset] + + +def _prepare_corrections( + map_descriptor: MapDescriptor, + descriptor: str, + sci_dependencies: dict, + anc_dependencies: list, +) -> tuple[bool, bool, bool, xr.Dataset | None, Path | None, bool]: + """ + Determine what corrections are needed and prepare oxygen dataset if required. + + This helper function encapsulates the logic for determining when sputtering + and bootstrap corrections should be applied, and handles the creation of + the oxygen dataset needed for sputtering corrections. + + Parameters + ---------- + map_descriptor : MapDescriptor + The parsed map descriptor containing species and data type information. + descriptor : str + The original descriptor string for creating the oxygen variant. + sci_dependencies : dict + Dictionary of datasets needed for L2 data product creation. + anc_dependencies : list + List of ancillary file paths. + + Returns + ------- + tuple[bool, bool, bool, xr.Dataset | None, Path | None, bool] + A tuple containing: + - sputtering_correction: Whether to apply sputtering corrections + - bootstrap_correction: Whether to apply bootstrap corrections + - flux_correction: Whether to apply flux corrections + - o_map_dataset: Oxygen dataset if needed, None otherwise + - flux_factors: Path to flux factors ancillary file if needed, + None otherwise + - cg_correction: Whether to apply CG correction to the dataset. + """ + # Default values - no corrections needed + sputtering_correction = False + bootstrap_correction = False + flux_correction = False + o_map_dataset = None + flux_factors: None | Path = None + + # Sputtering and bootstrap corrections are only applied to hydrogen ENA data + # Guard against recursion: don't process oxygen for oxygen maps + if ( + map_descriptor.species == "h" + and map_descriptor.principal_data == "ena" + and "-o-" not in descriptor + ): # Safety check to prevent infinite recursion + logger.info("Creating map for oxygen for sputtering corrections") + o_descriptor = descriptor.replace("-h-", "-o-") + o_map_dataset = lo_l2(sci_dependencies, anc_dependencies, o_descriptor)[0] + sputtering_correction = True + bootstrap_correction = True + + if "raw" not in map_descriptor.principal_data: + flux_correction = True + try: + flux_factors = next( + x for x in anc_dependencies if "esa-eta-fit-factors" in str(x) + ) + except StopIteration: + raise ValueError( + "No flux correction factor file found in ancillary dependencies" + ) from None + + cg_correction = True if map_descriptor.frame_descriptor == "hf" else False + + return ( + sputtering_correction, + bootstrap_correction, + flux_correction, + o_map_dataset, + flux_factors, + cg_correction, + ) + + +# ============================================================================= +# SETUP AND INITIALIZATION HELPERS +# ============================================================================= + + +def load_efficiency_data(anc_dependencies: list) -> pd.DataFrame: + """ + Load efficiency factor data from ancillary files. + + Parameters + ---------- anc_dependencies : list - Ancillary files needed for L2 data product creation. + List of ancillary file paths to search for efficiency factor files. + + Returns + ------- + pd.DataFrame + Concatenated efficiency factor data from all matching files. + Returns empty DataFrame if no efficiency files found. + """ + efficiency_files = [ + anc_file + for anc_file in anc_dependencies + if "efficiency-factor" in str(anc_file) + ] + + if not efficiency_files: + logger.warning("No efficiency factor files found in ancillary dependencies") + return pd.DataFrame() + + logger.debug(f"Loading {len(efficiency_files)} efficiency factor files") + return pd.concat( + [lo_ancillary.read_ancillary_file(anc_file) for anc_file in efficiency_files], + ignore_index=True, + ) + + +def load_sputter_correction_data( + source_species: str, target_species: str +) -> pd.DataFrame: + """ + Load sputter correction factors from an ancillary file. + + Parameters + ---------- + source_species : str + The species doing the sputtering (e.g. "o" for oxygen). + target_species : str + The species being corrected (e.g. "h" for hydrogen). + + Returns + ------- + pd.DataFrame + Rows matching the given species pair, sorted ascending by esa_step, + with columns: source_species, target_species, esa_step, + sputter_factor, sputter_factor_uncertainty. + """ + anc_path = Path(__file__).parent.parent / "ancillary_data" + sputter_files = sorted(anc_path.glob("*sputter-correction-factors*")) + + if not sputter_files: + raise ValueError("No sputter correction files found") + + df = pd.concat( + [lo_ancillary.read_ancillary_file(f) for f in sputter_files], + ignore_index=True, + ) + mask = (df["source_species"] == source_species) & ( + df["target_species"] == target_species + ) + result = df[mask].sort_values("esa_step").reset_index(drop=True) + return result + + +def load_bootstrap_correction_data() -> pd.DataFrame: + """ + Load bootstrap correction factors from an ancillary file. + + Returns + ------- + pd.DataFrame + Bootstrap correction factors with columns: esa_step_i, esa_step_k, + bootstrap_factor. Indices are 1-based ESA step numbers where esa_step_k=8 + refers to the virtual E8 channel. + """ + anc_path = Path(__file__).parent.parent / "ancillary_data" + bootstrap_files = sorted(anc_path.glob("*bootstrap-correction-factors*")) + + if not bootstrap_files: + raise ValueError("No bootstrap correction factor files found") + + return pd.concat( + [lo_ancillary.read_ancillary_file(f) for f in bootstrap_files], + ignore_index=True, + ) + + +def finalize_dataset(dataset: xr.Dataset, descriptor: str) -> xr.Dataset: + """ + Add attributes and perform final dataset preparation. + + Parameters + ---------- + dataset : xr.Dataset + The dataset to finalize with attributes. descriptor : str - The map descriptor to be produced. + The descriptor for this map dataset. Returns ------- - created_file_paths : list[Path] - Location of created CDF files. + xr.Dataset + The finalized dataset with all attributes added. """ - # create the attribute manager for this data level + # Initialize the attribute manager attr_mgr = ImapCdfAttributes() attr_mgr.add_instrument_global_attrs(instrument="lo") attr_mgr.add_instrument_variable_attrs(instrument="enamaps", level="l2-common") attr_mgr.add_instrument_variable_attrs(instrument="enamaps", level="l2-rectangular") - # if the dependencies are used to create Annotated Direct Events - if "imap_lo_l1c_pset" in sci_dependencies: - logical_source = "imap_lo_l2_l090-ena-h-sf-nsp-ram-hae-6deg-3mo" - psets = sci_dependencies["imap_lo_l1c_pset"] + # Add global and variable attributes + dataset.attrs.update(attr_mgr.get_global_attributes("imap_lo_l2_enamap")) - # Create an AbstractSkyMap (Rectangular or HEALPIX) from the pointing set - lo_sky_map = project_pset_to_sky_map(psets, descriptor) - if not isinstance(lo_sky_map, RectangularSkyMap): - raise NotImplementedError("HEALPix map output not supported for Lo") + # Our global attributes have placeholders for descriptor + # so iterate through here and fill that in with the map-specific descriptor + for key in ["Data_type", "Logical_source", "Logical_source_description"]: + dataset.attrs[key] = dataset.attrs[key].format(descriptor=descriptor) + for var in dataset.data_vars: + try: + dataset[var].attrs = attr_mgr.get_variable_attributes(var) + except KeyError: + # If no attributes found, try without schema validation + try: + dataset[var].attrs = attr_mgr.get_variable_attributes( + var, check_schema=False + ) + except KeyError: + logger.warning(f"No attributes found for variable {var}") - # Add the hydrogen rates to the rectangular map dataset. - lo_sky_map.data_1d["h_rate"] = calculate_rates( - lo_sky_map.data_1d["h_counts"], lo_sky_map.data_1d["exposure_time"] - ) - # Add the hydrogen flux to the rectangular map dataset. - lo_sky_map.data_1d["h_flux"] = calculate_fluxes(lo_sky_map.data_1d["h_rate"]) - # Create the dataset from the rectangular map. - lo_rect_map_ds = lo_sky_map.to_dataset() - # Add the attributes to the dataset. - lo_rect_map_ds = add_attributes( - lo_rect_map_ds, attr_mgr, logical_source=logical_source - ) + return dataset - return [lo_rect_map_ds] +# ============================================================================= +# SKY MAP CREATION PIPELINE +# ============================================================================= -def project_pset_to_sky_map(psets: list[xr.Dataset], descriptor: str) -> AbstractSkyMap: - """ - Project the pointing set to a sky map. - This function is used to create a sky map from the pointing set - data in the L1C dataset. +def create_sky_map_from_psets( + psets: list[xr.Dataset], + map_descriptor: MapDescriptor, + efficiency_data: pd.DataFrame, + cg_correct: bool, +) -> AbstractSkyMap: + """ + Create a sky map by processing all pointing sets. Parameters ---------- psets : list[xr.Dataset] - List of pointing sets in xarray Dataset format. - descriptor : str - The map descriptor for the map to be produced, - contains details about the map projection. + List of pointing set datasets to process. + map_descriptor : MapDescriptor + Map descriptor object defining the projection and binning. + efficiency_data : pd.DataFrame + Efficiency factor data for correcting counts. + cg_correct : bool + Whether to apply the CG correction to each PSET. Returns ------- AbstractSkyMap - The sky map created from the pointing set data. + The populated sky map with projected data from all pointing sets. + + Raises + ------ + NotImplementedError + If HEALPix map output is requested (only rectangular maps supported). """ - map_descriptor = MapDescriptor.from_string(descriptor) + # Initialize the output map output_map = map_descriptor.to_empty_map() - for pset in psets: - lo_pset = ena_maps.LoPointingSet(pset) - output_map.project_pset_values_to_map( - pointing_set=lo_pset, - value_keys=["h_counts", "exposure_time"], - index_match_method=ena_maps.IndexMatchMethod.PUSH, + if not isinstance(output_map, RectangularSkyMap): + raise NotImplementedError("HEALPix map output not supported for Lo") + + logger.debug(f"Processing {len(psets)} pointing sets") + # Process each pointing set + for i, pset in enumerate(psets): + logger.debug(f"Processing pointing set {i + 1}/{len(psets)}") + processed_pset = process_single_pset( + pset, + efficiency_data, + map_descriptor.species, + cg_correct, ) + directional_mask = get_pset_directional_mask( + processed_pset, map_descriptor.spin_phase + ) + project_pset_to_map(processed_pset, output_map, directional_mask, cg_correct) + return output_map -def calculate_rates(counts: xr.DataArray, exposure_time: xr.DataArray) -> xr.DataArray: +def process_single_pset( + pset: xr.Dataset, + efficiency_data: pd.DataFrame, + species: str, + cg_correct: bool = False, +) -> xr.Dataset: """ - Calculate the hydrogen rates from the counts and exposure time. + Process a single pointing set for projection to the sky map. Parameters ---------- - counts : xr.DataArray - The counts of hydrogen or oxygen ENAs. - exposure_time : xr.DataArray - The exposure time for the counts. + pset : xr.Dataset + Single pointing set dataset to process. + efficiency_data : pd.DataFrame + Efficiency factor data for correcting counts. + species : str + The species to process (e.g., "h", "o"). + cg_correct : bool + Whether to apply the CG correction to each PSET. A value of True will + cause the pre-projection Compton Getting Correction to be applied to + the PSET data. Returns ------- - xr.DataArray - The calculated hydrogen rates. + xr.Dataset + Processed pointing set ready for projection with efficiency corrections applied. """ - # Calculate the rates based on the h_counts and exposure_time - rate = counts / exposure_time - return rate + # Step 1: Normalize coordinate system + pset_processed = normalize_pset_coordinates(pset, species) + + # Step 2: Add efficiency factors + pset_processed = add_efficiency_factors_to_pset(pset_processed, efficiency_data) + + # Step 3: Calculate efficiency-corrected quantities + pset_processed = calculate_efficiency_corrected_quantities(pset_processed) + # Step 4: Optionally apply CG correction and calculate ram-mask + if cg_correct: + # NOTE: Heliospheric frame energy selection for CG correction + # The heliospheric (HF) energies passed to the CG correction algorithm + # could in principle be completely different from the ESA central energies. + # However, for Lo, the instrument team has chosen to use the same HF + # energies as the ESA central energies (from the geometric factor files). + # This decision aligns the energy grid between the spacecraft frame and + # heliospheric frame representations. -def calculate_fluxes(rates: xr.DataArray) -> xr.DataArray: + # Convert energy coordinate from keV to eV for CG correction + # (energy coordinate was set in normalize_pset_coordinates in keV) + energy_values_ev: xr.DataArray = pset_processed["energy"] * 1000.0 + pset_processed = apply_compton_getting_correction( + pset_processed, energy_values_ev + ) + # Prepare energy_sc for exposure time weighted projection + pset_processed["energy_sc_exposure_factor"] = ( + pset_processed["energy_sc"] * pset_processed["exposure_factor"] + ) + + # Always calculate ram-mask to identify ram/anti-ram bins + pset_processed = calculate_ram_mask(pset_processed) + + return pset_processed + + +def normalize_pset_coordinates(pset: xr.Dataset, species: str) -> xr.Dataset: """ - Calculate the flux from the hydrogen rate. + Normalize pointing set coordinates to match the output map. Parameters ---------- - rates : xr.Dataset - The hydrogen or oxygen rates. + pset : xr.Dataset + Input pointing set dataset with potentially mismatched coordinates. + species : str + The species to process (e.g., "h", "o"). Returns ------- - xr.DataArray - The calculated flux. + xr.Dataset + Pointing set with normalized energy coordinates and dimension names. """ - # Temporary values. These will all come from ancillary data when - # the data is available and integrated. - geometric_factor = 1.0 - efficiency_factor = 1.0 - energy_dict = {1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7} - energies = np.array([energy_dict[i] for i in range(1, 8)]) - energies = energies.reshape(1, 7, 1) + # Load true energy values for this species (in keV, matching map convention) + # TODO: Figure out how to handle esa_mode properly + if "esa_mode" in pset: + esa_mode = pset["esa_mode"].values[0] + else: + # Default to mode 0 if not available (HiRes mode) + esa_mode = 0 + gf_dataset = reduce_geometric_factor_dataset(species, esa_mode=esa_mode) + + # Ensure consistent energy coordinates (maps want energy not esa_energy_step) + pset_renamed = pset.rename_dims({"esa_energy_step": "energy"}) + + # Drop the esa_energy_step coordinate first to avoid conflicts + pset_renamed = pset_renamed.drop_vars("esa_energy_step") + + # Assign TRUE energy values as coordinates (in keV, matching map convention) + pset_renamed = pset_renamed.assign_coords(energy=gf_dataset["Cntr_E"].values) + + # Rename the variables in the pset for projection to the map + # L2 wants different variable names than l1c + rename_map = { + "exposure_time": "exposure_factor", + f"{species}_counts": "counts", + f"{species}_background_rates": "bg_rate", + f"{species}_background_rates_stat_uncert": "bg_rate_stat_uncert", + } + pset_renamed = pset_renamed.rename_vars(rename_map) - flux = rates / (geometric_factor * energies * efficiency_factor) - return flux + return pset_renamed -def add_attributes( - lo_map: xr.Dataset, attr_mgr: ImapCdfAttributes, logical_source: str +def add_efficiency_factors_to_pset( + pset: xr.Dataset, efficiency_data: pd.DataFrame ) -> xr.Dataset: """ - Add attributes to the map dataset. + Add efficiency factors to the pointing set based on observation date. Parameters ---------- - lo_map : xr.Dataset - The dataset to add attributes to. - attr_mgr : ImapCdfAttributes - The attribute manager to use for adding attributes. - logical_source : str - The logical source for the dataset. + pset : xr.Dataset + Pointing set dataset to add efficiency factors to. + efficiency_data : pd.DataFrame + Efficiency factor data containing date-indexed efficiency values. Returns ------- xr.Dataset - The dataset with added attributes. + Pointing set with efficiency factors added as new data variable. + + Raises + ------ + ValueError + If no efficiency factor found for the pointing set observation date. """ - # Add the global attributes to the dataset. - lo_map.attrs.update(attr_mgr.get_global_attributes(logical_source)) + if efficiency_data.empty: + # If no efficiency data, create unity efficiency + logger.warning("No efficiency data available, using unity efficiency") + pset["efficiency"] = xr.DataArray(np.ones(7), dims=["energy"]) + return pset - # TODO: Lo is using different field names than what's in the attributes. - # check if the Lo should use exposure factor instead of exposure time. - # check if hydrogen and oxygen specific ena intensities should be added - # to the attributes or if general ena intensities can be used or updated - # in the code. This dictionary is temporary solution for SIT-4 - map_fields = { - "epoch": "epoch", - "h_flux": "ena_intensity", - "h_rate": "ena_rate", - "h_counts": "ena_count", - "exposure_time": "exposure_factor", - "energy": "energy", - "solid_angle": "solid_angle", - "longitude": "longitude", - "latitude": "latitude", - } + # Convert the epoch to datetime64 + date = et_to_datetime64(ttj2000ns_to_et(pset["epoch"].values[0])) + # The efficiency file only has date as YYYYDDD, so drop the time for this + date = date.astype("M8[D]") # Convert to date only (no time) - # TODO: The mapping utility is supposed to handle at least some of these - # attributes but is not working. Need to investigate this after SIT-4 - # Add the attributes to the dataset variables. - for field, attr_name in map_fields.items(): - if field in lo_map.data_vars or field in lo_map.coords: - lo_map[field].attrs.update( - attr_mgr.get_variable_attributes(attr_name, check_schema=False) - ) + ef_df = efficiency_data[efficiency_data["Date"] == date] + if ef_df.empty: + raise ValueError(f"No efficiency factor found for pset date {date}") + + efficiency_values = ef_df[ + [ + "E-Step1_eff", + "E-Step2_eff", + "E-Step3_eff", + "E-Step4_eff", + "E-Step5_eff", + "E-Step6_eff", + "E-Step7_eff", + ] + ].values[0] + + pset["efficiency"] = xr.DataArray( + efficiency_values, + dims=["energy"], + ) + logger.debug(f"Applied efficiency factors for date {date}") + return pset + + +def calculate_efficiency_corrected_quantities( + pset: xr.Dataset, +) -> xr.Dataset: + """ + Calculate efficiency-corrected quantities for each particle type. + + Parameters + ---------- + pset : xr.Dataset + Pointing set with efficiency factors applied. + + Returns + ------- + xr.Dataset + Pointing set with efficiency-corrected count variables added. + """ + # counts / efficiency + pset["counts_over_eff"] = pset["counts"] / pset["efficiency"] + # counts / efficiency**2 (for variance propagation) + pset["counts_over_eff_squared"] = pset["counts"] / (pset["efficiency"] ** 2) + + # background * exposure_factor for weighted average + pset["bg_rate_exposure_factor"] = pset["bg_rate"] * pset["exposure_factor"] + # background_uncertainty ** 2 * exposure_factor ** 2 + pset["bg_rate_stat_uncert_exposure_factor2"] = ( + pset["bg_rate_stat_uncert"] ** 2 * pset["exposure_factor"] ** 2 + ) + + return pset + + +def project_pset_to_map( + pset: xr.Dataset, + output_map: AbstractSkyMap, + directional_mask: xr.DataArray, + cg_correct: bool = False, +) -> None: + """ + Project pointing set data to the output map. + + Parameters + ---------- + pset : xr.Dataset + Processed pointing set ready for projection. + output_map : AbstractSkyMap + Target sky map to receive the projected data. + directional_mask : xr.DataArray + Boolean mask indicating which PSET bins to use for projection. This is + how ram/anti-ram bins are removed depending on the descriptor spin phase. + cg_correct : bool + Whether the CG correction is being applied. If set to True, "energy_sc" + is added to the list of variables to be projected. + + Returns + ------- + None + Function modifies output_map in place. + """ + # Define base quantities to project + value_keys = [ + "exposure_factor", + "counts", + "counts_over_eff", + "counts_over_eff_squared", + "bg_rate", + "bg_rate_stat_uncert", + "bg_rate_exposure_factor", + "bg_rate_stat_uncert_exposure_factor2", + ] + if cg_correct: + value_keys.append("energy_sc_exposure_factor") + + # Create LoPointingSet and project to map + lo_pset = ena_maps.LoPointingSet(pset) + output_map.project_pset_values_to_map( + pointing_set=lo_pset, + value_keys=value_keys, + index_match_method=ena_maps.IndexMatchMethod.PUSH, + pset_valid_mask=directional_mask, + ) + logger.debug(f"Projected {len(value_keys)} quantities to sky map") + + +# ============================================================================= +# GEOMETRIC FACTORS +# ============================================================================= + + +def add_geometric_factors(dataset: xr.Dataset, species: str) -> xr.Dataset: + """ + Add geometric factors to the sky map after projection. + + Parameters + ---------- + dataset : xr.Dataset + Sky map dataset to add geometric factors to. + species : str + The species to process (only "h" and "o" have geometric factors). + + Returns + ------- + xr.Dataset + Dataset with geometric factor variables added for the specified species. + """ + # Only add geometric factors for hydrogen and oxygen + if species not in ["h", "o"]: + logger.warning(f"No geometric factors to add for species: {species}") + return dataset + + logger.info(f"Loading and applying geometric factors for species: {species}") + + # Initialize geometric factor variables + dataset = initialize_geometric_factor_variables(dataset) + + # Populate geometric factors for each energy step + dataset = populate_geometric_factors(dataset, species) + + return dataset + + +def load_geometric_factor_data(species: str) -> pd.DataFrame: + """ + Load geometric factor data for the specified species. + + Parameters + ---------- + species : str + The species to load geometric factors for ("h" or "o"). + + Returns + ------- + pd.DataFrame + Geometric factor dataframe for the specified species. + + Raises + ------ + ValueError + If species is not "h" or "o". + """ + if species not in ["h", "o"]: + raise ValueError( + f"Geometric factors only available for 'h' and 'o', got '{species}'" + ) + + anc_path = Path(__file__).parent.parent / "ancillary_data" + + if species == "h": + gf_file = anc_path / "imap_lo_hydrogen-geometric-factor_v001.csv" + else: # species == "o" + gf_file = anc_path / "imap_lo_oxygen-geometric-factor_v001.csv" + + return lo_ancillary.read_ancillary_file(gf_file) + + +def reduce_geometric_factor_dataset(species: str, esa_mode: int) -> xr.Dataset: + """ + Get geometric factor data as xarray Dataset for a specific species and ESA mode. + + This helper function loads geometric factor data, filters by ESA mode, converts + to xarray, and selects all 7 energy steps for vectorized operations. + + Parameters + ---------- + species : str + The species to load geometric factors for ("h" or "o"). + esa_mode : int + ESA mode (0 for HiRes, 1 for HiThr). + + Returns + ------- + xarray.Dataset + Geometric factor data indexed by Observed_E-Step (1-7), containing all + columns from the geometric factor CSV file. + """ + # Load geometric factor data for this species + gf_data = load_geometric_factor_data(species) + + # Filter for the specific ESA mode + if "esa_mode" in gf_data.columns: + gf_data = gf_data[gf_data["esa_mode"] == esa_mode].copy() + + # Convert to xarray Dataset indexed by energy step for vectorized selection + gf_ds = gf_data.set_index("Observed_E-Step").to_xarray() + + # Lo Instrument team: Use only geometric factors where + # incident_E-Step == Observed_E-Step + gf_ds = gf_ds.where(gf_ds["incident_E-Step"] == gf_ds["Observed_E-Step"], drop=True) + + # Select energy steps 1-7 and return + return gf_ds.sel({"Observed_E-Step": range(1, 8)}) + + +def initialize_geometric_factor_variables( + dataset: xr.Dataset, +) -> xr.Dataset: + """ + Initialize geometric factor variables for the specified species. - labels = { - "energy": np.arange(1, 8).astype(str), - "longitude": lo_map["longitude"].values.astype(str), - "latitude": lo_map["latitude"].values.astype(str), + Parameters + ---------- + dataset : xr.Dataset + Input dataset to add geometric factor variables to. + + Returns + ------- + xr.Dataset + Dataset with initialized geometric factor variables for the specified species. + """ + gf_vars = [ + "energy", + "energy_delta_minus", + "energy_delta_plus", + "geometric_factor", + "geometric_factor_stat_uncert", + ] + + # Initialize variables with proper dimensions (energy only) + for var in gf_vars: + dataset[var] = xr.DataArray( + np.zeros(7), + dims=["energy"], + ) + + return dataset + + +def populate_geometric_factors( + dataset: xr.Dataset, + species: str, +) -> xr.Dataset: + """ + Populate geometric factor values for each energy step. + + Parameters + ---------- + dataset : xr.Dataset + Dataset with initialized geometric factor variables. + species : str + The species to process (only "h" and "o" have geometric factors). + + Returns + ------- + xr.Dataset + Dataset with populated geometric factor values for the specified species. + """ + # Only populate if the species has geometric factors + if species not in ["h", "o"]: + logger.debug(f"No geometric factors to populate for species: {species}") + return dataset + + # Mapping of dataset variables to dataframe columns for this species + gf_coords = {"energy": "Cntr_E"} + gf_vars = { + "geometric_factor": f"GF_Trpl_{species.upper()}", + "geometric_factor_stat_uncert": f"GF_Trpl_{species.upper()}_unc", } - # add the coordinate labels to the dataset - for dim, values in labels.items(): - lo_map = lo_map.assign_coords( - { - f"{dim}_label": xr.DataArray( - values, - name=f"{dim}_label", - dims=[dim], - attrs=attr_mgr.get_variable_attributes( - f"{dim}_label", check_schema=False - ), - ) - } + if species == "h": + # NOTE: From an e-mail from Nathan on 2025-09-11 (values converted to keV) + energy_delta_hires_values = ( + np.array([5.43, 10.02, 18.61, 33.31, 64.98, 131.64, 262.35]) * 1e-3 + ) + energy_delta_hithr_values = ( + np.array([8.81, 16.04, 28.50, 53.13, 105.60, 219.67, 413.60]) * 1e-3 + ) + else: # species == "o" + energy_delta_hires_values = ( + np.array([5.82, 11.10, 21.78, 41.47, 85.61, 180.67, 361.93]) * 1e-3 + ) + energy_delta_hithr_values = ( + np.array([9.45, 17.84, 33.51, 66.61, 139.95, 302.24, 569.48]) * 1e-3 + ) + + # Get ESA mode from the map (assuming it's constant or we take the first) + # TODO: Figure out how to handle esa_mode properly + if "esa_mode" in dataset: + esa_mode = dataset["esa_mode"].values[0] + else: + # Default to mode 0 if not available (HiRes mode) + esa_mode = 0 + + # Filter for the specific ESA mode + gf_dataset = reduce_geometric_factor_dataset(species, esa_mode) + + # Populate geometric factors in dataset + dataset = dataset.assign_coords(energy=gf_dataset[gf_coords["energy"]].values) + for var, col in gf_vars.items(): + dataset[var].values = gf_dataset[col].values + + # Update delta_minus and delta_plus based on ESA mode + # converting eV to keV + if esa_mode == 0: # HiRes + dataset["energy_delta_minus"].values = energy_delta_hires_values + dataset["energy_delta_plus"].values = energy_delta_hires_values + else: # HiThr + dataset["energy_delta_minus"].values = energy_delta_hithr_values + dataset["energy_delta_plus"].values = energy_delta_hithr_values + + return dataset + + +# ============================================================================= +# RATES AND INTENSITIES CALCULATIONS +# ============================================================================= + + +def calculate_all_rates_and_intensities( + dataset: xr.Dataset, + sputtering_correction: bool = False, + bootstrap_correction: bool = False, + flux_correction: bool = False, + o_map_dataset: xr.Dataset | None = None, + flux_factors: Path | None = None, + cg_correction: bool = False, +) -> xr.Dataset: + """ + Calculate rates and intensities with proper error propagation. + + Parameters + ---------- + dataset : xr.Dataset + Sky map dataset with count data and geometric factors. + sputtering_correction : bool, optional + Whether to apply sputtering corrections to oxygen intensities. + Default is False. + bootstrap_correction : bool, optional + Whether to apply bootstrap corrections to intensities. + Default is False. + flux_correction : bool, optional + Whether to apply flux corrections to intensities. + Default is False. + o_map_dataset : xr.Dataset, optional + Dataset specifically for oxygen, needed for sputtering corrections. + flux_factors : Path, optional + Path to flux factor file for flux corrections. + cg_correction : bool, optional + Whether to apply CG correction to intensities. + + Returns + ------- + xr.Dataset + Dataset with calculated rates, intensities, and uncertainties for the + specified species. + """ + # Step 1: Calculate rates for the specified species + dataset = calculate_rates(dataset) + + # Step 2: Calculate intensities + dataset = calculate_intensities(dataset) + + # Step 3: Calculate background rates and intensities + dataset = calculate_backgrounds(dataset) + + # Optional Step 4: Calculate sputtering corrections + if sputtering_correction: + logger.info("Calculating sputtering corrections") + dataset = calculate_sputtering_corrections(dataset, o_map_dataset) + + # Optional Step 5: Calculate bootstrap corrections + if bootstrap_correction: + logger.info("Calculating bootstrap corrections") + dataset = calculate_bootstrap_corrections(dataset) + + # Optional Step 6: Calculate flux corrections + if flux_correction: + if flux_factors is None: + raise ValueError("Flux factors file must be provided for flux corrections") + dataset = calculate_flux_corrections(dataset, flux_factors) + + # Optional Step 7: Finish CG correction + if cg_correction: + logger.info("Interpolating map intensities to helio-frame energies") + # Finish calculation of the exposure factor weighted projection of energy_sc + # and convert to units of keV + dataset["energy_sc"] = ( + dataset["energy_sc_exposure_factor"] / dataset["exposure_factor"] / 1e3 + ) + dataset = interpolate_map_flux_to_helio_frame( + dataset, + dataset["energy"], + dataset["energy"], + ["ena_intensity", "bg_intensity"], + ) + + # Step 7: Clean up intermediate variables + dataset = cleanup_intermediate_variables(dataset) + + return dataset + + +def calculate_rates(dataset: xr.Dataset) -> xr.Dataset: + """ + Calculate count rates and their statistical uncertainties. + + Parameters + ---------- + dataset : xr.Dataset + Dataset with count data and exposure times. + + Returns + ------- + xr.Dataset + Dataset with calculated count rates and statistical uncertainties + for the specified species. + """ + # Rate = counts / exposure_factor + # TODO: Account for ena / isn naming differences + dataset["ena_count_rate"] = dataset["counts"] / dataset["exposure_factor"] + + # Poisson uncertainty on the counts propagated to the rate + # TODO: Is there uncertainty in the exposure time too? + dataset["ena_count_rate_stat_uncert"] = ( + np.sqrt(dataset["counts"]) / dataset["exposure_factor"] + ) + + return dataset + + +def calculate_intensities(dataset: xr.Dataset) -> xr.Dataset: + """ + Calculate particle intensities and uncertainties for the specified species. + + Parameters + ---------- + dataset : xr.Dataset + Dataset with count rates, geometric factors, and center energies. + + Returns + ------- + xr.Dataset + Dataset with calculated particle intensities and their statistical + and systematic uncertainties for the specified species. + """ + # Equation 3 from mapping document (average intensity) + dataset["ena_intensity"] = dataset["counts_over_eff"] / ( + dataset["geometric_factor"] * dataset["energy"] * dataset["exposure_factor"] + ) + + # Equation 4 from mapping document (statistical uncertainty) + # Note that we need to take the square root to get the uncertainty as + # the equation is for the variance + dataset["ena_intensity_stat_uncert"] = np.sqrt( + dataset["counts_over_eff_squared"] + ) / (dataset["geometric_factor"] * dataset["energy"] * dataset["exposure_factor"]) + + # Equation 5 from mapping document (systematic uncertainty) + dataset["ena_intensity_sys_err"] = ( + dataset["ena_intensity"] + * dataset["geometric_factor_stat_uncert"] + / dataset["geometric_factor"] + ) + + return dataset + + +def calculate_backgrounds(dataset: xr.Dataset) -> xr.Dataset: + """ + Calculate background rates and intensities for the specified species. + + Parameters + ---------- + dataset : xr.Dataset + Dataset with count rates, geometric factors, and center energies. + + Returns + ------- + xr.Dataset + Dataset with calculated background rates and intensities for the + specified species. + """ + # Equation 6 from mapping document (background rate) + # exposure time weighted average of the background rates + dataset["bg_rate"] = dataset["bg_rate_exposure_factor"] / dataset["exposure_factor"] + # Equation 7 from mapping document (background statistical uncertainty) + dataset["bg_rate_stat_uncert"] = np.sqrt( + dataset["bg_rate_stat_uncert_exposure_factor2"] + / dataset["exposure_factor"] ** 2 + ) + # Equation 8 from mapping document (background systematic uncertainty) + dataset["bg_rate_sys_err"] = ( + dataset["bg_rate"] + * dataset["geometric_factor_stat_uncert"] + / dataset["geometric_factor"] + ) + + # Background intensity + dataset["bg_intensity"] = dataset["bg_rate"] / ( + dataset["geometric_factor"] * dataset["energy"] + ) + dataset["bg_intensity_stat_uncert"] = dataset["bg_rate_stat_uncert"] / ( + dataset["geometric_factor"] * dataset["energy"] + ) + dataset["bg_intensity_sys_err"] = ( + dataset["bg_intensity"] + * dataset["geometric_factor_stat_uncert"] + / dataset["geometric_factor"] + ) + + return dataset + + +def calculate_sputtering_corrections( + dataset: xr.Dataset, o_dataset: xr.Dataset +) -> xr.Dataset: + """ + Calculate sputtering corrections from oxygen intensities. + + Correction factors are read from imap_lo_sputter-correction-factors_v001.csv. + Only for Oxygen sputtering and correction only at ESA levels 5 and 6 + for 90 degree maps. If off-angle maps are made, we may have to extend + this to levels 3 and 4 as well. + + Follows equations 9-13 from the mapping document. + + Parameters + ---------- + dataset : xr.Dataset + Dataset with count rates, geometric factors, and center energies. + This is an H dataset that we are applying the corrections to. + o_dataset : xr.Dataset + Dataset specifically for oxygen, needed to access oxygen intensities + and uncertainties. + + Returns + ------- + xr.Dataset + Dataset with calculated sputtering-corrected intensities and their + uncertainties. + """ + logger.info("Applying sputtering corrections to hydrogen intensities") + sputter_df = load_sputter_correction_data("o", "h") + energy_indices = (sputter_df["esa_step"].values - 1).tolist() + + small_dataset = dataset.isel(epoch=0, energy=energy_indices) + o_small_dataset = o_dataset.isel(epoch=0, energy=energy_indices) + + # We need to align the energy dimensions from the oxygen dataset to the + # Hydrogen dataset so the calculations below get aligned by xarray correctly. + o_small_dataset["energy"] = small_dataset["energy"] + + # Equation 9 + j_o_prime = o_small_dataset["ena_intensity"] - o_small_dataset["bg_intensity"] + j_o_prime.values[j_o_prime.values < 0] = 0 # No negative intensities + j_o_prime_valid = np.isfinite(j_o_prime) & (j_o_prime > 0) + + # Equation 10 + j_o_prime_var = ( + o_small_dataset["ena_intensity_stat_uncert"] ** 2 + + o_small_dataset["bg_intensity_stat_uncert"] ** 2 + ) + + sputter_correction_factor = xr.DataArray( + sputter_df["sputter_factor"].values, + dims=["energy"], + coords={"energy": small_dataset["energy"]}, + ) + # Equation 11 + # Remove the sputtered oxygen intensity to correct the original H intensity + sputter_corrected_intensity = xr.where( + j_o_prime_valid, + small_dataset["ena_intensity"] - sputter_correction_factor * j_o_prime, + small_dataset["ena_intensity"], + ) + + # Equation 12 + sputter_corrected_intensity_var = xr.where( + j_o_prime_valid, + small_dataset["ena_intensity_stat_uncert"] ** 2 + + (sputter_correction_factor**2) * j_o_prime_var, + small_dataset["ena_intensity_stat_uncert"] ** 2, + ) + + # Equation 13 + sputter_corrected_intensity_sys_err = xr.where( + j_o_prime_valid, + sputter_corrected_intensity + / small_dataset["ena_intensity"] + * small_dataset["ena_intensity_sys_err"], + small_dataset["ena_intensity_sys_err"], + ) + + # Now put the corrected values into the original dataset + dataset["ena_intensity"].values[0, energy_indices, ...] = ( + sputter_corrected_intensity.values + ) + dataset["ena_intensity_stat_uncert"].values[0, energy_indices, ...] = np.sqrt( + sputter_corrected_intensity_var.values + ) + dataset["ena_intensity_sys_err"].values[0, energy_indices, ...] = ( + sputter_corrected_intensity_sys_err.values + ) + + return dataset + + +def calculate_bootstrap_corrections(dataset: xr.Dataset) -> xr.Dataset: + """ + Calculate bootstrap corrections for hydrogen and oxygen intensities. + + Follows equations 14-35 from the mapping document. + + Parameters + ---------- + dataset : xr.Dataset + Dataset with count rates, geometric factors, and center energies. + + Returns + ------- + xr.Dataset + Dataset with calculated bootstrap-corrected intensities and their + uncertainties for hydrogen. + """ + logger.info("Applying bootstrap corrections") + + # Table 3 bootstrap terms h_i,k - load from an ancillary file + bootstrap_df = load_bootstrap_correction_data() + + # Create xarray DataArray with named dimensions for proper broadcasting + bootstrap_factor = ( + bootstrap_df.set_index(["esa_step_i", "esa_step_k"])["bootstrap_factor"] + .to_xarray() + .fillna(0) + .reindex(esa_step_i=range(1, 8), esa_step_k=range(1, 9), fill_value=0) + .rename({"esa_step_i": "energy_i", "esa_step_k": "energy_k"}) + .assign_coords( + energy_i=dataset["energy"].values, + # Add an extra coordinate for the virtual E8 channel, unused + # in the broadcasting calculations + energy_k=np.concatenate([dataset["energy"].values, [np.nan]]), ) + ) + + # Equation 14 + j_c_prime = dataset["ena_intensity"] - dataset["bg_intensity"] + j_c_prime.values[j_c_prime.values < 0] = 0 + + # Equation 15 + j_c_prime_var = dataset["ena_intensity_stat_uncert"] ** 2 + + # Equation 16 - systematic error propagation + # Handle division by zero: only compute where ena_intensity > 0 + j_c_prime_err = xr.where( + dataset["ena_intensity"] > 0, + j_c_prime / dataset["ena_intensity"] * dataset["ena_intensity_sys_err"], + 0, + ) + + # NOTE: E8 virtual channel calculation is from the text. This is to + # start the calculations off from the higher energies and avoid + # reliance on IMAP Hi energy channels. + # E8 is a virtual energy channel at 2.1 * E7 + e8 = 2.1 * dataset["energy"].values[-1] + + j_c_6 = j_c_prime.isel(energy=5) + j_c_7 = j_c_prime.isel(energy=6) + e_6 = dataset["energy"].isel(energy=5) + e_7 = dataset["energy"].isel(energy=6) + + # Calculate gamma, ignoring any invalid values + # Fill in the invalid values with zeros after the fact + with np.errstate(divide="ignore", invalid="ignore"): + gamma = np.log(j_c_6 / j_c_7) / np.log(e_6 / e_7) + j_8_b = j_c_7 * (e8 / e_7) ** gamma + + # Set j_8_b to zero where the calculation was invalid + j_8_b = j_8_b.where(np.isfinite(j_8_b) & (j_8_b > 0), 0) + + # Initialize bootstrap intensity and uncertainty arrays + dataset["bootstrap_intensity"] = xr.zeros_like(dataset["ena_intensity"]) + dataset["bootstrap_intensity_var"] = xr.zeros_like(dataset["ena_intensity"]) + dataset["bootstrap_intensity_sys_err"] = xr.zeros_like(dataset["ena_intensity"]) + + for i in range(6, -1, -1): + # Create views for the current energy channel to avoid repeated indexing + bootstrap_intensity_i = dataset["bootstrap_intensity"][0, i, ...] + bootstrap_intensity_var_i = dataset["bootstrap_intensity_var"][0, i, ...] + j_c_prime_i = j_c_prime[0, i, ...] + j_c_prime_var_i = j_c_prime_var[0, i, ...] + + # Initialize the variable with the non-summation term and virtual + # channel energy subtraction first, then iterate through the other + # channels which can be looked up via indexing + # i.e. the summation is always k=i+1 to 7, because we've already + # included the k=8 term here. + # NOTE: The paper uses 1-based indexing and we use 0-based indexing + # so there is an off-by-one difference in the indices. + bootstrap_intensity_i[:] = ( + j_c_prime_i - bootstrap_factor.isel(energy_i=i, energy_k=7) * j_8_b[0, ...] + ) + # NOTE: We will square root at the end to get the uncertainty, but + # all equations are with variances + bootstrap_intensity_var_i[:] = j_c_prime_var_i + + # Vectorized summation using xarray's built-in broadcasting + # Select the relevant k indices for summation (k = i+1 to 6) + k_indices = list(range(i + 1, 7)) + + # Get bootstrap factors for this i and the relevant k values + # Rename energy_k dimension to energy for alignment with intensity + bootstrap_factors_k = bootstrap_factor.isel( + energy_i=i, energy_k=k_indices + ).rename({"energy_k": "energy"}) + + # Get intensity slices - these will have an 'energy' dimension still + intensity_k = dataset["bootstrap_intensity"][0, k_indices, ...] + intensity_var_k = dataset["bootstrap_intensity_var"][0, k_indices, ...] + + # Subtraction terms from equations 18-23 (xarray vectorized) + bootstrap_intensity_i -= (bootstrap_factors_k * intensity_k).sum(dim="energy") + + # Summation terms from equations 25-30 (xarray vectorized) + bootstrap_intensity_var_i += (bootstrap_factors_k**2 * intensity_var_k).sum( + dim="energy" + ) + + # Again zero any bootstrap fluxes that are negative + bootstrap_intensity_i.values[bootstrap_intensity_i < 0] = 0.0 + + # Equation 31 - systematic error propagation for bootstrap intensity + # Handle division by zero: only compute where j_c_prime > 0 + dataset["bootstrap_intensity_sys_err"] = xr.where( + j_c_prime > 0, dataset["bootstrap_intensity"] / j_c_prime * j_c_prime_err, 0 + ) + + valid_bootstrap = (dataset["bootstrap_intensity"] > 0) & np.isfinite( + dataset["bootstrap_intensity"] + ) + # Update the original intensity values + # Equation 32 / 33 + # ena_intensity = ena_intensity (J_c) - (j_c_prime - J_b) + dataset["ena_intensity"] = xr.where( + valid_bootstrap, + dataset["ena_intensity"] - j_c_prime + dataset["bootstrap_intensity"], + dataset["ena_intensity"], + ) + + # Ensure corrected intensities are non-negative + dataset["ena_intensity"] = xr.where( + dataset["ena_intensity"] < 0, 0, dataset["ena_intensity"] + ) + + # Equation 34 - statistical uncertainty + # Take the square root, since we were in variances up to this point + dataset["ena_intensity_stat_uncert"] = xr.where( + valid_bootstrap, + np.sqrt(dataset["bootstrap_intensity_var"]), + dataset["ena_intensity_stat_uncert"], + ) + + # Equation 35 - systematic error for corrected intensity + # Handle division by zero and ensure reasonable values + dataset["ena_intensity_sys_err"] = xr.zeros_like(dataset["ena_intensity"]) + + # Only compute where bootstrap intensity is valid + dataset["ena_intensity_sys_err"] = xr.where( + valid_bootstrap, + ( + dataset["ena_intensity"] + / dataset["bootstrap_intensity"] + * dataset["bootstrap_intensity_sys_err"] + ), + 0, + ) + + # Drop the intermediate bootstrap variables + dataset = dataset.drop_vars( + [ + "bootstrap_intensity", + "bootstrap_intensity_var", + "bootstrap_intensity_sys_err", + ] + ) + + return dataset + + +def calculate_flux_corrections(dataset: xr.Dataset, flux_factors: Path) -> xr.Dataset: + """ + Calculate flux corrections for intensities. + + Uses the shared ena maps ``PowerLawFluxCorrector`` class to do the + correction calculations. + + Parameters + ---------- + dataset : xr.Dataset + Dataset with count rates, geometric factors, and center energies. + flux_factors : Path + Path to the eta flux factor file to use for corrections. Read in as + an ancillary file in the preprocessing step. + + Returns + ------- + xr.Dataset + Dataset with calculated flux-corrected intensities and their + uncertainties for the specified species. + """ + logger.info("Applying flux corrections") + + # Flux correction + corrector = PowerLawFluxCorrector(flux_factors) + + # NOTE: We need to apply this to both total flux and background flux + for var in ["ena", "bg"]: + # Apply flux correction with xarray inputs + dataset[f"{var}_intensity"], dataset[f"{var}_intensity_stat_uncert"] = ( + corrector.apply_flux_correction( + dataset[f"{var}_intensity"], + dataset[f"{var}_intensity_stat_uncert"], + dataset["energy"], + ) + ) + + return dataset + + +def cleanup_intermediate_variables(dataset: xr.Dataset) -> xr.Dataset: + """ + Remove intermediate variables that were only needed for calculations. + + Parameters + ---------- + dataset : xr.Dataset + Dataset containing intermediate calculation variables. + + Returns + ------- + xr.Dataset + Cleaned dataset with intermediate variables removed. + """ + # Remove the intermediate variables from the map + # i.e. the ones that were projected from the pset only for the purposes + # of math and not desired in the output. + vars_to_remove = [] + + # Only remove variables that exist in the dataset for the specific species + potential_vars = [ + "geometric_factor", + "geometric_factor_stat_uncert", + "counts_over_eff", + "counts_over_eff_squared", + "bg_rate_exposure_factor", + "bg_rate_stat_uncert_exposure_factor2", + ] + + for potential_var in potential_vars: + if potential_var in dataset.data_vars: + vars_to_remove.append(potential_var) - return lo_map + return dataset.drop_vars(vars_to_remove) diff --git a/imap_processing/mag/constants.py b/imap_processing/mag/constants.py index 8def1f80cd..57e37b7d0d 100644 --- a/imap_processing/mag/constants.py +++ b/imap_processing/mag/constants.py @@ -132,6 +132,11 @@ class ModeFlags(Enum): RANGE_BIT_WIDTH = 2 MAX_COMPRESSED_VECTOR_BITS = 60 FILLVAL = -1e31 +# Relative tolerance for L1C timestamp-gap checks; allows small clock-drift +# variation around the expected cadence before a spacing is treated as a gap. +# This is 7.5% of expected_gap = 1e9 / vectors_per_second ns +# (75, 37.5, 18.75, or 9.375 ms at 1, 2, 4, or 8 Hz, respectively). +L1C_TIMESTAMP_GAP_TOLERANCE = 0.075 def vectors_per_second_from_string(vecsec_string: str) -> dict: diff --git a/imap_processing/mag/l0/decom_mag.py b/imap_processing/mag/l0/decom_mag.py index 28d89a1582..b1e432948e 100644 --- a/imap_processing/mag/l0/decom_mag.py +++ b/imap_processing/mag/l0/decom_mag.py @@ -9,7 +9,6 @@ import numpy as np import xarray as xr -from space_packet_parser import definitions from imap_processing import imap_module_directory from imap_processing.ccsds.ccsds_data import CcsdsData @@ -17,6 +16,7 @@ from imap_processing.mag.constants import DataMode from imap_processing.mag.l0.mag_l0_data import MagL0, Mode from imap_processing.spice.time import met_to_ttj2000ns +from imap_processing.utils import packet_generator, separate_ccsds_header_userdata logger = logging.getLogger(__name__) @@ -41,25 +41,20 @@ def decom_packets(packet_file_path: str | Path) -> dict[str, list[MagL0]]: f"{imap_module_directory}/mag/packet_definitions/MAG_SCI_COMBINED.xml" ) - packet_definition = definitions.XtcePacketDefinition(xtce_document) - # Store in a dict for de-duplication. Only the keys are returned as a list. norm_dict: dict[MagL0, None] = {} burst_dict: dict[MagL0, None] = {} - with open(packet_file_path, "rb") as binary_data: - mag_packets = packet_definition.packet_generator(binary_data) - - for packet in mag_packets: - apid = packet["PKT_APID"] - if apid in (Mode.BURST, Mode.NORMAL): - values = [item.raw_value for item in packet.user_data.values()] - mag_l0 = MagL0(CcsdsData(packet.header), *values) - if apid == Mode.NORMAL: - if mag_l0 not in norm_dict: - norm_dict[mag_l0] = None - elif mag_l0 not in burst_dict: - burst_dict[mag_l0] = None + for packet in packet_generator(packet_file_path, xtce_document): + apid = packet["PKT_APID"] + if apid in (Mode.BURST, Mode.NORMAL): + header, userdata = separate_ccsds_header_userdata(packet) + mag_l0 = MagL0(CcsdsData(header), *list(userdata.values())) + if apid == Mode.NORMAL: + if mag_l0 not in norm_dict: + norm_dict[mag_l0] = None + elif mag_l0 not in burst_dict: + burst_dict[mag_l0] = None return {"norm": list(norm_dict.keys()), "burst": list(burst_dict.keys())} @@ -89,7 +84,7 @@ def generate_dataset( # TODO: Correct CDF attributes from email vector_data = np.zeros((len(l0_data), len(l0_data[0].VECTORS))) - shcoarse_data = np.zeros(len(l0_data), dtype="datetime64[ns]") + shcoarse_data: np.ndarray = np.zeros(len(l0_data), dtype="datetime64[ns]") support_data = defaultdict(list) diff --git a/imap_processing/mag/l1a/mag_l1a.py b/imap_processing/mag/l1a/mag_l1a.py index 74271dfc96..5bf8080d51 100644 --- a/imap_processing/mag/l1a/mag_l1a.py +++ b/imap_processing/mag/l1a/mag_l1a.py @@ -43,7 +43,7 @@ def mag_l1a(packet_filepath: Path) -> list[xr.Dataset]: A list of generated filenames. """ packets = decom_mag.decom_packets(packet_filepath) - + logger.info("Packet decoding complete, beginning L1A processing.") norm_data = packets["norm"] burst_data = packets["burst"] @@ -188,7 +188,7 @@ def process_packets( secondary_packet_data.start_time, ) - # Sort primary and secondary into MAGo and MAGi by 24 hour chunks + # Sort primary and secondary into MAGo and MAGi if mago is None: mago = MagL1a( diff --git a/imap_processing/mag/l1a/mag_l1a_data.py b/imap_processing/mag/l1a/mag_l1a_data.py index f81e3011d5..ca360490fc 100644 --- a/imap_processing/mag/l1a/mag_l1a_data.py +++ b/imap_processing/mag/l1a/mag_l1a_data.py @@ -205,13 +205,25 @@ class MagL1a: 1 if the sensor is active, 0 if not shcoarse : int Mission elapsed time for the first packet, the start time for the whole day - vectors : numpy.ndarray - List of magnetic vector samples, starting at start_time. [x, y, z, range, time], - where time is numpy.datetime64[ns] + starting_vectors : InitVar[numpy.ndarray] + Initvar to create the first entry in the vector list. This is to preserve the + external API of creating the object with the first set of vectors. + This cannot be accessed from an instance of the class. Instead, vectors + should be used. starting_packet : InitVar[MagL1aPacketProperties] The packet properties for the first packet in the day. As an InitVar, this cannot be accessed from an instance of the class. Instead, packet_definitions should be used. + vectors : numpy.ndarray + List of magnetic vector samples, starting at start_time. [x, y, z, range, time], + where time is numpy.datetime64[ns]. This is a property that concatenates the + internal vector list on demand. + compression_flags : numpy.ndarray + Array of flags to indicate compression and width for all timestamps in the + L1A file. Shaped like (n, 2) where n is the number of vectors. First value + is a boolean for compressed/uncompressed, second vector is a number between 0-20 + if the data is compressed, which is the width in bits of the compressed data. + This is a property that concatenates the internal compression flags list. packet_definitions : dict[numpy.datetime64, MagL1aPacketProperties] Dictionary of packet properties for each packet in the day. The key is the start time of the packet, and the value is a dataclass of packet properties. @@ -221,11 +233,20 @@ class MagL1a: List of missing sequence numbers in the day start_time : numpy.int64 Start time of the day, in ns since J2000 epoch - compression_flags : np.ndarray + _compression_flags_list : np.ndarray Array of flags to indication compression and width for all timestamps in the L1A file. Shaped like (n, 2) where n is the number of vectors. First value is a boolean for compressed/uncompressed, second vector is a number between 0-20 if the data is compressed, which is the width in bits of the compressed data. + Transformed into a numpy array upon retrieval. + _vector_list : list + Internal list of vectors, used to build the final vectors attribute. + This is a list of numpy arrays, each with shape (n, 5) where n is the + number of vectors in that packet, and each vector is (x, y, z, range, time). + _vector_cache : numpy.ndarray | None + A cache of the concatenated vector list. This is None until the vectors + property is accessed, at which point it is created and stored here for future + access. Methods ------- @@ -248,23 +269,30 @@ class MagL1a: is_mago: bool is_active: int shcoarse: int - vectors: np.ndarray + starting_vectors: InitVar[np.ndarray] starting_packet: InitVar[MagL1aPacketProperties] packet_definitions: dict[np.int64, MagL1aPacketProperties] = field(init=False) most_recent_sequence: int = field(init=False) missing_sequences: list[int] = field(default_factory=list) start_time: np.int64 = field(init=False) - compression_flags: np.ndarray | None = field(init=False, default=None) + _compression_flags_list: list = field(default_factory=list) + _vector_list: list = field(init=False) + _vector_cache: np.ndarray | None = field(init=False, default=None) - def __post_init__(self, starting_packet: MagL1aPacketProperties) -> None: + def __post_init__( + self, starting_vectors: np.ndarray, starting_packet: MagL1aPacketProperties + ) -> None: """ - Initialize the packet_definition dictionary and most_recent_sequence. + Initialize the vector list, packet_definition dictionary & most_recent_sequence. Parameters ---------- + starting_vectors : numpy.ndarray + The vectors for the first packet in the day. starting_packet : MagL1aPacketProperties The packet properties for the first packet in the day, including start time. """ + self._vector_list = [starting_vectors] self.start_time = np.int64(met_to_ttj2000ns(starting_packet.shcoarse)) self.packet_definitions = {self.start_time: starting_packet} # most_recent_sequence is the sequence number of the packet used to initialize @@ -272,6 +300,36 @@ def __post_init__(self, starting_packet: MagL1aPacketProperties) -> None: self.most_recent_sequence = starting_packet.src_seq_ctr self.update_compression_array(starting_packet, self.vectors.shape[0]) + @property + def vectors(self) -> np.ndarray: + """ + Concatenate the internal vector list into a numpy array. + + If the array has already been created, return the cached version. + + Returns + ------- + np.ndarray + Array of vectors with shape (n, 5) where n is the number of vectors, + and each vector is (x, y, z, range, time). + """ + if self._vector_cache is None: + self._vector_cache = np.concatenate(self._vector_list, axis=0) + return self._vector_cache + + @property + def compression_flags(self) -> np.ndarray: + """ + Return the compression flags array. + + Returns + ------- + np.ndarray + Array of compression flags with shape (n, 2) where n is the number of + vectors, and each entry is (is_compressed, compression_width). + """ + return np.concatenate(self._compression_flags_list, axis=0) + def append_vectors( self, additional_vectors: np.ndarray, packet_properties: MagL1aPacketProperties ) -> None: @@ -285,9 +343,12 @@ def append_vectors( packet_properties : MagL1aPacketProperties Additional vector definition to add to the l0_packets dictionary. """ + self._vector_list.append(additional_vectors) + # Invalidate the cache + self._vector_cache = None + vector_sequence = packet_properties.src_seq_ctr - self.vectors = np.concatenate([self.vectors, additional_vectors]) start_time = np.int64(met_to_ttj2000ns(packet_properties.shcoarse)) self.packet_definitions[start_time] = packet_properties @@ -317,15 +378,12 @@ def update_compression_array( Length of new array to add or append to the compression_flags attribute. This is expected to be the length of the vector array. """ - new_flags = np.full( + new_flags: np.ndarray = np.full( (length, 2), [packet_properties.compression, packet_properties.compression_width], dtype=np.int8, ) - if self.compression_flags is None: - self.compression_flags = new_flags - else: - self.compression_flags = np.concatenate([self.compression_flags, new_flags]) + self._compression_flags_list.append(new_flags) @staticmethod def calculate_vector_time( @@ -1008,7 +1066,7 @@ def unpack_one_vector( f"{width * AXIS_COUNT} or {width * AXIS_COUNT + RANGE_BIT_WIDTH} if " f"has_range." ) - padding = np.zeros(8 - (width % 8), dtype=np.uint8) + padding: np.ndarray = np.zeros(8 - (width % 8), dtype=np.uint8) # take slices of the input data and pack from an array of bits to an array of # uint8 bytes diff --git a/imap_processing/mag/l1b/mag_l1b.py b/imap_processing/mag/l1b/mag_l1b.py index 1ea248a731..d18ce6177d 100644 --- a/imap_processing/mag/l1b/mag_l1b.py +++ b/imap_processing/mag/l1b/mag_l1b.py @@ -398,7 +398,7 @@ def shift_time(epoch_times: xr.DataArray, time_shift: xr.DataArray) -> xr.DataAr if time_shift.size != 1: raise ValueError("Time shift must be a single value.") # Time shift is in seconds - time_shift_ns = time_shift.data * 1e9 + time_shift_ns = np.int64(round(time_shift.data.item() * 1e9)) return epoch_times + time_shift_ns @@ -426,7 +426,7 @@ def timeshift_vectors_per_second( str The updated vectors per second attribute. """ - time_shift_ns = time_shift.data * 1e9 + time_shift_ns = np.int64(round(time_shift.data.item() * 1e9)) vecsec = vectors_per_second_from_string(vectors_per_second) new_vecsec = "" diff --git a/imap_processing/mag/l1c/interpolation_methods.py b/imap_processing/mag/l1c/interpolation_methods.py index d6dc516e97..717e53cdb1 100644 --- a/imap_processing/mag/l1c/interpolation_methods.py +++ b/imap_processing/mag/l1c/interpolation_methods.py @@ -33,9 +33,11 @@ def remove_invalid_output_timestamps( numpy.ndarray All valid output timestamps where there exists input data. """ - if input_timestamps[0] > output_timestamps[0]: - # Chop data where we don't have input timestamps to interpolate - output_timestamps = output_timestamps[output_timestamps >= input_timestamps[0]] + # Chop data where we don't have input timestamps to interpolate + output_timestamps = output_timestamps[ + (output_timestamps >= input_timestamps[0]) + & (output_timestamps <= input_timestamps[-1]) + ] return output_timestamps @@ -45,7 +47,8 @@ def linear( output_timestamps: np.ndarray, input_rate: VecSec | None = None, output_rate: VecSec | None = None, -) -> np.ndarray: + extrapolate: bool = False, +) -> tuple[np.ndarray, np.ndarray]: """ Linear interpolation of input vectors to output timestamps. @@ -63,6 +66,9 @@ def linear( Not required for this interpolation method. output_rate : VecSec, optional Not required for this interpolation method. + extrapolate : bool, optional + Whether to allow extrapolation of output timestamps outside the range of input + timestamps. Default is False. Returns ------- @@ -70,9 +76,12 @@ def linear( Interpolated vectors of shape (m, 3) where m is equal to the number of output timestamps. Contains x, y, z components of the vector. """ - # TODO: Remove invalid timestamps using remove_invalid_output_timestamps + if not extrapolate: + output_timestamps = remove_invalid_output_timestamps( + input_timestamps, output_timestamps + ) spline = make_interp_spline(input_timestamps, input_vectors, k=1) - return spline(output_timestamps) + return output_timestamps, spline(output_timestamps) def quadratic( @@ -81,7 +90,7 @@ def quadratic( output_timestamps: np.ndarray, input_rate: VecSec | None = None, output_rate: VecSec | None = None, -) -> np.ndarray: +) -> tuple[np.ndarray, np.ndarray]: """ Quadratic interpolation of input vectors to output timestamps. @@ -106,8 +115,11 @@ def quadratic( Interpolated vectors of shape (m, 3) where m is equal to the number of output timestamps. Contains x, y, z components of the vector. """ + output_timestamps = remove_invalid_output_timestamps( + input_timestamps, output_timestamps + ) spline = make_interp_spline(input_timestamps, input_vectors, k=2) - return spline(output_timestamps) + return output_timestamps, spline(output_timestamps) def cubic( @@ -116,7 +128,7 @@ def cubic( output_timestamps: np.ndarray, input_rate: VecSec | None = None, output_rate: VecSec | None = None, -) -> np.ndarray: +) -> tuple[np.ndarray, np.ndarray]: """ Cubic interpolation of input vectors to output timestamps. @@ -141,8 +153,11 @@ def cubic( Interpolated vectors of shape (m, 3) where m is equal to the number of output timestamps. Contains x, y, z components of the vector. """ + output_timestamps = remove_invalid_output_timestamps( + input_timestamps, output_timestamps + ) spline = make_interp_spline(input_timestamps, input_vectors, k=3) - return spline(output_timestamps) + return output_timestamps, spline(output_timestamps) def estimate_rate(timestamps: np.ndarray) -> VecSec: @@ -229,11 +244,13 @@ def cic_filter( cic1 = cic1 / decimation_factor cic2 = np.convolve(cic1, cic1) delay = (len(cic2) - 1) // 2 + input_filtered = input_timestamps + vectors_filtered = lfilter(cic2, 1, input_vectors, axis=0) if delay != 0: input_filtered = input_timestamps[:-delay] + vectors_filtered = vectors_filtered[delay:] - vectors_filtered = lfilter(cic2, 1, input_vectors, axis=0)[delay:] return input_filtered, vectors_filtered @@ -243,7 +260,7 @@ def linear_filtered( output_timestamps: np.ndarray, input_rate: VecSec | None = None, output_rate: VecSec | None = None, -) -> np.ndarray: +) -> tuple[np.ndarray, np.ndarray]: """ Linear filtered interpolation of input vectors to output timestamps. @@ -270,6 +287,12 @@ def linear_filtered( Interpolated vectors of shape (m, 3) where m is equal to the number of output timestamps. Contains x, y, z components of the vector. """ + if input_vectors.shape[0] != input_timestamps.shape[0]: + raise ValueError( + "Input vectors and input timestamps must have the same length. " + f"Got {input_vectors.shape[0]} and {input_timestamps.shape[0]}" + ) + input_filtered, vectors_filtered = cic_filter( input_vectors, input_timestamps, output_timestamps, input_rate, output_rate ) @@ -282,7 +305,7 @@ def quadratic_filtered( output_timestamps: np.ndarray, input_rate: VecSec | None = None, output_rate: VecSec | None = None, -) -> np.ndarray: +) -> tuple[np.ndarray, np.ndarray]: """ Quadratic filtered interpolation of input vectors to output timestamps. @@ -309,6 +332,9 @@ def quadratic_filtered( Interpolated vectors of shape (m, 3) where m is equal to the number of output timestamps. Contains x, y, z components of the vector. """ + output_timestamps = remove_invalid_output_timestamps( + input_timestamps, output_timestamps + ) input_filtered, vectors_filtered = cic_filter( input_vectors, input_timestamps, output_timestamps, input_rate, output_rate ) @@ -321,7 +347,7 @@ def cubic_filtered( output_timestamps: np.ndarray, input_rate: VecSec | None = None, output_rate: VecSec | None = None, -) -> np.ndarray: +) -> tuple[np.ndarray, np.ndarray]: """ Cubic filtered interpolation of input vectors to output timestamps. @@ -348,6 +374,9 @@ def cubic_filtered( Interpolated vectors of shape (m, 3) where m is equal to the number of output timestamps. Contains x, y, z components of the vector. """ + output_timestamps = remove_invalid_output_timestamps( + input_timestamps, output_timestamps + ) input_filtered, vectors_filtered = cic_filter( input_vectors, input_timestamps, output_timestamps, input_rate, output_rate ) diff --git a/imap_processing/mag/l1c/mag_l1c.py b/imap_processing/mag/l1c/mag_l1c.py index e7e2d4bb91..885f1bd9c8 100644 --- a/imap_processing/mag/l1c/mag_l1c.py +++ b/imap_processing/mag/l1c/mag_l1c.py @@ -7,14 +7,20 @@ from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes from imap_processing.mag import imap_mag_sdc_configuration_v001 as configuration -from imap_processing.mag.constants import ModeFlags, VecSec +from imap_processing.mag.constants import ( + L1C_TIMESTAMP_GAP_TOLERANCE, + ModeFlags, + VecSec, +) from imap_processing.mag.l1c.interpolation_methods import InterpolationFunction +from imap_processing.spice.time import et_to_ttj2000ns, str_to_et logger = logging.getLogger(__name__) def mag_l1c( first_input_dataset: xr.Dataset, + day_to_process: np.datetime64, second_input_dataset: xr.Dataset = None, ) -> xr.Dataset: """ @@ -27,6 +33,9 @@ def mag_l1c( first_input_dataset : xr.Dataset The first input dataset to process. This can be either burst or norm data, for mago or magi. + day_to_process : np.datetime64 + The day to process, in np.datetime64[D] format. This is used to fill gaps at + the beginning or end of the day if needed. second_input_dataset : xr.Dataset, optional The second input dataset to process. This should be burst if first_input_dataset was norm, or norm if first_input_dataset was burst. It should match the @@ -39,9 +48,6 @@ def mag_l1c( """ # TODO: # find missing sequences and output them - # Fix gaps at the beginning of the day by going to previous day's file - # Fix gaps at the end of the day - # Allow for one input to be missing # Missing burst file - just pass through norm file # Missing norm file - go back to previous L1C file to find timestamps, then # interpolate the entire day from burst @@ -58,17 +64,14 @@ def mag_l1c( ) interp_function = InterpolationFunction[configuration.L1C_INTERPOLATION_METHOD] - if normal_mode_dataset and burst_mode_dataset: - full_interpolated_timeline = process_mag_l1c( - normal_mode_dataset, burst_mode_dataset, interp_function + if burst_mode_dataset is not None: + full_interpolated_timeline: np.ndarray = process_mag_l1c( + normal_mode_dataset, burst_mode_dataset, interp_function, day_to_process ) elif normal_mode_dataset is not None: - full_interpolated_timeline = fill_normal_data( - normal_mode_dataset, normal_mode_dataset["epoch"].data - ) + full_interpolated_timeline = fill_normal_data(normal_mode_dataset) else: - # TODO: With only burst data, downsample by retrieving the timeline - raise NotImplementedError + raise ValueError("At least one of norm or burst dataset must be provided.") completed_timeline = remove_missing_data(full_interpolated_timeline) @@ -122,12 +125,14 @@ def mag_l1c( global_attributes["missing_sequences"] = "" try: - global_attributes["is_mago"] = normal_mode_dataset.attrs["is_mago"] - global_attributes["is_active"] = normal_mode_dataset.attrs["is_active"] + active_dataset = normal_mode_dataset or burst_mode_dataset + + global_attributes["is_mago"] = active_dataset.attrs["is_mago"] + global_attributes["is_active"] = active_dataset.attrs["is_active"] # Check if all vectors are primary in both normal and burst datasets - is_mago = normal_mode_dataset.attrs.get("is_mago", "False") == "True" - normal_all_primary = normal_mode_dataset.attrs.get("all_vectors_primary", False) + is_mago = active_dataset.attrs.get("is_mago", "False") == "True" + normal_all_primary = active_dataset.attrs.get("all_vectors_primary", False) # Default for missing burst dataset: 1 if MAGO (expected primary), 0 if MAGI burst_all_primary = is_mago @@ -141,14 +146,14 @@ def mag_l1c( normal_all_primary and burst_all_primary ) - global_attributes["missing_sequences"] = normal_mode_dataset.attrs[ + global_attributes["missing_sequences"] = active_dataset.attrs[ "missing_sequences" ] except KeyError as e: logger.info( f"Key error when assigning global attributes, attribute not found in " f"L1B file with logical source " - f"{normal_mode_dataset.attrs['Logical_source']}: {e}" + f"{active_dataset.attrs['Logical_source']}: {e}" ) global_attributes["interpolation_method"] = interp_function.name @@ -171,16 +176,24 @@ def mag_l1c( attrs=attribute_manager.get_variable_attributes("vector_attrs"), ) - output_dataset["vector_magnitude"] = xr.apply_ufunc( - lambda x: np.linalg.norm(x[:4]), - output_dataset["vectors"], - input_core_dims=[["direction"]], - output_core_dims=[[]], - vectorize=True, - ) - output_dataset[ - "vector_magnitude" - ].attrs = attribute_manager.get_variable_attributes("vector_magnitude_attrs") + if len(output_dataset["vectors"]) > 0: + output_dataset["vector_magnitude"] = xr.apply_ufunc( + lambda x: np.linalg.norm(x[:4]), + output_dataset["vectors"], + input_core_dims=[["direction"]], + output_core_dims=[[]], + vectorize=True, + ) + output_dataset[ + "vector_magnitude" + ].attrs = attribute_manager.get_variable_attributes("vector_magnitude_attrs") + else: + output_dataset["vector_magnitude"] = xr.DataArray( + np.empty((0, 1)), + name="vector_magnitude", + dims=["epoch", "vector_magnitude"], + attrs=attribute_manager.get_variable_attributes("vector_magnitude_attrs"), + ) output_dataset["compression_flags"] = xr.DataArray( completed_timeline[:, 6:8], @@ -260,16 +273,18 @@ def select_datasets( def process_mag_l1c( - normal_mode_dataset: xr.Dataset, + normal_mode_dataset: xr.Dataset | None, burst_mode_dataset: xr.Dataset, interpolation_function: InterpolationFunction, + day_to_process: np.datetime64 | None = None, ) -> np.ndarray: """ Create MAG L1C data from L1B datasets. This function starts from the normal mode dataset and completes the following steps: 1. find all the gaps in the dataset - 2. generate a new timeline with the gaps filled + 2. generate a new timeline with the gaps filled, including new timestamps to fill + out the rest of the day to +/- 15 minutes on either side 3. fill the timeline with normal mode data (so, all the non-gap timestamps) 4. interpolate the gaps using the burst mode data and the method specified in interpolation_function. @@ -288,29 +303,61 @@ def process_mag_l1c( The burst mode dataset, which is used to fill in the gaps in the normal mode. interpolation_function : InterpolationFunction The interpolation function to use to fill in the gaps. + day_to_process : np.datetime64, optional + The day to process, in np.datetime64[D] format. This is used to fill + gaps at the beginning or end of the day if needed. If not included, these + gaps will not be filled. Returns ------- np.ndarray An (n, 8) shaped array containing the completed timeline. """ - norm_epoch = normal_mode_dataset["epoch"].data - if "vectors_per_second" in normal_mode_dataset.attrs: - normal_vecsec_dict = vectors_per_second_from_string( - normal_mode_dataset.attrs["vectors_per_second"] + day_start_ns = None + day_end_ns = None + + if day_to_process is not None: + day_start = day_to_process.astype("datetime64[s]") - np.timedelta64(30, "m") + + # get the end of the day plus 30 minutes + day_end = ( + day_to_process.astype("datetime64[s]") + + np.timedelta64(1, "D") + + np.timedelta64(30, "m") ) - else: - normal_vecsec_dict = None - output_dataset = normal_mode_dataset.copy(deep=True) - output_dataset["sample_interpolated"] = xr.DataArray( - np.zeros(len(normal_mode_dataset)) - ) + day_start_ns = et_to_ttj2000ns(str_to_et(str(day_start))) + day_end_ns = et_to_ttj2000ns(str_to_et(str(day_end))) - gaps = find_all_gaps(norm_epoch, normal_vecsec_dict) + if normal_mode_dataset: + norm_epoch = normal_mode_dataset["epoch"].data + if "vectors_per_second" in normal_mode_dataset.attrs: + normal_vecsec_dict = vectors_per_second_from_string( + normal_mode_dataset.attrs["vectors_per_second"] + ) + else: + normal_vecsec_dict = None + + gaps = find_all_gaps(norm_epoch, normal_vecsec_dict, day_start_ns, day_end_ns) + else: + norm_epoch = [day_start_ns, day_end_ns] + gaps = np.array( + [ + [ + day_start_ns, + day_end_ns, + VecSec.TWO_VECS_PER_S.value, + ] + ] + ) new_timeline = generate_timeline(norm_epoch, gaps) - norm_filled = fill_normal_data(normal_mode_dataset, new_timeline) + + if normal_mode_dataset: + norm_filled: np.ndarray = fill_normal_data(normal_mode_dataset, new_timeline) + else: + norm_filled = generate_empty_norm_array(new_timeline) + interpolated = interpolate_gaps( burst_mode_dataset, gaps, norm_filled, interpolation_function ) @@ -318,8 +365,32 @@ def process_mag_l1c( return interpolated +def generate_empty_norm_array(new_timeline: np.ndarray) -> np.ndarray: + """ + Generate an empty Normal mode array with the new timeline. + + Parameters + ---------- + new_timeline : np.ndarray + A 1D array of timestamps to fill. + + Returns + ------- + np.ndarray + An (n, 8) shaped array containing the timeline filled with `FILLVAL` data. + """ + # TODO: fill with FILLVAL + norm_filled: np.ndarray = np.zeros((len(new_timeline), 8)) + norm_filled[:, 0] = new_timeline + # Flags, will also indicate any missed timestamps + norm_filled[:, 5] = ModeFlags.MISSING.value + + return norm_filled + + def fill_normal_data( - normal_dataset: xr.Dataset, new_timeline: np.ndarray + normal_dataset: xr.Dataset, + new_timeline: np.ndarray | None = None, ) -> np.ndarray: """ Fill the new timeline with the normal mode data. @@ -330,22 +401,22 @@ def fill_normal_data( ---------- normal_dataset : xr.Dataset The normal mode dataset. - new_timeline : np.ndarray - A 1D array of timestamps to fill. + new_timeline : np.ndarray, optional + A 1D array of timestamps to fill. If not provided, the normal mode timestamps + will be used. Returns ------- - np.ndarray + filled_timeline : np.ndarray An (n, 8) shaped array containing the timeline filled with normal mode data. Gaps are marked as -1 in the generated flag column at index 5. Indices: 0 - epoch, 1-4 - vector x, y, z, and range, 5 - generated flag, 6-7 - compression flags. """ - # TODO: fill with FILLVAL? - filled_timeline: np.ndarray = np.zeros((len(new_timeline), 8)) - filled_timeline[:, 0] = new_timeline - # Flags, will also indicate any missed timestamps - filled_timeline[:, 5] = ModeFlags.MISSING.value + if new_timeline is None: + new_timeline = normal_dataset["epoch"].data + + filled_timeline = generate_empty_norm_array(new_timeline) for index, timestamp in enumerate(normal_dataset["epoch"].data): timeline_index = np.searchsorted(new_timeline, timestamp) @@ -389,6 +460,8 @@ def interpolate_gaps( 6-7 - compression flags. """ burst_epochs = burst_dataset["epoch"].data + filled_timeline_epochs = filled_norm_timeline[:, 0] + has_norm_context = np.any(filled_norm_timeline[:, 5] == ModeFlags.NORM.value) # Exclude range values burst_vectors = burst_dataset["vectors"].data # Default to two vectors per second @@ -399,9 +472,11 @@ def interpolate_gaps( ) for gap in gaps: - # TODO: we might need a few inputs before or after start/end + # TODO: we need extra data at the beginning and end of the gap burst_gap_start = (np.abs(burst_epochs - gap[0])).argmin() burst_gap_end = (np.abs(burst_epochs - gap[1])).argmin() + # if this gap is too big, we may be missing burst data at the start or end of + # the day and shouldn't use it here. # for the CIC filter, we need 2x normal mode cadence seconds @@ -423,31 +498,30 @@ def interpolate_gaps( burst_buffer = int(required_seconds * burst_rate.value) burst_start = max(0, burst_gap_start - burst_buffer) - burst_end = min(len(burst_epochs) - 1, burst_gap_end + burst_buffer) + burst_end = min(len(burst_epochs), burst_gap_end + burst_buffer + 1) - gap_timeline = filled_norm_timeline[ - (filled_norm_timeline > gap[0]) & (filled_norm_timeline < gap[1]) + gap_timeline = filled_timeline_epochs[ + (filled_timeline_epochs > gap[0]) & (filled_timeline_epochs < gap[1]) ] - logger.info( - f"difference between gap start and burst start: " - f"{gap_timeline[0] - burst_epochs[burst_start]}" - ) + + usable_burst_end_epoch = burst_epochs[burst_end - 1] + if not has_norm_context: + # In the burst-only fallback, CIC delay compensation shortens the usable + # filtered range at the trailing edge by roughly one output cadence. + usable_burst_end_epoch -= int(1e9 / norm_rate.value) short = (gap_timeline >= burst_epochs[burst_start]) & ( - gap_timeline <= burst_epochs[burst_gap_end] + gap_timeline <= usable_burst_end_epoch ) - if len(gap_timeline) != (short).sum(): - print(f"Chopping timeline from {len(gap_timeline)} to {short.sum()}") + num_short = int(short.sum()) + + if len(gap_timeline) != num_short: + print(f"Chopping timeline from {len(gap_timeline)} to {num_short}") # Limit timestamps to only include the areas with burst data - gap_timeline = gap_timeline[ - ( - (gap_timeline >= burst_epochs[burst_start]) - & (gap_timeline <= burst_epochs[burst_gap_end]) - ) - ] + gap_timeline = gap_timeline[short] # do not include range - gap_fill = interpolation_function( + adjusted_gap_timeline, gap_fill = interpolation_function( burst_vectors[burst_start:burst_end, :3], burst_epochs[burst_start:burst_end], gap_timeline, @@ -456,8 +530,8 @@ def interpolate_gaps( ) # gaps should not have data in timeline, still check it - for index, timestamp in enumerate(gap_timeline): - timeline_index = np.searchsorted(filled_norm_timeline[:, 0], timestamp) + for index, timestamp in enumerate(adjusted_gap_timeline): + timeline_index = np.searchsorted(filled_timeline_epochs, timestamp) if sum( filled_norm_timeline[timeline_index, 1:4] ) == 0 and burst_gap_start + index < len(burst_vectors): @@ -471,6 +545,17 @@ def interpolate_gaps( "compression_flags" ].data[burst_gap_start + index] + # for any timestamp that was not filled and is still missing, remove it + missing_timeline = np.setdiff1d(gap_timeline, adjusted_gap_timeline) + + for timestamp in missing_timeline: + timeline_index = np.searchsorted(filled_timeline_epochs, timestamp) + if filled_norm_timeline[timeline_index, 5] != ModeFlags.MISSING.value: + raise RuntimeError( + "Self-inconsistent data. " + "Gaps not included in final timeline should be missing." + ) + return filled_norm_timeline @@ -478,8 +563,8 @@ def generate_timeline(epoch_data: np.ndarray, gaps: np.ndarray) -> np.ndarray: """ Generate a new timeline from existing, gap-filled timeline and gaps. - The gaps are generated at a .5 second cadence, regardless of the cadence of the - existing data. + The gaps are generated at the cadence implied by the gap rate. If no rate is + provided, a default cadence of 0.5 seconds is used. Parameters ---------- @@ -487,40 +572,48 @@ def generate_timeline(epoch_data: np.ndarray, gaps: np.ndarray) -> np.ndarray: The existing timeline data, in the shape (n,). gaps : numpy.ndarray An array of gaps to fill, with shape (n, 2) where n is the number of gaps. - The gap is specified as (start, end) where start and end both exist in the - timeline already. + The gap is specified as (start, end). Returns ------- numpy.ndarray The new timeline, filled with the existing data and the generated gaps. """ - full_timeline: np.ndarray = np.zeros(0) - - # When we have our gaps, generate the full timeline - last_gap = 0 + epoch_data = np.asarray(epoch_data) + full_timeline: np.ndarray = np.array([], dtype=epoch_data.dtype) + last_index = 0 for gap in gaps: - gap_start_index = np.where(epoch_data == gap[0])[0] - gap_end_index = np.where(epoch_data == gap[1])[0] - if gap_start_index.size != 1 or gap_end_index.size != 1: - raise ValueError("Gap start or end not found in input timeline") - + epoch_start_index = np.searchsorted(epoch_data, gap[0], side="left") full_timeline = np.concatenate( - ( - full_timeline, - epoch_data[last_gap : gap_start_index[0]], - generate_missing_timestamps(gap), - ) + (full_timeline, epoch_data[last_index:epoch_start_index]) ) - last_gap = gap_end_index[0] + generated_timestamps = generate_missing_timestamps(gap) + if generated_timestamps.size == 0: + last_index = int(np.searchsorted(epoch_data, gap[1], side="left")) + continue - full_timeline = np.concatenate((full_timeline, epoch_data[last_gap:])) + # Remove any generated timestamps that are already in the timeline + # Use np.isin to check for exact matches + mask = ~np.isin(generated_timestamps, full_timeline) + generated_timestamps = generated_timestamps[mask] + + if generated_timestamps.size == 0: + print("All generated timestamps already exist in timeline") + continue + + full_timeline = np.concatenate((full_timeline, generated_timestamps)) + last_index = int(np.searchsorted(epoch_data, gap[1], side="left")) + + full_timeline = np.concatenate((full_timeline, epoch_data[last_index:])) return full_timeline def find_all_gaps( - epoch_data: np.ndarray, vecsec_dict: dict | None = None + epoch_data: np.ndarray, + vecsec_dict: dict | None = None, + start_of_day_ns: float | None = None, + end_of_day_ns: float | None = None, ) -> np.ndarray: """ Find all the gaps in the epoch data. @@ -529,6 +622,9 @@ def find_all_gaps( it will assume a nominal 1/2 second gap. A gap is defined as missing data from the expected sequence as defined by vectors_per_second_attr. + If start_of_day_ns and end_of_day_ns are provided, gaps at the beginning and end of + the day will be added if the epoch_data does not cover the full day. + Parameters ---------- epoch_data : numpy.ndarray @@ -537,6 +633,12 @@ def find_all_gaps( A dictionary of the form {start: vecsec, start: vecsec} where start is the time in nanoseconds and vecsec is the number of vectors per second. This will be used to find the gaps. If not provided, a 1/2 second gap is assumed. + start_of_day_ns : float, optional + The start of the day in nanoseconds since TTJ2000. If provided, a gap will be + added from this time to the first epoch if they don't match. + end_of_day_ns : float, optional + The end of the day in nanoseconds since TTJ2000. If provided, a gap will be + added from the last epoch to this time if they don't match. Returns ------- @@ -545,25 +647,49 @@ def find_all_gaps( specified as (start, end, vector_rate) where start and end both exist in the timeline. """ - gaps: np.ndarray = np.zeros((0, 3)) - if vecsec_dict is None: - # TODO: when we go back to the previous file, also retrieve expected - # vectors per second - # If no vecsec is provided, assume 2 vectors per second - vecsec_dict = {0: VecSec.TWO_VECS_PER_S.value} - - end_index = epoch_data.shape[0] - for start_time in reversed(sorted(vecsec_dict.keys())): - start_index = np.where(start_time == epoch_data)[0][0] + gaps: np.ndarray = np.empty((0, 3), dtype=np.int64) + + # TODO: when we go back to the previous file, also retrieve expected + # vectors per second + + vecsec_dict = {0: VecSec.TWO_VECS_PER_S.value} | (vecsec_dict or {}) + + rate_segments = _find_rate_segments(epoch_data, vecsec_dict) + if rate_segments: + first_rate = rate_segments[0][1] + last_rate = rate_segments[-1][1] + else: + default_rate = next(iter(vecsec_dict.values())) + first_rate = default_rate + last_rate = default_rate + + if start_of_day_ns is not None and epoch_data[0] > start_of_day_ns: + # Add a gap from the start of the day to the first timestamp gaps = np.concatenate( ( - find_gaps( - epoch_data[start_index : end_index + 1], vecsec_dict[start_time] + gaps, + np.array( + [[start_of_day_ns, epoch_data[0], first_rate]], dtype=np.int64 ), + ) + ) + + for index, (start_index, vectors_per_second) in enumerate(rate_segments): + next_start_index = ( + rate_segments[index + 1][0] + if index + 1 < len(rate_segments) + else epoch_data.shape[0] - 1 + ) + epoch_slice = epoch_data[start_index : next_start_index + 1] + gaps = np.concatenate((gaps, find_gaps(epoch_slice, vectors_per_second))) + + if end_of_day_ns is not None and epoch_data[-1] < end_of_day_ns: + gaps = np.concatenate( + ( gaps, + np.array([[epoch_data[-1], end_of_day_ns, last_rate]], dtype=np.int64), ) ) - end_index = start_index return gaps @@ -589,16 +715,19 @@ def find_gaps(timeline_data: np.ndarray, vectors_per_second: int) -> np.ndarray: end_gap, as well as vectors_per_second. Start_gap and end_gap both correspond to points in timeline_data. """ + if timeline_data.shape[0] < 2: + return np.empty((0, 3), dtype=np.int64) + # Expected difference between timestamps in nanoseconds. expected_gap = 1 / vectors_per_second * 1e9 - # TODO: timestamps can vary by a few ms. Per Alastair, this can be around 7.5% of - # cadence without counting as a "gap". diffs = abs(np.diff(timeline_data)) - # 3.5e7 == 7.5% of 0.5s in nanoseconds, a common gap. In the future, this number - # will be calculated from the expected gap. - gap_index = np.asarray(diffs - expected_gap > expected_gap * 0.075).nonzero()[0] - output: np.ndarray = np.zeros((len(gap_index), 3)) + + # Gap can be up to 7.5% larger than expected vectors per second due to clock drift + gap_index = np.asarray( + diffs - expected_gap > expected_gap * L1C_TIMESTAMP_GAP_TOLERANCE + ).nonzero()[0] + output: np.ndarray = np.zeros((len(gap_index), 3), dtype=np.int64) for index, gap in enumerate(gap_index): output[index, :] = [ @@ -607,7 +736,6 @@ def find_gaps(timeline_data: np.ndarray, vectors_per_second: int) -> np.ndarray: vectors_per_second, ] - # TODO: How should I handle/find gaps at the end? return output @@ -615,28 +743,104 @@ def generate_missing_timestamps(gap: np.ndarray) -> np.ndarray: """ Generate a new timeline from input gaps. - Any gaps specified in gaps will be filled with timestamps that are 0.5 seconds - apart. + Any gaps specified in gaps will be filled with timestamps at the gap rate. If the + gap rate is not included, the default cadence is 0.5 seconds. Parameters ---------- gap : numpy.ndarray Array of timestamps of shape (2,) containing n gaps with start_gap and - end_gap. Start_gap and end_gap both correspond to points in timeline_data. + end_gap. Start_gap and end_gap both correspond to points in timeline_data and + are included in the output timespan. Returns ------- full_timeline: numpy.ndarray Completed timeline. """ - # Generated timestamps should always be 0.5 seconds apart - # TODO: is this in the configuration file? - difference_ns = 0.5 * 1e9 - - output: np.ndarray = np.arange(gap[0], gap[1], difference_ns) + difference_ns = int(0.5 * 1e9) + # Support both legacy (start, end) gaps, which use the historical 0.5 s cadence, + # and newer (start, end, rate) gaps, which use the declared cadence. + if len(gap) > 2: + difference_ns = int(1e9 / int(gap[2])) + output: np.ndarray = np.arange( + int(np.rint(gap[0])), + int(np.rint(gap[1])), + difference_ns, + dtype=np.int64, + ) return output +def _is_expected_rate(timestamp_difference: float, vectors_per_second: int) -> bool: + """ + Determine whether a timestamp spacing matches an expected cadence. + + Parameters + ---------- + timestamp_difference : float + The observed spacing between adjacent timestamps, in nanoseconds. + vectors_per_second : int + The expected number of vectors per second for the cadence being checked. + + Returns + ------- + bool + True when the observed spacing is within `L1C_TIMESTAMP_GAP_TOLERANCE` + of the expected cadence. + """ + expected_gap = 1 / vectors_per_second * 1e9 + return ( + abs(timestamp_difference - expected_gap) + <= expected_gap * L1C_TIMESTAMP_GAP_TOLERANCE + ) + + +def _find_rate_segments( + epoch_data: np.ndarray, vecsec_dict: dict[int, int] +) -> list[tuple[int, int]]: + """ + Build contiguous rate segments using observed cadence near each transition. + + Walk each configured transition backward while the observed cadence already matches + the new rate so gaps stay attached to the correct segment instead of producing + spurious single-sample micro-gaps at delayed Config boundaries. + + Parameters + ---------- + epoch_data : numpy.ndarray + The sorted epoch timestamps for the current timeline, in nanoseconds. + vecsec_dict : dict[int, int] + Mapping of transition start time to expected vectors-per-second rate. + + Returns + ------- + list[tuple[int, int]] + Pairs of `(start_index, vectors_per_second)` describing contiguous rate + segments in `epoch_data`. + """ + if epoch_data.shape[0] == 0: + return [] + + segments: list[tuple[int, int]] = [] + for start_time, vectors_per_second in sorted(vecsec_dict.items()): + start_index = int(np.searchsorted(epoch_data, start_time, side="left")) + start_index = min(start_index, epoch_data.shape[0] - 1) + lower_bound = segments[-1][0] if segments else 0 + + while start_index > lower_bound and _is_expected_rate( + epoch_data[start_index] - epoch_data[start_index - 1], vectors_per_second + ): + start_index -= 1 + + if segments and start_index == segments[-1][0]: + segments[-1] = (start_index, vectors_per_second) + else: + segments.append((start_index, vectors_per_second)) + + return segments + + def vectors_per_second_from_string(vecsec_string: str) -> dict: """ Extract the vectors per second from a string into a dictionary. @@ -657,8 +861,9 @@ def vectors_per_second_from_string(vecsec_string: str) -> dict: vecsec_dict = {} vecsec_segments = vecsec_string.split(",") for vecsec_segment in vecsec_segments: - start_time, vecsec = vecsec_segment.split(":") - vecsec_dict[int(start_time)] = int(vecsec) + if vecsec_segment: + start_time, vecsec = vecsec_segment.split(":") + vecsec_dict[int(start_time)] = int(vecsec) return vecsec_dict diff --git a/imap_processing/mag/l1d/mag_l1d.py b/imap_processing/mag/l1d/mag_l1d.py index 71c18d7d2d..f51f799111 100644 --- a/imap_processing/mag/l1d/mag_l1d.py +++ b/imap_processing/mag/l1d/mag_l1d.py @@ -78,7 +78,6 @@ def mag_l1d( # noqa: PLR0912 if not input_mago_norm.attrs.get("all_vectors_primary", 1): config.apply_gradiometry = False - # TODO: L1D attributes attributes = ImapCdfAttributes() attributes.add_instrument_global_attrs("mag") attributes.add_instrument_variable_attrs("mag", "l2") @@ -153,14 +152,14 @@ def mag_l1d( # noqa: PLR0912 # Add spin offsets dataset from normal mode processing if l1d_norm.spin_offsets is not None: spin_offset_dataset = l1d_norm.generate_spin_offset_dataset() - spin_offset_dataset.attrs["Logical_source"] = "imap_mag_l1d-spin-offsets" + spin_offset_dataset.attrs["Logical_source"] = "imap_mag_l1d_spin-offsets" output_datasets.append(spin_offset_dataset) # Add gradiometry offsets dataset if gradiometry was applied if l1d_norm.config.apply_gradiometry and hasattr(l1d_norm, "gradiometry_offsets"): gradiometry_dataset = l1d_norm.gradiometry_offsets.copy() gradiometry_dataset.attrs["Logical_source"] = ( - "imap_mag_l1d-gradiometry-offsets-norm" + "imap_mag_l1d_gradiometry-offsets-norm" ) output_datasets.append(gradiometry_dataset) @@ -169,7 +168,7 @@ def mag_l1d( # noqa: PLR0912 if hasattr(l1d_burst, "gradiometry_offsets"): burst_gradiometry_dataset = l1d_burst.gradiometry_offsets.copy() burst_gradiometry_dataset.attrs["Logical_source"] = ( - "imap_mag_l1d-gradiometry-offsets-burst" + "imap_mag_l1d_gradiometry-offsets-burst" ) output_datasets.append(burst_gradiometry_dataset) diff --git a/imap_processing/mag/l1d/mag_l1d_data.py b/imap_processing/mag/l1d/mag_l1d_data.py index 404ddd3523..e52546b580 100644 --- a/imap_processing/mag/l1d/mag_l1d_data.py +++ b/imap_processing/mag/l1d/mag_l1d_data.py @@ -1,7 +1,8 @@ # mypy: disable-error-code="unused-ignore" """Data classes for MAG L1D processing.""" -from dataclasses import InitVar, dataclass +import logging +from dataclasses import InitVar, dataclass, field import numpy as np import xarray as xr @@ -14,7 +15,9 @@ from imap_processing.mag.l2.mag_l2_data import MagL2L1dBase, ValidFrames from imap_processing.spice import spin from imap_processing.spice.geometry import frame_transform -from imap_processing.spice.time import ttj2000ns_to_met +from imap_processing.spice.time import ttj2000ns_to_et, ttj2000ns_to_met + +logger = logging.getLogger(__name__) @dataclass @@ -153,6 +156,7 @@ class MagL1d(MagL2L1dBase): # type: ignore[misc] config: MagL1dConfiguration spin_offsets: xr.Dataset = None day: InitVar[np.datetime64] + data_level: str = field(default="l1d", init=False) def __post_init__(self, day: np.datetime64) -> None: """ @@ -166,8 +170,14 @@ def __post_init__(self, day: np.datetime64) -> None: The day we are processing, in np.datetime64[D] format. This is used to truncate the data to exactly 24 hours. """ + # The main data frame is MAGO, even though we have MAGI data included. + self.frame = ValidFrames.MAGO + # set the magnitude before truncating - self.magnitude = np.zeros(self.vectors.shape[0], dtype=np.float64) # type: ignore[has-type] + self.magnitude: np.ndarray = np.zeros( # type: ignore[var-annotated] + self.vectors.shape[0], # type: ignore[has-type] + dtype=np.float64, + ) self.truncate_to_24h(day) self.vectors, self.magi_vectors = self._calibrate_and_offset_vectors( @@ -221,7 +231,8 @@ def generate_dataset( Generate an xarray dataset from the dataclass. This overrides the parent method to conditionally swap MAGO/MAGI data - based on the always_output_mago configuration setting. + based on the always_output_mago configuration setting, and to construct + the logical_source_id for L1D files. Parameters ---------- @@ -247,7 +258,7 @@ def generate_dataset( self.epoch = self.magi_epoch # type: ignore[no-redef] self.range = self.magi_range # type: ignore[no-redef] - # Call parent generate_dataset method + # Call parent generate_dataset method with L1D data level dataset = super().generate_dataset(attribute_manager, day) # Restore original vectors for any further processing @@ -272,14 +283,57 @@ def rotate_frame(self, end_frame: ValidFrames) -> None: end_frame : ValidFrames The frame to rotate to. Should be one of the ValidFrames enum. """ + # Self.frame should refer to the main data in self.vectors, which is MAGO + # data. For most frames, MAGO and MAGI are in the same frame, except the + # instrument reference frame. + if ValidFrames.MAGI in (self.frame, end_frame): + raise ValueError( + "MAGL1d.frame should never be equal to MAGI frame. If the " + "data is in the instrument frame, use MAGO." + ) + start_frame = self.frame - super().rotate_frame(end_frame) - self.magi_vectors = frame_transform( - self.magi_epoch, + + if self.epoch_et is None: + self.epoch_et: np.ndarray = ttj2000ns_to_et(self.epoch) + self.magi_epoch_et: np.ndarray = ttj2000ns_to_et(self.magi_epoch) + + new_vectors = frame_transform( + self.epoch_et, + self.vectors, + from_frame=start_frame.spice_frame, + to_frame=end_frame.spice_frame, + allow_spice_noframeconnect=True, + ) + if np.isnan(self.vectors).any() or (self.vectors == FILLVAL).any(): + new_vectors = np.where( + np.isnan(self.vectors) | (self.vectors == FILLVAL), + FILLVAL, + new_vectors, + ) + self.vectors = new_vectors + + # If we were in MAGO frame, we need to rotate MAGI vectors from MAGI to + # end_frame + if start_frame == ValidFrames.MAGO: + start_frame = ValidFrames.MAGI + + new_magi_vectors = frame_transform( + self.magi_epoch_et, self.magi_vectors, - from_frame=start_frame.value, - to_frame=end_frame.value, + from_frame=start_frame.spice_frame, + to_frame=end_frame.spice_frame, + allow_spice_noframeconnect=True, ) + if np.isnan(self.magi_vectors).any() or (self.magi_vectors == FILLVAL).any(): + new_magi_vectors = np.where( + np.isnan(self.magi_vectors) | (self.magi_vectors == FILLVAL), + FILLVAL, + new_magi_vectors, + ) + self.magi_vectors = new_magi_vectors + + self.frame = end_frame def _calibrate_and_offset_vectors( self, @@ -368,7 +422,7 @@ def apply_calibration_offset_single_vector( updated_vector = input_vector.copy() rng = int(input_vector[3]) x_y_z = input_vector[:3] - updated_vector[:3] = x_y_z - offsets[int(is_magi), rng, :] + updated_vector[:3] = x_y_z + offsets[int(is_magi), rng, :] return updated_vector def calculate_spin_offsets(self) -> xr.Dataset: @@ -404,7 +458,7 @@ def calculate_spin_offsets(self) -> xr.Dataset: epoch_met = ttj2000ns_to_met(self.epoch) sc_spin_phase = spin.get_spacecraft_spin_phase(epoch_met) # mark vectors as nan where they are nan in sc_spin_phase - vectors = self.vectors.copy().astype(np.float64) + vectors: np.ndarray = self.vectors.copy().astype(np.float64) vectors[np.isnan(sc_spin_phase), :] = np.nan @@ -469,6 +523,14 @@ def calculate_spin_offsets(self) -> xr.Dataset: chunk_vectors = self.vectors[chunk_indices[0] : chunk_indices[-1]] chunk_epoch = self.epoch[chunk_indices[0] : chunk_indices[-1]] + if len(chunk_epoch) == 0: + logger.warning( + "Skipping empty chunk at spin_starts index %d", + chunk_start, + ) + chunk_start = chunk_start + self.config.spin_count_calibration + continue + # Check if more than half of the chunk data is NaN before processing x_valid_count: int = int(np.sum(~np.isnan(chunk_vectors[:, 0]))) y_valid_count: int = int(np.sum(~np.isnan(chunk_vectors[:, 1]))) @@ -491,8 +553,8 @@ def calculate_spin_offsets(self) -> xr.Dataset: if not np.isnan(avg_x) and not np.isnan(avg_y): offset_epochs.append(chunk_epoch[0]) - x_avg_calcs.append(avg_x) - y_avg_calcs.append(avg_y) + x_avg_calcs.append(np.float64(avg_x)) + y_avg_calcs.append(np.float64(avg_y)) # Add validity time range for this chunk validity_start_times.append(chunk_epoch[0]) @@ -660,10 +722,12 @@ def calculate_gradiometry_offsets( - gradiometer_offset_magnitude: magnitude of the offset vector - quality_flags: quality flags (1 if magnitude > threshold, 0 otherwise) """ - aligned_magi = linear( + # TODO: should this extrapolate or should non-overlapping data be removed? + _, aligned_magi = linear( magi_vectors, magi_epoch, mago_epoch, + extrapolate=True, ) diff = aligned_magi - mago_vectors diff --git a/imap_processing/mag/l2/mag_l2.py b/imap_processing/mag/l2/mag_l2.py index 48101f9774..65632ae1a5 100644 --- a/imap_processing/mag/l2/mag_l2.py +++ b/imap_processing/mag/l2/mag_l2.py @@ -1,5 +1,7 @@ """Module to run MAG L2 processing.""" +import logging + import numpy as np import xarray as xr @@ -8,6 +10,16 @@ from imap_processing.mag.constants import DataMode from imap_processing.mag.l2.mag_l2_data import MagL2, ValidFrames +logger = logging.getLogger(__name__) + +DEFAULT_L2_FRAMES = [ + ValidFrames.SRF, + ValidFrames.GSE, + ValidFrames.GSM, + ValidFrames.RTN, + ValidFrames.DSRF, # should be last as some vectors may become NaN +] + def mag_l2( calibration_dataset: xr.Dataset, @@ -15,6 +27,7 @@ def mag_l2( input_data: xr.Dataset, day_to_process: np.datetime64, mode: DataMode = DataMode.NORM, + frames: list[ValidFrames] = DEFAULT_L2_FRAMES, ) -> list[xr.Dataset]: """ Complete MAG L2 processing. @@ -66,6 +79,9 @@ def mag_l2( mode : DataMode The data mode to process. Default is DataMode.NORM (normal mode). Can also be DataMode.BURST for burst mode processing. + frames : list[ValidFrames] + List of frames to output. DEFAULT_L2_FRAMES is [SRF, GSE, GSM, RTN, DSRF] + Note that DSRF should be last as some vectors may become NaN after rotation. Returns ------- @@ -75,6 +91,9 @@ def mag_l2( """ always_output_mago = configuration.ALWAYS_OUTPUT_MAGO + if not frames: + frames = DEFAULT_L2_FRAMES + # TODO Check that the input file matches the offsets file if not np.array_equal(input_data["epoch"].data, offsets_dataset["epoch"].data): raise ValueError("Input file and offsets file must have the same timestamps.") @@ -90,6 +109,7 @@ def mag_l2( ) # level 2 vectors don't include range vectors = cal_vectors[:, :3] + instrument_frame = ValidFrames.MAGO if always_output_mago else ValidFrames.MAGI l2_data = MagL2( vectors=vectors, @@ -101,19 +121,25 @@ def mag_l2( data_mode=mode, offsets=offsets_dataset["offsets"].data, timedelta=offsets_dataset["timedeltas"].data, + frame=instrument_frame, ) + # L2 data should not include the extra 30 min padding either side + # Note: this must be done after applying offsets and timedeltas + l2_data.truncate_to_24h(day) + attributes = ImapCdfAttributes() attributes.add_instrument_global_attrs("mag") attributes.add_instrument_variable_attrs("mag", "l2") # Rotate from the MAG frame into the SRF frame - l2_data.rotate_frame(ValidFrames.SRF) - imap_srf = l2_data.generate_dataset(attributes, day) - l2_data.rotate_frame(ValidFrames.DSRF) - imap_dsrf = l2_data.generate_dataset(attributes, day) + datasets: list[xr.Dataset] = [] + + for frame in frames: + l2_data.rotate_frame(frame) + datasets.append(l2_data.generate_dataset(attributes, day)) - return [imap_dsrf, imap_srf] + return datasets def retrieve_matrix_from_l2_calibration( diff --git a/imap_processing/mag/l2/mag_l2_data.py b/imap_processing/mag/l2/mag_l2_data.py index 41b24cc021..a12d1ce886 100644 --- a/imap_processing/mag/l2/mag_l2_data.py +++ b/imap_processing/mag/l2/mag_l2_data.py @@ -7,6 +7,7 @@ import xarray as xr from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes +from imap_processing.mag import constants from imap_processing.mag.constants import FILLVAL, DataMode from imap_processing.mag.l1b.mag_l1b import calibrate_vector from imap_processing.spice.geometry import SpiceFrame, frame_transform @@ -20,11 +21,105 @@ class ValidFrames(Enum): """SPICE reference frames for output.""" - MAG = SpiceFrame.IMAP_MAG - DSRF = SpiceFrame.IMAP_DPS - SRF = SpiceFrame.IMAP_SPACECRAFT - GSE = SpiceFrame.IMAP_GSE - RTN = SpiceFrame.IMAP_RTN + """ + Default MAGO and MAGI L1D and L2 frames both map to the same SPICE frame. + This is because the idealised IMAP_MAG_BASE frame is used for both sensors, + as the MAG team provides a calibration matrix to convert from the real mechanical + mount as assessed in flight into the idealised frame. + + MAGO_GROUND_CAL and MAGI_GROUND_CAL additionally included for reference to the + ground assessed mount, and for future use if needed. + """ + MAGO = ("MAGO", SpiceFrame.IMAP_MAG_BASE, "vector_attrs", "vectors") + MAGI = ("MAGI", SpiceFrame.IMAP_MAG_BASE, "vector_attrs", "vectors") + + MAGO_GROUND_CAL = ( + "MAGO_GROUND_CAL", + SpiceFrame.IMAP_MAG_O, + "vector_attrs", + "vectors", + ) + MAGI_GROUND_CAL = ( + "MAGI_GROUND_CAL", + SpiceFrame.IMAP_MAG_I, + "vector_attrs", + "vectors", + ) + + DSRF = ("DSRF", SpiceFrame.IMAP_DPS, "vector_attrs_dsrf", "b_dsrf") + SRF = ("SRF", SpiceFrame.IMAP_SPACECRAFT, "vector_attrs_srf", "b_srf") + GSE = ("GSE", SpiceFrame.IMAP_GSE, "vector_attrs_gse", "b_gse") + GSM = ("GSM", SpiceFrame.IMAP_GSM, "vector_attrs_gsm", "b_gsm") + RTN = ("RTN", SpiceFrame.IMAP_RTN, "vector_attrs_rtn", "b_rtn") + + _spice_frame_: SpiceFrame + _vector_attrs_name_: str + _var_name_: str + + def __new__( + cls, value: str, spice_frame: SpiceFrame, attrs_name: str, var_name: str + ) -> "ValidFrames": + """ + Construct a new Valid Frame. + + Parameters + ---------- + value : str + Unique name of the frame. + spice_frame : str + The SPICE frame name corresponding to this frame. + attrs_name : str + The name of the variable attributes in the attribute manager for this frame. + var_name : str + The name of the variable in the output dataset for this frame. + + Returns + ------- + ValidFrame : ValidFrame + A ValidFrame enum member. + """ + obj = object.__new__(cls) + obj._value_ = value + obj._spice_frame_ = spice_frame + obj._vector_attrs_name_ = attrs_name + obj._var_name_ = var_name + return obj + + @property + def spice_frame(self) -> SpiceFrame: + """ + Get the SPICE frame name for this ValidFrame. + + Returns + ------- + spice_frame : str + The frame's associated spice frame. + """ + return self._spice_frame_ + + @property + def vector_attrs_name(self) -> str: + """ + Get the vector attributes name for this valid frame. + + Returns + ------- + vector_attrs_name : str + The frame's associated vector attributes name. + """ + return self._vector_attrs_name_ + + @property + def var_name(self) -> str: + """ + Get the vector variable name for this valid frame. + + Returns + ------- + var_name : str + The frame's associated vectors variable name. + """ + return self._var_name_ @dataclass(kw_only=True) @@ -56,10 +151,13 @@ class MagL2L1dBase: Quality bitmask for each vector. Should be of length n. Copied from offset file in L2, marked as good always in L1D. frame: - The reference frame of the input vectors. Starts as the MAG instrument frame. + The reference frame of the input vectors. Defaults to the MAGO instrument frame. epoch_et: np.ndarray The epoch timestamps converted to ET format. Used for frame transformations. Calculated on first use and then saved. Should not be passed in. + data_level: str + The data level of the product, to be used in the output attributes. + This should always be overridden by base classes. """ vectors: np.ndarray @@ -70,8 +168,9 @@ class MagL2L1dBase: quality_bitmask: np.ndarray data_mode: DataMode magnitude: np.ndarray = field(init=False) - frame: ValidFrames = ValidFrames.MAG + frame: ValidFrames = ValidFrames.MAGO epoch_et: np.ndarray | None = field(init=False, default=None) + data_level: str = field(init=False) def generate_dataset( self, @@ -99,8 +198,10 @@ def generate_dataset( self.truncate_to_24h(day) logical_source_id = ( - f"imap_mag_l2_{self.data_mode.value.lower()}-{self.frame.name.lower()}" + f"imap_mag_{self.data_level}_{self.data_mode.value.lower()}-" + f"{self.frame.name.lower()}" ) + direction = xr.DataArray( np.arange(3), name="direction", @@ -130,9 +231,11 @@ def generate_dataset( vectors = xr.DataArray( self.vectors, - name="vectors", + name=self.frame.var_name, dims=["epoch", "direction"], - attrs=attribute_manager.get_variable_attributes("vector_attrs"), + attrs=attribute_manager.get_variable_attributes( + self.frame.vector_attrs_name, check_schema=False + ), ) quality_flags = xr.DataArray( @@ -153,15 +256,18 @@ def generate_dataset( self.range, name="range", dims=["epoch"], - # TODO temp attrs - attrs=attribute_manager.get_variable_attributes("fill"), + attrs=attribute_manager.get_variable_attributes( + "range", check_schema=False + ), ) magnitude = xr.DataArray( self.magnitude, name="magnitude", dims=["epoch"], - attrs=attribute_manager.get_variable_attributes("fill"), + attrs=attribute_manager.get_variable_attributes( + "magnitude", check_schema=False + ), ) global_attributes = ( @@ -178,7 +284,7 @@ def generate_dataset( attrs=global_attributes, ) - output["vectors"] = vectors + output[self.frame.var_name] = vectors output["quality_flags"] = quality_flags output["quality_bitmask"] = quality_bitmask output["range"] = rng @@ -214,6 +320,12 @@ def truncate_to_24h(self, timestamp: np.datetime64) -> None: self.quality_flags = self.quality_flags[day_start_index:day_end_index] self.quality_bitmask = self.quality_bitmask[day_start_index:day_end_index] + if self.epoch_et is not None: + self.epoch_et = self.epoch_et[day_start_index:day_end_index] + + if self.epoch.shape[0] == 0: + raise ValueError("After truncating to 24 hours, no data remains.") + @staticmethod def calculate_magnitude( vectors: np.ndarray, @@ -309,27 +421,31 @@ def rotate_frame(self, end_frame: ValidFrames) -> None: """ if self.epoch_et is None: self.epoch_et = ttj2000ns_to_et(self.epoch) - self.vectors = frame_transform( + new_vectors = frame_transform( self.epoch_et, self.vectors, - from_frame=self.frame.value, - to_frame=end_frame.value, + from_frame=self.frame.spice_frame, + to_frame=end_frame.spice_frame, + allow_spice_noframeconnect=True, ) + if np.isnan(self.vectors).any() or (self.vectors == constants.FILLVAL).any(): + new_vectors = np.where( + np.isnan(self.vectors) | (self.vectors == constants.FILLVAL), + constants.FILLVAL, + new_vectors, + ) + + self.vectors = new_vectors self.frame = end_frame @dataclass(kw_only=True) class MagL2(MagL2L1dBase): - """ - Dataclass for MAG L2 data. - - Since L2 and L1D should have the same structure, this can be used for either level. - - Some of the methods are also static, so they can be used in i-ALiRT processing. - """ + """Dataclass for MAG L2 data.""" offsets: InitVar[np.ndarray] = None timedelta: InitVar[np.ndarray] = None + data_level: str = field(default="l2", init=False) def __post_init__(self, offsets: np.ndarray, timedelta: np.ndarray) -> None: """ diff --git a/imap_processing/quality_flags.py b/imap_processing/quality_flags.py index 6c5f478101..e0c48df2bb 100644 --- a/imap_processing/quality_flags.py +++ b/imap_processing/quality_flags.py @@ -43,6 +43,10 @@ class ImapDEOutliersUltraFlags(FlagNameMixin): NONE = CommonFlags.NONE FOV = 2**0 # bit 0 PHCORR = 2**1 # bit 1 + COINPH = 2**2 # bit 2 # Event validity + INVALID_ENERGY = 2**3 # bit 3 + DURINGREPOINT = 2**4 # bit 4 # event during a repointing + BACKTOF = 2**5 # bit 5 # Back TOF outlier class ImapHkUltraFlags(FlagNameMixin): @@ -83,6 +87,13 @@ class ImapDEScatteringUltraFlags(FlagNameMixin): NAN_PHI_OR_THETA = 2**1 # bit 1 +class ImapPSETUltraFlags(FlagNameMixin): + """IMAP Ultra Rates flags.""" + + NONE = CommonFlags.NONE + EARTH_FOV = 2**0 # bit 0 + + class ImapInstrumentUltraFlags(FlagNameMixin): """IMAP Ultra flags using other instruments.""" @@ -131,3 +142,32 @@ class SWAPIFlags( SCEM_V_ST = 2**12 # bit 12 SCEM_I_ST = 2**13 # bit 13 SCEM_INT_ST = 2**14 # bit 14 + + +class GLOWSL1bFlags(FlagNameMixin): + """Glows L1b flags.""" + + NONE = CommonFlags.NONE + IS_CLOSE_TO_UV_SOURCE = 2**0 # Is the bin close to a UV source. + IS_INSIDE_EXCLUDED_REGION = 2**1 # Is the bin inside an excluded sky region. + IS_EXCLUDED_BY_INSTR_TEAM = 2**2 # Is the bin excluded by the instrument team. + IS_SUSPECTED_TRANSIENT = 2**3 # Is the bin a suspected transient. + + +class SweL1bFlags(FlagNameMixin): + """SWE L1b flags.""" + + NONE = CommonFlags.NONE + INF = CommonFlags.INF + NEG = CommonFlags.NEG + LAST_CAL_INTERVAL = ( + 2**2 + ) # bit 2, counter values extrapolated using last two cal entries + + +class ImapHiL1bDeFlags(FlagNameMixin): + """IMAP Hi L1B Direct Event CCSDS packet quality flags.""" + + NONE = CommonFlags.NONE + PACKET_FULL = 2**0 # bit 0, packet contained 664 events (max capacity) + BADSPIN = ENAFlags.BADSPIN # bit 2, packet contained events from an invalid spin diff --git a/imap_processing/spice/geometry.py b/imap_processing/spice/geometry.py index 557eace2c0..1325609327 100644 --- a/imap_processing/spice/geometry.py +++ b/imap_processing/spice/geometry.py @@ -9,6 +9,7 @@ * Always return numpy arrays for vectorized calls. """ +import logging import typing from enum import IntEnum @@ -17,11 +18,13 @@ import spiceypy from numpy.typing import NDArray +logger = logging.getLogger(__name__) + class SpiceBody(IntEnum): """Enum containing SPICE IDs for bodies that we use.""" - # A subset of IMAP Specific bodies as defined in imap_wkcp.tf + # A subset of IMAP Specific bodies as defined in imap_xxx.tf IMAP = -43 IMAP_SPACECRAFT = -43000 # IMAP Pointing Frame (Despun) as defined in imap_science_xxx.tf @@ -33,7 +36,7 @@ class SpiceBody(IntEnum): class SpiceFrame(IntEnum): - """SPICE IDs for reference frames in imap_wkcp.tf and imap_science_xxx.tf.""" + """SPICE IDs for reference frames in imap_###.tf and imap_science_xxx.tf.""" # Standard SPICE Frames J2000 = spiceypy.irfnum("J2000") @@ -41,16 +44,19 @@ class SpiceFrame(IntEnum): ITRF93 = 13000 # IMAP Pointing Frame (Despun) as defined in imap_science_xxx.tf IMAP_DPS = -43901 - # IMAP specific as defined in imap_wkcp.tf + # IMAP specific as defined in imap_###.tf IMAP_SPACECRAFT = -43000 IMAP_LO_BASE = -43100 - IMAP_LO_STAR_SENSOR = -43103 - IMAP_LO = -43105 + IMAP_LO = -43101 + IMAP_LO_STAR_SENSOR = -43102 IMAP_HI_45 = -43150 - IMAP_HI_90 = -43160 + IMAP_HI_90 = -43151 IMAP_ULTRA_45 = -43200 - IMAP_ULTRA_90 = -43210 - IMAP_MAG = -43250 + IMAP_ULTRA_90 = -43201 + IMAP_MAG_BOOM = -43250 + IMAP_MAG_I = -43251 + IMAP_MAG_O = -43252 + IMAP_MAG_BASE = -43253 IMAP_SWE = -43300 IMAP_SWAPI = -43350 IMAP_CODICE = -43400 @@ -59,7 +65,9 @@ class SpiceFrame(IntEnum): IMAP_GLOWS = -43750 # IMAP Science Frames (new additions from imap_science_xxx.tf) - IMAP_OMD = -43900 + # IMAP_OMD appears to have a bad definition in imap_science_120.tf + # Commenting it out for now. + # IMAP_OMD = -43900 IMAP_EARTHFIXED = -43910 IMAP_ECLIPDATE = -43911 IMAP_MDI = -43912 @@ -79,15 +87,19 @@ class SpiceFrame(IntEnum): IMAP_HRE = -43927 IMAP_HNU = -43928 IMAP_GCS = -43929 + IMAP_HRC = -43930 BORESIGHT_LOOKUP = { SpiceFrame.IMAP_LO_BASE: np.array([0, -1, 0]), + SpiceFrame.IMAP_LO: np.array([0, -1, 0]), + SpiceFrame.IMAP_LO_STAR_SENSOR: np.array([0, -1, 0]), SpiceFrame.IMAP_HI_45: np.array([0, 1, 0]), SpiceFrame.IMAP_HI_90: np.array([0, 1, 0]), SpiceFrame.IMAP_ULTRA_45: np.array([0, 0, 1]), SpiceFrame.IMAP_ULTRA_90: np.array([0, 0, 1]), - SpiceFrame.IMAP_MAG: np.array([0, 0, 1]), + SpiceFrame.IMAP_MAG_I: np.array([0, 0, 1]), + SpiceFrame.IMAP_MAG_O: np.array([0, 0, 1]), SpiceFrame.IMAP_SWE: np.array([-1, 0, 0]), SpiceFrame.IMAP_SWAPI: np.array([0, 1, 0]), SpiceFrame.IMAP_CODICE: np.array([0, 0, 1]), @@ -124,7 +136,7 @@ def imap_state( ------- state : np.ndarray The Cartesian state vector representing the position and velocity of the - IMAP spacecraft. + IMAP spacecraft. Units are km and km/s. """ state, _ = spiceypy.spkezr( SpiceBody.IMAP.name, et, ref_frame.name, abcorr, observer.name @@ -157,12 +169,13 @@ def get_instrument_mounting_az_el(instrument: SpiceFrame) -> np.ndarray: # frame that is used to compute the s/c to instrument mounting. # Most of these vectors are the same as the instrument boresight vector. mounting_normal_vector = { - SpiceFrame.IMAP_LO_BASE: np.array([0, -1, 0]), + SpiceFrame.IMAP_LO_BASE: np.array([0, 0, -1]), SpiceFrame.IMAP_HI_45: np.array([0, 1, 0]), SpiceFrame.IMAP_HI_90: np.array([0, 1, 0]), SpiceFrame.IMAP_ULTRA_45: np.array([0, 0, 1]), SpiceFrame.IMAP_ULTRA_90: np.array([0, 0, 1]), - SpiceFrame.IMAP_MAG: np.array([-1, 0, 0]), + SpiceFrame.IMAP_MAG_I: np.array([-1, 0, 0]), + SpiceFrame.IMAP_MAG_O: np.array([-1, 0, 0]), SpiceFrame.IMAP_SWE: np.array([-1, 0, 0]), SpiceFrame.IMAP_SWAPI: np.array([0, 0, -1]), SpiceFrame.IMAP_CODICE: np.array([-1, 0, 0]), @@ -186,11 +199,16 @@ def get_spacecraft_to_instrument_spin_phase_offset(instrument: SpiceFrame) -> fl """ Get the spin phase offset from the spacecraft to the instrument. - For now, the offset is a fixed lookup based on `Table 1: Nominal Instrument + Nominal offset values were determined using `Table 1: Nominal Instrument to S/C CS Transformations` in document `7516-0011_drw.pdf`. That Table - defines the angle from the spacecraft y-axis. We add 90 and take the modulous - with 360 in order to get the angle from the spacecraft x-axis. These fixed - values will need to be updated based on calibration data. + defines the angle from the spacecraft y-axis. We add 90-degrees and take the + modulus with 360 to get the angle from the spacecraft x-axis. This math is + shown in the comments after each key value pair in the dictionary defined + in code. The true values differ slightly from the nominal values. True + values are derived from the frame definitions in the IMAP frames kernel + which uses ground calibration measurements to define the as-built mounting + of each instrument. The function in this module, `get_instrument_mounting_az_el`, + was used to retrieve the true azimuth angles from the IMAP frames kernel. Parameters ---------- @@ -203,18 +221,21 @@ def get_spacecraft_to_instrument_spin_phase_offset(instrument: SpiceFrame) -> fl The spin phase offset from the spacecraft to the instrument. """ phase_offset_lookup = { - SpiceFrame.IMAP_LO_BASE: 60 / 360, # (330 + 90) % 360 = 60 - SpiceFrame.IMAP_HI_45: 345 / 360, # 255 + 90 = 345 - SpiceFrame.IMAP_HI_90: 15 / 360, # (285 + 90) % 360 = 15 - SpiceFrame.IMAP_ULTRA_45: 123 / 360, # 33 + 90 = 123 - SpiceFrame.IMAP_ULTRA_90: 300 / 360, # 210 + 90 = 300 - SpiceFrame.IMAP_SWAPI: 258 / 360, # 168 + 90 = 258 - SpiceFrame.IMAP_IDEX: 180 / 360, # 90 + 90 = 180 - SpiceFrame.IMAP_CODICE: 226 / 360, # 136 + 90 = 226 - SpiceFrame.IMAP_HIT: 120 / 360, # 30 + 90 = 120 - SpiceFrame.IMAP_SWE: 243 / 360, # 153 + 90 = 243 - SpiceFrame.IMAP_GLOWS: 217 / 360, # 127 + 90 = 217 - SpiceFrame.IMAP_MAG: 90 / 360, # 0 + 90 = 90 + # Phase offset values based on imap_130.tf frame kernel + # See docstring notes for details on how these values were determined. + SpiceFrame.IMAP_LO: 60 / 360, # (330 + 90) % 360 = 60 + SpiceFrame.IMAP_HI_45: 344.8264 / 360, # 255 + 90 = 345 + SpiceFrame.IMAP_HI_90: 15.1649 / 360, # (285 + 90) % 360 = 15 + SpiceFrame.IMAP_ULTRA_45: 122.8642 / 360, # 33 + 90 = 123 + SpiceFrame.IMAP_ULTRA_90: 299.9511 / 360, # 210 + 90 = 300 + SpiceFrame.IMAP_SWAPI: 258.0135 / 360, # 168 + 90 = 258 + SpiceFrame.IMAP_IDEX: 179.9229 / 360, # 90 + 90 = 180 + SpiceFrame.IMAP_CODICE: 225.9086 / 360, # 136 + 90 = 226 + SpiceFrame.IMAP_HIT: 119.6452 / 360, # 30 + 90 = 120 + SpiceFrame.IMAP_SWE: 243.0155 / 360, # 153 + 90 = 243 + SpiceFrame.IMAP_GLOWS: 217.1384 / 360, # 127 + 90 = 217 + SpiceFrame.IMAP_MAG_I: 89.9709 / 360, # 0 + 90 = 90 + SpiceFrame.IMAP_MAG_O: 89.4077 / 360, # 0 + 90 = 90 } return phase_offset_lookup[instrument] @@ -224,6 +245,7 @@ def frame_transform( position: npt.NDArray, from_frame: SpiceFrame, to_frame: SpiceFrame, + allow_spice_noframeconnect: bool = False, ) -> npt.NDArray: """ Transform an vector between reference frames (rotation only). @@ -250,6 +272,11 @@ def frame_transform( Reference frame of input vector(s). to_frame : SpiceFrame Reference frame of output vector(s). + allow_spice_noframeconnect : bool + If True, does not throw SPICE NOFRAMECONNECT error and returns a NaN vector + for those `et`s where there is insufficient information available to transform + from `from_frame` to `to_frame`. + Defaults to False. Returns ------- @@ -282,7 +309,7 @@ def frame_transform( # rotate will have shape = (3, 3) or (n, 3, 3) # position will have shape = (3,) or (n, 3) - rotate = get_rotation_matrix(et, from_frame, to_frame) + rotate = get_rotation_matrix(et, from_frame, to_frame, allow_spice_noframeconnect) # adding a dimension to position results in the following input and output # shapes from matrix multiplication # Single et/position: (3, 3),(3, 1) -> (3, 1) @@ -309,6 +336,7 @@ def frame_transform_az_el( Ephemeris time(s) corresponding to position(s). az_el : np.ndarray vector or array of vectors in reference frame `from_frame`. + Azimuth and elevation pairs are always the final dimension of the array. There are several possible shapes for the input az_el and et: 1. A single az_el vector may be provided for multiple `et` query times 2. A single `et` may be provided for multiple az_el vectors, @@ -326,15 +354,16 @@ def frame_transform_az_el( to_frame_az_el : np.ndarray Azimuth/elevation coordinates in reference frame `to_frame`. This output coordinate vector will have shape (2,) if a single `az_el` position - vector and single `et` time are input. Otherwise, it will have shape (n, 2) - where n is the number of input position vector or ephemeris times. The last - axis of the output vector contains azimuth in the 0th position and elevation - in the 1st position. + vector and single `et` time are input. Otherwise, it will have shape (..., 2) + where ... matches the leading dimensions of the input position vector or + ephemeris times. The last axis of the output vector contains azimuth in + the 0th position and elevation in the 1st position. """ # Convert input az/el to Cartesian vectors - spherical_coords_in = np.array( - [np.ones_like(az_el[..., 0]), az_el[..., 0], az_el[..., 1]] - ).T + spherical_coords_in = np.stack( + [np.ones_like(az_el[..., 0]), az_el[..., 0], az_el[..., 1]], + axis=-1, + ) from_frame_cartesian = spherical_to_cartesian(spherical_coords_in) # Transform to to_frame to_frame_cartesian = frame_transform(et, from_frame_cartesian, from_frame, to_frame) @@ -347,10 +376,13 @@ def get_rotation_matrix( et: float | npt.NDArray, from_frame: SpiceFrame, to_frame: SpiceFrame, + allow_spice_noframeconnect: bool = False, ) -> npt.NDArray: """ Get the rotation matrix/matrices that can be used to transform between frames. + If no transformation is defined for a specific time, a matrix of NaNs is returned. + This is a vectorized wrapper around `spiceypy.pxform` "Return the matrix that transforms position vectors from one specified frame to another at a specified epoch." @@ -364,6 +396,11 @@ def get_rotation_matrix( Reference frame to transform from. to_frame : SpiceFrame Reference frame to transform to. + allow_spice_noframeconnect : bool + If True, does not throw SPICE NOFRAMECONNECT error and returns a NaN matrix + for those `et`s where there is insufficient information available to transform + from `from_frame` to `to_frame`. + Defaults to False. Returns ------- @@ -371,9 +408,27 @@ def get_rotation_matrix( If `et` is a float, the returned rotation matrix is of shape `(3, 3)`. If `et` is a np.ndarray, the returned rotation matrix is of shape `(n, 3, 3)` where `n` matches the number of elements in et. + Some of the matrices in the output may be NaN if no transformation was + available for the corresponding `et` and `allow_spice_noframeconnect` is True. """ + + def pxform_error_handler( # type: ignore[no-untyped-def] + *arg, **kwargs + ): # numpydoc ignore=GL08 + try: + return spiceypy.pxform(*arg, **kwargs) + except spiceypy.utils.exceptions.SpiceNOFRAMECONNECT as e: + if not allow_spice_noframeconnect: + raise e + logger.debug( + "Returning NaN matrix due to spiceypy error in rotation from" + f" {from_frame} to {to_frame} at et={et}", + exc_info=e, + ) + return np.full((3, 3), np.nan) + vec_pxform = np.vectorize( - spiceypy.pxform, + pxform_error_handler, excluded=["fromstr", "tostr"], signature="(),(),()->(3,3)", otypes=[np.float64], @@ -419,6 +474,97 @@ def instrument_pointing( return np.rad2deg(spiceypy.reclat(pointing)[1:]) +def get_lo_pivot_boresight(pivot_angle: float) -> npt.NDArray: + """ + Calculate IMAP-Lo boresight direction as a function of pivot angle. + + IMAP-Lo has a pivot mechanism that rotates the instrument about its X-axis. + The base boresight direction in IMAP_LO_BASE frame is [0, -1, 0] (negative Y). + This function rotates that boresight about the X-axis by the specified + pivot angle to get the actual boresight direction. + + At a pivot angle of 90 degrees, the boresight points in the -Z direction + in the IMAP_LO_BASE frame, which corresponds to near-zero off-pointing in the + despun (IMAP_DPS) frame. + + Parameters + ---------- + pivot_angle : float + The pivot angle in degrees. Nominal value is 90 degrees. + + Returns + ------- + boresight : np.ndarray + The boresight unit vector (shape (3,)) in the IMAP_LO_BASE frame. + """ + # Base boresight direction in IMAP_LO_BASE frame (negative Y) + base_boresight = BORESIGHT_LOOKUP[SpiceFrame.IMAP_LO_BASE] + + # Convert pivot angle to radians + # Negate the angle because the SPICE rotate function rotates counterclockwise + # when viewed from positive axis, but we want the physical pivot direction + # where 90 degrees gives us -Z direction (into the spin plane) + pivot_rad = np.deg2rad(-pivot_angle) + + # Use SPICE rotate function to create rotation matrix about X-axis (axis 1) + # spiceypy.rotate returns a rotation matrix for the specified angle about + # the specified axis (1=X, 2=Y, 3=Z) + rotation_matrix = spiceypy.rotate(pivot_rad, 1) + boresight = spiceypy.mxv(rotation_matrix, base_boresight) + + return np.asarray(boresight) + + +def lo_instrument_pointing( + et: float | npt.NDArray, + pivot_angle: float, + to_frame: SpiceFrame, + cartesian: bool = False, +) -> npt.NDArray: + """ + Compute IMAP-Lo instrument pointing accounting for pivot angle. + + This function computes the Lo boresight direction in the specified reference + frame, accounting for the instrument's pivot mechanism. The pivot rotates + the boresight about the instrument's X-axis. + + By default, the coordinates returned are (Longitude, Latitude) coordinates in + the reference frame `to_frame`. In the IMAP_DPS frame, Longitude corresponds + to spin angle and Latitude corresponds to off-pointing angle. + + Parameters + ---------- + et : float or np.ndarray + Ephemeris time(s) at which to compute instrument pointing. + pivot_angle : float + The Lo pivot angle in degrees. Nominal value is 90 degrees. + to_frame : SpiceFrame + Reference frame in which the pointing is to be expressed. + Typically SpiceFrame.IMAP_DPS for spin angle / off-pointing calculations. + cartesian : bool + If set to True, the pointing is returned in Cartesian coordinates. + Defaults to False. + + Returns + ------- + pointing : np.ndarray + The instrument pointing at the specified times. + If cartesian=False (default): returns (longitude, latitude) in degrees. + If cartesian=True: returns (x, y, z) unit vectors. + """ + # Get the pivot-adjusted boresight in IMAP_LO_BASE frame + boresight = get_lo_pivot_boresight(pivot_angle) + + # Transform from IMAP_LO_BASE to the target frame + pointing = frame_transform(et, boresight, SpiceFrame.IMAP_LO_BASE, to_frame) + + if cartesian: + return pointing + if isinstance(et, typing.Collection): + return np.rad2deg([spiceypy.reclat(vec)[1:] for vec in pointing]) + return np.rad2deg(spiceypy.reclat(pointing)[1:]) + + def basis_vectors( et: float | npt.NDArray, from_frame: SpiceFrame, @@ -517,7 +663,7 @@ def cartesian_to_spherical( az = np.degrees(az) el = np.degrees(el) - spherical_coords = np.stack((np.squeeze(magnitude_v), az, el), axis=-1) + spherical_coords = np.stack((np.squeeze(magnitude_v, -1), az, el), axis=-1) return spherical_coords diff --git a/imap_processing/spice/pointing_frame.py b/imap_processing/spice/pointing_frame.py index d5b7818000..9d3990fe40 100644 --- a/imap_processing/spice/pointing_frame.py +++ b/imap_processing/spice/pointing_frame.py @@ -11,7 +11,8 @@ from imap_data_access import SPICEFilePath from numpy.typing import NDArray -from imap_processing.spice.geometry import SpiceFrame +from imap_processing.spice import IMAP_SC_ID +from imap_processing.spice.geometry import SpiceBody, SpiceFrame, frame_transform from imap_processing.spice.repoint import get_repoint_data from imap_processing.spice.time import ( TICK_DURATION, @@ -22,7 +23,7 @@ logger = logging.getLogger(__name__) -POINTING_SEGMENT_DTYPE = np.dtype( +POINTING_SEGMENT_DTYPE: np.dtype = np.dtype( [ # sclk ticks are a double precision number of SCLK ticks since the # start of the mission (e.g. MET_seconds / TICK_DURATION) @@ -34,14 +35,14 @@ ) -def generate_pointing_attitude_kernel(imap_attitude_ck: Path) -> list[Path]: +def generate_pointing_attitude_kernel(imap_attitude_cks: list[Path]) -> list[Path]: """ Generate pointing attitude kernel from input IMAP CK kernel. Parameters ---------- - imap_attitude_ck : Path - Location of the IMAP attitude kernel from which to generate pointing + imap_attitude_cks : list[Path] + List of the IMAP attitude kernels from which to generate pointing attitude. Returns @@ -49,20 +50,29 @@ def generate_pointing_attitude_kernel(imap_attitude_ck: Path) -> list[Path]: pointing_kernel_path : list[Path] Location of the new pointing kernels. """ - pointing_segments = calculate_pointing_attitude_segments(imap_attitude_ck) + pointing_segments = calculate_pointing_attitude_segments(imap_attitude_cks) + if len(pointing_segments) == 0: + raise ValueError("No Pointings covered by input dependencies.") + # get the start and end yyyy_doy strings - # TODO: For now just use the input CK start/end dates. It is possible that - # the end date is incorrect b/c the repoint table determines the last - # segment in the pointing kernel. - spice_file = SPICEFilePath(imap_attitude_ck.name) + start_datetime = spiceypy.et2datetime( + sct_to_et(pointing_segments[0]["start_sclk_ticks"]) + ) + end_datetime = spiceypy.et2datetime( + sct_to_et(pointing_segments[-1]["end_sclk_ticks"]) + ) + # Use the last ck from sorted list to get the version number. I + # don't think this will be anything but 1. + sorted_ck_paths = list(sorted(imap_attitude_cks, key=lambda x: x.name)) + spice_file = SPICEFilePath(sorted_ck_paths[-1].name) pointing_kernel_path = ( - imap_attitude_ck.parent / f"imap_dps_" - f"{spice_file.spice_metadata['start_date'].strftime('%Y_%j')}_" - f"{spice_file.spice_metadata['end_date'].strftime('%Y_%j')}_" + sorted_ck_paths[-1].parent / f"imap_dps_" + f"{start_datetime.strftime('%Y_%j')}_" + f"{end_datetime.strftime('%Y_%j')}_" f"{spice_file.spice_metadata['version']}.ah.bc" ) write_pointing_frame_ck( - pointing_kernel_path, pointing_segments, imap_attitude_ck.name + pointing_kernel_path, pointing_segments, [p.name for p in imap_attitude_cks] ) return [pointing_kernel_path] @@ -93,7 +103,7 @@ def open_spice_ck_file(pointing_frame_path: Path) -> Generator[int, None, None]: def write_pointing_frame_ck( - pointing_kernel_path: Path, segment_data: np.ndarray, parent_ck: str + pointing_kernel_path: Path, segment_data: np.ndarray, parent_cks: list[str] ) -> None: """ Write a Pointing Frame attitude kernel. @@ -108,21 +118,21 @@ def write_pointing_frame_ck( ("end_sclk_ticks", np.float64), ("quaternion", np.float64, (4,)), ("pointing_id", np.uint32), - parent_ck : str - Filename of the CK kernel that the quaternion was derived from. + parent_cks : list[str] + Filenames of the CK kernels that the quaternions were derived from. """ - id_imap_dps = spiceypy.gipool("FRAME_IMAP_DPS", 0, 1) - comments = [ "CK FOR IMAP_DPS FRAME", "==================================================================", "", f"Original file name: {pointing_kernel_path.name}", f"Creation date: {datetime.now(timezone.utc).strftime('%Y-%m-%d')}", - f"Parent file: {parent_ck}", + f"Parent files: {parent_cks}", "", ] + logger.debug(f"Writing pointing attitude kernel: {pointing_kernel_path}") + with open_spice_ck_file(pointing_kernel_path) as handle: # Write the comments to the file spiceypy.dafac(handle, comments) @@ -138,7 +148,7 @@ def write_pointing_frame_ck( # End time of the segment. segment["end_sclk_ticks"], # Pointing frame ID. - int(id_imap_dps), + SpiceFrame.IMAP_DPS.value, # Reference frame. SpiceFrame.ECLIPJ2000.name, # Reference frame # Identifier. @@ -161,9 +171,11 @@ def write_pointing_frame_ck( np.array([TICK_DURATION]), ) + logger.debug(f"Finished writing pointing attitude kernel: {pointing_kernel_path}") + def calculate_pointing_attitude_segments( - ck_path: Path, + ck_paths: list[Path], ) -> NDArray: """ Calculate the data for each segment of the DPS_FRAME attitude kernel. @@ -177,8 +189,8 @@ def calculate_pointing_attitude_segments( Parameters ---------- - ck_path : pathlib.Path - Location of the CK kernel. + ck_paths : list[pathlib.Path] + List of CK kernels to use to generate the pointing attitude kernel. Returns ------- @@ -195,39 +207,42 @@ def calculate_pointing_attitude_segments( - Latest NAIF leapseconds kernel (naif0012.tls) - The latest IMAP sclk (imap_sclk_NNNN.tsc) - - The latest IMAP frame kernel (imap_wkcp.tf) - - IMAP DPS frame kernel (imap_science_100.tf) + - The latest IMAP frame kernel (imap_###.tf) + - IMAP DPS frame kernel (imap_science_120.tf) - IMAP historical attitude kernel from which the pointing frame kernel will be generated. """ - logger.info(f"Extracting mean spin axes from CK kernel {ck_path.name}") - # Get IDs. - # https://spiceypy.readthedocs.io/en/main/documentation.html#spiceypy.spiceypy.gipool - id_imap_sclk = spiceypy.gipool("CK_-43000_SCLK", 0, 1) - - # Check that the last loaded kernel matches it input kernel name. This ensures - # that this CK take priority when computing attitude for it's time coverage. - count = spiceypy.ktotal("ck") - loaded_ck_kernel, _, _, _ = spiceypy.kdata(count - 1, "ck") - if str(ck_path) != loaded_ck_kernel: - raise ValueError(f"Error: Expected CK kernel {ck_path}") - - id_imap_spacecraft = spiceypy.gipool("FRAME_IMAP_SPACECRAFT", 0, 1) - - # Select only the pointings within the attitude coverage. - ck_cover = spiceypy.ckcov( - str(ck_path), int(id_imap_spacecraft), True, "INTERVAL", 0, "TDB" + logger.info( + f"Extracting mean spin axes for all Pointings that are" + f" fully covered by the CK files: {[p.name for p in ck_paths]}" ) - num_intervals = spiceypy.wncard(ck_cover) - et_start, _ = spiceypy.wnfetd(ck_cover, 0) - _, et_end = spiceypy.wnfetd(ck_cover, num_intervals - 1) + + # This job relies on the batch starter to provide all the correct CK kernels + # to cover the time range of the new repoint table. + # Get the coverage of the CK files storing the earliest start time and + # latest end time. + et_start = np.inf + et_end = -np.inf + for ck_path in ck_paths: + ck_cover = spiceypy.ckcov( + str(ck_path), SpiceBody.IMAP_SPACECRAFT.value, True, "INTERVAL", 0, "TDB" + ) + num_intervals = spiceypy.wncard(ck_cover) + individual_ck_start, _ = spiceypy.wnfetd(ck_cover, 0) + _, individual_ck_end = spiceypy.wnfetd(ck_cover, num_intervals - 1) + logger.debug( + f"{ck_path.name} covers time range: ({et_to_utc(individual_ck_start)}, " + f"{et_to_utc(individual_ck_end)}) in {num_intervals} intervals." + ) + et_start = min(et_start, individual_ck_start) + et_end = max(et_end, individual_ck_end) + logger.info( - f"{ck_path.name} contains {num_intervals} intervals with " - f"start time: {et_to_utc(et_start)}, and end time: {et_to_utc(et_end)}" + f"CK kernels combined coverage range: " + f"{(et_to_utc(et_start), et_to_utc(et_end))}, " ) - # Get data from the repoint table and filter to only the pointings fully - # covered by this attitude kernel + # Get data from the repoint table and convert to Pointings repoint_df = get_repoint_data() repoint_df["repoint_start_et"] = sct_to_et( met_to_sclkticks(repoint_df["repoint_start_met"].values) @@ -235,28 +250,37 @@ def calculate_pointing_attitude_segments( repoint_df["repoint_end_et"] = sct_to_et( met_to_sclkticks(repoint_df["repoint_end_met"].values) ) - repoint_df = repoint_df[ - (repoint_df["repoint_end_et"] >= et_start) - & (repoint_df["repoint_start_et"] <= et_end) - ] - n_pointings = len(repoint_df) - 1 + pointing_ids = repoint_df["repoint_id"].values[:-1] + pointing_start_ets = repoint_df["repoint_end_et"].values[:-1] + pointing_end_ets = repoint_df["repoint_start_et"].values[1:] + + # Keep only the pointings that are fully covered by the attitude kernels. + keep_mask = (pointing_start_ets >= et_start) & (pointing_end_ets <= et_end) + # Filter the pointing data. + pointing_ids = pointing_ids[keep_mask] + pointing_start_ets = pointing_start_ets[keep_mask] + pointing_end_ets = pointing_end_ets[keep_mask] + + n_pointings = len(pointing_ids) + if n_pointings == 0: + logger.warning( + "No Pointings identified based on coverage of CK files. Skipping." + ) pointing_segments = np.zeros(n_pointings, dtype=POINTING_SEGMENT_DTYPE) for i_pointing in range(n_pointings): - pointing_segments[i_pointing]["pointing_id"] = repoint_df.iloc[i_pointing][ - "repoint_id" - ] - pointing_start_et = repoint_df.iloc[i_pointing]["repoint_end_et"] - pointing_end_et = repoint_df.iloc[i_pointing + 1]["repoint_start_et"] + pointing_segments[i_pointing]["pointing_id"] = pointing_ids[i_pointing] + pointing_start_et = pointing_start_ets[i_pointing] + pointing_end_et = pointing_end_ets[i_pointing] logger.debug( f"Calculating pointing attitude for pointing " f"{pointing_segments[i_pointing]['pointing_id']} with time " f"range: ({et_to_utc(pointing_start_et)}, {et_to_utc(pointing_end_et)})" ) - # 1 spin/15 seconds; 10 quaternions / spin. - num_samples = (pointing_end_et - pointing_start_et) / 15 * 10 + # Sample at 1Hz + num_samples = pointing_end_et - pointing_start_et # There were rounding errors when using spiceypy.pxform # so np.ceil and np.floor were used to ensure the start # and end times were within the ck range. @@ -266,11 +290,11 @@ def calculate_pointing_attitude_segments( int(num_samples), ) - # Get the average quaternions for the pointing - q_avg = _average_quaternions(et_times) + # Get the average spin-axis in HAE coordinates + z_avg = _mean_spin_axis(et_times) # Create a rotation matrix - rotation_matrix = _create_rotation_matrix(q_avg) + rotation_matrix = _create_rotation_matrix(z_avg) # Convert the rotation matrix to a quaternion. # https://spiceypy.readthedocs.io/en/main/documentation.html#spiceypy.spiceypy.m2q @@ -279,18 +303,23 @@ def calculate_pointing_attitude_segments( # https://spiceypy.readthedocs.io/en/main/documentation.html#spiceypy.spiceypy.sce2c # Convert start and end times to SCLK ticks. pointing_segments[i_pointing]["start_sclk_ticks"] = spiceypy.sce2c( - int(id_imap_sclk), pointing_start_et + IMAP_SC_ID, pointing_start_et ) pointing_segments[i_pointing]["end_sclk_ticks"] = spiceypy.sce2c( - int(id_imap_sclk), pointing_end_et + IMAP_SC_ID, pointing_end_et ) return pointing_segments -def _average_quaternions(et_times: np.ndarray) -> NDArray: +def _mean_spin_axis(et_times: np.ndarray) -> NDArray: """ - Average the quaternions. + Compute the mean spin axis for a given time range. + + The mean spin-axis is computed by taking the mean of the spacecraft z-axis + expressed in HAE Cartesian coordinates at each of the input et_times. The + mean is computed by finding the mean of each component of the vector across + time. Parameters ---------- @@ -299,72 +328,52 @@ def _average_quaternions(et_times: np.ndarray) -> NDArray: Returns ------- - q_avg : np.ndarray - Average quaternion. + z_avg : np.ndarray + Mean spin-axis. Shape is (3,), a single 3D vector (x, y, z). """ - aggregate = np.zeros((4, 4)) - for tdb in et_times: - # we use a quick and dirty method here for grabbing the quaternions - # from the attitude kernel. Depending on how well the kernel input - # data is built and sampled, there may or may not be aliasing with this - # approach. If it turns out that we need to pull the quaternions - # directly from the CK there are several routines that exist to do this - # but it's not straight forward. We'll revisit this if needed. - - # Rotation matrix from IMAP spacecraft frame to ECLIPJ2000. - # https://spiceypy.readthedocs.io/en/main/documentation.html#spiceypy.spiceypy.pxform - body_rots = spiceypy.pxform("IMAP_SPACECRAFT", "ECLIPJ2000", tdb) - # Convert rotation matrix to quaternion. - # https://spiceypy.readthedocs.io/en/main/documentation.html#spiceypy.spiceypy.m2q - body_quat = spiceypy.m2q(body_rots) - - # Standardize the quaternion so that they may be compared. - body_quat = body_quat * np.sign(body_quat[0]) - # Aggregate quaternions into a single matrix. - aggregate += np.outer(body_quat, body_quat) - - # Reference: "On Averaging Rotations". - # Link: https://link.springer.com/content/pdf/10.1023/A:1011129215388.pdf - aggregate /= len(et_times) - - # Compute eigen values and vectors of the matrix A - # Eigenvalues tell you how much "influence" each - # direction (eigenvector) has. - # The largest eigenvalue corresponds to the direction - # that has the most influence. - # The eigenvector corresponding to the largest - # eigenvalue points in the direction that has the most - # combined rotation influence. - eigvals, eigvecs = np.linalg.eig(aggregate) - # q0: The scalar part of the quaternion. - # q1, q2, q3: The vector part of the quaternion. - q_avg = eigvecs[:, np.argmax(eigvals)] - - return q_avg - - -def _create_rotation_matrix(q_avg: np.ndarray) -> NDArray: + # we use a quick and dirty method here for sampling the instantaneous + # spin-axis. Depending on how well the kernel input + # data is built and sampled, there may or may not be aliasing with this + # approach. If it turns out that we need to pull the quaternions + # directly from the CK there are several routines that exist to do this + # but it's not straight forward. We'll revisit this if needed. + z_inertial_hae = frame_transform( + et_times, np.array([0, 0, 1]), SpiceFrame.IMAP_SPACECRAFT, SpiceFrame.ECLIPJ2000 + ) + + # Compute the average spin axis by averaging each component across time + z_avg = np.mean(z_inertial_hae, axis=0) + # We don't need to worry about the magnitude being close to zero when + # normalizing because the instantaneous spin-axes will always be close + # to the same direction. + z_avg /= np.linalg.norm(z_avg) + + return z_avg + + +def _create_rotation_matrix(z_avg: np.ndarray) -> NDArray: """ - Create a rotation matrix. + Create a rotation matrix from the average spin axis. Parameters ---------- - q_avg : numpy.ndarray - Averaged quaternions for the pointing. + z_avg : numpy.ndarray + Average spin-axis that has been normalized to have unit length expressed + in HAE coordinates. Returns ------- rotation_matrix : np.ndarray Rotation matrix. """ - # Converts the averaged quaternion (q_avg) into a rotation matrix - # and get inertial z axis. - # https://spiceypy.readthedocs.io/en/main/documentation.html#spiceypy.spiceypy.q2m - z_avg = spiceypy.q2m(list(q_avg))[:, 2] - # y_avg is perpendicular to both z_avg and the standard Z-axis. + # y_avg is perpendicular to both z_avg and the HAE Z-axis. + # Since z_avg will never point anywhere near the HAE Z-axis, this + # cross-product will always work to define the Pointing Y-axis y_avg = np.cross(z_avg, [0, 0, 1]) + y_avg /= np.linalg.norm(y_avg) # x_avg is perpendicular to y_avg and z_avg. x_avg = np.cross(y_avg, z_avg) + x_avg /= np.linalg.norm(x_avg) # Construct the rotation matrix from x_avg, y_avg, z_avg rotation_matrix = np.asarray([x_avg, y_avg, z_avg]) diff --git a/imap_processing/spice/repoint.py b/imap_processing/spice/repoint.py index 97d91a9035..c20d285620 100644 --- a/imap_processing/spice/repoint.py +++ b/imap_processing/spice/repoint.py @@ -2,6 +2,7 @@ import functools import logging +import re from pathlib import Path import numpy as np @@ -9,6 +10,8 @@ from numpy import typing as npt from imap_processing.spice import config +from imap_processing.spice.geometry import imap_state +from imap_processing.spice.time import met_to_sclkticks, sct_to_et logger = logging.getLogger(__name__) @@ -221,3 +224,93 @@ def get_pointing_times(met_time: float) -> tuple[float, float]: ][0] pointing_end_met = repoint_df["repoint_start_met"].iloc[pointing_idx + 1].item() return pointing_start_met, pointing_end_met + + +def get_pointing_times_from_id(repoint_id: int | str) -> tuple[float, float]: + """ + Get the start and end MET times for the pointing given a repoint ID. + + Parameters + ---------- + repoint_id : int + The repoint ID corresponding to the pointing. + + Returns + ------- + pointing_start_time : float + The MET time of the repoint maneuver that ends before the query MET time. + pointing_end_time : float + The MET time of the repoint maneuver that starts after the query MET time. + """ + if isinstance(repoint_id, str): + if not bool(re.fullmatch(r"repoint\d{5}", str(repoint_id))): + raise ValueError( + f"Invalid repoint ID string format: {repoint_id}. " + f"Expected format is 'repointXXXXX'" + ) + + repoint_id = int(repoint_id.replace("repoint", "")) + + repoint_df = get_repoint_data() + # To find the pointing start and stop, get the end of the current repointing + # and the start of the next repointing + repoint_row = repoint_df[repoint_df["repoint_id"] == repoint_id] + if repoint_row.empty: + raise ValueError(f"Repoint ID {repoint_id} not found in repoint table.") + next_repoint_row = repoint_df[repoint_df["repoint_id"] == repoint_id + 1] + if next_repoint_row.empty: + raise ValueError( + f"Pointing end time not found for repoint ID {repoint_id}. Either current " + "pointing is ongoing or the repoint table is outdated." + ) + + pointing_start_met = repoint_row["repoint_end_met"].values[0] + pointing_end_met = next_repoint_row["repoint_start_met"].values[0] + return pointing_start_met, pointing_end_met + + +def get_pointing_mid_time(met_time: float) -> float: + """ + Get mid-point of the pointing for the given MET time. + + Get the mid-point time between the end of one repoint and + start of the next. Input could be a MET time. + + Parameters + ---------- + met_time : float + The MET time in a repoint. + + Returns + ------- + repoint_mid_time : float + The mid MET time of the repoint maneuver. + """ + pointing_start_met, pointing_end_met = get_pointing_times(met_time) + return (pointing_start_met + pointing_end_met) / 2 + + +def get_mid_point_state(met_time: float) -> npt.NDArray: + """ + Get IMAP state for the mid-point. + + Get IMAP state for the mid-point of the pointing in + reference frame, ECLIPJ2000 and observer, SUN. + + Parameters + ---------- + met_time : float + The MET time in a pointing. + + Returns + ------- + mid_point_state : numpy.ndarray + The mid state of the pointing maneuver. + """ + # Get mid point time in ET + mid_point_time = get_pointing_mid_time(met_time) + mid_point_time_et = sct_to_et(met_to_sclkticks(mid_point_time)) + + # Convert mid point time to state + pointing_state = imap_state(mid_point_time_et) + return pointing_state diff --git a/imap_processing/spice/spin.py b/imap_processing/spice/spin.py index fab4152d09..20264e4739 100644 --- a/imap_processing/spice/spin.py +++ b/imap_processing/spice/spin.py @@ -54,7 +54,9 @@ def get_spin_data() -> pd.DataFrame: * `spin_start_subsec_sclk`: MET microseconds of spin start time. * `spin_start_met`: Floating point MET seconds of spin start. * `spin_start_utc`: UTC string of spin start time. - * `spin_period_sec`: Floating point spin period in seconds. + * `spin_period_sec`: Floating point spin period in seconds (estimated). + * `actual_spin_period`: Floating point actual spin period computed from + consecutive spin start times. More accurate than spin_period_sec. * `spin_period_valid`: Boolean indicating whether spin period is valid. * `spin_phase_valid`: Boolean indicating whether spin phase is valid. * `spin_period_source`: Source used for determining spin period. @@ -106,6 +108,7 @@ def _load_spin_data_with_cache(csv_paths: tuple[Path]) -> pd.DataFrame: "spin_start_utc": str, "spin_period_sec": float, "spin_period_valid": bool, + "spin_phase_valid": bool, "spin_period_source": int, "thruster_firing": bool, }, @@ -125,6 +128,22 @@ def _load_spin_data_with_cache(csv_paths: tuple[Path]) -> pd.DataFrame: combined_df["spin_start_met"] = ( combined_df["spin_start_sec_sclk"] + combined_df["spin_start_subsec_sclk"] / 1e6 ) + # Precompute actual spin periods from consecutive spin start times + # Only use actual periods when spin numbers increment by exactly 1 + # This prevents invalid times from appearing valid when spins are missing + spin_numbers = combined_df["spin_number"].values + spin_number_diffs = np.diff(spin_numbers) + time_diffs = np.diff(combined_df["spin_start_met"].values) + + # Use actual time diff only where spin numbers increment by 1 + # Otherwise use the estimated spin_period_sec + actual_spin_periods = np.where( + spin_number_diffs == 1, time_diffs, combined_df["spin_period_sec"].values[:-1] + ) + # For the last spin, use the provided spin_period_sec since there's no next spin + combined_df["actual_spin_period"] = np.append( + actual_spin_periods, combined_df["spin_period_sec"].values[-1] + ) return combined_df @@ -159,11 +178,13 @@ def interpolate_spin_data(query_met_times: float | npt.NDArray) -> pd.DataFrame: # convert scalar to array query_met_times = np.atleast_1d(query_met_times) + # Cache frequently accessed arrays to avoid repeated .values calls + spin_start_met = spin_df["spin_start_met"].values + actual_spin_periods = spin_df["actual_spin_period"].values + # Make sure input times are within the bounds of spin data - spin_df_start_time = spin_df["spin_start_met"].values[0] - spin_df_end_time = ( - spin_df["spin_start_met"].values[-1] + spin_df["spin_period_sec"].values[-1] - ) + spin_df_start_time = spin_start_met[0] + spin_df_end_time = spin_start_met[-1] + actual_spin_periods[-1] input_start_time = query_met_times.min() input_end_time = query_met_times.max() if input_start_time < spin_df_start_time or input_end_time >= spin_df_end_time: @@ -180,15 +201,19 @@ def interpolate_spin_data(query_met_times: float | npt.NDArray) -> pd.DataFrame: # >>> np.searchsorted(df['a'], [0, 13, 15, 32, 70], side='right') # array([1, 1, 2, 3, 5]) last_spin_indices = ( - np.searchsorted(spin_df["spin_start_met"], query_met_times, side="right") - 1 + np.searchsorted(spin_start_met, query_met_times, side="right") - 1 ) + # Generate a dataframe with one row per query time - out_df = spin_df.iloc[last_spin_indices] + out_df = spin_df.iloc[last_spin_indices].copy() + + # Get the precomputed actual spin period for each query time + spin_periods_for_query = actual_spin_periods[last_spin_indices] - # Calculate spin phase - spin_phases = (query_met_times - out_df["spin_start_met"].values) / out_df[ - "spin_period_sec" - ].values + # Calculate spin phase using actual computed periods + spin_phases = ( + query_met_times - out_df["spin_start_met"].values + ) / spin_periods_for_query # Check for invalid spin phase using below checks: # 1. Check that the spin phase is in valid range, [0, 1). @@ -212,7 +237,7 @@ def interpolate_spin_data(query_met_times: float | npt.NDArray) -> pd.DataFrame: return out_df -def get_spin_number(met_time: float) -> int: +def get_spin_number(met_time: float | npt.NDArray) -> int | npt.NDArray: """ Get the spin number for the input query time. @@ -221,16 +246,18 @@ def get_spin_number(met_time: float) -> int: Parameters ---------- - met_time : float + met_time : float or np.ndarray Query time in Mission Elapsed Time (MET). Returns ------- - spin_number : int + spin_number : int or np.ndarray Spin number for the input query time. """ spin_df = interpolate_spin_data(met_time) - return spin_df["spin_number"].item() + spin_numbers = spin_df["spin_number"].values + + return spin_numbers.item() if np.asarray(met_time).ndim == 0 else spin_numbers def get_spin_angle( diff --git a/imap_processing/spice/time.py b/imap_processing/spice/time.py index 8129cb2fe9..e4baebf625 100644 --- a/imap_processing/spice/time.py +++ b/imap_processing/spice/time.py @@ -407,3 +407,63 @@ def epoch_to_doy(epoch: np.ndarray) -> npt.NDArray: return np.array( [datetime.fromisoformat(date).timetuple().tm_yday for date in time_strings] ) + + +def epoch_to_fractional_doy(epoch: int | Iterable[int]) -> float | np.ndarray: + """ + Convert epoch in TTJ2000ns to floating point day-of-year. + + Uses SPICE's timout function to directly extract day of year and # codespell:ignore + time components, avoiding intermediate datetime parsing. + + Parameters + ---------- + epoch : int or Iterable[int] + Epoch in TTJ2000ns format (nanoseconds since J2000). Can be a single + integer or an iterable of integers. + + Returns + ------- + doy : float or numpy.ndarray + Floating point day of year (1.0 = Jan 1 00:00:00). Returns a scalar + when `epoch` is a single integer, or a NumPy array when `epoch` is an + iterable. + + References + ---------- + https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/timout_c.html + """ + # Convert to ephemeris time (ET/TDB) + et = ttj2000ns_to_et(epoch) + + def single_et_to_fractional_doy(et: float) -> float: # numpydoc ignore=GL08 + # Use SPICE timout to extract DOY and time components # codespell:ignore + # Format: "DOY.####" with ::UTC modifier for UTC-based output + # The ::UTC modifier converts ET to UTC but doesn't appear in output + return float(spiceypy.timout(et, "DOY.#### ::UTC", 30)) # codespell:ignore + + vectorized_et_to_frac_doy = _vectorize(single_et_to_fractional_doy, otypes=[float]) + + return vectorized_et_to_frac_doy(et) + + +def str_yyyymmdd_to_ttj2000ns(date_str: str) -> np.int64: + """ + Convert a YYYYMMDD date string to TTJ2000 nanoseconds. + + Parameters + ---------- + date_str : str + The date string in YYYYMMDD format. + + Returns + ------- + int + The corresponding time in TTJ2000 nanoseconds. + """ + if len(date_str) != 8: + raise ValueError( + f"Date {date_str} must be 8 characters long in yyyymmdd format." + ) + date_string = datetime.strptime(date_str, "%Y%m%d").strftime("%Y-%m-%dT00:00:00") + return np.int64(et_to_ttj2000ns(str_to_et(date_string))) diff --git a/imap_processing/swapi/constants.py b/imap_processing/swapi/constants.py new file mode 100644 index 0000000000..5b00c72d42 --- /dev/null +++ b/imap_processing/swapi/constants.py @@ -0,0 +1,4 @@ +"""Constants for SWAPI processing.""" + +NUM_PACKETS_PER_SWEEP = 12 +NUM_ENERGY_STEPS = 72 diff --git a/imap_processing/swapi/l1/swapi_l1.py b/imap_processing/swapi/l1/swapi_l1.py index 639df00510..b552caa27f 100644 --- a/imap_processing/swapi/l1/swapi_l1.py +++ b/imap_processing/swapi/l1/swapi_l1.py @@ -12,6 +12,8 @@ from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes from imap_processing.cdf.utils import load_cdf from imap_processing.quality_flags import SWAPIFlags +from imap_processing.spice.time import met_to_utc, ttj2000ns_to_met +from imap_processing.swapi.constants import NUM_ENERGY_STEPS, NUM_PACKETS_PER_SWEEP from imap_processing.swapi.swapi_utils import SWAPIAPID, SWAPIMODE from imap_processing.utils import packet_file_to_datasets @@ -41,10 +43,10 @@ def filter_good_data(full_sweep_sci: xr.Dataset) -> npt.NDArray: """ # PLAN_ID for current sweep should all be one value and # SWEEP_TABLE should all be one value. - plan_id = full_sweep_sci["plan_id"].data.reshape(-1, 12) - sweep_table = full_sweep_sci["sweep_table"].data.reshape(-1, 12) + plan_id = full_sweep_sci["plan_id"].data.reshape(-1, NUM_PACKETS_PER_SWEEP) + sweep_table = full_sweep_sci["sweep_table"].data.reshape(-1, NUM_PACKETS_PER_SWEEP) - mode = full_sweep_sci["mode"].data.reshape(-1, 12) + mode = full_sweep_sci["mode"].data.reshape(-1, NUM_PACKETS_PER_SWEEP) sweep_indices = (sweep_table == sweep_table[:, 0, None]).all(axis=1) plan_id_indices = (plan_id == plan_id[:, 0, None]).all(axis=1) @@ -62,10 +64,10 @@ def filter_good_data(full_sweep_sci: xr.Dataset) -> npt.NDArray: # From this: [0 24] # To this: [[ 0 1 2 3 4 5 6 7 8 9 10 11] # [24 25 26 27 28 29 30 31 32 33 34 35]] - cycle_start_indices = np.where(bad_data_indices == 0)[0] * 12 - bad_cycle_indices = cycle_start_indices[..., None] + np.arange(12)[ - None, ... - ].reshape(-1) + cycle_start_indices = np.where(bad_data_indices == 0)[0] * NUM_PACKETS_PER_SWEEP + bad_cycle_indices = cycle_start_indices[..., None] + np.arange( + NUM_PACKETS_PER_SWEEP + )[None, ...].reshape(-1) logger.debug("Cycle data was bad due to one of below reasons:") logger.debug( @@ -124,7 +126,7 @@ def decompress_count( # Decompress counts based on compression indicators # If 0, value is already decompressed. If 1, value is compressed. # If 1 and count is 0xFFFF, value is overflow. - new_count = copy.deepcopy(count_data).astype(np.int32) + new_count: np.ndarray = copy.deepcopy(count_data).astype(np.int32) # If data is compressed, decompress it compressed_indices = compression_flag == 1 @@ -162,7 +164,7 @@ def find_sweep_starts(packets: xr.Dataset) -> npt.NDArray: indices_start : numpy.ndarray Array of indices of start cycle. """ - if packets["shcoarse"].size < 12: + if packets["shcoarse"].size < NUM_PACKETS_PER_SWEEP: return np.array([], np.int64) # calculate time difference between consecutive sweep @@ -387,7 +389,7 @@ def process_sweep_data(full_sweep_sci: xr.Dataset, cem_prefix: str) -> xr.Datase # [ 2 3 4 5 6 7 8 9 10 11 12 13]]] # In other word, we grouped each cem's # data by full sweep. - current_cem_counts = current_cem_counts.reshape(6, -1, 12) + current_cem_counts = current_cem_counts.reshape(6, -1, NUM_PACKETS_PER_SWEEP) # Then, we go from above to # to this final output: @@ -421,7 +423,7 @@ def process_sweep_data(full_sweep_sci: xr.Dataset, cem_prefix: str) -> xr.Datase all_cem_data = np.stack(current_cem_counts, axis=-1) # This line just flatten the inner most array to # (total_full_sweeps x 72) - all_cem_data = all_cem_data.reshape(-1, 72) + all_cem_data = all_cem_data.reshape(-1, NUM_ENERGY_STEPS) return all_cem_data @@ -490,7 +492,9 @@ def process_swapi_science( # =================================================================== # Quality flags # =================================================================== - quality_flags_data = np.zeros((total_full_sweeps, 72), dtype=np.uint16) + quality_flags_data: np.ndarray = np.zeros( + (total_full_sweeps, NUM_ENERGY_STEPS), dtype=np.uint16 + ) # Add science data quality flags # Have to match datatype to bitwise OR @@ -546,9 +550,9 @@ def process_swapi_science( ] for flag_name in hk_flags_name: - current_flag = np.repeat(good_sweep_hk_data[flag_name.lower()].data, 6).reshape( - -1, 72 - ) + current_flag: np.ndarray = np.repeat( + good_sweep_hk_data[flag_name.lower()].data, 6 + ).reshape(-1, NUM_ENERGY_STEPS) # Use getattr to dynamically access the flag in SWAPIFlags class flag_to_set = getattr(SWAPIFlags, flag_name) # set the quality flag for each data @@ -568,7 +572,9 @@ def process_swapi_science( # Use center time for epoch to line up with mission requests. Center time # of SWAPI is time of 7th packet(aka SEQ_NUMBER == 6) creation time at the # beginning of 7th packet. - epoch_values = good_sweep_sci["epoch"].data.reshape(total_full_sweeps, 12)[:, 6] + epoch_values = good_sweep_sci["epoch"].data.reshape( + total_full_sweeps, NUM_PACKETS_PER_SWEEP + )[:, 6] epoch_time = xr.DataArray( epoch_values, @@ -626,20 +632,33 @@ def process_swapi_science( # Add other support data dataset["sweep_table"] = xr.DataArray( - good_sweep_sci["sweep_table"].data.reshape(total_full_sweeps, 12)[:, 0], + good_sweep_sci["sweep_table"].data.reshape( + total_full_sweeps, NUM_PACKETS_PER_SWEEP + )[:, 0], name="sweep_table", dims=["epoch"], attrs=cdf_manager.get_variable_attributes("sweep_table"), ) dataset["plan_id"] = xr.DataArray( - good_sweep_sci["plan_id"].data.reshape(total_full_sweeps, 12)[:, 0], + good_sweep_sci["plan_id"].data.reshape( + total_full_sweeps, NUM_PACKETS_PER_SWEEP + )[:, 0], name="plan_id", dims=["epoch"], attrs=cdf_manager.get_variable_attributes("plan_id"), ) # Store start time for L3 purposes per SWAPI requests + # Per SWAPI request, convert start time of sweep to UTC time. + sci_start_time = met_to_utc( + ttj2000ns_to_met( + good_sweep_sci["epoch"].data.reshape( + total_full_sweeps, NUM_PACKETS_PER_SWEEP + )[:, 0] + ), + precision=3, + ) dataset["sci_start_time"] = xr.DataArray( - good_sweep_sci["epoch"].data.reshape(total_full_sweeps, 12)[:, 0], + sci_start_time, name="sci_start_time", dims=["epoch"], attrs=cdf_manager.get_variable_attributes("sci_start_time"), @@ -650,7 +669,9 @@ def process_swapi_science( # updated every 6th step. This is used in L2 to calculate last 9 fine # energy steps. dataset["esa_lvl5"] = xr.DataArray( - good_sweep_sci["esa_lvl5"].data.reshape(total_full_sweeps, 12)[:, 11], + good_sweep_sci["esa_lvl5"].data.reshape( + total_full_sweeps, NUM_PACKETS_PER_SWEEP + )[:, 11], name="esa_lvl5", dims=["epoch"], attrs=cdf_manager.get_variable_attributes("esa_lvl5"), @@ -661,19 +682,25 @@ def process_swapi_science( # SWP_HK.FPGA_TYPE - Type number of the FPGA # SWP_HK.FPGA_REV - Revision number of the FPGA dataset["lut_choice"] = xr.DataArray( - good_sweep_hk_data["lut_choice"].data.reshape(total_full_sweeps, 12)[:, 0], + good_sweep_hk_data["lut_choice"].data.reshape( + total_full_sweeps, NUM_PACKETS_PER_SWEEP + )[:, 0], name="lut_choice", dims=["epoch"], attrs=cdf_manager.get_variable_attributes("lut_choice"), ) dataset["fpga_type"] = xr.DataArray( - good_sweep_hk_data["fpga_type"].data.reshape(total_full_sweeps, 12)[:, 0], + good_sweep_hk_data["fpga_type"].data.reshape( + total_full_sweeps, NUM_PACKETS_PER_SWEEP + )[:, 0], name="fpga_type", dims=["epoch"], attrs=cdf_manager.get_variable_attributes("fpga_type"), ) dataset["fpga_rev"] = xr.DataArray( - good_sweep_hk_data["fpga_rev"].data.reshape(total_full_sweeps, 12)[:, 0], + good_sweep_hk_data["fpga_rev"].data.reshape( + total_full_sweeps, NUM_PACKETS_PER_SWEEP + )[:, 0], name="fpga_rev", dims=["epoch"], attrs=cdf_manager.get_variable_attributes("fpga_rev"), @@ -727,7 +754,7 @@ def process_swapi_science( return dataset -def swapi_l1(dependencies: ProcessingInputCollection) -> xr.Dataset: +def swapi_l1(dependencies: ProcessingInputCollection, descriptor: str) -> xr.Dataset: """ Will process SWAPI level 0 data to level 1. @@ -735,6 +762,9 @@ def swapi_l1(dependencies: ProcessingInputCollection) -> xr.Dataset: ---------- dependencies : ProcessingInputCollection Input dependencies needed for L1 processing. + descriptor : str + Descriptor for the type of data to process. + Options are 'hk' or 'sci'. Returns ------- @@ -754,9 +784,11 @@ def swapi_l1(dependencies: ProcessingInputCollection) -> xr.Dataset: l0_files[0], xtce_definition, use_derived_value=False ) - hk_files = dependencies.get_file_paths(descriptor="hk") - if hk_files and l0_unpacked_dict.get(SWAPIAPID.SWP_SCI, None) is not None: + if descriptor == "sci": logger.info(f"Processing SWAPI science data for {l0_files[0]}.") + if SWAPIAPID.SWP_SCI not in l0_unpacked_dict: + logger.warning("No SWP_SCI packets found.") + return [] # process science data. # First read HK data. hk_files = dependencies.get_file_paths(descriptor="hk") @@ -770,8 +802,11 @@ def swapi_l1(dependencies: ProcessingInputCollection) -> xr.Dataset: ) return [sci_dataset] - elif l0_unpacked_dict[SWAPIAPID.SWP_HK]: + elif descriptor == "hk": logger.info(f"Processing HK data for {l0_files[0]}.") + if SWAPIAPID.SWP_HK not in l0_unpacked_dict: + logger.warning("No SWP_HK packets found.") + return [] # Get L1A and L1B HK data. l1a_hk_data = l0_unpacked_dict[SWAPIAPID.SWP_HK] l1b_hk_data = packet_file_to_datasets( diff --git a/imap_processing/swapi/l2/swapi_l2.py b/imap_processing/swapi/l2/swapi_l2.py index 1e9efb136a..6065102af6 100644 --- a/imap_processing/swapi/l2/swapi_l2.py +++ b/imap_processing/swapi/l2/swapi_l2.py @@ -8,6 +8,7 @@ import xarray as xr from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes +from imap_processing.swapi.constants import NUM_ENERGY_STEPS logger = logging.getLogger(__name__) @@ -64,89 +65,89 @@ def solve_full_sweep_energy( dtype="datetime64[ns]" ) - first_63_energies = [] + # Initialize the output energy array + # Each sweep will have different energies for each step. + # The first 63 energies are coarse steps, then followed by 9 fine steps. + # The 9 fine steps may be defined in the main table (fixed steps), or "solve" + # which requires a separate lookup in the lut-notes table. + energy_data: np.ndarray = np.empty( + (len(sweep_table), NUM_ENERGY_STEPS), dtype=float + ) - for time, sweep_id in zip(data_time, sweep_table, strict=False): + for i_sweep, (time, sweep_id, esa_lvl5_val) in enumerate( + zip(data_time, sweep_table, esa_lvl5_data, strict=True) + ): # Find the sweep's ESA data for the given time and sweep_id subset = esa_table_df[ (esa_table_df["timestamp"] <= time) & (esa_table_df["Sweep #"] == sweep_id) ] if subset.empty: - first_63_energies.append(np.full(63, np.nan, dtype=np.float64)) + # Get the earliest timestamp available + earliest_time = esa_table_df["timestamp"].min() + + # Find the sweep's ESA data for the earliest time and sweep_id + earliest_subset = esa_table_df[ + (esa_table_df["timestamp"] == earliest_time) + & (esa_table_df["Sweep #"] == sweep_id) + ] + if earliest_subset.empty: + raise ValueError( + f"No matching ESA table entry found for sweep ID {sweep_id} " + f"at time {time}, and no entries found for earliest time " + f"{earliest_time}." + ) + subset = earliest_subset + + # Subset data can contain multiple sweeps of 72 energy values. + # We need to sort by time and ESA step to maintain correct + # order. Then take the last sweep (72 values). + subset = subset.sort_values(["timestamp", "ESA Step #"]).iloc[ + -NUM_ENERGY_STEPS: + ] + sweep_esa_energies = subset["Energy"].values + + # Solve steps are the fine sweep steps. This can be variable numbers and is + # not always the final 9 steps. They are negative values when reading in the df + solve_steps = sweep_esa_energies < 0 + energy_data[i_sweep, ~solve_steps] = sweep_esa_energies[~solve_steps] + if not np.any(solve_steps): + # No solve steps, we've already filled all energies continue to next sweep continue - # Subset data can contain multiple 72 energy values with last 9 fine energies - # with 'Solve' value. We need to sort by time and ESA step to maintain correct - # order. Then take the last group of 72 steps values and select first 63 - # values only. - subset = subset.sort_values(["timestamp", "ESA Step #"]) - grouped = subset["Energy"].values.reshape(-1, 72) - first_63 = grouped[-1, :63] - first_63_energies.append(first_63) - - # Find last 9 fine energy values of all sweeps data - # ------------------------------------------------- - # First, verify that all values in the LUT-notes table's 'ESA DAC (Hex)' column - # exactly matches a value in the esa_lvl5_data. - has_exact_match = np.isin(esa_lvl5_data, lut_notes_df["ESA DAC (Hex)"].values) - if not np.all(has_exact_match): - raise ValueError( - "These ESA_LVL5 values not found in lut-notes table: " - f"{esa_lvl5_data[np.where(~has_exact_match)[0]]} " - ) - - # Find index of 71st energy step for all sweeps data in lut-notes table. - # Tried using np.where(np.isin(...)) or df.index[np.isin(...)] to find the index - # of each value in esa_lvl5_data within the LUT table. However, these methods - # return only the unique matching indices β€” not one index per input value. - # For example, given the input: - # ['12F1', '12F1', '12F1', '12F1'] - # np.where(np.isin(...)) would return: - # [336] - # because it finds that '12F1' exists in the LUT and only returns its position once. - # What we actually need is: - # [336, 336, 336, 336] - # β€” one index for *each* occurrence in the input, preserving its shape and order. - # Therefore, instead of relying on np.isin or similar, we explicitly use - # np.where in a loop to find the index of each value in esa_lvl5_data individually, - # ensuring the output array has the same shape as the input. - - last_energy_step_indices = np.array( - [ - np.where(lut_notes_df["ESA DAC (Hex)"].values == val)[0][0] - for val in esa_lvl5_data + # Page 31 of algorithm document + # Get the last energy step index for use in looking up the fine sweep values + # Find the index of the matching ESA DAC value + matching_indices = np.nonzero( + lut_notes_df["ESA DAC (Hex)"].values == esa_lvl5_val + )[0] + if len(matching_indices) == 0: + raise ValueError( + f"ESA DAC value '{esa_lvl5_val}' not found in LUT notes table " + f"for sweep {i_sweep} at time {time}" + ) + last_energy_step_index = matching_indices[0] + + # The ESA Index Number contains the offset indices for the fine energy values + fine_offsets = subset["ESA Index Number"].values[solve_steps] + # Since we are backtracking from the final index, we need to subtract that + # offset from all of the other indices. + fine_offsets -= fine_offsets[-1] + fine_lut_indices = last_energy_step_index + fine_offsets + + # NOTE: Per SWAPI instruction, set every index that result in negative + # indices during back tracking to zero index. SWAPI calls this + # "flooring" the index. For example, if the 71st energy step index results + # in less than 32, then it would result in some negative indices. Eg. + # 71st index = 31 + # nine fine energy indices = [31, 27, 23, 19, 15, 11, 7, 3, -1] + # flooring = [31, 27, 23, 19, 15, 11, 7, 3, 0] + fine_lut_indices[fine_lut_indices < 0] = 0 # Ensure no negative indices + + energy_data[i_sweep, solve_steps] = lut_notes_df["Energy"].values[ + fine_lut_indices ] - ) - # Use back tracking steps to find all 9 fine energy value indices - # Eg. [0, -4, -8, ..., -28, -32] - steps = np.arange(9) * -4 - - # Find indices of last 9 fine energy values of all sweeps data - fine_energy_indices = last_energy_step_indices[:, None] + steps - - # NOTE: Per SWAPI instruction, set every index that result in negative - # indices during back tracking to zero index. SWAPI calls this - # "flooring" the index. For example, if the 71st energy step index results - # in less than 32, then it would result in some negative indices. Eg. - # 71st index = 31 - # nine fine energy indices = [31, 27, 23, 19, 15, 11, 7, 3, -1] - # flooring = [31, 27, 23, 19, 15, 11, 7, 3, 0] - fine_energy_indices[fine_energy_indices < 0] = 0 - - energy_values = lut_notes_df["Energy"].values[fine_energy_indices] - # In above steps, we were calculating energy for these energy steps - # in this order: - # [72, 71, 70, 69, 68, 67, 66, 65, 64] - # Now, we need to reverse the order of these energy steps to match the - # order it should be in: - # [64, 65, 66, 67, 68, 69, 70, 71, 72] - energy_values = np.flip(energy_values, axis=1) - - # Append the first_63_values in front of energy_values - sweeps_energy_value = np.hstack([first_63_energies, energy_values]) - - return sweeps_energy_value + return energy_data def swapi_l2( @@ -206,16 +207,22 @@ def swapi_l2( # ----------------------------------- # Convert unpacked ESA_LVL5 values to hex to match the LUT table # value - esa_lvl5_hex = np.vectorize(lambda x: format(x, "X"))(l1_dataset["esa_lvl5"].values) + esa_lvl5_hex = np.vectorize(lambda x: format(x, "04X"))( + l1_dataset["esa_lvl5"].values + ) + + # Turn the string start times into numpy datetime64 + sci_start_time = l1_dataset["sci_start_time"].values.astype("datetime64[ns]") + esa_energy = solve_full_sweep_energy( esa_lvl5_hex, l1_dataset["sweep_table"].data, esa_table_df=esa_table_df, lut_notes_df=lut_notes_df, - data_time=np.array(l1_dataset["epoch"].data, dtype="datetime64[ns]"), + data_time=sci_start_time, ) - l2_dataset["swp_esa_energy"] = xr.DataArray( + l2_dataset["esa_energy"] = xr.DataArray( esa_energy, name="esa_energy", dims=["epoch", "esa_step"], @@ -234,6 +241,11 @@ def swapi_l2( l2_dataset["swp_pcem_rate"] = l1_dataset["swp_pcem_counts"] / SWAPI_LIVETIME l2_dataset["swp_scem_rate"] = l1_dataset["swp_scem_counts"] / SWAPI_LIVETIME l2_dataset["swp_coin_rate"] = l1_dataset["swp_coin_counts"] / SWAPI_LIVETIME + + # NOTE: The counts can be negative from FILLVAL in l1a data. We want to ignore those + # and propagate nans + for var in ["swp_pcem_rate", "swp_scem_rate", "swp_coin_rate"]: + l2_dataset[var] = l2_dataset[var].where(l2_dataset[var] >= 0, np.nan) # update attrs l2_dataset["swp_pcem_rate"].attrs = cdf_manager.get_variable_attributes("pcem_rate") l2_dataset["swp_scem_rate"].attrs = cdf_manager.get_variable_attributes("scem_rate") diff --git a/imap_processing/swe/l1b/swe_l1b.py b/imap_processing/swe/l1b/swe_l1b.py index 83d39b80ea..add5051b2b 100644 --- a/imap_processing/swe/l1b/swe_l1b.py +++ b/imap_processing/swe/l1b/swe_l1b.py @@ -12,6 +12,7 @@ from imap_processing import imap_module_directory from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes from imap_processing.cdf.utils import load_cdf +from imap_processing.quality_flags import SweL1bFlags from imap_processing.spice.time import met_to_ttj2000ns from imap_processing.swe.utils import swe_constants from imap_processing.swe.utils.swe_utils import ( @@ -166,18 +167,23 @@ def read_in_flight_cal_data(in_flight_cal_files: list) -> pd.DataFrame: "cem6", "cem7", ] - in_flight_cal_df = pd.concat( - [ - pd.read_csv(file_path, header=0, names=column_names) - for file_path in in_flight_cal_files - ] - ) - # Drop duplicates and keep only last occurrence - in_flight_cal_df = in_flight_cal_df.drop_duplicates( - subset=["met_time"], keep="last" + in_flight_cal_df = ( + pd.concat( + [ + pd.read_csv(file_path, header=0, names=column_names) + for file_path in in_flight_cal_files + ], + ignore_index=True, + ) + # Remove rows without MET + .dropna(subset=["met_time"]) + # Sort once so "keep=last" is meaningful + .sort_values("met_time") + # Drop duplicate METs, keeping most recent entry + .drop_duplicates(subset=["met_time"], keep="last") + # Clean index + .reset_index(drop=True) ) - # Sort by 'met_time' column - in_flight_cal_df = in_flight_cal_df.sort_values(by="met_time") return in_flight_cal_df @@ -251,7 +257,7 @@ def apply_in_flight_calibration( corrected_counts: np.ndarray, acquisition_time: np.ndarray, in_flight_cal_files: list, -) -> npt.NDArray: +) -> tuple[npt.NDArray, npt.NDArray]: """ Apply in flight calibration to full cycle data. @@ -263,10 +269,10 @@ def apply_in_flight_calibration( ---------- corrected_counts : numpy.ndarray Corrected count of full cycle data. Data shape is - (N_ESA_STEPS, N_ANGLE_SECTORS, N_CEMS). + (n_epochs, N_ESA_STEPS, N_ANGLE_SECTORS, N_CEMS). acquisition_time : numpy.ndarray Acquisition time of full cycle data. Data shape is - (N_ESA_STEPS, N_ANGLE_SECTORS). + (n_epochs, N_ESA_STEPS, N_ANGLE_SECTORS). in_flight_cal_files : list List of in-flight calibration files. @@ -274,21 +280,39 @@ def apply_in_flight_calibration( ------- corrected_counts : numpy.ndarray Corrected count of full cycle data after applying in-flight calibration. - Array shape is (N_ESA_STEPS, N_ANGLE_SECTORS, N_CEMS). + Array shape is (n_epochs, N_ESA_STEPS, N_ANGLE_SECTORS, N_CEMS). + flags : numpy.ndarray + Per-epoch quality flags of shape (n_epochs,). The LAST_CAL_INTERVAL bit + is set for any epoch where at least one acquisition time falls in the + interval between the second-to-last and last calibration entries. """ # Read in in-flight calibration data in_flight_cal_df = read_in_flight_cal_data(in_flight_cal_files) + cal_times = in_flight_cal_df["met_time"].values # calculate calibration factor. # return shape of calculate_calibration_factor is # (N_ESA_STEPS, N_ANGLE_SECTORS, N_CEMS) where # last 7 dimension contains calibration factor for each CEM detector. cal_factor = calculate_calibration_factor( acquisition_time, - in_flight_cal_df["met_time"].values, + cal_times, in_flight_cal_df.iloc[:, 1:].values, ) - # Apply to full cycle data - return corrected_counts.astype(np.float64) * cal_factor + + # Flag epochs where any acquisition time is extrapolated using the last + # two calibration entries, i.e. falls in (cal_times[-2], cal_times[-1]]. + in_last_interval = acquisition_time > cal_times[-2] + # Reduce over all axes except the epoch axis (first axis) + epoch_in_last_interval = in_last_interval.any( + axis=tuple(range(1, in_last_interval.ndim)) + ) + flags = np.where( + epoch_in_last_interval, + SweL1bFlags.LAST_CAL_INTERVAL.value, + SweL1bFlags.NONE.value, + ).astype(np.uint8) + + return corrected_counts.astype(np.float64) * cal_factor, flags def find_cycle_starts(cycles: np.ndarray) -> npt.NDArray: @@ -380,7 +404,9 @@ def get_esa_energy_pattern(esa_lut_file: Path, esa_table_num: int = 0) -> npt.ND # Now define variable to store pattern for the first two columns # because that pattern is repeated in the rest of the columns. - first_two_columns = np.zeros((swe_constants.N_ESA_STEPS, 2), dtype=np.float64) + first_two_columns: np.ndarray = np.zeros( + (swe_constants.N_ESA_STEPS, 2), dtype=np.float64 + ) # Get row indices of all four quarter cycles. Then minus 1 to get # the row indices in 0-23 instead of 1-24. cycle_row_indices = esa_table_df["v_index"].values - 1 @@ -438,7 +464,7 @@ def get_checker_board_pattern( # Now define variable to store pattern for the first two columns # because that pattern is repeated in the rest of the columns. - first_two_columns = np.zeros((24, 2), dtype=np.int64) + first_two_columns: np.ndarray = np.zeros((24, 2), dtype=np.int64) # Get row indices of all four quarter cycles. Then minus 1 to get # the row indices in 0-23 instead of 1-24. cycle_row_indices = esa_table_df["v_index"].values - 1 @@ -470,7 +496,7 @@ def get_checker_board_pattern( # Generate increment offsets: [0, 0, 12, 12, ..., 168, 168] - # shape: (30,) - column_offsets = np.repeat(np.arange(15) * 12, 2) + column_offsets: np.ndarray = np.repeat(np.arange(15) * 12, 2) increment_by = np.tile(column_offsets, (24, 1)) # Final checkerboard pattern with index offsets applied @@ -647,8 +673,6 @@ def swe_l1b_science(dependencies: ProcessingInputCollection) -> xr.Dataset: science_files = dependencies.get_file_paths(descriptor="sci") l1a_data = load_cdf(science_files[0]) - total_packets = len(l1a_data["science_data"].data) - l1a_data_copy = l1a_data.copy(deep=True) # First convert some science data to engineering units @@ -695,25 +719,18 @@ def swe_l1b_science(dependencies: ProcessingInputCollection) -> xr.Dataset: logger.info("No full cycle data found. Skipping.") return None - # In this case, we found incomplete cycle data. We need to filter + # We may have potentially found incomplete cycle data. We need to filter # out all the data that does not make a full cycle. - if len(full_cycle_data_indices) != total_packets: - # Filter metadata and science data of packets that makes full cycles - full_cycle_l1a_data = l1a_data_copy.isel({"epoch": full_cycle_data_indices}) - - # Update total packets - total_packets = len(full_cycle_data_indices) - logger.debug( - "Quarters cycle after filtering: " - f"{full_cycle_l1a_data['quarter_cycle'].data}" - ) - if len(full_cycle_data_indices) != len( - full_cycle_l1a_data["quarter_cycle"].data - ): - raise ValueError( - "Error: full cycle data indices and filtered quarter cycle data size " - "mismatch" - ) + n_cycles = len(full_cycle_data_indices) + logger.info( + f"Length of data [{len(l1a_data['science_data'])}]; " + f"Number of full cycles found [{n_cycles}]" + ) + full_cycle_l1a_data = l1a_data_copy.isel({"epoch": full_cycle_data_indices}) + + logger.debug( + f"Quarters cycle after filtering: {full_cycle_l1a_data['quarter_cycle'].data}" + ) # Main science processing steps # --------------------------------------------------------------- @@ -754,7 +771,7 @@ def swe_l1b_science(dependencies: ProcessingInputCollection) -> xr.Dataset: # Read in-flight calibration data in_flight_cal_files = dependencies.get_file_paths(descriptor="l1b-in-flight-cal") - inflight_applied_count = apply_in_flight_calibration( + inflight_applied_count, data_quality = apply_in_flight_calibration( corrected_count, acq_time, in_flight_cal_files ) @@ -767,7 +784,7 @@ def swe_l1b_science(dependencies: ProcessingInputCollection) -> xr.Dataset: # Store ESA energies of full cycle for L2 purposes. esa_energies = get_esa_energy_pattern(esa_lut_files[0]) # Repeat the (24, 30) energy pattern n_cycles times along a new first axis - esa_energies = np.repeat(esa_energies[np.newaxis, :, :], total_packets // 4, axis=0) + esa_energies = np.repeat(esa_energies[np.newaxis, :, :], n_cycles // 4, axis=0) # Convert voltage to electron energy in eV by apply conversion factor esa_energies = esa_energies * swe_constants.ENERGY_CONVERSION_FACTOR # ------------------------------------------------------------------ @@ -785,7 +802,7 @@ def swe_l1b_science(dependencies: ProcessingInputCollection) -> xr.Dataset: # get indices of 3rd quarter cycle data packet in each full cycle # and use that to calculate center time of data acquisition time. # Quarter cycle indices: 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, ... - indices_of_center_time = np.arange(2, total_packets, swe_constants.N_QUARTER_CYCLES) + indices_of_center_time = np.arange(2, n_cycles, swe_constants.N_QUARTER_CYCLES) center_time = combine_acquisition_time( full_cycle_l1a_data["acq_start_coarse"].data[indices_of_center_time], @@ -917,6 +934,12 @@ def swe_l1b_science(dependencies: ProcessingInputCollection) -> xr.Dataset: attrs=cdf_attrs.get_variable_attributes("esa_energy"), ) + science_dataset["data_quality"] = xr.DataArray( + data_quality, + dims=["epoch"], + attrs=cdf_attrs.get_variable_attributes("data_quality"), + ) + # create xarray dataarray for each data field for key, value in full_cycle_l1a_data.items(): if key in ["science_data", "acq_duration"]: diff --git a/imap_processing/swe/l2/swe_l2.py b/imap_processing/swe/l2/swe_l2.py index c282fbec21..e5d9cfd755 100644 --- a/imap_processing/swe/l2/swe_l2.py +++ b/imap_processing/swe/l2/swe_l2.py @@ -436,6 +436,11 @@ def swe_l2(l1b_dataset: xr.Dataset) -> xr.Dataset: dataset["acq_duration"].attrs = cdf_attributes.get_variable_attributes( "acq_duration" ) + # Carry over data_quality for L3 purposes. + dataset["data_quality"] = l1b_dataset["data_quality"] + dataset["data_quality"].attrs = cdf_attributes.get_variable_attributes( + "data_quality" + ) # Calculate spin phase using SWE acquisition_time from the # L1B dataset. The L1B dataset stores acquisition_time with diff --git a/imap_processing/swe/utils/swe_constants.py b/imap_processing/swe/utils/swe_constants.py index 3af863d973..8bf814892f 100644 --- a/imap_processing/swe/utils/swe_constants.py +++ b/imap_processing/swe/utils/swe_constants.py @@ -16,13 +16,13 @@ # 7 CEMs geometric factors in cm^2 sr eV/eV units. GEOMETRIC_FACTORS = np.array( [ - 435e-6, - 599e-6, - 808e-6, - 781e-6, - 876e-6, - 548e-6, - 432e-6, + 424.4e-6, + 564.5e-6, + 763.8e-6, + 916.9e-6, + 792.0e-6, + 667.7e-6, + 425.2e-6, ] ) diff --git a/imap_processing/tests/ancillary/test_ancillary_dataset_combiner.py b/imap_processing/tests/ancillary/test_ancillary_dataset_combiner.py index fb45059fab..36b9b13434 100644 --- a/imap_processing/tests/ancillary/test_ancillary_dataset_combiner.py +++ b/imap_processing/tests/ancillary/test_ancillary_dataset_combiner.py @@ -236,6 +236,19 @@ def test_glows_excluded_regions_combiner(glows_ancillary_filepath): assert dataset["ecliptic_latitude_deg"].dims == ("region",) +def test_glows_excluded_regions_combiner_empty_file(tmp_path): + file_path = tmp_path / "imap_glows_l1b-map-of-excluded-regions_20251112_v001.dat" + file_path.write_text("# header only\n") + + combiner = GlowsAncillaryCombiner([], "20251115") + dataset = combiner.convert_file_to_dataset(file_path) + + assert "ecliptic_longitude_deg" in dataset.data_vars + assert "ecliptic_latitude_deg" in dataset.data_vars + assert len(dataset["ecliptic_longitude_deg"]) == 0 + assert len(dataset["ecliptic_latitude_deg"]) == 0 + + def test_glows_uv_sources_combiner(glows_ancillary_filepath): file_path = ( glows_ancillary_filepath / "imap_glows_map-of-uv-sources_20250923_v002.dat" @@ -300,6 +313,26 @@ def test_glows_exclusions_by_instr_team_combiner(glows_ancillary_filepath): assert combiner.timestamped_data[0].version == "v002" +def test_glows_l2_calibration_combiner(tmp_path): + file_path = tmp_path / "imap_glows_l2-calibration_20251112_v001.dat" + file_path.write_text( + "# header\n2025-11-13T18:12:48 1.020\n" + "2025-11-14T09:58:04 0.849\n" + "2025-11-14T20:58:04 0.649\n" + ) + + combiner = GlowsAncillaryCombiner([], "20251115") + dataset = combiner.convert_file_to_dataset(file_path) + + assert "start_time_utc" in dataset.data_vars + assert ( + np.diff(dataset.start_time_utc.values.astype("datetime64")) >= np.timedelta64(0) + ).all() + assert "cps_per_r" in dataset.data_vars + assert len(dataset["cps_per_r"]) == 3 + assert dataset["cps_per_r"].values[0] == pytest.approx(1.020) + + def test_ancillary_combiner_empty_input(): """Test AncillaryCombiner with empty input list.""" combiner = AncillaryCombiner([], "20251031") diff --git a/imap_processing/tests/cdf/test_metadata_yaml_order.py b/imap_processing/tests/cdf/test_metadata_yaml_order.py new file mode 100644 index 0000000000..39bc326926 --- /dev/null +++ b/imap_processing/tests/cdf/test_metadata_yaml_order.py @@ -0,0 +1,26 @@ +from pathlib import Path + +import yaml +from yaml.nodes import MappingNode + +CONFIG_DIR = Path(__file__).parents[2] / "cdf" / "config" + + +def test_cdf_attribute_yaml_keys_are_sorted(): + """Verify CDF metadata attribute mappings stay alphabetized.""" + unsorted_blocks = [] + + for path in sorted(CONFIG_DIR.glob("*_attrs.yaml")): + doc = yaml.compose(path.read_text()) + for top_key_node, top_value_node in doc.value: + if not isinstance(top_value_node, MappingNode): + continue + + keys = [key.value for key, _ in top_value_node.value if key.value != "<<"] + if keys != sorted(keys): + unsorted_blocks.append(f"{path.name}:{top_key_node.value}: {keys}") + + assert not unsorted_blocks, ( + "CDF metadata attribute keys must be in alphabetical order:\n" + + "\n".join(unsorted_blocks) + ) diff --git a/imap_processing/tests/cdf/test_utils.py b/imap_processing/tests/cdf/test_utils.py index 266700aa26..2860a53257 100644 --- a/imap_processing/tests/cdf/test_utils.py +++ b/imap_processing/tests/cdf/test_utils.py @@ -35,7 +35,8 @@ def test_dataset(): "epoch": ( "epoch", met_to_ttj2000ns([1, 2, 3]), - ) + ), + "nan_data": ("epoch", np.array([1.0, 2.0, np.nan]), {"FILLVAL": -1.0e31}), }, attrs=swe_attrs.get_global_attributes("imap_swe_l1a_sci") | { @@ -67,6 +68,8 @@ def test_load_cdf(test_dataset): for attr in xarray_attrs: assert attr not in data_array.attrs + assert np.isnan(dataset["nan_data"].data[2]) + def test_load_cdf_extra_kwargs(test_dataset): """Test that load_cdf passes the correct extra kwargs to xarray_to_cdf""" diff --git a/imap_processing/tests/codice/conftest.py b/imap_processing/tests/codice/conftest.py index 57cb2295d0..9d77379545 100644 --- a/imap_processing/tests/codice/conftest.py +++ b/imap_processing/tests/codice/conftest.py @@ -1,50 +1,237 @@ +from pathlib import Path + +import pytest + from imap_processing import imap_module_directory TEST_DATA_PATH = imap_module_directory / "tests" / "codice" / "data" -TEST_L0_FILE = TEST_DATA_PATH / "imap_codice_l0_raw_20241110_v001.pkts" - -TEST_L1A_FILES = [ - TEST_DATA_PATH / "imap_codice_l1a_hi-counters-aggregated_20241110_v001.cdf", - TEST_DATA_PATH / "imap_codice_l1a_hi-counters-singles_20241110_v001.cdf", - TEST_DATA_PATH / "imap_codice_l1a_hi-ialirt_20241110_v001.cdf", - TEST_DATA_PATH / "imap_codice_l1a_hi-omni_20241110_v001.cdf", - TEST_DATA_PATH / "imap_codice_l1a_hi-priority_20241110_v001.cdf", - TEST_DATA_PATH / "imap_codice_l1a_hi-sectored_20241110_v001.cdf", - TEST_DATA_PATH / "imap_codice_l1a_hskp_20241110_v001.cdf", - TEST_DATA_PATH / "imap_codice_l1a_lo-counters-aggregated_20241110_v001.cdf", - TEST_DATA_PATH / "imap_codice_l1a_lo-counters-singles_20241110_v001.cdf", - TEST_DATA_PATH / "imap_codice_l1a_lo-ialirt_20241110_v001.cdf", - TEST_DATA_PATH / "imap_codice_l1a_lo-nsw-angular_20241110_v001.cdf", - TEST_DATA_PATH / "imap_codice_l1a_lo-nsw-priority_20241110_v001.cdf", - TEST_DATA_PATH / "imap_codice_l1a_lo-nsw-species_20241110_v001.cdf", - TEST_DATA_PATH / "imap_codice_l1a_lo-sw-angular_20241110_v001.cdf", - TEST_DATA_PATH / "imap_codice_l1a_lo-sw-priority_20241110_v001.cdf", - TEST_DATA_PATH / "imap_codice_l1a_lo-sw-species_20241110_v001.cdf", -] - -TEST_L2_FILES = [ - TEST_DATA_PATH / "imap_codice_l1a_hi-direct-events_20241110_v001.cdf", - TEST_DATA_PATH / "imap_codice_l1a_lo-direct-events_20241110_v001.cdf", -] - -# ruff: noqa -VALIDATION_DATA = [ - TEST_DATA_PATH / "validation" / "imap_codice_l1a_hi-ialirt_20241110193900_v0.0.2.cdf", - TEST_DATA_PATH / "validation" / "imap_codice_l1a_lo-ialirt_20241110193900_v0.0.2.cdf", - TEST_DATA_PATH / "validation" / "imap_codice_l1a_hskp_20241110193622_v0.0.2.cdf", - TEST_DATA_PATH / "validation" / "imap_codice_l1a_lo-counters-aggregated_20241110193900_v0.0.2.cdf", - TEST_DATA_PATH / "validation" / "imap_codice_l1a_lo-counters-singles_20241110193900_v0.0.2.cdf", - TEST_DATA_PATH / "validation" / "imap_codice_l1a_lo-sw-priority_20241110193900_v0.0.2.cdf", - TEST_DATA_PATH / "validation" / "imap_codice_l1a_lo-nsw-priority_20241110193900_v0.0.2.cdf", - TEST_DATA_PATH / "validation" / "imap_codice_l1a_lo-sw-species_20241110193900_v0.0.2.cdf", - TEST_DATA_PATH / "validation" / "imap_codice_l1a_lo-nsw-species_20241110193900_v0.0.2.cdf", - TEST_DATA_PATH / "validation" / "imap_codice_l1a_lo-sw-angular_20241110193900_v0.0.2.cdf", - TEST_DATA_PATH / "validation" / "imap_codice_l1a_lo-nsw-angular_20241110193900_v0.0.2.cdf", - TEST_DATA_PATH / "validation" / "imap_codice_l1a_hi-counters-aggregated_20241110193900_v0.0.2.cdf", - TEST_DATA_PATH / "validation" / "imap_codice_l1a_hi-counters-singles_20241110193900_v0.0.2.cdf", - TEST_DATA_PATH / "validation" / "imap_codice_l1a_hi-omni_20241110193900_v0.0.2.cdf", - TEST_DATA_PATH / "validation" / "imap_codice_l1a_hi-sectored_20241110193900_v0.0.2.cdf", - TEST_DATA_PATH / "validation" / "imap_codice_l1a_hi-priorities_20241110193900_v0.0.2.cdf", - TEST_DATA_PATH / "validation" / "imap_codice_l1a_lo-direct-events_20241110193900_v0.0.2.cdf", - TEST_DATA_PATH / "validation" / "imap_codice_l1a_hi-direct-events_20241110193900_v0.0.2.cdf", -] # fmt: skip +TEST_DATA_L0_PATH = TEST_DATA_PATH / "l0_data" +TEST_L0_FILE = TEST_DATA_L0_PATH / "imap_codice_l0_raw_20241110_v001.pkts" + +VALIDATION_FILE_DATE = "20250814" +VALIDATION_FILE_VERSION = "v015" + + +@pytest.fixture(scope="session") +def codice_lut_path(): + """Return a callable side-effect that returns LUT paths based on descriptor. + + This fixture is intended to be used as the `side_effect` for + `ProcessingInputCollection.get_file_paths` in tests, e.g.: + + mock_get_file_paths.side_effect = codice_lut_path + + The returned function accepts a single argument `descriptor` and returns + a list of Paths. + """ + + def _side_effect(descriptor: str = None, data_type: str = None) -> list[Path]: # noqa: RUF013, PLR0911, PLR0912 + # Science data could need to be distinguished by data_type since + # there are both L0 and L1A science files for same descriptor. + if descriptor == "lo-sw-species" and data_type == "l0": + return [ + imap_module_directory + / "tests" + / "codice" + / "data" + / "l1a_input" + / f"imap_codice_l0_lo-sw-species_{VALIDATION_FILE_DATE}_v001.pkts" + ] + elif descriptor == "hi-sectored" and data_type == "l0": + return [ + imap_module_directory + / "tests" + / "codice" + / "data" + / "l1a_input" + / f"imap_codice_l0_hi-sectored_{VALIDATION_FILE_DATE}_v001.pkts" + ] + elif descriptor == "hi-omni" and data_type == "l0": + return [ + imap_module_directory + / "tests" + / "codice" + / "data" + / "l1a_input" + / f"imap_codice_l0_hi-omni_{VALIDATION_FILE_DATE}_v001.pkts" + ] + elif descriptor == "lo-direct-events" and data_type == "l0": + return [ + imap_module_directory + / "tests" + / "codice" + / "data" + / "l1a_input" + / f"imap_codice_l0_lo-direct-events_{VALIDATION_FILE_DATE}_v001.pkts" + ] + elif descriptor == "hi-direct-events" and data_type == "l0": + return [ + imap_module_directory + / "tests" + / "codice" + / "data" + / "l1a_input" + / f"imap_codice_l0_hi-direct-events_{VALIDATION_FILE_DATE}_v001.pkts" + ] + elif descriptor == "lo-nsw-priority" and data_type == "l0": + return [ + imap_module_directory + / "tests" + / "codice" + / "data" + / "l1a_input" + / f"imap_codice_l0_lo-nsw-priority_{VALIDATION_FILE_DATE}_v001.pkts" + ] + elif descriptor == "lo-sw-priority" and data_type == "l0": + return [ + imap_module_directory + / "tests" + / "codice" + / "data" + / "l1a_input" + / f"imap_codice_l0_lo-sw-priority_{VALIDATION_FILE_DATE}_v001.pkts" + ] + elif descriptor == "hi-priorities" and data_type == "l0": + return [ + imap_module_directory + / "tests" + / "codice" + / "data" + / "l1a_input" + / f"imap_codice_l0_hi-priority_{VALIDATION_FILE_DATE}_v001.pkts" + ] + elif descriptor == "hi-counters-singles" and data_type == "l0": + return [ + imap_module_directory + / "tests" + / "codice" + / "data" + / "l1a_input" + / "imap_codice_l0_hi-counters-singles_20250814_v001.pkts" + ] + elif descriptor == "hi-counters-aggregated" and data_type == "l0": + return [ + imap_module_directory + / "tests" + / "codice" + / "data" + / "l1a_input" + / "imap_codice_l0_hi-counters-aggregated_20250814_v001.pkts" + ] + elif descriptor == "lo-counters-singles" and data_type == "l0": + return [ + imap_module_directory + / "tests" + / "codice" + / "data" + / "l1a_input" + / "imap_codice_l0_lo-counters-singles_20250814_v001.pkts" + ] + elif descriptor == "lo-counters-aggregated" and data_type == "l0": + return [ + imap_module_directory + / "tests" + / "codice" + / "data" + / "l1a_input" + / "imap_codice_l0_lo-counters-aggregated_20250814_v001.pkts" + ] + elif descriptor == "hskp" and data_type == "l0": + return [ + imap_module_directory + / "tests" + / "codice" + / "data" + / "l1a_input" + / "imap_codice_l0_hskp_20250814_v001.pkts" + ] + elif descriptor == "lo-sw-species" and data_type == "l1b": + return [ + imap_module_directory + / "tests" + / "codice" + / "data" + / "l1b_validation" + / ( + f"imap_codice_l1b_lo-sw-species_{VALIDATION_FILE_DATE}" + f"_{VALIDATION_FILE_VERSION}.cdf" + ) + ] + elif descriptor == "hi-sectored" and data_type == "l1b": + return [ + imap_module_directory + / "tests/codice/data/l1b_validation" + / ( + f"imap_codice_l1b_hi-sectored_{VALIDATION_FILE_DATE}" + f"_{VALIDATION_FILE_VERSION}.cdf" + ) + ] + elif descriptor == "hi-omni" and data_type == "l1b": + return [ + imap_module_directory + / "tests/codice/data/l1b_validation" + / ( + f"imap_codice_l1b_hi-omni_{VALIDATION_FILE_DATE}" + f"_{VALIDATION_FILE_VERSION}.cdf" + ) + ] + elif descriptor == "l1a-sci-lut": + return [ + TEST_DATA_PATH + / "l1a_lut" + / "imap_codice_l1a-sci-lut_20251007_v005.json" + ] + elif descriptor == "l1a-sci-lut-jan": + return [ + TEST_DATA_PATH + / "l1a_lut" + / "imap_codice_l1a-sci-lut_20260129_v002.json" + ] + elif descriptor == "l2-hi-omni-efficiency": + return [ + TEST_DATA_PATH + / "l2_lut/imap_codice_l2-hi-omni-efficiency_20251212_v003.csv" + ] + elif descriptor == "l2-hi-sectored-efficiency": + return [ + TEST_DATA_PATH + / "l2_lut/imap_codice_l2-hi-sectored-efficiency_20251212_v003.csv" + ] + elif descriptor == "l2-lo-efficiency": + return [ + TEST_DATA_PATH / "l2_lut/imap_codice_l2-lo-efficiency_20251212_v003.csv" + ] + elif descriptor == "l2-lo-gfactor": + return [ + TEST_DATA_PATH / "l2_lut/imap_codice_l2-lo-gfactor_20251212_v003.csv" + ] + elif descriptor == "l2-lo-onboard-mpq-cal": + return [ + TEST_DATA_PATH + / "l2_lut/imap_codice_l2-lo-onboard-mpq-cal_20250101_v001.csv" + ] + elif descriptor == "l2-lo-onboard-energy-bins": + return [ + TEST_DATA_PATH + / "l2_lut/imap_codice_l2-lo-onboard-energy-bins_20250101_v001.csv" + ] + elif descriptor == "l2-lo-onboard-energy-table": + return [ + TEST_DATA_PATH + / "l2_lut/imap_codice_l2-lo-onboard-energy-table_20250101_v001.csv" + ] + elif descriptor == "l2-hi-energy-table": + return [ + TEST_DATA_PATH + / "l2_lut/imap_codice_l2-hi-energy-table_20250101_v001.csv" + ] + elif descriptor == "l2-hi-tof-table": + return [ + TEST_DATA_PATH / "l2_lut/imap_codice_l2-hi-tof-table_20250101_v001.csv" + ] + elif descriptor == "fsw-changes": + return [TEST_DATA_PATH / "l1a_input/imap_codice_l0_raw_20260130_v001.pkts"] + else: + raise ValueError(f"Unknown descriptor: {descriptor}") + + return _side_effect diff --git a/imap_processing/tests/codice/test_codice_hi_l2.py b/imap_processing/tests/codice/test_codice_hi_l2.py new file mode 100644 index 0000000000..af7f277168 --- /dev/null +++ b/imap_processing/tests/codice/test_codice_hi_l2.py @@ -0,0 +1,163 @@ +from unittest.mock import patch + +import numpy as np +import pytest +from imap_data_access.processing_input import ( + AncillaryInput, + ProcessingInputCollection, + ScienceInput, +) + +from imap_processing import imap_module_directory +from imap_processing.cdf.utils import load_cdf, write_cdf +from imap_processing.codice.codice_l2 import ( + process_codice_l2, +) +from imap_processing.tests.codice.conftest import ( + VALIDATION_FILE_DATE, + VALIDATION_FILE_VERSION, +) + +pytestmark = pytest.mark.external_test_data + + +@pytest.fixture +def mock_get_file_paths(codice_lut_path): + with patch( + "imap_data_access.processing_input.ProcessingInputCollection.get_file_paths" + ) as mock_get_file_paths: + # Ensure the side effect treats science inputs as L1B for these L2 tests + mock_get_file_paths.side_effect = lambda descriptor, data_type=None: ( + codice_lut_path(descriptor, data_type="l1b") + ) + yield mock_get_file_paths + + +def test_l2_hi_omni(mock_get_file_paths): + sci_input = ScienceInput( + f"imap_codice_l1b_hi-omni_{VALIDATION_FILE_DATE}_{VALIDATION_FILE_VERSION}.cdf" + ) + anc_input = AncillaryInput("imap_codice_l2-hi-omni-efficiency_20251212_v003.csv") + dependencies = ProcessingInputCollection(anc_input, sci_input) + + processed_l2 = process_codice_l2("hi-omni", dependencies) + + val_data = ( + imap_module_directory + / "tests/codice/data/l2_validation" + / f"imap_codice_l2_hi-omni_{VALIDATION_FILE_DATE}_{VALIDATION_FILE_VERSION}.cdf" + ) + + val_data = load_cdf(val_data) + for variable in val_data.data_vars: + if variable.startswith("unc_"): + continue + np.testing.assert_allclose( + processed_l2[variable].values, + val_data[variable].values, + rtol=1e-5, + err_msg=f"Mismatch in variable '{variable}'", + ) + + # Check coordinates + for variable in val_data.coords: + np.testing.assert_allclose( + processed_l2[variable].values, + val_data[variable].values, + rtol=1e-5, + err_msg=f"Mismatch in coordinate '{variable}'", + ) + # Tests that dimensions match + assert processed_l2[variable].dims == val_data[variable].dims, ( + f"Dimension mismatch in coordinate '{variable}'" + ) + + processed_l2.attrs["Data_version"] = "001" + omni_cdf_file = write_cdf(processed_l2) + assert ( + omni_cdf_file.name == f"imap_codice_l2_hi-omni_{VALIDATION_FILE_DATE}_v001.cdf" + ) + + +def test_l2_hi_sectored(mock_get_file_paths): + anc_input = AncillaryInput( + "imap_codice_l2-hi-sectored-efficiency_20251008_v001.csv" + ) + sci_input = ScienceInput( + f"imap_codice_l1b_hi-sectored_{VALIDATION_FILE_DATE}_{VALIDATION_FILE_VERSION}.cdf" + ) + dependencies = ProcessingInputCollection(anc_input, sci_input) + + processed_l2 = process_codice_l2("hi-sectored", dependencies) + + val_data = ( + imap_module_directory + / "tests/codice/data/l2_validation" + / ( + f"imap_codice_l2_hi-sectored_{VALIDATION_FILE_DATE}" + f"_{VALIDATION_FILE_VERSION}.cdf" + ) + ) + + val_data = load_cdf(val_data) + # TODO fix validation data to have correct array name. Spin_angles -> spin_angle + val_data = val_data.rename({"spin_angles": "spin_angle"}) + # Check data variables + for variable in val_data.data_vars: + # Spin angle bug is fixed but the old validation data is outdated. + # Verified with new 20260201 L2 validation file from Joey. + if variable.startswith("unc_"): + continue + if variable == "spin_angle": + # The external validation file has outdated spin_angle values, but we + # still verify structure and basic numeric sanity to guard against + # regressions in the spin angle computation. + assert processed_l2[variable].dims == val_data[variable].dims, ( + f"Dimension mismatch in variable '{variable}'" + ) + spin_vals = processed_l2[variable].values + # All values should be finite and lie within a reasonable angular range. + assert np.all(np.isfinite(spin_vals)), ( + "spin_angle contains non-finite values" + ) + assert np.min(spin_vals) >= 0.0, "spin_angle has values below 0 degrees" + assert np.max(spin_vals) <= 360.0, "spin_angle has values above 360 degrees" + continue + np.testing.assert_allclose( + processed_l2[variable].values, + val_data[variable].values, + rtol=1e-5, + err_msg=f"Mismatch in variable '{variable}'", + ) + # Tests that dimensions match + if variable in ["epoch_delta_plus", "epoch_delta_minus"]: + continue + assert processed_l2[variable].dims == val_data[variable].dims, ( + f"Dimension mismatch in variable '{variable}'" + ) + + # Check coordinates + for variable in val_data.coords: + if variable.endswith("_label"): + assert np.array_equal( + processed_l2[variable].values, + val_data[variable].values, + ), f"Mismatch in coordinate '{variable}'" + continue + np.testing.assert_allclose( + processed_l2[variable].values, + val_data[variable].values, + rtol=1e-5, + err_msg=f"Mismatch in coordinate '{variable}'", + ) + # Tests that dimensions match + assert processed_l2[variable].dims == val_data[variable].dims, ( + f"Dimension mismatch in coordinate '{variable}'" + ) + + processed_l2.attrs["Data_version"] = "001" + sectored_cdf_file = write_cdf(processed_l2) + assert ( + sectored_cdf_file.name + == f"imap_codice_l2_hi-sectored_{VALIDATION_FILE_DATE}_v001.cdf" + ) diff --git a/imap_processing/tests/codice/test_codice_l0.py b/imap_processing/tests/codice/test_codice_l0.py deleted file mode 100644 index 6a8a425938..0000000000 --- a/imap_processing/tests/codice/test_codice_l0.py +++ /dev/null @@ -1,84 +0,0 @@ -"""Tests the decommutation process for CoDICE CCSDS Packets - -The tests within ensure that the test L0 data can be decommed and result in -the expected APIDs, number of packets, and contain valid CCSDS header contents. -""" - -import pytest -import xarray as xr - -from imap_processing.codice import codice_l0 -from imap_processing.codice.utils import CODICEAPID - -from .conftest import TEST_L0_FILE - -pytestmark = pytest.mark.external_test_data - -EXPECTED_RESULTS = { - CODICEAPID.COD_NHK: 31778, - CODICEAPID.COD_LO_IAL: 18917, - CODICEAPID.COD_LO_PHA: 616, - CODICEAPID.COD_LO_SW_PRIORITY_COUNTS: 77, - CODICEAPID.COD_LO_SW_SPECIES_COUNTS: 77, - CODICEAPID.COD_LO_NSW_SPECIES_COUNTS: 77, - CODICEAPID.COD_LO_SW_ANGULAR_COUNTS: 77, - CODICEAPID.COD_LO_NSW_ANGULAR_COUNTS: 77, - CODICEAPID.COD_LO_NSW_PRIORITY_COUNTS: 77, - CODICEAPID.COD_LO_INST_COUNTS_AGGREGATED: 77, - CODICEAPID.COD_LO_INST_COUNTS_SINGLES: 77, - CODICEAPID.COD_HI_IAL: 18883, - CODICEAPID.COD_HI_PHA: 633, - CODICEAPID.COD_HI_INST_COUNTS_AGGREGATED: 77, - CODICEAPID.COD_HI_INST_COUNTS_SINGLES: 77, - CODICEAPID.COD_HI_OMNI_SPECIES_COUNTS: 77, - CODICEAPID.COD_HI_SECT_SPECIES_COUNTS: 77, - CODICEAPID.COD_HI_INST_COUNTS_PRIORITIES: 77, -} - - -@pytest.fixture(scope="session") -def decom_test_data(_download_test_data) -> xr.Dataset: - """Read test data from file and return a decommutated housekeeping packet. - - Returns - ------- - packet : xr.Dataset - A decommutated housekeeping packet - """ - - packet = codice_l0.decom_packets(TEST_L0_FILE) - - return packet - - -@pytest.mark.parametrize("apid", EXPECTED_RESULTS.keys()) -def test_ccsds_headers(decom_test_data: xr.Dataset, apid): - """Tests that the CCSDS headers are present in the decommed data""" - - for ccsds_header_field in [ - "shcoarse", - "version", - "type", - "sec_hdr_flg", - "pkt_apid", - "seq_flgs", - "src_seq_ctr", - "pkt_len", - ]: - assert ccsds_header_field in decom_test_data[apid] - - -@pytest.mark.parametrize("apid", EXPECTED_RESULTS.keys()) -def test_expected_apids(decom_test_data: xr.Dataset, apid): - """Tests that the expected APIDs are present in the decommed data""" - - assert apid in decom_test_data - - -@pytest.mark.parametrize("apid, expected_num_packets", EXPECTED_RESULTS.items()) -def test_expected_total_packets( - decom_test_data: xr.Dataset, apid, expected_num_packets -): - """Test if total packets in the decommed data is correct""" - - assert len(decom_test_data[apid].epoch) == expected_num_packets diff --git a/imap_processing/tests/codice/test_codice_l1a.py b/imap_processing/tests/codice/test_codice_l1a.py index 8b07e14bb5..af9dec2bb6 100644 --- a/imap_processing/tests/codice/test_codice_l1a.py +++ b/imap_processing/tests/codice/test_codice_l1a.py @@ -1,439 +1,672 @@ -"""Tests the L1a processing for decommutated CoDICE data""" +"""Tests the L1a processing for decommutated CoDICE data + + +Create specific side_effect for each test. Tenzin tried to create generic +function but we query either by data_type to get l0 file or +by descriptor to get lut file. Since each product have their own +l0 test file but processing pipeline has one l0 file, it +caused too much complexity. +""" import logging -import re +from unittest.mock import patch import numpy as np import pytest -import xarray as xr +from imap_data_access import ProcessingInputCollection +from imap_processing import imap_module_directory from imap_processing.cdf.utils import load_cdf, write_cdf -from imap_processing.codice import constants -from imap_processing.codice.codice_l1a import process_codice_l1a - -from .conftest import TEST_L0_FILE, VALIDATION_DATA +from imap_processing.codice.codice_l1a import process_l1a +from imap_processing.codice.codice_l1a_de import l1a_direct_event +from imap_processing.codice.utils import CODICEAPID +from imap_processing.tests.codice.conftest import ( + VALIDATION_FILE_DATE, + VALIDATION_FILE_VERSION, +) +from imap_processing.utils import packet_file_to_datasets logger = logging.getLogger(__name__) -logger.setLevel(logging.INFO) - pytestmark = pytest.mark.external_test_data -DESCRIPTORS = [ - "hi-ialirt", - "lo-ialirt", - "hskp", - "lo-counters-aggregated", - "lo-counters-singles", - "lo-sw-priority", - "lo-nsw-priority", - "lo-sw-species", - "lo-nsw-species", - "lo-sw-angular", - "lo-nsw-angular", - "hi-counters-aggregated", - "hi-counters-singles", - "hi-omni", - "hi-sectored", - "hi-priority", - "lo-direct-events", - "hi-direct-events", -] - - -EXPECTED_ARRAY_SHAPES = [ - (304, 15), # hi-ialirt - (76, 128, 1), # lo-ialirt - (31778,), # hskp - (77, 128, 6), # lo-counters-aggregated - (77, 128, 24, 6), # lo-counters-singles - (77, 128, 24), # lo-sw-priority - (77, 128, 24), # lo-nsw-priority - (77, 128, 1), # lo-sw-species - (77, 128, 1), # lo-nsw-species - (77, 128, 5, 24), # lo-sw-angular - (77, 128, 19, 24), # lo-nsw-angular - (77,), # hi-counters-aggregated - (77, 12), # hi-counters-singles - (), # hi-omni, shapes are specific to species - (77, 8, 12, 12), # hi-sectored - (77,), # hi-priorities - (77, 10000), # lo-direct-events - (77, 10000), # hi-direct-events -] - -EXPECTED_HI_OMNI_ARRAY_SHAPES = { - "h": (308, 15), - "he3": (308, 15), - "he4": (308, 15), - "c": (308, 18), - "o": (308, 18), - "ne_mg_si": (308, 15), - "fe": (308, 18), - "uh": (308, 5), - "junk": (308, 1), -} - -EXPECTED_NUM_VARIABLES = [ - 3, # hi-ialirt - 18, # lo-ialirt - 139, # hskp - 9 + len(constants.LO_COUNTERS_AGGREGATED_VARIABLE_NAMES), # lo-counters-aggregated - 10, # lo-counters-singles - 14, # lo-sw-priority - 11, # lo-nsw-priority - 25, # lo-sw-species - 17, # lo-nsw-species - 13, # lo-sw-angular - 10, # lo-nsw-angular - 2 + len(constants.HI_COUNTERS_AGGREGATED_VARIABLE_NAMES), # hi-counters-aggregated - 5, # hi-counters-singles - 11, # hi-omni - 6, # hi-sectored - 8, # hi-priority - 80, # lo-direct-events - 60, # hi-direct-events -] - -# CoDICE-Hi products that have support variables to test -CODICE_HI_PRODUCTS = [ - "hi-counters-aggregated", - "hi-counters-singles", - "hi-priority", - "hi-sectored", -] -# TODO: Add hi-omni here once I sort out the array shape discrepancy with the -# validation data - -# CoDICE-Lo products that have support variables to test -# TODO: Investigate why lo-ialirt is failing some tests -CODICE_LO_PRODUCTS = [ - "lo-counters-aggregated", - "lo-counters-singles", - "lo-nsw-angular", - "lo-nsw-priority", - "lo-nsw-species", - "lo-sw-angular", - "lo-sw-priority", - "lo-sw-species", -] - - -@pytest.fixture(scope="session") -def test_l1a_data() -> list[xr.Dataset]: - """Return a ``xarray`` dataset containing test data. - - Returns - ------- - processed_datasets : list[xarray.Dataset] - A list of ``xarray`` datasets containing the test data - """ - processed_datasets = process_codice_l1a(file_path=TEST_L0_FILE) - - return processed_datasets - - -@pytest.mark.parametrize("index", range(len(EXPECTED_ARRAY_SHAPES))) -def test_l1a_data_array_shape(test_l1a_data, index): - """Tests that the data arrays in the generated CDFs have the expected shape. - - Parameters - ---------- - test_l1a_data : list[xarray.Dataset] - A list of ``xarray`` datasets containing the test data - index : int - The index of the list to test - """ - - descriptor = DESCRIPTORS[index] - processed_dataset = test_l1a_data[index] - expected_shape = EXPECTED_ARRAY_SHAPES[index] - - # hi-omni data array shapes depend on the species - if descriptor == "hi-omni": - for variable in constants.HI_OMNI_VARIABLE_NAMES: - assert ( - processed_dataset[variable].data.shape - == EXPECTED_HI_OMNI_ARRAY_SHAPES[variable] + +@patch("imap_data_access.processing_input.ProcessingInputCollection.get_file_paths") +def test_updated_packet_version(mock_get_file_paths, codice_lut_path, caplog): + """Tests the new FSW changes (jan 2026).""" + codice_lut_path_jan = codice_lut_path(descriptor="l1a-sci-lut-jan") + mock_get_file_paths.side_effect = [ + codice_lut_path(descriptor="fsw-changes", data_type="l0"), + *([codice_lut_path_jan] * 20), + ] + datasets = process_l1a(dependency=ProcessingInputCollection()) + # Assert that we have all of the expected datasets + assert len(datasets) == 14 + for ds in datasets: + # Only check lo products. Skip direct-events + if ( + "lo" not in ds.attrs["Data_type"] + or "direct-events" in ds.attrs["Data_type"] + ): + continue + # Check that the lo datasets contain the new unpacked variables + expected_vars = [ + "rgfo_spin_sector", + "nso_spin_sector", + "rgfo_esa_step", + "nso_esa_step", + ] + for var in expected_vars: + assert var in ds.data_vars, ( + f"Expected variable '{var}' not found in dataset" ) - else: - # There are exceptions for some variables - for variable in processed_dataset: - # For variables with energy dimensions - if variable in ["energy_table", "acquisition_time_per_step"]: - assert processed_dataset[variable].data.shape == (128,) - # For "support" variables with epoch dimensions - elif variable in [ - "rgfo_half_spin", - "nso_half_spin", - "sw_bias_gain_mode", - "st_bias_gain_mode", - "data_quality", - "spin_period", - ]: - assert processed_dataset[variable].data.shape == ( - len(processed_dataset["epoch"].data), - ) - # For some direct event variables: - elif re.match(r"p[0-7]_(num_events|data_quality)", variable): - assert processed_dataset[variable].data.shape == (77,) - # For the k-factor - elif variable == "k_factor": - assert processed_dataset[variable].data.shape == (1,) - # For nominal variables - else: - assert processed_dataset[variable].data.shape == expected_shape - - -@pytest.mark.parametrize("index", range(len(DESCRIPTORS))) -def test_l1a_logical_sources(test_l1a_data, index): - """Tests that the Logical source of the dataset is what is expected. - - Since the logical source gets set by ``write_cdf``, this also tests that - the dataset can be written to a file. - - Parameters - ---------- - test_l1a_data : list[xarray.Dataset] - A list of ``xarray`` datasets containing the test data - index : int - The index of the list to test - """ - - processed_dataset = test_l1a_data[index] - expected_logical_source = f"imap_codice_l1a_{DESCRIPTORS[index]}" - - # Write the dataset to a file to set the logical source attribute - _ = write_cdf(processed_dataset) - - assert processed_dataset.attrs["Logical_source"] == expected_logical_source - - -@pytest.mark.parametrize("index", range(len(EXPECTED_NUM_VARIABLES))) -def test_l1a_num_data_variables(test_l1a_data, index): - """Tests that the generated CDFs have the expected number of data variables. - - These data variables include counter data (e.g. hplus, heplus, etc.) as well - as any "support" variables (e.g. data_quality, spin_period, etc.). - - Parameters - ---------- - test_l1a_data : list[xarray.Dataset] - A list of ``xarray`` datasets containing the test data - index : int - The index of the list to test - """ - - processed_dataset = test_l1a_data[index] - assert len(processed_dataset) == EXPECTED_NUM_VARIABLES[index] - - -@pytest.mark.parametrize("index", range(len(VALIDATION_DATA))) -@pytest.mark.xfail(reason="Validation test turned off; awaiting fixes") -def test_l1a_validate_data_arrays(test_l1a_data: xr.Dataset, index): - """Tests that the generated L1a CDF data array contents are valid. - - Parameters - ---------- - test_l1a_data : list[xarray.Dataset] - A list of ``xarray`` datasets containing the test data - index : int - The index of the list to test - """ - - descriptor = DESCRIPTORS[index] - - # Mark currently broken/unsupported datasets as expected to fail - if descriptor == "hskp": - pytest.skip("Housekeeping data is validated in a separate test") - # TODO: Remove this next condition once hi-ialirt is validated - if descriptor == "hi-ialirt": - pytest.xfail("Awaiting validation fixes") - - counters = getattr( - constants, f"{descriptor.upper().replace('-', '_')}_VARIABLE_NAMES" + # check that a warning is logged for the missing "cnoplus" species + assert ( + "Desired species cnoplus not found in actual species names from LUT" + in caplog.text + ) + + +@patch("imap_data_access.processing_input.ProcessingInputCollection.get_file_paths") +def test_hskp(mock_get_file_paths, codice_lut_path): + """Tests the housekeeping.""" + mock_get_file_paths.side_effect = [ + codice_lut_path(descriptor="hskp", data_type="l0"), + codice_lut_path(descriptor="l1a-sci-lut"), + ] + processed_datasets = process_l1a(dependency=ProcessingInputCollection()) + + assert len(processed_datasets) == 2 + processed_l1a = processed_datasets[0] + processed_l1b = processed_datasets[1] + + # spot check the l1a value is an integer and the l1b is a float after conversion + np.testing.assert_almost_equal(processed_l1a["fee_ssd_eb_temp_1_t"].values[0], 2199) + np.testing.assert_almost_equal( + processed_l1b["fee_ssd_eb_temp_1_t"].values[0], 18.71, decimal=2 ) - processed_dataset = test_l1a_data[index] - validation_dataset = load_cdf(VALIDATION_DATA[index]) - - for counter in counters: - # Ensure the data arrays are equal - np.testing.assert_equal( - processed_dataset[counter].data, validation_dataset[counter].data - ) - - -@pytest.mark.parametrize("index", range(len(DESCRIPTORS))) -def test_l1a_validate_dimensions(test_l1a_data, index): - """Tests that the dimensions of the data are in the expected order. - - Parameters - ---------- - test_l1a_data : list[xarray.Dataset] - A list of ``xarray`` datasets containing the test data - index : int - The index of the list to test - """ - - descriptor = DESCRIPTORS[index] - dataset = test_l1a_data[index] - - # This is the expected order of dimensions. Not all of these appear in every - # data product, but for those that do appear, they should be in this order. - expected_dims_order = [ - "epoch", - "esa_step", - "inst_az", - "spin_sector", - "spin_sector_pairs", - "ssd_index", + + +@patch("imap_data_access.processing_input.ProcessingInputCollection.get_file_paths") +def test_lo_counters_aggregated(mock_get_file_paths, codice_lut_path): + """Tests lo-counters-aggregated.""" + mock_get_file_paths.side_effect = [ + codice_lut_path(descriptor="lo-counters-aggregated", data_type="l0"), + codice_lut_path(descriptor="l1a-sci-lut"), ] - # We don't need to check hskp, direct events, or binned datasets since they - # are not multidimensional - if descriptor not in [ - "hskp", - "lo-direct-events", - "hi-direct-events", - "hi-omni", - "hi-ialirt", - "hi-sectored", - ]: - # Get the variables that have dimensions that need to be checked - counters = getattr( - constants, f"{descriptor.upper().replace('-', '_')}_VARIABLE_NAMES" - ) - - # Ensure that, of the dimensions in the particular variable, they occur - # in the expected order. - for counter in counters: - positions = [ - expected_dims_order.index(dim) for dim in dataset[counter].dims - ] - assert positions == sorted(positions) - - -@pytest.mark.parametrize("index", range(len(DESCRIPTORS))) -def test_l1a_validate_epoch_values(test_l1a_data, index): - """Tests that the epoch values in the generated data products match the - validation data. - - Parameters - ---------- - test_l1a_data : list[xarray.Dataset] - A list of ``xarray`` datasets containing the test data - index : int - The index of the list to test - """ - - descriptor = DESCRIPTORS[index] - dataset = test_l1a_data[index] - validation_dataset = load_cdf(VALIDATION_DATA[index]) - - if descriptor in ["hi-ialirt", "lo-ialirt"]: - pytest.xfail( - f"Awaiting implementation of proper epoch calculation for {descriptor}" - ) - - # TODO: Add checks for epoch_delta_minus - # TODO: Revisit this at some point to see if we can do an exact comparison - np.testing.assert_allclose( - dataset.epoch.data, validation_dataset.epoch.data, rtol=1e-6, atol=0 + processed_data = process_l1a(dependency=ProcessingInputCollection())[0] + + # Validation + val_path = ( + imap_module_directory + / "tests/codice/data/l1a_validation/" + / ( + f"imap_codice_l1a_lo-counters-aggregated_{VALIDATION_FILE_DATE}" + f"_{VALIDATION_FILE_VERSION}.cdf" + ) ) + val_data = load_cdf(val_path) + for variable in val_data.data_vars: + # TODO: ask Joey to remove reserved variables from validation files + if variable.startswith("reserved"): + continue + try: + np.testing.assert_allclose( + processed_data[variable].values, + val_data[variable].values, + rtol=1e-5, + err_msg=f"Mismatch in variable '{variable}'", + ) + except AssertionError: + # TODO: remove this try/except after non-active variables + # dimensions are fixed in Joey's validation files. + continue + + processed_data.attrs["Data_version"] = "001" + cdf_file = write_cdf(processed_data, terminate_on_warning=True) + assert ( + cdf_file.name + == f"imap_codice_l1a_lo-counters-aggregated_{VALIDATION_FILE_DATE}_v001.cdf" + ) + + +@patch("imap_data_access.processing_input.ProcessingInputCollection.get_file_paths") +def test_lo_counters_singles(mock_get_file_paths, codice_lut_path): + """Tests lo-counters-singles.""" + mock_get_file_paths.side_effect = [ + codice_lut_path(descriptor="lo-counters-singles", data_type="l0"), + codice_lut_path(descriptor="l1a-sci-lut"), + ] + processed_data = process_l1a(dependency=ProcessingInputCollection())[0] + # Validation + val_path = ( + imap_module_directory + / "tests/codice/data/l1a_validation/" + / ( + f"imap_codice_l1a_lo-counters-singles_{VALIDATION_FILE_DATE}" + f"_{VALIDATION_FILE_VERSION}.cdf" + ) + ) + val_data = load_cdf(val_path) + for variable in val_data.data_vars: + np.testing.assert_allclose( + processed_data[variable].values, + val_data[variable].values, + rtol=1e-5, + err_msg=f"Mismatch in variable '{variable}'", + ) -def test_l1a_validate_hskp_data(test_l1a_data): - """Tests that the L1a housekeeping data is valid""" + processed_data.attrs["Data_version"] = "001" + cdf_file = write_cdf(processed_data, terminate_on_warning=True) + assert ( + cdf_file.name + == f"imap_codice_l1a_lo-counters-singles_{VALIDATION_FILE_DATE}_v001.cdf" + ) - # Housekeeping data is the 2nd element in the list of test products - hskp_data = test_l1a_data[2] - validation_hskp_filepath = VALIDATION_DATA[2] - # Load the validation housekeeping data - validation_hskp_data = load_cdf(validation_hskp_filepath) +@patch("imap_data_access.processing_input.ProcessingInputCollection.get_file_paths") +def test_lo_sw_priority(mock_get_file_paths, codice_lut_path): + """Tests lo-sw-priority.""" - # These variables are not present in the validation dataset - exclude_variables = [ - "version", - "type", - "sec_hdr_flg", - "pkt_apid", - "seq_flgs", - "src_seq_ctr", - "pkt_len", + mock_get_file_paths.side_effect = [ + codice_lut_path(descriptor="lo-sw-priority", data_type="l0"), + codice_lut_path(descriptor="l1a-sci-lut"), ] - for variable in hskp_data: - if variable not in exclude_variables: - np.testing.assert_array_equal( - hskp_data[variable], validation_hskp_data[variable.upper()] - ) + processed_data = process_l1a(dependency=ProcessingInputCollection())[0] + + # Validation + val_path = ( + imap_module_directory + / "tests/codice/data/l1a_validation/" + / ( + f"imap_codice_l1a_lo-sw-priority_{VALIDATION_FILE_DATE}" + f"_{VALIDATION_FILE_VERSION}.cdf" + ) + ) + val_data = load_cdf(val_path) + + for variable in val_data.data_vars: + np.testing.assert_allclose( + processed_data[variable].values, + val_data[variable].values, + rtol=1e-5, + err_msg=f"Mismatch in variable '{variable}'", + ) + for variable in val_data.coords: + if variable.endswith("_label"): + assert np.array_equal( + processed_data[variable].values, + val_data[variable].values, + ), f"Mismatch in coordinate '{variable}'" + continue + np.testing.assert_allclose( + processed_data[variable].values, + val_data[variable].values, + rtol=1e-5, + err_msg=f"Mismatch in coordinate '{variable}'", + ) -@pytest.mark.parametrize("index", range(len(DESCRIPTORS))) -def test_l1a_validate_support_variables(test_l1a_data, index): - """Tests that the support variables for the generated products match the - validation data - - Parameters - ---------- - test_l1a_data : list[xarray.Dataset] - A list of ``xarray`` datasets containing the test data - index : int - The index of the list to test - """ - - support_variables = [ - "data_quality", - "nso_half_spin", - "rgfo_half_spin", - "spin_period", - "st_bias_gain_mode", - "sw_bias_gain_mode", - "k_factor", + processed_data.attrs["Data_version"] = "001" + cdf_file = write_cdf(processed_data, terminate_on_warning=True) + assert ( + cdf_file.name + == f"imap_codice_l1a_lo-sw-priority_{VALIDATION_FILE_DATE}_v001.cdf" + ) + + +@patch("imap_data_access.processing_input.ProcessingInputCollection.get_file_paths") +def test_lo_nsw_priority(mock_get_file_paths, codice_lut_path): + """Tests lo-nsw-priority.""" + mock_get_file_paths.side_effect = [ + codice_lut_path(descriptor="lo-nsw-priority", data_type="l0"), + codice_lut_path(descriptor="l1a-sci-lut"), ] - descriptor = DESCRIPTORS[index] - dataset = test_l1a_data[index] - validation_dataset = load_cdf(VALIDATION_DATA[index]) - - if descriptor in CODICE_LO_PRODUCTS: - # Note that for the energy table and acquisition time, the validation - # data only carries three decimal places whereas the SDC-generated CDFs - # carry more significant figures - - # Ensure the energy table values are (nearly) equal - np.testing.assert_almost_equal( - dataset.energy_table.data, validation_dataset.voltage_table.data, decimal=3 - ) - - # Ensure that the acquisition times are (nearly) equal - # TODO: Turn this back on when Joey supplies updated validation data with - # updated acquisition times - # np.testing.assert_almost_equal( - # dataset.acquisition_time_per_step.data, - # validation_dataset.acquisition_time_per_step.data, - # decimal=3, - # ) - - # Ensure that the support variables derived from packet data are equal - for variable in support_variables: - np.testing.assert_equal( - dataset[variable].data, - validation_dataset[variable].data, - ) + processed_data = process_l1a(dependency=ProcessingInputCollection())[0] + + # Validation + val_path = ( + imap_module_directory + / "tests/codice/data/l1a_validation/" + / ( + f"imap_codice_l1a_lo-nsw-priority_{VALIDATION_FILE_DATE}" + f"_{VALIDATION_FILE_VERSION}.cdf" + ) + ) + val_data = load_cdf(val_path) + + for variable in val_data.data_vars: + np.testing.assert_allclose( + processed_data[variable].values, + val_data[variable].values, + rtol=1e-5, + err_msg=f"Mismatch in variable '{variable}'", + ) + + for variable in val_data.coords: + # If string type, do equal. + if variable.endswith("_label"): + assert np.array_equal( + processed_data[variable].values, + val_data[variable].values, + ), f"Mismatch in coordinate '{variable}'" + continue + np.testing.assert_allclose( + processed_data[variable].values, + val_data[variable].values, + rtol=1e-5, + err_msg=f"Mismatch in coordinate '{variable}'", + ) + + processed_data.attrs["Data_version"] = "001" + cdf_file = write_cdf(processed_data, terminate_on_warning=True) + assert ( + cdf_file.name + == f"imap_codice_l1a_lo-nsw-priority_{VALIDATION_FILE_DATE}_v001.cdf" + ) - elif descriptor in CODICE_HI_PRODUCTS: - for variable in ["spin_period", "data_quality"]: - np.testing.assert_equal( - dataset[variable].data, - validation_dataset[variable].data, - ) +@patch("imap_data_access.processing_input.ProcessingInputCollection.get_file_paths") +def test_lo_sw_species(mock_get_file_paths, codice_lut_path): + """Tests lo-sw-species.""" -def test_l1a_multiple_packets(): - """Tests that an input L0 file containing multiple APIDs can be processed.""" + mock_get_file_paths.side_effect = [ + codice_lut_path(descriptor="lo-sw-species", data_type="l0"), + codice_lut_path(descriptor="l1a-sci-lut"), + ] - processed_datasets = process_codice_l1a(file_path=TEST_L0_FILE) + # Validation + val_path = ( + imap_module_directory + / "tests/codice/data/l1a_validation/" + / ( + f"imap_codice_l1a_lo-sw-species_{VALIDATION_FILE_DATE}" + f"_{VALIDATION_FILE_VERSION}.cdf" + ) + ) - assert len(processed_datasets) == 18 + val_data = load_cdf(val_path) + + # Process the input data + processed_data = process_l1a(dependency=ProcessingInputCollection())[0] + # Compare only the common variables + for variable in val_data.data_vars: + np.testing.assert_allclose( + processed_data[variable].values, + val_data[variable].values, + rtol=1e-5, + err_msg=f"Mismatch in variable '{variable}'", + ) + + for variable in val_data.coords: + if variable.endswith("_label"): + assert np.array_equal( + processed_data[variable].values, + val_data[variable].values, + ), f"Mismatch in coordinate '{variable}'" + continue + np.testing.assert_allclose( + processed_data[variable].values, + val_data[variable].values, + rtol=1e-5, + err_msg=f"Mismatch in coordinate '{variable}'", + ) + processed_data.attrs["Data_version"] = "002" + cdf_file = write_cdf(processed_data, terminate_on_warning=True) + assert ( + cdf_file.name + == f"imap_codice_l1a_lo-sw-species_{VALIDATION_FILE_DATE}_v002.cdf" + ) + + +@patch("imap_data_access.processing_input.ProcessingInputCollection.get_file_paths") +def test_hi_counters_aggregated(mock_get_file_paths, codice_lut_path): + """Tests hi-counters-aggregated.""" + mock_get_file_paths.side_effect = [ + codice_lut_path(descriptor="hi-counters-aggregated", data_type="l0"), + codice_lut_path(descriptor="l1a-sci-lut"), + ] + + processed_data = process_l1a(ProcessingInputCollection())[0] + # Validation + val_path = ( + imap_module_directory + / "tests/codice/data/l1a_validation/" + / ( + f"imap_codice_l1a_hi-counters-aggregated_{VALIDATION_FILE_DATE}" + f"_{VALIDATION_FILE_VERSION}.cdf" + ) + ) + val_data = load_cdf(val_path) + for variable in val_data.data_vars: + np.testing.assert_allclose( + processed_data[variable].values, + val_data[variable].values, + rtol=1e-5, + err_msg=f"Mismatch in variable '{variable}'", + ) + + processed_data.attrs["Data_version"] = "001" + cdf_file = write_cdf(processed_data, terminate_on_warning=True) + assert ( + cdf_file.name + == f"imap_codice_l1a_hi-counters-aggregated_{VALIDATION_FILE_DATE}_v001.cdf" + ) + + +@patch("imap_data_access.processing_input.ProcessingInputCollection.get_file_paths") +def test_hi_counters_singles(mock_get_file_paths, codice_lut_path): + """Tests hi-counters-singles.""" + mock_get_file_paths.side_effect = [ + codice_lut_path(descriptor="hi-counters-singles", data_type="l0"), + codice_lut_path(descriptor="l1a-sci-lut"), + ] + + processed_data = process_l1a(dependency=ProcessingInputCollection())[0] + + # Validation + val_path = ( + imap_module_directory + / "tests/codice/data/l1a_validation/" + / ( + f"imap_codice_l1a_hi-counters-singles_{VALIDATION_FILE_DATE}" + f"_{VALIDATION_FILE_VERSION}.cdf" + ) + ) + val_data = load_cdf(val_path) + + for variable in val_data.data_vars: + np.testing.assert_allclose( + processed_data[variable].values, + val_data[variable].values, + rtol=1e-5, + err_msg=f"Mismatch in variable '{variable}'", + ) + + processed_data.attrs["Data_version"] = "001" + cdf_file = write_cdf(processed_data, terminate_on_warning=True) + assert ( + cdf_file.name + == f"imap_codice_l1a_hi-counters-singles_{VALIDATION_FILE_DATE}_v001.cdf" + ) + + +@patch("imap_data_access.processing_input.ProcessingInputCollection.get_file_paths") +def test_hi_omni(mock_get_file_paths, codice_lut_path): + """Tests hi-omni.""" + + mock_get_file_paths.side_effect = [ + codice_lut_path(descriptor="hi-omni", data_type="l0"), + codice_lut_path(descriptor="l1a-sci-lut"), + ] + + processed_data = process_l1a(dependency=ProcessingInputCollection())[0] + + # Validation + val_path = ( + imap_module_directory + / "tests/codice/data/l1a_validation/" + / ( + f"imap_codice_l1a_hi-omni_{VALIDATION_FILE_DATE}" + f"_{VALIDATION_FILE_VERSION}.cdf" + ) + ) + val_data = load_cdf(val_path) + + for variable in val_data.data_vars: + np.testing.assert_allclose( + processed_data[variable].values, + val_data[variable].values, + rtol=1e-5, + err_msg=f"Mismatch in variable '{variable}'", + ) + + for variable in val_data.coords: + np.testing.assert_allclose( + processed_data[variable].values, + val_data[variable].values, + rtol=1e-5, + err_msg=f"Mismatch in variable '{variable}'", + ) + processed_data.attrs["Data_version"] = "001" + cdf_file = write_cdf(processed_data, terminate_on_warning=True) + assert cdf_file.name == f"imap_codice_l1a_hi-omni_{VALIDATION_FILE_DATE}_v001.cdf" + + +@pytest.mark.xfail(reason="Need to revisit in future PR") +@patch("imap_data_access.processing_input.ProcessingInputCollection.get_file_paths") +def test_hi_sectored(mock_get_file_paths, codice_lut_path): + """Tests hi-sectored.""" + mock_get_file_paths.side_effect = [ + codice_lut_path(descriptor="hi-sectored", data_type="l0"), + codice_lut_path(descriptor="l1a-sci-lut"), + ] + # Validation + val_path = ( + imap_module_directory + / "tests/codice/data/l1a_validation/" + / ( + f"imap_codice_l1a_hi-sectored_{VALIDATION_FILE_DATE}" + f"_{VALIDATION_FILE_VERSION}.cdf" + ) + ) + val_data = load_cdf(val_path) + + processed_data = process_l1a(dependency=ProcessingInputCollection())[0] + for variable in val_data.data_vars: + np.testing.assert_allclose( + processed_data[variable].values, + val_data[variable].values, + rtol=1e-5, + err_msg=f"Mismatch in variable '{variable}'", + ) + for variable in val_data.coords: + # If _label, do string comparison + if variable.endswith("_label"): + assert np.array_equal( + processed_data[variable].values, + val_data[variable].values, + ), f"Mismatch in coordinate '{variable}'" + continue + + np.testing.assert_allclose( + processed_data[variable].values, + val_data[variable].values, + rtol=1e-5, + err_msg=f"Mismatch in coordinate '{variable}'", + ) + + processed_data.attrs["Data_version"] = "001" + cdf_file = write_cdf(processed_data, terminate_on_warning=True) + assert ( + cdf_file.name == f"imap_codice_l1a_hi-sectored_{VALIDATION_FILE_DATE}_v001.cdf" + ) + + +@patch("imap_data_access.processing_input.ProcessingInputCollection.get_file_paths") +def test_hi_priority(mock_get_file_paths, codice_lut_path): + """Tests hi-priorities.""" + mock_get_file_paths.side_effect = [ + codice_lut_path(descriptor="hi-priorities", data_type="l0"), + codice_lut_path(descriptor="l1a-sci-lut"), + ] + + # Process the input data + processed_data = process_l1a(ProcessingInputCollection())[0] + + # Validation + val_path = ( + imap_module_directory + / "tests/codice/data/l1a_validation/" + / ( + f"imap_codice_l1a_hi-priority_{VALIDATION_FILE_DATE}" + f"_{VALIDATION_FILE_VERSION}.cdf" + ) + ) + + val_data = load_cdf(val_path) + + for variable in val_data.data_vars: + np.testing.assert_allclose( + processed_data[variable].values, + val_data[variable].values, + rtol=1e-5, + err_msg=f"Mismatch in variable '{variable}'", + ) + for variable in val_data.coords: + if variable.endswith("_label"): + assert np.array_equal( + processed_data[variable].values, + val_data[variable].values, + ), f"Mismatch in coordinate '{variable}'" + continue + np.testing.assert_allclose( + processed_data[variable].values, + val_data[variable].values, + rtol=1e-5, + err_msg=f"Mismatch in coordinate '{variable}'", + ) + + processed_data.attrs["Data_version"] = "001" + cdf_file = write_cdf(processed_data, terminate_on_warning=True) + assert ( + cdf_file.name == f"imap_codice_l1a_hi-priority_{VALIDATION_FILE_DATE}_v001.cdf" + ) + + +@patch("imap_data_access.processing_input.ProcessingInputCollection.get_file_paths") +def test_lo_direct_events(mock_get_file_paths, codice_lut_path): + """Tests lo-direct-events.""" + mock_get_file_paths.side_effect = [ + codice_lut_path(descriptor="lo-direct-events", data_type="l0"), + ] + + # Validation + val_path = ( + imap_module_directory + / "tests/codice/data/l1a_validation/" + / ( + f"imap_codice_l1a_lo-direct-events_{VALIDATION_FILE_DATE}" + f"_{VALIDATION_FILE_VERSION}.cdf" + ) + ) + val_data = load_cdf(val_path) + + processed_data = process_l1a(dependency=ProcessingInputCollection())[0] + + for variable in val_data.data_vars: + if variable in ["priority_label"]: + # Do string comparison for priority_label + assert np.array_equal( + processed_data[variable].values, val_data[variable].values + ), f"Mismatch in variable '{variable}'" + continue + + np.testing.assert_allclose( + processed_data[variable].values, + val_data[variable].values, + rtol=1e-5, + err_msg=f"Mismatch in variable '{variable}'", + ) + for variable in val_data.coords: + np.testing.assert_allclose( + processed_data[variable].values, + val_data[variable].values, + rtol=1e-5, + err_msg=f"Mismatch in coordinate '{variable}'", + ) + + processed_data.attrs["Data_version"] = "002" + cdf_file = write_cdf(processed_data, terminate_on_warning=True) + assert ( + cdf_file.name + == f"imap_codice_l1a_lo-direct-events_{VALIDATION_FILE_DATE}_v002.cdf" + ) + + +def test_direct_events_incomplete_groups(codice_lut_path, caplog): + """Tests lo-direct-events with a packet containing incomplete groups.""" + + # Get science data which is L0 packet file + science_file = codice_lut_path(descriptor="lo-direct-events", data_type="l0")[0] + + xtce_file = ( + imap_module_directory + / "codice/packet_definitions/imap_codice_packet-definition_20250101_v001.xml" + ) + # Decom packet + datasets_by_apid = packet_file_to_datasets( + science_file, + xtce_file, + ) + apid = CODICEAPID.COD_LO_PHA + de_dataset = datasets_by_apid[apid] + # Drop the first packet to test incomplete group handling + # This mocks the case when one priority group is incomplete + # in this example, the first group is missing the first priority + len_epoch = de_dataset.sizes["epoch"] + de_dataset = de_dataset.isel(epoch=slice(1, len_epoch)) + dataset = l1a_direct_event(de_dataset, apid) + # Check that fillvals are used for the first missing priority for the first epoch + assert np.all(dataset.tof[0, 0, :].values == 65535) + # Check that there is data for the remaining priorities + assert np.any(dataset.tof[0, 1:, :].values != 65535) + # Check logs for incomplete groups + assert ( + f"Found 1 incomplete priority group(s) for APID {apid}. " + f"Expected 8 packets per group" + ) in caplog.text + + +@patch("imap_data_access.processing_input.ProcessingInputCollection.get_file_paths") +def test_hi_direct_events(mock_get_file_paths, codice_lut_path): + """Tests hi-direct-events.""" + mock_get_file_paths.side_effect = [ + codice_lut_path(descriptor="hi-direct-events", data_type="l0"), + ] + + # Validation + val_path = ( + imap_module_directory + / "tests/codice/data/l1a_validation/" + / ( + f"imap_codice_l1a_hi-direct-events_{VALIDATION_FILE_DATE}" + f"_{VALIDATION_FILE_VERSION}.cdf" + ) + ) + val_data = load_cdf(val_path) + + processed_data = process_l1a(dependency=ProcessingInputCollection())[0] + + for variable in val_data.data_vars: + if variable in ["priority_label"]: + # Do string comparison for priority_label + assert np.array_equal( + processed_data[variable].values, val_data[variable].values + ), f"Mismatch in variable '{variable}'" + continue + + np.testing.assert_allclose( + processed_data[variable].values, + val_data[variable].values, + rtol=1e-5, + err_msg=f"Mismatch in variable '{variable}'", + ) + for variable in val_data.coords: + np.testing.assert_allclose( + processed_data[variable].values, + val_data[variable].values, + rtol=1e-5, + err_msg=f"Mismatch in coordinate '{variable}'", + ) + + processed_data.attrs["Data_version"] = "002" + cdf_file = write_cdf(processed_data, terminate_on_warning=True) + assert ( + cdf_file.name + == f"imap_codice_l1a_hi-direct-events_{VALIDATION_FILE_DATE}_v002.cdf" + ) diff --git a/imap_processing/tests/codice/test_codice_l1a_lut.py b/imap_processing/tests/codice/test_codice_l1a_lut.py new file mode 100644 index 0000000000..31e1e33b10 --- /dev/null +++ b/imap_processing/tests/codice/test_codice_l1a_lut.py @@ -0,0 +1,282 @@ +import json + +import numpy as np +import pytest + +from imap_processing.codice.utils import ( + calculate_acq_time_per_step, + get_collapse_pattern_shape, + get_counters_aggregated_pattern, +) + +pytestmark = pytest.mark.external_test_data + + +def test_codice_non_zero_patterns(codice_lut_path): + """Test L1A collapse Lo and Hi non-zero patterns. + + This is mainly checking for expected row indices of non-zero + of Lo and Hi collapse patterns. This doesn't check for unique + values in rows and column. It returns shape of data as it is, + (row, column). This is different from collapse pattern shape + which is tested in `test_get_collapse_pattern_shape`. + """ + sci_lut_path = codice_lut_path(descriptor="l1a-sci-lut")[0] + + sci_lut = json.loads(sci_lut_path.read_text()) + table_id = "3952862729" + assert table_id in sci_lut + + collapse_lo = sci_lut[table_id]["collapse_lo"] + + # expected non-zero row indices for each collapse_lo matrix + expected_lo_non_zero_rows = { + "0": [1, 2, 3, 23, 24], + # "1" aggregation is tested separately below + "2": list(range(1, 25)), + "3": [1, 2, 3, 23, 24, 28, 31], + "4": list(range(4, 23)), + "5": [1, 2, 3, 23, 24], + "6": list(range(4, 23)), + "7": [1, 2, 3, 23, 24], + "8": list(range(4, 23)), + } + for key in collapse_lo.keys(): + if key == "1": + continue + # check matrix shape is uniform across all keys + arr = np.array(collapse_lo[f"{key}"]["matrix"]) + assert arr.shape == (32, 12) + + # check non-zero row indices match expected + non_zero_rows = np.where(arr.any(axis=1))[0].tolist() + if key in expected_lo_non_zero_rows: + assert non_zero_rows == expected_lo_non_zero_rows[key] + + # Test Lo aggregation separately as its structure is different + # instrument counts stores data as each variable in a separate key + key = "1" + for variable_name in collapse_lo[key]["variables"]: + arr = np.array(collapse_lo[key]["variables"][variable_name]) + assert arr.shape == (12,) + + hi_collapse = sci_lut[table_id]["collapse_hi"] + + # expected non-zero row indices for each collapse_hi matrix + # actual non-zero rows observed in the JSON collapse_hi matrices + expected_hi_non_zero_rows = { + # Tested Hi aggregated separately below + # "0": [0, 1, 2, 4, 5, 6, 9, 12, 13, 14, 15], + "1": [0, 1, 3, 4, 5, 7, 8, 9, 11, 12, 13, 15], + "2": [0, 1, 3, 4, 5, 7, 8, 9, 11, 12, 13, 15], + "4": [0, 1, 3, 4, 5, 7, 8, 9, 11, 12, 13, 15], + "7": [0, 1, 2, 3, 4, 5], + "9": [0, 1, 3, 4, 5, 7, 8, 9, 11, 12, 13, 15], + "10": [0, 1, 3, 4, 5, 7, 8, 9, 11, 12, 13, 15], + } + for key in hi_collapse.keys(): + if key == "0": + continue + arr = np.array(hi_collapse[f"{key}"]["matrix"]) + assert arr.shape == (16, 24) + non_zero_rows = np.where(arr.any(axis=1))[0].tolist() + if key in expected_hi_non_zero_rows: + assert non_zero_rows == expected_hi_non_zero_rows[key] + + # Test Hi aggregated separately as its structure is different + key = "0" + for variable_name in hi_collapse[key]["variables"]: + arr = np.array(hi_collapse[key]["variables"][variable_name]) + assert arr.shape == (24,) + + +def test_get_collapse_pattern_shape(codice_lut_path): + """Test collapse pattern shapes used to reshape data. + + Here, we expact the shape to be in this order: + (num_spin_sectors, num_positions) + """ + sci_lut_path = codice_lut_path(descriptor="l1a-sci-lut")[0] + + table_id = "3952862729" + sci_lut_data = json.loads(sci_lut_path.read_text()).get(table_id) + + # Lo instrument counts - singles + column_collapsed_example = get_collapse_pattern_shape( + sci_lut_data, + sensor_id=0, + collapse_table_id=2, + ) + assert column_collapsed_example == (6, 24) + + # Hi omni + aggre_counts = get_collapse_pattern_shape( + sci_lut_data, sensor_id=1, collapse_table_id=2 + ) + assert aggre_counts == (1,) + + # Hi aggregated counts + collapsed_row_example = get_counters_aggregated_pattern( + sci_lut_data, + sensor_id=1, + collapse_table_id=0, + ) + for variable in collapsed_row_example.keys(): + # All Hi aggregated variables should have + # collapsed to one column cell. + assert collapsed_row_example[variable] == 1 + # LoSW priority + row_collapsed_example = get_collapse_pattern_shape( + sci_lut_data, sensor_id=0, collapse_table_id=4 + ) + assert row_collapsed_example == (12, 1) + + # Lo SW angular + non_collapsed_example = get_collapse_pattern_shape( + sci_lut_data, sensor_id=0, collapse_table_id=7 + ) + assert non_collapsed_example == (12, 5) + + +def test_acquisition_time(codice_lut_path): + sci_lut_path = codice_lut_path(descriptor="l1a-sci-lut")[0] + sci_lut_data = json.loads(sci_lut_path.read_text()) + table_id = "3952862729" + low_stepping_tab = sci_lut_data[table_id]["lo_stepping_tab"] + acq_time_per_step = calculate_acq_time_per_step(low_stepping_tab) + expected_acq_times = ( + np.array( + [ + 578.70833333, + 578.70833333, + 578.70833333, + 578.70833333, + 289.35416667, + 289.35416667, + 289.35416667, + 289.35416667, + 289.35416667, + 289.35416667, + 289.35416667, + 289.35416667, + 192.90277778, + 192.90277778, + 192.90277778, + 192.90277778, + 192.90277778, + 192.90277778, + 192.90277778, + 192.90277778, + 192.90277778, + 192.90277778, + 192.90277778, + 192.90277778, + 144.67708333, + 144.67708333, + 144.67708333, + 144.67708333, + 144.67708333, + 144.67708333, + 144.67708333, + 144.67708333, + 144.67708333, + 144.67708333, + 144.67708333, + 144.67708333, + 144.67708333, + 144.67708333, + 144.67708333, + 144.67708333, + 115.74166667, + 115.74166667, + 115.74166667, + 115.74166667, + 115.74166667, + 115.74166667, + 115.74166667, + 115.74166667, + 115.74166667, + 115.74166667, + 115.74166667, + 115.74166667, + 115.74166667, + 115.74166667, + 115.74166667, + 115.74166667, + 115.74166667, + 115.74166667, + 115.74166667, + 115.74166667, + 115.74166667, + 115.74166667, + 115.74166667, + 115.74166667, + 115.74166667, + 115.74166667, + 115.74166667, + 115.74166667, + 115.74166667, + 115.74166667, + 115.74166667, + 115.74166667, + 115.74166667, + 115.74166667, + 115.74166667, + 115.74166667, + 115.74166667, + 115.74166667, + 115.74166667, + 115.74166667, + 95.69438889, + 95.69438889, + 95.69438889, + 95.69438889, + 95.69438889, + 95.69438889, + 95.69438889, + 95.69438889, + 95.69438889, + 95.69438889, + 95.69438889, + 95.69438889, + 95.69438889, + 95.69438889, + 95.69438889, + 95.69438889, + 95.69438889, + 95.69438889, + 95.69438889, + 95.69438889, + 95.69438889, + 95.69438889, + 95.69438889, + 95.69438889, + 95.69438889, + 95.69438889, + 95.69438889, + 95.69438889, + 95.69438889, + 95.69438889, + 95.69438889, + 95.69438889, + 95.69438889, + 95.69438889, + 95.69438889, + 95.69438889, + 95.69438889, + 95.69438889, + 95.69438889, + 95.69438889, + 95.69438889, + 95.69438889, + 95.69438889, + 95.69438889, + 95.69438889, + 95.69438889, + 95.69438889, + 95.69438889, + ] + ) + / 1e3 + ) + np.testing.assert_allclose(acq_time_per_step, expected_acq_times, rtol=1e-5) diff --git a/imap_processing/tests/codice/test_codice_l1b.py b/imap_processing/tests/codice/test_codice_l1b.py index 81060c3b93..3c4532d8a4 100644 --- a/imap_processing/tests/codice/test_codice_l1b.py +++ b/imap_processing/tests/codice/test_codice_l1b.py @@ -1,63 +1,390 @@ """Tests the L1b processing for CoDICE L1a data""" +from unittest.mock import patch + +import numpy as np import pytest -import xarray as xr +from imap_data_access import ProcessingInputCollection +from imap_processing import imap_module_directory +from imap_processing.cdf.utils import load_cdf, write_cdf +from imap_processing.codice.codice_l1a import process_l1a from imap_processing.codice.codice_l1b import process_codice_l1b - -from .conftest import TEST_L1A_FILES +from imap_processing.tests.codice.conftest import ( + VALIDATION_FILE_DATE, + VALIDATION_FILE_VERSION, +) pytestmark = pytest.mark.external_test_data -EXPECTED_LOGICAL_SOURCES = [ - "imap_codice_l1b_hi-counters-aggregated", - "imap_codice_l1b_hi-counters-singles", - "imap_codice_l1b_hi-ialirt", - "imap_codice_l1b_hi-omni", - "imap_codice_l1b_hi-priority", - "imap_codice_l1b_hi-sectored", - "imap_codice_l1b_hskp", - "imap_codice_l1b_lo-counters-aggregated", - "imap_codice_l1b_lo-counters-singles", - "imap_codice_l1b_lo-ialirt", - "imap_codice_l1b_lo-nsw-angular", - "imap_codice_l1b_lo-nsw-priority", - "imap_codice_l1b_lo-nsw-species", - "imap_codice_l1b_lo-sw-angular", - "imap_codice_l1b_lo-sw-priority", - "imap_codice_l1b_lo-sw-species", +TIME_MISMATCHES = [ + "voltage_table", # many products + "epoch_delta_plus", # many products + "epoch_delta_minus", # many products ] -@pytest.fixture(params=TEST_L1A_FILES) -def test_l1b_data(request) -> xr.Dataset: - """Return a ``xarray`` dataset containing test data. +@patch("imap_data_access.processing_input.ProcessingInputCollection.get_file_paths") +def test_l1b_lo_sw_species(mock_get_file_paths, codice_lut_path): + """Tests lo-sw-species.""" - Returns - ------- - dataset : xr.Dataset - A ``xarray`` dataset containing the test data - """ - dataset = process_codice_l1b(request.param) - return dataset + mock_get_file_paths.side_effect = [ + codice_lut_path(descriptor="lo-sw-species", data_type="l0"), + codice_lut_path(descriptor="l1a-sci-lut"), + ] + processed_l1a_file = write_cdf(process_l1a(ProcessingInputCollection())[0]) + l1b_val_data = ( + imap_module_directory + / "tests" + / "codice" + / "data" + / "l1b_validation" + / ( + f"imap_codice_l1b_lo-sw-species_{VALIDATION_FILE_DATE}" + f"_{VALIDATION_FILE_VERSION}.cdf" + ) + ) + l1b_val_data = load_cdf(l1b_val_data) + processed_data = process_codice_l1b(processed_l1a_file) + for variable in l1b_val_data.data_vars: + np.testing.assert_allclose( + processed_data[variable].values, + l1b_val_data[variable].values, + rtol=1e-5, + err_msg=f"Mismatch in variable '{variable}'", + ) + for variable in l1b_val_data.coords: + if variable.endswith("_label"): + assert np.array_equal( + processed_data[variable].values, + l1b_val_data[variable].values, + ), f"Mismatch in coordinate '{variable}'" + continue + elif variable == "energy_table": + np.testing.assert_allclose( + processed_data["energy_per_charge"].values, + l1b_val_data[variable].values, + rtol=1e-5, + err_msg=f"Mismatch in variable '{variable}'", + ) + continue + np.testing.assert_allclose( + processed_data[variable].values, + l1b_val_data[variable].values, + rtol=1e-5, + err_msg=f"Mismatch in coordinate '{variable}'", + ) -@pytest.mark.parametrize( - "test_l1b_data, expected_logical_source", - list(zip(TEST_L1A_FILES, EXPECTED_LOGICAL_SOURCES, strict=False)), - indirect=["test_l1b_data"], -) -def test_l1b_logical_sources(test_l1b_data: xr.Dataset, expected_logical_source: str): - """Tests that the ``process_codice_l1b`` function generates datasets - with the expected logical source. - - Parameters - ---------- - test_l1b_data : xr.Dataset - A ``xarray`` dataset containing the test data - expected_logical_source : str - The expected CDF filename - """ - - dataset = test_l1b_data - assert dataset.attrs["Logical_source"] == expected_logical_source + # Write to CDF + processed_data.attrs["Data_version"] = "002" + cdf_file = write_cdf(processed_data, terminate_on_warning=True) + assert ( + cdf_file.name + == f"imap_codice_l1b_lo-sw-species_{VALIDATION_FILE_DATE}_v002.cdf" + ) + + +@patch("imap_data_access.processing_input.ProcessingInputCollection.get_file_paths") +def test_l1b_hi_omni(mock_get_file_paths, codice_lut_path): + mock_get_file_paths.side_effect = [ + codice_lut_path(descriptor="hi-omni", data_type="l0"), + codice_lut_path(descriptor="l1a-sci-lut"), + ] + + l1a_file_path = write_cdf(process_l1a(dependency=ProcessingInputCollection())[0]) + val_path = ( + imap_module_directory + / "tests/codice/data/l1b_validation/" + / f"imap_codice_l1b_hi-omni_{VALIDATION_FILE_DATE}" + f"_{VALIDATION_FILE_VERSION}.cdf" + ) + val_data = load_cdf(val_path) + processed_data = process_codice_l1b(file_path=l1a_file_path) + # hi-omni has species-specific shapes + for variable in val_data.data_vars: + assert processed_data[variable].shape == val_data[variable].shape + np.testing.assert_allclose( + processed_data[variable].values, + val_data[variable].values, + rtol=1.5e-5, + err_msg=f"Mismatch in variable '{variable}'", + ) + + cdf_file = write_cdf(processed_data) + assert cdf_file.name == f"imap_codice_l1b_hi-omni_{VALIDATION_FILE_DATE}_v999.cdf" + + +@pytest.mark.xfail(reason="Need to revisit in future PR") +@patch("imap_data_access.processing_input.ProcessingInputCollection.get_file_paths") +def test_l1b_hi_sectored(mock_get_file_paths, codice_lut_path): + mock_get_file_paths.side_effect = [ + codice_lut_path(descriptor="hi-sectored", data_type="l0"), + codice_lut_path(descriptor="l1a-sci-lut"), + ] + val_path = ( + imap_module_directory + / "tests/codice/data/l1b_validation/" + / f"imap_codice_l1b_hi-sectored_{VALIDATION_FILE_DATE}" + f"_{VALIDATION_FILE_VERSION}.cdf" + ) + l1a_file_path = write_cdf(process_l1a(dependency=ProcessingInputCollection())[0]) + val_data = load_cdf(val_path) + processed_data = process_codice_l1b(file_path=l1a_file_path) + for variable in val_data.data_vars: + np.testing.assert_allclose( + processed_data[variable].values, + val_data[variable].values, + rtol=1.2e-5, + err_msg=f"Mismatch in variable '{variable}'", + ) + + cdf_file = write_cdf(processed_data) + assert ( + cdf_file.name == f"imap_codice_l1b_hi-sectored_{VALIDATION_FILE_DATE}_v999.cdf" + ) + + +@patch("imap_data_access.processing_input.ProcessingInputCollection.get_file_paths") +def test_l1b_hi_priorities(mock_get_file_paths, codice_lut_path): + mock_get_file_paths.side_effect = [ + codice_lut_path(descriptor="hi-priorities", data_type="l0"), + codice_lut_path(descriptor="l1a-sci-lut"), + ] + val_path = ( + imap_module_directory + / "tests/codice/data/l1b_validation/" + / f"imap_codice_l1b_hi-priority_{VALIDATION_FILE_DATE}" + f"_{VALIDATION_FILE_VERSION}.cdf" + ) + l1a_ds = process_l1a(ProcessingInputCollection())[0] + l1a_file_path = write_cdf(l1a_ds) + val_data = load_cdf(val_path) + processed_data = process_codice_l1b(file_path=l1a_file_path) + for variable in val_data.data_vars: + np.testing.assert_allclose( + processed_data[variable].values, + val_data[variable].values, + rtol=1.2e-5, + err_msg=f"Mismatch in variable '{variable}'", + ) + + cdf_file = write_cdf(processed_data) + assert ( + cdf_file.name == f"imap_codice_l1b_hi-priority_{VALIDATION_FILE_DATE}_v999.cdf" + ) + + +@patch("imap_data_access.processing_input.ProcessingInputCollection.get_file_paths") +def test_l1b_nsw_lo_priorities(mock_get_file_paths, codice_lut_path): + mock_get_file_paths.side_effect = [ + codice_lut_path(descriptor="lo-nsw-priority", data_type="l0"), + codice_lut_path(descriptor="l1a-sci-lut"), + ] + val_path = ( + imap_module_directory + / "tests/codice/data/l1b_validation/" + / f"imap_codice_l1b_lo-nsw-priority_{VALIDATION_FILE_DATE}" + f"_{VALIDATION_FILE_VERSION}.cdf" + ) + l1a_ds = process_l1a(ProcessingInputCollection())[0] + l1a_file_path = write_cdf(l1a_ds) + val_data = load_cdf(val_path) + processed_data = process_codice_l1b(file_path=l1a_file_path) + for variable in val_data.data_vars: + np.testing.assert_allclose( + processed_data[variable].values, + val_data[variable].values, + rtol=1e-5, + err_msg=f"Mismatch in variable '{variable}'", + ) + + cdf_file = write_cdf(processed_data) + assert ( + cdf_file.name + == f"imap_codice_l1b_lo-nsw-priority_{VALIDATION_FILE_DATE}_v999.cdf" + ) + + +@patch("imap_data_access.processing_input.ProcessingInputCollection.get_file_paths") +def test_l1b_sw_lo_priorities(mock_get_file_paths, codice_lut_path): + mock_get_file_paths.side_effect = [ + codice_lut_path(descriptor="lo-sw-priority", data_type="l0"), + codice_lut_path(descriptor="l1a-sci-lut"), + ] + val_path = ( + imap_module_directory + / "tests/codice/data/l1b_validation/" + / f"imap_codice_l1b_lo-sw-priority_{VALIDATION_FILE_DATE}" + f"_{VALIDATION_FILE_VERSION}.cdf" + ) + l1a_ds = process_l1a(ProcessingInputCollection())[0] + l1a_file_path = write_cdf(l1a_ds) + val_data = load_cdf(val_path) + processed_data = process_codice_l1b(file_path=l1a_file_path) + for variable in val_data.data_vars: + np.testing.assert_allclose( + processed_data[variable].values, + val_data[variable].values, + rtol=1e-5, + err_msg=f"Mismatch in variable '{variable}'", + ) + + cdf_file = write_cdf(processed_data) + assert ( + cdf_file.name + == f"imap_codice_l1b_lo-sw-priority_{VALIDATION_FILE_DATE}_v999.cdf" + ) + + +@patch("imap_data_access.processing_input.ProcessingInputCollection.get_file_paths") +def test_l1b_lo_counters_aggregated(mock_get_file_paths, codice_lut_path): + """Tests l1b lo-counters-aggregated.""" + mock_get_file_paths.side_effect = [ + codice_lut_path(descriptor="lo-counters-aggregated", data_type="l0"), + codice_lut_path(descriptor="l1a-sci-lut"), + ] + + l1a_data = process_l1a(dependency=ProcessingInputCollection())[0] + l1a_file_path = write_cdf(l1a_data) + processed_data = process_codice_l1b(file_path=l1a_file_path) + # Validation + val_path = ( + imap_module_directory + / "tests/codice/data/l1b_validation/" + / ( + f"imap_codice_l1b_lo-counters-aggregated_{VALIDATION_FILE_DATE}" + f"_{VALIDATION_FILE_VERSION}.cdf" + ) + ) + val_data = load_cdf(val_path) + for variable in val_data.data_vars: + # TODO ask Joey about these variables. E.g. tof_only + if val_data[variable].values.size == 0: + continue + np.testing.assert_allclose( + processed_data[variable].values, + val_data[variable].values, + rtol=1e-5, + err_msg=f"Mismatch in variable '{variable}'", + ) + + processed_data.attrs["Data_version"] = "001" + cdf_file = write_cdf(processed_data, terminate_on_warning=True) + assert ( + cdf_file.name + == f"imap_codice_l1b_lo-counters-aggregated_{VALIDATION_FILE_DATE}_v001.cdf" + ) + + +@patch("imap_data_access.processing_input.ProcessingInputCollection.get_file_paths") +def test_l1b_hi_counters_aggregated(mock_get_file_paths, codice_lut_path): + """Tests l1b lo-counters-aggregated.""" + mock_get_file_paths.side_effect = [ + codice_lut_path(descriptor="hi-counters-aggregated", data_type="l0"), + codice_lut_path(descriptor="l1a-sci-lut"), + ] + + l1a_data = process_l1a(dependency=ProcessingInputCollection())[0] + l1a_file_path = write_cdf(l1a_data) + processed_data = process_codice_l1b(file_path=l1a_file_path) + # Validation + val_path = ( + imap_module_directory + / "tests/codice/data/l1b_validation/" + / ( + f"imap_codice_l1b_hi-counters-aggregated_{VALIDATION_FILE_DATE}" + f"_{VALIDATION_FILE_VERSION}.cdf" + ) + ) + val_data = load_cdf(val_path) + for variable in val_data.data_vars: + np.testing.assert_allclose( + processed_data[variable].values, + val_data[variable].values, + rtol=1.2e-5, + err_msg=f"Mismatch in variable '{variable}'", + ) + + processed_data.attrs["Data_version"] = "001" + cdf_file = write_cdf(processed_data, terminate_on_warning=True) + assert ( + cdf_file.name + == f"imap_codice_l1b_hi-counters-aggregated_{VALIDATION_FILE_DATE}_v001.cdf" + ) + + +@patch("imap_data_access.processing_input.ProcessingInputCollection.get_file_paths") +def test_lo_counters_singles(mock_get_file_paths, codice_lut_path): + """Tests l1b lo-counters-singles.""" + mock_get_file_paths.side_effect = [ + codice_lut_path(descriptor="lo-counters-singles", data_type="l0"), + codice_lut_path(descriptor="l1a-sci-lut"), + ] + + l1a_data = process_l1a(dependency=ProcessingInputCollection())[0] + l1a_file_path = write_cdf(l1a_data) + processed_data = process_codice_l1b(file_path=l1a_file_path) + + # Validation + val_path = ( + imap_module_directory + / "tests/codice/data/l1b_validation/" + / ( + f"imap_codice_l1b_lo-counters-singles_{VALIDATION_FILE_DATE}" + f"_{VALIDATION_FILE_VERSION}.cdf" + ) + ) + val_data = load_cdf(val_path) + for variable in val_data.data_vars: + np.testing.assert_allclose( + processed_data[variable].values, + val_data[variable].values, + rtol=1e-5, + err_msg=f"Mismatch in variable '{variable}'", + ) + + processed_data.attrs["Data_version"] = "001" + cdf_file = write_cdf(processed_data, terminate_on_warning=True) + assert ( + cdf_file.name + == f"imap_codice_l1b_lo-counters-singles_{VALIDATION_FILE_DATE}_v001.cdf" + ) + + +@patch("imap_data_access.processing_input.ProcessingInputCollection.get_file_paths") +def test_hi_counters_singles(mock_get_file_paths, codice_lut_path): + """Tests l1b hi-counters-singles.""" + mock_get_file_paths.side_effect = [ + codice_lut_path(descriptor="hi-counters-singles", data_type="l0"), + codice_lut_path(descriptor="l1a-sci-lut"), + ] + + l1a_data = process_l1a(dependency=ProcessingInputCollection())[0] + l1a_file_path = write_cdf(l1a_data) + processed_data = process_codice_l1b(file_path=l1a_file_path) + + # Validation + val_path = ( + imap_module_directory + / "tests/codice/data/l1b_validation/" + / ( + f"imap_codice_l1b_hi-counters-singles_{VALIDATION_FILE_DATE}" + f"_{VALIDATION_FILE_VERSION}.cdf" + ) + ) + val_data = load_cdf(val_path) + for variable in val_data.data_vars: + np.testing.assert_allclose( + processed_data[variable].values, + val_data[variable].values, + rtol=1.2e-5, + err_msg=f"Mismatch in variable '{variable}'", + ) + + processed_data.attrs["Data_version"] = "001" + cdf_file = write_cdf(processed_data, terminate_on_warning=True) + assert ( + cdf_file.name + == f"imap_codice_l1b_hi-counters-singles_{VALIDATION_FILE_DATE}_v001.cdf" + ) diff --git a/imap_processing/tests/codice/test_codice_l2.py b/imap_processing/tests/codice/test_codice_l2.py index befcadb678..86e356e4d3 100644 --- a/imap_processing/tests/codice/test_codice_l2.py +++ b/imap_processing/tests/codice/test_codice_l2.py @@ -1,14 +1,37 @@ """Tests the L2 processing of CoDICE L1 data""" +from unittest import mock from unittest.mock import MagicMock, patch +import numpy as np +import pandas as pd import pytest import xarray as xr +from imap_data_access import AncillaryInput, ProcessingInputCollection +from sammi.validation import CDFValidator +from imap_processing import imap_module_directory from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes -from imap_processing.codice.codice_l2 import add_dataset_attributes, process_codice_l2 - -from .conftest import TEST_L2_FILES +from imap_processing.cdf.utils import load_cdf, write_cdf +from imap_processing.codice.codice_l1a import process_l1a +from imap_processing.codice.codice_l1b import process_codice_l1b +from imap_processing.codice.codice_l2 import ( + compute_geometric_factors, + get_efficiency_lut, + get_geometric_factor_lut, + get_hi_de_luts, + get_mpq_calc_energy_conversion_vals, + get_mpq_calc_tof_conversion_vals, + process_codice_l2, + process_lo_species_intensity, +) +from imap_processing.codice.constants import ( + LO_SW_SOLAR_WIND_SPECIES_VARIABLE_NAMES, +) +from imap_processing.tests.codice.conftest import ( + VALIDATION_FILE_DATE, + VALIDATION_FILE_VERSION, +) pytestmark = pytest.mark.external_test_data @@ -18,17 +41,26 @@ ] -@pytest.fixture(params=TEST_L2_FILES) -def test_l2_data(request) -> xr.Dataset: - """Return a ``xarray`` dataset containing test data. +@pytest.fixture +def processing_dependencies(codice_lut_path): + eff_file = "imap_codice_l2-lo-efficiency_20251008_v001.csv" + gf_file = "imap_codice_l2-lo-gfactor_20251008_v001.csv" + mpq_file = "imap_codice_lo-mpq-cal_20250101_v001.csv" + return ProcessingInputCollection( + AncillaryInput(gf_file), AncillaryInput(eff_file), AncillaryInput(mpq_file) + ) - Returns - ------- - dataset : xr.Dataset - A ``xarray`` dataset containing the test data - """ - dataset = process_codice_l2(request.param) - return dataset + +@pytest.fixture +def mock_get_file_paths(codice_lut_path): + with patch( + "imap_data_access.processing_input.ProcessingInputCollection.get_file_paths" + ) as mock_get_file_paths: + # Ensure the side effect treats science inputs as L1B for these L2 tests + mock_get_file_paths.side_effect = lambda descriptor, data_type=None: ( + codice_lut_path(descriptor, data_type="l1b") + ) + yield mock_get_file_paths @pytest.fixture @@ -45,62 +77,421 @@ def mock_cdf_attrs(): return cdf_attrs -@pytest.mark.parametrize( - "test_l2_data, expected_logical_source", - list(zip(TEST_L2_FILES, EXPECTED_LOGICAL_SOURCES, strict=False)), - indirect=["test_l2_data"], -) -def test_l2_logical_sources(test_l2_data: xr.Dataset, expected_logical_source: str): - """Tests that the ``process_codice_l2`` function generates datasets - with the expected logical source. - - Parameters - ---------- - test_l2_data : xr.Dataset - A ``xarray`` dataset containing the test data - expected_logical_source : str - The expected CDF filename +@pytest.fixture +def mock_half_spin_per_esa_step(): """ + Mock half_spin_per_esa_step for testing. + Example: + ESA steps 0–63 belong to half_spin=2 + ESA steps 64–127 belong to half_spin=3 + """ + half_spin_per_esa = np.repeat([2, 3], 64) + # repeat along epoch dimension to create shape (2, 128) for testing + return np.tile(half_spin_per_esa, (2, 1)) + + +def test_compute_geometric_factors_all_full_mode(mock_half_spin_per_esa_step): + # rgfo_half_spin = 4 means all half_spin values (2 or 3) are < rgfo_half_spin + dataset = xr.Dataset( + { + "rgfo_half_spin": (("epoch",), np.array([4, 4])), + "half_spin_per_esa_step": ( + ( + "epoch", + "esa_step", + ), + mock_half_spin_per_esa_step, + ), + }, + attrs={"Logical_file_id": "imap_codice_l1b_lo-sw-species_20250101_v001"}, + ) + geometric_factor_lut = { + "full": np.zeros((128, 24)), + "reduced": np.ones((128, 24)), + } + result = compute_geometric_factors(dataset, geometric_factor_lut) + + # Expect "full" values everywhere + expected = np.full((2, 128, 24), 0) + np.testing.assert_array_equal(result, expected) + + +def test_compute_geometric_factors_past_nov_24th(mock_half_spin_per_esa_step): + # rgfo_half_spin = 1 means all half_spin values (>=2) are >= rgfo_half_spin + # Although the rgfo_half_spin indicates reduced mode, the date is past Nov 24th, + # 2025 so we expect full mode to be used. + dataset = xr.Dataset( + { + "rgfo_half_spin": (("epoch",), np.array([1, 1])), + "half_spin_per_esa_step": ( + ( + "epoch", + "esa_step", + ), + mock_half_spin_per_esa_step, + ), + }, + # Make sure epoch is past Nov 24th, 2025 + attrs={"Logical_file_id": "imap_codice_l1b_lo-sw-species_20251125_v001"}, + ) + geometric_factor_lut = { + "full": np.zeros((128, 24)), + "reduced": np.ones((128, 24)), + } + result = compute_geometric_factors(dataset, geometric_factor_lut) + + # Expect "full" values everywhere + expected = np.full((2, 128, 24), 0) + np.testing.assert_array_equal(result, expected) + + +def test_compute_geometric_factors_all_reduced_mode(mock_half_spin_per_esa_step): + # rgfo_half_spin = 1 means all half_spin values (>=2) are >= rgfo_half_spin + dataset = xr.Dataset( + { + "rgfo_half_spin": (("epoch",), np.array([1])), + "half_spin_per_esa_step": ( + ( + "epoch", + "esa_step", + ), + mock_half_spin_per_esa_step[0:1], + ), + }, + attrs={"Logical_file_id": "imap_codice_l1b_lo-sw-species_20250101_v001"}, + ) + geometric_factor_lut = { + "full": np.zeros((128, 24)), + "reduced": np.ones((128, 24)), + } + result = compute_geometric_factors(dataset, geometric_factor_lut) + + # Expect "reduced" values everywhere + expected = np.full((1, 128, 24), 1) + np.testing.assert_array_equal(result, expected) + + +def test_compute_geometric_factors_mixed(mock_half_spin_per_esa_step): + # rgfo_half_spin = 2 + dataset = xr.Dataset( + { + "rgfo_half_spin": (("epoch",), np.array([2])), + "half_spin_per_esa_step": ( + ( + "epoch", + "esa_step", + ), + mock_half_spin_per_esa_step[0:1], + ), + }, + attrs={"Logical_file_id": "imap_codice_l1b_lo-sw-species_20250101_v001"}, + ) + geometric_factor_lut = { + "full": np.zeros((128, 24)), + "reduced": np.ones((128, 24)), + } + result = compute_geometric_factors(dataset, geometric_factor_lut) - dataset = test_l2_data + # ESA steps 0-63 (half_spin=1) -> 2 > 1 β†’ mode=full β†’ 1 + # ESA steps 64-127 (half_spin=2) -> 1 !>1 β†’ mode=reduced β†’ 0 + expected = np.repeat(np.array([[[0]] * 64 + [[1]] * 64]), 24, -1) + np.testing.assert_array_equal(result, expected) - assert dataset.attrs["Logical_source"] == expected_logical_source +def test_get_geometric_factor_lut(processing_dependencies, mock_get_file_paths): + gfactor_lut = get_geometric_factor_lut(processing_dependencies) -def test_add_dataset_attributes(mock_cdf_attrs): - dataset_name = "imap_codice_l2_test-product" + # Load the csv files directly to compare + geometric_factors = pd.read_csv( + processing_dependencies.get_file_paths("l2-lo-gfactor")[0] + ) + full = ( + geometric_factors[geometric_factors["mode"] == "full"] + .drop(["mode", "esa_step"], axis=1) + .to_numpy() + ) + reduced = ( + geometric_factors[geometric_factors["mode"] == "reduced"] + .drop(["mode", "esa_step"], axis=1) + .to_numpy() + ) + + # Test the shape is (modes, esa_steps, positions) + np.testing.assert_array_equal(gfactor_lut["full"].shape, (128, 24)) + + np.testing.assert_array_equal(gfactor_lut["full"], full) + np.testing.assert_array_equal(gfactor_lut["reduced"], reduced) + + +def test_get_efficiency_lut(processing_dependencies, mock_get_file_paths): + efficiency_lut = get_efficiency_lut(processing_dependencies) + expected_colnames = ["esa_step", "product", "species"] + [ + f"position_{x}" for x in range(1, 25) + ] + + for col in expected_colnames: + assert col in efficiency_lut.columns, f"Missing column {col} in efficiency LUT" + + +def test_get_tof_ns_from_mpq_lut(processing_dependencies, mock_get_file_paths): + tof_ns = get_mpq_calc_tof_conversion_vals(processing_dependencies) + assert tof_ns.shape == (1024,) + mpq_calc_lut_file = processing_dependencies.get_file_paths( + descriptor="l2-lo-onboard-mpq-cal" + )[0] + mpq_df = pd.read_csv(mpq_calc_lut_file, header=None) + expected_tof_ns = mpq_df.loc[6:, 1].to_numpy().astype(np.float64) + # Calculated values should be more precise than LUT but should be close + np.testing.assert_allclose(tof_ns, expected_tof_ns, atol=1e-5) + + +def test_get_energy_kev_from_mpq_lut(processing_dependencies, mock_get_file_paths): + energy_kev = get_mpq_calc_energy_conversion_vals(processing_dependencies) + assert energy_kev.shape == (128,) + mpq_calc_lut_file = processing_dependencies.get_file_paths( + descriptor="l2-lo-onboard-mpq-cal" + )[0] + mpq_df = pd.read_csv(mpq_calc_lut_file, header=None) + expected_e_kev = mpq_df.loc[5, 4:].to_numpy().astype(np.float64) + # Calculated values should be more precise than LUT but should be close + np.testing.assert_allclose(energy_kev, expected_e_kev, rtol=0.01) + + +def test_get_hi_de_luts(processing_dependencies, mock_get_file_paths): + # Mock get_file_paths to return specific files for hi-energy-table and hi-tof-table + energy_table, tof_table = get_hi_de_luts(processing_dependencies) + assert energy_table.shape == (2048, 48) + assert tof_table.shape == (1024, 2) + + +def test_process_lo_species_intensity(mock_get_file_paths, codice_lut_path): + mock_get_file_paths.side_effect = [ + codice_lut_path(descriptor="lo-sw-species", data_type="l0"), + codice_lut_path(descriptor="l1a-sci-lut"), + ] + processed_l1a_file = write_cdf(process_l1a(ProcessingInputCollection())[0]) + l1b_data = process_codice_l1b(processed_l1a_file) + l1b_val_data_processed = l1b_data.copy() + gf = xr.DataArray( + np.ones((len(l1b_data.epoch), 128, 24)) * 2, + dims=("epoch", "esa_step", "inst_az"), + ) + with mock.patch( + "imap_processing.codice.codice_l2.get_species_efficiency", + return_value=xr.DataArray(np.ones((128, 24)) * 2, dims=("esa_step", "inst_az")), + ): + len_pos = 5 + process_lo_species_intensity( + l1b_val_data_processed, + LO_SW_SOLAR_WIND_SPECIES_VARIABLE_NAMES, + gf, + None, + list(np.arange(0, len_pos)), + ) - # Create a sample xarray.Dataset - sample_dataset = xr.Dataset( + for var in LO_SW_SOLAR_WIND_SPECIES_VARIABLE_NAMES: + assert var in l1b_val_data_processed, f"Missing variable {var} after processing" + # Check that values are non-negative + assert np.all(l1b_val_data_processed[var].values >= 0), ( + f"Variable {var} contains negative values" + ) + # Check that values match expected calculation + expected_intensity = ( + l1b_data[var] + / (len_pos * 4 * l1b_data["energy_per_charge"].data)[ + np.newaxis, :, np.newaxis + ] + ) + np.testing.assert_allclose( + l1b_val_data_processed[var].values, expected_intensity.values, rtol=1e-5 + ) + + +def test_process_lo_missing_species_intensity(): + l1b_val_data = xr.Dataset( { - "var1": (["dim1"], [1, 2, 3]), - "var2": (["dim1"], [4, 5, 6]), - "var3": (["dim1"], [7, 8, 9]), + "epoch": ("epoch", np.ones(5)), + "energy_per_charge": (("esa_step",), np.ones(128) * 10), + "packet_version": ("epoch", np.ones(5)), + "half_spin_per_esa_step": (("epoch", "esa_step"), np.ones((5, 128)) * 2), + "rgfo_half_spin": ("epoch", np.ones(5) * 2), } ) - # Patch the logger to capture error messages - with patch("imap_processing.codice.codice_l2.logger") as mock_logger: - # Call the function - updated_dataset = add_dataset_attributes( - sample_dataset, dataset_name, mock_cdf_attrs + l1b_val_data_processed = l1b_val_data.copy() + gf = xr.DataArray( + np.ones((len(l1b_val_data.epoch), 128, 24)) * 2, + dims=("epoch", "energy_per_charge", "inst_az"), + ) + with mock.patch( + "imap_processing.codice.codice_l2.get_species_efficiency", + return_value=xr.DataArray( + np.ones((128, 24)) * 2, dims=("energy_per_charge", "inst_az") + ), + ): + len_pos = 5 + with pytest.raises(ValueError, match="Species hplus not found in dataset"): + process_lo_species_intensity( + l1b_val_data_processed, + LO_SW_SOLAR_WIND_SPECIES_VARIABLE_NAMES, + gf, + None, + list(np.arange(0, len_pos)), + ) + + +@patch("imap_data_access.processing_input.ProcessingInputCollection.get_file_paths") +def test_codice_l2_sw_species_intensity(mock_get_file_paths, codice_lut_path): + mock_get_file_paths.side_effect = [ + codice_lut_path(descriptor="lo-sw-species", data_type="l0"), + codice_lut_path(descriptor="l1a-sci-lut"), + ] + processed_l1a_file = write_cdf(process_l1a(ProcessingInputCollection())[0]) + processed_l1b_file = write_cdf(process_codice_l1b(processed_l1a_file)) + # Mock get_files for l2 + mock_get_file_paths.side_effect = [ + [processed_l1b_file.as_posix()], + codice_lut_path(descriptor="l2-lo-gfactor"), + codice_lut_path(descriptor="l2-lo-efficiency"), + ] + processed_2_ds = process_codice_l2("lo-sw-species", ProcessingInputCollection()) + l2_val_data = ( + imap_module_directory + / "tests" + / "codice" + / "data" + / "l2_validation" + / ( + f"imap_codice_l2_lo-sw-species_{VALIDATION_FILE_DATE}" + f"_{VALIDATION_FILE_VERSION}.cdf" + ) + ) + l2_val_data = load_cdf(l2_val_data) + for variable in l2_val_data.data_vars: + processed_val = processed_2_ds[variable].values + # NOTE: Replace nan with 0 for comparison as the validation data uses 0 + processed_val[np.isnan(processed_val)] = 0.0 + np.testing.assert_allclose( + processed_val, + l2_val_data[variable].values, + rtol=1e-5, + err_msg=f"Mismatch in variable '{variable}'", + ) + processed_2_ds.attrs["Data_version"] = "001" + assert processed_2_ds.attrs["Logical_source"] == "imap_codice_l2_lo-sw-species" + write_cdf(processed_2_ds) + + +@patch("imap_data_access.processing_input.ProcessingInputCollection.get_file_paths") +def test_codice_l2_lo_de(mock_get_file_paths, codice_lut_path): + mock_get_file_paths.side_effect = [ + codice_lut_path(descriptor="lo-direct-events", data_type="l0") + ] + l1a_cdf = process_l1a(ProcessingInputCollection())[0] + + processed_l1a_file = write_cdf(l1a_cdf) + file_path = processed_l1a_file.as_posix() + # Mock get_files for l2 + mock_get_file_paths.side_effect = [ + [file_path], + [file_path], + codice_lut_path(descriptor="l2-lo-onboard-energy-table"), + codice_lut_path(descriptor="l2-lo-onboard-energy-bins"), + codice_lut_path(descriptor="l2-lo-onboard-mpq-cal"), + codice_lut_path(descriptor="l2-lo-onboard-mpq-cal"), + ] + + processed_l2_ds = process_codice_l2("lo-direct-events", ProcessingInputCollection()) + l2_val_data = ( + imap_module_directory + / "tests" + / "codice" + / "data" + / "l2_validation" + / ( + f"imap_codice_l2_lo-direct-events_{VALIDATION_FILE_DATE}" + f"_{VALIDATION_FILE_VERSION}.cdf" ) + ) - # Assert global attributes are updated - assert updated_dataset.attrs == {"global_attr_key": "global_attr_value"} + l2_val_data = load_cdf(l2_val_data) - # Assert variable attributes are updated + for variable in l2_val_data.data_vars: + if variable in ["spin_angle", "spin_sector"]: + # TODO remove this block when joey fixes spin_angle and spin_sector + # calculation. Currently they are not setting spin sector and spin angles + # to NaNs for invalid positions. + continue # skip spin_angle + if "label" in variable: + np.testing.assert_array_equal( + processed_l2_ds[variable].values, + l2_val_data[variable].values, + err_msg=f"Mismatch in variable '{variable}'", + ) + else: + np.testing.assert_allclose( + processed_l2_ds[variable].values, + l2_val_data[variable].values, + rtol=5e-5, + err_msg=f"Mismatch in variable '{variable}'", + equal_nan=True, + ) + processed_l2_ds.attrs["Data_version"] = "001" + assert processed_l2_ds.attrs["Logical_source"] == "imap_codice_l2_lo-direct-events" + file = write_cdf(processed_l2_ds) + errors = CDFValidator().validate(file) + assert not errors + load_cdf(file) - # var1 should get attributes directly - assert updated_dataset["var1"].attrs == {"attr1": "value1"} - # var2 should get attributes with product descriptor prefix (test-product) - assert updated_dataset["var2"].attrs == {"attr2": "value2"} +@patch("imap_data_access.processing_input.ProcessingInputCollection.get_file_paths") +def test_codice_l2_hi_de(mock_get_file_paths, codice_lut_path): + mock_get_file_paths.side_effect = [ + codice_lut_path(descriptor="hi-direct-events", data_type="l0") + ] + l1a_cdf = process_l1a(ProcessingInputCollection())[0] - # var3 should log an error since it doesn't have corresponding attributes - assert updated_dataset["var3"].attrs == {} + processed_l1a_file = write_cdf(l1a_cdf) + file_path = processed_l1a_file.as_posix() + # Mock get_files for l2 + mock_get_file_paths.side_effect = [ + [file_path], + [file_path], + codice_lut_path(descriptor="l2-hi-energy-table"), + codice_lut_path(descriptor="l2-hi-tof-table"), + ] - # Check logger error call for missing attributes - mock_logger.error.assert_called_with( - "Field 'var3' and 'test-product-var3' not found in attribute manager." + processed_l2_ds = process_codice_l2("hi-direct-events", ProcessingInputCollection()) + l2_val_data = ( + imap_module_directory + / "tests" + / "codice" + / "data" + / "l2_validation" + / ( + f"imap_codice_l2_hi-direct-events_{VALIDATION_FILE_DATE}" + f"_{VALIDATION_FILE_VERSION}.cdf" ) + ) + l2_val_data = load_cdf(l2_val_data) + for variable in l2_val_data.data_vars: + if "label" in variable: + np.testing.assert_array_equal( + processed_l2_ds[variable].values, + l2_val_data[variable].values, + err_msg=f"Mismatch in variable '{variable}'", + ) + else: + np.testing.assert_allclose( + processed_l2_ds[variable].values, + l2_val_data[variable].values, + rtol=5e-5, + err_msg=f"Mismatch in variable '{variable}'", + ) + + processed_l2_ds.attrs["Data_version"] = "001" + assert processed_l2_ds.attrs["Logical_source"] == "imap_codice_l2_hi-direct-events" + file = write_cdf(processed_l2_ds) + errors = CDFValidator().validate(file) + assert not errors + load_cdf(file) diff --git a/imap_processing/tests/codice/test_decompress.py b/imap_processing/tests/codice/test_decompress.py index 83486b2174..f4081cb4c4 100644 --- a/imap_processing/tests/codice/test_decompress.py +++ b/imap_processing/tests/codice/test_decompress.py @@ -3,8 +3,10 @@ import lzma from enum import IntEnum +import numpy as np import pytest +from imap_processing.codice.codice_l1a_de import unpack_bits from imap_processing.codice.decompress import decompress from imap_processing.codice.utils import CoDICECompression @@ -48,3 +50,24 @@ def test_decompress_raises(): with pytest.raises(ValueError, match="some_unsupported_algorithm"): decompress("11101010", "some_unsupported_algorithm") + + +def test_unpack_bits(): + """Test that 64-bits is unpacked in LSB order correctly.""" + test_data = np.array([0x3, 0x9F], dtype=np.uint64) + bit_chunks = { + "c": {"bit_length": 52}, + "b": {"bit_length": 7}, + "a": {"bit_length": 5}, + } + + unpacked_fields = unpack_bits(bit_chunks, test_data) + expected_unpacked = { + "a": np.array([0, 0], dtype=np.uint64), + "b": np.array([0, 0], dtype=np.uint64), + "c": np.array([3, 159], dtype=np.uint64), + } + assert all( + np.array_equal(unpacked_fields[key], expected_unpacked[key]) + for key in bit_chunks + ) diff --git a/imap_processing/tests/conftest.py b/imap_processing/tests/conftest.py index a70096b6a7..9bae21b7b3 100644 --- a/imap_processing/tests/conftest.py +++ b/imap_processing/tests/conftest.py @@ -96,17 +96,17 @@ def _download_test_data(): _download_external_data() -def _download_external_data(): +def _download_external_data(external_test_data=EXTERNAL_TEST_DATA): """This fixture downloads externally-located test data files into a specific location. The list of files and their storage locations are specified in - the `test_data_paths` parameter, which is a list of tuples; the zeroth + the `external_test_data` parameter, which is a list of tuples; the zeroth element being the source of the test file in the AWS S3 bucket, and the first element being the location in which to store the downloaded file.""" logger = logging.getLogger(__name__) api_path = "https://api.dev.imap-mission.com/download/test_data/" - for source_filename, destination_path in EXTERNAL_TEST_DATA: + for source_filename, destination_path in external_test_data: source = api_path + source_filename destination = ( Path(f"{imap_module_directory}/tests") / destination_path / source_filename @@ -474,9 +474,9 @@ def imap_ena_sim_metakernel(furnish_kernels, _download_kernels): "naif0012.tls", "imap_spk_demo.bsp", "sim_1yr_imap_attitude.bc", - "imap_wkcp.tf", + "imap_130.tf", "de440s.bsp", - "imap_science_100.tf", + "imap_science_120.tf", "sim_1yr_imap_pointing_frame.bc", ] with furnish_kernels(kernels) as k: @@ -485,7 +485,7 @@ def imap_ena_sim_metakernel(furnish_kernels, _download_kernels): @pytest.fixture def imap_ialirt_sim_metakernel(furnish_kernels): - kernels = ["imap_wkcp.tf"] + kernels = ["imap_130.tf"] with furnish_kernels(kernels) as k: yield k diff --git a/imap_processing/tests/ena_maps/conftest.py b/imap_processing/tests/ena_maps/conftest.py index 785ab600a8..e6391c34ae 100644 --- a/imap_processing/tests/ena_maps/conftest.py +++ b/imap_processing/tests/ena_maps/conftest.py @@ -12,12 +12,14 @@ @pytest.fixture(scope="module") def ultra_l1c_pset_datasets(): """Make fake L1C Ultra PSET products on a HEALPix tiling for testing""" - l1c_nside = 32 + l1c_nside = 16 + counts_nside = 32 return { "nside": l1c_nside, "products": [ mock_l1c_pset_product_healpix( nside=l1c_nside, + counts_nside=counts_nside, stripe_center_lat=mid_latitude, width_scale=5, counts_scaling_params=(50, 0.5), @@ -49,3 +51,8 @@ def rectangular_l1c_pset_datasets(): for i, mid_latitude in enumerate(np.arange(-90, 90, 22.5)) ], } + + +@pytest.fixture(scope="session") +def ena_maps_test_data_path(imap_tests_path): + return imap_tests_path / "ena_maps" / "data" diff --git a/imap_processing/tests/ena_maps/data/imap_hi_90sensor-esa-eta-fit-factors_20240101_v001.csv b/imap_processing/tests/ena_maps/data/imap_hi_90sensor-esa-eta-fit-factors_20240101_v001.csv new file mode 100644 index 0000000000..ae89dc7446 --- /dev/null +++ b/imap_processing/tests/ena_maps/data/imap_hi_90sensor-esa-eta-fit-factors_20240101_v001.csv @@ -0,0 +1,10 @@ +esa_step,M0,M1,M2,M3,M4,M5 +1,1.0005,-0.017926,0.017878,-0.00079827,0.00021563,-0.000013949 +2,1.0005,-0.031794,0.017075,-0.0011034,0.00022,-0.000017474 +3,1.0006,-0.018905,0.018902,-0.0008856,0.00024955,-0.000017013 +4,1.0006,-0.018871,0.018889,-0.00088328,0.00024867,-0.000016911 +5,1.0006,-0.018531,0.018513,-0.00085172,0.00023603,-0.00001577 +6,1.0006,-0.018594,0.018616,-0.00085914,0.00023923,-0.000016041 +7,1.0006,-0.018668,0.018684,-0.0008653,0.00024159,-0.000016259 +8,1.0006,-0.018621,0.01864,-0.0008617,0.00024033,-0.000016151 +9,1.0006,-0.018605,0.018627,-0.00085998,0.0002395,-0.000016062 \ No newline at end of file diff --git a/imap_processing/tests/ena_maps/data/imap_lo_esa-eta-fit-factors_20240101_v001.csv b/imap_processing/tests/ena_maps/data/imap_lo_esa-eta-fit-factors_20240101_v001.csv new file mode 100644 index 0000000000..4fda625bab --- /dev/null +++ b/imap_processing/tests/ena_maps/data/imap_lo_esa-eta-fit-factors_20240101_v001.csv @@ -0,0 +1,8 @@ +esa_step,M0,M1,M2,M3,M4,M5 +1,1.0152,-0.047723,0.0304,-0.001817,0.0023649,-0.00032519 +2,1.0142,-0.045778,0.030061,-0.0020424,0.0021796,-0.00029036 +3,1.013,-0.045334,0.030649,-0.0021426,0.0021755,-0.0002869 +4,1.0109,-0.043671,0.029741,-0.0014197,0.0016756,-0.0002298 +5,1.0145,-0.045219,0.029705,-0.0021726,0.0020739,-0.0002652 +6,1.0116,-0.043433,0.030755,-0.0020747,0.001899,-0.0002476 +7,1.0156,-0.048728,0.029868,-0.0016762,0.0022885,-0.0003183 \ No newline at end of file diff --git a/imap_processing/tests/ena_maps/test_corrections.py b/imap_processing/tests/ena_maps/test_corrections.py new file mode 100644 index 0000000000..7ac0dff6cc --- /dev/null +++ b/imap_processing/tests/ena_maps/test_corrections.py @@ -0,0 +1,2169 @@ +"""Test coverage for ena_maps.corrections module.""" + +from unittest import mock + +import numpy as np +import pytest +import xarray as xr + +from imap_processing.cdf.utils import load_cdf +from imap_processing.ena_maps.ena_maps import HiPointingSet +from imap_processing.ena_maps.utils.coordinates import CoordNames +from imap_processing.ena_maps.utils.corrections import ( + PowerLawFluxCorrector, + _add_cartesian_look_direction, + _calculate_compton_getting_transform, + add_spacecraft_position_and_velocity_to_pset, + apply_compton_getting_correction, + calculate_ram_mask, + get_pset_directional_mask, + interpolate_map_flux_to_helio_frame, +) +from imap_processing.spice import geometry + + +@pytest.fixture +def hi_coeffs_file(ena_maps_test_data_path): + """Define the location of the hi coefficients file.""" + return ( + ena_maps_test_data_path + / "imap_hi_90sensor-esa-eta-fit-factors_20240101_v001.csv" + ) + + +@pytest.fixture +def lo_coeffs_file(ena_maps_test_data_path): + """Define the location of the hi coefficients file.""" + return ena_maps_test_data_path / "imap_lo_esa-eta-fit-factors_20240101_v001.csv" + + +class TestPowerLawFluxCorrector: + """Test suite for ena_maps.corrections.PowerLawFluxCorrector.""" + + def test_load_coefficients_invalid_file(self, tmp_path): + """Test that loading a missing CSV file raises FileNotFoundError.""" + + with pytest.raises(FileNotFoundError): + PowerLawFluxCorrector(tmp_path / "missing.csv") + + def test_eta_esa_non_negative(self, lo_coeffs_file): + """Test eta_esa will not return negative values.""" + + corr = PowerLawFluxCorrector(lo_coeffs_file) + k = np.array([1, 2]) + # Experimentally found that gamma=10 produces negative eta + gamma = np.array([1.5, 10]) + eta = corr.eta_esa(k, gamma) + assert eta[1] == 1 + + def test_estimate_power_law_with_uncertainties(self): + """Test slope estimation with flux uncertainties.""" + + # Create 2D arrays (n_energy, n_pixels) + fluxes = np.array([10, 20, 40, 80, 160, 320, 640])[:, np.newaxis] + energies = np.arange(7) + 1 + uncertainties = np.sqrt(fluxes) + gamma, delta_gamma = PowerLawFluxCorrector.estimate_power_law_slope( + fluxes, energies, uncertainties + ) + assert np.all(np.isfinite(gamma)) + assert delta_gamma is not None + assert np.all(delta_gamma > 0) + + def test_estimate_power_law_with_zero_flux(self): + """Test slope estimation falls back to linear differencing.""" + + # Create 2D arrays (n_energy, n_pixels) + fluxes = np.array([10, 0, 40, 60, 0, 0, 80])[:, np.newaxis] + uncertainties = np.maximum(0.1 * fluxes, 1) + expected_gamma = np.array( + [ + 0, # End point should fail to find slope + np.log(40 / 10) + / np.log(3 / 1), # Normal central differencing log-slope + np.log(60 / 40) + / np.log(4 / 3), # Fallback to forward linear differencing + np.log(60 / 40) + / np.log(4 / 3), # Fallback to backward linear differencing + 0, # No differencing scheme works + 0, # No differencing scheme works + 0, # End point fails to find slope + ] + )[:, np.newaxis] + expected_delta_gamma = np.array( + [ + 0, + np.sqrt(2 * (0.1**2)) / np.log(3 / 1), + np.sqrt(2 * (0.1**2)) / np.log(4 / 3), + np.sqrt(2 * (0.1**2)) / np.log(4 / 3), + 0, + 0, + 0, + ] + )[:, np.newaxis] + energies = np.arange(len(fluxes)) + 1 + corr = PowerLawFluxCorrector + gamma, delta_gamma = corr.estimate_power_law_slope( + fluxes, energies, uncertainties + ) + np.testing.assert_array_almost_equal(gamma, expected_gamma) + np.testing.assert_array_almost_equal(delta_gamma, expected_delta_gamma) + + def test_predictor_corrector_nonconvergence(self, lo_coeffs_file): + """Test predictor-corrector stops after max_iterations.""" + + corr = PowerLawFluxCorrector(lo_coeffs_file) + # Create 2D arrays (n_energy, n_pixels) + fluxes = ((np.ones(7) * 1000**2)[::-1])[:, np.newaxis] + energies = np.arange(1, 8) + 1 + _, _, n_iter = corr.predictor_corrector_iteration( + fluxes, + np.sqrt(fluxes), + energies, + max_iterations=3, + convergence_threshold=1e-12, + ) + assert np.all(n_iter == 3) + + def create_lo_test_data(self): + """Create synthetic Lo data to test.""" + # Test data matches data from MappingValidation_transforms_V02.xlsx + # Example data - 7 energy levels + energies = np.array([16.35, 30.56, 56.42, 105.21, 199.79, 407.49, 795.28]) # eV + + # Example observed fluxes + observed_fluxes = np.array([1000, 800, 50, 200, 1, 30, 10]) + delta_fluxes = np.sqrt(observed_fluxes) # Poisson uncertainties + sigma_fluxes = 0.1 * observed_fluxes # 10% systematic uncertainties + + # Example background fluxes (much smaller than signal) + background_fluxes = 0.01 * observed_fluxes + delta_background = np.sqrt(background_fluxes) + sigma_background = 0.15 * background_fluxes + + flux_dict = { + "J": observed_fluxes, + "delta_J": delta_fluxes, + "sigma_J": sigma_fluxes, + } + + background_dict = { + "J_B": background_fluxes, + "delta_J_B": delta_background, + "sigma_J_B": sigma_background, + } + + return energies, flux_dict, background_dict + + def create_hi_test_data(self): + """Create synthetic Hi data to test.""" + # Test data matches data from MappingValidation_Hi_transforms_V03.xlsx + # Example data - 9 energy levels + energies = ( + np.array([0.5, 0.75, 1.1, 1.65, 2.5, 3.75, 5.7, 8.52, 12.80]) * 1000 + ) # eV + + # Example observed fluxes + observed_fluxes = np.array([1000, 800, 50, 200, 1, 30, 10, 2, 5]) + delta_fluxes = np.sqrt(observed_fluxes) # Poisson uncertainties + sigma_fluxes = 0.1 * observed_fluxes # 10% systematic uncertainties + + # Example background fluxes (much smaller than signal) + background_fluxes = 0.01 * observed_fluxes + delta_background = np.sqrt(background_fluxes) + sigma_background = 0.15 * background_fluxes + + flux_dict = { + "J": observed_fluxes, + "delta_J": delta_fluxes, + "sigma_J": sigma_fluxes, + } + + background_dict = { + "J_B": background_fluxes, + "delta_J_B": delta_background, + "sigma_J_B": sigma_background, + } + + return energies, flux_dict, background_dict + + def test_predictor_corrector_lo_example(self, lo_coeffs_file): + """Test correction using sample data from Nathan's spreadsheet.""" + flux_corr = PowerLawFluxCorrector(lo_coeffs_file) + energies, flux_dict, background_dict = self.create_lo_test_data() + # Reshape to 2D arrays (n_energy, n_pixels) + corrected_fluxes, corrected_unc, _ = flux_corr.predictor_corrector_iteration( + flux_dict["J"][:, np.newaxis], flux_dict["delta_J"][:, np.newaxis], energies + ) + expected_corr_fluxes = np.array( + [ + 926.9339867, + 553.5811764, + 44.32189088, + 118.6296225, + 0.911160458, + 29.3853061, + 7.828285642, + ] + ) + np.testing.assert_allclose( + corrected_fluxes.squeeze(), expected_corr_fluxes, rtol=1e-2 + ) + + def test_predictor_corrector_hi_example(self, hi_coeffs_file): + """Test correction using sample data from Nathan's spreadsheet.""" + flux_corr = PowerLawFluxCorrector(hi_coeffs_file) + energies, flux_dict, background_dict = self.create_hi_test_data() + # Reshape to 2D arrays (n_energy, n_pixels) + corrected_fluxes, corrected_unc, _ = flux_corr.predictor_corrector_iteration( + flux_dict["J"][:, np.newaxis], flux_dict["delta_J"][:, np.newaxis], energies + ) + expected_corr_fluxes = np.array( + [ + 934.9348044, + 528.302229, + 44.47463759, + 111.0485641, + 0.915876546, + 27.96414141, + 7.587531207, + 1.96618265, + 4.782030232, + ] + ) + np.testing.assert_allclose( + corrected_fluxes.squeeze(), expected_corr_fluxes, rtol=1e-2 + ) + + def test_predictor_corrector_zero_flux_convergence(self, hi_coeffs_file): + """Test that convergence is achieved when we have a zero flux.""" + flux_corr = PowerLawFluxCorrector(hi_coeffs_file) + energies, flux_dict, background_dict = self.create_hi_test_data() + # set flux for ESA 9 to zero + flux_dict["J"][-1] = 0 + # Reshape to 2D arrays (n_energy, n_pixels) + _, _, n_iterations = flux_corr.predictor_corrector_iteration( + flux_dict["J"][:, np.newaxis], flux_dict["delta_J"][:, np.newaxis], energies + ) + assert np.all(n_iterations < 20) + + @mock.patch( + "imap_processing.ena_maps.utils.corrections.PowerLawFluxCorrector.predictor_corrector_iteration" + ) + def test_apply_flux_correction(self, mock_predictor_corrector, hi_coeffs_file): + """Test applying the correction to map data.""" + # Mock returns 2D arrays (n_energy, n_pixels) and n_iterations + mock_predictor_corrector.side_effect = lambda f, d_f, e: ( + f * 2, + d_f / 2, + np.zeros(f.shape[1], dtype=int), + ) + + # Create xarray DataArrays with energy dimension + flux_data = np.arange(90).reshape(9, 10) + delta_flux_data = np.sqrt(flux_data) + energies_data = np.arange(flux_data.shape[0]) + + flux = xr.DataArray( + flux_data, + dims=["energy", "spatial"], + coords={"energy": energies_data, "spatial": np.arange(10)}, + ) + delta_flux = xr.DataArray( + delta_flux_data, + dims=["energy", "spatial"], + coords={"energy": energies_data, "spatial": np.arange(10)}, + ) + energies = xr.DataArray( + energies_data, dims=["energy"], coords={"energy": energies_data} + ) + + flux_corr = PowerLawFluxCorrector(hi_coeffs_file) + corrected_flux, corrected_delta_flux = flux_corr.apply_flux_correction( + flux, delta_flux, energies + ) + + # Verify output is xarray DataArray with correct dimensions + assert isinstance(corrected_flux, xr.DataArray) + assert isinstance(corrected_delta_flux, xr.DataArray) + assert corrected_flux.dims == flux.dims + assert corrected_delta_flux.dims == delta_flux.dims + + # Verify values are correct + np.testing.assert_array_equal(corrected_flux.values, flux_data * 2) + np.testing.assert_array_equal(corrected_delta_flux.values, delta_flux_data / 2) + + def test_estimate_power_law_slope_multi_pixel(self): + """Test slope estimation with multiple spatial pixels (true 2D array).""" + # Create test data with 7 energy levels and 12 spatial pixels + # Shape: (n_energy=7, n_pixels=12) + n_energy = 7 + n_pixels = 12 + + # Create varying flux values across pixels + energies = np.arange(n_energy) + 1 + base_fluxes = np.array([10, 20, 40, 80, 160, 320, 640]) + + # Create 2D array where each pixel has slightly different flux scaling + fluxes = ( + base_fluxes[:, np.newaxis] * np.linspace(0.8, 1.2, n_pixels)[np.newaxis, :] + ) + uncertainties = np.sqrt(fluxes) + + gamma, delta_gamma = PowerLawFluxCorrector.estimate_power_law_slope( + fluxes, energies, uncertainties + ) + + # Check output shapes + assert gamma.shape == (n_energy, n_pixels) + assert delta_gamma.shape == (n_energy, n_pixels) + + # All slopes should be finite and non-zero for this simple power-law data + assert np.all(np.isfinite(gamma)) + assert np.all(np.isfinite(delta_gamma)) + + # All slopes should be positive (fluxes increase with energy) + assert np.all(gamma > 0) + assert np.all(delta_gamma > 0) + + def test_estimate_power_law_slope_with_zeros_multi_pixel(self): + """Test slope estimation with zero fluxes in multi-pixel array.""" + # Create test data with some zero fluxes at different locations per pixel + n_energy = 7 + n_pixels = 5 + + energies = np.arange(n_energy) + 1 + + # Create different zero patterns for each pixel + fluxes = np.array( + [ + [10, 0, 10, 10, 10], # energy 0: zero at pixel 1 + [20, 20, 0, 20, 20], # energy 1: zero at pixel 2 + [40, 40, 40, 0, 40], # energy 2: zero at pixel 3 + [60, 60, 60, 60, 0], # energy 3: zero at pixel 4 + [0, 0, 0, 0, 80], # energy 4: zeros at pixels 0-3 + [0, 80, 80, 80, 80], # energy 5: zero at pixel 0 + [80, 80, 80, 80, 80], # energy 6: no zeros + ] + ) + uncertainties = np.maximum(0.1 * fluxes, 1) + + gamma, delta_gamma = PowerLawFluxCorrector.estimate_power_law_slope( + fluxes, energies, uncertainties + ) + + # Check output shapes + assert gamma.shape == (n_energy, n_pixels) + assert delta_gamma.shape == (n_energy, n_pixels) + + # Where we have valid data on both sides, slopes should be non-zero + # Last energy level with all valid fluxes should have positive slopes + assert np.all(gamma[-1, :] >= 0) + + def test_predictor_corrector_multi_pixel(self, lo_coeffs_file): + """Test predictor-corrector with multiple spatial pixels.""" + corr = PowerLawFluxCorrector(lo_coeffs_file) + + # Create 2D array with 7 energy levels and 8 spatial pixels + energies = np.array([16.35, 30.56, 56.42, 105.21, 199.79, 407.49, 795.28]) + n_energy = len(energies) + n_pixels = 8 + + # Create base fluxes that vary across pixels + base_fluxes = np.array([1000, 800, 50, 200, 1, 30, 10]) + # base_fluxes = ((np.arange(n_energy) + 1) * 1000**2)[::-1] + fluxes = ( + base_fluxes[:, np.newaxis] * np.linspace(0.9, 1.1, n_pixels)[np.newaxis, :] + ) + uncertainties = np.sqrt(fluxes) + + corrected_fluxes, corrected_unc, n_iter = corr.predictor_corrector_iteration( + fluxes, + uncertainties, + energies, + max_iterations=20, + convergence_threshold=0.005, + ) + + # Check output shapes + assert corrected_fluxes.shape == (n_energy, n_pixels) + assert corrected_unc.shape == (n_energy, n_pixels) + assert n_iter.shape == (n_pixels,) + + # All pixels should converge + assert np.all(n_iter < 20) + assert np.all(n_iter > 0) + + # Corrected fluxes should be finite and positive + assert np.all(np.isfinite(corrected_fluxes)) + assert np.all(corrected_fluxes > 0) + + def test_apply_flux_correction_2d_spatial(self, hi_coeffs_file): + """Test applying correction to data with 2D spatial dimensions (like Lo).""" + flux_corr = PowerLawFluxCorrector(hi_coeffs_file) + + # Create xarray DataArrays with 2D spatial dimensions + # Shape: (energy=9, spin=36, elevation=4) - simulating Lo's structure + n_energy = 9 + n_spin = 36 + n_elev = 4 + + energies_data = np.arange(n_energy) + 1 + flux_data = np.random.rand(n_energy, n_spin, n_elev) * 1000 + 100 + delta_flux_data = np.sqrt(flux_data) + + flux = xr.DataArray( + flux_data, + dims=["energy", "spin", "elevation"], + coords={ + "energy": energies_data, + "spin": np.arange(n_spin), + "elevation": np.arange(n_elev), + }, + ) + delta_flux = xr.DataArray( + delta_flux_data, + dims=["energy", "spin", "elevation"], + coords={ + "energy": energies_data, + "spin": np.arange(n_spin), + "elevation": np.arange(n_elev), + }, + ) + energies = xr.DataArray( + energies_data, dims=["energy"], coords={"energy": energies_data} + ) + + # Apply correction + corrected_flux, corrected_unc = flux_corr.apply_flux_correction( + flux, delta_flux, energies + ) + + # Verify output has same dimensions and shape as input + assert corrected_flux.dims == flux.dims + assert corrected_unc.dims == delta_flux.dims + assert corrected_flux.shape == flux.shape + assert corrected_unc.shape == delta_flux.shape + + # Verify dimension order is preserved + assert corrected_flux.dims == ("energy", "spin", "elevation") + assert corrected_unc.dims == ("energy", "spin", "elevation") + + # Verify coordinates are preserved + np.testing.assert_array_equal(corrected_flux.coords["energy"], energies_data) + np.testing.assert_array_equal(corrected_flux.coords["spin"], np.arange(n_spin)) + np.testing.assert_array_equal( + corrected_flux.coords["elevation"], np.arange(n_elev) + ) + + # Corrected values should be finite and mostly positive + assert np.all(np.isfinite(corrected_flux)) + assert np.sum(corrected_flux > 0) > 0.9 * corrected_flux.size + + +@pytest.fixture +def hi_pset_cdf_path(imap_tests_path): + """Path to test Hi PSET CDF file.""" + return imap_tests_path / "hi/data/l1/imap_hi_l1c_45sensor-pset_20250415_v999.cdf" + + +@pytest.fixture +def mock_hi_pset(): + """Create a minimal mock Hi pointing set dataset for testing.""" + # Create a simple dataset with necessary fields + n_epoch = 1 + n_spin = 100 + + data = xr.Dataset( + { + "epoch": (["epoch"], np.array([797949131184000000])), + "epoch_delta": (["epoch"], np.array([1e12])), + "hae_longitude": ( + ["epoch", "spin_angle_bin"], + np.linspace(0, 360, n_spin, endpoint=False).reshape(n_epoch, n_spin), + ), + "hae_latitude": ( + ["epoch", "spin_angle_bin"], + np.linspace(-90, 90, n_spin).reshape(n_epoch, n_spin), + ), + "spin_angle_bin": (["spin_angle_bin"], np.arange(n_spin)), + }, + attrs={"Logical_source": "imap_hi_l1c_45sensor-pset"}, + ) + + return data + + +@pytest.fixture +def mock_lo_pset(): + """Create a minimal mock Lo pointing set dataset for testing.""" + # Create a simple dataset with necessary fields for Lo + n_epoch = 1 + n_spin = 50 + n_off = 20 + + data = xr.Dataset( + { + "epoch": (["epoch"], np.array([797949131184000000])), + "pointing_start_met": (["epoch"], np.array([100.0])), + "pointing_end_met": (["epoch"], np.array([200.0])), + "hae_longitude": ( + ["epoch", "spin_angle_bin", "off_angle_bin"], + np.linspace(0, 360, n_spin * n_off, endpoint=False).reshape( + n_epoch, n_spin, n_off + ), + ), + "hae_latitude": ( + ["epoch", "spin_angle_bin", "off_angle_bin"], + np.linspace(-90, 90, n_spin * n_off).reshape(n_epoch, n_spin, n_off), + ), + }, + attrs={"Logical_source": "imap_lo_l1c_pset"}, + ) + + return data + + +class TestComptonGettingCorrection: + """Test suite for Compton-Getting correction functions.""" + + @mock.patch("imap_processing.ena_maps.utils.corrections.ttj2000ns_to_et") + @mock.patch("imap_processing.ena_maps.utils.corrections.geometry.imap_state") + def test_add_spacecraft_position_and_velocity_to_pset( + self, mock_imap_state, mock_ttj2000_to_et, mock_hi_pset + ): + """Test that spacecraft position and velocity are correctly added to pset.""" + # Mock conversion from TTJ2000ns to ET + et = 1000.0 + mock_ttj2000_to_et.return_value = et + # Mock spacecraft state vector (position + velocity in HAE frame) + mock_sc_state = np.array([1e8, 2e8, 3e8, 10.0, 20.0, 30.0]) # km and km/s + mock_imap_state.return_value = mock_sc_state + + mock_hi_pset = add_spacecraft_position_and_velocity_to_pset(mock_hi_pset) + + # Verify SPICE was called correctly + mock_imap_state.assert_called_once_with( + et, ref_frame=geometry.SpiceFrame.IMAP_HAE + ) + + # Verify sc_velocity was added + assert "sc_velocity" in mock_hi_pset + assert isinstance(mock_hi_pset["sc_velocity"], xr.DataArray) + np.testing.assert_array_equal( + mock_hi_pset["sc_velocity"].values, np.array([10.0, 20.0, 30.0]) + ) + + # Verify sc_position was added + assert "sc_position" in mock_hi_pset + assert isinstance(mock_hi_pset["sc_position"], xr.DataArray) + np.testing.assert_array_equal( + mock_hi_pset["sc_position"].values, np.array([1e8, 2e8, 3e8]) + ) + + @mock.patch("imap_processing.ena_maps.utils.corrections.ttj2000ns_to_et") + @mock.patch("imap_processing.ena_maps.utils.corrections.geometry.imap_state") + def test_add_spacecraft_position_and_velocity_to_pset_lo( + self, mock_imap_state, mock_ttj2000_to_et, mock_lo_pset + ): + """Test that S/C position and velocity are correctly added to Lo pset.""" + # Mock conversion from TTJ2000ns to ET + et = 1000.0 + mock_ttj2000_to_et.return_value = et + # Mock spacecraft state vector (position + velocity in HAE frame) + mock_sc_state = np.array([1e8, 2e8, 3e8, 15.0, 25.0, 35.0]) # km and km/s + mock_imap_state.return_value = mock_sc_state + + # For Lo, pointing duration is calculated from MET times + # pointing_end_met - pointing_start_met = 200.0 - 100.0 = 100.0 seconds + # In nanoseconds: 100.0 * 1e9 = 1e11 ns + # Midpoint: epoch + pointing_duration_ns / 2 + expected_midpoint_time_ns = mock_lo_pset["epoch"].values[0] + 1e11 / 2 + + mock_lo_pset = add_spacecraft_position_and_velocity_to_pset(mock_lo_pset) + + # Verify SPICE was called correctly + mock_ttj2000_to_et.assert_called_once_with(expected_midpoint_time_ns) + mock_imap_state.assert_called_once_with( + et, ref_frame=geometry.SpiceFrame.IMAP_HAE + ) + + # Verify sc_velocity was added + assert "sc_velocity" in mock_lo_pset + assert isinstance(mock_lo_pset["sc_velocity"], xr.DataArray) + np.testing.assert_array_equal( + mock_lo_pset["sc_velocity"].values, np.array([15.0, 25.0, 35.0]) + ) + + # Verify sc_position was added + assert "sc_position" in mock_lo_pset + assert isinstance(mock_lo_pset["sc_position"], xr.DataArray) + np.testing.assert_array_equal( + mock_lo_pset["sc_position"].values, np.array([1e8, 2e8, 3e8]) + ) + + def test_add_spacecraft_position_and_velocity_unsupported_instrument(self): + """Test that unsupported instrument raises NotImplementedError.""" + # Create a dataset with unsupported Logical_source + unsupported_pset = xr.Dataset( + { + "epoch": (["epoch"], np.array([797949131184000000])), + "epoch_delta": (["epoch"], np.array([1e12])), + }, + attrs={"Logical_source": "imap_unsupported_instrument_pset"}, + ) + + with pytest.raises(NotImplementedError, match="does not support PSETs"): + add_spacecraft_position_and_velocity_to_pset(unsupported_pset) + + def test_add_spacecraft_position_and_velocity_zero_duration(self, mock_hi_pset): + """Test that zero pointing duration sets pos and velocity to zero vectors.""" + # Set epoch_delta to zero to simulate an empty/filtered pointing set + mock_hi_pset["epoch_delta"] = xr.DataArray(np.array([0.0]), dims=["epoch"]) + + result = add_spacecraft_position_and_velocity_to_pset(mock_hi_pset) + + # Both sc_velocity and sc_position should be zero vectors + np.testing.assert_array_equal(result["sc_velocity"].values, np.zeros(3)) + np.testing.assert_array_equal(result["sc_position"].values, np.zeros(3)) + + def test_add_cartesian_look_direction(self, mock_hi_pset): + """Test that look directions are correctly calculated and added.""" + mock_hi_pset = _add_cartesian_look_direction(mock_hi_pset) + + # _add_cartesian_look_direction is just a wrapper around + # geometry.spherical_to_cartesian. We only need to test that the + # look_direction variable was added and has the correct shape. + # Verify look_direction was added + assert "look_direction" in mock_hi_pset + assert isinstance(mock_hi_pset["look_direction"], xr.DataArray) + + # Verify shape + expected_shape = (1, 100, 3) # (epoch, spin_angle_bin, x_y_z) + assert mock_hi_pset["look_direction"].shape == expected_shape + + @mock.patch("imap_processing.ena_maps.utils.corrections.geometry.imap_state") + def test_calculate_compton_getting_transform(self, mock_imap_state, mock_hi_pset): + """Test Compton-Getting transformation calculations.""" + # Set up spacecraft velocity + mock_sc_state = np.array([1e8, 2e8, 3e8, 10.0, 20.0, 30.0]) + mock_imap_state.return_value = mock_sc_state + + mock_hi_pset = add_spacecraft_position_and_velocity_to_pset(mock_hi_pset) + mock_hi_pset = _add_cartesian_look_direction(mock_hi_pset) + + # Create energy array + energy_hf = xr.DataArray( + np.array([500.0, 1000.0, 2000.0]), + dims=["esa_energy_step"], + coords={"esa_energy_step": [1, 2, 3]}, + ) + + mock_hi_pset = _calculate_compton_getting_transform(mock_hi_pset, energy_hf) + + # Verify required variables were added + assert "energy_hf" in mock_hi_pset + assert "energy_sc" in mock_hi_pset + assert "hae_longitude" in mock_hi_pset + assert "hae_latitude" in mock_hi_pset + + # Verify energy_hf matches input + np.testing.assert_array_equal( + mock_hi_pset["energy_hf"].values, energy_hf.values + ) + + # Verify energy_sc has correct shape + # The transformation should broadcast across energy and spatial dimensions + assert "energy_sc" in mock_hi_pset + energy_sc = mock_hi_pset["energy_sc"] + # Shape should include energy dimension + assert len(energy_sc.dims) >= 2 + + # Verify energy_sc values are positive and reasonable + assert np.all(energy_sc.values > 0) + assert np.all(np.isfinite(energy_sc.values)) + + # Verify corrected coordinates are within valid ranges + assert np.all(mock_hi_pset["hae_longitude"].values >= 0) + assert np.all(mock_hi_pset["hae_longitude"].values <= 360) + assert np.all(mock_hi_pset["hae_latitude"].values >= -90) + assert np.all(mock_hi_pset["hae_latitude"].values <= 90) + + @mock.patch("imap_processing.ena_maps.utils.corrections.geometry.imap_state") + def test_apply_compton_getting_correction(self, mock_imap_state, mock_hi_pset): + """Test full Compton-Getting correction pipeline.""" + # Set up spacecraft velocity + mock_sc_state = np.array([1e8, 2e8, 3e8, 10.0, 20.0, 30.0]) + mock_imap_state.return_value = mock_sc_state + + # Create energy array + energy_hf = xr.DataArray( + np.array([500.0, 1000.0, 2000.0]), + dims=["esa_energy_step"], + coords={"esa_energy_step": [1, 2, 3]}, + ) + + # add the required sc_velocity to the pointing set + mock_hi_pset = add_spacecraft_position_and_velocity_to_pset(mock_hi_pset) + + # Apply the full correction + mock_hi_pset = apply_compton_getting_correction(mock_hi_pset, energy_hf) + + # Verify all intermediate variables were added + assert "sc_velocity" in mock_hi_pset + assert "look_direction" in mock_hi_pset + assert "energy_hf" in mock_hi_pset + assert "energy_sc" in mock_hi_pset + assert "hae_longitude" in mock_hi_pset + assert "hae_latitude" in mock_hi_pset + + @pytest.mark.external_test_data + def test_compton_getting_with_real_pset(self, hi_pset_cdf_path): + """Test Compton-Getting correction with real Hi PSET data.""" + # Load real pointing set + pset = load_cdf(hi_pset_cdf_path) + pset = pset.rename(HiPointingSet.l1c_to_l2_var_mapping) + + # Store original coordinates for comparison + original_lon = pset["hae_longitude"].copy() + + # Mock spacecraft state + pset["sc_velocity"] = xr.DataArray( + np.array([12.0, -27.0, 0.02]), dims=[CoordNames.CARTESIAN_VECTOR.value] + ) + + # Create energy array (Hi has 9 energy steps) + energy_hf = xr.DataArray( + np.array( + [500.0, 750.0, 1100.0, 1650.0, 2500.0, 3750.0, 5700.0, 8520.0, 12800.0] + ), + dims=["esa_energy_step"], + coords={"esa_energy_step": np.arange(1, 10)}, + ) + + # Apply correction (pass the dataset, not the pointing set object) + pset = apply_compton_getting_correction(pset, energy_hf) + + # Verify coordinates were modified + corrected_lon = pset["hae_longitude"] + corrected_lat = pset["hae_latitude"] + + # Shape should now include energy dimension + assert "esa_energy_step" in corrected_lon.dims + assert "esa_energy_step" in corrected_lat.dims + assert corrected_lon.dims == ( + original_lon.dims[0], + "esa_energy_step", + original_lon.dims[1], + ) + + # Verify all values are in valid ranges + assert np.all(corrected_lon.values >= 0) + assert np.all(corrected_lon.values <= 360) + assert np.all(corrected_lat.values >= -90) + assert np.all(corrected_lat.values <= 90) + + def test_compton_getting_physical_consistency(self, mock_hi_pset): + """Test physical consistency of Compton-Getting correction.""" + # Set up a known spacecraft velocity + sc_velocity = np.array([30.0, 0.0, 0.0]) # Moving in +X direction at 30 km/s + + mock_hi_pset["sc_velocity"] = xr.DataArray(sc_velocity, dims=["x_y_z"]) + mock_hi_pset["sc_direction_vector"] = xr.DataArray( + sc_velocity / np.linalg.norm(sc_velocity), dims=["x_y_z"] + ) + + # Set up simple look directions + mock_hi_pset = _add_cartesian_look_direction(mock_hi_pset) + + # Single energy level + energy_hf = xr.DataArray(np.array([1000.0]), dims=["esa_energy_step"]) + + _calculate_compton_getting_transform(mock_hi_pset, energy_hf) + + # Physical checks: + # 1. Energy in spacecraft frame should be higher for particles coming + # from the direction of spacecraft motion (ram direction) + energy_sc = mock_hi_pset["energy_sc"] + + # 2. All energies should be positive + assert np.all(energy_sc.values > 0) + + # 3. The spacecraft frame energy should differ from heliosphere frame + # (they should not all be exactly 1000 eV) + assert not np.allclose(energy_sc.values, 1000.0) + + # 4. Energy variation should exist across different look directions + assert energy_sc.values.std() > 0 + + +class TestRamMask: + """Test suite for calculate_ram_mask function.""" + + def test_ram_mask_calculation(self): + """Test ram_mask correctly identifies ram and anti-ram directions.""" + # Create a simple mock pset with specific look directions + n_directions = 4 + dataset = xr.Dataset( + { + "epoch": (["epoch"], np.array([797949131184000000])), + # Set up specific look directions: + # 0 degrees lon, 0 lat = +X direction (ram) + # 180 degrees lon, 0 lat = -X direction (anti-ram) + # 90 degrees lon, 0 lat = +Y direction (perpendicular) + # 270 degrees lon, 0 lat = -Y direction (perpendicular) + "hae_longitude": ( + ["epoch", "direction"], + np.array([[0.0, 180.0, 90.0, 270.0]]), + ), + "hae_latitude": ( + ["epoch", "direction"], + np.array([[0.0, 0.0, 0.0, 0.0]]), + ), + "direction": (["direction"], np.arange(n_directions)), + } + ).transpose("epoch", "direction") + + # Set up spacecraft velocity in +X direction + sc_velocity = np.array([30.0, 0.0, 0.0]) # km/s + dataset["sc_velocity"] = xr.DataArray(sc_velocity, dims=["x_y_z"]) + + # Add look directions + dataset = _add_cartesian_look_direction(dataset) + + # Single energy level + energy_hf = xr.DataArray(np.array([1000.0]), dims=["esa_energy_step"]) + + # Calculate CG transform + dataset = _calculate_compton_getting_transform(dataset, energy_hf) + + dataset = calculate_ram_mask(dataset) + + # Verify ram_mask exists + assert "ram_mask" in dataset + ram_mask = dataset["ram_mask"] + + # Verify dimensions + assert set(ram_mask.dims) == {"epoch", "esa_energy_step", "direction"} + + # Extract the mask values for easier checking + mask_values = ram_mask.values.squeeze() + + # Direction 0 (0 deg lon, 0 lat = +X): Should be ram (True) + # Direction 1 (180 deg lon, 0 lat = -X): Should be anti-ram (False) + # Directions 2 and 3 (perpendicular): Will always be anti-ram (False) + + # The key test: particles coming from the spacecraft's direction of motion + # (opposite to velocity) should be anti-ram (False) + assert not mask_values[1], ( + "Particles from -X (opposite velocity) should be anti-ram" + ) + + # Particles coming from the direction the spacecraft is moving toward + # should be ram (True) + assert mask_values[0], "Particles from +X (along velocity) should be ram" + + # Particles coming from the perpendicular direction should always shift + # to be coming from a slightly anti-ram direction + assert not mask_values[2], "Particles from +Y should be anti-ram" + assert not mask_values[3], "Particles from -Y should be anti-ram" + + # Verify all values are boolean + assert ram_mask.dtype == bool + + @staticmethod + def create_synthetic_pset_with_hae_coords(shape=(10, 20)): + """Create a synthetic dataset with known HAE coordinates.""" + # Create longitude and latitude grids + lons = np.linspace(0, 360, shape[0], endpoint=False) + lats = np.linspace(-90, 90, shape[1]) + lon_grid, lat_grid = np.meshgrid(lons, lats, indexing="ij") + + # Create a minimal dataset + dataset = xr.Dataset( + { + "hae_longitude": xr.DataArray( + lon_grid[np.newaxis, :, :], + dims=["epoch", "spin_angle", "off_angle"], + ), + "hae_latitude": xr.DataArray( + lat_grid[np.newaxis, :, :], + dims=["epoch", "spin_angle", "off_angle"], + ), + }, + coords={ + "epoch": xr.DataArray([1e18], dims=["epoch"]), + }, + ) + + return dataset + + def test_update_ram_mask_plus_x_direction(self): + """Test RAM mask with spacecraft velocity in +X direction.""" + pset = self.create_synthetic_pset_with_hae_coords() + + # Spacecraft velocity in +X direction (HAE frame) + pset["sc_velocity"] = np.array([1.0, 0.0, 0.0]) + pset = calculate_ram_mask(pset) + + lon = pset["hae_longitude"].values + ram_mask = pset["ram_mask"].values + + # For +X direction, RAM should be anywhere that the longitude is between + # -90 and +90. + idx_ram = np.nonzero((lon < 90) | (lon > 270)) + assert np.all(ram_mask[idx_ram]), ( + "Expected lon < 90 or lon > 270 to be RAM for +X velocity" + ) + + # Pixels with 90 < lon < 270 should be anti-RAM (pointing in -X direction) + idx_anti = np.nonzero((lon > 90) & (lon < 270)) + assert not np.any(ram_mask[idx_anti]), ( + "Expected 90 < lon < 270 to be anti-RAM for +X velocity" + ) + + def test_update_ram_mask_minus_x_direction(self): + """Test RAM mask with spacecraft velocity in -X direction.""" + pset = self.create_synthetic_pset_with_hae_coords() + + # Spacecraft velocity in -X direction (HAE frame) + pset["sc_velocity"] = np.array([-1.0, 0.0, 0.0]) + pset = calculate_ram_mask(pset) + + lon = pset["hae_longitude"].values + ram_mask = pset["ram_mask"].values + + # For -X direction, anti-RAM should be anywhere that 90 < lon < 270. + idx_ram = np.nonzero((lon > 90) & (lon < 270)) + assert np.all(ram_mask[idx_ram]), ( + "Expected 90 < lon < 270 to be RAM for -X velocity" + ) + + # Pixels with lon < 90 or lon > 270 should be RAM (pointing in -X direction) + idx_anti = np.nonzero((lon < 90) | (lon > 270)) + assert not np.any(ram_mask[idx_anti]), ( + "Expected lon < 90 or lon > 270 to be anit-RAM for -X velocity" + ) + + def test_update_ram_mask_plus_y_direction(self): + """Test RAM mask with spacecraft velocity in +Y direction.""" + pset = self.create_synthetic_pset_with_hae_coords() + + # Spacecraft velocity in +Y direction (HAE frame) + pset["sc_velocity"] = np.array([0.0, 1.0, 0.0]) + pset = calculate_ram_mask(pset) + + lon = pset["hae_longitude"].values + ram_mask = pset["ram_mask"].values + + # For +Y direction, RAM should be anywhere that the 0 < lon < 180. + idx_ram = np.nonzero((0 < lon) & (lon < 180)) + assert np.all(ram_mask[idx_ram]), "Expected lat > 0 to be RAM for +Y velocity" + + # Pixels with lon > 180 should be anti-RAM (pointing in -Y direction) + idx_anti = np.nonzero(lon > 180) + assert not np.any(ram_mask[idx_anti]), ( + "Expected lat < 0 to be anti-RAM for +Y velocity" + ) + + def test_update_ram_mask_magnitude_invariance(self): + """Test that RAM mask is invariant to velocity vector magnitude.""" + pset = self.create_synthetic_pset_with_hae_coords() + + # Test with two different magnitudes in the same direction + pset["sc_velocity"] = np.array([1.0, 0.0, 0.0]) + pset = calculate_ram_mask(pset) + ram_mask_1 = pset["ram_mask"].values.copy() + + pset["sc_velocity"] = np.array([100.0, 0.0, 0.0]) + pset = calculate_ram_mask(pset) + ram_mask_2 = pset["ram_mask"].values.copy() + + # The masks should be identical since direction is the same + np.testing.assert_array_equal(ram_mask_1, ram_mask_2) + + def test_update_ram_mask_dot_product_correctness(self): + """Test that dot product calculation is mathematically correct.""" + pset = self.create_synthetic_pset_with_hae_coords() + + # Use a simple spacecraft velocity vector + pset["sc_velocity"] = np.array([1.0, 0.0, 0.0]) + pset = calculate_ram_mask(pset) + + # Manually verify a few specific pixels + lon = pset["hae_longitude"].values + lat = pset["hae_latitude"].values + ram_mask = pset["ram_mask"].values + + # Test pixel at lon=0, lat=0 (should point in +X direction) + lon_rad = np.deg2rad(0) + lat_rad = np.deg2rad(0) + x = np.cos(lat_rad) * np.cos(lon_rad) # = 1.0 + dot_product = x * 1.0 # = 1.0 + expected_ram = dot_product >= 0 # True + + idx = np.where((np.abs(lon - 0) < 1) & (np.abs(lat - 0) < 1)) + if idx[0].size > 0: + assert ram_mask[idx][0] == expected_ram + + def test_update_ram_mask_dimensions_preserved(self): + """Test that update_ram_mask preserves coordinate dimensions.""" + # Test with 2D spatial dimensions (like LoPointingSet) + pset_2d = self.create_synthetic_pset_with_hae_coords(shape=(5, 10)) + + # Get original dimensions + original_dims_2d = pset_2d["hae_longitude"].dims + + # Update ram_mask + pset_2d["sc_velocity"] = np.array([1.0, 1.0, 0.0]) + pset_2d = calculate_ram_mask(pset_2d) + + # Verify dimensions are preserved + assert pset_2d["ram_mask"].dims == original_dims_2d + + # Test with 1D spatial dimensions (like HiPointingSet) + # Create synthetic dataset with 1D spatial dimension + lons = np.linspace(0, 360, 20, endpoint=False) + lats = np.linspace(-90, 90, 20) + + dataset_1d = xr.Dataset( + { + "hae_longitude": xr.DataArray( + lons[np.newaxis, :], + dims=["epoch", "spin_angle_bin"], + ), + "hae_latitude": xr.DataArray( + lats[np.newaxis, :], + dims=["epoch", "spin_angle_bin"], + ), + }, + coords={ + "epoch": xr.DataArray([1e18], dims=["epoch"]), + }, + ) + + # Get original dimensions + original_dims_1d = dataset_1d["hae_longitude"].dims + + # Update ram_mask + dataset_1d["sc_velocity"] = np.array([1.0, 1.0, 0.0]) + dataset_1d = calculate_ram_mask(dataset_1d) + + # Verify dimensions are preserved + assert dataset_1d["ram_mask"].dims == original_dims_1d + + def test_update_ram_mask_replaces_existing(self): + """Test that update_ram_mask replaces existing ram_mask.""" + pset = self.create_synthetic_pset_with_hae_coords() + + # Set initial mask with +X direction + pset["sc_velocity"] = np.array([1.0, 0.0, 0.0]) + pset = calculate_ram_mask(pset) + ram_mask_1 = pset["ram_mask"].values.copy() + + # Update mask with opposite direction + pset["sc_velocity"] = np.array([-1.0, 0.0, 0.0]) + pset = calculate_ram_mask(pset) + ram_mask_2 = pset["ram_mask"].values.copy() + + # The masks should be different + assert not np.array_equal(ram_mask_1, ram_mask_2) + + def test_update_ram_mask_arbitrary_direction(self): + """Test RAM mask with arbitrary spacecraft velocity direction.""" + pset = self.create_synthetic_pset_with_hae_coords(shape=(36, 18)) + + # Use an arbitrary direction (not aligned with axes) + pset["sc_velocity"] = np.array([1.0, 1.0, 0.5]) + pset = calculate_ram_mask(pset) + + # Verify the mask was created + assert "ram_mask" in pset + + # Verify approximately half the pixels are RAM (for a sphere) + ram_fraction = pset["ram_mask"].sum().values / pset["ram_mask"].size + # Should be close to 0.5, allowing for discretization effects + np.testing.assert_allclose(ram_fraction, 0.5, atol=0.05) + + +class TestInterpolateMapFluxToHelioFrame: + """Test suite for interpolate_map_flux_to_helio_frame function.""" + + def create_test_map_dataset(self, n_energy=5, n_spatial=10, power_law_slope=-2.0): + """Create a synthetic map dataset for testing interpolation. + + Parameters + ---------- + n_energy : int + Number of energy channels + n_spatial : int + Number of spatial pixels + power_law_slope : float + Power-law spectral index for test flux + + Returns + ------- + tuple + (map_ds, esa_energies, helio_energies) + """ + # Define ESA energy channels (in eV) + esa_energies = np.array([500.0, 1000.0, 2000.0, 4000.0, 8000.0])[:n_energy] + + # Create flux with a simple power-law spectrum: flux = E^slope + flux_base = esa_energies[:, np.newaxis] ** power_law_slope + + # Add some spatial variation (multiply by factors between 0.5 and 1.5) + spatial_factors = np.linspace(0.5, 1.5, n_spatial) + flux = flux_base * spatial_factors + + # Create uncertainties (10% statistical, 5% systematic) + stat_unc = 0.1 * flux + sys_err = 0.05 * flux + + # Create spacecraft energies slightly different from ESA energies + # to simulate Compton-Getting shift + # Add a small spatial-dependent shift + energy_shift_factor = 1.0 + 0.1 * np.linspace(-1, 1, n_spatial) + energy_sc = esa_energies[:, np.newaxis] * energy_shift_factor + + # Create xarray Dataset + map_ds = xr.Dataset( + { + "ena_intensity": (["energy", "spatial"], flux), + "ena_intensity_stat_uncert": (["energy", "spatial"], stat_unc), + "ena_intensity_sys_err": (["energy", "spatial"], sys_err), + "energy_sc": (["energy", "spatial"], energy_sc), + }, + coords={ + "energy": np.arange(n_energy), + "spatial": np.arange(n_spatial), + }, + ) + + # Helio energies are the same as ESA energies (standard case) + helio_energies = xr.DataArray( + esa_energies, + dims=["energy"], + coords={"energy": np.arange(n_energy)}, + ) + + esa_energies_da = xr.DataArray( + esa_energies, + dims=["energy"], + coords={"energy": np.arange(n_energy)}, + ) + + return map_ds, esa_energies_da, helio_energies + + def test_basic_interpolation(self): + """Test basic functionality of interpolation.""" + + map_ds, esa_energies, helio_energies = self.create_test_map_dataset() + + # Apply interpolation + result_ds = interpolate_map_flux_to_helio_frame( + map_ds, esa_energies, helio_energies, ["ena_intensity"] + ) + + # Verify output structure + assert "ena_intensity" in result_ds + assert "ena_intensity_stat_uncert" in result_ds + assert "ena_intensity_sys_err" in result_ds + + # Verify shapes are preserved + assert result_ds["ena_intensity"].shape == map_ds["ena_intensity"].shape + assert ( + result_ds["ena_intensity_stat_uncert"].shape + == map_ds["ena_intensity_stat_uncert"].shape + ) + assert ( + result_ds["ena_intensity_sys_err"].shape + == map_ds["ena_intensity_sys_err"].shape + ) + + def test_energy_unit_insensitivity(self): + """Test that units of eV or keV produce the same result.""" + + map_ds, esa_energies, helio_energies = self.create_test_map_dataset() + + # Apply interpolation + ev_ds = interpolate_map_flux_to_helio_frame( + map_ds, esa_energies, helio_energies, ["ena_intensity"] + ) + kev_ds = interpolate_map_flux_to_helio_frame( + map_ds, esa_energies / 1000, helio_energies / 1000, ["ena_intensity"] + ) + + # Verify results are the same + xr.testing.assert_equal(ev_ds, kev_ds) + + def test_power_law_interpolation_accuracy(self): + """Test that power-law interpolation formula is correct.""" + + # Create simple test case with known power-law + # flux = E^(-2) + power_law_slope = -2.0 + map_ds, esa_energies, helio_energies = self.create_test_map_dataset( + n_energy=3, n_spatial=1, power_law_slope=power_law_slope + ) + + # Manually set energy_sc to be between two ESA energies + # ESA energies: [500, 1000, 2000] + # Set energy_sc for middle channel to 750 eV (between 500 and 1000) + map_ds["energy_sc"].values[1, 0] = 750.0 + + result_ds = interpolate_map_flux_to_helio_frame( + map_ds, esa_energies, helio_energies, ["ena_intensity"] + ) + + # For a perfect power-law with flux = E^(-2) * spatial_factor: + # With n_spatial=1, spatial_factor = 0.5 (from np.linspace(0.5, 1.5, 1)) + # The interpolation process does: + # 1. Interpolates flux at E_sc=750 from values at 500 and 1000 + # Expected: 750^(-2) * 0.5 + # 2. Scales to E_helio=1000: flux * (1000/750) + # = 750^(-2) * 0.5 * (1000/750) + + # Calculate expected result for middle energy channel + e_sc = 750.0 + e_helio = 1000.0 + spatial_factor = 0.5 # From create_test_map_dataset with n_spatial=1 + expected_flux_middle = ( + (e_sc**power_law_slope) * (e_helio / e_sc) * spatial_factor + ) + unc_factor = np.log(e_sc / 500) / np.log(1000 / 500) + expected_stat_uncert = expected_flux_middle * np.sqrt( + 0.1**2 * (1 + unc_factor**2) + unc_factor**2 * 0.1**2 + ) + + # Compare interpolated result to expected value + # (should be very close for a perfect power-law) + np.testing.assert_allclose( + result_ds["ena_intensity"].values[1, 0], + expected_flux_middle, + rtol=1e-10, + ) + + # Check expected stat. unc. + np.testing.assert_allclose( + result_ds["ena_intensity_stat_uncert"].values[1, 0], + expected_stat_uncert, + rtol=1e-10, + ) + + # The flux should be finite and positive + assert np.all(np.isfinite(result_ds["ena_intensity"].values)) + assert np.all(result_ds["ena_intensity"].values > 0) + + def test_statistical_uncertainty_propagation(self): + """Test that statistical uncertainty follows Equation 75.""" + + map_ds, esa_energies, helio_energies = self.create_test_map_dataset( + n_energy=3, n_spatial=1 + ) + + # Set up a specific case where we can verify the formula + # Set energy_sc to midpoint between two channels + e_sc = 1400.0 # Between left and right + + map_ds["energy_sc"].values[1, 0] = e_sc + + result_ds = interpolate_map_flux_to_helio_frame( + map_ds, esa_energies, helio_energies, ["ena_intensity"] + ) + + # Statistical uncertainty should be positive and finite + stat_unc = result_ds["ena_intensity_stat_uncert"].values + assert np.all(stat_unc >= 0) + assert np.all(np.isfinite(stat_unc)) + + # Statistical uncertainty should scale with flux + # (relative uncertainty should be similar to input) + flux = result_ds["ena_intensity"].values + rel_unc_output = stat_unc / flux + + # Should be on the order of input relative uncertainty (10%) + # Allow for propagation effects + assert np.all(rel_unc_output > 0) + assert np.all(rel_unc_output < 1.0) # Should be reasonable + + def test_systematic_uncertainty_propagation(self): + """Test that systematic uncertainty follows Equation 76.""" + + map_ds, esa_energies, helio_energies = self.create_test_map_dataset( + n_energy=3, n_spatial=1 + ) + + result_ds = interpolate_map_flux_to_helio_frame( + map_ds, esa_energies, helio_energies, ["ena_intensity"] + ) + + # Systematic uncertainty should be positive and finite + sys_err = result_ds["ena_intensity_sys_err"].values + assert np.all(sys_err >= 0) + assert np.all(np.isfinite(sys_err)) + + # Systematic error should scale proportionally with flux + flux = result_ds["ena_intensity"].values + rel_sys_err = sys_err / flux + + # Relative systematic error should be preserved (5% in input) + # within reasonable tolerance for the transformations + assert np.all(rel_sys_err > 0) + assert np.all(rel_sys_err < 0.5) # Should be reasonable + + def test_systematic_uncertainty_update_flag(self): + """Test that systematic error is unchanged when flag is set False.""" + + map_ds, esa_energies, helio_energies = self.create_test_map_dataset( + n_energy=3, n_spatial=1 + ) + sys_err_input = map_ds["ena_intensity_sys_err"].copy() + + result_ds = interpolate_map_flux_to_helio_frame( + map_ds, + esa_energies, + helio_energies, + ["ena_intensity"], + update_sys_err=False, + ) + + # Systematic uncertainty should be positive and finite + xr.testing.assert_equal(result_ds["ena_intensity_sys_err"], sys_err_input) + + def test_energy_scaling_transformation(self): + """Test Liouville theorem: flux_helio = flux_sc * (E_helio / E_sc).""" + + # Create dataset where energy_sc equals ESA energies (no CG shift) + map_ds, esa_energies, helio_energies = self.create_test_map_dataset( + n_energy=3, n_spatial=1 + ) + + # Set energy_sc exactly equal to ESA energies + map_ds["energy_sc"].values[:, 0] = esa_energies.values + + # Store original flux for comparison + original_flux = map_ds["ena_intensity"].values.copy() + + result_ds = interpolate_map_flux_to_helio_frame( + map_ds, esa_energies, helio_energies, ["ena_intensity"] + ) + + # When E_sc = E_esa and E_helio = E_esa, then E_helio/E_sc = 1 + # So flux should be approximately preserved (modulo interpolation effects) + result_flux = result_ds["ena_intensity"].values + + # The ratio should be close to 1 for each pixel + # (within numerical precision and interpolation effects) + ratio = result_flux / original_flux + + # Allow for some numerical error and interpolation effects + assert np.all(np.isfinite(ratio)) + # Most values should be reasonably close to original + # (exact match not expected due to interpolation) + np.testing.assert_allclose(ratio, 1) + + def test_infinite_values_converted_to_nan(self): + """Test that infinite values are converted to NaN.""" + + map_ds, esa_energies, helio_energies = self.create_test_map_dataset( + n_energy=3, n_spatial=2 + ) + + # Introduce a zero flux to create divide-by-zero + map_ds["ena_intensity"].values[1, 0] = 0.0 + + # Set energy_sc to zero to create potential infinities + map_ds["energy_sc"].values[1, 1] = 0.0 + + result_ds = interpolate_map_flux_to_helio_frame( + map_ds, esa_energies, helio_energies, ["ena_intensity"] + ) + + # Check that we have NaN values where expected, not infinities + flux = result_ds["ena_intensity"].values + stat_unc = result_ds["ena_intensity_stat_uncert"].values + sys_err = result_ds["ena_intensity_sys_err"].values + + # Should have no infinities + assert not np.any(np.isinf(flux)) + assert not np.any(np.isinf(stat_unc)) + assert not np.any(np.isinf(sys_err)) + + def test_nan_input_propagation(self): + """Test that NaN inputs properly propagate to NaN outputs.""" + map_ds, esa_energies, helio_energies = self.create_test_map_dataset( + n_energy=3, n_spatial=3 + ) + + # Set some input values to NaN + map_ds["ena_intensity"].values[1, 0] = np.nan + map_ds["ena_intensity_stat_uncert"].values[1, 1] = np.nan + map_ds["ena_intensity_sys_err"].values[1, 2] = np.nan + + result_ds = interpolate_map_flux_to_helio_frame( + map_ds, esa_energies, helio_energies, ["ena_intensity"] + ) + + # NaN in flux should propagate to flux, stat_uncert, and sys_err + # at that location + assert np.isnan(result_ds["ena_intensity"].values[1, 0]) + assert np.isnan(result_ds["ena_intensity_stat_uncert"].values[1, 0]) + assert np.isnan(result_ds["ena_intensity_sys_err"].values[1, 0]) + + # NaN in stat_uncert input should result in NaN stat_uncert output + assert np.isnan(result_ds["ena_intensity_stat_uncert"].values[1, 1]) + + # NaN in sys_err input should result in NaN sys_err output + assert np.isnan(result_ds["ena_intensity_sys_err"].values[1, 2]) + + def test_multidimensional_spatial_coords(self): + """Test that interpolation works with multi-dimensional spatial coordinates.""" + + n_energy = 4 + n_lat = 6 + n_lon = 8 + + # Define ESA energies + esa_energies_vals = np.array([500.0, 1000.0, 2000.0, 4000.0]) + + # Create flux with spatial dimensions (lat, lon) + power_law_slope = -2.0 + flux = np.zeros((n_energy, n_lat, n_lon)) + stat_unc = np.zeros((n_energy, n_lat, n_lon)) + sys_err = np.zeros((n_energy, n_lat, n_lon)) + energy_sc = np.zeros((n_energy, n_lat, n_lon)) + + for i in range(n_energy): + # Power-law flux with spatial variation + spatial_pattern = 1.0 + 0.5 * np.random.random((n_lat, n_lon)) + flux[i, :, :] = (esa_energies_vals[i] ** power_law_slope) * spatial_pattern + stat_unc[i, :, :] = 0.1 * flux[i, :, :] + sys_err[i, :, :] = 0.05 * flux[i, :, :] + + # Energy shift varies with position + energy_sc[i, :, :] = esa_energies_vals[i] * ( + 1.0 + 0.1 * np.random.random((n_lat, n_lon)) + ) + + # Create dataset with 2D spatial coordinates + map_ds = xr.Dataset( + { + "ena_intensity": (["energy", "latitude", "longitude"], flux), + "ena_intensity_stat_uncert": ( + ["energy", "latitude", "longitude"], + stat_unc, + ), + "ena_intensity_sys_err": (["energy", "latitude", "longitude"], sys_err), + "energy_sc": (["energy", "latitude", "longitude"], energy_sc), + }, + coords={ + "energy": np.arange(n_energy), + "latitude": np.arange(n_lat), + "longitude": np.arange(n_lon), + }, + ) + + esa_energies = xr.DataArray( + esa_energies_vals, + dims=["energy"], + coords={"energy": np.arange(n_energy)}, + ) + helio_energies = esa_energies.copy() + + # Apply interpolation + result_ds = interpolate_map_flux_to_helio_frame( + map_ds, esa_energies, helio_energies, ["ena_intensity"] + ) + + # Verify output shape matches input + assert result_ds["ena_intensity"].shape == (n_energy, n_lat, n_lon) + assert result_ds["ena_intensity_stat_uncert"].shape == (n_energy, n_lat, n_lon) + assert result_ds["ena_intensity_sys_err"].shape == (n_energy, n_lat, n_lon) + + # Verify dimensions are preserved + assert list(result_ds["ena_intensity"].dims) == [ + "energy", + "latitude", + "longitude", + ] + + # Verify values are reasonable + assert np.all(result_ds["ena_intensity"].values > 0) + assert np.all(np.isfinite(result_ds["ena_intensity"].values)) + + def test_boundary_energy_channels(self): + """Test interpolation behavior at energy boundaries.""" + + map_ds, esa_energies, helio_energies = self.create_test_map_dataset( + n_energy=5, n_spatial=3 + ) + + # Test when energy_sc is below the lowest ESA energy + map_ds["energy_sc"].values[0, 0] = 0.9 * esa_energies.values[0] + + # Test when energy_sc is above the highest ESA energy + map_ds["energy_sc"].values[-1, -1] = 1.1 * esa_energies.values[-1] + + result_ds = interpolate_map_flux_to_helio_frame( + map_ds, esa_energies, helio_energies, ["ena_intensity"] + ) + + # Should handle boundary cases without errors + flux = result_ds["ena_intensity"].values + + # Boundary pixels should have values (possibly NaN, but no crashes) + # The function clips indices to valid range, so these should interpolate + # using the boundary channels + assert flux.shape == map_ds["ena_intensity"].shape + + def test_preserves_dataset_structure(self): + """Test that the function preserves the dataset structure.""" + + map_ds, esa_energies, helio_energies = self.create_test_map_dataset() + + # Store original attributes + original_dims = list(map_ds["ena_intensity"].dims) + original_coords = list(map_ds.coords.keys()) + + result_ds = interpolate_map_flux_to_helio_frame( + map_ds, esa_energies, helio_energies, ["ena_intensity"] + ) + + # Verify dimensions are preserved + assert list(result_ds["ena_intensity"].dims) == original_dims + + # Verify coordinates are preserved + assert list(result_ds.coords.keys()) == original_coords + + # Verify it's still an xarray Dataset + assert isinstance(result_ds, xr.Dataset) + + def test_with_uniform_flux(self): + """Test interpolation with uniform flux (no spatial variation).""" + + n_energy = 4 + n_spatial = 5 + + esa_energies_vals = np.array([500.0, 1000.0, 2000.0, 4000.0]) + + # Create uniform flux (same for all spatial pixels) + power_law_slope = -2.0 + flux_uniform = (esa_energies_vals**power_law_slope)[:, np.newaxis] + flux = np.tile(flux_uniform, (1, n_spatial)) + + stat_unc = 0.1 * flux + sys_err = 0.05 * flux + + # Energy shift uniform across space + energy_sc = np.tile(esa_energies_vals[:, np.newaxis] * 1.05, (1, n_spatial)) + + map_ds = xr.Dataset( + { + "ena_intensity": (["energy", "spatial"], flux), + "ena_intensity_stat_uncert": (["energy", "spatial"], stat_unc), + "ena_intensity_sys_err": (["energy", "spatial"], sys_err), + "energy_sc": (["energy", "spatial"], energy_sc), + }, + coords={ + "energy": np.arange(n_energy), + "spatial": np.arange(n_spatial), + }, + ) + + esa_energies = xr.DataArray( + esa_energies_vals, + dims=["energy"], + coords={"energy": np.arange(n_energy)}, + ) + helio_energies = esa_energies.copy() + + result_ds = interpolate_map_flux_to_helio_frame( + map_ds, esa_energies, helio_energies, ["ena_intensity"] + ) + + # With uniform input, output should also be uniform across spatial dimension + result_flux = result_ds["ena_intensity"].values + + # Check that each energy channel has uniform values across spatial pixels + for i_energy in range(n_energy): + spatial_values = result_flux[i_energy, :] + # All spatial pixels at this energy should be similar + if np.all(np.isfinite(spatial_values)): + std_dev = np.std(spatial_values) + mean_val = np.mean(spatial_values) + # Relative std should be very small for uniform input + if mean_val > 0: + rel_std = std_dev / mean_val + assert rel_std < 1e-10, f"Energy {i_energy}: rel_std = {rel_std}" + + def test_multiple_variables_interpolation(self): + """Test interpolation with multiple intensity variables.""" + # Create base dataset with ena_intensity + map_ds, esa_energies, helio_energies = self.create_test_map_dataset( + n_energy=3, n_spatial=5 + ) + + # Add a second intensity variable (e.g., background) with different values + map_ds["background_intensity"] = map_ds["ena_intensity"] * 0.2 # 20% of signal + map_ds["background_intensity_stat_uncert"] = ( + map_ds["ena_intensity_stat_uncert"] * 0.2 + ) + map_ds["background_intensity_sys_err"] = map_ds["ena_intensity_sys_err"] * 0.2 + + # Interpolate both variables + result_ds = interpolate_map_flux_to_helio_frame( + map_ds, + esa_energies, + helio_energies, + ["ena_intensity", "background_intensity"], + ) + + # Verify shapes are preserved for ena_intensity + assert result_ds["ena_intensity"].shape == map_ds["ena_intensity"].shape + assert ( + result_ds["ena_intensity_stat_uncert"].shape + == map_ds["ena_intensity_stat_uncert"].shape + ) + assert ( + result_ds["ena_intensity_sys_err"].shape + == map_ds["ena_intensity_sys_err"].shape + ) + + # Verify shapes are preserved for background + assert ( + result_ds["background_intensity"].shape + == map_ds["background_intensity"].shape + ) + assert ( + result_ds["background_intensity_stat_uncert"].shape + == map_ds["background_intensity_stat_uncert"].shape + ) + assert ( + result_ds["background_intensity_sys_err"].shape + == map_ds["background_intensity_sys_err"].shape + ) + + # Verify all values are finite and positive + assert np.all(np.isfinite(result_ds["ena_intensity"].values)) + assert np.all(result_ds["ena_intensity"].values > 0) + assert np.all(np.isfinite(result_ds["background_intensity"].values)) + assert np.all(result_ds["background_intensity"].values > 0) + + # Verify the relative scaling between signal and background is + # approximately preserved (background should still be ~20% of signal + # after interpolation) + signal_values = result_ds["ena_intensity"].values + background_values = result_ds["background_intensity"].values + ratio = background_values / signal_values + # Allow for some numerical variation due to interpolation + np.testing.assert_allclose(ratio, 0.2, rtol=0.01) + + def test_linear_fallback_when_flux_left_zero(self): + """Test that linear interpolation is used when flux_left is zero.""" + n_energy = 3 + n_spatial = 2 + + esa_energies_vals = np.array([500.0, 1000.0, 2000.0]) + + # Create flux where one pixel has zero flux at energy index 0 + flux = np.array( + [ + [0.0, 1.0], # energy 0: pixel 0 is zero + [1.0, 2.0], # energy 1 + [0.5, 1.5], # energy 2 + ] + ) + stat_unc = 0.1 * np.maximum(flux, 0.1) + sys_err = 0.05 * np.maximum(flux, 0.1) + + # Set energy_sc to be between energy channels 0 and 1 + energy_sc = np.array( + [ + [750.0, 750.0], # interpolating between 500 and 1000 + [1500.0, 1500.0], # interpolating between 1000 and 2000 + [1800.0, 1800.0], # near the boundary + ] + ) + + map_ds = xr.Dataset( + { + "ena_intensity": (["energy", "spatial"], flux), + "ena_intensity_stat_uncert": (["energy", "spatial"], stat_unc), + "ena_intensity_sys_err": (["energy", "spatial"], sys_err), + "energy_sc": (["energy", "spatial"], energy_sc), + }, + coords={ + "energy": np.arange(n_energy), + "spatial": np.arange(n_spatial), + }, + ) + + esa_energies = xr.DataArray( + esa_energies_vals, + dims=["energy"], + coords={"energy": np.arange(n_energy)}, + ) + helio_energies = esa_energies.copy() + + result_ds = interpolate_map_flux_to_helio_frame( + map_ds, esa_energies, helio_energies, ["ena_intensity"] + ) + + # Verify results are finite (not NaN) where we expect valid values + result_flux = result_ds["ena_intensity"].values + + # With linear fallback, pixel 0 at energy 0 should produce a valid result + # because we're interpolating between 0 (at 500eV) and 1 (at 1000eV) + # Linear interpolation at 750eV: 0 + (1-0) * (750-500)/(1000-500) = 0.5 + # Then energy scaling: 0.5 * (500/750) = 1/3 + expected_flux = 0.5 * (500.0 / 750.0) # = 1/3 + np.testing.assert_allclose( + result_flux[0, 0], + expected_flux, + rtol=1e-10, + err_msg="Linear fallback should produce correct interpolated value", + ) + + # Statistical uncertainty should also be finite + result_stat_unc = result_ds["ena_intensity_stat_uncert"].values + assert np.isfinite(result_stat_unc[0, 0]), ( + "Statistical uncertainty should be finite with linear fallback" + ) + + def test_linear_fallback_when_flux_right_zero(self): + """Test that linear interpolation is used when flux_right is zero.""" + n_energy = 3 + n_spatial = 2 + + esa_energies_vals = np.array([500.0, 1000.0, 2000.0]) + + # Create flux where one pixel has zero flux at energy index 1 + flux = np.array( + [ + [1.0, 1.0], # energy 0 + [0.0, 2.0], # energy 1: pixel 0 is zero + [0.5, 1.5], # energy 2 + ] + ) + stat_unc = 0.1 * np.maximum(flux, 0.1) + sys_err = 0.05 * np.maximum(flux, 0.1) + + # Set energy_sc to be between energy channels 0 and 1 + energy_sc = np.array( + [ + [750.0, 750.0], # interpolating between 500 and 1000 + [1500.0, 1500.0], # interpolating between 1000 and 2000 + [1800.0, 1800.0], # near the boundary + ] + ) + + map_ds = xr.Dataset( + { + "ena_intensity": (["energy", "spatial"], flux), + "ena_intensity_stat_uncert": (["energy", "spatial"], stat_unc), + "ena_intensity_sys_err": (["energy", "spatial"], sys_err), + "energy_sc": (["energy", "spatial"], energy_sc), + }, + coords={ + "energy": np.arange(n_energy), + "spatial": np.arange(n_spatial), + }, + ) + + esa_energies = xr.DataArray( + esa_energies_vals, + dims=["energy"], + coords={"energy": np.arange(n_energy)}, + ) + helio_energies = esa_energies.copy() + + result_ds = interpolate_map_flux_to_helio_frame( + map_ds, esa_energies, helio_energies, ["ena_intensity"] + ) + + result_flux = result_ds["ena_intensity"].values + + # With linear fallback, pixel 0 at energy 0 should produce a valid result + # Linear interpolation from flux=1 at 500eV to flux=0 at 1000eV + # At 750eV: 1 + (0-1) * (750-500)/(1000-500) = 1 - 0.5 = 0.5 + # Then energy scaling: 0.5 * (500/750) = 1/3 + expected_flux = 0.5 * (500.0 / 750.0) # = 1/3 + np.testing.assert_allclose( + result_flux[0, 0], + expected_flux, + rtol=1e-10, + err_msg="Linear fallback should produce correct interpolated value", + ) + + def test_linear_fallback_when_both_fluxes_zero(self): + """Test that both bounding fluxes being zero produces zero output.""" + n_energy = 3 + n_spatial = 2 + + esa_energies_vals = np.array([500.0, 1000.0, 2000.0]) + + # Create flux where pixel 0 has zero flux at both energy 0 and 1 + flux = np.array( + [ + [0.0, 1.0], # energy 0: pixel 0 is zero + [0.0, 2.0], # energy 1: pixel 0 is zero + [0.5, 1.5], # energy 2 + ] + ) + stat_unc = 0.1 * np.maximum(flux, 0.1) + sys_err = 0.05 * np.maximum(flux, 0.1) + + # Set energy_sc to be between energy channels 0 and 1 for first energy + energy_sc = np.array( + [ + [750.0, 750.0], # interpolating between 500 and 1000 + [1500.0, 1500.0], + [1800.0, 1800.0], + ] + ) + + map_ds = xr.Dataset( + { + "ena_intensity": (["energy", "spatial"], flux), + "ena_intensity_stat_uncert": (["energy", "spatial"], stat_unc), + "ena_intensity_sys_err": (["energy", "spatial"], sys_err), + "energy_sc": (["energy", "spatial"], energy_sc), + }, + coords={ + "energy": np.arange(n_energy), + "spatial": np.arange(n_spatial), + }, + ) + + esa_energies = xr.DataArray( + esa_energies_vals, + dims=["energy"], + coords={"energy": np.arange(n_energy)}, + ) + helio_energies = esa_energies.copy() + + result_ds = interpolate_map_flux_to_helio_frame( + map_ds, esa_energies, helio_energies, ["ena_intensity"] + ) + + result_flux = result_ds["ena_intensity"].values + + # When both bounding fluxes are zero, linear interpolation gives 0 + # Result should be 0 (not NaN) + assert result_flux[0, 0] == 0.0, ( + "When both bounding fluxes are zero, result should be 0" + ) + + def test_negative_interpolated_flux_clamped_to_zero(self): + """Test that negative interpolated flux is clamped to zero.""" + n_energy = 3 + n_spatial = 1 + + esa_energies_vals = np.array([500.0, 1000.0, 2000.0]) + + # Create flux that decreases steeply - linear extrapolation could go negative + flux = np.array( + [ + [2.0], # energy 0 + [0.1], # energy 1: much smaller + [0.5], # energy 2 + ] + ) + stat_unc = 0.1 * flux + sys_err = 0.05 * flux + + # Set energy_sc beyond the range to trigger extrapolation + # At energy index 0, set energy_sc below 500eV to extrapolate + energy_sc = np.array( + [ + [400.0], # Below lowest ESA energy - will use channels 0,1 + [800.0], + [1500.0], + ] + ) + + map_ds = xr.Dataset( + { + "ena_intensity": (["energy", "spatial"], flux), + "ena_intensity_stat_uncert": (["energy", "spatial"], stat_unc), + "ena_intensity_sys_err": (["energy", "spatial"], sys_err), + "energy_sc": (["energy", "spatial"], energy_sc), + }, + coords={ + "energy": np.arange(n_energy), + "spatial": np.arange(n_spatial), + }, + ) + + esa_energies = xr.DataArray( + esa_energies_vals, + dims=["energy"], + coords={"energy": np.arange(n_energy)}, + ) + helio_energies = esa_energies.copy() + + result_ds = interpolate_map_flux_to_helio_frame( + map_ds, esa_energies, helio_energies, ["ena_intensity"] + ) + + result_flux = result_ds["ena_intensity"].values + + # All flux values should be non-negative + assert np.all(result_flux >= 0), "All interpolated flux values should be >= 0" + + def test_linear_and_powerlaw_mixed(self): + """Test correct interpolation method for mixed zero/positive flux.""" + n_energy = 3 + n_spatial = 4 + + esa_energies_vals = np.array([500.0, 1000.0, 2000.0]) + + # Create mixed flux data: + # - Pixel 0: zero at left boundary (needs linear) + # - Pixel 1: zero at right boundary (needs linear) + # - Pixel 2: all positive (can use power-law) + # - Pixel 3: zero at both (needs linear, result=0) + flux = np.array( + [ + [0.0, 1.0, 1.0, 0.0], # energy 0 + [1.0, 0.0, 2.0, 0.0], # energy 1 + [0.5, 0.5, 1.5, 0.5], # energy 2 + ] + ) + stat_unc = 0.1 * np.maximum(flux, 0.1) + sys_err = 0.05 * np.maximum(flux, 0.1) + + # Set energy_sc to be between energy channels 0 and 1 + energy_sc = np.full((n_energy, n_spatial), 750.0) + energy_sc[1, :] = 1500.0 + energy_sc[2, :] = 1800.0 + + map_ds = xr.Dataset( + { + "ena_intensity": (["energy", "spatial"], flux), + "ena_intensity_stat_uncert": (["energy", "spatial"], stat_unc), + "ena_intensity_sys_err": (["energy", "spatial"], sys_err), + "energy_sc": (["energy", "spatial"], energy_sc), + }, + coords={ + "energy": np.arange(n_energy), + "spatial": np.arange(n_spatial), + }, + ) + + esa_energies = xr.DataArray( + esa_energies_vals, + dims=["energy"], + coords={"energy": np.arange(n_energy)}, + ) + helio_energies = esa_energies.copy() + + result_ds = interpolate_map_flux_to_helio_frame( + map_ds, esa_energies, helio_energies, ["ena_intensity"] + ) + + result_flux = result_ds["ena_intensity"].values + + # Check that all pixels at energy 0 have finite, non-negative results + assert np.all(np.isfinite(result_flux[0, :])), ( + "All pixels should have finite results" + ) + assert np.all(result_flux[0, :] >= 0), "All flux values should be non-negative" + + # Pixel 0: Linear interpolation from 0 to 1 at 750eV should give positive + assert result_flux[0, 0] > 0, ( + "Pixel 0 should have positive flux (linear from 0 to 1)" + ) + + # Pixel 1: Linear interpolation from 1 to 0 at 750eV should give positive + assert result_flux[0, 1] > 0, ( + "Pixel 1 should have positive flux (linear from 1 to 0)" + ) + + # Pixel 2: Power-law interpolation should give positive + assert result_flux[0, 2] > 0, "Pixel 2 should have positive flux (power-law)" + + # Pixel 3: Both bounds zero, should be zero + assert result_flux[0, 3] == 0.0, "Pixel 3 should be zero (both bounds zero)" + + +class TestGetPsetDirectionalMask: + """Test suite for get_pset_direction_bin_mask function.""" + + @pytest.fixture + def pset_with_ram_mask(self): + """Create a test dataset with ram_mask for testing.""" + n_epoch = 2 + n_spin = 100 + n_energy = 3 + + # Create boolean mask with known pattern + # First half True (ram), second half False (anti-ram) + ram_mask_values = np.zeros((n_epoch, n_energy, n_spin), dtype=bool) + ram_mask_values[:, :, :50] = True + + # Create hae_longitude with the same shape for epochs + hae_lon_values = np.tile( + np.linspace(0, 360, n_spin, endpoint=False), (n_epoch, 1) + ) + + dataset = xr.Dataset( + { + "epoch": (["epoch"], np.array([1e18, 1.1e18])), + "ram_mask": ( + ["epoch", "esa_energy_step", "spin_angle_bin"], + ram_mask_values, + ), + "hae_longitude": ( + ["epoch", "spin_angle_bin"], + hae_lon_values, + ), + }, + coords={ + "esa_energy_step": np.arange(n_energy), + "spin_angle_bin": np.arange(n_spin), + }, + ) + + return dataset + + def test_invalid_direction_raises_error(self, pset_with_ram_mask): + """Test that invalid direction string raises ValueError.""" + with pytest.raises(ValueError, match="Invalid direction string"): + get_pset_directional_mask(pset_with_ram_mask, "invalid") + + def test_ram_direction_returns_ram_mask(self, pset_with_ram_mask): + """Test that 'ram' direction returns the ram_mask.""" + result = get_pset_directional_mask(pset_with_ram_mask, "ram") + + # Should return the ram_mask DataArray + assert isinstance(result, xr.DataArray) + assert result.name == "ram_mask" + + # Values should match the original ram_mask + np.testing.assert_array_equal( + result.values, pset_with_ram_mask["ram_mask"].values + ) + + def test_anti_direction_returns_inverted_mask(self, pset_with_ram_mask): + """Test that 'anti' direction returns inverted ram_mask.""" + result = get_pset_directional_mask(pset_with_ram_mask, "anti") + + # Should return a DataArray + assert isinstance(result, xr.DataArray) + + # Values should be inverted from the original ram_mask + expected = ~pset_with_ram_mask["ram_mask"] + np.testing.assert_array_equal(result.values, expected.values) + + def test_full_direction_returns_none(self, pset_with_ram_mask): + """Test that 'full' direction returns None.""" + result = get_pset_directional_mask(pset_with_ram_mask, "full") + + # Should return None + assert result is None + + def test_ram_mask_dimensions_preserved(self, pset_with_ram_mask): + """Test that returned mask has same dimensions as input ram_mask.""" + result = get_pset_directional_mask(pset_with_ram_mask, "ram") + + # Dimensions should match original ram_mask + assert result.dims == pset_with_ram_mask["ram_mask"].dims + assert result.shape == pset_with_ram_mask["ram_mask"].shape + + def test_anti_mask_dimensions_preserved(self, pset_with_ram_mask): + """Test that anti-ram mask has same dimensions as input ram_mask.""" + result = get_pset_directional_mask(pset_with_ram_mask, "anti") + + # Dimensions should match original ram_mask + assert result.dims == pset_with_ram_mask["ram_mask"].dims + assert result.shape == pset_with_ram_mask["ram_mask"].shape + + def test_ram_mask_boolean_type(self, pset_with_ram_mask): + """Test that returned masks are boolean type.""" + ram_result = get_pset_directional_mask(pset_with_ram_mask, "ram") + anti_result = get_pset_directional_mask(pset_with_ram_mask, "anti") + + assert ram_result.dtype == bool + assert anti_result.dtype == bool + + def test_ram_and_anti_are_complementary(self, pset_with_ram_mask): + """Test that ram and anti masks are complementary.""" + ram_mask = get_pset_directional_mask(pset_with_ram_mask, "ram") + anti_mask = get_pset_directional_mask(pset_with_ram_mask, "anti") + + # ram_mask and anti_mask should be complementary + # (no overlap, cover all pixels) + combined = ram_mask.values | anti_mask.values + assert np.all(combined), "RAM and anti-RAM masks should cover all pixels" + + overlap = ram_mask.values & anti_mask.values + assert not np.any(overlap), "RAM and anti-RAM masks should not overlap" + + def test_with_1d_spatial_dimension(self): + """Test with 1D spatial dimension (like HiPointingSet).""" + n_spin = 50 + + # Create dataset with 1D spatial dimension + ram_mask_values = np.zeros(n_spin, dtype=bool) + ram_mask_values[:25] = True # First half is ram + + dataset = xr.Dataset( + { + "ram_mask": (["spin_angle_bin"], ram_mask_values), + "hae_longitude": ( + ["spin_angle_bin"], + np.linspace(0, 360, n_spin, endpoint=False), + ), + }, + coords={"spin_angle_bin": np.arange(n_spin)}, + ) + + ram_result = get_pset_directional_mask(dataset, "ram") + anti_result = get_pset_directional_mask(dataset, "anti") + + # Verify shape is preserved + assert ram_result.shape == (n_spin,) + assert anti_result.shape == (n_spin,) + + # Verify values + assert np.sum(ram_result.values) == 25 + assert np.sum(anti_result.values) == 25 + + def test_with_2d_spatial_dimension(self): + """Test with 2D spatial dimension (like LoPointingSet).""" + n_spin = 20 + n_off = 10 + + # Create dataset with 2D spatial dimensions + ram_mask_values = np.zeros((n_spin, n_off), dtype=bool) + ram_mask_values[:10, :] = True # First half of spin dimension is ram + + dataset = xr.Dataset( + { + "ram_mask": (["spin_angle", "off_angle"], ram_mask_values), + "hae_longitude": ( + ["spin_angle", "off_angle"], + np.tile( + np.linspace(0, 360, n_spin, endpoint=False)[:, np.newaxis], + (1, n_off), + ), + ), + }, + coords={ + "spin_angle": np.arange(n_spin), + "off_angle": np.arange(n_off), + }, + ) + + ram_result = get_pset_directional_mask(dataset, "ram") + anti_result = get_pset_directional_mask(dataset, "anti") + + # Verify shape is preserved + assert ram_result.shape == (n_spin, n_off) + assert anti_result.shape == (n_spin, n_off) + + # Verify values + assert np.sum(ram_result.values) == 10 * n_off + assert np.sum(anti_result.values) == 10 * n_off diff --git a/imap_processing/tests/ena_maps/test_ena_maps.py b/imap_processing/tests/ena_maps/test_ena_maps.py index a7b460dfec..d2fa53b80f 100644 --- a/imap_processing/tests/ena_maps/test_ena_maps.py +++ b/imap_processing/tests/ena_maps/test_ena_maps.py @@ -4,9 +4,11 @@ import json import tempfile +import warnings from copy import deepcopy from pathlib import Path from unittest import mock +from unittest.mock import patch import astropy_healpix.healpy as hp import numpy as np @@ -19,6 +21,7 @@ from imap_processing.ena_maps.utils import spatial_utils from imap_processing.ena_maps.utils.coordinates import CoordNames from imap_processing.spice import geometry +from imap_processing.spice.time import met_to_ttj2000ns, ttj2000ns_to_et @pytest.fixture(autouse=True, scope="module") @@ -75,7 +78,10 @@ def test_instantiate(self): ultra_pset.num_points, hp.nside2npix(self.nside), ) - + # check that the midpoint_j2000_et property is equal to the expected value + assert ultra_pset.midpoint_j2000_et == ttj2000ns_to_et( + ultra_pset.epoch + self.l1c_pset_products[0].epoch_delta[0] / 2 + ) # Check the repr exists assert "UltraPointingSet" in repr(ultra_pset) @@ -92,6 +98,16 @@ def test_instantiate(self): "energy_bin_geometric_mean", ) + # TODO remove this test when the TODO in the ultra downsample_counts function is + # removed. + def test_old_pset(self): + pset = self.l1c_pset_products[0] + pset = pset.drop_dims("counts_pixel_index") + pset = ena_maps.UltraPointingSet( + pset, + spice_reference_frame=geometry.SpiceFrame.IMAP_DPS, + ) + @pytest.mark.usefixtures("_setup_ultra_l1c_pset_products") def test_init_cdf( self, @@ -100,10 +116,14 @@ def test_init_cdf( cdf_filepath = write_cdf(ultra_pset, istp=False) - ultra_pset_from_dataset = ena_maps.UltraPointingSet(ultra_pset) - - ultra_pset_from_str = ena_maps.UltraPointingSet(cdf_filepath) - ultra_pset_from_path = ena_maps.UltraPointingSet(Path(cdf_filepath)) + # Mock the downsample_counts method to avoid dimension bugs + # since this is a dummy cdf, the dimensions are not present. + with patch.object( + ena_maps.UltraPointingSet, "downsample_counts", lambda self: None + ): + ultra_pset_from_str = ena_maps.UltraPointingSet(cdf_filepath) + ultra_pset_from_path = ena_maps.UltraPointingSet(Path(cdf_filepath)) + ultra_pset_from_dataset = ena_maps.UltraPointingSet(ultra_pset) np.testing.assert_allclose( ultra_pset_from_dataset.data["counts"].values, @@ -117,7 +137,6 @@ def test_init_cdf( rtol=1e-6, ) - @pytest.mark.usefixtures("_setup_ultra_l1c_pset_products") @pytest.mark.usefixtures("_setup_ultra_l1c_pset_products") def test_different_spacing_raises_error(self): """Test that different spaced az/el from the L1C dataset raises ValueError""" @@ -134,6 +153,23 @@ def test_different_spacing_raises_error(self): spice_reference_frame=geometry.SpiceFrame.IMAP_DPS, ) + def test_downsample_counts(self): + ultra_pset = self.l1c_pset_products[0] + + # First check that counts are at a finer resolution than exposure factor + counts_npix_before = ultra_pset["counts"].shape[-1] + assert counts_npix_before != ultra_pset["exposure_factor"].shape[-1] + pset = ena_maps.UltraPointingSet(ultra_pset) + + # Verify counts are now at the same resolution as pset + counts_nside_after = hp.npix2nside(pset.data["counts"].shape[-1]) + assert counts_nside_after == pset.nside + + # Verify counts are the same after downsampling. + np.testing.assert_allclose( + pset.data["counts"].values.sum(), ultra_pset["counts"].values.sum() + ) + @pytest.fixture(scope="module") def hi_pset_cdf_path(imap_tests_path): @@ -147,47 +183,30 @@ class TestHiPointingSet: def test_init(self, hi_pset_cdf_path): """Test coverage for __init__ method.""" pset_ds = load_cdf(hi_pset_cdf_path) - hi_pset = ena_maps.HiPointingSet(pset_ds, spin_phase="full") + delta = 10 + pset_ds["epoch_delta"] = ("epoch", np.array([delta])) # Add dummy epoch delta + hi_pset = ena_maps.HiPointingSet(pset_ds) assert isinstance(hi_pset, ena_maps.HiPointingSet) - assert hi_pset.spice_reference_frame == geometry.SpiceFrame.ECLIPJ2000 + assert hi_pset.spice_reference_frame == geometry.SpiceFrame.IMAP_HAE assert hi_pset.num_points == 3600 np.testing.assert_array_equal(hi_pset.az_el_points.shape, (3600, 2)) - - for var_name in ["exposure_factor", "bg_rates", "bg_rates_unc"]: + # check that the midpoint_j2000_et property is equal to the expected value + assert hi_pset.midpoint_j2000_et == ttj2000ns_to_et(hi_pset.epoch + delta / 2) + for var_name in ["exposure_factor", "bg_rate", "bg_rate_sys_err"]: assert var_name in hi_pset.data def test_from_cdf(self, hi_pset_cdf_path): """Test coverage for instantiating HiPointingSet from cdf.""" - hi_pset = ena_maps.HiPointingSet(hi_pset_cdf_path, spin_phase="full") + hi_pset = ena_maps.HiPointingSet(hi_pset_cdf_path) assert isinstance(hi_pset, ena_maps.HiPointingSet) - def test_spin_phase_filtering(self, hi_pset_cdf_path): - """Test coverage for filtering pset data by ram or anti-ram directions.""" - pset_ds = load_cdf(hi_pset_cdf_path) - - # Test ram only direction - hi_pset = ena_maps.HiPointingSet(pset_ds, spin_phase="ram") - assert hi_pset.num_points == 1800 - np.testing.assert_array_equal( - hi_pset.data["spin_angle_bin"].data, np.arange(1800) - ) - - # Test anti-ram direction - hi_pset = ena_maps.HiPointingSet(pset_ds, spin_phase="anti-ram") - assert hi_pset.num_points == 1800 - np.testing.assert_array_equal( - hi_pset.data["spin_angle_bin"].data, np.arange(1800) + 1800 - ) - - # Test value error - with pytest.raises(ValueError, match="Unrecognized spin_phase value:"): - _ = ena_maps.HiPointingSet(pset_ds, spin_phase="foo-phase") - def test_plays_nice_with_rectangular_sky_map(self, hi_pset_cdf_path): """Test that HiPointingSet works with RectangularSkyMap""" - hi_pset = ena_maps.HiPointingSet(hi_pset_cdf_path, spin_phase="full") + hi_ds = load_cdf(hi_pset_cdf_path) + hi_ds["epoch_delta"] = ("epoch", np.array([0])) # Add dummy epoch delta + hi_pset = ena_maps.HiPointingSet(hi_ds) rect_map = ena_maps.RectangularSkyMap( - spacing_deg=2, spice_frame=geometry.SpiceFrame.ECLIPJ2000 + spacing_deg=2, spice_frame=geometry.SpiceFrame.IMAP_HAE ) rect_map.project_pset_values_to_map(hi_pset, ["counts", "exposure_factor"]) assert rect_map.data_1d["counts"].max() > 0 @@ -234,6 +253,16 @@ def lo_pset_ds(): dims=["epoch"], name="epoch", ) + dataset.coords["pointing_start_met"] = xr.DataArray( + [1], + dims=["epoch"], + name="epoch", + ) + dataset.coords["pointing_end_met"] = xr.DataArray( + [10], + dims=["epoch"], + name="epoch", + ) dataset.coords["spin_angle"] = xr.DataArray( [i for i in range(3600)], dims=["spin_angle"], @@ -275,6 +304,15 @@ def test_init(self, lo_pset_ds): assert lo_pset.num_points == 144000 np.testing.assert_array_equal(lo_pset.az_el_points.shape, (144000, 2)) + # check that the midpoint_j2000_et property is equal to the expected value + assert lo_pset.midpoint_j2000_et == ttj2000ns_to_et( + lo_pset.epoch + + ( + met_to_ttj2000ns(lo_pset_ds.pointing_end_met) + - met_to_ttj2000ns(lo_pset_ds.pointing_start_met) + ) + / 2 + ) for var_name in ["exposure_time", "h_counts"]: assert var_name in lo_pset.data @@ -290,6 +328,162 @@ def test_plays_nice_with_rectangular_sky_map(self, lo_pset_ds): assert rect_map.data_1d["h_counts"].max() > 0 +@pytest.mark.external_test_data +class TestLoHiBasePointingSet: + """Test suite for LoHiBasePointingSet class and its subclasses.""" + + @staticmethod + def create_hi_pset_with_multidim_coords( + hi_pset_cdf_path: str, + shape: tuple[int, int, int] = (1, 9, 3600), + ) -> ena_maps.HiPointingSet: + """ + Create a HiPointingSet with multi-dimensional coordinates. + + Parameters + ---------- + hi_pset_cdf_path : str + Path to the Hi PSET CDF file. + shape : tuple[int, int, int], optional + Shape of the coordinates (epoch, hf_energy, spin_angle_bin). + Default is (1, 9, 3600). + + Returns + ------- + ena_maps.HiPointingSet + HiPointingSet with multi-dimensional az_el_points. + """ + pset_ds = load_cdf(hi_pset_cdf_path) + pset_ds["epoch_delta"] = ("epoch", np.array([0])) # Add dummy epoch delta + hi_pset = ena_maps.HiPointingSet(pset_ds) + hi_pset.data["hae_longitude"] = xr.DataArray( + np.random.uniform(0, 360, shape), + dims=["epoch", "hf_energy", "spin_angle_bin"], + ) + hi_pset.data["hae_latitude"] = xr.DataArray( + np.random.uniform(-90, 90, shape), + dims=["epoch", "hf_energy", "spin_angle_bin"], + ) + hi_pset.update_az_el_points() + return hi_pset + + def test_hi_az_el_points_is_dataarray(self, hi_pset_cdf_path): + """Test that HiPointingSet.az_el_points is an xarray.DataArray.""" + hi_pset = ena_maps.HiPointingSet(hi_pset_cdf_path) + + # Verify az_el_points is a DataArray + assert isinstance(hi_pset.az_el_points, xr.DataArray) + + # Verify dimensions + assert hi_pset.az_el_points.dims == ("pixel", CoordNames.AZ_EL_VECTOR.value) + + # Verify shape + assert hi_pset.az_el_points.shape == (3600, 2) + + def test_lo_az_el_points_is_dataarray(self, lo_pset_ds): + """Test that LoPointingSet.az_el_points is an xarray.DataArray.""" + lo_pset = ena_maps.LoPointingSet(lo_pset_ds) + + # Verify az_el_points is a DataArray + assert isinstance(lo_pset.az_el_points, xr.DataArray) + + # Verify dimensions + assert lo_pset.az_el_points.dims == ("pixel", CoordNames.AZ_EL_VECTOR.value) + + # Verify shape + assert lo_pset.az_el_points.shape == (144000, 2) + + def test_inheritance(self, hi_pset_cdf_path, lo_pset_ds): + """Test that Hi and Lo pointing sets inherit from LoHiBasePointingSet.""" + hi_pset = ena_maps.HiPointingSet(hi_pset_cdf_path) + lo_pset = ena_maps.LoPointingSet(lo_pset_ds) + + # Verify inheritance + assert isinstance(hi_pset, ena_maps.LoHiBasePointingSet) + assert isinstance(lo_pset, ena_maps.LoHiBasePointingSet) + + # Verify tiling type is set correctly + assert hi_pset.tiling_type == ena_maps.SkyTilingType.RECTANGULAR + assert lo_pset.tiling_type == ena_maps.SkyTilingType.RECTANGULAR + + def test_update_az_el_points_multidimensional(self, hi_pset_cdf_path): + """Test update_az_el_points with multi-dimensional coordinates.""" + hi_pset = self.create_hi_pset_with_multidim_coords(hi_pset_cdf_path) + + # Verify az_el_points is still a DataArray + assert isinstance(hi_pset.az_el_points, xr.DataArray) + + # Verify dimensions are preserved (epoch squeezed, pixel stacked) + assert hi_pset.az_el_points.dims == ( + "hf_energy", + "pixel", + CoordNames.AZ_EL_VECTOR.value, + ) + + # Verify shape + assert hi_pset.az_el_points.shape == (9, 3600, 2) + + @mock.patch("imap_processing.spice.geometry.frame_transform_az_el") + def test_multidim_az_el_points_with_match_coords( + self, mock_frame_transform, hi_pset_cdf_path + ): + """Test multi-dimensional az_el_points with match_coords_to_indices.""" + # Mock frame_transform to return az_el unchanged + mock_frame_transform.side_effect = ( + lambda et, az_el, from_frame, to_frame, degrees: az_el + ) + + hi_pset = self.create_hi_pset_with_multidim_coords(hi_pset_cdf_path) + + # Create a rectangular map + rect_map = ena_maps.RectangularSkyMap( + spacing_deg=6, spice_frame=geometry.SpiceFrame.ECLIPJ2000 + ) + + # Match coordinates to indices + indices = ena_maps.match_coords_to_indices(hi_pset, rect_map) + + # Verify output is DataArray with preserved dimensions + assert isinstance(indices, xr.DataArray) + assert indices.dims == ("hf_energy", "pixel") + assert indices.shape == (9, 3600) + + @mock.patch("imap_processing.spice.geometry.frame_transform_az_el") + def test_broadcasting_with_multidim_pset( + self, mock_frame_transform, hi_pset_cdf_path + ): + """Test xr broadcasting in project_pset_values_to_map with multi-dim PSET.""" + # Mock frame_transform to return az_el unchanged + mock_frame_transform.side_effect = ( + lambda et, az_el, from_frame, to_frame, degrees: az_el + ) + + hi_pset = self.create_hi_pset_with_multidim_coords(hi_pset_cdf_path) + + # Add a mock multi-dimensional variable to the PSET + # Shape: (epoch, hf_energy, spin_angle_bin) + hi_pset.data["mock_flux"] = xr.DataArray( + np.random.uniform(0, 100, (1, 9, 3600)), + dims=["epoch", "hf_energy", "spin_angle_bin"], + ) + + # Create a rectangular map + rect_map = ena_maps.RectangularSkyMap( + spacing_deg=6, spice_frame=geometry.SpiceFrame.ECLIPJ2000 + ) + + # Project the multi-dimensional data to the map + rect_map.project_pset_values_to_map(hi_pset, ["mock_flux"]) + + # Verify the projection succeeded and has correct dimensions + assert "mock_flux" in rect_map.data_1d + # Expected dims: (epoch, hf_energy, pixel) + assert rect_map.data_1d["mock_flux"].dims == ("epoch", "hf_energy", "pixel") + assert rect_map.data_1d["mock_flux"].shape[0] == 1 # epoch + assert rect_map.data_1d["mock_flux"].shape[1] == 9 # hf_energy + assert rect_map.data_1d["mock_flux"].shape[2] == rect_map.num_points # pixel + + class TestRectangularSkyMap: @pytest.fixture(autouse=True) def _setup_ultra_l1c_pset_products(self, setup_all_pset_products): @@ -478,7 +672,13 @@ def test_project_rect_pset_values_to_map_push_method( ) @pytest.mark.usefixtures("_setup_ultra_l1c_pset_products") - def test_project_pset_values_to_map_errors(self): + @mock.patch("imap_processing.spice.geometry.frame_transform_az_el") + def test_project_pset_values_to_map_errors(self, mock_frame_transform_az_el): + # Mock frame_transform to return the az and el unchanged + mock_frame_transform_az_el.side_effect = ( + lambda et, az_el, from_frame, to_frame, degrees: az_el + ) + index_matching_method = ena_maps.IndexMatchMethod.PUSH rectangular_map = ena_maps.RectangularSkyMap( spacing_deg=1, @@ -486,13 +686,144 @@ def test_project_pset_values_to_map_errors(self): ) # An error should be raised if a key is not found in the PSET - with pytest.raises(ValueError, match="Value key invalid not found"): + with pytest.raises(KeyError, match="Value keys not found in pointing set:"): rectangular_map.project_pset_values_to_map( self.ultra_psets[0], value_keys=["invalid"], index_match_method=index_matching_method, ) + @pytest.mark.usefixtures("_setup_ultra_l1c_pset_products") + @mock.patch("imap_processing.spice.geometry.frame_transform_az_el") + def test_project_pset_with_valid_mask_push(self, mock_frame_transform_az_el): + """Test projection with pset_valid_mask using PUSH method.""" + # Mock frame_transform to return the az and el unchanged + mock_frame_transform_az_el.side_effect = ( + lambda et, az_el, from_frame, to_frame, degrees: az_el + ) + + rectangular_map = ena_maps.RectangularSkyMap( + spacing_deg=2, + spice_frame=geometry.SpiceFrame.ECLIPJ2000, + ) + + ultra_pset = self.ultra_psets[0] + ultra_pset.data["counts"] = xr.ones_like(ultra_pset.data["counts"]) + + # Create a mask that only allows half of the pixels + valid_mask = np.zeros(ultra_pset.num_points, dtype=bool) + valid_mask[: ultra_pset.num_points // 2] = True + + # Project with mask + rectangular_map.project_pset_values_to_map( + ultra_pset, + value_keys=["counts"], + index_match_method=ena_maps.IndexMatchMethod.PUSH, + pset_valid_mask=valid_mask, + ) + + # Total counts in map should be less than total counts in pset + map_total_counts = rectangular_map.data_1d["counts"].sum() + pset_total_counts = ultra_pset.data["counts"].sum() + + # With mask, map should have approximately half the counts + assert map_total_counts < pset_total_counts + np.testing.assert_allclose( + map_total_counts, + pset_total_counts / 2, + rtol=0.1, + ) + + @pytest.mark.usefixtures("_setup_rectangular_l1c_pset_products") + @mock.patch("imap_processing.spice.geometry.frame_transform_az_el") + def test_project_pset_with_dataarray_mask_push(self, mock_frame_transform_az_el): + """Test projection with xr.DataArray mask using PUSH method.""" + # Mock frame_transform to return the az and el unchanged + mock_frame_transform_az_el.side_effect = ( + lambda et, az_el, from_frame, to_frame, degrees: az_el + ) + + rectangular_map = ena_maps.RectangularSkyMap( + spacing_deg=10, + spice_frame=geometry.SpiceFrame.ECLIPJ2000, + ) + + rect_pset = self.rectangular_psets[0] + + # Set all counts to a uniform non-zero value + rect_pset.data["counts"] = xr.full_like( + rect_pset.data["counts"], fill_value=10.0 + ) + + # Create a DataArray mask matching the pset spatial dimensions + valid_mask = xr.DataArray( + np.ones(rect_pset.data["counts"].shape[2:], dtype=bool), + coords={ + "longitude": rect_pset.data["longitude"], + "latitude": rect_pset.data["latitude"], + }, + ) + # Mask out one quadrant + valid_mask_shape = valid_mask.shape + valid_mask[: valid_mask_shape[0] // 2, : valid_mask_shape[1] // 2] = False + + # Project with DataArray mask + rectangular_map.project_pset_values_to_map( + rect_pset, + value_keys=["counts"], + index_match_method=ena_maps.IndexMatchMethod.PUSH, + pset_valid_mask=valid_mask, + ) + + # Map should have data + assert "counts" in rectangular_map.data_1d + assert rectangular_map.data_1d["counts"].sum() > 0 + + # Check that pixel mask reduces total map counts to ~3/4 of pset counts + total_pset_counts = rect_pset.data["counts"].sum() + expected_map_counts = total_pset_counts * 3 / 4 # Only half should be included + actual_map_counts = rectangular_map.data_1d["counts"].sum() + np.testing.assert_allclose( + actual_map_counts, + expected_map_counts, + rtol=0.1, + err_msg=("Mask filtering failed"), + ) + + @pytest.mark.usefixtures("_setup_rectangular_l1c_pset_products") + @mock.patch("imap_processing.spice.geometry.frame_transform_az_el") + def test_project_pset_with_valid_mask_pull(self, mock_frame_transform_az_el): + """Test projection with pset_valid_mask using PULL method.""" + # Mock frame_transform to return the az and el unchanged + mock_frame_transform_az_el.side_effect = ( + lambda et, az_el, from_frame, to_frame, degrees: az_el + ) + + rectangular_map = ena_maps.RectangularSkyMap( + spacing_deg=10, + spice_frame=geometry.SpiceFrame.ECLIPJ2000, + ) + + rect_pset = self.rectangular_psets[0] + + # Create a mask that masks out some pixels + valid_mask = np.ones(rect_pset.num_points, dtype=bool) + valid_mask[: rect_pset.num_points // 4] = False + + # Project with mask using PULL method + rectangular_map.project_pset_values_to_map( + rect_pset, + value_keys=["counts"], + index_match_method=ena_maps.IndexMatchMethod.PULL, + pset_valid_mask=valid_mask, + ) + + # Map should have data, but some pixels should be zero due to mask + assert "counts" in rectangular_map.data_1d + assert rectangular_map.data_1d["counts"].sum() > 0 + # Some pixels should be zero + assert (rectangular_map.data_1d["counts"] == 0).any() + @pytest.mark.usefixtures("_setup_rectangular_l1c_pset_products") @mock.patch("imap_processing.spice.geometry.frame_transform_az_el") def test_project_rect_pset_values_to_map_pull_method( @@ -617,12 +948,27 @@ def mock_data_for_build_cdf_dataset(self): name="ena_intesity", dims=[k for k in coord_sizes.keys()][:-1], ) - # Add one variable that is expected to get removed - mock_dataset["foo_var"] = xr.DataArray( + # Add one variable that is expected to get removed because it has a + # dimension that is not in the list of `coord_names` + mock_dataset["extra_dimension_var"] = xr.DataArray( np.ones(tuple(s for s in coord_sizes.values())), - name="foo_var", + name="extra_dimension_var", dims=[k for k in coord_sizes.keys()], ) + # Add a variable that is expected to get removed because it has no + # attributes defined + mock_dataset["no_attr_var"] = xr.DataArray( + np.ones(tuple(s for s in coord_sizes.values())[:-1]), + name="no_attr_var", + dims=[k for k in coord_sizes.keys()][:-1], + ) + # Add required energy delta variables + for side in ["minus", "plus"]: + mock_dataset[f"{CoordNames.ENERGY_L2.value}_delta_{side}"] = xr.DataArray( + np.ones_like(mock_dataset[CoordNames.ENERGY_L2.value].data), + name=f"{CoordNames.ENERGY_L2.value}_delta_{side}", + dims=[CoordNames.ENERGY_L2.value], + ) return mock_dataset @mock.patch("imap_processing.ena_maps.ena_maps.RectangularSkyMap.to_dataset") @@ -635,20 +981,38 @@ def test_build_cdf_dataset(self, mock_to_dataset, mock_data_for_build_cdf_datase skymap.min_epoch = 10 skymap.max_epoch = 15 cdf_dataset = skymap.build_cdf_dataset( - "hi", "l2", "sf", "foo_descriptor", sensor="45" + "hi", + "l2", + "h45-ena-h-sf-nsp-ram-hae-6deg-6mo", + sensor="45", + drop_vars_with_no_attributes=True, ) - # Check that expected var gets removed - assert "foo_var" not in cdf_dataset + # Check that expected vars gets removed + assert "extra_dimension_var" not in cdf_dataset + assert "no_attr_var" not in cdf_dataset # Check the epoch values assert CoordNames.TIME.value in cdf_dataset assert cdf_dataset[CoordNames.TIME.value].values[0] == skymap.min_epoch + # Check epoch_delta + assert ( + cdf_dataset[CoordNames.TIME.value].attrs["DELTA_PLUS_VAR"] + == f"{CoordNames.TIME.value}_delta" + ) + assert ( + cdf_dataset[CoordNames.TIME.value].attrs["DELTA_MINUS_VAR"] + == f"{CoordNames.TIME.value}_delta_minus" + ) assert f"{CoordNames.TIME.value}_delta" in cdf_dataset assert ( cdf_dataset[f"{CoordNames.TIME.value}_delta"].values[0] == skymap.max_epoch - skymap.min_epoch ) + # Check epoch_delta_minus + assert f"{CoordNames.TIME.value}_delta_minus" in cdf_dataset + assert cdf_dataset[f"{CoordNames.TIME.value}_delta_minus"].values == 0 + # Energy related checks assert CoordNames.ENERGY_L2.value in cdf_dataset assert f"{CoordNames.ENERGY_L2.value}_delta_plus" in cdf_dataset assert f"{CoordNames.ENERGY_L2.value}_delta_minus" in cdf_dataset @@ -662,34 +1026,107 @@ def test_build_cdf_dataset(self, mock_to_dataset, mock_data_for_build_cdf_datase assert f"{CoordNames.ELEVATION_L2.value}_delta" in cdf_dataset assert f"{CoordNames.ELEVATION_L2.value}_label" in cdf_dataset + # Check that coordinate variables don't have the following variable attributes + not_coord_attrs = ["DEPEND_0", "DISPLAY_TYPE"] + for var in [ + CoordNames.TIME.value, + CoordNames.ENERGY_L2.value, + CoordNames.AZIMUTH_L2.value, + CoordNames.ELEVATION_L2.value, + ]: + for attr in not_coord_attrs: + assert attr not in cdf_dataset[var].attrs, ( + f"attr '{attr}' should not be in variable attributes for '{var}'" + ) + + # Check CATDESC made from descriptor + assert ( + cdf_dataset["ena_intensity"].attrs["CATDESC"] + == "IMAP Hi45 H Inten, HAE SC Frame, No Surv Corr, Ram, 6 deg, 6 Mon" + ) + + @mock.patch("imap_processing.ena_maps.ena_maps.RectangularSkyMap.to_dataset") + def test_build_cdf_dataset_external_dataset( + self, mock_to_dataset, mock_data_for_build_cdf_dataset + ): + """Test coverage for the RectangularSkyMap.build_cdf_dataset method.""" + # Set up the mock + mock_to_dataset.return_value = mock_data_for_build_cdf_dataset + + skymap = ena_maps.RectangularSkyMap(6, geometry.SpiceFrame.ECLIPJ2000) + skymap.min_epoch = 10 + skymap.max_epoch = 15 + cdf_dataset_standard = skymap.build_cdf_dataset( + "hi", + "l2", + "h45-ena-h-sf-nsp-ram-hae-6deg-6mo", + sensor="45", + drop_vars_with_no_attributes=True, + ) + cdf_dataset_external = skymap.build_cdf_dataset( + "hi", + "l2", + "h45-ena-h-sf-nsp-ram-hae-6deg-6mo", + sensor="45", + drop_vars_with_no_attributes=True, + external_map_dataset=mock_data_for_build_cdf_dataset, + ) + assert cdf_dataset_standard.equals(cdf_dataset_external) + @mock.patch("imap_processing.ena_maps.ena_maps.RectangularSkyMap.to_dataset") def test_build_cdf_dataset_key_error( self, mock_to_dataset, mock_data_for_build_cdf_dataset ): """Test build_cdf_dataset raising a KeyError.""" mock_dataset = mock_data_for_build_cdf_dataset - # Add ena intensity variable - mock_dataset["no_attrs_var"] = xr.DataArray( - np.ones( - tuple(s for s in mock_data_for_build_cdf_dataset.coords.sizes.values())[ - :-1 - ] - ), - name="no_attrs_var", - dims=[k for k in mock_data_for_build_cdf_dataset.coords.sizes.keys()][:-1], - ) mock_to_dataset.return_value = mock_dataset skymap = ena_maps.RectangularSkyMap(6, geometry.SpiceFrame.ECLIPJ2000) skymap.min_epoch = 10 skymap.max_epoch = 15 + + # Test that missing energy delta variable raise KeyError + # Test for missing energy_delta_plus + mock_dataset = mock_dataset.drop_vars(["energy_delta_plus"]) + mock_to_dataset.return_value = mock_dataset with pytest.raises( - KeyError, match="Attributes for variable no_attrs_var not found" + KeyError, + match="Required variable 'energy_delta_plus' not found in cdf Dataset.", + ): + _ = skymap.build_cdf_dataset("hi", "l2", "foo_descriptor", sensor="45") + # Test for missing energy_delta_minus + mock_dataset = mock_dataset.drop_vars(["energy_delta_minus"]) + mock_to_dataset.return_value = mock_dataset + with pytest.raises( + KeyError, + match="Required variable 'energy_delta_minus' not found in cdf Dataset.", ): _ = skymap.build_cdf_dataset( - "hi", "l2", "sf", "foo_descriptor", sensor="45" + "hi", "l2", "h45-ena-h-sf-nsp-ram-hae-6deg-6mo", sensor="45" ) + @mock.patch("imap_processing.ena_maps.ena_maps.RectangularSkyMap.to_dataset") + def test_keep_vars_with_no_attributes( + self, mock_to_dataset, mock_data_for_build_cdf_dataset + ): + """Test that variables with no attributes are kept when desired.""" + # Set up the mock + mock_to_dataset.return_value = mock_data_for_build_cdf_dataset + + skymap = ena_maps.RectangularSkyMap(6, geometry.SpiceFrame.ECLIPJ2000) + skymap.min_epoch = 10 + skymap.max_epoch = 15 + cdf_dataset = skymap.build_cdf_dataset( + "hi", + "l2", + "h45-ena-h-sf-nsp-ram-hae-6deg-6mo", + sensor="45", + drop_vars_with_no_attributes=False, + ) + + # Check that expected var was not removed + assert "no_attr_var" in cdf_dataset + class TestHealpixSkyMap: @pytest.fixture(autouse=True) @@ -975,18 +1412,19 @@ def test_calculate_rect_pixel_value_from_healpix_map_n_subdivisions( (179.5, -0.5): 10, (179.5, 0.5): 11, (179.5, 1.5): 12, - (180.5, -1.5): 12, + (180.5, -1.5): 13, (180.5, -0.5): 14, (180.5, 0.5): 15, (180.5, 1.5): 16, (181.5, -1.5): 17, (181.5, -0.5): 18, (181.5, 0.5): 19, - (181.5, 1.5): 20, + # Set the final entry to 999 to identify a pixel that will be set to NaN + (181.5, 1.5): 999, } expected_mean_0_subdivisions = 0 expected_mean_1_subdivisions = 2.5 - expected_mean_2_subdivisions = 12.5 + expected_mean_2_subdivisions = 12 def mock_ang2pix_fn(nside, theta, phi, nest=True, lonlat=False): vals = [] @@ -1002,10 +1440,11 @@ def mock_ang2pix_fn(nside, theta, phi, nest=True, lonlat=False): ) hp_map.data_1d["counts"] = xr.DataArray( data=[ - np.arange(hp_map.num_points), + np.arange(hp_map.num_points, dtype=float), ], dims=["epoch", "pixel"], ) + hp_map.data_1d["counts"][0, 999] = np.nan for num_subdiv, (expected_value, atol) in enumerate( [ @@ -1013,7 +1452,7 @@ def mock_ang2pix_fn(nside, theta, phi, nest=True, lonlat=False): (expected_mean_0_subdivisions, 1e-9), (expected_mean_1_subdivisions, 1e-9), # Slight difference from not taking into account asym solid angle - (expected_mean_2_subdivisions, 0.1), + (expected_mean_2_subdivisions, 1e-4), ] ): mock_ang2pix.reset_mock() @@ -1039,6 +1478,64 @@ def mock_ang2pix_fn(nside, theta, phi, nest=True, lonlat=False): num_subdivisions=0, ) + @mock.patch("astropy_healpix.healpy.ang2pix") + def test_calculate_rect_pixel_value_outputs_fill_for_pixels_with_zero_non_fill_vals( + self, + mock_ang2pix, + ): + """Test getting rectangular pixel values from HealpixSkyMap via subdivision.""" + + # Mock ang2pix to return fixed values based on a dict + pixel_dict = { + # 0 subdiv - just 1 pixel + (180, 0): 0, + # 1 subdiv - all subpix have same solid angle because centered on equator + (179, -1): 999, + (179, 1): 999, + (181, -1): 999, + (181, 1): 999, + } + + def mock_ang2pix_fn(nside, theta, phi, nest=True, lonlat=False): + vals = [] + for pix_num in range(len(theta)): + key = (theta[pix_num], phi[pix_num]) + vals.append(pixel_dict.get(key, 0)) + return np.array(vals) + + mock_ang2pix.side_effect = mock_ang2pix_fn + + hp_map = ena_maps.HealpixSkyMap( + nside=16, + spice_frame=geometry.SpiceFrame.ECLIPJ2000, + nested=True, + ) + hp_map.data_1d["counts"] = xr.DataArray( + data=[ + np.arange(hp_map.num_points, dtype=float), + ], + dims=["epoch", "pixel"], + ) + hp_map.data_1d["counts"][0, 999] = np.nan + + with warnings.catch_warnings(record=True) as w: + mean_value = ( + hp_map.calculate_rect_pixel_value_from_healpix_map_n_subdivisions( + rect_pix_center_lon_lat=(180, 0), + rect_pix_spacing_deg=4, + value_array=hp_map.data_1d["counts"], + num_subdivisions=1, + ) + ) + + assert len(w) == 0, "Should not raise RuntimeWarning for dividing by zero" + + np.testing.assert_allclose( + mean_value, + np.nan, + err_msg=f"Failed for num_subdivisions: {1}", + ) + @mock.patch( "imap_processing.ena_maps.ena_maps.HealpixSkyMap.calculate_rect_pixel_value_from_healpix_map_n_subdivisions" ) @@ -1200,20 +1697,23 @@ def test_match_coords_to_indices_rect_pset_to_rect_map( self.rectangular_l1c_pset_products[0], spice_reference_frame=geometry.SpiceFrame.IMAP_DPS, ) - manual_az_el_coords = np.array( - [ - [0, -90], # always -> RectangularSkyMap pixel 0 - [0.4999999, -90], - [180.5, -89.5], - [359.5, -89.5], - [0.5, 0], - [180.5, 0], - [359.5, 0], - [0.5, 89.5], - [180.5, 89.5], - [359.5, 89.5], - [359.999999, 89.99999], - ] + manual_az_el_coords = xr.DataArray( + np.array( + [ + [0, -90], # always -> RectangularSkyMap pixel 0 + [0.4999999, -90], + [180.5, -89.5], + [359.5, -89.5], + [0.5, 0], + [180.5, 0], + [359.5, 0], + [0.5, 89.5], + [180.5, 89.5], + [359.5, 89.5], + [359.999999, 89.99999], + ] + ), + dims=["pixel", "az_el_coords"], ) mock_pset_input_frame.az_el_points = manual_az_el_coords @@ -1251,6 +1751,82 @@ def test_match_coords_to_indices_rect_pset_to_rect_map( atol=map_spacing_deg, ) + @mock.patch("imap_processing.spice.geometry.frame_transform_az_el") + def test_match_coords_to_indices_multi_dimensional_input( + self, mock_frame_transform_az_el + ): + """Test that match_coords_to_indices works for multi-dimensional arrays.""" + map_spacing_deg = 6 + # Mock frame_transform to return the az and el unchanged + mock_frame_transform_az_el.side_effect = ( + lambda et, az_el, from_frame, to_frame, degrees: az_el + ) + + # Mock a PSET, overriding the az/el points + mock_pset_input_frame = ena_maps.RectangularPointingSet( + self.rectangular_l1c_pset_products[0], + spice_reference_frame=geometry.SpiceFrame.IMAP_DPS, + ) + # Create multi-dimensional az_el coordinates + multi_dim_az_el_coords = xr.DataArray( + np.array( + [ + list( + zip( + np.linspace(0, 359.9, 20), + np.linspace(-90, 89.9, 20), + strict=False, + ) + ), + list( + zip( + np.linspace(359.9, 0, 20), + np.linspace(89.9, -90, 20), + strict=False, + ) + ), + ] + ), + dims=["energy", "pixel", "az_el_coords"], + ) + mock_pset_input_frame.az_el_points = multi_dim_az_el_coords + + # Manually calculate the resulting 1D pixel indices for each az/el pair + # (num of pixels in an az row spanning 180 deg of elevation) * (current az row) + # + (pixel along in current az row) + expected_output_pixel = np.array( + [ + (az // map_spacing_deg) * (180 // map_spacing_deg) + + ((90 + el) // map_spacing_deg) + for [az, el] in multi_dim_az_el_coords.values.reshape(-1, 2) + ] + ).reshape(2, -1) + + # Create the rectangular map and check the output values + rect_map = ena_maps.RectangularSkyMap( + spacing_deg=map_spacing_deg, + spice_frame=geometry.SpiceFrame.ECLIPJ2000, + ) + flat_indices_input_grid_output_frame = ena_maps.match_coords_to_indices( + mock_pset_input_frame, rect_map + ) + np.testing.assert_equal( + flat_indices_input_grid_output_frame, expected_output_pixel + ) + + # Test that healpix binning also works with multi-dimensional input + healpix_map = ena_maps.HealpixSkyMap( + nside=32, spice_frame=geometry.SpiceFrame.ECLIPJ2000, nested=False + ) + healpix_indices = ena_maps.match_coords_to_indices( + mock_pset_input_frame, healpix_map + ) + assert healpix_indices.shape == expected_output_pixel.shape + # indices should be reversed in the second set + np.testing.assert_equal( + healpix_indices.values[0, :], healpix_indices.values[1, ::-1] + ) + @pytest.mark.parametrize( "nside,degree_tolerance", [ diff --git a/imap_processing/tests/ena_maps/test_map_utils.py b/imap_processing/tests/ena_maps/test_map_utils.py index 5977ec8818..fbfa16c5b5 100644 --- a/imap_processing/tests/ena_maps/test_map_utils.py +++ b/imap_processing/tests/ena_maps/test_map_utils.py @@ -4,6 +4,58 @@ from imap_processing.ena_maps.utils import map_utils +class TestVectorizedBincount: + def test_vectorized_bincount_1d(self): + """Test vectorized_bincount with 1D input (equivalent to np.bincount).""" + indices = np.array([0, 1, 1, 2, 2, 2]) + result = map_utils.vectorized_bincount(indices, minlength=4) + expected = np.array([1.0, 2.0, 3.0, 0.0]) + np.testing.assert_array_equal(result, expected) + + def test_vectorized_bincount_1d_with_weights(self): + """Test vectorized_bincount with 1D input and weights.""" + indices = np.array([0, 1, 1, 2, 2, 2]) + weights = np.array([1.0, 2.0, 3.0, 4.0, 5.0, 6.0]) + result = map_utils.vectorized_bincount(indices, weights=weights, minlength=4) + expected = np.array([1.0, 5.0, 15.0, 0.0]) + np.testing.assert_array_equal(result, expected) + + def test_vectorized_bincount_2d(self): + """Test vectorized_bincount with 2D input (multiple 1D bincounts).""" + indices = np.array([[0, 1, 1], [2, 2, 3]]) + result = map_utils.vectorized_bincount(indices, minlength=4) + expected = np.array([[1.0, 2.0, 0.0, 0.0], [0.0, 0.0, 2.0, 1.0]]) + np.testing.assert_array_equal(result, expected) + + def test_vectorized_bincount_2d_with_weights(self): + """Test vectorized_bincount with 2D input and weights.""" + indices = np.array([[0, 1, 1], [2, 2, 3]]) + weights = np.array([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]) + result = map_utils.vectorized_bincount(indices, weights=weights, minlength=4) + expected = np.array([[1.0, 5.0, 0.0, 0.0], [0.0, 0.0, 9.0, 6.0]]) + np.testing.assert_array_equal(result, expected) + + def test_vectorized_bincount_3d(self): + """Test vectorized_bincount with 3D input.""" + indices = np.array([[[0, 1], [1, 2]], [[2, 3], [3, 0]]]) + result = map_utils.vectorized_bincount(indices, minlength=4) + expected = np.array( + [ + [[1.0, 1.0, 0.0, 0.0], [0.0, 1.0, 1.0, 0.0]], + [[0.0, 0.0, 1.0, 1.0], [1.0, 0.0, 0.0, 1.0]], + ] + ) + np.testing.assert_array_equal(result, expected) + + def test_vectorized_bincount_no_minlength(self): + """Test vectorized_bincount without specifying minlength.""" + indices = np.array([[0, 1, 1], [2, 2, 3]]) + result = map_utils.vectorized_bincount(indices) + # Without minlength, output size is max(indices) + 1 = 4 + expected = np.array([[1.0, 2.0, 0.0, 0.0], [0.0, 0.0, 2.0, 1.0]]) + np.testing.assert_array_equal(result, expected) + + class TestENAMapMappingUtils: def test_bin_single_array_at_indices( self, @@ -28,19 +80,22 @@ def test_bin_single_array_at_indices_extra_axis( """Test coverage for bin_single_array_at_indices function w/ simple 2D input, Corresponding to an extra axis that is not spatially binned. """ - # Binning will occur along axis 1 seen below - # (combining 1, 2, 3 and 4, 5, 6 separately). + # value_array has shape (2, 4) - 2 energy bins, 4 spatial positions + # Binning will occur along the spatial axis (axis 1) value_array = np.array( [ - [1, 2, 3], - [4, 5, 6], + [1, 2, 3, 4], + [10, 20, 30, 40], ] ) - input_indices = np.array([0, 1, 2, 2]) + # Select input positions 0, 1, 2, 3 and map to projection positions + input_indices = np.array([0, 1, 2, 3]) projection_indices = np.array([1, 0, 1, 6]) - projection_grid_shape = (7, 1) + projection_grid_shape = (7,) + # Row 0: proj[0]=2, proj[1]=1+3=4, proj[6]=4 + # Row 1: proj[0]=20, proj[1]=10+30=40, proj[6]=40 expected_projection_values = np.array( - [[2, 4, 0, 0, 0, 0, 3], [5, 10, 0, 0, 0, 0, 6]] + [[2, 4, 0, 0, 0, 0, 4], [20, 40, 0, 0, 0, 0, 40]] ) projection_values = map_utils.bin_single_array_at_indices( value_array, @@ -51,88 +106,6 @@ def test_bin_single_array_at_indices_extra_axis( np.testing.assert_equal(projection_values, expected_projection_values) - @pytest.mark.parametrize( - "projection_grid_shape", [(1, 1), (10, 10), (180, 360), (360, 720), (360, 180)] - ) - @pytest.mark.parametrize( - "input_grid_shape", [(1, 1), (10, 10), (180, 360), (360, 720), (360, 180)] - ) - def test_bin_single_array_at_indices_complex_2d( - self, projection_grid_shape, input_grid_shape - ): - """Test coverage for bin_single_array_at_indices function w/ complex 2D input, - Corresponding to an extra axis that is not spatially binned. - Parameterized across different input and projection grid shapes. - """ - np.random.seed(0) - extra_axis_size = 11 # Another axis which is not spatially binned, e.g. energy - input_grid_size = np.prod(input_grid_shape) - projection_grid_size = np.prod(projection_grid_shape) - value_array = np.random.rand(extra_axis_size, input_grid_size) - input_indices = np.random.randint(0, input_grid_size, size=1000) - projection_indices = np.random.randint(0, projection_grid_size, size=1000) - projection_values = map_utils.bin_single_array_at_indices( - value_array, - input_indices=input_indices, - projection_indices=projection_indices, - projection_grid_shape=projection_grid_shape, - ) - - # Explicitly check that the shape of the output is the same as projection grid - np.testing.assert_equal( - projection_values.shape, - ( - extra_axis_size, - projection_grid_size, - ), - ) - - # Create the expected projection values by summing the input values in a loop - # This is different from the binning function, which uses np.bincount - expected_projection_values = np.zeros((extra_axis_size, projection_grid_size)) - for ii, ip in zip(input_indices, projection_indices, strict=False): - expected_projection_values[:, ip] += value_array[:, ii] - - np.testing.assert_allclose(projection_values, expected_projection_values) - - @pytest.mark.parametrize("projection_grid_shape", [(1, 1), (10, 10), (180, 360)]) - @pytest.mark.parametrize("input_grid_shape", [(1, 1), (10, 10), (180, 360)]) - @pytest.mark.parametrize("num_extra_dims", [1, 2, 3, 5]) - def test_bin_single_array_at_indices_complex_3d( - self, projection_grid_shape, input_grid_shape, num_extra_dims - ): - """Test coverage for bin_single_array_at_indices function w/ complex N-Dim input - Corresponding to 2 extra axes that are not spatially binned. - Parameterized across different input and projection grid shapes. - """ - np.random.seed(0) - extra_axes_sizes = np.full(num_extra_dims, 3, dtype=int).tolist() - input_grid_size = np.prod(input_grid_shape) - projection_grid_size = np.prod(projection_grid_shape) - value_array = np.random.rand(*extra_axes_sizes, input_grid_size) - input_indices = np.random.randint(0, input_grid_size, size=1000) - projection_indices = np.random.randint(0, projection_grid_size, size=1000) - projection_values = map_utils.bin_single_array_at_indices( - value_array, - input_indices=input_indices, - projection_indices=projection_indices, - projection_grid_shape=projection_grid_shape, - ) - - # Explicitly check that the shape of the output is the same as projection grid - np.testing.assert_equal( - projection_values.shape, - (*extra_axes_sizes, projection_grid_size), - ) - - # Create the expected projection values by summing the input values in a loop - # This is different from the binning function, which uses np.bincount - expected_projection_values = np.zeros((*extra_axes_sizes, projection_grid_size)) - for ii, ip in zip(input_indices, projection_indices, strict=False): - expected_projection_values[..., ip] += value_array[..., ii] - - np.testing.assert_allclose(projection_values, expected_projection_values) - # Parameterize by the size of the projection grid, # which is not necessarily same size as input grid @pytest.mark.parametrize("projection_grid_shape", [(1, 1), (10, 10), (360, 720)]) @@ -267,8 +240,8 @@ def test_bin_values_at_indices_collapse_to_idx_zero(self, projection_grid_shape) output_dict["sum_variable_3d"], expected_projection_values_3d ) - def test_bin_values_at_indices_2d_indices_raises(self): - """2D indices are not supported for binning. + def test_bin_single_array_at_indices_2d_input_indices_raises(self): + """2D input_indices are not supported for binning. Test that ValueError is raised.""" input_values = np.array([1, 2, 3]) input_indices = np.array([[0, 1], [1, 2]]) @@ -278,7 +251,7 @@ def test_bin_values_at_indices_2d_indices_raises(self): with pytest.raises( ValueError, match=( - "Indices must be 1D arrays. If using a rectangular grid, " + "input_indices must be a 1D array. If using a rectangular grid, " "the indices must be unwrapped." ), ): @@ -289,21 +262,250 @@ def test_bin_values_at_indices_2d_indices_raises(self): projection_grid_shape=projection_grid_shape, ) - def test_bin_values_at_indices_mismatched_sizes_raises(self): - """Mismatched input and projection indices should raise an error. - Test that ValueError is raised.""" - input_values = np.array([1, 2, 3]) - input_indices = np.array([0, 1, 0, 1]) - projection_indices = np.array([0, 1, 2]) + def test_bin_single_array_at_indices_multidim_projection_indices(self): + """Test bin_single_array_at_indices multi-dimensional projection_indices.""" + # 2D value_array with shape (3, 4) - 3 energy bins, 4 spatial positions + value_array = np.array( + [ + [1.0, 2.0, 3.0, 4.0], + [10.0, 20.0, 30.0, 40.0], + [100.0, 200.0, 300.0, 400.0], + ] + ) + # 2D projection_indices with shape (3, 4) - different mapping per energy + projection_indices = np.array([[0, 1, 1, 2], [1, 0, 2, 2], [2, 2, 1, 0]]) + input_indices = np.array([0, 1, 2, 3]) projection_grid_shape = (3,) + projection_values = map_utils.bin_single_array_at_indices( + value_array, + input_indices=input_indices, + projection_indices=projection_indices, + projection_grid_shape=projection_grid_shape, + ) + + # Expected output shape: (3, 3) - 3 energy bins, 3 projection bins + # Energy 0: [[0,0]=1, [0,1]+[0,2]=2+3=5, [0,3]=4] + # Energy 1: [[1,1]=20, [1,0]=10, [1,2]+[1,3]=30+40=70] + # Energy 2: [[2,3]=400, [2,2]=300, [2,0]+[2,1]=100+200=300] + expected_projection_values = np.array( + [[1.0, 5.0, 4.0], [20.0, 10.0, 70.0], [400.0, 300.0, 300.0]] + ) + + np.testing.assert_equal(projection_values.shape, (3, 3)) + np.testing.assert_allclose(projection_values, expected_projection_values) + + def test_bin_single_array_at_indices_broadcasting(self): + """Test broadcasting between 1D projection_indices and 2D value_array.""" + # 2D value_array with shape (2, 4) + value_array = np.array([[1.0, 2.0, 3.0], [10.0, 20.0, 30.0]]) + # 1D projection_indices with shape (3,) - broadcasts to (2, 3) + projection_indices = np.array([0, 1, 0]) + input_indices = np.array([0, 1, 2]) + projection_grid_shape = (2,) + + projection_values = map_utils.bin_single_array_at_indices( + value_array, + input_indices=input_indices, + projection_indices=projection_indices, + projection_grid_shape=projection_grid_shape, + ) + + # Expected: both rows use same projection_indices + # Row 0: bin 0 gets value[0,0]+value[0,2]=1+3=4, bin 1 gets value[0,1]=2 + # Row 1: bin 0 gets value[1,0]+value[1,2]=10+30=40, bin 1 gets value[1,1]=20 + expected_projection_values = np.array([[4.0, 2.0], [40.0, 20.0]]) + + np.testing.assert_equal(projection_values.shape, (2, 2)) + np.testing.assert_allclose(projection_values, expected_projection_values) + + def test_bin_single_array_at_indices_with_1d_mask(self): + """Test bin_single_array_at_indices with 1D input_valid_mask.""" + value_array = np.array([1, 2, 3, 4, 5, 6]) + input_indices = np.array([0, 1, 2, 2, 1, 0]) + projection_indices = np.array([1, 2, 3, 1, 2, 3]) + projection_grid_shape = (5,) + # Mask out indices 1 and 4 (values 2 and 5) + input_valid_mask = np.array([True, False, True, True, False, False]) + + projection_values = map_utils.bin_single_array_at_indices( + value_array, + input_indices=input_indices, + projection_indices=projection_indices, + projection_grid_shape=projection_grid_shape, + input_valid_mask=input_valid_mask, + ) + + # Without mask: [0, 4, 4, 4, 0] + # With mask (excluding indices 1,4,5 -> values 2,2,1): [0, 4, 0, 3, 0] + expected_projection_values = np.array([0, 4, 0, 3, 0]) + np.testing.assert_equal(projection_values, expected_projection_values) + + def test_bin_single_array_at_indices_with_2d_mask(self): + """ + Test bin_single_array_at_indices with 2D input_valid_mask. + + input_valid_mask matches value_array shape. + """ + # 2D value_array with shape (2, 6) + value_array = np.array( + [ + [1, 2, 3, 4, 5, 6], + [10, 20, 30, 40, 50, 60], + ] + ) + input_indices = np.array([0, 1, 2, 2, 1, 0]) + projection_indices = np.array([1, 2, 3, 1, 2, 3]) + projection_grid_shape = (5,) + # Mask with different patterns for each row + input_valid_mask = np.array( + [ + [True, False, True, True, False, True], # Row 0: mask out 2, 5 + [True, True, False, True, True, False], # Row 1: mask out 3, 6 + ] + ) + + projection_values = map_utils.bin_single_array_at_indices( + value_array, + input_indices=input_indices, + projection_indices=projection_indices, + projection_grid_shape=projection_grid_shape, + input_valid_mask=input_valid_mask, + ) + + # Row 0: mask excludes values 2,5 -> [0, 4, 0, 4, 0] + # Row 1: mask excludes values 30,60 -> [0, 40, 40, 0, 0] + expected_projection_values = np.array([[0, 4, 0, 4, 0], [0, 40, 40, 0, 0]]) + np.testing.assert_equal(projection_values, expected_projection_values) + + def test_bin_single_array_at_indices_with_broadcast_mask(self): + """Test bin_single_array_at_indices with 1D mask, 2D value_array.""" + # 2D value_array with shape (2, 6) + value_array = np.array( + [ + [1, 2, 3, 4, 5, 6], + [10, 20, 30, 40, 50, 60], + ] + ) + input_indices = np.array([0, 1, 2, 2, 1, 0]) + projection_indices = np.array([1, 2, 3, 1, 2, 3]) + projection_grid_shape = (5,) + # 1D mask that broadcasts to both rows + input_valid_mask = np.array([True, False, True, True, False, True]) + + projection_values = map_utils.bin_single_array_at_indices( + value_array, + input_indices=input_indices, + projection_indices=projection_indices, + projection_grid_shape=projection_grid_shape, + input_valid_mask=input_valid_mask, + ) + + # Same mask applied to both rows: exclude indices 1,4 + # Row 0: mask excludes values 2,5 -> [0, 4, 0, 4, 0] + # Row 1: mask excludes values 30,60 -> [0, 40, 0, 40, 0] + expected_projection_values = np.array([[0, 4, 0, 4, 0], [0, 40, 0, 40, 0]]) + np.testing.assert_equal(projection_values, expected_projection_values) + + def test_bin_single_array_at_indices_mask_all_invalid(self): + """Test bin_single_array_at_indices with all values masked out.""" + value_array = np.array([1, 2, 3, 4, 5, 6]) + input_indices = np.array([0, 1, 2, 2, 1, 0]) + projection_indices = np.array([1, 2, 3, 1, 2, 3]) + projection_grid_shape = (5,) + # Mask out all values + input_valid_mask = np.array([False, False, False, False, False, False]) + + projection_values = map_utils.bin_single_array_at_indices( + value_array, + input_indices=input_indices, + projection_indices=projection_indices, + projection_grid_shape=projection_grid_shape, + input_valid_mask=input_valid_mask, + ) + + # All values masked -> all zeros + expected_projection_values = np.array([0, 0, 0, 0, 0]) + np.testing.assert_equal(projection_values, expected_projection_values) + + def test_bin_single_array_at_indices_mask_shape_mismatch_raises(self): + """Test that ValueError is raised when shapes are incompatible.""" + value_array = np.array([1, 2, 3, 4, 5, 6]) + input_indices = np.array([0, 1, 2]) + projection_indices = np.array([1, 2, 3]) + projection_grid_shape = (5,) + # Incompatible mask shape + input_valid_mask = np.array([True, False, True]) + with pytest.raises( ValueError, - match=("The number of input and projection indices must be the same"), + match="projection_indices shape .* must be broadcastable " + "with value_array shape", ): map_utils.bin_single_array_at_indices( - input_values, + value_array, input_indices=input_indices, projection_indices=projection_indices, projection_grid_shape=projection_grid_shape, + input_valid_mask=input_valid_mask, ) + with pytest.raises( + ValueError, + match="input_valid_mask shape .* must be broadcastable " + "with value_array shape", + ): + map_utils.bin_single_array_at_indices( + value_array, + input_indices=input_indices, + projection_indices=np.arange(6), + projection_grid_shape=projection_grid_shape, + input_valid_mask=input_valid_mask, + ) + + def test_bin_single_array_at_indices_mask_default_input_indices(self): + """Test bin_single_array_at_indices with mask and default input_indices=None.""" + # Test that when input_indices is not provided, the function uses + # np.arange(value_array.shape[-1]) and masking works correctly + value_array = np.array([1, 2, 3, 4, 5, 6]) + projection_indices = np.array([0, 1, 1, 2, 2, 0]) + projection_grid_shape = (3,) + # Mask out values at positions 1, 3, 5 (values 2, 4, 6) + input_valid_mask = np.array([True, False, True, False, True, False]) + + projection_values = map_utils.bin_single_array_at_indices( + value_array, + projection_indices=projection_indices, + projection_grid_shape=projection_grid_shape, + input_valid_mask=input_valid_mask, + ) + + # Without mask: bin[0]=1+6=7, bin[1]=2+3=5, bin[2]=4+5=9 + # With mask: bin[0]=1+0=1, bin[1]=0+3=3, bin[2]=0+5=5 + expected_projection_values = np.array([1, 3, 5]) + np.testing.assert_equal(projection_values, expected_projection_values) + + def test_bin_single_array_at_indices_mask_default_input_indices_2d(self): + """Test with mask, default input_indices, and 2D value_array.""" + # 2D value_array with shape (2, 6) + value_array = np.array( + [ + [1, 2, 3, 4, 5, 6], + [10, 20, 30, 40, 50, 60], + ] + ) + projection_indices = np.array([0, 1, 1, 2, 2, 0]) + projection_grid_shape = (3,) + # 1D mask broadcasting to both rows + input_valid_mask = np.array([True, False, True, False, True, False]) + + projection_values = map_utils.bin_single_array_at_indices( + value_array, + projection_indices=projection_indices, + projection_grid_shape=projection_grid_shape, + input_valid_mask=input_valid_mask, + ) + + # Row 0: bin[0]=1, bin[1]=3, bin[2]=5 + # Row 1: bin[0]=10, bin[1]=30, bin[2]=50 + expected_projection_values = np.array([[1, 3, 5], [10, 30, 50]]) + np.testing.assert_equal(projection_values, expected_projection_values) diff --git a/imap_processing/tests/ena_maps/test_naming.py b/imap_processing/tests/ena_maps/test_naming.py index 3c47452931..0c5d03ffbb 100644 --- a/imap_processing/tests/ena_maps/test_naming.py +++ b/imap_processing/tests/ena_maps/test_naming.py @@ -170,9 +170,10 @@ def test_get_map_frame( assert MapDescriptor.get_map_coord_frame("hre") is SpiceFrame.IMAP_HRE assert MapDescriptor.get_map_coord_frame("hnu") is SpiceFrame.IMAP_HNU assert MapDescriptor.get_map_coord_frame("gcs") is SpiceFrame.IMAP_GCS + assert MapDescriptor.get_map_coord_frame("hrc") is SpiceFrame.IMAP_HRC # Test with not implemented 'hgi' - with pytest.raises(NotImplementedError): + with pytest.raises(KeyError, match="Coordinate frame hgi"): MapDescriptor.get_map_coord_frame("hgi") def test_get_output_map_structure_from_descriptor_string(self): @@ -304,3 +305,92 @@ def test_to_string(self): ) descriptor_str_ultra_combined = md_ultra_combined.to_string() assert descriptor_str_ultra_combined == "ulc-ena-h-sf-nsp-full-hae-nside32-1yr" + + @pytest.mark.parametrize( + "descriptor_str, expected_catdesc", + [ + ( + "h45-spx-h-hf-sp-ram-hae-4deg-3mo", + "IMAP Hi45 H Spectral, HAE Helio Frame, Surv Corr, Ram, 4 deg, 3 Mon", + ), + ( + "h45-spx0305-h-hf-sp-ram-hae-4deg-3mo", + "IMAP Hi45 H Spectral, HAE Helio Frame, Surv Corr, Ram, 4 deg, 3 Mon", + ), + ( + "hic-ena-h-hf-sp-ram-hae-4deg-3mo", + "IMAP Hi Combined H Inten, HAE Helio Frame, Surv Corr, Ram," + " 4 deg, 3 Mon", + ), + ( + "u45-ena-h-hf-sp-ram-hae-4deg-3mo", + "IMAP Ultra45 H Inten, HAE Helio Frame, Surv Corr, Ram, 4 deg, 3 Mon", + ), + ( + "u45-ena-h-hf-sp-full-hae-4deg-3mo", + "IMAP Ultra45 H Inten, HAE Helio Frame, Surv Corr, Full Spin," + " 4 deg, 3 Mon", + ), + ( + "u45-ena-h-hf-sp-ram-hae-nside128-3mo", + "IMAP Ultra45 H Inten, HAE Helio Frame, Surv Corr, Ram, NSide 128," + " 3 Mon", + ), + ( + "u45-enaCUSTOM-h-hf-sp-ram-hae-4deg-3mo", + "IMAP Ultra45 H Inten, HAE Helio Frame, Surv Corr, Ram, 4 deg, 3 Mon", + ), + ( + "l090-enanbs-h-sf-nsp-ram-hae-6deg-1yr", + "IMAP Lo90 H Inten, HAE SC Frame, No Surv Corr, Ram, 6 deg, 1 Yr," + " No sputter/bootstrap", + ), + ( + "t090-ena-o-sf-nsp-ram-hae-6deg-1yr", + "IMAP Lo90 O Inten, HAE SC Frame, No Surv Corr, Ram, 6 deg, 1 Yr", + ), + ( + "l090-ena-h-hf-nsp-ram-gcs-6deg-1yr", + "IMAP Lo90 H Inten, GCS Helio Frame, No Surv Corr, Ram, 6 deg, 1 Yr", + ), + ( + "l090-isn-h-sf-nsp-ram-hae-6deg-1yr", + "IMAP Lo90 ISN H Rate, HAE SC Frame, No Surv Corr, Ram, 6 deg, 1 Yr", + ), + ( + "l090-isnnbkgnd-h-sf-nsp-ram-hae-6deg-1yr", + "IMAP Lo90 ISN H Rate, HAE SC Frame, No Surv Corr, Ram, 6 deg, 1 Yr," + " No bkgnd sub", + ), + ( + "glx-int-uv-sf-nsp-full-hae-6deg-1yr", + "IMAP GLOWS UV Inten, HAE SC Frame, No Surv Corr, Full Spin, 6 deg," + " 1 Yr", + ), + ( + "idx-drt-dust-sf-nsp-full-hae-6deg-1yr", + "IMAP IDEX Dust Rate, HAE SC Frame, No Surv Corr, Full Spin, 6 deg," + " 1 Yr", + ), + ], + ) + def test_to_catdesc(self, descriptor_str, expected_catdesc): + # Use case is primarily from descriptor str to CATDESC + md = MapDescriptor.from_string(descriptor_str) + actual_catdesc = md.to_catdesc() + assert actual_catdesc == expected_catdesc + + @pytest.mark.parametrize( + "descriptor_str, expected_principal_data_var", + [ + ("hic-ena-h-hf-sp-ram-hae-4deg-3mo", "ena_intensity"), + ("h45-spx0305-h-hf-sp-ram-hae-4deg-3mo", "ena_spectral_index"), + ("idx-drt-dust-sf-nsp-full-hae-6deg-1yr", "dust_rate"), + ("glx-int-uv-sf-nsp-full-hae-6deg-1yr", "glows_rate"), + ("l090-isnnbkgnd-h-sf-nsp-ram-hae-6deg-1yr", "isn_rate"), + ("l090-isn-h-sf-nsp-ram-hae-6deg-1yr", "isn_rate_bg_subtracted"), + ], + ) + def test_principal_data_var(self, descriptor_str, expected_principal_data_var): + md = MapDescriptor.from_string(descriptor_str) + assert md.principal_data_var == expected_principal_data_var diff --git a/imap_processing/tests/external_test_data_config.py b/imap_processing/tests/external_test_data_config.py index dae2531537..b7c7ba4bf4 100644 --- a/imap_processing/tests/external_test_data_config.py +++ b/imap_processing/tests/external_test_data_config.py @@ -7,47 +7,88 @@ """ # ruff: noqa: E501 +from imap_processing.tests.codice.conftest import ( + VALIDATION_FILE_DATE, + VALIDATION_FILE_VERSION, +) + EXTERNAL_TEST_DATA = [ # CoDICE - ("imap_codice_l0_raw_20241110_v001.pkts", "codice/data/"), - ("imap_codice_l1a_hi-counters-aggregated_20241110_v001.cdf", "codice/data/"), - ("imap_codice_l1a_hi-counters-singles_20241110_v001.cdf", "codice/data/"), - ("imap_codice_l1a_hi-ialirt_20241110_v001.cdf", "codice/data/"), - ("imap_codice_l1a_hi-omni_20241110_v001.cdf", "codice/data/"), - ("imap_codice_l1a_hi-direct-events_20241110_v001.cdf", "codice/data/"), - ("imap_codice_l1a_hi-priority_20241110_v001.cdf", "codice/data/"), - ("imap_codice_l1a_hi-sectored_20241110_v001.cdf", "codice/data/"), - ("imap_codice_l1a_hskp_20241110_v001.cdf", "codice/data/"), - ("imap_codice_l1a_lo-counters-aggregated_20241110_v001.cdf", "codice/data/"), - ("imap_codice_l1a_lo-counters-singles_20241110_v001.cdf", "codice/data/"), - ("imap_codice_l1a_lo-ialirt_20241110_v001.cdf", "codice/data/"), - ("imap_codice_l1a_lo-nsw-angular_20241110_v001.cdf", "codice/data/"), - ("imap_codice_l1a_lo-nsw-priority_20241110_v001.cdf", "codice/data/"), - ("imap_codice_l1a_lo-nsw-species_20241110_v001.cdf", "codice/data/"), - ("imap_codice_l1a_lo-direct-events_20241110_v001.cdf", "codice/data/"), - ("imap_codice_l1a_lo-sw-angular_20241110_v001.cdf", "codice/data/"), - ("imap_codice_l1a_lo-sw-priority_20241110_v001.cdf", "codice/data/"), - ("imap_codice_l1a_lo-sw-species_20241110_v001.cdf", "codice/data/"), - - ("imap_codice_l1a_hi-counters-aggregated_20241110193900_v0.0.2.cdf", "codice/data/validation/"), - ("imap_codice_l1a_lo-counters-singles_20241110193900_v0.0.2.cdf", "codice/data/validation/"), - ("imap_codice_l1a_hi-counters-singles_20241110193900_v0.0.2.cdf", "codice/data/validation/"), - ("imap_codice_l1a_lo-ialirt_20241110193900_v0.0.2.cdf", "codice/data/validation/"), - ("imap_codice_l1a_hi-ialirt_20241110193900_v0.0.2.cdf", "codice/data/validation/"), - ("imap_codice_l1a_lo-nsw-angular_20241110193900_v0.0.2.cdf", "codice/data/validation/"), - ("imap_codice_l1a_hi-omni_20241110193900_v0.0.2.cdf", "codice/data/validation/"), - ("imap_codice_l1a_lo-nsw-priority_20241110193900_v0.0.2.cdf", "codice/data/validation/"), - ("imap_codice_l1a_hi-direct-events_20241110193900_v0.0.2.cdf", "codice/data/validation/"), - ("imap_codice_l1a_lo-nsw-species_20241110193900_v0.0.2.cdf", "codice/data/validation/"), - ("imap_codice_l1a_hi-priorities_20241110193900_v0.0.2.cdf", "codice/data/validation/"), - ("imap_codice_l1a_lo-direct-events_20241110193900_v0.0.2.cdf", "codice/data/validation/"), - ("imap_codice_l1a_hi-sectored_20241110193900_v0.0.2.cdf", "codice/data/validation/"), - ("imap_codice_l1a_lo-sw-angular_20241110193900_v0.0.2.cdf", "codice/data/validation/"), - ("imap_codice_l1a_hskp_20241110193622_v0.0.2.cdf", "codice/data/validation/"), - ("imap_codice_l1a_lo-sw-priority_20241110193900_v0.0.2.cdf", "codice/data/validation/"), - ("imap_codice_l1a_lo-counters-aggregated_20241110193900_v0.0.2.cdf", "codice/data/validation/"), - ("imap_codice_l1a_lo-sw-species_20241110193900_v0.0.2.cdf", "codice/data/validation/"), + # L0 data + ("imap_codice_l0_lo-sw-species_20250814_v001.pkts", "codice/data/l1a_input/"), + ("imap_codice_l0_lo-nsw-priority_20250814_v001.pkts", "codice/data/l1a_input/"), + ("imap_codice_l0_lo-sw-priority_20250814_v001.pkts", "codice/data/l1a_input/"), + ("imap_codice_l0_lo-counters-aggregated_20250814_v001.pkts", "codice/data/l1a_input/"), + ("imap_codice_l0_lo-counters-singles_20250814_v001.pkts", "codice/data/l1a_input/"), + ("imap_codice_l0_lo-ialirt_20250814_v001.pkts", "codice/data/l1a_input/"), + ("imap_codice_l0_lo-direct-events_20250814_v001.pkts", "codice/data/l1a_input/"), + ("imap_codice_l0_hi-ialirt_20250814_v001.pkts", "codice/data/l1a_input/"), + ("imap_codice_l0_hi-counters-aggregated_20250814_v001.pkts", "codice/data/l1a_input/"), + ("imap_codice_l0_hi-counters-singles_20250814_v001.pkts", "codice/data/l1a_input/"), + ("imap_codice_l0_hi-omni_20250814_v001.pkts", "codice/data/l1a_input/"), + ("imap_codice_l0_hi-sectored_20250814_v001.pkts", "codice/data/l1a_input/"), + ("imap_codice_l0_hi-priority_20250814_v001.pkts", "codice/data/l1a_input/"), + ("imap_codice_l0_hi-direct-events_20250814_v001.pkts", "codice/data/l1a_input/"), + ("imap_codice_l0_hskp_20250814_v001.pkts", "codice/data/l1a_input/"), + ("imap_codice_l0_raw_20260130_v001.pkts", "codice/data/l1a_input/"), + + # L1A LUT + ("imap_codice_l1a-sci-lut_20251007_v005.json", "codice/data/l1a_lut/"), + ("imap_codice_l1a-sci-lut_20260129_v002.json", "codice/data/l1a_lut/"), + + # L1A validation data + (f"imap_codice_l1a_hi-counters-aggregated_{VALIDATION_FILE_DATE}_{VALIDATION_FILE_VERSION}.cdf", "codice/data/l1a_validation"), + (f"imap_codice_l1a_hi-counters-singles_{VALIDATION_FILE_DATE}_{VALIDATION_FILE_VERSION}.cdf", "codice/data/l1a_validation"), + (f"imap_codice_l1a_hi-direct-events_{VALIDATION_FILE_DATE}_{VALIDATION_FILE_VERSION}.cdf", "codice/data/l1a_validation"), + (f"imap_codice_l1a_hi-ialirt_{VALIDATION_FILE_DATE}_{VALIDATION_FILE_VERSION}.cdf", "codice/data/l1a_validation"), + (f"imap_codice_l1a_hi-omni_{VALIDATION_FILE_DATE}_{VALIDATION_FILE_VERSION}.cdf", "codice/data/l1a_validation"), + (f"imap_codice_l1a_hi-sectored_{VALIDATION_FILE_DATE}_{VALIDATION_FILE_VERSION}.cdf", "codice/data/l1a_validation"), + (f"imap_codice_l1a_hi-priority_{VALIDATION_FILE_DATE}_{VALIDATION_FILE_VERSION}.cdf", "codice/data/l1a_validation"), + (f"imap_codice_l1a_hi-sectored_{VALIDATION_FILE_DATE}_{VALIDATION_FILE_VERSION}.cdf", "codice/data/l1a_validation"), + (f"imap_codice_l1a_lo-counters-aggregated_{VALIDATION_FILE_DATE}_{VALIDATION_FILE_VERSION}.cdf", "codice/data/l1a_validation"), + (f"imap_codice_l1a_lo-counters-singles_{VALIDATION_FILE_DATE}_{VALIDATION_FILE_VERSION}.cdf", "codice/data/l1a_validation"), + (f"imap_codice_l1a_lo-direct-events_{VALIDATION_FILE_DATE}_{VALIDATION_FILE_VERSION}.cdf", "codice/data/l1a_validation"), + (f"imap_codice_l1a_lo-ialirt_{VALIDATION_FILE_DATE}_{VALIDATION_FILE_VERSION}.cdf", "codice/data/l1a_validation"), + ("imap_codice_l1a_hi-ialirt_20260331_v0.0.22.cdf", "codice/data/l1a_validation"), + (f"imap_codice_l1a_lo-nsw-priority_{VALIDATION_FILE_DATE}_{VALIDATION_FILE_VERSION}.cdf", "codice/data/l1a_validation"), + (f"imap_codice_l1a_lo-sw-priority_{VALIDATION_FILE_DATE}_{VALIDATION_FILE_VERSION}.cdf", "codice/data/l1a_validation"), + (f"imap_codice_l1a_lo-sw-species_{VALIDATION_FILE_DATE}_{VALIDATION_FILE_VERSION}.cdf", "codice/data/l1a_validation"), + # L1B Input data is same as L1A validation data + + # L1B validation data + (f"imap_codice_l1b_hi-counters-aggregated_{VALIDATION_FILE_DATE}_{VALIDATION_FILE_VERSION}.cdf", "codice/data/l1b_validation"), + (f"imap_codice_l1b_hi-counters-singles_{VALIDATION_FILE_DATE}_{VALIDATION_FILE_VERSION}.cdf", "codice/data/l1b_validation"), + (f"imap_codice_l1b_hi-ialirt_{VALIDATION_FILE_DATE}_{VALIDATION_FILE_VERSION}.cdf", "codice/data/l1b_validation"), + (f"imap_codice_l1b_hi-omni_{VALIDATION_FILE_DATE}_{VALIDATION_FILE_VERSION}.cdf", "codice/data/l1b_validation"), + (f"imap_codice_l1b_hi-priority_{VALIDATION_FILE_DATE}_{VALIDATION_FILE_VERSION}.cdf", "codice/data/l1b_validation"), + (f"imap_codice_l1b_hi-sectored_{VALIDATION_FILE_DATE}_{VALIDATION_FILE_VERSION}.cdf", "codice/data/l1b_validation"), + (f"imap_codice_l1b_lo-counters-aggregated_{VALIDATION_FILE_DATE}_{VALIDATION_FILE_VERSION}.cdf", "codice/data/l1b_validation"), + (f"imap_codice_l1b_lo-counters-singles_{VALIDATION_FILE_DATE}_{VALIDATION_FILE_VERSION}.cdf", "codice/data/l1b_validation"), + (f"imap_codice_l1b_lo-ialirt_{VALIDATION_FILE_DATE}_{VALIDATION_FILE_VERSION}.cdf", "codice/data/l1b_validation"), + (f"imap_codice_l1b_lo-nsw-priority_{VALIDATION_FILE_DATE}_{VALIDATION_FILE_VERSION}.cdf", "codice/data/l1b_validation"), + (f"imap_codice_l1b_lo-sw-priority_{VALIDATION_FILE_DATE}_{VALIDATION_FILE_VERSION}.cdf", "codice/data/l1b_validation"), + (f"imap_codice_l1b_lo-sw-species_{VALIDATION_FILE_DATE}_{VALIDATION_FILE_VERSION}.cdf", "codice/data/l1b_validation"), + # L2 LUT input data + ("imap_codice_l2-hi-omni-efficiency_20251212_v003.csv", "codice/data/l2_lut/"), + ("imap_codice_l2-hi-sectored-efficiency_20251212_v003.csv", "codice/data/l2_lut/"), + ("imap_codice_l2-hi-ialirt-efficiency_20251212_v003.csv", "codice/data/l2_lut/"), + ("imap_codice_l2-lo-gfactor_20251212_v003.csv", "codice/data/l2_lut/"), + ("imap_codice_l2-lo-efficiency_20251212_v003.csv", "codice/data/l2_lut/"), + ("imap_codice_l2-hi-tof-table_20250101_v001.csv", "codice/data/l2_lut/"), + ("imap_codice_l2-hi-energy-table_20250101_v001.csv", "codice/data/l2_lut/"), + ("imap_codice_l2-lo-onboard-energy-bins_20250101_v001.csv", "codice/data/l2_lut/"), + ("imap_codice_l2-lo-onboard-energy-table_20250101_v001.csv", "codice/data/l2_lut/"), + ("imap_codice_l2-lo-onboard-mpq-cal_20250101_v001.csv", "codice/data/l2_lut/"), + + # L2 Validation data + (f"imap_codice_l2_hi-omni_{VALIDATION_FILE_DATE}_{VALIDATION_FILE_VERSION}.cdf", "codice/data/l2_validation/"), + (f"imap_codice_l2_hi-sectored_{VALIDATION_FILE_DATE}_{VALIDATION_FILE_VERSION}.cdf", "codice/data/l2_validation/"), + (f"imap_codice_l2_lo-sw-species_{VALIDATION_FILE_DATE}_{VALIDATION_FILE_VERSION}.cdf", "codice/data/l2_validation/"), + (f"imap_codice_l2_lo-direct-events_{VALIDATION_FILE_DATE}_{VALIDATION_FILE_VERSION}.cdf", "codice/data/l2_validation/"), + (f"imap_codice_l2_hi-direct-events_{VALIDATION_FILE_DATE}_{VALIDATION_FILE_VERSION}.cdf", "codice/data/l2_validation/"), + (f"imap_codice_l2_hi-ialirt_{VALIDATION_FILE_DATE}_{VALIDATION_FILE_VERSION}.cdf", "codice/data/l2_validation/"), + (f"imap_codice_l2_lo-ialirt_{VALIDATION_FILE_DATE}_{VALIDATION_FILE_VERSION}.cdf", "codice/data/l2_validation/"), # Hi ("imap_hi_l1a_45sensor-de_20250415_v999.cdf", "hi/data/l1/"), @@ -55,19 +96,60 @@ ("imap_hi_l1b_90sensor-hk_20241105-repoint00099_v001.cdf", "hi/data/l1/"), ("imap_hi_l1a_90sensor-de_20241105-repoint00099_v001.cdf", "hi/data/l1/"), ("imap_hi_l1c_45sensor-pset_20250415_v999.cdf", "hi/data/l1/"), + ("imap_hi_l1b_45sensor-goodtimes_20250415_v999.cdf", "hi/data/l1/"), # I-ALiRT ("apid_478.bin", "ialirt/data/l0/"), + ("iois_1_packets_2025_284_05_40_25", "ialirt/data/l0/"), + ("iois_1_packets_2025_284_05_41_26", "ialirt/data/l0/"), + ("iois_1_packets_2025_284_05_42_27", "ialirt/data/l0/"), + ("iois_1_packets_2025_284_05_43_28", "ialirt/data/l0/"), + ("iois_1_packets_2025_284_05_44_29", "ialirt/data/l0/"), + ("iois_1_packets_2025_284_05_45_30", "ialirt/data/l0/"), + ("iois_1_packets_2025_284_05_46_31", "ialirt/data/l0/"), + ("iois_1_packets_2025_284_05_47_32", "ialirt/data/l0/"), + ("iois_1_packets_2025_284_05_48_33", "ialirt/data/l0/"), + ("iois_1_packets_2025_284_05_49_34", "ialirt/data/l0/"), + ("iois_1_packets_2025_284_05_50_35", "ialirt/data/l0/"), + ("iois_1_packets_2025_284_05_51_36", "ialirt/data/l0/"), + ("iois_1_packets_2025_284_05_52_37", "ialirt/data/l0/"), + ("iois_1_packets_2025_284_05_53_38", "ialirt/data/l0/"), + ("iois_1_packets_2025_284_05_54_39", "ialirt/data/l0/"), + ("iois_1_packets_2025_344_05_57_56", "ialirt/data/l0/"), + ("iois_1_packets_2025_344_05_59_58", "ialirt/data/l0/"), + ("iois_1_packets_2026_090_05_03_05", "ialirt/data/l0/"), + ("iois_1_packets_2026_090_05_04_06", "ialirt/data/l0/"), + ("iois_1_packets_2026_090_05_05_07", "ialirt/data/l0/"), + ("iois_1_packets_2026_090_05_06_08", "ialirt/data/l0/"), + ("iois_1_packets_2026_090_05_07_09", "ialirt/data/l0/"), + ("imap_recon_od005_20250925_20251014_v01.bsp", "spice/test_data/"), + ("imap_2025_283_2025_284_001.ah.bc", "spice/test_data/"), # IDEX ("idex_l1a_validation_file.h5", "idex/test_data/"), - ("idex_l1b_validation_file.h5", "idex/test_data/"), + ("imap_idex_l1b_sci_20231218_v004.h5", "idex/test_data/"), ("imap_idex_l2a-calibration-curve-yield-params_20250101_v001.csv", "idex/test_data/"), - ("imap_idex_l2a-calibration-curve-t-rise_20250101_v001.csv", "idex/test_data/"), + ("imap_idex_l2a-calibration-curve-t-rise_20250101_v002.csv", "idex/test_data/"), + + # Lo + ("imap_lo_l1c_pset_20260101-repoint01261_v001.cdf", "lo/test_cdfs"), + + # Pointing Attitude Kernel + ("imap_2025_338_2025_339_001.ah.bc", "spice/test_data/"), + ("imap_2025_339_2025_339_001.ah.bc", "spice/test_data/"), + ("imap_2025_339_2025_340_001.ah.bc", "spice/test_data/"), # Ultra ("FM90_Startup_20230711T081655.CCSDS", "ultra/data/l0/"), ("IMAP-Ultra45_r1_L1_V0_shortened.csv", "ultra/data/l1/"), + ("extendedspin_test_data_repoint00047.csv", "ultra/data/l1/"), + ("status_test_data_repoint00047.csv", "ultra/data/l1/"), + ("voltage_culling_results_repoint00047.csv", "ultra/data/l1/"), + ("validate_high_energy_culling_results_repoint00047_v2.csv", "ultra/data/l1/"), + ("validate_stat_culling_results_repoint00047_v3.csv", "ultra/data/l1/"), + ("validate_upstream_ion_1_culling_results_repoint00047_v1.csv", "ultra/data/l1/"), + ("validate_spectral_culling_results_repoint00047_v1.csv", "ultra/data/l1/"), + ("de_test_data_repoint00047.csv", "ultra/data/l1/"), ("FM45_UltraFM45Extra_TV_Tests_2024-01-22T0930_20240122T093008.CCSDS", "ultra/data/l0/"), ("ultra45_raw_sc_rawnrgevnt_19840122_00.csv", "ultra/data/l0/"), ("ultra45_raw_sc_enaphxtofhnrgimg_FM45_UltraFM45Extra_TV_Tests_2024-01-22T0930_20240122T093008.csv", @@ -82,6 +164,11 @@ ("ultra45_raw_sc_ultraenaphxtofhtimeresimg_FM45_UltraFM45Extra_TV_Tests_2024-01-22T0930_20240122T093008.csv", "ultra/data/l0/"), ("ultra45_raw_sc_enaextofhangimg_FM45_UltraFM45Extra_TV_Tests_2024-01-22T0930_20240122T093008.csv", "ultra/data/l0/"), ("ultra45_raw_sc_ionextofhnrgimg_FM45_UltraFM45Extra_TV_Tests_2024-01-22T0930_20240122T093008.csv", "ultra/data/l0/"), + ("ultra45_l1b_raw_sc_ionextofhtimeimg_20240122_00_SDCStyle.csv", "ultra/data/l0/"), + ("ultra45_l1b_raw_sc_ionextofhnrgimg_20240122_00_SDCStyle.csv", "ultra/data/l0/"), + ("ultra45_l1b_raw_sc_enaextofhangimg_20240122_00_SDCStyle.csv", "ultra/data/l0/"), + ("ultra45_l1b_raw_sc_enaphxtofhtimeimg_20240122_00_SDCStyle.csv", "ultra/data/l0/"), + ("ultra45_l1b_raw_sc_enaphxtofhnrgimg_20240122_00_SDCStyle.csv", "ultra/data/l0/"), ("imap_ultra_l0_raw_20260924_v001.pkts", "ultra/data/l0/"), ("imap_ultra_l1b_45sensor-de_20240207_v999.cdf", "ultra/data/l1/"), ("ultra-90_raw_event_data_shortened.csv", "ultra/data/l1/"), @@ -112,13 +199,18 @@ ("imap_ultra_l1b-90sensor-tofxemedium_20250101_v000.pgm", "ultra/data/l1/"), ("imap_ultra_l1b-90sensor-tofxesteep_20250101_v000.pgm", "ultra/data/l1/"), ("imap_ultra_l1b-tofxph_20250101_v000.pgm","ultra/data/l1/"), - ("imap_ultra_l1c-90sensor-sc-pointing-theta-n32-test_20250101_v000.csv", "ultra/data/l1/"), - ("imap_ultra_l1c-90sensor-sc-pointing-phi-n32-test_20250101_v000.csv", "ultra/data/l1/"), - ("imap_ultra_l1c-90sensor-sc-pointing-index-n32-test_20250101_v000.csv", "ultra/data/l1/"), - ("imap_ultra_l1c-90sensor-sc-pointing-bsf-n32-test_20250101_v000.csv", "ultra/data/l1/"), + ("imap_ultra_l1c-90sensor-sc-pointing-theta-test_20250101_v000.csv", "ultra/data/l1/"), + ("imap_ultra_l1c-90sensor-sc-pointing-phi-test_20250101_v000.csv", "ultra/data/l1/"), + ("imap_ultra_l1c-90sensor-sc-pointing-index-test_20250101_v000.csv", "ultra/data/l1/"), + ("imap_ultra_l1c-90sensor-sc-pointing-bsf-test_20250101_v000.csv", "ultra/data/l1/"), ("imap_ultra_l1b-scattering-thresholds-per-energy_20250101_v000.csv", "ultra/data/l1/"), ("imap_ultra_l1b_45sensor-de_20240207-repoint99999_v999.cdf","ultra/data/l1/"), ("imap_ultra_l1c-45sensor-nominal-for-lookup_20250101_v000.csv", "ultra/data/l1/"), + ("imap_ultra_l1c-45sensor-static-dead-times_20250101_v000.csv", "ultra/data/l1/"), + ("imap_ultra_l1c-90sensor-static-dead-times_20250101_v000.csv", "ultra/data/l1/"), + + # l2 + ("imap_ultra_l2-energy-bin-group-sizes_20250101_v000.csv", "ultra/data/l2/"), # MAG ("mag-l1b-l1c-t013-magi-burst-in.csv", @@ -169,4 +261,9 @@ ("swe_l0_unpacked-data_20240510_v001_VALIDATION_L2_bins_v0F_15.dat", "swe/l2_validation/"), ("swe_l0_unpacked-data_20240510_v001_VALIDATION_L2_bins_v1H_14_6.dat", "swe/l2_validation/"), ("swe_l0_unpacked-data_20240510_v001_VALIDATION_L2_bins_v0H_14_6.dat", "swe/l2_validation/"), + + # GLOWS + ("combined_de_l1a.csv", "glows/validation_data"), + ("imap_glows_l0_raw_20260202-repoint00145_v001.pkts", "glows/validation_data"), + ("imap_glows_l0_raw_20251113-repoint00047_v001.pkts", "glows/validation_data") ] # fmt: skip diff --git a/imap_processing/tests/glows/conftest.py b/imap_processing/tests/glows/conftest.py index 7b3c098dc6..7f34dc6dc1 100644 --- a/imap_processing/tests/glows/conftest.py +++ b/imap_processing/tests/glows/conftest.py @@ -13,6 +13,7 @@ AncillaryParameters, ) from imap_processing.glows.l2.glows_l2 import glows_l2 +from imap_processing.glows.l2.glows_l2_data import DailyLightcurve @pytest.fixture @@ -21,6 +22,26 @@ def packet_path(): return current_directory / "validation_data" / "glows_test_packet_20110921_v01.pkts" +@pytest.fixture +def repoint_packet_path(): + current_directory = Path(__file__).parent + return ( + current_directory + / "validation_data" + / "imap_glows_l0_raw_20260202-repoint00145_v001.pkts" + ) + + +@pytest.fixture +def in_flight_packet_path(): + current_directory = Path(__file__).parent + return ( + current_directory + / "validation_data" + / "imap_glows_l0_raw_20251113-repoint00047_v001.pkts" + ) + + @pytest.fixture def decom_test_data(packet_path): """Read test data from file""" @@ -29,6 +50,14 @@ def decom_test_data(packet_path): return data_packet_list +@pytest.fixture +def in_flight_decom_test_data(in_flight_packet_path): + """Read test data from file""" + + data_packet_list = decom_glows.decom_packets(in_flight_packet_path) + return data_packet_list + + @pytest.fixture def l1a_test_data(decom_test_data): hist_l1a = [] @@ -47,19 +76,26 @@ def l1a_dataset(packet_path): @pytest.fixture -def l1b_hist_dataset(l1a_dataset, mock_ancillary_exclusions): +def l1b_hist_dataset( + l1a_dataset, + mock_ancillary_exclusions, + mock_pipeline_settings, + mock_conversion_table_dict, +): return glows_l1b( l1a_dataset[0], mock_ancillary_exclusions.excluded_regions, mock_ancillary_exclusions.uv_sources, mock_ancillary_exclusions.suspected_transients, mock_ancillary_exclusions.exclusions_by_instr_team, + mock_pipeline_settings, + mock_conversion_table_dict, ) @pytest.fixture -def l2_hist_dataset(l1b_datasets): - return glows_l2(l1b_datasets) +def l2_hist_dataset(l1b_hist_dataset, mock_pipeline_settings): + return glows_l2(l1b_hist_dataset, mock_pipeline_settings) @pytest.fixture @@ -74,13 +110,21 @@ def mock_ancillary_exclusions(): # Create datasets with epoch dimension and some mock data mock_excluded_regions = xr.Dataset( { + # degrees in [0, 360) "ecliptic_longitude_deg": ( - ["epoch", "region"], - np.random.rand(len(epoch_range), 5), + ["epoch", "source"], + np.tile( + np.array([202.0812, 120.0, 250.0], dtype=np.float64), + (len(epoch_range), 1), + ), ), + # degrees in [-90, 90] "ecliptic_latitude_deg": ( - ["epoch", "region"], - np.random.rand(len(epoch_range), 5), + ["epoch", "source"], + np.tile( + np.array([18.4119, 0.0, 35.0], dtype=np.float64), + (len(epoch_range), 1), + ), ), }, coords={"epoch": epoch_range}, @@ -92,31 +136,43 @@ def mock_ancillary_exclusions(): ["epoch", "source"], [["star1", "star2", "star3"]] * len(epoch_range), ), + # degrees in [0, 360) "ecliptic_longitude_deg": ( ["epoch", "source"], - np.random.rand(len(epoch_range), 3), + np.tile( + np.array([202.0812, 120.0, 250.0], dtype=np.float64), + (len(epoch_range), 1), + ), ), + # degrees in [-90, 90] "ecliptic_latitude_deg": ( ["epoch", "source"], - np.random.rand(len(epoch_range), 3), + np.tile( + np.array([18.4119, 0.0, 35.0], dtype=np.float64), + (len(epoch_range), 1), + ), ), + # masking radius in degrees "angular_radius_for_masking": ( ["epoch", "source"], - np.random.rand(len(epoch_range), 3), + np.tile( + np.array([2.0, 0.0, 0.0], dtype=np.float64), (len(epoch_range), 1) + ), ), }, coords={"epoch": epoch_range}, ) + # Mask array based on data in imap_glows_suspected-transients_20250923_v002.dat. mock_suspected_transients = xr.Dataset( { "l1b_unique_block_identifier": ( ["epoch", "time_block"], - [["block1", "block2"]] * len(epoch_range), + [["2026-01-01T15:00:00", "2026-01-01T15:01:00"]] * len(epoch_range), ), "histogram_mask_array": ( ["epoch", "time_block"], - [["mask1", "mask2"]] * len(epoch_range), + [["0" * 3600, "0" * 600 + "1" * 100 + "0" * 2900]] * len(epoch_range), ), }, coords={"epoch": epoch_range}, @@ -126,11 +182,11 @@ def mock_ancillary_exclusions(): { "l1b_unique_block_identifier": ( ["epoch", "time_block"], - [["block1", "block2"]] * len(epoch_range), + [["2026-01-01T15:00:00", "2026-01-01T15:01:00"]] * len(epoch_range), ), "histogram_mask_array": ( ["epoch", "time_block"], - [["mask1", "mask2"]] * len(epoch_range), + [["0" * 100 + "1" * 10 + "0" * 3490, "0" * 3600]] * len(epoch_range), ), }, coords={"epoch": epoch_range}, @@ -145,12 +201,21 @@ def mock_ancillary_exclusions(): @pytest.fixture -def mock_ancillary_parameters(): +def mock_ancillary_parameters(mock_conversion_table_dict): """Create a mock AncillaryParameters object for testing.""" - mock_table = { - "description": "Table for conversion/decoding ancillary parameters collected " - "onboard by IMAP/GLOWS", - "version": "0.1", + + return AncillaryParameters(mock_conversion_table_dict) + + +@pytest.fixture +def mock_conversion_table_dict(): + """Create a mock conversion table dataset for testing. + + This aligns with the validation output for GLOWS unit testing.""" + + mock_dict = { + "description": "Table for conversion/decoding ancillary parameters", + "version": "v001", "date_of_creation_yyyymmdd": "20230527", "filter_temperature": { "min": -30.0, @@ -160,6 +225,7 @@ def mock_ancillary_parameters(): "p02": 0.0, "p03": 0.0, "p04": 0.0, + "physical_unit": "Celsius degree", }, "hv_voltage": { "min": 0.0, @@ -169,9 +235,20 @@ def mock_ancillary_parameters(): "p02": 0.0, "p03": 0.0, "p04": 0.0, + "physical_unit": "Celsius degree", + }, + "spin_period": { + "min": 0.0, + "max": 20.9712, + "n_bits": 16, + "physical_unit": "Celsius degree", + }, + "spin_phase": { + "min": 0.0, + "max": 360.0, + "n_bits": 16, + "physical_unit": "Celsius degree", }, - "spin_period": {"min": 0.0, "max": 20.9712, "n_bits": 16}, - "spin_phase": {"min": 0.0, "max": 360.0, "n_bits": 16}, "pulse_length": { "min": 0.0, "max": 255.0, @@ -180,9 +257,109 @@ def mock_ancillary_parameters(): "p02": 0.0, "p03": 0.0, "p04": 0.0, + "physical_unit": "Celsius degree", }, } - return AncillaryParameters(mock_table) + + return mock_dict + + +@pytest.fixture +def mock_calibration_dataset(): + """Create a mock CalibrationDataset object for testing.""" + + # Both cps_per_r and start_time_utc are 2D: (epoch, *_dim_0). + return xr.Dataset( + { + "cps_per_r": xr.DataArray( + [[0.849, 1.020, 1.500], [0.849, 1.020, 1.500]], + dims=["epoch", "cps_per_r_dim_0"], + ), + "start_time_utc": xr.DataArray( + np.array( + [ + [ + "2011-09-19T09:58:04", + "2011-09-20T18:12:48", + "2011-09-21T18:15:50", + ], + [ + "2011-09-19T09:58:04", + "2011-09-20T18:12:48", + "2011-09-21T18:15:50", + ], + ], + ), + dims=["epoch", "start_time_utc_dim_0"], + ), + }, + coords={ + "epoch": np.array( + ["2011-09-19T00:00:00", "2011-09-20T00:00:00"], dtype="datetime64[s]" + ) + }, + ) + + +@pytest.fixture +def mock_pipeline_settings(): + """Create a mock PipelineSettings dataset for testing.""" + # Create a mock dataset with pipeline settings data which matches the output + # from GlowsAncillaryCombiner + epoch_range = np.arange( + np.datetime64("2010-01-01"), np.datetime64("2010-12-31"), dtype="datetime64[D]" + ) + + mock_pipeline_dataset = xr.Dataset( + { + "active_bad_angle_flags": ( + ["epoch", "flag_index"], + np.tile([True, True, True, True], (len(epoch_range), 1)), + ), + "active_bad_time_flags": ( + ["epoch", "time_flag_index"], + np.tile( + [True] * 17, (len(epoch_range), 1) + ), # 17 bad time flags from the JSON + ), + "sunrise_offset": (["epoch"], [0.0] * len(epoch_range)), + "sunset_offset": (["epoch"], [0.0] * len(epoch_range)), + "spin_offset_correction": (["epoch"], [0.0] * len(epoch_range)), + "n_sigma_threshold_lower": (["epoch"], [3.0] * len(epoch_range)), + "n_sigma_threshold_upper": (["epoch"], [3.0] * len(epoch_range)), + "relative_difference_threshold": (["epoch"], [7.0e-5] * len(epoch_range)), + "std_dev_threshold__celsius_deg": (["epoch"], [2.03] * len(epoch_range)), + "std_dev_threshold__volt": (["epoch"], [50.0] * len(epoch_range)), + "std_dev_threshold__sec": (["epoch"], [0.033333] * len(epoch_range)), + "std_dev_threshold__usec": (["epoch"], [1.0] * len(epoch_range)), + "angular_radius_for_excl_regions__deg": ( + ["epoch"], + [2.0] * len(epoch_range), + ), + "number_of_good_histograms_at_night": (["epoch"], [3] * len(epoch_range)), + "l3a_nominal_number_of_bins": (["epoch"], [90] * len(epoch_range)), + }, + coords={"epoch": epoch_range}, + ) + + return mock_pipeline_dataset + + +@pytest.fixture +def mock_ecliptic_bin_centers(monkeypatch): + """Mock ecliptic coordinates for bin centers.""" + + def _mock_compute_coords( + _data_start_time_et: float, spin_angle: np.ndarray + ) -> tuple[np.ndarray, np.ndarray]: + n_bins = len(spin_angle) + return np.zeros(n_bins, dtype=float), np.zeros(n_bins, dtype=float) + + monkeypatch.setattr( + DailyLightcurve, + "compute_ecliptic_coords_of_bin_centers", + staticmethod(_mock_compute_coords), + ) def mock_update_spice_parameters(self, *args, **kwargs): diff --git a/imap_processing/tests/glows/test_glows_l1a_cdf.py b/imap_processing/tests/glows/test_glows_l1a_cdf.py index 9f6fce9381..5e648436ac 100644 --- a/imap_processing/tests/glows/test_glows_l1a_cdf.py +++ b/imap_processing/tests/glows/test_glows_l1a_cdf.py @@ -1,13 +1,19 @@ import dataclasses +from unittest.mock import MagicMock import numpy as np +import pytest +from imap_processing.glows.l0.decom_glows import decom_packets from imap_processing.glows.l1a.glows_l1a import ( create_glows_attr_obj, generate_de_dataset, generate_histogram_dataset, + glows_l1a, ) +from imap_processing.glows.l1a.glows_l1a_data import HistogramL1A from imap_processing.glows.utils.constants import TimeTuple +from imap_processing.spice.time import met_to_ttj2000ns def test_generate_histogram_dataset(l1a_test_data): @@ -33,19 +39,72 @@ def test_generate_histogram_dataset(l1a_test_data): dataset["is_generated_on_ground"].data[0] == item["is_generated_on_ground"] ) - elif key not in ["histogram", "ground_software_version", "pkts_file_name"]: - assert dataset[key].data[0] == item for i in range(len(dataset["histogram"].data)): assert (dataset["histogram"].data[i] == histogram_l1a[i].histogram).all() + for i, hist in enumerate(histogram_l1a): + expected_epoch = met_to_ttj2000ns( + hist.imap_start_time.to_seconds() + hist.imap_time_offset.to_seconds() / 2 + ) + assert dataset["epoch"].data[i] == expected_epoch + + +def test_generate_histogram_dataset_filters_empty(l1a_test_data): + histogram_l1a, _ = l1a_test_data + glows_attrs = create_glows_attr_obj() + + # Create an empty histogram (number_of_bins_per_histogram == 0) + empty_hist = MagicMock() + empty_hist.number_of_bins_per_histogram = 0 + empty_hist.histogram = [] + + # Mix empty histograms into the list + mixed_list = [empty_hist, histogram_l1a[0], empty_hist, histogram_l1a[1]] + + dataset = generate_histogram_dataset(mixed_list, glows_attrs) + + # Only the two non-empty histograms should appear in the output + assert len(dataset["epoch"].values) == 2 + + +def test_generate_histogram_dataset_filters_zero_imap_start_time(l1a_test_data): + histogram_l1a, _ = l1a_test_data + glows_attrs = create_glows_attr_obj() + + zero_time_hist = MagicMock() + zero_time_hist.number_of_bins_per_histogram = 3600 + zero_time_hist.imap_start_time = TimeTuple(0, 0) + + mixed_list = [zero_time_hist, histogram_l1a[0], zero_time_hist, histogram_l1a[1]] + + dataset = generate_histogram_dataset(mixed_list, glows_attrs) + + assert len(dataset["epoch"].values) == 2 + + +@pytest.mark.external_test_data +def test_generate_histogram_dataset_deduplicates(in_flight_packet_path): + hist_l0, _ = decom_packets(in_flight_packet_path) + hist_l1a = [HistogramL1A(h) for h in hist_l0] + glows_attrs = create_glows_attr_obj() + + dataset = generate_histogram_dataset(hist_l1a, glows_attrs) + + epochs = dataset["epoch"].values.tolist() + assert len(epochs) == len(set(epochs)) + def test_generate_de_dataset(l1a_test_data): _, de_l1a = l1a_test_data glows_attrs = create_glows_attr_obj() + dataset = generate_de_dataset(de_l1a, glows_attrs) - assert len(dataset["epoch"].values) == len(de_l1a) + non_none_len = len([de for de in de_l1a if de.de_data is not None]) + assert len(dataset["epoch"].values) == non_none_len + # Output dataarrays are padded to the longest length in the entire set of packets. + # Test data for the first and last DE need to be padded to this length assert ( dataset["direct_events"].data[0] == np.pad( @@ -59,3 +118,16 @@ def test_generate_de_dataset(l1a_test_data): [event.to_list() for event in de_l1a[-1].direct_events], ((0, 651), (0, 0)) ) ).all() + + +@pytest.mark.external_test_data +def test_glows_l1a_no_zero_imap_start_time(in_flight_packet_path): + hist_l0, _ = decom_packets(in_flight_packet_path) + hist_l1a = [HistogramL1A(h) for h in hist_l0] + non_empty = [h for h in hist_l1a if h.number_of_bins_per_histogram > 0] + excluded = [h for h in non_empty if h.imap_start_time.seconds == 0] + + datasets = glows_l1a(in_flight_packet_path) + hist_dataset = next(ds for ds in datasets if "hist" in ds.attrs["Logical_source"]) + assert (hist_dataset["imap_start_time"].values != 0).all() + assert len(excluded) == 77 diff --git a/imap_processing/tests/glows/test_glows_l1a_data.py b/imap_processing/tests/glows/test_glows_l1a_data.py index 5c475cccad..4ee0cda652 100644 --- a/imap_processing/tests/glows/test_glows_l1a_data.py +++ b/imap_processing/tests/glows/test_glows_l1a_data.py @@ -1,13 +1,12 @@ -import ast import dataclasses import json from pathlib import Path +from unittest import mock import numpy as np import pandas as pd import pytest -from imap_processing.glows import __version__ from imap_processing.glows.l1a.glows_l1a import glows_l1a from imap_processing.glows.l1a.glows_l1a_data import ( DirectEventL1A, @@ -40,6 +39,45 @@ def test_histogram_list(histogram_test_data, decom_test_data): assert sum(histogram_test_data.histogram) == histl0.EVENTS +def test_histogram_bin_handling(decom_test_data): + """Test histogram bin handling for odd bins.""" + histl0 = decom_test_data[0][0] + + # Test odd number of bins - extra byte should be removed + mock_histl0_odd = mock.MagicMock(spec=histl0) + mock_histl0_odd.NBINS = 3599 + mock_histl0_odd.HISTOGRAM_DATA = list(range(3600)) + mock_histl0_odd.SWVER = 1 + mock_histl0_odd.packet_file_name = "test.pkts" + mock_histl0_odd.ccsds_header = mock.MagicMock() + mock_histl0_odd.ccsds_header.SRC_SEQ_CTR = 0 + mock_histl0_odd.STARTID = 0 + mock_histl0_odd.ENDID = 10 + mock_histl0_odd.SEC = 1000 + mock_histl0_odd.SUBSEC = 0 + mock_histl0_odd.OFFSETSEC = 0 + mock_histl0_odd.OFFSETSUBSEC = 0 + mock_histl0_odd.GLXSEC = 1000 + mock_histl0_odd.GLXSUBSEC = 0 + mock_histl0_odd.GLXOFFSEC = 0 + mock_histl0_odd.GLXOFFSUBSEC = 0 + mock_histl0_odd.SPINS = 10 + mock_histl0_odd.EVENTS = 1000 + mock_histl0_odd.TEMPAVG = 100 + mock_histl0_odd.TEMPVAR = 10 + mock_histl0_odd.HVAVG = 500 + mock_histl0_odd.HVVAR = 5 + mock_histl0_odd.SPAVG = 150 + mock_histl0_odd.SPVAR = 1 + mock_histl0_odd.ELAVG = 20 + mock_histl0_odd.ELVAR = 2 + mock_histl0_odd.FLAGS = 0 + + hist_odd = HistogramL1A(mock_histl0_odd) + assert len(hist_odd.histogram) == 3599 + assert hist_odd.number_of_bins_per_histogram == 3599 + + def test_histogram_obs_day(packet_path): l1a = glows_l1a(packet_path) @@ -59,7 +97,6 @@ def test_histogram_attributes(histogram_test_data): expected_block_header = { "flight_software_version": 131329, - "ground_software_version": __version__, "pkts_file_name": "glows_test_packet_20110921_v01.pkts", "seq_count_in_pkts_file": 0, } @@ -68,10 +105,6 @@ def test_histogram_attributes(histogram_test_data): histogram_test_data.flight_software_version == expected_block_header["flight_software_version"] ) - assert ( - histogram_test_data.ground_software_version - == expected_block_header["ground_software_version"] - ) assert histogram_test_data.pkts_file_name == expected_block_header["pkts_file_name"] assert ( histogram_test_data.seq_count_in_pkts_file @@ -384,26 +417,25 @@ def test_generate_status_data(): assert dataclasses.asdict(output) == expected +@pytest.mark.external_test_data def test_expected_de_results(l1a_test_data): _, de_data = l1a_test_data # Validation data is generated from the code sent over by GLOWS team. Contains the # first 20 packets validation_data = pd.read_csv( - Path(__file__).parent - / "validation_data" - / "direct_events_validation_data_l1a.csv", - converters={"de_data": ast.literal_eval}, + Path(__file__).parent / "validation_data" / "combined_de_l1a.csv", + converters={ + "de_data": lambda x: [ + [int(i) for i in n.split(" ") if i != ""] for n in x.split("\n") + ] + }, ) - assert validation_data.index.size == 5703 for index in validation_data.index: - de = de_data[validation_data["packet_counter"][index]] + de = de_data[index] - assert ( - de.l0.ccsds_header.SRC_SEQ_CTR - == validation_data["seq_count_in_pkts_file"][index] - ) + assert de.l0.SEC == validation_data["imap_start_time_seconds"][index] assert ( de.status_data.imap_sclk_last_pps == validation_data["imap_sclk_last_pps"][index] @@ -481,26 +513,11 @@ def test_expected_de_results(l1a_test_data): assert de.l0.LEN == validation_data["number_of_de_packets"][index] - assert ( - de.direct_events[ - validation_data["de_data_counter"][index] - ].timestamp.seconds - == validation_data["de_data"][index][0] - ) - assert ( - de.direct_events[ - validation_data["de_data_counter"][index] - ].timestamp.subseconds - == validation_data["de_data"][index][1] - ) - assert ( - de.direct_events[validation_data["de_data_counter"][index]].impulse_length - == validation_data["de_data"][index][2] - ) - assert ( - de.direct_events[validation_data["de_data_counter"][index]].multi_event - == validation_data["de_data"][index][3] - ) + de_val = validation_data["de_data"][index] + for de_counter, direct_event in enumerate(de.direct_events): + assert direct_event.timestamp.seconds == de_val[de_counter][0] + assert direct_event.timestamp.subseconds == de_val[de_counter][1] + assert direct_event.impulse_length == de_val[de_counter][2] def test_expected_hist_results(l1a_dataset): @@ -521,10 +538,11 @@ def test_expected_hist_results(l1a_dataset): } # block header and flags are handled differently, so not tested here + # "number_of_spins_per_block" is a special case and handled specifically + # (validation data is incorrect) compare_fields = [ "first_spin_id", "last_spin_id", - "number_of_spins_per_block", "number_of_bins_per_histogram", "histogram", "number_of_events", @@ -539,12 +557,15 @@ def test_expected_hist_results(l1a_dataset): ] for data in out["output"]: - epoch_val = met_to_ttj2000ns( - TimeTuple( - data["imap_start_time"]["seconds"], - data["imap_start_time"]["subseconds"], - ).to_seconds() - ) + imap_start = TimeTuple( + data["imap_start_time"]["seconds"], + data["imap_start_time"]["subseconds"], + ).to_seconds() + imap_offset = TimeTuple( + data["imap_end_time_offset"]["seconds"], + data["imap_end_time_offset"]["subseconds"], + ).to_seconds() + epoch_val = met_to_ttj2000ns(imap_start + imap_offset / 2) # Validation data spans the two obs days, so this selects the correct output dataset_index = 1 if epoch_val > end_time else 0 @@ -559,3 +580,23 @@ def test_expected_hist_results(l1a_dataset): for field in compare_fields: assert np.array_equal(data[field], datapoint[field].data) + assert np.array_equal( + data["number_of_spins_per_block"] - 1, + datapoint["number_of_spins_per_block"].data, + ) + + +@mock.patch("imap_processing.glows.l1a.glows_l1a.decom_packets") +def test_glows_l1a_no_packet_data(decom_packets_mock): + # Should return empty list when no packet data is present + decom_packets_mock.return_value = ([], []) + output = glows_l1a("fake/filepath/packets.bin") + assert output == [] + + +@pytest.mark.external_test_data +def test_glows_l1a_empty_de_packet(repoint_packet_path): + """Test that L1A processing handles packets with no direct event data.""" + result = glows_l1a(repoint_packet_path) + + assert len(result) == 2 diff --git a/imap_processing/tests/glows/test_glows_l1b.py b/imap_processing/tests/glows/test_glows_l1b.py index 41654e5344..c13c9e9ac8 100644 --- a/imap_processing/tests/glows/test_glows_l1b.py +++ b/imap_processing/tests/glows/test_glows_l1b.py @@ -8,26 +8,34 @@ from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes from imap_processing.cdf.utils import write_cdf -from imap_processing.glows.l1b.glows_l1b import glows_l1b, process_de, process_histogram +from imap_processing.glows.l1b.glows_l1b import ( + glows_l1b, + glows_l1b_de, + process_de, + process_histogram, +) from imap_processing.glows.l1b.glows_l1b_data import ( AncillaryParameters, DirectEventL1B, HistogramL1B, + PipelineSettings, ) +from imap_processing.spice.geometry import cartesian_to_spherical +from imap_processing.spice.time import met_to_datetime64 from imap_processing.tests.glows.conftest import mock_update_spice_parameters +# Fixture for L1a histogram dataset @pytest.fixture def hist_dataset(): variables = { - "flight_software_version": np.zeros((20,)), "seq_count_in_pkts_file": np.zeros((20,)), "first_spin_id": np.zeros((20,)), "last_spin_id": np.zeros((20,)), "flags_set_onboard": np.zeros((20,)), "is_generated_on_ground": np.zeros((20,)), "number_of_spins_per_block": np.zeros((20,)), - "number_of_bins_per_histogram": np.zeros((20,)), + "number_of_bins_per_histogram": np.full((20,), 3600), "number_of_events": np.zeros((20,)), "filter_temperature_average": np.zeros((20,)), "filter_temperature_variance": np.zeros((20,)), @@ -37,27 +45,26 @@ def hist_dataset(): "spin_period_variance": np.zeros((20,)), "pulse_length_average": np.zeros((20,)), "pulse_length_variance": np.zeros((20,)), - "imap_start_time": np.zeros((20,)), + "imap_start_time": np.arange(1, 21, dtype=np.float64), "imap_time_offset": np.zeros((20,)), "glows_start_time": np.zeros((20,)), "glows_time_offset": np.zeros((20,)), } cdf_attrs = ImapCdfAttributes() cdf_attrs.add_instrument_global_attrs("glows") - cdf_attrs.add_instrument_variable_attrs("glows", "l1b") + cdf_attrs.add_instrument_variable_attrs("glows", "l1a") epoch = xr.DataArray( np.arange(20), name="epoch", dims=["epoch"], - attrs=cdf_attrs.get_variable_attributes("epoch"), + attrs=cdf_attrs.get_variable_attributes("epoch", check_schema=False), ) bins = xr.DataArray(np.arange(3600), name="bins", dims=["bins"]) ds = xr.Dataset( - coords={"epoch": epoch}, - attrs=cdf_attrs.get_global_attributes("imap_glows_l1b_hist"), + attrs=cdf_attrs.get_global_attributes("imap_glows_l1a_hist"), ) ds["histogram"] = xr.DataArray( @@ -69,6 +76,9 @@ def hist_dataset(): for var, data in variables.items(): ds[var] = xr.DataArray(data, dims=["epoch"], coords={"epoch": epoch}) + ds.attrs["flight_software_version"] = np.array([67], dtype=int) + ds.attrs["Parents"] = ["test_packet_file.pkts", "test_spice_file.tls"] + return ds @@ -141,6 +151,8 @@ def de_dataset(): }, ) + ds.attrs["Parents"] = ["test_packet_file.pkts", "test_spice_file.tls"] + for var, data in variables.items(): ds[var] = xr.DataArray(data, dims=["epoch"], coords={"epoch": epoch}) @@ -187,33 +199,44 @@ def ancillary_dict(): return dictionary +@patch.object( + HistogramL1B, + "flag_uv_and_excluded", + return_value=(np.zeros(3600, dtype=bool), np.zeros(3600, dtype=bool)), +) @patch.object(HistogramL1B, "update_spice_parameters", autospec=True) def test_histogram_mapping( - mock_spice_function, mock_ancillary_exclusions, mock_ancillary_parameters + mock_spice_function, + mock_flag_uv_and_excluded, + mock_ancillary_exclusions, + mock_ancillary_parameters, + mock_pipeline_settings, ): mock_spice_function.side_effect = mock_update_spice_parameters - time_val = 1111111.11 - # A = 2.318 - # B = 69.5454 - expected_temp = 100 + time_val = np.double(1111111.11) - test_hists = np.zeros((200, 3600)) - # For temp - encoded_val = expected_temp * 2.318 + 69.5454 + test_hists = np.zeros(3600) + expected_temp = 100 + encoded_val = np.double(expected_temp * 2.3182 + 69.5455) # For now, testing types and number of inputs + pipeline_settings = PipelineSettings( + mock_pipeline_settings.sel( + epoch=mock_pipeline_settings.epoch[0], method="nearest" + ) + ) + output = tuple( dataclasses.asdict( HistogramL1B( test_hists, - "test", - 0, 0, 0, 0, 0, 0, 0, + 3600, 0, encoded_val, encoded_val, @@ -229,69 +252,172 @@ def test_histogram_mapping( time_val, mock_ancillary_exclusions, mock_ancillary_parameters, + pipeline_settings, ) ).values() ) - assert output[18] == time_val - # Correctly decoded temperature - assert output[10] - expected_temp < 0.1 + assert np.isclose(output[9], expected_temp, 0.1) + + # Ensure time values are correctly mapped + assert output[17] == time_val + assert output[20] == time_val +@patch.object( + HistogramL1B, + "flag_uv_and_excluded", + return_value=(np.zeros(3600, dtype=bool), np.zeros(3600, dtype=bool)), +) @patch.object(HistogramL1B, "update_spice_parameters", autospec=True) def test_process_histogram( mock_spice_function, + mock_flag_uv_and_excluded, hist_dataset, mock_ancillary_exclusions, mock_ancillary_parameters, + mock_pipeline_settings, ): mock_spice_function.side_effect = mock_update_spice_parameters - time_val = np.single(1111111.11) - # A = 2.318 - # B = 69.5454 + time_val = np.double(1111111.11) expected_temp = 100 - test_hists = np.zeros((200,)) + test_hists = np.zeros(3600) # For temp - encoded_val = np.single(expected_temp * 2.318 + 69.5454) + encoded_val = np.double(expected_temp * 2.3182 + 69.5455) + + pipeline_settings = PipelineSettings( + mock_pipeline_settings.sel( + epoch=mock_pipeline_settings.epoch[0], method="nearest" + ) + ) test_l1b = HistogramL1B( test_hists, - "test", - 0, - 0, - 0, 0, 0, 0, + 64, # flags_set_onboard: bit 6 (is_night) set + 1, # is_generated_on_ground 0, + 3600, 0, encoded_val, + np.single(30.0), # filter_temperature_variance: exceeds 2.03Β°C threshold encoded_val, + np.single(3500.0), # hv_voltage_variance: exceeds 50.0V threshold encoded_val, + np.single(11000.0), # spin_period_variance: exceeds 0.033333s threshold encoded_val, - encoded_val, - encoded_val, - encoded_val, - encoded_val, + np.single(2.0), # pulse_length_variance: exceeds 1.0ΞΌs threshold time_val, time_val, time_val, time_val, mock_ancillary_exclusions, mock_ancillary_parameters, + pipeline_settings, ) output = process_histogram( - hist_dataset, mock_ancillary_exclusions, mock_ancillary_parameters + hist_dataset, + mock_ancillary_exclusions, + mock_ancillary_parameters, + pipeline_settings, ) assert len(output) == len(dataclasses.asdict(test_l1b)) + # flags[0:10] = onboard flags (1=good, 0=bad), one per bit of flags_set_onboard + # flags[10] = is_generated_on_ground (1=onboard, 0=ground) + # flags[11] = is_beyond_daily_statistical_error (placeholder, always 1) + # flags[12:16] = std_dev threshold flags + # flags[16] = is_beyond_background + assert test_l1b.flags[6] == 0 # is_night + assert test_l1b.flags[10] == 0 # is_generated_on_ground + assert test_l1b.flags[12] == 0 # is_temp_ok + assert test_l1b.flags[13] == 0 # is_hv_ok + assert test_l1b.flags[14] == 0 # is_spin_std_ok + assert test_l1b.flags[15] == 0 # is_pulse_ok + assert test_l1b.flags[16] == 1 # is_beyond_background + + +@patch.object( + HistogramL1B, + "flag_uv_and_excluded", + return_value=(np.zeros(3600, dtype=bool), np.zeros(3600, dtype=bool)), +) +@patch.object(HistogramL1B, "update_spice_parameters", autospec=True) +def test_bins_from_histogram_not_nbins( + mock_spice_function, + mock_flag_uv_and_excluded, + hist_dataset, + mock_ancillary_exclusions, + mock_ancillary_parameters, + mock_pipeline_settings, +): + """Output bin arrays should use len(histogram), not number_of_bins_per_histogram.""" + mock_spice_function.side_effect = mock_update_spice_parameters + # Set NBINS to a value that differs from the actual histogram length (3600) + hist_dataset["number_of_bins_per_histogram"][:] = 225 + + pipeline_settings = PipelineSettings( + mock_pipeline_settings.sel( + epoch=mock_pipeline_settings.epoch[0], method="nearest" + ) + ) + output = process_histogram( + hist_dataset, + mock_ancillary_exclusions, + mock_ancillary_parameters, + pipeline_settings, + ) + # All output variables with a bins dimension must use len(histogram), not NBINS + for da in output: + if "bins" in da.sizes: + assert da.sizes["bins"] == 3600 -def test_process_de(de_dataset, ancillary_dict): - output = process_de(de_dataset) + +@patch.object( + HistogramL1B, + "flag_uv_and_excluded", + return_value=(np.zeros(3600, dtype=bool), np.zeros(3600, dtype=bool)), +) +@patch.object(HistogramL1B, "update_spice_parameters", autospec=True) +def test_process_histogram_skips_zero_imap_start_time( + mock_spice_function, + mock_flag_uv_and_excluded, + hist_dataset, + mock_ancillary_exclusions, + mock_ancillary_parameters, + mock_pipeline_settings, +): + mock_spice_function.side_effect = mock_update_spice_parameters + pipeline_settings = PipelineSettings( + mock_pipeline_settings.sel( + epoch=mock_pipeline_settings.epoch[0], method="nearest" + ) + ) + + # Set two epochs to invalid time + hist_dataset["imap_start_time"].values[3] = 0.0 + hist_dataset["imap_start_time"].values[7] = 0.0 + + output = process_histogram( + hist_dataset, + mock_ancillary_exclusions, + mock_ancillary_parameters, + pipeline_settings, + ) + # 2 invalid epochs dropped; 18 valid epochs remain in every output DataArray + for da in output: + assert da.sizes["epoch"] == 18 + assert len(output[0].coords["epoch"]) == 18 + + +def test_process_de(de_dataset, ancillary_dict, mock_ancillary_parameters): + output = process_de(de_dataset, mock_ancillary_parameters) # Output has the same length as non-initvar fields in DirectEventL1B assert len(output) == len(dataclasses.fields(DirectEventL1B)) @@ -308,9 +434,20 @@ def test_process_de(de_dataset, ancillary_dict): assert np.isclose(output[8].data[0], expected_temp) +@patch.object( + HistogramL1B, + "flag_uv_and_excluded", + return_value=(np.zeros(3600, dtype=bool), np.zeros(3600, dtype=bool)), +) @patch.object(HistogramL1B, "update_spice_parameters", autospec=True) def test_glows_l1b( - mock_spice_function, de_dataset, hist_dataset, mock_ancillary_exclusions + mock_spice_function, + mock_flag_uv_and_excluded, + de_dataset, + hist_dataset, + mock_ancillary_exclusions, + mock_pipeline_settings, + mock_conversion_table_dict, ): mock_spice_function.side_effect = mock_update_spice_parameters @@ -320,6 +457,8 @@ def test_glows_l1b( mock_ancillary_exclusions.uv_sources, mock_ancillary_exclusions.suspected_transients, mock_ancillary_exclusions.exclusions_by_instr_team, + mock_pipeline_settings, + mock_conversion_table_dict, ) assert hist_output["histogram"].dims == ("epoch", "bins") @@ -327,11 +466,7 @@ def test_glows_l1b( # This needs to be added eventually, but is skipped for now. expected_de_data = [ - "flight_software_version", - "ground_software_version", "pkts_file_name", - "seq_count_in_pkts_file", - "l1a_file_name", "ancillary_data_files", ] @@ -368,17 +503,17 @@ def test_glows_l1b( "spacecraft_velocity_std_dev", "flags", ] - for key in expected_hist_data: assert key in hist_output - de_output = glows_l1b( - de_dataset, - mock_ancillary_exclusions.excluded_regions, - mock_ancillary_exclusions.uv_sources, - mock_ancillary_exclusions.suspected_transients, - mock_ancillary_exclusions.exclusions_by_instr_team, - ) + expected_global_attrs = [ + "flight_software_version", + "pkts_file_name", + ] + for key in expected_global_attrs: + assert key in hist_output._attrs + + de_output = glows_l1b_de(de_dataset, mock_conversion_table_dict) # From table 15 in the algorithm document expected_de_data = [ @@ -400,9 +535,19 @@ def test_glows_l1b( assert key in de_output +@patch.object( + HistogramL1B, + "flag_uv_and_excluded", + return_value=(np.zeros(3600, dtype=bool), np.zeros(3600, dtype=bool)), +) @patch.object(HistogramL1B, "update_spice_parameters", autospec=True) def test_generate_histogram_dataset( - mock_spice_function, hist_dataset, mock_ancillary_exclusions + mock_spice_function, + mock_flag_uv_and_excluded, + hist_dataset, + mock_ancillary_exclusions, + mock_pipeline_settings, + mock_conversion_table_dict, ): mock_spice_function.side_effect = mock_update_spice_parameters @@ -412,6 +557,8 @@ def test_generate_histogram_dataset( mock_ancillary_exclusions.uv_sources, mock_ancillary_exclusions.suspected_transients, mock_ancillary_exclusions.exclusions_by_instr_team, + mock_pipeline_settings, + mock_conversion_table_dict, ) output_path = write_cdf(l1b_data) @@ -419,14 +566,13 @@ def test_generate_histogram_dataset( assert Path.exists(output_path) -def test_generate_de_dataset(de_dataset, mock_ancillary_exclusions): - l1b_data = glows_l1b( - de_dataset, - mock_ancillary_exclusions.excluded_regions, - mock_ancillary_exclusions.uv_sources, - mock_ancillary_exclusions.suspected_transients, - mock_ancillary_exclusions.exclusions_by_instr_team, - ) +def test_generate_de_dataset( + de_dataset, + mock_ancillary_exclusions, + mock_pipeline_settings, + mock_conversion_table_dict, +): + l1b_data = glows_l1b_de(de_dataset, mock_conversion_table_dict) output_path = write_cdf(l1b_data) @@ -442,6 +588,7 @@ def test_hist_spice_output( furnish_kernels, mock_ancillary_exclusions, mock_ancillary_parameters, + mock_pipeline_settings, ): # Mock the imap_state function mock_imap_state.return_value = np.array( @@ -455,8 +602,7 @@ def test_hist_spice_output( data_start_time = 504975600.125 # 2026-01-01T15:00:00.125 use_fake_spin_data_for_time(data_start_time) params = { - "histogram": np.zeros((1, 3600)), - "flight_software_version": "v0.0.1", + "histogram": np.zeros(3600), "seq_count_in_pkts_file": 0, "first_spin_id": 0, "last_spin_id": 0, @@ -479,20 +625,30 @@ def test_hist_spice_output( "glows_time_offset": 200.0, "ancillary_exclusions": mock_ancillary_exclusions, "ancillary_parameters": mock_ancillary_parameters, + "pipeline_settings": PipelineSettings( + mock_pipeline_settings.sel( + epoch=mock_pipeline_settings.epoch[0], method="nearest" + ), + ), } kernels = [ "naif0012.tls", "de440s.bsp", "imap_sclk_0000.tsc", - "imap_wkcp.tf", - "imap_science_100.tf", + "imap_130.tf", + "imap_science_120.tf", "sim_1yr_imap_attitude.bc", "sim_1yr_imap_pointing_frame.bc", ] with furnish_kernels(kernels): hist_data = HistogramL1B(**params) + day = met_to_datetime64(hist_data.imap_start_time) + day_exclusions = mock_ancillary_exclusions.limit_by_day(day) + + uv_mask, region_mask = hist_data.flag_uv_and_excluded(day_exclusions) + # Assert that all these variables are the correct shape: assert isinstance(hist_data.spin_period_ground_average, np.float64) assert isinstance(hist_data.spin_period_ground_std_dev, np.float64) @@ -504,5 +660,53 @@ def test_hist_spice_output( assert hist_data.spacecraft_location_std_dev.shape == (3,) assert hist_data.spacecraft_velocity_average.shape == (3,) assert hist_data.spacecraft_velocity_std_dev.shape == (3,) + assert uv_mask.shape == (3600,) + # For 2 degree radius: 20 + 20 + 1(center) β‰ˆ 41 bins. + assert np.count_nonzero(uv_mask) == 41 + # Each individual excluded region center can only flag 0 or 1 bins + # (since the 0.05Β° threshold is exactly half the 0.1Β° bin spacing. + assert np.count_nonzero(region_mask) == 1 + + assert np.all(uv_mask[1397:1437]) + assert region_mask[1417] + + # Test flag_from_mask_dataset using the fixture data + instr_mask = hist_data.flag_from_mask_dataset( + day_exclusions.exclusions_by_instr_team + ) + assert instr_mask.shape == (3600,) + assert np.count_nonzero(instr_mask) == 10 # TODO: Maxine will validate actual data with GLOWS team + + +def test_calculate_calculate_look_vectors_dps_uses_correct_azimuth_calculation( + furnish_kernels, +): + kernels = [ + "imap_130.tf", + ] + with furnish_kernels(kernels): + imap_spin_angle_bin_cntr = np.array([0, 90, 180, 270]) + some_position_angle_offset_average = np.double(41.5) + + expected_azimuth = ( + np.array([360, 90, 180, 270]) - some_position_angle_offset_average + ) + expected_radius = np.array([1, 1, 1, 1]) + + # As-built mounting elevation of GLOWS in the s/c frame is 15.025791 degrees + expected_elevation = np.array([15.025791, 15.025791, 15.025791, 15.025791]) + + look_vectors = HistogramL1B.calculate_look_vectors_dps( + imap_spin_angle_bin_cntr, some_position_angle_offset_average + ) + + actual_spherical = cartesian_to_spherical(look_vectors) + actual_azimuth = actual_spherical[:, 1] + actual_radius = actual_spherical[:, 0] + actual_elevation = actual_spherical[:, 2] + + np.testing.assert_allclose(expected_azimuth, actual_azimuth) + np.testing.assert_allclose(expected_radius, actual_radius) + np.testing.assert_allclose(expected_elevation, actual_elevation) diff --git a/imap_processing/tests/glows/test_glows_l1b_data.py b/imap_processing/tests/glows/test_glows_l1b_data.py index 855b252098..bc298c4680 100644 --- a/imap_processing/tests/glows/test_glows_l1b_data.py +++ b/imap_processing/tests/glows/test_glows_l1b_data.py @@ -3,13 +3,16 @@ from unittest.mock import patch import numpy as np +import pandas as pd import pytest +import xarray as xr -from imap_processing.glows.l1b.glows_l1b import glows_l1b +from imap_processing.glows.l1b.glows_l1b import glows_l1b, glows_l1b_de from imap_processing.glows.l1b.glows_l1b_data import ( AncillaryParameters, DirectEventL1B, HistogramL1B, + PipelineSettings, ) from imap_processing.spice.time import met_to_ttj2000ns from imap_processing.tests.glows.conftest import mock_update_spice_parameters @@ -81,28 +84,38 @@ def test_glows_l1b_de(): assert np.allclose(pulse_len, expected_pulse) +@patch.object( + HistogramL1B, + "flag_uv_and_excluded", + return_value=(np.zeros(3600, dtype=bool), np.zeros(3600, dtype=bool)), +) @patch.object(HistogramL1B, "update_spice_parameters", autospec=True) def test_validation_data_histogram( - mock_spice_function, l1a_dataset, mock_ancillary_exclusions + mock_spice_function, + mock_flag_uv_and_excluded, + l1a_dataset, + mock_ancillary_exclusions, + mock_pipeline_settings, + mock_conversion_table_dict, ): mock_spice_function.side_effect = mock_update_spice_parameters - l1b = [ - glows_l1b( - l1a_dataset[0], - mock_ancillary_exclusions.excluded_regions, - mock_ancillary_exclusions.uv_sources, - mock_ancillary_exclusions.suspected_transients, - mock_ancillary_exclusions.exclusions_by_instr_team, - ), - glows_l1b( - l1a_dataset[1], - mock_ancillary_exclusions.excluded_regions, - mock_ancillary_exclusions.uv_sources, - mock_ancillary_exclusions.suspected_transients, - mock_ancillary_exclusions.exclusions_by_instr_team, - ), - ] - end_time = l1b[0]["epoch"].data[-1] + ds = l1a_dataset[0] + ds.attrs["flight_software_version"] = ds.attrs["flight_software_version"] + ds.attrs["Parents"] = np.array( + ["glows_test_packet_20110921_v01.pkts", "test_spice_file.tls"], dtype=object + ) + + # Only test with histogram data (l1a_dataset[0]) + l1b = glows_l1b( + ds, + mock_ancillary_exclusions.excluded_regions, + mock_ancillary_exclusions.uv_sources, + mock_ancillary_exclusions.suspected_transients, + mock_ancillary_exclusions.exclusions_by_instr_team, + mock_pipeline_settings, + mock_conversion_table_dict, + ) + end_time = l1b["epoch"].data[-1] validation_data = ( Path(__file__).parent @@ -118,7 +131,6 @@ def test_validation_data_histogram( "glows_end_time_offset": "glows_time_offset", "imap_start_time": "imap_start_time", "imap_end_time_offset": "imap_time_offset", - "number_of_spins_per_block": "number_of_spins_per_block", "number_of_bins_per_histogram": "number_of_bins_per_histogram", "histogram": "histogram", "number_of_events": "number_of_events", @@ -146,11 +158,15 @@ def test_validation_data_histogram( } for validation_output in out["output"]: - epoch_val = met_to_ttj2000ns(validation_output["imap_start_time"]) + epoch_val = met_to_ttj2000ns( + validation_output["imap_start_time"] + + validation_output["imap_end_time_offset"] / 2 + ) - # Validation data spans the two obs days, so this selects the correct output - dataset_index = 1 if epoch_val > end_time else 0 - datapoint = l1b[dataset_index].sel(epoch=epoch_val) + # Skip validation data that doesn't match our single dataset timerange + if epoch_val > end_time: + continue + datapoint = l1b.sel(epoch=epoch_val) assert np.equal( validation_output["imap_start_time"], @@ -167,16 +183,15 @@ def test_validation_data_histogram( ) -def test_validation_data_de(l1a_dataset, mock_ancillary_exclusions): +def test_validation_data_de( + l1a_dataset, + mock_ancillary_exclusions, + mock_pipeline_settings, + mock_conversion_table_dict, +): de_data = l1a_dataset[1] - l1b = glows_l1b( - de_data, - mock_ancillary_exclusions.excluded_regions, - mock_ancillary_exclusions.uv_sources, - mock_ancillary_exclusions.suspected_transients, - mock_ancillary_exclusions.exclusions_by_instr_team, - ) + l1b = glows_l1b_de(de_data, mock_conversion_table_dict) validation_data = ( Path(__file__).parent / "validation_data" / "imap_glows_l1b_de_output.json" ) @@ -224,3 +239,199 @@ def test_validation_data_de(l1a_dataset, mock_ancillary_exclusions): def test_deserialize_flags(flags, expected): output = HistogramL1B.deserialize_flags(flags) assert np.array_equal(output, expected) + + +def test_pipeline_settings_from_flattened_json(): + """PipelineSettings correctly reads flags from flattened JSON format. + + convert_json_to_dataset flattens nested dicts, so + active_bad_time_flags.is_night -> active_bad_time_flags_is_night. + PipelineSettings must reconstruct the ordered flag lists from these keys. + """ + data_vars = { + "active_bad_time_flags_is_pps_missing": ([], True), + "active_bad_time_flags_is_time_status_missing": ([], True), + "active_bad_time_flags_is_phase_missing": ([], True), + "active_bad_time_flags_is_spin_period_missing": ([], True), + "active_bad_time_flags_is_overexposed": ([], True), + "active_bad_time_flags_is_direct_event_non_monotonic": ([], True), + "active_bad_time_flags_is_night": ([], False), + "active_bad_time_flags_is_hv_test_in_progress": ([], True), + "active_bad_time_flags_is_test_pulse_in_progress": ([], True), + "active_bad_time_flags_is_memory_error_detected": ([], True), + "active_bad_time_flags_is_generated_on_ground": ([], True), + "active_bad_time_flags_is_beyond_daily_statistical_error": ( + [], + True, + ), + "active_bad_time_flags_is_temperature_std_dev_beyond_threshold": ( + [], + True, + ), + "active_bad_time_flags_is_hv_voltage_std_dev_beyond_threshold": ( + [], + True, + ), + "active_bad_time_flags_is_spin_period_std_dev_beyond_threshold": ( + [], + True, + ), + "active_bad_time_flags_is_pulse_length_std_dev_beyond_threshold": ( + [], + True, + ), + "active_bad_time_flags_is_spin_period_difference_beyond_threshold": ( + [], + False, + ), + "active_bad_angle_flags_is_close_to_uv_source": ([], True), + "active_bad_angle_flags_is_inside_excluded_region": ([], True), + "active_bad_angle_flags_is_excluded_by_instr_team": ([], True), + "active_bad_angle_flags_is_suspected_transient": ([], False), + } + settings = PipelineSettings(xr.Dataset(data_vars)) + + assert len(settings.active_bad_time_flags) == 17 + assert settings.active_bad_time_flags[6] is False # is_night + assert settings.active_bad_time_flags[16] is False # is_spin_period_diff + + assert len(settings.active_bad_angle_flags) == 4 + assert settings.active_bad_angle_flags[3] is False # is_suspected_transient + + +def test_get_threshold(): + "Test PipelineSettings.get_threshold method." + + test_data = { + "n_sigma_threshold_lower": 3.0, + "n_sigma_threshold_upper": 3.0, + "relative_difference_threshold": 7e-05, + "std_dev_threshold__celsius_deg": 2.03, + "std_dev_threshold__volt": 50.0, + "std_dev_threshold__sec": 0.033333, + "std_dev_threshold__usec": 1.0, + } + pipeline_dataset = xr.Dataset({k: xr.DataArray(v) for k, v in test_data.items()}) + settings = PipelineSettings(pipeline_dataset) + + expected = [2.03, 50.0, 0.033333, 1.0, 7e-5] + description = [ + "std_dev_threshold__celsius_deg", + "std_dev_threshold__volt", + "std_dev_threshold__sec", + "std_dev_threshold__usec", + "relative_difference_threshold", + ] + + for name, exp in zip(description, expected, strict=False): + threshold = settings.get_threshold(name) + assert threshold == exp + + +@patch("imap_processing.glows.l1b.glows_l1b_data.geometry.imap_state") +@patch("imap_processing.glows.l1b.glows_l1b_data.get_instrument_spin_phase") +@patch("imap_processing.glows.l1b.glows_l1b_data.get_spin_data") +@patch("imap_processing.glows.l1b.glows_l1b_data.geometry.frame_transform") +@patch("imap_processing.glows.l1b.glows_l1b_data.sct_to_et") +@patch("imap_processing.glows.l1b.glows_l1b_data.met_to_sclkticks") +def test_update_spice_parameters_spin_axis_near_wrapping_point( + mock_met_to_sclkticks, + mock_sct_to_et, + mock_frame_transform, + mock_get_spin_data, + mock_get_instrument_spin_phase, + mock_imap_state, +): + """Test spin axis orientation longitude is in [0, 360] near the 0/360 boundary. + + Verifies that circmean correctly averages longitudes that straddle the 0/360 + degree boundary and that the result is wrapped to [0, 360) rather than [-180, 180]. + + Test conditions: + - Longitude values straddling 0/360 degrees + - Latitude near equator (-4 degrees) + + Arithmetic mean of [359, 1, 358, 2, 0] would give ~144 degrees (wrong). + Correct circular mean should give ~0 degrees. + """ + # Mock time conversions - creates a time range of 5 seconds + mock_met_to_sclkticks.return_value = 1000 + mock_sct_to_et.side_effect = lambda x: 100.0 if x == 1000 else 105.0 + + # Mock spin data + mock_spin_df = { + "spin_start_met": np.array([99.0, 100.0, 101.0, 102.0, 103.0, 104.0]), + "spin_period_sec": np.array([15.0, 15.0, 15.0, 15.0, 15.0, 15.0]), + } + mock_get_spin_data.return_value = pd.DataFrame(mock_spin_df) + + # Mock instrument spin phase + mock_get_instrument_spin_phase.return_value = 0.5 + + # Create cartesian vectors that straddle the 0/360 degree boundary. + # Points at [359, 1, 358, 2, 0] degrees longitude, latitude near equator. + # + # For spherical to cartesian (r=1): + # x = cos(lat) * cos(lon) + # y = cos(lat) * sin(lon) + # z = sin(lat) + lat_rad = np.deg2rad(-4.0) # Near equator + + # Equivalent in [-180, 180] range: [-1, 1, -2, 2, 0] degrees + longitudes_deg = np.array([359.0, 1.0, 358.0, 2.0, 0.0]) + longitudes_rad = np.deg2rad(longitudes_deg) + + # Build cartesian vectors for each time step + n_times = len(longitudes_rad) + cartesian_vecs = np.zeros((n_times, 3)) + for i, lon_rad in enumerate(longitudes_rad): + cartesian_vecs[i, 0] = np.cos(lat_rad) * np.cos(lon_rad) # x + cartesian_vecs[i, 1] = np.cos(lat_rad) * np.sin(lon_rad) # y + cartesian_vecs[i, 2] = np.sin(lat_rad) # z + + mock_frame_transform.return_value = cartesian_vecs + + # Mock imap_state to return position and velocity for each time step + mock_imap_state.return_value = np.tile( + [[1e8, 2e8, 3e7, 10.0, 20.0, 5.0]], (n_times, 1) + ) + + # Create a minimal HistogramL1B-like object to test update_spice_parameters + class MockHistogram: + def __init__(self): + self.imap_start_time = 100.0 + self.imap_time_offset = 5.0 # 5 second duration + + mock_hist = MockHistogram() + + # Call the actual update_spice_parameters method + HistogramL1B.update_spice_parameters(mock_hist) + + # Verify spin_offset_correction shifts position_angle_offset_average by the + # given amount. + base_angle = mock_hist.position_angle_offset_average + HistogramL1B.update_spice_parameters(mock_hist, spin_offset_correction=5.0) + assert mock_hist.position_angle_offset_average == pytest.approx(base_angle + 5.0) + + # Verify the spin axis orientation values + lon_result = mock_hist.spin_axis_orientation_average[0] + lat_result = mock_hist.spin_axis_orientation_average[1] + lon_std = mock_hist.spin_axis_orientation_std_dev[0] + lat_std = mock_hist.spin_axis_orientation_std_dev[1] + + # Output longitude must be in [0, 360). + assert 0.0 <= lon_result < 360.0, f"Longitude {lon_result} is outside [0, 360)." + + # Circular mean of values near 0/360 boundary should be near 0 degrees, + # not near 144 degrees (arithmetic mean) or 180 degrees. + assert lon_result < 5.0 or lon_result > 355.0, ( + f"Longitude {lon_result} should be near 0/360 degrees. " + "If near 144 or 180, the circular mean failed at the wrapping point." + ) + + # Latitude should be near -4 degrees + np.testing.assert_allclose(lat_result, -4.0, atol=1.0) + + # Standard deviations should be small (all points are within a few degrees) + assert lon_std < 5.0, f"Longitude std dev {lon_std} should be small" + assert lat_std < 1.0, f"Latitude std dev {lat_std} should be small" diff --git a/imap_processing/tests/glows/test_glows_l2.py b/imap_processing/tests/glows/test_glows_l2.py index f5e075c3ec..b4e40de25f 100644 --- a/imap_processing/tests/glows/test_glows_l2.py +++ b/imap_processing/tests/glows/test_glows_l2.py @@ -4,15 +4,19 @@ import pytest import xarray as xr +from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes from imap_processing.glows.l1b.glows_l1b import glows_l1b -from imap_processing.glows.l1b.glows_l1b_data import HistogramL1B -from imap_processing.glows.l2.glows_l2 import ( - generate_l2, - glows_l2, - return_good_times, +from imap_processing.glows.l1b.glows_l1b_data import ( + HistogramL1B, + PipelineSettings, +) +from imap_processing.glows.l2.glows_l2 import create_l2_dataset, glows_l2 +from imap_processing.glows.l2.glows_l2_data import DailyLightcurve, HistogramL2 +from imap_processing.glows.utils.constants import GlowsConstants +from imap_processing.spice.time import et_to_datetime64, ttj2000ns_to_et +from imap_processing.tests.glows.conftest import ( + mock_update_spice_parameters, ) -from imap_processing.glows.l2.glows_l2_data import DailyLightcurve -from imap_processing.tests.glows.conftest import mock_update_spice_parameters @pytest.fixture @@ -22,10 +26,10 @@ def l1b_hists(): hist = xr.DataArray( np.ones((4, 5)), dims=["epoch", "bins"], coords={"epoch": epoch, "bins": bins} ) - hist[1, 0] = -1 - hist[2, 0] = -1 - hist[1, 1] = -1 - hist[2, 3] = -1 + hist[1, 0] = GlowsConstants.HISTOGRAM_FILLVAL + hist[2, 0] = GlowsConstants.HISTOGRAM_FILLVAL + hist[1, 1] = GlowsConstants.HISTOGRAM_FILLVAL + hist[2, 3] = GlowsConstants.HISTOGRAM_FILLVAL input = xr.Dataset(coords={"epoch": epoch, "bins": bins}) input["histogram"] = hist @@ -33,8 +37,25 @@ def l1b_hists(): return input +@patch.object(HistogramL2, "compute_position_angle", return_value=42.0) +@patch.object( + HistogramL1B, + "flag_uv_and_excluded", + return_value=(np.zeros(3600, dtype=bool), np.zeros(3600, dtype=bool)), +) @patch.object(HistogramL1B, "update_spice_parameters", autospec=True) -def test_glows_l2(mock_spice_function, l1a_dataset, mock_ancillary_exclusions): +def test_glows_l2( + mock_spice_function, + mock_flag_uv_and_excluded, + mock_compute_position_angle, + l1a_dataset, + mock_ancillary_exclusions, + mock_pipeline_settings, + mock_conversion_table_dict, + mock_ecliptic_bin_centers, + mock_calibration_dataset, + caplog, +): mock_spice_function.side_effect = mock_update_spice_parameters l1b_hist_dataset = glows_l1b( @@ -43,29 +64,63 @@ def test_glows_l2(mock_spice_function, l1a_dataset, mock_ancillary_exclusions): mock_ancillary_exclusions.uv_sources, mock_ancillary_exclusions.suspected_transients, mock_ancillary_exclusions.exclusions_by_instr_team, + mock_pipeline_settings, + mock_conversion_table_dict, ) - l2 = glows_l2(l1b_hist_dataset)[0] - assert l2.attrs["Logical_source"] == "imap_glows_l2_hist" + l1b_hist_dataset.attrs["Repointing"] = "repoint00047" + # Test case 1: L1B dataset has good times + l2 = glows_l2(l1b_hist_dataset, mock_pipeline_settings, mock_calibration_dataset)[0] + assert l2.attrs["Logical_source"] == "imap_glows_l2_hist" assert np.allclose(l2["filter_temperature_average"].values, [57.6], rtol=0.1) + assert l2["identifier"].values[0] == 47 + assert "flight_software_version" in l2.attrs + assert "pkts_file_name" in l2.attrs + assert "flight_software_version" not in l2.data_vars + assert "pkts_file_name" not in l2.data_vars + + # Test case 2: L1B dataset has no good times (all flags 0) + l1b_hist_dataset_no_good_times = l1b_hist_dataset.copy(deep=True) + l1b_hist_dataset_no_good_times["flags"].values = np.zeros( + l1b_hist_dataset_no_good_times.flags.shape + ) + caplog.set_level("WARNING") + result = glows_l2( + l1b_hist_dataset_no_good_times, mock_pipeline_settings, mock_calibration_dataset + ) + assert result == [] + assert any(record.levelname == "WARNING" for record in caplog.records) + + # Test case 3: Dataset has zero exposure and flux values + l1b_hist_dataset_zero_values = l1b_hist_dataset.copy(deep=True) + l1b_hist_dataset_zero_values["spin_period_average"].data[:] = 0 + l1b_hist_dataset_zero_values["number_of_spins_per_block"].data[:] = 0 + caplog.set_level("WARNING") + result = glows_l2( + l1b_hist_dataset_zero_values, mock_pipeline_settings, mock_calibration_dataset + ) + assert result == [] + assert any(record.levelname == "WARNING" for record in caplog.records) -def test_filter_good_times(): - active_flags = np.ones((17,)) - active_flags[16] = 0 - test_flags = np.ones((4, 17)) - test_flags[1, 0] = 0 - test_flags[3, 16] = 0 - flags = xr.DataArray(test_flags, dims=["epoch", "flags"]) - - good_times = return_good_times(flags, active_flags) - expected_good_times = [0, 2, 3] - - assert np.array_equal(good_times, expected_good_times) - - +@patch.object(HistogramL2, "compute_position_angle", return_value=42.0) +@patch.object( + HistogramL1B, + "flag_uv_and_excluded", + return_value=(np.zeros(3600, dtype=bool), np.zeros(3600, dtype=bool)), +) @patch.object(HistogramL1B, "update_spice_parameters", autospec=True) -def test_generate_l2(mock_spice_function, l1a_dataset, mock_ancillary_exclusions): +def test_generate_l2( + mock_spice_function, + mock_flag_uv_and_excluded, + mock_compute_position_angle, + l1a_dataset, + mock_ancillary_exclusions, + mock_pipeline_settings, + mock_conversion_table_dict, + mock_ecliptic_bin_centers, + mock_calibration_dataset, +): mock_spice_function.side_effect = mock_update_spice_parameters l1b_hist_dataset = glows_l1b( @@ -74,41 +129,57 @@ def test_generate_l2(mock_spice_function, l1a_dataset, mock_ancillary_exclusions mock_ancillary_exclusions.uv_sources, mock_ancillary_exclusions.suspected_transients, mock_ancillary_exclusions.exclusions_by_instr_team, + mock_pipeline_settings, + mock_conversion_table_dict, ) - l2 = generate_l2(l1b_hist_dataset) - - expected_values = { - "filter_temperature_average": [57.59], - "filter_temperature_std_dev": [0.21], - "hv_voltage_average": [1715.4], - "hv_voltage_std_dev": [0.0], - } - - assert np.isclose( - l2.filter_temperature_average, - expected_values["filter_temperature_average"], - 0.01, - ) - assert np.isclose( - l2.filter_temperature_std_dev, - expected_values["filter_temperature_std_dev"], - 0.01, - ) - assert np.isclose( - l2.hv_voltage_average, expected_values["hv_voltage_average"], 0.01 + l1b_hist_dataset.attrs["Repointing"] = "repoint00047" + day = et_to_datetime64(ttj2000ns_to_et(l1b_hist_dataset["epoch"].data[0])) + pipeline_settings = PipelineSettings( + mock_pipeline_settings.sel(epoch=day, method="nearest") ) - assert np.isclose( - l2.hv_voltage_std_dev, expected_values["hv_voltage_std_dev"], 0.01 - ) - - -def test_exposure_times(l1b_hists): - exposure_time = xr.DataArray([10, 10, 20, 10]) - expected_times = np.array([20, 40, 50, 30, 50]) - - times = DailyLightcurve.calculate_exposure_times(l1b_hists, exposure_time) - assert np.array_equal(times, expected_times) + # Test case 1: L1B dataset has good times + with patch.object(HistogramL2, "get_calibration_factor", return_value=1): + l2 = HistogramL2(l1b_hist_dataset, pipeline_settings, mock_calibration_dataset) + + expected_values = { + "filter_temperature_average": [57.59], + "filter_temperature_std_dev": [0.21], + "hv_voltage_average": [1715.4], + "hv_voltage_std_dev": [0.0], + } + + assert np.isclose( + l2.filter_temperature_average, + expected_values["filter_temperature_average"], + 0.01, + ) + assert np.isclose( + l2.filter_temperature_std_dev, + expected_values["filter_temperature_std_dev"], + 0.01, + ) + assert np.isclose( + l2.hv_voltage_average, expected_values["hv_voltage_average"], 0.01 + ) + assert np.isclose( + l2.hv_voltage_std_dev, expected_values["hv_voltage_std_dev"], 0.01 + ) + + cdf_attrs = ImapCdfAttributes() + cdf_attrs.add_instrument_global_attrs("glows") + cdf_attrs.add_instrument_variable_attrs("glows", "l2") + assert ( + create_l2_dataset(l2, cdf_attrs, l1b_hist_dataset.attrs)["epoch"].data[0] + == (l2.start_time + l2.end_time) / 2 + ) + + # Test case 2: L1B dataset has no good times (all flags 0) + l1b_hist_dataset["flags"].values = np.zeros(l1b_hist_dataset.flags.shape) + ds = HistogramL2(l1b_hist_dataset, pipeline_settings, mock_calibration_dataset) + expected_number_of_good_l1b_inputs = 0 + assert ds.number_of_good_l1b_inputs == expected_number_of_good_l1b_inputs + assert ds.bad_time_flag_occurrences.dtype == np.uint16 def test_bin_exclusions(l1b_hists): diff --git a/imap_processing/tests/glows/test_glows_l2_data.py b/imap_processing/tests/glows/test_glows_l2_data.py index e69de29bb2..a34d978ba6 100644 --- a/imap_processing/tests/glows/test_glows_l2_data.py +++ b/imap_processing/tests/glows/test_glows_l2_data.py @@ -0,0 +1,565 @@ +from unittest.mock import patch + +import numpy as np +import pytest +import xarray as xr + +from imap_processing.glows.l1b.glows_l1b_data import PipelineSettings +from imap_processing.glows.l2.glows_l2_data import DailyLightcurve, HistogramL2 +from imap_processing.glows.utils.constants import GlowsConstants +from imap_processing.spice.time import met_to_sclkticks, sct_to_et + + +@pytest.fixture +def pipeline_settings(): + """PipelineSettings with flags matching the default pipeline settings JSON. + + active_bad_time_flags has 17 entries (is_night and + is_spin_period_difference_beyond_threshold are False, all others True). + active_bad_angle_flags has 4 entries (all True). + """ + active_bad_time_flags = [ + True, # is_pps_missing + True, # is_time_status_missing + True, # is_phase_missing + True, # is_spin_period_missing + True, # is_overexposed + True, # is_direct_event_non_monotonic + False, # is_night + True, # is_hv_test_in_progress + True, # is_test_pulse_in_progress + True, # is_memory_error_detected + True, # is_generated_on_ground + True, # is_beyond_daily_statistical_error + True, # is_temperature_std_dev_beyond_threshold + True, # is_hv_voltage_std_dev_beyond_threshold + True, # is_spin_period_std_dev_beyond_threshold + True, # is_pulse_length_std_dev_beyond_threshold + False, # is_spin_period_difference_beyond_threshold + ] + active_bad_angle_flags = [ + True, # is_close_to_uv_source + True, # is_inside_excluded_region + True, # is_excluded_by_instr_team + True, # is_suspected_transient + ] + pipeline_dataset = xr.Dataset( + { + "active_bad_time_flags": xr.DataArray( + active_bad_time_flags, dims=["time_flag_index"] + ), + "active_bad_angle_flags": xr.DataArray( + active_bad_angle_flags, dims=["angle_flag_index"] + ), + } + ) + return PipelineSettings(pipeline_dataset) + + +@pytest.fixture +def l1b_dataset(): + """Minimal L1B dataset for testing DailyLightcurve. + + Two timestamps, four bins. + Bin 3 is masked (HISTOGRAM_FILLVAL) at timestamp 0. + histogram_flag_array has shape (epoch, bad_angle_flags, bins) with all zeros. + """ + n_epochs, n_bins, n_flags = 2, 4, 4 + fillval = GlowsConstants.HISTOGRAM_FILLVAL + epoch = xr.DataArray(np.arange(n_epochs), dims=["epoch"]) + bins = xr.DataArray(np.arange(n_bins), dims=["bins"]) + + histogram = np.array([[10, 20, 30, fillval], [10, 20, 30, 40]], dtype=float) + spin_angle = np.tile(np.linspace(0, 270, n_bins), (n_epochs, 1)) + histogram_flag_array = np.zeros((n_epochs, n_flags, n_bins), dtype=np.uint8) + + ds = xr.Dataset( + { + "histogram": (["epoch", "bins"], histogram), + "spin_period_average": (["epoch"], [15.0, 15.0]), + "number_of_spins_per_block": (["epoch"], [5, 5]), + "imap_spin_angle_bin_cntr": (["epoch", "bins"], spin_angle), + "imap_start_time": (["epoch"], [0.0, 1.0]), + "histogram_flag_array": ( + ["epoch", "bad_angle_flags", "bins"], + histogram_flag_array, + ), + "number_of_bins_per_histogram": (["epoch"], [n_bins, n_bins]), + }, + coords={"epoch": epoch, "bins": bins}, + ) + return ds + + +def test_get_calibration_factor(mock_calibration_dataset): + """Test selecting correct calibration factor. + + Mock calibration data: + start_time_utc (dims epoch Γ— start_time_utc_dim_0, same per epoch): + ["2011-09-19T09:58:04", "2011-09-20T18:12:48", "2011-09-21T18:15:50"] + cps_per_r (dims epoch Γ— cps_per_r_dim_0, same per epoch): + index 0 β†’ 0.849, index 1 β†’ 1.020, index 2 β†’ 1.500 + """ + # Case 1: The mid-epoch ('2011-09-22T10:30:55.015') falls after the + # start_time_utc entries, so the last entry (index 2) is selected β†’ 1.500. + + # ["2011-09-22T07:45:55.015", "2011-09-22T10:30:55.015", "2011-09-22T13:15:55.015"] + later_epoch = np.array([369949621199000000, 369959521199000000, 369969421199000000]) + assert HistogramL2.get_calibration_factor( + later_epoch, mock_calibration_dataset + ) == pytest.approx(1.500) + + # Case 2: The mid-epoch ('2011-09-21T00:52:15.000') falls between the 2nd and + # 3rd start_time_utc entries, so the 2nd entry (index 1) is selected β†’ 1.020. + + # ['2011-09-21T00:50:15.000', '2011-09-21T00:52:15.000', '2011-09-21T00:54:15.000'] + between_epoch = np.array( + [369838281184000000, 369838401184000000, 369838521184000000] + ) + assert HistogramL2.get_calibration_factor( + between_epoch, mock_calibration_dataset + ) == pytest.approx(1.020) + + # Case 3: The mid-epoch is before all start_time_utc entries, + # so a KeyError is raised by xarray's "pad" selection method. + + # ['2011-09-18T19:59:08.816', '2011-09-18T20:01:08.816', '2011-09-18T20:03:08.816'] + early_epoch = np.array([369648015000000000, 369648135000000000, 369648255000000000]) + with pytest.raises(KeyError): + HistogramL2.get_calibration_factor(early_epoch, mock_calibration_dataset) + + +@pytest.mark.external_kernel +def test_ecliptic_coords_computation(furnish_kernels): + """Test method that computes ecliptic coordinates.""" + + # Use a met value within the SPICE kernel coverage (2026-01-01). + data_start_time_et = sct_to_et(met_to_sclkticks(504975603.125)) + n_bins = 4 + spin_angle = np.linspace(0, 270, n_bins) + + kernels = [ + "naif0012.tls", + "imap_sclk_0000.tsc", + "imap_130.tf", + "imap_science_120.tf", + "sim_1yr_imap_pointing_frame.bc", + ] + + with furnish_kernels(kernels): + ecliptic_lon, ecliptic_lat = ( + DailyLightcurve.compute_ecliptic_coords_of_bin_centers( + data_start_time_et, spin_angle + ) + ) + + # ecliptic_lon and ecliptic_lat must have one entry per bin + assert len(ecliptic_lon) == n_bins + assert len(ecliptic_lat) == n_bins + + # ecliptic longitude must be in [0, 360) + assert np.all(ecliptic_lon >= 0.0) + assert np.all(ecliptic_lon < 360.0) + + # ecliptic latitude must be in [-90, 90] + assert np.all(ecliptic_lat >= -90.0) + assert np.all(ecliptic_lat <= 90.0) + + # values must be finite (no NaN / Inf from SPICE) + assert np.all(np.isfinite(ecliptic_lon)) + assert np.all(np.isfinite(ecliptic_lat)) + + +def test_photon_flux(l1b_dataset, mock_ecliptic_bin_centers): + """ + Flux = (sum(histograms) / sum(exposure_times)) / + Rayleigh calibration factor + + per bin (Eq. 50-53) + """ + mock_cal_factor = 2 + lc = DailyLightcurve( + l1b_dataset, position_angle=0.0, calibration_factor=mock_cal_factor + ) + + # l1b_exposure_time_per_bin = spin_period_average * + # number_of_spins_per_block / number_of_bins_per_histogram + exposure_per = 15.0 * 5 / 4 + expected_raw = np.array([20, 40, 60, 40]) + # Exposure accumulates uniformly per good-time file regardless of per-bin masking + expected_exposure = np.array( + [2 * exposure_per, 2 * exposure_per, 2 * exposure_per, 2 * exposure_per] + ) + expected_flux = (expected_raw / expected_exposure) / mock_cal_factor + + assert np.allclose(lc.raw_histograms, expected_raw) + assert np.allclose(lc.exposure_times, expected_exposure) + assert np.allclose(lc.photon_flux, expected_flux) + + +def test_flux_uncertainty(l1b_dataset, mock_ecliptic_bin_centers): + """ + Uncertainty = sqrt(sum_hist) / exposure / + Rayleigh calibration factor + + per bin (Eq. 54-55).""" + mock_cal_factor = 2 + lc = DailyLightcurve( + l1b_dataset, position_angle=0.0, calibration_factor=mock_cal_factor + ) + + expected_uncertainty = ( + np.sqrt(lc.raw_histograms) / lc.exposure_times + ) / mock_cal_factor + assert np.allclose(lc.flux_uncertainties, expected_uncertainty) + + +def test_zero_exposure_bins(l1b_dataset, mock_ecliptic_bin_centers): + """Bins with all-masked histograms get zero flux and uncertainty. + + Exposure time still accumulates uniformly from each good-time file even + when all histogram values are masked (HISTOGRAM_FILLVAL). Flux and + uncertainty are zero because the raw histogram sums are zero. + """ + mock_cal_factor = 1 + l1b_dataset["histogram"].values[:] = GlowsConstants.HISTOGRAM_FILLVAL + lc = DailyLightcurve( + l1b_dataset, position_angle=0.0, calibration_factor=mock_cal_factor + ) + + expected_exposure = 2 * 15.0 * 5 / 4 + assert np.all(lc.photon_flux == 0) + assert np.all(lc.flux_uncertainties == 0) + assert np.allclose(lc.exposure_times, expected_exposure) + + +def test_zero_exposure_values(l1b_dataset, mock_ecliptic_bin_centers): + """Zero exposure yields zero flux and zero uncertainty per bin.""" + + # Note: all bins have the same exposure time, so if one is zero all are zero. + + # Update values used to calculate exposure times to + # ensure a zero exposure result. + l1b_dataset["spin_period_average"].data[:] = 0 + l1b_dataset["number_of_spins_per_block"].data[:] = 0 + + mock_cal_factor = 1 + + with np.errstate(divide="raise", invalid="raise"): + lc = DailyLightcurve( + l1b_dataset, position_angle=0.0, calibration_factor=mock_cal_factor + ) + + expected = np.zeros(l1b_dataset.sizes["bins"], dtype=float) + assert lc.exposure_times.shape == expected.shape + assert len(np.unique(lc.exposure_times)) == 1 + assert np.array_equal(lc.exposure_times, expected) + assert np.array_equal(lc.photon_flux, expected) + assert np.array_equal(lc.flux_uncertainties, expected) + assert np.all(np.isfinite(lc.photon_flux)) + assert np.all(np.isfinite(lc.flux_uncertainties)) + + +def test_number_of_bins(l1b_dataset, mock_ecliptic_bin_centers): + mock_cal_factor = 1 + lc = DailyLightcurve( + l1b_dataset, position_angle=0.0, calibration_factor=mock_cal_factor + ) + assert lc.number_of_bins == 4 + assert len(lc.spin_angle) == 4 + assert len(lc.photon_flux) == 4 + assert len(lc.flux_uncertainties) == 4 + assert len(lc.exposure_times) == 4 + assert len(lc.ecliptic_lon) == 4 + assert len(lc.ecliptic_lat) == 4 + + +def test_histogram_flag_array_or_propagation(l1b_dataset, mock_ecliptic_bin_centers): + """histogram_flag_array is OR'd across all L1B epochs and flag rows per bin. + + Per Section 12.3.4: a flag is True in L2 if it is True in any L1B block. + """ + # epoch 0, flag row 0 (IS_CLOSE_TO_UV_SOURCE=1): bin 0 flagged + # epoch 1, flag row 1 (IS_INSIDE_EXCLUDED_REGION=2): bin 2 flagged + # epoch 1, flag row 0 (IS_CLOSE_TO_UV_SOURCE=2): bin 0 flagged + l1b_dataset["histogram_flag_array"].values[0, 0, 0] = 1 + l1b_dataset["histogram_flag_array"].values[1, 1, 2] = 2 + l1b_dataset["histogram_flag_array"].values[1, 0, 0] = 2 + + mock_cal_factor = 1 + lc = DailyLightcurve( + l1b_dataset, position_angle=0.0, calibration_factor=mock_cal_factor + ) + + assert ( + lc.histogram_flag_array[0] == 3 + ) # IS_CLOSE_TO_UV_SOURCE and IS_INSIDE_EXCLUDED_REGION + assert lc.histogram_flag_array[1] == 0 # no flags on bin 1 + assert lc.histogram_flag_array[2] == 2 # IS_INSIDE_EXCLUDED_REGION + assert lc.histogram_flag_array[3] == 0 # no flags on bin 3 + + +def test_histogram_flag_array_zero_epochs(mock_ecliptic_bin_centers): + """histogram_flag_array is all zeros when the input dataset is empty. + + Note: this is NEVER expected to happen in production + """ + n_bins, n_flags = 4, 4 + histogram = np.empty((0, n_bins), dtype=float) + spin_angle = np.empty((0, n_bins), dtype=float) + histogram_flag_array = np.empty((0, n_flags, n_bins), dtype=np.uint8) + + ds = xr.Dataset( + { + "histogram": (["epoch", "bins"], histogram), + "spin_period_average": (["epoch"], []), + "number_of_spins_per_block": (["epoch"], []), + "imap_spin_angle_bin_cntr": (["epoch", "bins"], spin_angle), + "histogram_flag_array": ( + ["epoch", "bad_angle_flags", "bins"], + histogram_flag_array, + ), + "number_of_bins_per_histogram": (["epoch"], []), + }, + coords={"epoch": xr.DataArray(np.arange(0), dims=["epoch"])}, + ) + mock_cal_factor = 1 + lc = DailyLightcurve(ds, position_angle=0.0, calibration_factor=mock_cal_factor) + + # if the dataset is empty, there is no way to infer the number_of_bins + assert len(lc.histogram_flag_array) == 0 + assert np.all(lc.histogram_flag_array == 0) + + +def test_filter_good_times(): + """Epochs where any active flag is 0 are excluded; inactive flags are ignored.""" + active_flags = np.ones((17,)) + active_flags[16] = 0 # flag 16 is inactive + test_flags = np.ones((4, 17)) + test_flags[1, 0] = 0 # epoch 1 fails active flag 0 -> bad time + test_flags[3, 16] = 0 # epoch 3 fails inactive flag 16 -> still good time + flags = xr.DataArray(test_flags, dims=["epoch", "flags"]) + + good_times = HistogramL2.return_good_times(flags, active_flags) + expected_good_times = [0, 2, 3] + + assert np.array_equal(good_times, expected_good_times) + + +@pytest.mark.parametrize( + "sunrise_offset, sunset_offset, expected_is_night", + [ + # sunrise>0 extends at sunrise; sunset>0 shortens at sunset + (1, 1, [1, 1, 1, 1, 0, 0, 0, 1]), + # sunrise<0 shortens at sunrise; sunset>0 shortens at sunset + (-1, 1, [1, 1, 1, 1, 0, 1, 1, 1]), + # sunrise>0 extends at sunrise; sunset<0 extends at sunset + (1, -1, [1, 1, 0, 0, 0, 0, 0, 1]), + # sunrise<0 shortens at sunrise; sunset<0 extends at sunset + (-1, -1, [1, 1, 0, 0, 0, 1, 1, 1]), + # zero offsets: no change + (0, 0, [1, 1, 1, 0, 0, 0, 1, 1]), + ], +) +def test_apply_is_night_offsets(sunrise_offset, sunset_offset, expected_is_night): + """Test apply_is_night_offsets function.""" + + # Setup: epochs 0-2 day, 3-5 night, 6-7 day (processed flags: 0=night, 1=day). + flags = np.ones((8, 17), dtype=float) + flags[3:6, 6] = 0 # epochs 3-5 are night + original_flags = flags.copy() + + result = HistogramL2.apply_is_night_offsets( + flags, + is_night_idx=6, + sunrise_offset=sunrise_offset, + sunset_offset=sunset_offset, + ) + + assert np.array_equal(result[:, 6], np.array(expected_is_night, dtype=float)) + + if sunrise_offset == 0 and sunset_offset == 0: + # No offsets: original array returned as-is (no copy) + assert result is flags + else: + # Offsets applied: result is a copy, original flags are unchanged + assert result is not flags + assert np.array_equal(flags, original_flags) + + +# ── spin_angle tests ────────────────────────────────────────────────────────── + + +def test_spin_angle_offset_formula(l1b_dataset, mock_ecliptic_bin_centers): + """spin_angle = (imap_spin_angle_bin_cntr - position_angle + 360) % 360. + + Fixture spin_angle_bin_cntr = [0, 90, 180, 270], position_angle = 90. + Expected before roll: [270, 0, 90, 180]. + Minimum is at index 1, so roll = -1 -> [0, 90, 180, 270]. + """ + mock_cal_factor = 1 + lc = DailyLightcurve( + l1b_dataset, position_angle=90.0, calibration_factor=mock_cal_factor + ) + expected = np.array([0.0, 90.0, 180.0, 270.0]) + assert np.allclose(lc.spin_angle, expected) + + +def test_spin_angle_starts_at_minimum(l1b_dataset, mock_ecliptic_bin_centers): + """After rolling, lc.spin_angle[0] is the minimum value. + + Fixture spin_angle_bin_cntr = [0, 90, 180, 270], position_angle = 45. + Before roll: [315, 45, 135, 225]; minimum 45 is at index 1 -> roll = -1 + -> [45, 135, 225, 315]. + """ + mock_cal_factor = 1 + lc = DailyLightcurve( + l1b_dataset, position_angle=45.0, calibration_factor=mock_cal_factor + ) + assert lc.spin_angle[0] == np.min(lc.spin_angle) + assert np.allclose(lc.spin_angle, np.array([45.0, 135.0, 225.0, 315.0])) + + +# ── position_angle_offset_average tests ────────────────────────────────────── + + +def test_compute_position_angle(): + """compute_position_angle returns (360 - azimuth) % 360 (Eq. 30).""" + target_module = ( + "imap_processing.glows.l2.glows_l2_data.get_instrument_mounting_az_el" + ) + with patch(target_module, return_value=(270.0, 0.0)): + result = HistogramL2.compute_position_angle(None) + assert result == pytest.approx(90.0) + + +@patch( + "imap_processing.glows.l2.glows_l2_data.get_instrument_mounting_az_el", + return_value=(270.0, 0.0), +) +def test_compute_position_angle_spin_offset_correction(mock_az_el): + """spin_offset_correction shifts the position angle by the given amount.""" + + assert HistogramL2.compute_position_angle(None, 0.0) == 90.0 + assert HistogramL2.compute_position_angle(None, 5.0) == 95.0 + assert HistogramL2.compute_position_angle(None, -10.0) == 80.0 + + +@pytest.fixture +def l1b_dataset_full(): + """Minimal L1B dataset with all variables required by HistogramL2. + + Two epochs, four bins, 17 flags. Both epochs are daytime (is_night=1). + All other flags are 1 (good). + """ + n_epochs, n_bins, n_angle_flags, n_time_flags = 2, 4, 4, 17 + fillval = GlowsConstants.HISTOGRAM_FILLVAL + epoch = np.arange(n_epochs, dtype=np.float64) + + histogram = np.array([[10, 20, 30, fillval], [10, 20, 30, 40]], dtype=float) + spin_angle = np.tile(np.linspace(0, 270, n_bins), (n_epochs, 1)) + histogram_flag_array = np.zeros((n_epochs, n_angle_flags, n_bins), dtype=np.uint8) + + # All flags good (1). Index 6 is is_night: 1 = daytime (good). + flags = np.ones((n_epochs, n_time_flags), dtype=float) + + return xr.Dataset( + { + "histogram": (["epoch", "bins"], histogram), + "spin_period_average": (["epoch"], [15.0, 15.0]), + "number_of_spins_per_block": (["epoch"], [5, 5]), + "imap_spin_angle_bin_cntr": (["epoch", "bins"], spin_angle), + "histogram_flag_array": ( + ["epoch", "bad_angle_flags", "bins"], + histogram_flag_array, + ), + "number_of_bins_per_histogram": (["epoch"], [n_bins, n_bins]), + "flags": (["epoch", "flag_index"], flags), + "filter_temperature_average": (["epoch"], [20.0, 21.0]), + "hv_voltage_average": (["epoch"], [1000.0, 1000.0]), + "pulse_length_average": (["epoch"], [5.0, 5.0]), + "spin_period_ground_average": (["epoch"], [15.0, 15.0]), + "spacecraft_location_average": ( + ["epoch", "xyz"], + np.ones((n_epochs, 3)), + ), + "spacecraft_velocity_average": ( + ["epoch", "xyz"], + np.ones((n_epochs, 3)), + ), + "spin_axis_orientation_average": ( + ["epoch", "lonlat"], + np.ones((n_epochs, 2)), + ), + "imap_start_time": (["epoch"], [0.0, 1.0]), + "imap_time_offset": (["epoch"], [60.0, 60.0]), + }, + coords={"epoch": xr.DataArray(epoch, dims=["epoch"])}, + attrs={"Repointing": "repoint00047"}, + ) + + +def test_position_angle_offset_average( + l1b_dataset_full, + pipeline_settings, + mock_ecliptic_bin_centers, + mock_calibration_dataset, +): + """position_angle_offset_average is a scalar equal to the result of + compute_position_angle (Eq. 30, Section 10.6). It is constant across the + observational day since it depends only on instrument mounting geometry. + """ + mock_pa = 42.5 + mock_cal_factor = 1 + + with ( + patch.object(HistogramL2, "compute_position_angle", return_value=mock_pa), + patch.object( + HistogramL2, "get_calibration_factor", return_value=mock_cal_factor + ), + ): + l2 = HistogramL2(l1b_dataset_full, pipeline_settings, mock_calibration_dataset) + + assert l2.position_angle_offset_average == pytest.approx(mock_pa) + + +# ── spin_axis_orientation_average tests ────────────────────────────────────── + + +def test_spin_axis_orientation_average_wrapping( + l1b_dataset_full, + pipeline_settings, + mock_ecliptic_bin_centers, + mock_calibration_dataset, +): + """Longitude averaging uses circular mean to handle the 0/360 boundary correctly. + + Arithmetic mean of [358, 2] gives 180 (wrong). + Circular mean correctly gives ~0. + """ + wrapping_dataset = l1b_dataset_full.copy() + wrapping_dataset["spin_axis_orientation_average"] = xr.DataArray( + np.array([[358.0, 5.0], [2.0, 5.0]]), + dims=["epoch", "lonlat"], + ) + + with ( + patch.object(HistogramL2, "compute_position_angle", return_value=42.5), + patch.object(HistogramL2, "get_calibration_factor", return_value=1.0), + ): + l2 = HistogramL2(wrapping_dataset, pipeline_settings, mock_calibration_dataset) + + lon_avg = l2.spin_axis_orientation_average[0, 0] + lat_avg = l2.spin_axis_orientation_average[0, 1] + + # Result must be in [0, 360). + assert 0.0 <= lon_avg < 360.0, f"Longitude {lon_avg} is outside [0, 360)." + + # Circular mean of 358 and 2 should be near 0 (both within 2Β° of boundary), + # not 180 (arithmetic mean). + assert lon_avg < 5.0 or lon_avg > 355.0, ( + f"Longitude {lon_avg} should be near 0/360, not near 180." + ) + + # Latitude is not circular β€” arithmetic mean of [5, 5] = 5. + assert lat_avg == pytest.approx(5.0) diff --git a/imap_processing/tests/glows/validation_data/direct_events_validation_data_l1a.csv b/imap_processing/tests/glows/validation_data/direct_events_validation_data_l1a.csv deleted file mode 100644 index ba81ffc270..0000000000 --- a/imap_processing/tests/glows/validation_data/direct_events_validation_data_l1a.csv +++ /dev/null @@ -1,5704 +0,0 @@ -,packet_counter,de_data_counter,seq_count_in_pkts_file,imap_start_time_seconds,number_of_de_packets,de_data,imap_sclk_last_pps,glows_sclk_last_pps,glows_ssclk_last_pps,imap_sclk_next_pps,catbed_heater_active,spin_period_valid,spin_phase_at_next_pps_valid,spin_period_source,spin_period,spin_phase_at_next_pps,number_of_completed_spins,filter_temperature,hv_voltage,glows_time_on_pps_valid,time_status_valid,housekeeping_valid,is_pps_autogenerated,hv_test_in_progress,pulse_test_in_progress,memory_error_detected -7201,12,0,12,54232350,1,"[54232349, 1998047, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7202,12,1,12,54232350,1,"[54232350, 318, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7203,12,2,12,54232350,1,"[54232350, 2588, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7204,12,3,12,54232350,1,"[54232350, 4858, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7205,12,4,12,54232350,1,"[54232350, 7127, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7206,12,5,12,54232350,1,"[54232350, 9395, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7207,12,6,12,54232350,1,"[54232350, 11663, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7208,12,7,12,54232350,1,"[54232350, 13930, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7209,12,8,12,54232350,1,"[54232350, 16196, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7210,12,9,12,54232350,1,"[54232350, 18461, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7211,12,10,12,54232350,1,"[54232350, 20726, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7212,12,11,12,54232350,1,"[54232350, 22990, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7213,12,12,12,54232350,1,"[54232350, 25254, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7214,12,13,12,54232350,1,"[54232350, 27516, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7215,12,14,12,54232350,1,"[54232350, 29778, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7216,12,15,12,54232350,1,"[54232350, 32040, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7217,12,16,12,54232350,1,"[54232350, 34300, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7218,12,17,12,54232350,1,"[54232350, 36560, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7219,12,18,12,54232350,1,"[54232350, 38819, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7220,12,19,12,54232350,1,"[54232350, 41078, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7221,12,20,12,54232350,1,"[54232350, 43336, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7222,12,21,12,54232350,1,"[54232350, 45593, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7223,12,22,12,54232350,1,"[54232350, 47849, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7224,12,23,12,54232350,1,"[54232350, 50105, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7225,12,24,12,54232350,1,"[54232350, 52360, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7226,12,25,12,54232350,1,"[54232350, 54614, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7227,12,26,12,54232350,1,"[54232350, 56868, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7228,12,27,12,54232350,1,"[54232350, 59121, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7229,12,28,12,54232350,1,"[54232350, 61373, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7230,12,29,12,54232350,1,"[54232350, 63624, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7231,12,30,12,54232350,1,"[54232350, 65875, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7232,12,31,12,54232350,1,"[54232350, 68125, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7233,12,32,12,54232350,1,"[54232350, 70375, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7234,12,33,12,54232350,1,"[54232350, 72623, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7235,12,34,12,54232350,1,"[54232350, 74871, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7236,12,35,12,54232350,1,"[54232350, 77119, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7237,12,36,12,54232350,1,"[54232350, 79365, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7238,12,37,12,54232350,1,"[54232350, 81611, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7239,12,38,12,54232350,1,"[54232350, 83856, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7240,12,39,12,54232350,1,"[54232350, 86101, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7241,12,40,12,54232350,1,"[54232350, 88345, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7242,12,41,12,54232350,1,"[54232350, 90588, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7243,12,42,12,54232350,1,"[54232350, 92830, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7244,12,43,12,54232350,1,"[54232350, 95072, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7245,12,44,12,54232350,1,"[54232350, 97313, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7246,12,45,12,54232350,1,"[54232350, 99553, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7247,12,46,12,54232350,1,"[54232350, 101793, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7248,12,47,12,54232350,1,"[54232350, 104032, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7249,12,48,12,54232350,1,"[54232350, 106270, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7250,12,49,12,54232350,1,"[54232350, 108507, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7251,12,50,12,54232350,1,"[54232350, 110744, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7252,12,51,12,54232350,1,"[54232350, 112980, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7253,12,52,12,54232350,1,"[54232350, 115216, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7254,12,53,12,54232350,1,"[54232350, 117450, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7255,12,54,12,54232350,1,"[54232350, 119684, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7256,12,55,12,54232350,1,"[54232350, 121918, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7257,12,56,12,54232350,1,"[54232350, 124150, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7258,12,57,12,54232350,1,"[54232350, 126382, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7259,12,58,12,54232350,1,"[54232350, 128613, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7260,12,59,12,54232350,1,"[54232350, 130844, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7261,12,60,12,54232350,1,"[54232350, 133074, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7262,12,61,12,54232350,1,"[54232350, 135303, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7263,12,62,12,54232350,1,"[54232350, 137531, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7264,12,63,12,54232350,1,"[54232350, 139759, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7265,12,64,12,54232350,1,"[54232350, 141986, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7266,12,65,12,54232350,1,"[54232350, 144212, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7267,12,66,12,54232350,1,"[54232350, 146438, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7268,12,67,12,54232350,1,"[54232350, 148663, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7269,12,68,12,54232350,1,"[54232350, 150887, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7270,12,69,12,54232350,1,"[54232350, 153110, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7271,12,70,12,54232350,1,"[54232350, 155333, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7272,12,71,12,54232350,1,"[54232350, 157555, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7273,12,72,12,54232350,1,"[54232350, 159777, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7274,12,73,12,54232350,1,"[54232350, 161997, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7275,12,74,12,54232350,1,"[54232350, 164217, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7276,12,75,12,54232350,1,"[54232350, 166437, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7277,12,76,12,54232350,1,"[54232350, 168655, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7278,12,77,12,54232350,1,"[54232350, 170873, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7279,12,78,12,54232350,1,"[54232350, 173090, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7280,12,79,12,54232350,1,"[54232350, 175307, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7281,12,80,12,54232350,1,"[54232350, 177523, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7282,12,81,12,54232350,1,"[54232350, 179738, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7283,12,82,12,54232350,1,"[54232350, 181952, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7284,12,83,12,54232350,1,"[54232350, 184166, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7285,12,84,12,54232350,1,"[54232350, 186379, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7286,12,85,12,54232350,1,"[54232350, 188591, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7287,12,86,12,54232350,1,"[54232350, 190803, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7288,12,87,12,54232350,1,"[54232350, 193014, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7289,12,88,12,54232350,1,"[54232350, 195224, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7290,12,89,12,54232350,1,"[54232350, 197433, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7291,12,90,12,54232350,1,"[54232350, 199642, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7292,12,91,12,54232350,1,"[54232350, 201850, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7293,12,92,12,54232350,1,"[54232350, 204058, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7294,12,93,12,54232350,1,"[54232350, 206264, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7295,12,94,12,54232350,1,"[54232350, 208470, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7296,12,95,12,54232350,1,"[54232350, 210676, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7297,12,96,12,54232350,1,"[54232350, 212880, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7298,12,97,12,54232350,1,"[54232350, 215084, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7299,12,98,12,54232350,1,"[54232350, 217287, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7300,12,99,12,54232350,1,"[54232350, 219490, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7301,12,100,12,54232350,1,"[54232350, 221692, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7302,12,101,12,54232350,1,"[54232350, 223893, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7303,12,102,12,54232350,1,"[54232350, 226093, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7304,12,103,12,54232350,1,"[54232350, 228293, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7305,12,104,12,54232350,1,"[54232350, 230492, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7306,12,105,12,54232350,1,"[54232350, 232690, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7307,12,106,12,54232350,1,"[54232350, 234888, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7308,12,107,12,54232350,1,"[54232350, 237085, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7309,12,108,12,54232350,1,"[54232350, 239281, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7310,12,109,12,54232350,1,"[54232350, 241476, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7311,12,110,12,54232350,1,"[54232350, 243671, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7312,12,111,12,54232350,1,"[54232350, 245865, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7313,12,112,12,54232350,1,"[54232350, 248059, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7314,12,113,12,54232350,1,"[54232350, 250251, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7315,12,114,12,54232350,1,"[54232350, 252443, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7316,12,115,12,54232350,1,"[54232350, 254635, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7317,12,116,12,54232350,1,"[54232350, 256825, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7318,12,117,12,54232350,1,"[54232350, 259015, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7319,12,118,12,54232350,1,"[54232350, 261204, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7320,12,119,12,54232350,1,"[54232350, 263393, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7321,12,120,12,54232350,1,"[54232350, 265581, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7322,12,121,12,54232350,1,"[54232350, 267768, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7323,12,122,12,54232350,1,"[54232350, 269954, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7324,12,123,12,54232350,1,"[54232350, 272140, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7325,12,124,12,54232350,1,"[54232350, 274325, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7326,12,125,12,54232350,1,"[54232350, 276509, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7327,12,126,12,54232350,1,"[54232350, 278693, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7328,12,127,12,54232350,1,"[54232350, 280876, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7329,12,128,12,54232350,1,"[54232350, 283058, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7330,12,129,12,54232350,1,"[54232350, 285239, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7331,12,130,12,54232350,1,"[54232350, 287420, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7332,12,131,12,54232350,1,"[54232350, 289600, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7333,12,132,12,54232350,1,"[54232350, 291780, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7334,12,133,12,54232350,1,"[54232350, 293958, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7335,12,134,12,54232350,1,"[54232350, 296136, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7336,12,135,12,54232350,1,"[54232350, 298314, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7337,12,136,12,54232350,1,"[54232350, 300490, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7338,12,137,12,54232350,1,"[54232350, 302666, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7339,12,138,12,54232350,1,"[54232350, 304841, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7340,12,139,12,54232350,1,"[54232350, 307016, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7341,12,140,12,54232350,1,"[54232350, 309190, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7342,12,141,12,54232350,1,"[54232350, 311363, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7343,12,142,12,54232350,1,"[54232350, 313535, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7344,12,143,12,54232350,1,"[54232350, 315707, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7345,12,144,12,54232350,1,"[54232350, 317878, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7346,12,145,12,54232350,1,"[54232350, 320048, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7347,12,146,12,54232350,1,"[54232350, 322218, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7348,12,147,12,54232350,1,"[54232350, 324387, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7349,12,148,12,54232350,1,"[54232350, 326555, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7350,12,149,12,54232350,1,"[54232350, 328722, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7351,12,150,12,54232350,1,"[54232350, 330889, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7352,12,151,12,54232350,1,"[54232350, 333055, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7353,12,152,12,54232350,1,"[54232350, 335221, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7354,12,153,12,54232350,1,"[54232350, 337385, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7355,12,154,12,54232350,1,"[54232350, 339549, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7356,12,155,12,54232350,1,"[54232350, 341713, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7357,12,156,12,54232350,1,"[54232350, 343875, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7358,12,157,12,54232350,1,"[54232350, 346037, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7359,12,158,12,54232350,1,"[54232350, 348198, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7360,12,159,12,54232350,1,"[54232350, 350359, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7361,12,160,12,54232350,1,"[54232350, 352519, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7362,12,161,12,54232350,1,"[54232350, 354678, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7363,12,162,12,54232350,1,"[54232350, 356836, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7364,12,163,12,54232350,1,"[54232350, 358994, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7365,12,164,12,54232350,1,"[54232350, 361151, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7366,12,165,12,54232350,1,"[54232350, 363307, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7367,12,166,12,54232350,1,"[54232350, 365463, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7368,12,167,12,54232350,1,"[54232350, 367618, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7369,12,168,12,54232350,1,"[54232350, 369772, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7370,12,169,12,54232350,1,"[54232350, 371925, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7371,12,170,12,54232350,1,"[54232350, 374078, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7372,12,171,12,54232350,1,"[54232350, 376230, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7373,12,172,12,54232350,1,"[54232350, 378382, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7374,12,173,12,54232350,1,"[54232350, 380532, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7375,12,174,12,54232350,1,"[54232350, 382682, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7376,12,175,12,54232350,1,"[54232350, 384832, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7377,12,176,12,54232350,1,"[54232350, 386980, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7378,12,177,12,54232350,1,"[54232350, 389128, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7379,12,178,12,54232350,1,"[54232350, 391275, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7380,12,179,12,54232350,1,"[54232350, 393422, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7381,12,180,12,54232350,1,"[54232350, 395568, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7382,12,181,12,54232350,1,"[54232350, 397713, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7383,12,182,12,54232350,1,"[54232350, 399857, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7384,12,183,12,54232350,1,"[54232350, 402001, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7385,12,184,12,54232350,1,"[54232350, 404144, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7386,12,185,12,54232350,1,"[54232350, 406286, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7387,12,186,12,54232350,1,"[54232350, 408428, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7388,12,187,12,54232350,1,"[54232350, 410569, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7389,12,188,12,54232350,1,"[54232350, 412709, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7390,12,189,12,54232350,1,"[54232350, 414848, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7391,12,190,12,54232350,1,"[54232350, 416987, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7392,12,191,12,54232350,1,"[54232350, 419125, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7393,12,192,12,54232350,1,"[54232350, 421263, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7394,12,193,12,54232350,1,"[54232350, 423399, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7395,12,194,12,54232350,1,"[54232350, 425535, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7396,12,195,12,54232350,1,"[54232350, 427671, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7397,12,196,12,54232350,1,"[54232350, 429805, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7398,12,197,12,54232350,1,"[54232350, 431939, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7399,12,198,12,54232350,1,"[54232350, 434072, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7400,12,199,12,54232350,1,"[54232350, 436205, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7401,12,200,12,54232350,1,"[54232350, 438337, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7402,12,201,12,54232350,1,"[54232350, 440468, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7403,12,202,12,54232350,1,"[54232350, 442598, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7404,12,203,12,54232350,1,"[54232350, 444728, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7405,12,204,12,54232350,1,"[54232350, 446857, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7406,12,205,12,54232350,1,"[54232350, 448985, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7407,12,206,12,54232350,1,"[54232350, 451113, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7408,12,207,12,54232350,1,"[54232350, 453240, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7409,12,208,12,54232350,1,"[54232350, 455366, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7410,12,209,12,54232350,1,"[54232350, 457491, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7411,12,210,12,54232350,1,"[54232350, 459616, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7412,12,211,12,54232350,1,"[54232350, 461740, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7413,12,212,12,54232350,1,"[54232350, 463864, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7414,12,213,12,54232350,1,"[54232350, 465986, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7415,12,214,12,54232350,1,"[54232350, 468108, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7416,12,215,12,54232350,1,"[54232350, 470230, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7417,12,216,12,54232350,1,"[54232350, 472350, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7418,12,217,12,54232350,1,"[54232350, 474470, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7419,12,218,12,54232350,1,"[54232350, 476589, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7420,12,219,12,54232350,1,"[54232350, 478708, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7421,12,220,12,54232350,1,"[54232350, 480826, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7422,12,221,12,54232350,1,"[54232350, 482943, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7423,12,222,12,54232350,1,"[54232350, 485059, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7424,12,223,12,54232350,1,"[54232350, 487175, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7425,12,224,12,54232350,1,"[54232350, 489290, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7426,12,225,12,54232350,1,"[54232350, 491404, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7427,12,226,12,54232350,1,"[54232350, 493518, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7428,12,227,12,54232350,1,"[54232350, 495631, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7429,12,228,12,54232350,1,"[54232350, 497743, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7430,12,229,12,54232350,1,"[54232350, 499854, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7431,12,230,12,54232350,1,"[54232350, 501965, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7432,12,231,12,54232350,1,"[54232350, 504075, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7433,12,232,12,54232350,1,"[54232350, 506185, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7434,12,233,12,54232350,1,"[54232350, 508293, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7435,12,234,12,54232350,1,"[54232350, 510401, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7436,12,235,12,54232350,1,"[54232350, 512509, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7437,12,236,12,54232350,1,"[54232350, 514615, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7438,12,237,12,54232350,1,"[54232350, 516721, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7439,12,238,12,54232350,1,"[54232350, 518826, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7440,12,239,12,54232350,1,"[54232350, 520931, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7441,12,240,12,54232350,1,"[54232350, 523035, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7442,12,241,12,54232350,1,"[54232350, 525138, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7443,12,242,12,54232350,1,"[54232350, 527240, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7444,12,243,12,54232350,1,"[54232350, 529342, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7445,12,244,12,54232350,1,"[54232350, 531443, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7446,12,245,12,54232350,1,"[54232350, 533543, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7447,12,246,12,54232350,1,"[54232350, 535643, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7448,12,247,12,54232350,1,"[54232350, 537742, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7449,12,248,12,54232350,1,"[54232350, 539840, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7450,12,249,12,54232350,1,"[54232350, 541937, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7451,12,250,12,54232350,1,"[54232350, 544034, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7452,12,251,12,54232350,1,"[54232350, 546130, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7453,12,252,12,54232350,1,"[54232350, 548226, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7454,12,253,12,54232350,1,"[54232350, 550320, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7455,12,254,12,54232350,1,"[54232350, 552414, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7456,12,255,12,54232350,1,"[54232350, 554508, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7457,12,256,12,54232350,1,"[54232350, 556600, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7458,12,257,12,54232350,1,"[54232350, 558692, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7459,12,258,12,54232350,1,"[54232350, 560783, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7460,12,259,12,54232350,1,"[54232350, 562874, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7461,12,260,12,54232350,1,"[54232350, 564964, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7462,12,261,12,54232350,1,"[54232350, 567053, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7463,12,262,12,54232350,1,"[54232350, 569141, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7464,12,263,12,54232350,1,"[54232350, 571229, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7465,12,264,12,54232350,1,"[54232350, 573316, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7466,12,265,12,54232350,1,"[54232350, 575402, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7467,12,266,12,54232350,1,"[54232350, 577488, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7468,12,267,12,54232350,1,"[54232350, 579573, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7469,12,268,12,54232350,1,"[54232350, 581657, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7470,12,269,12,54232350,1,"[54232350, 583740, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7471,12,270,12,54232350,1,"[54232350, 585823, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7472,12,271,12,54232350,1,"[54232350, 587905, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7473,12,272,12,54232350,1,"[54232350, 589987, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7474,12,273,12,54232350,1,"[54232350, 592067, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7475,12,274,12,54232350,1,"[54232350, 594147, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7476,12,275,12,54232350,1,"[54232350, 596227, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7477,12,276,12,54232350,1,"[54232350, 598305, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7478,12,277,12,54232350,1,"[54232350, 600383, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7479,12,278,12,54232350,1,"[54232350, 602460, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7480,12,279,12,54232350,1,"[54232350, 604537, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7481,12,280,12,54232350,1,"[54232350, 606613, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7482,12,281,12,54232350,1,"[54232350, 608688, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7483,12,282,12,54232350,1,"[54232350, 610762, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7484,12,283,12,54232350,1,"[54232350, 612836, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7485,12,284,12,54232350,1,"[54232350, 614909, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7486,12,285,12,54232350,1,"[54232350, 616981, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7487,12,286,12,54232350,1,"[54232350, 619053, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7488,12,287,12,54232350,1,"[54232350, 621124, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7489,12,288,12,54232350,1,"[54232350, 623194, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7490,12,289,12,54232350,1,"[54232350, 625263, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7491,12,290,12,54232350,1,"[54232350, 627332, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7492,12,291,12,54232350,1,"[54232350, 629400, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7493,12,292,12,54232350,1,"[54232350, 631468, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7494,12,293,12,54232350,1,"[54232350, 633534, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7495,12,294,12,54232350,1,"[54232350, 635600, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7496,12,295,12,54232350,1,"[54232350, 637666, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7497,12,296,12,54232350,1,"[54232350, 639730, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7498,12,297,12,54232350,1,"[54232350, 641794, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7499,12,298,12,54232350,1,"[54232350, 643857, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7500,12,299,12,54232350,1,"[54232350, 645920, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7501,12,300,12,54232350,1,"[54232350, 647982, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7502,12,301,12,54232350,1,"[54232350, 650043, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7503,12,302,12,54232350,1,"[54232350, 652103, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7504,12,303,12,54232350,1,"[54232350, 654163, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7505,12,304,12,54232350,1,"[54232350, 656222, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7506,12,305,12,54232350,1,"[54232350, 658280, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7507,12,306,12,54232350,1,"[54232350, 660338, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7508,12,307,12,54232350,1,"[54232350, 662395, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7509,12,308,12,54232350,1,"[54232350, 664451, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7510,12,309,12,54232350,1,"[54232350, 666506, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7511,12,310,12,54232350,1,"[54232350, 668561, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7512,12,311,12,54232350,1,"[54232350, 670615, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7513,12,312,12,54232350,1,"[54232350, 672669, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7514,12,313,12,54232350,1,"[54232350, 674721, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7515,12,314,12,54232350,1,"[54232350, 676773, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7516,12,315,12,54232350,1,"[54232350, 678825, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7517,12,316,12,54232350,1,"[54232350, 680875, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7518,12,317,12,54232350,1,"[54232350, 682925, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7519,12,318,12,54232350,1,"[54232350, 684974, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7520,12,319,12,54232350,1,"[54232350, 687023, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7521,12,320,12,54232350,1,"[54232350, 689071, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7522,12,321,12,54232350,1,"[54232350, 691118, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7523,12,322,12,54232350,1,"[54232350, 693164, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7524,12,323,12,54232350,1,"[54232350, 695210, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7525,12,324,12,54232350,1,"[54232350, 697255, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7526,12,325,12,54232350,1,"[54232350, 699299, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7527,12,326,12,54232350,1,"[54232350, 701343, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7528,12,327,12,54232350,1,"[54232350, 703386, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7529,12,328,12,54232350,1,"[54232350, 705428, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7530,12,329,12,54232350,1,"[54232350, 707469, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7531,12,330,12,54232350,1,"[54232350, 709510, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7532,12,331,12,54232350,1,"[54232350, 711550, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7533,12,332,12,54232350,1,"[54232350, 713590, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7534,12,333,12,54232350,1,"[54232350, 715628, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7535,12,334,12,54232350,1,"[54232350, 717666, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7536,12,335,12,54232350,1,"[54232350, 719704, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7537,12,336,12,54232350,1,"[54232350, 721740, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7538,12,337,12,54232350,1,"[54232350, 723776, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7539,12,338,12,54232350,1,"[54232350, 725811, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7540,12,339,12,54232350,1,"[54232350, 727846, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7541,12,340,12,54232350,1,"[54232350, 729880, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7542,12,341,12,54232350,1,"[54232350, 731913, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7543,12,342,12,54232350,1,"[54232350, 733945, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7544,12,343,12,54232350,1,"[54232350, 735977, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7545,12,344,12,54232350,1,"[54232350, 738008, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7546,12,345,12,54232350,1,"[54232350, 740038, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7547,12,346,12,54232350,1,"[54232350, 742068, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7548,12,347,12,54232350,1,"[54232350, 744097, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7549,12,348,12,54232350,1,"[54232350, 746125, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7550,12,349,12,54232350,1,"[54232350, 748152, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7551,12,350,12,54232350,1,"[54232350, 750179, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7552,12,351,12,54232350,1,"[54232350, 752205, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7553,12,352,12,54232350,1,"[54232350, 754231, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7554,12,353,12,54232350,1,"[54232350, 756255, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7555,12,354,12,54232350,1,"[54232350, 758279, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7556,12,355,12,54232350,1,"[54232350, 760303, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7557,12,356,12,54232350,1,"[54232350, 762325, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7558,12,357,12,54232350,1,"[54232350, 764347, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7559,12,358,12,54232350,1,"[54232350, 766368, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7560,12,359,12,54232350,1,"[54232350, 768389, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7561,12,360,12,54232350,1,"[54232350, 770409, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7562,12,361,12,54232350,1,"[54232350, 772428, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7563,12,362,12,54232350,1,"[54232350, 774446, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7564,12,363,12,54232350,1,"[54232350, 776464, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7565,12,364,12,54232350,1,"[54232350, 778481, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7566,12,365,12,54232350,1,"[54232350, 780497, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7567,12,366,12,54232350,1,"[54232350, 782513, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7568,12,367,12,54232350,1,"[54232350, 784528, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7569,12,368,12,54232350,1,"[54232350, 786542, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7570,12,369,12,54232350,1,"[54232350, 788555, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7571,12,370,12,54232350,1,"[54232350, 790568, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7572,12,371,12,54232350,1,"[54232350, 792580, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7573,12,372,12,54232350,1,"[54232350, 794592, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7574,12,373,12,54232350,1,"[54232350, 796602, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7575,12,374,12,54232350,1,"[54232350, 798612, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7576,12,375,12,54232350,1,"[54232350, 800622, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7577,12,376,12,54232350,1,"[54232350, 802630, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7578,12,377,12,54232350,1,"[54232350, 804638, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7579,12,378,12,54232350,1,"[54232350, 806645, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7580,12,379,12,54232350,1,"[54232350, 808652, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7581,12,380,12,54232350,1,"[54232350, 810658, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7582,12,381,12,54232350,1,"[54232350, 812663, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7583,12,382,12,54232350,1,"[54232350, 814667, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7584,12,383,12,54232350,1,"[54232350, 816671, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7585,12,384,12,54232350,1,"[54232350, 818674, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7586,12,385,12,54232350,1,"[54232350, 820676, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7587,12,386,12,54232350,1,"[54232350, 822678, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7588,12,387,12,54232350,1,"[54232350, 824679, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7589,12,388,12,54232350,1,"[54232350, 826679, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7590,12,389,12,54232350,1,"[54232350, 828678, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7591,12,390,12,54232350,1,"[54232350, 830677, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7592,12,391,12,54232350,1,"[54232350, 832675, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7593,12,392,12,54232350,1,"[54232350, 834673, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7594,12,393,12,54232350,1,"[54232350, 836669, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7595,12,394,12,54232350,1,"[54232350, 838665, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7596,12,395,12,54232350,1,"[54232350, 840661, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7597,12,396,12,54232350,1,"[54232350, 842655, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7598,12,397,12,54232350,1,"[54232350, 844649, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7599,12,398,12,54232350,1,"[54232350, 846642, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7600,12,399,12,54232350,1,"[54232350, 848635, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7601,12,400,12,54232350,1,"[54232350, 850627, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7602,12,401,12,54232350,1,"[54232350, 852618, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7603,12,402,12,54232350,1,"[54232350, 854608, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7604,12,403,12,54232350,1,"[54232350, 856598, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7605,12,404,12,54232350,1,"[54232350, 858587, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7606,12,405,12,54232350,1,"[54232350, 860575, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7607,12,406,12,54232350,1,"[54232350, 862563, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7608,12,407,12,54232350,1,"[54232350, 864550, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7609,12,408,12,54232350,1,"[54232350, 866536, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7610,12,409,12,54232350,1,"[54232350, 868521, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7611,12,410,12,54232350,1,"[54232350, 870506, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7612,12,411,12,54232350,1,"[54232350, 872490, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7613,12,412,12,54232350,1,"[54232350, 874474, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7614,12,413,12,54232350,1,"[54232350, 876456, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7615,12,414,12,54232350,1,"[54232350, 878438, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7616,12,415,12,54232350,1,"[54232350, 880420, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7617,12,416,12,54232350,1,"[54232350, 882400, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7618,12,417,12,54232350,1,"[54232350, 884380, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7619,12,418,12,54232350,1,"[54232350, 886359, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7620,12,419,12,54232350,1,"[54232350, 888338, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7621,12,420,12,54232350,1,"[54232350, 890316, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7622,12,421,12,54232350,1,"[54232350, 892293, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7623,12,422,12,54232350,1,"[54232350, 894269, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7624,12,423,12,54232350,1,"[54232350, 896245, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7625,12,424,12,54232350,1,"[54232350, 898220, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7626,12,425,12,54232350,1,"[54232350, 900194, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7627,12,426,12,54232350,1,"[54232350, 902168, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7628,12,427,12,54232350,1,"[54232350, 904141, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7629,12,428,12,54232350,1,"[54232350, 906113, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7630,12,429,12,54232350,1,"[54232350, 908084, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7631,12,430,12,54232350,1,"[54232350, 910055, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7632,12,431,12,54232350,1,"[54232350, 912025, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7633,12,432,12,54232350,1,"[54232350, 913995, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7634,12,433,12,54232350,1,"[54232350, 915963, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7635,12,434,12,54232350,1,"[54232350, 917931, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7636,12,435,12,54232350,1,"[54232350, 919899, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7637,12,436,12,54232350,1,"[54232350, 921865, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7638,12,437,12,54232350,1,"[54232350, 923831, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7639,12,438,12,54232350,1,"[54232350, 925796, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7640,12,439,12,54232350,1,"[54232350, 927761, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7641,12,440,12,54232350,1,"[54232350, 929725, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7642,12,441,12,54232350,1,"[54232350, 931688, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7643,12,442,12,54232350,1,"[54232350, 933650, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7644,12,443,12,54232350,1,"[54232350, 935612, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7645,12,444,12,54232350,1,"[54232350, 937573, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7646,12,445,12,54232350,1,"[54232350, 939533, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7647,12,446,12,54232350,1,"[54232350, 941493, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7648,12,447,12,54232350,1,"[54232350, 943452, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7649,12,448,12,54232350,1,"[54232350, 945410, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7650,12,449,12,54232350,1,"[54232350, 947367, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7651,12,450,12,54232350,1,"[54232350, 949324, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7652,12,451,12,54232350,1,"[54232350, 951280, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7653,12,452,12,54232350,1,"[54232350, 953236, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7654,12,453,12,54232350,1,"[54232350, 955190, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7655,12,454,12,54232350,1,"[54232350, 957144, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7656,12,455,12,54232350,1,"[54232350, 959098, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7657,12,456,12,54232350,1,"[54232350, 961050, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7658,12,457,12,54232350,1,"[54232350, 963002, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7659,12,458,12,54232350,1,"[54232350, 964953, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7660,12,459,12,54232350,1,"[54232350, 966904, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7661,12,460,12,54232350,1,"[54232350, 968854, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7662,12,461,12,54232350,1,"[54232350, 970803, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7663,12,462,12,54232350,1,"[54232350, 972751, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7664,12,463,12,54232350,1,"[54232350, 974699, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7665,12,464,12,54232350,1,"[54232350, 976646, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7666,12,465,12,54232350,1,"[54232350, 978592, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7667,12,466,12,54232350,1,"[54232350, 980538, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7668,12,467,12,54232350,1,"[54232350, 982483, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7669,12,468,12,54232350,1,"[54232350, 984427, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7670,12,469,12,54232350,1,"[54232350, 986370, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7671,12,470,12,54232350,1,"[54232350, 988313, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7672,12,471,12,54232350,1,"[54232350, 990255, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7673,12,472,12,54232350,1,"[54232350, 992197, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7674,12,473,12,54232350,1,"[54232350, 994137, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7675,12,474,12,54232350,1,"[54232350, 996077, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7676,12,475,12,54232350,1,"[54232350, 998017, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7677,12,476,12,54232350,1,"[54232350, 999955, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7678,12,477,12,54232350,1,"[54232350, 1001893, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7679,12,478,12,54232350,1,"[54232350, 1003830, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7680,12,479,12,54232350,1,"[54232350, 1005767, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7681,12,480,12,54232350,1,"[54232350, 1007703, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7682,12,481,12,54232350,1,"[54232350, 1009638, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7683,12,482,12,54232350,1,"[54232350, 1011572, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7684,12,483,12,54232350,1,"[54232350, 1013506, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7685,12,484,12,54232350,1,"[54232350, 1015439, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7686,12,485,12,54232350,1,"[54232350, 1017371, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7687,12,486,12,54232350,1,"[54232350, 1019303, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7688,12,487,12,54232350,1,"[54232350, 1021234, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7689,12,488,12,54232350,1,"[54232350, 1023164, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7690,12,489,12,54232350,1,"[54232350, 1025093, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7691,12,490,12,54232350,1,"[54232350, 1027022, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7692,12,491,12,54232350,1,"[54232350, 1028950, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7693,12,492,12,54232350,1,"[54232350, 1030878, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7694,12,493,12,54232350,1,"[54232350, 1032804, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7695,12,494,12,54232350,1,"[54232350, 1034730, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7696,12,495,12,54232350,1,"[54232350, 1036656, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7697,12,496,12,54232350,1,"[54232350, 1038580, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7698,12,497,12,54232350,1,"[54232350, 1040504, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7699,12,498,12,54232350,1,"[54232350, 1042427, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7700,12,499,12,54232350,1,"[54232350, 1044350, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7701,12,500,12,54232350,1,"[54232350, 1046272, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7702,12,501,12,54232350,1,"[54232350, 1048193, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7703,12,502,12,54232350,1,"[54232350, 1050113, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7704,12,503,12,54232350,1,"[54232350, 1052033, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7705,12,504,12,54232350,1,"[54232350, 1053952, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7706,12,505,12,54232350,1,"[54232350, 1055870, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7707,12,506,12,54232350,1,"[54232350, 1057788, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7708,12,507,12,54232350,1,"[54232350, 1059705, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7709,12,508,12,54232350,1,"[54232350, 1061621, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7710,12,509,12,54232350,1,"[54232350, 1063536, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7711,12,510,12,54232350,1,"[54232350, 1065451, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7712,12,511,12,54232350,1,"[54232350, 1067365, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7713,12,512,12,54232350,1,"[54232350, 1069279, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7714,12,513,12,54232350,1,"[54232350, 1071191, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7715,12,514,12,54232350,1,"[54232350, 1073103, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7716,12,515,12,54232350,1,"[54232350, 1075015, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7717,12,516,12,54232350,1,"[54232350, 1076925, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7718,12,517,12,54232350,1,"[54232350, 1078835, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7719,12,518,12,54232350,1,"[54232350, 1080744, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7720,12,519,12,54232350,1,"[54232350, 1082653, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7721,12,520,12,54232350,1,"[54232350, 1084561, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7722,12,521,12,54232350,1,"[54232350, 1086468, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7723,12,522,12,54232350,1,"[54232350, 1088374, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7724,12,523,12,54232350,1,"[54232350, 1090280, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7725,12,524,12,54232350,1,"[54232350, 1092185, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7726,12,525,12,54232350,1,"[54232350, 1094089, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7727,12,526,12,54232350,1,"[54232350, 1095993, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7728,12,527,12,54232350,1,"[54232350, 1097896, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7729,12,528,12,54232350,1,"[54232350, 1099798, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7730,12,529,12,54232350,1,"[54232350, 1101699, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7731,12,530,12,54232350,1,"[54232350, 1103600, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7732,12,531,12,54232350,1,"[54232350, 1105500, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7733,12,532,12,54232350,1,"[54232350, 1107400, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7734,12,533,12,54232350,1,"[54232350, 1109298, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7735,12,534,12,54232350,1,"[54232350, 1111196, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7736,12,535,12,54232350,1,"[54232350, 1113094, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7737,12,536,12,54232350,1,"[54232350, 1114990, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7738,12,537,12,54232350,1,"[54232350, 1116886, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7739,12,538,12,54232350,1,"[54232350, 1118781, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7740,12,539,12,54232350,1,"[54232350, 1120676, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7741,12,540,12,54232350,1,"[54232350, 1122570, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7742,12,541,12,54232350,1,"[54232350, 1124463, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7743,12,542,12,54232350,1,"[54232350, 1126355, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7744,12,543,12,54232350,1,"[54232350, 1128247, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7745,12,544,12,54232350,1,"[54232350, 1130138, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7746,12,545,12,54232350,1,"[54232350, 1132028, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7747,12,546,12,54232350,1,"[54232350, 1133918, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7748,12,547,12,54232350,1,"[54232350, 1135807, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7749,12,548,12,54232350,1,"[54232350, 1137695, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7750,12,549,12,54232350,1,"[54232350, 1139582, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7751,12,550,12,54232350,1,"[54232350, 1141469, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7752,12,551,12,54232350,1,"[54232350, 1143355, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7753,12,552,12,54232350,1,"[54232350, 1145241, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7754,12,553,12,54232350,1,"[54232350, 1147125, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7755,12,554,12,54232350,1,"[54232350, 1149009, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7756,12,555,12,54232350,1,"[54232350, 1150893, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7757,12,556,12,54232350,1,"[54232350, 1152775, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7758,12,557,12,54232350,1,"[54232350, 1154657, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7759,12,558,12,54232350,1,"[54232350, 1156538, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7760,12,559,12,54232350,1,"[54232350, 1158419, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7761,12,560,12,54232350,1,"[54232350, 1160299, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7762,12,561,12,54232350,1,"[54232350, 1162178, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7763,12,562,12,54232350,1,"[54232350, 1164056, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7764,12,563,12,54232350,1,"[54232350, 1165934, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7765,12,564,12,54232350,1,"[54232350, 1167811, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7766,12,565,12,54232350,1,"[54232350, 1169687, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7767,12,566,12,54232350,1,"[54232350, 1171563, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7768,12,567,12,54232350,1,"[54232350, 1173438, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7769,12,568,12,54232350,1,"[54232350, 1175312, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7770,12,569,12,54232350,1,"[54232350, 1177185, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7771,12,570,12,54232350,1,"[54232350, 1179058, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7772,12,571,12,54232350,1,"[54232350, 1180930, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7773,12,572,12,54232350,1,"[54232350, 1182802, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7774,12,573,12,54232350,1,"[54232350, 1184672, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7775,12,574,12,54232350,1,"[54232350, 1186542, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7776,12,575,12,54232350,1,"[54232350, 1188412, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7777,12,576,12,54232350,1,"[54232350, 1190280, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7778,12,577,12,54232350,1,"[54232350, 1192148, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7779,12,578,12,54232350,1,"[54232350, 1194015, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7780,12,579,12,54232350,1,"[54232350, 1195882, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7781,12,580,12,54232350,1,"[54232350, 1197748, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7782,12,581,12,54232350,1,"[54232350, 1199613, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7783,12,582,12,54232350,1,"[54232350, 1201477, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7784,12,583,12,54232350,1,"[54232350, 1203341, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7785,12,584,12,54232350,1,"[54232350, 1205204, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7786,12,585,12,54232350,1,"[54232350, 1207066, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7787,12,586,12,54232350,1,"[54232350, 1208928, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7788,12,587,12,54232350,1,"[54232350, 1210789, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7789,12,588,12,54232350,1,"[54232350, 1212649, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7790,12,589,12,54232350,1,"[54232350, 1214508, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7791,12,590,12,54232350,1,"[54232350, 1216367, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7792,12,591,12,54232350,1,"[54232350, 1218225, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7793,12,592,12,54232350,1,"[54232350, 1220083, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7794,12,593,12,54232350,1,"[54232350, 1221939, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7795,12,594,12,54232350,1,"[54232350, 1223795, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7796,12,595,12,54232350,1,"[54232350, 1225651, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7797,12,596,12,54232350,1,"[54232350, 1227505, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7798,12,597,12,54232350,1,"[54232350, 1229359, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7799,12,598,12,54232350,1,"[54232350, 1231212, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7800,12,599,12,54232350,1,"[54232350, 1233065, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7801,12,600,12,54232350,1,"[54232350, 1234917, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7802,12,601,12,54232350,1,"[54232350, 1236768, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7803,12,602,12,54232350,1,"[54232350, 1238618, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7804,12,603,12,54232350,1,"[54232350, 1240468, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7805,12,604,12,54232350,1,"[54232350, 1242317, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7806,12,605,12,54232350,1,"[54232350, 1244165, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7807,12,606,12,54232350,1,"[54232350, 1246013, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7808,12,607,12,54232350,1,"[54232350, 1247860, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7809,12,608,12,54232350,1,"[54232350, 1249706, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7810,12,609,12,54232350,1,"[54232350, 1251551, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7811,12,610,12,54232350,1,"[54232350, 1253396, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7812,12,611,12,54232350,1,"[54232350, 1255240, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7813,12,612,12,54232350,1,"[54232350, 1257084, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7814,12,613,12,54232350,1,"[54232350, 1258926, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7815,12,614,12,54232350,1,"[54232350, 1260768, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7816,12,615,12,54232350,1,"[54232350, 1262610, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7817,12,616,12,54232350,1,"[54232350, 1264450, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7818,12,617,12,54232350,1,"[54232350, 1266290, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7819,12,618,12,54232350,1,"[54232350, 1268129, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7820,12,619,12,54232350,1,"[54232350, 1269968, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7821,12,620,12,54232350,1,"[54232350, 1271806, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7822,12,621,12,54232350,1,"[54232350, 1273643, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7823,12,622,12,54232350,1,"[54232350, 1275479, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7824,12,623,12,54232350,1,"[54232350, 1277315, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7825,12,624,12,54232350,1,"[54232350, 1279150, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7826,12,625,12,54232350,1,"[54232350, 1280984, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7827,12,626,12,54232350,1,"[54232350, 1282818, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7828,12,627,12,54232350,1,"[54232350, 1284651, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7829,12,628,12,54232350,1,"[54232350, 1286483, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7830,12,629,12,54232350,1,"[54232350, 1288314, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7831,12,630,12,54232350,1,"[54232350, 1290145, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7832,12,631,12,54232350,1,"[54232350, 1291975, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7833,12,632,12,54232350,1,"[54232350, 1293805, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7834,12,633,12,54232350,1,"[54232350, 1295633, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7835,12,634,12,54232350,1,"[54232350, 1297461, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7836,12,635,12,54232350,1,"[54232350, 1299289, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7837,12,636,12,54232350,1,"[54232350, 1301115, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7838,12,637,12,54232350,1,"[54232350, 1302941, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7839,12,638,12,54232350,1,"[54232350, 1304766, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7840,12,639,12,54232350,1,"[54232350, 1306591, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7841,12,640,12,54232350,1,"[54232350, 1308415, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7842,12,641,12,54232350,1,"[54232350, 1310238, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7843,12,642,12,54232350,1,"[54232350, 1312060, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7844,12,643,12,54232350,1,"[54232350, 1313882, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7845,12,644,12,54232350,1,"[54232350, 1315703, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7846,12,645,12,54232350,1,"[54232350, 1317523, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7847,12,646,12,54232350,1,"[54232350, 1319343, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7848,12,647,12,54232350,1,"[54232350, 1321162, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7849,12,648,12,54232350,1,"[54232350, 1322980, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7850,12,649,12,54232350,1,"[54232350, 1324797, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7851,12,650,12,54232350,1,"[54232350, 1326614, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7852,12,651,12,54232350,1,"[54232350, 1328430, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7853,12,652,12,54232350,1,"[54232350, 1330246, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7854,12,653,12,54232350,1,"[54232350, 1332060, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7855,12,654,12,54232350,1,"[54232350, 1333874, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7856,12,655,12,54232350,1,"[54232350, 1335688, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7857,12,656,12,54232350,1,"[54232350, 1337500, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7858,12,657,12,54232350,1,"[54232350, 1339312, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7859,12,658,12,54232350,1,"[54232350, 1341123, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7860,12,659,12,54232350,1,"[54232350, 1342934, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7861,12,660,12,54232350,1,"[54232350, 1344744, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7862,12,661,12,54232350,1,"[54232350, 1346553, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7863,12,662,12,54232350,1,"[54232350, 1348361, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7864,12,663,12,54232350,1,"[54232350, 1350169, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7865,12,664,12,54232350,1,"[54232350, 1351976, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7866,12,665,12,54232350,1,"[54232350, 1353782, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7867,12,666,12,54232350,1,"[54232350, 1355588, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7868,12,667,12,54232350,1,"[54232350, 1357393, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7869,12,668,12,54232350,1,"[54232350, 1359197, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7870,12,669,12,54232350,1,"[54232350, 1361000, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7871,12,670,12,54232350,1,"[54232350, 1362803, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7872,12,671,12,54232350,1,"[54232350, 1364605, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7873,12,672,12,54232350,1,"[54232350, 1366407, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7874,12,673,12,54232350,1,"[54232350, 1368207, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7875,12,674,12,54232350,1,"[54232350, 1370007, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7876,12,675,12,54232350,1,"[54232350, 1371807, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7877,12,676,12,54232350,1,"[54232350, 1373605, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7878,12,677,12,54232350,1,"[54232350, 1375403, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7879,12,678,12,54232350,1,"[54232350, 1377200, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7880,12,679,12,54232350,1,"[54232350, 1378997, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7881,12,680,12,54232350,1,"[54232350, 1380793, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7882,12,681,12,54232350,1,"[54232350, 1382588, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7883,12,682,12,54232350,1,"[54232350, 1384382, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7884,12,683,12,54232350,1,"[54232350, 1386176, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7885,12,684,12,54232350,1,"[54232350, 1387969, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7886,12,685,12,54232350,1,"[54232350, 1389761, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7887,12,686,12,54232350,1,"[54232350, 1391553, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7888,12,687,12,54232350,1,"[54232350, 1393344, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7889,12,688,12,54232350,1,"[54232350, 1395134, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7890,12,689,12,54232350,1,"[54232350, 1396923, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7891,12,690,12,54232350,1,"[54232350, 1398712, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7892,12,691,12,54232350,1,"[54232350, 1400500, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7893,12,692,12,54232350,1,"[54232350, 1402288, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7894,12,693,12,54232350,1,"[54232350, 1404074, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7895,12,694,12,54232350,1,"[54232350, 1405860, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7896,12,695,12,54232350,1,"[54232350, 1407646, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7897,12,696,12,54232350,1,"[54232350, 1409430, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7898,12,697,12,54232350,1,"[54232350, 1411214, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7899,12,698,12,54232350,1,"[54232350, 1412997, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7900,12,699,12,54232350,1,"[54232350, 1414780, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7901,12,700,12,54232350,1,"[54232350, 1416562, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7902,12,701,12,54232350,1,"[54232350, 1418343, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7903,12,702,12,54232350,1,"[54232350, 1420123, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7904,12,703,12,54232350,1,"[54232350, 1421903, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7905,12,704,12,54232350,1,"[54232350, 1423682, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7906,12,705,12,54232350,1,"[54232350, 1425460, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7907,12,706,12,54232350,1,"[54232350, 1427238, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7908,12,707,12,54232350,1,"[54232350, 1429015, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7909,12,708,12,54232350,1,"[54232350, 1430791, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7910,12,709,12,54232350,1,"[54232350, 1432566, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7911,12,710,12,54232350,1,"[54232350, 1434341, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7912,12,711,12,54232350,1,"[54232350, 1436115, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7913,12,712,12,54232350,1,"[54232350, 1437889, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7914,12,713,12,54232350,1,"[54232350, 1439661, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7915,12,714,12,54232350,1,"[54232350, 1441433, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7916,12,715,12,54232350,1,"[54232350, 1443205, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7917,12,716,12,54232350,1,"[54232350, 1444975, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7918,12,717,12,54232350,1,"[54232350, 1446745, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7919,12,718,12,54232350,1,"[54232350, 1448514, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7920,12,719,12,54232350,1,"[54232350, 1450283, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7921,12,720,12,54232350,1,"[54232350, 1452051, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7922,12,721,12,54232350,1,"[54232350, 1453818, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7923,12,722,12,54232350,1,"[54232350, 1455584, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7924,12,723,12,54232350,1,"[54232350, 1457350, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7925,12,724,12,54232350,1,"[54232350, 1459115, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7926,12,725,12,54232350,1,"[54232350, 1460879, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7927,12,726,12,54232350,1,"[54232350, 1462643, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7928,12,727,12,54232350,1,"[54232350, 1464406, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7929,12,728,12,54232350,1,"[54232350, 1466168, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7930,12,729,12,54232350,1,"[54232350, 1467929, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7931,12,730,12,54232350,1,"[54232350, 1469690, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7932,12,731,12,54232350,1,"[54232350, 1471450, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7933,12,732,12,54232350,1,"[54232350, 1473210, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7934,12,733,12,54232350,1,"[54232350, 1474968, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7935,12,734,12,54232350,1,"[54232350, 1476726, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7936,12,735,12,54232350,1,"[54232350, 1478484, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7937,12,736,12,54232350,1,"[54232350, 1480240, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7938,12,737,12,54232350,1,"[54232350, 1481996, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7939,12,738,12,54232350,1,"[54232350, 1483751, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7940,12,739,12,54232350,1,"[54232350, 1485506, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7941,12,740,12,54232350,1,"[54232350, 1487260, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7942,12,741,12,54232350,1,"[54232350, 1489013, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7943,12,742,12,54232350,1,"[54232350, 1490765, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7944,12,743,12,54232350,1,"[54232350, 1492517, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7945,12,744,12,54232350,1,"[54232350, 1494268, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7946,12,745,12,54232350,1,"[54232350, 1496018, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7947,12,746,12,54232350,1,"[54232350, 1497768, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7948,12,747,12,54232350,1,"[54232350, 1499517, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7949,12,748,12,54232350,1,"[54232350, 1501265, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7950,12,749,12,54232350,1,"[54232350, 1503012, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7951,12,750,12,54232350,1,"[54232350, 1504759, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7952,12,751,12,54232350,1,"[54232350, 1506505, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7953,12,752,12,54232350,1,"[54232350, 1508251, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7954,12,753,12,54232350,1,"[54232350, 1509995, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7955,12,754,12,54232350,1,"[54232350, 1511739, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7956,12,755,12,54232350,1,"[54232350, 1513483, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7957,12,756,12,54232350,1,"[54232350, 1515225, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7958,12,757,12,54232350,1,"[54232350, 1516967, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7959,12,758,12,54232350,1,"[54232350, 1518708, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7960,12,759,12,54232350,1,"[54232350, 1520449, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7961,12,760,12,54232350,1,"[54232350, 1522189, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7962,12,761,12,54232350,1,"[54232350, 1523928, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7963,12,762,12,54232350,1,"[54232350, 1525666, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7964,12,763,12,54232350,1,"[54232350, 1527404, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7965,12,764,12,54232350,1,"[54232350, 1529141, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7966,12,765,12,54232350,1,"[54232350, 1530877, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7967,12,766,12,54232350,1,"[54232350, 1532613, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7968,12,767,12,54232350,1,"[54232350, 1534348, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7969,12,768,12,54232350,1,"[54232350, 1536082, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7970,12,769,12,54232350,1,"[54232350, 1537815, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7971,12,770,12,54232350,1,"[54232350, 1539548, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7972,12,771,12,54232350,1,"[54232350, 1541280, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7973,12,772,12,54232350,1,"[54232350, 1543012, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7974,12,773,12,54232350,1,"[54232350, 1544742, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7975,12,774,12,54232350,1,"[54232350, 1546472, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7976,12,775,12,54232350,1,"[54232350, 1548202, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7977,12,776,12,54232350,1,"[54232350, 1549930, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7978,12,777,12,54232350,1,"[54232350, 1551658, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7979,12,778,12,54232350,1,"[54232350, 1553385, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7980,12,779,12,54232350,1,"[54232350, 1555112, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7981,12,780,12,54232350,1,"[54232350, 1556838, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7982,12,781,12,54232350,1,"[54232350, 1558563, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7983,12,782,12,54232350,1,"[54232350, 1560287, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7984,12,783,12,54232350,1,"[54232350, 1562011, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7985,12,784,12,54232350,1,"[54232350, 1563734, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7986,12,785,12,54232350,1,"[54232350, 1565456, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7987,12,786,12,54232350,1,"[54232350, 1567178, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7988,12,787,12,54232350,1,"[54232350, 1568899, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7989,12,788,12,54232350,1,"[54232350, 1570619, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7990,12,789,12,54232350,1,"[54232350, 1572338, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7991,12,790,12,54232350,1,"[54232350, 1574057, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7992,12,791,12,54232350,1,"[54232350, 1575775, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7993,12,792,12,54232350,1,"[54232350, 1577493, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7994,12,793,12,54232350,1,"[54232350, 1579209, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7995,12,794,12,54232350,1,"[54232350, 1580925, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7996,12,795,12,54232350,1,"[54232350, 1582641, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7997,12,796,12,54232350,1,"[54232350, 1584355, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7998,12,797,12,54232350,1,"[54232350, 1586069, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -7999,12,798,12,54232350,1,"[54232350, 1587782, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8000,12,799,12,54232350,1,"[54232350, 1589495, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8001,12,800,12,54232350,1,"[54232350, 1591207, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8002,12,801,12,54232350,1,"[54232350, 1592918, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8003,12,802,12,54232350,1,"[54232350, 1594628, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8004,12,803,12,54232350,1,"[54232350, 1596338, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8005,12,804,12,54232350,1,"[54232350, 1598047, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8006,12,805,12,54232350,1,"[54232350, 1599755, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8007,12,806,12,54232350,1,"[54232350, 1601463, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8008,12,807,12,54232350,1,"[54232350, 1603170, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8009,12,808,12,54232350,1,"[54232350, 1604876, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8010,12,809,12,54232350,1,"[54232350, 1606581, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8011,12,810,12,54232350,1,"[54232350, 1608286, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8012,12,811,12,54232350,1,"[54232350, 1609990, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8013,12,812,12,54232350,1,"[54232350, 1611694, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8014,12,813,12,54232350,1,"[54232350, 1613396, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8015,12,814,12,54232350,1,"[54232350, 1615098, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8016,12,815,12,54232350,1,"[54232350, 1616800, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8017,12,816,12,54232350,1,"[54232350, 1618500, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8018,12,817,12,54232350,1,"[54232350, 1620200, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8019,12,818,12,54232350,1,"[54232350, 1621899, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8020,12,819,12,54232350,1,"[54232350, 1623598, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8021,12,820,12,54232350,1,"[54232350, 1625296, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8022,12,821,12,54232350,1,"[54232350, 1626993, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8023,12,822,12,54232350,1,"[54232350, 1628689, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8024,12,823,12,54232350,1,"[54232350, 1630385, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8025,12,824,12,54232350,1,"[54232350, 1632080, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8026,12,825,12,54232350,1,"[54232350, 1633774, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8027,12,826,12,54232350,1,"[54232350, 1635468, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8028,12,827,12,54232350,1,"[54232350, 1637161, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8029,12,828,12,54232350,1,"[54232350, 1638853, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8030,12,829,12,54232350,1,"[54232350, 1640544, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8031,12,830,12,54232350,1,"[54232350, 1642235, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8032,12,831,12,54232350,1,"[54232350, 1643925, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8033,12,832,12,54232350,1,"[54232350, 1645615, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8034,12,833,12,54232350,1,"[54232350, 1647303, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8035,12,834,12,54232350,1,"[54232350, 1648991, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8036,12,835,12,54232350,1,"[54232350, 1650679, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8037,12,836,12,54232350,1,"[54232350, 1652365, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8038,12,837,12,54232350,1,"[54232350, 1654051, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8039,12,838,12,54232350,1,"[54232350, 1655736, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8040,12,839,12,54232350,1,"[54232350, 1657421, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8041,12,840,12,54232350,1,"[54232350, 1659105, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8042,12,841,12,54232350,1,"[54232350, 1660788, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8043,12,842,12,54232350,1,"[54232350, 1662470, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8044,12,843,12,54232350,1,"[54232350, 1664152, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8045,12,844,12,54232350,1,"[54232350, 1665833, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8046,12,845,12,54232350,1,"[54232350, 1667513, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8047,12,846,12,54232350,1,"[54232350, 1669193, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8048,12,847,12,54232350,1,"[54232350, 1670872, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8049,12,848,12,54232350,1,"[54232350, 1672550, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8050,12,849,12,54232350,1,"[54232350, 1674227, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8051,12,850,12,54232350,1,"[54232350, 1675904, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8052,12,851,12,54232350,1,"[54232350, 1677580, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8053,12,852,12,54232350,1,"[54232350, 1679256, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8054,12,853,12,54232350,1,"[54232350, 1680930, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8055,12,854,12,54232350,1,"[54232350, 1682604, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8056,12,855,12,54232350,1,"[54232350, 1684278, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8057,12,856,12,54232350,1,"[54232350, 1685950, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8058,12,857,12,54232350,1,"[54232350, 1687622, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8059,12,858,12,54232350,1,"[54232350, 1689293, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8060,12,859,12,54232350,1,"[54232350, 1690964, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8061,12,860,12,54232350,1,"[54232350, 1692634, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8062,12,861,12,54232350,1,"[54232350, 1694303, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8063,12,862,12,54232350,1,"[54232350, 1695971, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8064,12,863,12,54232350,1,"[54232350, 1697639, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8065,12,864,12,54232350,1,"[54232350, 1699306, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8066,12,865,12,54232350,1,"[54232350, 1700972, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8067,12,866,12,54232350,1,"[54232350, 1702638, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8068,12,867,12,54232350,1,"[54232350, 1704303, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8069,12,868,12,54232350,1,"[54232350, 1705967, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8070,12,869,12,54232350,1,"[54232350, 1707630, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8071,12,870,12,54232350,1,"[54232350, 1709293, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8072,12,871,12,54232350,1,"[54232350, 1710955, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8073,12,872,12,54232350,1,"[54232350, 1712617, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8074,12,873,12,54232350,1,"[54232350, 1714277, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8075,12,874,12,54232350,1,"[54232350, 1715937, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8076,12,875,12,54232350,1,"[54232350, 1717597, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8077,12,876,12,54232350,1,"[54232350, 1719255, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8078,12,877,12,54232350,1,"[54232350, 1720913, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8079,12,878,12,54232350,1,"[54232350, 1722570, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8080,12,879,12,54232350,1,"[54232350, 1724227, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8081,12,880,12,54232350,1,"[54232350, 1725883, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8082,12,881,12,54232350,1,"[54232350, 1727538, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8083,12,882,12,54232350,1,"[54232350, 1729192, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8084,12,883,12,54232350,1,"[54232350, 1730846, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8085,12,884,12,54232350,1,"[54232350, 1732499, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8086,12,885,12,54232350,1,"[54232350, 1734151, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8087,12,886,12,54232350,1,"[54232350, 1735803, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8088,12,887,12,54232350,1,"[54232350, 1737454, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8089,12,888,12,54232350,1,"[54232350, 1739104, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8090,12,889,12,54232350,1,"[54232350, 1740753, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8091,12,890,12,54232350,1,"[54232350, 1742402, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8092,12,891,12,54232350,1,"[54232350, 1744050, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8093,12,892,12,54232350,1,"[54232350, 1745698, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8094,12,893,12,54232350,1,"[54232350, 1747344, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8095,12,894,12,54232350,1,"[54232350, 1748990, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8096,12,895,12,54232350,1,"[54232350, 1750636, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8097,12,896,12,54232350,1,"[54232350, 1752280, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8098,12,897,12,54232350,1,"[54232350, 1753924, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8099,12,898,12,54232350,1,"[54232350, 1755567, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8100,12,899,12,54232350,1,"[54232350, 1757210, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8101,12,900,12,54232350,1,"[54232350, 1758852, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8102,12,901,12,54232350,1,"[54232350, 1760493, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8103,12,902,12,54232350,1,"[54232350, 1762133, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8104,12,903,12,54232350,1,"[54232350, 1763773, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8105,12,904,12,54232350,1,"[54232350, 1765412, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8106,12,905,12,54232350,1,"[54232350, 1767050, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8107,12,906,12,54232350,1,"[54232350, 1768688, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8108,12,907,12,54232350,1,"[54232350, 1770325, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8109,12,908,12,54232350,1,"[54232350, 1771961, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8110,12,909,12,54232350,1,"[54232350, 1773596, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8111,12,910,12,54232350,1,"[54232350, 1775231, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8112,12,911,12,54232350,1,"[54232350, 1776865, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8113,12,912,12,54232350,1,"[54232350, 1778499, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8114,12,913,12,54232350,1,"[54232350, 1780131, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8115,12,914,12,54232350,1,"[54232350, 1781763, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8116,12,915,12,54232350,1,"[54232350, 1783395, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8117,12,916,12,54232350,1,"[54232350, 1785025, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8118,12,917,12,54232350,1,"[54232350, 1786655, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8119,12,918,12,54232350,1,"[54232350, 1788284, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8120,12,919,12,54232350,1,"[54232350, 1789913, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8121,12,920,12,54232350,1,"[54232350, 1791541, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8122,12,921,12,54232350,1,"[54232350, 1793168, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8123,12,922,12,54232350,1,"[54232350, 1794794, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8124,12,923,12,54232350,1,"[54232350, 1796420, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8125,12,924,12,54232350,1,"[54232350, 1798045, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8126,12,925,12,54232350,1,"[54232350, 1799669, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8127,12,926,12,54232350,1,"[54232350, 1801293, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8128,12,927,12,54232350,1,"[54232350, 1802916, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8129,12,928,12,54232350,1,"[54232350, 1804538, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8130,12,929,12,54232350,1,"[54232350, 1806159, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8131,12,930,12,54232350,1,"[54232350, 1807780, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8132,12,931,12,54232350,1,"[54232350, 1809400, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8133,12,932,12,54232350,1,"[54232350, 1811020, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8134,12,933,12,54232350,1,"[54232350, 1812638, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8135,12,934,12,54232350,1,"[54232350, 1814256, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8136,12,935,12,54232350,1,"[54232350, 1815874, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8137,12,936,12,54232350,1,"[54232350, 1817490, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8138,12,937,12,54232350,1,"[54232350, 1819106, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8139,12,938,12,54232350,1,"[54232350, 1820721, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8140,12,939,12,54232350,1,"[54232350, 1822336, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8141,12,940,12,54232350,1,"[54232350, 1823950, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8142,12,941,12,54232350,1,"[54232350, 1825563, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8143,12,942,12,54232350,1,"[54232350, 1827175, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8144,12,943,12,54232350,1,"[54232350, 1828787, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8145,12,944,12,54232350,1,"[54232350, 1830398, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8146,12,945,12,54232350,1,"[54232350, 1832008, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8147,12,946,12,54232350,1,"[54232350, 1833618, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8148,12,947,12,54232350,1,"[54232350, 1835227, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8149,12,948,12,54232350,1,"[54232350, 1836835, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8150,12,949,12,54232350,1,"[54232350, 1838442, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8151,12,950,12,54232350,1,"[54232350, 1840049, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8152,12,951,12,54232350,1,"[54232350, 1841655, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8153,12,952,12,54232350,1,"[54232350, 1843261, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8154,12,953,12,54232350,1,"[54232350, 1844865, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8155,12,954,12,54232350,1,"[54232350, 1846469, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8156,12,955,12,54232350,1,"[54232350, 1848073, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8157,12,956,12,54232350,1,"[54232350, 1849675, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8158,12,957,12,54232350,1,"[54232350, 1851277, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8159,12,958,12,54232350,1,"[54232350, 1852878, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8160,12,959,12,54232350,1,"[54232350, 1854479, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8161,12,960,12,54232350,1,"[54232350, 1856079, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8162,12,961,12,54232350,1,"[54232350, 1857678, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8163,12,962,12,54232350,1,"[54232350, 1859276, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8164,12,963,12,54232350,1,"[54232350, 1860874, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8165,12,964,12,54232350,1,"[54232350, 1862471, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8166,12,965,12,54232350,1,"[54232350, 1864067, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8167,12,966,12,54232350,1,"[54232350, 1865663, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8168,12,967,12,54232350,1,"[54232350, 1867258, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8169,12,968,12,54232350,1,"[54232350, 1868852, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8170,12,969,12,54232350,1,"[54232350, 1870445, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8171,12,970,12,54232350,1,"[54232350, 1872038, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8172,12,971,12,54232350,1,"[54232350, 1873630, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8173,12,972,12,54232350,1,"[54232350, 1875222, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8174,12,973,12,54232350,1,"[54232350, 1876812, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8175,12,974,12,54232350,1,"[54232350, 1878402, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8176,12,975,12,54232350,1,"[54232350, 1879992, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8177,12,976,12,54232350,1,"[54232350, 1881580, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8178,12,977,12,54232350,1,"[54232350, 1883168, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8179,12,978,12,54232350,1,"[54232350, 1884755, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8180,12,979,12,54232350,1,"[54232350, 1886342, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8181,12,980,12,54232350,1,"[54232350, 1887928, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8182,12,981,12,54232350,1,"[54232350, 1889513, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8183,12,982,12,54232350,1,"[54232350, 1891097, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8184,12,983,12,54232350,1,"[54232350, 1892681, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8185,12,984,12,54232350,1,"[54232350, 1894264, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8186,12,985,12,54232350,1,"[54232350, 1895846, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8187,12,986,12,54232350,1,"[54232350, 1897428, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8188,12,987,12,54232350,1,"[54232350, 1899009, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8189,12,988,12,54232350,1,"[54232350, 1900589, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8190,12,989,12,54232350,1,"[54232350, 1902168, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8191,12,990,12,54232350,1,"[54232350, 1903747, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8192,12,991,12,54232350,1,"[54232350, 1905325, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8193,12,992,12,54232350,1,"[54232350, 1906903, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8194,12,993,12,54232350,1,"[54232350, 1908479, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8195,12,994,12,54232350,1,"[54232350, 1910055, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8196,12,995,12,54232350,1,"[54232350, 1911631, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8197,12,996,12,54232350,1,"[54232350, 1913205, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8198,12,997,12,54232350,1,"[54232350, 1914779, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8199,12,998,12,54232350,1,"[54232350, 1916352, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8200,12,999,12,54232350,1,"[54232350, 1917925, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8201,12,1000,12,54232350,1,"[54232350, 1919497, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8202,12,1001,12,54232350,1,"[54232350, 1921068, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8203,12,1002,12,54232350,1,"[54232350, 1922638, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8204,12,1003,12,54232350,1,"[54232350, 1924208, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8205,12,1004,12,54232350,1,"[54232350, 1925777, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8206,12,1005,12,54232350,1,"[54232350, 1927345, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8207,12,1006,12,54232350,1,"[54232350, 1928913, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8208,12,1007,12,54232350,1,"[54232350, 1930480, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8209,12,1008,12,54232350,1,"[54232350, 1932046, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8210,12,1009,12,54232350,1,"[54232350, 1933611, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8211,12,1010,12,54232350,1,"[54232350, 1935176, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8212,12,1011,12,54232350,1,"[54232350, 1936740, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8213,12,1012,12,54232350,1,"[54232350, 1938304, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8214,12,1013,12,54232350,1,"[54232350, 1939866, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8215,12,1014,12,54232350,1,"[54232350, 1941428, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8216,12,1015,12,54232350,1,"[54232350, 1942990, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8217,12,1016,12,54232350,1,"[54232350, 1944550, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8218,12,1017,12,54232350,1,"[54232350, 1946110, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8219,12,1018,12,54232350,1,"[54232350, 1947669, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8220,12,1019,12,54232350,1,"[54232350, 1949228, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8221,12,1020,12,54232350,1,"[54232350, 1950786, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8222,12,1021,12,54232350,1,"[54232350, 1952343, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8223,12,1022,12,54232350,1,"[54232350, 1953899, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8224,12,1023,12,54232350,1,"[54232350, 1955455, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8225,12,1024,12,54232350,1,"[54232350, 1957010, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8226,12,1025,12,54232350,1,"[54232350, 1958564, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8227,12,1026,12,54232350,1,"[54232350, 1960118, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8228,12,1027,12,54232350,1,"[54232350, 1961671, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8229,12,1028,12,54232350,1,"[54232350, 1963223, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8230,12,1029,12,54232350,1,"[54232350, 1964774, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8231,12,1030,12,54232350,1,"[54232350, 1966325, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8232,12,1031,12,54232350,1,"[54232350, 1967875, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8233,12,1032,12,54232350,1,"[54232350, 1969425, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8234,12,1033,12,54232350,1,"[54232350, 1970973, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8235,12,1034,12,54232350,1,"[54232350, 1972521, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8236,12,1035,12,54232350,1,"[54232350, 1974069, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8237,12,1036,12,54232350,1,"[54232350, 1975615, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8238,12,1037,12,54232350,1,"[54232350, 1977161, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8239,12,1038,12,54232350,1,"[54232350, 1978706, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8240,12,1039,12,54232350,1,"[54232350, 1980251, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8241,12,1040,12,54232350,1,"[54232350, 1981795, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8242,12,1041,12,54232350,1,"[54232350, 1983338, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8243,12,1042,12,54232350,1,"[54232350, 1984880, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8244,12,1043,12,54232350,1,"[54232350, 1986422, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8245,12,1044,12,54232350,1,"[54232350, 1987963, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8246,12,1045,12,54232350,1,"[54232350, 1989503, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8247,12,1046,12,54232350,1,"[54232350, 1991043, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8248,12,1047,12,54232350,1,"[54232350, 1992582, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8249,12,1048,12,54232350,1,"[54232350, 1994120, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8250,12,1049,12,54232350,1,"[54232350, 1995657, 6, False]",54232350,54232349,1995868,54232351,False,True,True,False,46875,4369,3615490,2510,2007,True,True,True,False,False,False,False -8251,13,0,13,54232351,2,"[54232350, 1997194, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8252,13,1,13,54232351,2,"[54232350, 1998730, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8253,13,2,13,54232351,2,"[54232351, 266, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8254,13,3,13,54232351,2,"[54232351, 1800, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8255,13,4,13,54232351,2,"[54232351, 3334, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8256,13,5,13,54232351,2,"[54232351, 4868, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8257,13,6,13,54232351,2,"[54232351, 6400, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8258,13,7,13,54232351,2,"[54232351, 7932, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8259,13,8,13,54232351,2,"[54232351, 9463, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8260,13,9,13,54232351,2,"[54232351, 10994, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8261,13,10,13,54232351,2,"[54232351, 12524, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8262,13,11,13,54232351,2,"[54232351, 14053, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8263,13,12,13,54232351,2,"[54232351, 15581, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8264,13,13,13,54232351,2,"[54232351, 17109, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8265,13,14,13,54232351,2,"[54232351, 18636, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8266,13,15,13,54232351,2,"[54232351, 20162, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8267,13,16,13,54232351,2,"[54232351, 21688, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8268,13,17,13,54232351,2,"[54232351, 23213, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8269,13,18,13,54232351,2,"[54232351, 24737, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8270,13,19,13,54232351,2,"[54232351, 26260, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8271,13,20,13,54232351,2,"[54232351, 27783, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8272,13,21,13,54232351,2,"[54232351, 29305, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8273,13,22,13,54232351,2,"[54232351, 30827, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8274,13,23,13,54232351,2,"[54232351, 32347, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8275,13,24,13,54232351,2,"[54232351, 33867, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8276,13,25,13,54232351,2,"[54232351, 35387, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8277,13,26,13,54232351,2,"[54232351, 36905, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8278,13,27,13,54232351,2,"[54232351, 38423, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8279,13,28,13,54232351,2,"[54232351, 39940, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8280,13,29,13,54232351,2,"[54232351, 41457, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8281,13,30,13,54232351,2,"[54232351, 42973, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8282,13,31,13,54232351,2,"[54232351, 44488, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8283,13,32,13,54232351,2,"[54232351, 46002, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8284,13,33,13,54232351,2,"[54232351, 47516, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8285,13,34,13,54232351,2,"[54232351, 49029, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8286,13,35,13,54232351,2,"[54232351, 50541, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8287,13,36,13,54232351,2,"[54232351, 52053, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8288,13,37,13,54232351,2,"[54232351, 53564, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8289,13,38,13,54232351,2,"[54232351, 55074, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8290,13,39,13,54232351,2,"[54232351, 56583, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8291,13,40,13,54232351,2,"[54232351, 58092, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8292,13,41,13,54232351,2,"[54232351, 59600, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8293,13,42,13,54232351,2,"[54232351, 61108, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8294,13,43,13,54232351,2,"[54232351, 62614, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8295,13,44,13,54232351,2,"[54232351, 64120, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8296,13,45,13,54232351,2,"[54232351, 65626, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8297,13,46,13,54232351,2,"[54232351, 67130, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8298,13,47,13,54232351,2,"[54232351, 68634, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8299,13,48,13,54232351,2,"[54232351, 70137, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8300,13,49,13,54232351,2,"[54232351, 71640, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8301,13,50,13,54232351,2,"[54232351, 73142, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8302,13,51,13,54232351,2,"[54232351, 74643, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8303,13,52,13,54232351,2,"[54232351, 76143, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8304,13,53,13,54232351,2,"[54232351, 77643, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8305,13,54,13,54232351,2,"[54232351, 79142, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8306,13,55,13,54232351,2,"[54232351, 80640, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8307,13,56,13,54232351,2,"[54232351, 82138, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8308,13,57,13,54232351,2,"[54232351, 83635, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8309,13,58,13,54232351,2,"[54232351, 85131, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8310,13,59,13,54232351,2,"[54232351, 86626, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8311,13,60,13,54232351,2,"[54232351, 88121, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8312,13,61,13,54232351,2,"[54232351, 89615, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8313,13,62,13,54232351,2,"[54232351, 91109, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8314,13,63,13,54232351,2,"[54232351, 92601, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8315,13,64,13,54232351,2,"[54232351, 94093, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8316,13,65,13,54232351,2,"[54232351, 95585, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8317,13,66,13,54232351,2,"[54232351, 97075, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8318,13,67,13,54232351,2,"[54232351, 98565, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8319,13,68,13,54232351,2,"[54232351, 100054, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8320,13,69,13,54232351,2,"[54232351, 101543, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8321,13,70,13,54232351,2,"[54232351, 103031, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8322,13,71,13,54232351,2,"[54232351, 104518, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8323,13,72,13,54232351,2,"[54232351, 106004, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8324,13,73,13,54232351,2,"[54232351, 107490, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8325,13,74,13,54232351,2,"[54232351, 108975, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8326,13,75,13,54232351,2,"[54232351, 110459, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8327,13,76,13,54232351,2,"[54232351, 111943, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8328,13,77,13,54232351,2,"[54232351, 113426, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8329,13,78,13,54232351,2,"[54232351, 114908, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8330,13,79,13,54232351,2,"[54232351, 116389, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8331,13,80,13,54232351,2,"[54232351, 117870, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8332,13,81,13,54232351,2,"[54232351, 119350, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8333,13,82,13,54232351,2,"[54232351, 120830, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8334,13,83,13,54232351,2,"[54232351, 122308, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8335,13,84,13,54232351,2,"[54232351, 123786, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8336,13,85,13,54232351,2,"[54232351, 125264, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8337,13,86,13,54232351,2,"[54232351, 126740, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8338,13,87,13,54232351,2,"[54232351, 128216, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8339,13,88,13,54232351,2,"[54232351, 129691, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8340,13,89,13,54232351,2,"[54232351, 131166, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8341,13,90,13,54232351,2,"[54232351, 132640, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8342,13,91,13,54232351,2,"[54232351, 134113, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8343,13,92,13,54232351,2,"[54232351, 135585, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8344,13,93,13,54232351,2,"[54232351, 137057, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8345,13,94,13,54232351,2,"[54232351, 138528, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8346,13,95,13,54232351,2,"[54232351, 139998, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8347,13,96,13,54232351,2,"[54232351, 141468, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8348,13,97,13,54232351,2,"[54232351, 142937, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8349,13,98,13,54232351,2,"[54232351, 144405, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8350,13,99,13,54232351,2,"[54232351, 145872, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8351,13,100,13,54232351,2,"[54232351, 147339, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8352,13,101,13,54232351,2,"[54232351, 148805, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8353,13,102,13,54232351,2,"[54232351, 150271, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8354,13,103,13,54232351,2,"[54232351, 151735, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8355,13,104,13,54232351,2,"[54232351, 153199, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8356,13,105,13,54232351,2,"[54232351, 154663, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8357,13,106,13,54232351,2,"[54232351, 156125, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8358,13,107,13,54232351,2,"[54232351, 157587, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8359,13,108,13,54232351,2,"[54232351, 159048, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8360,13,109,13,54232351,2,"[54232351, 160509, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8361,13,110,13,54232351,2,"[54232351, 161969, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8362,13,111,13,54232351,2,"[54232351, 163428, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8363,13,112,13,54232351,2,"[54232351, 164886, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8364,13,113,13,54232351,2,"[54232351, 166344, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8365,13,114,13,54232351,2,"[54232351, 167801, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8366,13,115,13,54232351,2,"[54232351, 169257, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8367,13,116,13,54232351,2,"[54232351, 170713, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8368,13,117,13,54232351,2,"[54232351, 172168, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8369,13,118,13,54232351,2,"[54232351, 173622, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8370,13,119,13,54232351,2,"[54232351, 175075, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8371,13,120,13,54232351,2,"[54232351, 176528, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8372,13,121,13,54232351,2,"[54232351, 177980, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8373,13,122,13,54232351,2,"[54232351, 179432, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8374,13,123,13,54232351,2,"[54232351, 180882, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8375,13,124,13,54232351,2,"[54232351, 182332, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8376,13,125,13,54232351,2,"[54232351, 183782, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8377,13,126,13,54232351,2,"[54232351, 185230, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8378,13,127,13,54232351,2,"[54232351, 186678, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8379,13,128,13,54232351,2,"[54232351, 188125, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8380,13,129,13,54232351,2,"[54232351, 189572, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8381,13,130,13,54232351,2,"[54232351, 191018, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8382,13,131,13,54232351,2,"[54232351, 192463, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8383,13,132,13,54232351,2,"[54232351, 193907, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8384,13,133,13,54232351,2,"[54232351, 195351, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8385,13,134,13,54232351,2,"[54232351, 196794, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8386,13,135,13,54232351,2,"[54232351, 198236, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8387,13,136,13,54232351,2,"[54232351, 199678, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8388,13,137,13,54232351,2,"[54232351, 201119, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8389,13,138,13,54232351,2,"[54232351, 202559, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8390,13,139,13,54232351,2,"[54232351, 203998, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8391,13,140,13,54232351,2,"[54232351, 205437, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8392,13,141,13,54232351,2,"[54232351, 206875, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8393,13,142,13,54232351,2,"[54232351, 208313, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8394,13,143,13,54232351,2,"[54232351, 209749, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8395,13,144,13,54232351,2,"[54232351, 211185, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8396,13,145,13,54232351,2,"[54232351, 212621, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8397,13,146,13,54232351,2,"[54232351, 214055, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8398,13,147,13,54232351,2,"[54232351, 215489, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8399,13,148,13,54232351,2,"[54232351, 216922, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8400,13,149,13,54232351,2,"[54232351, 218355, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8401,13,150,13,54232351,2,"[54232351, 219787, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8402,13,151,13,54232351,2,"[54232351, 221218, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8403,13,152,13,54232351,2,"[54232351, 222648, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8404,13,153,13,54232351,2,"[54232351, 224078, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8405,13,154,13,54232351,2,"[54232351, 225507, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8406,13,155,13,54232351,2,"[54232351, 226935, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8407,13,156,13,54232351,2,"[54232351, 228363, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8408,13,157,13,54232351,2,"[54232351, 229790, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8409,13,158,13,54232351,2,"[54232351, 231216, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8410,13,159,13,54232351,2,"[54232351, 232641, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8411,13,160,13,54232351,2,"[54232351, 234066, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8412,13,161,13,54232351,2,"[54232351, 235490, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8413,13,162,13,54232351,2,"[54232351, 236914, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8414,13,163,13,54232351,2,"[54232351, 238336, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8415,13,164,13,54232351,2,"[54232351, 239758, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8416,13,165,13,54232351,2,"[54232351, 241180, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8417,13,166,13,54232351,2,"[54232351, 242600, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8418,13,167,13,54232351,2,"[54232351, 244020, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8419,13,168,13,54232351,2,"[54232351, 245439, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8420,13,169,13,54232351,2,"[54232351, 246858, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8421,13,170,13,54232351,2,"[54232351, 248276, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8422,13,171,13,54232351,2,"[54232351, 249693, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8423,13,172,13,54232351,2,"[54232351, 251109, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8424,13,173,13,54232351,2,"[54232351, 252525, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8425,13,174,13,54232351,2,"[54232351, 253940, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8426,13,175,13,54232351,2,"[54232351, 255354, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8427,13,176,13,54232351,2,"[54232351, 256768, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8428,13,177,13,54232351,2,"[54232351, 258181, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8429,13,178,13,54232351,2,"[54232351, 259593, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8430,13,179,13,54232351,2,"[54232351, 261004, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8431,13,180,13,54232351,2,"[54232351, 262415, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8432,13,181,13,54232351,2,"[54232351, 263825, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8433,13,182,13,54232351,2,"[54232351, 265235, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8434,13,183,13,54232351,2,"[54232351, 266643, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8435,13,184,13,54232351,2,"[54232351, 268051, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8436,13,185,13,54232351,2,"[54232351, 269459, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8437,13,186,13,54232351,2,"[54232351, 270865, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8438,13,187,13,54232351,2,"[54232351, 272271, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8439,13,188,13,54232351,2,"[54232351, 273676, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8440,13,189,13,54232351,2,"[54232351, 275081, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8441,13,190,13,54232351,2,"[54232351, 276485, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8442,13,191,13,54232351,2,"[54232351, 277888, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8443,13,192,13,54232351,2,"[54232351, 279290, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8444,13,193,13,54232351,2,"[54232351, 280692, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8445,13,194,13,54232351,2,"[54232351, 282093, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8446,13,195,13,54232351,2,"[54232351, 283493, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8447,13,196,13,54232351,2,"[54232351, 284893, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8448,13,197,13,54232351,2,"[54232351, 286292, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8449,13,198,13,54232351,2,"[54232351, 287690, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8450,13,199,13,54232351,2,"[54232351, 289087, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8451,13,200,13,54232351,2,"[54232351, 290484, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8452,13,201,13,54232351,2,"[54232351, 291880, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8453,13,202,13,54232351,2,"[54232351, 293276, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8454,13,203,13,54232351,2,"[54232351, 294670, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8455,13,204,13,54232351,2,"[54232351, 296064, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8456,13,205,13,54232351,2,"[54232351, 297458, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8457,13,206,13,54232351,2,"[54232351, 298850, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8458,13,207,13,54232351,2,"[54232351, 300242, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8459,13,208,13,54232351,2,"[54232351, 301633, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8460,13,209,13,54232351,2,"[54232351, 303024, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8461,13,210,13,54232351,2,"[54232351, 304414, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8462,13,211,13,54232351,2,"[54232351, 305803, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8463,13,212,13,54232351,2,"[54232351, 307191, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8464,13,213,13,54232351,2,"[54232351, 308579, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8465,13,214,13,54232351,2,"[54232351, 309966, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8466,13,215,13,54232351,2,"[54232351, 311352, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8467,13,216,13,54232351,2,"[54232351, 312738, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8468,13,217,13,54232351,2,"[54232351, 314123, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8469,13,218,13,54232351,2,"[54232351, 315507, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8470,13,219,13,54232351,2,"[54232351, 316890, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8471,13,220,13,54232351,2,"[54232351, 318273, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8472,13,221,13,54232351,2,"[54232351, 319655, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8473,13,222,13,54232351,2,"[54232351, 321037, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8474,13,223,13,54232351,2,"[54232351, 322417, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8475,13,224,13,54232351,2,"[54232351, 323797, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8476,13,225,13,54232351,2,"[54232351, 325177, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8477,13,226,13,54232351,2,"[54232351, 326555, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8478,13,227,13,54232351,2,"[54232351, 327933, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8479,13,228,13,54232351,2,"[54232351, 329310, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8480,13,229,13,54232351,2,"[54232351, 330687, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8481,13,230,13,54232351,2,"[54232351, 332063, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8482,13,231,13,54232351,2,"[54232351, 333438, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8483,13,232,13,54232351,2,"[54232351, 334812, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8484,13,233,13,54232351,2,"[54232351, 336186, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8485,13,234,13,54232351,2,"[54232351, 337559, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8486,13,235,13,54232351,2,"[54232351, 338931, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8487,13,236,13,54232351,2,"[54232351, 340303, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8488,13,237,13,54232351,2,"[54232351, 341674, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8489,13,238,13,54232351,2,"[54232351, 343044, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8490,13,239,13,54232351,2,"[54232351, 344413, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8491,13,240,13,54232351,2,"[54232351, 345782, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8492,13,241,13,54232351,2,"[54232351, 347150, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8493,13,242,13,54232351,2,"[54232351, 348518, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8494,13,243,13,54232351,2,"[54232351, 349884, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8495,13,244,13,54232351,2,"[54232351, 351250, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8496,13,245,13,54232351,2,"[54232351, 352616, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8497,13,246,13,54232351,2,"[54232351, 353980, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8498,13,247,13,54232351,2,"[54232351, 355344, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8499,13,248,13,54232351,2,"[54232351, 356707, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8500,13,249,13,54232351,2,"[54232351, 358070, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8501,13,250,13,54232351,2,"[54232351, 359432, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8502,13,251,13,54232351,2,"[54232351, 360793, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8503,13,252,13,54232351,2,"[54232351, 362153, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8504,13,253,13,54232351,2,"[54232351, 363513, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8505,13,254,13,54232351,2,"[54232351, 364872, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8506,13,255,13,54232351,2,"[54232351, 366230, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8507,13,256,13,54232351,2,"[54232351, 367588, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8508,13,257,13,54232351,2,"[54232351, 368945, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8509,13,258,13,54232351,2,"[54232351, 370301, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8510,13,259,13,54232351,2,"[54232351, 371656, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8511,13,260,13,54232351,2,"[54232351, 373011, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8512,13,261,13,54232351,2,"[54232351, 374365, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8513,13,262,13,54232351,2,"[54232351, 375719, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8514,13,263,13,54232351,2,"[54232351, 377071, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8515,13,264,13,54232351,2,"[54232351, 378423, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8516,13,265,13,54232351,2,"[54232351, 379775, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8517,13,266,13,54232351,2,"[54232351, 381125, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8518,13,267,13,54232351,2,"[54232351, 382475, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8519,13,268,13,54232351,2,"[54232351, 383824, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8520,13,269,13,54232351,2,"[54232351, 385173, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8521,13,270,13,54232351,2,"[54232351, 386521, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8522,13,271,13,54232351,2,"[54232351, 387868, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8523,13,272,13,54232351,2,"[54232351, 389214, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8524,13,273,13,54232351,2,"[54232351, 390560, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8525,13,274,13,54232351,2,"[54232351, 391905, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8526,13,275,13,54232351,2,"[54232351, 393249, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8527,13,276,13,54232351,2,"[54232351, 394593, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8528,13,277,13,54232351,2,"[54232351, 395936, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8529,13,278,13,54232351,2,"[54232351, 397278, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8530,13,279,13,54232351,2,"[54232351, 398619, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8531,13,280,13,54232351,2,"[54232351, 399960, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8532,13,281,13,54232351,2,"[54232351, 401300, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8533,13,282,13,54232351,2,"[54232351, 402640, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8534,13,283,13,54232351,2,"[54232351, 403978, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8535,13,284,13,54232351,2,"[54232351, 405316, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8536,13,285,13,54232351,2,"[54232351, 406654, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8537,13,286,13,54232351,2,"[54232351, 407990, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8538,13,287,13,54232351,2,"[54232351, 409326, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8539,13,288,13,54232351,2,"[54232351, 410661, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8540,13,289,13,54232351,2,"[54232351, 411996, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8541,13,290,13,54232351,2,"[54232351, 413330, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8542,13,291,13,54232351,2,"[54232351, 414663, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8543,13,292,13,54232351,2,"[54232351, 415995, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8544,13,293,13,54232351,2,"[54232351, 417327, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8545,13,294,13,54232351,2,"[54232351, 418658, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8546,13,295,13,54232351,2,"[54232351, 419988, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8547,13,296,13,54232351,2,"[54232351, 421318, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8548,13,297,13,54232351,2,"[54232351, 422647, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8549,13,298,13,54232351,2,"[54232351, 423975, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8550,13,299,13,54232351,2,"[54232351, 425302, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8551,13,300,13,54232351,2,"[54232351, 426629, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8552,13,301,13,54232351,2,"[54232351, 427955, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8553,13,302,13,54232351,2,"[54232351, 429281, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8554,13,303,13,54232351,2,"[54232351, 430605, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8555,13,304,13,54232351,2,"[54232351, 431929, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8556,13,305,13,54232351,2,"[54232351, 433253, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8557,13,306,13,54232351,2,"[54232351, 434575, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8558,13,307,13,54232351,2,"[54232351, 435897, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8559,13,308,13,54232351,2,"[54232351, 437218, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8560,13,309,13,54232351,2,"[54232351, 438539, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8561,13,310,13,54232351,2,"[54232351, 439859, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8562,13,311,13,54232351,2,"[54232351, 441178, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8563,13,312,13,54232351,2,"[54232351, 442496, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8564,13,313,13,54232351,2,"[54232351, 443814, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8565,13,314,13,54232351,2,"[54232351, 445131, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8566,13,315,13,54232351,2,"[54232351, 446447, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8567,13,316,13,54232351,2,"[54232351, 447763, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8568,13,317,13,54232351,2,"[54232351, 449078, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8569,13,318,13,54232351,2,"[54232351, 450392, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8570,13,319,13,54232351,2,"[54232351, 451705, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8571,13,320,13,54232351,2,"[54232351, 453018, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8572,13,321,13,54232351,2,"[54232351, 454330, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8573,13,322,13,54232351,2,"[54232351, 455642, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8574,13,323,13,54232351,2,"[54232351, 456952, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8575,13,324,13,54232351,2,"[54232351, 458262, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8576,13,325,13,54232351,2,"[54232351, 459572, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8577,13,326,13,54232351,2,"[54232351, 460880, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8578,13,327,13,54232351,2,"[54232351, 462188, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8579,13,328,13,54232351,2,"[54232351, 463495, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8580,13,329,13,54232351,2,"[54232351, 464802, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8581,13,330,13,54232351,2,"[54232351, 466108, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8582,13,331,13,54232351,2,"[54232351, 467413, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8583,13,332,13,54232351,2,"[54232351, 468717, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8584,13,333,13,54232351,2,"[54232351, 470021, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8585,13,334,13,54232351,2,"[54232351, 471324, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8586,13,335,13,54232351,2,"[54232351, 472626, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8587,13,336,13,54232351,2,"[54232351, 473928, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8588,13,337,13,54232351,2,"[54232351, 475229, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8589,13,338,13,54232351,2,"[54232351, 476529, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8590,13,339,13,54232351,2,"[54232351, 477828, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8591,13,340,13,54232351,2,"[54232351, 479127, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8592,13,341,13,54232351,2,"[54232351, 480425, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8593,13,342,13,54232351,2,"[54232351, 481723, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8594,13,343,13,54232351,2,"[54232351, 483019, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8595,13,344,13,54232351,2,"[54232351, 484315, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8596,13,345,13,54232351,2,"[54232351, 485611, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8597,13,346,13,54232351,2,"[54232351, 486905, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8598,13,347,13,54232351,2,"[54232351, 488199, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8599,13,348,13,54232351,2,"[54232351, 489492, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8600,13,349,13,54232351,2,"[54232351, 490785, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8601,13,350,13,54232351,2,"[54232351, 492077, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8602,13,351,13,54232351,2,"[54232351, 493368, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8603,13,352,13,54232351,2,"[54232351, 494658, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8604,13,353,13,54232351,2,"[54232351, 495948, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8605,13,354,13,54232351,2,"[54232351, 497237, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8606,13,355,13,54232351,2,"[54232351, 498525, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8607,13,356,13,54232351,2,"[54232351, 499813, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8608,13,357,13,54232351,2,"[54232351, 501100, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8609,13,358,13,54232351,2,"[54232351, 502386, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8610,13,359,13,54232351,2,"[54232351, 503671, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8611,13,360,13,54232351,2,"[54232351, 504956, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8612,13,361,13,54232351,2,"[54232351, 506240, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8613,13,362,13,54232351,2,"[54232351, 507524, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8614,13,363,13,54232351,2,"[54232351, 508806, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8615,13,364,13,54232351,2,"[54232351, 510088, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8616,13,365,13,54232351,2,"[54232351, 511370, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8617,13,366,13,54232351,2,"[54232351, 512650, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8618,13,367,13,54232351,2,"[54232351, 513930, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8619,13,368,13,54232351,2,"[54232351, 515209, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8620,13,369,13,54232351,2,"[54232351, 516488, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8621,13,370,13,54232351,2,"[54232351, 517766, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8622,13,371,13,54232351,2,"[54232351, 519043, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8623,13,372,13,54232351,2,"[54232351, 520319, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8624,13,373,13,54232351,2,"[54232351, 521595, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8625,13,374,13,54232351,2,"[54232351, 522870, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8626,13,375,13,54232351,2,"[54232351, 524144, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8627,13,376,13,54232351,2,"[54232351, 525418, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8628,13,377,13,54232351,2,"[54232351, 526691, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8629,13,378,13,54232351,2,"[54232351, 527963, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8630,13,379,13,54232351,2,"[54232351, 529234, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8631,13,380,13,54232351,2,"[54232351, 530505, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8632,13,381,13,54232351,2,"[54232351, 531775, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8633,13,382,13,54232351,2,"[54232351, 533045, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8634,13,383,13,54232351,2,"[54232351, 534313, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8635,13,384,13,54232351,2,"[54232351, 535581, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8636,13,385,13,54232351,2,"[54232351, 536849, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8637,13,386,13,54232351,2,"[54232351, 538115, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8638,13,387,13,54232351,2,"[54232351, 539381, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8639,13,388,13,54232351,2,"[54232351, 540646, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8640,13,389,13,54232351,2,"[54232351, 541911, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8641,13,390,13,54232351,2,"[54232351, 543175, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8642,13,391,13,54232351,2,"[54232351, 544438, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8643,13,392,13,54232351,2,"[54232351, 545700, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8644,13,393,13,54232351,2,"[54232351, 546962, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8645,13,394,13,54232351,2,"[54232351, 548223, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8646,13,395,13,54232351,2,"[54232351, 549483, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8647,13,396,13,54232351,2,"[54232351, 550743, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8648,13,397,13,54232351,2,"[54232351, 552002, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8649,13,398,13,54232351,2,"[54232351, 553260, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8650,13,399,13,54232351,2,"[54232351, 554517, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8651,13,400,13,54232351,2,"[54232351, 555774, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8652,13,401,13,54232351,2,"[54232351, 557030, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8653,13,402,13,54232351,2,"[54232351, 558286, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8654,13,403,13,54232351,2,"[54232351, 559540, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8655,13,404,13,54232351,2,"[54232351, 560794, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8656,13,405,13,54232351,2,"[54232351, 562048, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8657,13,406,13,54232351,2,"[54232351, 563300, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8658,13,407,13,54232351,2,"[54232351, 564552, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8659,13,408,13,54232351,2,"[54232351, 565803, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8660,13,409,13,54232351,2,"[54232351, 567054, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8661,13,410,13,54232351,2,"[54232351, 568304, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8662,13,411,13,54232351,2,"[54232351, 569553, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8663,13,412,13,54232351,2,"[54232351, 570801, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8664,13,413,13,54232351,2,"[54232351, 572049, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8665,13,414,13,54232351,2,"[54232351, 573296, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8666,13,415,13,54232351,2,"[54232351, 574542, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8667,13,416,13,54232351,2,"[54232351, 575788, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8668,13,417,13,54232351,2,"[54232351, 577033, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8669,13,418,13,54232351,2,"[54232351, 578277, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8670,13,419,13,54232351,2,"[54232351, 579520, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8671,13,420,13,54232351,2,"[54232351, 580763, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8672,13,421,13,54232351,2,"[54232351, 582005, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8673,13,422,13,54232351,2,"[54232351, 583247, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8674,13,423,13,54232351,2,"[54232351, 584487, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8675,13,424,13,54232351,2,"[54232351, 585727, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8676,13,425,13,54232351,2,"[54232351, 586967, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8677,13,426,13,54232351,2,"[54232351, 588205, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8678,13,427,13,54232351,2,"[54232351, 589443, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8679,13,428,13,54232351,2,"[54232351, 590680, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8680,13,429,13,54232351,2,"[54232351, 591917, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8681,13,430,13,54232351,2,"[54232351, 593153, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8682,13,431,13,54232351,2,"[54232351, 594388, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8683,13,432,13,54232351,2,"[54232351, 595622, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8684,13,433,13,54232351,2,"[54232351, 596856, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8685,13,434,13,54232351,2,"[54232351, 598089, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8686,13,435,13,54232351,2,"[54232351, 599321, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8687,13,436,13,54232351,2,"[54232351, 600553, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8688,13,437,13,54232351,2,"[54232351, 601784, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8689,13,438,13,54232351,2,"[54232351, 603014, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8690,13,439,13,54232351,2,"[54232351, 604243, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8691,13,440,13,54232351,2,"[54232351, 605472, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8692,13,441,13,54232351,2,"[54232351, 606700, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8693,13,442,13,54232351,2,"[54232351, 607928, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8694,13,443,13,54232351,2,"[54232351, 609154, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8695,13,444,13,54232351,2,"[54232351, 610380, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8696,13,445,13,54232351,2,"[54232351, 611606, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8697,13,446,13,54232351,2,"[54232351, 612830, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8698,13,447,13,54232351,2,"[54232351, 614054, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8699,13,448,13,54232351,2,"[54232351, 615277, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8700,13,449,13,54232351,2,"[54232351, 616500, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8701,13,450,13,54232351,2,"[54232351, 617722, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8702,13,451,13,54232351,2,"[54232351, 618943, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8703,13,452,13,54232351,2,"[54232351, 620163, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8704,13,453,13,54232351,2,"[54232351, 621383, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8705,13,454,13,54232351,2,"[54232351, 622602, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8706,13,455,13,54232351,2,"[54232351, 623820, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8707,13,456,13,54232351,2,"[54232351, 625038, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8708,13,457,13,54232351,2,"[54232351, 626255, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8709,13,458,13,54232351,2,"[54232351, 627471, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8710,13,459,13,54232351,2,"[54232351, 628686, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8711,13,460,13,54232351,2,"[54232351, 629901, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8712,13,461,13,54232351,2,"[54232351, 631115, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8713,13,462,13,54232351,2,"[54232351, 632329, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8714,13,463,13,54232351,2,"[54232351, 633541, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8715,13,464,13,54232351,2,"[54232351, 634753, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8716,13,465,13,54232351,2,"[54232351, 635965, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8717,13,466,13,54232351,2,"[54232351, 637175, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8718,13,467,13,54232351,2,"[54232351, 638385, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8719,13,468,13,54232351,2,"[54232351, 639594, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8720,13,469,13,54232351,2,"[54232351, 640803, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8721,13,470,13,54232351,2,"[54232351, 642011, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8722,13,471,13,54232351,2,"[54232351, 643218, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8723,13,472,13,54232351,2,"[54232351, 644424, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8724,13,473,13,54232351,2,"[54232351, 645630, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8725,13,474,13,54232351,2,"[54232351, 646835, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8726,13,475,13,54232351,2,"[54232351, 648039, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8727,13,476,13,54232351,2,"[54232351, 649243, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8728,13,477,13,54232351,2,"[54232351, 650446, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8729,13,478,13,54232351,2,"[54232351, 651648, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8730,13,479,13,54232351,2,"[54232351, 652849, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8731,13,480,13,54232351,2,"[54232351, 654050, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8732,13,481,13,54232351,2,"[54232351, 655250, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8733,13,482,13,54232351,2,"[54232351, 656450, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8734,13,483,13,54232351,2,"[54232351, 657648, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8735,13,484,13,54232351,2,"[54232351, 658846, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8736,13,485,13,54232351,2,"[54232351, 660044, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8737,13,486,13,54232351,2,"[54232351, 661240, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8738,13,487,13,54232351,2,"[54232351, 662436, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8739,13,488,13,54232351,2,"[54232351, 663631, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8740,13,489,13,54232351,2,"[54232351, 664826, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8741,13,490,13,54232351,2,"[54232351, 666020, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8742,13,491,13,54232351,2,"[54232351, 667213, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8743,13,492,13,54232351,2,"[54232351, 668405, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8744,13,493,13,54232351,2,"[54232351, 669597, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8745,13,494,13,54232351,2,"[54232351, 670788, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8746,13,495,13,54232351,2,"[54232351, 671978, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8747,13,496,13,54232351,2,"[54232351, 673168, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8748,13,497,13,54232351,2,"[54232351, 674357, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8749,13,498,13,54232351,2,"[54232351, 675545, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8750,13,499,13,54232351,2,"[54232351, 676732, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8751,13,500,13,54232351,2,"[54232351, 677919, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8752,13,501,13,54232351,2,"[54232351, 679105, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8753,13,502,13,54232351,2,"[54232351, 680291, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8754,13,503,13,54232351,2,"[54232351, 681475, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8755,13,504,13,54232351,2,"[54232351, 682659, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8756,13,505,13,54232351,2,"[54232351, 683843, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8757,13,506,13,54232351,2,"[54232351, 685025, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8758,13,507,13,54232351,2,"[54232351, 686207, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8759,13,508,13,54232351,2,"[54232351, 687388, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8760,13,509,13,54232351,2,"[54232351, 688569, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8761,13,510,13,54232351,2,"[54232351, 689749, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8762,13,511,13,54232351,2,"[54232351, 690928, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8763,13,512,13,54232351,2,"[54232351, 692106, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8764,13,513,13,54232351,2,"[54232351, 693284, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8765,13,514,13,54232351,2,"[54232351, 694461, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8766,13,515,13,54232351,2,"[54232351, 695637, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8767,13,516,13,54232351,2,"[54232351, 696813, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8768,13,517,13,54232351,2,"[54232351, 697988, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8769,13,518,13,54232351,2,"[54232351, 699162, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8770,13,519,13,54232351,2,"[54232351, 700335, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8771,13,520,13,54232351,2,"[54232351, 701508, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8772,13,521,13,54232351,2,"[54232351, 702680, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8773,13,522,13,54232351,2,"[54232351, 703852, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8774,13,523,13,54232351,2,"[54232351, 705022, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8775,13,524,13,54232351,2,"[54232351, 706192, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8776,13,525,13,54232351,2,"[54232351, 707362, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8777,13,526,13,54232351,2,"[54232351, 708530, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8778,13,527,13,54232351,2,"[54232351, 709698, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8779,13,528,13,54232351,2,"[54232351, 710865, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8780,13,529,13,54232351,2,"[54232351, 712032, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8781,13,530,13,54232351,2,"[54232351, 713198, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8782,13,531,13,54232351,2,"[54232351, 714363, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8783,13,532,13,54232351,2,"[54232351, 715527, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8784,13,533,13,54232351,2,"[54232351, 716691, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8785,13,534,13,54232351,2,"[54232351, 717854, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8786,13,535,13,54232351,2,"[54232351, 719016, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8787,13,536,13,54232351,2,"[54232351, 720178, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8788,13,537,13,54232351,2,"[54232351, 721339, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8789,13,538,13,54232351,2,"[54232351, 722499, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8790,13,539,13,54232351,2,"[54232351, 723658, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8791,13,540,13,54232351,2,"[54232351, 724817, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8792,13,541,13,54232351,2,"[54232351, 725975, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8793,13,542,13,54232351,2,"[54232351, 727133, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8794,13,543,13,54232351,2,"[54232351, 728289, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8795,13,544,13,54232351,2,"[54232351, 729445, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8796,13,545,13,54232351,2,"[54232351, 730601, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8797,13,546,13,54232351,2,"[54232351, 731755, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8798,13,547,13,54232351,2,"[54232351, 732909, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8799,13,548,13,54232351,2,"[54232351, 734062, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8800,13,549,13,54232351,2,"[54232351, 735215, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8801,13,550,13,54232351,2,"[54232351, 736367, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8802,13,551,13,54232351,2,"[54232351, 737518, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8803,13,552,13,54232351,2,"[54232351, 738668, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8804,13,553,13,54232351,2,"[54232351, 739818, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8805,13,554,13,54232351,2,"[54232351, 740967, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8806,13,555,13,54232351,2,"[54232351, 742115, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8807,13,556,13,54232351,2,"[54232351, 743263, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8808,13,557,13,54232351,2,"[54232351, 744410, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8809,13,558,13,54232351,2,"[54232351, 745556, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8810,13,559,13,54232351,2,"[54232351, 746701, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8811,13,560,13,54232351,2,"[54232351, 747846, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8812,13,561,13,54232351,2,"[54232351, 748990, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8813,13,562,13,54232351,2,"[54232351, 750134, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8814,13,563,13,54232351,2,"[54232351, 751276, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8815,13,564,13,54232351,2,"[54232351, 752418, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8816,13,565,13,54232351,2,"[54232351, 753560, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8817,13,566,13,54232351,2,"[54232351, 754700, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8818,13,567,13,54232351,2,"[54232351, 755840, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8819,13,568,13,54232351,2,"[54232351, 756979, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8820,13,569,13,54232351,2,"[54232351, 758118, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8821,13,570,13,54232351,2,"[54232351, 759256, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8822,13,571,13,54232351,2,"[54232351, 760393, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8823,13,572,13,54232351,2,"[54232351, 761529, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8824,13,573,13,54232351,2,"[54232351, 762665, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8825,13,574,13,54232351,2,"[54232351, 763800, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8826,13,575,13,54232351,2,"[54232351, 764934, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8827,13,576,13,54232351,2,"[54232351, 766068, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8828,13,577,13,54232351,2,"[54232351, 767201, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8829,13,578,13,54232351,2,"[54232351, 768333, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8830,13,579,13,54232351,2,"[54232351, 769464, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8831,13,580,13,54232351,2,"[54232351, 770595, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8832,13,581,13,54232351,2,"[54232351, 771725, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8833,13,582,13,54232351,2,"[54232351, 772855, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8834,13,583,13,54232351,2,"[54232351, 773983, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8835,13,584,13,54232351,2,"[54232351, 775111, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8836,13,585,13,54232351,2,"[54232351, 776239, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8837,13,586,13,54232351,2,"[54232351, 777365, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8838,13,587,13,54232351,2,"[54232351, 778491, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8839,13,588,13,54232351,2,"[54232351, 779616, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8840,13,589,13,54232351,2,"[54232351, 780741, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8841,13,590,13,54232351,2,"[54232351, 781865, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8842,13,591,13,54232351,2,"[54232351, 782988, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8843,13,592,13,54232351,2,"[54232351, 784110, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8844,13,593,13,54232351,2,"[54232351, 785232, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8845,13,594,13,54232351,2,"[54232351, 786353, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8846,13,595,13,54232351,2,"[54232351, 787473, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8847,13,596,13,54232351,2,"[54232351, 788593, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8848,13,597,13,54232351,2,"[54232351, 789712, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8849,13,598,13,54232351,2,"[54232351, 790830, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8850,13,599,13,54232351,2,"[54232351, 791947, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8851,13,600,13,54232351,2,"[54232351, 793064, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8852,13,601,13,54232351,2,"[54232351, 794180, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8853,13,602,13,54232351,2,"[54232351, 795296, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8854,13,603,13,54232351,2,"[54232351, 796410, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8855,13,604,13,54232351,2,"[54232351, 797524, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8856,13,605,13,54232351,2,"[54232351, 798638, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8857,13,606,13,54232351,2,"[54232351, 799750, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8858,13,607,13,54232351,2,"[54232351, 800862, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8859,13,608,13,54232351,2,"[54232351, 801973, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8860,13,609,13,54232351,2,"[54232351, 803084, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8861,13,610,13,54232351,2,"[54232351, 804194, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8862,13,611,13,54232351,2,"[54232351, 805303, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8863,13,612,13,54232351,2,"[54232351, 806411, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8864,13,613,13,54232351,2,"[54232351, 807519, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8865,13,614,13,54232351,2,"[54232351, 808626, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8866,13,615,13,54232351,2,"[54232351, 809732, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8867,13,616,13,54232351,2,"[54232351, 810838, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8868,13,617,13,54232351,2,"[54232351, 811943, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8869,13,618,13,54232351,2,"[54232351, 813047, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8870,13,619,13,54232351,2,"[54232351, 814150, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8871,13,620,13,54232351,2,"[54232351, 815253, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8872,13,621,13,54232351,2,"[54232351, 816355, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8873,13,622,13,54232351,2,"[54232351, 817457, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8874,13,623,13,54232351,2,"[54232351, 818557, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8875,13,624,13,54232351,2,"[54232351, 819657, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8876,13,625,13,54232351,2,"[54232351, 820757, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8877,13,626,13,54232351,2,"[54232351, 821855, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8878,13,627,13,54232351,2,"[54232351, 822953, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8879,13,628,13,54232351,2,"[54232351, 824050, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8880,13,629,13,54232351,2,"[54232351, 825147, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8881,13,630,13,54232351,2,"[54232351, 826243, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8882,13,631,13,54232351,2,"[54232351, 827338, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8883,13,632,13,54232351,2,"[54232351, 828432, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8884,13,633,13,54232351,2,"[54232351, 829526, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8885,13,634,13,54232351,2,"[54232351, 830619, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8886,13,635,13,54232351,2,"[54232351, 831711, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8887,13,636,13,54232351,2,"[54232351, 832803, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8888,13,637,13,54232351,2,"[54232351, 833894, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8889,13,638,13,54232351,2,"[54232351, 834984, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8890,13,639,13,54232351,2,"[54232351, 836073, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8891,13,640,13,54232351,2,"[54232351, 837162, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8892,13,641,13,54232351,2,"[54232351, 838250, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8893,13,642,13,54232351,2,"[54232351, 839338, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8894,13,643,13,54232351,2,"[54232351, 840424, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8895,13,644,13,54232351,2,"[54232351, 841510, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8896,13,645,13,54232351,2,"[54232351, 842596, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8897,13,646,13,54232351,2,"[54232351, 843680, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8898,13,647,13,54232351,2,"[54232351, 844764, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8899,13,648,13,54232351,2,"[54232351, 845847, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8900,13,649,13,54232351,2,"[54232351, 846930, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8901,13,650,13,54232351,2,"[54232351, 848012, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8902,13,651,13,54232351,2,"[54232351, 849093, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8903,13,652,13,54232351,2,"[54232351, 850173, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8904,13,653,13,54232351,2,"[54232351, 851253, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8905,13,654,13,54232351,2,"[54232351, 852332, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8906,13,655,13,54232351,2,"[54232351, 853410, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8907,13,656,13,54232351,2,"[54232351, 854488, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8908,13,657,13,54232351,2,"[54232351, 855565, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8909,13,658,13,54232351,2,"[54232351, 856641, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8910,13,659,13,54232351,2,"[54232351, 857716, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8911,13,660,13,54232351,2,"[54232351, 858791, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8912,13,661,13,54232351,2,"[54232351, 859865, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8913,13,662,13,54232351,2,"[54232351, 860939, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8914,13,663,13,54232351,2,"[54232351, 862011, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8915,13,664,13,54232351,2,"[54232351, 863083, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8916,13,665,13,54232351,2,"[54232351, 864155, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8917,13,666,13,54232351,2,"[54232351, 865225, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8918,13,667,13,54232351,2,"[54232351, 866295, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8919,13,668,13,54232351,2,"[54232351, 867364, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8920,13,669,13,54232351,2,"[54232351, 868433, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8921,13,670,13,54232351,2,"[54232351, 869501, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8922,13,671,13,54232351,2,"[54232351, 870568, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8923,13,672,13,54232351,2,"[54232351, 871634, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8924,13,673,13,54232351,2,"[54232351, 872700, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8925,13,674,13,54232351,2,"[54232351, 873765, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8926,13,675,13,54232351,2,"[54232351, 874829, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8927,13,676,13,54232351,2,"[54232351, 875893, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8928,13,677,13,54232351,2,"[54232351, 876956, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8929,13,678,13,54232351,2,"[54232351, 878018, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8930,13,679,13,54232351,2,"[54232351, 879079, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8931,13,680,13,54232351,2,"[54232351, 880140, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8932,13,681,13,54232351,2,"[54232351, 881200, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8933,13,682,13,54232351,2,"[54232351, 882260, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8934,13,683,13,54232351,2,"[54232351, 883318, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8935,13,684,13,54232351,2,"[54232351, 884376, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8936,13,685,13,54232351,2,"[54232351, 885434, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8937,13,686,13,54232351,2,"[54232351, 886490, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8938,13,687,13,54232351,2,"[54232351, 887546, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8939,13,688,13,54232351,2,"[54232351, 888601, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8940,13,689,13,54232351,2,"[54232351, 889656, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8941,13,690,13,54232351,2,"[54232351, 890710, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8942,13,691,13,54232351,2,"[54232351, 891763, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8943,13,692,13,54232351,2,"[54232351, 892815, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8944,13,693,13,54232351,2,"[54232351, 893867, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8945,13,694,13,54232351,2,"[54232351, 894918, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8946,13,695,13,54232351,2,"[54232351, 895968, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8947,13,696,13,54232351,2,"[54232351, 897018, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8948,13,697,13,54232351,2,"[54232351, 898067, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8949,13,698,13,54232351,2,"[54232351, 899115, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8950,13,699,13,54232351,2,"[54232351, 900162, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8951,13,700,13,54232351,2,"[54232351, 901209, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8952,13,701,13,54232351,2,"[54232351, 902255, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8953,13,702,13,54232351,2,"[54232351, 903301, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8954,13,703,13,54232351,2,"[54232351, 904345, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8955,13,704,13,54232351,2,"[54232351, 905389, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8956,13,705,13,54232351,2,"[54232351, 906433, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8957,13,706,13,54232351,2,"[54232351, 907475, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8958,13,707,13,54232351,2,"[54232351, 908517, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8959,13,708,13,54232351,2,"[54232351, 909558, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8960,13,709,13,54232351,2,"[54232351, 910599, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8961,13,710,13,54232351,2,"[54232351, 911639, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8962,13,711,13,54232351,2,"[54232351, 912678, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8963,13,712,13,54232351,2,"[54232351, 913716, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8964,13,713,13,54232351,2,"[54232351, 914754, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8965,13,714,13,54232351,2,"[54232351, 915791, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8966,13,715,13,54232351,2,"[54232351, 916827, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8967,13,716,13,54232351,2,"[54232351, 917863, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8968,13,717,13,54232351,2,"[54232351, 918898, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8969,13,718,13,54232351,2,"[54232351, 919932, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8970,13,719,13,54232351,2,"[54232351, 920965, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8971,13,720,13,54232351,2,"[54232351, 921998, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8972,13,721,13,54232351,2,"[54232351, 923030, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8973,13,722,13,54232351,2,"[54232351, 924062, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8974,13,723,13,54232351,2,"[54232351, 925092, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8975,13,724,13,54232351,2,"[54232351, 926122, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8976,13,725,13,54232351,2,"[54232351, 927152, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8977,13,726,13,54232351,2,"[54232351, 928180, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8978,13,727,13,54232351,2,"[54232351, 929208, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8979,13,728,13,54232351,2,"[54232351, 930235, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8980,13,729,13,54232351,2,"[54232351, 931262, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8981,13,730,13,54232351,2,"[54232351, 932288, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8982,13,731,13,54232351,2,"[54232351, 933313, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8983,13,732,13,54232351,2,"[54232351, 934337, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8984,13,733,13,54232351,2,"[54232351, 935361, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8985,13,734,13,54232351,2,"[54232351, 936384, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8986,13,735,13,54232351,2,"[54232351, 937406, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8987,13,736,13,54232351,2,"[54232351, 938428, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8988,13,737,13,54232351,2,"[54232351, 939449, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8989,13,738,13,54232351,2,"[54232351, 940469, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8990,13,739,13,54232351,2,"[54232351, 941488, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8991,13,740,13,54232351,2,"[54232351, 942507, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8992,13,741,13,54232351,2,"[54232351, 943525, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8993,13,742,13,54232351,2,"[54232351, 944543, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8994,13,743,13,54232351,2,"[54232351, 945559, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8995,13,744,13,54232351,2,"[54232351, 946575, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8996,13,745,13,54232351,2,"[54232351, 947591, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8997,13,746,13,54232351,2,"[54232351, 948605, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8998,13,747,13,54232351,2,"[54232351, 949619, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -8999,13,748,13,54232351,2,"[54232351, 950632, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9000,13,749,13,54232351,2,"[54232351, 951645, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9001,13,750,13,54232351,2,"[54232351, 952657, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9002,13,751,13,54232351,2,"[54232351, 953668, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9003,13,752,13,54232351,2,"[54232351, 954678, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9004,13,753,13,54232351,2,"[54232351, 955688, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9005,13,754,13,54232351,2,"[54232351, 956697, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9006,13,755,13,54232351,2,"[54232351, 957705, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9007,13,756,13,54232351,2,"[54232351, 958713, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9008,13,757,13,54232351,2,"[54232351, 959720, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9009,13,758,13,54232351,2,"[54232351, 960726, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9010,13,759,13,54232351,2,"[54232351, 961731, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9011,13,760,13,54232351,2,"[54232351, 962736, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9012,13,761,13,54232351,2,"[54232351, 963740, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9013,13,762,13,54232351,2,"[54232351, 964744, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9014,13,763,13,54232351,2,"[54232351, 965746, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9015,13,764,13,54232351,2,"[54232351, 966748, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9016,13,765,13,54232351,2,"[54232351, 967750, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9017,13,766,13,54232351,2,"[54232351, 968750, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9018,13,767,13,54232351,2,"[54232351, 969750, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9019,13,768,13,54232351,2,"[54232351, 970749, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9020,13,769,13,54232351,2,"[54232351, 971748, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9021,13,770,13,54232351,2,"[54232351, 972746, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9022,13,771,13,54232351,2,"[54232351, 973743, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9023,13,772,13,54232351,2,"[54232351, 974739, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9024,13,773,13,54232351,2,"[54232351, 975735, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9025,13,774,13,54232351,2,"[54232351, 976730, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9026,13,775,13,54232351,2,"[54232351, 977724, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9027,13,776,13,54232351,2,"[54232351, 978718, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9028,13,777,13,54232351,2,"[54232351, 979711, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9029,13,778,13,54232351,2,"[54232351, 980703, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9030,13,779,13,54232351,2,"[54232351, 981694, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9031,13,780,13,54232351,2,"[54232351, 982685, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9032,13,781,13,54232351,2,"[54232351, 983675, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9033,13,782,13,54232351,2,"[54232351, 984665, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9034,13,783,13,54232351,2,"[54232351, 985653, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9035,13,784,13,54232351,2,"[54232351, 986641, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9036,13,785,13,54232351,2,"[54232351, 987629, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9037,13,786,13,54232351,2,"[54232351, 988615, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9038,13,787,13,54232351,2,"[54232351, 989601, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9039,13,788,13,54232351,2,"[54232351, 990586, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9040,13,789,13,54232351,2,"[54232351, 991571, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9041,13,790,13,54232351,2,"[54232351, 992555, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9042,13,791,13,54232351,2,"[54232351, 993538, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9043,13,792,13,54232351,2,"[54232351, 994520, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9044,13,793,13,54232351,2,"[54232351, 995502, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9045,13,794,13,54232351,2,"[54232351, 996483, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9046,13,795,13,54232351,2,"[54232351, 997463, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9047,13,796,13,54232351,2,"[54232351, 998443, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9048,13,797,13,54232351,2,"[54232351, 999422, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9049,13,798,13,54232351,2,"[54232351, 1000400, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9050,13,799,13,54232351,2,"[54232351, 1001377, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9051,13,800,13,54232351,2,"[54232351, 1002354, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9052,13,801,13,54232351,2,"[54232351, 1003330, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9053,13,802,13,54232351,2,"[54232351, 1004306, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9054,13,803,13,54232351,2,"[54232351, 1005280, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9055,13,804,13,54232351,2,"[54232351, 1006254, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9056,13,805,13,54232351,2,"[54232351, 1007228, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9057,13,806,13,54232351,2,"[54232351, 1008200, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9058,13,807,13,54232351,2,"[54232351, 1009172, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9059,13,808,13,54232351,2,"[54232351, 1010143, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9060,13,809,13,54232351,2,"[54232351, 1011114, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9061,13,810,13,54232351,2,"[54232351, 1012084, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9062,13,811,13,54232351,2,"[54232351, 1013053, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9063,13,812,13,54232351,2,"[54232351, 1014021, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9064,13,813,13,54232351,2,"[54232351, 1014989, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9065,13,814,13,54232351,2,"[54232351, 1015956, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9066,13,815,13,54232351,2,"[54232351, 1016922, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9067,13,816,13,54232351,2,"[54232351, 1017888, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9068,13,817,13,54232351,2,"[54232351, 1018853, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9069,13,818,13,54232351,2,"[54232351, 1019817, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9070,13,819,13,54232351,2,"[54232351, 1020780, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9071,13,820,13,54232351,2,"[54232351, 1021743, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9072,13,821,13,54232351,2,"[54232351, 1022705, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9073,13,822,13,54232351,2,"[54232351, 1023667, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9074,13,823,13,54232351,2,"[54232351, 1024627, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9075,13,824,13,54232351,2,"[54232351, 1025587, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9076,13,825,13,54232351,2,"[54232351, 1026547, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9077,13,826,13,54232351,2,"[54232351, 1027505, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9078,13,827,13,54232351,2,"[54232351, 1028463, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9079,13,828,13,54232351,2,"[54232351, 1029420, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9080,13,829,13,54232351,2,"[54232351, 1030377, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9081,13,830,13,54232351,2,"[54232351, 1031333, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9082,13,831,13,54232351,2,"[54232351, 1032288, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9083,13,832,13,54232351,2,"[54232351, 1033242, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9084,13,833,13,54232351,2,"[54232351, 1034196, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9085,13,834,13,54232351,2,"[54232351, 1035149, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9086,13,835,13,54232351,2,"[54232351, 1036101, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9087,13,836,13,54232351,2,"[54232351, 1037053, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9088,13,837,13,54232351,2,"[54232351, 1038004, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9089,13,838,13,54232351,2,"[54232351, 1038954, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9090,13,839,13,54232351,2,"[54232351, 1039903, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9091,13,840,13,54232351,2,"[54232351, 1040852, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9092,13,841,13,54232351,2,"[54232351, 1041800, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9093,13,842,13,54232351,2,"[54232351, 1042748, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9094,13,843,13,54232351,2,"[54232351, 1043694, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9095,13,844,13,54232351,2,"[54232351, 1044640, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9096,13,845,13,54232351,2,"[54232351, 1045586, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9097,13,846,13,54232351,2,"[54232351, 1046530, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9098,13,847,13,54232351,2,"[54232351, 1047474, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9099,13,848,13,54232351,2,"[54232351, 1048417, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9100,13,849,13,54232351,2,"[54232351, 1049360, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9101,13,850,13,54232351,2,"[54232351, 1050302, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9102,13,851,13,54232351,2,"[54232351, 1051243, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9103,13,852,13,54232351,2,"[54232351, 1052183, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9104,13,853,13,54232351,2,"[54232351, 1053123, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9105,13,854,13,54232351,2,"[54232351, 1054062, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9106,13,855,13,54232351,2,"[54232351, 1055000, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9107,13,856,13,54232351,2,"[54232351, 1055938, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9108,13,857,13,54232351,2,"[54232351, 1056875, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9109,13,858,13,54232351,2,"[54232351, 1057811, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9110,13,859,13,54232351,2,"[54232351, 1058746, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9111,13,860,13,54232351,2,"[54232351, 1059681, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9112,13,861,13,54232351,2,"[54232351, 1060615, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9113,13,862,13,54232351,2,"[54232351, 1061549, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9114,13,863,13,54232351,2,"[54232351, 1062481, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9115,13,864,13,54232351,2,"[54232351, 1063413, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9116,13,865,13,54232351,2,"[54232351, 1064345, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9117,13,866,13,54232351,2,"[54232351, 1065275, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9118,13,867,13,54232351,2,"[54232351, 1066205, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9119,13,868,13,54232351,2,"[54232351, 1067134, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9120,13,869,13,54232351,2,"[54232351, 1068063, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9121,13,870,13,54232351,2,"[54232351, 1068991, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9122,13,871,13,54232351,2,"[54232351, 1069918, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9123,13,872,13,54232351,2,"[54232351, 1070844, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9124,13,873,13,54232351,2,"[54232351, 1071770, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9125,13,874,13,54232351,2,"[54232351, 1072695, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9126,13,875,13,54232351,2,"[54232351, 1073619, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9127,13,876,13,54232351,2,"[54232351, 1074543, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9128,13,877,13,54232351,2,"[54232351, 1075466, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9129,13,878,13,54232351,2,"[54232351, 1076388, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9130,13,879,13,54232351,2,"[54232351, 1077309, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9131,13,880,13,54232351,2,"[54232351, 1078230, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9132,13,881,13,54232351,2,"[54232351, 1079150, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9133,13,882,13,54232351,2,"[54232351, 1080070, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9134,13,883,13,54232351,2,"[54232351, 1080988, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9135,13,884,13,54232351,2,"[54232351, 1081906, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9136,13,885,13,54232351,2,"[54232351, 1082824, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9137,13,886,13,54232351,2,"[54232351, 1083740, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9138,13,887,13,54232351,2,"[54232351, 1084656, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9139,13,888,13,54232351,2,"[54232351, 1085571, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9140,13,889,13,54232351,2,"[54232351, 1086486, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9141,13,890,13,54232351,2,"[54232351, 1087400, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9142,13,891,13,54232351,2,"[54232351, 1088313, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9143,13,892,13,54232351,2,"[54232351, 1089225, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9144,13,893,13,54232351,2,"[54232351, 1090137, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9145,13,894,13,54232351,2,"[54232351, 1091048, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9146,13,895,13,54232351,2,"[54232351, 1091958, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9147,13,896,13,54232351,2,"[54232351, 1092868, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9148,13,897,13,54232351,2,"[54232351, 1093777, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9149,13,898,13,54232351,2,"[54232351, 1094685, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9150,13,899,13,54232351,2,"[54232351, 1095592, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9151,13,900,13,54232351,2,"[54232351, 1096499, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9152,13,901,13,54232351,2,"[54232351, 1097405, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9153,13,902,13,54232351,2,"[54232351, 1098311, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9154,13,903,13,54232351,2,"[54232351, 1099215, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9155,13,904,13,54232351,2,"[54232351, 1100119, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9156,13,905,13,54232351,2,"[54232351, 1101023, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9157,13,906,13,54232351,2,"[54232351, 1101925, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9158,13,907,13,54232351,2,"[54232351, 1102827, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9159,13,908,13,54232351,2,"[54232351, 1103728, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9160,13,909,13,54232351,2,"[54232351, 1104629, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9161,13,910,13,54232351,2,"[54232351, 1105529, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9162,13,911,13,54232351,2,"[54232351, 1106428, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9163,13,912,13,54232351,2,"[54232351, 1107326, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9164,13,913,13,54232351,2,"[54232351, 1108224, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9165,13,914,13,54232351,2,"[54232351, 1109121, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9166,13,915,13,54232351,2,"[54232351, 1110017, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9167,13,916,13,54232351,2,"[54232351, 1110913, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9168,13,917,13,54232351,2,"[54232351, 1111808, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9169,13,918,13,54232351,2,"[54232351, 1112702, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9170,13,919,13,54232351,2,"[54232351, 1113595, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9171,13,920,13,54232351,2,"[54232351, 1114488, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9172,13,921,13,54232351,2,"[54232351, 1115380, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9173,13,922,13,54232351,2,"[54232351, 1116272, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9174,13,923,13,54232351,2,"[54232351, 1117162, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9175,13,924,13,54232351,2,"[54232351, 1118052, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9176,13,925,13,54232351,2,"[54232351, 1118942, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9177,13,926,13,54232351,2,"[54232351, 1119830, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9178,13,927,13,54232351,2,"[54232351, 1120718, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9179,13,928,13,54232351,2,"[54232351, 1121605, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9180,13,929,13,54232351,2,"[54232351, 1122492, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9181,13,930,13,54232351,2,"[54232351, 1123378, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9182,13,931,13,54232351,2,"[54232351, 1124263, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9183,13,932,13,54232351,2,"[54232351, 1125147, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9184,13,933,13,54232351,2,"[54232351, 1126031, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9185,13,934,13,54232351,2,"[54232351, 1126914, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9186,13,935,13,54232351,2,"[54232351, 1127796, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9187,13,936,13,54232351,2,"[54232351, 1128678, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9188,13,937,13,54232351,2,"[54232351, 1129559, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9189,13,938,13,54232351,2,"[54232351, 1130439, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9190,13,939,13,54232351,2,"[54232351, 1131318, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9191,13,940,13,54232351,2,"[54232351, 1132197, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9192,13,941,13,54232351,2,"[54232351, 1133075, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9193,13,942,13,54232351,2,"[54232351, 1133953, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9194,13,943,13,54232351,2,"[54232351, 1134829, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9195,13,944,13,54232351,2,"[54232351, 1135705, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9196,13,945,13,54232351,2,"[54232351, 1136581, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9197,13,946,13,54232351,2,"[54232351, 1137455, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9198,13,947,13,54232351,2,"[54232351, 1138329, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9199,13,948,13,54232351,2,"[54232351, 1139202, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9200,13,949,13,54232351,2,"[54232351, 1140075, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9201,13,950,13,54232351,2,"[54232351, 1140947, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9202,13,951,13,54232351,2,"[54232351, 1141818, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9203,13,952,13,54232351,2,"[54232351, 1142688, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9204,13,953,13,54232351,2,"[54232351, 1143558, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9205,13,954,13,54232351,2,"[54232351, 1144427, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9206,13,955,13,54232351,2,"[54232351, 1145295, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9207,13,956,13,54232351,2,"[54232351, 1146163, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9208,13,957,13,54232351,2,"[54232351, 1147030, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9209,13,958,13,54232351,2,"[54232351, 1147896, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9210,13,959,13,54232351,2,"[54232351, 1148761, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9211,13,960,13,54232351,2,"[54232351, 1149626, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9212,13,961,13,54232351,2,"[54232351, 1150490, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9213,13,962,13,54232351,2,"[54232351, 1151354, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9214,13,963,13,54232351,2,"[54232351, 1152216, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9215,13,964,13,54232351,2,"[54232351, 1153078, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9216,13,965,13,54232351,2,"[54232351, 1153940, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9217,13,966,13,54232351,2,"[54232351, 1154800, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9218,13,967,13,54232351,2,"[54232351, 1155660, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9219,13,968,13,54232351,2,"[54232351, 1156519, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9220,13,969,13,54232351,2,"[54232351, 1157378, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9221,13,970,13,54232351,2,"[54232351, 1158236, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9222,13,971,13,54232351,2,"[54232351, 1159093, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9223,13,972,13,54232351,2,"[54232351, 1159949, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9224,13,973,13,54232351,2,"[54232351, 1160805, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9225,13,974,13,54232351,2,"[54232351, 1161660, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9226,13,975,13,54232351,2,"[54232351, 1162514, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9227,13,976,13,54232351,2,"[54232351, 1163368, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9228,13,977,13,54232351,2,"[54232351, 1164221, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9229,13,978,13,54232351,2,"[54232351, 1165073, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9230,13,979,13,54232351,2,"[54232351, 1165924, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9231,13,980,13,54232351,2,"[54232351, 1166775, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9232,13,981,13,54232351,2,"[54232351, 1167625, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9233,13,982,13,54232351,2,"[54232351, 1168475, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9234,13,983,13,54232351,2,"[54232351, 1169323, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9235,13,984,13,54232351,2,"[54232351, 1170171, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9236,13,985,13,54232351,2,"[54232351, 1171019, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9237,13,986,13,54232351,2,"[54232351, 1171865, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9238,13,987,13,54232351,2,"[54232351, 1172711, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9239,13,988,13,54232351,2,"[54232351, 1173556, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9240,13,989,13,54232351,2,"[54232351, 1174401, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9241,13,990,13,54232351,2,"[54232351, 1175245, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9242,13,991,13,54232351,2,"[54232351, 1176088, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9243,13,992,13,54232351,2,"[54232351, 1176930, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9244,13,993,13,54232351,2,"[54232351, 1177772, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9245,13,994,13,54232351,2,"[54232351, 1178613, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9246,13,995,13,54232351,2,"[54232351, 1179453, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9247,13,996,13,54232351,2,"[54232351, 1180293, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9248,13,997,13,54232351,2,"[54232351, 1181132, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9249,13,998,13,54232351,2,"[54232351, 1181970, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9250,13,999,13,54232351,2,"[54232351, 1182807, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9251,13,1000,13,54232351,2,"[54232351, 1183644, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9252,13,1001,13,54232351,2,"[54232351, 1184480, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9253,13,1002,13,54232351,2,"[54232351, 1185316, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9254,13,1003,13,54232351,2,"[54232351, 1186150, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9255,13,1004,13,54232351,2,"[54232351, 1186984, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9256,13,1005,13,54232351,2,"[54232351, 1187818, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9257,13,1006,13,54232351,2,"[54232351, 1188650, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9258,13,1007,13,54232351,2,"[54232351, 1189482, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9259,13,1008,13,54232351,2,"[54232351, 1190313, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9260,13,1009,13,54232351,2,"[54232351, 1191144, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9261,13,1010,13,54232351,2,"[54232351, 1191974, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9262,13,1011,13,54232351,2,"[54232351, 1192803, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9263,13,1012,13,54232351,2,"[54232351, 1193631, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9264,13,1013,13,54232351,2,"[54232351, 1194459, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9265,13,1014,13,54232351,2,"[54232351, 1195286, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9266,13,1015,13,54232351,2,"[54232351, 1196112, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9267,13,1016,13,54232351,2,"[54232351, 1196938, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9268,13,1017,13,54232351,2,"[54232351, 1197763, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9269,13,1018,13,54232351,2,"[54232351, 1198587, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9270,13,1019,13,54232351,2,"[54232351, 1199410, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9271,13,1020,13,54232351,2,"[54232351, 1200233, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9272,13,1021,13,54232351,2,"[54232351, 1201055, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9273,13,1022,13,54232351,2,"[54232351, 1201877, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9274,13,1023,13,54232351,2,"[54232351, 1202697, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9275,13,1024,13,54232351,2,"[54232351, 1203517, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9276,13,1025,13,54232351,2,"[54232351, 1204337, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9277,13,1026,13,54232351,2,"[54232351, 1205155, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9278,13,1027,13,54232351,2,"[54232351, 1205973, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9279,13,1028,13,54232351,2,"[54232351, 1206790, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9280,13,1029,13,54232351,2,"[54232351, 1207607, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9281,13,1030,13,54232351,2,"[54232351, 1208423, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9282,13,1031,13,54232351,2,"[54232351, 1209238, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9283,13,1032,13,54232351,2,"[54232351, 1210052, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9284,13,1033,13,54232351,2,"[54232351, 1210866, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9285,13,1034,13,54232351,2,"[54232351, 1211679, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9286,13,1035,13,54232351,2,"[54232351, 1212491, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9287,13,1036,13,54232351,2,"[54232351, 1213303, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9288,13,1037,13,54232351,2,"[54232351, 1214114, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9289,13,1038,13,54232351,2,"[54232351, 1214924, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9290,13,1039,13,54232351,2,"[54232351, 1215733, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9291,13,1040,13,54232351,2,"[54232351, 1216542, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9292,13,1041,13,54232351,2,"[54232351, 1217350, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9293,13,1042,13,54232351,2,"[54232351, 1218158, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9294,13,1043,13,54232351,2,"[54232351, 1218964, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9295,13,1044,13,54232351,2,"[54232351, 1219770, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9296,13,1045,13,54232351,2,"[54232351, 1220576, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9297,13,1046,13,54232351,2,"[54232351, 1221380, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9298,13,1047,13,54232351,2,"[54232351, 1222184, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9299,13,1048,13,54232351,2,"[54232351, 1222987, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9300,13,1049,13,54232351,2,"[54232351, 1223790, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9301,13,1050,13,54232351,2,"[54232351, 1224592, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9302,13,1051,13,54232351,2,"[54232351, 1225393, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9303,13,1052,13,54232351,2,"[54232351, 1226193, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9304,13,1053,13,54232351,2,"[54232351, 1226993, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9305,13,1054,13,54232351,2,"[54232351, 1227792, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9306,13,1055,13,54232351,2,"[54232351, 1228590, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9307,13,1056,13,54232351,2,"[54232351, 1229388, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9308,13,1057,13,54232351,2,"[54232351, 1230185, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9309,13,1058,13,54232351,2,"[54232351, 1230981, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9310,13,1059,13,54232351,2,"[54232351, 1231776, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9311,13,1060,13,54232351,2,"[54232351, 1232571, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9312,13,1061,13,54232351,2,"[54232351, 1233365, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9313,13,1062,13,54232351,2,"[54232351, 1234159, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9314,13,1063,13,54232351,2,"[54232351, 1234951, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9315,13,1064,13,54232351,2,"[54232351, 1235743, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9316,13,1065,13,54232351,2,"[54232351, 1236535, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9317,13,1066,13,54232351,2,"[54232351, 1237325, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9318,13,1067,13,54232351,2,"[54232351, 1238115, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9319,13,1068,13,54232351,2,"[54232351, 1238904, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9320,13,1069,13,54232351,2,"[54232351, 1239693, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9321,13,1070,13,54232351,2,"[54232351, 1240481, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9322,13,1071,13,54232351,2,"[54232351, 1241268, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9323,13,1072,13,54232351,2,"[54232351, 1242054, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9324,13,1073,13,54232351,2,"[54232351, 1242840, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9325,13,1074,13,54232351,2,"[54232351, 1243625, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9326,13,1075,13,54232351,2,"[54232351, 1244409, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9327,13,1076,13,54232351,2,"[54232351, 1245193, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9328,13,1077,13,54232351,2,"[54232351, 1245976, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9329,13,1078,13,54232351,2,"[54232351, 1246758, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9330,13,1079,13,54232351,2,"[54232351, 1247539, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9331,13,1080,13,54232351,2,"[54232351, 1248320, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9332,13,1081,13,54232351,2,"[54232351, 1249100, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9333,13,1082,13,54232351,2,"[54232351, 1249880, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9334,13,1083,13,54232351,2,"[54232351, 1250658, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9335,13,1084,13,54232351,2,"[54232351, 1251436, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9336,13,1085,13,54232351,2,"[54232351, 1252214, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9337,13,1086,13,54232351,2,"[54232351, 1252990, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9338,13,1087,13,54232351,2,"[54232351, 1253766, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9339,13,1088,13,54232351,2,"[54232351, 1254541, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9340,13,1089,13,54232351,2,"[54232351, 1255316, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9341,13,1090,13,54232351,2,"[54232351, 1256090, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9342,13,1091,13,54232351,2,"[54232351, 1256863, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9343,13,1092,13,54232351,2,"[54232351, 1257635, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9344,13,1093,13,54232351,2,"[54232351, 1258407, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9345,13,1094,13,54232351,2,"[54232351, 1259178, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9346,13,1095,13,54232351,2,"[54232351, 1259948, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9347,13,1096,13,54232351,2,"[54232351, 1260718, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9348,13,1097,13,54232351,2,"[54232351, 1261487, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9349,13,1098,13,54232351,2,"[54232351, 1262255, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9350,13,1099,13,54232351,2,"[54232351, 1263022, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9351,13,1100,13,54232351,2,"[54232351, 1263789, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9352,13,1101,13,54232351,2,"[54232351, 1264555, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9353,13,1102,13,54232351,2,"[54232351, 1265321, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9354,13,1103,13,54232351,2,"[54232351, 1266085, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9355,13,1104,13,54232351,2,"[54232351, 1266849, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9356,13,1105,13,54232351,2,"[54232351, 1267613, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9357,13,1106,13,54232351,2,"[54232351, 1268375, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9358,13,1107,13,54232351,2,"[54232351, 1269137, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9359,13,1108,13,54232351,2,"[54232351, 1269898, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9360,13,1109,13,54232351,2,"[54232351, 1270659, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9361,13,1110,13,54232351,2,"[54232351, 1271419, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9362,13,1111,13,54232351,2,"[54232351, 1272178, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9363,13,1112,13,54232351,2,"[54232351, 1272936, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9364,13,1113,13,54232351,2,"[54232351, 1273694, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9365,13,1114,13,54232351,2,"[54232351, 1274451, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9366,13,1115,13,54232351,2,"[54232351, 1275207, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9367,13,1116,13,54232351,2,"[54232351, 1275963, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9368,13,1117,13,54232351,2,"[54232351, 1276718, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9369,13,1118,13,54232351,2,"[54232351, 1277472, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9370,13,1119,13,54232351,2,"[54232351, 1278225, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9371,13,1120,13,54232351,2,"[54232351, 1278978, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9372,13,1121,13,54232351,2,"[54232351, 1279730, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9373,13,1122,13,54232351,2,"[54232351, 1280482, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9374,13,1123,13,54232351,2,"[54232351, 1281232, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9375,13,1124,13,54232351,2,"[54232351, 1281982, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9376,13,1125,13,54232351,2,"[54232351, 1282732, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9377,13,1126,13,54232351,2,"[54232351, 1283480, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9378,13,1127,13,54232351,2,"[54232351, 1284228, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9379,13,1128,13,54232351,2,"[54232351, 1284975, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9380,13,1129,13,54232351,2,"[54232351, 1285722, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9381,13,1130,13,54232351,2,"[54232351, 1286468, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9382,13,1131,13,54232351,2,"[54232351, 1287213, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9383,13,1132,13,54232351,2,"[54232351, 1287957, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9384,13,1133,13,54232351,2,"[54232351, 1288701, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9385,13,1134,13,54232351,2,"[54232351, 1289444, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9386,13,1135,13,54232351,2,"[54232351, 1290186, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9387,13,1136,13,54232351,2,"[54232351, 1290928, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9388,13,1137,13,54232351,2,"[54232351, 1291669, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9389,13,1138,13,54232351,2,"[54232351, 1292409, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9390,13,1139,13,54232351,2,"[54232351, 1293148, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9391,13,1140,13,54232351,2,"[54232351, 1293887, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9392,13,1141,13,54232351,2,"[54232351, 1294625, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9393,13,1142,13,54232351,2,"[54232351, 1295363, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9394,13,1143,13,54232351,2,"[54232351, 1296099, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9395,13,1144,13,54232351,2,"[54232351, 1296835, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9396,13,1145,13,54232351,2,"[54232351, 1297571, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9397,13,1146,13,54232351,2,"[54232351, 1298305, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9398,13,1147,13,54232351,2,"[54232351, 1299039, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9399,13,1148,13,54232351,2,"[54232351, 1299772, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9400,13,1149,13,54232351,2,"[54232351, 1300505, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9401,13,1150,13,54232351,2,"[54232351, 1301237, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9402,13,1151,13,54232351,2,"[54232351, 1301968, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9403,13,1152,13,54232351,2,"[54232351, 1302698, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9404,13,1153,13,54232351,2,"[54232351, 1303428, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9405,13,1154,13,54232351,2,"[54232351, 1304157, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9406,13,1155,13,54232351,2,"[54232351, 1304885, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9407,13,1156,13,54232351,2,"[54232351, 1305613, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9408,13,1157,13,54232351,2,"[54232351, 1306340, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9409,13,1158,13,54232351,2,"[54232351, 1307066, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9410,13,1159,13,54232351,2,"[54232351, 1307791, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9411,13,1160,13,54232351,2,"[54232351, 1308516, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9412,13,1161,13,54232351,2,"[54232351, 1309240, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9413,13,1162,13,54232351,2,"[54232351, 1309964, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9414,13,1163,13,54232351,2,"[54232351, 1310686, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9415,13,1164,13,54232351,2,"[54232351, 1311408, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9416,13,1165,13,54232351,2,"[54232351, 1312130, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9417,13,1166,13,54232351,2,"[54232351, 1312850, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9418,13,1167,13,54232351,2,"[54232351, 1313570, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9419,13,1168,13,54232351,2,"[54232351, 1314289, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9420,13,1169,13,54232351,2,"[54232351, 1315008, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9421,13,1170,13,54232351,2,"[54232351, 1315726, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9422,13,1171,13,54232351,2,"[54232351, 1316443, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9423,13,1172,13,54232351,2,"[54232351, 1317159, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9424,13,1173,13,54232351,2,"[54232351, 1317875, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9425,13,1174,13,54232351,2,"[54232351, 1318590, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9426,13,1175,13,54232351,2,"[54232351, 1319304, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9427,13,1176,13,54232351,2,"[54232351, 1320018, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9428,13,1177,13,54232351,2,"[54232351, 1320731, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9429,13,1178,13,54232351,2,"[54232351, 1321443, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9430,13,1179,13,54232351,2,"[54232351, 1322154, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9431,13,1180,13,54232351,2,"[54232351, 1322865, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9432,13,1181,13,54232351,2,"[54232351, 1323575, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9433,13,1182,13,54232351,2,"[54232351, 1324285, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9434,13,1183,13,54232351,2,"[54232351, 1324993, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9435,13,1184,13,54232351,2,"[54232351, 1325701, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9436,13,1185,13,54232351,2,"[54232351, 1326409, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9437,13,1186,13,54232351,2,"[54232351, 1327115, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9438,13,1187,13,54232351,2,"[54232351, 1327821, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9439,13,1188,13,54232351,2,"[54232351, 1328526, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9440,13,1189,13,54232351,2,"[54232351, 1329231, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9441,13,1190,13,54232351,2,"[54232351, 1329935, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9442,13,1191,13,54232351,2,"[54232351, 1330638, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9443,13,1192,13,54232351,2,"[54232351, 1331340, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9444,13,1193,13,54232351,2,"[54232351, 1332042, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9445,13,1194,13,54232351,2,"[54232351, 1332743, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9446,13,1195,13,54232351,2,"[54232351, 1333443, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9447,13,1196,13,54232351,2,"[54232351, 1334143, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9448,13,1197,13,54232351,2,"[54232351, 1334842, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9449,13,1198,13,54232351,2,"[54232351, 1335540, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9450,13,1199,13,54232351,2,"[54232351, 1336237, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9451,13,1200,13,54232351,2,"[54232351, 1336934, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9452,13,1201,13,54232351,2,"[54232351, 1337630, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9453,13,1202,13,54232351,2,"[54232351, 1338326, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9454,13,1203,13,54232351,2,"[54232351, 1339020, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9455,13,1204,13,54232351,2,"[54232351, 1339714, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9456,13,1205,13,54232351,2,"[54232351, 1340408, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9457,13,1206,13,54232351,2,"[54232351, 1341100, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9458,13,1207,13,54232351,2,"[54232351, 1341792, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9459,13,1208,13,54232351,2,"[54232351, 1342483, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9460,13,1209,13,54232351,2,"[54232351, 1343174, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9461,13,1210,13,54232351,2,"[54232351, 1343864, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9462,13,1211,13,54232351,2,"[54232351, 1344553, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9463,13,1212,13,54232351,2,"[54232351, 1345241, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9464,13,1213,13,54232351,2,"[54232351, 1345929, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9465,13,1214,13,54232351,2,"[54232351, 1346616, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9466,13,1215,13,54232351,2,"[54232351, 1347302, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9467,13,1216,13,54232351,2,"[54232351, 1347988, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9468,13,1217,13,54232351,2,"[54232351, 1348673, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9469,13,1218,13,54232351,2,"[54232351, 1349357, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9470,13,1219,13,54232351,2,"[54232351, 1350040, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9471,13,1220,13,54232351,2,"[54232351, 1350723, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9472,13,1221,13,54232351,2,"[54232351, 1351405, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9473,13,1222,13,54232351,2,"[54232351, 1352087, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9474,13,1223,13,54232351,2,"[54232351, 1352767, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9475,13,1224,13,54232351,2,"[54232351, 1353447, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9476,13,1225,13,54232351,2,"[54232351, 1354127, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9477,13,1226,13,54232351,2,"[54232351, 1354805, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9478,13,1227,13,54232351,2,"[54232351, 1355483, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9479,13,1228,13,54232351,2,"[54232351, 1356160, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9480,13,1229,13,54232351,2,"[54232351, 1356837, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9481,13,1230,13,54232351,2,"[54232351, 1357513, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9482,13,1231,13,54232351,2,"[54232351, 1358188, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9483,13,1232,13,54232351,2,"[54232351, 1358862, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9484,13,1233,13,54232351,2,"[54232351, 1359536, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9485,13,1234,13,54232351,2,"[54232351, 1360209, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9486,13,1235,13,54232351,2,"[54232351, 1360881, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9487,13,1236,13,54232351,2,"[54232351, 1361553, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9488,13,1237,13,54232351,2,"[54232351, 1362224, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9489,13,1238,13,54232351,2,"[54232351, 1362894, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9490,13,1239,13,54232351,2,"[54232351, 1363563, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9491,13,1240,13,54232351,2,"[54232351, 1364232, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9492,13,1241,13,54232351,2,"[54232351, 1364900, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9493,13,1242,13,54232351,2,"[54232351, 1365568, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9494,13,1243,13,54232351,2,"[54232351, 1366234, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9495,13,1244,13,54232351,2,"[54232351, 1366900, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9496,13,1245,13,54232351,2,"[54232351, 1367566, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9497,13,1246,13,54232351,2,"[54232351, 1368230, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9498,13,1247,13,54232351,2,"[54232351, 1368894, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9499,13,1248,13,54232351,2,"[54232351, 1369557, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9500,13,1249,13,54232351,2,"[54232351, 1370220, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9501,13,1250,13,54232351,2,"[54232351, 1370882, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9502,13,1251,13,54232351,2,"[54232351, 1371543, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9503,13,1252,13,54232351,2,"[54232351, 1372203, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9504,13,1253,13,54232351,2,"[54232351, 1372863, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9505,13,1254,13,54232351,2,"[54232351, 1373522, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9506,13,1255,13,54232351,2,"[54232351, 1374180, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9507,13,1256,13,54232351,2,"[54232351, 1374838, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9508,13,1257,13,54232351,2,"[54232351, 1375495, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9509,13,1258,13,54232351,2,"[54232351, 1376151, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9510,13,1259,13,54232351,2,"[54232351, 1376806, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9511,13,1260,13,54232351,2,"[54232351, 1377461, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9512,13,1261,13,54232351,2,"[54232351, 1378115, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9513,13,1262,13,54232351,2,"[54232351, 1378769, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9514,13,1263,13,54232351,2,"[54232351, 1379421, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9515,13,1264,13,54232351,2,"[54232351, 1380073, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9516,13,1265,13,54232351,2,"[54232351, 1380725, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9517,13,1266,13,54232351,2,"[54232351, 1381375, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9518,13,1267,13,54232351,2,"[54232351, 1382025, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9519,13,1268,13,54232351,2,"[54232351, 1382674, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9520,13,1269,13,54232351,2,"[54232351, 1383323, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9521,13,1270,13,54232351,2,"[54232351, 1383971, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9522,13,1271,13,54232351,2,"[54232351, 1384618, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9523,13,1272,13,54232351,2,"[54232351, 1385264, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9524,13,1273,13,54232351,2,"[54232351, 1385910, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9525,13,1274,13,54232351,2,"[54232351, 1386555, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9526,13,1275,13,54232351,2,"[54232351, 1387199, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9527,13,1276,13,54232351,2,"[54232351, 1387843, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9528,13,1277,13,54232351,2,"[54232351, 1388486, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9529,13,1278,13,54232351,2,"[54232351, 1389128, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9530,13,1279,13,54232351,2,"[54232351, 1389769, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9531,13,1280,13,54232351,2,"[54232351, 1390410, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9532,13,1281,13,54232351,2,"[54232351, 1391050, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9533,13,1282,13,54232351,2,"[54232351, 1391690, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9534,13,1283,13,54232351,2,"[54232351, 1392328, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9535,13,1284,13,54232351,2,"[54232351, 1392966, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9536,13,1285,13,54232351,2,"[54232351, 1393604, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9537,13,1286,13,54232351,2,"[54232351, 1394240, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9538,13,1287,13,54232351,2,"[54232351, 1394876, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9539,13,1288,13,54232351,2,"[54232351, 1395511, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9540,13,1289,13,54232351,2,"[54232351, 1396146, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9541,13,1290,13,54232351,2,"[54232351, 1396780, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9542,13,1291,13,54232351,2,"[54232351, 1397413, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9543,13,1292,13,54232351,2,"[54232351, 1398045, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9544,13,1293,13,54232351,2,"[54232351, 1398677, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9545,13,1294,13,54232351,2,"[54232351, 1399308, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9546,13,1295,13,54232351,2,"[54232351, 1399938, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9547,13,1296,13,54232351,2,"[54232351, 1400568, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9548,13,1297,13,54232351,2,"[54232351, 1401197, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9549,13,1298,13,54232351,2,"[54232351, 1401825, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9550,13,1299,13,54232351,2,"[54232351, 1402452, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9551,13,1300,13,54232351,2,"[54232351, 1403079, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9552,13,1301,13,54232351,2,"[54232351, 1403705, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9553,13,1302,13,54232351,2,"[54232351, 1404331, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9554,13,1303,13,54232351,2,"[54232351, 1404955, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9555,13,1304,13,54232351,2,"[54232351, 1405579, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9556,13,1305,13,54232351,2,"[54232351, 1406203, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9557,13,1306,13,54232351,2,"[54232351, 1406825, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9558,13,1307,13,54232351,2,"[54232351, 1407447, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9559,13,1308,13,54232351,2,"[54232351, 1408068, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9560,13,1309,13,54232351,2,"[54232351, 1408689, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9561,13,1310,13,54232351,2,"[54232351, 1409309, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9562,13,1311,13,54232351,2,"[54232351, 1409928, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9563,13,1312,13,54232351,2,"[54232351, 1410546, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9564,13,1313,13,54232351,2,"[54232351, 1411164, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9565,13,1314,13,54232351,2,"[54232351, 1411781, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9566,13,1315,13,54232351,2,"[54232351, 1412397, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9567,13,1316,13,54232351,2,"[54232351, 1413013, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9568,13,1317,13,54232351,2,"[54232351, 1413628, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9569,13,1318,13,54232351,2,"[54232351, 1414242, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9570,13,1319,13,54232351,2,"[54232351, 1414855, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9571,13,1320,13,54232351,2,"[54232351, 1415468, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9572,13,1321,13,54232351,2,"[54232351, 1416080, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9573,13,1322,13,54232351,2,"[54232351, 1416692, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9574,13,1323,13,54232351,2,"[54232351, 1417302, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9575,13,1324,13,54232351,2,"[54232351, 1417912, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9576,13,1325,13,54232351,2,"[54232351, 1418522, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9577,13,1326,13,54232351,2,"[54232351, 1419130, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9578,13,1327,13,54232351,2,"[54232351, 1419738, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9579,13,1328,13,54232351,2,"[54232351, 1420345, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9580,13,1329,13,54232351,2,"[54232351, 1420952, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9581,13,1330,13,54232351,2,"[54232351, 1421558, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9582,13,1331,13,54232351,2,"[54232351, 1422163, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9583,13,1332,13,54232351,2,"[54232351, 1422767, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9584,13,1333,13,54232351,2,"[54232351, 1423371, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9585,13,1334,13,54232351,2,"[54232351, 1423974, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9586,13,1335,13,54232351,2,"[54232351, 1424576, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9587,13,1336,13,54232351,2,"[54232351, 1425178, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9588,13,1337,13,54232351,2,"[54232351, 1425779, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9589,13,1338,13,54232351,2,"[54232351, 1426379, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9590,13,1339,13,54232351,2,"[54232351, 1426978, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9591,13,1340,13,54232351,2,"[54232351, 1427577, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9592,13,1341,13,54232351,2,"[54232351, 1428175, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9593,13,1342,13,54232351,2,"[54232351, 1428773, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9594,13,1343,13,54232351,2,"[54232351, 1429369, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9595,13,1344,13,54232351,2,"[54232351, 1429965, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9596,13,1345,13,54232351,2,"[54232351, 1430561, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9597,13,1346,13,54232351,2,"[54232351, 1431155, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9598,13,1347,13,54232351,2,"[54232351, 1431749, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9599,13,1348,13,54232351,2,"[54232351, 1432342, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9600,13,1349,13,54232351,2,"[54232351, 1432935, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9601,13,1350,13,54232351,2,"[54232351, 1433527, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9602,13,1351,13,54232351,2,"[54232351, 1434118, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9603,13,1352,13,54232351,2,"[54232351, 1434708, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9604,13,1353,13,54232351,2,"[54232351, 1435298, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9605,13,1354,13,54232351,2,"[54232351, 1435887, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9606,13,1355,13,54232351,2,"[54232351, 1436475, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9607,13,1356,13,54232351,2,"[54232351, 1437063, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9608,13,1357,13,54232351,2,"[54232351, 1437650, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9609,13,1358,13,54232351,2,"[54232351, 1438236, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9610,13,1359,13,54232351,2,"[54232351, 1438821, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9611,13,1360,13,54232351,2,"[54232351, 1439406, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9612,13,1361,13,54232351,2,"[54232351, 1439990, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9613,13,1362,13,54232351,2,"[54232351, 1440574, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9614,13,1363,13,54232351,2,"[54232351, 1441156, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9615,13,1364,13,54232351,2,"[54232351, 1441738, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9616,13,1365,13,54232351,2,"[54232351, 1442320, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9617,13,1366,13,54232351,2,"[54232351, 1442900, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9618,13,1367,13,54232351,2,"[54232351, 1443480, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9619,13,1368,13,54232351,2,"[54232351, 1444059, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9620,13,1369,13,54232351,2,"[54232351, 1444638, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9621,13,1370,13,54232351,2,"[54232351, 1445216, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9622,13,1371,13,54232351,2,"[54232351, 1445793, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9623,13,1372,13,54232351,2,"[54232351, 1446369, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9624,13,1373,13,54232351,2,"[54232351, 1446945, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9625,13,1374,13,54232351,2,"[54232351, 1447520, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9626,13,1375,13,54232351,2,"[54232351, 1448094, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9627,13,1376,13,54232351,2,"[54232351, 1448668, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9628,13,1377,13,54232351,2,"[54232351, 1449241, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9629,13,1378,13,54232351,2,"[54232351, 1449813, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9630,13,1379,13,54232351,2,"[54232351, 1450384, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9631,13,1380,13,54232351,2,"[54232351, 1450955, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9632,13,1381,13,54232351,2,"[54232351, 1451525, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9633,13,1382,13,54232351,2,"[54232351, 1452095, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9634,13,1383,13,54232351,2,"[54232351, 1452663, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9635,13,1384,13,54232351,2,"[54232351, 1453231, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9636,13,1385,13,54232351,2,"[54232351, 1453799, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9637,13,1386,13,54232351,2,"[54232351, 1454365, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9638,13,1387,13,54232351,2,"[54232351, 1454931, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9639,13,1388,13,54232351,2,"[54232351, 1455496, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9640,13,1389,13,54232351,2,"[54232351, 1456061, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9641,13,1390,13,54232351,2,"[54232351, 1456625, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9642,13,1391,13,54232351,2,"[54232351, 1457188, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9643,13,1392,13,54232351,2,"[54232351, 1457750, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9644,13,1393,13,54232351,2,"[54232351, 1458312, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9645,13,1394,13,54232351,2,"[54232351, 1458873, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9646,13,1395,13,54232351,2,"[54232351, 1459433, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9647,13,1396,13,54232351,2,"[54232351, 1459993, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9648,13,1397,13,54232351,2,"[54232351, 1460552, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9649,13,1398,13,54232351,2,"[54232351, 1461110, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9650,13,1399,13,54232351,2,"[54232351, 1461667, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9651,13,1400,13,54232351,2,"[54232351, 1462224, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9652,13,1401,13,54232351,2,"[54232351, 1462780, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9653,13,1402,13,54232351,2,"[54232351, 1463336, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9654,13,1403,13,54232351,2,"[54232351, 1463890, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9655,13,1404,13,54232351,2,"[54232351, 1464444, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9656,13,1405,13,54232351,2,"[54232351, 1464998, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9657,13,1406,13,54232351,2,"[54232351, 1465550, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9658,13,1407,13,54232351,2,"[54232351, 1466102, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9659,13,1408,13,54232351,2,"[54232351, 1466653, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9660,13,1409,13,54232351,2,"[54232351, 1467204, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9661,13,1410,13,54232351,2,"[54232351, 1467754, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9662,13,1411,13,54232351,2,"[54232351, 1468303, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9663,13,1412,13,54232351,2,"[54232351, 1468851, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9664,13,1413,13,54232351,2,"[54232351, 1469399, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9665,13,1414,13,54232351,2,"[54232351, 1469946, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9666,13,1415,13,54232351,2,"[54232351, 1470492, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9667,13,1416,13,54232351,2,"[54232351, 1471038, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9668,13,1417,13,54232351,2,"[54232351, 1471583, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9669,13,1418,13,54232351,2,"[54232351, 1472127, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9670,13,1419,13,54232351,2,"[54232351, 1472670, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9671,13,1420,13,54232351,2,"[54232351, 1473213, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9672,13,1421,13,54232351,2,"[54232351, 1473755, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9673,13,1422,13,54232351,2,"[54232351, 1474297, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9674,13,1423,13,54232351,2,"[54232351, 1474837, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9675,13,1424,13,54232351,2,"[54232351, 1475377, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9676,13,1425,13,54232351,2,"[54232351, 1475917, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9677,13,1426,13,54232351,2,"[54232351, 1476455, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9678,13,1427,13,54232351,2,"[54232351, 1476993, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9679,13,1428,13,54232351,2,"[54232351, 1477530, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9680,13,1429,13,54232351,2,"[54232351, 1478067, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9681,13,1430,13,54232351,2,"[54232351, 1478603, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9682,13,1431,13,54232351,2,"[54232351, 1479138, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9683,13,1432,13,54232351,2,"[54232351, 1479672, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9684,13,1433,13,54232351,2,"[54232351, 1480206, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9685,13,1434,13,54232351,2,"[54232351, 1480739, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9686,13,1435,13,54232351,2,"[54232351, 1481271, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9687,13,1436,13,54232351,2,"[54232351, 1481803, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9688,13,1437,13,54232351,2,"[54232351, 1482334, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9689,13,1438,13,54232351,2,"[54232351, 1482864, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9690,13,1439,13,54232351,2,"[54232351, 1483393, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9691,13,1440,13,54232351,2,"[54232351, 1483922, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9692,13,1441,13,54232351,2,"[54232351, 1484450, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9693,13,1442,13,54232351,2,"[54232351, 1484978, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9694,13,1443,13,54232351,2,"[54232351, 1485504, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9695,13,1444,13,54232351,2,"[54232351, 1486030, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9696,13,1445,13,54232351,2,"[54232351, 1486556, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9697,13,1446,13,54232351,2,"[54232351, 1487080, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9698,13,1447,13,54232351,2,"[54232351, 1487604, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9699,13,1448,13,54232351,2,"[54232351, 1488127, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9700,13,1449,13,54232351,2,"[54232351, 1488650, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9701,13,1450,13,54232351,2,"[54232351, 1489172, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9702,13,1451,13,54232351,2,"[54232351, 1489693, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9703,13,1452,13,54232351,2,"[54232351, 1490213, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9704,13,1453,13,54232351,2,"[54232351, 1490733, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9705,13,1454,13,54232351,2,"[54232351, 1491252, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9706,13,1455,13,54232351,2,"[54232351, 1491770, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9707,13,1456,13,54232351,2,"[54232351, 1492288, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9708,13,1457,13,54232351,2,"[54232351, 1492805, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9709,13,1458,13,54232351,2,"[54232351, 1493321, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9710,13,1459,13,54232351,2,"[54232351, 1493836, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9711,13,1460,13,54232351,2,"[54232351, 1494351, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9712,13,1461,13,54232351,2,"[54232351, 1494865, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9713,13,1462,13,54232351,2,"[54232351, 1495379, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9714,13,1463,13,54232351,2,"[54232351, 1495891, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9715,13,1464,13,54232351,2,"[54232351, 1496403, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9716,13,1465,13,54232351,2,"[54232351, 1496915, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9717,13,1466,13,54232351,2,"[54232351, 1497425, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9718,13,1467,13,54232351,2,"[54232351, 1497935, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9719,13,1468,13,54232351,2,"[54232351, 1498444, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9720,13,1469,13,54232351,2,"[54232351, 1498953, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9721,13,1470,13,54232351,2,"[54232351, 1499461, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9722,13,1471,13,54232351,2,"[54232351, 1499968, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9723,13,1472,13,54232351,2,"[54232351, 1500474, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9724,13,1473,13,54232351,2,"[54232351, 1500980, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9725,13,1474,13,54232351,2,"[54232351, 1501485, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9726,13,1475,13,54232351,2,"[54232351, 1501989, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9727,13,1476,13,54232351,2,"[54232351, 1502493, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9728,13,1477,13,54232351,2,"[54232351, 1502996, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9729,13,1478,13,54232351,2,"[54232351, 1503498, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9730,13,1479,13,54232351,2,"[54232351, 1503999, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9731,13,1480,13,54232351,2,"[54232351, 1504500, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9732,13,1481,13,54232351,2,"[54232351, 1505000, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9733,13,1482,13,54232351,2,"[54232351, 1505500, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9734,13,1483,13,54232351,2,"[54232351, 1505998, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9735,13,1484,13,54232351,2,"[54232351, 1506496, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9736,13,1485,13,54232351,2,"[54232351, 1506994, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9737,13,1486,13,54232351,2,"[54232351, 1507490, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9738,13,1487,13,54232351,2,"[54232351, 1507986, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9739,13,1488,13,54232351,2,"[54232351, 1508481, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9740,13,1489,13,54232351,2,"[54232351, 1508976, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9741,13,1490,13,54232351,2,"[54232351, 1509470, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9742,13,1491,13,54232351,2,"[54232351, 1509963, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9743,13,1492,13,54232351,2,"[54232351, 1510455, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9744,13,1493,13,54232351,2,"[54232351, 1510947, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9745,13,1494,13,54232351,2,"[54232351, 1511438, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9746,13,1495,13,54232351,2,"[54232351, 1511928, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9747,13,1496,13,54232351,2,"[54232351, 1512418, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9748,13,1497,13,54232351,2,"[54232351, 1512907, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9749,13,1498,13,54232351,2,"[54232351, 1513395, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9750,13,1499,13,54232351,2,"[54232351, 1513882, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9751,13,1500,13,54232351,2,"[54232351, 1514369, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9752,13,1501,13,54232351,2,"[54232351, 1514855, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9753,13,1502,13,54232351,2,"[54232351, 1515341, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9754,13,1503,13,54232351,2,"[54232351, 1515825, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9755,13,1504,13,54232351,2,"[54232351, 1516309, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9756,13,1505,13,54232351,2,"[54232351, 1516793, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9757,13,1506,13,54232351,2,"[54232351, 1517275, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9758,13,1507,13,54232351,2,"[54232351, 1517757, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9759,13,1508,13,54232351,2,"[54232351, 1518238, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9760,13,1509,13,54232351,2,"[54232351, 1518719, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9761,13,1510,13,54232351,2,"[54232351, 1519199, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9762,13,1511,13,54232351,2,"[54232351, 1519678, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9763,13,1512,13,54232351,2,"[54232351, 1520156, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9764,13,1513,13,54232351,2,"[54232351, 1520634, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9765,13,1514,13,54232351,2,"[54232351, 1521111, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9766,13,1515,13,54232351,2,"[54232351, 1521587, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9767,13,1516,13,54232351,2,"[54232351, 1522063, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9768,13,1517,13,54232351,2,"[54232351, 1522538, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9769,13,1518,13,54232351,2,"[54232351, 1523012, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9770,13,1519,13,54232351,2,"[54232351, 1523485, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9771,13,1520,13,54232351,2,"[54232351, 1523958, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9772,13,1521,13,54232351,2,"[54232351, 1524430, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9773,13,1522,13,54232351,2,"[54232351, 1524902, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9774,13,1523,13,54232351,2,"[54232351, 1525372, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9775,13,1524,13,54232351,2,"[54232351, 1525842, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9776,13,1525,13,54232351,2,"[54232351, 1526312, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9777,13,1526,13,54232351,2,"[54232351, 1526780, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9778,13,1527,13,54232351,2,"[54232351, 1527248, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9779,13,1528,13,54232351,2,"[54232351, 1527715, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9780,13,1529,13,54232351,2,"[54232351, 1528182, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9781,13,1530,13,54232351,2,"[54232351, 1528648, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9782,13,1531,13,54232351,2,"[54232351, 1529113, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9783,13,1532,13,54232351,2,"[54232351, 1529577, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9784,13,1533,13,54232351,2,"[54232351, 1530041, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9785,13,1534,13,54232351,2,"[54232351, 1530504, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9786,13,1535,13,54232351,2,"[54232351, 1530966, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9787,13,1536,13,54232351,2,"[54232351, 1531428, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9788,13,1537,13,54232351,2,"[54232351, 1531889, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9789,13,1538,13,54232351,2,"[54232351, 1532349, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9790,13,1539,13,54232351,2,"[54232351, 1532808, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9791,13,1540,13,54232351,2,"[54232351, 1533267, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9792,13,1541,13,54232351,2,"[54232351, 1533725, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9793,13,1542,13,54232351,2,"[54232351, 1534183, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9794,13,1543,13,54232351,2,"[54232351, 1534639, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9795,13,1544,13,54232351,2,"[54232351, 1535095, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9796,13,1545,13,54232351,2,"[54232351, 1535551, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9797,13,1546,13,54232351,2,"[54232351, 1536005, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9798,13,1547,13,54232351,2,"[54232351, 1536459, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9799,13,1548,13,54232351,2,"[54232351, 1536912, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9800,13,1549,13,54232351,2,"[54232351, 1537365, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9801,13,1550,13,54232351,2,"[54232351, 1537817, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9802,13,1551,13,54232351,2,"[54232351, 1538268, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9803,13,1552,13,54232351,2,"[54232351, 1538718, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9804,13,1553,13,54232351,2,"[54232351, 1539168, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9805,13,1554,13,54232351,2,"[54232351, 1539617, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9806,13,1555,13,54232351,2,"[54232351, 1540065, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9807,13,1556,13,54232351,2,"[54232351, 1540513, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9808,13,1557,13,54232351,2,"[54232351, 1540960, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9809,13,1558,13,54232351,2,"[54232351, 1541406, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9810,13,1559,13,54232351,2,"[54232351, 1541851, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9811,13,1560,13,54232351,2,"[54232351, 1542296, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9812,13,1561,13,54232351,2,"[54232351, 1542740, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9813,13,1562,13,54232351,2,"[54232351, 1543184, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9814,13,1563,13,54232351,2,"[54232351, 1543626, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9815,13,1564,13,54232351,2,"[54232351, 1544068, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9816,13,1565,13,54232351,2,"[54232351, 1544510, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9817,13,1566,13,54232351,2,"[54232351, 1544950, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9818,13,1567,13,54232351,2,"[54232351, 1545390, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9819,13,1568,13,54232351,2,"[54232351, 1545829, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9820,13,1569,13,54232351,2,"[54232351, 1546268, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9821,13,1570,13,54232351,2,"[54232351, 1546706, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9822,13,1571,13,54232351,2,"[54232351, 1547143, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9823,13,1572,13,54232351,2,"[54232351, 1547579, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9824,13,1573,13,54232351,2,"[54232351, 1548015, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9825,13,1574,13,54232351,2,"[54232351, 1548450, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9826,13,1575,13,54232351,2,"[54232351, 1548884, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9827,13,1576,13,54232351,2,"[54232351, 1549318, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9828,13,1577,13,54232351,2,"[54232351, 1549751, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9829,13,1578,13,54232351,2,"[54232351, 1550183, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9830,13,1579,13,54232351,2,"[54232351, 1550614, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9831,13,1580,13,54232351,2,"[54232351, 1551045, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9832,13,1581,13,54232351,2,"[54232351, 1551475, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9833,13,1582,13,54232351,2,"[54232351, 1551905, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9834,13,1583,13,54232351,2,"[54232351, 1552333, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9835,13,1584,13,54232351,2,"[54232351, 1552761, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9836,13,1585,13,54232351,2,"[54232351, 1553189, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9837,13,1586,13,54232351,2,"[54232351, 1553615, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9838,13,1587,13,54232351,2,"[54232351, 1554041, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9839,13,1588,13,54232351,2,"[54232351, 1554466, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9840,13,1589,13,54232351,2,"[54232351, 1554891, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9841,13,1590,13,54232351,2,"[54232351, 1555315, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9842,13,1591,13,54232351,2,"[54232351, 1555738, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9843,13,1592,13,54232351,2,"[54232351, 1556160, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9844,13,1593,13,54232351,2,"[54232351, 1556582, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9845,13,1594,13,54232351,2,"[54232351, 1557003, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9846,13,1595,13,54232351,2,"[54232351, 1557423, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9847,13,1596,13,54232351,2,"[54232351, 1557843, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9848,13,1597,13,54232351,2,"[54232351, 1558262, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9849,13,1598,13,54232351,2,"[54232351, 1558680, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9850,13,1599,13,54232351,2,"[54232351, 1559097, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9851,13,1600,13,54232351,2,"[54232351, 1559514, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9852,13,1601,13,54232351,2,"[54232351, 1559930, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9853,13,1602,13,54232351,2,"[54232351, 1560346, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9854,13,1603,13,54232351,2,"[54232351, 1560760, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9855,13,1604,13,54232351,2,"[54232351, 1561174, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9856,13,1605,13,54232351,2,"[54232351, 1561588, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9857,13,1606,13,54232351,2,"[54232351, 1562000, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9858,13,1607,13,54232351,2,"[54232351, 1562412, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9859,13,1608,13,54232351,2,"[54232351, 1562823, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9860,13,1609,13,54232351,2,"[54232351, 1563234, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9861,13,1610,13,54232351,2,"[54232351, 1563644, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9862,13,1611,13,54232351,2,"[54232351, 1564053, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9863,13,1612,13,54232351,2,"[54232351, 1564461, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9864,13,1613,13,54232351,2,"[54232351, 1564869, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9865,13,1614,13,54232351,2,"[54232351, 1565276, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9866,13,1615,13,54232351,2,"[54232351, 1565682, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9867,13,1616,13,54232351,2,"[54232351, 1566088, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9868,13,1617,13,54232351,2,"[54232351, 1566493, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9869,13,1618,13,54232351,2,"[54232351, 1566897, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9870,13,1619,13,54232351,2,"[54232351, 1567300, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9871,13,1620,13,54232351,2,"[54232351, 1567703, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9872,13,1621,13,54232351,2,"[54232351, 1568105, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9873,13,1622,13,54232351,2,"[54232351, 1568507, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9874,13,1623,13,54232351,2,"[54232351, 1568907, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9875,13,1624,13,54232351,2,"[54232351, 1569309, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9876,13,1625,13,54232351,2,"[54232351, 1569711, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9877,13,1626,13,54232351,2,"[54232351, 1570114, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9878,13,1627,13,54232351,2,"[54232351, 1570517, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9879,13,1628,13,54232351,2,"[54232351, 1570922, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9880,13,1629,13,54232351,2,"[54232351, 1571326, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9881,13,1630,13,54232351,2,"[54232351, 1571732, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9882,13,1631,13,54232351,2,"[54232351, 1572138, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9883,13,1632,13,54232351,2,"[54232351, 1572545, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9884,13,1633,13,54232351,2,"[54232351, 1572953, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9885,13,1634,13,54232351,2,"[54232351, 1573361, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9886,13,1635,13,54232351,2,"[54232351, 1573771, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9887,13,1636,13,54232351,2,"[54232351, 1574180, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9888,13,1637,13,54232351,2,"[54232351, 1574591, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9889,13,1638,13,54232351,2,"[54232351, 1575002, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9890,13,1639,13,54232351,2,"[54232351, 1575414, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9891,13,1640,13,54232351,2,"[54232351, 1575827, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9892,13,1641,13,54232351,2,"[54232351, 1576240, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9893,13,1642,13,54232351,2,"[54232351, 1576654, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9894,13,1643,13,54232351,2,"[54232351, 1577069, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9895,13,1644,13,54232351,2,"[54232351, 1577484, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9896,13,1645,13,54232351,2,"[54232351, 1577900, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9897,13,1646,13,54232351,2,"[54232351, 1578317, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9898,13,1647,13,54232351,2,"[54232351, 1578734, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9899,13,1648,13,54232351,2,"[54232351, 1579153, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9900,13,1649,13,54232351,2,"[54232351, 1579571, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9901,13,1650,13,54232351,2,"[54232351, 1579991, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9902,13,1651,13,54232351,2,"[54232351, 1580411, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9903,13,1652,13,54232351,2,"[54232351, 1580832, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9904,13,1653,13,54232351,2,"[54232351, 1581254, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9905,13,1654,13,54232351,2,"[54232351, 1581676, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9906,13,1655,13,54232351,2,"[54232351, 1582100, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9907,13,1656,13,54232351,2,"[54232351, 1582523, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9908,13,1657,13,54232351,2,"[54232351, 1582948, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9909,13,1658,13,54232351,2,"[54232351, 1583373, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9910,13,1659,13,54232351,2,"[54232351, 1583799, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9911,13,1660,13,54232351,2,"[54232351, 1584226, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9912,13,1661,13,54232351,2,"[54232351, 1584653, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9913,13,1662,13,54232351,2,"[54232351, 1585081, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9914,13,1663,13,54232351,2,"[54232351, 1585510, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9915,13,1664,13,54232351,2,"[54232351, 1585939, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9916,13,1665,13,54232351,2,"[54232351, 1586369, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9917,13,1666,13,54232351,2,"[54232351, 1586800, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9918,13,1667,13,54232351,2,"[54232351, 1587231, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9919,13,1668,13,54232351,2,"[54232351, 1587664, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9920,13,1669,13,54232351,2,"[54232351, 1588096, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9921,13,1670,13,54232351,2,"[54232351, 1588530, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9922,13,1671,13,54232351,2,"[54232351, 1588964, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9923,13,1672,13,54232351,2,"[54232351, 1589399, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9924,13,1673,13,54232351,2,"[54232351, 1589835, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9925,13,1674,13,54232351,2,"[54232351, 1590271, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9926,13,1675,13,54232351,2,"[54232351, 1590709, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9927,13,1676,13,54232351,2,"[54232351, 1591146, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9928,13,1677,13,54232351,2,"[54232351, 1591585, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9929,13,1678,13,54232351,2,"[54232351, 1592024, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9930,13,1679,13,54232351,2,"[54232351, 1592464, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9931,13,1680,13,54232351,2,"[54232351, 1592905, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9932,13,1681,13,54232351,2,"[54232351, 1593346, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9933,13,1682,13,54232351,2,"[54232351, 1593788, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9934,13,1683,13,54232351,2,"[54232351, 1594231, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9935,13,1684,13,54232351,2,"[54232351, 1594674, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9936,13,1685,13,54232351,2,"[54232351, 1595118, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9937,13,1686,13,54232351,2,"[54232351, 1595563, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9938,13,1687,13,54232351,2,"[54232351, 1596008, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9939,13,1688,13,54232351,2,"[54232351, 1596455, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9940,13,1689,13,54232351,2,"[54232351, 1596901, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9941,13,1690,13,54232351,2,"[54232351, 1597349, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9942,13,1691,13,54232351,2,"[54232351, 1597797, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9943,13,1692,13,54232351,2,"[54232351, 1598246, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9944,13,1693,13,54232351,2,"[54232351, 1598696, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9945,13,1694,13,54232351,2,"[54232351, 1599146, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9946,13,1695,13,54232351,2,"[54232351, 1599598, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9947,13,1696,13,54232351,2,"[54232351, 1600049, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9948,13,1697,13,54232351,2,"[54232351, 1600502, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9949,13,1698,13,54232351,2,"[54232351, 1600955, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9950,13,1699,13,54232351,2,"[54232351, 1601409, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9951,13,1700,13,54232351,2,"[54232351, 1601864, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9952,13,1701,13,54232351,2,"[54232351, 1602319, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9953,13,1702,13,54232351,2,"[54232351, 1602775, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9954,13,1703,13,54232351,2,"[54232351, 1603232, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9955,13,1704,13,54232351,2,"[54232351, 1603689, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9956,13,1705,13,54232351,2,"[54232351, 1604147, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9957,13,1706,13,54232351,2,"[54232351, 1604606, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9958,13,1707,13,54232351,2,"[54232351, 1605065, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9959,13,1708,13,54232351,2,"[54232351, 1605526, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9960,13,1709,13,54232351,2,"[54232351, 1605986, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9961,13,1710,13,54232351,2,"[54232351, 1606448, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9962,13,1711,13,54232351,2,"[54232351, 1606910, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9963,13,1712,13,54232351,2,"[54232351, 1607373, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9964,13,1713,13,54232351,2,"[54232351, 1607837, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9965,13,1714,13,54232351,2,"[54232351, 1608301, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9966,13,1715,13,54232351,2,"[54232351, 1608767, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9967,13,1716,13,54232351,2,"[54232351, 1609232, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9968,13,1717,13,54232351,2,"[54232351, 1609699, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9969,13,1718,13,54232351,2,"[54232351, 1610166, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9970,13,1719,13,54232351,2,"[54232351, 1610634, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9971,13,1720,13,54232351,2,"[54232351, 1611103, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9972,13,1721,13,54232351,2,"[54232351, 1611572, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9973,13,1722,13,54232351,2,"[54232351, 1612042, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9974,13,1723,13,54232351,2,"[54232351, 1612513, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9975,13,1724,13,54232351,2,"[54232351, 1612984, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9976,13,1725,13,54232351,2,"[54232351, 1613456, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9977,13,1726,13,54232351,2,"[54232351, 1613929, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9978,13,1727,13,54232351,2,"[54232351, 1614402, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9979,13,1728,13,54232351,2,"[54232351, 1614877, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9980,13,1729,13,54232351,2,"[54232351, 1615351, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9981,13,1730,13,54232351,2,"[54232351, 1615827, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9982,13,1731,13,54232351,2,"[54232351, 1616303, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9983,13,1732,13,54232351,2,"[54232351, 1616780, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9984,13,1733,13,54232351,2,"[54232351, 1617258, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9985,13,1734,13,54232351,2,"[54232351, 1617736, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9986,13,1735,13,54232351,2,"[54232351, 1618216, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9987,13,1736,13,54232351,2,"[54232351, 1618695, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9988,13,1737,13,54232351,2,"[54232351, 1619176, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9989,13,1738,13,54232351,2,"[54232351, 1619657, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9990,13,1739,13,54232351,2,"[54232351, 1620139, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9991,13,1740,13,54232351,2,"[54232351, 1620622, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9992,13,1741,13,54232351,2,"[54232351, 1621105, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9993,13,1742,13,54232351,2,"[54232351, 1621589, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9994,13,1743,13,54232351,2,"[54232351, 1622074, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9995,13,1744,13,54232351,2,"[54232351, 1622559, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9996,13,1745,13,54232351,2,"[54232351, 1623045, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9997,13,1746,13,54232351,2,"[54232351, 1623532, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9998,13,1747,13,54232351,2,"[54232351, 1624019, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -9999,13,1748,13,54232351,2,"[54232351, 1624508, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10000,13,1749,13,54232351,2,"[54232351, 1624996, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10001,13,1750,13,54232351,2,"[54232351, 1625486, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10002,13,1751,13,54232351,2,"[54232351, 1625976, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10003,13,1752,13,54232351,2,"[54232351, 1626467, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10004,13,1753,13,54232351,2,"[54232351, 1626959, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10005,13,1754,13,54232351,2,"[54232351, 1627451, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10006,13,1755,13,54232351,2,"[54232351, 1627945, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10007,13,1756,13,54232351,2,"[54232351, 1628438, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10008,13,1757,13,54232351,2,"[54232351, 1628933, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10009,13,1758,13,54232351,2,"[54232351, 1629428, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10010,13,1759,13,54232351,2,"[54232351, 1629924, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10011,13,1760,13,54232351,2,"[54232351, 1630421, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10012,13,1761,13,54232351,2,"[54232351, 1630918, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10013,13,1762,13,54232351,2,"[54232351, 1631416, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10014,13,1763,13,54232351,2,"[54232351, 1631915, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10015,13,1764,13,54232351,2,"[54232351, 1632414, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10016,13,1765,13,54232351,2,"[54232351, 1632914, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10017,13,1766,13,54232351,2,"[54232351, 1633415, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10018,13,1767,13,54232351,2,"[54232351, 1633916, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10019,13,1768,13,54232351,2,"[54232351, 1634419, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10020,13,1769,13,54232351,2,"[54232351, 1634921, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10021,13,1770,13,54232351,2,"[54232351, 1635425, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10022,13,1771,13,54232351,2,"[54232351, 1635929, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10023,13,1772,13,54232351,2,"[54232351, 1636434, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10024,13,1773,13,54232351,2,"[54232351, 1636940, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10025,13,1774,13,54232351,2,"[54232351, 1637446, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10026,13,1775,13,54232351,2,"[54232351, 1637954, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10027,13,1776,13,54232351,2,"[54232351, 1638461, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10028,13,1777,13,54232351,2,"[54232351, 1638970, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10029,13,1778,13,54232351,2,"[54232351, 1639479, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10030,13,1779,13,54232351,2,"[54232351, 1639989, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10031,13,1780,13,54232351,2,"[54232351, 1640500, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10032,13,1781,13,54232351,2,"[54232351, 1641011, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10033,13,1782,13,54232351,2,"[54232351, 1641523, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10034,13,1783,13,54232351,2,"[54232351, 1642036, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10035,13,1784,13,54232351,2,"[54232351, 1642549, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10036,13,1785,13,54232351,2,"[54232351, 1643063, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10037,13,1786,13,54232351,2,"[54232351, 1643578, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10038,13,1787,13,54232351,2,"[54232351, 1644093, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10039,13,1788,13,54232351,2,"[54232351, 1644610, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10040,13,1789,13,54232351,2,"[54232351, 1645126, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10041,13,1790,13,54232351,2,"[54232351, 1645644, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10042,13,1791,13,54232351,2,"[54232351, 1646162, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10043,13,1792,13,54232351,2,"[54232351, 1646681, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10044,13,1793,13,54232351,2,"[54232351, 1647201, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10045,13,1794,13,54232351,2,"[54232351, 1647721, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10046,13,1795,13,54232351,2,"[54232351, 1648243, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10047,13,1796,13,54232351,2,"[54232351, 1648764, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10048,13,1797,13,54232351,2,"[54232351, 1649287, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10049,13,1798,13,54232351,2,"[54232351, 1649810, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10050,13,1799,13,54232351,2,"[54232351, 1650334, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10051,13,1800,13,54232351,2,"[54232351, 1650859, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10052,13,1801,13,54232351,2,"[54232351, 1651384, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10053,13,1802,13,54232351,2,"[54232351, 1651910, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10054,13,1803,13,54232351,2,"[54232351, 1652437, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10055,13,1804,13,54232351,2,"[54232351, 1652964, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10056,13,1805,13,54232351,2,"[54232351, 1653492, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10057,13,1806,13,54232351,2,"[54232351, 1654021, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10058,13,1807,13,54232351,2,"[54232351, 1654550, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10059,13,1808,13,54232351,2,"[54232351, 1655081, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10060,13,1809,13,54232351,2,"[54232351, 1655611, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10061,13,1810,13,54232351,2,"[54232351, 1656143, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10062,13,1811,13,54232351,2,"[54232351, 1656675, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10063,13,1812,13,54232351,2,"[54232351, 1657208, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10064,13,1813,13,54232351,2,"[54232351, 1657742, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10065,13,1814,13,54232351,2,"[54232351, 1658276, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10066,13,1815,13,54232351,2,"[54232351, 1658812, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10067,13,1816,13,54232351,2,"[54232351, 1659347, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10068,13,1817,13,54232351,2,"[54232351, 1659884, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10069,13,1818,13,54232351,2,"[54232351, 1660421, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10070,13,1819,13,54232351,2,"[54232351, 1660959, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10071,13,1820,13,54232351,2,"[54232351, 1661498, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10072,13,1821,13,54232351,2,"[54232351, 1662037, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10073,13,1822,13,54232351,2,"[54232351, 1662577, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10074,13,1823,13,54232351,2,"[54232351, 1663118, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10075,13,1824,13,54232351,2,"[54232351, 1663659, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10076,13,1825,13,54232351,2,"[54232351, 1664201, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10077,13,1826,13,54232351,2,"[54232351, 1664744, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10078,13,1827,13,54232351,2,"[54232351, 1665287, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10079,13,1828,13,54232351,2,"[54232351, 1665832, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10080,13,1829,13,54232351,2,"[54232351, 1666376, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10081,13,1830,13,54232351,2,"[54232351, 1666922, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10082,13,1831,13,54232351,2,"[54232351, 1667468, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10083,13,1832,13,54232351,2,"[54232351, 1668015, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10084,13,1833,13,54232351,2,"[54232351, 1668563, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10085,13,1834,13,54232351,2,"[54232351, 1669111, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10086,13,1835,13,54232351,2,"[54232351, 1669661, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10087,13,1836,13,54232351,2,"[54232351, 1670210, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10088,13,1837,13,54232351,2,"[54232351, 1670761, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10089,13,1838,13,54232351,2,"[54232351, 1671312, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10090,13,1839,13,54232351,2,"[54232351, 1671864, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10091,13,1840,13,54232351,2,"[54232351, 1672417, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10092,13,1841,13,54232351,2,"[54232351, 1672970, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10093,13,1842,13,54232351,2,"[54232351, 1673524, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10094,13,1843,13,54232351,2,"[54232351, 1674079, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10095,13,1844,13,54232351,2,"[54232351, 1674634, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10096,13,1845,13,54232351,2,"[54232351, 1675190, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10097,13,1846,13,54232351,2,"[54232351, 1675747, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10098,13,1847,13,54232351,2,"[54232351, 1676304, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10099,13,1848,13,54232351,2,"[54232351, 1676863, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10100,13,1849,13,54232351,2,"[54232351, 1677421, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10101,13,1850,13,54232351,2,"[54232351, 1677981, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10102,13,1851,13,54232351,2,"[54232351, 1678541, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10103,13,1852,13,54232351,2,"[54232351, 1679102, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10104,13,1853,13,54232351,2,"[54232351, 1679664, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10105,13,1854,13,54232351,2,"[54232351, 1680226, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10106,13,1855,13,54232351,2,"[54232351, 1680790, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10107,13,1856,13,54232351,2,"[54232351, 1681353, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10108,13,1857,13,54232351,2,"[54232351, 1681918, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10109,13,1858,13,54232351,2,"[54232351, 1682483, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10110,13,1859,13,54232351,2,"[54232351, 1683049, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10111,13,1860,13,54232351,2,"[54232351, 1683616, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10112,13,1861,13,54232351,2,"[54232351, 1684183, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10113,13,1862,13,54232351,2,"[54232351, 1684751, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10114,13,1863,13,54232351,2,"[54232351, 1685320, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10115,13,1864,13,54232351,2,"[54232351, 1685889, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10116,13,1865,13,54232351,2,"[54232351, 1686459, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10117,13,1866,13,54232351,2,"[54232351, 1687030, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10118,13,1867,13,54232351,2,"[54232351, 1687601, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10119,13,1868,13,54232351,2,"[54232351, 1688174, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10120,13,1869,13,54232351,2,"[54232351, 1688746, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10121,13,1870,13,54232351,2,"[54232351, 1689320, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10122,13,1871,13,54232351,2,"[54232351, 1689894, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10123,13,1872,13,54232351,2,"[54232351, 1690469, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10124,13,1873,13,54232351,2,"[54232351, 1691045, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10125,13,1874,13,54232351,2,"[54232351, 1691621, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10126,13,1875,13,54232351,2,"[54232351, 1692199, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10127,13,1876,13,54232351,2,"[54232351, 1692776, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10128,13,1877,13,54232351,2,"[54232351, 1693355, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10129,13,1878,13,54232351,2,"[54232351, 1693934, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10130,13,1879,13,54232351,2,"[54232351, 1694514, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10131,13,1880,13,54232351,2,"[54232351, 1695095, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10132,13,1881,13,54232351,2,"[54232351, 1695676, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10133,13,1882,13,54232351,2,"[54232351, 1696258, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10134,13,1883,13,54232351,2,"[54232351, 1696841, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10135,13,1884,13,54232351,2,"[54232351, 1697424, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10136,13,1885,13,54232351,2,"[54232351, 1698008, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10137,13,1886,13,54232351,2,"[54232351, 1698593, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10138,13,1887,13,54232351,2,"[54232351, 1699178, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10139,13,1888,13,54232351,2,"[54232351, 1699765, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10140,13,1889,13,54232351,2,"[54232351, 1700351, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10141,13,1890,13,54232351,2,"[54232351, 1700939, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10142,13,1891,13,54232351,2,"[54232351, 1701527, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10143,13,1892,13,54232351,2,"[54232351, 1702116, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10144,13,1893,13,54232351,2,"[54232351, 1702706, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10145,13,1894,13,54232351,2,"[54232351, 1703296, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10146,13,1895,13,54232351,2,"[54232351, 1703888, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10147,13,1896,13,54232351,2,"[54232351, 1704479, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10148,13,1897,13,54232351,2,"[54232351, 1705072, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10149,13,1898,13,54232351,2,"[54232351, 1705665, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10150,13,1899,13,54232351,2,"[54232351, 1706259, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10151,13,1900,13,54232351,2,"[54232351, 1706854, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10152,13,1901,13,54232351,2,"[54232351, 1707449, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10153,13,1902,13,54232351,2,"[54232351, 1708045, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10154,13,1903,13,54232351,2,"[54232351, 1708642, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10155,13,1904,13,54232351,2,"[54232351, 1709239, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10156,13,1905,13,54232351,2,"[54232351, 1709837, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10157,13,1906,13,54232351,2,"[54232351, 1710436, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10158,13,1907,13,54232351,2,"[54232351, 1711035, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10159,13,1908,13,54232351,2,"[54232351, 1711636, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10160,13,1909,13,54232351,2,"[54232351, 1712236, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10161,13,1910,13,54232351,2,"[54232351, 1712838, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10162,13,1911,13,54232351,2,"[54232351, 1713440, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10163,13,1912,13,54232351,2,"[54232351, 1714043, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10164,13,1913,13,54232351,2,"[54232351, 1714647, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10165,13,1914,13,54232351,2,"[54232351, 1715251, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10166,13,1915,13,54232351,2,"[54232351, 1715857, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10167,13,1916,13,54232351,2,"[54232351, 1716462, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10168,13,1917,13,54232351,2,"[54232351, 1717069, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10169,13,1918,13,54232351,2,"[54232351, 1717676, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10170,13,1919,13,54232351,2,"[54232351, 1718284, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10171,13,1920,13,54232351,2,"[54232351, 1718893, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10172,13,1921,13,54232351,2,"[54232351, 1719502, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10173,13,1922,13,54232351,2,"[54232351, 1720112, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10174,13,1923,13,54232351,2,"[54232351, 1720723, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10175,13,1924,13,54232351,2,"[54232351, 1721334, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10176,13,1925,13,54232351,2,"[54232351, 1721946, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10177,13,1926,13,54232351,2,"[54232351, 1722559, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10178,13,1927,13,54232351,2,"[54232351, 1723172, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10179,13,1928,13,54232351,2,"[54232351, 1723787, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10180,13,1929,13,54232351,2,"[54232351, 1724401, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10181,13,1930,13,54232351,2,"[54232351, 1725017, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10182,13,1931,13,54232351,2,"[54232351, 1725633, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10183,13,1932,13,54232351,2,"[54232351, 1726250, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10184,13,1933,13,54232351,2,"[54232351, 1726868, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10185,13,1934,13,54232351,2,"[54232351, 1727486, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10186,13,1935,13,54232351,2,"[54232351, 1728106, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10187,13,1936,13,54232351,2,"[54232351, 1728725, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10188,13,1937,13,54232351,2,"[54232351, 1729346, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10189,13,1938,13,54232351,2,"[54232351, 1729967, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10190,13,1939,13,54232351,2,"[54232351, 1730589, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10191,13,1940,13,54232351,2,"[54232351, 1731212, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10192,13,1941,13,54232351,2,"[54232351, 1731835, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10193,13,1942,13,54232351,2,"[54232351, 1732459, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10194,13,1943,13,54232351,2,"[54232351, 1733084, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10195,13,1944,13,54232351,2,"[54232351, 1733709, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10196,13,1945,13,54232351,2,"[54232351, 1734335, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10197,13,1946,13,54232351,2,"[54232351, 1734962, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10198,13,1947,13,54232351,2,"[54232351, 1735589, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10199,13,1948,13,54232351,2,"[54232351, 1736218, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10200,13,1949,13,54232351,2,"[54232351, 1736846, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10201,13,1950,13,54232351,2,"[54232351, 1737476, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10202,13,1951,13,54232351,2,"[54232351, 1738106, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10203,13,1952,13,54232351,2,"[54232351, 1738737, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10204,13,1953,13,54232351,2,"[54232351, 1739369, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10205,13,1954,13,54232351,2,"[54232351, 1740001, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10206,13,1955,13,54232351,2,"[54232351, 1740635, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10207,13,1956,13,54232351,2,"[54232351, 1741268, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10208,13,1957,13,54232351,2,"[54232351, 1741903, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10209,13,1958,13,54232351,2,"[54232351, 1742538, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10210,13,1959,13,54232351,2,"[54232351, 1743174, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10211,13,1960,13,54232351,2,"[54232351, 1743811, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10212,13,1961,13,54232351,2,"[54232351, 1744448, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10213,13,1962,13,54232351,2,"[54232351, 1745086, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10214,13,1963,13,54232351,2,"[54232351, 1745725, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10215,13,1964,13,54232351,2,"[54232351, 1746364, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10216,13,1965,13,54232351,2,"[54232351, 1747004, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10217,13,1966,13,54232351,2,"[54232351, 1747645, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10218,13,1967,13,54232351,2,"[54232351, 1748286, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10219,13,1968,13,54232351,2,"[54232351, 1748929, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10220,13,1969,13,54232351,2,"[54232351, 1749571, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10221,13,1970,13,54232351,2,"[54232351, 1750215, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10222,13,1971,13,54232351,2,"[54232351, 1750859, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10223,13,1972,13,54232351,2,"[54232351, 1751504, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10224,13,1973,13,54232351,2,"[54232351, 1752150, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10225,13,1974,13,54232351,2,"[54232351, 1752796, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10226,13,1975,13,54232351,2,"[54232351, 1753444, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10227,13,1976,13,54232351,2,"[54232351, 1754091, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10228,13,1977,13,54232351,2,"[54232351, 1754740, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10229,13,1978,13,54232351,2,"[54232351, 1755389, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10230,13,1979,13,54232351,2,"[54232351, 1756039, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10231,13,1980,13,54232351,2,"[54232351, 1756690, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10232,13,1981,13,54232351,2,"[54232351, 1757341, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10233,13,1982,13,54232351,2,"[54232351, 1757993, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10234,13,1983,13,54232351,2,"[54232351, 1758646, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10235,13,1984,13,54232351,2,"[54232351, 1759299, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10236,13,1985,13,54232351,2,"[54232351, 1759953, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10237,13,1986,13,54232351,2,"[54232351, 1760608, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10238,13,1987,13,54232351,2,"[54232351, 1761263, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10239,13,1988,13,54232351,2,"[54232351, 1761920, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10240,13,1989,13,54232351,2,"[54232351, 1762576, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10241,13,1990,13,54232351,2,"[54232351, 1763234, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10242,13,1991,13,54232351,2,"[54232351, 1763892, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10243,13,1992,13,54232351,2,"[54232351, 1764551, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10244,13,1993,13,54232351,2,"[54232351, 1765211, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10245,13,1994,13,54232351,2,"[54232351, 1765871, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10246,13,1995,13,54232351,2,"[54232351, 1766533, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10247,13,1996,13,54232351,2,"[54232351, 1767194, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10248,13,1997,13,54232351,2,"[54232351, 1767857, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10249,13,1998,13,54232351,2,"[54232351, 1768520, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10250,13,1999,13,54232351,2,"[54232351, 1769184, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10251,13,2000,13,54232351,2,"[54232351, 1769849, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10252,13,2001,13,54232351,2,"[54232351, 1770514, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10253,13,2002,13,54232351,2,"[54232351, 1771180, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10254,13,2003,13,54232351,2,"[54232351, 1771847, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10255,13,2004,13,54232351,2,"[54232351, 1772514, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10256,13,2005,13,54232351,2,"[54232351, 1773182, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10257,13,2006,13,54232351,2,"[54232351, 1773851, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10258,13,2007,13,54232351,2,"[54232351, 1774520, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10259,13,2008,13,54232351,2,"[54232351, 1775191, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10260,13,2009,13,54232351,2,"[54232351, 1775861, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10261,13,2010,13,54232351,2,"[54232351, 1776533, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10262,13,2011,13,54232351,2,"[54232351, 1777205, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10263,13,2012,13,54232351,2,"[54232351, 1777878, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10264,13,2013,13,54232351,2,"[54232351, 1778552, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10265,13,2014,13,54232351,2,"[54232351, 1779226, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10266,13,2015,13,54232351,2,"[54232351, 1779902, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10267,13,2016,13,54232351,2,"[54232351, 1780577, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10268,13,2017,13,54232351,2,"[54232351, 1781254, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10269,13,2018,13,54232351,2,"[54232351, 1781931, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10270,13,2019,13,54232351,2,"[54232351, 1782609, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10271,13,2020,13,54232351,2,"[54232351, 1783288, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10272,13,2021,13,54232351,2,"[54232351, 1783967, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10273,13,2022,13,54232351,2,"[54232351, 1784647, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10274,13,2023,13,54232351,2,"[54232351, 1785328, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10275,13,2024,13,54232351,2,"[54232351, 1786009, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10276,13,2025,13,54232351,2,"[54232351, 1786691, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10277,13,2026,13,54232351,2,"[54232351, 1787374, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10278,13,2027,13,54232351,2,"[54232351, 1788057, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10279,13,2028,13,54232351,2,"[54232351, 1788742, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10280,13,2029,13,54232351,2,"[54232351, 1789426, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10281,13,2030,13,54232351,2,"[54232351, 1790112, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10282,13,2031,13,54232351,2,"[54232351, 1790798, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10283,13,2032,13,54232351,2,"[54232351, 1791485, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10284,13,2033,13,54232351,2,"[54232351, 1792173, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10285,13,2034,13,54232351,2,"[54232351, 1792861, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10286,13,2035,13,54232351,2,"[54232351, 1793551, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10287,13,2036,13,54232351,2,"[54232351, 1794240, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10288,13,2037,13,54232351,2,"[54232351, 1794931, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10289,13,2038,13,54232351,2,"[54232351, 1795622, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10290,13,2039,13,54232351,2,"[54232351, 1796314, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10291,13,2040,13,54232351,2,"[54232351, 1797007, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10292,13,2041,13,54232351,2,"[54232351, 1797700, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10293,13,2042,13,54232351,2,"[54232351, 1798394, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10294,13,2043,13,54232351,2,"[54232351, 1799089, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10295,13,2044,13,54232351,2,"[54232351, 1799784, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10296,13,2045,13,54232351,2,"[54232351, 1800480, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10297,13,2046,13,54232351,2,"[54232351, 1801177, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10298,13,2047,13,54232351,2,"[54232351, 1801874, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10299,13,2048,13,54232351,2,"[54232351, 1802573, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10300,13,2049,13,54232351,2,"[54232351, 1803271, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10301,13,2050,13,54232351,2,"[54232351, 1803971, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10302,13,2051,13,54232351,2,"[54232351, 1804671, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10303,13,2052,13,54232351,2,"[54232351, 1805372, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10304,13,2053,13,54232351,2,"[54232351, 1806074, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10305,13,2054,13,54232351,2,"[54232351, 1806776, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10306,13,2055,13,54232351,2,"[54232351, 1807480, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10307,13,2056,13,54232351,2,"[54232351, 1808183, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10308,13,2057,13,54232351,2,"[54232351, 1808888, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10309,13,2058,13,54232351,2,"[54232351, 1809593, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10310,13,2059,13,54232351,2,"[54232351, 1810299, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10311,13,2060,13,54232351,2,"[54232351, 1811006, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10312,13,2061,13,54232351,2,"[54232351, 1811713, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10313,13,2062,13,54232351,2,"[54232351, 1812421, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10314,13,2063,13,54232351,2,"[54232351, 1813130, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10315,13,2064,13,54232351,2,"[54232351, 1813839, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10316,13,2065,13,54232351,2,"[54232351, 1814549, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10317,13,2066,13,54232351,2,"[54232351, 1815260, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10318,13,2067,13,54232351,2,"[54232351, 1815971, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10319,13,2068,13,54232351,2,"[54232351, 1816684, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10320,13,2069,13,54232351,2,"[54232351, 1817396, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10321,13,2070,13,54232351,2,"[54232351, 1818110, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10322,13,2071,13,54232351,2,"[54232351, 1818824, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10323,13,2072,13,54232351,2,"[54232351, 1819539, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10324,13,2073,13,54232351,2,"[54232351, 1820255, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10325,13,2074,13,54232351,2,"[54232351, 1820971, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10326,13,2075,13,54232351,2,"[54232351, 1821689, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10327,13,2076,13,54232351,2,"[54232351, 1822406, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10328,13,2077,13,54232351,2,"[54232351, 1823125, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10329,13,2078,13,54232351,2,"[54232351, 1823844, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10330,13,2079,13,54232351,2,"[54232351, 1824564, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10331,13,2080,13,54232351,2,"[54232351, 1825285, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10332,13,2081,13,54232351,2,"[54232351, 1826006, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10333,13,2082,13,54232351,2,"[54232351, 1826728, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10334,13,2083,13,54232351,2,"[54232351, 1827451, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10335,13,2084,13,54232351,2,"[54232351, 1828174, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10336,13,2085,13,54232351,2,"[54232351, 1828898, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10337,13,2086,13,54232351,2,"[54232351, 1829623, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10338,13,2087,13,54232351,2,"[54232351, 1830348, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10339,13,2088,13,54232351,2,"[54232351, 1831075, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10340,13,2089,13,54232351,2,"[54232351, 1831801, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10341,13,2090,13,54232351,2,"[54232351, 1832529, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10342,13,2091,13,54232351,2,"[54232351, 1833257, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10343,13,2092,13,54232351,2,"[54232351, 1833986, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10344,13,2093,13,54232351,2,"[54232351, 1834716, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10345,13,2094,13,54232351,2,"[54232351, 1835446, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10346,13,2095,13,54232351,2,"[54232351, 1836178, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10347,13,2096,13,54232351,2,"[54232351, 1836909, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10348,13,2097,13,54232351,2,"[54232351, 1837642, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10349,13,2098,13,54232351,2,"[54232351, 1838375, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10350,13,2099,13,54232351,2,"[54232351, 1839109, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10351,13,2100,13,54232351,2,"[54232351, 1839844, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10352,13,2101,13,54232351,2,"[54232351, 1840579, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10353,13,2102,13,54232351,2,"[54232351, 1841315, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10354,13,2103,13,54232351,2,"[54232351, 1842052, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10355,13,2104,13,54232351,2,"[54232351, 1842789, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10356,13,2105,13,54232351,2,"[54232351, 1843527, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10357,13,2106,13,54232351,2,"[54232351, 1844266, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10358,13,2107,13,54232351,2,"[54232351, 1845005, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10359,13,2108,13,54232351,2,"[54232351, 1845746, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10360,13,2109,13,54232351,2,"[54232351, 1846486, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10361,13,2110,13,54232351,2,"[54232351, 1847228, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10362,13,2111,13,54232351,2,"[54232351, 1847970, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10363,13,2112,13,54232351,2,"[54232351, 1848713, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10364,13,2113,13,54232351,2,"[54232351, 1849457, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10365,13,2114,13,54232351,2,"[54232351, 1850201, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10366,13,2115,13,54232351,2,"[54232351, 1850947, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10367,13,2116,13,54232351,2,"[54232351, 1851692, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10368,13,2117,13,54232351,2,"[54232351, 1852439, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10369,13,2118,13,54232351,2,"[54232351, 1853186, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10370,13,2119,13,54232351,2,"[54232351, 1853934, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10371,13,2120,13,54232351,2,"[54232351, 1854683, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10372,13,2121,13,54232351,2,"[54232351, 1855432, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10373,13,2122,13,54232351,2,"[54232351, 1856182, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10374,13,2123,13,54232351,2,"[54232351, 1856933, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10375,13,2124,13,54232351,2,"[54232351, 1857684, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10376,13,2125,13,54232351,2,"[54232351, 1858436, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10377,13,2126,13,54232351,2,"[54232351, 1859189, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10378,13,2127,13,54232351,2,"[54232351, 1859942, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10379,13,2128,13,54232351,2,"[54232351, 1860697, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10380,13,2129,13,54232351,2,"[54232351, 1861451, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10381,13,2130,13,54232351,2,"[54232351, 1862207, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10382,13,2131,13,54232351,2,"[54232351, 1862963, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10383,13,2132,13,54232351,2,"[54232351, 1863720, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10384,13,2133,13,54232351,2,"[54232351, 1864478, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10385,13,2134,13,54232351,2,"[54232351, 1865236, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10386,13,2135,13,54232351,2,"[54232351, 1865996, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10387,13,2136,13,54232351,2,"[54232351, 1866755, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10388,13,2137,13,54232351,2,"[54232351, 1867516, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10389,13,2138,13,54232351,2,"[54232351, 1868277, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10390,13,2139,13,54232351,2,"[54232351, 1869039, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10391,13,2140,13,54232351,2,"[54232351, 1869802, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10392,13,2141,13,54232351,2,"[54232351, 1870565, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10393,13,2142,13,54232351,2,"[54232351, 1871329, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10394,13,2143,13,54232351,2,"[54232351, 1872094, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10395,13,2144,13,54232351,2,"[54232351, 1872859, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10396,13,2145,13,54232351,2,"[54232351, 1873625, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10397,13,2146,13,54232351,2,"[54232351, 1874392, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10398,13,2147,13,54232351,2,"[54232351, 1875159, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10399,13,2148,13,54232351,2,"[54232351, 1875928, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10400,13,2149,13,54232351,2,"[54232351, 1876696, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10401,13,2150,13,54232351,2,"[54232351, 1877466, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10402,13,2151,13,54232351,2,"[54232351, 1878236, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10403,13,2152,13,54232351,2,"[54232351, 1879007, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10404,13,2153,13,54232351,2,"[54232351, 1879779, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10405,13,2154,13,54232351,2,"[54232351, 1880551, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10406,13,2155,13,54232351,2,"[54232351, 1881325, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10407,13,2156,13,54232351,2,"[54232351, 1882098, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10408,13,2157,13,54232351,2,"[54232351, 1882873, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10409,13,2158,13,54232351,2,"[54232351, 1883648, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10410,13,2159,13,54232351,2,"[54232351, 1884424, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10411,13,2160,13,54232351,2,"[54232351, 1885201, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10412,13,2161,13,54232351,2,"[54232351, 1885978, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10413,13,2162,13,54232351,2,"[54232351, 1886756, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10414,13,2163,13,54232351,2,"[54232351, 1887535, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10415,13,2164,13,54232351,2,"[54232351, 1888314, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10416,13,2165,13,54232351,2,"[54232351, 1889094, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10417,13,2166,13,54232351,2,"[54232351, 1889875, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10418,13,2167,13,54232351,2,"[54232351, 1890656, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10419,13,2168,13,54232351,2,"[54232351, 1891439, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10420,13,2169,13,54232351,2,"[54232351, 1892221, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10421,13,2170,13,54232351,2,"[54232351, 1893005, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10422,13,2171,13,54232351,2,"[54232351, 1893789, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10423,13,2172,13,54232351,2,"[54232351, 1894574, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10424,13,2173,13,54232351,2,"[54232351, 1895360, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10425,13,2174,13,54232351,2,"[54232351, 1896146, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10426,13,2175,13,54232351,2,"[54232351, 1896934, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10427,13,2176,13,54232351,2,"[54232351, 1897721, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10428,13,2177,13,54232351,2,"[54232351, 1898510, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10429,13,2178,13,54232351,2,"[54232351, 1899299, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10430,13,2179,13,54232351,2,"[54232351, 1900089, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10431,13,2180,13,54232351,2,"[54232351, 1900880, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10432,13,2181,13,54232351,2,"[54232351, 1901671, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10433,13,2182,13,54232351,2,"[54232351, 1902463, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10434,13,2183,13,54232351,2,"[54232351, 1903256, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10435,13,2184,13,54232351,2,"[54232351, 1904049, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10436,13,2185,13,54232351,2,"[54232351, 1904843, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10437,13,2186,13,54232351,2,"[54232351, 1905638, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10438,13,2187,13,54232351,2,"[54232351, 1906433, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10439,13,2188,13,54232351,2,"[54232351, 1907230, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10440,13,2189,13,54232351,2,"[54232351, 1908026, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10441,13,2190,13,54232351,2,"[54232351, 1908824, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10442,13,2191,13,54232351,2,"[54232351, 1909622, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10443,13,2192,13,54232351,2,"[54232351, 1910421, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10444,13,2193,13,54232351,2,"[54232351, 1911221, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10445,13,2194,13,54232351,2,"[54232351, 1912021, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10446,13,2195,13,54232351,2,"[54232351, 1912823, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10447,13,2196,13,54232351,2,"[54232351, 1913624, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10448,13,2197,13,54232351,2,"[54232351, 1914427, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10449,13,2198,13,54232351,2,"[54232351, 1915230, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10450,13,2199,13,54232351,2,"[54232351, 1916034, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10451,13,2200,13,54232351,2,"[54232351, 1916839, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10452,13,2201,13,54232351,2,"[54232351, 1917644, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10453,13,2202,13,54232351,2,"[54232351, 1918450, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10454,13,2203,13,54232351,2,"[54232351, 1919257, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10455,13,2204,13,54232351,2,"[54232351, 1920064, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10456,13,2205,13,54232351,2,"[54232351, 1920872, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10457,13,2206,13,54232351,2,"[54232351, 1921681, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10458,13,2207,13,54232351,2,"[54232351, 1922490, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10459,13,2208,13,54232351,2,"[54232351, 1923301, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10460,13,2209,13,54232351,2,"[54232351, 1924111, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10461,13,2210,13,54232351,2,"[54232351, 1924923, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10462,13,2211,13,54232351,2,"[54232351, 1925735, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10463,13,2212,13,54232351,2,"[54232351, 1926548, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10464,13,2213,13,54232351,2,"[54232351, 1927362, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10465,13,2214,13,54232351,2,"[54232351, 1928176, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10466,13,2215,13,54232351,2,"[54232351, 1928992, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10467,13,2216,13,54232351,2,"[54232351, 1929807, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10468,13,2217,13,54232351,2,"[54232351, 1930624, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10469,13,2218,13,54232351,2,"[54232351, 1931441, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10470,13,2219,13,54232351,2,"[54232351, 1932259, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10471,13,2220,13,54232351,2,"[54232351, 1933078, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10472,13,2221,13,54232351,2,"[54232351, 1933897, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10473,13,2222,13,54232351,2,"[54232351, 1934717, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10474,13,2223,13,54232351,2,"[54232351, 1935538, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10475,13,2224,13,54232351,2,"[54232351, 1936359, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10476,13,2225,13,54232351,2,"[54232351, 1937181, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10477,13,2226,13,54232351,2,"[54232351, 1938004, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10478,13,2227,13,54232351,2,"[54232351, 1938827, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10479,13,2228,13,54232351,2,"[54232351, 1939652, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10480,13,2229,13,54232351,2,"[54232351, 1940476, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10481,13,2230,13,54232351,2,"[54232351, 1941302, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10482,13,2231,13,54232351,2,"[54232351, 1942128, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10483,13,2232,13,54232351,2,"[54232351, 1942955, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10484,13,2233,13,54232351,2,"[54232351, 1943783, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10485,13,2234,13,54232351,2,"[54232351, 1944611, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10486,13,2235,13,54232351,2,"[54232351, 1945441, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10487,13,2236,13,54232351,2,"[54232351, 1946270, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10488,13,2237,13,54232351,2,"[54232351, 1947101, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10489,13,2238,13,54232351,2,"[54232351, 1947932, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10490,13,2239,13,54232351,2,"[54232351, 1948764, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10491,13,2240,13,54232351,2,"[54232351, 1949597, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10492,13,2241,13,54232351,2,"[54232351, 1950430, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10493,13,2242,13,54232351,2,"[54232351, 1951264, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10494,13,2243,13,54232351,2,"[54232351, 1952099, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10495,13,2244,13,54232351,2,"[54232351, 1952934, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10496,13,2245,13,54232351,2,"[54232351, 1953770, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10497,13,2246,13,54232351,2,"[54232351, 1954607, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10498,13,2247,13,54232351,2,"[54232351, 1955444, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10499,13,2248,13,54232351,2,"[54232351, 1956283, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10500,13,2249,13,54232351,2,"[54232351, 1957121, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10501,13,2250,13,54232351,2,"[54232351, 1957961, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10502,13,2251,13,54232351,2,"[54232351, 1958801, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10503,13,2252,13,54232351,2,"[54232351, 1959642, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10504,13,2253,13,54232351,2,"[54232351, 1960484, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10505,13,2254,13,54232351,2,"[54232351, 1961326, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10506,13,2255,13,54232351,2,"[54232351, 1962170, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10507,13,2256,13,54232351,2,"[54232351, 1963013, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10508,13,2257,13,54232351,2,"[54232351, 1963858, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10509,13,2258,13,54232351,2,"[54232351, 1964703, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10510,13,2259,13,54232351,2,"[54232351, 1965549, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10511,13,2260,13,54232351,2,"[54232351, 1966396, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10512,13,2261,13,54232351,2,"[54232351, 1967243, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10513,13,2262,13,54232351,2,"[54232351, 1968091, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10514,13,2263,13,54232351,2,"[54232351, 1968940, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10515,13,2264,13,54232351,2,"[54232351, 1969789, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10516,13,2265,13,54232351,2,"[54232351, 1970639, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10517,13,2266,13,54232351,2,"[54232351, 1971490, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10518,13,2267,13,54232351,2,"[54232351, 1972341, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10519,13,2268,13,54232351,2,"[54232351, 1973194, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10520,13,2269,13,54232351,2,"[54232351, 1974046, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10521,13,2270,13,54232351,2,"[54232351, 1974900, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10522,13,2271,13,54232351,2,"[54232351, 1975754, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10523,13,2272,13,54232351,2,"[54232351, 1976609, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10524,13,2273,13,54232351,2,"[54232351, 1977465, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10525,13,2274,13,54232351,2,"[54232351, 1978321, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10526,13,2275,13,54232351,2,"[54232351, 1979179, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10527,13,2276,13,54232351,2,"[54232351, 1980036, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10528,13,2277,13,54232351,2,"[54232351, 1980895, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10529,13,2278,13,54232351,2,"[54232351, 1981754, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10530,13,2279,13,54232351,2,"[54232351, 1982614, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10531,13,2280,13,54232351,2,"[54232351, 1983475, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10532,13,2281,13,54232351,2,"[54232351, 1984336, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10533,13,2282,13,54232351,2,"[54232351, 1985198, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10534,13,2283,13,54232351,2,"[54232351, 1986061, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10535,13,2284,13,54232351,2,"[54232351, 1986924, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10536,13,2285,13,54232351,2,"[54232351, 1987788, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10537,13,2286,13,54232351,2,"[54232351, 1988653, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10538,13,2287,13,54232351,2,"[54232351, 1989518, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10539,13,2288,13,54232351,2,"[54232351, 1990385, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10540,13,2289,13,54232351,2,"[54232351, 1991251, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10541,13,2290,13,54232351,2,"[54232351, 1992119, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10542,13,2291,13,54232351,2,"[54232351, 1992987, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10543,13,2292,13,54232351,2,"[54232351, 1993856, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10544,13,2293,13,54232351,2,"[54232351, 1994726, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10545,13,2294,13,54232351,2,"[54232351, 1995596, 6, False]",54232351,54232350,1995858,54232352,False,True,True,False,46875,8738,3615490,2508,2007,True,True,True,False,False,False,False -10546,14,0,15,54232352,2,"[54232351, 1996468, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10547,14,1,15,54232352,2,"[54232351, 1997339, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10548,14,2,15,54232352,2,"[54232351, 1998212, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10549,14,3,15,54232352,2,"[54232351, 1999085, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10550,14,4,15,54232352,2,"[54232351, 1999959, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10551,14,5,15,54232352,2,"[54232352, 834, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10552,14,6,15,54232352,2,"[54232352, 1709, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10553,14,7,15,54232352,2,"[54232352, 2585, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10554,14,8,15,54232352,2,"[54232352, 3462, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10555,14,9,15,54232352,2,"[54232352, 4339, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10556,14,10,15,54232352,2,"[54232352, 5217, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10557,14,11,15,54232352,2,"[54232352, 6096, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10558,14,12,15,54232352,2,"[54232352, 6975, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10559,14,13,15,54232352,2,"[54232352, 7856, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10560,14,14,15,54232352,2,"[54232352, 8736, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10561,14,15,15,54232352,2,"[54232352, 9618, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10562,14,16,15,54232352,2,"[54232352, 10500, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10563,14,17,15,54232352,2,"[54232352, 11383, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10564,14,18,15,54232352,2,"[54232352, 12267, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10565,14,19,15,54232352,2,"[54232352, 13151, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10566,14,20,15,54232352,2,"[54232352, 14037, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10567,14,21,15,54232352,2,"[54232352, 14922, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10568,14,22,15,54232352,2,"[54232352, 15809, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10569,14,23,15,54232352,2,"[54232352, 16696, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10570,14,24,15,54232352,2,"[54232352, 17584, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10571,14,25,15,54232352,2,"[54232352, 18473, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10572,14,26,15,54232352,2,"[54232352, 19362, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10573,14,27,15,54232352,2,"[54232352, 20252, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10574,14,28,15,54232352,2,"[54232352, 21143, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10575,14,29,15,54232352,2,"[54232352, 22034, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10576,14,30,15,54232352,2,"[54232352, 22926, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10577,14,31,15,54232352,2,"[54232352, 23819, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10578,14,32,15,54232352,2,"[54232352, 24712, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10579,14,33,15,54232352,2,"[54232352, 25607, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10580,14,34,15,54232352,2,"[54232352, 26501, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10581,14,35,15,54232352,2,"[54232352, 27397, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10582,14,36,15,54232352,2,"[54232352, 28293, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10583,14,37,15,54232352,2,"[54232352, 29190, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10584,14,38,15,54232352,2,"[54232352, 30088, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10585,14,39,15,54232352,2,"[54232352, 30986, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10586,14,40,15,54232352,2,"[54232352, 31886, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10587,14,41,15,54232352,2,"[54232352, 32785, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10588,14,42,15,54232352,2,"[54232352, 33686, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10589,14,43,15,54232352,2,"[54232352, 34587, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10590,14,44,15,54232352,2,"[54232352, 35489, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10591,14,45,15,54232352,2,"[54232352, 36392, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10592,14,46,15,54232352,2,"[54232352, 37295, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10593,14,47,15,54232352,2,"[54232352, 38199, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10594,14,48,15,54232352,2,"[54232352, 39104, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10595,14,49,15,54232352,2,"[54232352, 40009, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10596,14,50,15,54232352,2,"[54232352, 40915, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10597,14,51,15,54232352,2,"[54232352, 41822, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10598,14,52,15,54232352,2,"[54232352, 42729, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10599,14,53,15,54232352,2,"[54232352, 43638, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10600,14,54,15,54232352,2,"[54232352, 44546, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10601,14,55,15,54232352,2,"[54232352, 45456, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10602,14,56,15,54232352,2,"[54232352, 46366, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10603,14,57,15,54232352,2,"[54232352, 47277, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10604,14,58,15,54232352,2,"[54232352, 48189, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10605,14,59,15,54232352,2,"[54232352, 49101, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10606,14,60,15,54232352,2,"[54232352, 50015, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10607,14,61,15,54232352,2,"[54232352, 50928, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10608,14,62,15,54232352,2,"[54232352, 51843, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10609,14,63,15,54232352,2,"[54232352, 52758, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10610,14,64,15,54232352,2,"[54232352, 53674, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10611,14,65,15,54232352,2,"[54232352, 54591, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10612,14,66,15,54232352,2,"[54232352, 55508, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10613,14,67,15,54232352,2,"[54232352, 56426, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10614,14,68,15,54232352,2,"[54232352, 57345, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10615,14,69,15,54232352,2,"[54232352, 58264, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10616,14,70,15,54232352,2,"[54232352, 59184, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10617,14,71,15,54232352,2,"[54232352, 60105, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10618,14,72,15,54232352,2,"[54232352, 61026, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10619,14,73,15,54232352,2,"[54232352, 61949, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10620,14,74,15,54232352,2,"[54232352, 62871, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10621,14,75,15,54232352,2,"[54232352, 63795, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10622,14,76,15,54232352,2,"[54232352, 64719, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10623,14,77,15,54232352,2,"[54232352, 65644, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10624,14,78,15,54232352,2,"[54232352, 66570, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10625,14,79,15,54232352,2,"[54232352, 67496, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10626,14,80,15,54232352,2,"[54232352, 68424, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10627,14,81,15,54232352,2,"[54232352, 69351, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10628,14,82,15,54232352,2,"[54232352, 70280, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10629,14,83,15,54232352,2,"[54232352, 71209, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10630,14,84,15,54232352,2,"[54232352, 72139, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10631,14,85,15,54232352,2,"[54232352, 73070, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10632,14,86,15,54232352,2,"[54232352, 74001, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10633,14,87,15,54232352,2,"[54232352, 74933, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10634,14,88,15,54232352,2,"[54232352, 75866, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10635,14,89,15,54232352,2,"[54232352, 76799, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10636,14,90,15,54232352,2,"[54232352, 77733, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10637,14,91,15,54232352,2,"[54232352, 78668, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10638,14,92,15,54232352,2,"[54232352, 79603, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10639,14,93,15,54232352,2,"[54232352, 80540, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10640,14,94,15,54232352,2,"[54232352, 81476, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10641,14,95,15,54232352,2,"[54232352, 82414, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10642,14,96,15,54232352,2,"[54232352, 83352, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10643,14,97,15,54232352,2,"[54232352, 84291, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10644,14,98,15,54232352,2,"[54232352, 85231, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10645,14,99,15,54232352,2,"[54232352, 86171, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10646,14,100,15,54232352,2,"[54232352, 87113, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10647,14,101,15,54232352,2,"[54232352, 88054, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10648,14,102,15,54232352,2,"[54232352, 88997, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10649,14,103,15,54232352,2,"[54232352, 89940, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10650,14,104,15,54232352,2,"[54232352, 90884, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10651,14,105,15,54232352,2,"[54232352, 91829, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10652,14,106,15,54232352,2,"[54232352, 92774, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10653,14,107,15,54232352,2,"[54232352, 93720, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10654,14,108,15,54232352,2,"[54232352, 94667, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10655,14,109,15,54232352,2,"[54232352, 95614, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10656,14,110,15,54232352,2,"[54232352, 96562, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10657,14,111,15,54232352,2,"[54232352, 97511, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10658,14,112,15,54232352,2,"[54232352, 98460, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10659,14,113,15,54232352,2,"[54232352, 99411, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10660,14,114,15,54232352,2,"[54232352, 100361, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10661,14,115,15,54232352,2,"[54232352, 101313, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10662,14,116,15,54232352,2,"[54232352, 102265, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10663,14,117,15,54232352,2,"[54232352, 103218, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10664,14,118,15,54232352,2,"[54232352, 104172, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10665,14,119,15,54232352,2,"[54232352, 105126, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10666,14,120,15,54232352,2,"[54232352, 106082, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10667,14,121,15,54232352,2,"[54232352, 107037, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10668,14,122,15,54232352,2,"[54232352, 107994, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10669,14,123,15,54232352,2,"[54232352, 108951, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10670,14,124,15,54232352,2,"[54232352, 109909, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10671,14,125,15,54232352,2,"[54232352, 110868, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10672,14,126,15,54232352,2,"[54232352, 111827, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10673,14,127,15,54232352,2,"[54232352, 112787, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10674,14,128,15,54232352,2,"[54232352, 113748, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10675,14,129,15,54232352,2,"[54232352, 114709, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10676,14,130,15,54232352,2,"[54232352, 115671, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10677,14,131,15,54232352,2,"[54232352, 116634, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10678,14,132,15,54232352,2,"[54232352, 117597, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10679,14,133,15,54232352,2,"[54232352, 118562, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10680,14,134,15,54232352,2,"[54232352, 119526, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10681,14,135,15,54232352,2,"[54232352, 120492, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10682,14,136,15,54232352,2,"[54232352, 121458, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10683,14,137,15,54232352,2,"[54232352, 122425, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10684,14,138,15,54232352,2,"[54232352, 123393, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10685,14,139,15,54232352,2,"[54232352, 124361, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10686,14,140,15,54232352,2,"[54232352, 125331, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10687,14,141,15,54232352,2,"[54232352, 126300, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10688,14,142,15,54232352,2,"[54232352, 127271, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10689,14,143,15,54232352,2,"[54232352, 128242, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10690,14,144,15,54232352,2,"[54232352, 129214, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10691,14,145,15,54232352,2,"[54232352, 130187, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10692,14,146,15,54232352,2,"[54232352, 131160, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10693,14,147,15,54232352,2,"[54232352, 132134, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10694,14,148,15,54232352,2,"[54232352, 133109, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10695,14,149,15,54232352,2,"[54232352, 134084, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10696,14,150,15,54232352,2,"[54232352, 135060, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10697,14,151,15,54232352,2,"[54232352, 136037, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10698,14,152,15,54232352,2,"[54232352, 137014, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10699,14,153,15,54232352,2,"[54232352, 137993, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10700,14,154,15,54232352,2,"[54232352, 138971, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10701,14,155,15,54232352,2,"[54232352, 139951, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10702,14,156,15,54232352,2,"[54232352, 140931, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10703,14,157,15,54232352,2,"[54232352, 141912, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10704,14,158,15,54232352,2,"[54232352, 142894, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10705,14,159,15,54232352,2,"[54232352, 143876, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10706,14,160,15,54232352,2,"[54232352, 144860, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10707,14,161,15,54232352,2,"[54232352, 145843, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10708,14,162,15,54232352,2,"[54232352, 146828, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10709,14,163,15,54232352,2,"[54232352, 147813, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10710,14,164,15,54232352,2,"[54232352, 148799, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10711,14,165,15,54232352,2,"[54232352, 149786, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10712,14,166,15,54232352,2,"[54232352, 150773, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10713,14,167,15,54232352,2,"[54232352, 151761, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10714,14,168,15,54232352,2,"[54232352, 152750, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10715,14,169,15,54232352,2,"[54232352, 153739, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10716,14,170,15,54232352,2,"[54232352, 154729, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10717,14,171,15,54232352,2,"[54232352, 155720, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10718,14,172,15,54232352,2,"[54232352, 156711, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10719,14,173,15,54232352,2,"[54232352, 157704, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10720,14,174,15,54232352,2,"[54232352, 158696, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10721,14,175,15,54232352,2,"[54232352, 159690, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10722,14,176,15,54232352,2,"[54232352, 160684, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10723,14,177,15,54232352,2,"[54232352, 161679, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10724,14,178,15,54232352,2,"[54232352, 162675, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10725,14,179,15,54232352,2,"[54232352, 163671, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10726,14,180,15,54232352,2,"[54232352, 164669, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10727,14,181,15,54232352,2,"[54232352, 165666, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10728,14,182,15,54232352,2,"[54232352, 166665, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10729,14,183,15,54232352,2,"[54232352, 167664, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10730,14,184,15,54232352,2,"[54232352, 168664, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10731,14,185,15,54232352,2,"[54232352, 169665, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10732,14,186,15,54232352,2,"[54232352, 170666, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10733,14,187,15,54232352,2,"[54232352, 171668, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10734,14,188,15,54232352,2,"[54232352, 172671, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10735,14,189,15,54232352,2,"[54232352, 173674, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10736,14,190,15,54232352,2,"[54232352, 174678, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10737,14,191,15,54232352,2,"[54232352, 175683, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10738,14,192,15,54232352,2,"[54232352, 176688, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10739,14,193,15,54232352,2,"[54232352, 177695, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10740,14,194,15,54232352,2,"[54232352, 178701, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10741,14,195,15,54232352,2,"[54232352, 179709, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10742,14,196,15,54232352,2,"[54232352, 180717, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10743,14,197,15,54232352,2,"[54232352, 181726, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10744,14,198,15,54232352,2,"[54232352, 182736, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10745,14,199,15,54232352,2,"[54232352, 183746, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10746,14,200,15,54232352,2,"[54232352, 184758, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10747,14,201,15,54232352,2,"[54232352, 185769, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10748,14,202,15,54232352,2,"[54232352, 186782, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10749,14,203,15,54232352,2,"[54232352, 187795, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10750,14,204,15,54232352,2,"[54232352, 188809, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10751,14,205,15,54232352,2,"[54232352, 189824, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10752,14,206,15,54232352,2,"[54232352, 190839, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10753,14,207,15,54232352,2,"[54232352, 191855, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10754,14,208,15,54232352,2,"[54232352, 192872, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10755,14,209,15,54232352,2,"[54232352, 193889, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10756,14,210,15,54232352,2,"[54232352, 194907, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10757,14,211,15,54232352,2,"[54232352, 195926, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10758,14,212,15,54232352,2,"[54232352, 196945, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10759,14,213,15,54232352,2,"[54232352, 197966, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10760,14,214,15,54232352,2,"[54232352, 198986, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10761,14,215,15,54232352,2,"[54232352, 200008, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10762,14,216,15,54232352,2,"[54232352, 201030, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10763,14,217,15,54232352,2,"[54232352, 202053, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10764,14,218,15,54232352,2,"[54232352, 203077, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10765,14,219,15,54232352,2,"[54232352, 204101, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10766,14,220,15,54232352,2,"[54232352, 205127, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10767,14,221,15,54232352,2,"[54232352, 206152, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10768,14,222,15,54232352,2,"[54232352, 207179, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10769,14,223,15,54232352,2,"[54232352, 208206, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10770,14,224,15,54232352,2,"[54232352, 209234, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10771,14,225,15,54232352,2,"[54232352, 210263, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10772,14,226,15,54232352,2,"[54232352, 211292, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10773,14,227,15,54232352,2,"[54232352, 212322, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10774,14,228,15,54232352,2,"[54232352, 213353, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10775,14,229,15,54232352,2,"[54232352, 214384, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10776,14,230,15,54232352,2,"[54232352, 215416, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10777,14,231,15,54232352,2,"[54232352, 216449, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10778,14,232,15,54232352,2,"[54232352, 217482, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10779,14,233,15,54232352,2,"[54232352, 218517, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10780,14,234,15,54232352,2,"[54232352, 219551, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10781,14,235,15,54232352,2,"[54232352, 220587, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10782,14,236,15,54232352,2,"[54232352, 221623, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10783,14,237,15,54232352,2,"[54232352, 222660, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10784,14,238,15,54232352,2,"[54232352, 223698, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10785,14,239,15,54232352,2,"[54232352, 224736, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10786,14,240,15,54232352,2,"[54232352, 225776, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10787,14,241,15,54232352,2,"[54232352, 226815, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10788,14,242,15,54232352,2,"[54232352, 227856, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10789,14,243,15,54232352,2,"[54232352, 228897, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10790,14,244,15,54232352,2,"[54232352, 229939, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10791,14,245,15,54232352,2,"[54232352, 230982, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10792,14,246,15,54232352,2,"[54232352, 232025, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10793,14,247,15,54232352,2,"[54232352, 233069, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10794,14,248,15,54232352,2,"[54232352, 234114, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10795,14,249,15,54232352,2,"[54232352, 235159, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10796,14,250,15,54232352,2,"[54232352, 236205, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10797,14,251,15,54232352,2,"[54232352, 237252, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10798,14,252,15,54232352,2,"[54232352, 238299, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10799,14,253,15,54232352,2,"[54232352, 239348, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10800,14,254,15,54232352,2,"[54232352, 240396, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10801,14,255,15,54232352,2,"[54232352, 241446, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10802,14,256,15,54232352,2,"[54232352, 242496, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10803,14,257,15,54232352,2,"[54232352, 243547, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10804,14,258,15,54232352,2,"[54232352, 244599, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10805,14,259,15,54232352,2,"[54232352, 245651, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10806,14,260,15,54232352,2,"[54232352, 246705, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10807,14,261,15,54232352,2,"[54232352, 247758, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10808,14,262,15,54232352,2,"[54232352, 248813, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10809,14,263,15,54232352,2,"[54232352, 249868, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10810,14,264,15,54232352,2,"[54232352, 250924, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10811,14,265,15,54232352,2,"[54232352, 251981, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10812,14,266,15,54232352,2,"[54232352, 253038, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10813,14,267,15,54232352,2,"[54232352, 254096, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10814,14,268,15,54232352,2,"[54232352, 255155, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10815,14,269,15,54232352,2,"[54232352, 256214, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10816,14,270,15,54232352,2,"[54232352, 257274, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10817,14,271,15,54232352,2,"[54232352, 258335, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10818,14,272,15,54232352,2,"[54232352, 259396, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10819,14,273,15,54232352,2,"[54232352, 260459, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10820,14,274,15,54232352,2,"[54232352, 261521, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10821,14,275,15,54232352,2,"[54232352, 262585, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10822,14,276,15,54232352,2,"[54232352, 263649, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10823,14,277,15,54232352,2,"[54232352, 264714, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10824,14,278,15,54232352,2,"[54232352, 265780, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10825,14,279,15,54232352,2,"[54232352, 266846, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10826,14,280,15,54232352,2,"[54232352, 267914, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10827,14,281,15,54232352,2,"[54232352, 268981, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10828,14,282,15,54232352,2,"[54232352, 270050, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10829,14,283,15,54232352,2,"[54232352, 271119, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10830,14,284,15,54232352,2,"[54232352, 272189, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10831,14,285,15,54232352,2,"[54232352, 273260, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10832,14,286,15,54232352,2,"[54232352, 274331, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10833,14,287,15,54232352,2,"[54232352, 275403, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10834,14,288,15,54232352,2,"[54232352, 276476, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10835,14,289,15,54232352,2,"[54232352, 277549, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10836,14,290,15,54232352,2,"[54232352, 278623, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10837,14,291,15,54232352,2,"[54232352, 279698, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10838,14,292,15,54232352,2,"[54232352, 280773, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10839,14,293,15,54232352,2,"[54232352, 281850, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10840,14,294,15,54232352,2,"[54232352, 282926, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10841,14,295,15,54232352,2,"[54232352, 284004, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10842,14,296,15,54232352,2,"[54232352, 285082, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10843,14,297,15,54232352,2,"[54232352, 286161, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10844,14,298,15,54232352,2,"[54232352, 287241, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10845,14,299,15,54232352,2,"[54232352, 288321, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10846,14,300,15,54232352,2,"[54232352, 289403, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10847,14,301,15,54232352,2,"[54232352, 290484, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10848,14,302,15,54232352,2,"[54232352, 291567, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10849,14,303,15,54232352,2,"[54232352, 292650, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10850,14,304,15,54232352,2,"[54232352, 293734, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10851,14,305,15,54232352,2,"[54232352, 294819, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10852,14,306,15,54232352,2,"[54232352, 295904, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10853,14,307,15,54232352,2,"[54232352, 296990, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10854,14,308,15,54232352,2,"[54232352, 298077, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10855,14,309,15,54232352,2,"[54232352, 299164, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10856,14,310,15,54232352,2,"[54232352, 300252, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10857,14,311,15,54232352,2,"[54232352, 301341, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10858,14,312,15,54232352,2,"[54232352, 302430, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10859,14,313,15,54232352,2,"[54232352, 303521, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10860,14,314,15,54232352,2,"[54232352, 304611, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10861,14,315,15,54232352,2,"[54232352, 305703, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10862,14,316,15,54232352,2,"[54232352, 306795, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10863,14,317,15,54232352,2,"[54232352, 307888, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10864,14,318,15,54232352,2,"[54232352, 308982, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10865,14,319,15,54232352,2,"[54232352, 310076, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10866,14,320,15,54232352,2,"[54232352, 311172, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10867,14,321,15,54232352,2,"[54232352, 312267, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10868,14,322,15,54232352,2,"[54232352, 313364, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10869,14,323,15,54232352,2,"[54232352, 314461, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10870,14,324,15,54232352,2,"[54232352, 315559, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10871,14,325,15,54232352,2,"[54232352, 316658, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10872,14,326,15,54232352,2,"[54232352, 317757, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10873,14,327,15,54232352,2,"[54232352, 318857, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10874,14,328,15,54232352,2,"[54232352, 319958, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10875,14,329,15,54232352,2,"[54232352, 321059, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10876,14,330,15,54232352,2,"[54232352, 322161, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10877,14,331,15,54232352,2,"[54232352, 323264, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10878,14,332,15,54232352,2,"[54232352, 324367, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10879,14,333,15,54232352,2,"[54232352, 325472, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10880,14,334,15,54232352,2,"[54232352, 326576, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10881,14,335,15,54232352,2,"[54232352, 327682, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10882,14,336,15,54232352,2,"[54232352, 328788, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10883,14,337,15,54232352,2,"[54232352, 329895, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10884,14,338,15,54232352,2,"[54232352, 331003, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10885,14,339,15,54232352,2,"[54232352, 332111, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10886,14,340,15,54232352,2,"[54232352, 333221, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10887,14,341,15,54232352,2,"[54232352, 334330, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10888,14,342,15,54232352,2,"[54232352, 335441, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10889,14,343,15,54232352,2,"[54232352, 336552, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10890,14,344,15,54232352,2,"[54232352, 337664, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10891,14,345,15,54232352,2,"[54232352, 338777, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10892,14,346,15,54232352,2,"[54232352, 339890, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10893,14,347,15,54232352,2,"[54232352, 341004, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10894,14,348,15,54232352,2,"[54232352, 342119, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10895,14,349,15,54232352,2,"[54232352, 343234, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10896,14,350,15,54232352,2,"[54232352, 344350, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10897,14,351,15,54232352,2,"[54232352, 345467, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10898,14,352,15,54232352,2,"[54232352, 346584, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10899,14,353,15,54232352,2,"[54232352, 347703, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10900,14,354,15,54232352,2,"[54232352, 348821, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10901,14,355,15,54232352,2,"[54232352, 349941, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10902,14,356,15,54232352,2,"[54232352, 351061, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10903,14,357,15,54232352,2,"[54232352, 352182, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10904,14,358,15,54232352,2,"[54232352, 353304, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10905,14,359,15,54232352,2,"[54232352, 354426, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10906,14,360,15,54232352,2,"[54232352, 355550, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10907,14,361,15,54232352,2,"[54232352, 356673, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10908,14,362,15,54232352,2,"[54232352, 357798, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10909,14,363,15,54232352,2,"[54232352, 358923, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10910,14,364,15,54232352,2,"[54232352, 360049, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10911,14,365,15,54232352,2,"[54232352, 361176, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10912,14,366,15,54232352,2,"[54232352, 362303, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10913,14,367,15,54232352,2,"[54232352, 363431, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10914,14,368,15,54232352,2,"[54232352, 364560, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10915,14,369,15,54232352,2,"[54232352, 365689, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10916,14,370,15,54232352,2,"[54232352, 366819, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10917,14,371,15,54232352,2,"[54232352, 367950, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10918,14,372,15,54232352,2,"[54232352, 369081, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10919,14,373,15,54232352,2,"[54232352, 370214, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10920,14,374,15,54232352,2,"[54232352, 371346, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10921,14,375,15,54232352,2,"[54232352, 372480, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10922,14,376,15,54232352,2,"[54232352, 373614, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10923,14,377,15,54232352,2,"[54232352, 374749, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10924,14,378,15,54232352,2,"[54232352, 375885, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10925,14,379,15,54232352,2,"[54232352, 377021, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10926,14,380,15,54232352,2,"[54232352, 378159, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10927,14,381,15,54232352,2,"[54232352, 379296, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10928,14,382,15,54232352,2,"[54232352, 380435, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10929,14,383,15,54232352,2,"[54232352, 381574, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10930,14,384,15,54232352,2,"[54232352, 382714, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10931,14,385,15,54232352,2,"[54232352, 383855, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10932,14,386,15,54232352,2,"[54232352, 384996, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10933,14,387,15,54232352,2,"[54232352, 386138, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10934,14,388,15,54232352,2,"[54232352, 387281, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10935,14,389,15,54232352,2,"[54232352, 388424, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10936,14,390,15,54232352,2,"[54232352, 389568, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10937,14,391,15,54232352,2,"[54232352, 390713, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10938,14,392,15,54232352,2,"[54232352, 391858, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10939,14,393,15,54232352,2,"[54232352, 393005, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10940,14,394,15,54232352,2,"[54232352, 394151, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10941,14,395,15,54232352,2,"[54232352, 395299, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10942,14,396,15,54232352,2,"[54232352, 396447, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10943,14,397,15,54232352,2,"[54232352, 397596, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10944,14,398,15,54232352,2,"[54232352, 398746, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10945,14,399,15,54232352,2,"[54232352, 399896, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10946,14,400,15,54232352,2,"[54232352, 401048, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10947,14,401,15,54232352,2,"[54232352, 402199, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10948,14,402,15,54232352,2,"[54232352, 403352, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10949,14,403,15,54232352,2,"[54232352, 404505, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10950,14,404,15,54232352,2,"[54232352, 405659, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10951,14,405,15,54232352,2,"[54232352, 406814, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10952,14,406,15,54232352,2,"[54232352, 407969, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10953,14,407,15,54232352,2,"[54232352, 409125, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10954,14,408,15,54232352,2,"[54232352, 410282, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10955,14,409,15,54232352,2,"[54232352, 411439, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10956,14,410,15,54232352,2,"[54232352, 412597, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10957,14,411,15,54232352,2,"[54232352, 413756, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10958,14,412,15,54232352,2,"[54232352, 414915, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10959,14,413,15,54232352,2,"[54232352, 416076, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10960,14,414,15,54232352,2,"[54232352, 417236, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10961,14,415,15,54232352,2,"[54232352, 418398, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10962,14,416,15,54232352,2,"[54232352, 419560, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10963,14,417,15,54232352,2,"[54232352, 420723, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10964,14,418,15,54232352,2,"[54232352, 421887, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10965,14,419,15,54232352,2,"[54232352, 423051, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10966,14,420,15,54232352,2,"[54232352, 424217, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10967,14,421,15,54232352,2,"[54232352, 425382, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10968,14,422,15,54232352,2,"[54232352, 426549, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10969,14,423,15,54232352,2,"[54232352, 427716, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10970,14,424,15,54232352,2,"[54232352, 428884, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10971,14,425,15,54232352,2,"[54232352, 430053, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10972,14,426,15,54232352,2,"[54232352, 431222, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10973,14,427,15,54232352,2,"[54232352, 432392, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10974,14,428,15,54232352,2,"[54232352, 433563, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10975,14,429,15,54232352,2,"[54232352, 434734, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10976,14,430,15,54232352,2,"[54232352, 435906, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10977,14,431,15,54232352,2,"[54232352, 437079, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10978,14,432,15,54232352,2,"[54232352, 438252, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10979,14,433,15,54232352,2,"[54232352, 439427, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10980,14,434,15,54232352,2,"[54232352, 440601, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10981,14,435,15,54232352,2,"[54232352, 441777, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10982,14,436,15,54232352,2,"[54232352, 442953, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10983,14,437,15,54232352,2,"[54232352, 444130, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10984,14,438,15,54232352,2,"[54232352, 445308, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10985,14,439,15,54232352,2,"[54232352, 446486, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10986,14,440,15,54232352,2,"[54232352, 447666, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10987,14,441,15,54232352,2,"[54232352, 448845, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10988,14,442,15,54232352,2,"[54232352, 450026, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10989,14,443,15,54232352,2,"[54232352, 451207, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10990,14,444,15,54232352,2,"[54232352, 452389, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10991,14,445,15,54232352,2,"[54232352, 453572, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10992,14,446,15,54232352,2,"[54232352, 454755, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10993,14,447,15,54232352,2,"[54232352, 455939, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10994,14,448,15,54232352,2,"[54232352, 457124, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10995,14,449,15,54232352,2,"[54232352, 458309, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10996,14,450,15,54232352,2,"[54232352, 459495, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10997,14,451,15,54232352,2,"[54232352, 460682, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10998,14,452,15,54232352,2,"[54232352, 461869, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -10999,14,453,15,54232352,2,"[54232352, 463058, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11000,14,454,15,54232352,2,"[54232352, 464246, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11001,14,455,15,54232352,2,"[54232352, 465436, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11002,14,456,15,54232352,2,"[54232352, 466626, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11003,14,457,15,54232352,2,"[54232352, 467817, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11004,14,458,15,54232352,2,"[54232352, 469009, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11005,14,459,15,54232352,2,"[54232352, 470201, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11006,14,460,15,54232352,2,"[54232352, 471395, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11007,14,461,15,54232352,2,"[54232352, 472588, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11008,14,462,15,54232352,2,"[54232352, 473783, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11009,14,463,15,54232352,2,"[54232352, 474978, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11010,14,464,15,54232352,2,"[54232352, 476174, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11011,14,465,15,54232352,2,"[54232352, 477371, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11012,14,466,15,54232352,2,"[54232352, 478568, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11013,14,467,15,54232352,2,"[54232352, 479766, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11014,14,468,15,54232352,2,"[54232352, 480965, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11015,14,469,15,54232352,2,"[54232352, 482164, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11016,14,470,15,54232352,2,"[54232352, 483364, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11017,14,471,15,54232352,2,"[54232352, 484565, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11018,14,472,15,54232352,2,"[54232352, 485766, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11019,14,473,15,54232352,2,"[54232352, 486969, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11020,14,474,15,54232352,2,"[54232352, 488171, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11021,14,475,15,54232352,2,"[54232352, 489375, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11022,14,476,15,54232352,2,"[54232352, 490579, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11023,14,477,15,54232352,2,"[54232352, 491784, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11024,14,478,15,54232352,2,"[54232352, 492990, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11025,14,479,15,54232352,2,"[54232352, 494196, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11026,14,480,15,54232352,2,"[54232352, 495404, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11027,14,481,15,54232352,2,"[54232352, 496611, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11028,14,482,15,54232352,2,"[54232352, 497820, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11029,14,483,15,54232352,2,"[54232352, 499029, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11030,14,484,15,54232352,2,"[54232352, 500239, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11031,14,485,15,54232352,2,"[54232352, 501450, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11032,14,486,15,54232352,2,"[54232352, 502661, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11033,14,487,15,54232352,2,"[54232352, 503873, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11034,14,488,15,54232352,2,"[54232352, 505086, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11035,14,489,15,54232352,2,"[54232352, 506299, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11036,14,490,15,54232352,2,"[54232352, 507513, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11037,14,491,15,54232352,2,"[54232352, 508728, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11038,14,492,15,54232352,2,"[54232352, 509943, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11039,14,493,15,54232352,2,"[54232352, 511160, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11040,14,494,15,54232352,2,"[54232352, 512376, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11041,14,495,15,54232352,2,"[54232352, 513594, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11042,14,496,15,54232352,2,"[54232352, 514812, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11043,14,497,15,54232352,2,"[54232352, 516031, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11044,14,498,15,54232352,2,"[54232352, 517251, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11045,14,499,15,54232352,2,"[54232352, 518471, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11046,14,500,15,54232352,2,"[54232352, 519693, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11047,14,501,15,54232352,2,"[54232352, 520914, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11048,14,502,15,54232352,2,"[54232352, 522137, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11049,14,503,15,54232352,2,"[54232352, 523360, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11050,14,504,15,54232352,2,"[54232352, 524584, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11051,14,505,15,54232352,2,"[54232352, 525809, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11052,14,506,15,54232352,2,"[54232352, 527034, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11053,14,507,15,54232352,2,"[54232352, 528260, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11054,14,508,15,54232352,2,"[54232352, 529487, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11055,14,509,15,54232352,2,"[54232352, 530714, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11056,14,510,15,54232352,2,"[54232352, 531942, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11057,14,511,15,54232352,2,"[54232352, 533171, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11058,14,512,15,54232352,2,"[54232352, 534400, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11059,14,513,15,54232352,2,"[54232352, 535631, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11060,14,514,15,54232352,2,"[54232352, 536861, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11061,14,515,15,54232352,2,"[54232352, 538093, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11062,14,516,15,54232352,2,"[54232352, 539325, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11063,14,517,15,54232352,2,"[54232352, 540558, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11064,14,518,15,54232352,2,"[54232352, 541792, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11065,14,519,15,54232352,2,"[54232352, 543026, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11066,14,520,15,54232352,2,"[54232352, 544262, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11067,14,521,15,54232352,2,"[54232352, 545497, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11068,14,522,15,54232352,2,"[54232352, 546734, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11069,14,523,15,54232352,2,"[54232352, 547971, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11070,14,524,15,54232352,2,"[54232352, 549209, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11071,14,525,15,54232352,2,"[54232352, 550448, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11072,14,526,15,54232352,2,"[54232352, 551687, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11073,14,527,15,54232352,2,"[54232352, 552927, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11074,14,528,15,54232352,2,"[54232352, 554168, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11075,14,529,15,54232352,2,"[54232352, 555409, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11076,14,530,15,54232352,2,"[54232352, 556651, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11077,14,531,15,54232352,2,"[54232352, 557894, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11078,14,532,15,54232352,2,"[54232352, 559137, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11079,14,533,15,54232352,2,"[54232352, 560382, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11080,14,534,15,54232352,2,"[54232352, 561626, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11081,14,535,15,54232352,2,"[54232352, 562872, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11082,14,536,15,54232352,2,"[54232352, 564118, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11083,14,537,15,54232352,2,"[54232352, 565365, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11084,14,538,15,54232352,2,"[54232352, 566613, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11085,14,539,15,54232352,2,"[54232352, 567861, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11086,14,540,15,54232352,2,"[54232352, 569111, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11087,14,541,15,54232352,2,"[54232352, 570360, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11088,14,542,15,54232352,2,"[54232352, 571611, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11089,14,543,15,54232352,2,"[54232352, 572862, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11090,14,544,15,54232352,2,"[54232352, 574114, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11091,14,545,15,54232352,2,"[54232352, 575367, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11092,14,546,15,54232352,2,"[54232352, 576620, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11093,14,547,15,54232352,2,"[54232352, 577874, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11094,14,548,15,54232352,2,"[54232352, 579129, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11095,14,549,15,54232352,2,"[54232352, 580384, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11096,14,550,15,54232352,2,"[54232352, 581640, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11097,14,551,15,54232352,2,"[54232352, 582897, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11098,14,552,15,54232352,2,"[54232352, 584154, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11099,14,553,15,54232352,2,"[54232352, 585413, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11100,14,554,15,54232352,2,"[54232352, 586671, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11101,14,555,15,54232352,2,"[54232352, 587931, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11102,14,556,15,54232352,2,"[54232352, 589191, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11103,14,557,15,54232352,2,"[54232352, 590452, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11104,14,558,15,54232352,2,"[54232352, 591714, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11105,14,559,15,54232352,2,"[54232352, 592976, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11106,14,560,15,54232352,2,"[54232352, 594240, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11107,14,561,15,54232352,2,"[54232352, 595503, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11108,14,562,15,54232352,2,"[54232352, 596768, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11109,14,563,15,54232352,2,"[54232352, 598033, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11110,14,564,15,54232352,2,"[54232352, 599299, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11111,14,565,15,54232352,2,"[54232352, 600566, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11112,14,566,15,54232352,2,"[54232352, 601833, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11113,14,567,15,54232352,2,"[54232352, 603101, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11114,14,568,15,54232352,2,"[54232352, 604370, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11115,14,569,15,54232352,2,"[54232352, 605639, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11116,14,570,15,54232352,2,"[54232352, 606909, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11117,14,571,15,54232352,2,"[54232352, 608180, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11118,14,572,15,54232352,2,"[54232352, 609451, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11119,14,573,15,54232352,2,"[54232352, 610724, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11120,14,574,15,54232352,2,"[54232352, 611996, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11121,14,575,15,54232352,2,"[54232352, 613270, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11122,14,576,15,54232352,2,"[54232352, 614544, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11123,14,577,15,54232352,2,"[54232352, 615819, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11124,14,578,15,54232352,2,"[54232352, 617095, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11125,14,579,15,54232352,2,"[54232352, 618371, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11126,14,580,15,54232352,2,"[54232352, 619649, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11127,14,581,15,54232352,2,"[54232352, 620926, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11128,14,582,15,54232352,2,"[54232352, 622205, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11129,14,583,15,54232352,2,"[54232352, 623484, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11130,14,584,15,54232352,2,"[54232352, 624764, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11131,14,585,15,54232352,2,"[54232352, 626045, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11132,14,586,15,54232352,2,"[54232352, 627326, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11133,14,587,15,54232352,2,"[54232352, 628608, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11134,14,588,15,54232352,2,"[54232352, 629891, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11135,14,589,15,54232352,2,"[54232352, 631174, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11136,14,590,15,54232352,2,"[54232352, 632458, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11137,14,591,15,54232352,2,"[54232352, 633743, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11138,14,592,15,54232352,2,"[54232352, 635028, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11139,14,593,15,54232352,2,"[54232352, 636315, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11140,14,594,15,54232352,2,"[54232352, 637601, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11141,14,595,15,54232352,2,"[54232352, 638889, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11142,14,596,15,54232352,2,"[54232352, 640177, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11143,14,597,15,54232352,2,"[54232352, 641466, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11144,14,598,15,54232352,2,"[54232352, 642756, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11145,14,599,15,54232352,2,"[54232352, 644046, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11146,14,600,15,54232352,2,"[54232352, 645338, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11147,14,601,15,54232352,2,"[54232352, 646629, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11148,14,602,15,54232352,2,"[54232352, 647922, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11149,14,603,15,54232352,2,"[54232352, 649215, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11150,14,604,15,54232352,2,"[54232352, 650509, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11151,14,605,15,54232352,2,"[54232352, 651804, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11152,14,606,15,54232352,2,"[54232352, 653099, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11153,14,607,15,54232352,2,"[54232352, 654395, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11154,14,608,15,54232352,2,"[54232352, 655692, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11155,14,609,15,54232352,2,"[54232352, 656989, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11156,14,610,15,54232352,2,"[54232352, 658287, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11157,14,611,15,54232352,2,"[54232352, 659586, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11158,14,612,15,54232352,2,"[54232352, 660885, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11159,14,613,15,54232352,2,"[54232352, 662186, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11160,14,614,15,54232352,2,"[54232352, 663486, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11161,14,615,15,54232352,2,"[54232352, 664788, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11162,14,616,15,54232352,2,"[54232352, 666090, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11163,14,617,15,54232352,2,"[54232352, 667393, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11164,14,618,15,54232352,2,"[54232352, 668697, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11165,14,619,15,54232352,2,"[54232352, 670001, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11166,14,620,15,54232352,2,"[54232352, 671307, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11167,14,621,15,54232352,2,"[54232352, 672612, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11168,14,622,15,54232352,2,"[54232352, 673919, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11169,14,623,15,54232352,2,"[54232352, 675226, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11170,14,624,15,54232352,2,"[54232352, 676534, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11171,14,625,15,54232352,2,"[54232352, 677843, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11172,14,626,15,54232352,2,"[54232352, 679152, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11173,14,627,15,54232352,2,"[54232352, 680462, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11174,14,628,15,54232352,2,"[54232352, 681773, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11175,14,629,15,54232352,2,"[54232352, 683084, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11176,14,630,15,54232352,2,"[54232352, 684396, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11177,14,631,15,54232352,2,"[54232352, 685709, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11178,14,632,15,54232352,2,"[54232352, 687022, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11179,14,633,15,54232352,2,"[54232352, 688337, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11180,14,634,15,54232352,2,"[54232352, 689651, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11181,14,635,15,54232352,2,"[54232352, 690967, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11182,14,636,15,54232352,2,"[54232352, 692283, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11183,14,637,15,54232352,2,"[54232352, 693600, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11184,14,638,15,54232352,2,"[54232352, 694918, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11185,14,639,15,54232352,2,"[54232352, 696236, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11186,14,640,15,54232352,2,"[54232352, 697556, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11187,14,641,15,54232352,2,"[54232352, 698875, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11188,14,642,15,54232352,2,"[54232352, 700196, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11189,14,643,15,54232352,2,"[54232352, 701517, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11190,14,644,15,54232352,2,"[54232352, 702839, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11191,14,645,15,54232352,2,"[54232352, 704162, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11192,14,646,15,54232352,2,"[54232352, 705485, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11193,14,647,15,54232352,2,"[54232352, 706809, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11194,14,648,15,54232352,2,"[54232352, 708134, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11195,14,649,15,54232352,2,"[54232352, 709459, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11196,14,650,15,54232352,2,"[54232352, 710785, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11197,14,651,15,54232352,2,"[54232352, 712112, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11198,14,652,15,54232352,2,"[54232352, 713439, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11199,14,653,15,54232352,2,"[54232352, 714768, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11200,14,654,15,54232352,2,"[54232352, 716096, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11201,14,655,15,54232352,2,"[54232352, 717426, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11202,14,656,15,54232352,2,"[54232352, 718756, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11203,14,657,15,54232352,2,"[54232352, 720087, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11204,14,658,15,54232352,2,"[54232352, 721419, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11205,14,659,15,54232352,2,"[54232352, 722751, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11206,14,660,15,54232352,2,"[54232352, 724085, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11207,14,661,15,54232352,2,"[54232352, 725418, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11208,14,662,15,54232352,2,"[54232352, 726753, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11209,14,663,15,54232352,2,"[54232352, 728088, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11210,14,664,15,54232352,2,"[54232352, 729424, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11211,14,665,15,54232352,2,"[54232352, 730761, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11212,14,666,15,54232352,2,"[54232352, 732098, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11213,14,667,15,54232352,2,"[54232352, 733436, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11214,14,668,15,54232352,2,"[54232352, 734775, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11215,14,669,15,54232352,2,"[54232352, 736114, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11216,14,670,15,54232352,2,"[54232352, 737454, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11217,14,671,15,54232352,2,"[54232352, 738795, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11218,14,672,15,54232352,2,"[54232352, 740136, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11219,14,673,15,54232352,2,"[54232352, 741479, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11220,14,674,15,54232352,2,"[54232352, 742821, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11221,14,675,15,54232352,2,"[54232352, 744165, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11222,14,676,15,54232352,2,"[54232352, 745509, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11223,14,677,15,54232352,2,"[54232352, 746854, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11224,14,678,15,54232352,2,"[54232352, 748200, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11225,14,679,15,54232352,2,"[54232352, 749546, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11226,14,680,15,54232352,2,"[54232352, 750894, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11227,14,681,15,54232352,2,"[54232352, 752241, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11228,14,682,15,54232352,2,"[54232352, 753590, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11229,14,683,15,54232352,2,"[54232352, 754939, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11230,14,684,15,54232352,2,"[54232352, 756289, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11231,14,685,15,54232352,2,"[54232352, 757640, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11232,14,686,15,54232352,2,"[54232352, 758991, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11233,14,687,15,54232352,2,"[54232352, 760343, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11234,14,688,15,54232352,2,"[54232352, 761696, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11235,14,689,15,54232352,2,"[54232352, 763049, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11236,14,690,15,54232352,2,"[54232352, 764403, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11237,14,691,15,54232352,2,"[54232352, 765758, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11238,14,692,15,54232352,2,"[54232352, 767113, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11239,14,693,15,54232352,2,"[54232352, 768470, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11240,14,694,15,54232352,2,"[54232352, 769826, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11241,14,695,15,54232352,2,"[54232352, 771184, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11242,14,696,15,54232352,2,"[54232352, 772542, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11243,14,697,15,54232352,2,"[54232352, 773901, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11244,14,698,15,54232352,2,"[54232352, 775261, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11245,14,699,15,54232352,2,"[54232352, 776621, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11246,14,700,15,54232352,2,"[54232352, 777983, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11247,14,701,15,54232352,2,"[54232352, 779344, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11248,14,702,15,54232352,2,"[54232352, 780707, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11249,14,703,15,54232352,2,"[54232352, 782070, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11250,14,704,15,54232352,2,"[54232352, 783434, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11251,14,705,15,54232352,2,"[54232352, 784799, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11252,14,706,15,54232352,2,"[54232352, 786164, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11253,14,707,15,54232352,2,"[54232352, 787530, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11254,14,708,15,54232352,2,"[54232352, 788897, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11255,14,709,15,54232352,2,"[54232352, 790264, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11256,14,710,15,54232352,2,"[54232352, 791632, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11257,14,711,15,54232352,2,"[54232352, 793001, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11258,14,712,15,54232352,2,"[54232352, 794370, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11259,14,713,15,54232352,2,"[54232352, 795741, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11260,14,714,15,54232352,2,"[54232352, 797111, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11261,14,715,15,54232352,2,"[54232352, 798483, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11262,14,716,15,54232352,2,"[54232352, 799855, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11263,14,717,15,54232352,2,"[54232352, 801228, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11264,14,718,15,54232352,2,"[54232352, 802602, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11265,14,719,15,54232352,2,"[54232352, 803976, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11266,14,720,15,54232352,2,"[54232352, 805352, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11267,14,721,15,54232352,2,"[54232352, 806727, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11268,14,722,15,54232352,2,"[54232352, 808104, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11269,14,723,15,54232352,2,"[54232352, 809481, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11270,14,724,15,54232352,2,"[54232352, 810859, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11271,14,725,15,54232352,2,"[54232352, 812238, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11272,14,726,15,54232352,2,"[54232352, 813617, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11273,14,727,15,54232352,2,"[54232352, 814997, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11274,14,728,15,54232352,2,"[54232352, 816378, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11275,14,729,15,54232352,2,"[54232352, 817759, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11276,14,730,15,54232352,2,"[54232352, 819141, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11277,14,731,15,54232352,2,"[54232352, 820524, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11278,14,732,15,54232352,2,"[54232352, 821907, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11279,14,733,15,54232352,2,"[54232352, 823292, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11280,14,734,15,54232352,2,"[54232352, 824676, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11281,14,735,15,54232352,2,"[54232352, 826062, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11282,14,736,15,54232352,2,"[54232352, 827448, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11283,14,737,15,54232352,2,"[54232352, 828835, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11284,14,738,15,54232352,2,"[54232352, 830223, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11285,14,739,15,54232352,2,"[54232352, 831611, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11286,14,740,15,54232352,2,"[54232352, 833001, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11287,14,741,15,54232352,2,"[54232352, 834390, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11288,14,742,15,54232352,2,"[54232352, 835781, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11289,14,743,15,54232352,2,"[54232352, 837172, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11290,14,744,15,54232352,2,"[54232352, 838564, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11291,14,745,15,54232352,2,"[54232352, 839957, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11292,14,746,15,54232352,2,"[54232352, 841350, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11293,14,747,15,54232352,2,"[54232352, 842744, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11294,14,748,15,54232352,2,"[54232352, 844139, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11295,14,749,15,54232352,2,"[54232352, 845534, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11296,14,750,15,54232352,2,"[54232352, 846930, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11297,14,751,15,54232352,2,"[54232352, 848327, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11298,14,752,15,54232352,2,"[54232352, 849724, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11299,14,753,15,54232352,2,"[54232352, 851123, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11300,14,754,15,54232352,2,"[54232352, 852521, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11301,14,755,15,54232352,2,"[54232352, 853921, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11302,14,756,15,54232352,2,"[54232352, 855321, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11303,14,757,15,54232352,2,"[54232352, 856722, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11304,14,758,15,54232352,2,"[54232352, 858124, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11305,14,759,15,54232352,2,"[54232352, 859526, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11306,14,760,15,54232352,2,"[54232352, 860930, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11307,14,761,15,54232352,2,"[54232352, 862333, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11308,14,762,15,54232352,2,"[54232352, 863738, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11309,14,763,15,54232352,2,"[54232352, 865143, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11310,14,764,15,54232352,2,"[54232352, 866549, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11311,14,765,15,54232352,2,"[54232352, 867956, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11312,14,766,15,54232352,2,"[54232352, 869363, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11313,14,767,15,54232352,2,"[54232352, 870771, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11314,14,768,15,54232352,2,"[54232352, 872180, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11315,14,769,15,54232352,2,"[54232352, 873589, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11316,14,770,15,54232352,2,"[54232352, 874999, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11317,14,771,15,54232352,2,"[54232352, 876410, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11318,14,772,15,54232352,2,"[54232352, 877821, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11319,14,773,15,54232352,2,"[54232352, 879234, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11320,14,774,15,54232352,2,"[54232352, 880646, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11321,14,775,15,54232352,2,"[54232352, 882060, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11322,14,776,15,54232352,2,"[54232352, 883474, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11323,14,777,15,54232352,2,"[54232352, 884889, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11324,14,778,15,54232352,2,"[54232352, 886305, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11325,14,779,15,54232352,2,"[54232352, 887721, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11326,14,780,15,54232352,2,"[54232352, 889139, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11327,14,781,15,54232352,2,"[54232352, 890556, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11328,14,782,15,54232352,2,"[54232352, 891975, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11329,14,783,15,54232352,2,"[54232352, 893394, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11330,14,784,15,54232352,2,"[54232352, 894814, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11331,14,785,15,54232352,2,"[54232352, 896235, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11332,14,786,15,54232352,2,"[54232352, 897656, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11333,14,787,15,54232352,2,"[54232352, 899078, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11334,14,788,15,54232352,2,"[54232352, 900501, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11335,14,789,15,54232352,2,"[54232352, 901924, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11336,14,790,15,54232352,2,"[54232352, 903348, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11337,14,791,15,54232352,2,"[54232352, 904773, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11338,14,792,15,54232352,2,"[54232352, 906198, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11339,14,793,15,54232352,2,"[54232352, 907625, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11340,14,794,15,54232352,2,"[54232352, 909051, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11341,14,795,15,54232352,2,"[54232352, 910479, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11342,14,796,15,54232352,2,"[54232352, 911907, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11343,14,797,15,54232352,2,"[54232352, 913336, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11344,14,798,15,54232352,2,"[54232352, 914766, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11345,14,799,15,54232352,2,"[54232352, 916196, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11346,14,800,15,54232352,2,"[54232352, 917628, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11347,14,801,15,54232352,2,"[54232352, 919059, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11348,14,802,15,54232352,2,"[54232352, 920492, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11349,14,803,15,54232352,2,"[54232352, 921925, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11350,14,804,15,54232352,2,"[54232352, 923359, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11351,14,805,15,54232352,2,"[54232352, 924794, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11352,14,806,15,54232352,2,"[54232352, 926229, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11353,14,807,15,54232352,2,"[54232352, 927665, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11354,14,808,15,54232352,2,"[54232352, 929102, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11355,14,809,15,54232352,2,"[54232352, 930539, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11356,14,810,15,54232352,2,"[54232352, 931977, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11357,14,811,15,54232352,2,"[54232352, 933416, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11358,14,812,15,54232352,2,"[54232352, 934855, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11359,14,813,15,54232352,2,"[54232352, 936296, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11360,14,814,15,54232352,2,"[54232352, 937736, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11361,14,815,15,54232352,2,"[54232352, 939178, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11362,14,816,15,54232352,2,"[54232352, 940620, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11363,14,817,15,54232352,2,"[54232352, 942063, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11364,14,818,15,54232352,2,"[54232352, 943507, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11365,14,819,15,54232352,2,"[54232352, 944951, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11366,14,820,15,54232352,2,"[54232352, 946397, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11367,14,821,15,54232352,2,"[54232352, 947842, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11368,14,822,15,54232352,2,"[54232352, 949289, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11369,14,823,15,54232352,2,"[54232352, 950736, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11370,14,824,15,54232352,2,"[54232352, 952184, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11371,14,825,15,54232352,2,"[54232352, 953633, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11372,14,826,15,54232352,2,"[54232352, 955082, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11373,14,827,15,54232352,2,"[54232352, 956532, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11374,14,828,15,54232352,2,"[54232352, 957983, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11375,14,829,15,54232352,2,"[54232352, 959434, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11376,14,830,15,54232352,2,"[54232352, 960886, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11377,14,831,15,54232352,2,"[54232352, 962339, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11378,14,832,15,54232352,2,"[54232352, 963792, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11379,14,833,15,54232352,2,"[54232352, 965247, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11380,14,834,15,54232352,2,"[54232352, 966701, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11381,14,835,15,54232352,2,"[54232352, 968157, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11382,14,836,15,54232352,2,"[54232352, 969613, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11383,14,837,15,54232352,2,"[54232352, 971070, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11384,14,838,15,54232352,2,"[54232352, 972528, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11385,14,839,15,54232352,2,"[54232352, 973986, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11386,14,840,15,54232352,2,"[54232352, 975446, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11387,14,841,15,54232352,2,"[54232352, 976905, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11388,14,842,15,54232352,2,"[54232352, 978366, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11389,14,843,15,54232352,2,"[54232352, 979827, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11390,14,844,15,54232352,2,"[54232352, 981289, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11391,14,845,15,54232352,2,"[54232352, 982752, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11392,14,846,15,54232352,2,"[54232352, 984215, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11393,14,847,15,54232352,2,"[54232352, 985679, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11394,14,848,15,54232352,2,"[54232352, 987144, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11395,14,849,15,54232352,2,"[54232352, 988609, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11396,14,850,15,54232352,2,"[54232352, 990075, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11397,14,851,15,54232352,2,"[54232352, 991542, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11398,14,852,15,54232352,2,"[54232352, 993009, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11399,14,853,15,54232352,2,"[54232352, 994478, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11400,14,854,15,54232352,2,"[54232352, 995946, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11401,14,855,15,54232352,2,"[54232352, 997416, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11402,14,856,15,54232352,2,"[54232352, 998886, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11403,14,857,15,54232352,2,"[54232352, 1000357, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11404,14,858,15,54232352,2,"[54232352, 1001829, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11405,14,859,15,54232352,2,"[54232352, 1003301, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11406,14,860,15,54232352,2,"[54232352, 1004775, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11407,14,861,15,54232352,2,"[54232352, 1006248, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11408,14,862,15,54232352,2,"[54232352, 1007723, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11409,14,863,15,54232352,2,"[54232352, 1009198, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11410,14,864,15,54232352,2,"[54232352, 1010674, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11411,14,865,15,54232352,2,"[54232352, 1012151, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11412,14,866,15,54232352,2,"[54232352, 1013628, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11413,14,867,15,54232352,2,"[54232352, 1015106, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11414,14,868,15,54232352,2,"[54232352, 1016585, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11415,14,869,15,54232352,2,"[54232352, 1018064, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11416,14,870,15,54232352,2,"[54232352, 1019544, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11417,14,871,15,54232352,2,"[54232352, 1021025, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11418,14,872,15,54232352,2,"[54232352, 1022506, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11419,14,873,15,54232352,2,"[54232352, 1023989, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11420,14,874,15,54232352,2,"[54232352, 1025471, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11421,14,875,15,54232352,2,"[54232352, 1026955, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11422,14,876,15,54232352,2,"[54232352, 1028439, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11423,14,877,15,54232352,2,"[54232352, 1029924, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11424,14,878,15,54232352,2,"[54232352, 1031410, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11425,14,879,15,54232352,2,"[54232352, 1032896, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11426,14,880,15,54232352,2,"[54232352, 1034384, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11427,14,881,15,54232352,2,"[54232352, 1035871, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11428,14,882,15,54232352,2,"[54232352, 1037360, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11429,14,883,15,54232352,2,"[54232352, 1038849, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11430,14,884,15,54232352,2,"[54232352, 1040339, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11431,14,885,15,54232352,2,"[54232352, 1041830, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11432,14,886,15,54232352,2,"[54232352, 1043321, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11433,14,887,15,54232352,2,"[54232352, 1044813, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11434,14,888,15,54232352,2,"[54232352, 1046306, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11435,14,889,15,54232352,2,"[54232352, 1047799, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11436,14,890,15,54232352,2,"[54232352, 1049293, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11437,14,891,15,54232352,2,"[54232352, 1050788, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11438,14,892,15,54232352,2,"[54232352, 1052283, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11439,14,893,15,54232352,2,"[54232352, 1053780, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11440,14,894,15,54232352,2,"[54232352, 1055276, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11441,14,895,15,54232352,2,"[54232352, 1056774, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11442,14,896,15,54232352,2,"[54232352, 1058272, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11443,14,897,15,54232352,2,"[54232352, 1059771, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11444,14,898,15,54232352,2,"[54232352, 1061271, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11445,14,899,15,54232352,2,"[54232352, 1062771, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11446,14,900,15,54232352,2,"[54232352, 1064273, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11447,14,901,15,54232352,2,"[54232352, 1065774, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11448,14,902,15,54232352,2,"[54232352, 1067277, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11449,14,903,15,54232352,2,"[54232352, 1068780, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11450,14,904,15,54232352,2,"[54232352, 1070284, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11451,14,905,15,54232352,2,"[54232352, 1071789, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11452,14,906,15,54232352,2,"[54232352, 1073294, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11453,14,907,15,54232352,2,"[54232352, 1074800, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11454,14,908,15,54232352,2,"[54232352, 1076307, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11455,14,909,15,54232352,2,"[54232352, 1077814, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11456,14,910,15,54232352,2,"[54232352, 1079322, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11457,14,911,15,54232352,2,"[54232352, 1080831, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11458,14,912,15,54232352,2,"[54232352, 1082340, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11459,14,913,15,54232352,2,"[54232352, 1083851, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11460,14,914,15,54232352,2,"[54232352, 1085361, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11461,14,915,15,54232352,2,"[54232352, 1086873, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11462,14,916,15,54232352,2,"[54232352, 1088385, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11463,14,917,15,54232352,2,"[54232352, 1089898, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11464,14,918,15,54232352,2,"[54232352, 1091412, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11465,14,919,15,54232352,2,"[54232352, 1092926, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11466,14,920,15,54232352,2,"[54232352, 1094442, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11467,14,921,15,54232352,2,"[54232352, 1095957, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11468,14,922,15,54232352,2,"[54232352, 1097474, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11469,14,923,15,54232352,2,"[54232352, 1098991, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11470,14,924,15,54232352,2,"[54232352, 1100509, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11471,14,925,15,54232352,2,"[54232352, 1102028, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11472,14,926,15,54232352,2,"[54232352, 1103547, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11473,14,927,15,54232352,2,"[54232352, 1105067, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11474,14,928,15,54232352,2,"[54232352, 1106588, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11475,14,929,15,54232352,2,"[54232352, 1108109, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11476,14,930,15,54232352,2,"[54232352, 1109631, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11477,14,931,15,54232352,2,"[54232352, 1111154, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11478,14,932,15,54232352,2,"[54232352, 1112677, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11479,14,933,15,54232352,2,"[54232352, 1114202, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11480,14,934,15,54232352,2,"[54232352, 1115726, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11481,14,935,15,54232352,2,"[54232352, 1117252, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11482,14,936,15,54232352,2,"[54232352, 1118778, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11483,14,937,15,54232352,2,"[54232352, 1120305, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11484,14,938,15,54232352,2,"[54232352, 1121833, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11485,14,939,15,54232352,2,"[54232352, 1123361, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11486,14,940,15,54232352,2,"[54232352, 1124891, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11487,14,941,15,54232352,2,"[54232352, 1126420, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11488,14,942,15,54232352,2,"[54232352, 1127951, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11489,14,943,15,54232352,2,"[54232352, 1129482, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11490,14,944,15,54232352,2,"[54232352, 1131014, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11491,14,945,15,54232352,2,"[54232352, 1132547, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11492,14,946,15,54232352,2,"[54232352, 1134080, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11493,14,947,15,54232352,2,"[54232352, 1135614, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11494,14,948,15,54232352,2,"[54232352, 1137149, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11495,14,949,15,54232352,2,"[54232352, 1138684, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11496,14,950,15,54232352,2,"[54232352, 1140220, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11497,14,951,15,54232352,2,"[54232352, 1141757, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11498,14,952,15,54232352,2,"[54232352, 1143294, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11499,14,953,15,54232352,2,"[54232352, 1144833, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11500,14,954,15,54232352,2,"[54232352, 1146371, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11501,14,955,15,54232352,2,"[54232352, 1147911, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11502,14,956,15,54232352,2,"[54232352, 1149451, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11503,14,957,15,54232352,2,"[54232352, 1150992, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11504,14,958,15,54232352,2,"[54232352, 1152534, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11505,14,959,15,54232352,2,"[54232352, 1154076, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11506,14,960,15,54232352,2,"[54232352, 1155620, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11507,14,961,15,54232352,2,"[54232352, 1157163, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11508,14,962,15,54232352,2,"[54232352, 1158708, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11509,14,963,15,54232352,2,"[54232352, 1160253, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11510,14,964,15,54232352,2,"[54232352, 1161799, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11511,14,965,15,54232352,2,"[54232352, 1163346, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11512,14,966,15,54232352,2,"[54232352, 1164893, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11513,14,967,15,54232352,2,"[54232352, 1166441, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11514,14,968,15,54232352,2,"[54232352, 1167990, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11515,14,969,15,54232352,2,"[54232352, 1169539, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11516,14,970,15,54232352,2,"[54232352, 1171089, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11517,14,971,15,54232352,2,"[54232352, 1172640, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11518,14,972,15,54232352,2,"[54232352, 1174191, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11519,14,973,15,54232352,2,"[54232352, 1175744, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11520,14,974,15,54232352,2,"[54232352, 1177296, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11521,14,975,15,54232352,2,"[54232352, 1178850, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11522,14,976,15,54232352,2,"[54232352, 1180404, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11523,14,977,15,54232352,2,"[54232352, 1181959, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11524,14,978,15,54232352,2,"[54232352, 1183515, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11525,14,979,15,54232352,2,"[54232352, 1185071, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11526,14,980,15,54232352,2,"[54232352, 1186629, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11527,14,981,15,54232352,2,"[54232352, 1188186, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11528,14,982,15,54232352,2,"[54232352, 1189745, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11529,14,983,15,54232352,2,"[54232352, 1191304, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11530,14,984,15,54232352,2,"[54232352, 1192864, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11531,14,985,15,54232352,2,"[54232352, 1194425, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11532,14,986,15,54232352,2,"[54232352, 1195986, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11533,14,987,15,54232352,2,"[54232352, 1197548, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11534,14,988,15,54232352,2,"[54232352, 1199111, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11535,14,989,15,54232352,2,"[54232352, 1200674, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11536,14,990,15,54232352,2,"[54232352, 1202238, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11537,14,991,15,54232352,2,"[54232352, 1203803, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11538,14,992,15,54232352,2,"[54232352, 1205368, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11539,14,993,15,54232352,2,"[54232352, 1206935, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11540,14,994,15,54232352,2,"[54232352, 1208501, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11541,14,995,15,54232352,2,"[54232352, 1210069, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11542,14,996,15,54232352,2,"[54232352, 1211637, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11543,14,997,15,54232352,2,"[54232352, 1213206, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11544,14,998,15,54232352,2,"[54232352, 1214776, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11545,14,999,15,54232352,2,"[54232352, 1216346, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11546,14,1000,15,54232352,2,"[54232352, 1217918, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11547,14,1001,15,54232352,2,"[54232352, 1219489, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11548,14,1002,15,54232352,2,"[54232352, 1221062, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11549,14,1003,15,54232352,2,"[54232352, 1222635, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11550,14,1004,15,54232352,2,"[54232352, 1224209, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11551,14,1005,15,54232352,2,"[54232352, 1225784, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11552,14,1006,15,54232352,2,"[54232352, 1227359, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11553,14,1007,15,54232352,2,"[54232352, 1228935, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11554,14,1008,15,54232352,2,"[54232352, 1230512, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11555,14,1009,15,54232352,2,"[54232352, 1232089, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11556,14,1010,15,54232352,2,"[54232352, 1233667, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11557,14,1011,15,54232352,2,"[54232352, 1235246, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11558,14,1012,15,54232352,2,"[54232352, 1236825, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11559,14,1013,15,54232352,2,"[54232352, 1238406, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11560,14,1014,15,54232352,2,"[54232352, 1239986, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11561,14,1015,15,54232352,2,"[54232352, 1241568, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11562,14,1016,15,54232352,2,"[54232352, 1243150, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11563,14,1017,15,54232352,2,"[54232352, 1244733, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11564,14,1018,15,54232352,2,"[54232352, 1246317, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11565,14,1019,15,54232352,2,"[54232352, 1247901, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11566,14,1020,15,54232352,2,"[54232352, 1249487, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11567,14,1021,15,54232352,2,"[54232352, 1251072, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11568,14,1022,15,54232352,2,"[54232352, 1252659, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11569,14,1023,15,54232352,2,"[54232352, 1254246, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11570,14,1024,15,54232352,2,"[54232352, 1255834, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11571,14,1025,15,54232352,2,"[54232352, 1257423, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11572,14,1026,15,54232352,2,"[54232352, 1259012, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11573,14,1027,15,54232352,2,"[54232352, 1260602, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11574,14,1028,15,54232352,2,"[54232352, 1262193, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11575,14,1029,15,54232352,2,"[54232352, 1263784, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11576,14,1030,15,54232352,2,"[54232352, 1265376, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11577,14,1031,15,54232352,2,"[54232352, 1266969, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11578,14,1032,15,54232352,2,"[54232352, 1268562, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11579,14,1033,15,54232352,2,"[54232352, 1270157, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11580,14,1034,15,54232352,2,"[54232352, 1271751, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11581,14,1035,15,54232352,2,"[54232352, 1273347, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11582,14,1036,15,54232352,2,"[54232352, 1274943, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11583,14,1037,15,54232352,2,"[54232352, 1276540, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11584,14,1038,15,54232352,2,"[54232352, 1278138, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11585,14,1039,15,54232352,2,"[54232352, 1279736, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11586,14,1040,15,54232352,2,"[54232352, 1281336, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11587,14,1041,15,54232352,2,"[54232352, 1282935, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11588,14,1042,15,54232352,2,"[54232352, 1284536, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11589,14,1043,15,54232352,2,"[54232352, 1286137, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11590,14,1044,15,54232352,2,"[54232352, 1287739, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11591,14,1045,15,54232352,2,"[54232352, 1289342, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11592,14,1046,15,54232352,2,"[54232352, 1290945, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11593,14,1047,15,54232352,2,"[54232352, 1292549, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11594,14,1048,15,54232352,2,"[54232352, 1294154, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11595,14,1049,15,54232352,2,"[54232352, 1295759, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11596,14,1050,15,54232352,2,"[54232352, 1297365, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11597,14,1051,15,54232352,2,"[54232352, 1298972, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11598,14,1052,15,54232352,2,"[54232352, 1300579, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11599,14,1053,15,54232352,2,"[54232352, 1302188, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11600,14,1054,15,54232352,2,"[54232352, 1303796, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11601,14,1055,15,54232352,2,"[54232352, 1305406, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11602,14,1056,15,54232352,2,"[54232352, 1307016, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11603,14,1057,15,54232352,2,"[54232352, 1308627, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11604,14,1058,15,54232352,2,"[54232352, 1310239, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11605,14,1059,15,54232352,2,"[54232352, 1311851, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11606,14,1060,15,54232352,2,"[54232352, 1313465, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11607,14,1061,15,54232352,2,"[54232352, 1315078, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11608,14,1062,15,54232352,2,"[54232352, 1316693, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11609,14,1063,15,54232352,2,"[54232352, 1318308, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11610,14,1064,15,54232352,2,"[54232352, 1319924, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11611,14,1065,15,54232352,2,"[54232352, 1321541, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11612,14,1066,15,54232352,2,"[54232352, 1323158, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11613,14,1067,15,54232352,2,"[54232352, 1324776, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11614,14,1068,15,54232352,2,"[54232352, 1326395, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11615,14,1069,15,54232352,2,"[54232352, 1328014, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11616,14,1070,15,54232352,2,"[54232352, 1329634, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11617,14,1071,15,54232352,2,"[54232352, 1331255, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11618,14,1072,15,54232352,2,"[54232352, 1332876, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11619,14,1073,15,54232352,2,"[54232352, 1334499, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11620,14,1074,15,54232352,2,"[54232352, 1336121, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11621,14,1075,15,54232352,2,"[54232352, 1337745, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11622,14,1076,15,54232352,2,"[54232352, 1339369, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11623,14,1077,15,54232352,2,"[54232352, 1340994, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11624,14,1078,15,54232352,2,"[54232352, 1342620, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11625,14,1079,15,54232352,2,"[54232352, 1344246, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11626,14,1080,15,54232352,2,"[54232352, 1345874, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11627,14,1081,15,54232352,2,"[54232352, 1347501, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11628,14,1082,15,54232352,2,"[54232352, 1349130, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11629,14,1083,15,54232352,2,"[54232352, 1350759, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11630,14,1084,15,54232352,2,"[54232352, 1352389, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11631,14,1085,15,54232352,2,"[54232352, 1354020, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11632,14,1086,15,54232352,2,"[54232352, 1355651, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11633,14,1087,15,54232352,2,"[54232352, 1357283, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11634,14,1088,15,54232352,2,"[54232352, 1358916, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11635,14,1089,15,54232352,2,"[54232352, 1360549, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11636,14,1090,15,54232352,2,"[54232352, 1362183, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11637,14,1091,15,54232352,2,"[54232352, 1363818, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11638,14,1092,15,54232352,2,"[54232352, 1365453, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11639,14,1093,15,54232352,2,"[54232352, 1367090, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11640,14,1094,15,54232352,2,"[54232352, 1368726, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11641,14,1095,15,54232352,2,"[54232352, 1370364, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11642,14,1096,15,54232352,2,"[54232352, 1372002, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11643,14,1097,15,54232352,2,"[54232352, 1373641, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11644,14,1098,15,54232352,2,"[54232352, 1375281, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11645,14,1099,15,54232352,2,"[54232352, 1376921, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11646,14,1100,15,54232352,2,"[54232352, 1378563, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11647,14,1101,15,54232352,2,"[54232352, 1380204, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11648,14,1102,15,54232352,2,"[54232352, 1381847, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11649,14,1103,15,54232352,2,"[54232352, 1383490, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11650,14,1104,15,54232352,2,"[54232352, 1385134, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11651,14,1105,15,54232352,2,"[54232352, 1386779, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11652,14,1106,15,54232352,2,"[54232352, 1388424, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11653,14,1107,15,54232352,2,"[54232352, 1390070, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11654,14,1108,15,54232352,2,"[54232352, 1391717, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11655,14,1109,15,54232352,2,"[54232352, 1393364, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11656,14,1110,15,54232352,2,"[54232352, 1395012, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11657,14,1111,15,54232352,2,"[54232352, 1396661, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11658,14,1112,15,54232352,2,"[54232352, 1398310, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11659,14,1113,15,54232352,2,"[54232352, 1399961, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11660,14,1114,15,54232352,2,"[54232352, 1401611, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11661,14,1115,15,54232352,2,"[54232352, 1403263, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11662,14,1116,15,54232352,2,"[54232352, 1404915, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11663,14,1117,15,54232352,2,"[54232352, 1406568, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11664,14,1118,15,54232352,2,"[54232352, 1408222, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11665,14,1119,15,54232352,2,"[54232352, 1409876, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11666,14,1120,15,54232352,2,"[54232352, 1411532, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11667,14,1121,15,54232352,2,"[54232352, 1413187, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11668,14,1122,15,54232352,2,"[54232352, 1414844, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11669,14,1123,15,54232352,2,"[54232352, 1416501, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11670,14,1124,15,54232352,2,"[54232352, 1418159, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11671,14,1125,15,54232352,2,"[54232352, 1419818, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11672,14,1126,15,54232352,2,"[54232352, 1421477, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11673,14,1127,15,54232352,2,"[54232352, 1423137, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11674,14,1128,15,54232352,2,"[54232352, 1424798, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11675,14,1129,15,54232352,2,"[54232352, 1426459, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11676,14,1130,15,54232352,2,"[54232352, 1428121, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11677,14,1131,15,54232352,2,"[54232352, 1429784, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11678,14,1132,15,54232352,2,"[54232352, 1431447, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11679,14,1133,15,54232352,2,"[54232352, 1433112, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11680,14,1134,15,54232352,2,"[54232352, 1434776, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11681,14,1135,15,54232352,2,"[54232352, 1436442, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11682,14,1136,15,54232352,2,"[54232352, 1438108, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11683,14,1137,15,54232352,2,"[54232352, 1439775, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11684,14,1138,15,54232352,2,"[54232352, 1441443, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11685,14,1139,15,54232352,2,"[54232352, 1443111, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11686,14,1140,15,54232352,2,"[54232352, 1444781, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11687,14,1141,15,54232352,2,"[54232352, 1446450, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11688,14,1142,15,54232352,2,"[54232352, 1448121, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11689,14,1143,15,54232352,2,"[54232352, 1449792, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11690,14,1144,15,54232352,2,"[54232352, 1451464, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11691,14,1145,15,54232352,2,"[54232352, 1453137, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11692,14,1146,15,54232352,2,"[54232352, 1454810, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11693,14,1147,15,54232352,2,"[54232352, 1456484, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11694,14,1148,15,54232352,2,"[54232352, 1458159, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11695,14,1149,15,54232352,2,"[54232352, 1459834, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11696,14,1150,15,54232352,2,"[54232352, 1461510, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11697,14,1151,15,54232352,2,"[54232352, 1463187, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11698,14,1152,15,54232352,2,"[54232352, 1464864, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11699,14,1153,15,54232352,2,"[54232352, 1466543, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11700,14,1154,15,54232352,2,"[54232352, 1468221, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11701,14,1155,15,54232352,2,"[54232352, 1469901, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11702,14,1156,15,54232352,2,"[54232352, 1471581, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11703,14,1157,15,54232352,2,"[54232352, 1473262, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11704,14,1158,15,54232352,2,"[54232352, 1474944, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11705,14,1159,15,54232352,2,"[54232352, 1476626, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11706,14,1160,15,54232352,2,"[54232352, 1478310, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11707,14,1161,15,54232352,2,"[54232352, 1479993, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11708,14,1162,15,54232352,2,"[54232352, 1481678, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11709,14,1163,15,54232352,2,"[54232352, 1483363, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11710,14,1164,15,54232352,2,"[54232352, 1485049, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11711,14,1165,15,54232352,2,"[54232352, 1486736, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11712,14,1166,15,54232352,2,"[54232352, 1488423, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11713,14,1167,15,54232352,2,"[54232352, 1490111, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11714,14,1168,15,54232352,2,"[54232352, 1491800, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11715,14,1169,15,54232352,2,"[54232352, 1493489, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11716,14,1170,15,54232352,2,"[54232352, 1495179, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11717,14,1171,15,54232352,2,"[54232352, 1496870, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11718,14,1172,15,54232352,2,"[54232352, 1498561, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11719,14,1173,15,54232352,2,"[54232352, 1500254, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11720,14,1174,15,54232352,2,"[54232352, 1501946, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11721,14,1175,15,54232352,2,"[54232352, 1503640, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11722,14,1176,15,54232352,2,"[54232352, 1505334, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11723,14,1177,15,54232352,2,"[54232352, 1507029, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11724,14,1178,15,54232352,2,"[54232352, 1508725, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11725,14,1179,15,54232352,2,"[54232352, 1510421, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11726,14,1180,15,54232352,2,"[54232352, 1512119, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11727,14,1181,15,54232352,2,"[54232352, 1513816, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11728,14,1182,15,54232352,2,"[54232352, 1515515, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11729,14,1183,15,54232352,2,"[54232352, 1517214, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11730,14,1184,15,54232352,2,"[54232352, 1518914, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11731,14,1185,15,54232352,2,"[54232352, 1520615, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11732,14,1186,15,54232352,2,"[54232352, 1522316, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11733,14,1187,15,54232352,2,"[54232352, 1524018, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11734,14,1188,15,54232352,2,"[54232352, 1525721, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11735,14,1189,15,54232352,2,"[54232352, 1527424, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11736,14,1190,15,54232352,2,"[54232352, 1529128, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11737,14,1191,15,54232352,2,"[54232352, 1530833, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11738,14,1192,15,54232352,2,"[54232352, 1532538, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11739,14,1193,15,54232352,2,"[54232352, 1534245, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11740,14,1194,15,54232352,2,"[54232352, 1535951, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11741,14,1195,15,54232352,2,"[54232352, 1537659, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11742,14,1196,15,54232352,2,"[54232352, 1539367, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11743,14,1197,15,54232352,2,"[54232352, 1541076, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11744,14,1198,15,54232352,2,"[54232352, 1542786, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11745,14,1199,15,54232352,2,"[54232352, 1544496, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11746,14,1200,15,54232352,2,"[54232352, 1546208, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11747,14,1201,15,54232352,2,"[54232352, 1547919, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11748,14,1202,15,54232352,2,"[54232352, 1549632, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11749,14,1203,15,54232352,2,"[54232352, 1551345, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11750,14,1204,15,54232352,2,"[54232352, 1553059, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11751,14,1205,15,54232352,2,"[54232352, 1554774, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11752,14,1206,15,54232352,2,"[54232352, 1556489, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11753,14,1207,15,54232352,2,"[54232352, 1558205, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11754,14,1208,15,54232352,2,"[54232352, 1559922, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11755,14,1209,15,54232352,2,"[54232352, 1561639, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11756,14,1210,15,54232352,2,"[54232352, 1563357, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11757,14,1211,15,54232352,2,"[54232352, 1565076, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11758,14,1212,15,54232352,2,"[54232352, 1566795, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11759,14,1213,15,54232352,2,"[54232352, 1568516, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11760,14,1214,15,54232352,2,"[54232352, 1570236, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11761,14,1215,15,54232352,2,"[54232352, 1571958, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11762,14,1216,15,54232352,2,"[54232352, 1573680, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11763,14,1217,15,54232352,2,"[54232352, 1575403, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11764,14,1218,15,54232352,2,"[54232352, 1577127, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11765,14,1219,15,54232352,2,"[54232352, 1578851, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11766,14,1220,15,54232352,2,"[54232352, 1580577, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11767,14,1221,15,54232352,2,"[54232352, 1582302, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11768,14,1222,15,54232352,2,"[54232352, 1584029, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11769,14,1223,15,54232352,2,"[54232352, 1585756, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11770,14,1224,15,54232352,2,"[54232352, 1587484, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11771,14,1225,15,54232352,2,"[54232352, 1589213, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11772,14,1226,15,54232352,2,"[54232352, 1590942, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11773,14,1227,15,54232352,2,"[54232352, 1592672, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11774,14,1228,15,54232352,2,"[54232352, 1594403, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11775,14,1229,15,54232352,2,"[54232352, 1596134, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11776,14,1230,15,54232352,2,"[54232352, 1597866, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11777,14,1231,15,54232352,2,"[54232352, 1599599, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11778,14,1232,15,54232352,2,"[54232352, 1601332, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11779,14,1233,15,54232352,2,"[54232352, 1603067, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11780,14,1234,15,54232352,2,"[54232352, 1604801, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11781,14,1235,15,54232352,2,"[54232352, 1606537, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11782,14,1236,15,54232352,2,"[54232352, 1608273, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11783,14,1237,15,54232352,2,"[54232352, 1610010, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11784,14,1238,15,54232352,2,"[54232352, 1611748, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11785,14,1239,15,54232352,2,"[54232352, 1613486, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11786,14,1240,15,54232352,2,"[54232352, 1615226, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11787,14,1241,15,54232352,2,"[54232352, 1616965, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11788,14,1242,15,54232352,2,"[54232352, 1618706, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11789,14,1243,15,54232352,2,"[54232352, 1620447, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11790,14,1244,15,54232352,2,"[54232352, 1622189, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11791,14,1245,15,54232352,2,"[54232352, 1623932, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11792,14,1246,15,54232352,2,"[54232352, 1625675, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11793,14,1247,15,54232352,2,"[54232352, 1627419, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11794,14,1248,15,54232352,2,"[54232352, 1629164, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11795,14,1249,15,54232352,2,"[54232352, 1630909, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11796,14,1250,15,54232352,2,"[54232352, 1632655, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11797,14,1251,15,54232352,2,"[54232352, 1634402, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11798,14,1252,15,54232352,2,"[54232352, 1636149, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11799,14,1253,15,54232352,2,"[54232352, 1637898, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11800,14,1254,15,54232352,2,"[54232352, 1639646, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11801,14,1255,15,54232352,2,"[54232352, 1641396, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11802,14,1256,15,54232352,2,"[54232352, 1643146, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11803,14,1257,15,54232352,2,"[54232352, 1644897, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11804,14,1258,15,54232352,2,"[54232352, 1646649, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11805,14,1259,15,54232352,2,"[54232352, 1648401, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11806,14,1260,15,54232352,2,"[54232352, 1650155, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11807,14,1261,15,54232352,2,"[54232352, 1651908, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11808,14,1262,15,54232352,2,"[54232352, 1653663, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11809,14,1263,15,54232352,2,"[54232352, 1655418, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11810,14,1264,15,54232352,2,"[54232352, 1657174, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11811,14,1265,15,54232352,2,"[54232352, 1658931, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11812,14,1266,15,54232352,2,"[54232352, 1660688, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11813,14,1267,15,54232352,2,"[54232352, 1662446, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11814,14,1268,15,54232352,2,"[54232352, 1664205, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11815,14,1269,15,54232352,2,"[54232352, 1665964, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11816,14,1270,15,54232352,2,"[54232352, 1667724, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11817,14,1271,15,54232352,2,"[54232352, 1669485, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11818,14,1272,15,54232352,2,"[54232352, 1671246, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11819,14,1273,15,54232352,2,"[54232352, 1673009, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11820,14,1274,15,54232352,2,"[54232352, 1674771, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11821,14,1275,15,54232352,2,"[54232352, 1676535, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11822,14,1276,15,54232352,2,"[54232352, 1678299, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11823,14,1277,15,54232352,2,"[54232352, 1680064, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11824,14,1278,15,54232352,2,"[54232352, 1681830, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11825,14,1279,15,54232352,2,"[54232352, 1683596, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11826,14,1280,15,54232352,2,"[54232352, 1685364, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11827,14,1281,15,54232352,2,"[54232352, 1687131, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11828,14,1282,15,54232352,2,"[54232352, 1688900, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11829,14,1283,15,54232352,2,"[54232352, 1690669, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11830,14,1284,15,54232352,2,"[54232352, 1692439, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11831,14,1285,15,54232352,2,"[54232352, 1694210, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11832,14,1286,15,54232352,2,"[54232352, 1695981, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11833,14,1287,15,54232352,2,"[54232352, 1697753, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11834,14,1288,15,54232352,2,"[54232352, 1699526, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11835,14,1289,15,54232352,2,"[54232352, 1701299, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11836,14,1290,15,54232352,2,"[54232352, 1703073, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11837,14,1291,15,54232352,2,"[54232352, 1704848, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11838,14,1292,15,54232352,2,"[54232352, 1706623, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11839,14,1293,15,54232352,2,"[54232352, 1708400, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11840,14,1294,15,54232352,2,"[54232352, 1710176, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11841,14,1295,15,54232352,2,"[54232352, 1711954, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11842,14,1296,15,54232352,2,"[54232352, 1713732, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11843,14,1297,15,54232352,2,"[54232352, 1715511, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11844,14,1298,15,54232352,2,"[54232352, 1717291, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11845,14,1299,15,54232352,2,"[54232352, 1719071, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11846,14,1300,15,54232352,2,"[54232352, 1720853, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11847,14,1301,15,54232352,2,"[54232352, 1722634, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11848,14,1302,15,54232352,2,"[54232352, 1724417, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11849,14,1303,15,54232352,2,"[54232352, 1726200, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11850,14,1304,15,54232352,2,"[54232352, 1727984, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11851,14,1305,15,54232352,2,"[54232352, 1729769, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11852,14,1306,15,54232352,2,"[54232352, 1731554, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11853,14,1307,15,54232352,2,"[54232352, 1733340, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11854,14,1308,15,54232352,2,"[54232352, 1735127, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11855,14,1309,15,54232352,2,"[54232352, 1736914, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11856,14,1310,15,54232352,2,"[54232352, 1738702, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11857,14,1311,15,54232352,2,"[54232352, 1740491, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11858,14,1312,15,54232352,2,"[54232352, 1742280, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11859,14,1313,15,54232352,2,"[54232352, 1744071, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11860,14,1314,15,54232352,2,"[54232352, 1745861, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11861,14,1315,15,54232352,2,"[54232352, 1747653, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11862,14,1316,15,54232352,2,"[54232352, 1749445, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11863,14,1317,15,54232352,2,"[54232352, 1751238, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11864,14,1318,15,54232352,2,"[54232352, 1753032, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11865,14,1319,15,54232352,2,"[54232352, 1754826, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11866,14,1320,15,54232352,2,"[54232352, 1756622, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11867,14,1321,15,54232352,2,"[54232352, 1758417, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11868,14,1322,15,54232352,2,"[54232352, 1760214, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11869,14,1323,15,54232352,2,"[54232352, 1762011, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11870,14,1324,15,54232352,2,"[54232352, 1763809, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11871,14,1325,15,54232352,2,"[54232352, 1765608, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11872,14,1326,15,54232352,2,"[54232352, 1767407, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11873,14,1327,15,54232352,2,"[54232352, 1769207, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11874,14,1328,15,54232352,2,"[54232352, 1771008, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11875,14,1329,15,54232352,2,"[54232352, 1772809, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11876,14,1330,15,54232352,2,"[54232352, 1774611, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11877,14,1331,15,54232352,2,"[54232352, 1776414, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11878,14,1332,15,54232352,2,"[54232352, 1778217, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11879,14,1333,15,54232352,2,"[54232352, 1780022, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11880,14,1334,15,54232352,2,"[54232352, 1781826, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11881,14,1335,15,54232352,2,"[54232352, 1783632, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11882,14,1336,15,54232352,2,"[54232352, 1785438, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11883,14,1337,15,54232352,2,"[54232352, 1787245, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11884,14,1338,15,54232352,2,"[54232352, 1789053, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11885,14,1339,15,54232352,2,"[54232352, 1790861, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11886,14,1340,15,54232352,2,"[54232352, 1792671, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11887,14,1341,15,54232352,2,"[54232352, 1794480, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11888,14,1342,15,54232352,2,"[54232352, 1796291, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11889,14,1343,15,54232352,2,"[54232352, 1798102, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11890,14,1344,15,54232352,2,"[54232352, 1799914, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11891,14,1345,15,54232352,2,"[54232352, 1801727, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11892,14,1346,15,54232352,2,"[54232352, 1803540, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11893,14,1347,15,54232352,2,"[54232352, 1805354, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11894,14,1348,15,54232352,2,"[54232352, 1807169, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11895,14,1349,15,54232352,2,"[54232352, 1808984, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11896,14,1350,15,54232352,2,"[54232352, 1810800, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11897,14,1351,15,54232352,2,"[54232352, 1812617, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11898,14,1352,15,54232352,2,"[54232352, 1814434, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11899,14,1353,15,54232352,2,"[54232352, 1816253, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11900,14,1354,15,54232352,2,"[54232352, 1818071, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11901,14,1355,15,54232352,2,"[54232352, 1819891, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11902,14,1356,15,54232352,2,"[54232352, 1821711, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11903,14,1357,15,54232352,2,"[54232352, 1823532, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11904,14,1358,15,54232352,2,"[54232352, 1825354, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11905,14,1359,15,54232352,2,"[54232352, 1827176, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11906,14,1360,15,54232352,2,"[54232352, 1829000, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11907,14,1361,15,54232352,2,"[54232352, 1830823, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11908,14,1362,15,54232352,2,"[54232352, 1832648, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11909,14,1363,15,54232352,2,"[54232352, 1834473, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11910,14,1364,15,54232352,2,"[54232352, 1836299, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11911,14,1365,15,54232352,2,"[54232352, 1838126, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11912,14,1366,15,54232352,2,"[54232352, 1839953, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11913,14,1367,15,54232352,2,"[54232352, 1841781, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11914,14,1368,15,54232352,2,"[54232352, 1843610, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11915,14,1369,15,54232352,2,"[54232352, 1845439, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11916,14,1370,15,54232352,2,"[54232352, 1847269, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11917,14,1371,15,54232352,2,"[54232352, 1849100, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11918,14,1372,15,54232352,2,"[54232352, 1850931, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11919,14,1373,15,54232352,2,"[54232352, 1852764, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11920,14,1374,15,54232352,2,"[54232352, 1854596, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11921,14,1375,15,54232352,2,"[54232352, 1856430, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11922,14,1376,15,54232352,2,"[54232352, 1858264, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11923,14,1377,15,54232352,2,"[54232352, 1860099, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11924,14,1378,15,54232352,2,"[54232352, 1861935, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11925,14,1379,15,54232352,2,"[54232352, 1863771, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11926,14,1380,15,54232352,2,"[54232352, 1865609, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11927,14,1381,15,54232352,2,"[54232352, 1867446, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11928,14,1382,15,54232352,2,"[54232352, 1869285, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11929,14,1383,15,54232352,2,"[54232352, 1871124, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11930,14,1384,15,54232352,2,"[54232352, 1872964, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11931,14,1385,15,54232352,2,"[54232352, 1874805, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11932,14,1386,15,54232352,2,"[54232352, 1876646, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11933,14,1387,15,54232352,2,"[54232352, 1878488, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11934,14,1388,15,54232352,2,"[54232352, 1880331, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11935,14,1389,15,54232352,2,"[54232352, 1882174, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11936,14,1390,15,54232352,2,"[54232352, 1884018, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11937,14,1391,15,54232352,2,"[54232352, 1885863, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11938,14,1392,15,54232352,2,"[54232352, 1887708, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11939,14,1393,15,54232352,2,"[54232352, 1889555, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11940,14,1394,15,54232352,2,"[54232352, 1891401, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11941,14,1395,15,54232352,2,"[54232352, 1893249, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11942,14,1396,15,54232352,2,"[54232352, 1895097, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11943,14,1397,15,54232352,2,"[54232352, 1896946, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11944,14,1398,15,54232352,2,"[54232352, 1898796, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11945,14,1399,15,54232352,2,"[54232352, 1900646, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11946,14,1400,15,54232352,2,"[54232352, 1902498, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11947,14,1401,15,54232352,2,"[54232352, 1904349, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11948,14,1402,15,54232352,2,"[54232352, 1906202, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11949,14,1403,15,54232352,2,"[54232352, 1908055, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11950,14,1404,15,54232352,2,"[54232352, 1909909, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11951,14,1405,15,54232352,2,"[54232352, 1911764, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11952,14,1406,15,54232352,2,"[54232352, 1913619, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11953,14,1407,15,54232352,2,"[54232352, 1915475, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11954,14,1408,15,54232352,2,"[54232352, 1917332, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11955,14,1409,15,54232352,2,"[54232352, 1919189, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11956,14,1410,15,54232352,2,"[54232352, 1921047, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11957,14,1411,15,54232352,2,"[54232352, 1922906, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11958,14,1412,15,54232352,2,"[54232352, 1924765, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11959,14,1413,15,54232352,2,"[54232352, 1926626, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11960,14,1414,15,54232352,2,"[54232352, 1928486, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11961,14,1415,15,54232352,2,"[54232352, 1930348, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11962,14,1416,15,54232352,2,"[54232352, 1932210, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11963,14,1417,15,54232352,2,"[54232352, 1934073, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11964,14,1418,15,54232352,2,"[54232352, 1935937, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11965,14,1419,15,54232352,2,"[54232352, 1937801, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11966,14,1420,15,54232352,2,"[54232352, 1939667, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11967,14,1421,15,54232352,2,"[54232352, 1941532, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11968,14,1422,15,54232352,2,"[54232352, 1943399, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11969,14,1423,15,54232352,2,"[54232352, 1945266, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11970,14,1424,15,54232352,2,"[54232352, 1947134, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11971,14,1425,15,54232352,2,"[54232352, 1949003, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11972,14,1426,15,54232352,2,"[54232352, 1950872, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11973,14,1427,15,54232352,2,"[54232352, 1952742, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11974,14,1428,15,54232352,2,"[54232352, 1954613, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11975,14,1429,15,54232352,2,"[54232352, 1956484, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11976,14,1430,15,54232352,2,"[54232352, 1958356, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11977,14,1431,15,54232352,2,"[54232352, 1960229, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11978,14,1432,15,54232352,2,"[54232352, 1962102, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11979,14,1433,15,54232352,2,"[54232352, 1963977, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11980,14,1434,15,54232352,2,"[54232352, 1965851, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11981,14,1435,15,54232352,2,"[54232352, 1967727, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11982,14,1436,15,54232352,2,"[54232352, 1969603, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11983,14,1437,15,54232352,2,"[54232352, 1971480, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11984,14,1438,15,54232352,2,"[54232352, 1973358, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11985,14,1439,15,54232352,2,"[54232352, 1975236, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11986,14,1440,15,54232352,2,"[54232352, 1977116, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11987,14,1441,15,54232352,2,"[54232352, 1978995, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11988,14,1442,15,54232352,2,"[54232352, 1980876, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11989,14,1443,15,54232352,2,"[54232352, 1982757, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11990,14,1444,15,54232352,2,"[54232352, 1984639, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11991,14,1445,15,54232352,2,"[54232352, 1986522, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11992,14,1446,15,54232352,2,"[54232352, 1988405, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11993,14,1447,15,54232352,2,"[54232352, 1990289, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11994,14,1448,15,54232352,2,"[54232352, 1992174, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11995,14,1449,15,54232352,2,"[54232352, 1994059, 6, False]",54232352,54232351,1995848,54232353,False,True,True,False,46875,13107,3615490,2514,2007,True,True,True,False,False,False,False -11996,15,0,17,54232353,1,"[54232352, 1995945, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -11997,15,1,17,54232353,1,"[54232352, 1997832, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -11998,15,2,17,54232353,1,"[54232352, 1999719, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -11999,15,3,17,54232353,1,"[54232353, 1608, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12000,15,4,17,54232353,1,"[54232353, 3496, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12001,15,5,17,54232353,1,"[54232353, 5386, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12002,15,6,17,54232353,1,"[54232353, 7276, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12003,15,7,17,54232353,1,"[54232353, 9167, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12004,15,8,17,54232353,1,"[54232353, 11059, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12005,15,9,17,54232353,1,"[54232353, 12951, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12006,15,10,17,54232353,1,"[54232353, 14845, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12007,15,11,17,54232353,1,"[54232353, 16738, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12008,15,12,17,54232353,1,"[54232353, 18633, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12009,15,13,17,54232353,1,"[54232353, 20528, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12010,15,14,17,54232353,1,"[54232353, 22424, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12011,15,15,17,54232353,1,"[54232353, 24321, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12012,15,16,17,54232353,1,"[54232353, 26218, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12013,15,17,17,54232353,1,"[54232353, 28116, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12014,15,18,17,54232353,1,"[54232353, 30015, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12015,15,19,17,54232353,1,"[54232353, 31914, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12016,15,20,17,54232353,1,"[54232353, 33814, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12017,15,21,17,54232353,1,"[54232353, 35715, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12018,15,22,17,54232353,1,"[54232353, 37616, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12019,15,23,17,54232353,1,"[54232353, 39519, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12020,15,24,17,54232353,1,"[54232353, 41421, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12021,15,25,17,54232353,1,"[54232353, 43325, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12022,15,26,17,54232353,1,"[54232353, 45229, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12023,15,27,17,54232353,1,"[54232353, 47134, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12024,15,28,17,54232353,1,"[54232353, 49040, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12025,15,29,17,54232353,1,"[54232353, 50946, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12026,15,30,17,54232353,1,"[54232353, 52854, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12027,15,31,17,54232353,1,"[54232353, 54761, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12028,15,32,17,54232353,1,"[54232353, 56670, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12029,15,33,17,54232353,1,"[54232353, 58579, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12030,15,34,17,54232353,1,"[54232353, 60489, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12031,15,35,17,54232353,1,"[54232353, 62400, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12032,15,36,17,54232353,1,"[54232353, 64311, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12033,15,37,17,54232353,1,"[54232353, 66223, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12034,15,38,17,54232353,1,"[54232353, 68136, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12035,15,39,17,54232353,1,"[54232353, 70049, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12036,15,40,17,54232353,1,"[54232353, 71963, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12037,15,41,17,54232353,1,"[54232353, 73878, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12038,15,42,17,54232353,1,"[54232353, 75793, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12039,15,43,17,54232353,1,"[54232353, 77710, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12040,15,44,17,54232353,1,"[54232353, 79626, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12041,15,45,17,54232353,1,"[54232353, 81544, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12042,15,46,17,54232353,1,"[54232353, 83462, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12043,15,47,17,54232353,1,"[54232353, 85381, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12044,15,48,17,54232353,1,"[54232353, 87301, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12045,15,49,17,54232353,1,"[54232353, 89221, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12046,15,50,17,54232353,1,"[54232353, 91143, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12047,15,51,17,54232353,1,"[54232353, 93064, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12048,15,52,17,54232353,1,"[54232353, 94987, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12049,15,53,17,54232353,1,"[54232353, 96910, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12050,15,54,17,54232353,1,"[54232353, 98834, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12051,15,55,17,54232353,1,"[54232353, 100759, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12052,15,56,17,54232353,1,"[54232353, 102684, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12053,15,57,17,54232353,1,"[54232353, 104610, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12054,15,58,17,54232353,1,"[54232353, 106537, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12055,15,59,17,54232353,1,"[54232353, 108464, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12056,15,60,17,54232353,1,"[54232353, 110392, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12057,15,61,17,54232353,1,"[54232353, 112321, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12058,15,62,17,54232353,1,"[54232353, 114250, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12059,15,63,17,54232353,1,"[54232353, 116181, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12060,15,64,17,54232353,1,"[54232353, 118111, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12061,15,65,17,54232353,1,"[54232353, 120043, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12062,15,66,17,54232353,1,"[54232353, 121975, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12063,15,67,17,54232353,1,"[54232353, 123908, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12064,15,68,17,54232353,1,"[54232353, 125842, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12065,15,69,17,54232353,1,"[54232353, 127776, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12066,15,70,17,54232353,1,"[54232353, 129712, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12067,15,71,17,54232353,1,"[54232353, 131647, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12068,15,72,17,54232353,1,"[54232353, 133584, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12069,15,73,17,54232353,1,"[54232353, 135521, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12070,15,74,17,54232353,1,"[54232353, 137459, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12071,15,75,17,54232353,1,"[54232353, 139398, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12072,15,76,17,54232353,1,"[54232353, 141337, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12073,15,77,17,54232353,1,"[54232353, 143277, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12074,15,78,17,54232353,1,"[54232353, 145218, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12075,15,79,17,54232353,1,"[54232353, 147159, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12076,15,80,17,54232353,1,"[54232353, 149101, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12077,15,81,17,54232353,1,"[54232353, 151044, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12078,15,82,17,54232353,1,"[54232353, 152987, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12079,15,83,17,54232353,1,"[54232353, 154932, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12080,15,84,17,54232353,1,"[54232353, 156876, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12081,15,85,17,54232353,1,"[54232353, 158822, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12082,15,86,17,54232353,1,"[54232353, 160768, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12083,15,87,17,54232353,1,"[54232353, 162715, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12084,15,88,17,54232353,1,"[54232353, 164663, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12085,15,89,17,54232353,1,"[54232353, 166611, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12086,15,90,17,54232353,1,"[54232353, 168561, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12087,15,91,17,54232353,1,"[54232353, 170510, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12088,15,92,17,54232353,1,"[54232353, 172461, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12089,15,93,17,54232353,1,"[54232353, 174412, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12090,15,94,17,54232353,1,"[54232353, 176364, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12091,15,95,17,54232353,1,"[54232353, 178317, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12092,15,96,17,54232353,1,"[54232353, 180270, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12093,15,97,17,54232353,1,"[54232353, 182224, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12094,15,98,17,54232353,1,"[54232353, 184179, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12095,15,99,17,54232353,1,"[54232353, 186134, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12096,15,100,17,54232353,1,"[54232353, 188090, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12097,15,101,17,54232353,1,"[54232353, 190047, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12098,15,102,17,54232353,1,"[54232353, 192004, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12099,15,103,17,54232353,1,"[54232353, 193963, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12100,15,104,17,54232353,1,"[54232353, 195921, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12101,15,105,17,54232353,1,"[54232353, 197881, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12102,15,106,17,54232353,1,"[54232353, 199841, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12103,15,107,17,54232353,1,"[54232353, 201802, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12104,15,108,17,54232353,1,"[54232353, 203764, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12105,15,109,17,54232353,1,"[54232353, 205726, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12106,15,110,17,54232353,1,"[54232353, 207690, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12107,15,111,17,54232353,1,"[54232353, 209653, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12108,15,112,17,54232353,1,"[54232353, 211618, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12109,15,113,17,54232353,1,"[54232353, 213583, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12110,15,114,17,54232353,1,"[54232353, 215549, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12111,15,115,17,54232353,1,"[54232353, 217516, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12112,15,116,17,54232353,1,"[54232353, 219483, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12113,15,117,17,54232353,1,"[54232353, 221451, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12114,15,118,17,54232353,1,"[54232353, 223420, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12115,15,119,17,54232353,1,"[54232353, 225389, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12116,15,120,17,54232353,1,"[54232353, 227359, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12117,15,121,17,54232353,1,"[54232353, 229330, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12118,15,122,17,54232353,1,"[54232353, 231301, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12119,15,123,17,54232353,1,"[54232353, 233274, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12120,15,124,17,54232353,1,"[54232353, 235246, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12121,15,125,17,54232353,1,"[54232353, 237220, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12122,15,126,17,54232353,1,"[54232353, 239194, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12123,15,127,17,54232353,1,"[54232353, 241169, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12124,15,128,17,54232353,1,"[54232353, 243145, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12125,15,129,17,54232353,1,"[54232353, 245121, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12126,15,130,17,54232353,1,"[54232353, 247099, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12127,15,131,17,54232353,1,"[54232353, 249076, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12128,15,132,17,54232353,1,"[54232353, 251055, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12129,15,133,17,54232353,1,"[54232353, 253034, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12130,15,134,17,54232353,1,"[54232353, 255014, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12131,15,135,17,54232353,1,"[54232353, 256995, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12132,15,136,17,54232353,1,"[54232353, 258976, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12133,15,137,17,54232353,1,"[54232353, 260958, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12134,15,138,17,54232353,1,"[54232353, 262941, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12135,15,139,17,54232353,1,"[54232353, 264924, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12136,15,140,17,54232353,1,"[54232353, 266908, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12137,15,141,17,54232353,1,"[54232353, 268893, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12138,15,142,17,54232353,1,"[54232353, 270878, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12139,15,143,17,54232353,1,"[54232353, 272865, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12140,15,144,17,54232353,1,"[54232353, 274851, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12141,15,145,17,54232353,1,"[54232353, 276839, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12142,15,146,17,54232353,1,"[54232353, 278827, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12143,15,147,17,54232353,1,"[54232353, 280816, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12144,15,148,17,54232353,1,"[54232353, 282806, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12145,15,149,17,54232353,1,"[54232353, 284796, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12146,15,150,17,54232353,1,"[54232353, 286788, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12147,15,151,17,54232353,1,"[54232353, 288779, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12148,15,152,17,54232353,1,"[54232353, 290772, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12149,15,153,17,54232353,1,"[54232353, 292765, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12150,15,154,17,54232353,1,"[54232353, 294759, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12151,15,155,17,54232353,1,"[54232353, 296754, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12152,15,156,17,54232353,1,"[54232353, 298749, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12153,15,157,17,54232353,1,"[54232353, 300745, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12154,15,158,17,54232353,1,"[54232353, 302742, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12155,15,159,17,54232353,1,"[54232353, 304739, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12156,15,160,17,54232353,1,"[54232353, 306737, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12157,15,161,17,54232353,1,"[54232353, 308736, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12158,15,162,17,54232353,1,"[54232353, 310735, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12159,15,163,17,54232353,1,"[54232353, 312736, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12160,15,164,17,54232353,1,"[54232353, 314736, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12161,15,165,17,54232353,1,"[54232353, 316738, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12162,15,166,17,54232353,1,"[54232353, 318740, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12163,15,167,17,54232353,1,"[54232353, 320743, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12164,15,168,17,54232353,1,"[54232353, 322747, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12165,15,169,17,54232353,1,"[54232353, 324751, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12166,15,170,17,54232353,1,"[54232353, 326757, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12167,15,171,17,54232353,1,"[54232353, 328762, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12168,15,172,17,54232353,1,"[54232353, 330769, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12169,15,173,17,54232353,1,"[54232353, 332776, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12170,15,174,17,54232353,1,"[54232353, 334784, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12171,15,175,17,54232353,1,"[54232353, 336793, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12172,15,176,17,54232353,1,"[54232353, 338802, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12173,15,177,17,54232353,1,"[54232353, 340812, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12174,15,178,17,54232353,1,"[54232353, 342823, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12175,15,179,17,54232353,1,"[54232353, 344834, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12176,15,180,17,54232353,1,"[54232353, 346846, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12177,15,181,17,54232353,1,"[54232353, 348859, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12178,15,182,17,54232353,1,"[54232353, 350872, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12179,15,183,17,54232353,1,"[54232353, 352887, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12180,15,184,17,54232353,1,"[54232353, 354901, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12181,15,185,17,54232353,1,"[54232353, 356917, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12182,15,186,17,54232353,1,"[54232353, 358933, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12183,15,187,17,54232353,1,"[54232353, 360950, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12184,15,188,17,54232353,1,"[54232353, 362968, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12185,15,189,17,54232353,1,"[54232353, 364986, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12186,15,190,17,54232353,1,"[54232353, 367006, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12187,15,191,17,54232353,1,"[54232353, 369025, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12188,15,192,17,54232353,1,"[54232353, 371046, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12189,15,193,17,54232353,1,"[54232353, 373067, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12190,15,194,17,54232353,1,"[54232353, 375089, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12191,15,195,17,54232353,1,"[54232353, 377112, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12192,15,196,17,54232353,1,"[54232353, 379135, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12193,15,197,17,54232353,1,"[54232353, 381159, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12194,15,198,17,54232353,1,"[54232353, 383184, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12195,15,199,17,54232353,1,"[54232353, 385209, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12196,15,200,17,54232353,1,"[54232353, 387235, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12197,15,201,17,54232353,1,"[54232353, 389262, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12198,15,202,17,54232353,1,"[54232353, 391289, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12199,15,203,17,54232353,1,"[54232353, 393318, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12200,15,204,17,54232353,1,"[54232353, 395346, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12201,15,205,17,54232353,1,"[54232353, 397376, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12202,15,206,17,54232353,1,"[54232353, 399406, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12203,15,207,17,54232353,1,"[54232353, 401437, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12204,15,208,17,54232353,1,"[54232353, 403469, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12205,15,209,17,54232353,1,"[54232353, 405501, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12206,15,210,17,54232353,1,"[54232353, 407535, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12207,15,211,17,54232353,1,"[54232353, 409568, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12208,15,212,17,54232353,1,"[54232353, 411603, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12209,15,213,17,54232353,1,"[54232353, 413638, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12210,15,214,17,54232353,1,"[54232353, 415674, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12211,15,215,17,54232353,1,"[54232353, 417711, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12212,15,216,17,54232353,1,"[54232353, 419748, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12213,15,217,17,54232353,1,"[54232353, 421786, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12214,15,218,17,54232353,1,"[54232353, 423825, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12215,15,219,17,54232353,1,"[54232353, 425864, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12216,15,220,17,54232353,1,"[54232353, 427904, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12217,15,221,17,54232353,1,"[54232353, 429945, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12218,15,222,17,54232353,1,"[54232353, 431986, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12219,15,223,17,54232353,1,"[54232353, 434029, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12220,15,224,17,54232353,1,"[54232353, 436071, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12221,15,225,17,54232353,1,"[54232353, 438115, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12222,15,226,17,54232353,1,"[54232353, 440159, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12223,15,227,17,54232353,1,"[54232353, 442204, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12224,15,228,17,54232353,1,"[54232353, 444250, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12225,15,229,17,54232353,1,"[54232353, 446296, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12226,15,230,17,54232353,1,"[54232353, 448344, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12227,15,231,17,54232353,1,"[54232353, 450391, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12228,15,232,17,54232353,1,"[54232353, 452440, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12229,15,233,17,54232353,1,"[54232353, 454489, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12230,15,234,17,54232353,1,"[54232353, 456539, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12231,15,235,17,54232353,1,"[54232353, 458590, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12232,15,236,17,54232353,1,"[54232353, 460641, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12233,15,237,17,54232353,1,"[54232353, 462693, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12234,15,238,17,54232353,1,"[54232353, 464746, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12235,15,239,17,54232353,1,"[54232353, 466799, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12236,15,240,17,54232353,1,"[54232353, 468853, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12237,15,241,17,54232353,1,"[54232353, 470908, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12238,15,242,17,54232353,1,"[54232353, 472963, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12239,15,243,17,54232353,1,"[54232353, 475020, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12240,15,244,17,54232353,1,"[54232353, 477076, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12241,15,245,17,54232353,1,"[54232353, 479134, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12242,15,246,17,54232353,1,"[54232353, 481192, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12243,15,247,17,54232353,1,"[54232353, 483251, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12244,15,248,17,54232353,1,"[54232353, 485311, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12245,15,249,17,54232353,1,"[54232353, 487371, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12246,15,250,17,54232353,1,"[54232353, 489433, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12247,15,251,17,54232353,1,"[54232353, 491494, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12248,15,252,17,54232353,1,"[54232353, 493557, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12249,15,253,17,54232353,1,"[54232353, 495620, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12250,15,254,17,54232353,1,"[54232353, 497684, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12251,15,255,17,54232353,1,"[54232353, 499749, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12252,15,256,17,54232353,1,"[54232353, 501814, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12253,15,257,17,54232353,1,"[54232353, 503880, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12254,15,258,17,54232353,1,"[54232353, 505947, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12255,15,259,17,54232353,1,"[54232353, 508014, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12256,15,260,17,54232353,1,"[54232353, 510082, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12257,15,261,17,54232353,1,"[54232353, 512151, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12258,15,262,17,54232353,1,"[54232353, 514220, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12259,15,263,17,54232353,1,"[54232353, 516291, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12260,15,264,17,54232353,1,"[54232353, 518361, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12261,15,265,17,54232353,1,"[54232353, 520433, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12262,15,266,17,54232353,1,"[54232353, 522505, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12263,15,267,17,54232353,1,"[54232353, 524578, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12264,15,268,17,54232353,1,"[54232353, 526652, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12265,15,269,17,54232353,1,"[54232353, 528726, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12266,15,270,17,54232353,1,"[54232353, 530802, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12267,15,271,17,54232353,1,"[54232353, 532877, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12268,15,272,17,54232353,1,"[54232353, 534954, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12269,15,273,17,54232353,1,"[54232353, 537031, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12270,15,274,17,54232353,1,"[54232353, 539109, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12271,15,275,17,54232353,1,"[54232353, 541188, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12272,15,276,17,54232353,1,"[54232353, 543267, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12273,15,277,17,54232353,1,"[54232353, 545347, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12274,15,278,17,54232353,1,"[54232353, 547428, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12275,15,279,17,54232353,1,"[54232353, 549509, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12276,15,280,17,54232353,1,"[54232353, 551591, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12277,15,281,17,54232353,1,"[54232353, 553674, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12278,15,282,17,54232353,1,"[54232353, 555757, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12279,15,283,17,54232353,1,"[54232353, 557842, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12280,15,284,17,54232353,1,"[54232353, 559926, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12281,15,285,17,54232353,1,"[54232353, 562012, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12282,15,286,17,54232353,1,"[54232353, 564098, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12283,15,287,17,54232353,1,"[54232353, 566185, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12284,15,288,17,54232353,1,"[54232353, 568273, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12285,15,289,17,54232353,1,"[54232353, 570361, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12286,15,290,17,54232353,1,"[54232353, 572451, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12287,15,291,17,54232353,1,"[54232353, 574540, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12288,15,292,17,54232353,1,"[54232353, 576631, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12289,15,293,17,54232353,1,"[54232353, 578722, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12290,15,294,17,54232353,1,"[54232353, 580814, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12291,15,295,17,54232353,1,"[54232353, 582907, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12292,15,296,17,54232353,1,"[54232353, 585000, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12293,15,297,17,54232353,1,"[54232353, 587094, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12294,15,298,17,54232353,1,"[54232353, 589189, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12295,15,299,17,54232353,1,"[54232353, 591284, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12296,15,300,17,54232353,1,"[54232353, 593380, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12297,15,301,17,54232353,1,"[54232353, 595477, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12298,15,302,17,54232353,1,"[54232353, 597574, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12299,15,303,17,54232353,1,"[54232353, 599673, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12300,15,304,17,54232353,1,"[54232353, 601771, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12301,15,305,17,54232353,1,"[54232353, 603871, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12302,15,306,17,54232353,1,"[54232353, 605971, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12303,15,307,17,54232353,1,"[54232353, 608072, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12304,15,308,17,54232353,1,"[54232353, 610174, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12305,15,309,17,54232353,1,"[54232353, 612276, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12306,15,310,17,54232353,1,"[54232353, 614380, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12307,15,311,17,54232353,1,"[54232353, 616483, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12308,15,312,17,54232353,1,"[54232353, 618588, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12309,15,313,17,54232353,1,"[54232353, 620693, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12310,15,314,17,54232353,1,"[54232353, 622799, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12311,15,315,17,54232353,1,"[54232353, 624906, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12312,15,316,17,54232353,1,"[54232353, 627013, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12313,15,317,17,54232353,1,"[54232353, 629121, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12314,15,318,17,54232353,1,"[54232353, 631230, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12315,15,319,17,54232353,1,"[54232353, 633339, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12316,15,320,17,54232353,1,"[54232353, 635449, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12317,15,321,17,54232353,1,"[54232353, 637560, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12318,15,322,17,54232353,1,"[54232353, 639671, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12319,15,323,17,54232353,1,"[54232353, 641784, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12320,15,324,17,54232353,1,"[54232353, 643896, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12321,15,325,17,54232353,1,"[54232353, 646010, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12322,15,326,17,54232353,1,"[54232353, 648124, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12323,15,327,17,54232353,1,"[54232353, 650239, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12324,15,328,17,54232353,1,"[54232353, 652355, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12325,15,329,17,54232353,1,"[54232353, 654471, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12326,15,330,17,54232353,1,"[54232353, 656589, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12327,15,331,17,54232353,1,"[54232353, 658706, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12328,15,332,17,54232353,1,"[54232353, 660825, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12329,15,333,17,54232353,1,"[54232353, 662944, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12330,15,334,17,54232353,1,"[54232353, 665064, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12331,15,335,17,54232353,1,"[54232353, 667185, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12332,15,336,17,54232353,1,"[54232353, 669306, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12333,15,337,17,54232353,1,"[54232353, 671428, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12334,15,338,17,54232353,1,"[54232353, 673551, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12335,15,339,17,54232353,1,"[54232353, 675674, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12336,15,340,17,54232353,1,"[54232353, 677798, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12337,15,341,17,54232353,1,"[54232353, 679923, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12338,15,342,17,54232353,1,"[54232353, 682048, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12339,15,343,17,54232353,1,"[54232353, 684175, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12340,15,344,17,54232353,1,"[54232353, 686301, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12341,15,345,17,54232353,1,"[54232353, 688429, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12342,15,346,17,54232353,1,"[54232353, 690557, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12343,15,347,17,54232353,1,"[54232353, 692686, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12344,15,348,17,54232353,1,"[54232353, 694816, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12345,15,349,17,54232353,1,"[54232353, 696946, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12346,15,350,17,54232353,1,"[54232353, 699078, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12347,15,351,17,54232353,1,"[54232353, 701209, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12348,15,352,17,54232353,1,"[54232353, 703342, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12349,15,353,17,54232353,1,"[54232353, 705475, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12350,15,354,17,54232353,1,"[54232353, 707609, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12351,15,355,17,54232353,1,"[54232353, 709744, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12352,15,356,17,54232353,1,"[54232353, 711879, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12353,15,357,17,54232353,1,"[54232353, 714015, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12354,15,358,17,54232353,1,"[54232353, 716152, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12355,15,359,17,54232353,1,"[54232353, 718289, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12356,15,360,17,54232353,1,"[54232353, 720427, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12357,15,361,17,54232353,1,"[54232353, 722566, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12358,15,362,17,54232353,1,"[54232353, 724705, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12359,15,363,17,54232353,1,"[54232353, 726846, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12360,15,364,17,54232353,1,"[54232353, 728986, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12361,15,365,17,54232353,1,"[54232353, 731128, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12362,15,366,17,54232353,1,"[54232353, 733270, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12363,15,367,17,54232353,1,"[54232353, 735413, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12364,15,368,17,54232353,1,"[54232353, 737557, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12365,15,369,17,54232353,1,"[54232353, 739701, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12366,15,370,17,54232353,1,"[54232353, 741847, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12367,15,371,17,54232353,1,"[54232353, 743992, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12368,15,372,17,54232353,1,"[54232353, 746139, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12369,15,373,17,54232353,1,"[54232353, 748286, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12370,15,374,17,54232353,1,"[54232353, 750434, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12371,15,375,17,54232353,1,"[54232353, 752583, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12372,15,376,17,54232353,1,"[54232353, 754732, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12373,15,377,17,54232353,1,"[54232353, 756882, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12374,15,378,17,54232353,1,"[54232353, 759033, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12375,15,379,17,54232353,1,"[54232353, 761184, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12376,15,380,17,54232353,1,"[54232353, 763336, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12377,15,381,17,54232353,1,"[54232353, 765489, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12378,15,382,17,54232353,1,"[54232353, 767642, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12379,15,383,17,54232353,1,"[54232353, 769797, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12380,15,384,17,54232353,1,"[54232353, 771951, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12381,15,385,17,54232353,1,"[54232353, 774107, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12382,15,386,17,54232353,1,"[54232353, 776263, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12383,15,387,17,54232353,1,"[54232353, 778420, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12384,15,388,17,54232353,1,"[54232353, 780578, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12385,15,389,17,54232353,1,"[54232353, 782736, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12386,15,390,17,54232353,1,"[54232353, 784896, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12387,15,391,17,54232353,1,"[54232353, 787055, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12388,15,392,17,54232353,1,"[54232353, 789216, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12389,15,393,17,54232353,1,"[54232353, 791377, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12390,15,394,17,54232353,1,"[54232353, 793539, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12391,15,395,17,54232353,1,"[54232353, 795702, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12392,15,396,17,54232353,1,"[54232353, 797865, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12393,15,397,17,54232353,1,"[54232353, 800029, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12394,15,398,17,54232353,1,"[54232353, 802194, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12395,15,399,17,54232353,1,"[54232353, 804359, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12396,15,400,17,54232353,1,"[54232353, 806525, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12397,15,401,17,54232353,1,"[54232353, 808692, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12398,15,402,17,54232353,1,"[54232353, 810859, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12399,15,403,17,54232353,1,"[54232353, 813028, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12400,15,404,17,54232353,1,"[54232353, 815196, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12401,15,405,17,54232353,1,"[54232353, 817366, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12402,15,406,17,54232353,1,"[54232353, 819536, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12403,15,407,17,54232353,1,"[54232353, 821707, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12404,15,408,17,54232353,1,"[54232353, 823879, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12405,15,409,17,54232353,1,"[54232353, 826051, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12406,15,410,17,54232353,1,"[54232353, 828225, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12407,15,411,17,54232353,1,"[54232353, 830398, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12408,15,412,17,54232353,1,"[54232353, 832573, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12409,15,413,17,54232353,1,"[54232353, 834748, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12410,15,414,17,54232353,1,"[54232353, 836924, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12411,15,415,17,54232353,1,"[54232353, 839101, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12412,15,416,17,54232353,1,"[54232353, 841278, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12413,15,417,17,54232353,1,"[54232353, 843456, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12414,15,418,17,54232353,1,"[54232353, 845635, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12415,15,419,17,54232353,1,"[54232353, 847814, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12416,15,420,17,54232353,1,"[54232353, 849994, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12417,15,421,17,54232353,1,"[54232353, 852175, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12418,15,422,17,54232353,1,"[54232353, 854356, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12419,15,423,17,54232353,1,"[54232353, 856539, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12420,15,424,17,54232353,1,"[54232353, 858721, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12421,15,425,17,54232353,1,"[54232353, 860905, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12422,15,426,17,54232353,1,"[54232353, 863089, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12423,15,427,17,54232353,1,"[54232353, 865274, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12424,15,428,17,54232353,1,"[54232353, 867460, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12425,15,429,17,54232353,1,"[54232353, 869646, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12426,15,430,17,54232353,1,"[54232353, 871834, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12427,15,431,17,54232353,1,"[54232353, 874021, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12428,15,432,17,54232353,1,"[54232353, 876210, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12429,15,433,17,54232353,1,"[54232353, 878399, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12430,15,434,17,54232353,1,"[54232353, 880589, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12431,15,435,17,54232353,1,"[54232353, 882780, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12432,15,436,17,54232353,1,"[54232353, 884971, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12433,15,437,17,54232353,1,"[54232353, 887163, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12434,15,438,17,54232353,1,"[54232353, 889356, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12435,15,439,17,54232353,1,"[54232353, 891549, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12436,15,440,17,54232353,1,"[54232353, 893743, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12437,15,441,17,54232353,1,"[54232353, 895938, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12438,15,442,17,54232353,1,"[54232353, 898133, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12439,15,443,17,54232353,1,"[54232353, 900330, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12440,15,444,17,54232353,1,"[54232353, 902526, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12441,15,445,17,54232353,1,"[54232353, 904724, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12442,15,446,17,54232353,1,"[54232353, 906922, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12443,15,447,17,54232353,1,"[54232353, 909121, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12444,15,448,17,54232353,1,"[54232353, 911321, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12445,15,449,17,54232353,1,"[54232353, 913521, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12446,15,450,17,54232353,1,"[54232353, 915723, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12447,15,451,17,54232353,1,"[54232353, 917924, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12448,15,452,17,54232353,1,"[54232353, 920127, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12449,15,453,17,54232353,1,"[54232353, 922330, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12450,15,454,17,54232353,1,"[54232353, 924534, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12451,15,455,17,54232353,1,"[54232353, 926739, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12452,15,456,17,54232353,1,"[54232353, 928944, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12453,15,457,17,54232353,1,"[54232353, 931150, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12454,15,458,17,54232353,1,"[54232353, 933357, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12455,15,459,17,54232353,1,"[54232353, 935564, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12456,15,460,17,54232353,1,"[54232353, 937772, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12457,15,461,17,54232353,1,"[54232353, 939981, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12458,15,462,17,54232353,1,"[54232353, 942190, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12459,15,463,17,54232353,1,"[54232353, 944401, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12460,15,464,17,54232353,1,"[54232353, 946611, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12461,15,465,17,54232353,1,"[54232353, 948823, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12462,15,466,17,54232353,1,"[54232353, 951035, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12463,15,467,17,54232353,1,"[54232353, 953248, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12464,15,468,17,54232353,1,"[54232353, 955462, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12465,15,469,17,54232353,1,"[54232353, 957676, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12466,15,470,17,54232353,1,"[54232353, 959892, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12467,15,471,17,54232353,1,"[54232353, 962107, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12468,15,472,17,54232353,1,"[54232353, 964324, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12469,15,473,17,54232353,1,"[54232353, 966541, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12470,15,474,17,54232353,1,"[54232353, 968759, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12471,15,475,17,54232353,1,"[54232353, 970978, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12472,15,476,17,54232353,1,"[54232353, 973197, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12473,15,477,17,54232353,1,"[54232353, 975417, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12474,15,478,17,54232353,1,"[54232353, 977638, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12475,15,479,17,54232353,1,"[54232353, 979859, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12476,15,480,17,54232353,1,"[54232353, 982081, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12477,15,481,17,54232353,1,"[54232353, 984304, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12478,15,482,17,54232353,1,"[54232353, 986527, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12479,15,483,17,54232353,1,"[54232353, 988752, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12480,15,484,17,54232353,1,"[54232353, 990976, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12481,15,485,17,54232353,1,"[54232353, 993202, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12482,15,486,17,54232353,1,"[54232353, 995428, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12483,15,487,17,54232353,1,"[54232353, 997655, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12484,15,488,17,54232353,1,"[54232353, 999883, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12485,15,489,17,54232353,1,"[54232353, 1002111, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12486,15,490,17,54232353,1,"[54232353, 1004341, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12487,15,491,17,54232353,1,"[54232353, 1006570, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12488,15,492,17,54232353,1,"[54232353, 1008801, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12489,15,493,17,54232353,1,"[54232353, 1011032, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12490,15,494,17,54232353,1,"[54232353, 1013264, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12491,15,495,17,54232353,1,"[54232353, 1015497, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12492,15,496,17,54232353,1,"[54232353, 1017730, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12493,15,497,17,54232353,1,"[54232353, 1019964, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12494,15,498,17,54232353,1,"[54232353, 1022199, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12495,15,499,17,54232353,1,"[54232353, 1024434, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12496,15,500,17,54232353,1,"[54232353, 1026670, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12497,15,501,17,54232353,1,"[54232353, 1028907, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12498,15,502,17,54232353,1,"[54232353, 1031144, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12499,15,503,17,54232353,1,"[54232353, 1033383, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12500,15,504,17,54232353,1,"[54232353, 1035621, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12501,15,505,17,54232353,1,"[54232353, 1037861, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12502,15,506,17,54232353,1,"[54232353, 1040101, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12503,15,507,17,54232353,1,"[54232353, 1042342, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12504,15,508,17,54232353,1,"[54232353, 1044584, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12505,15,509,17,54232353,1,"[54232353, 1046826, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12506,15,510,17,54232353,1,"[54232353, 1049070, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12507,15,511,17,54232353,1,"[54232353, 1051313, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12508,15,512,17,54232353,1,"[54232353, 1053558, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12509,15,513,17,54232353,1,"[54232353, 1055803, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12510,15,514,17,54232353,1,"[54232353, 1058049, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12511,15,515,17,54232353,1,"[54232353, 1060296, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12512,15,516,17,54232353,1,"[54232353, 1062543, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12513,15,517,17,54232353,1,"[54232353, 1064791, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12514,15,518,17,54232353,1,"[54232353, 1067040, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12515,15,519,17,54232353,1,"[54232353, 1069289, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12516,15,520,17,54232353,1,"[54232353, 1071539, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12517,15,521,17,54232353,1,"[54232353, 1073790, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12518,15,522,17,54232353,1,"[54232353, 1076041, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12519,15,523,17,54232353,1,"[54232353, 1078294, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12520,15,524,17,54232353,1,"[54232353, 1080546, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12521,15,525,17,54232353,1,"[54232353, 1082800, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12522,15,526,17,54232353,1,"[54232353, 1085054, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12523,15,527,17,54232353,1,"[54232353, 1087309, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12524,15,528,17,54232353,1,"[54232353, 1089565, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12525,15,529,17,54232353,1,"[54232353, 1091821, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12526,15,530,17,54232353,1,"[54232353, 1094079, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12527,15,531,17,54232353,1,"[54232353, 1096336, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12528,15,532,17,54232353,1,"[54232353, 1098595, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12529,15,533,17,54232353,1,"[54232353, 1100854, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12530,15,534,17,54232353,1,"[54232353, 1103114, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12531,15,535,17,54232353,1,"[54232353, 1105375, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12532,15,536,17,54232353,1,"[54232353, 1107636, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12533,15,537,17,54232353,1,"[54232353, 1109898, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12534,15,538,17,54232353,1,"[54232353, 1112161, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12535,15,539,17,54232353,1,"[54232353, 1114424, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12536,15,540,17,54232353,1,"[54232353, 1116688, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12537,15,541,17,54232353,1,"[54232353, 1118953, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12538,15,542,17,54232353,1,"[54232353, 1121218, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12539,15,543,17,54232353,1,"[54232353, 1123485, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12540,15,544,17,54232353,1,"[54232353, 1125751, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12541,15,545,17,54232353,1,"[54232353, 1128019, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12542,15,546,17,54232353,1,"[54232353, 1130287, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12543,15,547,17,54232353,1,"[54232353, 1132556, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12544,15,548,17,54232353,1,"[54232353, 1134826, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12545,15,549,17,54232353,1,"[54232353, 1137096, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12546,15,550,17,54232353,1,"[54232353, 1139368, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12547,15,551,17,54232353,1,"[54232353, 1141639, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12548,15,552,17,54232353,1,"[54232353, 1143912, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12549,15,553,17,54232353,1,"[54232353, 1146185, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12550,15,554,17,54232353,1,"[54232353, 1148459, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12551,15,555,17,54232353,1,"[54232353, 1150734, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12552,15,556,17,54232353,1,"[54232353, 1153009, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12553,15,557,17,54232353,1,"[54232353, 1155285, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12554,15,558,17,54232353,1,"[54232353, 1157562, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12555,15,559,17,54232353,1,"[54232353, 1159839, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12556,15,560,17,54232353,1,"[54232353, 1162117, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12557,15,561,17,54232353,1,"[54232353, 1164396, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12558,15,562,17,54232353,1,"[54232353, 1166675, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12559,15,563,17,54232353,1,"[54232353, 1168956, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12560,15,564,17,54232353,1,"[54232353, 1171236, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12561,15,565,17,54232353,1,"[54232353, 1173518, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12562,15,566,17,54232353,1,"[54232353, 1175800, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12563,15,567,17,54232353,1,"[54232353, 1178083, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12564,15,568,17,54232353,1,"[54232353, 1180367, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12565,15,569,17,54232353,1,"[54232353, 1182651, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12566,15,570,17,54232353,1,"[54232353, 1184937, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12567,15,571,17,54232353,1,"[54232353, 1187222, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12568,15,572,17,54232353,1,"[54232353, 1189509, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12569,15,573,17,54232353,1,"[54232353, 1191796, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12570,15,574,17,54232353,1,"[54232353, 1194084, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12571,15,575,17,54232353,1,"[54232353, 1196373, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12572,15,576,17,54232353,1,"[54232353, 1198662, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12573,15,577,17,54232353,1,"[54232353, 1200952, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12574,15,578,17,54232353,1,"[54232353, 1203243, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12575,15,579,17,54232353,1,"[54232353, 1205534, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12576,15,580,17,54232353,1,"[54232353, 1207826, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12577,15,581,17,54232353,1,"[54232353, 1210119, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12578,15,582,17,54232353,1,"[54232353, 1212412, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12579,15,583,17,54232353,1,"[54232353, 1214707, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12580,15,584,17,54232353,1,"[54232353, 1217001, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12581,15,585,17,54232353,1,"[54232353, 1219297, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12582,15,586,17,54232353,1,"[54232353, 1221593, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12583,15,587,17,54232353,1,"[54232353, 1223890, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12584,15,588,17,54232353,1,"[54232353, 1226188, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12585,15,589,17,54232353,1,"[54232353, 1228486, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12586,15,590,17,54232353,1,"[54232353, 1230786, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12587,15,591,17,54232353,1,"[54232353, 1233085, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12588,15,592,17,54232353,1,"[54232353, 1235386, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12589,15,593,17,54232353,1,"[54232353, 1237687, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12590,15,594,17,54232353,1,"[54232353, 1239989, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12591,15,595,17,54232353,1,"[54232353, 1242292, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12592,15,596,17,54232353,1,"[54232353, 1244595, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12593,15,597,17,54232353,1,"[54232353, 1246899, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12594,15,598,17,54232353,1,"[54232353, 1249204, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12595,15,599,17,54232353,1,"[54232353, 1251509, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12596,15,600,17,54232353,1,"[54232353, 1253815, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12597,15,601,17,54232353,1,"[54232353, 1256122, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12598,15,602,17,54232353,1,"[54232353, 1258429, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12599,15,603,17,54232353,1,"[54232353, 1260738, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12600,15,604,17,54232353,1,"[54232353, 1263046, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12601,15,605,17,54232353,1,"[54232353, 1265356, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12602,15,606,17,54232353,1,"[54232353, 1267666, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12603,15,607,17,54232353,1,"[54232353, 1269977, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12604,15,608,17,54232353,1,"[54232353, 1272289, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12605,15,609,17,54232353,1,"[54232353, 1274601, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12606,15,610,17,54232353,1,"[54232353, 1276915, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12607,15,611,17,54232353,1,"[54232353, 1279228, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12608,15,612,17,54232353,1,"[54232353, 1281543, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12609,15,613,17,54232353,1,"[54232353, 1283858, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12610,15,614,17,54232353,1,"[54232353, 1286174, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12611,15,615,17,54232353,1,"[54232353, 1288491, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12612,15,616,17,54232353,1,"[54232353, 1290808, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12613,15,617,17,54232353,1,"[54232353, 1293126, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12614,15,618,17,54232353,1,"[54232353, 1295445, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12615,15,619,17,54232353,1,"[54232353, 1297764, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12616,15,620,17,54232353,1,"[54232353, 1300084, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12617,15,621,17,54232353,1,"[54232353, 1302405, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12618,15,622,17,54232353,1,"[54232353, 1304726, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12619,15,623,17,54232353,1,"[54232353, 1307049, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12620,15,624,17,54232353,1,"[54232353, 1309371, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12621,15,625,17,54232353,1,"[54232353, 1311695, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12622,15,626,17,54232353,1,"[54232353, 1314019, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12623,15,627,17,54232353,1,"[54232353, 1316344, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12624,15,628,17,54232353,1,"[54232353, 1318670, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12625,15,629,17,54232353,1,"[54232353, 1320996, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12626,15,630,17,54232353,1,"[54232353, 1323324, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12627,15,631,17,54232353,1,"[54232353, 1325651, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12628,15,632,17,54232353,1,"[54232353, 1327980, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12629,15,633,17,54232353,1,"[54232353, 1330309, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12630,15,634,17,54232353,1,"[54232353, 1332639, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12631,15,635,17,54232353,1,"[54232353, 1334970, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12632,15,636,17,54232353,1,"[54232353, 1337301, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12633,15,637,17,54232353,1,"[54232353, 1339633, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12634,15,638,17,54232353,1,"[54232353, 1341966, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12635,15,639,17,54232353,1,"[54232353, 1344299, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12636,15,640,17,54232353,1,"[54232353, 1346633, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12637,15,641,17,54232353,1,"[54232353, 1348968, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12638,15,642,17,54232353,1,"[54232353, 1351303, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12639,15,643,17,54232353,1,"[54232353, 1353640, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12640,15,644,17,54232353,1,"[54232353, 1355976, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12641,15,645,17,54232353,1,"[54232353, 1358314, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12642,15,646,17,54232353,1,"[54232353, 1360652, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12643,15,647,17,54232353,1,"[54232353, 1362991, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12644,15,648,17,54232353,1,"[54232353, 1365331, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12645,15,649,17,54232353,1,"[54232353, 1367671, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12646,15,650,17,54232353,1,"[54232353, 1370013, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12647,15,651,17,54232353,1,"[54232353, 1372354, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12648,15,652,17,54232353,1,"[54232353, 1374697, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12649,15,653,17,54232353,1,"[54232353, 1377040, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12650,15,654,17,54232353,1,"[54232353, 1379384, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12651,15,655,17,54232353,1,"[54232353, 1381729, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12652,15,656,17,54232353,1,"[54232353, 1384074, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12653,15,657,17,54232353,1,"[54232353, 1386420, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12654,15,658,17,54232353,1,"[54232353, 1388767, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12655,15,659,17,54232353,1,"[54232353, 1391114, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12656,15,660,17,54232353,1,"[54232353, 1393462, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12657,15,661,17,54232353,1,"[54232353, 1395811, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12658,15,662,17,54232353,1,"[54232353, 1398160, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12659,15,663,17,54232353,1,"[54232353, 1400511, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12660,15,664,17,54232353,1,"[54232353, 1402861, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12661,15,665,17,54232353,1,"[54232353, 1405213, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12662,15,666,17,54232353,1,"[54232353, 1407565, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12663,15,667,17,54232353,1,"[54232353, 1409918, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12664,15,668,17,54232353,1,"[54232353, 1412272, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12665,15,669,17,54232353,1,"[54232353, 1414626, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12666,15,670,17,54232353,1,"[54232353, 1416982, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12667,15,671,17,54232353,1,"[54232353, 1419337, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12668,15,672,17,54232353,1,"[54232353, 1421694, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12669,15,673,17,54232353,1,"[54232353, 1424051, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12670,15,674,17,54232353,1,"[54232353, 1426409, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12671,15,675,17,54232353,1,"[54232353, 1428768, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12672,15,676,17,54232353,1,"[54232353, 1431127, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12673,15,677,17,54232353,1,"[54232353, 1433487, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12674,15,678,17,54232353,1,"[54232353, 1435848, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12675,15,679,17,54232353,1,"[54232353, 1438209, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12676,15,680,17,54232353,1,"[54232353, 1440571, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12677,15,681,17,54232353,1,"[54232353, 1442934, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12678,15,682,17,54232353,1,"[54232353, 1445297, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12679,15,683,17,54232353,1,"[54232353, 1447662, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12680,15,684,17,54232353,1,"[54232353, 1450026, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12681,15,685,17,54232353,1,"[54232353, 1452392, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12682,15,686,17,54232353,1,"[54232353, 1454758, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12683,15,687,17,54232353,1,"[54232353, 1457125, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12684,15,688,17,54232353,1,"[54232353, 1459493, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12685,15,689,17,54232353,1,"[54232353, 1461861, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12686,15,690,17,54232353,1,"[54232353, 1464231, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12687,15,691,17,54232353,1,"[54232353, 1466600, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12688,15,692,17,54232353,1,"[54232353, 1468971, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12689,15,693,17,54232353,1,"[54232353, 1471342, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12690,15,694,17,54232353,1,"[54232353, 1473714, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12691,15,695,17,54232353,1,"[54232353, 1476087, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12692,15,696,17,54232353,1,"[54232353, 1478460, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12693,15,697,17,54232353,1,"[54232353, 1480834, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12694,15,698,17,54232353,1,"[54232353, 1483209, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12695,15,699,17,54232353,1,"[54232353, 1485584, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12696,15,700,17,54232353,1,"[54232353, 1487960, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12697,15,701,17,54232353,1,"[54232353, 1490337, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12698,15,702,17,54232353,1,"[54232353, 1492714, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12699,15,703,17,54232353,1,"[54232353, 1495093, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12700,15,704,17,54232353,1,"[54232353, 1497471, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12701,15,705,17,54232353,1,"[54232353, 1499851, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12702,15,706,17,54232353,1,"[54232353, 1502231, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12703,15,707,17,54232353,1,"[54232353, 1504612, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12704,15,708,17,54232353,1,"[54232353, 1506994, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12705,15,709,17,54232353,1,"[54232353, 1509376, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12706,15,710,17,54232353,1,"[54232353, 1511760, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12707,15,711,17,54232353,1,"[54232353, 1514143, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12708,15,712,17,54232353,1,"[54232353, 1516528, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12709,15,713,17,54232353,1,"[54232353, 1518913, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12710,15,714,17,54232353,1,"[54232353, 1521299, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12711,15,715,17,54232353,1,"[54232353, 1523686, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12712,15,716,17,54232353,1,"[54232353, 1526073, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12713,15,717,17,54232353,1,"[54232353, 1528461, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12714,15,718,17,54232353,1,"[54232353, 1530850, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12715,15,719,17,54232353,1,"[54232353, 1533239, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12716,15,720,17,54232353,1,"[54232353, 1535629, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12717,15,721,17,54232353,1,"[54232353, 1538020, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12718,15,722,17,54232353,1,"[54232353, 1540411, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12719,15,723,17,54232353,1,"[54232353, 1542804, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12720,15,724,17,54232353,1,"[54232353, 1545196, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12721,15,725,17,54232353,1,"[54232353, 1547590, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12722,15,726,17,54232353,1,"[54232353, 1549984, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12723,15,727,17,54232353,1,"[54232353, 1552379, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12724,15,728,17,54232353,1,"[54232353, 1554775, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12725,15,729,17,54232353,1,"[54232353, 1557171, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12726,15,730,17,54232353,1,"[54232353, 1559569, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12727,15,731,17,54232353,1,"[54232353, 1561966, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12728,15,732,17,54232353,1,"[54232353, 1564365, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12729,15,733,17,54232353,1,"[54232353, 1566764, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12730,15,734,17,54232353,1,"[54232353, 1569164, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12731,15,735,17,54232353,1,"[54232353, 1571565, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12732,15,736,17,54232353,1,"[54232353, 1573966, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12733,15,737,17,54232353,1,"[54232353, 1576368, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12734,15,738,17,54232353,1,"[54232353, 1578771, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12735,15,739,17,54232353,1,"[54232353, 1581174, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12736,15,740,17,54232353,1,"[54232353, 1583578, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12737,15,741,17,54232353,1,"[54232353, 1585983, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12738,15,742,17,54232353,1,"[54232353, 1588388, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12739,15,743,17,54232353,1,"[54232353, 1590795, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12740,15,744,17,54232353,1,"[54232353, 1593201, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12741,15,745,17,54232353,1,"[54232353, 1595609, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12742,15,746,17,54232353,1,"[54232353, 1598017, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12743,15,747,17,54232353,1,"[54232353, 1600426, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12744,15,748,17,54232353,1,"[54232353, 1602836, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12745,15,749,17,54232353,1,"[54232353, 1605246, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12746,15,750,17,54232353,1,"[54232353, 1607658, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12747,15,751,17,54232353,1,"[54232353, 1610069, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12748,15,752,17,54232353,1,"[54232353, 1612482, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12749,15,753,17,54232353,1,"[54232353, 1614895, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12750,15,754,17,54232353,1,"[54232353, 1617309, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12751,15,755,17,54232353,1,"[54232353, 1619724, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12752,15,756,17,54232353,1,"[54232353, 1622139, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12753,15,757,17,54232353,1,"[54232353, 1624555, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12754,15,758,17,54232353,1,"[54232353, 1626972, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12755,15,759,17,54232353,1,"[54232353, 1629389, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12756,15,760,17,54232353,1,"[54232353, 1631807, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12757,15,761,17,54232353,1,"[54232353, 1634226, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12758,15,762,17,54232353,1,"[54232353, 1636645, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12759,15,763,17,54232353,1,"[54232353, 1639066, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12760,15,764,17,54232353,1,"[54232353, 1641486, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12761,15,765,17,54232353,1,"[54232353, 1643908, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12762,15,766,17,54232353,1,"[54232353, 1646330, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12763,15,767,17,54232353,1,"[54232353, 1648753, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12764,15,768,17,54232353,1,"[54232353, 1651177, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12765,15,769,17,54232353,1,"[54232353, 1653601, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12766,15,770,17,54232353,1,"[54232353, 1656027, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12767,15,771,17,54232353,1,"[54232353, 1658452, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12768,15,772,17,54232353,1,"[54232353, 1660879, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12769,15,773,17,54232353,1,"[54232353, 1663306, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12770,15,774,17,54232353,1,"[54232353, 1665734, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12771,15,775,17,54232353,1,"[54232353, 1668163, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12772,15,776,17,54232353,1,"[54232353, 1670592, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12773,15,777,17,54232353,1,"[54232353, 1673022, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12774,15,778,17,54232353,1,"[54232353, 1675453, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12775,15,779,17,54232353,1,"[54232353, 1677884, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12776,15,780,17,54232353,1,"[54232353, 1680316, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12777,15,781,17,54232353,1,"[54232353, 1682749, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12778,15,782,17,54232353,1,"[54232353, 1685182, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12779,15,783,17,54232353,1,"[54232353, 1687617, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12780,15,784,17,54232353,1,"[54232353, 1690051, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12781,15,785,17,54232353,1,"[54232353, 1692487, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12782,15,786,17,54232353,1,"[54232353, 1694923, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12783,15,787,17,54232353,1,"[54232353, 1697360, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12784,15,788,17,54232353,1,"[54232353, 1699798, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12785,15,789,17,54232353,1,"[54232353, 1702236, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12786,15,790,17,54232353,1,"[54232353, 1704676, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12787,15,791,17,54232353,1,"[54232353, 1707115, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12788,15,792,17,54232353,1,"[54232353, 1709556, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12789,15,793,17,54232353,1,"[54232353, 1711997, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12790,15,794,17,54232353,1,"[54232353, 1714439, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12791,15,795,17,54232353,1,"[54232353, 1716882, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12792,15,796,17,54232353,1,"[54232353, 1719325, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12793,15,797,17,54232353,1,"[54232353, 1721769, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12794,15,798,17,54232353,1,"[54232353, 1724214, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12795,15,799,17,54232353,1,"[54232353, 1726659, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12796,15,800,17,54232353,1,"[54232353, 1729105, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12797,15,801,17,54232353,1,"[54232353, 1731552, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12798,15,802,17,54232353,1,"[54232353, 1733999, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12799,15,803,17,54232353,1,"[54232353, 1736448, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12800,15,804,17,54232353,1,"[54232353, 1738896, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12801,15,805,17,54232353,1,"[54232353, 1741346, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12802,15,806,17,54232353,1,"[54232353, 1743796, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12803,15,807,17,54232353,1,"[54232353, 1746247, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12804,15,808,17,54232353,1,"[54232353, 1748699, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12805,15,809,17,54232353,1,"[54232353, 1751151, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12806,15,810,17,54232353,1,"[54232353, 1753605, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12807,15,811,17,54232353,1,"[54232353, 1756058, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12808,15,812,17,54232353,1,"[54232353, 1758513, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12809,15,813,17,54232353,1,"[54232353, 1760968, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12810,15,814,17,54232353,1,"[54232353, 1763424, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12811,15,815,17,54232353,1,"[54232353, 1765881, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12812,15,816,17,54232353,1,"[54232353, 1768338, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12813,15,817,17,54232353,1,"[54232353, 1770796, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12814,15,818,17,54232353,1,"[54232353, 1773255, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12815,15,819,17,54232353,1,"[54232353, 1775714, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12816,15,820,17,54232353,1,"[54232353, 1778174, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12817,15,821,17,54232353,1,"[54232353, 1780635, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12818,15,822,17,54232353,1,"[54232353, 1783096, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12819,15,823,17,54232353,1,"[54232353, 1785559, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12820,15,824,17,54232353,1,"[54232353, 1788021, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12821,15,825,17,54232353,1,"[54232353, 1790485, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12822,15,826,17,54232353,1,"[54232353, 1792949, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12823,15,827,17,54232353,1,"[54232353, 1795414, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12824,15,828,17,54232353,1,"[54232353, 1797880, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12825,15,829,17,54232353,1,"[54232353, 1800346, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12826,15,830,17,54232353,1,"[54232353, 1802814, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12827,15,831,17,54232353,1,"[54232353, 1805281, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12828,15,832,17,54232353,1,"[54232353, 1807750, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12829,15,833,17,54232353,1,"[54232353, 1810219, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12830,15,834,17,54232353,1,"[54232353, 1812689, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12831,15,835,17,54232353,1,"[54232353, 1815160, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12832,15,836,17,54232353,1,"[54232353, 1817631, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12833,15,837,17,54232353,1,"[54232353, 1820103, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12834,15,838,17,54232353,1,"[54232353, 1822576, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12835,15,839,17,54232353,1,"[54232353, 1825049, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12836,15,840,17,54232353,1,"[54232353, 1827523, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12837,15,841,17,54232353,1,"[54232353, 1829998, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12838,15,842,17,54232353,1,"[54232353, 1832473, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12839,15,843,17,54232353,1,"[54232353, 1834950, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12840,15,844,17,54232353,1,"[54232353, 1837426, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12841,15,845,17,54232353,1,"[54232353, 1839904, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12842,15,846,17,54232353,1,"[54232353, 1842382, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12843,15,847,17,54232353,1,"[54232353, 1844861, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12844,15,848,17,54232353,1,"[54232353, 1847341, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12845,15,849,17,54232353,1,"[54232353, 1849821, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12846,15,850,17,54232353,1,"[54232353, 1852303, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12847,15,851,17,54232353,1,"[54232353, 1854784, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12848,15,852,17,54232353,1,"[54232353, 1857267, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12849,15,853,17,54232353,1,"[54232353, 1859750, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12850,15,854,17,54232353,1,"[54232353, 1862234, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12851,15,855,17,54232353,1,"[54232353, 1864719, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12852,15,856,17,54232353,1,"[54232353, 1867204, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12853,15,857,17,54232353,1,"[54232353, 1869690, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12854,15,858,17,54232353,1,"[54232353, 1872177, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12855,15,859,17,54232353,1,"[54232353, 1874664, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12856,15,860,17,54232353,1,"[54232353, 1877152, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12857,15,861,17,54232353,1,"[54232353, 1879641, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12858,15,862,17,54232353,1,"[54232353, 1882130, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12859,15,863,17,54232353,1,"[54232353, 1884621, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12860,15,864,17,54232353,1,"[54232353, 1887111, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12861,15,865,17,54232353,1,"[54232353, 1889603, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12862,15,866,17,54232353,1,"[54232353, 1892095, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12863,15,867,17,54232353,1,"[54232353, 1894588, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12864,15,868,17,54232353,1,"[54232353, 1897082, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12865,15,869,17,54232353,1,"[54232353, 1899576, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12866,15,870,17,54232353,1,"[54232353, 1902072, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12867,15,871,17,54232353,1,"[54232353, 1904567, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12868,15,872,17,54232353,1,"[54232353, 1907064, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12869,15,873,17,54232353,1,"[54232353, 1909561, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12870,15,874,17,54232353,1,"[54232353, 1912059, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12871,15,875,17,54232353,1,"[54232353, 1914558, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12872,15,876,17,54232353,1,"[54232353, 1917057, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12873,15,877,17,54232353,1,"[54232353, 1919557, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12874,15,878,17,54232353,1,"[54232353, 1922058, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12875,15,879,17,54232353,1,"[54232353, 1924559, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12876,15,880,17,54232353,1,"[54232353, 1927061, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12877,15,881,17,54232353,1,"[54232353, 1929564, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12878,15,882,17,54232353,1,"[54232353, 1932067, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12879,15,883,17,54232353,1,"[54232353, 1934572, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12880,15,884,17,54232353,1,"[54232353, 1937076, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12881,15,885,17,54232353,1,"[54232353, 1939582, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12882,15,886,17,54232353,1,"[54232353, 1942088, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12883,15,887,17,54232353,1,"[54232353, 1944595, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12884,15,888,17,54232353,1,"[54232353, 1947103, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12885,15,889,17,54232353,1,"[54232353, 1949611, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12886,15,890,17,54232353,1,"[54232353, 1952121, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12887,15,891,17,54232353,1,"[54232353, 1954630, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12888,15,892,17,54232353,1,"[54232353, 1957141, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12889,15,893,17,54232353,1,"[54232353, 1959652, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12890,15,894,17,54232353,1,"[54232353, 1962164, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12891,15,895,17,54232353,1,"[54232353, 1964677, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12892,15,896,17,54232353,1,"[54232353, 1967190, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12893,15,897,17,54232353,1,"[54232353, 1969704, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12894,15,898,17,54232353,1,"[54232353, 1972219, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12895,15,899,17,54232353,1,"[54232353, 1974734, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12896,15,900,17,54232353,1,"[54232353, 1977250, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12897,15,901,17,54232353,1,"[54232353, 1979767, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12898,15,902,17,54232353,1,"[54232353, 1982284, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12899,15,903,17,54232353,1,"[54232353, 1984803, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12900,15,904,17,54232353,1,"[54232353, 1987321, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12901,15,905,17,54232353,1,"[54232353, 1989841, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12902,15,906,17,54232353,1,"[54232353, 1992361, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False -12903,15,907,17,54232353,1,"[54232353, 1994882, 6, False]",54232353,54232352,1995837,54232354,False,True,True,False,46875,17476,3615490,2501,2007,True,True,True,False,False,False,False diff --git a/imap_processing/tests/glows/validation_data/imap_glows_pipeline-settings_20251112_v001.json b/imap_processing/tests/glows/validation_data/imap_glows_pipeline-settings_20251112_v001.json new file mode 100644 index 0000000000..a7952c22d9 --- /dev/null +++ b/imap_processing/tests/glows/validation_data/imap_glows_pipeline-settings_20251112_v001.json @@ -0,0 +1,56 @@ +{ + "description": "Settings for ground-processing pipeline for IMAP/GLOWS instrument", + "version": "1.0", + "date_of_creation_yyyymmdd": "20250703", + "filter_based_on_daily_statistical_error": { + "n_sigma_threshold_lower": 3.0, + "n_sigma_threshold_upper": 3.0 + }, + "filter_based_on_comparison_of_spin_periods": { + "relative_difference_threshold": 7.0e-4 + }, + "filter_based_on_temperature_std_dev": { + "std_dev_threshold__celsius_deg": 2.03 + }, + "filter_based_on_hv_voltage_std_dev": { + "std_dev_threshold__volt": 50.0 + }, + "filter_based_on_spin_period_std_dev": { + "std_dev_threshold__sec": 0.033333 + }, + "filter_based_on_pulse_length_std_dev": { + "std_dev_threshold__usec": 1.0 + }, + "filter_based_on_maps": { + "angular_radius_for_excl_regions__deg": 0.5 + }, + "active_bad_time_flags": { + "is_pps_missing": true, + "is_time_status_missing": true, + "is_phase_missing": true, + "is_spin_period_missing": true, + "is_overexposed": false, + "is_direct_event_non_monotonic": true, + "is_night": true, + "is_hv_test_in_progress": false, + "is_test_pulse_in_progress": true, + "is_memory_error_detected": true, + "is_generated_on_ground": true, + "is_beyond_daily_statistical_error": false, + "is_temperature_std_dev_beyond_threshold": true, + "is_hv_voltage_std_dev_beyond_threshold": true, + "is_spin_period_std_dev_beyond_threshold": true, + "is_pulse_length_std_dev_beyond_threshold": true, + "is_spin_period_difference_beyond_threshold": true + }, + "active_bad_angle_flags": { + "is_close_to_uv_source": true, + "is_inside_excluded_region": true, + "is_excluded_by_instr_team": true, + "is_suspected_transient": true + }, + "sunrise_offset": 0, + "sunset_offset": 0, + "l3a_nominal_number_of_bins": 90, + "spin_offset_correction": 1.047 +} diff --git a/imap_processing/tests/hi/conftest.py b/imap_processing/tests/hi/conftest.py index 3c421f98e6..a63872ee07 100644 --- a/imap_processing/tests/hi/conftest.py +++ b/imap_processing/tests/hi/conftest.py @@ -18,6 +18,16 @@ def hi_l1_test_data_path(hi_test_data_path): return hi_test_data_path / "l1" +@pytest.fixture(scope="session") +def hi_test_cal_prod_config_path(hi_l1_test_data_path): + return hi_l1_test_data_path / "imap_hi_90sensor-cal-prod_20240101_v001.csv" + + +@pytest.fixture(scope="session") +def hi_test_background_config_path(hi_l1_test_data_path): + return hi_l1_test_data_path / "imap_hi_90sensor-backgrounds_20240101_v001.csv" + + def create_metaevent(esa_step, met_subseconds, met_seconds): start_bitmask_data = 0 # META return ( diff --git a/imap_processing/tests/hi/data/l0/H90_MEMDMP-2025-07-09.bin b/imap_processing/tests/hi/data/l0/H90_MEMDMP-2025-07-09.bin new file mode 100644 index 0000000000..67f6d52113 Binary files /dev/null and b/imap_processing/tests/hi/data/l0/H90_MEMDMP-2025-07-09.bin differ diff --git a/imap_processing/tests/hi/data/l0/H90_MEMDMP-2025-07-09.csv b/imap_processing/tests/hi/data/l0/H90_MEMDMP-2025-07-09.csv new file mode 100644 index 0000000000..22ad104e33 --- /dev/null +++ b/imap_processing/tests/hi/data/l0/H90_MEMDMP-2025-07-09.csv @@ -0,0 +1,14 @@ +ccsds_met,memory_id,start_address,lastbin_shorten,coinc_length,de_timetag,ab_min,ab_max,ac_min,ac_max,ba_min,ba_max,bc_min,bc_max,ca_min,ca_max,cb_min,cb_max,cc_min,cc_max,cfd_dac_a,cfd_dac_b,cfd_dac_c,cfd_dac_d,de_mask,ab_rnk,cc_rnk,ac_rnk,bc_rnk,abc_rnk,acc_rnk,bcc_rnk,abcc_rnk,esa_table,esa_steps,sci_cull,eng_cull,spins_per_step,spins_per_de +496552080,0x01000001,0x4004C758,20000,1000,2000,0,250,0,250,0,100,0,150,0,100,0,100,0,400,102,102,102,102,0,1,1,1,2,0,0,0,0,0,9,1,0,8,4 +496562492,0x01000001,0x4004C758,20000,1000,2000,0,250,0,250,0,100,0,150,0,100,0,100,0,400,102,102,102,102,0,1,1,1,2,0,0,0,0,0,9,1,0,8,4 +496563774,0x01000001,0x4004C758,20000,1000,2000,0,250,0,250,0,100,0,150,0,100,0,100,0,400,102,102,102,102,0,1,1,1,2,0,0,0,0,0,9,1,0,8,4 +498374356,0x01000001,0x4004C578,20000,1000,2000,0,250,0,250,0,100,0,150,0,100,0,100,0,400,103,103,103,103,0,1,1,1,2,0,0,0,0,0,9,1,0,8,4 +498374798,0x01000001,0x4004C578,20000,1000,2000,0,250,0,250,0,100,0,150,0,100,0,100,0,400,103,103,103,103,0,1,1,1,2,0,0,0,0,0,9,1,0,8,4 +498378711,0x01000001,0x4004C578,20000,1000,2000,0,250,0,250,0,100,0,150,0,100,0,100,0,400,103,103,103,103,0,1,1,1,2,0,0,0,0,0,9,1,0,8,4 +508999025,0x01000001,0x4004C758,20000,1000,2000,0,250,0,250,0,100,0,150,0,100,0,100,0,400,102,102,102,102,0,1,1,1,2,0,0,0,0,0,9,1,0,8,4 +527966507,0x01000001,0x4004C578,20000,1000,2000,0,250,0,250,0,100,0,150,0,100,0,100,0,400,102,102,102,102,0,1,1,1,2,0,0,0,0,0,9,1,0,8,4 +528141819,0x01000001,0x4004C578,20000,1000,2000,0,250,0,250,0,100,0,150,0,100,0,100,0,400,102,102,102,102,0,1,1,1,2,0,0,0,0,0,9,1,0,8,4 +528201496,0x01000001,0x4004C578,20000,1000,2000,0,250,0,250,0,100,0,150,0,100,0,100,0,400,102,102,102,102,0,1,1,1,2,0,0,0,0,0,9,1,0,8,4 +528287896,0x01000001,0x4004C578,20000,1000,2000,0,250,0,250,0,100,0,150,0,100,0,100,0,400,102,102,102,102,0,1,1,1,2,0,0,0,0,0,9,1,0,8,4 +528374296,0x01000001,0x4004C578,20000,1000,2000,0,250,0,250,0,100,0,150,0,100,0,100,0,400,102,102,102,102,0,1,1,1,2,0,0,0,0,0,9,1,0,8,4 +528411355,0x01000001,0x4004C578,20000,1000,2000,0,250,0,250,0,100,0,150,0,100,0,100,0,400,102,102,102,102,0,1,1,1,2,0,0,0,0,0,9,1,0,8,4 \ No newline at end of file diff --git a/imap_processing/tests/hi/data/l1/imap_hi_90sensor-backgrounds_20240101_v001.csv b/imap_processing/tests/hi/data/l1/imap_hi_90sensor-backgrounds_20240101_v001.csv new file mode 100644 index 0000000000..85ed97c974 --- /dev/null +++ b/imap_processing/tests/hi/data/l1/imap_hi_90sensor-backgrounds_20240101_v001.csv @@ -0,0 +1,55 @@ +# THIS IS A TEST FILE AND SHOULD NOT BE USED IN PRODUCTION PROCESSING. +# +# Backgrounds Determination Configuration File +# Valid start date: 2024-01-01 (from filename) +# This file will be used in processing until a new calibration file is uploaded +# to the SDC with either a higher version number or new date in the filename. +# For details on how the SDC selects ancillary files for processing, see: +# https://imap-processing.readthedocs.io/en/latest/data-access/calibration-files.html +# +# When creating PSET products, the following table will be used to determine per +# calibration product backgrounds. The backgrounds for each calibration product are +# computed individually and the sum is subtracted from the calibration product. Background +# uncertainties are summed in quadrature and reported in background uncertainties. +# +# TOF windows and coincidence_type_list only need to be specified on the first row +# of each (calibration_prod, background_index) group. Subsequent rows will inherit +# these values. scaling_factor and uncertainty must be specified for each ESA step. +# +calibration_prod,background_index,esa_energy_step,scaling_factor,uncertainty,coincidence_type_list,tof_ab_low,tof_ab_high,tof_ac1_low,tof_ac1_high,tof_bc1_low,tof_bc1_high,tof_c1c2_low,tof_c1c2_high +0,0,1,0.00306,0.00030,ABC1C2|ABC1,-20,16,-46,-15,-511,511,0,1023 +0,0,2,0.00310,0.00031,,,,,,,,, +0,0,3,0.00315,0.00032,,,,,,,,, +0,0,4,0.00320,0.00033,,,,,,,,, +0,0,5,0.00325,0.00034,,,,,,,,, +0,0,6,0.00330,0.00035,,,,,,,,, +0,0,7,0.00335,0.00036,,,,,,,,, +0,0,8,0.00340,0.00037,,,,,,,,, +0,0,9,0.00345,0.00038,,,,,,,,, +0,1,1,0.0189,0.0020,AB,-20,16,-46,-15,-511,511,0,1023 +0,1,2,0.0191,0.0021,,,,,,,,, +0,1,3,0.0193,0.0022,,,,,,,,, +0,1,4,0.0195,0.0023,,,,,,,,, +0,1,5,0.0197,0.0024,,,,,,,,, +0,1,6,0.0199,0.0025,,,,,,,,, +0,1,7,0.0201,0.0026,,,,,,,,, +0,1,8,0.0203,0.0027,,,,,,,,, +0,1,9,0.0205,0.0028,,,,,,,,, +1,0,1,0.00306,0.00030,BC1C2|AC1,-20,16,-46,-15,-511,511,0,1023 +1,0,2,0.00308,0.00031,,,,,,,,, +1,0,3,0.00310,0.00032,,,,,,,,, +1,0,4,0.00312,0.00033,,,,,,,,, +1,0,5,0.00314,0.00034,,,,,,,,, +1,0,6,0.00316,0.00035,,,,,,,,, +1,0,7,0.00318,0.00036,,,,,,,,, +1,0,8,0.00320,0.00037,,,,,,,,, +1,0,9,0.00322,0.00038,,,,,,,,, +1,1,1,0.0189,0.0020,AB,-20,16,-46,-15,-511,511,0,1023 +1,1,2,0.0190,0.0021,,,,,,,,, +1,1,3,0.0191,0.0022,,,,,,,,, +1,1,4,0.0192,0.0023,,,,,,,,, +1,1,5,0.0193,0.0024,,,,,,,,, +1,1,6,0.0194,0.0025,,,,,,,,, +1,1,7,0.0195,0.0026,,,,,,,,, +1,1,8,0.0196,0.0027,,,,,,,,, +1,1,9,0.0197,0.0028,,,,,,,,, diff --git a/imap_processing/tests/hi/data/l1/imap_hi_90sensor-cal-prod_20240101_v001.csv b/imap_processing/tests/hi/data/l1/imap_hi_90sensor-cal-prod_20240101_v001.csv index a133166f6b..6c15fa2fb5 100644 --- a/imap_processing/tests/hi/data/l1/imap_hi_90sensor-cal-prod_20240101_v001.csv +++ b/imap_processing/tests/hi/data/l1/imap_hi_90sensor-cal-prod_20240101_v001.csv @@ -10,22 +10,22 @@ # DEs with coincidence type contained in the `coincidence_type_list` and time-of-flight # values that are in the inclusive range specified by the low and high entries for each # energy step are included in the angular pset bins. -cal_prod_num,esa_energy_step,coincidence_type_list,tof_ab_low,tof_ab_high,tof_ac1_low,tof_ac1_high,tof_bc1_low,tof_bc1_high,tof_c1c2_low,tof_c1c2_high -0,1,ABC1C2|ABC1|AC1C2,15,55,0,70,-50,10,5,25 -0,2,ABC1C2|ABC1|AC1C2,15,55,0,70,-50,10,5,25 -0,3,ABC1C2|ABC1|AC1C2,15,55,0,70,-50,10,5,25 -0,4,ABC1C2|ABC1|AC1C2,15,55,0,70,-50,10,5,25 -0,5,ABC1C2|ABC1|AC1C2,15,55,0,70,-50,10,5,25 -0,6,ABC1C2|ABC1|AC1C2,15,55,0,70,-50,10,5,25 -0,7,ABC1C2|ABC1|AC1C2,15,55,0,70,-50,10,5,25 -0,8,ABC1C2|ABC1|AC1C2,15,55,0,70,-50,10,5,25 -0,9,ABC1C2|ABC1|AC1C2,15,55,0,70,-50,10,5,25 -1,1,BC1C2|AB|AC1,15,55,0,70,-50,10,5,25 -1,2,BC1C2|AB|AC1,15,55,0,70,-50,10,5,25 -1,3,BC1C2|AB|AC1,15,55,0,70,-50,10,5,25 -1,4,BC1C2|AB|AC1,15,55,0,70,-50,10,5,25 -1,5,BC1C2|AB|AC1,15,55,0,70,-50,10,5,25 -1,6,BC1C2|AB|AC1,15,55,0,70,-50,10,5,25 -1,7,BC1C2|AB|AC1,15,55,0,70,-50,10,5,25 -1,8,BC1C2|AB|AC1,15,55,0,70,-50,10,5,25 -1,9,BC1C2|AB|AC1,15,55,0,70,-50,10,5,25 \ No newline at end of file +calibration_prod,esa_energy_step,geometric_factor,coincidence_type_list,tof_ab_low,tof_ab_high,tof_ac1_low,tof_ac1_high,tof_bc1_low,tof_bc1_high,tof_c1c2_low,tof_c1c2_high +0,1,0.00055,ABC1C2|ABC1|AC1C2,15,55,0,70,-50,10,5,25 +0,2,0.00085,ABC1C2|ABC1|AC1C2,15,55,0,70,-50,10,5,25 +0,3,0.00126,ABC1C2|ABC1|AC1C2,15,55,0,70,-50,10,5,25 +0,4,0.00170,ABC1C2|ABC1|AC1C2,15,55,0,70,-50,10,5,25 +0,5,0.00340,ABC1C2|ABC1|AC1C2,15,55,0,70,-50,10,5,25 +0,6,0.00523,ABC1C2|ABC1|AC1C2,15,55,0,70,-50,10,5,25 +0,7,0.00659,ABC1C2|ABC1|AC1C2,15,55,0,70,-50,10,5,25 +0,8,0.01301,ABC1C2|ABC1|AC1C2,15,55,0,70,-50,10,5,25 +0,9,0.01830,ABC1C2|ABC1|AC1C2,15,55,0,70,-50,10,5,25 +1,1,0.00055,BC1C2|AB|AC1,15,55,0,70,-50,10,5,25 +1,2,0.00085,BC1C2|AB|AC1,15,55,0,70,-50,10,5,25 +1,3,0.00126,BC1C2|AB|AC1,15,55,0,70,-50,10,5,25 +1,4,0.00170,BC1C2|AB|AC1,15,55,0,70,-50,10,5,25 +1,5,0.00340,BC1C2|AB|AC1,15,55,0,70,-50,10,5,25 +1,6,0.00523,BC1C2|AB|AC1,15,55,0,70,-50,10,5,25 +1,7,0.00659,BC1C2|AB|AC1,15,55,0,70,-50,10,5,25 +1,8,0.01301,BC1C2|AB|AC1,15,55,0,70,-50,10,5,25 +1,9,0.01830,BC1C2|AB|AC1,15,55,0,70,-50,10,5,25 \ No newline at end of file diff --git a/imap_processing/tests/hi/data/l1/imap_hi_90sensor-esa-energies_20240101_v001.csv b/imap_processing/tests/hi/data/l1/imap_hi_90sensor-esa-energies_20240101_v001.csv index 79018dc8c8..1b9329fa11 100644 --- a/imap_processing/tests/hi/data/l1/imap_hi_90sensor-esa-energies_20240101_v001.csv +++ b/imap_processing/tests/hi/data/l1/imap_hi_90sensor-esa-energies_20240101_v001.csv @@ -12,14 +12,14 @@ # - To generate a mapping from ESA Step to ESA Energy Step for each contiguous HVSCI # interval. This is used in L1B DE processing. # - In L2 processing to associate an ESA Energy Step to an Energy band. -esa_energy_step,nominal_central_energy,inner_esa_voltage,inner_esa_delta_v,outer_esa_voltage,outer_esa_delta_v +esa_energy_step,nominal_central_energy,bandpass_sigma,bandpass_fwhm,inner_esa_voltage,inner_esa_delta_v,outer_esa_voltage,outer_esa_delta_v 0,,0,25,0,25 -1,0.50,-465,25,100,25 -2,0.75,-703,25,142,25 -3,1.10,-1010,25,191,25 -4,1.65,-1532,25,247,25 -5,2.50,-2056,25,695,25 -6,3.75,-2867,25,1213,25 -7,5.70,-4116,25,2014,25 -8,8.52,-5917,25,3169,25 -9,12.8,-8624,25,4897,25 \ No newline at end of file +1,0.50,0.10,0.23,-465,25,100,25 +2,0.75,0.15,0.35,-703,25,142,25 +3,1.10,0.22,0.52,-1010,25,191,25 +4,1.65,0.33,0.78,-1532,25,247,25 +5,2.50,0.50,1.17,-2056,25,695,25 +6,3.75,0.75,1.76,-2867,25,1213,25 +7,5.70,1.14,2.68,-4116,25,2014,25 +8,8.52,1.70,4.00,-5917,25,3169,25 +9,12.8,2.55,6.01,-8624,25,4897,25 \ No newline at end of file diff --git a/imap_processing/tests/hi/test_hi_goodtimes.py b/imap_processing/tests/hi/test_hi_goodtimes.py new file mode 100644 index 0000000000..f9d036e43f --- /dev/null +++ b/imap_processing/tests/hi/test_hi_goodtimes.py @@ -0,0 +1,4240 @@ +"""Test coverage for imap_processing.hi.hi_goodtimes.py""" + +from unittest.mock import MagicMock, patch + +import numpy as np +import pandas as pd +import pytest +import xarray as xr + +from imap_processing.hi.hi_goodtimes import ( + INTERVAL_DTYPE, + CullCode, + _add_sweep_indices, + _apply_goodtimes_filters, + _build_per_sweep_datasets, + _compute_bins_for_cluster, + _compute_median_and_sigma_per_esa, + _compute_normalized_counts_per_sweep, + _compute_qualified_counts_per_sweep, + _find_current_pointing_index, + _find_event_clusters, + _get_sweep_indices, + _identify_cull_pattern, + create_goodtimes_dataset, + hi_goodtimes, + mark_bad_esa_voltage, + mark_bad_tdc_cal, + mark_drf_times, + mark_incomplete_spin_sets, + mark_overflow_packets, + mark_statistical_filter_0, + mark_statistical_filter_1, + mark_statistical_filter_2, +) +from imap_processing.quality_flags import ImapHiL1bDeFlags + + +@pytest.fixture +def mock_l1b_de(): + """Create a mock L1B Direct Event dataset for testing.""" + # Create 10 unique MET times, each appearing twice (paired) + # Plus 2 unpaired MET times + n_paired = 10 + + # Paired METs: each appears twice + paired_mets = np.arange(1000.0, 1000.0 + n_paired * 10, 10) + esa_step_met = np.repeat(paired_mets, 2) + + # Add unpaired METs + unpaired_mets = np.array([2000.0, 3000.0]) + esa_step_met = np.concatenate([esa_step_met, unpaired_mets]) + + # ESA energy step cycles through values + esa_energy_step = np.tile(np.arange(1, 11), len(esa_step_met) // 10 + 1)[ + : len(esa_step_met) + ] + + ds = xr.Dataset( + { + "esa_step_met": (["epoch"], esa_step_met), + "esa_step": (["epoch"], esa_energy_step.astype(np.uint8)), + }, + attrs={ + "Logical_source": "imap_hi_l1b_45sensor-de", + "Repointing": "repoint00042", + }, + ) + return ds + + +@pytest.fixture +def goodtimes_instance(mock_l1b_de): + """Create a goodtimes dataset for testing.""" + return create_goodtimes_dataset(mock_l1b_de) + + +class TestCullCode: + """Test suite for CullCode IntEnum.""" + + def test_cull_code_values(self): + """Test CullCode enum values are bit flags (powers of 2).""" + assert CullCode.GOOD == 0 + assert CullCode.INCOMPLETE_SPIN == 1 + assert CullCode.DRF == 2 + assert CullCode.BAD_TDC_CAL == 4 + assert CullCode.OVERFLOW == 8 + assert CullCode.STAT_FILTER_0 == 16 + assert CullCode.STAT_FILTER_1 == 32 + assert CullCode.STAT_FILTER_2 == 64 + assert CullCode.BAD_ESA_VOLTAGE == 128 + + def test_cull_code_is_int(self): + """Test that CullCode values are integers.""" + assert isinstance(CullCode.GOOD, int) + assert isinstance(CullCode.INCOMPLETE_SPIN, int) + + def test_cull_codes_can_be_combined(self): + """Test that cull codes can be combined with bitwise OR.""" + combined = CullCode.INCOMPLETE_SPIN | CullCode.DRF + assert combined == 3 + # Check individual flags can be extracted with bitwise AND + assert combined & CullCode.INCOMPLETE_SPIN == CullCode.INCOMPLETE_SPIN + assert combined & CullCode.DRF == CullCode.DRF + assert combined & CullCode.BAD_TDC_CAL == 0 + + +class TestGoodtimesFromL1bDe: + """Test suite for create_goodtimes_dataset() from L1B DE.""" + + def test_from_l1b_de_basic(self, mock_l1b_de): + """Test basic creation from L1B DE data.""" + gt = create_goodtimes_dataset(mock_l1b_de) + + assert isinstance(gt, xr.Dataset) + + def test_from_l1b_de_keeps_unique_mets(self, mock_l1b_de): + """Test that all unique METs are included.""" + gt = create_goodtimes_dataset(mock_l1b_de) + + # Should have 12 unique METs (10 paired + 2 unpaired) + assert len(gt.coords["met"]) == 12 + + def test_from_l1b_de_dimensions(self, goodtimes_instance): + """Test that dimensions are correct.""" + assert "met" in goodtimes_instance.dims + assert "spin_bin" in goodtimes_instance.dims + assert goodtimes_instance.sizes["spin_bin"] == 90 + + def test_from_l1b_de_coordinates(self, goodtimes_instance): + """Test that coordinates are set correctly.""" + assert "met" in goodtimes_instance.coords + assert "spin_bin" in goodtimes_instance.coords + + # spin_bin should be 0-89 + np.testing.assert_array_equal( + goodtimes_instance.coords["spin_bin"].values, np.arange(90) + ) + + def test_from_l1b_de_data_variables(self, goodtimes_instance): + """Test that data variables are created.""" + assert "cull_flags" in goodtimes_instance.data_vars + assert "esa_step" in goodtimes_instance.data_vars + + def test_from_l1b_de_cull_flags_initialized_to_zero(self, goodtimes_instance): + """Test that cull_flags are initialized to 0 (good).""" + assert np.all(goodtimes_instance["cull_flags"].values == 0) + + def test_from_l1b_de_cull_flags_shape(self, goodtimes_instance): + """Test cull_flags array shape.""" + n_met = len(goodtimes_instance.coords["met"]) + assert goodtimes_instance["cull_flags"].shape == (n_met, 90) + + def test_from_l1b_de_esa_step_preserved(self, mock_l1b_de, goodtimes_instance): + """Test that ESA step values are preserved for all unique METs.""" + # Get first occurrence of each unique MET + met_all = mock_l1b_de["esa_step_met"].values + unique_mets, first_indices = np.unique(met_all, return_index=True) + expected_esa_steps = mock_l1b_de["esa_step"].values[first_indices] + + np.testing.assert_array_equal( + goodtimes_instance["esa_step"].values, expected_esa_steps + ) + + def test_from_l1b_de_attributes(self, goodtimes_instance): + """Test that attributes are set correctly.""" + assert goodtimes_instance.attrs["Sensor"] == "45sensor" + assert goodtimes_instance.attrs["Repointing"] == "repoint00042" + + +class TestRemoveTimes: + """Test suite for Goodtimes.mark_bad_times() method.""" + + def test_mark_bad_times_single_met_all_bins(self, goodtimes_instance): + """Test flagging a single MET with all bins.""" + met_val = goodtimes_instance.coords["met"].values[0] + goodtimes_instance.goodtimes.mark_bad_times( + met=met_val, bins=None, cull=CullCode.INCOMPLETE_SPIN + ) + + # Check that all bins for the first MET are flagged + assert np.all( + goodtimes_instance["cull_flags"].values[0, :] == CullCode.INCOMPLETE_SPIN + ) + + # Check that other METs are still good + assert np.all(goodtimes_instance["cull_flags"].values[1:, :] == CullCode.GOOD) + + def test_mark_bad_times_single_met_specific_bins(self, goodtimes_instance): + """Test flagging specific bins for a single MET.""" + met_val = goodtimes_instance.coords["met"].values[0] + bins_to_flag = np.array([0, 1, 2, 10]) + goodtimes_instance.goodtimes.mark_bad_times( + met=met_val, bins=bins_to_flag, cull=CullCode.INCOMPLETE_SPIN + ) + + # Check that specified bins are flagged + assert np.all( + goodtimes_instance["cull_flags"].values[0, bins_to_flag] + == CullCode.INCOMPLETE_SPIN + ) + + # Check that other bins are still good + other_bins = np.setdiff1d(np.arange(90), bins_to_flag) + assert np.all( + goodtimes_instance["cull_flags"].values[0, other_bins] == CullCode.GOOD + ) + + def test_mark_bad_times_multiple_mets(self, goodtimes_instance): + """Test flagging multiple METs.""" + met_vals = goodtimes_instance.coords["met"].values[:3] + goodtimes_instance.goodtimes.mark_bad_times( + met=met_vals, bins=None, cull=CullCode.INCOMPLETE_SPIN + ) + + # Check that first 3 METs are flagged + assert np.all( + goodtimes_instance["cull_flags"].values[:3, :] == CullCode.INCOMPLETE_SPIN + ) + + # Check that other METs are still good + assert np.all(goodtimes_instance["cull_flags"].values[3:, :] == CullCode.GOOD) + + def test_mark_bad_times_time_range(self, goodtimes_instance): + """Test flagging a time range.""" + met_vals = goodtimes_instance.coords["met"].values + met_start = met_vals[2] + met_end = met_vals[5] + + goodtimes_instance.goodtimes.mark_bad_times( + met=(met_start, met_end), bins=None, cull=CullCode.INCOMPLETE_SPIN + ) + + # Check that METs 2-5 are flagged + assert np.all( + goodtimes_instance["cull_flags"].values[2:6, :] == CullCode.INCOMPLETE_SPIN + ) + + # Check that other METs are still good + assert np.all(goodtimes_instance["cull_flags"].values[:2, :] == CullCode.GOOD) + assert np.all(goodtimes_instance["cull_flags"].values[6:, :] == CullCode.GOOD) + + def test_mark_bad_times_invalid_cull_code_zero(self, goodtimes_instance): + """Test that cull code 0 raises ValueError.""" + met_val = goodtimes_instance.coords["met"].values[0] + with pytest.raises(ValueError, match="Cull code must be non-zero"): + goodtimes_instance.goodtimes.mark_bad_times(met=met_val, cull=0) + + def test_mark_bad_times_invalid_bin_indices(self, goodtimes_instance): + """Test that invalid bin indices raise ValueError.""" + met_val = goodtimes_instance.coords["met"].values[0] + + # Test bin < 0 + with pytest.raises(ValueError, match="Spin bins must be in range"): + goodtimes_instance.goodtimes.mark_bad_times( + met=met_val, bins=np.array([-1, 0]) + ) + + # Test bin >= 90 + with pytest.raises(ValueError, match="Spin bins must be in range"): + goodtimes_instance.goodtimes.mark_bad_times( + met=met_val, bins=np.array([89, 90]) + ) + + def test_mark_bad_times_met_out_of_range(self, goodtimes_instance): + """Test that MET outside valid range raises ValueError.""" + met_vals = goodtimes_instance.coords["met"].values + # Use a value clearly beyond the valid range + # (last MET + 2x the interval between last two METs) + met_out_of_range = met_vals[-1] + 2000 + + with pytest.raises(ValueError, match="MET value\\(s\\) "): + goodtimes_instance.goodtimes.mark_bad_times(met=met_out_of_range) + + def test_mark_bad_times_combines_cull_codes(self, goodtimes_instance): + """Test that cull codes are combined using bitwise OR.""" + met_val = goodtimes_instance.coords["met"].values[0] + + # Flag with INCOMPLETE_SPIN (1) + goodtimes_instance.goodtimes.mark_bad_times( + met=met_val, bins=None, cull=CullCode.INCOMPLETE_SPIN + ) + assert np.all( + goodtimes_instance["cull_flags"].values[0, :] == CullCode.INCOMPLETE_SPIN + ) + + # Add another cull code with bitwise OR (1 | 2 = 3) + goodtimes_instance.goodtimes.mark_bad_times( + met=met_val, bins=None, cull=CullCode.DRF + ) + expected = CullCode.INCOMPLETE_SPIN | CullCode.DRF # 1 | 2 = 3 + assert np.all(goodtimes_instance["cull_flags"].values[0, :] == expected) + + +class TestGetGoodIntervals: + """Test suite for Goodtimes.get_good_intervals() method.""" + + def test_get_good_intervals_all_good(self, goodtimes_instance): + """Test getting intervals when all times are good.""" + intervals = goodtimes_instance.goodtimes.get_good_intervals() + + # With sweep-based grouping, consecutive sweeps with identical patterns + # are merged. The number of intervals depends on sweep structure. + assert len(intervals) >= 1 + assert intervals.dtype == INTERVAL_DTYPE + + # All intervals should be good (cull_value == 0) + for interval in intervals: + assert interval["cull_value"] == 0 + # All-good intervals have all ESAs marked in bitmask + assert interval["esa_step_mask"] > 0 + + def test_get_good_intervals_structure(self, goodtimes_instance): + """Test interval structure and attributes.""" + intervals = goodtimes_instance.goodtimes.get_good_intervals() + + # Check that intervals have the correct dtype + assert intervals.dtype == INTERVAL_DTYPE + + # Check that all required fields exist + required_fields = [ + "met_start", + "met_end", + "spin_bin_low", + "spin_bin_high", + "n_bins", + "esa_step_mask", + "cull_value", + ] + for field in required_fields: + assert field in intervals.dtype.names + + def test_get_good_intervals_all_good_values(self, goodtimes_instance): + """Test interval values when all bins are good.""" + intervals = goodtimes_instance.goodtimes.get_good_intervals() + + # With sweep-based grouping, we may have multiple intervals + assert len(intervals) >= 1 + + # All intervals should be all-good (cull_value == 0) + for interval in intervals: + assert interval["esa_step_mask"] > 0 + assert interval["cull_value"] == 0 + + # First interval should start at first MET + met_values = goodtimes_instance.coords["met"].values + assert intervals[0]["met_start"] == met_values[0] + + # Last interval's met_end should be the last MET + assert intervals[-1]["met_end"] == met_values[-1] + + # met_end of each interval (except last) should be met_start of next + for i in range(len(intervals) - 1): + assert intervals[i]["met_end"] == intervals[i + 1]["met_start"] + + def test_get_good_intervals_with_culled_bins(self, goodtimes_instance): + """Test intervals when some bins are culled.""" + # Flag bins 0-20 for first MET only + met_val = goodtimes_instance.coords["met"].values[0] + goodtimes_instance.goodtimes.mark_bad_times( + met=met_val, bins=np.arange(21), cull=CullCode.INCOMPLETE_SPIN + ) + + intervals = goodtimes_instance.goodtimes.get_good_intervals() + + # Only good intervals are output: + # - First sweep has one ESA step with partial cull (bins 21-89 good) + # - Remaining sweeps are fully good (all bins) + # The number of intervals depends on sweep grouping + assert len(intervals) >= 2 + + # Check for the partial interval (bins 21-89 good for the culled ESA step) + has_partial = any( + interval["spin_bin_low"] == 21 and interval["spin_bin_high"] == 89 + for interval in intervals + ) + assert has_partial, "Should have at least one partial region with bins 21-89" + + def test_get_good_intervals_with_gaps(self, goodtimes_instance): + """Test intervals when bins have gaps in cull values.""" + # Flag bins 20-70 for first MET, leaving bins 0-19 and 71-89 as good + met_val = goodtimes_instance.coords["met"].values[0] + goodtimes_instance.goodtimes.mark_bad_times( + met=met_val, bins=np.arange(20, 71), cull=CullCode.INCOMPLETE_SPIN + ) + + intervals = goodtimes_instance.goodtimes.get_good_intervals() + + # Only good intervals are output: + # - First sweep has one ESA step with partial cull (bins 0-19 and 71-89 good) + # - Remaining sweeps are fully good + # Bad intervals (bins 20-70) are not output + assert len(intervals) >= 3 + + # Check that we have good bin regions for the partial ESA step + # bins 0-19 good + low_good = [ + i for i in intervals if i["spin_bin_low"] == 0 and i["spin_bin_high"] == 19 + ] + assert len(low_good) >= 1 + + # bins 71-89 good + high_good = [ + i for i in intervals if i["spin_bin_low"] == 71 and i["spin_bin_high"] == 89 + ] + assert len(high_good) >= 1 + + def test_get_good_intervals_all_bins_culled(self, goodtimes_instance): + """Test intervals when all bins are culled for a MET.""" + # Flag all bins for first MET + met_val = goodtimes_instance.coords["met"].values[0] + goodtimes_instance.goodtimes.mark_bad_times( + met=met_val, bins=None, cull=CullCode.INCOMPLETE_SPIN + ) + + intervals = goodtimes_instance.goodtimes.get_good_intervals() + + # Only good intervals are output - the fully-culled ESA step is not output + # The remaining good ESA steps should be output + assert len(intervals) >= 1 + + # All output intervals should have good bins (cull_value indicates what + # was culled). Check that we have a fully-good interval (bins 0-89) for + # the good ESA steps + full_good = [ + i for i in intervals if i["spin_bin_low"] == 0 and i["spin_bin_high"] == 89 + ] + assert len(full_good) >= 1 + + # The cull_value should indicate the cull code for the culled ESA step + assert full_good[0]["cull_value"] == CullCode.INCOMPLETE_SPIN + + def test_get_good_intervals_empty(self): + """Test intervals with empty goodtimes dataset.""" + # Create empty dataset + gt = xr.Dataset( + data_vars={ + "cull_flags": xr.DataArray( + np.zeros((0, 90), dtype=np.uint8), dims=["met", "spin_bin"] + ), + "esa_step": xr.DataArray(np.array([], dtype=np.uint8), dims=["met"]), + }, + coords={"met": np.array([]), "spin_bin": np.arange(90)}, + attrs={"sensor": "45sensor", "pointing": 0}, + ) + + intervals = gt.goodtimes.get_good_intervals() + assert len(intervals) == 0 + + def test_get_good_intervals_esa_step_mask(self, goodtimes_instance): + """Test that ESA step mask includes ESA steps in each interval.""" + intervals = goodtimes_instance.goodtimes.get_good_intervals() + + # With sweep-based grouping, each interval has its own ESA step mask + assert len(intervals) >= 1 + + # Collect all ESA steps across all intervals + all_esa_steps_in_intervals = set() + for interval in intervals: + esa_step_mask = interval["esa_step_mask"] + for bit_position in range(10): # ESA steps 1-10 + if (esa_step_mask >> bit_position) & 1: + all_esa_steps_in_intervals.add(bit_position + 1) + + # All unique ESA steps should be represented across all intervals + unique_esa_steps = set(goodtimes_instance["esa_step"].values) + assert all_esa_steps_in_intervals == unique_esa_steps + + +class TestGetCullStatistics: + """Test suite for Goodtimes.get_cull_statistics() method.""" + + def test_get_cull_statistics_all_good(self, goodtimes_instance): + """Test statistics when all bins are good.""" + stats = goodtimes_instance.goodtimes.get_cull_statistics() + + total_bins = len(goodtimes_instance.coords["met"]) * 90 + assert stats["total_bins"] == total_bins + assert stats["good_bins"] == total_bins + assert stats["culled_bins"] == 0 + assert stats["fraction_good"] == 1.0 + assert stats["cull_code_counts"] == {} + + def test_get_cull_statistics_with_culls(self, goodtimes_instance): + """Test statistics after culling some bins.""" + # Flag first MET, all bins + met_val = goodtimes_instance.coords["met"].values[0] + goodtimes_instance.goodtimes.mark_bad_times( + met=met_val, bins=None, cull=CullCode.INCOMPLETE_SPIN + ) + + stats = goodtimes_instance.goodtimes.get_cull_statistics() + + total_bins = len(goodtimes_instance.coords["met"]) * 90 + assert stats["total_bins"] == total_bins + assert stats["good_bins"] == total_bins - 90 + assert stats["culled_bins"] == 90 + assert stats["fraction_good"] == (total_bins - 90) / total_bins + assert stats["cull_code_counts"][CullCode.INCOMPLETE_SPIN] == 90 + + def test_get_cull_statistics_multiple_cull_codes(self, goodtimes_instance): + """Test statistics with multiple cull codes.""" + met_vals = goodtimes_instance.coords["met"].values + + # Flag first MET with LOOSE + goodtimes_instance.goodtimes.mark_bad_times( + met=met_vals[0], bins=None, cull=CullCode.INCOMPLETE_SPIN + ) + + # Flag second MET with code 2 + goodtimes_instance.goodtimes.mark_bad_times(met=met_vals[1], bins=None, cull=2) + + stats = goodtimes_instance.goodtimes.get_cull_statistics() + + assert stats["culled_bins"] == 180 + assert stats["cull_code_counts"][CullCode.INCOMPLETE_SPIN] == 90 + assert stats["cull_code_counts"][2] == 90 + + +class TestToTxt: + """Test suite for Goodtimes.to_txt() method.""" + + def test_to_txt_creates_file(self, goodtimes_instance, tmp_path): + """Test that to_txt creates a file.""" + output_path = tmp_path / "goodtimes.txt" + result = goodtimes_instance.goodtimes.write_txt(output_path) + + assert result == output_path + assert output_path.exists() + + def test_to_txt_format(self, goodtimes_instance, tmp_path): + """Test the format of the output file.""" + output_path = tmp_path / "goodtimes.txt" + goodtimes_instance.goodtimes.write_txt(output_path) + + with open(output_path) as f: + lines = f.readlines() + + # With sweep-based grouping, may have multiple intervals + assert len(lines) >= 1 + + # Check format of first line + # Format: pointing met_start met_end bin_low bin_high sensor + # esa_steps[10] cull_value + parts = lines[0].strip().split() + assert len(parts) == 17 # 6 base fields + 10 ESA step flags + cull_value + assert parts[0] == "00042" # pointing + assert parts[5] == "45" # sensor + assert parts[16] == "0" # cull_value (all good, no culled ESA steps) + + def test_to_txt_values(self, goodtimes_instance, tmp_path): + """Test the values in the output file.""" + output_path = tmp_path / "goodtimes.txt" + goodtimes_instance.goodtimes.write_txt(output_path) + + with open(output_path) as f: + lines = f.readlines() + + # With sweep-based grouping, may have multiple intervals + assert len(lines) >= 1 + + # Check first line format + parts = lines[0].strip().split() + # Format: pointing met_start met_end bin_low bin_high sensor + # esa_steps[10] cull_value + pointing = parts[0] + met_start = parts[1] + bin_low = parts[3] + bin_high = parts[4] + sensor = parts[5] + cull_value = parts[16] + + assert pointing == "00042" + # First interval should start at first MET + assert float(met_start) == goodtimes_instance.coords["met"].values[0] + assert int(bin_low) == 0 + assert int(bin_high) == 89 + assert sensor == "45" + assert cull_value == "0" # All good, no culled ESA steps + + # Collect all ESA steps across all intervals + all_esa_steps = set() + for line in lines: + parts = line.strip().split() + esa_step_flags = parts[6:16] + for i, flag in enumerate(esa_step_flags): + if flag == "1": + all_esa_steps.add(i + 1) + + # All unique ESA steps should be represented + unique_esa_steps = set(goodtimes_instance["esa_step"].values) + assert all_esa_steps == unique_esa_steps + + def test_to_txt_with_culled_bins(self, goodtimes_instance, tmp_path): + """Test output when some bins are culled.""" + # Flag bins 0-20 for first MET + met_val = goodtimes_instance.coords["met"].values[0] + goodtimes_instance.goodtimes.mark_bad_times( + met=met_val, bins=np.arange(21), cull=CullCode.INCOMPLETE_SPIN + ) + + output_path = tmp_path / "goodtimes.txt" + goodtimes_instance.goodtimes.write_txt(output_path) + + with open(output_path) as f: + lines = f.readlines() + + # Only good intervals are output + # Should have intervals for: + # - Fully good ESA steps (all bins) + # - Partially good ESA step (bins 21-89) + assert len(lines) >= 2 + + # Check for interval with good bins 21-89 (partial) + partial_lines = [ + line + for line in lines + if line.strip().split()[3] == "21" and line.strip().split()[4] == "89" + ] + assert len(partial_lines) >= 1 + # cull_value should indicate what was culled + assert partial_lines[0].strip().split()[16] == "1" + + # Check for fully good intervals (bins 0-89) + full_lines = [ + line + for line in lines + if line.strip().split()[3] == "0" and line.strip().split()[4] == "89" + ] + assert len(full_lines) >= 1 + + def test_to_txt_with_gaps(self, goodtimes_instance, tmp_path): + """Test output when bins have gaps.""" + # Flag bins 20-70, leaving 0-19 and 71-89 as good + met_val = goodtimes_instance.coords["met"].values[0] + goodtimes_instance.goodtimes.mark_bad_times( + met=met_val, bins=np.arange(20, 71), cull=CullCode.INCOMPLETE_SPIN + ) + + output_path = tmp_path / "goodtimes.txt" + goodtimes_instance.goodtimes.write_txt(output_path) + + with open(output_path) as f: + lines = f.readlines() + + # Only good intervals are output (no culled intervals) + # Should have intervals for: + # - Fully good ESA steps (all bins) + # - Partially good ESA step (bins 0-19 and 71-89) + assert len(lines) >= 3 + + # Check for good region bins 0-19 + low_good = [ + line + for line in lines + if line.strip().split()[3] == "0" and line.strip().split()[4] == "19" + ] + assert len(low_good) >= 1 + # cull_value should indicate what was culled + assert low_good[0].strip().split()[16] == "1" + + # Check for good region bins 71-89 + high_good = [ + line + for line in lines + if line.strip().split()[3] == "71" and line.strip().split()[4] == "89" + ] + assert len(high_good) >= 1 + assert high_good[0].strip().split()[16] == "1" + + # Check for fully good intervals (bins 0-89) for other ESA steps + full_good = [ + line + for line in lines + if line.strip().split()[3] == "0" and line.strip().split()[4] == "89" + ] + assert len(full_good) >= 1 + + +class TestFinalizeDataset: + """Test suite for GoodtimesAccessor.finalize_dataset() method.""" + + def test_finalize_changes_dimension_to_epoch(self, goodtimes_instance): + """Test that finalize changes primary dimension from met to epoch.""" + # Mock met_to_ttj2000ns to avoid SPICE dependency + with patch("imap_processing.hi.hi_goodtimes.met_to_ttj2000ns") as mock_convert: + # Return fake epoch values + mock_convert.return_value = np.arange( + 100, 100 + len(goodtimes_instance.coords["met"]) + ) + + finalized = goodtimes_instance.goodtimes.finalize_dataset() + + assert "epoch" in finalized.dims + assert "met" not in finalized.dims + assert "spin_bin" in finalized.dims + + def test_finalize_adds_met_as_data_variable(self, goodtimes_instance): + """Test that met coordinate becomes a data variable.""" + with patch("imap_processing.hi.hi_goodtimes.met_to_ttj2000ns") as mock_convert: + mock_convert.return_value = np.arange( + 100, 100 + len(goodtimes_instance.coords["met"]) + ) + + finalized = goodtimes_instance.goodtimes.finalize_dataset() + + assert "met" in finalized.data_vars + assert "met" not in finalized.coords + + def test_finalize_preserves_met_values(self, goodtimes_instance): + """Test that original MET values are preserved in data variable.""" + original_met = goodtimes_instance.coords["met"].values.copy() + + with patch("imap_processing.hi.hi_goodtimes.met_to_ttj2000ns") as mock_convert: + mock_convert.return_value = np.arange(100, 100 + len(original_met)) + + finalized = goodtimes_instance.goodtimes.finalize_dataset() + + np.testing.assert_array_equal(finalized["met"].values, original_met) + + def test_finalize_converts_met_to_epoch(self, goodtimes_instance): + """Test that met_to_ttj2000ns is called with MET values.""" + with patch("imap_processing.hi.hi_goodtimes.met_to_ttj2000ns") as mock_convert: + # Return same number of epoch values as MET values + n_mets = len(goodtimes_instance.coords["met"]) + mock_convert.return_value = np.arange(1000, 1000 + n_mets, dtype=np.int64) + + goodtimes_instance.goodtimes.finalize_dataset() + + # Verify conversion function was called + mock_convert.assert_called_once() + called_mets = mock_convert.call_args[0][0] + np.testing.assert_array_equal( + called_mets, goodtimes_instance.coords["met"].values + ) + + def test_finalize_adds_epoch_coordinate(self, goodtimes_instance): + """Test that epoch coordinate is added with converted values.""" + fake_epochs = np.arange(100, 100 + len(goodtimes_instance.coords["met"])) + + with patch("imap_processing.hi.hi_goodtimes.met_to_ttj2000ns") as mock_convert: + mock_convert.return_value = fake_epochs + + finalized = goodtimes_instance.goodtimes.finalize_dataset() + + np.testing.assert_array_equal(finalized.coords["epoch"].values, fake_epochs) + + def test_finalize_adds_spin_bin_label_coordinate(self, goodtimes_instance): + """Test that spin_bin_label coordinate is added.""" + with patch("imap_processing.hi.hi_goodtimes.met_to_ttj2000ns") as mock_convert: + mock_convert.return_value = np.arange( + 100, 100 + len(goodtimes_instance.coords["met"]) + ) + + finalized = goodtimes_instance.goodtimes.finalize_dataset() + + assert "spin_bin_label" in finalized.coords + assert len(finalized.coords["spin_bin_label"]) == 90 + assert finalized.coords["spin_bin_label"].values[0] == "0" + assert finalized.coords["spin_bin_label"].values[89] == "89" + + def test_finalize_preserves_cull_flags_data(self, goodtimes_instance): + """Test that cull_flags data is preserved.""" + # Mark some bins as bad + goodtimes_instance.goodtimes.mark_bad_times( + met=goodtimes_instance.coords["met"].values[0], + bins=np.arange(10), + cull=CullCode.INCOMPLETE_SPIN, + ) + original_flags = goodtimes_instance["cull_flags"].values.copy() + + with patch("imap_processing.hi.hi_goodtimes.met_to_ttj2000ns") as mock_convert: + mock_convert.return_value = np.arange( + 100, 100 + len(goodtimes_instance.coords["met"]) + ) + + finalized = goodtimes_instance.goodtimes.finalize_dataset() + + np.testing.assert_array_equal( + finalized["cull_flags"].values, original_flags + ) + + def test_finalize_preserves_esa_step_data(self, goodtimes_instance): + """Test that esa_step data is preserved.""" + original_esa_step = goodtimes_instance["esa_step"].values.copy() + + with patch("imap_processing.hi.hi_goodtimes.met_to_ttj2000ns") as mock_convert: + mock_convert.return_value = np.arange( + 100, 100 + len(goodtimes_instance.coords["met"]) + ) + + finalized = goodtimes_instance.goodtimes.finalize_dataset() + + np.testing.assert_array_equal( + finalized["esa_step"].values, original_esa_step + ) + + def test_finalize_adds_cdf_attributes_to_variables(self, goodtimes_instance): + """Test that CDF attributes are added to all variables.""" + with patch("imap_processing.hi.hi_goodtimes.met_to_ttj2000ns") as mock_convert: + mock_convert.return_value = np.arange( + 100, 100 + len(goodtimes_instance.coords["met"]) + ) + + finalized = goodtimes_instance.goodtimes.finalize_dataset() + + # Check that variables have attributes + assert len(finalized["cull_flags"].attrs) > 0 + assert len(finalized["met"].attrs) > 0 + assert len(finalized["esa_step"].attrs) > 0 + assert len(finalized.coords["epoch"].attrs) > 0 + assert len(finalized.coords["spin_bin"].attrs) > 0 + + def test_finalize_adds_global_attributes(self, goodtimes_instance): + """Test that global CDF attributes are added.""" + with patch("imap_processing.hi.hi_goodtimes.met_to_ttj2000ns") as mock_convert: + mock_convert.return_value = np.arange( + 100, 100 + len(goodtimes_instance.coords["met"]) + ) + + finalized = goodtimes_instance.goodtimes.finalize_dataset() + + # Check for required global attributes + assert "Logical_source" in finalized.attrs + assert "Data_type" in finalized.attrs + + def test_finalize_formats_logical_source(self, goodtimes_instance): + """Test that Logical_source is properly formatted with sensor.""" + with patch("imap_processing.hi.hi_goodtimes.met_to_ttj2000ns") as mock_convert: + mock_convert.return_value = np.arange( + 100, 100 + len(goodtimes_instance.coords["met"]) + ) + + finalized = goodtimes_instance.goodtimes.finalize_dataset() + + # Should contain the sensor designation + assert ( + "45sensor" in finalized.attrs["Logical_source"] + or "45sensor" in finalized.attrs["Logical_source"] + ) + # Should not contain template markers + assert "{sensor}" not in finalized.attrs["Logical_source"] + + def test_finalize_preserves_original_dataset(self, goodtimes_instance): + """Test that finalize doesn't modify the original dataset.""" + original_dims = set(goodtimes_instance.sizes.keys()) + original_coords = set(goodtimes_instance.coords.keys()) + + with patch("imap_processing.hi.hi_goodtimes.met_to_ttj2000ns") as mock_convert: + mock_convert.return_value = np.arange( + 100, 100 + len(goodtimes_instance.coords["met"]) + ) + + # Call finalize but don't need to assign result + goodtimes_instance.goodtimes.finalize_dataset() + + # Original should be unchanged + assert set(goodtimes_instance.sizes.keys()) == original_dims + assert set(goodtimes_instance.coords.keys()) == original_coords + assert "epoch" not in goodtimes_instance.coords + + def test_finalize_cull_flags_dimensions(self, goodtimes_instance): + """Test that cull_flags has correct dimensions after finalization.""" + with patch("imap_processing.hi.hi_goodtimes.met_to_ttj2000ns") as mock_convert: + mock_convert.return_value = np.arange( + 100, 100 + len(goodtimes_instance.coords["met"]) + ) + + finalized = goodtimes_instance.goodtimes.finalize_dataset() + + assert finalized["cull_flags"].dims == ("epoch", "spin_bin") + + def test_finalize_esa_step_dimensions(self, goodtimes_instance): + """Test that esa_step has correct dimensions after finalization.""" + with patch("imap_processing.hi.hi_goodtimes.met_to_ttj2000ns") as mock_convert: + mock_convert.return_value = np.arange( + 100, 100 + len(goodtimes_instance.coords["met"]) + ) + + finalized = goodtimes_instance.goodtimes.finalize_dataset() + + assert finalized["esa_step"].dims == ("epoch",) + + def test_finalize_met_dimensions(self, goodtimes_instance): + """Test that met has correct dimensions after finalization.""" + with patch("imap_processing.hi.hi_goodtimes.met_to_ttj2000ns") as mock_convert: + mock_convert.return_value = np.arange( + 100, 100 + len(goodtimes_instance.coords["met"]) + ) + + finalized = goodtimes_instance.goodtimes.finalize_dataset() + + assert finalized["met"].dims == ("epoch",) + + def test_finalize_with_empty_dataset(self): + """Test finalize with an empty goodtimes dataset.""" + empty_ds = xr.Dataset( + { + "cull_flags": xr.DataArray( + np.zeros((0, 90), dtype=np.uint8), dims=["met", "spin_bin"] + ), + "esa_step": xr.DataArray(np.array([], dtype=np.uint8), dims=["met"]), + }, + coords={"met": np.array([]), "spin_bin": np.arange(90)}, + attrs={"Sensor": "45sensor", "Pointing": 1}, + ) + + with patch("imap_processing.hi.hi_goodtimes.met_to_ttj2000ns") as mock_convert: + mock_convert.return_value = np.array([]) + + finalized = empty_ds.goodtimes.finalize_dataset() + + assert len(finalized.coords["epoch"]) == 0 + assert finalized["cull_flags"].shape == (0, 90) + + +class TestIntervalDtype: + """Test suite for INTERVAL_DTYPE.""" + + def test_interval_dtype_fields(self): + """Test that INTERVAL_DTYPE has correct fields.""" + field_names = INTERVAL_DTYPE.names + assert "met_start" in field_names + assert "met_end" in field_names + assert "spin_bin_low" in field_names + assert "spin_bin_high" in field_names + assert "n_bins" in field_names + assert "esa_step_mask" in field_names + assert "cull_value" in field_names + + def test_interval_dtype_types(self): + """Test that INTERVAL_DTYPE has correct field types.""" + assert INTERVAL_DTYPE["met_start"] == np.float64 + assert INTERVAL_DTYPE["met_end"] == np.float64 + assert INTERVAL_DTYPE["spin_bin_low"] == np.uint8 + assert INTERVAL_DTYPE["spin_bin_high"] == np.uint8 + assert INTERVAL_DTYPE["n_bins"] == np.uint8 + assert INTERVAL_DTYPE["esa_step_mask"] == np.uint16 + assert INTERVAL_DTYPE["cull_value"] == np.uint8 + + +def _create_l1b_de_dataset( + esa_step_met: list[float], + last_spin_num: list[int], + esa_step: list[int], + ccsds_qf: list[int] | None = None, + repointing: str = "repoint00001", +) -> xr.Dataset: + """ + Helper function to create L1B DE datasets for testing. + + Parameters + ---------- + esa_step_met : list[float] + MET timestamps for each packet. + last_spin_num : list[int] + Last spin number (1-8) for each packet. + esa_step : list[int] + ESA energy step values for each packet. + ccsds_qf : list[int] | None + Quality flags for each packet. If None, all zeros (valid). + repointing : str + Repointing attribute value. + + Returns + ------- + xr.Dataset + Mock L1B DE dataset. + """ + n_packets = len(esa_step_met) + if ccsds_qf is None: + ccsds_qf = [0] * n_packets + + return xr.Dataset( + { + "esa_step_met": (["epoch"], np.array(esa_step_met, dtype=np.float64)), + "last_spin_num": (["epoch"], np.array(last_spin_num, dtype=np.uint8)), + "esa_step": (["epoch"], np.array(esa_step, dtype=np.uint8)), + "ccsds_qf": (["epoch"], np.array(ccsds_qf, dtype=np.uint8)), + }, + attrs={ + "Logical_source": "imap_hi_l1b_45sensor-de", + "Repointing": repointing, + }, + ) + + +class TestDropIncompleteSpinSets: + """Test suite for mark_incomplete_spin_sets() function.""" + + @pytest.fixture + def l1b_de_complete_4th_spin(self): + """Create L1B DE data with complete 4th spin cadence (last_spin_num 4,8).""" + # 5 unique METs, each with 2 packets (last_spin_num 4 and 8) + # 60 second intervals between METs (every 4th spin) + n_mets = 5 + mets = np.arange(1000.0, 1000.0 + n_mets * 60, 60) + + esa_step_met = [] + last_spin_num = [] + esa_step = [] + + for met in mets: + # Add two packets per MET: last_spin_num 4 and 8 + esa_step_met.extend([met, met]) + last_spin_num.extend([4, 8]) + esa_step.extend([1, 1]) + + return _create_l1b_de_dataset( + esa_step_met, last_spin_num, esa_step, repointing="repoint00001" + ) + + @pytest.fixture + def l1b_de_complete_2nd_spin(self): + """Create L1B DE data with complete 2nd spin cadence (last_spin_num 2,4,6,8).""" + # 3 unique METs, each with 4 packets + # 30 second intervals between METs (every 2nd spin) + n_mets = 3 + mets = np.arange(2000.0, 2000.0 + n_mets * 30, 30) + + esa_step_met = [] + last_spin_num = [] + esa_energy_step = [] + + for met in mets: + # Add four packets per MET: last_spin_num 2,4,6,8 + esa_step_met.extend([met] * 4) + last_spin_num.extend([2, 4, 6, 8]) + esa_energy_step.extend([2] * 4) + + return _create_l1b_de_dataset( + esa_step_met, last_spin_num, esa_energy_step, repointing="repoint00002" + ) + + @pytest.fixture + def l1b_de_complete_every_spin(self): + """Create L1B DE data with complete every spin cadence (last_spin_num 1-8).""" + # 2 unique METs, each with 8 packets + # 15 second intervals between METs (every spin) + n_mets = 2 + mets = np.arange(3000.0, 3000.0 + n_mets * 15, 15) + + esa_step_met = [] + last_spin_num = [] + esa_energy_step = [] + + for met in mets: + # Add eight packets per MET: last_spin_num 1-8 + esa_step_met.extend([met] * 8) + last_spin_num.extend(range(1, 9)) + esa_energy_step.extend([3] * 8) + + return _create_l1b_de_dataset( + esa_step_met, last_spin_num, esa_energy_step, repointing="repoint00003" + ) + + @pytest.fixture + def l1b_de_incomplete(self): + """Create L1B DE data with incomplete 8-spin periods.""" + # 4 METs: 2 complete (4,8), 2 incomplete (missing spin 8) + # 60 second intervals (every 4th spin cadence) + mets = [1000.0, 1060.0, 1120.0, 1180.0] + + esa_step_met = [] + last_spin_num = [] + esa_energy_step = [] + + # Complete METs + for met in mets[:2]: + esa_step_met.extend([met, met]) + last_spin_num.extend([4, 8]) + esa_energy_step.extend([1, 1]) + + # Incomplete METs (only spin 4, missing spin 8) + for met in mets[2:]: + esa_step_met.append(met) + last_spin_num.append(4) + esa_energy_step.append(1) + + return _create_l1b_de_dataset( + esa_step_met, last_spin_num, esa_energy_step, repointing="repoint00004" + ) + + @pytest.fixture + def l1b_de_with_invalid_spins(self): + """Create L1B DE data with ccsds_qf spin invalid flag set.""" + # 60 second intervals (every 4th spin cadence) + mets = [1000.0, 1060.0] + + esa_step_met = [] + last_spin_num = [] + esa_energy_step = [] + ccsds_qf = [] + + # First MET: complete but with spin invalid flag (bit 1 set = 0x02) + esa_step_met.extend([mets[0], mets[0]]) + last_spin_num.extend([4, 8]) + esa_energy_step.extend([1, 1]) + ccsds_qf.extend( + [ImapHiL1bDeFlags.BADSPIN, 0] + ) # First packet has spin invalid flag + + # Second MET: complete and valid + esa_step_met.extend([mets[1], mets[1]]) + last_spin_num.extend([4, 8]) + esa_energy_step.extend([1, 1]) + ccsds_qf.extend([0, 0]) + + return _create_l1b_de_dataset( + esa_step_met, + last_spin_num, + esa_energy_step, + ccsds_qf=ccsds_qf, + repointing="repoint00005", + ) + + def test_mark_incomplete_spin_sets_complete_4th_spin( + self, l1b_de_complete_4th_spin + ): + """Test that complete 4th spin cadence is accepted.""" + gt = create_goodtimes_dataset(l1b_de_complete_4th_spin) + mark_incomplete_spin_sets(gt, l1b_de_complete_4th_spin) + + # All times should still be good (no culling) + assert np.all(gt["cull_flags"].values == CullCode.GOOD) + + def test_mark_incomplete_spin_sets_complete_2nd_spin( + self, l1b_de_complete_2nd_spin + ): + """Test that complete 2nd spin cadence is accepted.""" + gt = create_goodtimes_dataset(l1b_de_complete_2nd_spin) + mark_incomplete_spin_sets(gt, l1b_de_complete_2nd_spin) + + # All times should still be good (no culling) + assert np.all(gt["cull_flags"].values == CullCode.GOOD) + + def test_mark_incomplete_spin_sets_complete_every_spin( + self, l1b_de_complete_every_spin + ): + """Test that complete every-spin cadence is accepted.""" + gt = create_goodtimes_dataset(l1b_de_complete_every_spin) + mark_incomplete_spin_sets(gt, l1b_de_complete_every_spin) + + # All times should still be good (no culling) + assert np.all(gt["cull_flags"].values == CullCode.GOOD) + + def test_mark_incomplete_spin_sets_incomplete(self, l1b_de_incomplete): + """Test that incomplete 8-spin periods are culled.""" + gt = create_goodtimes_dataset(l1b_de_incomplete) + mark_incomplete_spin_sets(gt, l1b_de_incomplete) + + # First 2 METs should be good, last 2 should be culled + assert np.all(gt["cull_flags"].values[0, :] == CullCode.GOOD) + assert np.all(gt["cull_flags"].values[1, :] == CullCode.GOOD) + assert np.all(gt["cull_flags"].values[2, :] == CullCode.INCOMPLETE_SPIN) + assert np.all(gt["cull_flags"].values[3, :] == CullCode.INCOMPLETE_SPIN) + + def test_mark_incomplete_spin_sets_with_invalid_spins( + self, l1b_de_with_invalid_spins + ): + """Test that times with spin invalid flag in ccsds_qf are culled.""" + gt = create_goodtimes_dataset(l1b_de_with_invalid_spins) + mark_incomplete_spin_sets(gt, l1b_de_with_invalid_spins) + + # First MET should be culled (has spin invalid flag), second should be good + assert np.all(gt["cull_flags"].values[0, :] == CullCode.INCOMPLETE_SPIN) + assert np.all(gt["cull_flags"].values[1, :] == CullCode.GOOD) + + def test_mark_incomplete_spin_sets_no_de_packets(self): + """Test that MET times with no DE packets are culled.""" + # Create L1B DE with packets at 1000.0 and 1120.0 + # (60 second intervals for 4th spin) + l1b_de = _create_l1b_de_dataset( + esa_step_met=[1000.0, 1000.0, 1120.0, 1120.0], + last_spin_num=[4, 8, 4, 8], + esa_step=[1, 1, 1, 1], + repointing="repoint00006", + ) + + gt = create_goodtimes_dataset(l1b_de) + + # Manually add a MET time with no packets (insert in sorted order) + # Original METs are [1000.0, 1120.0], insert 1060.0 at index 1 + new_met = np.insert(gt.coords["met"].values, 1, 1060.0) + new_cull_flags = np.insert( + gt["cull_flags"].values, 1, np.zeros((1, 90), dtype=np.uint8), axis=0 + ) + new_esa_step = np.insert(gt["esa_step"].values, 1, 1) + + gt = xr.Dataset( + { + "cull_flags": (["met", "spin_bin"], new_cull_flags), + "esa_step": (["met"], new_esa_step), + }, + coords={"met": new_met, "spin_bin": np.arange(90)}, + attrs=gt.attrs, + ) + + mark_incomplete_spin_sets(gt, l1b_de) + + # First and last METs should be good, middle one should be culled + assert np.all(gt["cull_flags"].values[0, :] == CullCode.GOOD) + assert np.all( + gt["cull_flags"].values[1, :] == CullCode.INCOMPLETE_SPIN + ) # No packets + assert np.all(gt["cull_flags"].values[2, :] == CullCode.GOOD) + + def test_mark_incomplete_spin_sets_mixed_cadence(self): + """Test that mixed/invalid cadence patterns are culled.""" + # Create packets with invalid pattern: has spins 4,8,1 (mixing cadences) + l1b_de = _create_l1b_de_dataset( + esa_step_met=[1000.0, 1000.0, 1000.0], + last_spin_num=[4, 8, 1], # Invalid - mixing cadences + esa_step=[1, 1, 1], + repointing="repoint00007", + ) + + gt = create_goodtimes_dataset(l1b_de) + mark_incomplete_spin_sets(gt, l1b_de) + + # Should be culled (invalid pattern) + assert np.all(gt["cull_flags"].values[0, :] == CullCode.INCOMPLETE_SPIN) + + def test_mark_incomplete_spin_sets_duplicate_spin_num(self): + """Test that duplicate last_spin_num values are culled.""" + # Create packets with duplicate spin: has spins 4,4 (should be 4,8) + l1b_de = _create_l1b_de_dataset( + esa_step_met=[1000.0, 1000.0], + last_spin_num=[4, 4], # Duplicate - invalid + esa_step=[1, 1], + repointing="repoint00008", + ) + + gt = create_goodtimes_dataset(l1b_de) + mark_incomplete_spin_sets(gt, l1b_de) + + # Should be culled (duplicate spin numbers) + assert np.all(gt["cull_flags"].values[0, :] == CullCode.INCOMPLETE_SPIN) + + def test_mark_incomplete_spin_sets_custom_cull_code(self, l1b_de_incomplete): + """Test that custom cull code is used.""" + gt = create_goodtimes_dataset(l1b_de_incomplete) + custom_cull_code = 5 + mark_incomplete_spin_sets(gt, l1b_de_incomplete, cull_code=custom_cull_code) + + # Incomplete METs should be culled with custom code + assert np.all(gt["cull_flags"].values[2, :] == custom_cull_code) + assert np.all(gt["cull_flags"].values[3, :] == custom_cull_code) + + def test_mark_incomplete_spin_sets_preserves_good_times(self, l1b_de_incomplete): + """Test that previously good times remain untouched.""" + gt = create_goodtimes_dataset(l1b_de_incomplete) + + # Manually mark first MET as culled with code 2 + gt["cull_flags"].values[0, :] = 2 + + mark_incomplete_spin_sets(gt, l1b_de_incomplete) + + # Check that complete times are good + assert np.all(gt["cull_flags"].values[1, :] == CullCode.GOOD) + + +class TestDropDrfTimes: + """Test suite for mark_drf_times() function.""" + + @pytest.fixture + def goodtimes_for_drf(self): + """Create a goodtimes dataset with METs spanning 2 hours.""" + # Create METs every 60 seconds for 2 hours (120 METs) + n_mets = 120 + met_values = np.arange(1000.0, 1000.0 + n_mets * 60, 60) + + gt = xr.Dataset( + { + "cull_flags": xr.DataArray( + np.zeros((n_mets, 90), dtype=np.uint8), dims=["met", "spin_bin"] + ), + "esa_step": xr.DataArray(np.ones(n_mets, dtype=np.uint8), dims=["met"]), + }, + coords={"met": met_values, "spin_bin": np.arange(90)}, + attrs={"sensor": "45sensor", "pointing": 1}, + ) + return gt + + @pytest.fixture + def hk_single_drf_transition(self): + """Create HK data with one DRF transition from 1->0.""" + # HK packets every 60 seconds for 2 hours + n_hk = 120 + shcoarse = np.arange(1000.0, 1000.0 + n_hk * 60, 60) + + # DRF active for first 30 minutes, then inactive + # Transition at index 30 (MET 2800.0) + fsw_thruster_warn = np.zeros(n_hk, dtype=np.uint8) + fsw_thruster_warn[:30] = 1 # DRF active + + hk = xr.Dataset( + { + "shcoarse": (["epoch"], shcoarse), + "fsw_thruster_warn": (["epoch"], fsw_thruster_warn), + } + ) + return hk + + @pytest.fixture + def hk_multiple_drf_transitions(self): + """Create HK data with multiple DRF transitions.""" + # HK packets every 60 seconds for 2 hours + n_hk = 120 + shcoarse = np.arange(1000.0, 1000.0 + n_hk * 60, 60) + + # Multiple DRF periods: + # Active: 0-30, inactive: 30-60, active: 60-90, inactive: 90-120 + # Transitions at indices 30 and 90 + fsw_thruster_warn = np.zeros(n_hk, dtype=np.uint8) + fsw_thruster_warn[0:30] = 1 # First DRF period + fsw_thruster_warn[60:90] = 1 # Second DRF period + + hk = xr.Dataset( + { + "shcoarse": (["epoch"], shcoarse), + "fsw_thruster_warn": (["epoch"], fsw_thruster_warn), + } + ) + return hk + + @pytest.fixture + def hk_no_drf(self): + """Create HK data with no DRF activity.""" + n_hk = 120 + shcoarse = np.arange(1000.0, 1000.0 + n_hk * 60, 60) + fsw_thruster_warn = np.zeros(n_hk, dtype=np.uint8) + + hk = xr.Dataset( + { + "shcoarse": (["epoch"], shcoarse), + "fsw_thruster_warn": (["epoch"], fsw_thruster_warn), + } + ) + return hk + + @pytest.fixture + def hk_always_drf(self): + """Create HK data with DRF always active (no transitions).""" + n_hk = 120 + shcoarse = np.arange(1000.0, 1000.0 + n_hk * 60, 60) + fsw_thruster_warn = np.ones(n_hk, dtype=np.uint8) + + hk = xr.Dataset( + { + "shcoarse": (["epoch"], shcoarse), + "fsw_thruster_warn": (["epoch"], fsw_thruster_warn), + } + ) + return hk + + @pytest.fixture + def hk_empty(self): + """Create empty HK data.""" + hk = xr.Dataset( + { + "shcoarse": (["epoch"], np.array([])), + "fsw_thruster_warn": (["epoch"], np.array([], dtype=np.uint8)), + } + ) + return hk + + def test_mark_drf_times_single_transition( + self, goodtimes_for_drf, hk_single_drf_transition + ): + """Test that a single DRF transition removes 30-minute window.""" + mark_drf_times(goodtimes_for_drf, hk_single_drf_transition) + + # Transition at index 30 (MET 2800.0) + # Window: 2800 - 1800 = 1000 to 2800 (inclusive on both ends) + # mark_bad_times uses (met_start, met_end) which includes both endpoints + # So METs from 1000 to 2800 should be culled (indices 0-30) + + # Check that METs in the window are culled (indices 0-30) + for i in range(31): + assert np.all( + goodtimes_for_drf["cull_flags"].values[i, :] == CullCode.DRF + ), ( + f"MET at index {i} (value " + f"{goodtimes_for_drf.coords['met'].values[i]}) should be culled" + ) + + # Check that METs after the window are good + for i in range(31, len(goodtimes_for_drf.coords["met"])): + assert np.all( + goodtimes_for_drf["cull_flags"].values[i, :] == CullCode.GOOD + ), f"MET at index {i} should be good" + + def test_mark_drf_times_multiple_transitions( + self, goodtimes_for_drf, hk_multiple_drf_transitions + ): + """Test that multiple DRF transitions remove multiple windows.""" + mark_drf_times(goodtimes_for_drf, hk_multiple_drf_transitions) + + # First transition at index 30 (MET 2800.0) + # Window: 2800 - 1800 = 1000 to 2800 (inclusive, so indices 0-30) + + # Second transition at index 90 (MET 6400.0) + # Window: 6400 - 1800 = 4600 to 6400 (inclusive, so indices 60-90) + + # Check first window (indices 0-30) + for i in range(31): + assert np.all( + goodtimes_for_drf["cull_flags"].values[i, :] == CullCode.DRF + ), f"MET at index {i} should be culled (first window)" + + # Check between windows (indices 31-59, should be good) + for i in range(31, 60): + assert np.all( + goodtimes_for_drf["cull_flags"].values[i, :] == CullCode.GOOD + ), f"MET at index {i} should be good (between windows)" + + # Check second window (indices 60-90) + for i in range(60, 91): + assert np.all( + goodtimes_for_drf["cull_flags"].values[i, :] == CullCode.DRF + ), f"MET at index {i} should be culled (second window)" + + # Check after second window (indices 91+, should be good) + for i in range(91, len(goodtimes_for_drf.coords["met"])): + assert np.all( + goodtimes_for_drf["cull_flags"].values[i, :] == CullCode.GOOD + ), f"MET at index {i} should be good (after windows)" + + def test_mark_drf_times_no_drf(self, goodtimes_for_drf, hk_no_drf): + """Test that no times are removed when DRF is never active.""" + mark_drf_times(goodtimes_for_drf, hk_no_drf) + + # All times should remain good + assert np.all(goodtimes_for_drf["cull_flags"].values == CullCode.GOOD) + + def test_mark_drf_times_always_drf(self, goodtimes_for_drf, hk_always_drf): + """Test that no times are removed when DRF is always active (no transitions).""" + mark_drf_times(goodtimes_for_drf, hk_always_drf) + + # All times should remain good (no 1->0 transitions) + assert np.all(goodtimes_for_drf["cull_flags"].values == CullCode.GOOD) + + def test_mark_drf_times_empty_hk(self, goodtimes_for_drf, hk_empty): + """Test that function handles empty HK data gracefully.""" + # Should log warning and return without error + mark_drf_times(goodtimes_for_drf, hk_empty) + + # All times should remain good + assert np.all(goodtimes_for_drf["cull_flags"].values == CullCode.GOOD) + + def test_mark_drf_times_custom_cull_code( + self, goodtimes_for_drf, hk_single_drf_transition + ): + """Test that custom cull code is used.""" + custom_cull_code = 5 + mark_drf_times( + goodtimes_for_drf, hk_single_drf_transition, cull_code=custom_cull_code + ) + + # Check that culled times use custom code (indices 0-30) + for i in range(31): + assert np.all( + goodtimes_for_drf["cull_flags"].values[i, :] == custom_cull_code + ), f"MET at index {i} should use custom cull code" + + def test_mark_drf_times_overwrites_existing_culls( + self, goodtimes_for_drf, hk_single_drf_transition + ): + """Test that existing cull flags are overwritten by DRF culling.""" + # Manually set some METs to a different cull code + goodtimes_for_drf["cull_flags"].values[0:5, :] = 2 + + mark_drf_times(goodtimes_for_drf, hk_single_drf_transition) + + # First 5 METs should now be DRF (overwritten via bitwise OR with existing 2) + for i in range(5): + assert np.all(goodtimes_for_drf["cull_flags"].values[i, :] == CullCode.DRF) + + def test_mark_drf_times_transition_at_start(self): + """Test DRF transition near the start - window exactly at data start.""" + # Create goodtimes starting at a later time + met_values = np.arange(2000.0, 4000.0, 60) + gt = xr.Dataset( + { + "cull_flags": xr.DataArray( + np.zeros((len(met_values), 90), dtype=np.uint8), + dims=["met", "spin_bin"], + ), + "esa_step": xr.DataArray( + np.ones(len(met_values), dtype=np.uint8), dims=["met"] + ), + }, + coords={"met": met_values, "spin_bin": np.arange(90)}, + attrs={"sensor": "45sensor", "pointing": 1}, + ) + + # HK with DRF active for first 30 samples, then transition + # Transition at index 30 gives window that exactly matches goodtimes start + shcoarse = np.arange(2000.0, 4000.0, 60) + fsw_thruster_warn = np.zeros(len(shcoarse), dtype=np.uint8) + fsw_thruster_warn[0:30] = 1 # Active for first 30 samples + + hk = xr.Dataset( + { + "shcoarse": (["epoch"], shcoarse), + "fsw_thruster_warn": (["epoch"], fsw_thruster_warn), + } + ) + + mark_drf_times(gt, hk) + + # Transition at index 30 (MET 3800.0) + # Window: 3800 - 1800 = 2000 to 3800 + # This includes METs from 2000 to 3800 (indices 0-30) + for i in range(31): + assert np.all(gt["cull_flags"].values[i, :] == CullCode.DRF), ( + f"MET at index {i} should be culled" + ) + + # Rest should be good + for i in range(31, len(met_values)): + assert np.all(gt["cull_flags"].values[i, :] == CullCode.GOOD), ( + f"MET at index {i} should be good" + ) + + def test_mark_drf_times_transition_at_end(self): + """Test DRF transition at the very end of HK data.""" + # Create goodtimes + met_values = np.arange(1000.0, 3000.0, 60) + gt = xr.Dataset( + { + "cull_flags": xr.DataArray( + np.zeros((len(met_values), 90), dtype=np.uint8), + dims=["met", "spin_bin"], + ), + "esa_step": xr.DataArray( + np.ones(len(met_values), dtype=np.uint8), dims=["met"] + ), + }, + coords={"met": met_values, "spin_bin": np.arange(90)}, + attrs={"sensor": "45sensor", "pointing": 1}, + ) + + # HK with DRF becoming active mid-way, then transition at end + shcoarse = np.arange(1000.0, 3000.0, 60) + fsw_thruster_warn = np.zeros(len(shcoarse), dtype=np.uint8) + fsw_thruster_warn[-10:] = 1 # Active for last 10 samples + fsw_thruster_warn[-1] = 0 # Transition at last sample + + hk = xr.Dataset( + { + "shcoarse": (["epoch"], shcoarse), + "fsw_thruster_warn": (["epoch"], fsw_thruster_warn), + } + ) + + mark_drf_times(gt, hk) + + # Transition at last index (MET ~2940) + # Should remove 30-minute window before it + # Most METs should still be good except the last ~30 + n_culled = np.sum(gt["cull_flags"].values[:, 0] == CullCode.DRF) + assert n_culled > 0 # Some should be culled + assert n_culled <= 31 # But not all (only last ~30 minutes) + + +class TestMarkBadTdcCal: + """Test suite for mark_bad_tdc_cal() function.""" + + @pytest.fixture + def goodtimes_for_tdc(self): + """Create a goodtimes dataset with METs spanning a range.""" + # Create METs every 50 seconds for 200 seconds (5 METs) + n_mets = 5 + met_values = np.arange(1000.0, 1000.0 + n_mets * 50, 50) + + gt = xr.Dataset( + { + "cull_flags": xr.DataArray( + np.zeros((n_mets, 90), dtype=np.uint8), dims=["met", "spin_bin"] + ), + "esa_step": xr.DataArray(np.ones(n_mets, dtype=np.uint8), dims=["met"]), + }, + coords={"met": met_values, "spin_bin": np.arange(90)}, + attrs={"sensor": "45sensor", "pointing": 1}, + ) + return gt + + @pytest.fixture + def diagfee_all_good(self): + """Create DIAG_FEE dataset where all TDC calibrations pass.""" + # 4 DIAG_FEE packets, all with bit 1 set (=2, meaning calibration good) + return xr.Dataset( + { + "shcoarse": (["epoch"], np.array([1000, 1050, 1100, 1150])), + "tdc1_cal_ctrl_stat": (["epoch"], np.array([2, 2, 2, 2])), + "tdc2_cal_ctrl_stat": (["epoch"], np.array([2, 2, 2, 2])), + "tdc3_cal_ctrl_stat": (["epoch"], np.array([2, 2, 2, 2])), + } + ) + + @pytest.fixture + def diagfee_tdc1_fails(self): + """Create DIAG_FEE dataset where TDC1 fails at packet index 2.""" + # TDC1 fails at index 2 (bit 1 not set, so value 0) + return xr.Dataset( + { + "shcoarse": (["epoch"], np.array([1000, 1050, 1100, 1150])), + "tdc1_cal_ctrl_stat": ( + ["epoch"], + np.array([2, 2, 0, 2]), + ), # fails at idx 2 + "tdc2_cal_ctrl_stat": (["epoch"], np.array([2, 2, 2, 2])), + "tdc3_cal_ctrl_stat": (["epoch"], np.array([2, 2, 2, 2])), + } + ) + + @pytest.fixture + def diagfee_with_duplicate(self): + """Create DIAG_FEE dataset with duplicate packets within 10 seconds.""" + # First two packets are within 10 seconds (should skip first) + return xr.Dataset( + { + "shcoarse": (["epoch"], np.array([1000, 1005, 1100, 1150])), + "tdc1_cal_ctrl_stat": ( + ["epoch"], + np.array([0, 2, 2, 2]), + ), # First would fail but is skipped + "tdc2_cal_ctrl_stat": (["epoch"], np.array([2, 2, 2, 2])), + "tdc3_cal_ctrl_stat": (["epoch"], np.array([2, 2, 2, 2])), + } + ) + + def test_mark_bad_tdc_cal_all_good(self, goodtimes_for_tdc, diagfee_all_good): + """Test that no times are marked when all TDC calibrations pass.""" + mark_bad_tdc_cal(goodtimes_for_tdc, diagfee_all_good) + + # All times should remain good + assert np.all(goodtimes_for_tdc["cull_flags"].values == CullCode.GOOD) + + def test_mark_bad_tdc_cal_tdc1_fails(self, goodtimes_for_tdc, diagfee_tdc1_fails): + """Test that times are marked when TDC1 fails.""" + mark_bad_tdc_cal(goodtimes_for_tdc, diagfee_tdc1_fails) + + # TDC1 fails at packet 2 (MET 1100), should mark times from 1100 to 1150 + # goodtimes METs are [1000, 1050, 1100, 1150, 1200] + # MET 1100 falls in window [1100, 1150), so MET 1100 should be culled + met_values = goodtimes_for_tdc.coords["met"].values + + # MET 1100 (index 2) should be culled + idx_1100 = np.where(met_values == 1100.0)[0][0] + assert np.all( + goodtimes_for_tdc["cull_flags"].values[idx_1100, :] == CullCode.BAD_TDC_CAL + ) + + # METs before 1100 should still be good + assert np.all( + goodtimes_for_tdc["cull_flags"].values[0, :] == CullCode.GOOD + ) # 1000 + assert np.all( + goodtimes_for_tdc["cull_flags"].values[1, :] == CullCode.GOOD + ) # 1050 + + def test_mark_bad_tdc_cal_skip_duplicate_packets( + self, goodtimes_for_tdc, diagfee_with_duplicate + ): + """Test that duplicate DIAG_FEE packets within 10 seconds are skipped.""" + mark_bad_tdc_cal(goodtimes_for_tdc, diagfee_with_duplicate) + + # First packet (MET 1000) has TDC1 fail but should be skipped + # because it's within 10 seconds of the next packet (MET 1005) + # So all times should remain good + assert np.all(goodtimes_for_tdc["cull_flags"].values == CullCode.GOOD) + + def test_mark_bad_tdc_cal_insufficient_packets(self, goodtimes_for_tdc): + """Test that less than 2 packets logs warning and returns early.""" + # Create DIAG_FEE with only 1 packet + diagfee_single = xr.Dataset( + { + "shcoarse": (["epoch"], np.array([1000])), + "tdc1_cal_ctrl_stat": (["epoch"], np.array([0])), # Fails but ignored + "tdc2_cal_ctrl_stat": (["epoch"], np.array([2])), + "tdc3_cal_ctrl_stat": (["epoch"], np.array([2])), + } + ) + + mark_bad_tdc_cal(goodtimes_for_tdc, diagfee_single) + + # All times should remain good (no culling due to insufficient packets) + assert np.all(goodtimes_for_tdc["cull_flags"].values == CullCode.GOOD) + + def test_mark_bad_tdc_cal_tdc2_fails(self, goodtimes_for_tdc): + """Test that times are marked when TDC2 fails.""" + diagfee_tdc2_fails = xr.Dataset( + { + "shcoarse": (["epoch"], np.array([1000, 1050, 1100, 1150])), + "tdc1_cal_ctrl_stat": (["epoch"], np.array([2, 2, 2, 2])), + "tdc2_cal_ctrl_stat": ( + ["epoch"], + np.array([2, 0, 2, 2]), + ), # fails at idx 1 + "tdc3_cal_ctrl_stat": (["epoch"], np.array([2, 2, 2, 2])), + } + ) + + mark_bad_tdc_cal(goodtimes_for_tdc, diagfee_tdc2_fails) + + # TDC2 fails at packet 1 (MET 1050), should mark times from 1050 to 1100 + met_values = goodtimes_for_tdc.coords["met"].values + + # MET 1050 (index 1) should be culled + idx_1050 = np.where(met_values == 1050.0)[0][0] + assert np.all( + goodtimes_for_tdc["cull_flags"].values[idx_1050, :] == CullCode.BAD_TDC_CAL + ) + + def test_mark_bad_tdc_cal_tdc3_fails(self, goodtimes_for_tdc): + """Test that times are marked when TDC3 fails.""" + diagfee_tdc3_fails = xr.Dataset( + { + "shcoarse": (["epoch"], np.array([1000, 1050, 1100, 1150])), + "tdc1_cal_ctrl_stat": (["epoch"], np.array([2, 2, 2, 2])), + "tdc2_cal_ctrl_stat": (["epoch"], np.array([2, 2, 2, 2])), + "tdc3_cal_ctrl_stat": ( + ["epoch"], + np.array([0, 2, 2, 2]), + ), # fails at idx 0 + } + ) + + # Check that setting check_tdc_3=False results in all good values + mark_bad_tdc_cal(goodtimes_for_tdc, diagfee_tdc3_fails, check_tdc_3=False) + assert np.all(goodtimes_for_tdc["cull_flags"].values[0, :] == CullCode.GOOD) + + # Now run with check_tdc_3=True, should mark times from 1050 to 1100 + mark_bad_tdc_cal(goodtimes_for_tdc, diagfee_tdc3_fails, check_tdc_3=True) + + # TDC3 fails at packet 0 (MET 1000), should mark times from 1000 to 1050 + # MET 1000 (index 0) should be culled + assert np.all( + goodtimes_for_tdc["cull_flags"].values[0, :] == CullCode.BAD_TDC_CAL + ) # 1000 + + # MET 1050 should be good (next DIAG_FEE packet starts good window) + assert np.all( + goodtimes_for_tdc["cull_flags"].values[1, :] == CullCode.GOOD + ) # 1050 + + def test_mark_bad_tdc_cal_custom_cull_code( + self, goodtimes_for_tdc, diagfee_tdc1_fails + ): + """Test that custom cull code is used.""" + custom_cull_code = 5 + mark_bad_tdc_cal( + goodtimes_for_tdc, diagfee_tdc1_fails, cull_code=custom_cull_code + ) + + # Check that culled times use custom code + assert np.any(goodtimes_for_tdc["cull_flags"].values == custom_cull_code) + + def test_mark_bad_tdc_cal_last_packet_fails(self, goodtimes_for_tdc): + """Test behavior when the last DIAG_FEE packet has TDC failure.""" + diagfee_last_fails = xr.Dataset( + { + "shcoarse": (["epoch"], np.array([1000, 1050, 1100, 1150])), + "tdc1_cal_ctrl_stat": ( + ["epoch"], + np.array([2, 2, 2, 0]), + ), # fails at last + "tdc2_cal_ctrl_stat": (["epoch"], np.array([2, 2, 2, 2])), + "tdc3_cal_ctrl_stat": (["epoch"], np.array([2, 2, 2, 2])), + } + ) + + mark_bad_tdc_cal(goodtimes_for_tdc, diagfee_last_fails) + + # TDC1 fails at last packet (MET 1150), should mark all times >= 1150 + met_values = goodtimes_for_tdc.coords["met"].values + + # METs >= 1150 should be culled + for i, met in enumerate(met_values): + if met >= 1150: + assert np.all( + goodtimes_for_tdc["cull_flags"].values[i, :] == CullCode.BAD_TDC_CAL + ) + else: + assert np.all( + goodtimes_for_tdc["cull_flags"].values[i, :] == CullCode.GOOD + ) + + def test_mark_bad_tdc_cal_empty_diagfee(self, goodtimes_for_tdc): + """Test that function handles empty DIAG_FEE data gracefully.""" + diagfee_empty = xr.Dataset( + { + "shcoarse": (["epoch"], np.array([], dtype=np.float64)), + "tdc1_cal_ctrl_stat": (["epoch"], np.array([], dtype=np.uint8)), + "tdc2_cal_ctrl_stat": (["epoch"], np.array([], dtype=np.uint8)), + "tdc3_cal_ctrl_stat": (["epoch"], np.array([], dtype=np.uint8)), + } + ) + + # Should log warning and return without error + mark_bad_tdc_cal(goodtimes_for_tdc, diagfee_empty) + + # All times should remain good + assert np.all(goodtimes_for_tdc["cull_flags"].values == CullCode.GOOD) + + +class TestMarkOverflowPackets: + """Test suite for mark_overflow_packets function.""" + + @pytest.fixture + def mock_config_df(self): + """Create a mock calibration product configuration DataFrame.""" + # Create a minimal config with coincidence types + # ABC1C2 = 15, ABC1 = 14, AB = 12 + data = { + "coincidence_type_list": [("ABC1C2", "ABC1"), ("AB",)], + "tof_ab_low": [0, 0], + "tof_ab_high": [100, 100], + "tof_ac1_low": [0, 0], + "tof_ac1_high": [100, 100], + "tof_bc1_low": [-50, -50], + "tof_bc1_high": [50, 50], + "tof_c1c2_low": [0, 0], + "tof_c1c2_high": [100, 100], + } + df = pd.DataFrame( + data, + index=pd.MultiIndex.from_tuples( + [(1, 1), (2, 1)], names=["calibration_prod", "esa_energy_step"] + ), + ) + # Add coincidence_type_values column (converted from strings to ints) + # ABC1C2=15, ABC1=14, AB=12 + df["coincidence_type_values"] = [(15, 14), (12,)] + return df + + @pytest.fixture + def mock_goodtimes(self): + """Create a mock goodtimes dataset.""" + met_values = np.arange(1000.0, 1100.0, 10.0) + return xr.Dataset( + { + "cull_flags": xr.DataArray( + np.zeros((len(met_values), 90), dtype=np.uint8), + dims=["met", "spin_bin"], + ), + "esa_step": xr.DataArray( + np.ones(len(met_values), dtype=np.uint8), dims=["met"] + ), + }, + coords={"met": met_values, "spin_bin": np.arange(90)}, + attrs={"sensor": "45sensor", "pointing": 1}, + ) + + def test_no_full_packets(self, mock_goodtimes, mock_config_df): + """Test that no culling occurs when no packets are full.""" + # Create L1B DE with packets having < 664 events + n_events = 100 + l1b_de = xr.Dataset( + { + "ccsds_index": (["event_met"], np.zeros(n_events, dtype=np.uint16)), + "coincidence_type": ( + ["event_met"], + np.full(n_events, 15, dtype=np.uint8), + ), + }, + coords={"event_met": np.linspace(1000.0, 1010.0, n_events)}, + ) + + mark_overflow_packets(mock_goodtimes, l1b_de, mock_config_df) + + # No times should be culled + assert np.all(mock_goodtimes["cull_flags"].values == 0) + + def test_full_packet_with_qualified_event(self, mock_goodtimes, mock_config_df): + """Test that full packet with qualified final event is culled.""" + # Create L1B DE with one packet having exactly 664 events + n_events = 664 + event_mets = np.linspace(1005.0, 1006.0, n_events) + l1b_de = xr.Dataset( + { + "ccsds_index": (["event_met"], np.zeros(n_events, dtype=np.uint16)), + # Final event has coincidence_type=15 (ABC1C2), which is qualified + "coincidence_type": ( + ["event_met"], + np.full(n_events, 15, dtype=np.uint8), + ), + }, + coords={"event_met": event_mets}, + ) + + mark_overflow_packets(mock_goodtimes, l1b_de, mock_config_df) + + # MET ~1006 should be culled (maps to goodtimes MET 1000) + # The MET 1000 bin should have all spin bins culled with OVERFLOW flag + assert np.all(mock_goodtimes["cull_flags"].values[0, :] == CullCode.OVERFLOW) + + def test_full_packet_with_unqualified_event(self, mock_goodtimes, mock_config_df): + """Test that full packet with unqualified final event is NOT culled.""" + # Create L1B DE with one packet having exactly 664 events + n_events = 664 + event_mets = np.linspace(1005.0, 1006.0, n_events) + l1b_de = xr.Dataset( + { + "ccsds_index": (["event_met"], np.zeros(n_events, dtype=np.uint16)), + # Final event has coincidence_type=3 (not in any cal product) + "coincidence_type": ( + ["event_met"], + np.full(n_events, 3, dtype=np.uint8), + ), + }, + coords={"event_met": event_mets}, + ) + + mark_overflow_packets(mock_goodtimes, l1b_de, mock_config_df) + + # No times should be culled since final event is unqualified + assert np.all(mock_goodtimes["cull_flags"].values == 0) + + def test_multiple_full_packets(self, mock_goodtimes, mock_config_df): + """Test handling of multiple full packets.""" + # Create L1B DE with two packets, each having 664 events + n_events_per_packet = 664 + n_packets = 2 + + ccsds_indices = np.concatenate( + [np.full(n_events_per_packet, i, dtype=np.uint16) for i in range(n_packets)] + ) + # Packet 0: final event qualified (15) + # Packet 1: final event unqualified (3) + coincidence_types = np.concatenate( + [ + np.concatenate( + [np.full(n_events_per_packet - 1, 3, dtype=np.uint8), [15]] + ), + np.full(n_events_per_packet, 3, dtype=np.uint8), + ] + ) + event_mets = np.concatenate( + [ + np.linspace(1005.0, 1006.0, n_events_per_packet), # Packet 0 + np.linspace(1015.0, 1016.0, n_events_per_packet), # Packet 1 + ] + ) + + l1b_de = xr.Dataset( + { + "ccsds_index": (["event_met"], ccsds_indices), + "coincidence_type": (["event_met"], coincidence_types), + }, + coords={"event_met": event_mets}, + ) + + mark_overflow_packets(mock_goodtimes, l1b_de, mock_config_df) + + # Only packet 0's MET should be culled (MET 1000) + # Packet 1 has unqualified final event, so MET 1010 should not be culled + assert np.sum(mock_goodtimes["cull_flags"].values[0, :] > 0) == 90 # All bins + assert np.all(mock_goodtimes["cull_flags"].values[1, :] == 0) # MET 1010 + + def test_empty_de_data(self, mock_goodtimes, mock_config_df): + """Test handling of empty L1B DE data.""" + l1b_de = xr.Dataset( + { + "ccsds_index": (["event_met"], np.array([], dtype=np.uint16)), + "coincidence_type": (["event_met"], np.array([], dtype=np.uint8)), + }, + coords={"event_met": np.array([])}, + ) + + # Should not raise, just return without culling + mark_overflow_packets(mock_goodtimes, l1b_de, mock_config_df) + assert np.all(mock_goodtimes["cull_flags"].values == 0) + + def test_custom_cull_code(self, mock_goodtimes, mock_config_df): + """Test using a custom cull code.""" + n_events = 664 + event_mets = np.linspace(1005.0, 1006.0, n_events) + l1b_de = xr.Dataset( + { + "ccsds_index": (["event_met"], np.zeros(n_events, dtype=np.uint16)), + "coincidence_type": ( + ["event_met"], + np.concatenate([np.full(n_events - 1, 3, dtype=np.uint8), [15]]), + ), + }, + coords={"event_met": event_mets}, + ) + + custom_cull = 5 + mark_overflow_packets( + mock_goodtimes, l1b_de, mock_config_df, cull_code=custom_cull + ) + + # Check that the custom cull code was used + assert np.any(mock_goodtimes["cull_flags"].values == custom_cull) + + def test_final_event_is_last_in_list(self, mock_goodtimes, mock_config_df): + """Test that the final event is the last one in the list for the packet.""" + n_events = 664 + event_mets = np.linspace(1005.0, 1006.0, n_events) + + # All events have unqualified type except the last one in the list + coincidence_types = np.full(n_events, 3, dtype=np.uint8) + coincidence_types[-1] = 12 # Last event is qualified + + l1b_de = xr.Dataset( + { + "ccsds_index": (["event_met"], np.zeros(n_events, dtype=np.uint16)), + "coincidence_type": (["event_met"], coincidence_types), + }, + coords={"event_met": event_mets}, + ) + + mark_overflow_packets(mock_goodtimes, l1b_de, mock_config_df) + + # Should be culled because the final event (last in list) is qualified + assert np.sum(mock_goodtimes["cull_flags"].values > 0) > 0 + + +class TestGetSweepIndices: + """Test suite for _get_sweep_indices() helper function.""" + + def test_empty_array(self): + """Test with empty input.""" + result = _get_sweep_indices(np.array([])) + assert len(result) == 0 + assert result.dtype == np.int32 + + def test_single_sweep(self): + """Test with single complete ESA sweep (no transitions).""" + esa_step = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9]) + result = _get_sweep_indices(esa_step) + + # All should be in sweep 0 + np.testing.assert_array_equal(result, np.zeros(9, dtype=np.int32)) + + def test_two_sweeps_standard_transition(self): + """Test with two sweeps with standard 9->1 transition.""" + esa_step = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9]) + result = _get_sweep_indices(esa_step) + + # First 9 should be sweep 0, next 9 should be sweep 1 + expected = np.array( + [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=np.int32 + ) + np.testing.assert_array_equal(result, expected) + + def test_multiple_sweeps(self): + """Test with multiple sweeps.""" + esa_step = np.array([3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3]) + result = _get_sweep_indices(esa_step) + + # Transitions at index 6->7 (9->1) and 15->16 (9->1) + expected = np.array( + [0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2], dtype=np.int32 + ) + np.testing.assert_array_equal(result, expected) + + def test_non_standard_transition(self): + """Test with non-standard ESA step decrease (e.g., 5->2).""" + esa_step = np.array([5, 6, 7, 8, 9, 2, 3, 4, 5]) + result = _get_sweep_indices(esa_step) + + # Transition at index 4->5 (9->2, diff=-7, negative so boundary) + expected = np.array([0, 0, 0, 0, 0, 1, 1, 1, 1], dtype=np.int32) + np.testing.assert_array_equal(result, expected) + + def test_no_decreases_only_increases(self): + """Test with only increasing steps (no sweep boundaries).""" + esa_step = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9]) + result = _get_sweep_indices(esa_step) + + # All in sweep 0 + np.testing.assert_array_equal(result, np.zeros(9, dtype=np.int32)) + + def test_constant_esa_step(self): + """Test with constant ESA step (no transitions).""" + esa_step = np.array([5, 5, 5, 5, 5]) + result = _get_sweep_indices(esa_step) + + # All in sweep 0 + np.testing.assert_array_equal(result, np.zeros(5, dtype=np.int32)) + + +class TestAddSweepIndices: + """Test suite for _add_sweep_indices() helper function.""" + + def test_adds_coordinate(self): + """Test that esa_sweep coordinate is added.""" + ds = xr.Dataset( + { + "ccsds_met": (["epoch"], np.array([1000.0, 1060.0, 1120.0])), + "esa_step": (["epoch"], np.array([1, 2, 3], dtype=np.uint8)), + }, + coords={"epoch": np.arange(3)}, + ) + + result = _add_sweep_indices(ds) + + assert "esa_sweep" in result.coords + assert result.coords["esa_sweep"].dims == ("epoch",) + + def test_coordinate_values(self): + """Test that sweep indices are correctly calculated.""" + ds = xr.Dataset( + { + "ccsds_met": (["epoch"], np.arange(1000.0, 1000.0 + 18 * 60, 60)), + "esa_step": ( + ["epoch"], + np.tile([1, 2, 3, 4, 5, 6, 7, 8, 9], 2).astype(np.uint8), + ), + }, + coords={"epoch": np.arange(18)}, + ) + + result = _add_sweep_indices(ds) + + # First 9 should be sweep 0, next 9 should be sweep 1 + expected = np.array( + [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=np.int32 + ) + np.testing.assert_array_equal(result.coords["esa_sweep"].values, expected) + + def test_preserves_original_data(self): + """Test that original dataset variables are preserved.""" + ds = xr.Dataset( + { + "ccsds_met": (["epoch"], np.array([1000.0, 1060.0, 1120.0])), + "esa_step": (["epoch"], np.array([1, 2, 1], dtype=np.uint8)), + "other_var": (["epoch"], np.array([10, 20, 30])), + }, + coords={"epoch": np.arange(3)}, + ) + + result = _add_sweep_indices(ds) + + assert "ccsds_met" in result.data_vars + assert "esa_step" in result.data_vars + assert "other_var" in result.data_vars + np.testing.assert_array_equal( + result["ccsds_met"].values, ds["ccsds_met"].values + ) + + +class TestComputeNormalizedCountsPerSweep: + """Test suite for _compute_normalized_counts_per_sweep() helper function.""" + + def _create_test_dataset( + self, + n_sweeps: int = 2, + n_esa_steps: int = 9, + packets_per_esa_step: int = 2, + events_per_packet: int = 10, + tof_ab_range: tuple[int, int] = (-15, 15), + ) -> xr.Dataset: + """Create a test L1B DE dataset with esa_sweep coordinate.""" + n_packets = n_sweeps * n_esa_steps * packets_per_esa_step + n_events = n_packets * events_per_packet + + # Create ESA steps: each step repeated packets_per_esa_step times per sweep + # e.g., [1,1,2,2,3,3,...,9,9, 1,1,2,2,3,3,...,9,9] for 2 sweeps, 2 packets/step + esa_step = np.tile( + np.repeat(np.arange(1, n_esa_steps + 1), packets_per_esa_step), n_sweeps + ).astype(np.uint8) + + # esa_energy_step same as esa_step for test purposes + # (in real data they can differ) + esa_energy_step = esa_step.copy() + + # Create METs with unique incrementing values for each packet + ccsds_met = np.arange(1000.0, 1000.0 + n_packets * 60, 60) + + # Create events + tof_ab = np.random.randint(tof_ab_range[0], tof_ab_range[1], n_events).astype( + np.int32 + ) + coincidence_type = np.full(n_events, 12, dtype=np.uint8) # AB = 12 + ccsds_index = np.repeat(np.arange(n_packets), events_per_packet).astype( + np.uint16 + ) + + ds = xr.Dataset( + { + "ccsds_met": (["epoch"], ccsds_met), + "esa_step": (["epoch"], esa_step), + "esa_energy_step": (["epoch"], esa_energy_step), + "tof_ab": (["event_met"], tof_ab), + "coincidence_type": (["event_met"], coincidence_type), + "ccsds_index": (["event_met"], ccsds_index), + }, + coords={ + "epoch": np.arange(n_packets), + "event_met": np.arange(n_events), + }, + ) + + # Add sweep indices + return _add_sweep_indices(ds) + + def test_output_dimensions(self): + """Test that output has correct dimensions.""" + np.random.seed(42) + ds = self._create_test_dataset(n_sweeps=2) + + result = _compute_normalized_counts_per_sweep(ds, tof_ab_limit_ns=15) + + assert "esa_sweep" in result.dims + assert "esa_energy_step" in result.dims + assert "epoch" not in result.dims + assert "event_met" not in result.dims + + def test_normalized_count_added(self): + """Test that normalized_count variable is added.""" + np.random.seed(42) + ds = self._create_test_dataset(n_sweeps=2) + + result = _compute_normalized_counts_per_sweep(ds, tof_ab_limit_ns=15) + + assert "normalized_count" in result.data_vars + assert result["normalized_count"].dims == ("esa_sweep",) + + def test_normalized_count_calculation(self): + """Test that normalized counts are calculated correctly.""" + np.random.seed(42) + # Create dataset where we know exact counts + n_sweeps = 2 + n_esa_steps = 9 + events_per_packet = 10 + + # All events within Β±15ns + ds = self._create_test_dataset( + n_sweeps=n_sweeps, + n_esa_steps=n_esa_steps, + events_per_packet=events_per_packet, + tof_ab_range=(-10, 10), + ) + + result = _compute_normalized_counts_per_sweep(ds, tof_ab_limit_ns=15) + + # Allow some tolerance for randomness in tof_ab values + assert len(result["normalized_count"]) == n_sweeps + assert np.all(result["normalized_count"].values >= 0) + + def test_filters_by_tof_ab_limit(self): + """Test that events outside tof_ab limit are excluded.""" + np.random.seed(42) + # Create dataset with events outside limit + ds = self._create_test_dataset(n_sweeps=2, tof_ab_range=(20, 100)) + + result = _compute_normalized_counts_per_sweep(ds, tof_ab_limit_ns=15) + + # All events have |tof_ab| > 15, so counts should be 0 + np.testing.assert_array_equal(result["normalized_count"].values, np.zeros(2)) + + def test_preserves_epoch_variables(self): + """Test that epoch-based variables are preserved.""" + np.random.seed(42) + ds = self._create_test_dataset(n_sweeps=2) + + result = _compute_normalized_counts_per_sweep(ds, tof_ab_limit_ns=15) + + assert "ccsds_met" in result.data_vars + # esa_step becomes a coordinate (dimension) after unstack + assert "esa_energy_step" in result.coords + + def test_removes_event_met_variables(self): + """Test that event_met dimension variables are removed.""" + np.random.seed(42) + ds = self._create_test_dataset(n_sweeps=2) + + result = _compute_normalized_counts_per_sweep(ds, tof_ab_limit_ns=15) + + # Variables that were on event_met dimension should be gone + assert "tof_ab" not in result.data_vars + assert "coincidence_type" not in result.data_vars + assert "ccsds_index" not in result.data_vars + + def test_raises_without_esa_sweep_coordinate(self): + """Test that function raises error without esa_sweep coordinate.""" + ds = xr.Dataset( + { + "ccsds_met": (["epoch"], np.array([1000.0, 1060.0])), + "esa_step": (["epoch"], np.array([1, 2], dtype=np.uint8)), + }, + coords={"epoch": np.arange(2)}, + ) + + with pytest.raises(ValueError, match="must have esa_sweep coordinate"): + _compute_normalized_counts_per_sweep(ds, tof_ab_limit_ns=15) + + def test_multiple_sweeps(self): + """Test with multiple sweeps.""" + np.random.seed(42) + ds = self._create_test_dataset(n_sweeps=5) + + result = _compute_normalized_counts_per_sweep(ds, tof_ab_limit_ns=15) + + assert len(result["normalized_count"]) == 5 + assert result.sizes["esa_sweep"] == 5 + + +class TestStatisticalFilter0: + """Test suite for mark_statistical_filter_0() integration tests.""" + + @pytest.fixture + def goodtimes_for_filter(self): + """Create a goodtimes dataset for testing statistical filter 0.""" + # Create 2 complete ESA sweeps (9 METs each = 18 total) + n_mets = 18 + met_values = np.arange(1000.0, 1000.0 + n_mets * 60, 60) + + gt = xr.Dataset( + { + "cull_flags": xr.DataArray( + np.zeros((n_mets, 90), dtype=np.uint8), dims=["met", "spin_bin"] + ), + "esa_step": xr.DataArray( + np.tile(np.arange(1, 10), 2).astype(np.uint8), dims=["met"] + ), + }, + coords={"met": met_values, "spin_bin": np.arange(90)}, + attrs={"sensor": "45sensor", "pointing": 1}, + ) + return gt + + def _create_l1b_de_dataset( + self, + n_sweeps: int = 2, + events_per_met: int = 10, + tof_ab_range: tuple[int, int] = (-15, 15), + base_met: float = 1000.0, + ) -> xr.Dataset: + """ + Create a mock L1B DE dataset with complete ESA sweeps. + + Parameters + ---------- + n_sweeps : int + Number of complete ESA sweeps (each sweep = 9 METs for ESA 1-9). + events_per_met : int + Number of events per MET. + tof_ab_range : tuple[int, int] + Range for random tof_ab values. + base_met : float + Base MET value for the dataset. + + Returns + ------- + xr.Dataset + Mock L1B DE dataset with complete ESA sweeps. + """ + n_esa_steps = 9 # ESA steps 1-9 + n_packets = n_sweeps * n_esa_steps + n_events = n_packets * events_per_met + + # Create ESA steps cycling through 1-9 for each sweep + esa_step = np.tile(np.arange(1, n_esa_steps + 1), n_sweeps).astype(np.uint8) + # esa_energy_step same as esa_step for test purposes + esa_energy_step = esa_step.copy() + + # Create ccsds_met for packets + ccsds_met = np.arange(base_met, base_met + n_packets * 60, 60, dtype=np.float64) + + # Create events distributed across packets + tof_ab_values = np.random.randint( + tof_ab_range[0], tof_ab_range[1], n_events + ).astype(np.int32) + coincidence_type = np.full(n_events, 12, dtype=np.uint8) # AB coincidence + ccsds_index = np.repeat(np.arange(n_packets), events_per_met).astype(np.uint16) + + return xr.Dataset( + data_vars={ + "tof_ab": (["event_met"], tof_ab_values, {"FILLVAL": -2147483648}), + "coincidence_type": (["event_met"], coincidence_type), + "ccsds_index": (["event_met"], ccsds_index), + "ccsds_met": (["epoch"], ccsds_met), + "esa_step": (["epoch"], esa_step, {"FILLVAL": 255}), + "esa_energy_step": (["epoch"], esa_energy_step, {"FILLVAL": 255}), + }, + coords={ + "event_met": np.arange(n_events), + "epoch": np.arange(n_packets), + }, + ) + + def test_passes_normal_sweeps(self, goodtimes_for_filter): + """Test that similar counts across sweeps passes the filter.""" + np.random.seed(42) + # Create 5 datasets with 2 sweeps each, similar event counts + l1b_de_datasets = [ + self._create_l1b_de_dataset(n_sweeps=2, events_per_met=10) for _ in range(5) + ] + + mark_statistical_filter_0( + goodtimes_for_filter, l1b_de_datasets, current_index=2 + ) + + # All times should still be good (no sweeps exceed threshold) + assert np.all(goodtimes_for_filter["cull_flags"].values == CullCode.GOOD) + + def test_fails_anomalous_sweep(self, goodtimes_for_filter): + """Test that sweeps exceeding 150% median are marked as culled.""" + np.random.seed(42) + l1b_de_datasets = [] + + for i in range(5): + if i == 2: # Current pointing - create many more events + ds = self._create_l1b_de_dataset(n_sweeps=2, events_per_met=50) + else: + ds = self._create_l1b_de_dataset(n_sweeps=2, events_per_met=10) + l1b_de_datasets.append(ds) + + mark_statistical_filter_0( + goodtimes_for_filter, l1b_de_datasets, current_index=2 + ) + + # Current sweeps have 5x the events, should be culled + # Check that at least some METs are culled + assert np.any( + goodtimes_for_filter["cull_flags"].values == CullCode.STAT_FILTER_0 + ) + + def test_insufficient_pointings(self, goodtimes_for_filter): + """Test that fewer than min_pointings raises ValueError.""" + l1b_de_datasets = [ + self._create_l1b_de_dataset(), + self._create_l1b_de_dataset(), + self._create_l1b_de_dataset(), + ] + + with pytest.raises(ValueError, match="At least 4 valid Pointings required"): + mark_statistical_filter_0( + goodtimes_for_filter, l1b_de_datasets, current_index=2 + ) + + def test_current_index_out_of_range(self, goodtimes_for_filter): + """Test that current_index out of range raises ValueError.""" + l1b_de_datasets = [self._create_l1b_de_dataset()] * 5 + + with pytest.raises(ValueError, match="current_index.*out of range"): + mark_statistical_filter_0( + goodtimes_for_filter, l1b_de_datasets, current_index=10 + ) + + def test_partial_sweep_culling(self, goodtimes_for_filter): + """Test that only bad sweeps are culled, not entire Pointing.""" + np.random.seed(42) + + # Create current pointing with one normal sweep and one anomalous sweep + n_esa_steps = 9 + n_packets = 2 * n_esa_steps # 2 sweeps + + # First sweep: normal count (10 events/MET) + # Second sweep: high count (100 events/MET) + events_sweep1 = 10 * n_esa_steps + events_sweep2 = 100 * n_esa_steps + n_events = events_sweep1 + events_sweep2 + + esa_step = np.tile(np.arange(1, 10), 2).astype(np.uint8) + esa_energy_step = esa_step.copy() + ccsds_met = np.arange(1000.0, 1000.0 + n_packets * 60, 60, dtype=np.float64) + + # Events for first sweep (packets 0-8) + ccsds_index_1 = np.repeat(np.arange(n_esa_steps), 10).astype(np.uint16) + # Events for second sweep (packets 9-17) + ccsds_index_2 = np.repeat(np.arange(n_esa_steps, 2 * n_esa_steps), 100).astype( + np.uint16 + ) + ccsds_index = np.concatenate([ccsds_index_1, ccsds_index_2]) + + tof_ab = np.random.randint(-10, 10, n_events).astype(np.int32) + coincidence_type = np.full(n_events, 12, dtype=np.uint8) + + current_ds = xr.Dataset( + data_vars={ + "tof_ab": (["event_met"], tof_ab, {"FILLVAL": -2147483648}), + "coincidence_type": (["event_met"], coincidence_type), + "ccsds_index": (["event_met"], ccsds_index), + "ccsds_met": (["epoch"], ccsds_met), + "esa_step": (["epoch"], esa_step, {"FILLVAL": 255}), + "esa_energy_step": (["epoch"], esa_energy_step, {"FILLVAL": 255}), + }, + coords={ + "event_met": np.arange(n_events), + "epoch": np.arange(n_packets), + }, + ) + + # Other pointings: all normal (10 events/MET) + l1b_de_datasets = [ + self._create_l1b_de_dataset(n_sweeps=2, events_per_met=10), + self._create_l1b_de_dataset(n_sweeps=2, events_per_met=10), + current_ds, # Current with mixed sweeps + self._create_l1b_de_dataset(n_sweeps=2, events_per_met=10), + self._create_l1b_de_dataset(n_sweeps=2, events_per_met=10), + ] + + mark_statistical_filter_0( + goodtimes_for_filter, l1b_de_datasets, current_index=2 + ) + + # First 9 METs (sweep 1) should be good, last 9 METs (sweep 2) should be bad + first_sweep_flags = goodtimes_for_filter["cull_flags"].values[:9, :] + second_sweep_flags = goodtimes_for_filter["cull_flags"].values[9:, :] + + assert np.all(first_sweep_flags == CullCode.GOOD) + assert np.all(second_sweep_flags == CullCode.STAT_FILTER_0) + + +class TestIdentifyCullPattern: + """Test suite for _identify_cull_pattern() convolution-based pattern detection.""" + + def _create_test_data( + self, n_sweeps: int = 10, n_esa_steps: int = 5 + ) -> tuple[xr.DataArray, xr.DataArray, xr.DataArray]: + """Create test counts, median, and sigma DataArrays.""" + # Create counts array (esa_sweep x esa_energy_step) + counts = xr.DataArray( + np.zeros((n_sweeps, n_esa_steps)), + dims=["esa_sweep", "esa_energy_step"], + coords={ + "esa_sweep": np.arange(n_sweeps), + "esa_energy_step": np.arange(1, n_esa_steps + 1), + }, + ) + + # Create median and sigma per ESA energy step (all valid) + median = xr.DataArray( + np.full(n_esa_steps, 10.0), + dims=["esa_energy_step"], + coords={"esa_energy_step": np.arange(1, n_esa_steps + 1)}, + ) + sigma = xr.DataArray( + np.full(n_esa_steps, 3), + dims=["esa_energy_step"], + coords={"esa_energy_step": np.arange(1, n_esa_steps + 1)}, + ) + + return counts, median, sigma + + def test_no_exceedances(self): + """Test with counts below all thresholds.""" + counts, median, sigma = self._create_test_data() + # All counts are 0, well below threshold of ~15 (10 + 1.8*3) + + cull_mask = _identify_cull_pattern(counts, median, sigma) + + assert cull_mask.dims == ("esa_sweep", "esa_energy_step") + assert not cull_mask.any() + + def test_consecutive_run_with_esa_neighbor(self): + """Test finding 3+ consecutive high counts with ESA neighbor confirmation.""" + counts, median, sigma = self._create_test_data(n_sweeps=10, n_esa_steps=5) + # threshold = 10 + 1.8 * 3 = 15.4 + + # Create 4 consecutive high counts at ESA step 3 (sweeps 2-5) + counts.loc[2:5, 3] = 20 + # Also make ESA step 2 high at same time positions (neighbor at same time) + counts.loc[2:5, 2] = 20 + + cull_mask = _identify_cull_pattern(counts, median, sigma) + + # Sweeps 2-5 at ESA 3 should be marked + # (consecutive run with neighbor at same time) + assert cull_mask.sel(esa_sweep=2, esa_energy_step=3).values + assert cull_mask.sel(esa_sweep=3, esa_energy_step=3).values + assert cull_mask.sel(esa_sweep=4, esa_energy_step=3).values + assert cull_mask.sel(esa_sweep=5, esa_energy_step=3).values + # ESA 2 should also be marked (consecutive run with ESA 3 as neighbor) + assert cull_mask.sel(esa_sweep=2, esa_energy_step=2).values + assert cull_mask.sel(esa_sweep=3, esa_energy_step=2).values + assert cull_mask.sel(esa_sweep=4, esa_energy_step=2).values + assert cull_mask.sel(esa_sweep=5, esa_energy_step=2).values + + def test_consecutive_run_no_esa_neighbor(self): + """Test that consecutive run without ESA neighbor is not marked.""" + counts, median, sigma = self._create_test_data(n_sweeps=10, n_esa_steps=5) + + # Create 4 consecutive high counts at ESA step 3, but no neighbors high + counts.loc[2:5, 3] = 20 + + cull_mask = _identify_cull_pattern(counts, median, sigma) + + # Without ESA neighbor confirmation, consecutive runs alone don't trigger + # (but extreme outliers at 5-sigma would - threshold = 10 + 5*3 = 25) + assert not cull_mask.sel(esa_energy_step=3).any() + + def test_isolated_interval_marked(self): + """Test that good interval surrounded by bad is marked.""" + counts, median, sigma = self._create_test_data(n_sweeps=10, n_esa_steps=5) + + # Create pattern: bad - good - bad at ESA step 3 + # First create a setup that triggers consecutive culling + counts.loc[0:3, 3] = 20 # 4 consecutive high + counts.loc[0:3, 2] = 20 # ESA neighbor + counts.loc[5:8, 3] = 20 # Another 4 consecutive high + counts.loc[5:8, 2] = 20 # ESA neighbor + # Sweep 4 at ESA 3 is good (low count) but surrounded by bad + + cull_mask = _identify_cull_pattern(counts, median, sigma) + + # Sweep 4 should be marked as isolated + assert cull_mask.sel(esa_sweep=4, esa_energy_step=3).values + + def test_extreme_outlier(self): + """Test detection of extreme outliers (5-sigma).""" + counts, median, sigma = self._create_test_data() + # extreme threshold = 10 + 5 * 3 = 25 + + # Single extreme outlier at sweep 5, ESA 3 + counts.loc[5, 3] = 30 + + cull_mask = _identify_cull_pattern(counts, median, sigma) + + # Only the extreme outlier should be marked + assert cull_mask.sel(esa_sweep=5, esa_energy_step=3).values + # Other positions should not be marked + assert not cull_mask.sel(esa_sweep=4, esa_energy_step=3).values + assert not cull_mask.sel(esa_sweep=6, esa_energy_step=3).values + + def test_nan_handling(self): + """Test that NaN values in counts are handled correctly.""" + counts, median, sigma = self._create_test_data() + + # Set some counts to NaN + counts.loc[3, 2] = np.nan + + cull_mask = _identify_cull_pattern(counts, median, sigma) + + # NaN positions should not be marked (treated as not exceeding) + assert not cull_mask.sel(esa_sweep=3, esa_energy_step=2).values + + def test_returns_dataarray_with_correct_coords(self): + """Test that returned mask has correct dimensions and coordinates.""" + counts, median, sigma = self._create_test_data(n_sweeps=8, n_esa_steps=4) + + cull_mask = _identify_cull_pattern(counts, median, sigma) + + assert isinstance(cull_mask, xr.DataArray) + assert cull_mask.dims == counts.dims + np.testing.assert_array_equal( + cull_mask.coords["esa_sweep"].values, counts.coords["esa_sweep"].values + ) + np.testing.assert_array_equal( + cull_mask.coords["esa_energy_step"].values, + counts.coords["esa_energy_step"].values, + ) + + def test_consecutive_run_at_first_esa_edge(self): + """Test that consecutive run at first ESA step passes neighbor check at edge.""" + counts, median, sigma = self._create_test_data(n_sweeps=10, n_esa_steps=5) + # threshold = 10 + 1.8 * 3 = 15.4 + + # Create 4 consecutive high counts at ESA step 1 (first ESA step) + counts.loc[2:5, 1] = 20 + # No ESA neighbor below (edge), but edge should pass the check + + cull_mask = _identify_cull_pattern(counts, median, sigma) + + # Sweeps 2-5 at ESA 1 should be marked (edge passes neighbor check) + assert cull_mask.sel(esa_sweep=2, esa_energy_step=1).values + assert cull_mask.sel(esa_sweep=3, esa_energy_step=1).values + assert cull_mask.sel(esa_sweep=4, esa_energy_step=1).values + assert cull_mask.sel(esa_sweep=5, esa_energy_step=1).values + + def test_consecutive_run_at_last_esa_edge(self): + """Test that consecutive run at last ESA step passes neighbor check at edge.""" + counts, median, sigma = self._create_test_data(n_sweeps=10, n_esa_steps=5) + # threshold = 10 + 1.8 * 3 = 15.4 + + # Create 4 consecutive high counts at ESA step 5 (last ESA step) + counts.loc[2:5, 5] = 20 + # No ESA neighbor above (edge), but edge should pass the check + + cull_mask = _identify_cull_pattern(counts, median, sigma) + + # Sweeps 2-5 at ESA 5 should be marked (edge passes neighbor check) + assert cull_mask.sel(esa_sweep=2, esa_energy_step=5).values + assert cull_mask.sel(esa_sweep=3, esa_energy_step=5).values + assert cull_mask.sel(esa_sweep=4, esa_energy_step=5).values + assert cull_mask.sel(esa_sweep=5, esa_energy_step=5).values + + def test_orphan_not_marked_at_time_edge(self): + """Test that positions at time edges are not marked as orphans.""" + counts, median, sigma = self._create_test_data(n_sweeps=10, n_esa_steps=5) + + # Create bad intervals at sweeps 1 and 3, leaving sweep 0 as "orphan-like" + # But sweep 0 is at edge and should NOT be marked as orphan + counts.loc[1:3, 3] = 20 # Consecutive run + counts.loc[1:3, 2] = 20 # ESA neighbor + + cull_mask = _identify_cull_pattern(counts, median, sigma) + + # Sweep 0 should NOT be marked (edge, not a true orphan) + assert not cull_mask.sel(esa_sweep=0, esa_energy_step=3).values + # Sweeps 1-3 should be marked (consecutive with neighbor) + assert cull_mask.sel(esa_sweep=1, esa_energy_step=3).values + assert cull_mask.sel(esa_sweep=2, esa_energy_step=3).values + assert cull_mask.sel(esa_sweep=3, esa_energy_step=3).values + + +class TestComputeQualifiedCountsPerSweep: + """Test suite for _compute_qualified_counts_per_sweep() helper function.""" + + def _create_test_dataset( + self, + n_packets: int = 10, + events_per_packet: int = 5, + coincidence_types: list[int] | None = None, + ) -> xr.Dataset: + """Create a test L1B DE dataset with esa_sweep coordinate.""" + n_events = n_packets * events_per_packet + + if coincidence_types is None: + # Default: mix of types, 12 (AB) is qualified + coincidence_types = [12, 4, 8, 12, 4] * (n_events // 5 + 1) + coincidence_types = coincidence_types[:n_events] + + ccsds_index = np.repeat(np.arange(n_packets), events_per_packet).astype( + np.uint16 + ) + + # Create ESA steps: 2 packets per ESA step, ESA steps 1-5 + esa_step = np.repeat(np.arange(1, n_packets // 2 + 1), 2)[:n_packets].astype( + np.uint8 + ) + # esa_energy_step same as esa_step for test purposes + esa_energy_step = esa_step.copy() + + ds = xr.Dataset( + { + "coincidence_type": ( + ["event_met"], + np.array(coincidence_types, dtype=np.uint8), + ), + "ccsds_index": (["event_met"], ccsds_index), + "ccsds_met": ( + ["epoch"], + np.arange(1000.0, 1000.0 + n_packets * 60, 60), + ), + "esa_step": (["epoch"], esa_step), + "esa_energy_step": (["epoch"], esa_energy_step), + }, + coords={ + "event_met": np.arange(n_events), + "epoch": np.arange(n_packets), + }, + ) + + # Add esa_sweep coordinate + return _add_sweep_indices(ds) + + def test_sums_counts_per_eight_spin(self): + """Test that counts are summed per 8-spin interval (esa_sweep, esa_step).""" + # 10 packets, 2 packets per ESA step = 5 unique (esa_sweep, esa_step) combos + # All in same sweep (no high-to-low transition), ESA steps 1-5 + ds = self._create_test_dataset(n_packets=10, events_per_packet=10) + + # Create qualified mask based on coincidence type 12 + qualified_mask = np.isin(ds["coincidence_type"].values, [12]) + + result = _compute_qualified_counts_per_sweep(ds, qualified_mask) + + assert "qualified_count" in result.data_vars + assert "esa_sweep" in result.dims + assert "esa_energy_step" in result.dims + + # Each packet has 10 events, 4 are type 12 (from pattern [12,4,8,12,4] * 2) + # 2 packets per 8-spin set = 8 qualified counts per (esa_sweep, esa_step) + # Select only the valid ESA steps (1-5) + for esa in range(1, 6): + count = ( + result["qualified_count"].sel(esa_sweep=0, esa_energy_step=esa).values + ) + assert count == 8 + + def test_raises_without_coordinate(self): + """Test that function raises error without esa_sweep coordinate.""" + ds = xr.Dataset( + { + "coincidence_type": (["event_met"], np.array([12, 4], dtype=np.uint8)), + "ccsds_index": (["event_met"], np.array([0, 0], dtype=np.uint16)), + "ccsds_met": (["epoch"], np.array([1000.0])), + "esa_step": (["epoch"], np.array([1], dtype=np.uint8)), + }, + coords={"event_met": np.arange(2), "epoch": np.arange(1)}, + ) + + # Create qualified mask for coincidence type 12 + qualified_mask = np.isin(ds["coincidence_type"].values, [12]) + + with pytest.raises(ValueError, match="must have esa_sweep coordinate"): + _compute_qualified_counts_per_sweep(ds, qualified_mask) + + +class TestBuildPerSweepDatasets: + """Test suite for _build_per_sweep_datasets() helper function.""" + + def _create_test_dataset( + self, n_packets: int = 18, base_met: float = 1000.0 + ) -> xr.Dataset: + """Create a test L1B DE dataset with 2 packets per ESA step (9 ESA steps).""" + events_per_packet = 10 + n_events = n_packets * events_per_packet + + # All events are type 12 (qualified) + coincidence_types = np.full(n_events, 12, dtype=np.uint8) + ccsds_index = np.repeat(np.arange(n_packets), events_per_packet).astype( + np.uint16 + ) + + # 2 packets per ESA step: [1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9] + esa_step = np.repeat(np.arange(1, 10), 2).astype(np.uint8) + # esa_energy_step same as esa_step for test purposes + esa_energy_step = esa_step.copy() + + return xr.Dataset( + { + "coincidence_type": (["event_met"], coincidence_types), + "ccsds_index": (["event_met"], ccsds_index), + "ccsds_met": ( + ["epoch"], + np.arange(base_met, base_met + n_packets * 60, 60), + ), + "esa_step": (["epoch"], esa_step), + "esa_energy_step": (["epoch"], esa_energy_step), + }, + coords={ + "event_met": np.arange(n_events), + "epoch": np.arange(n_packets), + }, + ) + + def test_builds_per_sweep_datasets(self): + """Test that per-sweep datasets are built correctly.""" + ds = self._create_test_dataset() + + # Add qualified mask based on coincidence type 12 directly to dataset + ds["qualified_mask"] = xr.DataArray( + np.isin(ds["coincidence_type"].values, [12]), + dims=["event_met"], + ) + + per_sweep_datasets = _build_per_sweep_datasets([ds]) + + # Should have per-sweep dataset for index 0 with 2D structure + assert 0 in per_sweep_datasets + assert "esa_sweep" in per_sweep_datasets[0].dims + assert "esa_energy_step" in per_sweep_datasets[0].dims + # 9 ESA energy steps (1-9) in the data + assert len(per_sweep_datasets[0].coords["esa_energy_step"]) == 9 + + # Each (esa_sweep, esa_energy_step) should have 20 qualified counts + # 2 packets per ESA step, 10 events each = 20 qualified counts per 8-spin + for esa in range(1, 10): + count = ( + per_sweep_datasets[0]["qualified_count"] + .sel(esa_sweep=0, esa_energy_step=esa) + .values + ) + assert count == 20 + + def test_multiple_datasets(self): + """Test with multiple datasets.""" + ds1 = self._create_test_dataset(base_met=1000.0) + ds2 = self._create_test_dataset(base_met=2000.0) + + # Add qualified masks directly to datasets + ds1["qualified_mask"] = xr.DataArray( + np.isin(ds1["coincidence_type"].values, [12]), + dims=["event_met"], + ) + ds2["qualified_mask"] = xr.DataArray( + np.isin(ds2["coincidence_type"].values, [12]), + dims=["event_met"], + ) + + per_sweep_datasets = _build_per_sweep_datasets([ds1, ds2]) + + # Should have per-sweep datasets for both indices + assert 0 in per_sweep_datasets + assert 1 in per_sweep_datasets + + +class TestComputeMedianAndSigmaPerEsa: + """Test suite for _compute_median_and_sigma_per_esa() helper function.""" + + def test_basic_calculation(self): + """Test basic median and sigma calculation.""" + # Create dataset with counts where median is 4 for each ESA energy step + # Using 5 sweeps with counts [2, 4, 6, 4, 4] for ESA energy steps 1-9 + n_sweeps = 5 + counts_per_sweep = [2, 4, 6, 4, 4] + counts_2d = np.zeros((n_sweeps, 10)) # ESA energy steps 0-9 + for sweep_idx, count in enumerate(counts_per_sweep): + for esa in range(1, 10): + counts_2d[sweep_idx, esa] = count + + per_sweep_datasets = { + 0: xr.Dataset( + { + "qualified_count": (["esa_sweep", "esa_energy_step"], counts_2d), + "ccsds_met": ( + ["esa_sweep", "esa_energy_step"], + np.full_like(counts_2d, 1000.0), + ), + }, + coords={ + "esa_sweep": np.arange(n_sweeps), + "esa_energy_step": np.arange(10), + }, + ) + } + + median_per_esa, sigma_per_esa = _compute_median_and_sigma_per_esa( + per_sweep_datasets + ) + + for esa in range(1, 10): + assert median_per_esa.sel(esa_energy_step=esa).values == 4.0 + # sigma = round(sqrt(4 + 1)) = round(2.236) = 2 + assert sigma_per_esa.sel(esa_energy_step=esa).values == 2 + + def test_zero_median_excluded(self): + """Test that ESA energy steps with zero median are excluded.""" + # ESA energy step 1: all zeros, ESA energy step 2: median 4 + n_sweeps = 5 + counts_2d = np.zeros((n_sweeps, 10)) + # ESA 1 stays at 0 + # ESA 2 gets counts [2, 4, 6, 4, 4] + for sweep_idx, count in enumerate([2, 4, 6, 4, 4]): + counts_2d[sweep_idx, 2] = count + + per_sweep_datasets = { + 0: xr.Dataset( + { + "qualified_count": (["esa_sweep", "esa_energy_step"], counts_2d), + "ccsds_met": ( + ["esa_sweep", "esa_energy_step"], + np.full_like(counts_2d, 1000.0), + ), + }, + coords={ + "esa_sweep": np.arange(n_sweeps), + "esa_energy_step": np.arange(10), + }, + ) + } + + median_per_esa, sigma_per_esa = _compute_median_and_sigma_per_esa( + per_sweep_datasets + ) + + # ESA energy step 1 should have NaN median (zero counts excluded) + assert np.isnan(median_per_esa.sel(esa_energy_step=1).values) + # ESA energy step 2 should have valid median + assert median_per_esa.sel(esa_energy_step=2).values == 4.0 + + def test_empty_datasets_handled(self): + """Test that empty datasets result in empty DataArrays.""" + # Empty per_sweep_datasets + per_sweep_datasets: dict[int, xr.Dataset] = {} + + median_per_esa, sigma_per_esa = _compute_median_and_sigma_per_esa( + per_sweep_datasets + ) + + assert len(median_per_esa) == 0 + assert len(sigma_per_esa) == 0 + + +class TestStatisticalFilter1: + """Test suite for mark_statistical_filter_1() integration tests.""" + + @pytest.fixture + def goodtimes_for_filter1(self): + """Create a goodtimes dataset for testing statistical filter 1.""" + # Create 18 METs (2 complete ESA sweeps) + n_mets = 18 + met_values = np.arange(1000.0, 1000.0 + n_mets * 60, 60) + + gt = xr.Dataset( + { + "cull_flags": xr.DataArray( + np.zeros((n_mets, 90), dtype=np.uint8), dims=["met", "spin_bin"] + ), + "esa_step": xr.DataArray( + np.tile(np.arange(1, 10), 2).astype(np.uint8), dims=["met"] + ), + }, + coords={"met": met_values, "spin_bin": np.arange(90)}, + attrs={"sensor": "45sensor", "pointing": 1}, + ) + return gt + + def _create_l1b_de_dataset( + self, + n_packets: int = 18, + events_per_packet: int = 10, + base_met: float = 1000.0, + coincidence_type: int = 12, + ) -> xr.Dataset: + """Create a mock L1B DE dataset.""" + n_events = n_packets * events_per_packet + + # ESA steps cycling 1-9 for each sweep + esa_step = np.tile(np.arange(1, 10), n_packets // 9 + 1)[:n_packets].astype( + np.uint8 + ) + # esa_energy_step same as esa_step for test purposes + esa_energy_step = esa_step.copy() + ccsds_met = np.arange(base_met, base_met + n_packets * 60, 60, dtype=np.float64) + coincidence_types = np.full(n_events, coincidence_type, dtype=np.uint8) + ccsds_index = np.repeat(np.arange(n_packets), events_per_packet).astype( + np.uint16 + ) + + return xr.Dataset( + data_vars={ + "coincidence_type": (["event_met"], coincidence_types), + "ccsds_index": (["event_met"], ccsds_index), + "ccsds_met": (["epoch"], ccsds_met), + "esa_step": (["epoch"], esa_step), + "esa_energy_step": (["epoch"], esa_energy_step), + }, + coords={ + "event_met": np.arange(n_events), + "epoch": np.arange(n_packets), + }, + ) + + def test_passes_normal_data(self, goodtimes_for_filter1): + """Test that normal data with consistent counts passes the filter.""" + # Current pointing at index 2 must have METs matching goodtimes (1000.0-2020.0) + l1b_de_datasets = [ + self._create_l1b_de_dataset(events_per_packet=10, base_met=0.0), + self._create_l1b_de_dataset(events_per_packet=10, base_met=500.0), + self._create_l1b_de_dataset( + events_per_packet=10, base_met=1000.0 + ), # Current + self._create_l1b_de_dataset(events_per_packet=10, base_met=2500.0), + self._create_l1b_de_dataset(events_per_packet=10, base_met=3500.0), + ] + + # Add qualified masks directly to datasets + for ds in l1b_de_datasets: + ds["qualified_mask"] = xr.DataArray( + np.isin(ds["coincidence_type"].values, [12]), + dims=["event_met"], + ) + + mark_statistical_filter_1( + goodtimes_for_filter1, + l1b_de_datasets, + current_index=2, + ) + + # All times should still be good + assert np.all(goodtimes_for_filter1["cull_flags"].values == CullCode.GOOD) + + def test_fails_extreme_outlier(self, goodtimes_for_filter1): + """Test that extreme outliers (>5-sigma) are marked as bad.""" + # Create datasets - current pointing at index 2 must have + # METs matching goodtimes + # goodtimes has METs from 1000.0 to ~2020.0 (18 METs, 60s apart) + l1b_de_datasets = [ + self._create_l1b_de_dataset(events_per_packet=10, base_met=0.0), + self._create_l1b_de_dataset(events_per_packet=10, base_met=500.0), + self._create_l1b_de_dataset( + events_per_packet=10, base_met=1000.0 + ), # Current - matches goodtimes + self._create_l1b_de_dataset(events_per_packet=10, base_met=2500.0), + self._create_l1b_de_dataset(events_per_packet=10, base_met=3500.0), + ] + + # Make current pointing have extreme counts for one interval + current_ds = l1b_de_datasets[2] + # Add many more events to first packet only + extra_events = 100 + new_coincidence = np.concatenate( + [ + current_ds["coincidence_type"].values, + np.full(extra_events, 12, dtype=np.uint8), + ] + ) + new_ccsds_index = np.concatenate( + [ + current_ds["ccsds_index"].values, + np.zeros(extra_events, dtype=np.uint16), # All to first packet + ] + ) + + l1b_de_datasets[2] = xr.Dataset( + data_vars={ + "coincidence_type": (["event_met"], new_coincidence), + "ccsds_index": (["event_met"], new_ccsds_index), + "ccsds_met": current_ds["ccsds_met"], + "esa_step": current_ds["esa_step"], + "esa_energy_step": current_ds["esa_energy_step"], + }, + coords={ + "event_met": np.arange(len(new_coincidence)), + "epoch": current_ds["epoch"], + }, + ) + + # Add qualified masks directly to datasets + for ds in l1b_de_datasets: + ds["qualified_mask"] = xr.DataArray( + np.isin(ds["coincidence_type"].values, [12]), + dims=["event_met"], + ) + + mark_statistical_filter_1( + goodtimes_for_filter1, + l1b_de_datasets, + current_index=2, + ) + + # At least the first MET should be marked bad (extreme outlier) + assert np.any( + goodtimes_for_filter1["cull_flags"].values == CullCode.STAT_FILTER_1 + ) + + def test_insufficient_pointings(self, goodtimes_for_filter1): + """Test that fewer than min_pointings raises ValueError.""" + l1b_de_datasets = [ + self._create_l1b_de_dataset(), + self._create_l1b_de_dataset(), + self._create_l1b_de_dataset(), + ] + + # Add qualified masks directly to datasets + for ds in l1b_de_datasets: + ds["qualified_mask"] = xr.DataArray( + np.isin(ds["coincidence_type"].values, [12]), + dims=["event_met"], + ) + + with pytest.raises(ValueError, match="At least 4 valid Pointings required"): + mark_statistical_filter_1( + goodtimes_for_filter1, + l1b_de_datasets, + current_index=1, + ) + + def test_current_index_out_of_range(self, goodtimes_for_filter1): + """Test that current_index out of range raises ValueError.""" + l1b_de_datasets = [self._create_l1b_de_dataset() for _ in range(5)] + + # Add qualified masks directly to datasets + for ds in l1b_de_datasets: + ds["qualified_mask"] = xr.DataArray( + np.isin(ds["coincidence_type"].values, [12]), + dims=["event_met"], + ) + + with pytest.raises(ValueError, match="current_index.*out of range"): + mark_statistical_filter_1( + goodtimes_for_filter1, + l1b_de_datasets, + current_index=10, + ) + + +class TestFindEventClusters: + """Test suite for _find_event_clusters() helper function.""" + + def test_empty_array(self): + """Test with empty input.""" + result = _find_event_clusters(np.array([]), min_events=3, max_time_delta=100) + assert result == [] + + def test_too_few_events(self): + """Test with fewer events than min_events.""" + de_tags = np.array([10, 50]) + result = _find_event_clusters(de_tags, min_events=3, max_time_delta=100) + assert result == [] + + def test_events_too_spread(self): + """Test with events spread beyond max_time_delta.""" + de_tags = np.array([0, 1000, 2000, 3000, 4000, 5000]) + result = _find_event_clusters(de_tags, min_events=3, max_time_delta=100) + assert result == [] + + def test_single_cluster(self): + """Test detection of a single cluster.""" + de_tags = np.array([100, 110, 120, 130, 140, 150]) + result = _find_event_clusters(de_tags, min_events=3, max_time_delta=100) + assert len(result) == 1 + assert result[0] == (0, 5) + + def test_multiple_clusters(self): + """Test detection of multiple separate clusters.""" + de_tags = np.array([100, 110, 120, 1000, 1010, 1020]) + result = _find_event_clusters(de_tags, min_events=3, max_time_delta=50) + assert len(result) == 2 + assert result[0] == (0, 2) + assert result[1] == (3, 5) + + def test_cluster_merge(self): + """Test that overlapping clusters are merged.""" + # Events that form overlapping windows + de_tags = np.array([0, 10, 20, 30, 40, 50]) + result = _find_event_clusters(de_tags, min_events=3, max_time_delta=30) + # All events should merge into one cluster + assert len(result) == 1 + assert result[0] == (0, 5) + + def test_exact_threshold(self): + """Test cluster detection at exact min_events threshold.""" + de_tags = np.array([0, 10, 20]) # Exactly 3 events within 20 ticks + result = _find_event_clusters(de_tags, min_events=3, max_time_delta=20) + assert len(result) == 1 + assert result[0] == (0, 2) + + +class TestComputeBinsForCluster: + """Test suite for _compute_bins_for_cluster() helper function.""" + + def test_basic_range(self): + """Test basic bin range computation.""" + nominal_bins = np.array([40, 42, 44, 46]) + bins = _compute_bins_for_cluster( + nominal_bins, cluster_start=0, cluster_end=3, bin_padding=1 + ) + expected = np.arange(39, 48) # 40-1 to 46+1 + np.testing.assert_array_equal(bins, expected) + + def test_wrapping_at_zero(self): + """Test that bins wrap around at 0.""" + nominal_bins = np.array([0, 1, 2]) + bins = _compute_bins_for_cluster( + nominal_bins, cluster_start=0, cluster_end=2, bin_padding=2, n_bins=90 + ) + # Should wrap: -2, -1, 0, 1, 2, 3, 4 -> 88, 89, 0, 1, 2, 3, 4 + expected = np.array([88, 89, 0, 1, 2, 3, 4]) + np.testing.assert_array_equal(bins, expected) + + def test_wrapping_at_max(self): + """Test that bins wrap around at n_bins.""" + nominal_bins = np.array([87, 88, 89]) + bins = _compute_bins_for_cluster( + nominal_bins, cluster_start=0, cluster_end=2, bin_padding=2, n_bins=90 + ) + # Should wrap: 85, 86, 87, 88, 89, 90, 91 -> 85, 86, 87, 88, 89, 0, 1 + expected = np.array([85, 86, 87, 88, 89, 0, 1]) + np.testing.assert_array_equal(bins, expected) + + def test_partial_cluster(self): + """Test range computation for partial cluster.""" + nominal_bins = np.array([10, 20, 30, 40, 50]) + bins = _compute_bins_for_cluster( + nominal_bins, cluster_start=1, cluster_end=3, bin_padding=1 + ) + expected = np.arange(19, 42) # 20-1 to 40+1 + np.testing.assert_array_equal(bins, expected) + + def test_no_wrapping_needed(self): + """Test middle bins that don't need wrapping.""" + nominal_bins = np.array([44, 45, 46]) + bins = _compute_bins_for_cluster( + nominal_bins, cluster_start=0, cluster_end=2, bin_padding=1 + ) + expected = np.arange(43, 48) # 44-1 to 46+1 + np.testing.assert_array_equal(bins, expected) + + def test_cluster_spanning_zero_boundary(self): + """Test cluster that spans across the 0/89 boundary.""" + # Cluster bins span from 87 to 2 (wrapping around) + nominal_bins = np.array([87, 88, 89, 0, 1, 2]) + bins = _compute_bins_for_cluster( + nominal_bins, cluster_start=0, cluster_end=5, bin_padding=1, n_bins=90 + ) + # Should mark 86-89 and 0-3 (cluster 87-2 plus padding of 1) + expected = np.array([86, 87, 88, 89, 0, 1, 2, 3]) + np.testing.assert_array_equal(bins, expected) + + +class TestStatisticalFilter2: + """Test suite for mark_statistical_filter_2() function.""" + + @pytest.fixture + def goodtimes_for_filter2(self): + """Create a goodtimes dataset for filter 2 testing.""" + n_mets = 10 + met_values = np.arange(1000.0, 1000.0 + n_mets * 120, 120) + + ds = xr.Dataset( + { + "cull_flags": xr.DataArray( + np.zeros((n_mets, 90), dtype=np.uint8), + dims=["met", "spin_bin"], + ), + "esa_step": xr.DataArray( + np.tile(np.arange(1, 11), 1)[:n_mets].astype(np.uint8), + dims=["met"], + ), + }, + coords={ + "met": met_values, + "spin_bin": np.arange(90), + }, + attrs={"sensor": "45sensor", "pointing": 1}, + ) + return ds + + def _create_l1b_de_for_filter2( + self, + n_packets: int = 10, + events_per_packet: int = 20, + base_met: float = 1000.0, + esa_step: int = 1, + ) -> xr.Dataset: + """Create L1B DE dataset for filter 2 testing. + + Creates a dataset with proper epoch and event_met dimensions: + - epoch: packet-level variables (ccsds_met, esa_step) + - event_met: event-level variables (ccsds_index, event_met, etc.) + """ + n_events = n_packets * events_per_packet + + # Spread events across packets + ccsds_index = np.repeat(np.arange(n_packets), events_per_packet).astype( + np.uint16 + ) + + # Packet-level METs (120 seconds apart) + packet_mets = np.arange(base_met, base_met + n_packets * 120, 120) + + # Default: events spread out in time within each packet (no clusters) + # Each packet spans ~120 seconds, events spread across that time + event_met_values = np.zeros(n_events, dtype=np.float64) + for i in range(n_packets): + start_idx = i * events_per_packet + end_idx = start_idx + events_per_packet + # Events spread 0-100 seconds within each packet + event_met_values[start_idx:end_idx] = packet_mets[i] + np.linspace( + 0, 100, events_per_packet + ) + + # All events are qualified type 12 + coincidence_type = np.full(n_events, 12, dtype=np.uint8) + + # Spread events across spin bins + nominal_bin = np.tile( + np.linspace(0, 89, events_per_packet).astype(np.uint8), n_packets + ) + + # All packets at same ESA step (single 8-spin set) + packet_esa_steps = np.full(n_packets, esa_step, dtype=np.uint8) + + return xr.Dataset( + { + # Packet-level variables (epoch dimension) + "ccsds_met": (["epoch"], packet_mets), + "esa_step": (["epoch"], packet_esa_steps), + # Event-level variables (event dimension) + "ccsds_index": (["event_met"], ccsds_index), + "coincidence_type": (["event_met"], coincidence_type), + "nominal_bin": (["even_met"], nominal_bin), + }, + coords={ + "epoch": np.arange(n_packets), + "event_met": event_met_values, + }, + ) + + def test_no_qualified_events(self, goodtimes_for_filter2): + """Test with no qualified events.""" + l1b_de = self._create_l1b_de_for_filter2() + # Change all events to unqualified type + l1b_de["coincidence_type"] = xr.DataArray( + np.full(len(l1b_de["event_met"]), 4, dtype=np.uint8), + dims=["event_met"], + ) + + # Add qualified mask directly to dataset - no events match type 12 + l1b_de["qualified_mask"] = xr.DataArray( + np.isin(l1b_de["coincidence_type"].values, [12]), + dims=["event_met"], + ) + + mark_statistical_filter_2( + goodtimes_for_filter2, + l1b_de, + min_events=6, + max_time_delta=10.0, + ) + + # No bins should be marked + assert np.all(goodtimes_for_filter2["cull_flags"].values == 0) + + def test_no_clusters(self, goodtimes_for_filter2): + """Test with qualified events but no clusters.""" + # Create l1b_de with different esa_steps per packet + # This ensures events are in different 8-spin sets and don't get pooled + n_packets = 10 + events_per_packet = 20 + n_events = n_packets * events_per_packet + base_met = 1000.0 + + ccsds_index = np.repeat(np.arange(n_packets), events_per_packet).astype( + np.uint16 + ) + # Events spread out in time within each packet (no clusters) + # Events at 0, 5, 10, ... 95 seconds - more than 0.2s apart + packet_mets = np.arange(base_met, base_met + n_packets * 120, 120) + event_met_values = np.zeros(n_events, dtype=np.float64) + for i in range(n_packets): + start_idx = i * events_per_packet + end_idx = start_idx + events_per_packet + event_met_values[start_idx:end_idx] = packet_mets[i] + np.linspace( + 0, 95, events_per_packet + ) + coincidence_type = np.full(n_events, 12, dtype=np.uint8) + nominal_bin = np.tile( + np.linspace(0, 89, events_per_packet).astype(np.uint8), n_packets + ) + # Each packet has a different esa_step (different 8-spin sets) + packet_esa_steps = np.arange(1, n_packets + 1, dtype=np.uint8) + + l1b_de = xr.Dataset( + { + "ccsds_met": (["epoch"], packet_mets), + "esa_step": (["epoch"], packet_esa_steps), + "ccsds_index": (["event_met"], ccsds_index), + "coincidence_type": (["event_met"], coincidence_type), + "nominal_bin": (["event_met"], nominal_bin), + }, + coords={ + "epoch": np.arange(n_packets), + "event_met": event_met_values, + }, + ) + + # Add qualified mask directly to dataset + l1b_de["qualified_mask"] = xr.DataArray( + np.isin(l1b_de["coincidence_type"].values, [12]), + dims=["event_met"], + ) + + mark_statistical_filter_2( + goodtimes_for_filter2, + l1b_de, + min_events=6, + max_time_delta=0.2, + ) + + # Events are spread out within each 8-spin set, no clusters should form + assert np.all(goodtimes_for_filter2["cull_flags"].values == 0) + + def test_cluster_detected(self, goodtimes_for_filter2): + """Test that a cluster is detected and bins are marked.""" + l1b_de = self._create_l1b_de_for_filter2(n_packets=1, events_per_packet=10) + + # Create a cluster: 6 events within 0.1 seconds, all at bins 40-45 + # Events at 0.01, 0.02, ..., 0.06 seconds (cluster) and + # 10, 11, 12, 13 seconds (spread out) + l1b_de["event_met"] = xr.DataArray( + np.array( + [ + 1000.01, + 1000.02, + 1000.03, + 1000.04, + 1000.05, + 1000.06, + 1010.0, + 1011.0, + 1012.0, + 1013.0, + ], + dtype=np.float64, + ), + dims=["event_met"], + ) + l1b_de["nominal_bin"] = xr.DataArray( + np.array([40, 41, 42, 43, 44, 45, 10, 20, 30, 50], dtype=np.uint8), + dims=["event_met"], + ) + + # Add qualified mask directly to dataset + l1b_de["qualified_mask"] = xr.DataArray( + np.isin(l1b_de["coincidence_type"].values, [12]), + dims=["event_met"], + ) + + mark_statistical_filter_2( + goodtimes_for_filter2, + l1b_de, + min_events=6, + max_time_delta=0.1, + bin_padding=1, + ) + + # Bins 39-46 should be marked for MET 1000.0 (first MET) + cull_flags = goodtimes_for_filter2["cull_flags"].sel(met=1000.0).values + assert np.all(cull_flags[39:47] == CullCode.STAT_FILTER_2) + # Other bins should be unmarked + assert np.all(cull_flags[:39] == 0) + assert np.all(cull_flags[47:] == 0) + + def test_multiple_clusters_same_packet(self, goodtimes_for_filter2): + """Test detection of multiple clusters in the same packet.""" + l1b_de = self._create_l1b_de_for_filter2(n_packets=1, events_per_packet=12) + + # Two clusters: one at 0.01-0.06s (bins 10-15), one at 10.0-10.05s (bins 70-75) + l1b_de["event_met"] = xr.DataArray( + np.array( + [ + 1000.01, + 1000.02, + 1000.03, + 1000.04, + 1000.05, + 1000.06, + 1010.00, + 1010.01, + 1010.02, + 1010.03, + 1010.04, + 1010.05, + ], + dtype=np.float64, + ), + dims=["event_met"], + ) + l1b_de["nominal_bin"] = xr.DataArray( + np.array([10, 11, 12, 13, 14, 15, 70, 71, 72, 73, 74, 75], dtype=np.uint8), + dims=["event_met"], + ) + + # Add qualified mask directly to dataset + l1b_de["qualified_mask"] = xr.DataArray( + np.isin(l1b_de["coincidence_type"].values, [12]), + dims=["event_met"], + ) + + mark_statistical_filter_2( + goodtimes_for_filter2, + l1b_de, + min_events=6, + max_time_delta=0.1, + bin_padding=1, + ) + + cull_flags = goodtimes_for_filter2["cull_flags"].sel(met=1000.0).values + # First cluster: bins 9-16 + assert np.all(cull_flags[9:17] == CullCode.STAT_FILTER_2) + # Second cluster: bins 69-76 + assert np.all(cull_flags[69:77] == CullCode.STAT_FILTER_2) + # Middle bins should be unmarked + assert np.all(cull_flags[17:69] == 0) + + def test_bin_padding_with_wrapping(self, goodtimes_for_filter2): + """Test that bin padding wraps at array boundaries.""" + l1b_de = self._create_l1b_de_for_filter2(n_packets=1, events_per_packet=6) + + # Cluster at bins 0-2 with padding=2: bins -2 to 4 wrap to + # [88, 89, 0, 1, 2, 3, 4] + # 6 events clustered within 0.1 seconds + l1b_de["event_met"] = xr.DataArray( + np.array( + [1000.01, 1000.02, 1000.03, 1000.04, 1000.05, 1000.06], dtype=np.float64 + ), + dims=["event_met"], + ) + l1b_de["nominal_bin"] = xr.DataArray( + np.array([0, 0, 1, 1, 2, 2], dtype=np.uint8), + dims=["event_met"], + ) + + # Add qualified mask directly to dataset + l1b_de["qualified_mask"] = xr.DataArray( + np.isin(l1b_de["coincidence_type"].values, [12]), + dims=["event_met"], + ) + + mark_statistical_filter_2( + goodtimes_for_filter2, + l1b_de, + min_events=6, + max_time_delta=0.1, + bin_padding=2, + ) + + cull_flags = goodtimes_for_filter2["cull_flags"].sel(met=1000.0).values + # Bins 0-4 should be marked (cluster at 0-2 + padding of 2) + assert np.all(cull_flags[0:5] == CullCode.STAT_FILTER_2) + # Bins 88-89 should also be marked due to wrapping (bin -2 and -1) + assert np.all(cull_flags[88:90] == CullCode.STAT_FILTER_2) + # Middle bins should be unmarked + assert np.all(cull_flags[5:88] == 0) + # Check that no cull_flags were set on any other METs + other_mets = goodtimes_for_filter2["cull_flags"].drop_sel(met=1000.0) + assert np.all(other_mets.values == 0) + + def test_custom_parameters(self, goodtimes_for_filter2): + """Test with custom min_events and max_time_delta.""" + l1b_de = self._create_l1b_de_for_filter2(n_packets=1, events_per_packet=10) + + # Create events: 4 close together (not enough for default min_events=6) + # First 4 events at 0.01-0.04s (cluster), rest spread out + l1b_de["event_met"] = xr.DataArray( + np.array( + [ + 1000.01, + 1000.02, + 1000.03, + 1000.04, + 1010.0, + 1011.0, + 1012.0, + 1013.0, + 1014.0, + 1015.0, + ], + dtype=np.float64, + ), + dims=["event_met"], + ) + l1b_de["nominal_bin"] = xr.DataArray( + np.array([40, 41, 42, 43, 10, 20, 30, 50, 60, 70], dtype=np.uint8), + dims=["event_met"], + ) + + # Add qualified mask directly to dataset + l1b_de["qualified_mask"] = xr.DataArray( + np.isin(l1b_de["coincidence_type"].values, [12]), + dims=["event_met"], + ) + + # With min_events=4, should detect cluster + mark_statistical_filter_2( + goodtimes_for_filter2, + l1b_de, + min_events=4, + max_time_delta=0.1, + bin_padding=1, + ) + + cull_flags = goodtimes_for_filter2["cull_flags"].sel(met=1000.0).values + assert np.all(cull_flags[39:45] == CullCode.STAT_FILTER_2) + + def test_only_qualified_events_contribute_to_clusters(self, goodtimes_for_filter2): + """Test that only qualified events are used for cluster detection. + + This test verifies the filtering behavior by creating a scenario where: + - Unqualified events (type 4) form a cluster if incorrectly included + - Qualified events (type 12) are spread out and don't form a cluster + - No cluster should be detected because only qualified events should be used + """ + n_events = 12 + # Create base dataset structure with correct event_met dimension + event_met_values = np.array( + [ + # 6 unqualified events clustered together + 1000.01, + 1000.02, + 1000.03, + 1000.04, + 1000.05, + 1000.06, + # 6 qualified events spread out (no cluster) + 1010.0, + 1020.0, + 1030.0, + 1040.0, + 1050.0, + 1060.0, + ], + dtype=np.float64, + ) + + # First 6 events are unqualified (type 4), last 6 are qualified (type 12) + coincidence_type = np.array( + [4, 4, 4, 4, 4, 4, 12, 12, 12, 12, 12, 12], dtype=np.uint8 + ) + + # All events at similar bins (so cluster would be detected if all included) + nominal_bin = np.array( + [40, 41, 42, 43, 44, 45, 40, 41, 42, 43, 44, 45], dtype=np.uint8 + ) + + # Create ccsds_index - all events in same packet + ccsds_index = np.zeros(n_events, dtype=np.uint16) + + l1b_de = xr.Dataset( + { + "ccsds_index": (["event_met"], ccsds_index), + "coincidence_type": (["event_met"], coincidence_type), + "nominal_bin": (["event_met"], nominal_bin), + "ccsds_met": (["epoch"], np.array([1000.0])), + "esa_step": (["epoch"], np.array([1], dtype=np.uint8)), + }, + coords={ + "event_met": event_met_values, + "epoch": np.arange(1), + }, + ) + + # Add qualified mask directly to dataset - only type 12 events are qualified + qualified_mask = np.isin(l1b_de["coincidence_type"].values, [12]) + l1b_de["qualified_mask"] = xr.DataArray(qualified_mask, dims=["event_met"]) + + # Verify our test setup: 6 unqualified, 6 qualified + assert np.sum(~qualified_mask) == 6 # 6 unqualified + assert np.sum(qualified_mask) == 6 # 6 qualified + + mark_statistical_filter_2( + goodtimes_for_filter2, + l1b_de, + min_events=6, + max_time_delta=0.1, + bin_padding=1, + ) + + # No bins should be marked because: + # - The 6 unqualified events form a cluster but should be filtered out + # - The 6 qualified events are spread out and don't form a cluster + cull_flags = goodtimes_for_filter2["cull_flags"].sel(met=1000.0).values + assert np.all(cull_flags == 0), ( + "Bins were incorrectly marked - unqualified events may have been " + "included in cluster detection" + ) + + +class TestFindCurrentPointingIndex: + """Test suite for _find_current_pointing_index helper function.""" + + def test_finds_current_index(self): + """Test that current index is found correctly.""" + ds1 = MagicMock() + ds1.attrs = {"Repointing": "repoint00001"} + ds2 = MagicMock() + ds2.attrs = {"Repointing": "repoint00002"} + ds3 = MagicMock() + ds3.attrs = {"Repointing": "repoint00003"} + + datasets = [ds1, ds2, ds3] + current_index = _find_current_pointing_index(datasets, "repoint00002") + + assert current_index == 1 + + def test_finds_first_matching_repointing(self): + """Test that the first matching repointing is returned.""" + ds1 = MagicMock() + ds1.attrs = {"Repointing": "repoint00005"} + ds2 = MagicMock() + ds2.attrs = {"Repointing": "repoint00005"} + + datasets = [ds1, ds2] + current_index = _find_current_pointing_index(datasets, "repoint00005") + + assert current_index == 0 + + def test_raises_when_repointing_not_found(self): + """Test that ValueError is raised when repointing not found.""" + ds1 = MagicMock() + ds1.attrs = {"Repointing": "repoint00001"} + ds2 = MagicMock() + ds2.attrs = {"Repointing": "repoint00002"} + + datasets = [ds1, ds2] + with pytest.raises(ValueError, match="Could not find current repointing"): + _find_current_pointing_index(datasets, "repoint00099") + + +class TestApplyGoodtimesFilters: + """Test suite for _apply_goodtimes_filters helper function.""" + + def test_loads_cal_config(self, tmp_path): + """Test that cal config is loaded.""" + mock_goodtimes = MagicMock() + mock_goodtimes.goodtimes.get_cull_statistics.return_value = { + "good_bins": 100, + "total_bins": 100, + } + mock_l1b_de = MagicMock() + mock_hk = MagicMock() + mock_cal = {"coincidence_type_values": [{12}]} + + cal_path = tmp_path / "cal.csv" + + with ( + patch( + "imap_processing.hi.utils.CalibrationProductConfig.from_csv" + ) as mock_cal_load, + patch("imap_processing.hi.hi_goodtimes.mark_bad_esa_voltage"), + patch("imap_processing.hi.hi_goodtimes.mark_incomplete_spin_sets"), + patch("imap_processing.hi.hi_goodtimes.mark_drf_times"), + patch("imap_processing.hi.hi_goodtimes.mark_overflow_packets"), + patch("imap_processing.hi.hi_goodtimes.mark_bad_tdc_cal"), + patch("imap_processing.hi.hi_goodtimes.mark_statistical_filter_0"), + patch("imap_processing.hi.hi_goodtimes.mark_statistical_filter_1"), + patch("imap_processing.hi.hi_goodtimes.mark_statistical_filter_2"), + ): + mock_cal_load.return_value = mock_cal + + _apply_goodtimes_filters( + mock_goodtimes, + [mock_l1b_de], + current_index=0, + l1b_hk=mock_hk, + l1a_diagfee=MagicMock(), + cal_product_config_path=cal_path, + ) + + mock_cal_load.assert_called_once_with(cal_path) + + def test_calls_all_filters(self, tmp_path): + """Test that all 8 filters are called.""" + mock_goodtimes = MagicMock() + mock_goodtimes.goodtimes.get_cull_statistics.return_value = { + "good_bins": 100, + "total_bins": 100, + } + mock_l1b_de = MagicMock() + mock_hk = MagicMock() + mock_cal = {"coincidence_type_values": [{12}]} + + with ( + patch( + "imap_processing.hi.utils.CalibrationProductConfig.from_csv", + return_value=mock_cal, + ), + patch("imap_processing.hi.hi_goodtimes.mark_bad_esa_voltage") as mock_f0, + patch( + "imap_processing.hi.hi_goodtimes.mark_incomplete_spin_sets" + ) as mock_f1, + patch("imap_processing.hi.hi_goodtimes.mark_drf_times") as mock_f2, + patch("imap_processing.hi.hi_goodtimes.mark_bad_tdc_cal") as mock_f3, + patch("imap_processing.hi.hi_goodtimes.mark_overflow_packets") as mock_f4, + patch( + "imap_processing.hi.hi_goodtimes.mark_statistical_filter_0" + ) as mock_f5, + patch( + "imap_processing.hi.hi_goodtimes.mark_statistical_filter_1" + ) as mock_f6, + patch( + "imap_processing.hi.hi_goodtimes.mark_statistical_filter_2" + ) as mock_f7, + ): + _apply_goodtimes_filters( + mock_goodtimes, + [mock_l1b_de], + current_index=0, + l1b_hk=mock_hk, + l1a_diagfee=MagicMock(), + cal_product_config_path=tmp_path / "cal.csv", + ) + + mock_f0.assert_called_once() + mock_f1.assert_called_once() + mock_f2.assert_called_once() + mock_f3.assert_called_once() + mock_f4.assert_called_once() + mock_f5.assert_called_once() + mock_f6.assert_called_once() + mock_f7.assert_called_once() + + def test_raises_statistical_filter_0_errors(self, tmp_path): + """Test that ValueError from statistical filter 0 is raised.""" + mock_goodtimes = MagicMock() + mock_goodtimes.goodtimes.get_cull_statistics.return_value = { + "good_bins": 100, + "total_bins": 100, + } + mock_l1b_de = MagicMock() + mock_hk = MagicMock() + mock_cal = {"coincidence_type_values": [{12}]} + + with ( + patch( + "imap_processing.hi.utils.CalibrationProductConfig.from_csv", + return_value=mock_cal, + ), + patch("imap_processing.hi.hi_goodtimes.mark_bad_esa_voltage"), + patch("imap_processing.hi.hi_goodtimes.mark_incomplete_spin_sets"), + patch("imap_processing.hi.hi_goodtimes.mark_drf_times"), + patch("imap_processing.hi.hi_goodtimes.mark_bad_tdc_cal"), + patch("imap_processing.hi.hi_goodtimes.mark_overflow_packets"), + patch( + "imap_processing.hi.hi_goodtimes.mark_statistical_filter_0", + side_effect=ValueError("filter 0 error"), + ), + ): + with pytest.raises(ValueError, match="filter 0 error"): + _apply_goodtimes_filters( + mock_goodtimes, + [mock_l1b_de], + current_index=0, + l1b_hk=mock_hk, + l1a_diagfee=MagicMock(), + cal_product_config_path=tmp_path / "cal.csv", + ) + + def test_raises_statistical_filter_1_errors(self, tmp_path): + """Test that ValueError from statistical filter 1 is raised.""" + mock_goodtimes = MagicMock() + mock_goodtimes.goodtimes.get_cull_statistics.return_value = { + "good_bins": 100, + "total_bins": 100, + } + mock_l1b_de = MagicMock() + mock_hk = MagicMock() + mock_cal = {"coincidence_type_values": [{12}]} + + with ( + patch( + "imap_processing.hi.utils.CalibrationProductConfig.from_csv", + return_value=mock_cal, + ), + patch("imap_processing.hi.hi_goodtimes.mark_bad_esa_voltage"), + patch("imap_processing.hi.hi_goodtimes.mark_incomplete_spin_sets"), + patch("imap_processing.hi.hi_goodtimes.mark_drf_times"), + patch("imap_processing.hi.hi_goodtimes.mark_bad_tdc_cal"), + patch("imap_processing.hi.hi_goodtimes.mark_overflow_packets"), + patch("imap_processing.hi.hi_goodtimes.mark_statistical_filter_0"), + patch( + "imap_processing.hi.hi_goodtimes.mark_statistical_filter_1", + side_effect=ValueError("filter 1 error"), + ), + ): + with pytest.raises(ValueError, match="filter 1 error"): + _apply_goodtimes_filters( + mock_goodtimes, + [mock_l1b_de], + current_index=0, + l1b_hk=mock_hk, + l1a_diagfee=MagicMock(), + cal_product_config_path=tmp_path / "cal.csv", + ) + + +class TestHiGoodtimes: + """Test suite for hi_goodtimes top-level function.""" + + def test_raises_value_error_when_repoint_not_complete(self, tmp_path): + """Test that ValueError is raised when repoint+3 has not occurred.""" + mock_repoint_df = pd.DataFrame( + { + "repoint_id": [1, 2, 3], + } + ) + mock_de = MagicMock() + mock_hk = MagicMock() + + with patch( + "imap_processing.hi.hi_goodtimes.get_repoint_data" + ) as mock_get_repoint: + mock_get_repoint.return_value = mock_repoint_df + with pytest.raises( + ValueError, match="Goodtimes cannot yet be processed for repoint00001" + ): + _ = hi_goodtimes( + current_repointing="repoint00001", + l1b_de_datasets=[mock_de], + l1b_hk=mock_hk, + l1a_diagfee=MagicMock(), + cal_product_config_path=tmp_path / "cal.csv", + ) + + def test_calls_find_current_index_when_repoint_complete(self, tmp_path): + """Test that _find_current_pointing_index is called when repoint passes.""" + mock_repoint_df = pd.DataFrame({"repoint_id": list(range(1, 10))}) + mock_goodtimes = MagicMock() + mock_goodtimes.attrs = {"sensor": "45sensor"} + mock_goodtimes.__getitem__ = MagicMock() + # Mock the goodtimes accessor methods + mock_goodtimes.goodtimes.get_cull_statistics.return_value = { + "total_bins": 100, + "good_bins": 80, + "culled_bins": 20, + "fraction_good": 0.8, + "cull_code_counts": {}, + } + mock_goodtimes.goodtimes.finalize_dataset.return_value = MagicMock() + mock_datasets = [MagicMock() for _ in range(7)] + mock_hk = MagicMock() + + with ( + patch( + "imap_processing.hi.hi_goodtimes.get_repoint_data", + return_value=mock_repoint_df, + ), + patch( + "imap_processing.hi.hi_goodtimes._find_current_pointing_index", + return_value=3, + ) as mock_find, + patch( + "imap_processing.hi.hi_goodtimes.create_goodtimes_dataset", + return_value=mock_goodtimes, + ), + patch("imap_processing.hi.hi_goodtimes._apply_goodtimes_filters"), + ): + hi_goodtimes( + current_repointing="repoint00004", + l1b_de_datasets=mock_datasets, + l1b_hk=mock_hk, + l1a_diagfee=MagicMock(), + cal_product_config_path=tmp_path / "cal.csv", + ) + + mock_find.assert_called_once_with(mock_datasets, "repoint00004") + + def test_marks_all_bad_when_incomplete_de_set(self, tmp_path): + """Test that cull_flags are set when DE set is incomplete.""" + mock_repoint_df = pd.DataFrame({"repoint_id": list(range(1, 10))}) + mock_goodtimes = MagicMock() + mock_goodtimes.attrs = {"sensor": "45sensor"} + mock_cull_flags = MagicMock() + mock_goodtimes.__getitem__ = MagicMock(return_value=mock_cull_flags) + # Mock the goodtimes accessor methods + mock_goodtimes.goodtimes.get_cull_statistics.return_value = { + "total_bins": 100, + "good_bins": 0, + "culled_bins": 100, + "fraction_good": 0.0, + "cull_code_counts": {1: 100}, + } + mock_goodtimes.goodtimes.finalize_dataset.return_value = MagicMock() + mock_datasets = [MagicMock() for _ in range(3)] # Less than 7 + mock_hk = MagicMock() + + with ( + patch( + "imap_processing.hi.hi_goodtimes.get_repoint_data", + return_value=mock_repoint_df, + ), + patch( + "imap_processing.hi.hi_goodtimes._find_current_pointing_index", + return_value=0, + ), + patch( + "imap_processing.hi.hi_goodtimes.create_goodtimes_dataset", + return_value=mock_goodtimes, + ), + ): + hi_goodtimes( + current_repointing="repoint00001", + l1b_de_datasets=mock_datasets, + l1b_hk=mock_hk, + l1a_diagfee=MagicMock(), + cal_product_config_path=tmp_path / "cal.csv", + ) + + # Verify cull_flags were set to LOOSE (all bad) + mock_goodtimes.__getitem__.assert_called_with("cull_flags") + + def test_calls_apply_filters_when_full_de_set(self, tmp_path): + """Test that _apply_goodtimes_filters is called with 7 DE datasets.""" + mock_repoint_df = pd.DataFrame({"repoint_id": list(range(1, 10))}) + mock_goodtimes = MagicMock() + mock_goodtimes.attrs = {"sensor": "45sensor"} + # Mock the goodtimes accessor methods + mock_goodtimes.goodtimes.get_cull_statistics.return_value = { + "total_bins": 100, + "good_bins": 80, + "culled_bins": 20, + "fraction_good": 0.8, + "cull_code_counts": {}, + } + mock_goodtimes.goodtimes.finalize_dataset.return_value = MagicMock() + mock_datasets = [MagicMock() for _ in range(7)] + mock_hk = MagicMock() + + with ( + patch( + "imap_processing.hi.hi_goodtimes.get_repoint_data", + return_value=mock_repoint_df, + ), + patch( + "imap_processing.hi.hi_goodtimes._find_current_pointing_index", + return_value=3, + ), + patch( + "imap_processing.hi.hi_goodtimes.create_goodtimes_dataset", + return_value=mock_goodtimes, + ), + patch( + "imap_processing.hi.hi_goodtimes._apply_goodtimes_filters" + ) as mock_apply, + ): + hi_goodtimes( + current_repointing="repoint00004", + l1b_de_datasets=mock_datasets, + l1b_hk=mock_hk, + l1a_diagfee=MagicMock(), + cal_product_config_path=tmp_path / "cal.csv", + ) + + mock_apply.assert_called_once() + + def test_returns_datasets(self, tmp_path): + """Test that hi_goodtimes returns list of datasets.""" + mock_repoint_df = pd.DataFrame({"repoint_id": list(range(1, 10))}) + mock_goodtimes = MagicMock() + mock_goodtimes.attrs = {"sensor": "45sensor"} + # Mock the goodtimes accessor methods + mock_goodtimes.goodtimes.get_cull_statistics.return_value = { + "total_bins": 100, + "good_bins": 80, + "culled_bins": 20, + "fraction_good": 0.8, + "cull_code_counts": {}, + } + mock_finalized = MagicMock() + mock_goodtimes.goodtimes.finalize_dataset.return_value = mock_finalized + mock_datasets = [MagicMock() for _ in range(7)] + mock_hk = MagicMock() + + with ( + patch( + "imap_processing.hi.hi_goodtimes.get_repoint_data", + return_value=mock_repoint_df, + ), + patch( + "imap_processing.hi.hi_goodtimes._find_current_pointing_index", + return_value=3, + ), + patch( + "imap_processing.hi.hi_goodtimes.create_goodtimes_dataset", + return_value=mock_goodtimes, + ), + patch("imap_processing.hi.hi_goodtimes._apply_goodtimes_filters"), + ): + result = hi_goodtimes( + current_repointing="repoint00004", + l1b_de_datasets=mock_datasets, + l1b_hk=mock_hk, + l1a_diagfee=MagicMock(), + cal_product_config_path=tmp_path / "cal.csv", + ) + + # Should return finalized dataset, not original + assert result == [mock_finalized] + + +class TestMarkBadEsaVoltage: + """Tests for mark_bad_esa_voltage culling function.""" + + @pytest.fixture + def goodtimes_for_esa(self): + """Create a goodtimes dataset for ESA voltage testing.""" + # METs at 50-second intervals + met_values = np.array([1000.0, 1050.0, 1100.0, 1150.0, 1200.0]) + return xr.Dataset( + { + "cull_flags": xr.DataArray( + np.zeros((5, 90), dtype=np.uint8), + dims=["met", "spin_bin"], + ), + "esa_step": xr.DataArray(np.array([1, 2, 3, 4, 5]), dims=["met"]), + }, + coords={ + "met": met_values, + "spin_bin": np.arange(90), + }, + ) + + @pytest.fixture + def l1b_de_all_valid(self): + """L1B DE with all valid esa_energy_step values.""" + return xr.Dataset( + { + "esa_step_met": (["epoch"], np.array([1000, 1050, 1100, 1150, 1200])), + "esa_energy_step": (["epoch"], np.array([1, 2, 3, 4, 5])), # All valid + } + ) + + @pytest.fixture + def l1b_de_with_zero(self): + """L1B DE with esa_energy_step=0 (calibration).""" + ds = xr.Dataset( + { + "esa_step_met": (["epoch"], np.array([1000, 1050, 1100, 1150, 1200])), + "esa_energy_step": (["epoch"], np.array([1, 0, 3, 4, 5])), # 0 at idx 1 + } + ) + ds["esa_energy_step"].attrs["FILLVAL"] = 255 + return ds + + @pytest.fixture + def l1b_de_with_fillval(self): + """L1B DE with esa_energy_step=FILLVAL (voltage mismatch).""" + ds = xr.Dataset( + { + "esa_step_met": (["epoch"], np.array([1000, 1050, 1100, 1150, 1200])), + "esa_energy_step": ( + ["epoch"], + np.array([1, 2, 255, 4, 5]), + ), # FILLVAL at idx 2 + } + ) + ds["esa_energy_step"].attrs["FILLVAL"] = 255 + return ds + + def test_mark_bad_esa_voltage_all_valid(self, goodtimes_for_esa, l1b_de_all_valid): + """Test that no times are marked when all ESA energy steps are valid.""" + mark_bad_esa_voltage(goodtimes_for_esa, l1b_de_all_valid) + assert np.all(goodtimes_for_esa["cull_flags"].values == CullCode.GOOD) + + def test_mark_bad_esa_voltage_with_zero(self, goodtimes_for_esa, l1b_de_with_zero): + """Test that times are marked when esa_energy_step=0 (calibration).""" + mark_bad_esa_voltage(goodtimes_for_esa, l1b_de_with_zero) + + # MET 1050 (index 1) should be culled + assert np.all( + goodtimes_for_esa["cull_flags"].values[1, :] == CullCode.BAD_ESA_VOLTAGE + ) + # Other times should remain good + assert np.all(goodtimes_for_esa["cull_flags"].values[0, :] == CullCode.GOOD) + assert np.all(goodtimes_for_esa["cull_flags"].values[2, :] == CullCode.GOOD) + + def test_mark_bad_esa_voltage_with_fillval( + self, goodtimes_for_esa, l1b_de_with_fillval + ): + """Test that times are marked when esa_energy_step=FILLVAL.""" + mark_bad_esa_voltage(goodtimes_for_esa, l1b_de_with_fillval) + + # MET 1100 (index 2) should be culled + assert np.all( + goodtimes_for_esa["cull_flags"].values[2, :] == CullCode.BAD_ESA_VOLTAGE + ) + # Other times should remain good + assert np.all(goodtimes_for_esa["cull_flags"].values[0, :] == CullCode.GOOD) + assert np.all(goodtimes_for_esa["cull_flags"].values[1, :] == CullCode.GOOD) + + def test_mark_bad_esa_voltage_custom_cull_code( + self, goodtimes_for_esa, l1b_de_with_zero + ): + """Test using a custom cull code.""" + custom_code = 200 + mark_bad_esa_voltage(goodtimes_for_esa, l1b_de_with_zero, cull_code=custom_code) + assert np.all(goodtimes_for_esa["cull_flags"].values[1, :] == custom_code) diff --git a/imap_processing/tests/hi/test_l1a.py b/imap_processing/tests/hi/test_hi_l1a.py similarity index 80% rename from imap_processing/tests/hi/test_l1a.py rename to imap_processing/tests/hi/test_hi_l1a.py index cfe2e605c5..d86f649a01 100644 --- a/imap_processing/tests/hi/test_l1a.py +++ b/imap_processing/tests/hi/test_hi_l1a.py @@ -1,5 +1,6 @@ import numpy as np import pandas as pd +from cdflib.xarray import xarray_to_cdf from imap_processing.cdf.utils import write_cdf from imap_processing.hi.hi_l1a import ( @@ -37,6 +38,34 @@ def test_sci_de_decom(hi_l0_test_data_path): assert cdf_filepath.name == cdf_filename +def test_create_de_dataset_no_events(tmp_path): + """Test that a DE dataset with no events correctly generates a CDF.""" + # Generate a fake de_data_dict with no events + keys_with_data = [ + "ccsds_met", + "src_seq_ctr", + "pkt_len", + "last_spin_num", + "spin_invalids", + "esa_step", + "esa_step_seconds", + "esa_step_milliseconds", + ] + de_data_dict = {k: np.arange(10) for k in keys_with_data} + empty_keys = ["de_tag", "trigger_id", "tof_1", "tof_2", "tof_3", "ccsds_index"] + for k in empty_keys: + de_data_dict[k] = [] + + ds = create_de_dataset(de_data_dict) + for k in empty_keys: + assert len(ds[k].data) == 1 + + # Just need to make sure that a cdf file gets written with compression on + out_path = tmp_path / "de.cdf" + xarray_to_cdf(ds, str(out_path), compression=6) + assert out_path.exists() + + def test_diag_fee_decom(hi_l0_test_data_path): """Test diag_fee data""" bin_data_path = hi_l0_test_data_path / "H45_diag_fee_20250208.bin" @@ -117,6 +146,29 @@ def test_memdmp_decom(hi_l0_test_data_path): ) +def test_validate_memdmp(hi_l0_test_data_path): + """Validate parsing of memdmp data against csv from Paul.""" + bin_data_path = hi_l0_test_data_path / "H90_MEMDMP-2025-07-09.bin" + memdmp_ds = hi_l1a(packet_file_path=bin_data_path)[0] + + def hex_convertor(hex_value): + """Define a converter function for hex values.""" + return int(hex_value, 16) + + validation_df = pd.read_csv( + hi_l0_test_data_path / "H90_MEMDMP-2025-07-09.csv", + header=0, + index_col=False, + converters={"memory_id": hex_convertor, "start_address": hex_convertor}, + ) + for col_name, series in validation_df.items(): + np.testing.assert_array_equal( + memdmp_ds[col_name].data, + series.values, + err_msg=f"Validation of {col_name} failed", + ) + + def test_unpack_hist_counter(): """Test hi.l1a.histogram.unpack_hist_counter()""" # To ensure correct unpacking, use expected values with ones in the upper diff --git a/imap_processing/tests/hi/test_hi_l1b.py b/imap_processing/tests/hi/test_hi_l1b.py index 26099601ce..91de0a9cbb 100644 --- a/imap_processing/tests/hi/test_hi_l1b.py +++ b/imap_processing/tests/hi/test_hi_l1b.py @@ -10,9 +10,12 @@ from imap_processing.cdf.utils import load_cdf from imap_processing.hi.hi_l1b import ( annotate_direct_events, + any_good_direct_events, compute_coincidence_type_and_tofs, compute_hae_coordinates, + de_ccsds_qf, de_esa_energy_step, + de_esa_step_met, de_nominal_bin_and_spin_phase, get_esa_to_esa_energy_step_lut, housekeeping, @@ -22,6 +25,7 @@ EsaEnergyStepLookupTable, HiConstants, ) +from imap_processing.quality_flags import ImapHiL1bDeFlags from imap_processing.spice.geometry import SpiceFrame @@ -65,7 +69,23 @@ def test_hi_annotate_direct_events( l1b_datasets = annotate_direct_events(l1a_dataset, xr.Dataset(), esa_energies_csv) assert len(l1b_datasets) == 1 assert l1b_datasets[0].attrs["Logical_source"] == "imap_hi_l1b_45sensor-de" - assert len(l1b_datasets[0].data_vars) == 15 + assert len(l1b_datasets[0].data_vars) == 18 + + +@pytest.mark.parametrize( + "trigger_id_data, fillval, expected_result", + [([0], 0, False), ([15, 15], 15, False), ([1], 0, True), ([1, 2, 3], 65536, True)], +) +def test_any_good_direct_events(trigger_id_data, fillval, expected_result): + """Test coverage for any_good_direct_events()""" + ds = xr.Dataset( + data_vars={ + "trigger_id": xr.DataArray( + trigger_id_data, name="trigger_id", attrs={"FILLVAL": fillval} + ) + } + ) + assert any_good_direct_events(ds) == expected_result @pytest.mark.external_test_data @@ -111,7 +131,10 @@ def test_annotate_direct_events_with_hk( l1b_datasets = annotate_direct_events(l1a_dataset, hk_dataset, esa_energies_csv) assert len(l1b_datasets) == 1 assert l1b_datasets[0].attrs["Logical_source"] == "imap_hi_l1b_90sensor-de" - assert len(l1b_datasets[0].data_vars) == 15 + assert len(l1b_datasets[0].data_vars) == 18 + # Verify new L1B variables exist + assert "esa_step_met" in l1b_datasets[0].data_vars + assert "ccsds_qf" in l1b_datasets[0].data_vars @pytest.fixture @@ -171,7 +194,10 @@ def synthetic_trigger_id_and_tof_data(): return synthetic_l1a_ds, expected_histogram -def test_compute_coincidence_type_and_time_deltas(synthetic_trigger_id_and_tof_data): +@mock.patch("imap_processing.hi.hi_l1b.any_good_direct_events", return_value=True) +def test_compute_coincidence_type_and_time_deltas( + mock_any_good_de, synthetic_trigger_id_and_tof_data +): """Test coverage for `imap_processing.hi.hi_l1b.compute_coincidence_type_and_time_deltas`.""" new_vars = compute_coincidence_type_and_tofs(synthetic_trigger_id_and_tof_data[0]) @@ -218,11 +244,15 @@ def test_compute_coincidence_type_and_time_deltas(synthetic_trigger_id_and_tof_d ) +@mock.patch("imap_processing.hi.hi_l1b.any_good_direct_events", return_value=True) @mock.patch("imap_processing.hi.hi_l1b.parse_sensor_number", return_value=90) @mock.patch("imap_processing.hi.hi_l1b.get_instrument_spin_phase") @mock.patch("imap_processing.hi.hi_l1b.get_spacecraft_spin_phase") def test_de_nominal_bin_and_spin_phase( - spacecraft_phase_moc, instrument_phase_mock, parse_sensor_number_mock + spacecraft_phase_moc, + instrument_phase_mock, + parse_sensor_number_mock, + any_good_de_mock, ): """Test coverage for de_nominal_bin_and_spin_phase.""" # set the spacecraft_phase_mock to return an array of values between 0 and 1 @@ -266,8 +296,11 @@ def test_de_nominal_bin_and_spin_phase( @pytest.mark.parametrize("sensor_number", [45, 90]) +@mock.patch("imap_processing.hi.hi_l1b.any_good_direct_events", return_value=True) @mock.patch("imap_processing.hi.hi_l1b.instrument_pointing") -def test_compute_hae_coordinates(mock_instrument_pointing, sensor_number): +def test_compute_hae_coordinates( + mock_instrument_pointing, mock_any_good_de, sensor_number +): """Test coverage for compute_hae_coordinates function.""" # Mock out the instrument_pointing function to avoid needing kernels @@ -302,9 +335,10 @@ def side_effect_func(et, inst_frame: SpiceFrame, to_frame): np.testing.assert_allclose(new_vars["hae_longitude"].values, sensor_number) +@mock.patch("imap_processing.hi.hi_l1b.any_good_direct_events", return_value=True) @mock.patch("imap_processing.hi.hi_l1b.pd.read_csv") @mock.patch("imap_processing.hi.hi_l1b.get_esa_to_esa_energy_step_lut") -def test_de_esa_energy_step(mock_get_esa_lut, mock_read_csv): +def test_de_esa_energy_step(mock_get_esa_lut, mock_read_csv, mock_any_good_de): """Test coverage for de_esa_energy_step function.""" mock_esa_lut = mock.MagicMock(spec=EsaEnergyStepLookupTable()) mock_esa_lut.query.side_effect = lambda a, b: np.arange(len(a))[::-1] % 9 @@ -612,3 +646,220 @@ def test_cal_data(self, hi_l1_test_data_path): # Check the generated lookup table # We expect 1 dataframe entry per esa step in the range [1, 9] np.testing.assert_array_equal(lut.df["esa_step"].values, np.arange(9) + 1) + + +class TestDeEsaStepMet: + """Tests for de_esa_step_met function.""" + + def test_computes_esa_step_met(self): + """Test that esa_step_met calculation from seconds and milliseconds.""" + ds = xr.Dataset( + coords={"epoch": [0, 1, 2], "event_met": [0.0, 1.0]}, + data_vars={ + "esa_step_seconds": ( + ["epoch"], + np.array([100, 200, 300], dtype=np.uint32), + ), + "esa_step_milliseconds": ( + ["epoch"], + np.array([500, 250, 750], dtype=np.uint16), + ), + "trigger_id": xr.DataArray( + [1, 2], dims=["event_met"], attrs={"FILLVAL": 0} + ), + }, + ) + result = de_esa_step_met(ds) + expected = np.array([100.5, 200.25, 300.75]) + np.testing.assert_array_almost_equal(result["esa_step_met"].values, expected) + + +class TestDeCcsdsQf: + """Tests for de_ccsds_qf function.""" + + def test_packet_full_flag_set(self): + """Test that PACKET_FULL flag is set for packets with 664 events.""" + n_packets = 3 + # Create events: packet 0 has 664 events, packet 1 has 100, packet 2 has 664 + ccsds_indices = np.concatenate( + [ + np.zeros(664, dtype=np.uint16), # 664 events for packet 0 + np.ones(100, dtype=np.uint16), # 100 events for packet 1 + np.full(664, 2, dtype=np.uint16), # 664 events for packet 2 + ] + ) + ds = xr.Dataset( + coords={ + "epoch": np.arange(n_packets), + "event_met": np.arange(len(ccsds_indices), dtype=np.float64), + }, + data_vars={ + "ccsds_index": (["event_met"], ccsds_indices), + "trigger_id": xr.DataArray( + np.ones(len(ccsds_indices), dtype=np.uint8), + dims=["event_met"], + attrs={"FILLVAL": 0}, + ), + "spin_invalids": (["epoch"], np.zeros(n_packets, dtype=np.uint8)), + }, + ) + result = de_ccsds_qf(ds) + # Packet 0 and 2 should have PACKET_FULL flag (1), packet 1 should be 0 + assert result["ccsds_qf"].values[0] == ImapHiL1bDeFlags.PACKET_FULL + assert result["ccsds_qf"].values[1] == 0 + assert result["ccsds_qf"].values[2] == ImapHiL1bDeFlags.PACKET_FULL + + def test_no_full_packets(self): + """Test that no flags are set when no packets are full.""" + n_packets = 2 + ccsds_indices = np.concatenate( + [ + np.zeros(100, dtype=np.uint16), + np.ones(200, dtype=np.uint16), + ] + ) + ds = xr.Dataset( + coords={ + "epoch": np.arange(n_packets), + "event_met": np.arange(len(ccsds_indices), dtype=np.float64), + }, + data_vars={ + "ccsds_index": (["event_met"], ccsds_indices), + "trigger_id": xr.DataArray( + np.ones(len(ccsds_indices), dtype=np.uint8), + dims=["event_met"], + attrs={"FILLVAL": 0}, + ), + "spin_invalids": (["epoch"], np.zeros(n_packets, dtype=np.uint8)), + }, + ) + result = de_ccsds_qf(ds) + assert result["ccsds_qf"].values[0] == 0 + assert result["ccsds_qf"].values[1] == 0 + + def test_spin_invalid_flag_set(self): + """Test that BADSPIN flag is set for packets with nonzero spin_invalids.""" + n_packets = 3 + ccsds_indices = np.concatenate( + [ + np.zeros(10, dtype=np.uint16), + np.ones(10, dtype=np.uint16), + np.full(10, 2, dtype=np.uint16), + ] + ) + ds = xr.Dataset( + coords={ + "epoch": np.arange(n_packets), + "event_met": np.arange(len(ccsds_indices), dtype=np.float64), + }, + data_vars={ + "ccsds_index": (["event_met"], ccsds_indices), + "trigger_id": xr.DataArray( + np.ones(len(ccsds_indices), dtype=np.uint8), + dims=["event_met"], + attrs={"FILLVAL": 0}, + ), + # Packet 1 has an invalid spin, packets 0 and 2 do not + "spin_invalids": ( + ["epoch"], + np.array([0, 1, 0], dtype=np.uint8), + ), + }, + ) + result = de_ccsds_qf(ds) + np.testing.assert_array_equal( + result["ccsds_qf"].values, [0, ImapHiL1bDeFlags.BADSPIN, 0] + ) + + def test_spin_invalid_and_packet_full_flags_combined(self): + """Test that BADSPIN and PACKET_FULL flags can be set together.""" + n_packets = 2 + ccsds_indices = np.concatenate( + [ + np.zeros(664, dtype=np.uint16), # 664 events for packet 0 + np.ones(10, dtype=np.uint16), + ] + ) + ds = xr.Dataset( + coords={ + "epoch": np.arange(n_packets), + "event_met": np.arange(len(ccsds_indices), dtype=np.float64), + }, + data_vars={ + "ccsds_index": (["event_met"], ccsds_indices), + "trigger_id": xr.DataArray( + np.ones(len(ccsds_indices), dtype=np.uint8), + dims=["event_met"], + attrs={"FILLVAL": 0}, + ), + # Packet 0 is both full and has an invalid spin + "spin_invalids": ( + ["epoch"], + np.array([1, 0], dtype=np.uint8), + ), + }, + ) + result = de_ccsds_qf(ds) + np.testing.assert_array_equal( + result["ccsds_qf"].values, + [ImapHiL1bDeFlags.PACKET_FULL | ImapHiL1bDeFlags.BADSPIN, 0], + ) + + def test_no_valid_direct_events_all_fill_trigger_id(self): + """de_ccsds_qf returns all zeros when trigger_id is entirely FILLVAL.""" + n_packets = 3 + # Some arbitrary, in-range CCSDS indices that would normally map to packets + ccsds_indices = np.array([0, 0, 1, 1, 2, 2, 0, 1, 2], dtype=np.uint16) + n_events = len(ccsds_indices) + # All trigger_id values are set to the FILLVAL (0), + # meaning no valid direct events + trigger_fillval = 0 + ds = xr.Dataset( + coords={ + "epoch": np.arange(n_packets), + "event_met": np.arange(n_events, dtype=np.float64), + }, + data_vars={ + "ccsds_index": (["event_met"], ccsds_indices), + "trigger_id": xr.DataArray( + np.full(n_events, trigger_fillval, dtype=np.uint8), + dims=["event_met"], + attrs={"FILLVAL": trigger_fillval}, + ), + "spin_invalids": (["epoch"], np.zeros(n_packets, dtype=np.uint8)), + }, + ) + result = de_ccsds_qf(ds) + # With no valid direct events, all CCSDS quality flags should be zero + assert "ccsds_qf" in result + assert result["ccsds_qf"].shape[0] == n_packets + assert np.all(result["ccsds_qf"].values == 0) + + def test_ccsds_index_fillvals_ignored(self): + """de_ccsds_qf returns all zeros when ccsds_index includes FILLVALs (65535).""" + n_packets = 2 + fillval = np.uint16(65535) + # Include some events with CCSDS index FILLVAL that should be ignored + ccsds_indices = np.array([fillval, fillval, 0, 0, 1, 1], dtype=np.uint16) + n_events = len(ccsds_indices) + ds = xr.Dataset( + coords={ + "epoch": np.arange(n_packets), + "event_met": np.arange(n_events, dtype=np.float64), + }, + data_vars={ + "ccsds_index": (["event_met"], ccsds_indices), + "trigger_id": xr.DataArray( + np.ones(n_events, dtype=np.uint8), + dims=["event_met"], + attrs={"FILLVAL": 0}, + ), + "spin_invalids": (["epoch"], np.zeros(n_packets, dtype=np.uint8)), + }, + ) + result = de_ccsds_qf(ds) + # No packet reaches the full-packet threshold; + # FILLVAL indices must not cause errors + assert "ccsds_qf" in result + assert result["ccsds_qf"].shape[0] == n_packets + assert np.all(result["ccsds_qf"].values == 0) diff --git a/imap_processing/tests/hi/test_hi_l1c.py b/imap_processing/tests/hi/test_hi_l1c.py index 7f5a2f0bc7..2fa1f9030a 100644 --- a/imap_processing/tests/hi/test_hi_l1c.py +++ b/imap_processing/tests/hi/test_hi_l1c.py @@ -1,6 +1,6 @@ """Test coverage for imap_processing.hi.l1c.hi_l1c.py""" -from collections import namedtuple +import io from unittest import mock from unittest.mock import MagicMock @@ -11,22 +11,41 @@ from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes from imap_processing.cdf.utils import load_cdf, write_cdf -from imap_processing.hi import hi_l1c -from imap_processing.hi.hi_l1a import DE_CLOCK_TICK_S -from imap_processing.hi.hi_l1c import CalibrationProductConfig -from imap_processing.hi.utils import HIAPID, CoincidenceBitmap +from imap_processing.hi import hi_l1c, utils +from imap_processing.hi.utils import HIAPID, HiConstants +from imap_processing.spice.time import met_to_ttj2000ns, ttj2000ns_to_et @pytest.fixture(scope="module") -def hi_test_cal_prod_config_path(hi_l1_test_data_path): - return hi_l1_test_data_path / "imap_hi_90sensor-cal-prod_20240101_v001.csv" +def hi_l1b_de_dataset(hi_l1_test_data_path): + """Load the Hi L1B DE test dataset.""" + l1b_de_path = hi_l1_test_data_path / "imap_hi_l1b_45sensor-de_20250415_v999.cdf" + return load_cdf(l1b_de_path) + + +@pytest.fixture(scope="module") +def hi_goodtimes_dataset(hi_l1_test_data_path): + """Load the Hi goodtimes test dataset.""" + goodtimes_path = ( + hi_l1_test_data_path / "imap_hi_l1b_45sensor-goodtimes_20250415_v999.cdf" + ) + return load_cdf(goodtimes_path) @mock.patch("imap_processing.hi.hi_l1c.generate_pset_dataset") -def test_hi_l1c(mock_generate_pset_dataset, hi_test_cal_prod_config_path): +def test_hi_l1c( + mock_generate_pset_dataset, + hi_test_cal_prod_config_path, + hi_test_background_config_path, +): """Test coverage for hi_l1c function""" mock_generate_pset_dataset.return_value = xr.Dataset() - pset = hi_l1c.hi_l1c(xr.Dataset(), hi_test_cal_prod_config_path)[0] + pset = hi_l1c.hi_l1c( + xr.Dataset(), + hi_test_cal_prod_config_path, + xr.Dataset(), + hi_test_background_config_path, + )[0] # Empty attributes, global values get added in post-processing assert pset.attrs == {} @@ -34,20 +53,35 @@ def test_hi_l1c(mock_generate_pset_dataset, hi_test_cal_prod_config_path): @pytest.mark.external_kernel @pytest.mark.external_test_data def test_generate_pset_dataset( - hi_l1_test_data_path, + hi_l1b_de_dataset, + hi_goodtimes_dataset, hi_test_cal_prod_config_path, + hi_test_background_config_path, use_fake_spin_data_for_time, + use_fake_repoint_data_for_time, imap_ena_sim_metakernel, ): """Test coverage for generate_pset_dataset function""" use_fake_spin_data_for_time(482372987.999) - l1b_de_path = hi_l1_test_data_path / "imap_hi_l1b_45sensor-de_20250415_v999.cdf" - l1b_dataset = load_cdf(l1b_de_path) + l1b_dataset = hi_l1b_de_dataset + l1b_met = l1b_dataset["ccsds_met"].values[0] + # Set repoint start and end times. + seconds_per_day = 24 * 60 * 60 + use_fake_repoint_data_for_time( + np.asarray([l1b_met - 15 * 60, l1b_met + seconds_per_day]), + np.asarray([l1b_met, l1b_met + seconds_per_day + 1]), + ) + goodtimes = hi_goodtimes_dataset + l1c_dataset = hi_l1c.generate_pset_dataset( - l1b_dataset, hi_test_cal_prod_config_path + l1b_dataset, + hi_test_cal_prod_config_path, + goodtimes, + hi_test_background_config_path, ) assert l1c_dataset.epoch.data[0] == l1b_dataset.epoch.data[0].astype(np.int64) + assert l1c_dataset.epoch_delta.data[0] == seconds_per_day * 1e9 np.testing.assert_array_equal(l1c_dataset.despun_z.data.shape, (1, 3)) np.testing.assert_array_equal(l1c_dataset.hae_latitude.data.shape, (1, 3600)) @@ -64,35 +98,128 @@ def test_generate_pset_dataset( write_cdf(l1c_dataset) -def test_empty_pset_dataset(): +@mock.patch("imap_processing.hi.hi_l1c.pset_backgrounds") +@mock.patch("imap_processing.hi.hi_l1c.pset_exposure") +@mock.patch("imap_processing.hi.hi_l1c.pset_counts") +@mock.patch("imap_processing.hi.hi_l1c.pset_geometry") +@mock.patch("imap_processing.hi.hi_l1c.get_pointing_times") +def test_generate_pset_dataset_uses_midpoint_time( + mock_get_pointing_times, + mock_pset_geometry, + mock_pset_counts, + mock_pset_exposure, + mock_pset_backgrounds, + hi_test_cal_prod_config_path, + hi_test_background_config_path, +): + """Test that generate_pset_dataset uses midpoint ET for pset_geometry.""" + # Create a mock L1B dataset + l1b_met = 482373065.0 + n_energy_steps = 2 + mock_l1b_dataset = xr.Dataset( + coords={ + "epoch": xr.DataArray(np.arange(10), dims=["epoch"]), + }, + data_vars={ + "ccsds_met": xr.DataArray(np.full(10, l1b_met), dims=["epoch"]), + "esa_energy_step": xr.DataArray( + np.concat( + (np.arange(n_energy_steps + 1).repeat(2), np.array([255, 255])) + ), + attrs={"FILLVAL": 255}, + ), + }, + attrs={ + "Logical_file_id": "imap_hi_l1b_45sensor-de_20250415_v999", + "Logical_source": "imap_hi_l1b_45sensor-de", + }, + ) + + # Mock get_pointing_times to return known start and end times + pointing_start_met = l1b_met - 1000.0 + pointing_end_met = l1b_met + 1000.0 + mock_get_pointing_times.return_value = (pointing_start_met, pointing_end_met) + + # Mock the return values for the sub-functions + mock_pset_geometry.return_value = {} + mock_pset_counts.return_value = {} + # pset_exposure must return exposure_times for pset_backgrounds to use + mock_exposure_times = xr.DataArray( + np.ones((1, n_energy_steps, 3600), dtype=np.float32), + dims=["epoch", "esa_energy_step", "spin_angle_bin"], + ) + mock_pset_exposure.return_value = {"exposure_times": mock_exposure_times} + mock_pset_backgrounds.return_value = {} + + # Call generate_pset_dataset + _ = hi_l1c.generate_pset_dataset( + mock_l1b_dataset, + hi_test_cal_prod_config_path, + xr.Dataset(), + hi_test_background_config_path, + ) + + # Calculate expected midpoint ET + # The PSET dataset should have epoch and epoch_delta based on pointing times + expected_epoch = met_to_ttj2000ns(np.array([pointing_start_met]))[0] + expected_epoch_delta = ( + met_to_ttj2000ns(np.array([pointing_end_met]))[0] + - met_to_ttj2000ns(np.array([pointing_start_met]))[0] + ) + expected_midpoint_ttj2000 = expected_epoch + expected_epoch_delta / 2 + expected_midpoint_et = ttj2000ns_to_et(expected_midpoint_ttj2000) + + # Verify that pset_geometry was called with the midpoint ET time + mock_pset_geometry.assert_called_once() + actual_et_arg = mock_pset_geometry.call_args[0][0] + actual_sensor_arg = mock_pset_geometry.call_args[0][1] + + # Use approximate comparison for the ET time (floating point) + np.testing.assert_allclose(actual_et_arg, expected_midpoint_et, rtol=1e-10) + assert actual_sensor_arg == "45sensor" + + +def test_empty_pset_dataset(use_fake_repoint_data_for_time): """Test coverage for empty_pset_dataset function""" n_energy_steps = 8 - l1b_esa_energy_steps = np.arange(n_energy_steps + 1).repeat(2) - n_calibration_prods = 5 + l1b_esa_energy_steps = xr.DataArray( + data=np.concat((np.arange(n_energy_steps + 1).repeat(2), np.array([255, 255]))), + attrs={"FILLVAL": 255}, + ) + # Create calibration product numbers array (0, 1, 2, 3, 4) + cal_prod_numbers = np.arange(5) sensor_str = HIAPID.H90_SCI_DE.sensor + l1b_met = 482373065 + use_fake_repoint_data_for_time( + np.asarray([l1b_met - 15 * 60, l1b_met + 24 * 60 * 60]) + ) + dataset = hi_l1c.empty_pset_dataset( - 100, l1b_esa_energy_steps, n_calibration_prods, sensor_str + l1b_met, l1b_esa_energy_steps, cal_prod_numbers, sensor_str ) assert dataset.epoch.size == 1 + assert dataset.epoch_delta.size == 1 assert dataset.spin_angle_bin.size == 3600 assert dataset.esa_energy_step.size == n_energy_steps np.testing.assert_array_equal( dataset.esa_energy_step.data, np.arange(n_energy_steps) + 1 ) - assert dataset.calibration_prod.size == n_calibration_prods + assert dataset.calibration_prod.size == len(cal_prod_numbers) + np.testing.assert_array_equal(dataset.calibration_prod.data, cal_prod_numbers) # verify that attrs defined in hi_pset_epoch have overwritten default # epoch attributes attr_mgr = ImapCdfAttributes() attr_mgr.add_instrument_global_attrs("hi") attr_mgr.add_instrument_variable_attrs(instrument="hi", level=None) - pset_epoch_attrs = attr_mgr.get_variable_attributes( - "hi_pset_epoch", check_schema=False - ) - for k, v in pset_epoch_attrs.items(): - assert k in dataset.epoch.attrs - assert dataset.epoch.attrs[k] == v + for var_name in ["epoch", "epoch_delta"]: + expected_attrs = attr_mgr.get_variable_attributes( + f"hi_pset_{var_name}", check_schema=False + ) + for k, v in expected_attrs.items(): + assert k in dataset[var_name].attrs + assert dataset[var_name].attrs[k] == v @pytest.mark.parametrize("sensor_str", ["90sensor", "45sensor"]) @@ -129,23 +256,59 @@ def test_pset_geometry(mock_frame_transform, mock_geom_frame_transform, sensor_s @pytest.mark.external_test_data -def test_pset_counts(hi_l1_test_data_path, hi_test_cal_prod_config_path): +@mock.patch("imap_processing.hi.hi_l1c.get_pointing_times", return_value=(100, 200)) +def test_pset_counts( + mock_pointing_times, + hi_l1b_de_dataset, + hi_goodtimes_dataset, + hi_test_cal_prod_config_path, + hi_test_background_config_path, +): """Test coverage for pset_counts function.""" - l1b_de_path = hi_l1_test_data_path / "imap_hi_l1b_45sensor-de_20250415_v999.cdf" - l1b_dataset = load_cdf(l1b_de_path) - cal_config_df = hi_l1c.CalibrationProductConfig.from_csv( + cal_config_df = utils.CalibrationProductConfig.from_csv( hi_test_cal_prod_config_path ) empty_pset = hi_l1c.empty_pset_dataset( 100, - l1b_dataset.esa_energy_step.data, - cal_config_df.cal_prod_config.number_of_products, + hi_l1b_de_dataset.esa_energy_step, + cal_config_df.cal_prod_config.calibration_product_numbers, HIAPID.H90_SCI_DE.sensor, ) - counts_var = hi_l1c.pset_counts(empty_pset.coords, cal_config_df, l1b_dataset) + counts_var = hi_l1c.pset_counts( + empty_pset.coords, cal_config_df, hi_l1b_de_dataset, hi_goodtimes_dataset + ) assert "counts" in counts_var +@pytest.mark.external_test_data +@mock.patch("imap_processing.hi.hi_l1c.get_pointing_times", return_value=(100, 200)) +def test_pset_counts_empty_l1b( + mock_pointing_times, + hi_l1b_de_dataset, + hi_goodtimes_dataset, + hi_test_cal_prod_config_path, + hi_test_background_config_path, +): + """Test coverage for pset_counts function when the input L1b contains no counts.""" + # Make a copy and modify it - + # remove all but one event and set its trigger_id to zero + l1b_dataset = hi_l1b_de_dataset.isel(event_met=[0]).copy(deep=True) + l1b_dataset["trigger_id"].data[0] = 0 + cal_config_df = utils.CalibrationProductConfig.from_csv( + hi_test_cal_prod_config_path + ) + empty_pset = hi_l1c.empty_pset_dataset( + 100, + l1b_dataset.esa_energy_step, + cal_config_df.cal_prod_config.calibration_product_numbers, + HIAPID.H90_SCI_DE.sensor, + ) + counts_var = hi_l1c.pset_counts( + empty_pset.coords, cal_config_df, l1b_dataset, hi_goodtimes_dataset + ) + assert counts_var["counts"].data.sum() == 0 + + def test_get_tof_window_mask(): """Test coverage for get_tof_window_mask function.""" # Create a synthetic dataframe with required columns containing data @@ -156,86 +319,604 @@ def test_get_tof_window_mask(): "tof_bc1": -13, "tof_c1c2": -14, } - Row = namedtuple( - "Row", - [ - "Index", - "tof_ab_low", - "tof_ab_high", - "tof_ac1_low", - "tof_ac1_high", - "tof_bc1_low", - "tof_bc1_high", - "tof_c1c2_low", - "tof_c1c2_high", - ], - ) - prod_config_row = Row((1, 0), 0, 1, -1, 2, 1, 5, 4, 6) - synth_df = pd.DataFrame( - { - "tof_ab": np.array( - [0, 2, 1, 0, -1, -5, -11], dtype=np.int32 - ), # T, F, T, T, F, F, FILL - "tof_ac1": np.array( - [-1, 2, -2, 0, 3, 0, -12], dtype=np.int32 - ), # T, T, F, T, F, T, FILL - "tof_bc1": np.array( - [1, 5, 3, 0, 6, 2, -13], dtype=np.int32 - ), # T, T, T, F, F, T, FILL - "tof_c1c2": np.array( - [4, 6, 5, 3, 7, -9, -14], dtype=np.int32 - ), # T, T, T, F, F, F, FILL + # Use dict-based tof_windows instead of named tuple + tof_windows = { + "tof_ab": (0, 1), + "tof_ac1": (-1, 2), + "tof_bc1": (1, 5), + "tof_c1c2": (4, 6), + } + synth_df = xr.Dataset( + coords={ + "event_met": xr.DataArray( + np.arange(7), name="event_met", dims=["event_met"] + ) + }, + data_vars={ + "tof_ab": xr.DataArray( + np.array( + [0, 2, 1, 0, -1, -5, -11], dtype=np.int32 + ), # T, F, T, T, F, F, FILL + dims=["event_met"], + ), + "tof_ac1": xr.DataArray( + np.array( + [-1, 2, -2, 0, 3, 0, -12], dtype=np.int32 + ), # T, T, F, T, F, T, FILL + dims=["event_met"], + ), + "tof_bc1": xr.DataArray( + np.array( + [1, 5, 3, 0, 6, 2, -13], dtype=np.int32 + ), # T, T, T, F, F, T, FILL + dims=["event_met"], + ), + "tof_c1c2": xr.DataArray( + np.array( + [4, 6, 5, 3, 7, -9, -14], dtype=np.int32 + ), # T, T, T, F, F, F, FILL + dims=["event_met"], + ), }, ) expected_mask = np.array([True, False, False, False, False, False, True]) - window_mask = hi_l1c.get_tof_window_mask(synth_df, prod_config_row, fill_vals) + window_mask = utils.get_tof_window_mask(synth_df, tof_windows, fill_vals) np.testing.assert_array_equal(expected_mask, window_mask) -def test_pset_backgrounds(): +def test_empty_pset_dataset_arbitrary_cal_prod_numbers(use_fake_repoint_data_for_time): + """Test empty_pset_dataset with non-sequential calibration product numbers.""" + n_energy_steps = 3 + l1b_esa_energy_steps = xr.DataArray( + data=np.concat((np.arange(n_energy_steps + 1).repeat(2), np.array([255, 255]))), + attrs={"FILLVAL": 255}, + ) + # Use non-sequential calibration product numbers + cal_prod_numbers = np.array([5, 10, 100]) + sensor_str = HIAPID.H45_SCI_DE.sensor + l1b_met = 482373065 + use_fake_repoint_data_for_time( + np.asarray([l1b_met - 15 * 60, l1b_met + 24 * 60 * 60]) + ) + + dataset = hi_l1c.empty_pset_dataset( + l1b_met, l1b_esa_energy_steps, cal_prod_numbers, sensor_str + ) + + # Verify calibration_prod coordinate has the correct non-sequential values + assert dataset.calibration_prod.size == len(cal_prod_numbers) + np.testing.assert_array_equal(dataset.calibration_prod.data, cal_prod_numbers) + # Verify the calibration_prod_label reflects the actual numbers + expected_labels = np.array(["5", "10", "100"]) + np.testing.assert_array_equal(dataset.calibration_prod_label.data, expected_labels) + + +@pytest.mark.external_test_data +def test_pset_counts_arbitrary_cal_prod_numbers( + hi_l1b_de_dataset, hi_goodtimes_dataset, use_fake_repoint_data_for_time +): + """Test pset_counts with non-sequential calibration product numbers.""" + # Create a test calibration product config with non-sequential numbers + csv_content = """\ +calibration_prod,esa_energy_step,geometric_factor,coincidence_type_list,tof_ab_low,tof_ab_high,tof_ac1_low,tof_ac1_high,tof_bc1_low,tof_bc1_high,tof_c1c2_low,tof_c1c2_high +5,1,0.00055,ABC1C2,0,1023,-1023,1023,-1023,1023,0,1023 +5,2,0.00085,ABC1C2,0,1023,-1023,1023,-1023,1023,0,1023 +10,1,0.00055,BC1C2,0,1023,-1023,1023,-1023,1023,0,1023 +10,2,0.00085,BC1C2,0,1023,-1023,1023,-1023,1023,0,1023 + """ + + cal_config_df = utils.CalibrationProductConfig.from_csv(io.StringIO(csv_content)) + + # Create PSET with non-sequential calibration product numbers + l1b_met = 482373065 + use_fake_repoint_data_for_time( + np.asarray([l1b_met - 15 * 60, l1b_met + 24 * 60 * 60]) + ) + + empty_pset = hi_l1c.empty_pset_dataset( + l1b_met, + hi_l1b_de_dataset.esa_energy_step, + cal_config_df.cal_prod_config.calibration_product_numbers, + HIAPID.H90_SCI_DE.sensor, + ) + + # Verify the calibration_prod coordinate has non-sequential values + np.testing.assert_array_equal(empty_pset.calibration_prod.data, np.array([5, 10])) + + # Mock get_pointing_times to avoid SPICE kernel requirements + with mock.patch( + "imap_processing.hi.hi_l1c.get_pointing_times", return_value=(100, 200) + ): + counts_var = hi_l1c.pset_counts( + empty_pset.coords, cal_config_df, hi_l1b_de_dataset, hi_goodtimes_dataset + ) + + # Verify counts array has correct shape based on coordinates + assert "counts" in counts_var + # Shape should be (n_epoch, n_esa_energy, n_cal_prod, n_spin_bins) + # where n_cal_prod is 2 (for products 5 and 10) + expected_shape = ( + 1, + empty_pset.esa_energy_step.size, + 2, # Two calibration products: 5 and 10 + 3600, + ) + assert counts_var["counts"].data.shape == expected_shape + # Check that total number of expected counts is correct + # ABC1C2 is coincidence type 15 + esa_1_2_mask = ( + hi_l1b_de_dataset["esa_step"][hi_l1b_de_dataset["ccsds_index"]] < 3 + ).values + coincidence_15_mask = (hi_l1b_de_dataset["coincidence_type"] == 15).values + np.testing.assert_equal( + np.sum(counts_var["counts"].data[:, :, 0]), + np.sum(coincidence_15_mask & esa_1_2_mask), + ) + # BC1C2 is coincidence type 7 + coincidence_7_mask = (hi_l1b_de_dataset["coincidence_type"] == 7).values + np.testing.assert_equal( + np.sum(counts_var["counts"].data[:, :, 1]), + np.sum(coincidence_7_mask & esa_1_2_mask), + ) + + +@mock.patch("imap_processing.hi.hi_l1c.get_pointing_times", return_value=(100, 200)) +@mock.patch("imap_processing.hi.hi_l1c.iter_qualified_events_by_config") +def test_pset_counts_goodtimes_filtering( + mock_iter_qualified, + mock_pointing_times, +): + """Test that pset_counts properly filters events based on goodtimes.""" + # Create 10 events: METs 100-109, nominal_bins 0-9, all at spin_phase=0.5 + # (spin_phase 0.5 -> spin_angle_bin 1800) + n_events = 10 + event_mets = np.arange(100.0, 100.0 + n_events) + nominal_bins = np.arange(n_events, dtype=np.uint8) + + l1b_dataset = xr.Dataset( + coords={ + "epoch": xr.DataArray(np.arange(2), dims=["epoch"]), + "event_met": xr.DataArray(event_mets, dims=["event_met"]), + }, + data_vars={ + "trigger_id": xr.DataArray( + np.ones(n_events, dtype=np.uint16), + dims=["event_met"], + attrs={"FILLVAL": 65535}, + ), + "nominal_bin": xr.DataArray(nominal_bins, dims=["event_met"]), + "spin_phase": xr.DataArray(np.full(n_events, 0.5), dims=["event_met"]), + "ccsds_index": xr.DataArray( + np.zeros(n_events, dtype=np.int32), dims=["event_met"] + ), + "esa_energy_step": xr.DataArray( + np.array([1, 1], dtype=np.uint8), + dims=["epoch"], + attrs={"FILLVAL": 255}, + ), + }, + attrs={"Logical_source": "imap_hi_l1b_90sensor-de"}, + ) + + # Goodtimes: METs 100-104 good, METs 105-109 bad + goodtimes_ds = xr.Dataset( + { + "cull_flags": xr.DataArray( + np.zeros((2, 90), dtype=np.uint8), + dims=["met", "spin_bin"], + ), + }, + coords={"met": [100.0, 105.0], "spin_bin": np.arange(90)}, + ) + goodtimes_ds["cull_flags"].values[1, :] = 1 # All bins bad for MET >= 105 + + # Create empty pset with single ESA step and single calibration product + empty_pset = hi_l1c.empty_pset_dataset( + 100, + l1b_dataset.esa_energy_step, + np.array([0]), + HIAPID.H90_SCI_DE.sensor, + ) + + # Mock iter_qualified_events_by_config to mark all events as qualified + # and return a single (esa_energy, config_row, mask) tuple + mock_config_row = MagicMock() + mock_config_row.Index = (0, 1) # (calibration_prod, esa_energy_step) + + def mock_iter(de_ds, config_df, esa_energy_steps): + n_remaining = len(de_ds["event_met"]) + yield 1, mock_config_row, np.ones(n_remaining, dtype=bool) + + mock_iter_qualified.side_effect = mock_iter + + # Use MagicMock for cal_config since it's not used with our mock + mock_cal_config = MagicMock() + + counts_var = hi_l1c.pset_counts( + empty_pset.coords, mock_cal_config, l1b_dataset, goodtimes_ds + ) + + # Only 5 events (METs 100-104) should pass goodtimes filtering + # All 5 events have spin_phase=0.5 -> spin_angle_bin 1800 + total_counts = counts_var["counts"].data.sum() + assert total_counts == 5, f"Expected 5 counts, got {total_counts}" + # Verify all counts are in the expected spin bin (1800) + assert counts_var["counts"].data[0, 0, 0, 1800] == 5 + + +@pytest.mark.external_test_data +def test_pset_backgrounds( + hi_test_background_config_path, + hi_test_cal_prod_config_path, + hi_l1b_de_dataset, + hi_goodtimes_dataset, + use_fake_spin_data_for_time, + use_fake_repoint_data_for_time, +): """Test coverage for pset_backgrounds function.""" - # Create some fake coordinates to use + # Setup required SPICE data + use_fake_spin_data_for_time(482372987.999) + l1b_met = hi_l1b_de_dataset["ccsds_met"].values[0] + seconds_per_day = 24 * 60 * 60 + use_fake_repoint_data_for_time( + np.asarray([l1b_met - 15 * 60, l1b_met + seconds_per_day]), + np.asarray([l1b_met, l1b_met + seconds_per_day + 1]), + ) + + # Load the background config + background_df = utils.BackgroundConfig.from_csv(hi_test_background_config_path) + + # Create empty pset dataset to get coordinates + cal_config_df = utils.CalibrationProductConfig.from_csv( + hi_test_cal_prod_config_path + ) + empty_pset = hi_l1c.empty_pset_dataset( + l1b_met, + hi_l1b_de_dataset.esa_energy_step, + cal_config_df.cal_prod_config.calibration_product_numbers, + HIAPID.H90_SCI_DE.sensor, + ) + + # Create exposure_times for the test + exposure_times_data = np.full( + ( + len(empty_pset.coords["epoch"]), + len(empty_pset.coords["esa_energy_step"]), + len(empty_pset.coords["spin_angle_bin"]), + ), + 1.0, + dtype=np.float32, + ) + exposure_times = xr.DataArray( + exposure_times_data, + dims=["epoch", "esa_energy_step", "spin_angle_bin"], + coords={ + "epoch": empty_pset.coords["epoch"], + "esa_energy_step": empty_pset.coords["esa_energy_step"], + "spin_angle_bin": empty_pset.coords["spin_angle_bin"], + }, + ) + + # Call pset_backgrounds with the new signature + backgrounds_vars = hi_l1c.pset_backgrounds( + empty_pset.coords, + background_df, + hi_l1b_de_dataset, + hi_goodtimes_dataset, + exposure_times, + ) + + assert "background_rates" in backgrounds_vars + assert backgrounds_vars["background_rates"].data.shape == ( + len(empty_pset.coords["epoch"]), + len(empty_pset.coords["esa_energy_step"]), + len(empty_pset.coords["calibration_prod"]), + len(empty_pset.coords["spin_angle_bin"]), + ) + + assert "background_rates_uncertainty" in backgrounds_vars + assert backgrounds_vars["background_rates_uncertainty"].data.shape == ( + len(empty_pset.coords["epoch"]), + len(empty_pset.coords["esa_energy_step"]), + len(empty_pset.coords["calibration_prod"]), + len(empty_pset.coords["spin_angle_bin"]), + ) + + # Verify ESA-dependent backgrounds: different ESA steps should have different + # background rates (since scaling factors vary by ESA in the test config). + # Check that not all ESA steps have identical background rates for each cal_prod. + bg_rates = backgrounds_vars["background_rates"].data + for i_cal_prod in range(len(empty_pset.coords["calibration_prod"])): + # Get background rates for this cal_prod across all ESA steps + # (take first spin bin) + rates_by_esa = bg_rates[0, :, i_cal_prod, 0] + # If there are any non-zero background counts, rates should vary by ESA + if np.any(rates_by_esa > 0): + # Verify not all ESA steps have identical rates + assert not np.allclose(rates_by_esa, rates_by_esa[0]), ( + f"Background rates should vary by ESA for cal_prod {i_cal_prod}" + ) + + +@mock.patch("imap_processing.hi.hi_l1c.good_time_and_phase_mask") +def test_compute_background_counts_missing_cal_prod_raises_error( + mock_good_time_and_phase_mask, + hi_test_background_config_path, +): + """Test _compute_background_counts raises ValueError with invalid bkgnd config.""" + # Mock good_time_and_phase_mask to return all True + mock_good_time_and_phase_mask.side_effect = lambda a, b, c: np.ones( + a.shape, dtype=bool + ) + # Load the background config (has cal prods 0 and 1) + background_df = utils.BackgroundConfig.from_csv(hi_test_background_config_path) + + # Create minimal pset_coords with a calibration product (999) that's + # NOT in the background config + missing_cal_prod = 999 + pset_coords = { + "epoch": xr.DataArray(np.array([0], dtype=np.int64), dims=["epoch"]), + "calibration_prod": xr.DataArray( + np.array([0, 1, missing_cal_prod], dtype=np.int32), + dims=["calibration_prod"], + ), + } + + hi_l1b_de_dataset = xr.Dataset( + { + "coincidence_type": xr.DataArray( + np.array([15], dtype=np.uint8), dims=["event_met"] + ), + "trigger_id": xr.DataArray( + np.array([0], dtype=np.float64), + dims=["event_met"], + attrs={"FILLVAL": 65535}, + ), + "nominal_bin": xr.DataArray( + np.array([0], dtype=np.uint8), dims=["event_met"] + ), + "tof_ab": xr.DataArray( + np.array([50], dtype=np.float32), dims=["event_met"] + ), + "tof_ac1": xr.DataArray( + np.array([50], dtype=np.float32), dims=["event_met"] + ), + "tof_bc1": xr.DataArray( + np.array([50], dtype=np.float32), dims=["event_met"] + ), + "tof_c1c2": xr.DataArray( + np.array([50], dtype=np.float32), dims=["event_met"] + ), + }, + coords={ + "epoch": xr.DataArray(np.array([0], dtype=np.int64), dims=["epoch"]), + "event_met": xr.DataArray( + np.array([0], dtype=np.float64), dims=["event_met"] + ), + }, + ) + + # Verify that calling _compute_background_counts raises ValueError + # with expected message + with pytest.raises( + ValueError, + match=f"Calibration product {missing_cal_prod} not found " + f"in background configuration", + ): + hi_l1c._compute_background_counts( + pset_coords, + background_df, + hi_l1b_de_dataset, + xr.Dataset(), + ) + + +@mock.patch("imap_processing.hi.hi_l1c._compute_background_counts") +def test_pset_backgrounds_cal_prod_mismatch_raises_error( + mock_compute_background_counts, +): + """Test pset_backgrounds raises ValueError when cal prods don't match. + + This tests the validation in pset_backgrounds that checks + if calibration products in pset_coords match those in background_config_df. + """ + # Create pset_coords with calibration products [0, 1] n_epoch = 1 - n_energy = 9 - n_cal_prod = 2 + n_energy = 2 n_spin_bins = 3600 pset_coords = { - "epoch": xr.DataArray(np.arange(n_epoch)), - "esa_energy_step": xr.DataArray(np.arange(n_energy) + 1), - "calibration_prod": xr.DataArray(np.arange(n_cal_prod)), - "spin_angle_bin": xr.DataArray(np.arange(n_spin_bins)), + "epoch": xr.DataArray(np.array([0], dtype=np.int64), dims=["epoch"]), + "esa_energy_step": xr.DataArray( + np.arange(n_energy) + 1, dims=["esa_energy_step"] + ), + "calibration_prod": xr.DataArray( + np.array([0, 1], dtype=np.int64), + dims=["calibration_prod"], + ), + "spin_angle_bin": xr.DataArray(np.arange(n_spin_bins), dims=["spin_angle_bin"]), } - backgrounds_vars = hi_l1c.pset_backgrounds(pset_coords) - assert "background_rates" in backgrounds_vars - np.testing.assert_array_equal( - backgrounds_vars["background_rates"].data, - np.zeros((n_epoch, n_energy, n_cal_prod, n_spin_bins)), + + # Create a background config DataFrame with DIFFERENT calibration products [5, 6] + # This simulates a mismatch between pset_coords and background_config_df + # Now includes esa_energy_step in the multi-index + background_config_data = { + "coincidence_type_list": [("ABC1C2",), ("ABC1C2",), ("ABC1C2",), ("ABC1C2",)], + "coincidence_type_values": [(15,), (15,), (15,), (15,)], + "tof_ab_low": [0, 0, 0, 0], + "tof_ab_high": [100, 100, 100, 100], + "tof_ac1_low": [0, 0, 0, 0], + "tof_ac1_high": [100, 100, 100, 100], + "tof_bc1_low": [0, 0, 0, 0], + "tof_bc1_high": [100, 100, 100, 100], + "tof_c1c2_low": [0, 0, 0, 0], + "tof_c1c2_high": [100, 100, 100, 100], + "scaling_factor": [1.0, 1.0, 1.0, 1.0], + "uncertainty": [0.1, 0.1, 0.1, 0.1], + } + # Use calibration products [5, 6] which don't match pset_coords [0, 1] + mismatched_cal_prods = [5, 5, 6, 6] + background_indices = [0, 0, 0, 0] + esa_energy_steps = [1, 2, 1, 2] + multi_index = pd.MultiIndex.from_arrays( + [mismatched_cal_prods, background_indices, esa_energy_steps], + names=["calibration_prod", "background_index", "esa_energy_step"], ) - assert "background_rates_uncertainty" in backgrounds_vars - np.testing.assert_array_equal( - backgrounds_vars["background_rates_uncertainty"].data, - np.ones((n_epoch, n_energy, n_cal_prod, n_spin_bins)), + background_df = pd.DataFrame(background_config_data, index=multi_index) + + # Create mock exposure_times + exposure_times = xr.DataArray( + np.ones((n_epoch, n_energy, n_spin_bins), dtype=np.float32), + dims=["epoch", "esa_energy_step", "spin_angle_bin"], + ) + + # Mock _compute_background_counts to return a DataArray with the mismatched + # calibration products (simulating what would happen if the earlier check + # didn't catch the mismatch) + mock_background_counts = xr.DataArray( + np.zeros((n_epoch, 2, 1)), + dims=["epoch", "calibration_prod", "background_index"], + coords={ + "epoch": pset_coords["epoch"], + "calibration_prod": [5, 6], + "background_index": [0], + }, + ) + mock_compute_background_counts.return_value = mock_background_counts + + # Create minimal l1b dataset and goodtimes (not used due to mock) + l1b_de_dataset = xr.Dataset() + goodtimes_ds = xr.Dataset() + + # Verify that pset_backgrounds raises ValueError with expected message + with pytest.raises( + ValueError, + match="Calibration products in pset_coords and " + "background_config_df do not match", + ): + hi_l1c.pset_backgrounds( + pset_coords, + background_df, + l1b_de_dataset, + goodtimes_ds, + exposure_times, + ) + + +@mock.patch("imap_processing.hi.hi_l1c._compute_background_counts") +def test_pset_backgrounds_esa_energy_step_mismatch_raises_error( + mock_compute_background_counts, +): + """Test pset_backgrounds raises ValueError when esa_energy_steps don't match. + + This tests the validation in pset_backgrounds that checks + if ESA energy steps in pset_coords match those in background_config_df. + """ + # Create pset_coords with ESA energy steps [1, 2] + n_epoch = 1 + n_energy = 2 + n_spin_bins = 3600 + pset_coords = { + "epoch": xr.DataArray(np.array([0], dtype=np.int64), dims=["epoch"]), + "esa_energy_step": xr.DataArray(np.array([1, 2]), dims=["esa_energy_step"]), + "calibration_prod": xr.DataArray( + np.array([0], dtype=np.int64), + dims=["calibration_prod"], + ), + "spin_angle_bin": xr.DataArray(np.arange(n_spin_bins), dims=["spin_angle_bin"]), + } + + # Create a background config DataFrame with DIFFERENT ESA energy steps [3, 4] + background_config_data = { + "coincidence_type_list": [("ABC1C2",), ("ABC1C2",)], + "coincidence_type_values": [(15,), (15,)], + "tof_ab_low": [0, 0], + "tof_ab_high": [100, 100], + "tof_ac1_low": [0, 0], + "tof_ac1_high": [100, 100], + "tof_bc1_low": [0, 0], + "tof_bc1_high": [100, 100], + "tof_c1c2_low": [0, 0], + "tof_c1c2_high": [100, 100], + "scaling_factor": [1.0, 1.0], + "uncertainty": [0.1, 0.1], + } + # Use ESA energy steps [3, 4] which don't match pset_coords [1, 2] + cal_prods = [0, 0] + background_indices = [0, 0] + mismatched_esa_steps = [3, 4] + multi_index = pd.MultiIndex.from_arrays( + [cal_prods, background_indices, mismatched_esa_steps], + names=["calibration_prod", "background_index", "esa_energy_step"], ) + background_df = pd.DataFrame(background_config_data, index=multi_index) + # Create mock exposure_times + exposure_times = xr.DataArray( + np.ones((n_epoch, n_energy, n_spin_bins), dtype=np.float32), + dims=["epoch", "esa_energy_step", "spin_angle_bin"], + ) + # Mock _compute_background_counts to return a valid DataArray + mock_background_counts = xr.DataArray( + np.zeros((n_epoch, 1, 1)), + dims=["epoch", "calibration_prod", "background_index"], + coords={ + "epoch": pset_coords["epoch"], + "calibration_prod": [0], + "background_index": [0], + }, + ) + mock_compute_background_counts.return_value = mock_background_counts + + # Create minimal l1b dataset and goodtimes (not used due to mock) + l1b_de_dataset = xr.Dataset() + goodtimes_ds = xr.Dataset() + + # Verify that pset_backgrounds raises ValueError with expected message + with pytest.raises( + ValueError, + match="ESA energy steps in pset_coords and background_config_df do not match", + ): + hi_l1c.pset_backgrounds( + pset_coords, + background_df, + l1b_de_dataset, + goodtimes_ds, + exposure_times, + ) + + +@mock.patch("imap_processing.hi.hi_l1c.good_time_and_phase_mask") +@mock.patch("imap_processing.hi.hi_l1c.get_pointing_times", return_value=(100, 200)) @mock.patch("imap_processing.hi.hi_l1c.get_spin_data", return_value=None) -@mock.patch("imap_processing.hi.hi_l1c.get_instrument_spin_phase") +@mock.patch( + "imap_processing.hi.hi_l1c.get_spacecraft_to_instrument_spin_phase_offset", + return_value=0.0, +) +@mock.patch("imap_processing.hi.hi_l1c.get_spacecraft_spin_phase") @mock.patch("imap_processing.hi.hi_l1c.get_de_clock_ticks_for_esa_step") -@mock.patch("imap_processing.hi.hi_l1c.find_second_de_packet_data") +@mock.patch("imap_processing.hi.hi_l1c.find_last_de_packet_data") def test_pset_exposure( - mock_find_second_de_packet_data, + mock_find_last_de_packet_data, mock_de_clock_ticks, - mock_spin_phase, + mock_sc_spin_phase, + mock_phase_offset, mock_spin_data, + mock_pointing_times, + mock_good_time_and_phase_mask, ): """Test coverage for pset_exposure function""" + l1b_energy_steps = xr.DataArray( + np.arange(2) + 1, + attrs={"FILLVAL": 255}, + ) empty_pset = hi_l1c.empty_pset_dataset( - 100, np.arange(2) + 1, 2, HIAPID.H90_SCI_DE.sensor + 100, l1b_energy_steps, np.array([0, 1]), HIAPID.H90_SCI_DE.sensor ) - # Set the mock of find_second_de_packet_data to return a xr.Dataset + # Set the mock of find_last_de_packet_data to return a xr.Dataset # with some dummy data. ESA 1 will get binned data once, ESA 2 will get # binned data twice. - mock_find_second_de_packet_data.return_value = xr.Dataset( + mock_find_last_de_packet_data.return_value = xr.Dataset( coords={"epoch": xr.DataArray(np.arange(3), dims=["epoch"])}, data_vars={ "ccsds_met": xr.DataArray(np.arange(3), dims=["epoch"]), @@ -246,7 +927,7 @@ def test_pset_exposure( # deterministic histogram values. # ESA step 1 should have repeating values of 3, 1. # ESA step 2 should have repeating values of 6, 2 - mock_spin_phase.return_value = np.concat( + mock_sc_spin_phase.return_value = np.concat( [hi_l1c.SPIN_PHASE_BIN_CENTERS, hi_l1c.SPIN_PHASE_BIN_CENTERS[::2]] ) mock_de_clock_ticks.return_value = ( @@ -259,8 +940,13 @@ def test_pset_exposure( l1b_dataset = MagicMock() l1b_dataset.attrs = {"Logical_source": "90sensor"} + # Mock goodtime to return all true + mock_good_time_and_phase_mask.side_effect = lambda x, y, z: np.ones( + x.shape, dtype=bool + ) + # All the setup is done, call the pset_exposure function - exposure_dict = hi_l1c.pset_exposure(empty_pset.coords, l1b_dataset) + exposure_dict = hi_l1c.pset_exposure(empty_pset.coords, l1b_dataset, xr.Dataset()) # Based on the spin phase and clock_tick mocks, the expected clock ticks are: # - Repeated values of 3, 1 for the first half of the spin bins @@ -272,21 +958,100 @@ def test_pset_exposure( ] ).astype(float)[None, :, :] # Convert expected clock ticks to seconds - expected_values *= DE_CLOCK_TICK_S + expected_values *= HiConstants.DE_CLOCK_TICK_S np.testing.assert_allclose( exposure_dict["exposure_times"].data, expected_values, - atol=DE_CLOCK_TICK_S / 100, + atol=HiConstants.DE_CLOCK_TICK_S / 100, + ) + + +@mock.patch("imap_processing.hi.hi_l1c.get_pointing_times", return_value=(100, 200)) +@mock.patch("imap_processing.hi.hi_l1c.get_spin_data", return_value=None) +@mock.patch( + "imap_processing.hi.hi_l1c.get_spacecraft_to_instrument_spin_phase_offset", + return_value=0.0, +) +@mock.patch("imap_processing.hi.hi_l1c.get_spacecraft_spin_phase") +@mock.patch("imap_processing.hi.hi_l1c.get_de_clock_ticks_for_esa_step") +@mock.patch("imap_processing.hi.hi_l1c.find_last_de_packet_data") +def test_pset_exposure_goodtimes_filtering( + mock_find_last_de_packet_data, + mock_de_clock_ticks, + mock_sc_spin_phase, + mock_phase_offset, + mock_spin_data, + mock_pointing_times, +): + """Test that pset_exposure properly filters clock ticks based on goodtimes.""" + l1b_energy_steps = xr.DataArray( + np.arange(1) + 1, # Single ESA step for simplicity + attrs={"FILLVAL": 255}, + ) + empty_pset = hi_l1c.empty_pset_dataset( + 100, l1b_energy_steps, np.array([0]), HIAPID.H90_SCI_DE.sensor + ) + + # Mock find_last_de_packet_data to return a single ESA step + mock_find_last_de_packet_data.return_value = xr.Dataset( + coords={"epoch": xr.DataArray(np.arange(1), dims=["epoch"])}, + data_vars={ + "ccsds_met": xr.DataArray(np.array([150.0]), dims=["epoch"]), + "esa_energy_step": xr.DataArray(np.array([1]), dims=["epoch"]), + }, ) + # Create 10 clock ticks at METs 100-109 with uniform spin phases + n_ticks = 10 + clock_tick_mets = np.arange(100.0, 100.0 + n_ticks) + mock_de_clock_ticks.return_value = (clock_tick_mets, np.ones(n_ticks)) + + # Mock spacecraft spin phase - each tick maps to a different spin bin + # Spin phases 0.0, 0.1, 0.2, ... -> nominal_bins 0, 9, 18, ... + spin_phases = np.arange(n_ticks) / n_ticks + mock_sc_spin_phase.return_value = spin_phases + + # Create a goodtimes dataset that marks half the clock ticks as bad + # METs 100-104 are good (cull_flags=0), METs 105-109 are bad (cull_flags=1) + goodtimes_ds = xr.Dataset( + { + "cull_flags": xr.DataArray( + np.zeros((2, 90), dtype=np.uint8), + dims=["met", "spin_bin"], + ), + }, + coords={"met": [100.0, 105.0], "spin_bin": np.arange(90)}, + ) + # Mark all spin bins as bad for METs >= 105 + goodtimes_ds["cull_flags"].values[1, :] = 1 + + # Mock l1b_dataset + l1b_dataset = MagicMock() + l1b_dataset.attrs = {"Logical_source": "90sensor"} + + # Call pset_exposure with the goodtimes dataset + exposure_dict = hi_l1c.pset_exposure(empty_pset.coords, l1b_dataset, goodtimes_ds) + + # Only the first 5 clock ticks (METs 100-104) should contribute + # Their spin phases are 0.0, 0.1, 0.2, 0.3, 0.4 -> spin_angle_bins 0, 360, 720, ... + total_exposure_ticks = exposure_dict["exposure_times"].data.sum() + expected_ticks = 5.0 * HiConstants.DE_CLOCK_TICK_S + np.testing.assert_allclose(total_exposure_ticks, expected_ticks, rtol=0.01) + def test_find_second_de_packet_data(): """Test coverage for find_second_de_packet_data function""" # Create a test l1b_dataset - # Expect to remove index 0 and 5 due to missing esa_step pair - # Expect to remove index 11 due to 0 being a calibration step - # Expect to return indices 2, 4, 7, 9, 13 - esa_steps = np.array([1, 2, 2, 3, 3, 4, 5, 5, 6, 6, 0, 0, 7, 7]) + # Indices represent CCSDS packets at various ESA steps + # Index: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 + # esa_step: 1 2 2 2 2 4 5 5 6 6 0 0 7 7 + # esa_energy: 1 2 2 3 3 4 5 5 6 6 0 0 7 7 + # + # Expected last packet indices from diff logic: [0, 2, 4, 5, 7, 9, 11, 13] + # Remove index 11: esa_energy_step is 0 (calibration) + # Expected final indices: [0, 2, 4, 5, 7, 9, 13] + esa_steps = np.array([1, 2, 2, 2, 2, 4, 5, 5, 6, 6, 0, 0, 7, 7]) + esa_energy_steps = np.array([1, 2, 2, 3, 3, 4, 5, 5, 6, 6, 0, 0, 7, 7]) l1b_dataset = xr.Dataset( coords={ "epoch": xr.DataArray( @@ -303,14 +1068,19 @@ def test_find_second_de_packet_data(): esa_steps, dims=["epoch"], ), + "esa_energy_step": xr.DataArray( + esa_energy_steps, + dims=["epoch"], + attrs={"FILLVAL": 255}, + ), "coincidence_type": xr.DataArray( np.ones(10), dims=["event_met"], ), }, ) - subset = hi_l1c.find_second_de_packet_data(l1b_dataset) - np.testing.assert_array_equal(subset.epoch.data, np.array([2, 4, 7, 9, 13])) + subset = hi_l1c.find_last_de_packet_data(l1b_dataset) + np.testing.assert_array_equal(subset.epoch.data, np.array([0, 2, 4, 5, 7, 9, 13])) @pytest.fixture(scope="module") @@ -346,7 +1116,7 @@ def test_get_de_clock_ticks_for_esa_step(fake_spin_df): np.absolute( fake_spin_df.spin_start_met.to_numpy() - clock_tick_mets[-1] ).min() - / DE_CLOCK_TICK_S + / HiConstants.DE_CLOCK_TICK_S ) assert clock_tick_weights[-1] == exp_final_weight assert np.all(clock_tick_weights[:-1] == 1) @@ -373,37 +1143,70 @@ def test_get_de_clock_ticks_for_esa_step_exceptions(fake_spin_df): hi_l1c.get_de_clock_ticks_for_esa_step(bad_ccsds_met, fake_spin_df) -class TestCalibrationProductConfig: - """ - All test coverage for the pd.DataFrame accessor extension "cal_prod_config". - """ +class TestGoodTimeAndPhaseMask: + """Tests for good_time_and_phase_mask function.""" + + def test_filters_bad_times_with_nominal_bins(self): + """Events in bad times are filtered out using nominal_bins.""" + # Create mock goodtimes with some bad times + gt_ds = xr.Dataset( + { + "cull_flags": xr.DataArray( + np.zeros((3, 90), dtype=np.uint8), + dims=["met", "spin_bin"], + ) + }, + coords={"met": [100.0, 200.0, 300.0], "spin_bin": np.arange(90)}, + ) + # Mark spin_bin 10 as bad at MET 200 + gt_ds["cull_flags"].values[1, 10] = 1 + + mets = np.array([150.0, 250.0, 250.0]) + nominal_bins = np.array([10, 10, 20]) + + mask = hi_l1c.good_time_and_phase_mask(mets, nominal_bins, gt_ds) + # Event at 150 maps to MET index 0, bin 10 β†’ good (cull_flags[0,10]=0) + # Event at 250 maps to MET index 1, bin 10 β†’ bad (cull_flags[1,10]=1) + # Event at 250 maps to MET index 1, bin 20 β†’ good (cull_flags[1,20]=0) + expected = np.array([True, False, True]) + np.testing.assert_array_equal(mask, expected) + + def test_met_before_goodtimes_range(self): + """Events before goodtimes range are clipped to first interval.""" + gt_ds = xr.Dataset( + { + "cull_flags": xr.DataArray( + np.zeros((2, 90), dtype=np.uint8), + dims=["met", "spin_bin"], + ) + }, + coords={"met": [100.0, 200.0], "spin_bin": np.arange(90)}, + ) + # Mark spin_bin 0 as bad at first MET + gt_ds["cull_flags"].values[0, 0] = 1 + + # Event at MET 50 (before goodtimes range) should use index 0 + mets = np.array([50.0]) + nominal_bins = np.array([0]) + + mask = hi_l1c.good_time_and_phase_mask(mets, nominal_bins, gt_ds) + # Clipped to index 0, bin 0 is bad + assert not mask[0] + + def test_all_bins_bad_for_interval(self): + """When all bins are bad for an interval, all events are filtered.""" + gt_ds = xr.Dataset( + { + "cull_flags": xr.DataArray( + np.ones((1, 90), dtype=np.uint8), # All bad + dims=["met", "spin_bin"], + ) + }, + coords={"met": [100.0], "spin_bin": np.arange(90)}, + ) + + mets = np.array([100.0, 150.0, 200.0]) + nominal_bins = np.array([0, 45, 89]) - def test_wrong_columns(self): - """Test coverage for a dataframe with the wrong columns.""" - required_columns = hi_l1c.CalibrationProductConfig.required_columns - for exclude_column_name in required_columns: - include_columns = set(required_columns) - {exclude_column_name} - df = pd.DataFrame({col: [1, 2, 3] for col in include_columns}) - with pytest.raises(AttributeError, match="Required column*"): - _ = df.cal_prod_config.number_of_products - - def test_from_csv(self, hi_test_cal_prod_config_path): - """Test coverage for read_csv function.""" - df = hi_l1c.CalibrationProductConfig.from_csv(hi_test_cal_prod_config_path) - assert isinstance(df["coincidence_type_list"][0, 1], tuple) - - def test_added_coincidence_type_values_column(self, hi_test_cal_prod_config_path): - df = CalibrationProductConfig.from_csv(hi_test_cal_prod_config_path) - assert "coincidence_type_values" in df.columns - for _, row in df.iterrows(): - for detect_string, val in zip( - row["coincidence_type_list"], - row["coincidence_type_values"], - strict=False, - ): - assert val == CoincidenceBitmap.detector_hit_str_to_int(detect_string) - - def test_number_of_products(self, hi_test_cal_prod_config_path): - """Test coverage for number of products accessor.""" - df = hi_l1c.CalibrationProductConfig.from_csv(hi_test_cal_prod_config_path) - assert df.cal_prod_config.number_of_products == 2 + mask = hi_l1c.good_time_and_phase_mask(mets, nominal_bins, gt_ds) + assert not np.any(mask) diff --git a/imap_processing/tests/hi/test_hi_l2.py b/imap_processing/tests/hi/test_hi_l2.py index 0305b0fcf2..12bd805147 100644 --- a/imap_processing/tests/hi/test_hi_l2.py +++ b/imap_processing/tests/hi/test_hi_l2.py @@ -1,38 +1,44 @@ """Test coverage for imap_processing.hi.l2.hi_l2.py""" from unittest import mock -from unittest.mock import Mock, patch +from unittest.mock import patch import numpy as np import pytest import xarray as xr -from imap_processing.cdf.utils import write_cdf -from imap_processing.ena_maps.ena_maps import RectangularSkyMap +from imap_processing.cdf.utils import load_cdf, write_cdf +from imap_processing.ena_maps.ena_maps import HealpixSkyMap, RectangularSkyMap +from imap_processing.ena_maps.utils.naming import MapDescriptor from imap_processing.hi.hi_l2 import ( + _calculate_improved_stat_variance, + calculate_all_rates_and_intensities, calculate_ena_intensity, calculate_ena_signal_rates, - esa_energy_lookup, - generate_hi_map, + cleanup_intermediate_variables, + combine_calibration_products, + combine_maps, + create_sky_map_from_psets, + esa_energy_df, hi_l2, + process_single_pset, ) from imap_processing.spice.geometry import SpiceFrame -@pytest.fixture +@pytest.fixture(scope="module") def empty_rectangular_map_dataset() -> xr.Dataset: """Generate an empty rectangular map Dataset with coords only""" coords = { "epoch": 1, - "esa_energy_step": 3, + "esa_energy_step": 9, "calibration_prod": 2, - "longitude": 9, - "latitude": 4, + "spatial": 12, } map_ds = xr.Dataset( coords={ k: xr.DataArray( - np.arange(v), + np.arange(v) + 1 if k == "esa_energy_step" else np.arange(v), name=k, dims=[k], ) @@ -42,19 +48,135 @@ def empty_rectangular_map_dataset() -> xr.Dataset: return map_ds +@pytest.fixture +def esa_energies_lut_path(hi_l1_test_data_path): + return hi_l1_test_data_path / "imap_hi_90sensor-esa-energies_20240101_v001.csv" + + +@pytest.fixture +def geometric_factors_path(hi_l1_test_data_path): + return hi_l1_test_data_path / "imap_hi_90sensor-cal-prod_20240101_v001.csv" + + +@pytest.fixture +def esa_eta_fit_factors_path(imap_tests_path): + return ( + imap_tests_path + / "ena_maps/data/imap_hi_90sensor-esa-eta-fit-factors_20240101_v001.csv" + ) + + +@pytest.fixture +def anc_path_dict( + esa_energies_lut_path, geometric_factors_path, esa_eta_fit_factors_path +): + path_dict = { + "cal-prod": geometric_factors_path, + "esa-energies": esa_energies_lut_path, + "esa-eta-fit-factors": esa_eta_fit_factors_path, + } + return path_dict + + +@pytest.fixture +def sample_map_dataset(): + """Generate a realistic map dataset for testing calibration product combining""" + coords = { + "epoch": 1, + "esa_energy_step": 3, + "calibration_prod": 3, + "longitude": 4, + "latitude": 2, + } + + coords = { + k: xr.DataArray( + np.arange(v) + 1 if k == "esa_energy_step" else np.arange(v), + name=k, + dims=[k], + ) + for k, v in coords.items() + } + + # Create fake geometric factors (different sensitivities) + geometric_factors = xr.DataArray( + np.array([[1.0, 2.0, 0.5], [1.5, 3.0, 0.75], [2.0, 4.0, 1.0]]), + dims=["esa_energy_step", "calibration_prod"], + ) + + # ESA energies + esa_energies = xr.DataArray( + np.array([0.5, 0.75, 1.1]), + dims=["esa_energy_step"], + ) + + # Create sample data with some realistic structure + shape = tuple(darray.size for darray in coords.values()) + + np.random.seed(42) # For reproducible tests + + # Create test dataset + test_ds = xr.Dataset( + { + "ena_signal_rates": xr.DataArray( + np.random.rand(*shape) * 1000 + 100, dims=list(coords.keys()) + ), + "ena_intensity": xr.DataArray( + np.random.rand(*shape) * 100 + 50, dims=list(coords.keys()) + ), + "ena_intensity_stat_uncert": xr.DataArray( + np.random.rand(*shape) * 10 + 5, dims=list(coords.keys()) + ), + "ena_intensity_sys_err": xr.DataArray( + np.random.rand(*shape) * 5 + 1, dims=list(coords.keys()) + ), + "bg_rate": xr.DataArray( + np.random.rand(*shape) * 20 + 5, dims=list(coords.keys()) + ), + "bg_rate_sys_err": xr.DataArray( + np.random.rand(*shape) * 2 + 1, dims=list(coords.keys()) + ), + "exposure_factor": xr.DataArray( + np.random.rand(*shape) * 5 + 1, dims=list(coords.keys()) + ), + }, + coords=coords, + ) + + return test_ds, geometric_factors, esa_energies + + +@pytest.mark.parametrize( + "descriptor_str", + [ + "h90-ena-h-sf-nsp-full-hae-4deg-3mo", + "h90-ena-h-hf-nsp-ram-gcs-6deg-3mo", + ], +) @pytest.mark.external_test_data @pytest.mark.external_kernel -def test_hi_l2(hi_l1_test_data_path, imap_ena_sim_metakernel): +def test_hi_l2( + descriptor_str, + hi_l1_test_data_path, + anc_path_dict, + imap_ena_sim_metakernel, +): """Integration type test for hi_l2()""" pset_path = hi_l1_test_data_path / "imap_hi_l1c_45sensor-pset_20250415_v999.cdf" - esa_energies_lut_path = ( - hi_l1_test_data_path / "imap_hi_90sensor-esa-energies_20240101_v001.csv" - ) + l2_dataset = hi_l2( - [pset_path], None, esa_energies_lut_path, "h90-ena-h-sf-nsp-full-hae-4deg-3mo" + [pset_path], + anc_path_dict, + descriptor_str, )[0] assert isinstance(l2_dataset, xr.Dataset) - assert len(l2_dataset.data_vars) == 15 + + # Check some global attributes + assert l2_dataset.attrs["Data_type"].startswith(f"L2_{descriptor_str}") + assert l2_dataset.attrs["Logical_source"] == f"imap_hi_l2_{descriptor_str}" + assert "Hi90" in l2_dataset.attrs["Logical_source_description"] + + assert len(l2_dataset.data_vars) == 16 np.testing.assert_array_equal( l2_dataset["ena_intensity"].dims, ["epoch", "energy", "longitude", "latitude"] ) @@ -63,80 +185,133 @@ def test_hi_l2(hi_l1_test_data_path, imap_ena_sim_metakernel): @pytest.mark.external_test_data -@patch("imap_processing.hi.hi_l2.generate_hi_map") +@patch( + "imap_processing.ena_maps.ena_maps.RectangularSkyMap.build_cdf_dataset", + autospec=True, +) +@patch("imap_processing.hi.hi_l2.calculate_all_rates_and_intensities") +@patch("imap_processing.hi.hi_l2.create_sky_map_from_psets") def test_hi_l2_uses_descriptor_to_setup_map( - mock_generate_hi_map, + mock_create_sky_map_from_psets, + mock_calculate_all_rates_and_intensities, + mock_map_build_cdf_dataset, hi_l1_test_data_path, ): pset_path = hi_l1_test_data_path / "imap_hi_l1c_45sensor-pset_20250415_v999.cdf" descriptor_str = "h90-ena-h-sf-nsp-full-hnu-2deg-3mo" - rect_map = Mock(spec=RectangularSkyMap) - mock_generate_hi_map.return_value = rect_map + rect_map = MapDescriptor.from_string(descriptor_str).to_empty_map() + # create_sky_map_from_psets returns a dict with spin_phase key + mock_create_sky_map_from_psets.return_value = {"full": rect_map} + # calculate_all_rates_and_intensities modifies and returns the map data + mock_calculate_all_rates_and_intensities.side_effect = lambda ds, *args: ds + mock_map_build_cdf_dataset.return_value = xr.Dataset() - _ = hi_l2([pset_path], None, None, descriptor_str)[0] + _ = hi_l2([pset_path], None, descriptor_str)[0] - output_map = mock_generate_hi_map.call_args.kwargs["output_map"] + assert rect_map.spice_reference_frame == SpiceFrame.IMAP_HNU + assert rect_map.spacing_deg == 2.0 - assert output_map.spice_reference_frame == SpiceFrame.IMAP_HNU - assert output_map.spacing_deg == 2.0 - assert mock_generate_hi_map.call_args.kwargs["spin_phase"] == "full" - assert not mock_generate_hi_map.call_args.kwargs["cg_corrected"] - - rect_map.build_cdf_dataset.assert_called_with( - "hi", "l2", "sf", descriptor_str, sensor="90" + mock_map_build_cdf_dataset.assert_called_with( + rect_map, "hi", "l2", descriptor_str, sensor="90" ) -@mock.patch("imap_processing.hi.hi_l2.calculate_ena_intensity", autospec=True) -@mock.patch("imap_processing.hi.hi_l2.esa_energy_lookup", autospec=True) +@pytest.mark.parametrize( + "descriptor_str, expected_keys", + [ + ("h90-ena-h-sf-nsp-full-gcs-6deg-3mo", ["full"]), + ("h90-ena-h-sf-nsp-ram-gcs-6deg-3mo", ["ram"]), + ("h90-ena-h-hf-nsp-ram-gcs-6deg-3mo", ["ram"]), + ("h90-ena-h-hf-nsp-full-gcs-6deg-3mo", ["ram", "anti"]), + ], +) @pytest.mark.external_test_data -def test_genarate_hi_map( - mock_esa_energy_lookup, - mock_calc_ena_intensity, +def test_create_sky_map_from_psets( hi_l1_test_data_path, + anc_path_dict, furnish_kernels, + descriptor_str, + expected_keys, ): - """Test coverage for genarate_hi_map()""" - - mock_esa_energy_lookup.side_effect = lambda x, y: y - + """Test coverage for create_sky_map_from_psets()""" kernels = [ "imap_sclk_0000.tsc", - "imap_science_100.tf", + "imap_science_120.tf", "naif0012.tls", "imap_spk_demo.bsp", + "de440s.bsp", ] with furnish_kernels(kernels): pset_path = hi_l1_test_data_path / "imap_hi_l1c_45sensor-pset_20250415_v999.cdf" - rectangular_sky_map = RectangularSkyMap( - spacing_deg=6, spice_frame=SpiceFrame.IMAP_GCS - ) - sky_map = generate_hi_map( + map_descriptor = MapDescriptor.from_string(descriptor_str) + sky_maps = create_sky_map_from_psets( [pset_path], - None, - None, - rectangular_sky_map, - cg_corrected=False, - spin_phase="full", + anc_path_dict, + map_descriptor, ) - assert isinstance(sky_map, RectangularSkyMap) - assert sky_map.spacing_deg == 6 - assert sky_map.spice_reference_frame == SpiceFrame.IMAP_GCS - # Check that calculate_ena_intensities was called - mock_calc_ena_intensity.assert_called_once() + # Check that returned dict has expected keys + assert isinstance(sky_maps, dict) + assert set(sky_maps.keys()) == set(expected_keys) + + # Check each map in the dict + for sky_map in sky_maps.values(): + assert isinstance(sky_map, RectangularSkyMap) + assert sky_map.spacing_deg == 6 + assert sky_map.spice_reference_frame == SpiceFrame.IMAP_GCS + + # Check that ESA energy data was added to the map + assert "energy_delta_minus" in sky_map.data_1d + assert "energy_delta_plus" in sky_map.data_1d + assert "energy" in sky_map.data_1d.coords + + # Test that we got some non-zero values + for var_name in ["counts", "exposure_factor", "obs_date"]: + assert var_name in sky_map.data_1d.data_vars + assert np.nanmax(sky_map.data_1d[var_name].data) > 0 + + # If the CG correction ran, check that the energy_sc variable is present + if "-hf-" in descriptor_str: + assert "energy_sc" in sky_map.data_1d.data_vars + assert np.nanmax(sky_map.data_1d["energy_sc"].data) > 0 + + # With a single PSET input, the valid obs_date values should be very close + # to the PSET midpoint. Convert to seconds to set reasonable comparison + # tolerance. + first_map = next(iter(sky_maps.values())) + pset = load_cdf(pset_path) + pset_midpoint = (pset["epoch"].values[0] + pset["epoch_delta"].values[0] / 2) / 1e9 + np.testing.assert_allclose( + np.nanmax(first_map.data_1d["obs_date"].data) / 1e9, + pset_midpoint, + atol=60, + ) - # Test that we got some non-zero values - for var_name in ["counts", "exposure_factor", "obs_date"]: - assert var_name in sky_map.data_1d.data_vars - assert np.nanmax(sky_map.data_1d[var_name].data) > 0 + +def test_create_sky_map_from_psets_healpix_not_supported(): + """Test that NotImplementedError is raised when HealpixSkyMap is returned.""" + # Create a mock descriptor that returns a HealpixSkyMap + mock_descriptor = mock.Mock() + mock_descriptor.frame_descriptor = "sf" + mock_descriptor.spin_phase = "full" + + # Create a mock HealpixSkyMap + mock_healpix_map = mock.Mock(spec=HealpixSkyMap) + mock_descriptor.to_empty_map.return_value = mock_healpix_map + + with pytest.raises(NotImplementedError, match="Healpix map output not supported"): + create_sky_map_from_psets( + ["fake_pset.cdf"], # non-empty psets list + {}, # empty ancillary dict + mock_descriptor, + ) def test_calculate_ena_signal_rates(empty_rectangular_map_dataset): """Test coverage for calculate_ena_signal_rates""" # Start with an empty (coords only) dataset - map_ds = empty_rectangular_map_dataset + map_ds = empty_rectangular_map_dataset.copy() # Add some data_vars needed for the signal rates calculations counts_shape = tuple(map_ds.sizes.values()) exposure_sizes = {k: v for k, v in map_ds.sizes.items() if k != "calibration_prod"} @@ -158,35 +333,35 @@ def test_calculate_ena_signal_rates(empty_rectangular_map_dataset): name="exposure_factor", dims=list(exposure_sizes.keys()), ), - "bg_rates": xr.DataArray( + "bg_rate": xr.DataArray( np.arange(np.prod(tuple(map_ds.sizes.values()))).reshape(counts_shape) % 2, - name="bg_rates", + name="bg_rate", dims=list(map_ds.sizes.keys()), ), } ) - signal_rates_vars = calculate_ena_signal_rates(map_ds) + result_ds = calculate_ena_signal_rates(map_ds) + # Function now returns the modified dataset + assert isinstance(result_ds, xr.Dataset) for var_name in ["ena_signal_rates", "ena_signal_rate_stat_unc"]: - assert var_name in signal_rates_vars - assert signal_rates_vars[var_name].shape == counts_shape + assert var_name in result_ds + assert result_ds[var_name].shape == counts_shape # Verify that there are no negative signal rates. The synthetic data combination - # where counts = 0, exposure_factor = 1, and bg_rates = 1 would result in + # where counts = 0, exposure_factor = 1, and bg_rate = 1 would result in # an ena_signal_rate of (0 / 1) - 1 = -1 - assert np.nanmin(signal_rates_vars["ena_signal_rates"].values) >= 0 + assert np.nanmin(result_ds["ena_signal_rates"].values) >= 0 # Verify that the minimum finite uncertainty is sqrt(1) / exposure_factor. # The max exposure factor is 2, so we can expect the minimum finite # uncertainty value to be 1/2. - assert np.nanmin(signal_rates_vars["ena_signal_rate_stat_unc"].values) == 1 / 2 + assert np.nanmin(result_ds["ena_signal_rate_stat_unc"].values) == 1 / 2 -def test_calculate_ena_intensity(empty_rectangular_map_dataset, hi_l1_test_data_path): - """Test coverage for calculate_ena_intensity""" - esa_energies_lut_path = ( - hi_l1_test_data_path / "imap_hi_90sensor-esa-energies_20240101_v001.csv" - ) +@pytest.fixture(scope="module") +def ena_intensity_map_ds(empty_rectangular_map_dataset): + """Fixture that produces a dataset to use in testing ena_intensity.""" # Start with an empty (coords only) dataset - map_ds = empty_rectangular_map_dataset + map_ds = empty_rectangular_map_dataset.copy() # Add some data_vars needed for the ena intensity calculations var_shape = tuple(map_ds.sizes.values()) map_ds.update( @@ -202,30 +377,1221 @@ def test_calculate_ena_intensity(empty_rectangular_map_dataset, hi_l1_test_data_ name="ena_signal_rate_stat_unc", dims=list(map_ds.sizes.keys()), ), - "bg_rates_unc": xr.DataArray( + "bg_rate_sys_err": xr.DataArray( np.arange(np.prod(tuple(map_ds.sizes.values()))).reshape(var_shape) % 3, - name="bg_rates_unc", + name="bg_rate_sys_err", dims=list(map_ds.sizes.keys()), ), } ) - ena_intesity_vars = calculate_ena_intensity(map_ds, None, esa_energies_lut_path) - # TODO: add value/functional test checks once the full algorithm is implemented + # Add required background data + bg_shape = tuple( + map_ds.sizes[k] for k in map_ds.sizes.keys() if k != "calibration_prod" + ) + map_ds.update( + { + "bg_rate": xr.DataArray( + np.ones(bg_shape) * 5.0, + dims=[d for d in map_ds.sizes.keys() if d != "calibration_prod"], + ), + "exposure_factor": xr.DataArray( + np.ones(bg_shape) * 2.0, + dims=[d for d in map_ds.sizes.keys() if d != "calibration_prod"], + ), + } + ) + return map_ds + + +def test_calculate_ena_intensity(ena_intensity_map_ds, anc_path_dict): + """Test coverage for calculate_ena_intensity""" + descriptor_str = "h90-ena-h-sf-nsp-full-gcs-6deg-3mo" + map_descriptor = MapDescriptor.from_string(descriptor_str) + + result_ds = calculate_ena_intensity( + ena_intensity_map_ds, anc_path_dict, map_descriptor + ) + for var_name in [ "ena_intensity", - "ena_intensity_stat_unc", + "ena_intensity_stat_uncert", "ena_intensity_sys_err", ]: - assert var_name in ena_intesity_vars + assert var_name in result_ds + # Check that calibration_prod dimension has been removed + assert "calibration_prod" not in result_ds[var_name].dims -def test_esa_energy_lookup(hi_l1_test_data_path): - """Test coverage for esa_energy_lookup()""" - lookup_file = ( - hi_l1_test_data_path / "imap_hi_90sensor-esa-energies_20240101_v001.csv" +@pytest.mark.parametrize( + "descriptor_str, flux_corrected", + [ + ("h90-ena-h-sf-nsp-anti-gcs-6deg-3mo", True), + ("h90-enaraw-h-hf-nsp-ram-gcs-6deg-3mo", False), + ], +) +@mock.patch("imap_processing.hi.hi_l2.PowerLawFluxCorrector", autospec=True) +def test_calculate_ena_intensity_flux_correction_logic( + mock_flux_corrector_class, + descriptor_str, + flux_corrected, + ena_intensity_map_ds, + anc_path_dict, +): + """Test that flux correction is applied based on map descriptor.""" + # Create a mock instance that will be returned when PowerLawFluxCorrector + # is instantiated + mock_instance = mock_flux_corrector_class.return_value + mock_instance.apply_flux_correction.side_effect = ( + lambda intensity, stat_unc, energy: (intensity, stat_unc) + ) + + map_descriptor = MapDescriptor.from_string(descriptor_str) + _ = calculate_ena_intensity(ena_intensity_map_ds, anc_path_dict, map_descriptor) + + # Now check if the method was called based on the flux_corrected expectation + if flux_corrected: + mock_instance.apply_flux_correction.assert_called_once() + else: + mock_instance.apply_flux_correction.assert_not_called() + + +def test_combine_calibration_products(sample_map_dataset): + """Test coverage for combine_calibration_products""" + test_ds, geometric_factors, esa_energies = sample_map_dataset + + # Make a copy to avoid modifying the fixture + test_ds_copy = test_ds.copy(deep=True) + + result_ds = combine_calibration_products( + test_ds_copy, geometric_factors, esa_energies + ) + + # Check that all expected variables are present + expected_vars = [ + "ena_intensity", + "ena_intensity_stat_uncert", + "ena_intensity_sys_err", + ] + for var_name in expected_vars: + assert var_name in result_ds + # Check that calibration_prod dimension has been removed + assert "calibration_prod" not in result_ds[var_name].dims + # Check that other dimensions are preserved + expected_dims = [ + d for d in test_ds["ena_intensity"].dims if d != "calibration_prod" + ] + assert list(result_ds[var_name].dims) == expected_dims + + # Check that combined flux is finite where input data is valid + combined_flux = result_ds["ena_intensity"] + assert np.any(np.isfinite(combined_flux.values)), ( + "No valid combined flux values produced" ) + + # Check that combined uncertainty is reasonable + combined_unc = result_ds["ena_intensity_stat_uncert"] + assert np.all(combined_unc.values[np.isfinite(combined_unc.values)] >= 0), ( + "Combined uncertainty should be non-negative" + ) + + # Check systematic error combination (root sum of squares) + input_sys_err = test_ds["ena_intensity_sys_err"] + expected_sys_err = np.sqrt((input_sys_err**2).sum(dim="calibration_prod")) + combined_sys_err = result_ds["ena_intensity_sys_err"] + + np.testing.assert_array_almost_equal( + combined_sys_err.values, expected_sys_err.values, decimal=10 + ) + + +def test_calculate_improved_variance(sample_map_dataset): + """Test _calculate_improved_stat_variance function""" + test_ds, geometric_factors, esa_energies = sample_map_dataset + + improved_unc = _calculate_improved_stat_variance( + test_ds, geometric_factors, esa_energies + ) + + # Check that result has same shape as input statistical uncertainties + original_unc = test_ds["ena_intensity_stat_uncert"] + assert improved_unc.shape == original_unc.shape + + # Check that improved uncertainties are finite and non-negative + assert np.all(improved_unc.values >= 0) + assert np.all(np.isfinite(improved_unc.values)) + + +def test_calculate_improved_variance_single_product(): + """Test improved variance with single calibration product""" + coords = { + "epoch": 1, + "esa_energy_step": 1, + "calibration_prod": 1, + "longitude": 1, + "latitude": 1, + } + + geom_factors = xr.DataArray( + np.array([[1.0]]), dims=["esa_energy_step", "calibration_prod"] + ) + + esa_energies = xr.DataArray(np.array([1.0]), dims=["esa_energy_step"]) + + test_ds = xr.Dataset( + { + "ena_intensity": xr.DataArray( + np.array([[[[[100.0]]]]]), dims=list(coords.keys()) + ), + "ena_intensity_stat_uncert": xr.DataArray( + np.array([[[[[10.0]]]]]), dims=list(coords.keys()) + ), + } + ) + + improved_var = _calculate_improved_stat_variance( + test_ds, geom_factors, esa_energies + ) + + # With single product, should return original uncertainties + np.testing.assert_array_equal( + improved_var.values, test_ds["ena_intensity_stat_uncert"].values ** 2 + ) + + +def test_esa_energy_lookup(esa_energies_lut_path): + """Test coverage for esa_energy_df()""" esa_energy_steps = np.array([1, 2, 3, 3, 7, 8, 9]) expected_energies = np.array([0.5, 0.75, 1.1, 1.1, 5.7, 8.52, 12.8]) - retrieved_energies = esa_energy_lookup(lookup_file, esa_energy_steps) + energy_df = esa_energy_df(esa_energies_lut_path, esa_energy_steps) + retrieved_energies = energy_df["nominal_central_energy"].values np.testing.assert_array_equal(retrieved_energies, expected_energies) + assert "bandpass_fwhm" in energy_df + + +def test_weighted_average_mathematical_correctness(): + """Test mathematical properties of the weighted average""" + # Create a simple test case where we can verify the weighted average manually + coords = { + "epoch": 1, + "esa_energy_step": 1, + "calibration_prod": 2, + "longitude": 1, + "latitude": 1, + } + + # Simple test data + flux_values = np.array([100.0, 200.0]).reshape(1, 1, 2, 1, 1) + stat_unc_values = np.array([10.0, 20.0]).reshape(1, 1, 2, 1, 1) + sys_err_values = np.array([5.0, 10.0]).reshape(1, 1, 2, 1, 1) + + test_ds = xr.Dataset( + { + "ena_intensity": xr.DataArray(flux_values, dims=list(coords.keys())), + "ena_intensity_stat_uncert": xr.DataArray( + stat_unc_values, dims=list(coords.keys()) + ), + "ena_intensity_sys_err": xr.DataArray( + sys_err_values, dims=list(coords.keys()) + ), + "ena_signal_rates": xr.DataArray( + np.array([100.0, 400.0]).reshape(1, 1, 2, 1, 1), + dims=list(coords.keys()), + ), + "bg_rate": xr.DataArray( + np.array([5.0]).reshape(1, 1, 1, 1), + dims=[d for d in coords.keys() if d != "calibration_prod"], + ), + "exposure_factor": xr.DataArray( + np.array([2.0]).reshape(1, 1, 1, 1), + dims=[d for d in coords.keys() if d != "calibration_prod"], + ), + } + ) + + geom_factors = xr.DataArray( + np.array([[1.0, 2.0]]), dims=["esa_energy_step", "calibration_prod"] + ) + + esa_energies = xr.DataArray(np.array([1.0]), dims=["esa_energy_step"]) + + result_ds = combine_calibration_products(test_ds, geom_factors, esa_energies) + + # Check that results are finite and reasonable + assert np.isfinite(result_ds["ena_intensity"].values[0, 0, 0, 0]) + assert result_ds["ena_intensity_stat_uncert"].values[0, 0, 0, 0] > 0 + assert result_ds["ena_intensity_sys_err"].values[0, 0, 0, 0] > 0 + + # Systematic error should be root sum of squares + expected_sys_err = np.sqrt(5.0**2 + 10.0**2) + np.testing.assert_almost_equal( + result_ds["ena_intensity_sys_err"].values[0, 0, 0, 0], + expected_sys_err, + decimal=10, + ) + + +def test_statistical_uncertainty_combination_correctness(): + """Test that statistical uncertainties are combined correctly.""" + coords = { + "epoch": 1, + "esa_energy_step": 1, + "calibration_prod": 2, + "longitude": 1, + "latitude": 1, + } + + # Create simple case with known statistical uncertainties + stat_unc_values = np.array([5.0, 10.0]).reshape(1, 1, 2, 1, 1) + sys_err_values = np.array([2.0, 4.0]).reshape(1, 1, 2, 1, 1) + flux_values = np.array([90.0, 210.0]).reshape(1, 1, 2, 1, 1) + + test_ds = xr.Dataset( + { + "ena_intensity": xr.DataArray(flux_values, dims=list(coords.keys())), + "ena_intensity_stat_uncert": xr.DataArray( + stat_unc_values, dims=list(coords.keys()) + ), + "ena_intensity_sys_err": xr.DataArray( + sys_err_values, dims=list(coords.keys()) + ), + "ena_signal_rates": xr.DataArray(flux_values, dims=list(coords.keys())), + "bg_rate": xr.DataArray( + np.array([1.0, 2.0]).reshape(1, 1, 2, 1, 1), dims=list(coords.keys()) + ), + "exposure_factor": xr.DataArray( + np.array([1.0, 1.0]).reshape(1, 1, 2, 1, 1), dims=list(coords.keys()) + ), + } + ) + + geom_factors = xr.DataArray( + np.array([[1.0, 2.0]]), + dims=["esa_energy_step", "calibration_prod"], + ) + + esa_energies = xr.DataArray(np.array([1.0]), dims=["esa_energy_step"]) + + result_ds = combine_calibration_products(test_ds, geom_factors, esa_energies) + + # Manual calculation of expected statistical uncertainty combination + # combined_stat_unc = sqrt(1/sum(1 / stat_unc**2)) + expected_combined_stat_unc = np.sqrt(1 / np.sum(1 / stat_unc_values**2)) + flux_weights = 1.0 / np.array([101, 101]) + expected_flux = np.sum(flux_values.squeeze() * flux_weights) / np.sum(flux_weights) + + np.testing.assert_almost_equal( + result_ds["ena_intensity_stat_uncert"].values, + expected_combined_stat_unc, + decimal=10, + ) + + np.testing.assert_almost_equal( + result_ds["ena_intensity"].values, expected_flux, decimal=10 + ) + + +def test_combine_calibration_products_edge_cases(): + """Test edge cases for combine_calibration_products""" + # Test with single calibration product + coords = { + "epoch": 1, + "esa_energy_step": 1, + "calibration_prod": 1, + "longitude": 1, + "latitude": 1, + } + + test_ds = xr.Dataset( + { + "ena_intensity": xr.DataArray( + np.array([100.0]).reshape(1, 1, 1, 1, 1), dims=list(coords.keys()) + ), + "ena_intensity_stat_uncert": xr.DataArray( + np.array([10.0]).reshape(1, 1, 1, 1, 1), dims=list(coords.keys()) + ), + "ena_intensity_sys_err": xr.DataArray( + np.array([5.0]).reshape(1, 1, 1, 1, 1), dims=list(coords.keys()) + ), + } + ) + + geom_factors = xr.DataArray( + np.array([[1.0]]), dims=["esa_energy_step", "calibration_prod"] + ) + + esa_energies = xr.DataArray(np.array([1.0]), dims=["esa_energy_step"]) + + result_ds = combine_calibration_products(test_ds, geom_factors, esa_energies) + + # With single calibration product, should return dataset unchanged + # (but without calib_prod dim). The intensity value should be the same. + np.testing.assert_almost_equal(result_ds["ena_intensity"].values[0, 0, 0, 0], 100.0) + + # Check that calibration_prod dimension was removed + for var in ["ena_intensity", "ena_intensity_stat_uncert", "ena_intensity_sys_err"]: + assert "calibration_prod" not in result_ds[var].dims + + +def test_combine_calibration_products_nan_handling(): + """Test that combine_calibration_products handles NaN values correctly. + + Tests the skipna=True, min_count=1 behavior: + - When one calibration product has NaN, the result should use the valid values + - When ALL calibration products have NaN at a position, the result should be NaN + """ + # Create test dataset with 2 calibration products + coords = { + "epoch": 1, + "esa_energy_step": 2, + "calibration_prod": 2, + "longitude": 2, + "latitude": 1, + } + + # Shape: (1, 2, 2, 2, 1) - epoch, energy, cal_prod, lon, lat + shape = (1, 2, 2, 2, 1) + + # Create base arrays with valid values + intensity = np.full(shape, 100.0) + stat_uncert = np.full(shape, 10.0) + sys_err = np.full(shape, 5.0) + signal_rates = np.full(shape, 500.0) + bg_rate = np.full(shape, 20.0) + bg_rate_sys_err = np.full(shape, 2.0) + exposure_factor = np.full(shape, 1.0) + + # Set NaN in one calibration product's uncertainty at position [0,0,0,0,0] + # The other calibration product is valid, so result should be finite + stat_uncert[0, 0, 0, 0, 0] = np.nan + + # Set NaN in both calibration products at position [0,1,:,0,0] + # Since ALL products have NaN, result should be NaN (due to min_count=1) + stat_uncert[0, 1, 0, 0, 0] = np.nan + stat_uncert[0, 1, 1, 0, 0] = np.nan + + # Set NaN in sys_err for one product at position [0,0,0,1,0] + sys_err[0, 0, 0, 1, 0] = np.nan + + # Set NaN in sys_err for both products at position [0,1,:,1,0] + sys_err[0, 1, 0, 1, 0] = np.nan + sys_err[0, 1, 1, 1, 0] = np.nan + + dim_names = list(coords.keys()) + test_ds = xr.Dataset( + { + "ena_intensity": xr.DataArray(intensity, dims=dim_names), + "ena_intensity_stat_uncert": xr.DataArray(stat_uncert, dims=dim_names), + "ena_intensity_sys_err": xr.DataArray(sys_err, dims=dim_names), + "ena_signal_rates": xr.DataArray(signal_rates, dims=dim_names), + "bg_rate": xr.DataArray(bg_rate, dims=dim_names), + "bg_rate_sys_err": xr.DataArray(bg_rate_sys_err, dims=dim_names), + "exposure_factor": xr.DataArray(exposure_factor, dims=dim_names), + } + ) + + geom_factors = xr.DataArray( + np.ones((2, 2)), dims=["esa_energy_step", "calibration_prod"] + ) + + esa_energies = xr.DataArray(np.array([1.0, 2.0]), dims=["esa_energy_step"]) + + result_ds = combine_calibration_products(test_ds, geom_factors, esa_energies) + + # Test 1: When one product has NaN stat_uncert, result should be finite + # (skipna=True uses the valid value from the other product) + assert np.isfinite(result_ds["ena_intensity_stat_uncert"].values[0, 0, 0, 0]) + + # Test 2: When ALL products have NaN stat_uncert, result should be NaN + # (min_count=1 ensures at least one valid value is needed) + assert np.isnan(result_ds["ena_intensity_stat_uncert"].values[0, 1, 0, 0]) + + # Test 3: When one product has NaN sys_err, result should be finite + assert np.isfinite(result_ds["ena_intensity_sys_err"].values[0, 0, 1, 0]) + + # Test 4: When ALL products have NaN sys_err, result should be NaN + assert np.isnan(result_ds["ena_intensity_sys_err"].values[0, 1, 1, 0]) + + +# ============================================================================= +# PSET PROCESSING TESTS +# ============================================================================= + + +@pytest.fixture +def mock_pset_dataset(): + """Create a mock PSET dataset for testing process_single_pset.""" + n_spin_bins = 10 + n_energy = 3 + n_cal_prod = 2 + + coords = { + "epoch": [0], + "esa_energy_step": [1, 2, 3], + "calibration_prod": [1, 2], + "spin_angle_bin": np.arange(n_spin_bins), + } + + # exposure_times has dims: epoch, esa_energy_step, + # spin_angle_bin (no calibration_prod) + exposure_shape = (1, n_energy, n_spin_bins) + # Other variables have all dims + full_shape = (1, n_energy, n_cal_prod, n_spin_bins) + + pset = xr.Dataset( + { + # Variables that get renamed by l1c_to_l2_var_mapping + "exposure_times": xr.DataArray( + np.ones(exposure_shape) * 100.0, + dims=["epoch", "esa_energy_step", "spin_angle_bin"], + ), + "background_rates": xr.DataArray( + np.ones(full_shape) * 5.0, + dims=["epoch", "esa_energy_step", "calibration_prod", "spin_angle_bin"], + ), + "background_rates_uncertainty": xr.DataArray( + np.ones(full_shape) * 1.0, + dims=["epoch", "esa_energy_step", "calibration_prod", "spin_angle_bin"], + ), + "counts": xr.DataArray( + np.ones(full_shape) * 50.0, + dims=["epoch", "esa_energy_step", "calibration_prod", "spin_angle_bin"], + ), + "epoch_delta": xr.DataArray([1000000000], dims=["epoch"]), # 1 second in ns + "hae_latitude": xr.DataArray( + np.zeros((1, n_spin_bins)), dims=["epoch", "spin_angle_bin"] + ), + "hae_longitude": xr.DataArray( + np.linspace(0, 360, n_spin_bins).reshape(1, -1), + dims=["epoch", "spin_angle_bin"], + ), + }, + coords=coords, + ) + return pset + + +@mock.patch("imap_processing.hi.hi_l2.calculate_ram_mask") +@mock.patch("imap_processing.hi.hi_l2.add_spacecraft_position_and_velocity_to_pset") +def test_process_single_pset_renames_variables( + mock_add_velocity, mock_calc_ram_mask, mock_pset_dataset +): + """Test that process_single_pset renames L1C variables to L2 names.""" + # Mock the external functions to avoid needing SPICE kernels + mock_add_velocity.side_effect = lambda ds: ds + mock_calc_ram_mask.side_effect = lambda ds: ds.assign( + ram_mask=xr.zeros_like(ds["hae_longitude"], dtype=bool) + ) + + descriptor = MapDescriptor.from_string("h90-ena-h-sf-nsp-full-gcs-6deg-3mo") + energy_kev = xr.DataArray([0.5, 0.75, 1.1], dims=["esa_energy_step"]) + + result = process_single_pset( + mock_pset_dataset, + energy_kev, + descriptor, + vars_to_exposure_time_average=set(), + ) + + # Check that variables were renamed + assert "exposure_factor" in result + assert "bg_rate" in result + assert "bg_rate_sys_err" in result + # Original names should not exist + assert "exposure_times" not in result + assert "background_rates" not in result + assert "background_rates_uncertainty" not in result + + +@mock.patch("imap_processing.hi.hi_l2.calculate_ram_mask") +@mock.patch("imap_processing.hi.hi_l2.add_spacecraft_position_and_velocity_to_pset") +def test_process_single_pset_adds_obs_date( + mock_add_velocity, mock_calc_ram_mask, mock_pset_dataset +): + """Test that process_single_pset adds obs_date variable.""" + mock_add_velocity.side_effect = lambda ds: ds + mock_calc_ram_mask.side_effect = lambda ds: ds.assign( + ram_mask=xr.zeros_like(ds["hae_longitude"]) + ) + + descriptor = MapDescriptor.from_string("h90-ena-h-sf-nsp-full-gcs-6deg-3mo") + energy_kev = xr.DataArray([0.5, 0.75, 1.1], dims=["esa_energy_step"]) + + result = process_single_pset( + mock_pset_dataset, + energy_kev, + descriptor, + vars_to_exposure_time_average=set(), + ) + + assert "obs_date" in result + # obs_date should be the midpoint of the epoch (epoch + epoch_delta/2) + expected_mid_time = ( + mock_pset_dataset["epoch"].values[0] + 500000000 + ) # half of 1 second + assert result["obs_date"].values.flat[0] == expected_mid_time + + +@mock.patch("imap_processing.hi.hi_l2.calculate_ram_mask") +@mock.patch("imap_processing.hi.hi_l2.add_spacecraft_position_and_velocity_to_pset") +def test_process_single_pset_exposure_time_weighting( + mock_add_velocity, mock_calc_ram_mask, mock_pset_dataset +): + """Test that variables are multiplied by exposure_factor for weighted averaging.""" + mock_add_velocity.side_effect = lambda ds: ds + mock_calc_ram_mask.side_effect = lambda ds: ds.assign( + ram_mask=xr.zeros_like(ds["hae_longitude"]) + ) + + descriptor = MapDescriptor.from_string("h90-ena-h-sf-nsp-full-gcs-6deg-3mo") + energy_kev = xr.DataArray([0.5, 0.75, 1.1], dims=["esa_energy_step"]) + + # bg_rate should be multiplied by exposure_factor + result = process_single_pset( + mock_pset_dataset, + energy_kev, + descriptor, + vars_to_exposure_time_average={"bg_rate"}, + ) + + # bg_rate was 5.0, exposure_factor is 100.0, so result should be 500.0 + assert np.allclose(result["bg_rate"].values, 500.0) + + +@mock.patch("imap_processing.hi.hi_l2.calculate_ram_mask") +@mock.patch("imap_processing.hi.hi_l2.add_spacecraft_position_and_velocity_to_pset") +def test_process_single_pset_calls_velocity_and_ram_mask( + mock_add_velocity, mock_calc_ram_mask, mock_pset_dataset +): + """Test that spacecraft velocity and ram mask functions are called.""" + mock_add_velocity.side_effect = lambda ds: ds.assign( + sc_velocity_x=xr.DataArray([1.0], dims=["epoch"]) + ) + mock_calc_ram_mask.side_effect = lambda ds: ds.assign( + ram_mask=xr.zeros_like(ds["hae_longitude"]) + ) + + descriptor = MapDescriptor.from_string("h90-ena-h-sf-nsp-full-gcs-6deg-3mo") + energy_kev = xr.DataArray([0.5, 0.75, 1.1], dims=["esa_energy_step"]) + + result = process_single_pset( + mock_pset_dataset, + energy_kev, + descriptor, + vars_to_exposure_time_average=set(), + ) + + # Both functions should have been called + mock_add_velocity.assert_called_once() + mock_calc_ram_mask.assert_called_once() + # Check that their outputs are in the result + assert "sc_velocity_x" in result + assert "ram_mask" in result + + +@mock.patch("imap_processing.hi.hi_l2.apply_compton_getting_correction") +@mock.patch("imap_processing.hi.hi_l2.calculate_ram_mask") +@mock.patch("imap_processing.hi.hi_l2.add_spacecraft_position_and_velocity_to_pset") +def test_process_single_pset_applies_cg_for_hf_frame( + mock_add_velocity, mock_calc_ram_mask, mock_apply_cg, mock_pset_dataset +): + """Test that CG correction is applied for heliocentric frame.""" + mock_add_velocity.side_effect = lambda ds: ds + mock_calc_ram_mask.side_effect = lambda ds: ds.assign( + ram_mask=xr.zeros_like(ds["exposure_factor"]) + ) + mock_apply_cg.side_effect = lambda ds, energies: ds.assign( + energy_sc=xr.full_like(ds["exposure_factor"], 1000.0) + ) + + # Use hf (heliocentric frame) descriptor + descriptor = MapDescriptor.from_string("h90-ena-h-hf-nsp-full-gcs-6deg-3mo") + energy_kev = xr.DataArray([0.5, 0.75, 1.1], dims=["esa_energy_step"]) + + result = process_single_pset( + mock_pset_dataset, + energy_kev, + descriptor, + vars_to_exposure_time_average=set(), + ) + + # CG correction should have been called for hf frame + mock_apply_cg.assert_called_once() + assert "energy_sc" in result + + +@mock.patch("imap_processing.hi.hi_l2.apply_compton_getting_correction") +@mock.patch("imap_processing.hi.hi_l2.calculate_ram_mask") +@mock.patch("imap_processing.hi.hi_l2.add_spacecraft_position_and_velocity_to_pset") +def test_process_single_pset_no_cg_for_sf_frame( + mock_add_velocity, mock_calc_ram_mask, mock_apply_cg, mock_pset_dataset +): + """Test that CG correction is NOT applied for spacecraft frame.""" + mock_add_velocity.side_effect = lambda ds: ds + mock_calc_ram_mask.side_effect = lambda ds: ds.assign( + ram_mask=xr.zeros_like(ds["exposure_factor"]) + ) + + # Use sf (spacecraft frame) descriptor + descriptor = MapDescriptor.from_string("h90-ena-h-sf-nsp-full-gcs-6deg-3mo") + energy_kev = xr.DataArray([0.5, 0.75, 1.1], dims=["esa_energy_step"]) + + _ = process_single_pset( + mock_pset_dataset, + energy_kev, + descriptor, + vars_to_exposure_time_average=set(), + ) + + # CG correction should NOT have been called for sf frame + mock_apply_cg.assert_not_called() + + +# ============================================================================= +# CALCULATE ALL RATES AND INTENSITIES TESTS +# ============================================================================= + + +@pytest.fixture +def mock_map_dataset_for_rates(): + """Create a mock map dataset for testing calculate_all_rates_and_intensities. + + This fixture includes the ESA energy data (energy_delta_minus, energy_delta_plus, + energy coordinate) that would normally be added by create_sky_map_from_psets. + """ + # ESA energy data (would be added by create_sky_map_from_psets) + bandpass_fwhm = np.array([0.1, 0.15, 0.2]) + energy_delta = bandpass_fwhm / 2 + energy_kev = np.array([0.5, 0.75, 1.1]) + + coords = { + "epoch": [0], + "esa_energy_step": [1, 2, 3], + "calibration_prod": [1, 2], + "longitude": np.arange(4), + "latitude": np.arange(2), + # Energy as auxiliary coordinate indexed by esa_energy_step + "energy": ("esa_energy_step", energy_kev), + } + shape = (1, 3, 2, 4, 2) + exposure_shape = (1, 3, 4, 2) # no calibration_prod dim + + map_ds = xr.Dataset( + { + "counts": xr.DataArray( + np.ones(shape) * 100.0, dims=list(coords.keys())[:5] + ), + "exposure_factor": xr.DataArray( + np.ones(exposure_shape) * 10.0, + dims=["epoch", "esa_energy_step", "longitude", "latitude"], + ), + "bg_rate": xr.DataArray(np.ones(shape) * 2.0, dims=list(coords.keys())[:5]), + "bg_rate_sys_err": xr.DataArray( + np.ones(shape) * 0.5, dims=list(coords.keys())[:5] + ), + "obs_date": xr.DataArray( + np.ones(exposure_shape) * 1e18, + dims=["epoch", "esa_energy_step", "longitude", "latitude"], + ), + "esa_energy_step_label": xr.DataArray( + ["1", "2", "3"], dims=["esa_energy_step"] + ), + # ESA energy data added by create_sky_map_from_psets + "energy_delta_minus": xr.DataArray(energy_delta, dims=["esa_energy_step"]), + "energy_delta_plus": xr.DataArray(energy_delta, dims=["esa_energy_step"]), + }, + coords=coords, + ) + return map_ds + + +def test_calculate_all_rates_and_intensities_basic( + mock_map_dataset_for_rates, anc_path_dict +): + """Test basic functionality of calculate_all_rates_and_intensities.""" + descriptor = MapDescriptor.from_string("h90-ena-h-sf-nsp-full-gcs-6deg-3mo") + + result = calculate_all_rates_and_intensities( + mock_map_dataset_for_rates, + anc_path_dict, + descriptor, + ) + + # Check that intensities were calculated + assert "ena_intensity" in result + assert "ena_intensity_stat_uncert" in result + assert "ena_intensity_sys_err" in result + + +def test_calculate_all_rates_and_intensities_renames_energy_coord( + mock_map_dataset_for_rates, anc_path_dict +): + """Test that esa_energy_step is renamed to energy.""" + descriptor = MapDescriptor.from_string("h90-ena-h-sf-nsp-full-gcs-6deg-3mo") + + result = calculate_all_rates_and_intensities( + mock_map_dataset_for_rates, + anc_path_dict, + descriptor, + ) + + # energy coordinate should exist + assert "energy" in result.coords + # esa_energy_step should not exist as a coordinate + assert "esa_energy_step" not in result.coords + # esa_energy_step_label should be dropped + assert "esa_energy_step_label" not in result + + +def test_calculate_all_rates_and_intensities_preserves_energy_deltas( + mock_map_dataset_for_rates, anc_path_dict +): + """Test that energy delta variables are preserved through calculation.""" + descriptor = MapDescriptor.from_string("h90-ena-h-sf-nsp-full-gcs-6deg-3mo") + + # Get the original energy deltas from the input dataset + original_deltas = mock_map_dataset_for_rates["energy_delta_minus"].values.copy() + + result = calculate_all_rates_and_intensities( + mock_map_dataset_for_rates, + anc_path_dict, + descriptor, + ) + + # Energy delta variables should be present and unchanged + assert "energy_delta_minus" in result + assert "energy_delta_plus" in result + np.testing.assert_array_almost_equal( + result["energy_delta_minus"].values, original_deltas + ) + np.testing.assert_array_almost_equal( + result["energy_delta_plus"].values, original_deltas + ) + + +def test_calculate_all_rates_and_intensities_adds_obs_date_range( + mock_map_dataset_for_rates, anc_path_dict +): + """Test that obs_date_range is added.""" + descriptor = MapDescriptor.from_string("h90-ena-h-sf-nsp-full-gcs-6deg-3mo") + + result = calculate_all_rates_and_intensities( + mock_map_dataset_for_rates, + anc_path_dict, + descriptor, + ) + + # obs_date_range should be present + assert "obs_date_range" in result + + +@mock.patch( + "imap_processing.hi.hi_l2.interpolate_map_flux_to_helio_frame", autospec=True +) +def test_calculate_all_rates_and_intensities_cg_correction( + mock_interp_flux, mock_map_dataset_for_rates, anc_path_dict +): + """Test that CG interpolation is applied for heliocentric frame.""" + mock_interp_flux.side_effect = lambda ds, *args, **kwargs: ds + + descriptor = MapDescriptor.from_string("h90-ena-h-hf-nsp-full-gcs-6deg-3mo") + + _ = calculate_all_rates_and_intensities( + mock_map_dataset_for_rates, + anc_path_dict, + descriptor, + ) + + # interpolate_map_flux_to_helio_frame should have been called for hf frame + mock_interp_flux.assert_called_once() + + +@mock.patch("imap_processing.hi.hi_l2.interpolate_map_flux_to_helio_frame") +def test_calculate_all_rates_and_intensities_no_cg_for_sf( + mock_interp_flux, mock_map_dataset_for_rates, anc_path_dict +): + """Test that CG interpolation is NOT applied for spacecraft frame.""" + mock_interp_flux.side_effect = lambda ds, *args: ds + + descriptor = MapDescriptor.from_string("h90-ena-h-sf-nsp-full-gcs-6deg-3mo") + + _ = calculate_all_rates_and_intensities( + mock_map_dataset_for_rates, + anc_path_dict, + descriptor, + ) + + # interpolate_map_flux_to_helio_frame should NOT have been called for sf frame + mock_interp_flux.assert_not_called() + + +# ============================================================================= +# CLEANUP INTERMEDIATE VARIABLES TESTS +# ============================================================================= + + +def test_cleanup_intermediate_variables(): + """Test that cleanup_intermediate_variables removes expected variables.""" + # Create a dataset with intermediate variables + ds = xr.Dataset( + { + "bg_rate": xr.DataArray([1, 2, 3], dims=["x"]), + "energy_sc": xr.DataArray([4, 5, 6], dims=["x"]), + "ena_signal_rates": xr.DataArray([7, 8, 9], dims=["x"]), + "ena_signal_rate_stat_unc": xr.DataArray([0.1, 0.2, 0.3], dims=["x"]), + "ena_intensity": xr.DataArray([10, 20, 30], dims=["x"]), + "exposure_factor": xr.DataArray([100, 200, 300], dims=["x"]), + } + ) + + result = cleanup_intermediate_variables(ds) + + # Intermediate variables should be removed + assert "bg_rate" not in result + assert "energy_sc" not in result + assert "ena_signal_rates" not in result + assert "ena_signal_rate_stat_unc" not in result + + # Non-intermediate variables should remain + assert "ena_intensity" in result + assert "exposure_factor" in result + + +def test_cleanup_intermediate_variables_missing_vars(): + """Test cleanup works when some intermediate variables don't exist.""" + # Create a dataset without all intermediate variables + ds = xr.Dataset( + { + "bg_rate": xr.DataArray([1, 2, 3], dims=["x"]), + "ena_intensity": xr.DataArray([10, 20, 30], dims=["x"]), + } + ) + + # Should not raise an error + result = cleanup_intermediate_variables(ds) + + assert "bg_rate" not in result + assert "ena_intensity" in result + + +# ============================================================================= +# COMBINE MAPS TESTS +# ============================================================================= + + +@pytest.fixture +def mock_sky_map_for_combine(): + """Create a mock RectangularSkyMap for testing combine_maps.""" + + def _create_map(intensity_offset=0, exposure_offset=0): + """Helper to create a map with configurable values.""" + descriptor = MapDescriptor.from_string("h90-ena-h-hf-nsp-full-gcs-6deg-3mo") + sky_map = descriptor.to_empty_map() + + # Create simple test data + shape = (1, 3, 4, 2) # epoch, energy, lon, lat + sky_map.data_1d = xr.Dataset( + { + "counts": xr.DataArray( + np.ones(shape) * (100 + intensity_offset), + dims=["epoch", "energy", "longitude", "latitude"], + ), + "exposure_factor": xr.DataArray( + np.ones(shape) * (10 + exposure_offset), + dims=["epoch", "energy", "longitude", "latitude"], + ), + "obs_date": xr.DataArray( + np.ones(shape) * (1e18 + intensity_offset * 1e15), + dims=["epoch", "energy", "longitude", "latitude"], + ), + "obs_date_range": xr.DataArray( + np.ones(shape) * (1e14 + intensity_offset * 1e13), + dims=["epoch", "energy", "longitude", "latitude"], + ), + "ena_intensity": xr.DataArray( + np.ones(shape) * (50 + intensity_offset), + dims=["epoch", "energy", "longitude", "latitude"], + ), + "ena_intensity_stat_uncert": xr.DataArray( + np.ones(shape) * 5.0, + dims=["epoch", "energy", "longitude", "latitude"], + ), + "ena_intensity_sys_err": xr.DataArray( + np.ones(shape) * 2.0, + dims=["epoch", "energy", "longitude", "latitude"], + ), + }, + coords={ + "epoch": [0], + "energy": [0.5, 0.75, 1.1], + "longitude": np.arange(4), + "latitude": np.arange(2), + }, + ) + return sky_map + + return _create_map + + +def test_combine_maps_single_map(mock_sky_map_for_combine): + """Test combine_maps with a single map returns it unchanged.""" + sky_map = mock_sky_map_for_combine() + sky_maps = {"full": sky_map} + + result = combine_maps(sky_maps) + + # Should return the same map + assert result is sky_map + + +def test_combine_maps_two_maps(mock_sky_map_for_combine): + """Test combine_maps properly combines ram and anti-ram maps.""" + ram_map = mock_sky_map_for_combine(intensity_offset=0, exposure_offset=0) + anti_map = mock_sky_map_for_combine(intensity_offset=20, exposure_offset=5) + sky_maps = {"ram": ram_map, "anti": anti_map} + + result = combine_maps(sky_maps) + + # Check that result is a RectangularSkyMap + assert isinstance(result, RectangularSkyMap) + + # Check additive variables + expected_counts = 100 + 120 # 100 + (100 + 20) + np.testing.assert_array_almost_equal( + result.data_1d["counts"].values, + np.ones_like(result.data_1d["counts"].values) * expected_counts, + ) + + expected_exposure = 10 + 15 # 10 + (10 + 5) + np.testing.assert_array_almost_equal( + result.data_1d["exposure_factor"].values, + np.ones_like(result.data_1d["exposure_factor"].values) * expected_exposure, + ) + + +def test_combine_maps_intensity_weighting(mock_sky_map_for_combine): + """Test that ena_intensity is combined with inverse-variance weighting.""" + ram_map = mock_sky_map_for_combine() + anti_map = mock_sky_map_for_combine(intensity_offset=20) + + # Give anti map higher uncertainty (lower weight) + anti_map.data_1d["ena_intensity_stat_uncert"] = xr.full_like( + anti_map.data_1d["ena_intensity_stat_uncert"], 10.0 + ) + + sky_maps = {"ram": ram_map, "anti": anti_map} + result = combine_maps(sky_maps) + + # Ram has uncertainty 5, anti has uncertainty 10 + # Weights: ram = 1/25 = 0.04, anti = 1/100 = 0.01 + # Weighted average: (50 * 0.04 + 70 * 0.01) / (0.04 + 0.01) = (2 + 0.7) / 0.05 = 54 + expected_intensity = (50 * 0.04 + 70 * 0.01) / (0.04 + 0.01) + np.testing.assert_array_almost_equal( + result.data_1d["ena_intensity"].values.flat[0], + expected_intensity, + decimal=5, + ) + + +def test_combine_maps_sys_err_exposure_weighted(mock_sky_map_for_combine): + """Test that systematic errors are combined with exposure weighting.""" + ram_map = mock_sky_map_for_combine() + anti_map = mock_sky_map_for_combine() + + # Set specific sys_err and exposure_factor values + ram_map.data_1d["ena_intensity_sys_err"] = xr.full_like( + ram_map.data_1d["ena_intensity_sys_err"], 5.0 + ) + ram_map.data_1d["exposure_factor"] = xr.full_like( + ram_map.data_1d["exposure_factor"], 1.0 + ) + anti_map.data_1d["ena_intensity_sys_err"] = xr.full_like( + anti_map.data_1d["ena_intensity_sys_err"], 5.0 + ) + anti_map.data_1d["exposure_factor"] = xr.full_like( + anti_map.data_1d["exposure_factor"], 4.0 + ) + + sky_maps = {"ram": ram_map, "anti": anti_map} + result = combine_maps(sky_maps) + + # Exposure weighted sum: (5 * 1 + 5 * 4) / (1 + 4) + expected_sys_err = 5.0 + np.testing.assert_array_almost_equal( + result.data_1d["ena_intensity_sys_err"].values.flat[0], + expected_sys_err, + decimal=10, + ) + + +def test_combine_maps_obs_date_exposure_weighted(mock_sky_map_for_combine): + """Test that obs_date is combined with exposure weighting.""" + ram_map = mock_sky_map_for_combine() + anti_map = mock_sky_map_for_combine() + + # Ram: obs_date=1000, exposure=10 + ram_map.data_1d["obs_date"] = xr.full_like(ram_map.data_1d["obs_date"], 1000) + ram_map.data_1d["exposure_factor"] = xr.full_like( + ram_map.data_1d["exposure_factor"], 10 + ) + + # Anti: obs_date=2000, exposure=30 + anti_map.data_1d["obs_date"] = xr.full_like(anti_map.data_1d["obs_date"], 2000) + anti_map.data_1d["exposure_factor"] = xr.full_like( + anti_map.data_1d["exposure_factor"], 30 + ) + + sky_maps = {"ram": ram_map, "anti": anti_map} + result = combine_maps(sky_maps) + + # Exposure-weighted average: (1000*10 + 2000*30) / (10+30) = 70000/40 = 1750 + expected_obs_date = (1000 * 10 + 2000 * 30) // 40 # Integer division + + # obs_date is cast to int64 after combining + assert result.data_1d["obs_date"].dtype == np.int64 + np.testing.assert_array_equal( + result.data_1d["obs_date"].values.flat[0], + expected_obs_date, + ) + + +def test_combine_maps_obs_date_range(mock_sky_map_for_combine): + """Test that obs_date_range accounts for within and between-group variance.""" + ram_map = mock_sky_map_for_combine() + anti_map = mock_sky_map_for_combine() + + # Ram: obs_date=1000, obs_date_range=100, exposure=10 + ram_map.data_1d["obs_date"] = xr.full_like(ram_map.data_1d["obs_date"], 1000) + ram_map.data_1d["obs_date_range"] = xr.full_like( + ram_map.data_1d["obs_date_range"], 100 + ) + ram_map.data_1d["exposure_factor"] = xr.full_like( + ram_map.data_1d["exposure_factor"], 10 + ) + + # Anti: obs_date=2000, obs_date_range=200, exposure=30 + anti_map.data_1d["obs_date"] = xr.full_like(anti_map.data_1d["obs_date"], 2000) + anti_map.data_1d["obs_date_range"] = xr.full_like( + anti_map.data_1d["obs_date_range"], 200 + ) + anti_map.data_1d["exposure_factor"] = xr.full_like( + anti_map.data_1d["exposure_factor"], 30 + ) + + sky_maps = {"ram": ram_map, "anti": anti_map} + result = combine_maps(sky_maps) + + # Calculate expected combined variance + w1, w2 = 10, 30 + sigma1, sigma2 = 100, 200 + mu1, mu2 = 1000, 2000 + total_exp = w1 + w2 + + within_variance = (w1 * sigma1**2 + w2 * sigma2**2) / total_exp + between_variance = (w1 * w2 * (mu1 - mu2) ** 2) / (total_exp**2) + expected_range = np.sqrt(within_variance + between_variance) + + # obs_date_range is cast to int64 after combining, so compare with truncated value + assert result.data_1d["obs_date_range"].dtype == np.int64 + np.testing.assert_array_equal( + result.data_1d["obs_date_range"].values.flat[0], + int(expected_range), + ) + + +def test_combine_maps_invalid_length(): + """Test that combine_maps raises error for invalid number of maps.""" + descriptor = MapDescriptor.from_string("h90-ena-h-hf-nsp-full-gcs-6deg-3mo") + sky_map = descriptor.to_empty_map() + + with pytest.raises(ValueError, match="Expected 1 or 2 sky maps"): + combine_maps({"a": sky_map, "b": sky_map, "c": sky_map}) + + +def test_combine_maps_handles_nan_intensity(mock_sky_map_for_combine): + """Test that combine_maps handles NaN values in ena_intensity correctly. + + When one map has NaN values and the other has valid data, the combined + result should use the valid data rather than propagating NaN. + This tests the fix using .fillna(0) in the weighted sum. + """ + ram_map = mock_sky_map_for_combine() + anti_map = mock_sky_map_for_combine(intensity_offset=20) + + # Set some positions in ram to NaN for ena_intensity + # Use a slice to set NaN at specific positions + ram_intensity = ram_map.data_1d["ena_intensity"].values.copy() + ram_intensity[0, 0, 0, 0] = np.nan # Set first position to NaN + ram_intensity[0, 1, 2, 1] = np.nan # Set another position to NaN + ram_map.data_1d["ena_intensity"] = xr.DataArray( + ram_intensity, dims=ram_map.data_1d["ena_intensity"].dims + ) + + # Anti map has valid values at all positions (intensity = 70 from offset=20) + sky_maps = {"ram": ram_map, "anti": anti_map} + result = combine_maps(sky_maps) + + # At positions where ram had NaN, the result should use anti's value + # Anti has intensity=70, uncertainty=5, so weight = 1/25 = 0.04 + # Ram has NaN (treated as 0), uncertainty=5, so weight = 1/25 = 0.04 + # Combined: (0 * 0.04 + 70 * 0.04) / (0.04 + 0.04) = 2.8 / 0.08 = 35 + # This is the expected behavior when ram's NaN is treated as 0 + + # Verify no NaN values in the combined result at those positions + assert np.isfinite(result.data_1d["ena_intensity"].values[0, 0, 0, 0]) + assert np.isfinite(result.data_1d["ena_intensity"].values[0, 1, 2, 1]) + + # The combined value should be 70 because ram's NaN should not contribute + expected_combined = 70.0 # (0 * 0 + 70 * 0.04) / 0.04 + np.testing.assert_almost_equal( + result.data_1d["ena_intensity"].values[0, 0, 0, 0], + expected_combined, + decimal=5, + ) + + # At positions where both maps have valid data, result should be normal + # weighted average + # Ram=50, Anti=70, both with uncertainty=5 + # Combined: (50 * 0.04 + 70 * 0.04) / 0.08 = 4.8 / 0.08 = 60 + expected_normal = 60.0 + # Check a position that wasn't set to NaN (e.g., [0, 0, 1, 0]) + np.testing.assert_almost_equal( + result.data_1d["ena_intensity"].values[0, 0, 1, 0], + expected_normal, + decimal=5, + ) + + +def test_combine_maps_handles_nan_uncertainties(mock_sky_map_for_combine): + """Test that combine_maps handles NaN values in uncertainties correctly. + + When one map has NaN values in ena_intensity_stat_uncert, the weight for + that map should be zero, so the combined result uses only the other map's + value. + """ + ram_map = mock_sky_map_for_combine() + anti_map = mock_sky_map_for_combine(intensity_offset=20) + + # Set NaN in stat_uncert - should result in zero weight for that map + ram_stat_unc = ram_map.data_1d["ena_intensity_stat_uncert"].values.copy() + ram_stat_unc[0, 0, 0, 0] = np.nan + ram_map.data_1d["ena_intensity_stat_uncert"] = xr.DataArray( + ram_stat_unc, dims=ram_map.data_1d["ena_intensity_stat_uncert"].dims + ) + + sky_maps = {"ram": ram_map, "anti": anti_map} + result = combine_maps(sky_maps) + + # Combined intensity at NaN uncertainty position should use only anti's + # value since ram has zero weight (due to NaN uncertainty) + assert np.isfinite(result.data_1d["ena_intensity"].values[0, 0, 0, 0]) + # The result should be anti's intensity since ram has zero weight + expected_intensity = 70.0 # anti's intensity + np.testing.assert_almost_equal( + result.data_1d["ena_intensity"].values[0, 0, 0, 0], + expected_intensity, + decimal=5, + ) + + # Combined stat_uncert should also be finite (from anti's value) + assert np.isfinite(result.data_1d["ena_intensity_stat_uncert"].values[0, 0, 0, 0]) diff --git a/imap_processing/tests/hi/test_utils.py b/imap_processing/tests/hi/test_utils.py index a3db7b6a21..78abfb5607 100644 --- a/imap_processing/tests/hi/test_utils.py +++ b/imap_processing/tests/hi/test_utils.py @@ -1,16 +1,28 @@ """Test coverage for imap_processing.hi.utils.py""" +import io + import numpy as np +import pandas as pd import pytest import xarray as xr +import imap_processing.hi from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes from imap_processing.hi.utils import ( HIAPID, + BackgroundConfig, + CalibrationProductConfig, CoincidenceBitmap, EsaEnergyStepLookupTable, + compute_qualified_event_mask, create_dataset_variables, + filter_events_by_coincidence, full_dataarray, + get_bin_range_with_wrap, + get_tof_window_mask, + iter_background_events_by_config, + iter_qualified_events_by_config, parse_sensor_number, ) @@ -327,3 +339,1258 @@ def test_edge_case_boundary_values(self, populated_lookup): result = populated_lookup.query(10.0, 1) # Should match both (0.0, 10.0, 1, 100.0) and (10.0, 20.0, 1, 150.0) assert result in [100.0, 150.0] + + +class TestCalibrationProductConfig: + """ + All test coverage for the pd.DataFrame accessor extension "cal_prod_config". + """ + + def test_wrong_columns(self): + """Test coverage for a dataframe with the wrong columns.""" + required_columns = ( + imap_processing.hi.utils.CalibrationProductConfig.required_columns + ) + for exclude_column_name in required_columns: + include_columns = set(required_columns) - {exclude_column_name} + # Create dataframe with proper indices but missing one column + df = pd.DataFrame( + {col: [1, 2, 3] for col in include_columns}, + index=pd.MultiIndex.from_tuples( + [(0, 0), (0, 1), (1, 0)], + names=["calibration_prod", "esa_energy_step"], + ), + ) + with pytest.raises(AttributeError, match="Required column.*"): + _ = df.cal_prod_config.number_of_products + + def test_from_csv(self, hi_test_cal_prod_config_path): + """Test coverage for read_csv function.""" + df = imap_processing.hi.utils.CalibrationProductConfig.from_csv( + hi_test_cal_prod_config_path + ) + assert isinstance(df["coincidence_type_list"][0, 1], tuple) + + def test_added_coincidence_type_values_column(self, hi_test_cal_prod_config_path): + df = CalibrationProductConfig.from_csv(hi_test_cal_prod_config_path) + assert "coincidence_type_values" in df.columns + for _, row in df.iterrows(): + for detect_string, val in zip( + row["coincidence_type_list"], + row["coincidence_type_values"], + strict=False, + ): + assert val == CoincidenceBitmap.detector_hit_str_to_int(detect_string) + + def test_number_of_products(self, hi_test_cal_prod_config_path): + """Test coverage for number of products accessor.""" + df = imap_processing.hi.utils.CalibrationProductConfig.from_csv( + hi_test_cal_prod_config_path + ) + assert df.cal_prod_config.number_of_products == 2 + + def test_calibration_product_numbers(self, hi_test_cal_prod_config_path): + """Test coverage for calibration_product_numbers accessor.""" + df = imap_processing.hi.utils.CalibrationProductConfig.from_csv( + hi_test_cal_prod_config_path + ) + cal_prod_numbers = df.cal_prod_config.calibration_product_numbers + # The test config file has calibration products 0 and 1 + np.testing.assert_array_equal(cal_prod_numbers, np.array([0, 1])) + # Verify it's a numpy array of integers + assert isinstance(cal_prod_numbers, np.ndarray) + assert cal_prod_numbers.dtype in [np.int32, np.int64] + + def test_calibration_product_numbers_arbitrary_values(self): + """Test calibration_product_numbers with arbitrary non-sequential values.""" + # Create a temporary CSV with non-sequential calibration product numbers + csv_content = """\ +calibration_prod,esa_energy_step,geometric_factor,coincidence_type_list,tof_ab_low,tof_ab_high,tof_ac1_low,tof_ac1_high,tof_bc1_low,tof_bc1_high,tof_c1c2_low,tof_c1c2_high +10,1,0.00055,BC1C2,15,55,0,70,-50,10,5,25 +10,2,0.00085,BC1C2,15,55,0,70,-50,10,5,25 +5,1,0.00055,ABC1C2,15,55,0,70,-50,10,5,25 +5,2,0.00085,ABC1C2,15,55,0,70,-50,10,5,25 +100,1,0.00055,AC1,15,55,0,70,-50,10,5,25 +100,2,0.00085,AC1,15,55,0,70,-50,10,5,25 + """ + + df = CalibrationProductConfig.from_csv(io.StringIO(csv_content)) + cal_prod_numbers = df.cal_prod_config.calibration_product_numbers + + # Should return sorted unique calibration product numbers + np.testing.assert_array_equal(cal_prod_numbers, np.array([5, 10, 100])) + assert isinstance(cal_prod_numbers, np.ndarray) + + +class TestBackgroundConfig: + """ + All test coverage for the pd.DataFrame accessor extension "background_config". + """ + + def test_wrong_columns(self): + """Test coverage for a dataframe with the wrong columns.""" + required_columns = BackgroundConfig.required_columns + for exclude_column_name in required_columns: + include_columns = set(required_columns) - {exclude_column_name} + # Create dataframe with proper indices but missing one column + df = pd.DataFrame( + {col: [1, 2, 3] for col in include_columns}, + index=pd.MultiIndex.from_tuples( + [(0, 0, 1), (0, 1, 1), (1, 0, 1)], + names=["calibration_prod", "background_index", "esa_energy_step"], + ), + ) + with pytest.raises(AttributeError, match="Required column.*"): + _ = df.background_config.calibration_product_numbers + + def test_from_csv(self, hi_test_background_config_path): + """Test coverage for from_csv function.""" + df = BackgroundConfig.from_csv(hi_test_background_config_path) + # Verify coincidence_type_list is a tuple + assert isinstance(df["coincidence_type_list"][0, 0, 1], tuple) + # Verify MultiIndex has 3 levels including esa_energy_step + assert df.index.names == [ + "calibration_prod", + "background_index", + "esa_energy_step", + ] + + def test_added_coincidence_type_values_column(self, hi_test_background_config_path): + """Test that coincidence_type_values column is added correctly.""" + df = BackgroundConfig.from_csv(hi_test_background_config_path) + assert "coincidence_type_values" in df.columns + for _, row in df.iterrows(): + for detect_string, val in zip( + row["coincidence_type_list"], + row["coincidence_type_values"], + strict=False, + ): + assert val == CoincidenceBitmap.detector_hit_str_to_int(detect_string) + + def test_calibration_product_numbers(self, hi_test_background_config_path): + """Test coverage for calibration_product_numbers accessor.""" + df = BackgroundConfig.from_csv(hi_test_background_config_path) + cal_prod_numbers = df.background_config.calibration_product_numbers + # The test config file has calibration products 0 and 1 + np.testing.assert_array_equal(cal_prod_numbers, np.array([0, 1])) + # Verify it's a numpy array of integers + assert isinstance(cal_prod_numbers, np.ndarray) + assert cal_prod_numbers.dtype in [np.int32, np.int64] + + def test_calibration_product_numbers_arbitrary_values(self): + """Test calibration_product_numbers with arbitrary non-sequential values.""" + csv_content = """\ +calibration_prod,background_index,esa_energy_step,scaling_factor,uncertainty,coincidence_type_list,tof_ab_low,tof_ab_high,tof_ac1_low,tof_ac1_high,tof_bc1_low,tof_bc1_high,tof_c1c2_low,tof_c1c2_high +10,0,1,0.01,0.001,ABC1C2,-20,16,-46,-15,-511,511,0,1023 +5,0,1,0.02,0.002,BC1C2,-20,16,-46,-15,-511,511,0,1023 +100,0,1,0.03,0.003,AB,-20,16,-46,-15,-511,511,0,1023 + """ + + df = BackgroundConfig.from_csv(io.StringIO(csv_content)) + cal_prod_numbers = df.background_config.calibration_product_numbers + + # Should return sorted unique calibration product numbers + np.testing.assert_array_equal(cal_prod_numbers, np.array([5, 10, 100])) + assert isinstance(cal_prod_numbers, np.ndarray) + + def test_validate_tof_consistency_passes(self): + """Test that TOF consistency validation passes with consistent TOF windows.""" + csv_content = """\ +calibration_prod,background_index,esa_energy_step,scaling_factor,uncertainty,coincidence_type_list,tof_ab_low,tof_ab_high,tof_ac1_low,tof_ac1_high,tof_bc1_low,tof_bc1_high,tof_c1c2_low,tof_c1c2_high +0,0,1,0.01,0.001,ABC1C2,-20,16,-46,-15,-511,511,0,1023 +0,0,2,0.02,0.002,ABC1C2,-20,16,-46,-15,-511,511,0,1023 +0,0,3,0.03,0.003,ABC1C2,-20,16,-46,-15,-511,511,0,1023 + """ + # Should not raise - TOF windows and coincidence_type_list are consistent + df = BackgroundConfig.from_csv(io.StringIO(csv_content)) + assert len(df) == 3 + + def test_validate_tof_consistency_fails_on_different_tof_windows(self): + """Test that TOF consistency validation fails with inconsistent TOF windows.""" + csv_content = """\ +calibration_prod,background_index,esa_energy_step,scaling_factor,uncertainty,coincidence_type_list,tof_ab_low,tof_ab_high,tof_ac1_low,tof_ac1_high,tof_bc1_low,tof_bc1_high,tof_c1c2_low,tof_c1c2_high +0,0,1,0.01,0.001,ABC1C2,-20,16,-46,-15,-511,511,0,1023 +0,0,2,0.02,0.002,ABC1C2,-25,16,-46,-15,-511,511,0,1023 + """ + # Should raise ValueError because tof_ab_low differs between ESA steps + with pytest.raises(ValueError, match="Inconsistent tof_ab_low values"): + BackgroundConfig.from_csv(io.StringIO(csv_content)) + + def test_validate_tof_consistency_fails_on_different_coincidence_types(self): + """Test TOF consistency validation fails with inconsistent coincidence types.""" + csv_content = """\ +calibration_prod,background_index,esa_energy_step,scaling_factor,uncertainty,coincidence_type_list,tof_ab_low,tof_ab_high,tof_ac1_low,tof_ac1_high,tof_bc1_low,tof_bc1_high,tof_c1c2_low,tof_c1c2_high +0,0,1,0.01,0.001,ABC1C2,-20,16,-46,-15,-511,511,0,1023 +0,0,2,0.02,0.002,AB,-20,16,-46,-15,-511,511,0,1023 + """ + # Should raise ValueError because coincidence_type_list differs between + # ESA steps + with pytest.raises( + ValueError, match="Inconsistent coincidence_type_list values" + ): + BackgroundConfig.from_csv(io.StringIO(csv_content)) + + def test_get_tof_config(self): + """Test get_tof_config returns one row per calibration_prod/background_index.""" + csv_content = """\ +calibration_prod,background_index,esa_energy_step,scaling_factor,uncertainty,coincidence_type_list,tof_ab_low,tof_ab_high,tof_ac1_low,tof_ac1_high,tof_bc1_low,tof_bc1_high,tof_c1c2_low,tof_c1c2_high +0,0,1,0.01,0.001,ABC1C2,-20,16,-46,-15,-511,511,0,1023 +0,0,2,0.02,0.002,ABC1C2,-20,16,-46,-15,-511,511,0,1023 +0,0,3,0.03,0.003,ABC1C2,-20,16,-46,-15,-511,511,0,1023 +0,1,1,0.05,0.005,AB,-10,20,-30,-10,-400,400,0,800 +0,1,2,0.06,0.006,AB,-10,20,-30,-10,-400,400,0,800 + """ + df = BackgroundConfig.from_csv(io.StringIO(csv_content)) + tof_config = df.background_config.get_tof_config() + + # Should have 2 rows: (0, 0) and (0, 1) + assert len(tof_config) == 2 + assert tof_config.index.names == ["calibration_prod", "background_index"] + + # Verify TOF columns are present + assert "tof_ab_low" in tof_config.columns + assert "coincidence_type_list" in tof_config.columns + assert "coincidence_type_values" in tof_config.columns + + # Verify values from first row of each group + assert tof_config.loc[(0, 0), "tof_ab_low"] == -20 + assert tof_config.loc[(0, 1), "tof_ab_low"] == -10 + + def test_forward_fill_tof_columns(self): + """Test that TOF columns are forward-filled from first row of each group.""" + # CSV with TOF values only on first row of each (cal_prod, bg_index) group + csv_content = """\ +calibration_prod,background_index,esa_energy_step,scaling_factor,uncertainty,coincidence_type_list,tof_ab_low,tof_ab_high,tof_ac1_low,tof_ac1_high,tof_bc1_low,tof_bc1_high,tof_c1c2_low,tof_c1c2_high +0,0,1,0.01,0.001,ABC1C2,-20,16,-46,-15,-511,511,0,1023 +0,0,2,0.02,0.002,,,,,,,,, +0,0,3,0.03,0.003,,,,,,,,, +0,1,1,0.05,0.005,AB,-10,20,-30,-10,-400,400,5,800 +0,1,2,0.06,0.006,,,,,,,,, + """ + df = BackgroundConfig.from_csv(io.StringIO(csv_content)) + + # Verify TOF columns were forward-filled + # All rows in group (0, 0) should have tof_ab_low = -20 + group_0_0 = df.loc[(0, 0)] + assert all(group_0_0["tof_ab_low"] == -20) + assert all(group_0_0["tof_c1c2_high"] == 1023) + assert all(group_0_0["coincidence_type_list"] == ("ABC1C2",)) + + # All rows in group (0, 1) should have tof_ab_low = -10 + group_0_1 = df.loc[(0, 1)] + assert all(group_0_1["tof_ab_low"] == -10) + assert all(group_0_1["tof_c1c2_high"] == 800) + assert all(group_0_1["coincidence_type_list"] == ("AB",)) + + # Verify scaling factors are NOT forward-filled (they vary by ESA) + assert list(group_0_0["scaling_factor"]) == [0.01, 0.02, 0.03] + + def test_validate_fails_on_missing_scaling_factor(self): + """Test that validation fails when scaling_factor is missing for some rows.""" + csv_content = """\ +calibration_prod,background_index,esa_energy_step,scaling_factor,uncertainty,coincidence_type_list,tof_ab_low,tof_ab_high,tof_ac1_low,tof_ac1_high,tof_bc1_low,tof_bc1_high,tof_c1c2_low,tof_c1c2_high +0,0,1,0.01,0.001,ABC1C2,-20,16,-46,-15,-511,511,0,1023 +0,0,2,,0.002,ABC1C2,-20,16,-46,-15,-511,511,0,1023 + """ + with pytest.raises(ValueError, match="Null values found in required column"): + BackgroundConfig.from_csv(io.StringIO(csv_content)) + + def test_validate_fails_on_missing_uncertainty(self): + """Test that validation fails when uncertainty is missing for some rows.""" + csv_content = """\ +calibration_prod,background_index,esa_energy_step,scaling_factor,uncertainty,coincidence_type_list,tof_ab_low,tof_ab_high,tof_ac1_low,tof_ac1_high,tof_bc1_low,tof_bc1_high,tof_c1c2_low,tof_c1c2_high +0,0,1,0.01,0.001,ABC1C2,-20,16,-46,-15,-511,511,0,1023 +0,0,2,0.02,,ABC1C2,-20,16,-46,-15,-511,511,0,1023 + """ + with pytest.raises(ValueError, match="Null values found in required column"): + BackgroundConfig.from_csv(io.StringIO(csv_content)) + + def test_validate_fails_on_missing_coincidence_type_list(self): + """Test validation fails when coincidence_type_list is missing for a group.""" + # First row of group is missing coincidence_type_list, so ffill has no source + csv_content = """\ +calibration_prod,background_index,esa_energy_step,scaling_factor,uncertainty,coincidence_type_list,tof_ab_low,tof_ab_high,tof_ac1_low,tof_ac1_high,tof_bc1_low,tof_bc1_high,tof_c1c2_low,tof_c1c2_high +0,0,1,0.01,0.001,,-20,16,-46,-15,-511,511,0,1023 +0,0,2,0.02,0.002,,-20,16,-46,-15,-511,511,0,1023 + """ + with pytest.raises(ValueError, match="Null values found in required column"): + BackgroundConfig.from_csv(io.StringIO(csv_content)) + + def test_validate_fails_on_missing_tof_column(self): + """Test validation fails when TOF column is missing for a group.""" + # First row of group is missing tof_ab_low, so ffill has no source + csv_content = """\ +calibration_prod,background_index,esa_energy_step,scaling_factor,uncertainty,coincidence_type_list,tof_ab_low,tof_ab_high,tof_ac1_low,tof_ac1_high,tof_bc1_low,tof_bc1_high,tof_c1c2_low,tof_c1c2_high +0,0,1,0.01,0.001,ABC1C2,,16,-46,-15,-511,511,0,1023 +0,0,2,0.02,0.002,,,,,,,,, + """ + with pytest.raises(ValueError, match="Null values found in required column"): + BackgroundConfig.from_csv(io.StringIO(csv_content)) + + +class TestGetTofWindowMask: + """Test suite for get_tof_window_mask function.""" + + @pytest.fixture + def mock_de_dataset(self): + """Create a mock L1B DE dataset with TOF values.""" + n_events = 10 + return xr.Dataset( + { + "tof_ab": ( + ["event_met"], + np.array([20, 50, 100, 30, 40, 60, 10, 80, 90, 55]), + ), + "tof_ac1": ( + ["event_met"], + np.array([10, 30, -5, 50, 20, 40, 0, 60, 70, 35]), + ), + "tof_bc1": ( + ["event_met"], + np.array([-30, 0, -20, 10, -40, -10, -50, 15, 20, 5]), + ), + "tof_c1c2": ( + ["event_met"], + np.array([50, 60, 80, 30, 40, 70, 20, 90, 100, 55]), + ), + }, + coords={"event_met": np.arange(n_events, dtype=float)}, + ) + + def test_all_tofs_in_window(self, mock_de_dataset): + """Test that events with all TOFs in window pass.""" + # Use wide windows that include all values + tof_windows = { + "tof_ab": (0, 200), + "tof_ac1": (-20, 100), + "tof_bc1": (-100, 50), + "tof_c1c2": (0, 200), + } + tof_fill_vals = {k: -9999 for k in tof_windows} + mask = get_tof_window_mask(mock_de_dataset, tof_windows, tof_fill_vals) + assert np.all(mask) + + def test_some_tofs_out_of_window(self, mock_de_dataset): + """Test that events with TOFs outside window are filtered.""" + # tof_ab values: [20, 50, 100, 30, 40, 60, 10, 80, 90, 55] + # Window (25, 75) should pass indices: 1, 3, 4, 5, 9 (values 50, 30, 40, 60, 55) + tof_windows = { + "tof_ab": (25, 75), + } + tof_fill_vals = {"tof_ab": -9999} + mask = get_tof_window_mask(mock_de_dataset, tof_windows, tof_fill_vals) + expected = np.array( + [False, True, False, True, True, True, False, False, False, True] + ) + np.testing.assert_array_equal(mask, expected) + + def test_with_fill_values(self, mock_de_dataset): + """Test that events with fill values pass the filter.""" + # Set some values to fill value + fill_val = -9999 + mock_de_dataset["tof_ab"].values[0] = fill_val # Was 20, now fill + mock_de_dataset["tof_ab"].values[2] = fill_val # Was 100, now fill + + tof_windows = {"tof_ab": (25, 75)} + tof_fill_vals = {"tof_ab": fill_val} + + mask = get_tof_window_mask(mock_de_dataset, tof_windows, tof_fill_vals) + # Events 0, 2 have fill values (pass), events 1, 3, 4, 5, 9 are in window + expected = np.array( + [True, True, True, True, True, True, False, False, False, True] + ) + np.testing.assert_array_equal(mask, expected) + + def test_multiple_tof_windows(self, mock_de_dataset): + """Test with multiple TOF windows - all must pass.""" + # tof_ab: [20, 50, 100, 30, 40, 60, 10, 80, 90, 55] + # tof_ac1: [10, 30, -5, 50, 20, 40, 0, 60, 70, 35] + tof_windows = { + "tof_ab": (20, 80), # Passes: 0,1,3,4,5,7,9 (not 2,6,8) + "tof_ac1": (10, 60), # Passes: 0,1,3,4,5,7,9 (not 2,6,8) + } + tof_fill_vals = {k: -9999 for k in tof_windows} + mask = get_tof_window_mask(mock_de_dataset, tof_windows, tof_fill_vals) + # Must pass both: 0, 1, 3, 4, 5, 7, 9 + expected = np.array( + [True, True, False, True, True, True, False, True, False, True] + ) + np.testing.assert_array_equal(mask, expected) + + def test_empty_dataset(self): + """Test with empty dataset.""" + empty_ds = xr.Dataset( + { + "tof_ab": (["event_met"], np.array([])), + "tof_ac1": (["event_met"], np.array([])), + "tof_bc1": (["event_met"], np.array([])), + "tof_c1c2": (["event_met"], np.array([])), + }, + coords={"event_met": np.array([])}, + ) + tof_windows = {"tof_ab": (0, 100)} + mask = get_tof_window_mask(empty_ds, tof_windows, {}) + assert len(mask) == 0 + + +class TestFilterEventsByCoincidence: + """Test suite for filter_events_by_coincidence function.""" + + @pytest.fixture + def mock_de_dataset(self): + """Create a mock L1B DE dataset with coincidence types.""" + # Coincidence bitmap: A=8, B=4, C1=2, C2=1 + # ABC1C2 = 15, ABC1 = 14, AB = 12, AC1 = 10, BC1 = 6, etc. + return xr.Dataset( + { + "coincidence_type": ( + ["event_met"], + np.array([15, 14, 12, 10, 6, 15, 8, 4, 2, 1]), + ), + }, + coords={"event_met": np.arange(10, dtype=float)}, + ) + + def test_single_coincidence_type(self, mock_de_dataset): + """Test filtering for a single coincidence type.""" + # Filter for ABC1C2 (15) + mask = filter_events_by_coincidence(mock_de_dataset, [15]) + expected = np.array( + [True, False, False, False, False, True, False, False, False, False] + ) + np.testing.assert_array_equal(mask, expected) + + def test_multiple_coincidence_types(self, mock_de_dataset): + """Test filtering for multiple coincidence types.""" + # Filter for ABC1C2 (15) or ABC1 (14) + mask = filter_events_by_coincidence(mock_de_dataset, [15, 14]) + expected = np.array( + [True, True, False, False, False, True, False, False, False, False] + ) + np.testing.assert_array_equal(mask, expected) + + def test_no_matching_coincidence(self, mock_de_dataset): + """Test when no events match the coincidence types.""" + # Filter for type 3 which doesn't exist + mask = filter_events_by_coincidence(mock_de_dataset, [3]) + assert not np.any(mask) + + def test_all_matching_coincidence(self, mock_de_dataset): + """Test when all events match the coincidence types.""" + all_types = [15, 14, 12, 10, 6, 8, 4, 2, 1] + mask = filter_events_by_coincidence(mock_de_dataset, all_types) + assert np.all(mask) + + def test_empty_coincidence_list(self, mock_de_dataset): + """Test with empty coincidence type list.""" + mask = filter_events_by_coincidence(mock_de_dataset, []) + assert not np.any(mask) + + def test_empty_dataset(self): + """Test with empty dataset.""" + empty_ds = xr.Dataset( + { + "coincidence_type": (["event_met"], np.array([], dtype=np.uint8)), + }, + coords={"event_met": np.array([])}, + ) + mask = filter_events_by_coincidence(empty_ds, [15]) + assert len(mask) == 0 + + +class TestGetBinRangeWithWrap: + """Test suite for get_bin_range_with_wrap function.""" + + def test_no_wrap_middle(self): + """Test range in middle of bins (no wraparound).""" + result = get_bin_range_with_wrap( + first_bin=10, last_bin=20, n_bins=90, extend_by=1 + ) + expected = np.arange(9, 22) # 10-1 to 20+1 + np.testing.assert_array_equal(result, expected) + + def test_no_wrap_with_larger_extension(self): + """Test with larger extension value.""" + result = get_bin_range_with_wrap( + first_bin=10, last_bin=20, n_bins=90, extend_by=3 + ) + expected = np.arange(7, 24) # 10-3 to 20+3 + np.testing.assert_array_equal(result, expected) + + def test_wrap_at_end(self): + """Test wraparound at high end (88 -> 0 boundary).""" + result = get_bin_range_with_wrap( + first_bin=87, last_bin=1, n_bins=90, extend_by=1 + ) + # Should get bins 86, 87, 88, 89, 0, 1, 2 + expected = np.array([86, 87, 88, 89, 0, 1, 2]) + np.testing.assert_array_equal(result, expected) + + def test_wrap_at_start(self): + """Test wraparound near bin 0.""" + result = get_bin_range_with_wrap( + first_bin=0, last_bin=5, n_bins=90, extend_by=1 + ) + # first-1 = -1 % 90 = 89, last+1 = 6 + # This should NOT wrap (89 > 6), so we get 89,0,1,2,3,4,5,6 + expected = np.array([89, 0, 1, 2, 3, 4, 5, 6]) + np.testing.assert_array_equal(result, expected) + + def test_wrap_at_both_ends(self): + """Test when first_bin is near end and last_bin is near start.""" + result = get_bin_range_with_wrap( + first_bin=88, last_bin=2, n_bins=90, extend_by=1 + ) + # bot = 87, top = 3 + # Since 3 < 87, we wrap: [87, 88, 89] + [0, 1, 2, 3] + expected = np.array([87, 88, 89, 0, 1, 2, 3]) + np.testing.assert_array_equal(result, expected) + + def test_single_bin_range(self): + """Test when first_bin equals last_bin.""" + result = get_bin_range_with_wrap( + first_bin=45, last_bin=45, n_bins=90, extend_by=1 + ) + expected = np.array([44, 45, 46]) + np.testing.assert_array_equal(result, expected) + + def test_zero_extension(self): + """Test with zero extension.""" + result = get_bin_range_with_wrap( + first_bin=10, last_bin=15, n_bins=90, extend_by=0 + ) + expected = np.arange(10, 16) + np.testing.assert_array_equal(result, expected) + + def test_different_n_bins(self): + """Test with different number of bins.""" + result = get_bin_range_with_wrap( + first_bin=350, last_bin=10, n_bins=360, extend_by=5 + ) + # bot = 345, top = 15 + # Since 15 < 345, we wrap: [345..359] + [0..15] + expected = np.concatenate([np.arange(345, 360), np.arange(0, 16)]) + np.testing.assert_array_equal(result, expected) + + def test_adjacent_to_boundary(self): + """Test bins adjacent to boundary (89 and 0).""" + result = get_bin_range_with_wrap( + first_bin=89, last_bin=89, n_bins=90, extend_by=1 + ) + # bot = 88, top = 0 (90 % 90) + # Since 0 < 88, we wrap: [88, 89] + [0] + expected = np.array([88, 89, 0]) + np.testing.assert_array_equal(result, expected) + + def test_full_spin_wrap(self): + """Test wrapping that covers almost all bins.""" + result = get_bin_range_with_wrap( + first_bin=85, last_bin=5, n_bins=90, extend_by=1 + ) + # bot = 84, top = 6 + # Since 6 < 84, we wrap + expected = np.concatenate([np.arange(84, 90), np.arange(0, 7)]) + np.testing.assert_array_equal(result, expected) + + +class TestComputeQualifiedEventMask: + """Test suite for compute_qualified_event_mask function.""" + + @pytest.fixture + def mock_cal_product_config(self): + """Create a mock calibration product config DataFrame.""" + # Create a config with 2 calibration products, 2 ESA energy steps + # Coincidence bitmap: A=8, B=4, C1=2, C2=1 + # ABC1C2=15, ABC1=14, AB=12 + data = { + "coincidence_type_list": [ + ("ABC1C2", "ABC1"), # cal_prod=1, esa_energy=1 + ("ABC1C2", "ABC1"), # cal_prod=1, esa_energy=2 + ("AB",), # cal_prod=2, esa_energy=1 + ("AB",), # cal_prod=2, esa_energy=2 + ], + "tof_ab_low": [10, 10, 10, 10], + "tof_ab_high": [100, 100, 100, 100], + "tof_ac1_low": [5, 5, 5, 5], + "tof_ac1_high": [80, 80, 80, 80], + "tof_bc1_low": [-50, -50, -50, -50], + "tof_bc1_high": [50, 50, 50, 50], + "tof_c1c2_low": [20, 20, 20, 20], + "tof_c1c2_high": [120, 120, 120, 120], + } + index = pd.MultiIndex.from_tuples( + [(1, 1), (1, 2), (2, 1), (2, 2)], + names=["calibration_prod", "esa_energy_step"], + ) + df = pd.DataFrame(data, index=index) + # Trigger the accessor to add coincidence_type_values column + _ = df.cal_prod_config.number_of_products + return df + + @pytest.fixture + def mock_de_dataset(self): + """Create a mock L1B DE dataset with events.""" + # 10 events with various coincidence types and TOF values + # Coincidence bitmap: A=8, B=4, C1=2, C2=1 + # ABC1C2=15, ABC1=14, AB=12, A=8 + n_events = 10 + fill_val = -9999.0 + ds = xr.Dataset( + { + "coincidence_type": ( + ["event_met"], + np.array([15, 14, 12, 8, 15, 14, 12, 8, 15, 12]), + ), + "tof_ab": ( + ["event_met"], + np.array([50, 50, 50, 50, 200, 50, 50, 50, 50, 50]), + ), # Event 4 out of window + "tof_ac1": ( + ["event_met"], + np.array([30, 30, 30, 30, 30, 30, 30, 30, 30, 30]), + ), + "tof_bc1": ( + ["event_met"], + np.array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), + ), + "tof_c1c2": ( + ["event_met"], + np.array([50, 50, 50, 50, 50, 50, 50, 50, 50, 50]), + ), + }, + coords={"event_met": np.arange(n_events, dtype=float)}, + ) + # Add FILLVAL attributes to TOF variables + for tof_var in ["tof_ab", "tof_ac1", "tof_bc1", "tof_c1c2"]: + ds[tof_var].attrs["FILLVAL"] = fill_val + return ds + + def test_qualifies_with_both_coincidence_and_tof( + self, mock_cal_product_config, mock_de_dataset + ): + """Events passing both coincidence and TOF checks qualify.""" + # All events at ESA energy step 1 + esa_energy_steps = np.ones(10, dtype=int) + + mask = compute_qualified_event_mask( + mock_de_dataset, mock_cal_product_config, esa_energy_steps + ) + + # Events with coincidence_type in [15, 14, 12] and TOF in window should pass + # Event 4 has bad TOF (200, outside 10-100 window) + # Events 3, 7 have coincidence_type=8 (A only, not in config) + expected = np.array( + [True, True, True, False, False, True, True, False, True, True] + ) + np.testing.assert_array_equal(mask, expected) + + def test_fails_coincidence_only(self, mock_cal_product_config, mock_de_dataset): + """Events with wrong coincidence type don't qualify.""" + # All events at ESA energy step 1 + esa_energy_steps = np.ones(10, dtype=int) + + # Check events 3, 7 which have coincidence_type=8 (not in config) + mask = compute_qualified_event_mask( + mock_de_dataset, mock_cal_product_config, esa_energy_steps + ) + + # Events 3 and 7 should not qualify + assert mask[3] is np.False_ + assert mask[7] is np.False_ + + def test_fails_tof_only(self, mock_cal_product_config, mock_de_dataset): + """Events with valid coincidence but bad TOF don't qualify.""" + # All events at ESA energy step 1 + esa_energy_steps = np.ones(10, dtype=int) + + # Event 4 has coincidence_type=15 (valid) but tof_ab=200 (outside 10-100) + mask = compute_qualified_event_mask( + mock_de_dataset, mock_cal_product_config, esa_energy_steps + ) + + assert mask[4] is np.False_ + + def test_union_across_cal_products(self, mock_cal_product_config, mock_de_dataset): + """Events qualify if they pass for ANY cal product.""" + esa_energy_steps = np.ones(10, dtype=int) + + # Event 2 has coincidence_type=12 (AB), valid for cal_prod 2 + # Event 0 has coincidence_type=15 (ABC1C2), valid for cal_prod 1 + mask = compute_qualified_event_mask( + mock_de_dataset, mock_cal_product_config, esa_energy_steps + ) + + assert mask[0] # Qualifies for cal_prod 1 + assert mask[2] # Qualifies for cal_prod 2 + + def test_fill_values_pass_tof(self, mock_cal_product_config, mock_de_dataset): + """Events with TOF fill values pass TOF check.""" + esa_energy_steps = np.ones(10, dtype=int) + + # Set event 4's TOF to fill value (it was failing due to high tof_ab) + # The FILLVAL attribute is already set by the fixture + fill_val = mock_de_dataset["tof_ab"].attrs["FILLVAL"] + mock_de_dataset["tof_ab"].values[4] = fill_val + + mask = compute_qualified_event_mask( + mock_de_dataset, mock_cal_product_config, esa_energy_steps + ) + + # Event 4 should now pass (fill value passes TOF check) + assert mask[4] + + def test_different_esa_energy_steps(self, mock_cal_product_config, mock_de_dataset): + """Events match config based on their ESA energy step.""" + # Half events at ESA 1, half at ESA 2 + esa_energy_steps = np.array([1, 1, 1, 1, 1, 2, 2, 2, 2, 2]) + + mask = compute_qualified_event_mask( + mock_de_dataset, mock_cal_product_config, esa_energy_steps + ) + + # Events 0-4 should match ESA 1 config + # Events 5-9 should match ESA 2 config + # Event 4 still fails due to bad TOF + # Events 7 fails due to bad coincidence type (8) + expected = np.array( + [True, True, True, False, False, True, True, False, True, True] + ) + np.testing.assert_array_equal(mask, expected) + + def test_no_matching_esa_energy_step( + self, mock_cal_product_config, mock_de_dataset + ): + """Events with unmatched ESA energy step don't qualify.""" + # All events at ESA energy step 99 (not in config) + esa_energy_steps = np.full(10, 99) + + mask = compute_qualified_event_mask( + mock_de_dataset, mock_cal_product_config, esa_energy_steps + ) + + # No events should qualify + assert not np.any(mask) + + def test_empty_dataset(self, mock_cal_product_config): + """Test with empty dataset.""" + empty_ds = xr.Dataset( + { + "coincidence_type": (["event_met"], np.array([], dtype=np.uint8)), + "tof_ab": (["event_met"], np.array([])), + "tof_ac1": (["event_met"], np.array([])), + "tof_bc1": (["event_met"], np.array([])), + "tof_c1c2": (["event_met"], np.array([])), + }, + coords={"event_met": np.array([])}, + ) + esa_energy_steps = np.array([]) + + mask = compute_qualified_event_mask( + empty_ds, mock_cal_product_config, esa_energy_steps + ) + + assert len(mask) == 0 + + +class TestIterQualifiedEventsByConfig: + """Test suite for iter_qualified_events_by_config function.""" + + @pytest.fixture + def mock_cal_product_config(self): + """Create a mock calibration product config DataFrame.""" + # Create a config with 2 calibration products, 2 ESA energy steps + # Coincidence bitmap: A=8, B=4, C1=2, C2=1 + # ABC1C2=15, ABC1=14, AB=12 + data = { + "coincidence_type_list": [ + ("ABC1C2", "ABC1"), # cal_prod=1, esa_energy=1 + ("ABC1C2", "ABC1"), # cal_prod=1, esa_energy=2 + ("AB",), # cal_prod=2, esa_energy=1 + ("AB",), # cal_prod=2, esa_energy=2 + ], + "tof_ab_low": [10, 10, 10, 10], + "tof_ab_high": [100, 100, 100, 100], + "tof_ac1_low": [5, 5, 5, 5], + "tof_ac1_high": [80, 80, 80, 80], + "tof_bc1_low": [-50, -50, -50, -50], + "tof_bc1_high": [50, 50, 50, 50], + "tof_c1c2_low": [20, 20, 20, 20], + "tof_c1c2_high": [120, 120, 120, 120], + } + index = pd.MultiIndex.from_tuples( + [(1, 1), (1, 2), (2, 1), (2, 2)], + names=["calibration_prod", "esa_energy_step"], + ) + df = pd.DataFrame(data, index=index) + # Trigger the accessor to add coincidence_type_values column + _ = df.cal_prod_config.number_of_products + return df + + @pytest.fixture + def mock_de_dataset(self): + """Create a mock L1B DE dataset with events.""" + # 10 events with various coincidence types and TOF values + # Coincidence bitmap: A=8, B=4, C1=2, C2=1 + # ABC1C2=15, ABC1=14, AB=12, A=8 + n_events = 10 + fill_val = -9999.0 + ds = xr.Dataset( + { + "coincidence_type": ( + ["event_met"], + np.array([15, 14, 12, 8, 15, 14, 12, 8, 15, 12]), + ), + "tof_ab": ( + ["event_met"], + np.array([50, 50, 50, 50, 200, 50, 50, 50, 50, 50]), + ), # Event 4 out of window + "tof_ac1": ( + ["event_met"], + np.array([30, 30, 30, 30, 30, 30, 30, 30, 30, 30]), + ), + "tof_bc1": ( + ["event_met"], + np.array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), + ), + "tof_c1c2": ( + ["event_met"], + np.array([50, 50, 50, 50, 50, 50, 50, 50, 50, 50]), + ), + }, + coords={"event_met": np.arange(n_events, dtype=float)}, + ) + # Add FILLVAL attributes to TOF variables + for tof_var in ["tof_ab", "tof_ac1", "tof_bc1", "tof_c1c2"]: + ds[tof_var].attrs["FILLVAL"] = fill_val + return ds + + def test_yields_correct_number_of_items( + self, mock_cal_product_config, mock_de_dataset + ): + """Test that iterator yields correct number of items.""" + esa_energy_steps = np.ones(10, dtype=int) + + results = list( + iter_qualified_events_by_config( + mock_de_dataset, mock_cal_product_config, esa_energy_steps + ) + ) + + # Should yield 4 items: 2 ESA steps x 2 cal prods per step + assert len(results) == 4 + + def test_yields_correct_structure(self, mock_cal_product_config, mock_de_dataset): + """Test that each yielded item has the correct structure.""" + esa_energy_steps = np.ones(10, dtype=int) + + for esa_energy, config_row, mask in iter_qualified_events_by_config( + mock_de_dataset, mock_cal_product_config, esa_energy_steps + ): + # Check that esa_energy is an int + assert isinstance(esa_energy, (int, np.integer)) + # Check that config_row has expected attributes + assert hasattr(config_row, "Index") + assert hasattr(config_row, "coincidence_type_values") + # Check that mask is a boolean array + assert isinstance(mask, np.ndarray) + assert mask.dtype == bool + assert len(mask) == 10 # Same length as dataset + + def test_filters_by_esa_energy_step(self, mock_cal_product_config, mock_de_dataset): + """Test that events are filtered by ESA energy step.""" + # Half events at ESA 1, half at ESA 2 + esa_energy_steps = np.array([1, 1, 1, 1, 1, 2, 2, 2, 2, 2]) + + results = list( + iter_qualified_events_by_config( + mock_de_dataset, mock_cal_product_config, esa_energy_steps + ) + ) + + # Check ESA 1 results (first 2 items) + esa_1_results = [r for r in results if r[0] == 1] + assert len(esa_1_results) == 2 + + for _, _, mask in esa_1_results: + # Only first 5 events can qualify (ESA=1) + assert not np.any(mask[5:]) # Events 5-9 should be False + + # Check ESA 2 results (last 2 items) + esa_2_results = [r for r in results if r[0] == 2] + assert len(esa_2_results) == 2 + + for _, _, mask in esa_2_results: + # Only last 5 events can qualify (ESA=2) + assert not np.any(mask[:5]) # Events 0-4 should be False + + def test_filters_by_coincidence_and_tof( + self, mock_cal_product_config, mock_de_dataset + ): + """Test that events are filtered by coincidence type and TOF windows.""" + esa_energy_steps = np.ones(10, dtype=int) + + # Get results for cal_prod=1, esa_energy=1 (expects ABC1C2=15 or ABC1=14) + for esa_energy, config_row, mask in iter_qualified_events_by_config( + mock_de_dataset, mock_cal_product_config, esa_energy_steps + ): + if esa_energy == 1 and config_row.Index[0] == 1: + # Events with coincidence 15 or 14: indices 0, 1, 4, 5, 8 + # But event 4 has bad TOF (200), so should fail + # Events 3, 7 have wrong coincidence (8) + expected = np.array( + [True, True, False, False, False, True, False, False, True, False] + ) + np.testing.assert_array_equal(mask, expected) + break + + def test_different_cal_products_different_masks( + self, mock_cal_product_config, mock_de_dataset + ): + """Test that different calibration products yield different masks.""" + esa_energy_steps = np.ones(10, dtype=int) + + masks_by_cal_prod = {} + for esa_energy, config_row, mask in iter_qualified_events_by_config( + mock_de_dataset, mock_cal_product_config, esa_energy_steps + ): + if esa_energy == 1: # Only look at ESA 1 + cal_prod = config_row.Index[0] + masks_by_cal_prod[cal_prod] = mask + + # Cal prod 1 accepts ABC1C2 and ABC1 + # Cal prod 2 accepts only AB + # They should have different masks + assert not np.array_equal(masks_by_cal_prod[1], masks_by_cal_prod[2]) + + # Cal prod 2 should match events with coincidence_type=12 (AB) + # That's events: 2, 6, 9 + expected_cal_prod_2 = np.array( + [False, False, True, False, False, False, True, False, False, True] + ) + np.testing.assert_array_equal(masks_by_cal_prod[2], expected_cal_prod_2) + + def test_empty_dataset(self, mock_cal_product_config): + """Test with empty dataset.""" + empty_ds = xr.Dataset( + { + "coincidence_type": (["event_met"], np.array([], dtype=np.uint8)), + "tof_ab": (["event_met"], np.array([])), + "tof_ac1": (["event_met"], np.array([])), + "tof_bc1": (["event_met"], np.array([])), + "tof_c1c2": (["event_met"], np.array([])), + }, + coords={"event_met": np.array([])}, + ) + esa_energy_steps = np.array([]) + + results = list( + iter_qualified_events_by_config( + empty_ds, mock_cal_product_config, esa_energy_steps + ) + ) + + # Should still yield 4 items, but all masks should be empty + assert len(results) == 4 + for _, _, mask in results: + assert len(mask) == 0 + + def test_no_matching_esa_energy(self, mock_cal_product_config, mock_de_dataset): + """Test with ESA energy steps that don't match config.""" + # All events at ESA 99 (not in config) + esa_energy_steps = np.full(10, 99) + + results = list( + iter_qualified_events_by_config( + mock_de_dataset, mock_cal_product_config, esa_energy_steps + ) + ) + + # Should still yield 4 items (one per config row) + assert len(results) == 4 + + # But none of the masks should have any True values + for _, _, mask in results: + assert not np.any(mask) + + def test_fill_values_pass_tof_check(self, mock_cal_product_config, mock_de_dataset): + """Test that TOF fill values pass the TOF window check.""" + esa_energy_steps = np.ones(10, dtype=int) + + # Set event 4's tof_ab to fill value (it was failing due to high value) + fill_val = mock_de_dataset["tof_ab"].attrs["FILLVAL"] + mock_de_dataset["tof_ab"].values[4] = fill_val + + # Get results for cal_prod=1, esa_energy=1 + for esa_energy, config_row, mask in iter_qualified_events_by_config( + mock_de_dataset, mock_cal_product_config, esa_energy_steps + ): + if esa_energy == 1 and config_row.Index[0] == 1: + # Event 4 should now pass (has coincidence 15 and fill value TOF) + assert mask[4] + break + + +class TestIterBackgroundEventsByConfig: + """Test suite for iter_background_events_by_config function.""" + + @pytest.fixture + def mock_background_config(self): + """Create a mock background config DataFrame. + + This creates a full background config with 3-level index + (calibration_prod, background_index, esa_energy_step) and then + returns the TOF config (2-level index) which is what + iter_background_events_by_config expects. + """ + # Create a config with 2 calibration products, 2 background indices each + # Include esa_energy_step in index (required for validation) + # TOF windows are the same across ESA steps, scaling factors can vary + data = { + "coincidence_type_list": [ + ("A",), # cal_prod=1, bg_index=0, esa=1 + ("A",), # cal_prod=1, bg_index=0, esa=2 + ("B",), # cal_prod=1, bg_index=1, esa=1 + ("B",), # cal_prod=1, bg_index=1, esa=2 + ("C1",), # cal_prod=2, bg_index=0, esa=1 + ("C1",), # cal_prod=2, bg_index=0, esa=2 + ("C2",), # cal_prod=2, bg_index=1, esa=1 (invalid, but for testing) + ("C2",), # cal_prod=2, bg_index=1, esa=2 (invalid, but for testing) + ], + "tof_ab_low": [10, 10, 10, 10, 10, 10, 10, 10], + "tof_ab_high": [100, 100, 100, 100, 100, 100, 100, 100], + "tof_ac1_low": [5, 5, 5, 5, 5, 5, 5, 5], + "tof_ac1_high": [80, 80, 80, 80, 80, 80, 80, 80], + "tof_bc1_low": [-50, -50, -50, -50, -50, -50, -50, -50], + "tof_bc1_high": [50, 50, 50, 50, 50, 50, 50, 50], + "tof_c1c2_low": [20, 20, 20, 20, 20, 20, 20, 20], + "tof_c1c2_high": [120, 120, 120, 120, 120, 120, 120, 120], + "scaling_factor": [1.0, 1.1, 1.0, 1.1, 1.0, 1.1, 1.0, 1.1], + "uncertainty": [0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1], + } + index = pd.MultiIndex.from_tuples( + [ + (1, 0, 1), + (1, 0, 2), + (1, 1, 1), + (1, 1, 2), + (2, 0, 1), + (2, 0, 2), + (2, 1, 1), + (2, 1, 2), + ], + names=["calibration_prod", "background_index", "esa_energy_step"], + ) + df = pd.DataFrame(data, index=index) + # Trigger the accessor to add coincidence_type_values column + # and return the TOF config (2-level index for iter_background_events_by_config) + return df.background_config.get_tof_config() + + @pytest.fixture + def mock_de_dataset(self): + """Create a mock L1B DE dataset with events.""" + # 10 events with various coincidence types and TOF values + # Coincidence bitmap: A=8, B=4, C1=2, C2=1 + n_events = 10 + fill_val = -9999.0 + ds = xr.Dataset( + { + "coincidence_type": ( + ["event_met"], + # A=8, B=4, C1=2, mix + np.array([8, 4, 2, 8, 4, 2, 8, 4, 2, 8]), + ), + "tof_ab": ( + ["event_met"], + np.array([50, 50, 50, 50, 50, 50, 200, 50, 50, 50]), + ), # Event 6 out of window + "tof_ac1": ( + ["event_met"], + np.array([30, 30, 30, 30, 30, 30, 30, 30, 30, 30]), + ), + "tof_bc1": ( + ["event_met"], + np.array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), + ), + "tof_c1c2": ( + ["event_met"], + np.array([50, 50, 50, 50, 50, 50, 50, 50, 50, 50]), + ), + }, + coords={"event_met": np.arange(n_events, dtype=float)}, + ) + # Add FILLVAL attributes to TOF variables + for tof_var in ["tof_ab", "tof_ac1", "tof_bc1", "tof_c1c2"]: + ds[tof_var].attrs["FILLVAL"] = fill_val + return ds + + def test_yields_correct_number_of_items( + self, mock_background_config, mock_de_dataset + ): + """Test that iterator yields correct number of items.""" + results = list( + iter_background_events_by_config(mock_de_dataset, mock_background_config) + ) + + # Should yield 4 items: one per (cal_prod, bg_index) combination + assert len(results) == 4 + + def test_yields_correct_structure(self, mock_background_config, mock_de_dataset): + """Test that each yielded item has the correct structure.""" + for config_row, filtered_ds in iter_background_events_by_config( + mock_de_dataset, mock_background_config + ): + # Check that config_row has expected attributes + # Note: The TOF config from get_tof_config() doesn't include + # scaling_factor or uncertainty (those are ESA-dependent) + assert hasattr(config_row, "Index") + assert hasattr(config_row, "coincidence_type_values") + assert hasattr(config_row, "tof_ab_low") + assert hasattr(config_row, "tof_ab_high") + # Check that filtered_ds is an xarray Dataset + assert isinstance(filtered_ds, xr.Dataset) + assert "event_met" in filtered_ds.dims + assert "coincidence_type" in filtered_ds + assert "tof_ab" in filtered_ds + + def test_filters_by_coincidence_and_tof( + self, mock_background_config, mock_de_dataset + ): + """Test that events are filtered by coincidence type and TOF windows.""" + results = list( + iter_background_events_by_config(mock_de_dataset, mock_background_config) + ) + + # Get results for cal_prod=1, bg_index=0 (expects A=8) + for config_row, filtered_ds in results: + if config_row.Index == (1, 0): + # Events with coincidence A=8: indices 0, 3, 6, 9 + # But event 6 has bad TOF (200), so should be excluded + expected_events = [0, 3, 9] + assert len(filtered_ds["event_met"]) == len(expected_events) + np.testing.assert_array_equal( + filtered_ds["event_met"].values, expected_events + ) + break + + def test_different_backgrounds_different_datasets( + self, mock_background_config, mock_de_dataset + ): + """Test that different background configs yield different filtered datasets.""" + results = list( + iter_background_events_by_config(mock_de_dataset, mock_background_config) + ) + + datasets_by_bg = {} + for config_row, filtered_ds in results: + datasets_by_bg[config_row.Index] = filtered_ds + + # Cal prod 1, bg 0 expects A=8 (events 0, 3, 6, 9; but 6 has bad TOF) + # Cal prod 1, bg 1 expects B=4 (events 1, 4, 7) + # Cal prod 2, bg 0 expects C1=2 (events 2, 5, 8) + + assert len(datasets_by_bg[(1, 0)]["event_met"]) == 3 # A events (minus bad TOF) + assert len(datasets_by_bg[(1, 1)]["event_met"]) == 3 # B events + assert len(datasets_by_bg[(2, 0)]["event_met"]) == 3 # C1 events + + def test_no_esa_energy_filtering(self, mock_background_config, mock_de_dataset): + """Test that backgrounds are NOT filtered by ESA energy step.""" + # Add esa_energy_step to dataset (should be ignored) + mock_de_dataset["esa_energy_step"] = ( + ["event_met"], + np.array([1, 2, 3, 1, 2, 3, 1, 2, 3, 1]), + ) + + results = list( + iter_background_events_by_config(mock_de_dataset, mock_background_config) + ) + + # Get results for cal_prod=1, bg_index=0 (expects A=8) + for config_row, filtered_ds in results: + if config_row.Index == (1, 0): + # Should include events with A=8 at ALL ESA energy steps + # Events 0, 3, 9 (event 6 excluded due to bad TOF) + # These have esa_energy_step values: 1, 1, 1 + assert len(filtered_ds["event_met"]) == 3 + # Verify events come from different ESA energy steps in the full dataset + # (This proves we're not filtering by ESA) + break + + def test_empty_dataset(self, mock_background_config): + """Test with empty dataset.""" + empty_ds = xr.Dataset( + { + "coincidence_type": (["event_met"], np.array([], dtype=np.uint8)), + "tof_ab": (["event_met"], np.array([])), + "tof_ac1": (["event_met"], np.array([])), + "tof_bc1": (["event_met"], np.array([])), + "tof_c1c2": (["event_met"], np.array([])), + }, + coords={"event_met": np.array([])}, + ) + + results = list( + iter_background_events_by_config(empty_ds, mock_background_config) + ) + + # Should still yield 4 items, but all datasets should be empty + assert len(results) == 4 + for _, filtered_ds in results: + assert len(filtered_ds["event_met"]) == 0 + + def test_no_matching_events(self, mock_background_config, mock_de_dataset): + """Test with events that don't match any background config.""" + # Change all coincidence types to something not in config + mock_de_dataset["coincidence_type"].values[:] = 15 # ABC1C2 + + results = list( + iter_background_events_by_config(mock_de_dataset, mock_background_config) + ) + + # Should yield 4 items, but all filtered datasets should be empty + assert len(results) == 4 + for _, filtered_ds in results: + assert len(filtered_ds["event_met"]) == 0 + + def test_fill_values_pass_tof_check(self, mock_background_config, mock_de_dataset): + """Test that TOF fill values pass the TOF window check.""" + # Set event 6's tof_ab to fill value (it was failing due to high value) + fill_val = mock_de_dataset["tof_ab"].attrs["FILLVAL"] + mock_de_dataset["tof_ab"].values[6] = fill_val + + results = list( + iter_background_events_by_config(mock_de_dataset, mock_background_config) + ) + + # Get results for cal_prod=1, bg_index=0 (expects A=8) + for config_row, filtered_ds in results: + if config_row.Index == (1, 0): + # Event 6 should now be included (has coincidence 8 and fill value TOF) + expected_events = [0, 3, 6, 9] + assert len(filtered_ds["event_met"]) == len(expected_events) + np.testing.assert_array_equal( + filtered_ds["event_met"].values, expected_events + ) + break + + def test_preserves_all_dataset_variables( + self, mock_background_config, mock_de_dataset + ): + """Test that filtered dataset preserves all original variables.""" + # Add some extra variables to the dataset + mock_de_dataset["extra_var"] = (["event_met"], np.arange(10)) + mock_de_dataset["spin_phase"] = (["event_met"], np.random.random(10)) + + results = list( + iter_background_events_by_config(mock_de_dataset, mock_background_config) + ) + + for _, filtered_ds in results: + # Check that all original variables are present + assert "coincidence_type" in filtered_ds + assert "tof_ab" in filtered_ds + assert "extra_var" in filtered_ds + assert "spin_phase" in filtered_ds + # Check that variables have correct length + n_events = len(filtered_ds["event_met"]) + assert len(filtered_ds["extra_var"]) == n_events + assert len(filtered_ds["spin_phase"]) == n_events diff --git a/imap_processing/tests/hit/helpers/l1_validation.py b/imap_processing/tests/hit/helpers/l1_validation.py index 699199b0da..1038de7c33 100644 --- a/imap_processing/tests/hit/helpers/l1_validation.py +++ b/imap_processing/tests/hit/helpers/l1_validation.py @@ -305,14 +305,16 @@ def add_species_energy(data: pd.DataFrame) -> pd.DataFrame: ) ) data["species"] = data["mod_10"].apply( - lambda row: MOD_VALUE_TO_SPECIES_ENERGY_MAP[row]["species"] - if row is not None - else None + lambda row: ( + MOD_VALUE_TO_SPECIES_ENERGY_MAP[row]["species"] if row is not None else None + ) ) data["energy_bin"] = data["mod_10"].apply( - lambda row: MOD_VALUE_TO_SPECIES_ENERGY_MAP[row]["energy_bin"] - if row is not None - else None + lambda row: ( + MOD_VALUE_TO_SPECIES_ENERGY_MAP[row]["energy_bin"] + if row is not None + else None + ) ) data.drop(columns=["sectorates_by_mod_val", "mod_10"], inplace=True) return data diff --git a/imap_processing/tests/hit/test_hit_l1a.py b/imap_processing/tests/hit/test_hit_l1a.py index 1bf7ab8156..13c672a9b9 100644 --- a/imap_processing/tests/hit/test_hit_l1a.py +++ b/imap_processing/tests/hit/test_hit_l1a.py @@ -576,6 +576,7 @@ def test_validate_l1a_housekeeping_data(hk_packet_filepath): ) +@pytest.mark.xfail(reason="To be fixed in ticket #3215", strict=False) def test_validate_l1a_counts_data(sci_packet_filepath, validation_data): """Compare the output of the L1A processing to the validation data. @@ -822,6 +823,7 @@ def test_validate_l1a_counts_data(sci_packet_filepath, validation_data): ) +@pytest.mark.xfail(reason="To be fixed in ticket #3215", strict=False) def test_hit_l1a(hk_packet_filepath, sci_packet_filepath): """Create L1A datasets from packet files. diff --git a/imap_processing/tests/hit/test_hit_l1b.py b/imap_processing/tests/hit/test_hit_l1b.py index 248ae54371..1350da7445 100644 --- a/imap_processing/tests/hit/test_hit_l1b.py +++ b/imap_processing/tests/hit/test_hit_l1b.py @@ -1,3 +1,5 @@ +from unittest import mock + import numpy as np import pandas as pd import pytest @@ -9,6 +11,7 @@ SUMMED_PARTICLE_ENERGY_RANGE_MAPPING, calculate_rates, hit_l1b, + livetime_fraction_calculation, process_sectored_rates_data, process_standard_rates_data, process_summed_rates_data, @@ -152,6 +155,7 @@ def test_sum_livetime_10min(): xr.testing.assert_equal(result, expected_livetime) +@pytest.mark.xfail(reason="To be fixed in ticket #3215", strict=False) def test_process_summed_rates_data(dependencies): """Test the variables in the summed rates dataset""" @@ -196,6 +200,7 @@ def test_process_summed_rates_data(dependencies): assert f"{particle}_energy_delta_plus" in l1b_summed_rates_dataset.data_vars +@pytest.mark.xfail(reason="To be fixed in ticket #3215", strict=False) def test_process_standard_rates_data(dependencies): """Test the variables in the standard rates dataset""" @@ -288,6 +293,7 @@ def test_process_standard_rates_data(dependencies): ) +@pytest.mark.xfail(reason="To be fixed in ticket #3215", strict=False) def test_process_sectored_rates_data(dependencies): """Test the variables in the sectored rates dataset""" @@ -335,6 +341,7 @@ def test_process_sectored_rates_data(dependencies): assert f"{particle}_energy_delta_plus" in l1b_sectored_rates_dataset.data_vars +@pytest.mark.xfail(reason="To be fixed in ticket #3215", strict=False) def test_hit_l1b_hk_dataset_variables(l1b_hk_dataset): """Test the variables in the housekeeping dataset""" # Define the keys that should have dropped from the housekeeping dataset @@ -422,6 +429,7 @@ def test_hit_l1b_hk_dataset_variables(l1b_hk_dataset): assert l1b_hk_dataset.coords.keys() == dataset_coords_dims +@pytest.mark.xfail(reason="To be fixed in ticket #3215", strict=False) def test_validate_l1b_hk_data(l1b_hk_dataset): """Test to validate the housekeeping dataset created by the L1B processing. @@ -511,16 +519,52 @@ def test_validate_l1b_hk_data(l1b_hk_dataset): ) -def test_validate_l1b_standard_rates_data(l1b_standard_rates_dataset): +def test_livetime_fraction(): + """Test the livetime fraction calculation function.""" + + # Create a sample livetime counter DataArray + livetime_counter = xr.DataArray( + np.array([0, 100, 5000, 20000], dtype=np.uint32), dims=["epoch"] + ) + + # Call the livetime fraction calculation function + livetime_fraction = livetime_fraction_calculation(livetime_counter) + + # Expected livetime fractions + expected_fractions = np.array( + [0.14, 100 * 3.41e-5 + 0.14, 5000 * 6.827e-5, 20000 * 1.04e-9], dtype=np.float32 + ) + + # Assert the result is as expected + np.testing.assert_allclose(livetime_fraction.values, expected_fractions, rtol=1e-6) + + +@mock.patch("imap_processing.hit.l1b.hit_l1b.livetime_fraction_calculation") +@pytest.mark.xfail(reason="To be fixed in ticket #3215", strict=False) +def test_validate_l1b_standard_rates_data( + livetime_fraction_calculation_mock, dependencies +): """A test to validate the standard rates dataset created by the L1B processing.""" + # Mock the livetime_fraction_calculation to use the old behavior (input / 270) + livetime_fraction_calculation_mock.side_effect = lambda livetime_counter: ( + livetime_counter / 270 + ) + + # Create the dataset with the mock in place + l1b_standard_rates_dataset = hit_l1b( + dependencies["standard-rates"], "standard-rates" + ) + + # TODO: This is old validation data and needs to be updated after the addition of + # a new livetime calculation method in L1B processing. + # For now we are mocking the old behavior to validate against this data. validation_data = pd.read_csv( imap_module_directory / "tests/hit/validation_data/hit_l1b_standard_sample2_nsrl_v4_3decimals.csv" ) validation_data = prepare_standard_rates_validation_data(validation_data) - for field in validation_data.columns: assert field in l1b_standard_rates_dataset.data_vars.keys(), ( f"Field {field} not found in actual data variables" @@ -574,6 +618,7 @@ def test_hit_l1b_unsupported_descriptor(): ("sectored-rates", "imap_hit_l1b_sectored-rates"), ], ) +@pytest.mark.xfail(reason="To be fixed in ticket #3215", strict=False) def test_hit_l1b(dependencies, dependency_key, expected_logical_source): """Test creating L1B CDF files diff --git a/imap_processing/tests/hit/test_hit_l2.py b/imap_processing/tests/hit/test_hit_l2.py index 85164726b0..0a1039bd9f 100644 --- a/imap_processing/tests/hit/test_hit_l2.py +++ b/imap_processing/tests/hit/test_hit_l2.py @@ -687,6 +687,7 @@ def test_add_total_uncertainties(): ) +@pytest.mark.xfail(reason="To be fixed in ticket #3215", strict=False) def test_process_macropixel_intensity( l1b_sectored_rates_dataset, ancillary_dependencies ): @@ -852,10 +853,11 @@ def test_process_standard_intensity(l1b_standard_rates_dataset, ancillary_depend [ ("imap_hit_l1b_summed-rates", "summed", "imap_hit_l2_summed-intensity"), ("imap_hit_l1b_standard-rates", "standard", "imap_hit_l2_standard-intensity"), - ( + pytest.param( "imap_hit_l1b_sectored-rates", "macropixel", "imap_hit_l2_macropixel-intensity", + marks=pytest.mark.xfail(reason="To be fixed in ticket #3215", strict=False), ), ], ) diff --git a/imap_processing/tests/ialirt/data/l0/UKS-DSST-GES-PLN-001 IMAP GHY-6 Availability Analysis v01.xlsx b/imap_processing/tests/ialirt/data/l0/UKS-DSST-GES-PLN-001 IMAP GHY-6 Availability Analysis v01.xlsx new file mode 100644 index 0000000000..9a70d97d4e Binary files /dev/null and b/imap_processing/tests/ialirt/data/l0/UKS-DSST-GES-PLN-001 IMAP GHY-6 Availability Analysis v01.xlsx differ diff --git a/imap_processing/tests/ialirt/data/l0/flight_iois_1.log.2025-295T17-28-05.937369 b/imap_processing/tests/ialirt/data/l0/flight_iois_1.log.2025-295T17-28-05.937369 new file mode 100644 index 0000000000..125e8a9b9d --- /dev/null +++ b/imap_processing/tests/ialirt/data/l0/flight_iois_1.log.2025-295T17-28-05.937369 @@ -0,0 +1,202 @@ +ID Description LastDataRcvd ConnectionTime Rate (kbps) + 2 tlmrelay 295-16:28:03 277-08:58:24 1.5 +10 Kiel 295-13:54:00 295-05:19:13 0.0 +2025/295-16:28:40.308 Closed packets file for SDC: iois_1_packets_2025_295_16_27_39.partial +2025/295-16:28:40.308 Renamed iois_1_packets_2025_295_16_27_39.partial to iois_1_packets_2025_295_16_27_39. +2025/295-16:28:40.308 Spawning: mv +2025/295-16:28:40.308 Opened packets file for SDC: iois_1_packets_2025_295_16_28_40.partial +2025/295-16:28:41.310 Spawned command succeeded: mv +2025/295-16:29:41.956 Closed packets file for SDC: iois_1_packets_2025_295_16_28_40.partial +2025/295-16:29:41.956 Renamed iois_1_packets_2025_295_16_28_40.partial to iois_1_packets_2025_295_16_28_40. +2025/295-16:29:41.956 Spawning: mv +2025/295-16:29:41.956 Opened packets file for SDC: iois_1_packets_2025_295_16_29_41.partial +2025/295-16:29:42.960 Spawned command succeeded: mv +2025/295-16:30:42.104 Closed packets file for SDC: iois_1_packets_2025_295_16_29_41.partial +2025/295-16:30:42.104 Renamed iois_1_packets_2025_295_16_29_41.partial to iois_1_packets_2025_295_16_29_41. +2025/295-16:30:42.104 Spawning: mv +2025/295-16:30:42.104 Opened packets file for SDC: iois_1_packets_2025_295_16_30_42.partial +2025/295-16:30:43.093 Spawned command succeeded: mv +2025/295-16:31:00.161 Deleting zero-length file: IOIS_1_raw_record_20_2025_295_16_26_00.partial +2025/295-16:31:00.162 Opened raw record file for Kiel antenna_partner: IOIS_1_raw_record_20_2025_295_16_31_00.partial +2025/295-16:31:43.225 Closed packets file for SDC: iois_1_packets_2025_295_16_30_42.partial +2025/295-16:31:43.225 Renamed iois_1_packets_2025_295_16_30_42.partial to iois_1_packets_2025_295_16_30_42. +2025/295-16:31:43.225 Spawning: mv +2025/295-16:31:43.225 Opened packets file for SDC: iois_1_packets_2025_295_16_31_43.partial +2025/295-16:31:44.226 Spawned command succeeded: mv +2025/295-16:32:44.388 Closed packets file for SDC: iois_1_packets_2025_295_16_31_43.partial +2025/295-16:32:44.389 Renamed iois_1_packets_2025_295_16_31_43.partial to iois_1_packets_2025_295_16_31_43. +2025/295-16:32:44.389 Spawning: mv +2025/295-16:32:44.389 Opened packets file for SDC: iois_1_packets_2025_295_16_32_44.partial +2025/295-16:32:45.392 Spawned command succeeded: mv +2025/295-16:33:45.043 Closed packets file for SDC: iois_1_packets_2025_295_16_32_44.partial +2025/295-16:33:45.043 Renamed iois_1_packets_2025_295_16_32_44.partial to iois_1_packets_2025_295_16_32_44. +2025/295-16:33:45.043 Spawning: mv +2025/295-16:33:45.043 Opened packets file for SDC: iois_1_packets_2025_295_16_33_45.partial +2025/295-16:33:46.046 Spawned command succeeded: mv +2025/295-16:34:46.204 Closed packets file for SDC: iois_1_packets_2025_295_16_33_45.partial +2025/295-16:34:46.204 Renamed iois_1_packets_2025_295_16_33_45.partial to iois_1_packets_2025_295_16_33_45. +2025/295-16:34:46.204 Spawning: mv +2025/295-16:34:46.204 Opened packets file for SDC: iois_1_packets_2025_295_16_34_46.partial +2025/295-16:34:47.205 Spawned command succeeded: mv +2025/295-16:35:47.860 Closed packets file for SDC: iois_1_packets_2025_295_16_34_46.partial +2025/295-16:35:47.860 Renamed iois_1_packets_2025_295_16_34_46.partial to iois_1_packets_2025_295_16_34_46. +2025/295-16:35:47.860 Spawning: mv +2025/295-16:35:47.860 Opened packets file for SDC: iois_1_packets_2025_295_16_35_47.partial +2025/295-16:35:48.862 Spawned command succeeded: mv +2025/295-16:36:00.891 Deleting zero-length file: IOIS_1_raw_record_20_2025_295_16_31_00.partial +2025/295-16:36:00.891 Opened raw record file for Kiel antenna_partner: IOIS_1_raw_record_20_2025_295_16_36_00.partial +2025/295-16:36:48.001 Closed packets file for SDC: iois_1_packets_2025_295_16_35_47.partial +2025/295-16:36:48.001 Renamed iois_1_packets_2025_295_16_35_47.partial to iois_1_packets_2025_295_16_35_47. +2025/295-16:36:48.001 Spawning: mv +2025/295-16:36:48.001 Opened packets file for SDC: iois_1_packets_2025_295_16_36_48.partial +2025/295-16:36:49.002 Spawned command succeeded: mv +2025/295-16:37:49.657 Closed packets file for SDC: iois_1_packets_2025_295_16_36_48.partial +2025/295-16:37:49.657 Renamed iois_1_packets_2025_295_16_36_48.partial to iois_1_packets_2025_295_16_36_48. +2025/295-16:37:49.657 Spawning: mv +2025/295-16:37:49.658 Opened packets file for SDC: iois_1_packets_2025_295_16_37_49.partial +2025/295-16:37:51.645 Spawned command succeeded: mv +2025/295-16:38:50.308 Closed packets file for SDC: iois_1_packets_2025_295_16_37_49.partial +2025/295-16:38:50.308 Renamed iois_1_packets_2025_295_16_37_49.partial to iois_1_packets_2025_295_16_37_49. +2025/295-16:38:50.308 Spawning: mv +2025/295-16:38:50.308 Opened packets file for SDC: iois_1_packets_2025_295_16_38_50.partial +2025/295-16:38:51.309 Spawned command succeeded: mv +2025/295-16:39:51.448 Closed packets file for SDC: iois_1_packets_2025_295_16_38_50.partial +2025/295-16:39:51.448 Renamed iois_1_packets_2025_295_16_38_50.partial to iois_1_packets_2025_295_16_38_50. +2025/295-16:39:51.448 Spawning: mv +2025/295-16:39:51.448 Opened packets file for SDC: iois_1_packets_2025_295_16_39_51.partial +2025/295-16:39:52.449 Spawned command succeeded: mv +2025/295-16:40:52.099 Closed packets file for SDC: iois_1_packets_2025_295_16_39_51.partial +2025/295-16:40:52.099 Renamed iois_1_packets_2025_295_16_39_51.partial to iois_1_packets_2025_295_16_39_51. +2025/295-16:40:52.099 Spawning: mv +2025/295-16:40:52.099 Opened packets file for SDC: iois_1_packets_2025_295_16_40_52.partial +2025/295-16:40:53.101 Spawned command succeeded: mv +2025/295-16:41:00.120 Deleting zero-length file: IOIS_1_raw_record_20_2025_295_16_36_00.partial +2025/295-16:41:00.120 Opened raw record file for Kiel antenna_partner: IOIS_1_raw_record_20_2025_295_16_41_00.partial +2025/295-16:41:53.769 Closed packets file for SDC: iois_1_packets_2025_295_16_40_52.partial +2025/295-16:41:53.769 Renamed iois_1_packets_2025_295_16_40_52.partial to iois_1_packets_2025_295_16_40_52. +2025/295-16:41:53.769 Spawning: mv +2025/295-16:41:53.769 Opened packets file for SDC: iois_1_packets_2025_295_16_41_53.partial +2025/295-16:41:54.836 Spawned command succeeded: mv +2025/295-16:42:54.940 Closed packets file for SDC: iois_1_packets_2025_295_16_41_53.partial +2025/295-16:42:54.940 Renamed iois_1_packets_2025_295_16_41_53.partial to iois_1_packets_2025_295_16_41_53. +2025/295-16:42:54.940 Spawning: mv +2025/295-16:42:54.940 Opened packets file for SDC: iois_1_packets_2025_295_16_42_54.partial +2025/295-16:42:55.940 Spawned command succeeded: mv +2025/295-16:43:55.098 Closed packets file for SDC: iois_1_packets_2025_295_16_42_54.partial +2025/295-16:43:55.098 Renamed iois_1_packets_2025_295_16_42_54.partial to iois_1_packets_2025_295_16_42_54. +2025/295-16:43:55.098 Spawning: mv +2025/295-16:43:55.098 Opened packets file for SDC: iois_1_packets_2025_295_16_43_55.partial +2025/295-16:43:56.098 Spawned command succeeded: mv +2025/295-16:44:56.250 Closed packets file for SDC: iois_1_packets_2025_295_16_43_55.partial +2025/295-16:44:56.250 Renamed iois_1_packets_2025_295_16_43_55.partial to iois_1_packets_2025_295_16_43_55. +2025/295-16:44:56.250 Spawning: mv +2025/295-16:44:56.250 Opened packets file for SDC: iois_1_packets_2025_295_16_44_56.partial +2025/295-16:44:57.252 Spawned command succeeded: mv +2025/295-16:45:57.320 Closed packets file for SDC: iois_1_packets_2025_295_16_44_56.partial +2025/295-16:45:57.320 Renamed iois_1_packets_2025_295_16_44_56.partial to iois_1_packets_2025_295_16_44_56. +2025/295-16:45:57.320 Spawning: mv +2025/295-16:45:57.320 Opened packets file for SDC: iois_1_packets_2025_295_16_45_57.partial +2025/295-16:45:59.323 Spawned command succeeded: mv +2025/295-16:46:01.325 Deleting zero-length file: IOIS_1_raw_record_20_2025_295_16_41_00.partial +2025/295-16:46:01.325 Opened raw record file for Kiel antenna_partner: IOIS_1_raw_record_20_2025_295_16_46_01.partial +2025/295-16:46:59.386 Deleting zero-length file: iois_1_packets_2025_295_16_45_57.partial +2025/295-16:46:59.386 Opened packets file for SDC: iois_1_packets_2025_295_16_46_59.partial +2025/295-16:48:01.450 Deleting zero-length file: iois_1_packets_2025_295_16_46_59.partial +2025/295-16:48:01.450 Opened packets file for SDC: iois_1_packets_2025_295_16_48_01.partial +2025/295-16:49:03.514 Deleting zero-length file: iois_1_packets_2025_295_16_48_01.partial +2025/295-16:49:03.514 Opened packets file for SDC: iois_1_packets_2025_295_16_49_03.partial +2025/295-16:50:05.580 Deleting zero-length file: iois_1_packets_2025_295_16_49_03.partial +2025/295-16:50:05.580 Opened packets file for SDC: iois_1_packets_2025_295_16_50_05.partial +2025/295-16:51:01.640 Deleting zero-length file: IOIS_1_raw_record_20_2025_295_16_46_01.partial +2025/295-16:51:01.640 Opened raw record file for Kiel antenna_partner: IOIS_1_raw_record_20_2025_295_16_51_01.partial +2025/295-16:51:07.646 Deleting zero-length file: iois_1_packets_2025_295_16_50_05.partial +2025/295-16:51:07.646 Opened packets file for SDC: iois_1_packets_2025_295_16_51_07.partial +2025/295-16:52:09.712 Deleting zero-length file: iois_1_packets_2025_295_16_51_07.partial +2025/295-16:52:09.712 Opened packets file for SDC: iois_1_packets_2025_295_16_52_09.partial +2025/295-16:53:11.777 Deleting zero-length file: iois_1_packets_2025_295_16_52_09.partial +2025/295-16:53:11.777 Opened packets file for SDC: iois_1_packets_2025_295_16_53_11.partial +2025/295-16:54:13.842 Deleting zero-length file: iois_1_packets_2025_295_16_53_11.partial +2025/295-16:54:13.843 Opened packets file for SDC: iois_1_packets_2025_295_16_54_13.partial +2025/295-16:55:15.901 Deleting zero-length file: iois_1_packets_2025_295_16_54_13.partial +2025/295-16:55:15.901 Opened packets file for SDC: iois_1_packets_2025_295_16_55_15.partial +2025/295-16:56:01.948 Deleting zero-length file: IOIS_1_raw_record_20_2025_295_16_51_01.partial +2025/295-16:56:01.948 Opened raw record file for Kiel antenna_partner: IOIS_1_raw_record_20_2025_295_16_56_01.partial +2025/295-16:56:17.965 Deleting zero-length file: iois_1_packets_2025_295_16_55_15.partial +2025/295-16:56:17.965 Opened packets file for SDC: iois_1_packets_2025_295_16_56_17.partial +2025/295-16:57:18.027 Deleting zero-length file: iois_1_packets_2025_295_16_56_17.partial +2025/295-16:57:18.027 Opened packets file for SDC: iois_1_packets_2025_295_16_57_18.partial +2025/295-16:58:04.075 Periodic status report: +ID Description LastDataRcvd ConnectionTime Rate (kbps) + 2 tlmrelay 295-16:45:03 277-08:58:24 0.0 +10 Kiel 295-13:54:00 295-05:19:13 0.0 +2025/295-16:58:20.092 Deleting zero-length file: iois_1_packets_2025_295_16_57_18.partial +2025/295-16:58:20.093 Opened packets file for SDC: iois_1_packets_2025_295_16_58_20.partial +2025/295-16:59:22.156 Deleting zero-length file: iois_1_packets_2025_295_16_58_20.partial +2025/295-16:59:22.156 Opened packets file for SDC: iois_1_packets_2025_295_16_59_22.partial +2025/295-17:00:24.221 Deleting zero-length file: iois_1_packets_2025_295_16_59_22.partial +2025/295-17:00:24.221 Opened packets file for SDC: iois_1_packets_2025_295_17_00_24.partial +2025/295-17:01:00.258 Deleting zero-length file: IOIS_1_raw_record_20_2025_295_16_56_01.partial +2025/295-17:01:00.258 Opened raw record file for Kiel antenna_partner: IOIS_1_raw_record_20_2025_295_17_01_00.partial +2025/295-17:01:26.285 Deleting zero-length file: iois_1_packets_2025_295_17_00_24.partial +2025/295-17:01:26.285 Opened packets file for SDC: iois_1_packets_2025_295_17_01_26.partial +2025/295-17:02:28.350 Deleting zero-length file: iois_1_packets_2025_295_17_01_26.partial +2025/295-17:02:28.350 Opened packets file for SDC: iois_1_packets_2025_295_17_02_28.partial +2025/295-17:03:30.412 Deleting zero-length file: iois_1_packets_2025_295_17_02_28.partial +2025/295-17:03:30.412 Opened packets file for SDC: iois_1_packets_2025_295_17_03_30.partial +2025/295-17:04:32.477 Deleting zero-length file: iois_1_packets_2025_295_17_03_30.partial +2025/295-17:04:32.477 Opened packets file for SDC: iois_1_packets_2025_295_17_04_32.partial +2025/295-17:05:34.540 Deleting zero-length file: iois_1_packets_2025_295_17_04_32.partial +2025/295-17:05:34.540 Opened packets file for SDC: iois_1_packets_2025_295_17_05_34.partial +2025/295-17:06:00.568 Deleting zero-length file: IOIS_1_raw_record_20_2025_295_17_01_00.partial +2025/295-17:06:00.568 Opened raw record file for Kiel antenna_partner: IOIS_1_raw_record_20_2025_295_17_06_00.partial +2025/295-17:06:36.604 Deleting zero-length file: iois_1_packets_2025_295_17_05_34.partial +2025/295-17:06:36.605 Opened packets file for SDC: iois_1_packets_2025_295_17_06_36.partial +2025/295-17:07:38.669 Deleting zero-length file: iois_1_packets_2025_295_17_06_36.partial +2025/295-17:07:38.669 Opened packets file for SDC: iois_1_packets_2025_295_17_07_38.partial +2025/295-17:08:40.734 Deleting zero-length file: iois_1_packets_2025_295_17_07_38.partial +2025/295-17:08:40.734 Opened packets file for SDC: iois_1_packets_2025_295_17_08_40.partial +2025/295-17:09:42.799 Deleting zero-length file: iois_1_packets_2025_295_17_08_40.partial +2025/295-17:09:42.799 Opened packets file for SDC: iois_1_packets_2025_295_17_09_42.partial +2025/295-17:10:44.864 Deleting zero-length file: iois_1_packets_2025_295_17_09_42.partial +2025/295-17:10:44.864 Opened packets file for SDC: iois_1_packets_2025_295_17_10_44.partial +2025/295-17:11:00.881 Deleting zero-length file: IOIS_1_raw_record_20_2025_295_17_06_00.partial +2025/295-17:11:00.881 Opened raw record file for Kiel antenna_partner: IOIS_1_raw_record_20_2025_295_17_11_00.partial +2025/295-17:11:46.930 Deleting zero-length file: iois_1_packets_2025_295_17_10_44.partial +2025/295-17:11:46.930 Opened packets file for SDC: iois_1_packets_2025_295_17_11_46.partial +2025/295-17:12:48.994 Deleting zero-length file: iois_1_packets_2025_295_17_11_46.partial +2025/295-17:12:48.994 Opened packets file for SDC: iois_1_packets_2025_295_17_12_48.partial +2025/295-17:13:49.056 Deleting zero-length file: iois_1_packets_2025_295_17_12_48.partial +2025/295-17:13:49.056 Opened packets file for SDC: iois_1_packets_2025_295_17_13_49.partial +2025/295-17:14:51.122 Deleting zero-length file: iois_1_packets_2025_295_17_13_49.partial +2025/295-17:14:51.122 Opened packets file for SDC: iois_1_packets_2025_295_17_14_51.partial +2025/295-17:15:53.186 Deleting zero-length file: iois_1_packets_2025_295_17_14_51.partial +2025/295-17:15:53.186 Opened packets file for SDC: iois_1_packets_2025_295_17_15_53.partial +2025/295-17:16:01.195 Deleting zero-length file: IOIS_1_raw_record_20_2025_295_17_11_00.partial +2025/295-17:16:01.195 Opened raw record file for Kiel antenna_partner: IOIS_1_raw_record_20_2025_295_17_16_01.partial +2025/295-17:16:55.251 Deleting zero-length file: iois_1_packets_2025_295_17_15_53.partial +2025/295-17:16:55.251 Opened packets file for SDC: iois_1_packets_2025_295_17_16_55.partial +2025/295-17:17:57.317 Deleting zero-length file: iois_1_packets_2025_295_17_16_55.partial +2025/295-17:17:57.317 Opened packets file for SDC: iois_1_packets_2025_295_17_17_57.partial +2025/295-17:18:59.377 Deleting zero-length file: iois_1_packets_2025_295_17_17_57.partial +2025/295-17:18:59.377 Opened packets file for SDC: iois_1_packets_2025_295_17_18_59.partial +2025/295-17:20:01.442 Deleting zero-length file: iois_1_packets_2025_295_17_18_59.partial +2025/295-17:20:01.442 Opened packets file for SDC: iois_1_packets_2025_295_17_20_01.partial +2025/295-17:21:01.500 Deleting zero-length file: IOIS_1_raw_record_20_2025_295_17_16_01.partial +2025/295-17:21:01.500 Opened raw record file for Kiel antenna_partner: IOIS_1_raw_record_20_2025_295_17_21_01.partial +2025/295-17:21:03.502 Deleting zero-length file: iois_1_packets_2025_295_17_20_01.partial +2025/295-17:21:03.502 Opened packets file for SDC: iois_1_packets_2025_295_17_21_03.partial +2025/295-17:22:05.566 Deleting zero-length file: iois_1_packets_2025_295_17_21_03.partial +2025/295-17:22:05.566 Opened packets file for SDC: iois_1_packets_2025_295_17_22_05.partial +2025/295-17:23:07.629 Deleting zero-length file: iois_1_packets_2025_295_17_22_05.partial +2025/295-17:23:07.630 Opened packets file for SDC: iois_1_packets_2025_295_17_23_07.partial +2025/295-17:24:09.694 Deleting zero-length file: iois_1_packets_2025_295_17_23_07.partial +2025/295-17:24:09.694 Opened packets file for SDC: iois_1_packets_2025_295_17_24_09.partial +2025/295-17:25:11.753 Deleting zero-length file: iois_1_packets_2025_295_17_24_09.partial +2025/295-17:25:11.754 Opened packets file for SDC: iois_1_packets_2025_295_17_25_11.partial +2025/295-17:26:01.807 Deleting zero-length file: IOIS_1_raw_record_20_2025_295_17_21_01.partial +2025/295-17:26:01.807 Opened raw record file for Kiel antenna_partner: IOIS_1_raw_record_20_2025_295_17_26_01.partial +2025/295-17:26:13.820 Deleting zero-length file: iois_1_packets_2025_295_17_25_11.partial +2025/295-17:26:13.820 Opened packets file for SDC: iois_1_packets_2025_295_17_26_13.partial +2025/295-17:27:15.884 Deleting zero-length file: iois_1_packets_2025_295_17_26_13.partial +2025/295-17:27:15.884 Opened packets file for SDC: iois_1_packets_2025_295_17_27_15.partial +2025/295-17:28:05.937 Periodic status report: diff --git a/imap_processing/tests/ialirt/data/l0/flight_iois_1.log.2026-021T10-58-00.171087 b/imap_processing/tests/ialirt/data/l0/flight_iois_1.log.2026-021T10-58-00.171087 new file mode 100644 index 0000000000..6fe75bf156 --- /dev/null +++ b/imap_processing/tests/ialirt/data/l0/flight_iois_1.log.2026-021T10-58-00.171087 @@ -0,0 +1,363 @@ +ID Description LastDataRcvd ConnectionTime Rate (kbps) + 2 tlmrelay 001-00:00:00 020-19:57:14 0.0 +10 Kiel 021-09:57:58 021-08:40:39 2.0 +2026/021-09:58:26.231 Closed packets file for SDC: iois_1_packets_2026_021_09_57_25.partial +2026/021-09:58:26.231 Renamed iois_1_packets_2026_021_09_57_25.partial to iois_1_packets_2026_021_09_57_25. +2026/021-09:58:26.231 Spawning: mv +2026/021-09:58:26.231 Opened packets file for SDC: iois_1_packets_2026_021_09_58_26.partial +2026/021-09:58:27.126 Spawned command succeeded: mv +2026/021-09:59:27.455 Closed packets file for SDC: iois_1_packets_2026_021_09_58_26.partial +2026/021-09:59:27.455 Renamed iois_1_packets_2026_021_09_58_26.partial to iois_1_packets_2026_021_09_58_26. +2026/021-09:59:27.455 Spawning: mv +2026/021-09:59:27.455 Opened packets file for SDC: iois_1_packets_2026_021_09_59_27.partial +2026/021-09:59:28.274 Spawned command succeeded: mv +2026/021-10:00:28.556 Closed packets file for SDC: iois_1_packets_2026_021_09_59_27.partial +2026/021-10:00:28.556 Renamed iois_1_packets_2026_021_09_59_27.partial to iois_1_packets_2026_021_09_59_27. +2026/021-10:00:28.556 Spawning: mv +2026/021-10:00:28.556 Opened packets file for SDC: iois_1_packets_2026_021_10_00_28.partial +2026/021-10:00:29.411 Spawned command succeeded: mv +2026/021-10:01:00.009 Closed raw record file for Kiel antenna_partner: IOIS_1_raw_record_20_2026_021_09_56_00.partial +2026/021-10:01:00.009 Renamed IOIS_1_raw_record_20_2026_021_09_56_00.partial to IOIS_1_raw_record_20_2026_021_09_56_00. +2026/021-10:01:00.009 Spawning: rsync +2026/021-10:01:00.010 Opened raw record file for Kiel antenna_partner: IOIS_1_raw_record_20_2026_021_10_01_00.partial +2026/021-10:01:02.628 Spawned command succeeded: rsync +2026/021-10:01:29.698 Closed packets file for SDC: iois_1_packets_2026_021_10_00_28.partial +2026/021-10:01:29.698 Renamed iois_1_packets_2026_021_10_00_28.partial to iois_1_packets_2026_021_10_00_28. +2026/021-10:01:29.698 Spawning: mv +2026/021-10:01:29.698 Opened packets file for SDC: iois_1_packets_2026_021_10_01_29.partial +2026/021-10:01:30.630 Spawned command succeeded: mv +2026/021-10:02:30.851 Closed packets file for SDC: iois_1_packets_2026_021_10_01_29.partial +2026/021-10:02:30.851 Renamed iois_1_packets_2026_021_10_01_29.partial to iois_1_packets_2026_021_10_01_29. +2026/021-10:02:30.851 Spawning: mv +2026/021-10:02:30.851 Opened packets file for SDC: iois_1_packets_2026_021_10_02_30.partial +2026/021-10:02:31.740 Spawned command succeeded: mv +2026/021-10:03:31.133 Closed packets file for SDC: iois_1_packets_2026_021_10_02_30.partial +2026/021-10:03:31.133 Renamed iois_1_packets_2026_021_10_02_30.partial to iois_1_packets_2026_021_10_02_30. +2026/021-10:03:31.133 Spawning: mv +2026/021-10:03:31.133 Opened packets file for SDC: iois_1_packets_2026_021_10_03_31.partial +2026/021-10:03:32.023 Spawned command succeeded: mv +2026/021-10:04:32.269 Closed packets file for SDC: iois_1_packets_2026_021_10_03_31.partial +2026/021-10:04:32.270 Renamed iois_1_packets_2026_021_10_03_31.partial to iois_1_packets_2026_021_10_03_31. +2026/021-10:04:32.270 Spawning: mv +2026/021-10:04:32.270 Opened packets file for SDC: iois_1_packets_2026_021_10_04_32.partial +2026/021-10:04:33.206 Spawned command succeeded: mv +2026/021-10:05:33.458 Closed packets file for SDC: iois_1_packets_2026_021_10_04_32.partial +2026/021-10:05:33.459 Renamed iois_1_packets_2026_021_10_04_32.partial to iois_1_packets_2026_021_10_04_32. +2026/021-10:05:33.459 Spawning: mv +2026/021-10:05:33.459 Opened packets file for SDC: iois_1_packets_2026_021_10_05_33.partial +2026/021-10:05:34.315 Spawned command succeeded: mv +2026/021-10:06:00.505 Closed raw record file for Kiel antenna_partner: IOIS_1_raw_record_20_2026_021_10_01_00.partial +2026/021-10:06:00.505 Renamed IOIS_1_raw_record_20_2026_021_10_01_00.partial to IOIS_1_raw_record_20_2026_021_10_01_00. +2026/021-10:06:00.505 Spawning: rsync +2026/021-10:06:00.505 Opened raw record file for Kiel antenna_partner: IOIS_1_raw_record_20_2026_021_10_06_00.partial +2026/021-10:06:03.149 Spawned command succeeded: rsync +2026/021-10:06:34.629 Closed packets file for SDC: iois_1_packets_2026_021_10_05_33.partial +2026/021-10:06:34.629 Renamed iois_1_packets_2026_021_10_05_33.partial to iois_1_packets_2026_021_10_05_33. +2026/021-10:06:34.629 Spawning: mv +2026/021-10:06:34.629 Opened packets file for SDC: iois_1_packets_2026_021_10_06_34.partial +2026/021-10:06:35.453 Spawned command succeeded: mv +2026/021-10:07:35.734 Closed packets file for SDC: iois_1_packets_2026_021_10_06_34.partial +2026/021-10:07:35.734 Renamed iois_1_packets_2026_021_10_06_34.partial to iois_1_packets_2026_021_10_06_34. +2026/021-10:07:35.734 Spawning: mv +2026/021-10:07:35.735 Opened packets file for SDC: iois_1_packets_2026_021_10_07_35.partial +2026/021-10:07:36.631 Spawned command succeeded: mv +2026/021-10:08:36.029 Closed packets file for SDC: iois_1_packets_2026_021_10_07_35.partial +2026/021-10:08:36.029 Renamed iois_1_packets_2026_021_10_07_35.partial to iois_1_packets_2026_021_10_07_35. +2026/021-10:08:36.029 Spawning: mv +2026/021-10:08:36.029 Opened packets file for SDC: iois_1_packets_2026_021_10_08_36.partial +2026/021-10:08:36.892 Spawned command succeeded: mv +2026/021-10:09:37.170 Closed packets file for SDC: iois_1_packets_2026_021_10_08_36.partial +2026/021-10:09:37.170 Renamed iois_1_packets_2026_021_10_08_36.partial to iois_1_packets_2026_021_10_08_36. +2026/021-10:09:37.170 Spawning: mv +2026/021-10:09:37.170 Opened packets file for SDC: iois_1_packets_2026_021_10_09_37.partial +2026/021-10:09:38.067 Spawned command succeeded: mv +2026/021-10:10:38.311 Closed packets file for SDC: iois_1_packets_2026_021_10_09_37.partial +2026/021-10:10:38.311 Renamed iois_1_packets_2026_021_10_09_37.partial to iois_1_packets_2026_021_10_09_37. +2026/021-10:10:38.311 Spawning: mv +2026/021-10:10:38.311 Opened packets file for SDC: iois_1_packets_2026_021_10_10_38.partial +2026/021-10:10:39.207 Spawned command succeeded: mv +2026/021-10:11:00.152 Closed raw record file for Kiel antenna_partner: IOIS_1_raw_record_20_2026_021_10_06_00.partial +2026/021-10:11:00.152 Renamed IOIS_1_raw_record_20_2026_021_10_06_00.partial to IOIS_1_raw_record_20_2026_021_10_06_00. +2026/021-10:11:00.152 Spawning: rsync +2026/021-10:11:00.152 Opened raw record file for Kiel antenna_partner: IOIS_1_raw_record_20_2026_021_10_11_00.partial +2026/021-10:11:03.650 Spawned command succeeded: rsync +2026/021-10:11:39.489 Closed packets file for SDC: iois_1_packets_2026_021_10_10_38.partial +2026/021-10:11:39.489 Renamed iois_1_packets_2026_021_10_10_38.partial to iois_1_packets_2026_021_10_10_38. +2026/021-10:11:39.489 Spawning: mv +2026/021-10:11:39.490 Opened packets file for SDC: iois_1_packets_2026_021_10_11_39.partial +2026/021-10:11:40.360 Spawned command succeeded: mv +2026/021-10:12:40.673 Closed packets file for SDC: iois_1_packets_2026_021_10_11_39.partial +2026/021-10:12:40.673 Renamed iois_1_packets_2026_021_10_11_39.partial to iois_1_packets_2026_021_10_11_39. +2026/021-10:12:40.673 Spawning: mv +2026/021-10:12:40.673 Opened packets file for SDC: iois_1_packets_2026_021_10_12_40.partial +2026/021-10:12:41.493 Spawned command succeeded: mv +2026/021-10:13:41.777 Closed packets file for SDC: iois_1_packets_2026_021_10_12_40.partial +2026/021-10:13:41.777 Renamed iois_1_packets_2026_021_10_12_40.partial to iois_1_packets_2026_021_10_12_40. +2026/021-10:13:41.777 Spawning: mv +2026/021-10:13:41.778 Opened packets file for SDC: iois_1_packets_2026_021_10_13_41.partial +2026/021-10:13:42.669 Spawned command succeeded: mv +2026/021-10:14:42.067 Closed packets file for SDC: iois_1_packets_2026_021_10_13_41.partial +2026/021-10:14:42.067 Renamed iois_1_packets_2026_021_10_13_41.partial to iois_1_packets_2026_021_10_13_41. +2026/021-10:14:42.067 Spawning: mv +2026/021-10:14:42.068 Opened packets file for SDC: iois_1_packets_2026_021_10_14_42.partial +2026/021-10:14:42.922 Spawned command succeeded: mv +2026/021-10:15:43.210 Closed packets file for SDC: iois_1_packets_2026_021_10_14_42.partial +2026/021-10:15:43.210 Renamed iois_1_packets_2026_021_10_14_42.partial to iois_1_packets_2026_021_10_14_42. +2026/021-10:15:43.210 Spawning: mv +2026/021-10:15:43.210 Opened packets file for SDC: iois_1_packets_2026_021_10_15_43.partial +2026/021-10:15:44.147 Spawned command succeeded: mv +2026/021-10:16:00.708 Closed raw record file for Kiel antenna_partner: IOIS_1_raw_record_20_2026_021_10_11_00.partial +2026/021-10:16:00.708 Renamed IOIS_1_raw_record_20_2026_021_10_11_00.partial to IOIS_1_raw_record_20_2026_021_10_11_00. +2026/021-10:16:00.708 Spawning: rsync +2026/021-10:16:00.708 Opened raw record file for Kiel antenna_partner: IOIS_1_raw_record_20_2026_021_10_16_00.partial +2026/021-10:16:04.207 Spawned command succeeded: rsync +2026/021-10:16:44.357 Closed packets file for SDC: iois_1_packets_2026_021_10_15_43.partial +2026/021-10:16:44.357 Renamed iois_1_packets_2026_021_10_15_43.partial to iois_1_packets_2026_021_10_15_43. +2026/021-10:16:44.358 Spawning: mv +2026/021-10:16:44.358 Opened packets file for SDC: iois_1_packets_2026_021_10_16_44.partial +2026/021-10:16:45.249 Spawned command succeeded: mv +2026/021-10:17:45.530 Closed packets file for SDC: iois_1_packets_2026_021_10_16_44.partial +2026/021-10:17:45.530 Renamed iois_1_packets_2026_021_10_16_44.partial to iois_1_packets_2026_021_10_16_44. +2026/021-10:17:45.530 Spawning: mv +2026/021-10:17:45.530 Opened packets file for SDC: iois_1_packets_2026_021_10_17_45.partial +2026/021-10:17:46.389 Spawned command succeeded: mv +2026/021-10:18:46.694 Closed packets file for SDC: iois_1_packets_2026_021_10_17_45.partial +2026/021-10:18:46.694 Renamed iois_1_packets_2026_021_10_17_45.partial to iois_1_packets_2026_021_10_17_45. +2026/021-10:18:46.694 Spawning: mv +2026/021-10:18:46.694 Opened packets file for SDC: iois_1_packets_2026_021_10_18_46.partial +2026/021-10:18:47.530 Spawned command succeeded: mv +2026/021-10:19:47.822 Closed packets file for SDC: iois_1_packets_2026_021_10_18_46.partial +2026/021-10:19:47.822 Renamed iois_1_packets_2026_021_10_18_46.partial to iois_1_packets_2026_021_10_18_46. +2026/021-10:19:47.822 Spawning: mv +2026/021-10:19:47.822 Opened packets file for SDC: iois_1_packets_2026_021_10_19_47.partial +2026/021-10:19:48.704 Spawned command succeeded: mv +2026/021-10:20:48.133 Closed packets file for SDC: iois_1_packets_2026_021_10_19_47.partial +2026/021-10:20:48.134 Renamed iois_1_packets_2026_021_10_19_47.partial to iois_1_packets_2026_021_10_19_47. +2026/021-10:20:48.134 Spawning: mv +2026/021-10:20:48.134 Opened packets file for SDC: iois_1_packets_2026_021_10_20_48.partial +2026/021-10:20:48.965 Spawned command succeeded: mv +2026/021-10:21:00.360 Closed raw record file for Kiel antenna_partner: IOIS_1_raw_record_20_2026_021_10_16_00.partial +2026/021-10:21:00.360 Renamed IOIS_1_raw_record_20_2026_021_10_16_00.partial to IOIS_1_raw_record_20_2026_021_10_16_00. +2026/021-10:21:00.360 Spawning: rsync +2026/021-10:21:00.360 Opened raw record file for Kiel antenna_partner: IOIS_1_raw_record_20_2026_021_10_21_00.partial +2026/021-10:21:02.945 Spawned command succeeded: rsync +2026/021-10:21:49.252 Closed packets file for SDC: iois_1_packets_2026_021_10_20_48.partial +2026/021-10:21:49.252 Renamed iois_1_packets_2026_021_10_20_48.partial to iois_1_packets_2026_021_10_20_48. +2026/021-10:21:49.252 Spawning: mv +2026/021-10:21:49.252 Opened packets file for SDC: iois_1_packets_2026_021_10_21_49.partial +2026/021-10:21:50.138 Spawned command succeeded: mv +2026/021-10:22:50.384 Closed packets file for SDC: iois_1_packets_2026_021_10_21_49.partial +2026/021-10:22:50.384 Renamed iois_1_packets_2026_021_10_21_49.partial to iois_1_packets_2026_021_10_21_49. +2026/021-10:22:50.384 Spawning: mv +2026/021-10:22:50.384 Opened packets file for SDC: iois_1_packets_2026_021_10_22_50.partial +2026/021-10:22:51.285 Spawned command succeeded: mv +2026/021-10:23:51.571 Closed packets file for SDC: iois_1_packets_2026_021_10_22_50.partial +2026/021-10:23:51.571 Renamed iois_1_packets_2026_021_10_22_50.partial to iois_1_packets_2026_021_10_22_50. +2026/021-10:23:51.571 Spawning: mv +2026/021-10:23:51.571 Opened packets file for SDC: iois_1_packets_2026_021_10_23_51.partial +2026/021-10:23:52.417 Spawned command succeeded: mv +2026/021-10:24:52.709 Closed packets file for SDC: iois_1_packets_2026_021_10_23_51.partial +2026/021-10:24:52.709 Renamed iois_1_packets_2026_021_10_23_51.partial to iois_1_packets_2026_021_10_23_51. +2026/021-10:24:52.709 Spawning: mv +2026/021-10:24:52.709 Opened packets file for SDC: iois_1_packets_2026_021_10_24_52.partial +2026/021-10:24:53.574 Spawned command succeeded: mv +2026/021-10:25:53.855 Closed packets file for SDC: iois_1_packets_2026_021_10_24_52.partial +2026/021-10:25:53.855 Renamed iois_1_packets_2026_021_10_24_52.partial to iois_1_packets_2026_021_10_24_52. +2026/021-10:25:53.855 Spawning: mv +2026/021-10:25:53.855 Opened packets file for SDC: iois_1_packets_2026_021_10_25_53.partial +2026/021-10:25:54.748 Spawned command succeeded: mv +2026/021-10:26:00.859 Closed raw record file for Kiel antenna_partner: IOIS_1_raw_record_20_2026_021_10_21_00.partial +2026/021-10:26:00.859 Renamed IOIS_1_raw_record_20_2026_021_10_21_00.partial to IOIS_1_raw_record_20_2026_021_10_21_00. +2026/021-10:26:00.859 Spawning: rsync +2026/021-10:26:00.859 Opened raw record file for Kiel antenna_partner: IOIS_1_raw_record_20_2026_021_10_26_00.partial +2026/021-10:26:03.449 Spawned command succeeded: rsync +2026/021-10:26:54.146 Closed packets file for SDC: iois_1_packets_2026_021_10_25_53.partial +2026/021-10:26:54.147 Renamed iois_1_packets_2026_021_10_25_53.partial to iois_1_packets_2026_021_10_25_53. +2026/021-10:26:54.147 Spawning: mv +2026/021-10:26:54.147 Opened packets file for SDC: iois_1_packets_2026_021_10_26_54.partial +2026/021-10:26:54.995 Spawned command succeeded: mv +2026/021-10:27:55.287 Closed packets file for SDC: iois_1_packets_2026_021_10_26_54.partial +2026/021-10:27:55.287 Renamed iois_1_packets_2026_021_10_26_54.partial to iois_1_packets_2026_021_10_26_54. +2026/021-10:27:55.287 Spawning: mv +2026/021-10:27:55.287 Opened packets file for SDC: iois_1_packets_2026_021_10_27_55.partial +2026/021-10:27:56.172 Spawned command succeeded: mv +2026/021-10:27:59.674 Periodic status report: +ID Description LastDataRcvd ConnectionTime Rate (kbps) + 2 tlmrelay 001-00:00:00 020-19:57:14 0.0 +10 Kiel 021-10:27:59 021-08:40:39 2.0 +2026/021-10:28:56.419 Closed packets file for SDC: iois_1_packets_2026_021_10_27_55.partial +2026/021-10:28:56.419 Renamed iois_1_packets_2026_021_10_27_55.partial to iois_1_packets_2026_021_10_27_55. +2026/021-10:28:56.419 Spawning: mv +2026/021-10:28:56.419 Opened packets file for SDC: iois_1_packets_2026_021_10_28_56.partial +2026/021-10:28:57.328 Spawned command succeeded: mv +2026/021-10:29:57.641 Closed packets file for SDC: iois_1_packets_2026_021_10_28_56.partial +2026/021-10:29:57.641 Renamed iois_1_packets_2026_021_10_28_56.partial to iois_1_packets_2026_021_10_28_56. +2026/021-10:29:57.641 Spawning: mv +2026/021-10:29:57.641 Opened packets file for SDC: iois_1_packets_2026_021_10_29_57.partial +2026/021-10:29:58.464 Spawned command succeeded: mv +2026/021-10:30:58.750 Closed packets file for SDC: iois_1_packets_2026_021_10_29_57.partial +2026/021-10:30:58.750 Renamed iois_1_packets_2026_021_10_29_57.partial to iois_1_packets_2026_021_10_29_57. +2026/021-10:30:58.750 Spawning: mv +2026/021-10:30:58.751 Opened packets file for SDC: iois_1_packets_2026_021_10_30_58.partial +2026/021-10:30:59.625 Spawned command succeeded: mv +2026/021-10:31:00.502 Closed raw record file for Kiel antenna_partner: IOIS_1_raw_record_20_2026_021_10_26_00.partial +2026/021-10:31:00.502 Renamed IOIS_1_raw_record_20_2026_021_10_26_00.partial to IOIS_1_raw_record_20_2026_021_10_26_00. +2026/021-10:31:00.502 Spawning: rsync +2026/021-10:31:00.502 Opened raw record file for Kiel antenna_partner: IOIS_1_raw_record_20_2026_021_10_31_00.partial +2026/021-10:31:03.137 Spawned command succeeded: rsync +2026/021-10:31:59.052 Closed packets file for SDC: iois_1_packets_2026_021_10_30_58.partial +2026/021-10:31:59.052 Renamed iois_1_packets_2026_021_10_30_58.partial to iois_1_packets_2026_021_10_30_58. +2026/021-10:31:59.052 Spawning: mv +2026/021-10:31:59.052 Opened packets file for SDC: iois_1_packets_2026_021_10_31_59.partial +2026/021-10:31:59.892 Spawned command succeeded: mv +2026/021-10:33:00.178 Closed packets file for SDC: iois_1_packets_2026_021_10_31_59.partial +2026/021-10:33:00.179 Renamed iois_1_packets_2026_021_10_31_59.partial to iois_1_packets_2026_021_10_31_59. +2026/021-10:33:00.179 Spawning: mv +2026/021-10:33:00.179 Opened packets file for SDC: iois_1_packets_2026_021_10_33_00.partial +2026/021-10:33:01.035 Spawned command succeeded: mv +2026/021-10:34:01.354 Closed packets file for SDC: iois_1_packets_2026_021_10_33_00.partial +2026/021-10:34:01.355 Renamed iois_1_packets_2026_021_10_33_00.partial to iois_1_packets_2026_021_10_33_00. +2026/021-10:34:01.355 Spawning: mv +2026/021-10:34:01.355 Opened packets file for SDC: iois_1_packets_2026_021_10_34_01.partial +2026/021-10:34:02.208 Spawned command succeeded: mv +2026/021-10:35:02.464 Closed packets file for SDC: iois_1_packets_2026_021_10_34_01.partial +2026/021-10:35:02.464 Renamed iois_1_packets_2026_021_10_34_01.partial to iois_1_packets_2026_021_10_34_01. +2026/021-10:35:02.464 Spawning: mv +2026/021-10:35:02.464 Opened packets file for SDC: iois_1_packets_2026_021_10_35_02.partial +2026/021-10:35:03.351 Spawned command succeeded: mv +2026/021-10:36:00.177 Closed raw record file for Kiel antenna_partner: IOIS_1_raw_record_20_2026_021_10_31_00.partial +2026/021-10:36:00.178 Renamed IOIS_1_raw_record_20_2026_021_10_31_00.partial to IOIS_1_raw_record_20_2026_021_10_31_00. +2026/021-10:36:00.178 Spawning: rsync +2026/021-10:36:00.178 Opened raw record file for Kiel antenna_partner: IOIS_1_raw_record_20_2026_021_10_36_00.partial +2026/021-10:36:02.744 Spawned command succeeded: rsync +2026/021-10:36:03.637 Closed packets file for SDC: iois_1_packets_2026_021_10_35_02.partial +2026/021-10:36:03.637 Renamed iois_1_packets_2026_021_10_35_02.partial to iois_1_packets_2026_021_10_35_02. +2026/021-10:36:03.637 Spawning: mv +2026/021-10:36:03.637 Opened packets file for SDC: iois_1_packets_2026_021_10_36_03.partial +2026/021-10:36:04.497 Spawned command succeeded: mv +2026/021-10:37:04.782 Closed packets file for SDC: iois_1_packets_2026_021_10_36_03.partial +2026/021-10:37:04.782 Renamed iois_1_packets_2026_021_10_36_03.partial to iois_1_packets_2026_021_10_36_03. +2026/021-10:37:04.782 Spawning: mv +2026/021-10:37:04.782 Opened packets file for SDC: iois_1_packets_2026_021_10_37_04.partial +2026/021-10:37:05.647 Spawned command succeeded: mv +2026/021-10:38:05.068 Closed packets file for SDC: iois_1_packets_2026_021_10_37_04.partial +2026/021-10:38:05.068 Renamed iois_1_packets_2026_021_10_37_04.partial to iois_1_packets_2026_021_10_37_04. +2026/021-10:38:05.068 Spawning: mv +2026/021-10:38:05.068 Opened packets file for SDC: iois_1_packets_2026_021_10_38_05.partial +2026/021-10:38:05.931 Spawned command succeeded: mv +2026/021-10:39:06.213 Closed packets file for SDC: iois_1_packets_2026_021_10_38_05.partial +2026/021-10:39:06.213 Renamed iois_1_packets_2026_021_10_38_05.partial to iois_1_packets_2026_021_10_38_05. +2026/021-10:39:06.213 Spawning: mv +2026/021-10:39:06.213 Opened packets file for SDC: iois_1_packets_2026_021_10_39_06.partial +2026/021-10:39:07.068 Spawned command succeeded: mv +2026/021-10:40:07.357 Closed packets file for SDC: iois_1_packets_2026_021_10_39_06.partial +2026/021-10:40:07.357 Renamed iois_1_packets_2026_021_10_39_06.partial to iois_1_packets_2026_021_10_39_06. +2026/021-10:40:07.357 Spawning: mv +2026/021-10:40:07.357 Opened packets file for SDC: iois_1_packets_2026_021_10_40_07.partial +2026/021-10:40:08.250 Spawned command succeeded: mv +2026/021-10:41:00.642 Closed raw record file for Kiel antenna_partner: IOIS_1_raw_record_20_2026_021_10_36_00.partial +2026/021-10:41:00.643 Renamed IOIS_1_raw_record_20_2026_021_10_36_00.partial to IOIS_1_raw_record_20_2026_021_10_36_00. +2026/021-10:41:00.643 Spawning: rsync +2026/021-10:41:00.643 Opened raw record file for Kiel antenna_partner: IOIS_1_raw_record_20_2026_021_10_41_00.partial +2026/021-10:41:03.289 Spawned command succeeded: rsync +2026/021-10:41:08.494 Closed packets file for SDC: iois_1_packets_2026_021_10_40_07.partial +2026/021-10:41:08.495 Renamed iois_1_packets_2026_021_10_40_07.partial to iois_1_packets_2026_021_10_40_07. +2026/021-10:41:08.495 Spawning: mv +2026/021-10:41:08.495 Opened packets file for SDC: iois_1_packets_2026_021_10_41_08.partial +2026/021-10:41:09.390 Spawned command succeeded: mv +2026/021-10:42:09.682 Closed packets file for SDC: iois_1_packets_2026_021_10_41_08.partial +2026/021-10:42:09.682 Renamed iois_1_packets_2026_021_10_41_08.partial to iois_1_packets_2026_021_10_41_08. +2026/021-10:42:09.682 Spawning: mv +2026/021-10:42:09.683 Opened packets file for SDC: iois_1_packets_2026_021_10_42_09.partial +2026/021-10:42:10.531 Spawned command succeeded: mv +2026/021-10:43:10.822 Closed packets file for SDC: iois_1_packets_2026_021_10_42_09.partial +2026/021-10:43:10.822 Renamed iois_1_packets_2026_021_10_42_09.partial to iois_1_packets_2026_021_10_42_09. +2026/021-10:43:10.822 Spawning: mv +2026/021-10:43:10.822 Opened packets file for SDC: iois_1_packets_2026_021_10_43_10.partial +2026/021-10:43:11.679 Spawned command succeeded: mv +2026/021-10:44:11.145 Closed packets file for SDC: iois_1_packets_2026_021_10_43_10.partial +2026/021-10:44:11.145 Renamed iois_1_packets_2026_021_10_43_10.partial to iois_1_packets_2026_021_10_43_10. +2026/021-10:44:11.145 Spawning: mv +2026/021-10:44:11.145 Opened packets file for SDC: iois_1_packets_2026_021_10_44_11.partial +2026/021-10:44:11.961 Spawned command succeeded: mv +2026/021-10:45:12.254 Closed packets file for SDC: iois_1_packets_2026_021_10_44_11.partial +2026/021-10:45:12.254 Renamed iois_1_packets_2026_021_10_44_11.partial to iois_1_packets_2026_021_10_44_11. +2026/021-10:45:12.254 Spawning: mv +2026/021-10:45:12.254 Opened packets file for SDC: iois_1_packets_2026_021_10_45_12.partial +2026/021-10:45:13.146 Spawned command succeeded: mv +2026/021-10:46:00.296 Closed raw record file for Kiel antenna_partner: IOIS_1_raw_record_20_2026_021_10_41_00.partial +2026/021-10:46:00.296 Renamed IOIS_1_raw_record_20_2026_021_10_41_00.partial to IOIS_1_raw_record_20_2026_021_10_41_00. +2026/021-10:46:00.296 Spawning: rsync +2026/021-10:46:00.296 Opened raw record file for Kiel antenna_partner: IOIS_1_raw_record_20_2026_021_10_46_00.partial +2026/021-10:46:02.936 Spawned command succeeded: rsync +2026/021-10:46:13.390 Closed packets file for SDC: iois_1_packets_2026_021_10_45_12.partial +2026/021-10:46:13.390 Renamed iois_1_packets_2026_021_10_45_12.partial to iois_1_packets_2026_021_10_45_12. +2026/021-10:46:13.390 Spawning: mv +2026/021-10:46:13.390 Opened packets file for SDC: iois_1_packets_2026_021_10_46_13.partial +2026/021-10:46:14.283 Spawned command succeeded: mv +2026/021-10:47:14.541 Closed packets file for SDC: iois_1_packets_2026_021_10_46_13.partial +2026/021-10:47:14.541 Renamed iois_1_packets_2026_021_10_46_13.partial to iois_1_packets_2026_021_10_46_13. +2026/021-10:47:14.541 Spawning: mv +2026/021-10:47:14.541 Opened packets file for SDC: iois_1_packets_2026_021_10_47_14.partial +2026/021-10:47:15.426 Spawned command succeeded: mv +2026/021-10:48:15.727 Closed packets file for SDC: iois_1_packets_2026_021_10_47_14.partial +2026/021-10:48:15.727 Renamed iois_1_packets_2026_021_10_47_14.partial to iois_1_packets_2026_021_10_47_14. +2026/021-10:48:15.727 Spawning: mv +2026/021-10:48:15.727 Opened packets file for SDC: iois_1_packets_2026_021_10_48_15.partial +2026/021-10:48:16.567 Spawned command succeeded: mv +2026/021-10:49:16.007 Closed packets file for SDC: iois_1_packets_2026_021_10_48_15.partial +2026/021-10:49:16.007 Renamed iois_1_packets_2026_021_10_48_15.partial to iois_1_packets_2026_021_10_48_15. +2026/021-10:49:16.007 Spawning: mv +2026/021-10:49:16.007 Opened packets file for SDC: iois_1_packets_2026_021_10_49_16.partial +2026/021-10:49:16.872 Spawned command succeeded: mv +2026/021-10:50:17.141 Closed packets file for SDC: iois_1_packets_2026_021_10_49_16.partial +2026/021-10:50:17.141 Renamed iois_1_packets_2026_021_10_49_16.partial to iois_1_packets_2026_021_10_49_16. +2026/021-10:50:17.141 Spawning: mv +2026/021-10:50:17.141 Opened packets file for SDC: iois_1_packets_2026_021_10_50_17.partial +2026/021-10:50:18.008 Spawned command succeeded: mv +2026/021-10:51:00.836 Closed raw record file for Kiel antenna_partner: IOIS_1_raw_record_20_2026_021_10_46_00.partial +2026/021-10:51:00.836 Renamed IOIS_1_raw_record_20_2026_021_10_46_00.partial to IOIS_1_raw_record_20_2026_021_10_46_00. +2026/021-10:51:00.836 Spawning: rsync +2026/021-10:51:00.836 Opened raw record file for Kiel antenna_partner: IOIS_1_raw_record_20_2026_021_10_51_00.partial +2026/021-10:51:03.438 Spawned command succeeded: rsync +2026/021-10:51:18.293 Closed packets file for SDC: iois_1_packets_2026_021_10_50_17.partial +2026/021-10:51:18.293 Renamed iois_1_packets_2026_021_10_50_17.partial to iois_1_packets_2026_021_10_50_17. +2026/021-10:51:18.293 Spawning: mv +2026/021-10:51:18.293 Opened packets file for SDC: iois_1_packets_2026_021_10_51_18.partial +2026/021-10:51:19.139 Spawned command succeeded: mv +2026/021-10:52:19.435 Closed packets file for SDC: iois_1_packets_2026_021_10_51_18.partial +2026/021-10:52:19.435 Renamed iois_1_packets_2026_021_10_51_18.partial to iois_1_packets_2026_021_10_51_18. +2026/021-10:52:19.435 Spawning: mv +2026/021-10:52:19.436 Opened packets file for SDC: iois_1_packets_2026_021_10_52_19.partial +2026/021-10:52:20.322 Spawned command succeeded: mv +2026/021-10:53:20.627 Closed packets file for SDC: iois_1_packets_2026_021_10_52_19.partial +2026/021-10:53:20.627 Renamed iois_1_packets_2026_021_10_52_19.partial to iois_1_packets_2026_021_10_52_19. +2026/021-10:53:20.627 Spawning: mv +2026/021-10:53:20.627 Opened packets file for SDC: iois_1_packets_2026_021_10_53_20.partial +2026/021-10:53:21.468 Spawned command succeeded: mv +2026/021-10:54:21.751 Closed packets file for SDC: iois_1_packets_2026_021_10_53_20.partial +2026/021-10:54:21.751 Renamed iois_1_packets_2026_021_10_53_20.partial to iois_1_packets_2026_021_10_53_20. +2026/021-10:54:21.751 Spawning: mv +2026/021-10:54:21.752 Opened packets file for SDC: iois_1_packets_2026_021_10_54_21.partial +2026/021-10:54:22.637 Spawned command succeeded: mv +2026/021-10:55:22.047 Closed packets file for SDC: iois_1_packets_2026_021_10_54_21.partial +2026/021-10:55:22.047 Renamed iois_1_packets_2026_021_10_54_21.partial to iois_1_packets_2026_021_10_54_21. +2026/021-10:55:22.047 Spawning: mv +2026/021-10:55:22.047 Opened packets file for SDC: iois_1_packets_2026_021_10_55_22.partial +2026/021-10:55:22.900 Spawned command succeeded: mv +2026/021-10:56:00.448 Closed raw record file for Kiel antenna_partner: IOIS_1_raw_record_20_2026_021_10_51_00.partial +2026/021-10:56:00.448 Renamed IOIS_1_raw_record_20_2026_021_10_51_00.partial to IOIS_1_raw_record_20_2026_021_10_51_00. +2026/021-10:56:00.448 Spawning: rsync +2026/021-10:56:00.448 Opened raw record file for Kiel antenna_partner: IOIS_1_raw_record_20_2026_021_10_56_00.partial +2026/021-10:56:03.084 Spawned command succeeded: rsync +2026/021-10:56:23.201 Closed packets file for SDC: iois_1_packets_2026_021_10_55_22.partial +2026/021-10:56:23.201 Renamed iois_1_packets_2026_021_10_55_22.partial to iois_1_packets_2026_021_10_55_22. +2026/021-10:56:23.201 Spawning: mv +2026/021-10:56:23.201 Opened packets file for SDC: iois_1_packets_2026_021_10_56_23.partial +2026/021-10:56:24.049 Spawned command succeeded: mv +2026/021-10:57:24.323 Closed packets file for SDC: iois_1_packets_2026_021_10_56_23.partial +2026/021-10:57:24.323 Renamed iois_1_packets_2026_021_10_56_23.partial to iois_1_packets_2026_021_10_56_23. +2026/021-10:57:24.323 Spawning: mv +2026/021-10:57:24.323 Opened packets file for SDC: iois_1_packets_2026_021_10_57_24.partial +2026/021-10:57:25.231 Spawned command succeeded: mv +2026/021-10:58:00.171 Periodic status report: diff --git a/imap_processing/tests/ialirt/data/l0/imap_codice_l1a_hi-ialirt.pickle b/imap_processing/tests/ialirt/data/l0/imap_codice_l1a_hi-ialirt.pickle new file mode 100644 index 0000000000..1a626ba73b Binary files /dev/null and b/imap_processing/tests/ialirt/data/l0/imap_codice_l1a_hi-ialirt.pickle differ diff --git a/imap_processing/tests/ialirt/data/l0/imap_codice_l1a_lo-ialirt.pickle b/imap_processing/tests/ialirt/data/l0/imap_codice_l1a_lo-ialirt.pickle new file mode 100644 index 0000000000..4eacfaa725 Binary files /dev/null and b/imap_processing/tests/ialirt/data/l0/imap_codice_l1a_lo-ialirt.pickle differ diff --git a/imap_processing/tests/ialirt/data/l0/imap_mag_ialirt-calibration_20250926_v002.cdf b/imap_processing/tests/ialirt/data/l0/imap_mag_ialirt-calibration_20250926_v002.cdf new file mode 100644 index 0000000000..f2dd10ba5c Binary files /dev/null and b/imap_processing/tests/ialirt/data/l0/imap_mag_ialirt-calibration_20250926_v002.cdf differ diff --git a/imap_processing/tests/ialirt/unit/conftest.py b/imap_processing/tests/ialirt/unit/conftest.py index f64f977b2c..df4ef2a7be 100644 --- a/imap_processing/tests/ialirt/unit/conftest.py +++ b/imap_processing/tests/ialirt/unit/conftest.py @@ -1,12 +1,9 @@ """Pytest plugin module for test data paths.""" -from unittest import mock - import pytest -from imap_data_access.processing_input import AncillaryInput from imap_processing import imap_module_directory -from imap_processing.ancillary.ancillary_dataset_combiner import MagAncillaryCombiner +from imap_processing.cdf.utils import load_cdf @pytest.fixture @@ -22,6 +19,21 @@ def sc_packet_path(): return packet_path, xtce_ialirt_path +@pytest.fixture +def swapi_postlaunch_sc_packet_path(): + """Returns the spacecraft packet directory.""" + xtce_ialirt_path = ( + imap_module_directory / "ialirt" / "packet_definitions" / "ialirt.xml" + ) + + directory = imap_module_directory / "tests" / "ialirt" / "data" / "l0" + filenames = [ + "iois_1_packets_2025_344_05_57_56", + "iois_1_packets_2025_344_05_59_58", + ] + return tuple(directory / fname for fname in filenames), xtce_ialirt_path + + @pytest.fixture def ialirt_mag_test_l1d_data(): """Returns the MAG I-ALiRT calibration dataset.""" @@ -34,11 +46,23 @@ def ialirt_mag_test_l1d_data(): / "imap_mag_ialirt-calibration_20250101_v002.cdf" ) - with mock.patch( - "imap_processing.ancillary.ancillary_dataset_combiner.AncillaryFilePath.construct_path", - return_value=cal_path, - ): - processing = AncillaryInput(cal_path.name) - calibration_data = MagAncillaryCombiner(processing, "20250101").combined_dataset + calibration_data = load_cdf(cal_path) + + return calibration_data + + +@pytest.fixture +def ialirt_mag_test_l1d_data_postlaunch(): + """Returns the MAG I-ALiRT calibration dataset.""" + cal_path = ( + imap_module_directory + / "tests" + / "ialirt" + / "data" + / "l0" + / "imap_mag_ialirt-calibration_20250926_v002.cdf" + ) + + calibration_data = load_cdf(cal_path) return calibration_data diff --git a/imap_processing/tests/ialirt/unit/test_calculate_ingest.py b/imap_processing/tests/ialirt/unit/test_calculate_ingest.py index 713545b57c..6bed9233ce 100644 --- a/imap_processing/tests/ialirt/unit/test_calculate_ingest.py +++ b/imap_processing/tests/ialirt/unit/test_calculate_ingest.py @@ -1,75 +1,48 @@ """Test calculate_ingest functions.""" -from datetime import datetime, timedelta, timezone -from typing import Any +from datetime import datetime, timedelta from imap_processing import imap_module_directory from imap_processing.ialirt.calculate_ingest import ( - find_tcp_connections, format_ingest_data, packets_created, ) -from imap_processing.ialirt.constants import STATIONS TEST_PATH = imap_module_directory / "tests" / "ialirt" / "data" / "l0" -def test_find_tcp_connections(): - """Test the find_tcp_connections function.""" - filename = "flight_iois_1.log.2025-212T16_55_27.531613" - # File creation time minus 1 hr. - timestamp_str = filename.split(".")[2] - timestamp_str = timestamp_str.replace("_", ":") - start_of_time = datetime.strptime(timestamp_str, "%Y-%jT%H:%M:%S") - timedelta( - hours=1 - ) - end_of_time = start_of_time + timedelta(hours=48) - - with open(TEST_PATH / filename, encoding="utf-8") as f: - lines = f.readlines() - - formatted: dict[str, Any] = { - "summary": "I-ALiRT Real-time Ingest Summary", - "generated": datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ"), - "time_format": "UTC (ISOC)", - "stations": list(STATIONS), - "time_range": [ - start_of_time.isoformat(), - end_of_time.isoformat(), - ], # Overall time range of the data - "packet_ingest": [], # Global packet ingest times - "connection_times": { - station: [] for station in list(STATIONS) - }, # Per-station TCP connection windows - } - - test = find_tcp_connections(start_of_time, end_of_time, lines, formatted) - - # 2025/212-16:33:03.247 - time_0 = datetime(2025, 7, 31, 16, 33, 3, 247000) - # 2025/212-16:33:40.189 - time_1 = datetime(2025, 7, 31, 16, 33, 40, 189000) - - assert test["connection_times"]["Kiel"][0]["start"] == datetime.isoformat(time_0) - assert test["connection_times"]["Kiel"][0]["end"] == datetime.isoformat(time_1) - - def test_packets_created(): """Test the packets_created function.""" with open( - TEST_PATH / "flight_iois_1.log.2025-212T16_55_27.531613", encoding="utf-8" + TEST_PATH / "flight_iois_1.log.2026-021T10-58-00.171087", encoding="utf-8" ) as f: lines = f.readlines() - actual_output = packets_created(datetime(2025, 7, 31, 16, 33, 39, 0), lines) - - # 2025/212-16:33:39.186 - time_0 = datetime(2025, 7, 31, 16, 33, 39, 186000) - # 2025/212-16:34:40.199 - time_1 = datetime(2025, 7, 31, 16, 34, 40, 199000) + actual_output = packets_created(datetime(2026, 7, 31, 16, 33, 39, 0), lines) + + expected = { + "Kiel": { + "last_data_received": [ + "2026-01-21T09:57:58Z", + "2026-01-21T10:27:59Z", + ], + "rate_kbps": [2.0, 2.0], + }, + "UKSA": { + "last_data_received": [], + "rate_kbps": [], + }, + "tlmrelay": { + "last_data_received": [ + "2026-01-01T00:00:00Z", + ], + "rate_kbps": [ + 0.0, + ], + }, + } - assert actual_output[0] == time_0 - assert actual_output[1] == time_1 + assert actual_output == expected def test_format_ingest_data(): @@ -111,67 +84,24 @@ def test_format_ingest_data(): f"iois_1_packets_{pkt_time}.\n" ) - current_time += timedelta(seconds=1) - - filenames = sorted(filenames) - - data = format_ingest_data(filenames[-1], log_lines) - - assert data["packet_ingest"][0] == "2025-07-31T08:00:00" - assert data["packet_ingest"][-1] == "2025-07-31T15:00:00" - assert data["connection_times"]["Kiel"][0]["start"] == "2025-07-31T08:00:00" - assert data["connection_times"]["Kiel"][0]["end"] == "2025-07-31T16:00:00" - - -def test_format_ingest_data_edge_cases(): - """Test the edge cases of the format_ingest_data function.""" + if current_time == base_date + timedelta(hours=8): + log_lines.append( + "ID Description LastDataRcvd ConnectionTime Rate (kbps)\n" + ) + log_lines.append("10 Kiel 365-08:00:00 365-08:00:00 2.0\n") - # File names for a short 3 hour test window - filenames = [ - "flight_iois_1.log.2025-212T00_00_00.000000", - "flight_iois_1.log.2025-212T01_00_00.000000", - "flight_iois_1.log.2025-212T02_00_00.000000", - ] + if current_time == base_date + timedelta(hours=15): + log_lines.append( + "ID Description LastDataRcvd ConnectionTime Rate (kbps)\n" + ) + log_lines.append("10 Kiel 001-15:00:00 001-08:00:00 2.0\n") - base_date = datetime(2025, 7, 31, 0, 0, 0) - log_lines = [] + current_time += timedelta(seconds=1) - # Simulate case: log starts with a "down!" at 00:15 (no prior "up.") - timestamp_down = (base_date + timedelta(minutes=15)).strftime("%Y/%j-%H:%M:%S.%f")[ - :-3 - ] - log_lines.append(f"{timestamp_down} Kiel antenna partner connection is down!\n") - - # Add packet event at 00:00 - timestamp_pkt = base_date.strftime("%Y/%j-%H:%M:%S.%f")[:-3] - pkt_time = base_date.strftime("%Y_%j_%H_%M_%S") - log_lines.append( - f"{timestamp_pkt} Renamed iois_1_packets_{pkt_time}.partial to " - f"iois_1_packets_{pkt_time}.\n" - ) - - # Simulate case: "up." at 02:00 (no matching "down!" before end of file) - timestamp_up = (base_date + timedelta(hours=2)).strftime("%Y/%j-%H:%M:%S.%f")[:-3] - log_lines.append(f"{timestamp_up} Kiel antenna partner connection is up.\n") - - # Add packet event at 02:01 - timestamp_pkt = (base_date + timedelta(hours=2, minutes=1)).strftime( - "%Y/%j-%H:%M:%S.%f" - )[:-3] - pkt_time = (base_date + timedelta(hours=2, minutes=1)).strftime("%Y_%j_%H_%M_%S") - log_lines.append( - f"{timestamp_pkt} Renamed iois_1_packets_{pkt_time}.partial to " - f"iois_1_packets_{pkt_time}.\n" - ) filenames = sorted(filenames) data = format_ingest_data(filenames[-1], log_lines) - assert data["connection_times"]["Kiel"][0]["start"] == "2025-07-29T02:00:00" - assert data["connection_times"]["Kiel"][0]["end"] == "2025-07-31T00:15:00" - - assert data["connection_times"]["Kiel"][1]["start"] == "2025-07-31T02:00:00" - assert data["connection_times"]["Kiel"][1]["end"] == "2025-07-31T02:00:00" - - assert data["packet_ingest"][0] == "2025-07-31T00:00:00" - assert data["packet_ingest"][1] == "2025-07-31T02:01:00" + assert data["Kiel"]["last_data_received"][0] == "2025-12-31T08:00:00Z" + assert data["Kiel"]["last_data_received"][-1] == "2026-01-01T15:00:00Z" + assert data["Kiel"]["rate_kbps"][0] == 2.0 diff --git a/imap_processing/tests/ialirt/unit/test_create_xarray.py b/imap_processing/tests/ialirt/unit/test_create_xarray.py index 123ee2b188..d56c502fd3 100644 --- a/imap_processing/tests/ialirt/unit/test_create_xarray.py +++ b/imap_processing/tests/ialirt/unit/test_create_xarray.py @@ -6,6 +6,7 @@ import numpy.testing as npt from imap_processing.cdf.utils import write_cdf +from imap_processing.ialirt.utils.constants import swe_energy from imap_processing.ialirt.utils.create_xarray import create_xarray_from_records @@ -13,119 +14,155 @@ def test_create_dataset(): """Tests create_dataset function.""" records = [ { - "apid": 478, - "met": 123456789, - "met_in_utc": "2025-06-20T08:00:00", - "ttj2000ns": 123456789000000, - "swe_normalized_counts": [Decimal("0.0") for _ in range(8)], - "swe_counterstreaming_electrons": Decimal("0.0"), - "swapi_pseudo_proton_speed": Decimal("0.0"), - "swapi_pseudo_proton_density": Decimal("0.0"), - "swapi_pseudo_proton_temperature": Decimal("0.0"), + "instrument": "mag", + "time_utc": "2025-06-20T08:00:00", + "ttj2000ns": 803692869184000000, + "mag_epoch": 803692869184000000, + "mag_B_GSE": [Decimal("5.0"), Decimal("-3.2"), Decimal("1.1")], + "mag_B_GSM": [Decimal("4.8"), Decimal("-3.0"), Decimal("1.0")], + "mag_B_RTN": [Decimal("5.1"), Decimal("-3.3"), Decimal("1.2")], + "mag_B_magnitude": Decimal("6.0"), + "mag_phi_B_GSM": Decimal("45.0"), + "mag_theta_B_GSM": Decimal("30.0"), + "mag_phi_B_GSE": Decimal("50.0"), + "mag_theta_B_GSE": Decimal("35.0"), + }, + { + "instrument": "codice_hi", + "time_utc": "2025-06-20T08:00:00", + "ttj2000ns": 803692869184000000, + "codice_hi_epoch": [ + 803692869184000000, + 803692869184000000, + 803692869184000000, + 803692869184000000, + ], + "codice_hi_h": [ + [ + [[Decimal("1.0") for _ in range(4)] for _ in range(4)] + for _ in range(15) + ] + for _ in range(4) + ], + }, + { + "instrument": "codice_lo", + "time_utc": "2025-06-20T08:00:00", + "ttj2000ns": 803692869184000000, + "codice_lo_epoch": 803692869184000000, + "codice_lo_c_over_o_abundance": Decimal("0.5"), + "codice_lo_mg_over_o_abundance": Decimal("0.3"), + "codice_lo_fe_over_o_abundance": Decimal("0.2"), + "codice_lo_c_plus_6_over_c_plus_5": Decimal("0.7"), + "codice_lo_o_plus_7_over_o_plus_6": Decimal("0.6"), + "codice_lo_fe_low_over_fe_high": Decimal("0.4"), + }, + { + "instrument": "hit", + "time_utc": "2025-06-20T08:00:00", + "ttj2000ns": 803692869184000000, + "hit_epoch": 803692869184000000, "hit_e_a_side_low_en": Decimal("0.0"), "hit_e_a_side_med_en": Decimal("0.0"), "hit_e_a_side_high_en": Decimal("0.0"), "hit_e_b_side_low_en": Decimal("0.0"), "hit_e_b_side_med_en": Decimal("0.0"), "hit_e_b_side_high_en": Decimal("0.0"), + "hit_h_omni_low_en": Decimal("0.0"), "hit_h_omni_med_en": Decimal("0.0"), "hit_h_a_side_high_en": Decimal("0.0"), "hit_h_b_side_high_en": Decimal("0.0"), "hit_he_omni_low_en": Decimal("0.0"), "hit_he_omni_high_en": Decimal("0.0"), - "mag_epoch": Decimal("0.0"), - "mag_B_GSE": [Decimal("0.0"), Decimal("0.0"), Decimal("0.0")], - "mag_B_GSM": [Decimal("0.0"), Decimal("0.0"), Decimal("0.0")], - "mag_B_RTN": [Decimal("0.0"), Decimal("0.0"), Decimal("0.0")], - "mag_B_magnitude": Decimal("0.0"), - "mag_phi_B_GSM": Decimal("0.0"), - "mag_theta_B_GSM": Decimal("0.0"), - "mag_phi_B_GSE": Decimal("0.0"), - "mag_theta_B_GSE": Decimal("0.0"), - "codice_lo_c_over_o_abundance": Decimal("0.0"), - "codice_lo_mg_over_o_abundance": Decimal("0.0"), - "codice_lo_fe_over_o_abundance": Decimal("0.0"), - "codice_lo_c_plus_6_over_c_plus_5_ratio": Decimal("0.0"), - "codice_lo_o_plus_7_over_o_plus_6_ratio": Decimal("0.0"), - "codice_lo_fe_low_over_fe_high_ratio": Decimal("0.0"), - "codice_hi_h": [ - [[Decimal("0.0") for _ in range(4)] for _ in range(4)] - for _ in range(15) - ], }, { - "apid": 478, - "met": 123456789, - "met_in_utc": "2025-06-20T08:00:00", - "ttj2000ns": 123456789000001, - # Only MAG is present - "mag_epoch": Decimal("0.0"), - "mag_B_GSE": [Decimal("0.0"), Decimal("0.0"), Decimal("0.0")], - "mag_B_GSM": [Decimal("0.0"), Decimal("0.0"), Decimal("0.0")], - "mag_B_RTN": [Decimal("0.0"), Decimal("0.0"), Decimal("0.0")], - "mag_B_magnitude": Decimal("0.0"), - "mag_phi_B_GSM": Decimal("0.0"), - "mag_theta_B_GSM": Decimal("0.0"), - "mag_phi_B_GSE": Decimal("0.0"), - "mag_theta_B_GSE": Decimal("0.0"), + "instrument": "swapi", + "time_utc": "2025-06-20T08:00:00", + "ttj2000ns": 803692869184000000, + "swapi_epoch": 803692869184000000, + "swapi_pseudo_proton_speed": Decimal("400.0"), + "swapi_pseudo_proton_density": Decimal("5.0"), + "swapi_pseudo_proton_temperature": Decimal("100000.0"), }, { - "apid": 478, - "met": 123456789, - "met_in_utc": "2025-06-20T08:00:00", + "instrument": "swe", + "time_utc": "2025-06-20T08:00:00", + "ttj2000ns": 803692869184000000, + "swe_epoch": 803692869184000000, + "swe_normalized_counts": [Decimal("0.0") for _ in range(8)], + "swe_counterstreaming_electrons": Decimal("1.0"), + }, + { + "instrument": "spacecraft", + "time_utc": "2025-10-29T18:55:02", "ttj2000ns": 123456789000002, - # Only SWAPI is present - "swapi_pseudo_proton_speed": Decimal("0.0"), - "swapi_pseudo_proton_density": Decimal("0.0"), - "swapi_pseudo_proton_temperature": Decimal("0.0"), + "sc_position_GSE": [ + Decimal("1373251.6968303905"), + Decimal("-431299.0150430931"), + Decimal("73446.43257187483"), + ], + "sc_position_GSM": [ + Decimal("1373251.6968303905"), + Decimal("-400988.5784292875"), + Decimal("174989.6534196707"), + ], + "sc_velocity_GSE": [ + Decimal("0.03919581036966908"), + Decimal("-0.21796820670587755"), + Decimal("-0.019698638532273577"), + ], + "sc_velocity_GSM": [ + Decimal("0.03919581036966908"), + Decimal("-1.9156200243319468"), + Decimal("-3.8606800975317896"), + ], }, ] dataset = create_xarray_from_records(records) - assert (dataset["component"].values == ["x", "y", "z"]).all() - assert (dataset["RTN_component"].values == ["radial", "tangential", "normal"]).all() - npt.assert_array_equal(dataset["esa_step"].values, np.arange(8)) + assert ( + dataset["B_GSM_labels"].values == ["Bx (GSM)", "By (GSM)", "Bz (GSM)"] + ).all() + assert ( + dataset["B_RTN_labels"].values + == ["B radial (RTN)", "B tangential (RTN)", "B normal (RTN)"] + ).all() + np.testing.assert_allclose( + dataset["swe_electron_energy"].values, + np.array(swe_energy), + rtol=1e-7, + atol=1e-6, + ) npt.assert_array_equal( dataset["swe_normalized_counts"].values[0], np.zeros(8, dtype=np.uint32), ) - npt.assert_array_equal( - dataset["swe_normalized_counts"].values[1], - np.full(8, 4294967295, dtype=np.uint32), - ) - np.testing.assert_allclose( - dataset["hit_e_a_side_low_en"].values, - [0, 4294967295, 4294967295], - ) - np.testing.assert_allclose( - dataset["mag_B_GSE"].isel(epoch=0).values, - [0, 0, 0], - ) np.testing.assert_allclose( - dataset["mag_B_GSE"].isel(epoch=1).values, - [0, 0, 0], + dataset["mag_B_GSE"].sel(mag_epoch=803692869184000000).values, + [5.0, -3.2, 1.1], ) - expected_zeros = np.zeros((15, 4, 4), dtype=np.float32) - expected_fill = np.full((15, 4, 4), -1e31, dtype=np.float32) - - npt.assert_array_equal(dataset["codice_hi_h"].isel(epoch=0).values, expected_zeros) - - npt.assert_array_equal(dataset["codice_hi_h"].isel(epoch=1).values, expected_fill) + expected_zeros = np.ones((15, 4, 4), dtype=np.float32) + npt.assert_array_equal( + dataset["codice_hi_h"].isel(codice_hi_epoch=0).values, expected_zeros + ) - assert dataset["mag_B_GSE"].dims == ("epoch", "component") - assert dataset["swe_normalized_counts"].dims == ("epoch", "esa_step") + assert dataset["mag_B_GSE"].dims == ("mag_epoch", "B_GSE_labels") + assert dataset["swe_normalized_counts"].dims == ("swe_epoch", "swe_electron_energy") assert dataset["codice_hi_h"].dims == ( - "epoch", - "codice_hi_h_energy_ranges", - "codice_hi_h_elevation", - "codice_hi_h_spin_angle", + "codice_hi_epoch", + "codice_hi_energy_center", + "codice_hi_spin_sector", + "codice_hi_polar", ) # Tests that you can write to a cdf. dataset.attrs["Data_version"] = "001" - test_data_path = write_cdf(dataset, istp=True) + dataset.attrs["Start_date"] = "20260114" + test_data_path = write_cdf( + dataset, istp=True, auto_fix_depends=False, compression=None + ) assert test_data_path.exists() diff --git a/imap_processing/tests/ialirt/unit/test_generate_coverage.py b/imap_processing/tests/ialirt/unit/test_generate_coverage.py index fd97fbdd9a..3b4d749ca3 100644 --- a/imap_processing/tests/ialirt/unit/test_generate_coverage.py +++ b/imap_processing/tests/ialirt/unit/test_generate_coverage.py @@ -1,16 +1,33 @@ """Test processEphemeris functions.""" -from datetime import datetime +from datetime import datetime, time +from types import SimpleNamespace +from unittest.mock import patch import numpy as np import pytest +from imap_processing import imap_module_directory from imap_processing.ialirt.generate_coverage import ( + create_schedule_mask, format_coverage_summary, generate_coverage, ) +@pytest.fixture(scope="session") +def schedule_path(): + """Returns the xtce auxiliary directory.""" + return ( + imap_module_directory + / "tests" + / "ialirt" + / "data" + / "l0" + / "UKS-DSST-GES-PLN-001 IMAP GHY-6 Availability Analysis v01.xlsx" + ) + + @pytest.mark.external_kernel def test_generate_coverage(furnish_kernels): """ @@ -52,21 +69,21 @@ def test_use_outages(furnish_kernels): with furnish_kernels(kernels): coverage_dict, outage_dict = generate_coverage("2026-09-22T00:00:00Z", outages) - expected = np.array( + expected_outages = np.array( [ - "2026-09-22T07:00:00.000", - "2026-09-22T08:00:00.000", - "2026-09-22T09:00:00.000", - "2026-09-22T10:00:00.000", - "2026-09-22T11:00:00.000", - "2026-09-22T13:00:00.000", - "2026-09-22T15:00:00.000", - "2026-09-22T16:00:00.000", + "2026-09-22T11:50:00.000", + "2026-09-22T11:55:00.000", + "2026-09-22T12:00:00.000", + "2026-09-22T12:05:00.000", + "2026-09-22T13:50:00.000", + "2026-09-22T13:55:00.000", + "2026-09-22T14:00:00.000", + "2026-09-22T14:05:00.000", ] ) - expected_outages = np.array(["2026-09-22T12:00:00.000", "2026-09-22T14:00:00.000"]) - np.testing.assert_array_equal(coverage_dict["Kiel"], expected) + assert coverage_dict["Kiel"][0] == "2026-09-22T06:10:00.000" + assert coverage_dict["Kiel"][-1] == "2026-09-22T16:10:00.000" np.testing.assert_array_equal(outage_dict["Kiel"], expected_outages) @@ -101,25 +118,66 @@ def test_dsn(furnish_kernels): "2026-09-22T00:00:00Z", outages=outages, dsn=dsn ) - dsn_expected = np.array(["2026-09-22T12:00:00.000", "2026-09-22T13:00:00.000"]) - kiel_expected = np.array( - [ - "2026-09-22T07:00:00.000", - "2026-09-22T08:00:00.000", - "2026-09-22T09:00:00.000", - "2026-09-22T10:00:00.000", - "2026-09-22T11:00:00.000", - "2026-09-22T15:00:00.000", - "2026-09-22T16:00:00.000", - ] - ) - - np.testing.assert_array_equal(coverage_dict["Kiel"], kiel_expected) - np.testing.assert_array_equal(coverage_dict["DSS-75"], dsn_expected) + assert coverage_dict["DSS-75"][-1] == "2026-09-22T13:45:00.000" output = format_coverage_summary( coverage_dict, outage_dict, "2026-09-22T00:00:00Z" ) assert "I-ALiRT Coverage Summary" in output["summary"] - assert 37.5 == output["total_coverage_percent"] + assert 40.6 == output["total_coverage_percent"] + + +@patch("imap_processing.ialirt.generate_coverage.et_to_utc") +def test_create_schedule_mask(mock_et_to_utc): + """ + Test create_schedule_mask. + """ + + mock_et_to_utc.return_value = np.array( + [ + "2026-09-22T11:30:00.000", + "2026-09-22T11:35:00.000", + "2026-09-22T11:40:00.000", + "2026-09-22T11:45:00.000", + "2026-09-22T11:50:00.000", + "2026-09-22T11:55:00.000", + "2026-09-22T12:00:00.000", + "2026-09-22T12:05:00.000", + "2026-09-22T12:10:00.000", + "2026-09-22T12:15:00.000", + "2026-09-22T12:20:00.000", + "2026-09-22T12:25:00.000", + "2026-09-22T12:30:00.000", + ] + ) + + time_range = np.arange(13) + + station = SimpleNamespace( + schedule_start=time(12, 0), + schedule_end=None, + ) + + mask = create_schedule_mask(station, time_range) + + expected = np.array( + [ + False, + False, + False, + False, + False, + False, + True, + True, + True, + True, + True, + True, + True, + ], + dtype=bool, + ) + + np.testing.assert_array_equal(mask, expected) diff --git a/imap_processing/tests/ialirt/unit/test_grouping.py b/imap_processing/tests/ialirt/unit/test_grouping.py index c792adf9e6..408e88f282 100644 --- a/imap_processing/tests/ialirt/unit/test_grouping.py +++ b/imap_processing/tests/ialirt/unit/test_grouping.py @@ -4,7 +4,11 @@ import pytest import xarray as xr -from imap_processing.ialirt.utils.grouping import filter_valid_groups, find_groups +from imap_processing.ialirt.utils.grouping import ( + _populate_instrument_header_items, + filter_valid_groups, + find_groups, +) @pytest.fixture @@ -79,3 +83,33 @@ def test_find_groups(test_data): grouped_data = find_groups(test_data, (0, 3), "sequence", "time_seconds") assert np.all(np.unique(grouped_data["group"]) == np.array([1, 3])) + + +def test_find_groups_no_valid(test_data): + """Tests the find_groups function when no valid groups are found.""" + + flag = np.ones(np.size(test_data["src_seq_ctr"]), dtype=int) + flag[-1] = 0 + + test_data["swe_nom_flag"] = ("epoch", flag) + + nominal_data = test_data.where( + test_data["swe_nom_flag"] != 0, + drop=True, + ) + grouped_data = find_groups(nominal_data, (0, 3), "sequence", "time_seconds") + + assert np.all(np.unique(grouped_data["group"]) == np.array([1])) + + +def test_populate_instrument_header_items_from_met_array(): + """Test _populate_instrument_header_items.""" + + met = np.array([100.0, 101.0, 102.0, 103.0], dtype=float) + + header = _populate_instrument_header_items(met) + + expected_keys = {"apid", "met", "met_in_utc", "ttj2000ns"} + assert expected_keys.issubset(header.keys()) + + assert header["met"] == (met[0] + met[-1]) // 2 diff --git a/imap_processing/tests/ialirt/unit/test_ialirt_spice.py b/imap_processing/tests/ialirt/unit/test_ialirt_spice.py index b36e493b6e..cd4bb88826 100644 --- a/imap_processing/tests/ialirt/unit/test_ialirt_spice.py +++ b/imap_processing/tests/ialirt/unit/test_ialirt_spice.py @@ -11,6 +11,7 @@ get_z_axis, transform_instrument_vectors_to_inertial, ) +from imap_processing.spice.geometry import SpiceFrame, frame_transform def test_get_z_axis(): @@ -41,16 +42,10 @@ def test_get_z_axis(): def test_get_rotation_matrix(): """Tests get_rotation_matrix function.""" - z_axis = np.array( - [ - [1.0, 0.0, 0.0], # RA=0, Dec=0 β†’ +X - [0.0, 1.0, 0.0], # RA=90Β°, Dec=0Β° β†’ +Y - [0.0, 0.0, 1.0], # RA=0Β°, Dec=90Β° β†’ +Z - ] - ) + z_axis = np.array([[0.0, 0.0, 1.0]]) # Rotate 90 degrees - spin_phase = np.array([90, 90, 90]) + spin_phase = np.array([90]) # Get rotation matrix r = get_rotation_matrix(z_axis, spin_phase) @@ -59,40 +54,21 @@ def test_get_rotation_matrix(): x = np.array([1, 0, 0]) x_rot = r @ x - expected = np.array( - [ - [1.0, 0.0, 0.0], # Rotating around X leaves X unchanged - [0.0, 0.0, -1.0], # Rotating around Y sends X β†’ -Z - [0.0, 1.0, 0.0], # Rotating around Z sends X β†’ Y - ] - ) + # Rotating a unit vector pointing along x-axis 90-degrees + # about z-axis results in a unit vector pointing along y-axis. + expected = np.array([0, 1.0, 0]) assert np.allclose(x_rot, expected, atol=1e-8) def test_get_x_y_axes(): """Tests get_x_y_axes function.""" - z_axis = np.array( - [ - [1.0, 0.0, 0.0], # RA=0, Dec=0 β†’ +X - [0.0, 1.0, 0.0], # RA=90Β°, Dec=0Β° β†’ +Y - [0.0, 0.0, 1.0], # RA=0Β°, Dec=90Β° β†’ +Z - ] - ) - frames = get_x_y_axes(z_axis) - x_axis = frames[:, 0, :] - y_axis = frames[:, 1, :] - z_axis = frames[:, 2, :] - - # Check that the axes are unit vectors. - assert np.allclose(np.linalg.norm(x_axis, axis=1), 1.0, atol=1e-6) - assert np.allclose(np.linalg.norm(y_axis, axis=1), 1.0, atol=1e-6) - assert np.allclose(np.linalg.norm(z_axis, axis=1), 1.0, atol=1e-6) + z_axis = np.array([[1.0, 0.0, 0.0]]) - # Check each pair of vectors is 90 degrees apart. - assert np.allclose(np.sum(z_axis * y_axis, axis=1), 0.0, atol=1e-6) - assert np.allclose(np.sum(z_axis * x_axis, axis=1), 0.0, atol=1e-6) - assert np.allclose(np.sum(y_axis * x_axis, axis=1), 0.0, atol=1e-6) + frames = get_x_y_axes(z_axis) + x_axis = frames[:, 0] + y_axis = frames[:, 1] + z_axis = frames[:, 2] # Check cross(X, Y) = Z. reconstructed_z = np.cross(x_axis, y_axis) @@ -149,94 +125,54 @@ def test_compute_total_rotation(): @pytest.mark.external_kernel -def test_transform_instrument_vectors_to_inertial( - imap_ena_sim_metakernel, spice_test_data_path -): - """Test transform_instrument_vectors_to_inertial function.""" - - ck_path = spice_test_data_path / "sim_1yr_imap_attitude.bc" - id_imap_spacecraft = spiceypy.gipool("FRAME_IMAP_SPACECRAFT", 0, 1) - - ck_cover = spiceypy.ckcov( - str(ck_path), int(id_imap_spacecraft), True, "INTERVAL", 0, "TDB" - ) - - # Pick midpoint of first coverage interval - et_start = ck_cover[0] - - # Assume IMAP_MAG +X is boresight - instrument_vector = np.array([[10.0, 2.0, 3.0]]) - - # Get RA/Dec of angular momentum vector (Z-axis) from SPICE - rot_sc_to_j2000 = spiceypy.pxform("IMAP_SPACECRAFT", "ECLIPJ2000", et_start + 10) - sc_z_inertial = rot_sc_to_j2000[:, 2] # SC +Z axis (angular momentum) - # Convert inertial Z into RA/Dec (radians) - _, ra, dec = spiceypy.recrad(sc_z_inertial.copy()) - - z_axis = get_z_axis(np.array([np.degrees(ra)]), np.array([np.degrees(dec)]))[ - 0 - ] # extract the single row - - # Test that our get_z_axis code is returning what SPICE returns. - np.testing.assert_allclose( - z_axis, - sc_z_inertial, - atol=1e-9, - ) - - v_manual_0 = transform_instrument_vectors_to_inertial( - instrument_vector, - np.array([120.0]), - np.array([np.degrees(ra)]), - np.array([np.degrees(dec)]), - ) - v_manual_1 = transform_instrument_vectors_to_inertial( - instrument_vector, - np.array([240.0]), - np.array([np.degrees(ra)]), - np.array([np.degrees(dec)]), - ) - - rot_inst_to_inertial_0 = spiceypy.pxform("IMAP_MAG", "ECLIPJ2000", et_start + 10) - rot_inst_to_inertial_1 = spiceypy.pxform("IMAP_MAG", "ECLIPJ2000", et_start + 20) - - v_spice_0 = spiceypy.mxv(rot_inst_to_inertial_0, instrument_vector[0]) - v_spice_1 = spiceypy.mxv(rot_inst_to_inertial_1, instrument_vector[0]) - +def test_transform_instrument_vectors_to_inertial_single(furnish_kernels): + """Test real-world application of this function.""" + + kernels = [ + "imap_science_120.tf", + "imap_130.tf", + "naif0012.tls", + "de440s.bsp", + "imap_recon_od005_20250925_20251014_v01.bsp", + "pck00011.tpc", + "imap_sclk_0036.tsc", + "imap_2025_283_2025_284_001.ah.bc", + ] + + with furnish_kernels(kernels): + # Compare SPICE z-axis with calculated. + rot_sc_to_j2000 = spiceypy.pxform( + "IMAP_SPACECRAFT", "ECLIPJ2000", 813433291.0018076 + ) + sc_z_inertial = rot_sc_to_j2000[:, 2] # SC +Z axis (angular momentum) + _, ra, dec = spiceypy.recrad(sc_z_inertial.copy()) + + z_axis = get_z_axis(np.array([np.degrees(ra)]), np.array([np.degrees(dec)]))[0] + np.testing.assert_allclose( + z_axis, + sc_z_inertial, + atol=1e-9, + ) + + # Spot check that calculations are similar for vectors. + instrument_vector = np.array([[-2.525630188, -0.337087161, -4.523789905]]) + + v_manual_0 = transform_instrument_vectors_to_inertial( + instrument_vector, + np.array([219.5068640401354]), # spin phase + np.array([np.degrees(ra)]), # right ascension + np.array([np.degrees(dec)]), # declination + SpiceFrame.IMAP_MAG_O, + ) + + mago_inertial_vector = frame_transform( + 813433291.0018076, + instrument_vector, + from_frame=SpiceFrame.IMAP_MAG_O, + to_frame=SpiceFrame.ECLIPJ2000, + ) np.testing.assert_allclose( v_manual_0[0], - v_spice_0, - atol=1e-9, - ) - np.testing.assert_allclose( - v_manual_1[0], - v_spice_1, - atol=1e-9, - ) - - -@pytest.mark.external_kernel -def test_no_attitude(imap_ialirt_sim_metakernel): - """Test transform_instrument_vectors_to_inertial function.""" - ra = 0.3653037895099079 - dec = 4.440892098775276e-16 - - # Assume IMAP_MAG +X is boresight - instrument_vector = np.array([[1.0, 0.0, 0.0]]) - - # At this timestamp for the attitude kernel. - spin_phase = np.array([0.0]) - - v_manual = transform_instrument_vectors_to_inertial( - instrument_vector, - spin_phase, - np.array([np.degrees(ra)]), - np.array([np.degrees(dec)]), + mago_inertial_vector, + atol=1e-2, ) - - # TODO: Put this into GSE and GSM once we have proper kernels. - # Example: - # rotation_ecl_to_gse = spiceypy.pxform("ECLIPJ2000", "GSE", et) - # v_j2000 = spiceypy.mxv(rotation_ecl_to_gse, v_manual[0]) - - assert v_manual is not None diff --git a/imap_processing/tests/ialirt/unit/test_parse_mag.py b/imap_processing/tests/ialirt/unit/test_parse_mag.py index 9b97a800a8..79cfe87e98 100644 --- a/imap_processing/tests/ialirt/unit/test_parse_mag.py +++ b/imap_processing/tests/ialirt/unit/test_parse_mag.py @@ -1,5 +1,7 @@ """Tests to support I-ALiRT MAG packet processing.""" +from unittest.mock import patch + import numpy as np import pandas as pd import pytest @@ -17,6 +19,7 @@ get_pkt_counter, get_status_data, get_time, + interpolate_spherical, process_packet, retrieve_matrix_from_single_l1b_calibration, transform_to_frames, @@ -25,8 +28,13 @@ from imap_processing.ialirt.utils.grouping import find_groups from imap_processing.ialirt.utils.time import calculate_time from imap_processing.mag.constants import MAX_FINE_TIME -from imap_processing.spice.geometry import SpiceFrame -from imap_processing.spice.time import et_to_ttj2000ns, met_to_ttj2000ns +from imap_processing.spice.geometry import ( + SpiceFrame, +) +from imap_processing.spice.time import ( + et_to_ttj2000ns, + met_to_ttj2000ns, +) from imap_processing.utils import packet_file_to_datasets @@ -54,6 +62,30 @@ def binary_packet_path(): return tuple(directory / fname for fname in filenames) +@pytest.fixture(scope="session") +def postlaunch_packet_path(): + """Returns the paths to the binary packets.""" + directory = imap_module_directory / "tests" / "ialirt" / "data" / "l0" + filenames = [ + "iois_1_packets_2025_284_05_40_25", + "iois_1_packets_2025_284_05_41_26", + "iois_1_packets_2025_284_05_42_27", + "iois_1_packets_2025_284_05_43_28", + "iois_1_packets_2025_284_05_44_29", + "iois_1_packets_2025_284_05_45_30", + "iois_1_packets_2025_284_05_46_31", + "iois_1_packets_2025_284_05_47_32", + "iois_1_packets_2025_284_05_48_33", + "iois_1_packets_2025_284_05_49_34", + "iois_1_packets_2025_284_05_50_35", + "iois_1_packets_2025_284_05_51_36", + "iois_1_packets_2025_284_05_52_37", + "iois_1_packets_2025_284_05_53_38", + "iois_1_packets_2025_284_05_54_39", + ] + return tuple(directory / fname for fname in filenames) + + @pytest.fixture(scope="session") def mag_test_data(): """Returns the test data directory.""" @@ -100,6 +132,21 @@ def xarray_data(binary_packet_path, xtce_mag_path): return merged_xarray_data +@pytest.fixture +def postlaunch_xarray_data(postlaunch_packet_path, sc_packet_path): + """Create xarray data for multiple packets.""" + apid = 478 + _, xtce_ialirt_path = sc_packet_path + + xarray_data = tuple( + packet_file_to_datasets(packet, xtce_ialirt_path, use_derived_value=False)[apid] + for packet in postlaunch_packet_path + ) + + merged_xarray_data = xr.concat(xarray_data, dim="epoch") + return merged_xarray_data + + @pytest.fixture def grouped_data(): """Creates grouped data for tests.""" @@ -148,7 +195,7 @@ def calibration_dataset(): / "mag" / "validation" / "calibration" - / "imap_mag_l1b-calibration_20240229_v001.cdf" + / "imap_mag_l1b-calibration_20240229_v002.cdf" ) return calibration_dataset @@ -389,9 +436,9 @@ def test_calibrate_and_offset_vectors(ialirt_mag_test_l1d_data): magi_vectors = np.array([[7.0, 8.0, 9.0, 2]]) # Calibration and offsets from ancillary cdf - mago_calibration = ialirt_mag_test_l1d_data["URFTOORFO"][0] - magi_calibration = ialirt_mag_test_l1d_data["URFTOORFI"][0] - offsets = ialirt_mag_test_l1d_data["offsets"][0] + mago_calibration = ialirt_mag_test_l1d_data["URFTOORFO"] + magi_calibration = ialirt_mag_test_l1d_data["URFTOORFI"] + offsets = ialirt_mag_test_l1d_data["offsets"] mago_out = calibrate_and_offset_vectors( mago_vectors, mago_calibration, offsets, is_magi=False @@ -409,7 +456,7 @@ def test_calibrate_and_offset_vectors(ialirt_mag_test_l1d_data): def test_apply_gradiometry_correction(ialirt_mag_test_l1d_data): """Tests apply_gradiometry_correction function.""" - gradiometer_factor = ialirt_mag_test_l1d_data["gradiometer_factor"].values + gradiometer_factor = ialirt_mag_test_l1d_data["gradiometer_factor"] # MAGo and MAGi vectors. mago_vector_eclipj2000 = np.array([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]) @@ -453,17 +500,19 @@ def test_apply_gradiometry_correction(ialirt_mag_test_l1d_data): @pytest.mark.external_kernel +@patch("imap_processing.ialirt.l0.ialirt_spice.SPIN_PHASE_OFFSET_DEG", 0.0) def test_transform_to_frames(furnish_kernels, spice_test_data_path): """Test transform_to_frames over multiple spin phases.""" kernels = [ - "imap_science_100.tf", - "imap_wkcp.tf", + "imap_science_120.tf", + "imap_130.tf", "naif0012.tls", "de440s.bsp", "imap_spk_demo.bsp", "pck00011.tpc", ] + inst_frame = SpiceFrame.IMAP_MAG_O # Use a fixed spin axis pointing at +Z (RA=0, Dec=90) ra = np.array([0.0, 0.0, 0.0, 0.0]) @@ -477,6 +526,20 @@ def test_transform_to_frames(furnish_kernels, spice_test_data_path): target_time = 817561854.0 # halfway between 90Β° and 180Β° spin phase with furnish_kernels(kernels): + # With spin phase halfway between 90 and 180, the +X MAG_O vector should + # be pointing at 135. Since MAG is not mounted perfectly with the + # instrument +X pointing in the S/C -Y direction, we need to rotate the + # expected vector from the instrument frame to the S/C frame. + inst_to_sc_rot = spiceypy.pxform( + inst_frame.name, SpiceFrame.IMAP_SPACECRAFT.name, 0.0 + ) + inverse_spin_phase_rot = spiceypy.axisar( + np.array([0, 0, 1]), float(np.radians(135.0)) + ) + expected_vector = ( + inverse_spin_phase_rot @ inst_to_sc_rot @ np.array([1.0, 0.0, 0.0]) + ) + inertial_vector = transform_to_inertial( np.radians(spin_phase), np.radians(ra), @@ -484,6 +547,7 @@ def test_transform_to_frames(furnish_kernels, spice_test_data_path): et_to_ttj2000ns(attitude_time), et_to_ttj2000ns(target_time), mag_vector, + inst_frame, ) gse_vector, gsm_vector, rtn_vector = transform_to_frames( @@ -504,40 +568,94 @@ def test_transform_to_frames(furnish_kernels, spice_test_data_path): ) expected_rtn = spiceypy.mxv(rot_ecl_to_rtn, inertial_vector) - # With spin phase halfway between 90 and 180, vector should be pointing at 135. - expected_vector = np.array([-np.sqrt(2) / 2, np.sqrt(2) / 2, 0.0]) np.testing.assert_allclose(inertial_vector, expected_vector, atol=1e-05) np.testing.assert_allclose(gse_vector, expected_gse, atol=1e-05) np.testing.assert_allclose(gsm_vector, expected_gsm, atol=1e-05) np.testing.assert_allclose(rtn_vector, expected_rtn, atol=1e-05) +def test_interpolate_spherical(): + """Test the interpolate_spherical function.""" + + attitude_time = np.array([2, 3]) + # Can be 0 -> 360 degrees + sc_inertial_right = np.array([0, 90]) + # Can be -pi/2 -> pi/2 + sc_inertial_decline = np.array([0, 0]) + # Can be 0 -> 2pi + sc_spin_phase = np.array([300, 10]) + + target_time = 2.5 + ra_deg, dec_deg, spin_phase_deg = interpolate_spherical( + sc_inertial_right, + sc_inertial_decline, + sc_spin_phase, + attitude_time, + target_time, + ) + + expected_ra = np.interp(target_time, attitude_time, sc_inertial_right) + + # Since declination is equal to 0 the ra value will be a simple interpolation here. + assert np.isclose(ra_deg, expected_ra, atol=1e-6) + # Tests that it wraps (360-300+10)/2 = 35 + assert spin_phase_deg == 335.0 + + sc_inertial_decline = np.array([0, 90]) + + ra_deg, dec_deg, spin_phase_deg = interpolate_spherical( + sc_inertial_right, + sc_inertial_decline, + sc_spin_phase, + attitude_time, + target_time, + ) + + # Function is working correctly with declination. + assert spin_phase_deg == 335.0 + assert np.isclose(ra_deg, 0, atol=1e-6) + assert np.isclose(dec_deg, 45.0, atol=1e-6) + + # Function works with wrapped values. + sc_inertial_decline = np.array([0, 0]) + sc_inertial_right = np.array([0, 360 + 90]) + + ra_deg, dec_deg, spin_phase_deg = interpolate_spherical( + sc_inertial_right, + sc_inertial_decline, + sc_spin_phase, + attitude_time, + target_time, + ) + assert np.isclose(ra_deg, expected_ra, atol=1e-6) + + @pytest.mark.external_test_data def test_process_packet( - sc_packet_path, calibration_dataset, ialirt_mag_test_l1d_data, furnish_kernels + postlaunch_xarray_data, + calibration_dataset, + ialirt_mag_test_l1d_data_postlaunch, + furnish_kernels, ): """Test the process_packet function.""" - kernels = [ - "imap_science_100.tf", - "imap_wkcp.tf", + "imap_science_120.tf", + "imap_130.tf", "naif0012.tls", "de440s.bsp", - "imap_spk_demo.bsp", + "imap_recon_od005_20250925_20251014_v01.bsp", "pck00011.tpc", - "imap_sclk_0000.tsc", + "imap_sclk_0036.tsc", + "imap_2025_283_2025_284_001.ah.bc", ] - packet_path, xtce_ialirt_path = sc_packet_path - sc_xarray_data = packet_file_to_datasets( - packet_path, xtce_ialirt_path, use_derived_value=False - )[478] with furnish_kernels(kernels): mag_data = process_packet( - sc_xarray_data, calibration_dataset, ialirt_mag_test_l1d_data + postlaunch_xarray_data, + calibration_dataset, + ialirt_mag_test_l1d_data_postlaunch, ) - # TODO: add validation data. assert isinstance(mag_data[0], dict) expected_keys = { "apid", diff --git a/imap_processing/tests/ialirt/unit/test_process_codice.py b/imap_processing/tests/ialirt/unit/test_process_codice.py index 67465305da..9410d1183f 100644 --- a/imap_processing/tests/ialirt/unit/test_process_codice.py +++ b/imap_processing/tests/ialirt/unit/test_process_codice.py @@ -4,16 +4,68 @@ code. """ +import pickle from pathlib import Path +from unittest.mock import patch +import cdflib +import numpy as np import pytest +import xarray as xr from imap_processing import imap_module_directory -from imap_processing.ialirt.l0.process_codice import process_codice +from imap_processing.cdf.utils import load_cdf +from imap_processing.codice import constants +from imap_processing.codice.codice_l1a_ialirt_hi import l1a_ialirt_hi +from imap_processing.codice.codice_l1a_lo_species import l1a_lo_species +from imap_processing.codice.codice_l1b import convert_to_rates +from imap_processing.codice.codice_l2 import ( + compute_geometric_factors, + get_efficiency_lut, + get_geometric_factor_lut, + process_lo_species_intensity, +) +from imap_processing.codice.decompress import decompress +from imap_processing.codice.utils import process_by_table_id +from imap_processing.ialirt.l0.process_codice import ( + COD_HI_COUNTER, + COD_LO_COUNTER, + concatenate_bytes, + convert_to_intensities, + create_xarray_dataset, + process_codice, + process_ialirt_data_streams, +) +from imap_processing.ialirt.utils.grouping import find_groups +from imap_processing.tests.codice.conftest import ( + VALIDATION_FILE_DATE, + VALIDATION_FILE_VERSION, +) from imap_processing.utils import packet_file_to_datasets pytestmark = pytest.mark.external_test_data +OLD_IAL_BIT_STRUCTURE = { + "SHCOARSE": 32, + "PACKET_VERSION": 16, + "SPIN_PERIOD": 16, + "ACQ_START_SECONDS": 32, + "ACQ_START_SUBSECONDS": 20, + "SPARE_00": 8, + "ST_BIAS_GAIN_MODE": 2, + "SW_BIAS_GAIN_MODE": 2, + "TABLE_ID": 32, + "PLAN_ID": 16, + "PLAN_STEP": 4, + "VIEW_ID": 4, + "RGFO_HALF_SPIN": 6, + "NSO_HALF_SPIN": 6, + "SPARE_01": 1, + "SUSPECT": 1, + "COMPRESSION": 3, + "BYTE_COUNT": 23, +} + @pytest.fixture(scope="session") def l0_test_file(): @@ -33,23 +85,805 @@ def test_datasets(l0_test_file): return datasets +@pytest.fixture(scope="session") +def cod_lo_test_file(): + return Path( + imap_module_directory + / "tests" + / "codice" + / "data" + / "l1a_input" + / f"imap_codice_l0_lo-ialirt_{VALIDATION_FILE_DATE}_v001.pkts" + ) + + +@pytest.fixture(scope="session") +def cod_lo_test_dataset(cod_lo_test_file): + xtce_packet_definition = Path( + imap_module_directory / "ialirt" / "packet_definitions" / "ialirt_codicelo.xml" + ) + + datasets = packet_file_to_datasets( + cod_lo_test_file, xtce_packet_definition, use_derived_value=True + )[1152] + + return datasets + + +@pytest.fixture(scope="session") +def cod_lo_l1a_test_data(): + """Returns the test data directory.""" + data_path = ( + imap_module_directory + / "tests" + / "codice" + / "data" + / "l1a_validation" + / ( + f"imap_codice_l1a_lo-ialirt_{VALIDATION_FILE_DATE}" + f"_{VALIDATION_FILE_VERSION}.cdf" + ) + ) + + data = load_cdf(data_path) + + return data + + +@pytest.fixture(scope="session") +def cod_hi_test_file(): + return Path( + imap_module_directory + / "tests" + / "codice" + / "data" + / "l1a_input" + / f"imap_codice_l0_hi-ialirt_{VALIDATION_FILE_DATE}_v001.pkts" + ) + + +@pytest.fixture(scope="session") +def cod_hi_test_dataset(cod_hi_test_file): + xtce_packet_definition = Path( + imap_module_directory / "ialirt" / "packet_definitions" / "ialirt_codicehi.xml" + ) + + datasets = packet_file_to_datasets( + cod_hi_test_file, xtce_packet_definition, use_derived_value=True + )[1168] + + return datasets + + +@pytest.fixture(scope="session") +def cod_hi_l1a_test_data_transposed(): + """Returns the test data directory.""" + data_path = ( + imap_module_directory + / "tests" + / "codice" + / "data" + / "l1a_validation" + / "imap_codice_l1a_hi-ialirt_20260331_v0.0.22.cdf" + ) + + data = load_cdf(data_path) + + return data + + +@pytest.fixture(scope="session") +def postlaunch_packet_path(): + """Returns the paths to the binary packets.""" + directory = imap_module_directory / "tests" / "ialirt" / "data" / "l0" + filenames = [ + "iois_1_packets_2026_090_05_03_05", + "iois_1_packets_2026_090_05_04_06", + "iois_1_packets_2026_090_05_05_07", + "iois_1_packets_2026_090_05_06_08", + "iois_1_packets_2026_090_05_07_09", + ] + return tuple(directory / fname for fname in filenames) + + +@pytest.fixture +def postlaunch_xarray_data(postlaunch_packet_path, sc_packet_path): + """Create xarray data for multiple packets.""" + apid = 478 + _, xtce_ialirt_path = sc_packet_path + + xarray_data = tuple( + packet_file_to_datasets(packet, xtce_ialirt_path, use_derived_value=False)[apid] + for packet in postlaunch_packet_path + ) + + merged_xarray_data = xr.concat(xarray_data, dim="epoch") + return merged_xarray_data + + @pytest.fixture def codice_test_data(test_datasets): return test_datasets[478] -def test_process_codice(codice_test_data, caplog): - """Ensure that the ``process_codice`` function creates a dataset +@pytest.fixture(scope="session") +def cod_lo_decom_test_file(): + return Path( + imap_module_directory + / "tests" + / "ialirt" + / "data" + / "l0" + / "imap_codice_l1a_lo-ialirt.pickle" + ) + + +@pytest.fixture(scope="session") +def cod_hi_decom_test_file(): + return Path( + imap_module_directory + / "tests" + / "ialirt" + / "data" + / "l0" + / "imap_codice_l1a_hi-ialirt.pickle" + ) + + +@pytest.fixture(scope="session") +def cod_lo_l1b_test_data(): + """Returns the test data directory.""" + data_path = ( + imap_module_directory + / "tests" + / "codice" + / "data" + / "l1b_validation" + / ( + f"imap_codice_l1b_lo-ialirt_{VALIDATION_FILE_DATE}" + f"_{VALIDATION_FILE_VERSION}.cdf" + ) + ) + + data = load_cdf(data_path) + + return data + + +def make_codice_lo_ialirt_dataset(cod_lo_l1a_test_data, descriptor): + coords = { + "epoch": cod_lo_l1a_test_data["epoch"], + "esa_step": cod_lo_l1a_test_data["esa_step"], + "spin_sector": cod_lo_l1a_test_data["spin_sector"], + } + + data_vars = { + "k_factor": ("dim0", cod_lo_l1a_test_data["k_factor"].data), + "voltage_table": ("esa_step", cod_lo_l1a_test_data["voltage_table"].data), + "data_quality": ("epoch", cod_lo_l1a_test_data["data_quality"].data), + "acquisition_time_per_esa_step": ( + ( + "epoch", + "esa_step", + ), + cod_lo_l1a_test_data["acquisition_time_per_esa_step"].data, + ), + "epoch_delta_minus": ("epoch", cod_lo_l1a_test_data["epoch_delta_minus"].data), + "epoch_delta_plus": ("epoch", cod_lo_l1a_test_data["epoch_delta_plus"].data), + } + + variables_to_convert = getattr( + constants, f"{descriptor.upper().replace('-', '_')}_VARIABLE_NAMES" + ) + + for variable in variables_to_convert: + data_vars[variable] = ( + ("epoch", "esa_step", "spin_sector"), + cod_lo_l1a_test_data[variable].data, + ) + data_vars[f"unc_{variable}"] = ( + ("epoch", "esa_step", "spin_sector"), + cod_lo_l1a_test_data[f"unc_{variable}"].data, + ) + + ds = xr.Dataset(data_vars=data_vars, coords=coords) + return ds + + +@patch("xarray.Dataset.drop_vars", new=lambda self, *args, **kwargs: self) +@pytest.mark.external_test_data +def test_l1b_ialirt_cod_lo(cod_lo_l1a_test_data, cod_lo_l1b_test_data): + "Test I-ALiRT CoDICE-Lo l1b data." + descriptor = "lo-ialirt" + dataset = make_codice_lo_ialirt_dataset(cod_lo_l1a_test_data, descriptor) + l1b = convert_to_rates( + dataset, + descriptor, + ) + variables_to_convert = getattr( + constants, f"{descriptor.upper().replace('-', '_')}_VARIABLE_NAMES" + ) + for variable in variables_to_convert: + actual = l1b[variable].data + expected = cod_lo_l1b_test_data[variable].data + + np.testing.assert_allclose(actual, expected, rtol=1e-5) + + +@pytest.fixture(scope="session") +def cod_hi_l1a_test_data(): + """Returns the test data directory.""" + data_path = ( + imap_module_directory + / "tests" + / "codice" + / "data" + / "l1a_validation" + / ( + f"imap_codice_l1a_hi-ialirt_{VALIDATION_FILE_DATE}" + f"_{VALIDATION_FILE_VERSION}.cdf" + ) + ) + + data = load_cdf(data_path) + + return data + + +@pytest.fixture(scope="session") +def cod_hi_l1b_test_data(): + """Returns the test data directory.""" + data_path = ( + imap_module_directory + / "tests" + / "codice" + / "data" + / "l1b_validation" + / ( + f"imap_codice_l1b_hi-ialirt_{VALIDATION_FILE_DATE}" + f"_{VALIDATION_FILE_VERSION}.cdf" + ) + ) + + data = load_cdf(data_path) + + return data + + +@pytest.fixture(scope="session") +def cod_lo_l2_test_data(): + """Returns the test data directory.""" + data_path = ( + imap_module_directory + / "tests" + / "codice" + / "data" + / "l2_validation" + / ( + f"imap_codice_l2_lo-ialirt_{VALIDATION_FILE_DATE}" + f"_{VALIDATION_FILE_VERSION}.cdf" + ) + ) + # TODO: fix error in cdf file and change to: + # data = load_cdf(data_path) + cdf_file = cdflib.CDF(data_path) + + return cdf_file + + +@pytest.fixture(scope="session") +def cod_hi_l2_test_data(): + """Returns the test data directory.""" + data_path = ( + imap_module_directory + / "tests" + / "codice" + / "data" + / "l2_validation" + / ( + f"imap_codice_l2_hi-ialirt_{VALIDATION_FILE_DATE}" + f"_{VALIDATION_FILE_VERSION}.cdf" + ) + ) + # TODO: fix error in cdf file and change to: + # data = load_cdf(data_path) + cdf_file = cdflib.CDF(data_path) + + return cdf_file + + +@patch("xarray.Dataset.drop_vars", new=lambda self, *args, **kwargs: self) +@pytest.mark.external_test_data +def test_l1b_ialirt_cod_hi(cod_hi_l1a_test_data, cod_hi_l1b_test_data): + "Test I-ALiRT CoDICE-Hi l1b data." + descriptor = "hi-ialirt" + l1b = convert_to_rates( + cod_hi_l1a_test_data, + descriptor, + ) + variables_to_convert = getattr( + constants, f"{descriptor.upper().replace('-', '_')}_VARIABLE_NAMES" + ) + for variable in variables_to_convert: + actual = l1b[variable].data + expected = cod_hi_l1b_test_data[variable].data + + np.testing.assert_allclose(actual, expected, atol=1e-5) + + +@pytest.fixture +def l1a_lut_path(): + """Returns the calibration data.""" + lut_path = ( + imap_module_directory + / "tests" + / "codice" + / "data" + / "l1a_lut" + / "imap_codice_l1a-sci-lut_20251007_v005.json" + ) + + return lut_path + + +@pytest.fixture +def l2_lut_path(): + """Returns the calibration data.""" + lut_path = ( + imap_module_directory + / "tests" + / "codice" + / "data" + / "l2_lut" + / "imap_codice_l2-hi-ialirt-efficiency_20251212_v003.csv" + ) + + return lut_path + + +@pytest.fixture +def l2_processing_dependencies(): + eff_path = ( + imap_module_directory + / "tests" + / "codice" + / "data" + / "l2_lut" + / "imap_codice_l2-lo-efficiency_20251212_v003.csv" + ) + gf_path = ( + imap_module_directory + / "tests" + / "codice" + / "data" + / "l2_lut" + / "imap_codice_l2-lo-gfactor_20251212_v003.csv" + ) + + return eff_path, gf_path + + +def test_create_xarray_dataset_basic(l1a_lut_path): + """Test create_xarray_dataset function.""" + + science_values = ["0000000100100011"] + metadata_values = { + "VIEW_ID": np.array([0]), + "TABLE_ID": np.array([3952862729]), + "ACQ_START_SECONDS": np.array([1625078400]), + "ACQ_START_SUBSECONDS": np.array([0]), + "SPIN_PERIOD": np.array([24]), + } + + ds = create_xarray_dataset(science_values, metadata_values, "lo") + + for key in metadata_values: + assert key.lower() in ds.variables + + assert ds["pkt_apid"].item() == 1152 + + combined_bytes = b"".join( + int(val, 2).to_bytes(len(val) // 8, byteorder="big") for val in science_values + ) + assert ds["data"].item() == combined_bytes + + +@pytest.mark.external_test_data +@patch( + "imap_processing.codice.constants.IAL_BIT_STRUCTURE", + OLD_IAL_BIT_STRUCTURE, +) +def test_group_and_decompress_ialirt_cod_lo( + cod_lo_test_dataset, cod_lo_decom_test_file, l1a_lut_path, cod_lo_l1a_test_data +): + "Test that I-ALiRT CoDICE-Lo data can be grouped and decompressed properly." + + grouped_cod_lo_data = find_groups( + cod_lo_test_dataset, (0, COD_LO_COUNTER), "cod_lo_counter", "cod_lo_acq" + ) + + # Verify that we grouped the values properly. + counter_values = cod_lo_test_dataset["cod_lo_counter"].data + valid_values = counter_values[counter_values != 255] + resets = np.where(valid_values == COD_LO_COUNTER) + + count = increment = 0 + for reset in resets[0]: + group = valid_values[increment : reset + 1] + np.testing.assert_array_equal( + group, np.arange(0, COD_LO_COUNTER + 1, dtype=np.uint8) + ) + increment = reset + 1 + count = count + 1 + + assert count == int(grouped_cod_lo_data.group.max()) + + unique_groups = np.unique(grouped_cod_lo_data["group"]) + + # Test data. + with open(cod_lo_decom_test_file, "rb") as handle: + data = pickle.load(handle) # noqa: S301 + test_grouped_data = data["grouped_lo_ialirt"][0] + test_decom_data = data["decompressed_lo_ialirt"][0] + + header_len = 6 # Test data header at start of block + checksum_len = 2 # Test data checksum at end of block + data_len = 3484 # Data length in decompressed packet + block_size = header_len + data_len + checksum_len + + test_grouped_data_array = [] + + for i, group in enumerate(unique_groups): + compressed_data = concatenate_bytes(grouped_cod_lo_data, group, "lo") + + start = header_len + i * block_size + end = start + data_len + expected_slice = test_grouped_data[start:end] + + test_grouped_data_array.append(expected_slice) + + assert expected_slice == compressed_data[:data_len] + + science_values, metadata_values = process_ialirt_data_streams( + test_grouped_data_array + ) + + for i in range(len(science_values)): + values = int(science_values[i], 2).to_bytes( + len(science_values[i]) // 8, byteorder="big" + ) + + decompressed_values = decompress(values, metadata_values["VIEW_ID"][0]) + test_decom_data_array = test_decom_data[i] + + np.testing.assert_array_equal(decompressed_values, test_decom_data_array) + + dataset = create_xarray_dataset(science_values, metadata_values, "lo") + result = process_by_table_id(dataset, l1a_lut_path, l1a_lo_species) + + expected_species = [ + "heplusplus", + "cplus5", + "cplus6", + "oplus6", + "oplus7", + "oplus8", + "mg", + "fe_loq", + "fe_hiq", + ] + + # Returns data for all expected species at 128 esa steps. + for species in expected_species: + np.array_equal(result[species].values, cod_lo_l1a_test_data["heplusplus"].data) + + +@pytest.mark.external_test_data +@patch( + "imap_processing.codice.constants.IAL_BIT_STRUCTURE", + OLD_IAL_BIT_STRUCTURE, +) +def test_group_and_decompress_ialirt_cod_hi( + cod_hi_test_dataset, cod_hi_decom_test_file, l1a_lut_path, cod_hi_l1a_test_data +): + "Test that I-ALiRT CoDICE-Hi data can be grouped and decompressed properly." + + codice_hi_counter = 197 + grouped_cod_hi_data = find_groups( + cod_hi_test_dataset, (0, codice_hi_counter), "cod_hi_counter", "cod_hi_acq" + ) + + # Verify that we grouped the values properly. + counter_values = cod_hi_test_dataset["cod_hi_counter"].data + valid_values = counter_values[counter_values != 255] + resets = np.where(valid_values == codice_hi_counter) + + count = increment = 0 + for reset in resets[0]: + group = valid_values[increment : reset + 1] + np.testing.assert_array_equal( + group, np.arange(0, codice_hi_counter + 1, dtype=np.uint8) + ) + increment = reset + 1 + count = count + 1 + + assert count == int(grouped_cod_hi_data.group.max()) + + unique_groups = np.unique(grouped_cod_hi_data["group"]) + + # Test data. + with open(cod_hi_decom_test_file, "rb") as handle: + data = pickle.load(handle) # noqa: S301 + test_grouped_data = data["grouped_hi_ialirt"][0] + test_decom_data = data["decompressed_hi_ialirt"][0] + + header_len = 6 # Test data header at start of block + checksum_len = 2 # Test data checksum at end of block + data_len = 988 # Data length in decompressed packet + block_size = header_len + data_len + checksum_len + + test_grouped_data_array = [] + + for i, group in enumerate(unique_groups): + compressed_data = concatenate_bytes(grouped_cod_hi_data, group, "hi") + + start = header_len + i * block_size + end = start + data_len + expected_slice = test_grouped_data[start:end] + + test_grouped_data_array.append(expected_slice) + + assert expected_slice == compressed_data[:data_len] + + science_values, metadata_values = process_ialirt_data_streams( + test_grouped_data_array + ) + + for i in range(len(science_values)): + values = int(science_values[i], 2).to_bytes( + len(science_values[i]) // 8, byteorder="big" + ) + + decompressed_values = decompress(values, metadata_values["VIEW_ID"][0]) + + np.testing.assert_array_equal(decompressed_values, test_decom_data[i]) + + dataset = create_xarray_dataset(science_values, metadata_values, "hi") + result = l1a_ialirt_hi(dataset, l1a_lut_path) + + expected_species = [ + "h", + ] + + # Returns data for all expected species at 15 energy steps. + for species in expected_species: + np.array_equal(result[species].values, cod_hi_l1a_test_data["h"].data) + assert np.array_equal(result["data_quality"], cod_hi_l1a_test_data["data_quality"]) + assert np.allclose( + result["spin_period"].values, + cod_hi_l1a_test_data["spin_period"].values, + atol=1e-6, + ) + + +@pytest.mark.external_test_data +def test_l2_ialirt_cod_hi(cod_hi_l1b_test_data, l2_lut_path, cod_hi_l2_test_data): + "Test that I-ALiRT CoDICE-Hi L2 data." + + # Read efficiency lookup table + intensity = convert_to_intensities(cod_hi_l1b_test_data, l2_lut_path, "h") + + # test data + test_data = cod_hi_l2_test_data["h"] + + np.testing.assert_allclose( + intensity, + test_data, + atol=1e-6, + ) + + +@pytest.mark.external_test_data +def test_l2_ialirt_cod_lo( + cod_lo_l1b_test_data, l1a_lut_path, cod_lo_l2_test_data, l2_processing_dependencies +): + """Test process_codice for hi.""" + eff_path, gf_path = l2_processing_dependencies + + geometric_factor_lookup = get_geometric_factor_lut(None, gf_path) + geometric_factors = compute_geometric_factors( + cod_lo_l1b_test_data, geometric_factor_lookup + ) + + efficiency_lookup = get_efficiency_lut(None, eff_path) + efficiencies = efficiency_lookup[efficiency_lookup["product"] == "sw"] + + # Temporarily store energy_per_charge values from energy_table variable. + energy_per_charge_values = cod_lo_l1b_test_data["energy_table"].values + + # L1B validation data is missing esa_step coordinate. Create esa_step coordinate. + # Also, all variables in l1b validation data is using energy_table as coordinate. + # Update both to match the processing code expectations with rename(). + cod_lo_l1b_test_data = cod_lo_l1b_test_data.rename({"energy_table": "esa_step"}) + # Now, create variable in data_vars with name energy_per_charge and values from + # energy_table variable. + cod_lo_l1b_test_data["energy_per_charge"] = xr.DataArray( + energy_per_charge_values, dims=["esa_step"] + ) + + intensity = process_lo_species_intensity( + cod_lo_l1b_test_data, + constants.LO_IALIRT_VARIABLE_NAMES, + geometric_factors, + efficiencies, + constants.SOLAR_WIND_POSITIONS, + ) + + pseudo_density_dict = {} + + for species in constants.LO_IALIRT_VARIABLE_NAMES: + pseudo_density = ( + intensity[species] + * np.sqrt(cod_lo_l1b_test_data["energy_per_charge"]) + * np.sqrt(constants.LO_IALIRT_M_OVER_Q[species]) + ) # (epoch, esa_step, spin_sector) + + summed_pseudo_density = pseudo_density.sum(dim="esa_step").squeeze( + "spin_sector" + ) # (epoch,) + pseudo_density_dict[species] = summed_pseudo_density.values + + species = constants.LO_IALIRT_VARIABLE_NAMES + + # Denominator. + # Note that outside of this test a zero value denominator + # will lead to a null value. + # The use of zeros here is only to match the test data as + # confirmed by the instrument team. + o_abundance_ratio = ( + pseudo_density_dict[species[3]] + + pseudo_density_dict[species[4]] + + pseudo_density_dict[species[5]] + ) + + c_over_o_abundance_ratio = np.divide( + pseudo_density_dict[species[1]] + pseudo_density_dict[species[2]], + o_abundance_ratio, + out=np.full(o_abundance_ratio.shape, np.nan), # fill with nans by default + where=o_abundance_ratio != 0, + ) + mg_over_o_abundance_ratio = np.divide( + pseudo_density_dict[species[6]], + o_abundance_ratio, + out=np.full(o_abundance_ratio.shape, np.nan), + where=o_abundance_ratio != 0, + ) + fe_over_o_abundance_ratio = np.divide( + pseudo_density_dict[species[7]] + pseudo_density_dict[species[8]], + o_abundance_ratio, + out=np.full(o_abundance_ratio.shape, np.nan), + where=o_abundance_ratio != 0, + ) + + c_plus_6_over_c_plus_5_ratio = np.divide( + pseudo_density_dict[species[2]], + pseudo_density_dict[species[1]], + out=np.full(pseudo_density_dict[species[1]].shape, np.nan), + where=o_abundance_ratio != 0, + ) + o_plus_7_over_o_plus_6_ratio = np.divide( + pseudo_density_dict[species[4]], + pseudo_density_dict[species[3]], + out=np.full(pseudo_density_dict[species[1]].shape, np.nan), + where=o_abundance_ratio != 0, + ) + fe_low_over_fe_high_ratio = np.divide( + pseudo_density_dict[species[7]], + pseudo_density_dict[species[8]], + out=np.full(pseudo_density_dict[species[1]].shape, np.nan), + where=o_abundance_ratio != 0, + ) + + np.testing.assert_array_equal( + c_over_o_abundance_ratio, cod_lo_l2_test_data["c_over_o_abundance_ratio"] + ) + np.testing.assert_array_equal( + mg_over_o_abundance_ratio, cod_lo_l2_test_data["mg_over_o_abundance_ratio"] + ) + np.testing.assert_array_equal( + fe_over_o_abundance_ratio, cod_lo_l2_test_data["fe_over_o_abundance_ratio"] + ) + np.testing.assert_array_equal( + c_plus_6_over_c_plus_5_ratio, + cod_lo_l2_test_data["c_plus_6_over_c_plus_5_ratio"], + ) + np.testing.assert_array_equal( + o_plus_7_over_o_plus_6_ratio, + cod_lo_l2_test_data["o_plus_7_over_o_plus_6_ratio"], + ) + np.testing.assert_array_equal( + fe_low_over_fe_high_ratio, cod_lo_l2_test_data["fe_low_over_fe_high_ratio"] + ) + + +@pytest.mark.external_test_data +@patch( + "imap_processing.codice.constants.IAL_BIT_STRUCTURE", + OLD_IAL_BIT_STRUCTURE, +) +def test_process_codice_lo( + cod_lo_test_dataset, + l1a_lut_path, + l2_lut_path, + cod_lo_l2_test_data, + l2_processing_dependencies, + furnish_kernels, +): + """Test process_codice for hi.""" + eff_path, gf_path = l2_processing_dependencies + + n = cod_lo_test_dataset.dims["epoch"] + cod_lo_test_dataset = cod_lo_test_dataset.assign( + sc_sclk_sec=("epoch", np.zeros(n, dtype=np.int64)), + sc_sclk_sub_sec=("epoch", np.zeros(n, dtype=np.int64)), + ) + kernels = [ + "naif0012.tls", + "imap_sclk_0036.tsc", + ] + with furnish_kernels(kernels): + cod_lo_data, _ = process_codice( + cod_lo_test_dataset, l1a_lut_path, eff_path, "codice_lo", gf_path + ) + + l2_products = [ + "codice_lo_c_over_o_abundance", + "codice_lo_mg_over_o_abundance", + "codice_lo_fe_over_o_abundance", + "codice_lo_c_plus_6_over_c_plus_5", + "codice_lo_o_plus_7_over_o_plus_6", + "codice_lo_fe_low_over_fe_high", + ] + + assert len(cod_lo_data) == 9 + + for product in l2_products: + assert cod_lo_data[0][product] is None + + +@pytest.mark.external_test_data +def test_process_codice_hi(postlaunch_xarray_data, cod_hi_l1a_test_data_transposed): + """Test process_codice for hi.""" + grouped_cod_hi_data = find_groups( + postlaunch_xarray_data, (0, COD_HI_COUNTER), "cod_hi_counter", "cod_hi_acq" + ) + unique_cod_hi_groups = np.unique(grouped_cod_hi_data["group"]) - Here we just need to make sure the function is returning the expected data. - CoDICE I-ALiRT data products are being validated separately in the - ``codice.test_codice_l[1a|1b|2]`` modules. - """ + for group in unique_cod_hi_groups: + cod_hi_data_stream = concatenate_bytes(grouped_cod_hi_data, group, "hi") + cod_hi_science_values, cod_hi_metadata_values = process_ialirt_data_streams( + [cod_hi_data_stream] + ) + if not cod_hi_science_values: + continue + cod_hi_dataset = create_xarray_dataset( + cod_hi_science_values, cod_hi_metadata_values, "hi" + ) + l1a_lut_path = ( + imap_module_directory + / "tests" + / "codice" + / "data" + / "l1a_lut" + / "imap_codice_l1a-sci-lut_20260129_v002.json" + ) + l1a_hi = l1a_ialirt_hi(cod_hi_dataset, l1a_lut_path) - with caplog.at_level("WARNING"): - cod_lo_data, cod_hi_data = process_codice(codice_test_data) + expected = cod_hi_l1a_test_data_transposed.sel( + epoch=l1a_hi["epoch"], method="nearest" + ) - assert isinstance(cod_lo_data, list) - assert all(isinstance(item, dict) for item in cod_lo_data) - assert isinstance(cod_hi_data, list) - assert all(isinstance(item, dict) for item in cod_hi_data) + np.testing.assert_array_equal( + l1a_hi["h"].values, + expected["h"].data, + ) diff --git a/imap_processing/tests/ialirt/unit/test_process_ephemeris.py b/imap_processing/tests/ialirt/unit/test_process_ephemeris.py index 1fd8f00e48..6875a4fbd2 100644 --- a/imap_processing/tests/ialirt/unit/test_process_ephemeris.py +++ b/imap_processing/tests/ialirt/unit/test_process_ephemeris.py @@ -80,17 +80,18 @@ def test_calculate_azimuth_and_elevation(furnish_kernels): "pck00011.tpc", "de440s.bsp", "imap_spk_demo.bsp", + "earth_latest_high_prec.bpc", ] with furnish_kernels(kernels): azimuth_result, elevation_result = ( process_ephemeris.calculate_azimuth_and_elevation( - longitude, latitude, altitude, observation_time + longitude, latitude, altitude, observation_time, obsref="ITRF93" ) ) assert azimuth_result, elevation_result is not None # test array of observation times - time_endpoints = ("2026 SEP 22 00:00:00", "2026 SEP 22 23:59:59") + time_endpoints = ("2025 JUL 14 00:00:00", "2025 JUL 14 23:59:59") time_interval = int(1e3) # seconds between data points observation_time = np.arange( str_to_et(time_endpoints[0]), str_to_et(time_endpoints[1]), time_interval @@ -98,7 +99,7 @@ def test_calculate_azimuth_and_elevation(furnish_kernels): with furnish_kernels(kernels): azimuth_result, elevation_result = ( process_ephemeris.calculate_azimuth_and_elevation( - longitude, latitude, altitude, observation_time + longitude, latitude, altitude, observation_time, obsref="ITRF93" ) ) assert len(azimuth_result) == len(observation_time) diff --git a/imap_processing/tests/ialirt/unit/test_process_hit.py b/imap_processing/tests/ialirt/unit/test_process_hit.py index 34c74de73c..25bea11a0b 100644 --- a/imap_processing/tests/ialirt/unit/test_process_hit.py +++ b/imap_processing/tests/ialirt/unit/test_process_hit.py @@ -50,7 +50,7 @@ def hit_test_data(): @pytest.fixture def xarray_data(binary_packet_path, xtce_hit_path): - """Create xarray data""" + """Create xarray data.""" apid = 1253 xarray_data = packet_file_to_datasets(binary_packet_path, xtce_hit_path)[apid] @@ -66,7 +66,7 @@ def test_process_spacecraft_packet(sc_packet_path): )[478] hit_product = process_hit(sc_xarray_data) - assert len(hit_product[0].keys()) == 15 + assert len(hit_product[0].keys()) == 18 def generate_prefixes(prefixes): @@ -174,32 +174,12 @@ def test_process_hit(xarray_data, caplog): hit_product = process_hit(xarray_data) assert len(hit_product) == 15 - # Make a subset of data that has values to check the calculations of process hit. - indices = (xarray_data["hit_met"] != 0).values.nonzero()[0] - xarray_data["hit_slow_rate"].values[indices[0] : indices[0] + 60] = 2 - subset = xarray_data.isel(epoch=slice(indices[0], indices[0] + 60)) - - hit_product = process_hit(subset) - - assert hit_product[0]["hit_e_a_side_low_en"] == 4 - assert hit_product[0]["hit_e_a_side_med_en"] == 4 - assert hit_product[0]["hit_e_b_side_low_en"] == 4 - assert hit_product[0]["hit_e_b_side_high_en"] == 2 - assert hit_product[0]["hit_e_b_side_med_en"] == 4 - assert hit_product[0]["hit_he_omni_high_en"] == 2 - - # Create a scrambled set of subcom values. - xarray_data["hit_subcom"].values[indices[0] : indices[0] + 60] = [ - i for i in range(29) for _ in range(2) - ] + [59, 59] - - with caplog.at_level("WARNING"): - process_hit(subset) - - assert any( - "does not contain all values from 0 to 59 without duplicates" in message - for message in caplog.text.splitlines() - ) + assert hit_product[0]["hit_e_a_side_low_en"] == 0 + assert hit_product[0]["hit_e_a_side_med_en"] == 0 + assert hit_product[0]["hit_e_b_side_low_en"] == 0 + assert hit_product[0]["hit_e_b_side_high_en"] == 0 + assert hit_product[0]["hit_e_b_side_med_en"] == 0 + assert hit_product[0]["hit_he_omni_high_en"] == 0 def test_decom_packets(xarray_data, hit_test_data): diff --git a/imap_processing/tests/ialirt/unit/test_process_status.py b/imap_processing/tests/ialirt/unit/test_process_status.py new file mode 100644 index 0000000000..b86bf7020c --- /dev/null +++ b/imap_processing/tests/ialirt/unit/test_process_status.py @@ -0,0 +1,52 @@ +"""Tests for the process_status module.""" + +import pytest +import xarray as xr + +from imap_processing import imap_module_directory +from imap_processing.ialirt.l0.process_status import process_status +from imap_processing.utils import packet_file_to_datasets + + +@pytest.fixture(scope="session") +def postlaunch_packet_path(): + """Returns the paths to the binary packets.""" + directory = imap_module_directory / "tests" / "ialirt" / "data" / "l0" + filenames = [ + "iois_1_packets_2026_090_05_03_05", + "iois_1_packets_2026_090_05_04_06", + "iois_1_packets_2026_090_05_05_07", + "iois_1_packets_2026_090_05_06_08", + "iois_1_packets_2026_090_05_07_09", + ] + return tuple(directory / fname for fname in filenames) + + +@pytest.fixture +def postlaunch_xarray_data(postlaunch_packet_path, sc_packet_path): + """Create xarray data for multiple packets.""" + apid = 478 + _, xtce_ialirt_path = sc_packet_path + + xarray_data = tuple( + packet_file_to_datasets(packet, xtce_ialirt_path, use_derived_value=False)[apid] + for packet in postlaunch_packet_path + ) + + merged_xarray_data = xr.concat(xarray_data, dim="epoch") + return merged_xarray_data + + +@pytest.mark.external_test_data +def test_process_status(postlaunch_xarray_data): + """Test the process_status function.""" + + status_data = process_status(postlaunch_xarray_data) + + for i in range(len(status_data)): + assert status_data[i]["sc_swapi_status"] == 1 + assert status_data[i]["sc_mag_status"] == 1 + assert status_data[i]["sc_hit_status"] == 1 + assert status_data[i]["sc_codice_status"] == 1 + assert status_data[i]["sc_lo_status"] == 1 + assert status_data[i]["sc_autonomy_status"] == 1 diff --git a/imap_processing/tests/ialirt/unit/test_process_swapi.py b/imap_processing/tests/ialirt/unit/test_process_swapi.py index db1e5778a6..e1f0a04b2d 100644 --- a/imap_processing/tests/ialirt/unit/test_process_swapi.py +++ b/imap_processing/tests/ialirt/unit/test_process_swapi.py @@ -3,13 +3,17 @@ import numpy as np import pandas as pd import pytest +import xarray as xr from imap_processing import imap_module_directory from imap_processing.ialirt.l0.process_swapi import ( + Consts, count_rate, + geometric_mean, optimize_pseudo_parameters, process_swapi_ialirt, ) +from imap_processing.swapi.swapi_utils import read_swapi_lut_table from imap_processing.utils import packet_file_to_datasets @@ -32,6 +36,24 @@ def binary_packet_path(): ) +@pytest.fixture(scope="session") +def esa_unit_conversion_table() -> pd.DataFrame: + """ + Read the ESA unit conversion table. + + Returns + ------- + esa_unit_conversion_table : pandas.DataFrame + The ESA unit conversion table. + """ + esa_file_path = ( + imap_module_directory + / "tests/swapi/lut/imap_swapi_esa-unit-conversion_20250626_v001.csv" + ) + df = read_swapi_lut_table(esa_file_path) + return df + + @pytest.fixture(scope="session") def swapi_test_data(): """Returns the l0 validation dataframe.""" @@ -121,7 +143,11 @@ def test_decom_packets(xarray_data, swapi_test_data): @pytest.mark.external_test_data @mock.patch("imap_processing.ialirt.l0.process_swapi.process_sweep_data") def test_process_swapi_ialirt( - mock_process_sweep_data, xarray_data, ialirt_test_data, sc_xarray_data + mock_process_sweep_data, + xarray_data, + ialirt_test_data, + sc_xarray_data, + esa_unit_conversion_table, ): """Test that the process_swapi_ialirt() function returns expected keys.""" @@ -137,34 +163,19 @@ def test_process_swapi_ialirt( 0 : xarray_data["swapi_flag"].shape[0] ].data - energy_passbands = pd.read_csv( - f"{imap_module_directory}/tests/ialirt/data/l0/swapi_ialirt_energy_steps.csv" - ) + swapi_result = process_swapi_ialirt(xarray_data, esa_unit_conversion_table) - swapi_result = process_swapi_ialirt(xarray_data, energy_passbands) - - key_names = [ - "apid", - "met", - "met_in_utc", - "ttj2000ns", - "swapi_pseudo_proton_density", - "swapi_pseudo_proton_speed", - "swapi_pseudo_proton_temperature", - ] - - for key in key_names: - assert swapi_result[0][key] is not None, ( - f"The expected attribute {key} was not filled in the result dict." - ) + assert swapi_result[0]["swapi_pseudo_proton_speed"] is None + assert swapi_result[0]["swapi_pseudo_proton_density"] is None + assert swapi_result[0]["swapi_pseudo_proton_temperature"] is None def test_count_rate(): """Use random realistic values to test for expected output of count_rate().""" actual_result = count_rate(1370, *[550, 5.27, 1e5]) - expected_result = 3073.023325893161 - assert actual_result == expected_result, ( + expected_result = 3073.023325893161 * Consts.temporary_density_factor + assert np.isclose(actual_result, expected_result), ( f"The actual result of count_rate()" f" {actual_result} does not " f"match the expected result " @@ -181,15 +192,15 @@ def test_optimize_parameters(): "file_name": "ialirt_test_data_u_sw_550_n_sw_5_T_sw_100000_v2.csv", "expected_values": { # expected output and acceptable tolerance "pseudo_speed": (550, 0.01), - "pseudo_density": (5, 0.14), - "pseudo_temperature": (1e5, 0.2), + "pseudo_density": (5 / Consts.temporary_density_factor, 0.14), + "pseudo_temperature": (1e5, 0.25), }, }, "test_set_2": { "file_name": "ialirt_test_data_u_sw_650_n_sw_3.0_T_sw_120000_v2.csv", "expected_values": { # expected output and acceptable tolerance "pseudo_speed": (650, 0.01), - "pseudo_density": (3, 0.3), + "pseudo_density": (3 / Consts.temporary_density_factor, 0.3), "pseudo_temperature": (1.2e5, 0.28), }, }, @@ -197,8 +208,8 @@ def test_optimize_parameters(): "file_name": "ialirt_test_data_u_sw_400_n_sw_6.0_T_sw_80000_v2.csv", "expected_values": { # expected output and acceptable tolerance "pseudo_speed": (400, 0.01), - "pseudo_density": (6, 0.39), - "pseudo_temperature": (8e4, 0.15), + "pseudo_density": (6 / Consts.temporary_density_factor, 0.39), + "pseudo_temperature": (8e4, 0.2), }, }, } @@ -215,18 +226,22 @@ def test_optimize_parameters(): ) count_rates = energy_data["Count Rates [Hz]"].to_numpy() count_rates[0] = 0.0 - count_rates = np.tile(count_rates, (2, 1)) count_rates_errors = energy_data["Count Rates Error [Hz]"].to_numpy() - count_rates_errors = np.tile(count_rates_errors, (2, 1)) result = optimize_pseudo_parameters( count_rates, count_rates_errors, energy_passbands ) + result_dict = { + "pseudo_speed": result[0], + "pseudo_density": result[1], + "pseudo_temperature": result[2], + } + for param in test_data[test_set]["expected_values"]: ( np.testing.assert_allclose( - result[param][0], + result_dict[param], test_data[test_set]["expected_values"][param][0], rtol=test_data[test_set]["expected_values"][param][1], ), @@ -234,39 +249,234 @@ def test_optimize_parameters(): ) -@pytest.mark.external_test_data -def test_process_spacecraft_packet(sc_xarray_data): - """Tests spacecraft packet processing.""" - calibration_file = pd.read_csv( +def test_optimize_parameters_exception_handling(): + """Test that the optimize_pseudo_parameters() function reports + speed only when given data that causes curve_fit to fail.""" + + expected_speed = 557.279273 # peak passband speed + file_name = "ialirt_test_data_u_sw_550_n_sw_5_T_sw_100000_v2.csv" + + calibration_test_file = pd.read_csv( f"{imap_module_directory}/tests/ialirt/data/l0/swapi_ialirt_energy_steps.csv" ) + energy_passbands = calibration_test_file["Energy"][0:63].to_numpy().astype(float) + + energy_data = pd.read_csv( + f"{imap_module_directory}/tests/ialirt/data/l0/{file_name}" + ) + count_rates = energy_data["Count Rates [Hz]"].to_numpy() + count_rates[0] = 0.0 + count_rates = np.tile(count_rates, (2, 1)) + count_rates_errors = energy_data["Count Rates Error [Hz]"].to_numpy() + + """ + code to select the random seed: + for i in range(100): + np.random.seed(i) + result = optimize_pseudo_parameters(count_rates * + np.abs(np.random.standard_normal(size=count_rates.shape)), + count_rates_errors, energy_passbands) + if np.isclose(result['pseudo_speed'][0], expected_speed, + rtol=1e-6) and np.isnan(result['pseudo_density'][0]): + print(i) + """ + np.random.seed(14) + speed, density, temperature = optimize_pseudo_parameters( + count_rates * np.abs(np.random.standard_normal(size=count_rates.shape)), + count_rates_errors, + energy_passbands, + ) - # Case 1: Not fixing the sequence number attribute, which is all zeros. - swapi_product = process_swapi_ialirt(sc_xarray_data, calibration_file) - assert swapi_product == [] - - # Case 2: Overwriting swapi_seq_number to be an acceptable array of numbers. - # Calculate how many times to tile the sequence to reach length of sc packet - target_length = sc_xarray_data["swapi_seq_number"].shape[0] - base_sequence = np.arange(12) - repeat_times = (target_length // len(base_sequence)) + 1 # Over-repeat - - # Tile the sequence and truncate to target_length - extended_data = np.tile(base_sequence, repeat_times)[:target_length] - sc_xarray_data["swapi_seq_number"].data = extended_data - - swapi_product1 = process_swapi_ialirt(sc_xarray_data, calibration_file) - key_names = [ - "apid", - "met", - "met_in_utc", - "ttj2000ns", - "swapi_pseudo_proton_density", - "swapi_pseudo_proton_speed", - "swapi_pseudo_proton_temperature", + np.testing.assert_allclose(speed, expected_speed, rtol=1e-6) + np.testing.assert_allclose(density, np.nan) + np.testing.assert_allclose(temperature, np.nan) + + +def test_optimize_parameters_bad_fit_handling(): + """Test that the optimize_pseudo_parameters() function + reports speed only when the fit is too poor.""" + + file_name = "ialirt_test_data_u_sw_550_n_sw_5_T_sw_100000_v2.csv" + + calibration_test_file = pd.read_csv( + f"{imap_module_directory}/tests/ialirt/data/l0/swapi_ialirt_energy_steps.csv" + ) + energy_passbands = calibration_test_file["Energy"][0:63].to_numpy().astype(float) + + energy_data = pd.read_csv( + f"{imap_module_directory}/tests/ialirt/data/l0/{file_name}" + ) + count_rates = energy_data["Count Rates [Hz]"].to_numpy() + count_rates[0] = 0.0 + count_rates_errors = energy_data["Count Rates Error [Hz]"].to_numpy() + + # add high-amplitude randomness to the count rates to make the fit poor + np.random.seed(0) + count_rates = count_rates + np.abs( + np.random.standard_normal(size=count_rates.shape) * count_rates.max() + ) + + speed, density, temperature = optimize_pseudo_parameters( + count_rates, count_rates_errors, energy_passbands + ) + + expected_speed = ( + np.sqrt(energy_passbands[count_rates.argmax(axis=-1)]) * Consts.speed_coeff + ) + + np.testing.assert_allclose(speed, expected_speed, rtol=1e-6) + np.testing.assert_allclose(density, np.nan) + np.testing.assert_allclose(temperature, np.nan) + + +def test_optimize_parameters_bad_covariance_handling(): + """Test that the optimize_pseudo_parameters() function + reports speed only when output covariance is nonsensical.""" + + file_name = "ialirt_test_data_u_sw_550_n_sw_5_T_sw_100000_v2.csv" + + calibration_test_file = pd.read_csv( + f"{imap_module_directory}/tests/ialirt/data/l0/swapi_ialirt_energy_steps.csv" + ) + energy_passbands = calibration_test_file["Energy"][0:63].to_numpy().astype(float) + + energy_data = pd.read_csv( + f"{imap_module_directory}/tests/ialirt/data/l0/{file_name}" + ) + count_rates = energy_data["Count Rates [Hz]"].to_numpy() + count_rates[0] = 0.0 + count_rates_errors = energy_data["Count Rates Error [Hz]"].to_numpy() + + # setting errors to 0 results in infinite covariance + count_rates_errors *= 0 + + speed, density, temperature = optimize_pseudo_parameters( + count_rates, count_rates_errors, energy_passbands + ) + + expected_speed = ( + np.sqrt(energy_passbands[count_rates.argmax(axis=-1)]) * Consts.speed_coeff + ) + + np.testing.assert_allclose(speed, expected_speed, rtol=1e-6) + np.testing.assert_allclose(density, np.nan) + np.testing.assert_allclose(temperature, np.nan) + + +def test_geometric_mean(): + """Test geometric_mean function.""" + + swapi_met_list = [12, 24, 36, 48, 60] + + pseudo_proton_speed_list = [400, 420, 440, 460, 480] + pseudo_proton_density_list = [5.0, 6.0, 7.0, 8.0, 9.0] + pseudo_proton_temperature_list = [60000, 62000, 64000, 66000, 68000] + + avg_swapi_met, avg_density, avg_speed, avg_temperature = geometric_mean( + swapi_met_list, + pseudo_proton_speed_list, + pseudo_proton_density_list, + pseudo_proton_temperature_list, + ) + + expected_density = np.exp(np.mean(np.log(pseudo_proton_density_list))) + expected_speed = np.exp(np.mean(np.log(pseudo_proton_speed_list))) + expected_temperature = np.exp(np.mean(np.log(pseudo_proton_temperature_list))) + expected_met = np.mean(swapi_met_list) + + assert np.isclose(avg_density, expected_density) + assert np.isclose(avg_speed, expected_speed) + assert np.isclose(avg_temperature, expected_temperature) + assert np.isclose(avg_swapi_met, expected_met) + + +def test_geometric_mean_nan(): + """Test geometric_mean function.""" + + swapi_met_list = [12, 24, 36, 48, 60] + + pseudo_proton_speed_list = [400, 420, 440, 460, np.nan] + pseudo_proton_density_list = [5.0, 6.0, 7.0, 8.0, np.nan] + pseudo_proton_temperature_list = [60000, 62000, 64000, 66000, np.nan] + + avg_swapi_met, avg_density, avg_speed, avg_temperature = geometric_mean( + swapi_met_list, + pseudo_proton_speed_list, + pseudo_proton_density_list, + pseudo_proton_temperature_list, + ) + + expected_density = np.exp(np.mean(np.log(pseudo_proton_density_list[0:4]))) + expected_speed = np.exp(np.mean(np.log(pseudo_proton_speed_list[0:4]))) + expected_temperature = np.exp(np.mean(np.log(pseudo_proton_temperature_list[0:4]))) + expected_met = np.mean(swapi_met_list[0:4]) + + assert np.isclose(avg_density, expected_density) + assert np.isclose(avg_speed, expected_speed) + assert np.isclose(avg_temperature, expected_temperature) + assert np.isclose(avg_swapi_met, expected_met) + + +def test_geometric_gaps(): + """Test geometric_mean function.""" + + swapi_met_list = [0, 12, 24, 36, 240, 252, 264, 272, 284] + + bool_check = len(swapi_met_list) >= 5 and np.all( + np.isclose(np.diff(swapi_met_list[-5:]), 12.0, atol=0.05) + ) + assert not bool_check + + pseudo_proton_speed_list = [400, 420, 440, 460, 480, 500, 520, 540, 560] + pseudo_proton_density_list = [5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0] + pseudo_proton_temperature_list = [ + 60000, + 62000, + 64000, + 66000, + 68000, + 70000, + 72000, + 74000, + 76000, ] - for key in key_names: - assert swapi_product1[0][key] is not None, ( - f"The expected attribute {key} was not filled in the result dict." - ) + avg_swapi_met, avg_density, avg_speed, avg_temperature = geometric_mean( + swapi_met_list[4::], + pseudo_proton_speed_list[4::], + pseudo_proton_density_list[4::], + pseudo_proton_temperature_list[4::], + ) + + expected_density = np.exp(np.mean(np.log(pseudo_proton_density_list[4::]))) + expected_speed = np.exp(np.mean(np.log(pseudo_proton_speed_list[4::]))) + expected_temperature = np.exp(np.mean(np.log(pseudo_proton_temperature_list[4::]))) + expected_met = np.mean(swapi_met_list[4::]) + + assert np.isclose(avg_density, expected_density) + assert np.isclose(avg_speed, expected_speed) + assert np.isclose(avg_temperature, expected_temperature) + assert np.isclose(avg_swapi_met, expected_met) + + +@pytest.mark.external_test_data +def test_process_spacecraft_packet( + esa_unit_conversion_table, swapi_postlaunch_sc_packet_path +): + """Tests spacecraft packet processing.""" + + packet_path, xtce_ialirt_path = swapi_postlaunch_sc_packet_path + xarray_data = tuple( + packet_file_to_datasets(packet, xtce_ialirt_path, use_derived_value=False)[478] + for packet in packet_path + ) + postlaunch_sc_xarray_data = xr.concat(xarray_data, dim="epoch") + + postlaunch_sc_xarray_data["swapi_version"].data = np.full_like( + postlaunch_sc_xarray_data["swapi_version"].data, 2 + ) + swapi_product = process_swapi_ialirt( + postlaunch_sc_xarray_data, esa_unit_conversion_table + ) + + assert len(swapi_product) == 0 diff --git a/imap_processing/tests/ialirt/unit/test_process_swe.py b/imap_processing/tests/ialirt/unit/test_process_swe.py index ad8c136a4f..a3302966c2 100644 --- a/imap_processing/tests/ialirt/unit/test_process_swe.py +++ b/imap_processing/tests/ialirt/unit/test_process_swe.py @@ -168,6 +168,7 @@ def test_process_spacecraft_packet( np.arange(462466219, 462466219 + n, dtype=np.uint32), ) sc_xarray_data["swe_seq"] = ("epoch", np.arange(n) % 60) + sc_xarray_data["swe_nom_flag"] = xr.ones_like(sc_xarray_data["swe_nom_flag"]) in_flight_cal_file = ( imap_module_directory @@ -176,7 +177,7 @@ def test_process_spacecraft_packet( swe_product = process_swe(sc_xarray_data, [in_flight_cal_file]) - assert len(swe_product[0].keys()) == 6 + assert len(swe_product[0].keys()) == 8 def test_get_energy(): @@ -323,19 +324,7 @@ def test_normalize_counts(): dtype=np.uint8, ) - latest_cal = pd.Series( - [2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0], - index=[ - "cem1", - "cem2", - "cem3", - "cem4", - "cem5", - "cem6", - "cem7", - ], # Simulating real data structure - dtype=np.float64, - ) + latest_cal = np.array([2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0]) expected = np.zeros((2, 7, 3), dtype=np.float64) for i in range(2): diff --git a/imap_processing/tests/idex/conftest.py b/imap_processing/tests/idex/conftest.py index 86a199e30b..add6dd9ad9 100644 --- a/imap_processing/tests/idex/conftest.py +++ b/imap_processing/tests/idex/conftest.py @@ -13,14 +13,14 @@ TEST_DATA_PATH = imap_module_directory / "tests" / "idex" / "test_data" TEST_L0_FILE_SCI = TEST_DATA_PATH / "imap_idex_l0_raw_20231218_v001.pkts" -TEST_L0_FILE_EVT = TEST_DATA_PATH / "imap_idex_l0_raw_20250108_v001.pkts" # 1418 +TEST_L0_FILE_MSG = TEST_DATA_PATH / "imap_idex_l0_raw_20250108_v001.pkts" # 1418 TEST_L0_FILE_CATLST = TEST_DATA_PATH / "imap_idex_l0_raw_20241206_v001.pkts" # 1419 L1A_EXAMPLE_FILE = TEST_DATA_PATH / "idex_l1a_validation_file.h5" -L1B_EXAMPLE_FILE = TEST_DATA_PATH / "idex_l1b_validation_file.h5" +L1B_EXAMPLE_FILE = TEST_DATA_PATH / "imap_idex_l1b_sci_20231218_v004.h5" L2A_CDF = TEST_DATA_PATH / "imap_idex_l2a_sci-1week_20251017_v001.cdf" -L1B_EVT_CDF = TEST_DATA_PATH / "imap_idex_l1b_evt_20250108_v001.cdf" +L1B_MSG_CDF = TEST_DATA_PATH / "imap_idex_l1b_msg_20250108_v001.cdf" pytestmark = pytest.mark.external_test_data @@ -50,15 +50,27 @@ def decom_test_data_catlst() -> xr.Dataset: @pytest.fixture -def decom_test_data_evt() -> xr.Dataset: - """List of ``xarray`` datasets containing the raw and derived event log data. +def decom_test_data_msg() -> xr.Dataset: + """``xarray`` dataset containing the raw event message data. Returns ------- - dataset : list[xarray.Dataset] - A list of ``xarray`` datasets containing the event log datasets. + dataset : xarray.Dataset + ``xarray`` dataset containing the event log data. + """ + return PacketParser(TEST_L0_FILE_MSG).data[0] + + +@pytest.fixture +def test_l1b_msg(decom_test_data_msg) -> xr.Dataset: + """``xarray`` dataset containing the l1b msg data. + + Returns + ------- + dataset : xarray.Dataset + ``xarray`` dataset containing the event log data. """ - return PacketParser(TEST_L0_FILE_EVT).data + return idex_l1b(decom_test_data_msg, "msg") @pytest.fixture @@ -112,7 +124,7 @@ def l1b_dataset(mock_get_spice_data, decom_test_data_sci: xr.Dataset) -> xr.Data """ mock_get_spice_data.side_effect = get_spice_data_side_effect_func - dataset = idex_l1b(decom_test_data_sci) + dataset = idex_l1b(decom_test_data_sci, "sci-1week") return dataset @@ -202,5 +214,5 @@ def ancillary_files(): "l2a-calibration-curve-yield-params": path / "imap_idex_l2a-calibration-curve-yield-params_20250101_v001.csv", "l2a-calibration-curve-t-rise": path - / "imap_idex_l2a-calibration-curve-t-rise_20250101_v001.csv", + / "imap_idex_l2a-calibration-curve-t-rise_20250101_v002.csv", } diff --git a/imap_processing/tests/idex/test_data/idex_event_messages.csv b/imap_processing/tests/idex/test_data/idex_event_messages.csv new file mode 100644 index 0000000000..07e30e1246 --- /dev/null +++ b/imap_processing/tests/idex/test_data/idex_event_messages.csv @@ -0,0 +1,29 @@ +timestamp,message +2025-01-08 20:40:25.222800 UTC,"MEM FLASH UErr FOUND, PARAM=0x000000fe" +2025-01-08 20:40:51.222740 UTC,"UPK oper fsw says hello, version=02.00.0000" +2025-01-08 20:40:56.222700 UTC,"SEQ success (len=0x0580, opCodeLCDictionary(dualcmd))" +2025-01-08 20:40:57.222700 UTC,"SEQ success (len=0x0580, opCodeLCDictionary(rawwrt))" +2025-01-08 20:41:00.222680 UTC,"SEQ engine has changed state, eng=seqEngineDictionary(0x00) was=seqEngineStateDictionary(ACTIV) is=seqEngineStateDictionary(IDLE) 0x00" +2025-01-08 20:48:39.220040 UTC,AUT hvps state changed to hvStateDictionary(STANDBY) +2025-01-08 20:50:27.219540 UTC,AUT hvps state changed to hvStateDictionary(ACTIVE) +2025-01-08 20:56:32.218180 UTC,"SEQ success (len=0x0580, opCodeLCDictionary(noop))" +2025-01-08 20:56:33.218160 UTC,"SEQ engine has changed state, eng=seqEngineDictionary(0x00) was=seqEngineStateDictionary(ACTIV) is=seqEngineStateDictionary(IDLE) 0x00" +2025-01-08 20:58:15.217920 UTC,SCI state change: sciState16Dictionary(IDLE) ==> sciState16Dictionary(ACQSETUP) +2025-01-08 20:58:20.217900 UTC,SCI state change: sciState16Dictionary(ACQSETUP) ==> sciState16Dictionary(ACQ) +2025-01-08 20:59:15.217800 UTC,SCI state change: sciState16Dictionary(ACQ) ==> sciState16Dictionary(CHILL) +2025-01-08 20:59:20.217800 UTC,SCI state change: sciState16Dictionary(CHILL) ==> sciState16Dictionary(ACQCLEANUP) +2025-01-08 20:59:21.217780 UTC,"MEM cleanup found sci data, blocks empty=0x0000, blocks w/data=0x0001" +2025-01-08 20:59:26.217780 UTC,SCI science activity completed: sciState16Dictionary(ACQ) +2025-01-08 20:59:27.217760 UTC,SCI state change: sciState16Dictionary(ACQCLEANUP) ==> sciState16Dictionary(IDLE) +2025-01-08 21:00:12.217700 UTC,"SEQ success (len=0x0580, opCodeLCDictionary(haltstim))" +2025-01-08 21:00:14.217680 UTC,"SEQ success (len=0x0580, opCodeLCDictionary(haltsci))" +2025-01-08 21:00:15.217680 UTC,"SEQ engine has changed state, eng=seqEngineDictionary(0x00) was=seqEngineStateDictionary(ACTIV) is=seqEngineStateDictionary(IDLE) 0x00" +2025-01-08 21:02:48.217480 UTC,AUT hvps state changed to hvStateDictionary(STANDBY) +2025-01-08 21:04:42.217340 UTC,AUT hvps state changed to hvStateDictionary(OFF) +2025-01-08 21:05:30.217280 UTC,"SEQ success (len=0x0580, opCodeLCDictionary(dualcmd))" +2025-01-08 21:05:33.217280 UTC,"SEQ success (len=0x0580, opCodeLCDictionary(rawwrt))" +2025-01-08 21:05:36.217280 UTC,"SEQ engine has changed state, eng=seqEngineDictionary(0x00) was=seqEngineStateDictionary(ACTIV) is=seqEngineStateDictionary(IDLE) 0x00" +2025-01-08 21:06:36.217180 UTC,"SEQ success (len=0x0580, opCodeLCDictionary(dshtr))" +2025-01-08 21:06:38.217180 UTC,"SEQ success (len=0x0580, opCodeLCDictionary(dualcmd))" +2025-01-08 21:06:39.217180 UTC,"SEQ success (len=0x0580, opCodeLCDictionary(rawwrt))" +2025-01-08 21:06:42.217180 UTC,"SEQ engine has changed state, eng=seqEngineDictionary(0x00) was=seqEngineStateDictionary(ACTIV) is=seqEngineStateDictionary(IDLE) 0x00" diff --git a/imap_processing/tests/idex/test_idex_l0.py b/imap_processing/tests/idex/test_idex_l0.py index 736c0565df..425168c74c 100644 --- a/imap_processing/tests/idex/test_idex_l0.py +++ b/imap_processing/tests/idex/test_idex_l0.py @@ -14,7 +14,7 @@ def test_idex_decom_length(decom_test_data_sci: xr.Dataset): decom_test_data_sci : xarray.Dataset The dataset to test with """ - assert len(decom_test_data_sci) == 110 + assert len(decom_test_data_sci) == 109 def test_idex_decom_event_num(decom_test_data_sci: xr.Dataset): @@ -61,13 +61,12 @@ def test_catlst_event_num(decom_test_data_catlst: list[xr.Dataset]): assert len(ds["epoch"]) == 1 -def test_evt_event_num(decom_test_data_evt: list[xr.Dataset]): +def test_msg_event_num(decom_test_data_msg: xr.Dataset): """Verify that a sample of the data is correct. Parameters ---------- - decom_test_data_evt : list[xarray.Dataset] - The raw and derived (l1a and l1b) datasets to test with. + decom_test_data_msg : xarray.Dataset + Event message data. """ - for ds in decom_test_data_evt: - assert len(ds["epoch"]) == 28 + assert len(decom_test_data_msg["epoch"]) == 28 diff --git a/imap_processing/tests/idex/test_idex_l1a.py b/imap_processing/tests/idex/test_idex_l1a.py index 6dab365652..1c96499537 100644 --- a/imap_processing/tests/idex/test_idex_l1a.py +++ b/imap_processing/tests/idex/test_idex_l1a.py @@ -4,16 +4,20 @@ from unittest import mock import numpy as np +import pandas as pd import pytest import xarray as xr from cdflib.xarray.xarray_to_cdf import ISTPError -from imap_processing import decom, imap_module_directory +from imap_processing import imap_module_directory from imap_processing.cdf.utils import load_cdf, write_cdf from imap_processing.idex.decode import _decode_sub_frame, read_bits, rice_decode from imap_processing.idex.idex_l1a import PacketParser from imap_processing.spice.time import met_to_ttj2000ns from imap_processing.tests.idex.conftest import TEST_L0_FILE_SCI +from imap_processing.utils import packet_generator + +TEST_DATA_DIR = f"{imap_module_directory}/tests/idex/test_data" def test_idex_cdf_file(decom_test_data_sci: xr.Dataset): @@ -97,7 +101,7 @@ def test_incomplete_event(caplog): f"idex_science_packet_definition.xml" ) caplog.at_level("WARNING") - packets = decom.decom_packets(TEST_L0_FILE_SCI, xml) + packets = list(packet_generator(TEST_L0_FILE_SCI, xml)) packets = packets[0:1] + packets[2:] with mock.patch( "imap_processing.idex.idex_l1a.decom_packets", @@ -155,11 +159,22 @@ def test_validate_l1a_idex_data_variables( "Ion Grid": "Ion_Grid", "Time (high sampling)": "time_high_sample_rate", "Time (low sampling)": "time_low_sample_rate", + "idx__txhdrfswaidcopy": "aid", } # The Engineering data is converting to UTC, and the SDC is converting to J2000, # for 'epoch' and 'Timestamp' so this test is using the raw time value 'SCHOARSE' to # validate time - arrays_to_skip = ["Timestamp", "Epoch", "event"] + # TODO remove the low and high time from this list after the IDEX team produces a + # new l1a h5 file. + arrays_to_skip = [ + "Timestamp", + "Epoch", + "event", + "Time (high sampling)", + "Time (low sampling)", + "IDX__SCI0AID", # This is dropped because it is invalid + "IDX__TXHDRFSWAIDCOPY", # this is renamed to aid + ] # loop through all keys from the l1a example dict for var in l1a_example_data.variables: @@ -179,10 +194,9 @@ def test_compressed_packet(): """ Test compressed data decompression against known non-compressed data. """ - test_data_dir = f"{imap_module_directory}/tests/idex/test_data" - compressed = Path(f"{test_data_dir}/compressed_2023_102_14_24_55.pkts") - non_compressed = Path(f"{test_data_dir}/non_compressed_2023_102_14_22_26.pkts") + compressed = Path(f"{TEST_DATA_DIR}/compressed_2023_102_14_24_55.pkts") + non_compressed = Path(f"{TEST_DATA_DIR}/non_compressed_2023_102_14_22_26.pkts") decompressed = PacketParser(compressed).data[0] expected = PacketParser(non_compressed).data[0] @@ -340,25 +354,30 @@ def test_catlst_dataset(decom_test_data_catlst: list[xr.Dataset]): assert filename_l1b.name == "imap_idex_l1b_catlst_20241206_v999.cdf" -def test_evt_dataset(decom_test_data_evt: list[xr.Dataset]): +def test_msg_dataset(decom_test_data_msg: xr.Dataset): """Verify that the dataset contains what we expect and can be written to a cdf. Parameters ---------- - decom_test_data_evt : list[xarray.Dataset] - The raw and derived (l1a and l1b) datasets to test with. + decom_test_data_msg : xarray.Dataset + The raw l1a dataset to test with. """ - for ds in decom_test_data_evt: - assert "shcoarse" in ds - assert "shfine" in ds - # Assert epoch is calculated using fine grained clock ticks - expected_epoch = met_to_ttj2000ns(ds["shcoarse"] + ds["shfine"] * 20e-6) - np.testing.assert_array_equal(ds.epoch, expected_epoch) - assert decom_test_data_evt[0]["elid_evtpkt"][9] == 192 - assert decom_test_data_evt[1]["elid_evtpkt"][9] == "SCI_STE" + assert "elsec_evtpkt" in decom_test_data_msg + assert "elssec_evtpkt" in decom_test_data_msg + # Assert epoch is calculated using fine grained clock ticks + expected_epoch = met_to_ttj2000ns( + decom_test_data_msg["elsec_evtpkt"] + + decom_test_data_msg["elssec_evtpkt"] * 20e-6 + ) + np.testing.assert_array_equal(decom_test_data_msg.epoch, expected_epoch) # Assert that the dataset can be written to a CDF file - filename_l1a = write_cdf(decom_test_data_evt[0]) - assert filename_l1a.name == "imap_idex_l1a_evt_20250108_v999.cdf" + filename_l1a = write_cdf(decom_test_data_msg) + assert filename_l1a.name == "imap_idex_l1a_msg_20100101_v999.cdf" + + # Validate the messages with the IDEX team example data + example_data = pd.read_csv( + f"{TEST_DATA_DIR}/idex_event_messages.csv", skiprows=1, header=None + ) - filename_l1b = write_cdf(decom_test_data_evt[1]) - assert filename_l1b.name == "imap_idex_l1b_evt_20250108_v999.cdf" + messages = example_data.iloc[:, 1].tolist() + np.testing.assert_array_equal(decom_test_data_msg["messages"].data, messages) diff --git a/imap_processing/tests/idex/test_idex_l1b.py b/imap_processing/tests/idex/test_idex_l1b.py index 3cf7a76e22..fa44983803 100644 --- a/imap_processing/tests/idex/test_idex_l1b.py +++ b/imap_processing/tests/idex/test_idex_l1b.py @@ -10,11 +10,19 @@ from imap_processing import imap_module_directory from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes from imap_processing.cdf.utils import write_cdf +from imap_processing.idex.idex_constants import DT_BLOCK from imap_processing.idex.idex_l1b import ( + TRIGGER_LABELS, + EventMessage, + TriggerOrigin, + get_event_dead_time, get_spice_data, get_trigger_mode_and_level, + get_trigger_origin, + idex_l1b, unpack_instrument_settings, ) +from imap_processing.idex.idex_utils import get_idex_attrs from imap_processing.tests.idex import conftest @@ -149,49 +157,79 @@ def test_get_trigger_settings_success(decom_test_data_sci): # correct when the modes and levels vary from event to event decom_test_data_sci["idx__txhdrmgtrigmode"][0] = 1 decom_test_data_sci["idx__txhdrhgtrigmode"][0] = 0 - + idex_attrs = get_idex_attrs("l1b") n_epochs = len(decom_test_data_sci["epoch"]) - trigger_settings = get_trigger_mode_and_level(decom_test_data_sci) + trigger_settings = get_trigger_mode_and_level(decom_test_data_sci, idex_attrs) + + expected_modes_lg = np.full(n_epochs, None) + expected_modes_hg = expected_modes_lg.copy() + expected_modes_hg[1:] = "HGThreshold" + expected_modes_mg = np.full(n_epochs, None) + expected_modes_mg[0] = "MGThreshold" + expected_levels_lg = np.full(n_epochs, np.nan) + expected_levels_hg = expected_levels_lg.copy() + expected_levels_hg[1:] = 0.16762 + expected_levels_mg = expected_levels_lg.copy() + expected_levels_mg[0] = 1023.0 * 1.13e-2 + + var_names = ["trigger_mode_lg", "trigger_mode_mg", "trigger_mode_hg"] + expected_modes = [expected_modes_lg, expected_modes_mg, expected_modes_hg] + for expected_mode, mode_name in zip(expected_modes, var_names, strict=False): + ( + np.testing.assert_array_equal( + trigger_settings[mode_name].data, + expected_mode, + err_msg=f"The dict entry {mode_name} values did not match the" + f" expected values: {expected_mode}. Found:" + f" {trigger_settings[mode_name].data}", + ), + ) + var_names = ["trigger_level_lg", "trigger_level_mg", "trigger_level_hg"] + expected_levels = [expected_levels_lg, expected_levels_mg, expected_levels_hg] + for expected_level, level_name in zip(expected_levels, var_names, strict=False): + ( + np.testing.assert_array_equal( + trigger_settings[level_name].data, + expected_level, + err_msg=f"The dic entry {level_name} values did not match the" + f" expected values: {expected_level}. Found: " + f"{trigger_settings[level_name].data}", + ), + ) - expected_modes = np.full(n_epochs, "HGThreshold") - expected_modes[0] = "MGThreshold" - expected_levels = np.full(n_epochs, 0.16762) - expected_levels[0] = 1023.0 * 1.13e-2 - assert (trigger_settings["triggermode"].data == expected_modes).all(), ( - f"The dict entry 'triggermode' values did not match the expected values: " - f"{expected_modes}. Found: {trigger_settings['triggermode'].data}" - ) +def test_trigger_origin(): + """Check that the correct labels are produced for trigger origin values""" - assert (trigger_settings["triggerlevel"].data == expected_levels).all(), ( - f"The dict entry 'triggerlevel' values did not match the expected values: " - f"{expected_levels}. Found: {trigger_settings['triggerlevel'].data}" + trigger_bits = np.full(10, 6) + origins = get_trigger_origin(trigger_bits, get_idex_attrs("l1b")) + # Bits 1 and 2 should be set for all events + expected_origin = np.full( + 10, + ", ".join([TRIGGER_LABELS[TriggerOrigin(1)], TRIGGER_LABELS[TriggerOrigin(2)]]), + ) + np.testing.assert_array_equal( + origins["trigger_origin"], + expected_origin, + err_msg=f"The trigger origin values did not match the expected values: " + f"{expected_origin}. Found: {origins}", ) -def test_get_trigger_settings_failure(decom_test_data_sci): - """ - Check that an error is thrown when there are more than one valid trigger for an - event +def test_invalid_trigger_origin(): + """Check the labels when there are invalid trigger origin values""" - Parameters - ---------- - decom_test_data_sci : xarray.Dataset - L1a dataset - """ - decom_test_data_sci["idx__txhdrhgtrigmode"][0] = 1 - decom_test_data_sci["idx__txhdrmgtrigmode"][0] = 2 - - error_ms = ( - "Only one channel can trigger a dust event. Please make sure there is " - "only one valid trigger value per event. This caused Merge Error: " - "conflicting values for variable 'trigger_mode' on objects to be " - "combined. You can skip this check by specifying compat='override'." + trigger_bits = np.full(10, 64) # invalid trigger origin values + origins = get_trigger_origin(trigger_bits, get_idex_attrs("l1b")) + # Bits 1 and 2 should be set for all events + expected_origin = np.full(10, "Unknown trigger origin") + np.testing.assert_array_equal( + origins["trigger_origin"], + expected_origin, + err_msg=f"The trigger origin values did not match the expected values:" + f"{expected_origin}. Found: {origins}", ) - with pytest.raises(ValueError, match=error_ms): - get_trigger_mode_and_level(decom_test_data_sci) - @pytest.mark.usefixtures("use_fake_spin_data_for_time") def test_get_spice_data( @@ -260,6 +298,10 @@ def test_validate_l1b_idex_data_variables( "voltage_3V3_op_ref": "voltage_3p3_op_ref", "voltage_3V3_ref": "voltage_3p3_ref", "voltage_pos3V3_bus": "voltage_pos3p3v_bus", + "HGTriggerLevel": "trigger_level_hg", + "MGTriggerLevel": "trigger_level_mg", + "LGTriggerLevel": "trigger_level_lg", + "TriggerOrigin": "trigger_origin", } # The Engineering data is converting to UTC, and the SDC is converting to J2000, @@ -268,7 +310,7 @@ def test_validate_l1b_idex_data_variables( # SPICE data is mocked. arrays_to_skip = [ "Timestamp", - "Epoch", + "epoch", "Pitch", "Roll", "Yaw", @@ -280,29 +322,127 @@ def test_validate_l1b_idex_data_variables( "VelocityY", "VelocityZ", "RightAscension", + "FIFODelay", + "FIFODelayMicroseconds", + "FIFODelay_H", + "FIFODelay_L", + "FIFODelay_M", + "HSPosttriggerBlocks", ] + # assert that "aid" is in l1b + assert "aid" in l1b_dataset, "The array 'aid' is missing from the l1b dataset." + # select only the first n events + l1b_example_data = l1b_example_data.isel( + event=np.arange(l1b_dataset.sizes["epoch"]) + ) # Compare each corresponding variable for var in l1b_example_data.data_vars: if var not in arrays_to_skip: # Get the corresponding array name cdf_var = match_variables.get(var, var.lower().replace(".", "p")) - warning = ( f"The array '{cdf_var}' does not equal the expected example array " + f"'{var}' produced by the IDEX team" ) - f"'{var}' produced by the IDEX team" - + # TODO remove this block once the IDEX team fixes the l1b validation file. + # They included a lot of extra variables in the current file. + try: + l1b_dataset[cdf_var] + except KeyError: + continue if l1b_dataset[cdf_var].dtype == object: - assert (l1b_dataset[cdf_var].data == l1b_example_data[var]).all(), ( - warning - ) + assert ( + l1b_dataset[cdf_var].data == np.squeeze(l1b_example_data[var]) + ).all(), warning else: - ( - np.testing.assert_array_almost_equal( - l1b_dataset[cdf_var].data, - l1b_example_data[var], - decimal=4, - ), - warning, + np.testing.assert_array_almost_equal( + l1b_dataset[cdf_var].data, + np.squeeze(l1b_example_data[var]), + decimal=4, + err_msg=warning, ) + + +def test_l1b_msg_processing(decom_test_data_msg: xr.Dataset): + """Verify that the MSG data is being processed correctly in the l1b processing. + + Parameters + ---------- + decom_test_data_msg : xr.Dataset + A dataset containing the MSG data produced by the l1a processing. + """ + msg_ds = decom_test_data_msg.copy() + # Set 2 consecutive events to have pulser on and pulser off + msg_ds.messages[2] = EventMessage.PULSER_ON.value + msg_ds.messages[3] = EventMessage.PULSER_OFF.value + # Set 2 to have a non-consecutive pulser on and pulser off to check that + # non-consecutive events are treated as non-valid pulser on and off events + msg_ds.messages[20] = EventMessage.PULSER_ON.value + msg_ds.messages[22] = EventMessage.PULSER_OFF.value + # Process the MSG data with the l1b function + test_l1b_msg = idex_l1b(msg_ds, "msg") + expected_vars = [ + "epoch", + "pulser_on", + "science_on", + ] + for var in expected_vars: + assert var in test_l1b_msg, ( + f"The variable '{var}' is missing from the MSG dataset." + ) + + # Check that the pulser_on variable is correct + expected_pulser_on = np.ones_like(test_l1b_msg["pulser_on"]) * 255 + # The pulser_on variable should be 1 for the 1st and 0 for the 2nd event, and + # 255 for all other events + expected_pulser_on[0] = 1 + expected_pulser_on[1] = 0 + # Check that the science_on variable is correct + expected_science_on = np.ones_like(test_l1b_msg["pulser_on"]) * 255 + # The science_on variable should be 1 for the 3rd event and 0 for the 4th event + expected_science_on[2] = 1 + expected_science_on[3] = 0 + np.testing.assert_array_equal(test_l1b_msg["pulser_on"].data, expected_pulser_on) + np.testing.assert_array_equal(test_l1b_msg["science_on"].data, expected_science_on) + + +def test_no_valid_messages(decom_test_data_msg: xr.Dataset): + """Verify that if there are no valid pulser and science events then no dataset is + returned. + + Parameters + ---------- + decom_test_data_msg : xr.Dataset + A dataset containing the MSG data produced by the l1a processing. + """ + msg_ds = decom_test_data_msg.copy() + # Set all messages to a value that is not a valid pulser on or off event + msg_ds.messages[:] = "Not a science or pulser event" + result = idex_l1b(msg_ds, "msg") + assert result is None + + +def test_get_event_dead_time(): + """Check that dead time is computed correctly from txhdrblocks.""" + base = np.array([0, 1, 3, 63, 0, 63], dtype=np.uint32) + shift = np.array([0, 1, 2, 15, 15, 0], dtype=np.uint32) + txhdrblocks = (base << 24) | (shift << 20) + + l1a_dataset = xr.Dataset( + {"idx__txhdrblocks": xr.DataArray(txhdrblocks, dims="epoch")} + ) + dead_time = get_event_dead_time(l1a_dataset, get_idex_attrs("l1b"))["dead_time"] + + expected_dead_time = ( + base.astype(np.float64) * (2.0 ** shift.astype(np.float64)) * DT_BLOCK + ) + + np.testing.assert_array_equal( + dead_time.data, + expected_dead_time, + err_msg=( + "The dead_time values did not match the expected values: " + f"{expected_dead_time}. Found: {dead_time.data}" + ), + ) diff --git a/imap_processing/tests/idex/test_idex_l2a.py b/imap_processing/tests/idex/test_idex_l2a.py index 5b4517de83..09a7abc2a0 100644 --- a/imap_processing/tests/idex/test_idex_l2a.py +++ b/imap_processing/tests/idex/test_idex_l2a.py @@ -22,6 +22,9 @@ estimate_dust_mass, fit_impact, idex_l2a, + invert_rise_time_to_velocity, + load_calibration_files, + log_smooth_powerlaw, remove_signal_noise, sine_fit, time_to_mass, @@ -49,7 +52,7 @@ def l2a_dataset( "imap_processing.idex.idex_l1b.get_spice_data", return_value={"spin_phase": spin_phase_angles}, ): - dataset = idex_l2a(idex_l1b(decom_test_data_sci), ancillary_files) + dataset = idex_l2a(idex_l1b(decom_test_data_sci, "sci-1week"), ancillary_files) return dataset @@ -66,6 +69,13 @@ def mock_microphonics_noise(time: np.ndarray) -> np.ndarray: return combined_sig +def _write_calibration_csv(path, values): + """Write a one-row calibration CSV with the ancillary-file structure.""" + header = "A,a1,a2,a3,v_b,v_c,k,sigma,delta\n" + row = ",".join(str(value) for value in values) + "\n" + path.write_text(header + row) + + @pytest.mark.external_test_data def test_l2a_logical_source_and_cdf(l2a_dataset: xr.Dataset): """Tests that the ``idex_l2a`` function generates datasets @@ -126,6 +136,24 @@ def test_l2a_logical_source_and_cdf(l2a_dataset: xr.Dataset): f"Variable {var} is missing the DICT_KEY attribute for SPASE metadata." ) + # TODO: remove this NAN block when fitting logic is applied + expected_nan_vars = [ + "ion_grid_dust_mass_estimate", + "ion_grid_velocity_estimate", + "tof_peak_area_under_fit", + "tof_peak_chi_square", + "tof_peak_fit_parameters", + "tof_peak_kappa", + "tof_peak_reduced_chi_square", + "tof_snr", + "mass", + "mass_scale", + ] + for var in expected_nan_vars: + assert np.isnan(l2a_dataset[var].data).all(), ( + f"Variable {var} should be fully NaN for the temporary L2A patch." + ) + def test_time_to_mass_zero_lag(): """ @@ -275,19 +303,121 @@ def test_analyze_peaks_warning(caplog): np.testing.assert_array_equal(area_under_curve, np.zeros(area_under_curve.shape)) +def test_load_calibration_files_returns_expected_t_rise_params(tmp_path): + """Tests that t-rise ancillary values are loaded into t_rise_params.""" + expected_t_rise_params = np.array([1.27, -0.2, -2.1, -0.37, 5.3, 13.3, 13.3, 0.28]) + yield_values = np.array([0.06, 2.8, 5.9, 4.1, 13.0, 22.7, 8.2, 0.40, 1.47]) + + t_rise_path = tmp_path / "t_rise.csv" + yield_path = tmp_path / "yield.csv" + _write_calibration_csv(t_rise_path, expected_t_rise_params) + _write_calibration_csv(yield_path, yield_values) + + t_rise_params, _yield_params = load_calibration_files( + { + "l2a-calibration-curve-t-rise": t_rise_path, + "l2a-calibration-curve-yield-params": yield_path, + } + ) + + np.testing.assert_allclose(t_rise_params, expected_t_rise_params) + + +def test_load_calibration_files_returns_expected_yield_params(tmp_path): + """Tests that yield ancillary values are loaded into yield_params.""" + t_rise_values = np.array([1.27, -0.2, -2.1, -0.37, 5.3, 13.3, 13.3, 0.28, 1.33]) + expected_yield_params = np.array([0.06, 2.8, 5.9, 4.1, 13.0, 22.7, 8.2, 0.40]) + + t_rise_path = tmp_path / "t_rise.csv" + yield_path = tmp_path / "yield.csv" + _write_calibration_csv(t_rise_path, t_rise_values) + _write_calibration_csv(yield_path, expected_yield_params) + + _t_rise_params, yield_params = load_calibration_files( + { + "l2a-calibration-curve-t-rise": t_rise_path, + "l2a-calibration-curve-yield-params": yield_path, + } + ) + + np.testing.assert_allclose(yield_params, expected_yield_params) + + +def test_log_smooth_powerlaw_yield_curve_at_10_km_s(): + """Tests that the yield calibration returns the expected value at 10 km/s.""" + yield_params = np.array([0.06, 2.8, 5.9, 4.1, 13.0, 22.7, 8.2, 0.40]) + + log_yield = log_smooth_powerlaw(np.log10(10.0), yield_params[0], yield_params[1:]) + yield_value = 10**log_yield + + assert yield_value == pytest.approx(755.0, rel=1e-3) + + +def test_invert_rise_time_to_velocity_at_10_km_s(): + """Tests that the rise-time calibration can be inverted back to 10 km/s.""" + t_rise_params = np.array([1.27, -0.2, -2.1, -0.37, 5.3, 13.3, 13.3, 0.28]) + expected_velocity = 10.0 + t_rise = 10 ** log_smooth_powerlaw( + np.log10(expected_velocity), float(t_rise_params[0]), t_rise_params[1:] + ) + + velocity_estimate = invert_rise_time_to_velocity(t_rise, t_rise_params) + + assert velocity_estimate == pytest.approx(expected_velocity, rel=1e-12) + + +def test_invert_rise_time_to_velocity_invalid_t_rise_returns_nan(): + """Tests that non-positive or non-finite rise times return NaN.""" + t_rise_params = np.array([1.27, -0.2, -2.1, -0.37, 5.3, 13.3, 13.3, 0.28]) + + assert np.isnan(invert_rise_time_to_velocity(np.nan, t_rise_params)) + assert np.isnan(invert_rise_time_to_velocity(0.0, t_rise_params)) + + +def test_calculate_velocity_and_mass_at_10_km_s(): + """Tests mass estimation using a mocked 10 km/s velocity solution.""" + t_rise_params = np.array([1.27, -0.2, -2.1, -0.37, 5.3, 13.3, 13.3, 0.28]) + yield_params = np.array([0.06, 2.8, 5.9, 4.1, 13.0, 22.7, 8.2, 0.40]) + sig_amp_pc = 10.0 + + # This test intentionally bypasses the t_rise -> velocity inversion. + # The t_rise calibration path is currently under review and will be + # covered by a dedicated follow-up test once that behavior is finalized. + mocked_root = mock.Mock() + mocked_root.root = 1.0 # 10**1.0 == 10 km/s + + with mock.patch( + "imap_processing.idex.idex_l2a.root_scalar", return_value=mocked_root + ): + velocity_estimate, mass_estimate = calculate_velocity_and_mass( + sig_amp_pc, 2.0, t_rise_params, yield_params + ) + + expected_yield = 755.0090524738858 + expected_mass_kg = sig_amp_pc * 1e-12 / expected_yield + + assert velocity_estimate == pytest.approx(10.0, rel=1e-12) + assert mass_estimate == pytest.approx(expected_mass_kg, rel=1e-12) + + @pytest.mark.external_test_data def test_velocity_and_mass_estimate(ancillary_files): """Tests that the velocity and mass estimate function.""" # Load calibration coefficients from ancillary files t_rise_params = pd.read_csv( - ancillary_files["l2a-calibration-curve-yield-params"], skiprows=1, header=None + ancillary_files["l2a-calibration-curve-t-rise"], skiprows=1, header=None ).values.flatten()[:8] yield_params = pd.read_csv( - ancillary_files["l2a-calibration-curve-t-rise"], skiprows=1, header=None + ancillary_files["l2a-calibration-curve-yield-params"], skiprows=1, header=None ).values.flatten()[:8] - estimates = calculate_velocity_and_mass(10, 2, t_rise_params, yield_params) + expected_velocity = 5.0 + t_rise = 10 ** log_smooth_powerlaw( + np.log10(expected_velocity), float(t_rise_params[0]), t_rise_params[1:] + ) + estimates = calculate_velocity_and_mass(10, t_rise, t_rise_params, yield_params) assert len(estimates) == 2 assert not np.any(np.isnan(estimates)) + assert estimates[0] == pytest.approx(expected_velocity, rel=1e-12) def test_analyze_peaks_perfect_fits(): @@ -366,6 +496,146 @@ def test_estimate_dust_mass_no_noise_removal(): assert np.allclose(result, signal) +def test_estimate_dust_mass_logs_baseline_warning(caplog): + """ + Test that estimate_dust_mass() logs a warning if no baseline is found. + """ + time = xr.DataArray(np.linspace(-60, 60, 16)) + signal = xr.DataArray(np.linspace(0, 1, 16)) + original_any = np.any + + def fake_any(arr): + fake_any.calls += 1 + if fake_any.calls == 1: + return False + return original_any(arr) + + fake_any.calls = 0 + + with ( + mock.patch("imap_processing.idex.idex_l2a.np.any", side_effect=fake_any), + mock.patch( + "imap_processing.idex.idex_l2a.curve_fit", + return_value=(np.array([0.0, 0.0, 1.0, 0.371, 37.1]), None), + ), + caplog.at_level("WARNING"), + ): + estimate_dust_mass(time, signal) + + assert any( + "Unable to find baseline noise" in message + for message in caplog.text.splitlines() + ) + + +def test_estimate_dust_mass_remove_noise_logs_debug(caplog): + """ + Test that estimate_dust_mass() logs that remove_noise is ignored. + """ + time = xr.DataArray(np.linspace(-60, 60, 64)) + signal = xr.DataArray( + fit_impact( + time.data, + time_of_impact=0.0, + constant_offset=1.0, + amplitude=10.0, + rise_time=0.371, + discharge_time=0.371, + ) + ) + + with caplog.at_level("DEBUG"): + estimate_dust_mass(time, signal, remove_noise=True) + + assert any( + "remove_noise is ignored for this fit path" in message + for message in caplog.text.splitlines() + ) + + +def test_estimate_dust_mass_nonfinite_signal_fallbacks(): + """ + Test fallback handling when the input signal is entirely non-finite. + """ + time = xr.DataArray(np.linspace(-60, 60, 16)) + signal = xr.DataArray(np.full(16, np.nan)) + + with mock.patch( + "imap_processing.idex.idex_l2a.curve_fit", + return_value=(np.array([0.0, 0.0, 1.0, 0.371, 37.1]), None), + ) as mocked_curve_fit: + estimate_dust_mass(time, signal) + + assert np.isnan(mocked_curve_fit.call_args.kwargs["p0"][2]) + + +def test_estimate_dust_mass_non_ion_grid_negative_amplitude_fallback(): + """ + Test the non-Ion_Grid negative-amplitude fallback path. + """ + time = xr.DataArray(np.linspace(-60, 60, 16)) + signal = xr.DataArray(np.full(16, -2.0)) + + with mock.patch( + "imap_processing.idex.idex_l2a.curve_fit", + return_value=(np.array([0.0, -2.0, -2.0, 0.371, 37.1]), None), + ) as mocked_curve_fit: + estimate_dust_mass(time, signal) + + assert mocked_curve_fit.call_args.kwargs["p0"][2] == -2.0 + + +def test_estimate_dust_mass_ion_grid_negative_amplitude_bounds(): + """ + Test that Ion Grid fits allow negative amplitudes. + """ + time = xr.DataArray(np.linspace(-60, 60, 64)) + signal = xr.DataArray( + fit_impact( + time.data, + time_of_impact=0.0, + constant_offset=0.0, + amplitude=-5.0, + rise_time=0.371, + discharge_time=0.371, + ) + ) + + with mock.patch( + "imap_processing.idex.idex_l2a.curve_fit", + return_value=(np.array([0.0, 0.0, -5.0, 0.371, 37.1]), None), + ) as mocked_curve_fit: + estimate_dust_mass(time, signal, waveform_name="Ion_Grid") + + bounds = mocked_curve_fit.call_args.kwargs["bounds"] + assert bounds[0][2] == -np.inf + assert bounds[1][2] < 0.0 + + +def test_estimate_dust_mass_curve_fit_failure_returns_nans(caplog): + """ + Test that estimate_dust_mass() returns NaNs if the fit fails. + """ + time = xr.DataArray(np.linspace(-60, 60, 16)) + signal = xr.DataArray(np.linspace(0, 1, 16)) + + with ( + mock.patch( + "imap_processing.idex.idex_l2a.curve_fit", + side_effect=RuntimeError("fit failed"), + ), + caplog.at_level("WARNING"), + ): + param, sig_amp, chisqr, redchi, result = estimate_dust_mass(time, signal) + + assert any("Failed to fit curve" in message for message in caplog.text.splitlines()) + assert np.all(np.isnan(param)) + assert np.isnan(sig_amp) + assert np.isnan(chisqr) + assert np.isnan(redchi) + assert np.all(np.isnan(result)) + + def test_lowpass_filter(): """ Tests that the lowpass filter is filtering out high frequency signals. diff --git a/imap_processing/tests/idex/test_idex_l2b.py b/imap_processing/tests/idex/test_idex_l2b.py index f672ac818f..cf3c5bc44c 100644 --- a/imap_processing/tests/idex/test_idex_l2b.py +++ b/imap_processing/tests/idex/test_idex_l2b.py @@ -1,13 +1,11 @@ """Tests the L2b processing for IDEX data""" -from unittest import mock - import numpy as np import pytest import xarray as xr from numpy.testing import assert_array_equal -from imap_processing.cdf.utils import load_cdf, write_cdf +from imap_processing.cdf.utils import write_cdf from imap_processing.idex.idex_constants import ( FG_TO_KG, IDEX_SPACING_DEG, @@ -23,14 +21,12 @@ compute_counts_by_charge_and_mass, compute_rates_by_charge_and_mass, get_science_acquisition_on_percentage, - get_science_acquisition_timestamps, idex_l2b, ) -from imap_processing.tests.idex.conftest import L1B_EVT_CDF @pytest.fixture -def l2b_and_l2c_datasets(l2a_dataset: xr.Dataset) -> list[xr.Dataset]: +def l2b_and_l2c_datasets(l2a_dataset: xr.Dataset, test_l1b_msg) -> list[xr.Dataset]: """Return a ``xarray`` dataset containing test data. Returns @@ -38,17 +34,16 @@ def l2b_and_l2c_datasets(l2a_dataset: xr.Dataset) -> list[xr.Dataset]: datasets : list[xr.Dataset] A list of ``xarray`` datasets containing the test data for L2B and L2C. """ - l1b_evt_dataset = load_cdf(L1B_EVT_CDF) - l1b_evt_dataset2 = ( - l1b_evt_dataset.copy() + l1b_msg_dataset2 = ( + test_l1b_msg.copy() ) # Add a second dataset with different epoch values for testing l2a_dataset2 = ( l2a_dataset.copy() ) # Add a second dataset with different epoch values for testing - l1b_evt_dataset2["epoch"] = l1b_evt_dataset2["epoch"] + NANOSECONDS_IN_DAY + l1b_msg_dataset2["epoch"] = l1b_msg_dataset2["epoch"] + NANOSECONDS_IN_DAY l2a_dataset2["epoch"] = l2a_dataset2["epoch"] + NANOSECONDS_IN_DAY datasets = idex_l2b( - [l2a_dataset, l2a_dataset2], [l1b_evt_dataset, l1b_evt_dataset2] + [l2a_dataset, l2a_dataset2], [test_l1b_msg.copy(), l1b_msg_dataset2] ) return datasets @@ -88,15 +83,17 @@ def test_l2c_attrs_and_vars( """ l2c_dataset = l2b_and_l2c_datasets[1] assert l2c_dataset.attrs["Logical_source"] == "imap_idex_l2c_rectangular-map-1mo" + # TODO: Uncomment when NAN block fixed # The total counts in the map should be equal to the number of dust events # in the l2a_dataset (*2 because the l2b fixture counts are doubled) - np.testing.assert_allclose( - l2c_dataset["counts_by_charge_map"].sum(), len(l2a_dataset.epoch) * 2 - ) - np.testing.assert_allclose( - l2c_dataset["counts_by_mass_map"].sum(), len(l2a_dataset.epoch) * 2 - ) + # np.testing.assert_allclose( + # l2c_dataset["counts_by_charge_map"].sum(), len(l2a_dataset.epoch) * 2 + # ) + # np.testing.assert_allclose( + # l2c_dataset["counts_by_mass_map"].sum(), len(l2a_dataset.epoch) * 2 + # ) assert l2c_dataset.sizes == { + "on_off_times": 4, "epoch": 2, "impact_charge": 10, "mass": 10, @@ -114,6 +111,18 @@ def test_l2c_attrs_and_vars( f"Variable {var} is missing the DICT_KEY attribute for SPASE metadata." ) + # TODO: This NAN check to be REMOVED in future + expected_nan_vars = [ + "counts_by_charge_map", + "counts_by_mass_map", + "rate_by_charge_map", + "rate_by_mass_map", + ] + for var in expected_nan_vars: + assert np.isnan(l2c_dataset[var].data).all(), ( + f"Variable {var} should be fully NaN for the temporary L2B/L2C patch." + ) + def test_l2b_cdf_variables(l2b_and_l2c_datasets: list[xr.Dataset]): """Tests that the ``idex_l2a`` function generates datasets @@ -141,6 +150,18 @@ def test_l2b_cdf_variables(l2b_and_l2c_datasets: list[xr.Dataset]): f"Variable {var} is missing the DICT_KEY attribute for SPASE metadata." ) + # TODO: This NAN check to be REMOVED in future + expected_nan_vars = [ + "counts_by_charge", + "counts_by_mass", + "rate_by_charge", + "rate_by_mass", + ] + for var in expected_nan_vars: + assert np.isnan(l2b_dataset[var].data).all(), ( + f"Variable {var} should be fully NaN for the temporary L2B patch." + ) + def test_bin_spin_phases(): """Tests that bin_spin_phases() produces expected results.""" @@ -176,42 +197,25 @@ def test_bin_spin_phases_warning(caplog): ) in caplog.text -def test_science_acquisition_times(decom_test_data_evt: list[xr.Dataset]): - """Tests that the expected science acquisition times and messages are present. - - Parameters - ---------- - decom_test_data_evt : list[xr.Dataset] - A ``xarray`` dataset containing the test data - """ - logs, times, vals = get_science_acquisition_timestamps(decom_test_data_evt[1]) - # For this example event message dataset we expect science acquisition events. - assert len(logs) == 2 - assert len(times) == 2 - assert len(vals) == 2 - # The first event message is the start of the science acquisition. - assert logs[0] == "SCI state change: ACQSETUP to ACQ" - # The second event message is the end of the science acquisition. - assert logs[1] == "SCI state change: ACQ to CHILL" - - # assert the values are correct - np.testing.assert_array_equal(vals, [1, 0]) - - -def test_get_science_acquisition_on_percentage(decom_test_data_evt: list[xr.Dataset]): +def test_get_science_acquisition_on_percentage(test_l1b_msg: xr.Dataset): """Test the function that calculates the percentage of uptime.""" - on_percentages = get_science_acquisition_on_percentage(decom_test_data_evt[1]) - # We expect 1 DOY and ~87% uptime for the science acquisition. + test_l1b_msg = test_l1b_msg.isel(epoch=np.isin(test_l1b_msg.science_on, [0, 1])) + msg_time = test_l1b_msg.epoch.data + msg_event = test_l1b_msg.science_on.data + on_percentages = get_science_acquisition_on_percentage(msg_time, msg_event) + # We expect 1 DOY with less than 1% uptime for the science acquisition. assert len(on_percentages) == 1 # The DOY should be 8 for this test dataset. assert on_percentages[8] < 1 - evt_ds = decom_test_data_evt[1].copy() - evt_ds_shifted = evt_ds.copy() - evt_ds_shifted["epoch"] = evt_ds["epoch"] + NANOSECONDS_IN_DAY - combined_ds = xr.concat([evt_ds, evt_ds_shifted], dim="epoch") + msg_ds = test_l1b_msg.copy() + msg_ds_shifted = msg_ds.copy() + msg_ds_shifted["epoch"] = msg_ds["epoch"] + NANOSECONDS_IN_DAY + combined_ds = xr.concat([msg_ds, msg_ds_shifted], dim="epoch") # expect a second DOY. - on_percentages = get_science_acquisition_on_percentage(combined_ds) + msg_time = combined_ds.epoch.data + msg_event = combined_ds.science_on.data + on_percentages = get_science_acquisition_on_percentage(msg_time, msg_event) # We expect 2 DOYs assert len(on_percentages) == 2 # The uptime should be less than 1% for both @@ -221,11 +225,7 @@ def test_get_science_acquisition_on_percentage(decom_test_data_evt: list[xr.Data def test_get_science_acquisition_on_percentage_no_acquisition(caplog): """Test the function returns an empty dict when there is no science acquisition.""" - with mock.patch( - "imap_processing.idex.idex_l2b.get_science_acquisition_timestamps", - return_value=([], [], []), - ): - on_percentages = get_science_acquisition_on_percentage(xr.Dataset()) + on_percentages = get_science_acquisition_on_percentage(np.array([]), np.array([])) assert not on_percentages assert "No science acquisition events found" in caplog.text diff --git a/imap_processing/tests/lo/test_anc/imap_lo_bad-times-small_20250101_20270101_v001.csv b/imap_processing/tests/lo/test_anc/imap_lo_bad-times-small_20250101_20270101_v001.csv new file mode 100644 index 0000000000..68ae9229d5 --- /dev/null +++ b/imap_processing/tests/lo/test_anc/imap_lo_bad-times-small_20250101_20270101_v001.csv @@ -0,0 +1,13 @@ +YYYYDDD,BadTime_start,BadTime_end,bin_start,bin_end,Instrument,E-Step1,E-Step2,E-Step3,E-Step4,E-Step5,E-Step6,E-Step7,Comment +2025001,473385600,473389200,30,59,Lo,1,0,0,0,0,0,0,#repointing maneuver +2025001,473407618,473420896,30,59,Lo,0,0,0,0,0,0,0,#high background +2025002,473472000,473475600,0,59,Lo,0,0,0,0,0,0,0,#repointing maneuver +2025002,473526046,473528426,0,59,Lo,0,0,0,0,0,0,0,#spin out of sync +2025003,473558400,473562000,0,59,Lo,0,0,0,0,0,0,0,#repointing maneuver +2025004,473644800,473648400,0,59,Lo,0,0,0,0,0,0,0,#repointing maneuver +2025005,473731200,473734800,0,59,Lo,0,0,0,0,0,0,0,#repointing maneuver +2025006,473817600,473821200,0,59,Lo,0,0,0,0,0,0,0,#repointing maneuver +2025007,473904000,473907600,0,59,Lo,0,0,0,0,0,0,0,#repointing maneuver +2025008,473990400,473994000,0,59,Lo,0,0,0,0,0,0,0,#repointing maneuver +2025008,474050712,474055891,0,59,Lo,0,0,0,0,0,0,0,#spin out of sync +2025009,474076800,474080400,0,59,Lo,0,0,0,0,0,0,0,#repointing maneuver diff --git a/imap_processing/tests/lo/test_anc/imap_lo_bg-rates-anti-ram-overrides_20250901_v001.csv b/imap_processing/tests/lo/test_anc/imap_lo_bg-rates-anti-ram-overrides_20250901_v001.csv new file mode 100755 index 0000000000..22c0e15393 --- /dev/null +++ b/imap_processing/tests/lo/test_anc/imap_lo_bg-rates-anti-ram-overrides_20250901_v001.csv @@ -0,0 +1,5 @@ +year,doy,counts/s +2026,62,0.0014 +2026,64,0.0 +2026,65,0.0 +2026,91,0.03 diff --git a/imap_processing/tests/lo/test_anc/imap_lo_esa-mode-lut_v001.csv b/imap_processing/tests/lo/test_anc/imap_lo_esa-mode-lut_v001.csv index 76c316877d..0564987f13 100644 --- a/imap_processing/tests/lo/test_anc/imap_lo_esa-mode-lut_v001.csv +++ b/imap_processing/tests/lo/test_anc/imap_lo_esa-mode-lut_v001.csv @@ -16,11 +16,11 @@ Tbl_Idx,E-Step_Idx,E-Step_lvl,ESA_POS_V,ESA_NEG_V,ESA_POS_Raw,ESA_NEG_Raw,ESA_Mo 1,7,7,2248.3,761.6,2634,1827,HiRes 2,1,1,40.3,13.7,40,26,HiRes 2,2,1,40.3,13.7,40,26,HiRes -2,3,1,40.3,13.7,40,26,HiRes -2,4,1,40.3,13.7,40,26,HiRes -2,5,1,40.3,13.7,40,26,HiRes -2,6,1,40.3,13.7,40,26,HiRes -2,7,1,40.3,13.7,40,26,HiRes +2,3,3,40.3,13.7,40,26,HiRes +2,4,4,40.3,13.7,40,26,HiRes +2,5,5,40.3,13.7,40,26,HiRes +2,6,6,40.3,13.7,40,26,HiRes +2,7,7,40.3,13.7,40,26,HiRes 3,1,2,77.7,26.3,84,57,HiRes 3,2,2,77.7,26.3,84,57,HiRes 3,3,2,77.7,26.3,84,57,HiRes diff --git a/imap_processing/tests/lo/test_anc/imap_lo_good-times-small_20250101_20270101_v001.csv b/imap_processing/tests/lo/test_anc/imap_lo_good-times-small_20250101_20270101_v001.csv new file mode 100644 index 0000000000..948f378cac --- /dev/null +++ b/imap_processing/tests/lo/test_anc/imap_lo_good-times-small_20250101_20270101_v001.csv @@ -0,0 +1,13 @@ +YYYYDDD,GoodTime_start,GoodTime_end,bin_start,bin_end,Instrument,E-Step1,E-Step2,E-Step3,E-Step4,E-Step5,E-Step6,E-Step7,Comment +2025001,473389200,473407618,30,59,Lo,1,0,1,0,1,0,1,#generated good time +2025001,473407618,473420896,0,29,Lo,1,1,1,1,1,1,1,#generated good time +2025001,473420896,473472000,0,59,Lo,1,1,1,1,1,1,1,#generated good time +2025002,473475600,473526046,0,59,Lo,1,1,1,1,1,1,1,#generated good time +2025002,473528426,473558400,0,59,Lo,1,1,1,1,1,1,1,#generated good time +2025003,473562000,473644800,0,59,Lo,1,1,1,1,1,1,1,#generated good time +2025004,473648400,473731200,0,59,Lo,1,1,1,1,1,1,1,#generated good time +2025005,473734800,473817600,0,59,Lo,1,1,1,1,1,1,1,#generated good time +2025006,473821200,473904000,0,59,Lo,1,1,1,1,1,1,1,#generated good time +2025007,473907600,473990400,0,59,Lo,1,1,1,1,1,1,1,#generated good time +2025008,473994000,474050712,0,59,Lo,1,1,1,1,1,1,1,#generated good time +2025008,474055891,474076800,0,59,Lo,1,1,1,1,1,1,1,#generated good time diff --git a/imap_processing/tests/lo/test_anc/imap_lo_goodtimes_20250415_v001.csv b/imap_processing/tests/lo/test_anc/imap_lo_goodtimes_20250415_v001.csv deleted file mode 100644 index ec05a5796d..0000000000 --- a/imap_processing/tests/lo/test_anc/imap_lo_goodtimes_20250415_v001.csv +++ /dev/null @@ -1,3 +0,0 @@ -YYYYDDD,GoodTime_strt,GoodTime_end,bin_strt,bin_end,Lo,E-Steps,Comments -2025001,0,558541625.0,0,29,Lo,1 1 1 1 1 1 1,generated good time -2025001,558541627.0,558541627.0,0,29,Lo,1 1 1 1 1 1 1,generated good time \ No newline at end of file diff --git a/imap_processing/tests/lo/test_anc/imap_lo_hydrogen-background-small_20250101_20270101_v001.csv b/imap_processing/tests/lo/test_anc/imap_lo_hydrogen-background-small_20250101_20270101_v001.csv index 15f74a2e94..fbc88964ec 100644 --- a/imap_processing/tests/lo/test_anc/imap_lo_hydrogen-background-small_20250101_20270101_v001.csv +++ b/imap_processing/tests/lo/test_anc/imap_lo_hydrogen-background-small_20250101_20270101_v001.csv @@ -1,13 +1,241 @@ -YYYYDDD,GoodTime_start,GoodTime_end,bin_start,bin_end,Instrument,E-Step1,E-Step2,E-Step3,E-Step4,E-Step5,E-Step6,E-Step7,rate/sigma -2025001,473389200,473407618,0,59,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0,rate -2025001,473389200,473407618,0,59,Lo,0.0025,0.002,0.0015,0.0015,0.001,0.0008,0,sigma -2025001,473407618,473420896,0,29,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0,rate -2025001,473407618,473420896,0,29,Lo,0.0025,0.002,0.0015,0.0015,0.001,0.0008,0,sigma -2025001,473420896,473472000,0,59,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0,rate -2025001,473420896,473472000,0,59,Lo,0.0025,0.002,0.0015,0.0015,0.001,0.0008,0,sigma -2025002,473475600,473526046,0,59,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0,rate -2025002,473475600,473526046,0,59,Lo,0.0025,0.002,0.0015,0.0015,0.001,0.0008,0,sigma -2025002,473528426,473558400,0,59,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0,rate -2025002,473528426,473558400,0,59,Lo,0.0025,0.002,0.0015,0.0015,0.001,0.0008,0,sigma -2025003,473562000,473644800,0,59,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0,rate -2025003,473562000,473644800,0,59,Lo,0.0025,0.002,0.0015,0.0015,0.001,0.0008,0,sigma \ No newline at end of file +YYYYDDD,GoodTime_start,GoodTime_end,bin_start,bin_end,Lo,E-Step1,E-Step2,E-Step3,E-Step4,E-Step5,E-Step6,E-Step7,rate/sigma +2025001,473389200.0,473472000.0,0,0,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,0,0,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,1,1,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,1,1,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,2,2,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,2,2,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,3,3,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,3,3,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,4,4,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,4,4,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,5,5,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,5,5,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,6,6,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,6,6,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,7,7,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,7,7,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,8,8,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,8,8,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,9,9,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,9,9,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,10,10,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,10,10,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,11,11,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,11,11,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,12,12,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,12,12,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,13,13,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,13,13,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,14,14,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,14,14,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,15,15,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,15,15,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,16,16,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,16,16,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,17,17,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,17,17,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,18,18,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,18,18,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,19,19,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,19,19,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,20,20,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,20,20,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,21,21,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,21,21,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,22,22,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,22,22,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,23,23,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,23,23,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,24,24,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,24,24,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,25,25,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,25,25,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,26,26,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,26,26,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,27,27,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,27,27,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,28,28,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,28,28,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,29,29,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,29,29,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,30,30,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,30,30,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,31,31,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,31,31,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,32,32,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,32,32,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,33,33,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,33,33,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,34,34,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,34,34,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,35,35,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,35,35,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,36,36,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,36,36,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,37,37,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,37,37,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,38,38,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,38,38,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,39,39,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,39,39,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,40,40,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,40,40,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,41,41,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,41,41,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,42,42,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,42,42,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,43,43,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,43,43,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,44,44,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,44,44,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,45,45,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,45,45,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,46,46,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,46,46,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,47,47,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,47,47,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,48,48,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,48,48,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,49,49,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,49,49,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,50,50,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,50,50,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,51,51,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,51,51,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,52,52,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,52,52,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,53,53,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,53,53,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,54,54,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,54,54,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,55,55,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,55,55,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,56,56,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,56,56,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,57,57,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,57,57,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,58,58,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,58,58,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,59,59,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,59,59,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,0,0,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,0,0,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,1,1,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,1,1,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,2,2,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,2,2,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,3,3,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,3,3,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,4,4,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,4,4,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,5,5,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,5,5,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,6,6,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,6,6,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,7,7,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,7,7,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,8,8,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,8,8,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,9,9,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,9,9,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,10,10,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,10,10,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,11,11,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,11,11,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,12,12,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,12,12,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,13,13,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,13,13,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,14,14,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,14,14,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,15,15,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,15,15,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,16,16,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,16,16,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,17,17,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,17,17,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,18,18,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,18,18,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,19,19,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,19,19,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,20,20,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,20,20,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,21,21,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,21,21,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,22,22,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,22,22,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,23,23,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,23,23,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,24,24,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,24,24,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,25,25,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,25,25,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,26,26,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,26,26,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,27,27,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,27,27,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,28,28,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,28,28,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,29,29,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,29,29,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,30,30,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,30,30,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,31,31,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,31,31,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,32,32,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,32,32,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,33,33,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,33,33,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,34,34,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,34,34,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,35,35,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,35,35,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,36,36,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,36,36,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,37,37,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,37,37,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,38,38,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,38,38,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,39,39,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,39,39,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,40,40,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,40,40,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,41,41,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,41,41,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,42,42,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,42,42,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,43,43,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,43,43,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,44,44,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,44,44,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,45,45,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,45,45,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,46,46,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,46,46,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,47,47,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,47,47,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,48,48,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,48,48,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,49,49,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,49,49,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,50,50,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,50,50,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,51,51,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,51,51,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,52,52,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,52,52,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,53,53,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,53,53,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,54,54,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,54,54,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,55,55,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,55,55,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,56,56,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,56,56,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,57,57,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,57,57,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,58,58,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,58,58,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,59,59,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,59,59,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma diff --git a/imap_processing/tests/lo/test_anc/imap_lo_hydrogen-geometric-factor_v001.csv b/imap_processing/tests/lo/test_anc/imap_lo_hydrogen-geometric-factor_v001.csv deleted file mode 100644 index f4172c2f77..0000000000 --- a/imap_processing/tests/lo/test_anc/imap_lo_hydrogen-geometric-factor_v001.csv +++ /dev/null @@ -1,75 +0,0 @@ -ο»Ώincident_E-Step,Observed_E-Step,Cntr_E,Cntr_E_unc,GF_Dbl_all,GF_Dbl_all_unc,GF_Trpl_all,GF_Trpl_all_unc,GF_Dbl_H,GF_Dbl_H_unc,GF_Trpl_H,GF_Trpl_H_unc -Hi_Res,,[keV],[keV],[cm^2sr keV/keV],[cm^2sr keV/keV],[cm^2sr keV/keV],[cm^2sr keV/keV],[cm^2sr keV/keV],[cm^2sr keV/keV],[cm^2sr keV/keV],[cm^2sr keV/keV] -1,1,0.015,0.00135,5.35E-05,4.82E-06,2.20E-05,1.87E-06,5.32E-05,4.26E-06,2.19E-05,1.86E-06 -2,1,0.015,0.00135,3.10E-05,2.79E-06,1.25E-05,1.06E-06,3.09E-05,2.47E-06,1.27E-05,1.08E-06 -2,2,0.029,0.00261,1.04E-04,9.36E-06,4.27E-05,3.63E-06,1.03E-04,8.26E-06,4.24E-05,3.61E-06 -3,1,0.015,0.00135,4.13E-05,3.72E-06,1.68E-05,1.43E-06,4.16E-05,3.33E-06,1.71E-05,1.45E-06 -3,2,0.029,0.00261,1.28E-04,1.15E-05,5.02E-05,4.26E-06,1.30E-04,1.04E-05,5.35E-05,4.55E-06 -3,3,0.055,0.00495,1.59E-04,1.43E-05,6.54E-05,5.56E-06,1.59E-04,1.27E-05,6.51E-05,5.54E-06 -4,1,0.015,0.00135,9.85E-06,8.86E-07,3.73E-06,3.17E-07,7.97E-06,6.38E-07,3.28E-06,2.79E-07 -4,2,0.029,0.00261,1.71E-05,1.54E-06,6.54E-06,5.56E-07,1.68E-05,1.34E-06,6.89E-06,5.86E-07 -4,3,0.055,0.00495,6.72E-05,6.05E-06,2.58E-05,2.19E-06,6.92E-05,5.53E-06,2.84E-05,2.42E-06 -4,4,0.11,0.0099,1.79E-04,1.61E-05,7.36E-05,6.25E-06,1.78E-04,1.42E-05,7.30E-05,6.20E-06 -5,1,0.015,0.00135,1.62E-05,1.46E-06,5.05E-06,4.29E-07,7.86E-06,6.29E-07,3.23E-06,2.75E-07 -5,2,0.029,0.00261,1.57E-05,1.41E-06,5.16E-06,4.39E-07,9.72E-06,7.77E-07,3.99E-06,3.39E-07 -5,3,0.055,0.00495,1.45E-05,1.31E-06,4.98E-06,4.24E-07,1.49E-05,1.20E-06,6.14E-06,5.22E-07 -5,4,0.11,0.0099,5.81E-05,5.23E-06,2.15E-05,1.83E-06,6.00E-05,4.80E-06,2.47E-05,2.10E-06 -5,5,0.209,0.01881,1.77E-04,1.59E-05,7.26E-05,6.17E-06,1.76E-04,1.41E-05,7.22E-05,6.14E-06 -6,1,0.015,0.00135,1.34E-05,1.21E-06,4.33E-06,3.68E-07,9.40E-06,7.52E-07,3.86E-06,3.28E-07 -6,2,0.029,0.00261,1.61E-05,1.45E-06,4.64E-06,3.94E-07,1.11E-05,8.92E-07,4.58E-06,3.89E-07 -6,3,0.055,0.00495,1.74E-05,1.57E-06,5.02E-06,4.27E-07,1.42E-05,1.14E-06,5.84E-06,4.96E-07 -6,4,0.11,0.0099,1.45E-05,1.30E-06,4.28E-06,3.64E-07,1.56E-05,1.25E-06,6.40E-06,5.44E-07 -6,5,0.209,0.01881,5.81E-05,5.23E-06,2.06E-05,1.75E-06,6.01E-05,4.81E-06,2.47E-05,2.10E-06 -6,6,0.439,0.03951,2.06E-04,1.85E-05,8.46E-05,7.19E-06,2.06E-04,1.64E-05,8.45E-05,7.18E-06 -7,1,0.015,0.00135,5.32E-06,4.79E-07,1.51E-06,1.29E-07,5.05E-06,4.04E-07,2.08E-06,1.76E-07 -7,2,0.029,0.00261,1.61E-05,1.45E-06,5.15E-06,4.38E-07,1.39E-05,1.11E-06,5.70E-06,4.85E-07 -7,3,0.055,0.00495,1.96E-05,1.77E-06,6.10E-06,5.19E-07,1.42E-05,1.14E-06,5.84E-06,4.96E-07 -7,4,0.11,0.0099,2.08E-05,1.87E-06,6.43E-06,5.46E-07,1.65E-05,1.32E-06,6.78E-06,5.77E-07 -7,5,0.209,0.01881,2.52E-05,2.27E-06,8.69E-06,7.39E-07,2.61E-05,2.09E-06,1.07E-05,9.11E-07 -7,6,0.439,0.03951,1.93E-04,1.74E-05,6.94E-05,5.90E-06,1.98E-04,1.59E-05,8.15E-05,6.93E-06 -7,7,0.872,0.07848,3.82E-04,3.44E-05,1.57E-04,1.33E-05,3.82E-04,3.05E-05,1.57E-04,1.33E-05 -8,1,0.015,0.00135,5.28E-05,4.75E-06,2.25E-05,1.91E-06,4.10E-05,3.28E-06,1.68E-05,1.43E-06 -8,2,0.029,0.00261,6.14E-06,5.53E-07,1.96E-06,1.66E-07,5.25E-06,4.20E-07,2.16E-06,1.83E-07 -8,3,0.055,0.00495,1.13E-05,1.02E-06,3.39E-06,2.88E-07,9.37E-06,7.50E-07,3.85E-06,3.27E-07 -8,4,0.11,0.0099,1.16E-05,1.04E-06,3.83E-06,3.25E-07,8.69E-06,6.95E-07,3.57E-06,3.03E-07 -8,5,0.209,0.01881,1.09E-05,9.78E-07,3.55E-06,3.02E-07,8.41E-06,6.73E-07,3.46E-06,2.94E-07 -8,6,0.439,0.03951,3.29E-05,2.96E-06,1.28E-05,1.08E-06,3.28E-05,2.62E-06,1.35E-05,1.15E-06 -8,7,0.872,0.07848,3.95E-04,3.56E-05,1.44E-04,1.23E-05,4.04E-04,3.23E-05,1.66E-04,1.41E-05 -8,8,1.821,0.16389,5.41E-04,4.87E-05,2.22E-04,1.89E-05,5.41E-04,4.33E-05,2.22E-04,1.89E-05 -Hi_Thr,,,,,,,,,,, -1,1,0.016,0.00144,8.92E-05,8.03E-06,3.67E-05,3.12E-06,8.87E-05,7.10E-06,3.65E-05,3.10E-06 -2,1,0.016,0.00144,5.16E-05,4.65E-06,2.08E-05,1.76E-06,5.15E-05,4.12E-06,2.12E-05,1.80E-06 -2,2,0.03,0.0027,1.73E-04,1.56E-05,7.12E-05,6.06E-06,1.72E-04,1.38E-05,7.07E-05,6.01E-06 -3,1,0.016,0.00144,6.88E-05,6.19E-06,2.80E-05,2.38E-06,6.94E-05,5.55E-06,2.85E-05,2.42E-06 -3,2,0.03,0.0027,2.13E-04,1.91E-05,8.36E-05,7.11E-06,2.17E-04,1.74E-05,8.92E-05,7.58E-06 -3,3,0.056,0.00504,2.65E-04,2.39E-05,1.09E-04,9.26E-06,2.64E-04,2.11E-05,1.09E-04,9.23E-06 -4,1,0.016,0.00144,1.64E-05,1.48E-06,6.22E-06,5.29E-07,1.33E-05,1.06E-06,5.46E-06,4.64E-07 -4,2,0.03,0.0027,2.84E-05,2.56E-06,1.09E-05,9.27E-07,2.80E-05,2.24E-06,1.15E-05,9.77E-07 -4,3,0.056,0.00504,1.12E-04,1.01E-05,4.30E-05,3.66E-06,1.15E-04,9.22E-06,4.74E-05,4.03E-06 -4,4,0.111,0.00999,2.98E-04,2.68E-05,1.23E-04,1.04E-05,2.96E-04,2.37E-05,1.22E-04,1.03E-05 -5,1,0.016,0.00144,2.70E-05,2.43E-06,8.42E-06,7.15E-07,1.31E-05,1.05E-06,5.38E-06,4.58E-07 -5,2,0.03,0.0027,2.61E-05,2.35E-06,8.61E-06,7.31E-07,1.62E-05,1.30E-06,6.65E-06,5.66E-07 -5,3,0.056,0.00504,2.42E-05,2.18E-06,8.30E-06,7.06E-07,2.49E-05,1.99E-06,1.02E-05,8.70E-07 -5,4,0.111,0.00999,9.69E-05,8.72E-06,3.58E-05,3.04E-06,1.00E-04,8.00E-06,4.11E-05,3.49E-06 -5,5,0.21,0.0189,2.94E-04,2.65E-05,1.21E-04,1.03E-05,2.93E-04,2.34E-05,1.20E-04,1.02E-05 -6,1,0.016,0.00144,2.24E-05,2.01E-06,7.22E-06,6.14E-07,1.57E-05,1.25E-06,6.44E-06,5.47E-07 -6,2,0.03,0.0027,2.68E-05,2.41E-06,7.73E-06,6.57E-07,1.86E-05,1.49E-06,7.64E-06,6.49E-07 -6,3,0.056,0.00504,2.91E-05,2.61E-06,8.37E-06,7.12E-07,2.37E-05,1.89E-06,9.73E-06,8.27E-07 -6,4,0.111,0.00999,2.41E-05,2.17E-06,7.13E-06,6.06E-07,2.60E-05,2.08E-06,1.07E-05,9.07E-07 -6,5,0.21,0.0189,9.68E-05,8.71E-06,3.44E-05,2.92E-06,1.00E-04,8.02E-06,4.12E-05,3.50E-06 -6,6,0.44,0.0396,3.43E-04,3.09E-05,1.41E-04,1.20E-05,3.43E-04,2.74E-05,1.41E-04,1.20E-05 -7,1,0.016,0.00144,8.87E-06,7.98E-07,2.52E-06,2.14E-07,8.42E-06,6.73E-07,3.46E-06,2.94E-07 -7,2,0.03,0.0027,2.68E-05,2.41E-06,8.59E-06,7.30E-07,2.31E-05,1.85E-06,9.50E-06,8.08E-07 -7,3,0.056,0.00504,3.27E-05,2.95E-06,1.02E-05,8.64E-07,2.37E-05,1.89E-06,9.73E-06,8.27E-07 -7,4,0.111,0.00999,3.47E-05,3.12E-06,1.07E-05,9.10E-07,2.75E-05,2.20E-06,1.13E-05,9.61E-07 -7,5,0.21,0.0189,4.20E-05,3.78E-06,1.45E-05,1.23E-06,4.35E-05,3.48E-06,1.79E-05,1.52E-06 -7,6,0.44,0.0396,3.21E-04,2.89E-05,1.16E-04,9.84E-06,3.31E-04,2.65E-05,1.36E-04,1.16E-05 -7,7,0.873,0.07857,6.36E-04,5.73E-05,2.61E-04,2.22E-05,6.36E-04,5.09E-05,2.61E-04,2.22E-05 -8,1,0.016,0.00144,8.79E-05,7.91E-06,3.75E-05,3.19E-06,6.83E-05,5.46E-06,2.81E-05,2.39E-06 -8,2,0.03,0.0027,1.02E-05,9.21E-07,3.26E-06,2.77E-07,8.75E-06,7.00E-07,3.60E-06,3.06E-07 -8,3,0.056,0.00504,1.88E-05,1.70E-06,5.65E-06,4.80E-07,1.56E-05,1.25E-06,6.42E-06,5.46E-07 -8,4,0.111,0.00999,1.93E-05,1.73E-06,6.38E-06,5.42E-07,1.45E-05,1.16E-06,5.95E-06,5.06E-07 -8,5,0.21,0.0189,1.81E-05,1.63E-06,5.92E-06,5.03E-07,1.40E-05,1.12E-06,5.76E-06,4.90E-07 -8,6,0.44,0.0396,5.48E-05,4.93E-06,2.13E-05,1.81E-06,5.46E-05,4.37E-06,2.25E-05,1.91E-06 -8,7,0.873,0.07857,6.59E-04,5.93E-05,2.40E-04,2.04E-05,6.74E-04,5.39E-05,2.77E-04,2.35E-05 -8,8,1.822,0.16398,9.01E-04,8.11E-05,3.70E-04,3.15E-05,9.01E-04,7.21E-05,3.70E-04,3.15E-05 \ No newline at end of file diff --git a/imap_processing/tests/lo/test_anc/imap_lo_oxygen-background-small_20250101_20270101_v001.csv b/imap_processing/tests/lo/test_anc/imap_lo_oxygen-background-small_20250101_20270101_v001.csv new file mode 100644 index 0000000000..fbc88964ec --- /dev/null +++ b/imap_processing/tests/lo/test_anc/imap_lo_oxygen-background-small_20250101_20270101_v001.csv @@ -0,0 +1,241 @@ +YYYYDDD,GoodTime_start,GoodTime_end,bin_start,bin_end,Lo,E-Step1,E-Step2,E-Step3,E-Step4,E-Step5,E-Step6,E-Step7,rate/sigma +2025001,473389200.0,473472000.0,0,0,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,0,0,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,1,1,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,1,1,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,2,2,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,2,2,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,3,3,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,3,3,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,4,4,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,4,4,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,5,5,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,5,5,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,6,6,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,6,6,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,7,7,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,7,7,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,8,8,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,8,8,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,9,9,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,9,9,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,10,10,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,10,10,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,11,11,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,11,11,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,12,12,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,12,12,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,13,13,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,13,13,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,14,14,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,14,14,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,15,15,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,15,15,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,16,16,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,16,16,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,17,17,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,17,17,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,18,18,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,18,18,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,19,19,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,19,19,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,20,20,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,20,20,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,21,21,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,21,21,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,22,22,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,22,22,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,23,23,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,23,23,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,24,24,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,24,24,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,25,25,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,25,25,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,26,26,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,26,26,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,27,27,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,27,27,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,28,28,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,28,28,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,29,29,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,29,29,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,30,30,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,30,30,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,31,31,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,31,31,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,32,32,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,32,32,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,33,33,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,33,33,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,34,34,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,34,34,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,35,35,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,35,35,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,36,36,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,36,36,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,37,37,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,37,37,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,38,38,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,38,38,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,39,39,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,39,39,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,40,40,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,40,40,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,41,41,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,41,41,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,42,42,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,42,42,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,43,43,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,43,43,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,44,44,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,44,44,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,45,45,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,45,45,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,46,46,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,46,46,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,47,47,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,47,47,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,48,48,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,48,48,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,49,49,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,49,49,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,50,50,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,50,50,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,51,51,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,51,51,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,52,52,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,52,52,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,53,53,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,53,53,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,54,54,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,54,54,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,55,55,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,55,55,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,56,56,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,56,56,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,57,57,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,57,57,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,58,58,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,58,58,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025001,473389200.0,473472000.0,59,59,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025001,473389200.0,473472000.0,59,59,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,0,0,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,0,0,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,1,1,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,1,1,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,2,2,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,2,2,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,3,3,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,3,3,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,4,4,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,4,4,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,5,5,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,5,5,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,6,6,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,6,6,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,7,7,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,7,7,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,8,8,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,8,8,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,9,9,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,9,9,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,10,10,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,10,10,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,11,11,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,11,11,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,12,12,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,12,12,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,13,13,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,13,13,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,14,14,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,14,14,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,15,15,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,15,15,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,16,16,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,16,16,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,17,17,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,17,17,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,18,18,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,18,18,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,19,19,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,19,19,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,20,20,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,20,20,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,21,21,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,21,21,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,22,22,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,22,22,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,23,23,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,23,23,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,24,24,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,24,24,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,25,25,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,25,25,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,26,26,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,26,26,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,27,27,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,27,27,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,28,28,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,28,28,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,29,29,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,29,29,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,30,30,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,30,30,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,31,31,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,31,31,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,32,32,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,32,32,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,33,33,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,33,33,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,34,34,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,34,34,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,35,35,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,35,35,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,36,36,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,36,36,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,37,37,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,37,37,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,38,38,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,38,38,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,39,39,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,39,39,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,40,40,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,40,40,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,41,41,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,41,41,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,42,42,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,42,42,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,43,43,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,43,43,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,44,44,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,44,44,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,45,45,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,45,45,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,46,46,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,46,46,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,47,47,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,47,47,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,48,48,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,48,48,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,49,49,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,49,49,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,50,50,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,50,50,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,51,51,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,51,51,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,52,52,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,52,52,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,53,53,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,53,53,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,54,54,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,54,54,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,55,55,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,55,55,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,56,56,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,56,56,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,57,57,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,57,57,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,58,58,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,58,58,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma +2025002,473475600.0,473558400.0,59,59,Lo,0.0098,0.0089,0.0118,0.0113,0.0056,0.0008,0.0000,rate +2025002,473475600.0,473558400.0,59,59,Lo,0.0025,0.0020,0.0015,0.0015,0.0010,0.0008,0.0000,sigma diff --git a/imap_processing/tests/lo/test_anc/imap_lo_sweep-table-small_20250101_20260301_v001.csv b/imap_processing/tests/lo/test_anc/imap_lo_sweep-table-small_20250101_20260301_v001.csv index b621fa5a63..6b4d507a81 100644 --- a/imap_processing/tests/lo/test_anc/imap_lo_sweep-table-small_20250101_20260301_v001.csv +++ b/imap_processing/tests/lo/test_anc/imap_lo_sweep-table-small_20250101_20260301_v001.csv @@ -1,7 +1,12 @@ YYYYDDD,ISN/ENA,Operation Mode,GoodTime_start,GoodTime_end,Instrument,LUT_table,ESA_Mode,E-Step1,E-Step2,E-Step3,E-Step4,E-Step5,E-Step6,E-Step7 +2024001,ENA,Nominal Mode,469024800,469084200,Lo,20,HiRes,1,2,3,4,5,6,7 2025001,ISN,HiRes Mode,473389200,473407618,Lo,1,HiRes,1,2,3,4,5,6,7 2025001,ISN,HiRes Mode,473407618,473420896,Lo,1,HiRes,1,2,3,4,5,6,7 2025001,ISN,HiRes Mode,473420896,473472000,Lo,1,HiRes,1,2,3,4,5,6,7 2025002,ENA,Nominal Mode,473475600,473526046,Lo,1,HiRes,1,2,3,4,5,6,7 -2025002,ENA,Nominal Mode,473528426,473558400,Lo,1,HiRes,1,2,3,4,5,6,7 -2025003,ISN,HiRes Mode,473562000,473644800,Lo,1,HiRes,1,2,3,4,5,6,7 \ No newline at end of file +2025002,ENA,Nominal Mode,473528426,473558400,Lo,1,HiThr,1,2,3,4,5,6,7 +2025003,ISN,HiRes Mode,473562000,473644800,Lo,1,HiThr,1,2,3,4,5,6,7 +2025105,ENA,Nominal Mode,476715600,476736000,Lo,2,HiRes,1,2,3,4,5,6,7 +2025105,ENA,Nominal Mode,476715600,476736000,Lo,2,HiRes,1,2,3,4,5,6,7 +2025106,ENA,Nominal Mode,476715600,476736000,Lo,1,HiRes,1,2,3,4,5,6,7 +2025106,ENA,Nominal Mode,476715600,476736000,Lo,2,HiRes,1,2,3,4,5,6,7 \ No newline at end of file diff --git a/imap_processing/tests/lo/test_cdfs/imap_lo_l1c_pset_20260101-repoint01261_v001.cdf b/imap_processing/tests/lo/test_cdfs/imap_lo_l1c_pset_20260101-repoint01261_v001.cdf new file mode 100644 index 0000000000..57e2060b59 Binary files /dev/null and b/imap_processing/tests/lo/test_cdfs/imap_lo_l1c_pset_20260101-repoint01261_v001.cdf differ diff --git a/imap_processing/tests/lo/test_lo_ancillary.py b/imap_processing/tests/lo/test_lo_ancillary.py index 696a738e0e..f167e63d85 100644 --- a/imap_processing/tests/lo/test_lo_ancillary.py +++ b/imap_processing/tests/lo/test_lo_ancillary.py @@ -12,7 +12,7 @@ def test_read_backgrounds(): ANCILLARY_DIR / "imap_lo_hydrogen-background-small_20250101_20270101_v001.csv" ) df = lo_ancillary.read_ancillary_file(ancillary_file) - assert len(df) == 12 + assert len(df) == 240 # spot check the first row first_row = df.iloc[0] @@ -21,10 +21,10 @@ def test_read_backgrounds(): np.array( [ pd.Timestamp("2025-01-01"), - 473389200, - 473407618, + 473389200.0, + 473472000.0, + 0, 0, - 59, "Lo", 0.0098, 0.0089, @@ -32,7 +32,7 @@ def test_read_backgrounds(): 0.0113, 0.0056, 0.0008, - 0, + 0.0000, "rate", ], dtype=object, @@ -41,7 +41,14 @@ def test_read_backgrounds(): def test_read_geometric_factor(): - ancillary_file = ANCILLARY_DIR / "imap_lo_hydrogen-geometric-factor_v001.csv" + # NOTE: The geometric factors are stored in the main project repository + # rather than the test ancillary data because they should be rarely + # changed and are considered basically static reference data. + + ancillary_file = ( + imap_module_directory + / "lo/ancillary_data/imap_lo_hydrogen-geometric-factor_v001.csv" + ) df = lo_ancillary.read_ancillary_file(ancillary_file) assert len(df) == 72 assert "esa_mode" in df.columns @@ -54,16 +61,16 @@ def test_read_geometric_factor(): [ 1, 1, - 0.015, - 0.00135, + 0.01633, + 0.00028, 5.35e-05, 4.82e-06, 2.20e-05, 1.87e-06, 5.32e-05, 4.26e-06, - 2.19e-05, - 1.86e-06, + 7.00e-05, + 4.90e-05, 0, ], ) @@ -128,20 +135,20 @@ def test_read_sweep_table(): ANCILLARY_DIR / "imap_lo_sweep-table-small_20250101_20260301_v001.csv" ) df = lo_ancillary.read_ancillary_file(ancillary_file) - assert len(df) == 6 + assert len(df) == 11 # spot check the first row np.testing.assert_array_equal( df.iloc[0], np.array( [ - pd.Timestamp("2025-01-01"), - "ISN", - "HiRes Mode", - 473389200, - 473407618, + pd.Timestamp("2024-01-01"), + "ENA", + "Nominal Mode", + 469024800, + 469084200, "Lo", - 1, + 20, "HiRes", 1, 2, diff --git a/imap_processing/tests/lo/test_lo_housekeeping.py b/imap_processing/tests/lo/test_lo_housekeeping.py index e4d43fa9b6..71387750e4 100644 --- a/imap_processing/tests/lo/test_lo_housekeeping.py +++ b/imap_processing/tests/lo/test_lo_housekeeping.py @@ -41,7 +41,6 @@ def test_housekeeping(housekeeping_datasets): # the first 3 and the final value. small_ds = ds.isel(epoch=[0, 1, 2, -1]) for var in validation_data_l1a.columns: - print(var) if var == "PPM_UPPER_BOUND": # This is 65535 in the validation data, but only 4095 in the dataset. # This is because it is defined as a 12-bit quantity in the packet diff --git a/imap_processing/tests/lo/test_lo_l1a.py b/imap_processing/tests/lo/test_lo_l1a.py index 096091d0e9..1f98a3655a 100644 --- a/imap_processing/tests/lo/test_lo_l1a.py +++ b/imap_processing/tests/lo/test_lo_l1a.py @@ -2,6 +2,7 @@ import pandas as pd from imap_processing import imap_module_directory +from imap_processing.cdf.utils import write_cdf from imap_processing.lo.l1a.lo_l1a import lo_l1a @@ -17,15 +18,40 @@ def test_lo_l1a(): "imap_lo_l1a_star", "imap_lo_l1a_nhk", "imap_lo_l1b_nhk", + "imap_lo_l1b_instrument-status-summary", ] output_dataset = lo_l1a(dependency) # Assert assert len(output_dataset) == len(expected_logical_source) + + no_depend_0_vars = [ + "direct_events", + "coincidence_type", + "de_time", + "mode", + "esa_step", + "tof0", + "tof1", + "tof2", + "tof3", + "pos", + "cksm", + "spin", + "azimuth_6", + "azimuth_60", + "spin_label", + ] for dataset, logical_source in zip( output_dataset, expected_logical_source, strict=False ): + # Try writing out the dataset to cdf in an attempt to catch any issues + # with attributes that cdflib doesn't like + _ = write_cdf(dataset) assert logical_source == dataset.attrs["Logical_source"] + for var in dataset: + if var in no_depend_0_vars or var.endswith("label"): + assert "DEPEND_0" not in dataset[var].attrs def test_lo_l1a_dataset(): @@ -121,3 +147,22 @@ def test_validate_spin_data(): np.testing.assert_array_equal( output_dataset[0][field], validation_data[field.upper()].values.tolist() ) + + +def test_instrument_status_summary(): + dependency = ( + imap_module_directory / "tests/lo/test_pkts/imap_lo_l0_raw_20240803_v002.pkts" + ) + list_of_data = lo_l1a(dependency) + status_summary_ds = list_of_data[-1] + assert ( + status_summary_ds.attrs["Logical_source"] + == "imap_lo_l1b_instrument-status-summary" + ) + + # We started out in HVENG mode and ended in HVSCI mode + assert status_summary_ds["op_mode"][0] == "HVENG" + assert status_summary_ds["op_mode"][-1] == "HVSCI" + # Make sure we have added the FSW version string variable + # even though it isn't in our packets in this test + assert "fsw_version_str" in status_summary_ds.variables diff --git a/imap_processing/tests/lo/test_lo_l1b.py b/imap_processing/tests/lo/test_lo_l1b.py index 3920e8014e..ba0c5b6c8f 100644 --- a/imap_processing/tests/lo/test_lo_l1b.py +++ b/imap_processing/tests/lo/test_lo_l1b.py @@ -1,40 +1,90 @@ +import logging from collections import namedtuple from unittest.mock import patch import numpy as np +import pandas as pd import pytest import xarray as xr from imap_processing import imap_module_directory from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes -from imap_processing.cdf.utils import load_cdf +from imap_processing.cdf.utils import load_cdf, write_cdf +from imap_processing.lo.constants import LoConstants from imap_processing.lo.l1b.lo_l1b import ( + DE_CLOCK_TICK_S, + calculate_de_rates, + calculate_histogram_rates, + calculate_star_sensor_profile_for_group, + calculate_star_sensor_profiles_by_group, calculate_tof1_for_golden_triples, convert_start_end_acq_times, convert_tofs_to_eu, + create_badtimes_dataset, create_datasets, + filter_valid_star_records, get_avg_spin_durations_per_cycle, - get_spin_angle, + get_pivot_angle_from_nhk, + get_sampling_cadence_from_nhk, get_spin_start_times, identify_species, initialize_l1b_de, + l1b_bgrates_and_goodtimes, + l1b_star, lo_l1b, + resweep_histogram_data, set_avg_spin_durations_per_event, - set_bad_times, set_coincidence_type, set_each_event_epoch, + set_esa_mode, set_event_met, set_pointing_bin, set_pointing_direction, - set_spin_bin, set_spin_cycle, + set_spin_cycle_from_spin_data, + split_backgrounds_and_goodtimes_dataset, ) -from imap_processing.spice.time import met_to_ttj2000ns +from imap_processing.spice.spin import get_spin_data +from imap_processing.spice.time import ( + et_to_met, + et_to_ttj2000ns, + met_to_ttj2000ns, + str_to_et, + ttj2000ns_to_met, +) + +SPIN_BIN_6_FIELDS = [ + "h_counts", + "o_counts", + "tof0_tof1_counts", + "tof0_tof2_counts", + "tof1_tof2_counts", + "silver_triple_counts", +] + +SPIN_BIN_60_FIELDS = [ + "start_a_counts", + "start_c_counts", + "stop_b0_counts", + "stop_b3_counts", + "tof0_counts", + "tof1_counts", + "tof2_counts", + "tof3_counts", + "disc_tof0_counts", + "disc_tof1_counts", + "disc_tof2_counts", + "disc_tof3_counts", + "pos0_counts", + "pos1_counts", + "pos2_counts", + "pos3_counts", +] @pytest.fixture def dependencies(): - return { + data = { "imap_lo_l1a_de": load_cdf( imap_module_directory / "tests/lo/test_cdfs/imap_lo_l1a_de_20241022_v002.cdf" @@ -45,6 +95,37 @@ def dependencies(): ), } + # We have 0 for num_completed which causes issues downstream + # when calculating the average spin durations and cascading + # failures. Set to 28 for testing. + data["imap_lo_l1a_spin"]["num_completed"] = 28 + + # There are 3 shcoarse values for some reason, this is a bad + # set of test data, so modify in-place here rather than updating + data["imap_lo_l1a_de"]["shcoarse"] = data["imap_lo_l1a_de"]["shcoarse"].values[0] + return data + + +@pytest.fixture +def anc_dependencies(): + return [ + str( + imap_module_directory + / "tests/lo/test_anc/imap_lo_sweep-table-small_20250101_20260301_v001.csv", + ), + str( + imap_module_directory + / "tests/lo/test_anc/imap_lo_bad-times-small_20250101_20270101_v001.csv", + ), + str( + imap_module_directory / "tests/lo/test_anc/imap_lo_esa-mode-lut_v001.csv", + ), + str( + imap_module_directory + / "tests/lo/test_anc/imap_lo_bg-rates-anti-ram-overrides_20250901_v001.csv", + ), + ] + @pytest.fixture def attr_mgr_l1b(): @@ -62,31 +143,171 @@ def attr_mgr_l1a(): return attr_mgr -@patch("imap_processing.lo.l1b.lo_l1b.instrument_pointing") -def test_lo_l1b(mock_instrument_pointing): +@pytest.fixture +def l1b_histrates(): + epoch_date = et_to_ttj2000ns( + str_to_et(["2025-04-15T02:00:00", "2025-04-15T03:00:00"]) + ) + + # Build dataset with all expected fields + data_vars = {} + for f in SPIN_BIN_6_FIELDS: + data_vars[f] = (("epoch", "esa_step", "spin_bin_6"), np.zeros((2, 7, 60))) + for f in SPIN_BIN_60_FIELDS: + data_vars[f] = (("epoch", "esa_step", "spin_bin_60"), np.zeros((2, 7, 6))) + + l1b_histrates = xr.Dataset( + data_vars, + coords={ + "epoch": epoch_date, + "esa_step": np.arange(1, 8), + "spin_bin_6": np.arange(60), + "spin_bin_60": np.arange(6), + }, + ) + + return l1b_histrates + + +@pytest.fixture +def l1a_hist(): + epoch_date = et_to_ttj2000ns(str_to_et(["2025-04-15T02:00:00"])) + l1a_hist = xr.Dataset( + { + "hydrogen": (("epoch", "esa_step", "azimuth_6"), np.zeros((1, 7, 60))), + "oxygen": (("epoch", "esa_step", "azimuth_6"), np.zeros((1, 7, 60))), + "tof0_tof1": (("epoch", "esa_step", "azimuth_6"), np.zeros((1, 7, 60))), + "tof0_tof2": (("epoch", "esa_step", "azimuth_6"), np.zeros((1, 7, 60))), + "tof1_tof2": (("epoch", "esa_step", "azimuth_6"), np.zeros((1, 7, 60))), + "silver": (("epoch", "esa_step", "azimuth_6"), np.zeros((1, 7, 60))), + "start_a": (("epoch", "esa_step", "azimuth_60"), np.zeros((1, 7, 6))), + "start_c": (("epoch", "esa_step", "azimuth_60"), np.zeros((1, 7, 6))), + "stop_b0": (("epoch", "esa_step", "azimuth_60"), np.zeros((1, 7, 6))), + "stop_b3": (("epoch", "esa_step", "azimuth_60"), np.zeros((1, 7, 6))), + "tof0_count": (("epoch", "esa_step", "azimuth_60"), np.zeros((1, 7, 6))), + "tof1_count": (("epoch", "esa_step", "azimuth_60"), np.zeros((1, 7, 6))), + "tof2_count": (("epoch", "esa_step", "azimuth_60"), np.zeros((1, 7, 6))), + "tof3_count": (("epoch", "esa_step", "azimuth_60"), np.zeros((1, 7, 6))), + "disc_tof0": (("epoch", "esa_step", "azimuth_60"), np.zeros((1, 7, 6))), + "disc_tof1": (("epoch", "esa_step", "azimuth_60"), np.zeros((1, 7, 6))), + "disc_tof2": (("epoch", "esa_step", "azimuth_60"), np.zeros((1, 7, 6))), + "disc_tof3": (("epoch", "esa_step", "azimuth_60"), np.zeros((1, 7, 6))), + "pos0": (("epoch", "esa_step", "azimuth_60"), np.zeros((1, 7, 6))), + "pos1": (("epoch", "esa_step", "azimuth_60"), np.zeros((1, 7, 6))), + "pos2": (("epoch", "esa_step", "azimuth_60"), np.zeros((1, 7, 6))), + "pos3": (("epoch", "esa_step", "azimuth_60"), np.zeros((1, 7, 6))), + }, + coords={ + "epoch": epoch_date, + "esa_step": np.arange(1, 8), + "azimuth_6": np.arange(60), + "azimuth_60": np.arange(6), + }, + attrs={"Logical_source": "imap_lo_l1a_histogram"}, + ) + return l1a_hist + + +@patch( + "imap_processing.lo.l1b.lo_l1b.frame_transform", + return_value=np.array([[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]), +) +@patch( + "imap_processing.lo.l1b.lo_l1b.lo_instrument_pointing", + return_value=np.zeros((2000, 3)), +) +@patch( + "imap_processing.lo.l1b.lo_l1b.get_pointing_times", + return_value=(473389199, 473472001), +) +@patch("imap_processing.lo.l1b.lo_l1b.get_spin_number", return_value=0) +@patch( + "imap_processing.lo.l1b.lo_l1b.cartesian_to_latitudinal", + return_value=np.zeros((2000, 3)), +) +@patch("imap_processing.lo.l1b.lo_l1b.interpolate_spin_data") +def test_lo_l1b_de( + mock_interpolate_spin_data, + mock_frame_transform, + mock_lo_instrument_pointing, + mocked_get_pointing_times, + mock_spin_number, + mock_cartesian_to_latitudinal, + dependencies, + anc_dependencies, +): # Arrange - de_file = ( - imap_module_directory / "tests/lo/test_cdfs/imap_lo_l1a_de_20241022_v002.cdf" + # Mock the spin data to provide spin start times + # Create a DataFrame covering the time range of the test data + mock_spin_df = pd.DataFrame( + { + "spin_start_met": np.ones([1]), + } + ) + mock_interpolate_spin_data.return_value = mock_spin_df + + # Add l1b_nhk dependency with pivot angle information + l1b_nhk = xr.Dataset( + {"pcc_cumulative_cnt_pri": ("epoch", [45.0])}, + coords={"epoch": [met_to_ttj2000ns(473389200)]}, ) - spin_file = ( - imap_module_directory / "tests/lo/test_cdfs/imap_lo_l1a_spin_20241022_v002.cdf" + dependencies["imap_lo_l1b_nhk"] = l1b_nhk + + expected_logical_source_de = "imap_lo_l1b_de" + + # Act + output_files = lo_l1b(dependencies, anc_dependencies, descriptor="de") + + # Assert + assert expected_logical_source_de == output_files[-1].attrs["Logical_source"] + # Verify that pivot_angle is present in the output + assert "pivot_angle" in output_files[-1] + assert output_files[-1]["pivot_angle"].values[0] == 45.0 + + +@patch("imap_processing.lo.l1b.lo_l1b.get_spin_number", return_value=0) +@patch( + "imap_processing.lo.l1b.lo_l1b.get_pointing_times", + return_value=(473389199, 473472001), +) +def test_lo_l1b_histogram_rates( + mock_repoint_times, mock_spin_number, l1a_hist, anc_dependencies +): + # Arrange + met = et_to_met(str_to_et(["2025-04-15T02:00:00"])) + l1a_spin = xr.Dataset( + { + "shcoarse": ("epoch", [0]), + "num_completed": ("epoch", [28]), + "acq_start_sec": ("epoch", met), + "acq_start_subsec": ("epoch", [0]), + "acq_end_sec": ("epoch", met + 420), + "acq_end_subsec": ("epoch", [0]), + }, + coords={ + "epoch": et_to_ttj2000ns(str_to_et(["2025-04-15T02:00:00"])), + }, + attrs={"Logical_source": "imap_lo_l1a_spin"}, ) - data = {} - for file in [de_file, spin_file]: - dataset = load_cdf(file) - data[dataset.attrs["Logical_source"]] = dataset + sci_dependencies = { + "imap_lo_l1a_histogram": l1a_hist, + "imap_lo_l1a_spin": l1a_spin, + } - expected_logical_source = "imap_lo_l1b_de" - mock_instrument_pointing.return_value = np.zeros((2000, 2)) # Act - output_file = lo_l1b(data) + l1b_datasets = lo_l1b(sci_dependencies, anc_dependencies, descriptor="all-rates") # Assert - assert expected_logical_source == output_file[0].attrs["Logical_source"] + assert "h_rates" in l1b_datasets[-2].data_vars + assert "o_rates" in l1b_datasets[-2].data_vars + assert "exposure_time_6deg" in l1b_datasets[-2].data_vars + assert "h_counts" in l1b_datasets[-2].data_vars + assert "o_counts" in l1b_datasets[-2].data_vars + assert l1b_datasets[-2]["exposure_time_6deg"].values[0, 0, 0] == 2 + # Should be 10x as large + assert l1b_datasets[-1]["exposure_time_60deg"].values[0, 0, 0] == 20 -# @pytest.mark.external_kernel -# @pytest.mark.use_test_metakernel("imap_ena_sim_metakernel.template") def test_create_datasets(): attr_mgr = ImapCdfAttributes() attr_mgr.add_instrument_global_attrs(instrument="lo") @@ -111,6 +332,9 @@ def test_create_datasets(): dataset = create_datasets(attr_mgr, logical_source, data_fields) + # verify that epoch does not have a DEPEND_0 attribute + assert "DEPEND_0" not in dataset["epoch"].attrs + assert len(dataset.tof0.shape) == 1 assert dataset.tof0.shape[0] == 3 assert len(dataset.tof1.shape) == 1 @@ -145,17 +369,60 @@ def test_initialize_dataset(dependencies, attr_mgr_l1b): # Assert assert l1b_de.attrs["Logical_source"] == logical_source assert list(l1b_de.coords.keys()) == [] - assert len(l1b_de.data_vars) == 4 + assert len(l1b_de.data_vars) == 5 assert len(l1b_de.coords) == 0 for l1b_name, l1a_name in { "pos": "pos", - "mode": "mode", + "mode_bit": "mode", "absent": "coincidence_type", "esa_step": "esa_step", }.items(): assert l1b_name in l1b_de.data_vars np.testing.assert_array_equal(l1b_de[l1b_name], l1a_de[l1a_name]) + expected_l1b_shcoarse = np.repeat( + l1a_de["shcoarse"].values, l1a_de["de_count"].values + ) + np.testing.assert_array_equal(l1b_de["shcoarse"], expected_l1b_shcoarse) + + +def test_set_esa_mode(anc_dependencies, attr_mgr_l1b): + # Arrange + l1b_de = xr.Dataset( + {}, + coords={"epoch": [0, 1, 2, 3, 4]}, + ) + pointing_start_met = 473389199 + pointing_end_met = 473472001 + + expected_esa_mode = np.array([0, 0, 0, 0, 0]) + + # Act + l1b_de = set_esa_mode( + pointing_start_met, pointing_end_met, anc_dependencies, l1b_de + ) + + # Assert + np.testing.assert_array_equal(l1b_de["esa_mode"].values, expected_esa_mode) + + +def test_set_esa_mode_error(anc_dependencies, attr_mgr_l1b): + # Arrange + l1b_de = xr.Dataset( + {}, + coords={"epoch": [0, 1, 2, 3, 4]}, + ) + pointing_start_met = 473389199 + pointing_end_met = 509369021 + + # Act / Assert + with pytest.raises( + ValueError, match="Multiple ESA modes found in sweep table for pointing." + ): + l1b_de = set_esa_mode( + pointing_start_met, pointing_end_met, anc_dependencies, l1b_de + ) + def test_convert_start_end_acq_times(): # Arrange @@ -196,61 +463,38 @@ def test_convert_start_end_acq_times(): def test_get_avg_spin_durations(): # Arrange - acq_start = xr.DataArray([0, 423, 846.2], dims="epoch") - acq_end = xr.DataArray([422.8, 846, 1269.7], dims="epoch") - expected_avg_spin_durations = np.array([422.8, 423, 423.5]) / 28 - - # Act - avg_spin_durations = get_avg_spin_durations_per_cycle(acq_start, acq_end) - - # Assert - np.testing.assert_array_equal(avg_spin_durations, expected_avg_spin_durations) - - -def test_get_spin_angle(): - # Arrange - de = xr.Dataset( + spin_ds = xr.Dataset( { - "de_count": ("epoch", [2, 3]), - "de_time": ("direct_event", [0000, 1000, 2000, 3000, 4000]), + "acq_start_sec": ("epoch", [1, 2, 3]), + "acq_start_subsec": ("epoch", [1e6, 2e6, 3e6]), + "acq_end_sec": ("epoch", [100, 200, 300]), + "acq_end_subsec": ("epoch", [1e6, 2e6, 3e6]), + "num_completed": ("epoch", [28, 14, 28]), }, - coords={"epoch": [0, 1], "direct_event": [0, 1, 2, 3, 4]}, + coords={"epoch": [0, 1, 2]}, ) - spin_angle_expected = np.array([0, 87.89, 175.78, 263.67, 351.56]) - - # Act - spin_angle = get_spin_angle(de) - - # Assert - np.testing.assert_allclose( - spin_angle, - spin_angle_expected, - atol=1e-2, + expected_avg_spin_durations = np.array( + [(101 - 2) / 28, (202 - 4) / 14, (303 - 6) / 28] ) - -def test_spin_bin(): - # Arrange - l1b_de = xr.Dataset() - spin_angle = np.array([0, 50, 150, 250, 365]) - expected_spin_bins = np.array([0, 8, 25, 41, 60]) - # Act - l1b_de = set_spin_bin(l1b_de, spin_angle) - + avg_spin_durations = get_avg_spin_durations_per_cycle(spin_ds) # Assert - np.testing.assert_array_equal(l1b_de["spin_bin"], expected_spin_bins) + np.testing.assert_array_equal(avg_spin_durations, expected_avg_spin_durations) -def test_spin_cycle(): +@patch("imap_processing.lo.l1b.lo_l1b.get_spin_number", return_value=0) +def test_spin_cycle(mock_get_spin_number): # Arrange de = xr.Dataset( { "de_count": ("epoch", [2, 3]), "esa_step": ("direct_event", [1, 2, 3, 4, 5]), + "met": ("epoch", [0, 7]), }, coords={"epoch": [0, 1], "direct_event": [1, 2, 3, 4, 5]}, ) + pointing_start_met = 0 # spin_cycle = spin_start + 7 + (esa_step - 1) * 2 # where spin start is the spin number for the first spin @@ -260,53 +504,43 @@ def test_spin_cycle(): spin_cycle_data = xr.Dataset() # Act - spin_cycle_data = set_spin_cycle(de, spin_cycle_data) + spin_cycle_data = set_spin_cycle(pointing_start_met, de, spin_cycle_data) # Assert np.testing.assert_array_equal(spin_cycle_data["spin_cycle"], spin_cycle_expected) -def test_get_spin_start_times(): +@patch("imap_processing.lo.l1b.lo_l1b.interpolate_spin_data") +def test_get_spin_start_times(mock_interpolate_spin_data): # Arrange - l1b_de = xr.Dataset( + # Mock the spin data to return specific spin start times + mock_spin_df = pd.DataFrame( { - "spin_cycle": ("epoch", [0, 1, 2, 3, 4]), - }, - coords={ - "epoch": [ - 0, - 1, - 2, - 3, - 4, - ] - }, + "spin_start_met": [10.5, 30.1], + } ) + mock_interpolate_spin_data.return_value = mock_spin_df + l1a_de = xr.Dataset( { + "met": ("epoch", [15, 35]), "de_count": ("epoch", [2, 3]), - "met": ("direct_event", [0, 1, 2, 3, 4]), - "de_time": ("direct_event", [0000, 1000, 2000, 3000, 4000]), + "de_time": ("direct_event", [0, 1000, 2000, 3000, 4000]), }, coords={"epoch": [0, 1], "direct_event": [0, 1, 2, 3, 4]}, ) - spin = xr.Dataset( - { - "start_sec_spin": ( - ["epoch", "spin"], - [[20, 25, 30, 35, 40], [45, 50, 55, 60, 65]], - ), - "start_subsec_spin": ( - ["epoch", "spin"], - [[2000, 3000, 4000, 5000, 6000], [1000, 1500, 2000, 3000, 4000]], - ), - } + + # Expected: met 15 should match spin at index 0 (10 < 15 < 20) + # met 35 should match spin at index 2 (30 < 35 < 40) + # Repeated by de_count: [2, 3] -> [index0, index0, index2, index2, index2] + spin_start_times_expected = np.array( + [10.5, 10.5, 30.1, 30.1, 30.1] # 10 + 0.5e6*1e-6 # 30 + 0.1e6*1e-6 ) - end_acq = xr.DataArray([0, 1], dims="epoch") - spin_start_times_expected = np.array([20.002, 50.0015, 55.002, 60.003, 65.004]) - spin_start_times = get_spin_start_times(l1a_de, l1b_de, spin, end_acq) + # Act + spin_start_times = get_spin_start_times(l1a_de) + # Assert np.testing.assert_allclose( spin_start_times, spin_start_times_expected, @@ -314,31 +548,44 @@ def test_get_spin_start_times(): ) -def test_set_event_met(): +@patch("imap_processing.lo.l1b.lo_l1b.interpolate_spin_data") +def test_set_event_met(mock_interpolate_spin_data): # Arrange + # Mock the spin data + mock_spin_df = pd.DataFrame( + { + "spin_start_met": [10, 30], + } + ) + mock_interpolate_spin_data.return_value = mock_spin_df + l1b_de = xr.Dataset() l1a_de = xr.Dataset( { + "met": ("epoch", [15, 35]), "de_count": ("epoch", [2, 3]), - "de_time": ("direct_event", [0000, 1000, 2000, 3000, 4000]), + "de_time": ("direct_event", [0, 1000, 2000, 3000, 4000]), }, coords={ "epoch": [0, 1], - "direct_event": [ - 0, - 1, - 2, - 3, - 4, - ], + "direct_event": [0, 1, 2, 3, 4], }, ) - avg_spin_durations = xr.DataArray([5, 10]) - spin_start_times = xr.DataArray([10, 20, 30, 40, 50]) - expected_event_met = np.array([10, 21.2207, 34.8828, 47.3242, 59.7656]) + + # met 15 -> spin_start 10, met 35 -> spin_start 30 + # event_met = spin_start + de_time * DE_CLOCK_TICK_S + expected_event_met = np.array( + [ + 10 + 0 * DE_CLOCK_TICK_S, # 10.0 + 10 + 1000 * DE_CLOCK_TICK_S, # 14.096 + 30 + 2000 * DE_CLOCK_TICK_S, # 38.192 + 30 + 3000 * DE_CLOCK_TICK_S, # 42.288 + 30 + 4000 * DE_CLOCK_TICK_S, # 46.384 + ] + ) # Act - l1b_de = set_event_met(l1a_de, l1b_de, spin_start_times, avg_spin_durations) + l1b_de = set_event_met(l1a_de, l1b_de) # Assert np.testing.assert_allclose( @@ -347,24 +594,25 @@ def test_set_event_met(): atol=1e-4, ) - def test_set_each_event_epoch(): - l1b_de = xr.Dataset( - { - "event_met": ("epoch", [10, 20, 30, 40, 50]), - }, - coords={ - "epoch": [0, 1, 2, 3, 4], - }, - ) - epoch_expected = met_to_ttj2000ns(np.array([10, 20, 30, 40, 50])) - l1b_de = set_each_event_epoch(l1b_de) +def test_set_each_event_epoch(): + l1b_de = xr.Dataset( + { + "event_met": ("epoch", [10, 20, 30, 40, 50]), + }, + coords={ + "epoch": [0, 1, 2, 3, 4], + }, + ) + epoch_expected = met_to_ttj2000ns(np.array([10, 20, 30, 40, 50])) - np.testing.assert_allclose( - l1b_de["epoch"].values, - epoch_expected, - atol=1e-4, - ) + l1b_de = set_each_event_epoch(l1b_de) + + np.testing.assert_allclose( + l1b_de["epoch"].values, + epoch_expected, + atol=1e-4, + ) def test_set_avg_spin_durations_per_event(): @@ -405,7 +653,7 @@ def test_calculate_tof1_for_golden_triples(): "coincidence_type": ("epoch", [0, 0, 0]), "mode": ("epoch", [0, 0, 1]), "tof0": ("epoch", [2, 4, 2]), - "tof1": ("epoch", [42, 36, 0]), + "tof1": ("epoch", [0, 0, 42]), "tof2": ("epoch", [2, 6, 2]), "tof3": ("epoch", [2, 8, 2]), "cksm": ("epoch", [2, 12, 2]), @@ -416,7 +664,7 @@ def test_calculate_tof1_for_golden_triples(): l1a_de = calculate_tof1_for_golden_triples(l1a_de) # Assert - assert l1a_de_expected.equals(l1a_de) + xr.testing.assert_equal(l1a_de, l1a_de_expected) def test_set_coincidence_type(attr_mgr_l1a): @@ -476,7 +724,7 @@ def test_convert_tofs_to_eu(attr_mgr_l1b, attr_mgr_l1a): tof0_expected = np.array([1.394394, 0.889272]) tof1_expected = np.array([0.931059, tof_fill_l1b]) tof2_expected = np.array([2.870557, 1.372876]) - tof3_expected = np.array([3.88245, 1.818162]) + tof3_expected = np.array([3.89606, 1.83878]) # Act l1b_de = convert_tofs_to_eu(l1a_de, l1b_de, attr_mgr_l1a, attr_mgr_l1b) @@ -514,89 +762,2142 @@ def test_identify_species(attr_mgr_l1b): np.testing.assert_array_equal(l1b_de["species"], expected_species) -def test_set_bad_times(): +@patch( + "imap_processing.lo.l1b.lo_l1b.lo_instrument_pointing", + return_value=np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]), +) +def test_set_direction(mock_lo_instrument_pointing, imap_ena_sim_metakernel): # Arrange l1b_de = xr.Dataset( - {}, - coords={ - "epoch": [0, 1, 2], + { + "pivot_angle": ("epoch", [0, 0, 0, 0]), }, - ) - - expected_bad_times = np.array([0, 0, 0]) - - # Act - l1b_de = set_bad_times(l1b_de) - - # Assert - np.testing.assert_array_equal(l1b_de["badtimes"], expected_bad_times) - - -@pytest.mark.external_kernel -def test_set_direction(imap_ena_sim_metakernel): - # Arrange - l1b_de = xr.Dataset( - {}, coords={ - "epoch": [ - 7.9794907254e17, - # + 1 second. Should be 24deg diff from - # previous epoch - 7.9794907254e17 + 1e9, - # + 7.5 seconds. Should be 180deg diff from - # first epoch - 7.9794907254e17 + 7.5e9, - # + 15 seconds. Should be 360deg diff from - # previous epoch - 7.9794907254e17 + 15e9, - ], + "epoch": [0, 1, 2, 3], }, ) # latitudes are -90 to 90 - expected_direction_lat = np.array([0, 0, 0, 0]) - # longitude are -180 to 180 - expected_direction_lon = np.array([140.5, 164.5, -39.5, 140.5]) + expected_hae_x = np.array([1, 4, 7, 10]) + expected_hae_y = np.array([2, 5, 8, 11]) + expected_hae_z = np.array([3, 6, 9, 12]) # Act l1b_de = set_pointing_direction(l1b_de) # Assert np.testing.assert_allclose( - l1b_de["direction_lat"].values, - expected_direction_lat, + l1b_de["hae_x"].values, + expected_hae_x, atol=1e-1, ) np.testing.assert_allclose( - l1b_de["direction_lon"].values, - expected_direction_lon, + l1b_de["hae_y"].values, + expected_hae_y, atol=1e-1, ) + np.testing.assert_allclose( + l1b_de["hae_z"].values, + expected_hae_z, + atol=1e-1, + ) + + +@pytest.mark.parametrize("pivot_angle", [75, 90, 105]) +def test_pointing_bins(pivot_angle): + # Arrange - Mock returns depend on pivot_angle + # Calculate offset based on pivot angle: lats = lats - (90 - pivot_angle) + offset = 90 - pivot_angle + + with ( + patch( + "imap_processing.lo.l1b.lo_l1b.frame_transform", + return_value=np.array([[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]), + ), + patch( + "imap_processing.lo.l1b.lo_l1b.cartesian_to_latitudinal", + # Adjust latitude values based on pivot angle offset + # Longitudes: -180 -> 180, 0 -> 0, 90 -> 90, 180 -> 180 + # After shift to 0-360: 180, 0, 90, 180 + return_value=np.array( + [ + [0, -180, -2 + offset], + [0, 0, 0 + offset], + [0, 90, 1 + offset], + [0, 180, 2 + offset], + ] + ), + ), + ): + l1b_de = xr.Dataset( + { + "hae_x": ("epoch", [1, 1, 1, 1]), + "hae_y": ("epoch", [0, 0, 0, 0]), + "hae_z": ("epoch", [0, 0, 0, 0]), + }, + coords={ + "epoch": [ + 7.9794907049e17, + 7.9794907153e17, + 7.9794907254e17, + 7.9794907354e17, + ], + "pivot_angle": [pivot_angle], + }, + ) + + expected_pointing_lats = np.array([0, 20, 30, 40]) + # Longitude bins are now in 0-360 range after the shift + expected_pointing_lons = np.array([1800, 0, 900, 1800]) + + # Act + l1b_de = set_pointing_bin(l1b_de) + + # Assert + np.testing.assert_array_equal(l1b_de["off_angle_bin"], expected_pointing_lats) + np.testing.assert_array_equal(l1b_de["spin_bin"], expected_pointing_lons) + + +def test_badtimes_no_spin(): + """An empty dataset should still be returned when no spin data is found.""" + badtimes_ds = create_badtimes_dataset() + + assert len(badtimes_ds["epoch"]) == 0 + # We should have put empty variables into the dataset + assert "BadTime_start" in badtimes_ds.data_vars + + +def test_badtimes_with_spin(spice_test_data_path, use_test_spin_data_csv): + """Verify some actual badtimes are created from thruster firings.""" + # Initialize the spin data + fake_spin_path = spice_test_data_path / "fake_spin_data.csv" + use_test_spin_data_csv([fake_spin_path]) + + badtimes_ds = create_badtimes_dataset() + spin_df = get_spin_data() + + thruster_df = spin_df[spin_df["thruster_firing"]] + n_thruster_firings = len(thruster_df) + # We should have some thruster firings + assert n_thruster_firings > 0 + + # Check the thruster firings we created match those in the spin data + assert len(badtimes_ds["epoch"]) == n_thruster_firings + np.testing.assert_array_equal( + badtimes_ds["BadTime_start"], thruster_df["spin_start_sec_sclk"] + ) + np.testing.assert_array_equal(badtimes_ds["badtime_flag"], 1) + # There should be a dataset returned from the main code in this case + datasets = lo_l1b({}, [], descriptor="badtimes") + assert len(datasets) == 1 -def test_pointing_bins(): + +def test_l1b_badtimes_skipped_if_empty(): + datasets = lo_l1b({}, [], descriptor="badtimes") + assert len(datasets) == 0 + + +def test_lo_l1b_unexpected_descriptor(caplog): + """Test that an unexpected descriptor logs a warning and returns empty list.""" + datasets = lo_l1b({}, [], descriptor="unknown") + assert len(datasets) == 0 + assert "Unexpected descriptor: 'unknown'" in caplog.text + + +def test_resweep_histogram_success(l1b_histrates, anc_dependencies): # Arrange - l1b_de = xr.Dataset( + epoch_date = et_to_ttj2000ns( + str_to_et(["2025-04-15T02:00:00", "2025-04-15T03:00:00"]) + ) + l1b_histrates["epoch"] = epoch_date + exposure_factor_6deg = np.full((2, 7, 60), 4) + exposure_factor_60deg = np.full((2, 7, 6), 4) + exposure_factor_6deg[:, 0, :] = 8 + exposure_factor_60deg[:, 0, :] = 8 + exposure_factor_6deg[:, 1, :] = 0 + exposure_factor_60deg[:, 1, :] = 0 + + l1b_histrates.h_counts[0, 0, 0] = 5 + l1b_histrates.h_counts[0, 1, 0] = 10 + l1b_histrates.h_counts[0, 2, 0] = 2 + l1b_histrates.o_counts[1, 0, 0] = 2 + l1b_histrates.o_counts[1, 1, 0] = 3 + l1b_histrates.o_counts[1, 2, 0] = 4 + + l1b_histrates, exposure_factor = resweep_histogram_data( + l1b_histrates, anc_dependencies + ) + + assert l1b_histrates.h_counts[0, 0, 0] == 15 + assert l1b_histrates.h_counts[0, 1, 0] == 0 + assert l1b_histrates.h_counts[0, 2, 0] == 2 + + assert l1b_histrates.o_counts[1, 0, 0] == 5 + assert l1b_histrates.o_counts[1, 1, 0] == 0 + assert l1b_histrates.o_counts[1, 2, 0] == 4 + + for field in SPIN_BIN_6_FIELDS + SPIN_BIN_60_FIELDS: + np.testing.assert_array_equal(l1b_histrates[field], l1b_histrates[field]) + np.testing.assert_array_equal(exposure_factor["6deg"], exposure_factor_6deg) + np.testing.assert_array_equal(exposure_factor["60deg"], exposure_factor_60deg) + + +def test_resweep_histogram_no_date_in_sweep(l1b_histrates, anc_dependencies, caplog): + # Arrange + epoch_date = et_to_ttj2000ns( + str_to_et(["2025-04-25T02:00:00", "2025-04-25T03:00:00"]) + ) + l1b_histrates["epoch"] = epoch_date + + l1b_histrates.h_counts[0, 0, 0] = 5 + l1b_histrates.h_counts[0, 1, 0] = 10 + l1b_histrates.h_counts[0, 2, 0] = 2 + + pytest.raises(ValueError, resweep_histogram_data, l1b_histrates, anc_dependencies) + + +def test_resweep_histogram_no_table_in_lut(l1b_histrates, anc_dependencies, caplog): + # Arrange + epoch_date = et_to_ttj2000ns( + str_to_et(["2024-01-01T02:00:00", "2024-01-01T03:00:00"]) + ) + l1b_histrates["epoch"] = epoch_date + + l1b_histrates.h_counts[0, 0, 0] = 5 + l1b_histrates.h_counts[0, 1, 0] = 10 + l1b_histrates.h_counts[0, 2, 0] = 2 + + with caplog.at_level(logging.WARNING): + result, _ = resweep_histogram_data(l1b_histrates, anc_dependencies) + + resweep_histogram_data(l1b_histrates, anc_dependencies) + # Check that warning was logged + assert any( + "No LUT entries for epoch" in record.message for record in caplog.records + ) + + +def test_resweep_histogram_multiple_lut(l1b_histrates, anc_dependencies, caplog): + epoch_date = et_to_ttj2000ns( + str_to_et(["2025-04-16T02:00:00", "2025-04-16T03:00:00"]) + ) + + l1b_histrates["epoch"] = epoch_date + + with caplog.at_level(logging.WARNING): + result, _ = resweep_histogram_data(l1b_histrates, anc_dependencies) + + # Check that warning was logged + assert any( + "Multiple LUT tables found for epoch" in record.message + for record in caplog.records + ) + assert any("but found tables" in record.message for record in caplog.records) + + +def test_calculate_histogram_rates(l1b_histrates): + acq_start = xr.DataArray( + [ + et_to_met(str_to_et("2025-04-15T01:55:00")), + et_to_met(str_to_et("2025-04-15T02:55:00")), + ] + ) + acq_end = xr.DataArray( + [ + et_to_met(str_to_et("2025-04-15T02:02:00")), + et_to_met(str_to_et("2025-04-15T03:02:00")), + ] + ) + avg_spin_durations_per_cycle = xr.DataArray([30, 15]) + # default zeros then set a sample exposure as in original test intent + exposure_factors_6deg = np.zeros((2, 7, 60)) + exposure_factors_60deg = np.zeros((2, 7, 6)) + exposure_factors_6deg[0, 0, 0] = 1 + exposure_factors_60deg[0, 0, 0] = 1 + exposure_factors_6deg[0, 1, 0] = 0 + exposure_factors_60deg[0, 1, 0] = 0 + + exposure_factors = {} + exposure_factors["6deg"] = exposure_factors_6deg + exposure_factors["60deg"] = exposure_factors_60deg + + # Populate counts used by assertions + l1b_histrates.h_counts[0, 0, 0] = 30 + l1b_histrates.h_counts[0, 1, 0] = 10 + l1b_histrates.h_counts[0, 2, 0] = 2 + l1b_histrates.h_counts[1, 0, 0] = 15 + l1b_histrates.h_counts[1, 1, 0] = 30 + l1b_histrates.h_counts[1, 2, 0] = 45 + + l1b_histrates.o_counts[0, 0, 0] = 100 + l1b_histrates.o_counts[0, 1, 0] = 50 + l1b_histrates.o_counts[0, 2, 0] = 25 + l1b_histrates.o_counts[1, 0, 0] = 2 + l1b_histrates.o_counts[1, 1, 0] = 3 + l1b_histrates.o_counts[1, 2, 0] = 4 + + l1b_histrate = calculate_histogram_rates( + l1b_histrates, + acq_start, + acq_end, + avg_spin_durations_per_cycle, + exposure_factors, + ) + + hist_rates_h_epoch_0 = l1b_histrate["h_rates"] + hist_rates_h_epoch_0[0, :, :] = hist_rates_h_epoch_0[0, :, :] / 2 + hist_rates_h_epoch_0[0, :, 0] = hist_rates_h_epoch_0[0, :, 0] / 2 + hist_rates_o_epoch_0 = l1b_histrate["o_rates"] + hist_rates_o_epoch_0[0, :, :] = hist_rates_o_epoch_0[0, :, :] / 2 + hist_rates_o_epoch_0[0, :, 0] = hist_rates_o_epoch_0[0, :, 0] / 2 + + np.testing.assert_array_equal( + l1b_histrate["h_rates"][0, :, :], hist_rates_h_epoch_0[0, :, :] + ) + np.testing.assert_array_equal( + l1b_histrate["h_rates"][1, :, :], hist_rates_h_epoch_0[1, :, :] + ) + np.testing.assert_array_equal( + l1b_histrate["o_rates"][0, :, :], hist_rates_o_epoch_0[0, :, :] + ) + np.testing.assert_array_equal( + l1b_histrate["o_rates"][1, :, :], hist_rates_o_epoch_0[1, :, :] + ) + + +def test_calculate_histogram_rates_no_interval_found(l1b_histrates): + acq_start = xr.DataArray( + [ + et_to_met(str_to_et("2025-04-30T01:55:00")), + et_to_met(str_to_et("2025-04-30T02:55:00")), + ] + ) + acq_end = xr.DataArray( + [ + et_to_met(str_to_et("2025-04-30T02:02:00")), + et_to_met(str_to_et("2025-04-30T03:02:00")), + ] + ) + avg_spin_durations_per_cycle = xr.DataArray([30, 15]) + + exposure_factors_6deg = np.zeros((2, 7, 60)) + exposure_factors_60deg = np.zeros((2, 7, 6)) + exposure_factors = {} + exposure_factors["6deg"] = exposure_factors_6deg + exposure_factors["60deg"] = exposure_factors_60deg + + l1b_histrate = calculate_histogram_rates( + l1b_histrates, + acq_start, + acq_end, + avg_spin_durations_per_cycle, + exposure_factors, + ) + + np.testing.assert_array_equal(l1b_histrate["h_rates"], np.zeros((2, 7, 60))) + np.testing.assert_array_equal(l1b_histrate["o_rates"], np.zeros((2, 7, 60))) + + +def test_calculate_histogram_rates_zero_exposure_time(l1b_histrates): + acq_start = xr.DataArray( + [ + et_to_met(str_to_et("2025-04-15T01:55:00")), + et_to_met(str_to_et("2025-04-15T02:55:00")), + ] + ) + acq_end = xr.DataArray( + [ + et_to_met(str_to_et("2025-04-15T02:02:00")), + et_to_met(str_to_et("2025-04-15T03:02:00")), + ] + ) + avg_spin_durations_per_cycle = xr.DataArray([0, 15]) + + exposure_factors_6deg = np.zeros((2, 7, 60)) + exposure_factors_60deg = np.zeros((2, 7, 6)) + exposure_factors = {} + exposure_factors["6deg"] = exposure_factors_6deg + exposure_factors["60deg"] = exposure_factors_60deg + + l1b_histrate = calculate_histogram_rates( + l1b_histrates, + acq_start, + acq_end, + avg_spin_durations_per_cycle, + exposure_factors, + ) + + np.testing.assert_array_equal(l1b_histrate["h_rates"], np.zeros((2, 7, 60))) + np.testing.assert_array_equal(l1b_histrate["o_rates"], np.zeros((2, 7, 60))) + + +def test_set_spin_cycle_from_spin_data_histogram(): + """Test spin cycle calculation for histogram data.""" + # Arrange + epoch_date = et_to_ttj2000ns( + str_to_et(["2025-04-15T02:00:00", "2025-04-15T03:00:00"]) + ) + l1a_hist = xr.Dataset( { - "direction_lat": ("epoch", [0, 0, 0, 0, 0]), - "direction_lon": ("epoch", [-180, 91.3, 116.3, 140.5, 180]), + "hydrogen": (("epoch", "esa_step", "azimuth_6"), np.zeros((2, 7, 60))), }, coords={ - "epoch": [ - 7.9794907049e17, - 7.9794907153e17, - 7.9794907254e17, - 7.9794907354e17, - 7.9794907454e17, - ], + "epoch": epoch_date, + "esa_step": np.arange(1, 8), + "azimuth_6": np.arange(60), }, + attrs={"Logical_source": "imap_lo_l1a_histogram"}, ) - expected_pointing_lats = np.array([20, 20, 20, 20, 20]) - expected_pointing_lons = np.array([0, 2712, 2962, 3205, 3600]) + l1b_hist = xr.Dataset( + coords={ + "epoch": epoch_date, + "esa_step": np.arange(1, 8), + } + ) + + met_times = ttj2000ns_to_met(epoch_date) + spin_data = xr.Dataset( + { + "shcoarse": ("epoch", met_times), + "num_completed": ("epoch", [28, 28]), + "acq_start_sec": ("epoch", met_times), + "acq_start_subsec": ("epoch", [0, 0]), + "acq_end_sec": ("epoch", met_times), + "acq_end_subsec": ("epoch", [0, 0]), + }, + coords={ + "epoch": epoch_date, + }, + ) + + # Mock get_spin_number to return predictable values + with patch( + "imap_processing.lo.l1b.lo_l1b.get_spin_number", return_value=np.array([0, 28]) + ): + # Act + l1b_hist = set_spin_cycle_from_spin_data(l1a_hist, l1b_hist, spin_data) + + # Expected: spin_cycle = spin_start + 7 + (esa_step - 1) * 2 + # For epoch 0: 0 + 7 + (1-1)*2 = 7, (2-1)*2 = 9, ..., (7-1)*2 = 19 + # For epoch 1: 28 + 7 + (1-1)*2 = 35, ..., 28 + 7 + (7-1)*2 = 47 + expected_spin_cycles = np.array( + [[7, 9, 11, 13, 15, 17, 19], [35, 37, 39, 41, 43, 45, 47]] + ) + + # Assert + assert "spin_cycle" in l1b_hist.data_vars + np.testing.assert_array_equal(l1b_hist["spin_cycle"].values, expected_spin_cycles) + + +def test_set_spin_cycle_from_spin_data_matching_ascs(): + """Test that science ASCs correctly match to spin ASCs.""" + # Arrange - Science ASCs that should match different spin ASCs + science_met = [100, 200, 300] + spin_met = [50, 150, 250] # Science times fall after these spin times + + epoch_date = met_to_ttj2000ns(science_met) + l1a_hist = xr.Dataset( + { + "hydrogen": (("epoch", "esa_step"), np.zeros((3, 7))), + }, + coords={ + "epoch": epoch_date, + "esa_step": np.arange(1, 8), + }, + attrs={"Logical_source": "imap_lo_l1a_histogram"}, + ) + + l1b_hist = xr.Dataset(coords={"epoch": epoch_date, "esa_step": np.arange(1, 8)}) + + spin_data = xr.Dataset( + { + "shcoarse": ("epoch", spin_met), + "num_completed": ("epoch", [28, 28, 28]), + "acq_start_sec": ("epoch", spin_met), + "acq_start_subsec": ("epoch", [0, 0, 0]), + "acq_end_sec": ("epoch", spin_met), + "acq_end_subsec": ("epoch", [0, 0, 0]), + }, + coords={"epoch": met_to_ttj2000ns(spin_met)}, + ) + + with patch( + "imap_processing.lo.l1b.lo_l1b.get_spin_number", + return_value=np.array([0, 28, 56]), + ): + # Act + l1b_hist = set_spin_cycle_from_spin_data(l1a_hist, l1b_hist, spin_data) + + # Assert - Each epoch should use the correct spin start number + assert l1b_hist["spin_cycle"][0, 0] == 7 # 0 + 7 + 0 + assert l1b_hist["spin_cycle"][1, 0] == 35 # 28 + 7 + 0 + assert l1b_hist["spin_cycle"][2, 2] == 67 # 56 + 7 + 2*2 + + +def test_set_spin_cycle_from_spin_data_repeated_closest(): + """Test when multiple science ASCs map to the same spin ASC.""" + # Arrange - Multiple science ASCs close to the same spin ASC + science_met = [100, 101, 200, 201] + spin_met = [50, 150] # First two science ASCs map to spin[0], last two to spin[1] + + epoch_date = met_to_ttj2000ns(science_met) + l1a_hist = xr.Dataset( + { + "hydrogen": (("epoch", "esa_step"), np.zeros((4, 7))), + }, + coords={ + "epoch": epoch_date, + "esa_step": np.arange(1, 8), + }, + attrs={"Logical_source": "imap_lo_l1a_histogram"}, + ) + + l1b_hist = xr.Dataset(coords={"epoch": epoch_date, "esa_step": np.arange(1, 8)}) + + spin_data = xr.Dataset( + { + "shcoarse": ("epoch", spin_met), + "num_completed": ("epoch", [28, 28]), + "acq_start_sec": ("epoch", spin_met), + "acq_start_subsec": ("epoch", [0, 0]), + "acq_end_sec": ("epoch", spin_met), + "acq_end_subsec": ("epoch", [0, 0]), + }, + coords={"epoch": met_to_ttj2000ns(spin_met)}, + ) + + with patch( + "imap_processing.lo.l1b.lo_l1b.get_spin_number", + return_value=np.array([10, 10, 38, 38]), + ): + # Act + l1b_hist = set_spin_cycle_from_spin_data(l1a_hist, l1b_hist, spin_data) + + # Assert - First two should use spin 10, last two should use spin 38 + assert l1b_hist["spin_cycle"][0, 0] == 17 # 10 + 7 + 0 + assert l1b_hist["spin_cycle"][1, 0] == 17 # 10 + 7 + 0 (same spin) + assert l1b_hist["spin_cycle"][2, 0] == 45 # 38 + 7 + 0 + assert l1b_hist["spin_cycle"][3, 0] == 45 # 38 + 7 + 0 (same spin) + + +def test_set_spin_cycle_from_spin_data_all_esa_steps(): + """Test that all ESA steps get correct spin cycles.""" + # Arrange + epoch_date = et_to_ttj2000ns(str_to_et(["2025-04-15T02:00:00"])) + l1a_hist = xr.Dataset( + { + "hydrogen": (("epoch", "esa_step"), np.zeros((1, 7))), + }, + coords={ + "epoch": epoch_date, + "esa_step": np.arange(1, 8), + }, + attrs={"Logical_source": "imap_lo_l1a_histogram"}, + ) + + l1b_hist = xr.Dataset(coords={"epoch": epoch_date, "esa_step": np.arange(1, 8)}) + + met_time = ttj2000ns_to_met(epoch_date) + spin_data = xr.Dataset( + { + "shcoarse": ("epoch", [met_time[0]]), + "num_completed": ("epoch", [28]), + "acq_start_sec": ("epoch", [met_time[0]]), + "acq_start_subsec": ("epoch", [0]), + "acq_end_sec": ("epoch", [met_time[0]]), + "acq_end_subsec": ("epoch", [0]), + }, + coords={"epoch": epoch_date}, + ) + + with patch( + "imap_processing.lo.l1b.lo_l1b.get_spin_number", return_value=np.array([0]) + ): + # Act + l1b_hist = set_spin_cycle_from_spin_data(l1a_hist, l1b_hist, spin_data) + + # Assert - Verify the formula: spin_start + 7 + (esa_step - 1) * 2 + expected = np.array([7, 9, 11, 13, 15, 17, 19]) + np.testing.assert_array_equal(l1b_hist["spin_cycle"].values[0], expected) + + +def test_set_spin_cycle_from_spin_data_insufficient_spins(): + """Test that ASCs with fewer than 28 spins are filtered out.""" + # Arrange - Mix of valid and invalid spin counts + science_met = [100, 200, 300] + spin_met = [50, 150, 250] + + epoch_date = met_to_ttj2000ns(science_met) + l1a_hist = xr.Dataset( + { + "hydrogen": (["epoch", "esa_step", "azimuth"], np.ones((3, 7, 60))), + "oxygen": (["epoch", "esa_step", "azimuth"], np.ones((3, 7, 60))), + }, + coords={ + "epoch": epoch_date, + "esa_step": np.arange(1, 8), + "azimuth": np.arange(60), + }, + attrs={"Logical_source": "imap_lo_l1a_histogram"}, + ) + + l1b_hist = xr.Dataset(coords={"epoch": epoch_date, "esa_step": np.arange(1, 8)}) + + # Spin data with mixed valid/invalid counts + spin_data = xr.Dataset( + { + "shcoarse": ("epoch", spin_met), + "num_completed": ("epoch", [20, 28, 15]), # 20 and 15 are < 28 + "acq_start_sec": ("epoch", np.array([50, 150, 250])), + "acq_start_subsec": ("epoch", np.zeros(3)), + "acq_end_sec": ("epoch", np.array([78, 178, 278])), + "acq_end_subsec": ("epoch", np.zeros(3)), + }, + coords={"epoch": np.arange(3)}, + ) # Act - l1b_de = set_pointing_bin(l1b_de) + with patch( + "imap_processing.lo.l1b.lo_l1b.get_spin_number", + return_value=np.array([28, 26, 24]), + ): + result = set_spin_cycle_from_spin_data(l1a_hist, l1b_hist, spin_data) + + assert len(result["epoch"]) == 3 + np.testing.assert_array_equal(result["epoch"].values, epoch_date) + + # Verify spin_cycle shape has all valid ESA steps and all epochs + assert result["spin_cycle"].shape == (3, 7) + # We should have added a flag about an incomplete ASC + np.testing.assert_array_equal(result["incomplete_asc"], [True, False, True]) + + +@patch( + "imap_processing.lo.l1b.lo_l1b.get_pointing_times", + return_value=(473389199, 473472001), +) +@patch( + "imap_processing.lo.l1b.lo_l1b._get_esa_level_indices", + return_value=np.arange(7), +) +def test_calculate_de_rates( + mock_get_esa_level_indices, mock_get_pointing_times, attr_mgr_l1b, anc_dependencies +): + """Test the calculate_de_rates function.""" + # Use MET times from the test sweep table (2025-01-01) + met_start = 473389200 + epoch_time = met_to_ttj2000ns([met_start, met_start + 15 * 28]) + + # Create individual epochs for each direct event in TTJ2000ns + de_epochs = met_to_ttj2000ns( + [ + met_start + 10, + met_start + 20, + met_start + 30, + met_start + 15 * 28 + 10, + met_start + 15 * 28 + 20, + ] + ) + + # Create a simple l1b_de dataset with a few direct events + l1b_de = xr.Dataset( + { + "spin_cycle": ("epoch", [7, 9, 11, 35, 37]), + "esa_step": ("epoch", [1, 2, 3, 1, 2]), + "spin_bin": ("epoch", [0, 120, 240, 60, 180]), + "species": ("epoch", ["H", "O", "H", "H", "O"]), + "coincidence_type": ( + "epoch", + ["111111", "110100", "111000", "101000", "100100"], + ), + "avg_spin_durations": ("epoch", [15.0, 15.0, 15.0, 15.0, 15.0]), + }, + coords={"epoch": de_epochs}, + ) + + # Create l1a_spin dataset + l1a_spin = xr.Dataset( + { + "shcoarse": ("epoch", [met_start, met_start + 15 * 28]), + "num_completed": ("epoch", [28, 28]), + "acq_start_sec": ("epoch", [met_start, met_start + 15 * 28]), + "acq_start_subsec": ("epoch", [0, 0]), + "acq_end_sec": ("epoch", [met_start + 15 * 28, met_start + 2 * 15 * 28]), + "acq_end_subsec": ("epoch", [0, 0]), + }, + coords={"epoch": epoch_time}, + ) + + # Create l1b_nhk dataset with pivot angle information + l1b_nhk = xr.Dataset( + {"pcc_cumulative_cnt_pri": ("epoch", [45.0])}, + coords={"epoch": epoch_time[:1]}, + ) + + # Add pivot_angle to l1b_de (normally set from l1b_nhk in l1b_de function) + l1b_de["pivot_angle"] = xr.DataArray([45.0], dims=["pivot_angle"]) + + sci_dependencies = { + "imap_lo_l1b_de": l1b_de, + "imap_lo_l1a_spin": l1a_spin, + "imap_lo_l1b_nhk": l1b_nhk, + } + + result = calculate_de_rates(sci_dependencies, anc_dependencies, attr_mgr_l1b) + + # Test that result can be written to CDF - this verifies that + # attributes are ok with cdflib + _ = write_cdf(result) + + assert result.attrs["Logical_source"] == "imap_lo_l1b_derates" + assert "epoch" in result.coords + assert "esa_step" in result.coords + assert "spin_bin" in result.coords + + # Check that all expected data variables are present + expected_vars = [ + "h_counts", + "o_counts", + "triple_counts", + "double_counts", + "h_rates", + "o_rates", + "triple_rates", + "double_rates", + "exposure_time", + "spin_cycle", + "esa_mode", + ] + for var in expected_vars: + assert var in result.data_vars + + # Check shapes + assert result["h_counts"].shape == (2, 7, 60) # (num_asc, num_esa_steps, num_bins) + assert result["o_counts"].shape == (2, 7, 60) + assert result["exposure_time"].shape == (2, 7) + + # Verify some counts are correct based on our test data + # First ASC (spin_cycle 0) has 3 events at esa_step 1, 2, 3 + # Second ASC (spin_cycle 28) has 2 events at esa_step 1, 2 + # H species: indices 0, 2, 3 + # ASC 0 has 2 H (esa_step 1, 3), ASC 1 has 1 H (esa_step 1) + # O species: indices 1, 4 + # ASC 0 has 1 O (esa_step 2), ASC 1 has 1 O (esa_step 2) + # First ASC, esa_step 1, spin_bin 0 + assert result["h_counts"][0, 0, 0] == 1 + # First ASC, esa_step 3, spin_bin 4 (240//60) + assert result["h_counts"][0, 2, 4] == 1 + # First ASC, esa_step 2, spin_bin 2 (120//60) + assert result["o_counts"][0, 1, 2] == 1 + + # Check that pivot angle was set + assert result["pivot_angle"].values[0] == 45.0 + + # Test that lo_l1b() with descriptor="derates" produces the correct output + output_datasets = lo_l1b(sci_dependencies, anc_dependencies, descriptor="derates") + assert len(output_datasets) == 1 + assert output_datasets[0].attrs["Logical_source"] == "imap_lo_l1b_derates" + + +# ============================================================================ +# Star Sensor L1B Tests +# ============================================================================ +class TestGetSamplingCadenceFromNhk: + """Tests for get_sampling_cadence_from_nhk function.""" + + def test_extracts_mean_cadence(self): + """Test extracting sampling cadence from NHK dataset.""" + # Arrange + l1b_nhk = xr.Dataset( + { + "ifb_data_interval": ("epoch", [20.0, 20.5, 21.0]), + }, + coords={"epoch": [0, 1, 2]}, + ) + expected_cadence = 20.5 # Mean of [20.0, 20.5, 21.0] + + # Act + sampling_cadence = get_sampling_cadence_from_nhk(l1b_nhk) + + # Assert + assert sampling_cadence == expected_cadence + + def test_raises_error_when_field_missing(self): + """Test error when ifb_data_interval field is missing.""" + # Arrange + l1b_nhk = xr.Dataset( + { + "other_field": ("epoch", [1, 2, 3]), + }, + coords={"epoch": [0, 1, 2]}, + ) + + # Act / Assert + with pytest.raises( + KeyError, + match="ifb_data_interval field not found in L1B NHK dataset", + ): + get_sampling_cadence_from_nhk(l1b_nhk) + + +class TestFilterValidStarRecords: + """Tests for filter_valid_star_records function.""" + + @patch("imap_processing.lo.l1b.lo_l1b.interpolate_repoint_data") + def test_filters_by_count_threshold(self, mock_repoint): + """Test filtering star records by COUNT >= 700.""" + # Arrange - Mock repoint data (no repoints in progress) + mock_repoint.return_value = pd.DataFrame( + {"repoint_in_progress": [False, False, False, False, False]} + ) + + l1a_star = xr.Dataset( + { + "count": ("epoch", [650, 700, 720, 699, 715]), + "shcoarse": ( + "epoch", + np.arange(5, dtype=np.float64), + ), # Already in seconds + }, + coords={"epoch": [0, 1, 2, 3, 4]}, + ) + expected_mask = np.array([False, True, True, False, True]) + + # Act + valid_mask = filter_valid_star_records(l1a_star, min_count=700) + + # Assert + np.testing.assert_array_equal(valid_mask, expected_mask) + + @patch("imap_processing.lo.l1b.lo_l1b.interpolate_repoint_data") + def test_filters_by_count_and_time_window(self, mock_repoint): + """Test filtering star records by both COUNT and time window.""" + # Arrange - Mock repoint data (no repoints in progress) + mock_repoint.return_value = pd.DataFrame( + {"repoint_in_progress": [False, False, False, False, False]} + ) + + # Create times: 0s, 10s, 20s, 30s, 40s (already in seconds) + l1a_star = xr.Dataset( + { + "count": ("epoch", [700, 710, 720, 715, 720]), + "shcoarse": ("epoch", np.array([0, 10, 20, 30, 40], dtype=np.float64)), + }, + coords={"epoch": [0, 1, 2, 3, 4]}, + ) + # # Time window: [5s, 25s] - should include epochs 1 and 2 + expected_mask = np.array([False, True, True, False, False]) + + # Act + valid_mask = filter_valid_star_records( + l1a_star, + min_count=700, + time_window_offset=5.0, + time_window_duration=20.0, + ) + + # Assert + np.testing.assert_array_equal(valid_mask, expected_mask) + + @patch("imap_processing.lo.l1b.lo_l1b.interpolate_repoint_data") + def test_processes_all_data_without_time_window(self, mock_repoint): + """Test filtering without time window (process all data).""" + # Arrange - Mock repoint data (no repoints in progress) + mock_repoint.return_value = pd.DataFrame( + {"repoint_in_progress": [False, False, False]} + ) + + l1a_star = xr.Dataset( + { + "count": ("epoch", [700, 710, 720]), + "shcoarse": ("epoch", np.array([0, 10, 20], dtype=np.float64)), + }, + coords={"epoch": [0, 1, 2]}, + ) + expected_mask = np.array([True, True, True]) + + # Act + valid_mask = filter_valid_star_records( + l1a_star, min_count=700, time_window_duration=None + ) + + # Assert + np.testing.assert_array_equal(valid_mask, expected_mask) + + @patch("imap_processing.lo.l1b.lo_l1b.interpolate_repoint_data") + def test_excludes_records_during_repoint(self, mock_repoint): + """Test filtering records during repoint maneuvers.""" + # Arrange - Mock repoint data with some repoints in progress + # Epochs 1 and 3 are during repoint maneuvers + mock_repoint.return_value = pd.DataFrame( + {"repoint_in_progress": [False, True, False, True, False]} + ) + + l1a_star = xr.Dataset( + { + "count": ("epoch", [700, 710, 720, 715, 720]), + "shcoarse": ("epoch", np.arange(5, dtype=np.float64)), + }, + coords={"epoch": [0, 1, 2, 3, 4]}, + ) + # Expected: epochs 0, 2, 4 pass (COUNT >= 700 AND not during repoint) + # Epochs 1 and 3 fail because they are during repoint + expected_mask = np.array([True, False, True, False, True]) + + # Act + valid_mask = filter_valid_star_records(l1a_star, min_count=700) + + # Assert + np.testing.assert_array_equal(valid_mask, expected_mask) + + +class TestCalculateStarSensorProfile: + """Tests for star sensor profile calculation functions.""" + + def test_profile_for_group_basic(self): + """Test basic star sensor profile calculation for a group.""" + # Arrange - 3 records with uniform data + np.random.seed(42) + data = np.random.randint(100, 200, size=(3, 720)).astype(np.uint16) + counts = np.array([720, 720, 720]) + + # Act + avg_amplitude, count_per_bin = calculate_star_sensor_profile_for_group( + data, counts, end_bins_to_exclude=0 + ) + + # Assert + assert len(avg_amplitude) == 720 + assert len(count_per_bin) == 720 + # All bins should have 3 samples + np.testing.assert_array_equal(count_per_bin, np.full(720, 3)) + # Averages should be between 100 and 200 + assert np.all(avg_amplitude >= 100) + assert np.all(avg_amplitude <= 200) + + def test_profile_for_group_end_bins_excluded(self): + """Test that edge bins are properly excluded.""" + # Arrange - 2 records with uniform data + data = np.ones((2, 720), dtype=np.uint16) * 100 + counts = np.array([720, 720]) + + # Act + avg_amplitude, count_per_bin = calculate_star_sensor_profile_for_group( + data, counts, end_bins_to_exclude=2 + ) + + # Assert + # Last 2 bins should have count=0 + assert count_per_bin[718] == 0 + assert count_per_bin[719] == 0 + # All other bins should have count=2 + assert np.all(count_per_bin[:718] == 2) + # Averages should be 100 for all bins except the excluded ones + assert np.all(avg_amplitude[:718] == 100.0) + # Excluded bins should be NaN + assert np.isnan(avg_amplitude[718]) + assert np.isnan(avg_amplitude[719]) + + def test_profile_for_group_empty_data(self): + """Test handling of empty data array.""" + # Arrange + data = np.empty((0, 720), dtype=np.uint16) + counts = np.array([], dtype=np.int32) + + # Act + avg_amplitude, count_per_bin = calculate_star_sensor_profile_for_group( + data, counts + ) + + # Assert + np.testing.assert_array_equal(count_per_bin, np.zeros(720)) + # Empty data returns NaN for all bins (consistent with bins having no samples) + assert np.all(np.isnan(avg_amplitude)) + + @patch("imap_processing.lo.l1b.lo_l1b.interpolate_repoint_data") + def test_profiles_by_group_creates_correct_groups(self, mock_repoint): + """Test that profiles are grouped correctly into 64-record groups.""" + # Arrange - Create 150 records (should produce 3 groups: 64, 64, 22) + n_records = 150 + mock_repoint.return_value = pd.DataFrame( + {"repoint_in_progress": [False] * n_records} + ) + met_times = np.arange(n_records, dtype=np.float64) * 15.0 + l1a_star = xr.Dataset( + { + "count": ("epoch", [720] * n_records), + "shcoarse": ( + "epoch", + np.arange(n_records, dtype=np.float64) * 15.0, + ), + "data": ( + ("epoch", "samples"), + np.ones((n_records, 720), dtype=np.uint16) * 100, + ), + }, + coords={ + "epoch": met_to_ttj2000ns(met_times), + "samples": np.arange(720), + }, + ) + + # Act + ( + spin_angle, + group_epochs, + avg_amplitudes, + counts_per_bin, + ) = calculate_star_sensor_profiles_by_group( + l1a_star, + sampling_cadence=21.0, + spin_period=15.0, + group_size=64, + ) + + # Assert + assert len(spin_angle) == 720 + assert len(group_epochs) == 3 # 150 records -> 3 groups + assert avg_amplitudes.shape == (3, 720) + assert counts_per_bin.shape == (3, 720) + # First two groups should have 64 samples per bin, last group 22 + assert np.all(counts_per_bin[0, 2:718] == 64) + assert np.all(counts_per_bin[1, 2:718] == 64) + assert np.all(counts_per_bin[2, 2:718] == 22) + + @patch("imap_processing.lo.l1b.lo_l1b.interpolate_repoint_data") + def test_profiles_by_group_handles_no_valid_records(self, mock_repoint): + """Test handling when no records pass the COUNT threshold.""" + # Arrange + mock_repoint.return_value = pd.DataFrame( + {"repoint_in_progress": [False, False, False]} + ) + l1a_star = xr.Dataset( + { + "count": ("epoch", [650, 600, 699]), # All below 700 + "shcoarse": ("epoch", np.array([0.0, 15.0, 30.0], dtype=np.float64)), + "data": ( + ("epoch", "samples"), + np.ones((3, 720), dtype=np.uint16) * 100, + ), + }, + coords={ + "epoch": met_to_ttj2000ns([0.0, 15.0, 30.0]), + "samples": np.arange(720), + }, + ) + + # Act + ( + spin_angle, + group_epochs, + avg_amplitudes, + counts_per_bin, + ) = calculate_star_sensor_profiles_by_group( + l1a_star, + sampling_cadence=21.0, + spin_period=15.0, + min_count_threshold=700, + ) + + # Assert + assert len(spin_angle) == 720 + assert len(group_epochs) == 0 # No valid records + assert avg_amplitudes.shape == (0, 720) + + @patch("imap_processing.lo.l1b.lo_l1b.interpolate_repoint_data") + def test_profiles_by_group_angle_wrapping(self, mock_repoint): + """Test that spin angles wrap correctly to [0, 360) range.""" + # Arrange + mock_repoint.return_value = pd.DataFrame({"repoint_in_progress": [False]}) + l1a_star = xr.Dataset( + { + "count": ("epoch", [720]), + "shcoarse": ("epoch", np.array([0.0], dtype=np.float64)), + "data": ( + ("epoch", "samples"), + np.ones((1, 720), dtype=np.uint16) * 100, + ), + }, + coords={"epoch": met_to_ttj2000ns([0.0]), "samples": np.arange(720)}, + ) + + # Act + spin_angle, _, _, _ = calculate_star_sensor_profiles_by_group( + l1a_star, + sampling_cadence=21.0, + spin_period=15.0, + start_angle_offset=350.0, # Large offset to test wrapping + ) + + # Assert + assert np.all(spin_angle >= 0) + assert np.all(spin_angle < 360) + # With offset=350Β°, first bin should be around 350Β° + assert 350.0 < spin_angle[0] < 351.0 + # Some bins will wrap to the lower range + assert np.any(spin_angle > 300) + assert np.any(spin_angle < 100) # Some angles wrapped to lower range + + +class TestL1bStar: + """Tests for l1b_star function.""" + + @patch("imap_processing.lo.l1b.lo_l1b.get_pointing_mid_time") + @patch("imap_processing.lo.l1b.lo_l1b.interpolate_repoint_data") + def test_initializes_with_spin_data( + self, mock_repoint, mock_pointing_mid, attr_mgr_l1b + ): + """Test successful initialization of L1B star dataset with spin data.""" + # Arrange - Create 150 records to produce multiple groups + n_records = 150 + mock_repoint.return_value = pd.DataFrame( + {"repoint_in_progress": [False] * n_records} + ) + mock_pointing_mid.return_value = 1000.0 # Mock pointing mid time in MET + np.random.seed(42) + met_times = np.arange(n_records, dtype=np.float64) * 15.0 + l1a_star = xr.Dataset( + { + "count": ("epoch", [720] * n_records), + "shcoarse": ( + "epoch", + np.arange(n_records, dtype=np.float64) * 15.0, + ), + "data": ( + ("epoch", "samples"), + np.random.randint(100, 200, size=(n_records, 720), dtype=np.uint16), + ), + }, + coords={ + "epoch": met_to_ttj2000ns(met_times), + "samples": np.arange(720), + }, + ) + l1b_nhk = xr.Dataset( + { + "ifb_data_interval": ("epoch", [21.0] * n_records), + }, + coords={"epoch": list(range(n_records))}, + ) + # Create spin data with known spin durations + spin_data = xr.Dataset( + { + "acq_start_sec": ("epoch", [0, 15]), + "acq_start_subsec": ("epoch", [0, 0]), + "acq_end_sec": ("epoch", [420, 435]), # 420s = 28 spins * 15s + "acq_end_subsec": ("epoch", [0, 0]), + "num_completed": ("epoch", [28, 28]), + }, + coords={"epoch": [0, 1]}, + ) + sci_dependencies = { + "imap_lo_l1a_star": l1a_star, + "imap_lo_l1b_nhk": l1b_nhk, + "imap_lo_l1a_spin": spin_data, + } + + # Act + l1b_star_ds = l1b_star(sci_dependencies, attr_mgr_l1b, group_size=64) + + # Assert + assert l1b_star_ds.attrs["Logical_source"] == "imap_lo_l1b_prostar" + assert "epoch" in l1b_star_ds.coords + # 150 records / 64 group_size = 3 groups (64 + 64 + 22) + assert len(l1b_star_ds.coords["epoch"]) == 3 + # spin_angle is now the coordinate (monotonically increasing) + assert "spin_angle" in l1b_star_ds.coords + assert len(l1b_star_ds.coords["spin_angle"]) == 720 + # spin_angle_bin is now a data variable + assert "spin_angle_bin" in l1b_star_ds.data_vars + assert "avg_amplitude" in l1b_star_ds.data_vars + assert "count_per_bin" in l1b_star_ds.data_vars + assert "pointing_mid_met" in l1b_star_ds.attrs + # Check that spin_angle is monotonically increasing + spin_angles = l1b_star_ds.coords["spin_angle"].values + assert np.all(np.diff(spin_angles) > 0), ( + "spin_angle should be monotonically increasing" + ) + assert spin_angles[0] >= 0.0 + assert spin_angles[-1] < 360.0 + # Check attributes + assert "sampling_cadence_ms" in l1b_star_ds.attrs + assert "spin_duration_sec" in l1b_star_ds.attrs + assert "group_size" in l1b_star_ds.attrs + assert l1b_star_ds.attrs["sampling_cadence_ms"] == 21.0 + assert l1b_star_ds.attrs["spin_duration_sec"] == 15.0 + assert l1b_star_ds.attrs["group_size"] == 64 + # Check data shapes - all variables have epoch as first dimension + assert l1b_star_ds["spin_angle_bin"].shape == (720,) + assert l1b_star_ds["avg_amplitude"].shape == (3, 720) + assert l1b_star_ds["count_per_bin"].shape == (3, 720) + # Check pointing_mid_met is a scalar with expected value + assert float(l1b_star_ds.attrs["pointing_mid_met"]) == 1000.0 + + @patch("imap_processing.lo.l1b.lo_l1b.get_pointing_mid_time") + @patch("imap_processing.lo.l1b.lo_l1b.interpolate_repoint_data") + def test_dataset_structure_and_attributes( + self, mock_repoint, mock_pointing_mid, attr_mgr_l1b + ): + """Test that L1B star dataset has correct structure and attributes.""" + # Arrange + mock_repoint.return_value = pd.DataFrame({"repoint_in_progress": [False]}) + mock_pointing_mid.return_value = 1000.0 + l1a_star = xr.Dataset( + { + "count": ("epoch", [720]), + "shcoarse": ("epoch", np.array([0.0], dtype=np.float64)), + "data": ( + ("epoch", "samples"), + np.ones((1, 720), dtype=np.uint16) * 150, + ), + }, + coords={"epoch": met_to_ttj2000ns([0.0]), "samples": np.arange(720)}, + ) + l1b_nhk = xr.Dataset( + { + "ifb_data_interval": ("epoch", [21.0]), + }, + coords={"epoch": [0]}, + ) + spin_data = xr.Dataset( + { + "acq_start_sec": ("epoch", [0]), + "acq_start_subsec": ("epoch", [0]), + "acq_end_sec": ("epoch", [420]), # 420s = 28 spins * 15s + "acq_end_subsec": ("epoch", [0]), + "num_completed": ("epoch", [28]), + }, + coords={"epoch": [0]}, + ) + sci_dependencies = { + "imap_lo_l1a_star": l1a_star, + "imap_lo_l1b_nhk": l1b_nhk, + "imap_lo_l1a_spin": spin_data, + } + + # Act + l1b_star_ds = l1b_star(sci_dependencies, attr_mgr_l1b) + + # Assert - Check spin_angle coordinate attributes + # Check that resulting dataset is cdf-able by writing to file + _ = write_cdf(l1b_star_ds) + + assert l1b_star_ds.coords["spin_angle"].attrs["UNITS"] == "deg" + assert l1b_star_ds.coords["spin_angle"].attrs["VALIDMIN"] == 0.0 + assert l1b_star_ds.coords["spin_angle"].attrs["VALIDMAX"] == 360.0 + + # Assert - Check spin_angle_bin variable attributes (now a data variable) + assert ( + "Original spin angle bin index" + in l1b_star_ds["spin_angle_bin"].attrs["CATDESC"] + ) + assert l1b_star_ds["spin_angle_bin"].attrs["VALIDMIN"] == 0 + assert l1b_star_ds["spin_angle_bin"].attrs["VALIDMAX"] == 719 + + assert l1b_star_ds["avg_amplitude"].attrs["UNITS"] == "mV" + assert l1b_star_ds["avg_amplitude"].attrs["FILLVAL"] == -1.0e31 + + assert l1b_star_ds["count_per_bin"].attrs["VALIDMIN"] == 0 + assert l1b_star_ds["count_per_bin"].attrs["VALIDMAX"] == 100000 + + # Assert - Check processing parameter attributes + assert "lo_angle_offset_deg" in l1b_star_ds.attrs + assert "end_bins_excluded" in l1b_star_ds.attrs + assert "min_count_threshold" in l1b_star_ds.attrs + assert l1b_star_ds.attrs["lo_angle_offset_deg"] == 2.0 + assert l1b_star_ds.attrs["end_bins_excluded"] == 2 + assert l1b_star_ds.attrs["min_count_threshold"] == 700 + + @patch("imap_processing.lo.l1b.lo_l1b.get_pointing_mid_time") + @patch("imap_processing.lo.l1b.lo_l1b.interpolate_repoint_data") + def test_start_and_end_doy_variables( + self, mock_repoint, mock_pointing_mid, attr_mgr_l1b + ): + """Test that start_doy and end_doy variables are computed correctly.""" + # Arrange + mock_pointing_mid.return_value = 1000.0 # Mock pointing mid time in MET + mock_repoint.return_value = pd.DataFrame( + {"repoint_in_progress": [False, False, False]} + ) + np.random.seed(42) + # Create epochs spanning 30 seconds + l1a_star = xr.Dataset( + { + "count": ("epoch", [720, 720, 720]), + "shcoarse": ("epoch", np.array([0.0, 15.0, 30.0], dtype=np.float64)), + "data": ( + ("epoch", "samples"), + np.random.randint(100, 200, size=(3, 720), dtype=np.uint16), + ), + }, + coords={ + "epoch": met_to_ttj2000ns([0.0, 15.0, 30.0]), + "samples": np.arange(720), + }, + ) + l1b_nhk = xr.Dataset( + { + "ifb_data_interval": ("epoch", [21.0, 21.0, 21.0]), + }, + coords={"epoch": [0, 1, 2]}, + ) + spin_data = xr.Dataset( + { + "acq_start_sec": ("epoch", [0, 15]), + "acq_start_subsec": ("epoch", [0, 0]), + "acq_end_sec": ("epoch", [420, 435]), + "acq_end_subsec": ("epoch", [0, 0]), + "num_completed": ("epoch", [28, 28]), + }, + coords={"epoch": [0, 1]}, + ) + sci_dependencies = { + "imap_lo_l1a_star": l1a_star, + "imap_lo_l1b_nhk": l1b_nhk, + "imap_lo_l1a_spin": spin_data, + } + + # Act + l1b_star_ds = l1b_star(sci_dependencies, attr_mgr_l1b) + + # Assert - Check that start_doy and end_doy exist as scalars (global values) + assert "start_doy" in l1b_star_ds.attrs + assert "end_doy" in l1b_star_ds.attrs + + # Assert - Check values are valid day of year (1.0 to 366.x for leap years) + start_doy = float(l1b_star_ds.attrs["start_doy"]) + end_doy = float(l1b_star_ds.attrs["end_doy"]) + assert 1.0 <= start_doy <= 367.0 + assert 1.0 <= end_doy <= 367.0 + + # Assert - end_doy should be >= start_doy (data spans 30 seconds) + assert end_doy >= start_doy + + @patch("imap_processing.lo.l1b.lo_l1b.get_pointing_mid_time") + @patch("imap_processing.lo.l1b.lo_l1b.interpolate_repoint_data") + def test_multiple_groups_created( + self, mock_repoint, mock_pointing_mid, attr_mgr_l1b + ): + """Test that multiple 64-spin groups are created correctly.""" + # Arrange - Create 150 records to produce 3 groups (64 + 64 + 22) + n_records = 150 + mock_pointing_mid.return_value = 1000.0 # Mock pointing mid time in MET + mock_repoint.return_value = pd.DataFrame( + {"repoint_in_progress": [False] * n_records} + ) + met_times = np.arange(n_records, dtype=np.float64) * 15.0 + l1a_star = xr.Dataset( + { + "count": ("epoch", [720] * n_records), + "shcoarse": ( + "epoch", + np.arange(n_records, dtype=np.float64) * 15.0, + ), + "data": ( + ("epoch", "samples"), + np.ones((n_records, 720), dtype=np.uint16) * 100, + ), + }, + coords={ + "epoch": met_to_ttj2000ns(met_times), + "samples": np.arange(720), + }, + ) + l1b_nhk = xr.Dataset( + { + "ifb_data_interval": ("epoch", [21.0] * n_records), + }, + coords={"epoch": list(range(n_records))}, + ) + spin_data = xr.Dataset( + { + "acq_start_sec": ("epoch", [0]), + "acq_start_subsec": ("epoch", [0]), + "acq_end_sec": ("epoch", [420]), + "acq_end_subsec": ("epoch", [0]), + "num_completed": ("epoch", [28]), + }, + coords={"epoch": [0]}, + ) + sci_dependencies = { + "imap_lo_l1a_star": l1a_star, + "imap_lo_l1b_nhk": l1b_nhk, + "imap_lo_l1a_spin": spin_data, + } + + # Act + l1b_star_ds = l1b_star(sci_dependencies, attr_mgr_l1b, group_size=64) + + # Assert + assert len(l1b_star_ds.coords["epoch"]) == 3 + # Check pointing_mid_met is present (scalar value) + assert "pointing_mid_met" in l1b_star_ds.attrs + # First group epoch should be the first L1A epoch + assert l1b_star_ds.coords["epoch"].values[0] == met_to_ttj2000ns([0.0])[0] + # Second group epoch should be record 64 + assert l1b_star_ds.coords["epoch"].values[1] == met_to_ttj2000ns([64 * 15.0])[0] + # Third group epoch should be record 128 + assert ( + l1b_star_ds.coords["epoch"].values[2] == met_to_ttj2000ns([128 * 15.0])[0] + ) + + +def test_get_pivot_angle_from_nhk(): + """Test get_pivot_angle_from_nhk function.""" + # Arrange - Create a mock NHK dataset with pivot angle information + l1b_nhk = xr.Dataset( + { + # Previous 90 degrees at the beginning, then shifted to 75 degrees + "pcc_cumulative_cnt_pri": ("epoch", [90, 90, 75, 75, 75, 75, 75]), + }, + coords={"epoch": [0, 1, 2, 3, 4, 5, 6]}, + ) + expected_pivot_angle = 75 + + # Act + pivot_angle = get_pivot_angle_from_nhk(l1b_nhk) # Assert - np.testing.assert_array_equal(l1b_de["pointing_bin_lat"], expected_pointing_lats) - np.testing.assert_array_equal(l1b_de["pointing_bin_lon"], expected_pointing_lons) + assert pivot_angle == expected_pivot_angle + + +def test_l1b_bgrates_and_goodtimes_basic(anc_dependencies, attr_mgr_l1b): + """Test basic functionality of l1b_bgrates_and_goodtimes.""" + # Arrange - Create a simple L1B histogram rates dataset + # with enough data points to create goodtime intervals + num_epochs = 100 + met_start = 473389200 + met_spacing = 42 + + met_times = np.arange(met_start, met_start + num_epochs * met_spacing, met_spacing) + epoch_times = met_to_ttj2000ns(met_times) + + # Low counts to keep background rates below threshold + h_counts = np.ones((num_epochs, 7, 60)) * 0.00028 + o_counts = np.ones((num_epochs, 7, 60)) * 0.000028 + + l1b_histrates = xr.Dataset( + { + "h_counts": (("epoch", "esa_step", "spin_bin_6"), h_counts), + "o_counts": (("epoch", "esa_step", "spin_bin_6"), o_counts), + }, + coords={ + "epoch": epoch_times, + "esa_step": np.arange(1, 8), + "spin_bin_6": np.arange(60), + }, + ) + + sci_dependencies = { + "imap_lo_l1b_histrates": l1b_histrates, + "imap_lo_l1b_de": xr.Dataset(), + "imap_lo_l1b_nhk": xr.Dataset(), + } + + # Act + result = l1b_bgrates_and_goodtimes( + sci_dependencies, anc_dependencies, attr_mgr_l1b, delay_max=840 + ) + + # Assert - Should return a list with two datasets + assert isinstance(result, list) + assert len(result) == 2 + + l1b_bgrates_ds, l1b_goodtimes_ds = result + + # Check that bgrates dataset is cdf-able by writing to file + _ = write_cdf(l1b_bgrates_ds) + assert "epoch" in l1b_bgrates_ds.coords + assert "esa_step" in l1b_bgrates_ds.coords + + # Check bgrates dataset structure (BACKGROUND_RATE_FIELDS) + assert "h_background_rates" in l1b_bgrates_ds.data_vars + assert "h_background_variance" in l1b_bgrates_ds.data_vars + assert "h_synthetic_floor" in l1b_bgrates_ds.data_vars + assert "h_proxy_floor" in l1b_bgrates_ds.data_vars + assert "o_background_rates" in l1b_bgrates_ds.data_vars + assert "o_background_variance" in l1b_bgrates_ds.data_vars + assert "o_synthetic_floor" in l1b_bgrates_ds.data_vars + assert "o_proxy_floor" in l1b_bgrates_ds.data_vars + + # Check that goodtimes dataset is cdf-able by writing to file + _ = write_cdf(l1b_goodtimes_ds) + assert "epoch" in l1b_goodtimes_ds.coords + + # Check goodtimes dataset structure (GOODTIMES_FIELDS) + assert "gt_start_met" in l1b_goodtimes_ds.data_vars + assert "gt_end_met" in l1b_goodtimes_ds.data_vars + assert "pivot" in l1b_goodtimes_ds.data_vars + assert "pivot_de" in l1b_goodtimes_ds.data_vars + + # Check that goodtime intervals were created + assert len(l1b_goodtimes_ds["gt_start_met"]) > 0 + assert len(l1b_goodtimes_ds["gt_end_met"]) > 0 + + # Check that start times are before end times + assert np.all( + l1b_goodtimes_ds["gt_start_met"].values <= l1b_goodtimes_ds["gt_end_met"].values + ) + + +def test_l1b_bgrates_and_goodtimes_with_gap(anc_dependencies, attr_mgr_l1b): + """Test l1b_bgrates_and_goodtimes handles data gaps correctly.""" + # Arrange - Create dataset with a large gap in the middle + num_epochs_first = 50 + num_epochs_second = 50 + met_start = 473389200 + met_spacing = 42 + gap_size = 10000 # Large gap (> delay_max + interval_nom) + + # First segment + met_times_first = np.arange( + met_start, met_start + num_epochs_first * met_spacing, met_spacing + ) + # Second segment after gap + met_times_second = np.arange( + met_start + num_epochs_first * met_spacing + gap_size, + met_start + + num_epochs_first * met_spacing + + gap_size + + num_epochs_second * met_spacing, + met_spacing, + ) + + met_times = np.concatenate([met_times_first, met_times_second]) + epoch_times = met_to_ttj2000ns(met_times) + + # Low background counts (below threshold) + h_counts = np.ones((len(met_times), 7, 60)) * 0.00028 + o_counts = np.ones((len(met_times), 7, 60)) * 0.000028 + + l1b_histrates = xr.Dataset( + { + "h_counts": (("epoch", "esa_step", "spin_bin_6"), h_counts), + "o_counts": (("epoch", "esa_step", "spin_bin_6"), o_counts), + }, + coords={ + "epoch": epoch_times, + "esa_step": np.arange(1, 8), + "spin_bin_6": np.arange(60), + }, + ) + + sci_dependencies = { + "imap_lo_l1b_histrates": l1b_histrates, + "imap_lo_l1b_de": xr.Dataset(), + "imap_lo_l1b_nhk": xr.Dataset(), + } + + # Act + result = l1b_bgrates_and_goodtimes( + sci_dependencies, anc_dependencies, attr_mgr_l1b, delay_max=840 + ) + + # Assert + l1b_bgrates_ds, l1b_goodtimes_ds = result + + # Should create at least 2 separate goodtime intervals (before and after gap) + assert len(l1b_goodtimes_ds["gt_start_met"]) >= 2 + + # Check that intervals don't span across the gap + for i in range(len(l1b_goodtimes_ds["gt_start_met"])): + interval_duration = ( + l1b_goodtimes_ds["gt_end_met"].values[i] + - l1b_goodtimes_ds["gt_start_met"].values[i] + ) + # No interval should be as large as the gap + assert interval_duration < gap_size + + +def test_l1b_bgrates_and_goodtimes_high_rate(anc_dependencies, attr_mgr_l1b): + """Test l1b_bgrates_and_goodtimes handles high count rates correctly.""" + # Arrange - Create dataset with high rates that exceed threshold + num_epochs = 100 + met_start = 473389200 + met_spacing = 42 + + met_times = np.arange(met_start, met_start + num_epochs * met_spacing, met_spacing) + epoch_times = met_to_ttj2000ns(met_times) + + # Create high counts (above threshold) + # h_bg_rate_nom = 0.0014925, exposure = 420*7*0.5 = 1470 seconds + # To be above threshold: rate > 0.0014925 + # Use 10x threshold for high rate periods: 0.014925 counts/sec + h_counts = np.ones((num_epochs, 7, 60)) * 0.014925 # High rate (10x threshold) + o_counts = np.ones((num_epochs, 7, 60)) * 0.0014925 + + # Make first 20 epochs low (below threshold) + h_counts[:20, :, :] = 0.00014925 + o_counts[:20, :, :] = 0.000014925 + + # Make last 20 epochs low + h_counts[80:, :, :] = 0.00014925 + o_counts[80:, :, :] = 0.000014925 + + l1b_histrates = xr.Dataset( + { + "h_counts": (("epoch", "esa_step", "spin_bin_6"), h_counts), + "o_counts": (("epoch", "esa_step", "spin_bin_6"), o_counts), + }, + coords={ + "epoch": epoch_times, + "esa_step": np.arange(1, 8), + "spin_bin_6": np.arange(60), + }, + ) + + sci_dependencies = { + "imap_lo_l1b_histrates": l1b_histrates, + "imap_lo_l1b_de": xr.Dataset(), + "imap_lo_l1b_nhk": xr.Dataset(), + } + + # Act + result = l1b_bgrates_and_goodtimes( + sci_dependencies, anc_dependencies, attr_mgr_l1b, delay_max=840 + ) + + # Assert + l1b_bgrates_ds, l1b_goodtimes_ds = result + + # Should create at least 2 intervals (before and after high rate period) + assert len(l1b_goodtimes_ds["gt_start_met"]) >= 2 + + # Check that background rates were calculated + assert np.all(l1b_bgrates_ds["h_background_rates"].values > 0) + assert np.all(l1b_bgrates_ds["o_background_rates"].values > 0) + + +def test_l1b_bgrates_and_goodtimes_no_goodtimes(anc_dependencies, attr_mgr_l1b): + """When no goodtimes are detected the function should still return datasets.""" + num_epochs = 50 + met_start = 473389200 + met_spacing = 42 + + met_times = np.arange(met_start, met_start + num_epochs * met_spacing, met_spacing) + epoch_times = met_to_ttj2000ns(met_times) + + # Make counts high everywhere so no low-rate goodtime intervals are found + h_counts = np.ones((num_epochs, 7, 60)) * 0.1 + o_counts = np.ones((num_epochs, 7, 60)) * 0.01 + + l1b_histrates = xr.Dataset( + { + "h_counts": (("epoch", "esa_step", "spin_bin_6"), h_counts), + "o_counts": (("epoch", "esa_step", "spin_bin_6"), o_counts), + }, + coords={ + "epoch": epoch_times, + "esa_step": np.arange(1, 8), + "spin_bin_6": np.arange(60), + }, + ) + + sci_dependencies = { + "imap_lo_l1b_histrates": l1b_histrates, + "imap_lo_l1b_de": xr.Dataset(), + "imap_lo_l1b_nhk": xr.Dataset(), + } + + _, goodtimes_ds = l1b_bgrates_and_goodtimes( + sci_dependencies, anc_dependencies, attr_mgr_l1b, delay_max=840 + ) + + # When no goodtimes are detected a single fallback row (0, 0) is used. + # The padding loop runs before the fallback is inserted, so the zeros are unchanged. + assert int(goodtimes_ds["gt_start_met"].values[0]) == 0 + assert int(goodtimes_ds["gt_end_met"].values[0]) == 0 + + +def test_l1b_bgrates_and_goodtimes_empty_dataset(anc_dependencies, attr_mgr_l1b): + """Test l1b_bgrates_and_goodtimes handles edge case with minimal data.""" + # Arrange - Create minimal dataset (just enough for one cycle) + num_epochs = 10 + met_start = 473389200 + met_spacing = 42 + + met_times = np.arange(met_start, met_start + num_epochs * met_spacing, met_spacing) + epoch_times = met_to_ttj2000ns(met_times) + + # Low counts (below threshold) + h_counts = np.ones((num_epochs, 7, 60)) * 0.00028 + o_counts = np.ones((num_epochs, 7, 60)) * 0.000028 + + l1b_histrates = xr.Dataset( + { + "h_counts": (("epoch", "esa_step", "spin_bin_6"), h_counts), + "o_counts": (("epoch", "esa_step", "spin_bin_6"), o_counts), + }, + coords={ + "epoch": epoch_times, + "esa_step": np.arange(1, 8), + "spin_bin_6": np.arange(60), + }, + ) + + sci_dependencies = { + "imap_lo_l1b_histrates": l1b_histrates, + "imap_lo_l1b_de": xr.Dataset(), + "imap_lo_l1b_nhk": xr.Dataset(), + } + + # Act + result = l1b_bgrates_and_goodtimes( + sci_dependencies, anc_dependencies, attr_mgr_l1b, delay_max=840 + ) + + # Assert - Should still create valid datasets even with minimal data + l1b_bgrates_ds, l1b_goodtimes_ds = result + + assert "h_background_rates" in l1b_bgrates_ds.data_vars + assert "gt_start_met" in l1b_goodtimes_ds.data_vars + + +def test_split_backgrounds_and_goodtimes_dataset(attr_mgr_l1b): + """Test split_backgrounds_and_goodtimes_dataset separates fields correctly.""" + # Arrange - Create a combined dataset matching the structure produced by + # l1b_bgrates_and_goodtimes: scalar background rate fields and epoch-indexed + # goodtime interval fields. + num_records = 3 + met_starts = np.arange(473389200, 473389200 + num_records * 420, 420) + epoch_times = met_to_ttj2000ns(met_starts) + + combined_ds = xr.Dataset( + coords={"epoch": epoch_times}, + ) + combined_ds["gt_start_met"] = xr.DataArray( + met_starts.astype(np.int64), dims=["epoch"] + ) + combined_ds["gt_end_met"] = xr.DataArray( + (met_starts + 400).astype(np.int64), dims=["epoch"] + ) + combined_ds["pivot"] = xr.DataArray(np.float32(90.0)) + combined_ds["pivot_de"] = xr.DataArray(np.float32(89.5)) + combined_ds["h_background_rates"] = xr.DataArray(np.float32(0.01)) + combined_ds["h_background_variance"] = xr.DataArray(np.float32(0.001)) + combined_ds["o_background_rates"] = xr.DataArray(np.float32(0.002)) + combined_ds["o_background_variance"] = xr.DataArray(np.float32(0.0002)) + combined_ds["h_synthetic_floor"] = xr.DataArray(np.float32(5.0)) + combined_ds["h_proxy_floor"] = xr.DataArray(np.float32(4.0)) + combined_ds["o_synthetic_floor"] = xr.DataArray(np.float32(0.5)) + combined_ds["o_proxy_floor"] = xr.DataArray(np.float32(0.4)) + + # Act + bgrates_ds, goodtimes_ds = split_backgrounds_and_goodtimes_dataset( + combined_ds, attr_mgr_l1b + ) + + # Assert - bgrates dataset contains all background rate fields (scalar) + for field in [ + "h_background_rates", + "h_background_variance", + "o_background_rates", + "o_background_variance", + "h_synthetic_floor", + "h_proxy_floor", + "o_synthetic_floor", + "o_proxy_floor", + ]: + assert field in bgrates_ds.data_vars + assert bgrates_ds[field].dims == () # scalar + + # Assert - goodtimes dataset contains the expected fields + assert "gt_start_met" in goodtimes_ds.data_vars + assert "gt_end_met" in goodtimes_ds.data_vars + assert "pivot" in goodtimes_ds.data_vars + assert "pivot_de" in goodtimes_ds.data_vars + + # Assert - goodtime intervals were created and are valid + assert len(goodtimes_ds["gt_start_met"]) > 0 + assert np.all( + goodtimes_ds["gt_start_met"].values <= goodtimes_ds["gt_end_met"].values + ) + + # Assert - pivot fields are scalar + assert goodtimes_ds["pivot"].dims == () + assert goodtimes_ds["pivot_de"].dims == () + + +def test_l1b_bgrates_and_goodtimes_ram_and_anti_ram_bins( + anc_dependencies, attr_mgr_l1b +): + """Test that the function correctly uses bins anti-RAM 20-50 and RAM 0-20/50-60.""" + # Arrange - Create dataset with specific counts in different azimuth bins + num_epochs = 30 + met_start = 473389200 + met_spacing = 42 + + met_times = np.arange(met_start, met_start + num_epochs * met_spacing, met_spacing) + epoch_times = met_to_ttj2000ns(met_times) + + # High counts everywhere by default + h_counts = np.ones((num_epochs, 7, 60)) * 0.028 + o_counts = np.ones((num_epochs, 7, 60)) * 0.0028 + + # Anti-RAM bins (20-50): set low across all ESA steps (below anti-RAM threshold) + h_counts[:, :, 20:50] = 0.00028 + o_counts[:, :, 20:50] = 0.000028 + + # RAM bins (0-20, 50-60) for RAM ESA steps (0-indexed 5, 6): + # set low (below RAM threshold) + h_counts[:, 5:7, 0:20] = 0.00028 + h_counts[:, 5:7, 50:60] = 0.00028 + o_counts[:, 5:7, 0:20] = 0.000028 + o_counts[:, 5:7, 50:60] = 0.000028 + + l1b_histrates = xr.Dataset( + { + "h_counts": (("epoch", "esa_step", "spin_bin_6"), h_counts), + "o_counts": (("epoch", "esa_step", "spin_bin_6"), o_counts), + }, + coords={ + "epoch": epoch_times, + "esa_step": np.arange(1, 8), + "spin_bin_6": np.arange(60), + }, + ) + + # Required dependencies added in the updated function signature + cdf_de = xr.Dataset({"pivot_angle": xr.DataArray(90.0)}) + cdf_hk = xr.Dataset() # No pcc_coarse_pot_pri; pivot defaults to 90.0 + + sci_dependencies = { + "imap_lo_l1b_histrates": l1b_histrates, + "imap_lo_l1b_de": cdf_de, + "imap_lo_l1b_nhk": cdf_hk, + } + + result = l1b_bgrates_and_goodtimes( + sci_dependencies, anc_dependencies, attr_mgr_l1b, delay_max=840 + ) + l1b_bgrates_ds, l1b_goodtimes_ds = result + + # Should create goodtime intervals because RAM and anti-RAM bins have low counts + assert len(l1b_goodtimes_ds["gt_start_met"]) > 0 + # h_synthetic_floor accumulates the modeled background during good times + assert l1b_bgrates_ds["h_synthetic_floor"].values > 0 + + +def test_l1b_bgrates_and_goodtimes_variance_calculation(anc_dependencies, attr_mgr_l1b): + """Test that variance is calculated correctly and handles edge cases.""" + # Arrange + num_epochs = 30 + met_start = 473389200 + met_spacing = 42 + + met_times = np.arange(met_start, met_start + num_epochs * met_spacing, met_spacing) + epoch_times = met_to_ttj2000ns(met_times) + + # Use very low counts to test zero variance handling + h_counts = np.zeros((num_epochs, 7, 60)) + o_counts = np.zeros((num_epochs, 7, 60)) + + # Add some small counts (below threshold) + h_counts[:, :, 20:50] = 0.00001 # Very low but non-zero + o_counts[:, :, 20:50] = 0.000001 + + l1b_histrates = xr.Dataset( + { + "h_counts": (("epoch", "esa_step", "spin_bin_6"), h_counts), + "o_counts": (("epoch", "esa_step", "spin_bin_6"), o_counts), + }, + coords={ + "epoch": epoch_times, + "esa_step": np.arange(1, 8), + "spin_bin_6": np.arange(60), + }, + ) + + sci_dependencies = { + "imap_lo_l1b_histrates": l1b_histrates, + "imap_lo_l1b_de": xr.Dataset(), + "imap_lo_l1b_nhk": xr.Dataset(), + } + + # Act + result = l1b_bgrates_and_goodtimes( + sci_dependencies, anc_dependencies, attr_mgr_l1b, delay_max=840 + ) + + # Assert + l1b_bgrates_ds, l1b_goodtimes_ds = result + + # Variance should never be zero (fallback logic should apply) + assert np.all(l1b_bgrates_ds["h_background_variance"].values > 0) + assert np.all(l1b_bgrates_ds["o_background_variance"].values > 0) + + # Background rates should also never be zero (fallback logic should apply) + assert np.all(l1b_bgrates_ds["h_background_rates"].values > 0) + assert np.all(l1b_bgrates_ds["o_background_rates"].values > 0) + + +def test_l1b_bgrates_and_goodtimes_offset_application(anc_dependencies, attr_mgr_l1b): + """Test that padding is applied to goodtime intervals.""" + # Arrange + num_epochs = 30 + met_start = 473389200 + met_spacing = 42 + + met_times = np.arange(met_start, met_start + num_epochs * met_spacing, met_spacing) + epoch_times = met_to_ttj2000ns(met_times) + + # Low counts (below threshold) + h_counts = np.ones((num_epochs, 7, 60)) * 0.00028 + o_counts = np.ones((num_epochs, 7, 60)) * 0.000028 + + l1b_histrates = xr.Dataset( + { + "h_counts": (("epoch", "esa_step", "spin_bin_6"), h_counts), + "o_counts": (("epoch", "esa_step", "spin_bin_6"), o_counts), + }, + coords={ + "epoch": epoch_times, + "esa_step": np.arange(1, 8), + "spin_bin_6": np.arange(60), + }, + ) + + sci_dependencies = { + "imap_lo_l1b_histrates": l1b_histrates, + "imap_lo_l1b_de": xr.Dataset(), + "imap_lo_l1b_nhk": xr.Dataset(), + } + + # Act + result = l1b_bgrates_and_goodtimes( + sci_dependencies, anc_dependencies, attr_mgr_l1b, delay_max=840 + ) + + # Assert + l1b_bgrates_ds, l1b_goodtimes_ds = result + + # All epochs are below threshold, so one goodtime interval spanning the full + # dataset is expected. GOODTIME_PADDING is subtracted from begin and added to end. + assert len(l1b_goodtimes_ds["gt_start_met"]) == 1 + + raw_begin = met_times[0] + raw_end = met_times[-1] + + assert l1b_goodtimes_ds["gt_start_met"].values[0] <= raw_begin + assert l1b_goodtimes_ds["gt_end_met"].values[0] >= raw_end + + +def test_l1b_bgrates_and_goodtimes_rate_transition_low_to_high( + anc_dependencies, attr_mgr_l1b +): + """Test interval closure when transitioning from low to high rate + (covers begin > 0.0 block).""" + # Arrange - Create dataset that transitions from LOW to HIGH rates + # This specifically tests the "if begin > 0.0:" code path at line ~2787 + num_epochs = 50 # Need at least 5 cycles (50 epochs / 10 per cycle) + met_start = 473389200 + met_spacing = 42 + + met_times = np.arange(met_start, met_start + num_epochs * met_spacing, met_spacing) + epoch_times = met_to_ttj2000ns(met_times) + + # Start with LOW rates for first 30 epochs (3 cycles) + # Then switch to HIGH rates for last 20 epochs (2 cycles) + h_counts = np.ones((num_epochs, 7, 60)) * 0.00028 # Low (below threshold) + o_counts = np.ones((num_epochs, 7, 60)) * 0.000028 + + # Make last 20 epochs HIGH (above threshold) to trigger interval closure + h_counts[30:, :, :] = 0.028 # High (10x threshold) + o_counts[30:, :, :] = 0.0028 + + l1b_histrates = xr.Dataset( + { + "h_counts": (("epoch", "esa_step", "spin_bin_6"), h_counts), + "o_counts": (("epoch", "esa_step", "spin_bin_6"), o_counts), + }, + coords={ + "epoch": epoch_times, + "esa_step": np.arange(1, 8), + "spin_bin_6": np.arange(60), + }, + ) + + sci_dependencies = { + "imap_lo_l1b_histrates": l1b_histrates, + "imap_lo_l1b_de": xr.Dataset(), + "imap_lo_l1b_nhk": xr.Dataset(), + } + + # Act + result = l1b_bgrates_and_goodtimes( + sci_dependencies, anc_dependencies, attr_mgr_l1b, delay_max=840 + ) + + # Assert + l1b_bgrates_ds, l1b_goodtimes_ds = result + + # Should create goodtime interval that gets closed when rate goes high + # The interval should span the first 3 cycles (epochs 0-29) + assert len(l1b_goodtimes_ds["gt_start_met"]) >= 1 + + # First interval should start around epoch 0's time + first_start = l1b_goodtimes_ds["gt_start_met"].values[0] + first_end = l1b_goodtimes_ds["gt_end_met"].values[0] + + # Verify interval was created + assert first_start < first_end + + # Background rates should be calculated from the low-rate period + assert np.all(l1b_bgrates_ds["h_background_rates"].values > 0) + assert np.all(l1b_bgrates_ds["o_background_rates"].values > 0) + + # Variance should also be positive + assert np.all(l1b_bgrates_ds["h_background_variance"].values > 0) + assert np.all(l1b_bgrates_ds["o_background_variance"].values > 0) + + +def test_l1b_bgrates_and_goodtimes_rate_transition_high_to_low_to_high( + anc_dependencies, attr_mgr_l1b +): + """Test multiple intervals created by multiple rate transitions.""" + # Arrange - Create dataset with HIGH -> LOW -> HIGH -> LOW pattern + # This tests multiple calls to the "if begin > 0.0:" code path + num_epochs = 80 + met_start = 473389200 + met_spacing = 42 + + met_times = np.arange(met_start, met_start + num_epochs * met_spacing, met_spacing) + epoch_times = met_to_ttj2000ns(met_times) + + # Initialize with HIGH rates + h_counts = np.ones((num_epochs, 7, 60)) * 0.028 + o_counts = np.ones((num_epochs, 7, 60)) * 0.0028 + + # Pattern: HIGH(0-9), LOW(10-29), HIGH(30-39), LOW(40-59), HIGH(60-79) + # Epochs 10-29 (2 cycles): LOW - should create interval 1 + h_counts[10:30, :, :] = 0.00028 + o_counts[10:30, :, :] = 0.000028 + + # Epochs 40-59 (2 cycles): LOW - should create interval 2 + h_counts[40:60, :, :] = 0.00028 + o_counts[40:60, :, :] = 0.000028 + + l1b_histrates = xr.Dataset( + { + "h_counts": (("epoch", "esa_step", "spin_bin_6"), h_counts), + "o_counts": (("epoch", "esa_step", "spin_bin_6"), o_counts), + }, + coords={ + "epoch": epoch_times, + "esa_step": np.arange(1, 8), + "spin_bin_6": np.arange(60), + }, + ) + + sci_dependencies = { + "imap_lo_l1b_histrates": l1b_histrates, + "imap_lo_l1b_de": xr.Dataset(), + "imap_lo_l1b_nhk": xr.Dataset(), + } + + # Act + result = l1b_bgrates_and_goodtimes( + sci_dependencies, anc_dependencies, attr_mgr_l1b, delay_max=840 + ) + + # Assert + l1b_bgrates_ds, l1b_goodtimes_ds = result + + # Should create at least 2 goodtime intervals (one for each LOW period) + assert len(l1b_goodtimes_ds["gt_start_met"]) >= 2 + + # All intervals should have valid start < end + for i in range(len(l1b_goodtimes_ds["gt_start_met"])): + assert ( + l1b_goodtimes_ds["gt_start_met"].values[i] + < l1b_goodtimes_ds["gt_end_met"].values[i] + ) + + # Background rates should be positive for all intervals + assert np.all(l1b_bgrates_ds["h_background_rates"].values > 0) + assert np.all(l1b_bgrates_ds["o_background_rates"].values > 0) + + +def test_l1b_bgrates_when_synthetic_floor_is_zero(anc_dependencies, attr_mgr_l1b): + num_epochs = 100 + met_start = 473389200 + met_spacing = 42 + met_times = np.arange(met_start, met_start + num_epochs * met_spacing, met_spacing) + epoch_times = met_to_ttj2000ns(met_times) + + # Low counts so that goodtime intervals are found + h_counts = np.ones((num_epochs, 7, 60)) * 0.00028 + o_counts = np.ones((num_epochs, 7, 60)) * 0.000028 + + l1b_histrates = xr.Dataset( + { + "h_counts": (("epoch", "esa_step", "spin_bin_6"), h_counts), + "o_counts": (("epoch", "esa_step", "spin_bin_6"), o_counts), + }, + coords={ + "epoch": epoch_times, + "esa_step": np.arange(1, 8), + "spin_bin_6": np.arange(60), + }, + ) + + sci_dependencies = { + "imap_lo_l1b_histrates": l1b_histrates, + "imap_lo_l1b_de": xr.Dataset(), + "imap_lo_l1b_nhk": xr.Dataset(), + } + + patched_bg_rates = dict(LoConstants.BG_RATES) + patched_bg_rates["H"] = 0.0 + with patch.object(LoConstants, "BG_RATES", patched_bg_rates): + bgrates_ds, _ = l1b_bgrates_and_goodtimes( + sci_dependencies, anc_dependencies, attr_mgr_l1b, delay_max=840 + ) + + # After the floor: bg_rate = anti_ram_nominal / BG_RATE_FLOOR_DIVISOR["H"] > 0 + assert np.all(bgrates_ds["h_background_rates"].values > 0) + + +def test_l1b_bgrates_sigma_when_anti_ram_nominal_is_zero( + anc_dependencies, attr_mgr_l1b +): + num_epochs = 50 + met_start = 473389200 + met_spacing = 42 + met_times = np.arange(met_start, met_start + num_epochs * met_spacing, met_spacing) + epoch_times = met_to_ttj2000ns(met_times) + + # High counts everywhere so no goodtime intervals are found + h_counts = np.ones((num_epochs, 7, 60)) * 0.1 + o_counts = np.ones((num_epochs, 7, 60)) * 0.01 + + l1b_histrates = xr.Dataset( + { + "h_counts": (("epoch", "esa_step", "spin_bin_6"), h_counts), + "o_counts": (("epoch", "esa_step", "spin_bin_6"), o_counts), + }, + coords={ + "epoch": epoch_times, + "esa_step": np.arange(1, 8), + "spin_bin_6": np.arange(60), + }, + ) + + sci_dependencies = { + "imap_lo_l1b_histrates": l1b_histrates, + "imap_lo_l1b_de": xr.Dataset(), + "imap_lo_l1b_nhk": xr.Dataset(), + } + + # Zero the anti-RAM threshold so bg_rate_anti_ram_nominal = 0 for any pivot angle + with ( + patch.object(LoConstants, "PIVOT_ANGLE_THRESHOLDS", {}), + patch.object(LoConstants, "THRESHOLD_BG_RATE_ANTI_RAM_DEFAULT", 0.0), + ): + bgrates_ds, _ = l1b_bgrates_and_goodtimes( + sci_dependencies, anc_dependencies, attr_mgr_l1b, delay_max=840 + ) + + assert np.all(bgrates_ds["h_background_rates"].values == 0.0) + assert np.all(bgrates_ds["h_background_variance"].values == 0.0) diff --git a/imap_processing/tests/lo/test_lo_l1c.py b/imap_processing/tests/lo/test_lo_l1c.py index c4fdf79e89..dd59a4f188 100644 --- a/imap_processing/tests/lo/test_lo_l1c.py +++ b/imap_processing/tests/lo/test_lo_l1c.py @@ -1,3 +1,5 @@ +from unittest.mock import patch + import numpy as np import pytest import xarray as xr @@ -5,13 +7,23 @@ from imap_processing import imap_module_directory from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes from imap_processing.lo.l1c.lo_l1c import ( + N_ESA_ENERGY_STEPS, + N_OFF_ANGLE_BINS, + N_SAMPLES_PER_SPIN, + N_SPIN_ANGLE_BINS, + OFF_ANGLE_BIN_CENTERS, PSET_SHAPE, FilterType, + calculate_bin_weights, calculate_exposure_times, + create_goodtimes_fraction, create_pset_counts, filter_goodtimes, - initialize_pset, + get_representative_spin_times, lo_l1c, + sample_boresight_bins, + set_background_rates, + set_pointing_directions, ) from imap_processing.spice.time import met_to_ttj2000ns @@ -20,20 +32,25 @@ def l1b_de(): l1b_de = xr.Dataset( { - "pointing_bin_lon": ("epoch", [20, 0, 20, 2000, 3500]), - "pointing_bin_lat": ("epoch", [20, 20, 20, 20, 20]), + "spin_bin": ("epoch", [20, 0, 20, 2000, 3500]), + "off_angle_bin": ("epoch", [20, 20, 20, 20, 20]), "esa_step": ("epoch", [1, 2, 1, 4, 5]), "coincidence_type": ( "epoch", [ - "111111", - "111100", - "111000", - "110100", - "110000", + "111111", # golden triple - H + "111111", # golden triple - O (based on TOF) + "111000", # triple + "110100", # double + "110000", # double ], ), - "species": ("epoch", ["h", "o", "h", "h", "o"]), + # TOF data for species identification + # Event 0: H (tof0_s=45, tof1_s=30, tof2=25) + "tof0": ("epoch", [40, 185, 40, 40, 40]), + "tof1": ("epoch", [40, 105, 40, 40, 40]), + "tof2": ("epoch", [25, 105, 25, 25, 25]), + "tof3": ("epoch", [10, 10, 10, 10, 10]), "spin_cycle": ("epoch", [1, 2, 3, 4, 5]), "avg_spin_durations": ("epoch", [15.2, 15.2, 14.9, 15, 14.9]), }, @@ -60,22 +77,29 @@ def repoint_met(): def l1b_de_spin(): l1b_de = xr.Dataset( { - "pointing_bin_lon": ("epoch", [20, 0, 20, 2000, 3500]), - "pointing_bin_lat": ("epoch", [20, 20, 20, 20, 20]), + "spin_bin": ("epoch", [20, 0, 20, 2000, 3500]), + "off_angle_bin": ("epoch", [20, 20, 20, 20, 20]), "esa_step": ("epoch", [1, 2, 1, 4, 5]), "coincidence_type": ( "epoch", [ - "111111", - "111100", - "111000", - "110100", - "110000", + "111111", # golden triple - H + "111111", # golden triple - O (based on TOF) + "111000", # triple + "110100", # double + "110000", # double ], ), - "species": ("epoch", ["h", "o", "h", "h", "o"]), + # TOF data for species identification + # Event 0: H (tof0_s=45, tof1_s=30, tof2=25) + # Event 1: O (tof0_s=185, tof1_s=105, tof2=105) + "tof0": ("epoch", [40, 185, 40, 40, 40]), + "tof1": ("epoch", [40, 105, 40, 40, 40]), + "tof2": ("epoch", [25, 105, 25, 25, 25]), + "tof3": ("epoch", [10, 10, 10, 10, 10]), "spin_cycle": ("epoch", [1, 2, 3, 4, 5]), "avg_spin_durations": ("epoch", [15.2, 15.2, 14.9, 15, 14.9]), + "pivot_angle": ([45.0]), }, coords={ "epoch": met_to_ttj2000ns(np.arange(511000000, 511000000 + 200, 40) + 902), @@ -86,10 +110,23 @@ def l1b_de_spin(): @pytest.fixture def anc_dependencies(): - anc_dependencies_path = ( - imap_module_directory / "tests/lo/test_anc/imap_lo_goodtimes_20250415_v001.csv" - ) - return [str(anc_dependencies_path)] + anc_dependencies_path = [ + str( + imap_module_directory + / "tests/lo/test_anc/imap_lo_good-times-small_20250101_20270101_v001.csv" + ), + str( + imap_module_directory + / "tests/lo/test_anc/" + / "imap_lo_hydrogen-background-small_20250101_20270101_v001.csv" + ), + str( + imap_module_directory + / "tests/lo/test_anc/" + / "imap_lo_oxygen-background-small_20250101_20270101_v001.csv" + ), + ] + return anc_dependencies_path @pytest.fixture @@ -106,39 +143,73 @@ def counts(): return np.zeros(PSET_SHAPE) +# ESA Indices are ESA step - 1 @pytest.fixture def h_counts(counts): h = counts.copy() - h[0, 1, 20, 20] = 2 - h[0, 4, 2000, 20] = 1 + # Only event 0 is H (golden triple with H TOF peaks) + h[0, 0, 20, 20] = 1 return h @pytest.fixture def o_counts(counts): o = counts.copy() - o[0, 5, 3500, 20] = 1 - o[0, 2, 0, 20] = 1 + # Only event 1 is O (golden triple with O TOF peaks) + o[0, 1, 0, 20] = 1 return o @pytest.fixture def triples_counts(counts): triples = counts.copy() - triples[0, 1, 20, 20] = 2 - triples[0, 2, 0, 20] = 1 + # Events 0, 1 are golden triples (111111), event 2 is regular triple (111000) + triples[0, 0, 20, 20] = 2 # events 0 and 2 (both esa_step=1) + triples[0, 1, 0, 20] = 1 # event 1 (esa_step=2) return triples @pytest.fixture def doubles_counts(counts): doubles = counts.copy() - doubles[0, 4, 2000, 20] = 1 - doubles[0, 5, 3500, 20] = 1 + doubles[0, 3, 2000, 20] = 1 + doubles[0, 4, 3500, 20] = 1 return doubles +@pytest.fixture +def l1b_bgrates_ds(): + h_rates = np.array([0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07], dtype=np.float32) + h_var = np.array( + [0.001, 0.002, 0.003, 0.004, 0.005, 0.006, 0.007], dtype=np.float32 + ) + o_rates = np.array( + [0.001, 0.002, 0.003, 0.004, 0.005, 0.006, 0.007], dtype=np.float32 + ) + o_var = np.array( + [0.0001, 0.0002, 0.0003, 0.0004, 0.0005, 0.0006, 0.0007], dtype=np.float32 + ) + return xr.Dataset( + { + "h_background_rates": ("esa_step", h_rates), + "h_background_variance": ("esa_step", h_var), + "o_background_rates": ("esa_step", o_rates), + "o_background_variance": ("esa_step", o_var), + } + ) + + +@patch("imap_processing.lo.l1c.lo_l1c.calculate_exposure_times") +@patch("imap_processing.lo.l1c.lo_l1c.set_background_rates") +@patch("imap_processing.lo.l1c.lo_l1c.filter_goodtimes") +@patch("imap_processing.lo.l1c.lo_l1c.set_pointing_directions") +@patch("imap_processing.lo.l1c.lo_l1c.add_spacecraft_position_and_velocity_to_pset") def test_lo_l1c( + mock_add_spacecraft_position_and_velocity_to_pset, + mock_set_pointing_directions, + mock_filter_goodtimes, + mock_set_background_rates, + mock_calculate_exposure_times, l1b_de_spin, anc_dependencies, use_fake_repoint_data_for_time, @@ -146,73 +217,139 @@ def test_lo_l1c( repoint_met, ): # Arrange - data = {"imap_lo_l1b_de": l1b_de_spin} + data = { + "imap_lo_l1b_de": l1b_de_spin, + "imap_lo_l1b_goodtimes": xr.Dataset( + { + "gt_start_met": ("epoch", [511000000.0]), + "gt_end_met": ("epoch", [511100000.0]), + }, + coords={"epoch": met_to_ttj2000ns([511000000.0])}, + ), + } use_fake_spin_data_for_time(511000000) use_fake_repoint_data_for_time(np.arange(511000000, 511000000 + 86400 * 5, 86400)) + mock_set_background_rates.return_value = (None, None, None) + mock_filter_goodtimes.return_value = l1b_de_spin + mock_set_pointing_directions.return_value = ( + xr.DataArray(np.zeros((3600, 40)), dims=("spin_angle", "off_angle")), + xr.DataArray(np.zeros((3600, 40)), dims=("spin_angle", "off_angle")), + ) + # Mock exposure time calculation to avoid SPICE calls + mock_calculate_exposure_times.return_value = xr.DataArray( + np.ones(PSET_SHAPE, dtype=np.float32), + dims=["epoch", "esa_energy_step", "spin_angle", "off_angle"], + ) + # Pass through the pset with sc_position and sc_velocity added + def mock_add_sc_pos_vel(pset): + pset["sc_position"] = xr.DataArray(np.zeros(3), dims=["x_y_z"]) + pset["sc_velocity"] = xr.DataArray(np.zeros(3), dims=["x_y_z"]) + return pset + + mock_add_spacecraft_position_and_velocity_to_pset.side_effect = mock_add_sc_pos_vel expected_logical_source = "imap_lo_l1c_pset" + # Act - output_dataset = lo_l1c(data, anc_dependencies) + output_dataset = lo_l1c(data, anc_dependencies)[0] # Assert - assert expected_logical_source == output_dataset[0].attrs["Logical_source"] + assert expected_logical_source == output_dataset.attrs["Logical_source"] + # Verify that pivot_angle is passed through from l1b_de + assert "pivot_angle" in output_dataset + assert output_dataset["pivot_angle"].values[0] == 45.0 + mock_add_spacecraft_position_and_velocity_to_pset.assert_called_once() + assert "sc_position" in output_dataset + assert "sc_velocity" in output_dataset -def test_initialize_pset(l1b_de, attr_mgr): +def test_filter_goodtimes(): # Arrange - logical_source = "imap_lo_l1c_pset" - expected_epoch = 7.9794907049e17 + event_mets = [473389199, 473389200, 473389201, 473389202, 473389203, 473407619] + l1b_de_all = xr.Dataset( + { + "esa_step": ("epoch", [1, 2, 1, 4, 5, 2]), + "spin_bin": ("epoch", [1900, 2000, 3000, 3000, 3000, 3000]), + }, + coords={"epoch": met_to_ttj2000ns(event_mets)}, + ) + + # Two goodtime windows: [473389201, 473389203] and [473407619, 473407620] + gt_starts = np.array([473389201.0, 473407619.0]) + goodtimes_ds = xr.Dataset( + { + "gt_start_met": ("epoch", gt_starts), + "gt_end_met": ("epoch", [473389203.0, 473407620.0]), + }, + coords={"epoch": met_to_ttj2000ns(gt_starts)}, + ) + + # Events at MET 473389201-473389203 and 473407619 fall inside goodtime windows; + # 473389199 and 473389200 are before the first window. + expected_mask = [False, False, True, True, True, True] + expected = l1b_de_all.isel(epoch=expected_mask) # Act - pset = initialize_pset(l1b_de, attr_mgr, logical_source) + result = filter_goodtimes(l1b_de_all, goodtimes_ds) # Assert - assert pset.attrs["Logical_source"] == logical_source - np.testing.assert_array_equal(pset["epoch"], expected_epoch) + xr.testing.assert_equal(result, expected) -def test_filter_goodtimes(l1b_de, anc_dependencies): +def test_lo_l1c_no_goodtimes( + l1b_de_spin, + anc_dependencies, + use_fake_repoint_data_for_time, + use_fake_spin_data_for_time, + repoint_met, +): # Arrange - l1b_de_with_badtimes = xr.Dataset( - { - "pointing_bin_lon": ("epoch", [20, 0, 20, 2000, 3500, 200]), - "pointing_bin_lat": ("epoch", [20, 20, 20, 20, 20, 40]), - "esa_step": ("epoch", [1, 2, 1, 4, 5, 2]), - "coincidence_type": ( - "epoch", - ["111111", "111100", "111000", "110100", "110000", "000000"], - ), - "species": ("epoch", ["h", "o", "h", "h", "o", "u"]), - "spin_cycle": ("epoch", [1, 2, 3, 4, 5, 12]), - "avg_spin_durations": ("epoch", [15.2, 15.2, 14.9, 15, 14.9, 50]), - }, - coords={ - "epoch": [ - 7.9794907049e17, - 7.9794907153e17, - 7.9794907254e17, - 7.9794907354e17, - 7.9794907454e17, - 8.74117692184e17, - ], - }, - ) - l1b_de_no_badtimes_expected = l1b_de.copy() + # Goodtime window [0, 1] does not cover any event + data = { + "imap_lo_l1b_de": l1b_de_spin, + "imap_lo_l1b_goodtimes": xr.Dataset( + { + "gt_start_met": ("epoch", [0.0]), + "gt_end_met": ("epoch", [1.0]), + }, + coords={"epoch": met_to_ttj2000ns([0.0])}, + ), + } + use_fake_spin_data_for_time(511000000) + use_fake_repoint_data_for_time(np.arange(511000000, 511000000 + 86400 * 5, 86400)) + expected_logical_source = "imap_lo_l1c_pset" # Act - l1b_no_badtimes = filter_goodtimes(l1b_de_with_badtimes, anc_dependencies) + output_dataset = lo_l1c(data, anc_dependencies)[0] # Assert - xr.testing.assert_equal(l1b_no_badtimes, l1b_de_no_badtimes_expected) + assert expected_logical_source == output_dataset.attrs["Logical_source"] + # Verify that pivot_angle is passed through from l1b_de + assert "pivot_angle" in output_dataset + assert output_dataset["pivot_angle"].values[0] == 45.0 + expected_counts = np.zeros((1, 7, 3600, 40)) + np.testing.assert_array_equal(output_dataset["h_counts"], expected_counts) + np.testing.assert_array_equal(output_dataset["o_counts"], expected_counts) + np.testing.assert_array_equal(output_dataset["doubles_counts"], expected_counts) + np.testing.assert_array_equal(output_dataset["triples_counts"], expected_counts) + np.testing.assert_array_equal(output_dataset["h_background_rates"], expected_counts) + np.testing.assert_array_equal(output_dataset["o_background_rates"], expected_counts) + expected = np.zeros((1, 3600, 40)) + np.testing.assert_array_equal(output_dataset["hae_latitude"], expected) def test_create_pset_counts(l1b_de): # Arrange expected_counts = np.zeros((1, 7, 3600, 40)) - expected_counts[0, 1, 20, 20] = 2 - expected_counts[0, 4, 2000, 20] = 1 - expected_counts[0, 5, 3500, 20] = 1 - expected_counts[0, 2, 0, 20] = 1 + # ESA Indices are ESA step - 1 + # Events 0 and 2 have esa_step=1, bin 20 + expected_counts[0, 0, 20, 20] = 2 + # Event 1 has esa_step=2, bin 0 + expected_counts[0, 1, 0, 20] = 1 + # Event 3 has esa_step=4, bin 2000 + expected_counts[0, 3, 2000, 20] = 1 + # Event 4 has esa_step=5, bin 3500 + expected_counts[0, 4, 3500, 20] = 1 # Act counts = create_pset_counts(l1b_de) @@ -253,21 +390,442 @@ def test_create_doubles_pset_counts(l1b_de, doubles_counts): np.testing.assert_array_equal(counts, doubles_counts) -def test_calculate_exposure_times(l1b_de): +def test_calculate_exposure_times(use_fake_spin_data_for_time): + """Test the statistical exposure time calculation.""" # Arrange - counts = create_pset_counts(l1b_de) - expected_exposure_times = np.full(PSET_SHAPE, np.nan) - # Average of the exposure times for each bin - expected_exposure_times[0, 1, 20, 20] = 4 * np.mean([15.2, 14.9]) / 3600 - expected_exposure_times[0, 4, 2000, 20] = 4 * 15 / 3600 - expected_exposure_times[0, 5, 3500, 20] = 4 * 14.9 / 3600 - expected_exposure_times[0, 2, 0, 20] = 4 * 15.2 / 2600 + pointing_start_met = 511000000.0 + pointing_end_met = 511000100.0 # 100 second pointing + use_fake_spin_data_for_time(pointing_start_met) + + with ( + patch( + "imap_processing.lo.l1c.lo_l1c.lo_instrument_pointing" + ) as mock_lo_instrument_pointing, + patch( + "imap_processing.lo.l1c.lo_l1c.met_to_ttj2000ns" + ) as mock_met_to_ttj2000ns, + patch("imap_processing.lo.l1c.lo_l1c.ttj2000ns_to_et") as mock_ttj2000ns_to_et, + ): + # Mock the time conversions to pass through + mock_met_to_ttj2000ns.side_effect = lambda x: x * 1e9 + mock_ttj2000ns_to_et.side_effect = lambda x: x / 1e9 + + # Mock lo_instrument_pointing to return pointing at spin_angle=270, off_angle=0 + # for all sample times (simulating no off-pointing with 90 degree pivot) + def mock_pointing(ets, pivot_angle, to_frame): + n_times = len(np.atleast_1d(ets)) + # Return (longitude, latitude) = (270, 0) for all times + return np.column_stack([np.full(n_times, 270.0), np.zeros(n_times)]) + + mock_lo_instrument_pointing.side_effect = mock_pointing + + # Act + exposure_times = calculate_exposure_times( + pointing_start_met, pointing_end_met, n_representative_spins=3 + ) + + # Assert + # Check shape + assert exposure_times.shape == PSET_SHAPE + + # Check that exposure times sum to approximately total pointing duration / 7 + # Each ESA energy step is only active for 1/7 of the total time + # (within tolerance due to binning) + total_duration = pointing_end_met - pointing_start_met + # Sum over spin_angle and off_angle dimensions for one ESA step + exposure_sum = exposure_times.values[0, 0, :, :].sum() + np.testing.assert_allclose( + exposure_sum, total_duration / N_ESA_ENERGY_STEPS, rtol=0.01 + ) + + # Check that all ESA steps have the same exposure (geometry-independent) + for i in range(1, 7): + np.testing.assert_array_equal( + exposure_times.values[0, 0, :, :], + exposure_times.values[0, i, :, :], + ) + + +def test_get_representative_spin_times(use_fake_spin_data_for_time): + """Test that representative spins are evenly distributed across pointing.""" + # Arrange + pointing_start_met = 511000000.0 + pointing_end_met = 511001500.0 # ~100 spins at ~15s each + use_fake_spin_data_for_time(pointing_start_met) + # Act - exposure_times = calculate_exposure_times(counts, l1b_de) + representative_spins = get_representative_spin_times( + pointing_start_met, pointing_end_met, n_spins=5 + ) # Assert - np.testing.assert_allclose( - exposure_times, - expected_exposure_times, - atol=1e-2, + assert len(representative_spins) == 5 + assert "spin_start_met" in representative_spins.columns + assert "actual_spin_period" in representative_spins.columns + + # Check that spins are within the pointing period + assert all(representative_spins["spin_start_met"] >= pointing_start_met) + assert all(representative_spins["spin_start_met"] < pointing_end_met) + + +def test_get_representative_spin_times_fewer_available(use_fake_spin_data_for_time): + """Test that we get all spins when fewer than requested are available.""" + # Arrange - very short pointing with only a few spins + pointing_start_met = 511000000.0 + pointing_end_met = 511000045.0 # ~3 spins at ~15s each + use_fake_spin_data_for_time(pointing_start_met) + + # Act + representative_spins = get_representative_spin_times( + pointing_start_met, pointing_end_met, n_spins=10 ) + + # Assert - should get all available spins (less than 10) + assert len(representative_spins) <= 10 + assert len(representative_spins) >= 1 + + +def test_sample_boresight_bins(): + """Test boresight sampling within a single spin.""" + # Arrange + spin_start_met = 511000000.0 + spin_period = 15.0 + + with ( + patch( + "imap_processing.lo.l1c.lo_l1c.lo_instrument_pointing" + ) as mock_lo_instrument_pointing, + patch( + "imap_processing.lo.l1c.lo_l1c.met_to_ttj2000ns" + ) as mock_met_to_ttj2000ns, + patch("imap_processing.lo.l1c.lo_l1c.ttj2000ns_to_et") as mock_ttj2000ns_to_et, + ): + # Mock time conversions + mock_met_to_ttj2000ns.side_effect = lambda x: x * 1e9 + mock_ttj2000ns_to_et.side_effect = lambda x: x / 1e9 + + # Mock lo_instrument_pointing to simulate rotating boresight + def mock_pointing(ets, pivot_angle, to_frame): + n_times = len(np.atleast_1d(ets)) + # Simulate boresight sweeping through spin angles (0-360) + # with zero off-angle (latitude) + spin_angles = np.linspace(0, 360, n_times, endpoint=False) + off_angles = np.zeros(n_times) + return np.column_stack([spin_angles, off_angles]) + + mock_lo_instrument_pointing.side_effect = mock_pointing + + # Act + spin_angles, off_angles = sample_boresight_bins(spin_start_met, spin_period) + + # Assert + assert len(spin_angles) == N_SAMPLES_PER_SPIN + assert len(off_angles) == N_SAMPLES_PER_SPIN + + # Check spin angles are in valid range [0, 360) + assert all(spin_angles >= 0) + assert all(spin_angles < 360) + + # Check off angles are near zero (as mocked) + np.testing.assert_allclose(off_angles, 0, atol=1e-10) + + +def test_calculate_bin_weights(): + """Test bin weight calculation from sampled angles.""" + # Arrange - create samples concentrated in specific bins + # All samples at off_angle=0 + n_samples = 1000 + off_angles = np.full(n_samples, 0.0) + + # Act + bin_weights = calculate_bin_weights(off_angles) + + # Assert + assert bin_weights.shape == (N_OFF_ANGLE_BINS,) + + # Weights should sum to 1 + np.testing.assert_allclose(bin_weights.sum(), 1.0) + + # Find the bin that should have all the weight + # off_angle=0 is in bin 20 (center of [-2, 2] range with 40 bins) + expected_off_bin = 20 # (0 - (-2)) / 0.1 = 20 + + # That bin should have weight close to 1 + assert bin_weights[expected_off_bin] > 0.9 + + +def test_calculate_bin_weights_distributed(): + """Test bin weights with uniformly distributed samples.""" + # Arrange - uniform distribution across off_angles + np.random.seed(42) + n_samples = 100000 + off_angles = np.random.uniform(-2, 2, n_samples) + + # Act + bin_weights = calculate_bin_weights(off_angles) + + # Assert + assert bin_weights.shape == (N_OFF_ANGLE_BINS,) + + # Weights should sum to 1 + np.testing.assert_allclose(bin_weights.sum(), 1.0) + + # With uniform distribution, weights should be approximately equal + expected_weight = 1.0 / N_OFF_ANGLE_BINS + np.testing.assert_allclose(bin_weights.mean(), expected_weight, rtol=0.1) + + +def test_create_goodtimes_fraction(): + """Test good-times fractional coverage calculation from ancillary data.""" + # Arrange - create a simple goodtimes Dataset + # Good-times cover the full pointing duration for all spin bins + # bin_start and bin_end are inclusive, 0-indexed (0-59 for 6-degree bins) + goodtimes_ds = xr.Dataset( + { + "gt_start_met": ("epoch", [500000000.0, 500000000.0]), + "gt_end_met": ("epoch", [500001000.0, 500001000.0]), + }, + coords={"epoch": [0, 1]}, + ) + + pointing_start_met = 500000000.0 + pointing_end_met = 500001000.0 + + # Act + fraction = create_goodtimes_fraction( + goodtimes_ds, pointing_start_met, pointing_end_met + ) + + # Assert + assert fraction.shape == (N_ESA_ENERGY_STEPS, N_SPIN_ANGLE_BINS) + + # The current implementation does not filter by bin range or E-Step flags, + # so coverage is 1.0 everywhere + np.testing.assert_allclose(fraction, 1.0) + + +def test_create_goodtimes_fraction_partial_coverage(): + """Test good-times with partial time coverage of pointing period.""" + # Arrange - good-times cover only half of the pointing duration + goodtimes_ds = xr.Dataset( + { + "gt_start_met": ("epoch", [500000000.0]), + "gt_end_met": ("epoch", [500000500.0]), # Only first 500s of 1000s pointing + }, + coords={"epoch": [0]}, + ) + + pointing_start_met = 500000000.0 + pointing_end_met = 500001000.0 + + # Act + fraction = create_goodtimes_fraction( + goodtimes_ds, pointing_start_met, pointing_end_met + ) + + # Assert - all bins should have 50% coverage + np.testing.assert_allclose(fraction, 0.5) + + +def test_create_goodtimes_fraction_no_overlap(): + """Test good-times fraction when no good-times overlap with pointing.""" + # Arrange - goodtimes outside pointing period + goodtimes_ds = xr.Dataset( + { + "gt_start_met": ("epoch", [400000000.0]), + "gt_end_met": ("epoch", [400001000.0]), + }, + coords={"epoch": [0]}, + ) + + pointing_start_met = 500000000.0 + pointing_end_met = 500001000.0 + + # Act + fraction = create_goodtimes_fraction( + goodtimes_ds, pointing_start_met, pointing_end_met + ) + + # Assert - all zeros since no overlap + np.testing.assert_allclose(fraction, 0.0) + + +@pytest.mark.parametrize("species", [FilterType.HYDROGEN, FilterType.OXYGEN]) +def test_set_background_rates(l1b_bgrates_ds, attr_mgr, species): + # Arrange + sci_deps = {"imap_lo_l1b_bgrates": l1b_bgrates_ds} + species_key = species.value + expected_rates = l1b_bgrates_ds[f"{species_key}_background_rates"].values + expected_var = l1b_bgrates_ds[f"{species_key}_background_variance"].values + + # Act + rates, uncert, err = set_background_rates(species, sci_deps, attr_mgr) + + # Assert shape + assert rates.shape == (1, N_ESA_ENERGY_STEPS, N_SPIN_ANGLE_BINS, N_OFF_ANGLE_BINS) + assert uncert.shape == (1, N_ESA_ENERGY_STEPS, N_SPIN_ANGLE_BINS, N_OFF_ANGLE_BINS) + assert err.shape == (1, N_ESA_ENERGY_STEPS, N_SPIN_ANGLE_BINS, N_OFF_ANGLE_BINS) + + # Rates and uncertainties must be uniform across spatial bins for each ESA step + for i in range(N_ESA_ENERGY_STEPS): + np.testing.assert_array_equal( + rates.values[0, i, :, :], + np.full( + (N_SPIN_ANGLE_BINS, N_OFF_ANGLE_BINS), + expected_rates[i], + dtype=np.float16, + ), + ) + np.testing.assert_array_equal( + uncert.values[0, i, :, :], + np.full( + (N_SPIN_ANGLE_BINS, N_OFF_ANGLE_BINS), expected_var[i], dtype=np.float16 + ), + ) + + # Systematic error is always zero + np.testing.assert_array_equal(err.values, 0) + + +def test_set_background_rates_no_bgrates(attr_mgr): + """Returns zeros when imap_lo_l1b_bgrates is absent from sci_dependencies.""" + rates, uncert, err = set_background_rates(FilterType.HYDROGEN, {}, attr_mgr) + + np.testing.assert_array_equal(rates.values, 0) + np.testing.assert_array_equal(uncert.values, 0) + np.testing.assert_array_equal(err.values, 0) + + +def test_set_background_rates_species_error(attr_mgr): + # Act + with pytest.raises( + ValueError, match="Species must be 'h' or 'o', but got doubles." + ): + set_background_rates(FilterType.DOUBLES, {}, attr_mgr) + + +def test_set_pointing_directions(attr_mgr): + """Test the set_pointing_directions function.""" + # Mock the external dependencies + mock_et = 123456789.0 + mock_hae_az_el = np.stack( + np.meshgrid(np.arange(3600), np.arange(40), indexing="ij"), axis=-1 + ) # spin_angle x off_angle x 2 + with ( + patch("imap_processing.lo.l1c.lo_l1c.ttj2000ns_to_et") as mock_ttj2000ns_to_et, + patch( + "imap_processing.lo.l1c.lo_l1c.frame_transform_az_el" + ) as mock_frame_transform, + ): + # Set up mocks + mock_ttj2000ns_to_et.return_value = mock_et + mock_frame_transform.return_value = mock_hae_az_el + + # Test input + test_epoch = 1000000000.0 + + # Call the function + hae_longitude, hae_latitude = set_pointing_directions(test_epoch, attr_mgr, 90) + + # Verify ttj2000ns_to_et was called correctly + mock_ttj2000ns_to_et.assert_called_once_with(test_epoch) + + # Verify frame_transform_az_el was called correctly + mock_frame_transform.assert_called_once() + call_args = mock_frame_transform.call_args + assert call_args[0][0] == mock_et # et parameter + assert call_args[1]["degrees"] is True + # Verify the shape of dps_az_el + dps_az_el = call_args[0][1] + assert dps_az_el.shape == (3600, 40, 2) # spin_angle x off_angle x 2 + + # Verify the returned DataArrays + assert isinstance(hae_longitude, xr.DataArray) + assert isinstance(hae_latitude, xr.DataArray) + + # Check dimensions + assert hae_longitude.dims == ("epoch", "spin_angle", "off_angle") + assert hae_latitude.dims == ("epoch", "spin_angle", "off_angle") + + # Check shapes + assert hae_longitude.shape == (1, 3600, 40) + assert hae_latitude.shape == (1, 3600, 40) + + # Check data types + assert hae_longitude.dtype == np.float64 + assert hae_latitude.dtype == np.float64 + + # Check that longitude uses first component (index 0) + # and latitude uses second (index 1) + # Note: Compare with the added epoch dimension [0] + np.testing.assert_array_equal(hae_longitude.values[0], mock_hae_az_el[:, :, 0]) + np.testing.assert_array_equal(hae_latitude.values[0], mock_hae_az_el[:, :, 1]) + + +def test_set_pointing_directions_meshgrid(attr_mgr): + """Test that the meshgrid is created correctly.""" + with ( + patch("imap_processing.lo.l1c.lo_l1c.ttj2000ns_to_et") as mock_ttj2000ns_to_et, + patch( + "imap_processing.lo.l1c.lo_l1c.frame_transform_az_el" + ) as mock_frame_transform, + ): + mock_ttj2000ns_to_et.return_value = 123456789.0 + mock_hae_az_el = np.stack( + np.meshgrid(np.arange(3600), np.arange(40), indexing="ij"), axis=-1 + ) # spin_angle x off_angle x 2 + mock_frame_transform.return_value = mock_hae_az_el + + set_pointing_directions(1000000000.0, attr_mgr, 90) + + # Get the dps_az_el array that was passed to frame_transform_az_el + call_args = mock_frame_transform.call_args + dps_az_el = call_args[0][1] + + # Verify the meshgrid was created correctly + # The first component should be spin angles repeated for each off angle + expected_spin_shape = (3600, 40) + assert dps_az_el[:, :, 0].shape == expected_spin_shape + + # The second component should be off angles repeated for each spin angle + assert dps_az_el[:, :, 1].shape == expected_spin_shape + + # Check that spin angles vary along the first dimension + assert not np.allclose(dps_az_el[0, 0, 0], dps_az_el[1, 0, 0]) + + # Check that off angles vary along the second dimension + assert not np.allclose(dps_az_el[0, 0, 1], dps_az_el[0, 1, 1]) + + +@pytest.mark.parametrize("pivot_angle", [75, 90, 105]) +def test_set_pointing_directions_pivot_angle(attr_mgr, pivot_angle): + """Test that pivot_angle correctly adjusts off_angles before transformation.""" + with ( + patch("imap_processing.lo.l1c.lo_l1c.ttj2000ns_to_et") as mock_ttj2000ns_to_et, + patch( + "imap_processing.lo.l1c.lo_l1c.frame_transform_az_el" + ) as mock_frame_transform, + ): + mock_ttj2000ns_to_et.return_value = 123456789.0 + mock_hae_az_el = np.stack( + np.meshgrid(np.arange(3600), np.arange(40), indexing="ij"), axis=-1 + ) + mock_frame_transform.return_value = mock_hae_az_el + + set_pointing_directions(1000000000.0, attr_mgr, pivot_angle=pivot_angle) + + # Get the dps_az_el array that was passed to frame_transform_az_el + call_args = mock_frame_transform.call_args + dps_az_el = call_args[0][1] + + # Calculate expected offset: off_angles should be adjusted by (90 - pivot_angle) + offset = 90 - pivot_angle + + # OFF_ANGLE_BIN_CENTERS range from -1.95 to 1.95 (40 bins from -2 to 2) + # After offset, they should be shifted by the offset amount + expected_off_angles = OFF_ANGLE_BIN_CENTERS + offset + + # Check that the off_angle component (index 1) was adjusted correctly + # dps_az_el[:, :, 1] should have the adjusted off angles repeated across spin + actual_off_angles = dps_az_el[0, :, 1] # Take first spin angle + np.testing.assert_allclose(actual_off_angles, expected_off_angles, rtol=1e-10) diff --git a/imap_processing/tests/lo/test_lo_l2.py b/imap_processing/tests/lo/test_lo_l2.py index 0179630961..3422f20704 100644 --- a/imap_processing/tests/lo/test_lo_l2.py +++ b/imap_processing/tests/lo/test_lo_l2.py @@ -1,9 +1,19 @@ +"""Comprehensive test suite for IMAP-Lo L2 data processing.""" + +from pathlib import Path +from unittest.mock import Mock, patch + import numpy as np +import pandas as pd import pytest import xarray as xr -from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes -from imap_processing.ena_maps.ena_maps import HealpixSkyMap, RectangularSkyMap +from imap_processing.cdf.utils import load_cdf +from imap_processing.ena_maps.ena_maps import RectangularSkyMap +from imap_processing.ena_maps.utils.corrections import ( + add_spacecraft_position_and_velocity_to_pset, +) +from imap_processing.ena_maps.utils.naming import MapDescriptor from imap_processing.lo.l1c.lo_l1c import ( ESA_ENERGY_STEPS, N_OFF_ANGLE_BINS, @@ -14,22 +24,53 @@ SPIN_ANGLE_BIN_CENTERS, ) from imap_processing.lo.l2.lo_l2 import ( - add_attributes, - calculate_fluxes, + _prepare_corrections, + add_efficiency_factors_to_pset, + calculate_all_rates_and_intensities, + calculate_backgrounds, + calculate_bootstrap_corrections, + calculate_efficiency_corrected_quantities, + calculate_flux_corrections, + calculate_intensities, calculate_rates, + calculate_sputtering_corrections, + cleanup_intermediate_variables, + create_sky_map_from_psets, + initialize_geometric_factor_variables, lo_l2, - project_pset_to_sky_map, + load_efficiency_data, + normalize_pset_coordinates, + populate_geometric_factors, + process_single_pset, + project_pset_to_map, + reduce_geometric_factor_dataset, ) -from imap_processing.spice import geometry + +# ============================================================================= +# FIXTURES FOR MOCK DATA +# ============================================================================= + + +@pytest.fixture(params=["h", "o", "doubles", "triples"]) +def species_name(request): + """Parametrized fixture for different species names.""" + return request.param @pytest.fixture -def pset(): - h_counts = np.zeros(PSET_SHAPE) - h_counts[:, :, :, 0:10] = 1 +def sample_pset(): + """Create a sample pointing set with typical data variables.""" + # Create counts data with some non-zero values + counts = np.zeros(PSET_SHAPE) + counts[:, 2:4, 10:20, 5:15] = 5 # Add some counts for testing - exposure_time = np.full(PSET_SHAPE, 0.5) + exposure_factor = np.full(PSET_SHAPE, 0.5) + # Create background rates data + background_rates = np.full(PSET_SHAPE, 0.1) # 0.1 counts/s background + background_rates_stat_uncert = np.full(PSET_SHAPE, 0.01) # 10% uncertainty + + # Create coordinate arrays lons, lats = np.meshgrid( SPIN_ANGLE_BIN_CENTERS, OFF_ANGLE_BIN_CENTERS, indexing="ij" ) @@ -40,13 +81,12 @@ def pset(): dataset = xr.Dataset( { - "h_counts": ( - PSET_DIMS, - h_counts, - ), - "exposure_time": ( + "counts": (PSET_DIMS, counts), + "exposure_factor": (PSET_DIMS, exposure_factor), + "background_rates": (PSET_DIMS, background_rates), + "background_rates_stat_uncert": ( PSET_DIMS, - exposure_time, + background_rates_stat_uncert, ), "hae_longitude": (("epoch", "spin_angle", "off_angle"), hae_longitude), "hae_latitude": (("epoch", "spin_angle", "off_angle"), hae_latitude), @@ -62,159 +102,2746 @@ def pset(): @pytest.fixture -def map(): - fake_field = np.zeros((1, 7, 60, 30)) - exposure_time = np.full((1, 7, 60, 30), 0.5) +def sample_pset_for_species(species_name): + """Create a sample pointing set for a specific species.""" + # Create counts data with some non-zero values + counts = np.zeros(PSET_SHAPE) + if species_name == "h": + counts[:, 2:4, 10:20, 5:15] = 5 + elif species_name == "o": + counts[:, 1:3, 15:25, 8:18] = 3 + elif species_name == "doubles": + counts[:, 0:2, 5:15, 10:20] = 2 + elif species_name == "triples": + counts[:, 3:5, 20:30, 15:25] = 1 + + exposure_factor = np.full(PSET_SHAPE, 0.5) + + # Create coordinate arrays + lons, lats = np.meshgrid( + SPIN_ANGLE_BIN_CENTERS, OFF_ANGLE_BIN_CENTERS, indexing="ij" + ) + hae_longitude = np.empty((1, N_SPIN_ANGLE_BINS, N_OFF_ANGLE_BINS)) + hae_latitude = np.empty((1, N_SPIN_ANGLE_BINS, N_OFF_ANGLE_BINS)) + hae_longitude[0, :, :] = lons + hae_latitude[0, :, :] = lats + + # Base dataset with coords and exposure time + dataset_dict = { + "counts": (PSET_DIMS, counts), + "exposure_factor": (PSET_DIMS, exposure_factor), + "hae_longitude": (("epoch", "spin_angle", "off_angle"), hae_longitude), + "hae_latitude": (("epoch", "spin_angle", "off_angle"), hae_latitude), + } + + # Add background rates only for h and o + if species_name in ["h", "o"]: + bg_rate = np.full(PSET_SHAPE, 0.1 if species_name == "h" else 0.05) + bg_uncert = np.full(PSET_SHAPE, 0.01 if species_name == "h" else 0.005) + dataset_dict["background_rates"] = (PSET_DIMS, bg_rate) + dataset_dict["background_rates_stat_uncert"] = ( + PSET_DIMS, + bg_uncert, + ) + + dataset = xr.Dataset( + dataset_dict, + coords={ + "epoch": [8.1794907049e17], + "esa_energy_step": ESA_ENERGY_STEPS, + "spin_angle": SPIN_ANGLE_BIN_CENTERS, + "off_angle": OFF_ANGLE_BIN_CENTERS, + }, + ) + return dataset + + +@pytest.fixture +def minimal_pset(): + """Create a minimal pointing set with typical data for testing.""" + counts = np.ones(PSET_SHAPE) # All ones for easy testing + exposure_factor = np.full(PSET_SHAPE, 1.0) # 1 second exposure for easy math + + # Create simple background rates for testing + background_rates = np.full(PSET_SHAPE, 0.2) # 0.2 counts/s + background_rates_stat_uncert = np.full(PSET_SHAPE, 0.02) # 10% uncertainty + + # Simple coordinate arrays + lons, lats = np.meshgrid( + SPIN_ANGLE_BIN_CENTERS, OFF_ANGLE_BIN_CENTERS, indexing="ij" + ) + hae_longitude = np.empty((1, N_SPIN_ANGLE_BINS, N_OFF_ANGLE_BINS)) + hae_latitude = np.empty((1, N_SPIN_ANGLE_BINS, N_OFF_ANGLE_BINS)) + hae_longitude[0, :, :] = lons + hae_latitude[0, :, :] = lats dataset = xr.Dataset( { - "h_counts": (("epoch", "energy", "longitude", "latitude"), fake_field), - "exposure_time": ( - ("epoch", "energy", "longitude", "latitude"), - exposure_time, + "counts": (PSET_DIMS, counts), + "exposure_factor": (PSET_DIMS, exposure_factor), + "background_rates": (PSET_DIMS, background_rates), + "background_rates_stat_uncert": ( + PSET_DIMS, + background_rates_stat_uncert, ), - "h_rate": (("epoch", "energy", "longitude", "latitude"), fake_field), - "h_flux": (("epoch", "energy", "longitude", "latitude"), fake_field), - "solid_angle": (("epoch", "energy", "longitude", "latitude"), fake_field), + "hae_longitude": (("epoch", "spin_angle", "off_angle"), hae_longitude), + "hae_latitude": (("epoch", "spin_angle", "off_angle"), hae_latitude), }, coords={ "epoch": [8.1794907049e17], - "longitude": [i for i in range(60)], - "latitude": [i for i in range(30)], - "energy": ESA_ENERGY_STEPS, + "esa_energy_step": ESA_ENERGY_STEPS, + "spin_angle": SPIN_ANGLE_BIN_CENTERS, + "off_angle": OFF_ANGLE_BIN_CENTERS, }, ) return dataset @pytest.fixture -def attr_mgr(): - attr_mgr = ImapCdfAttributes() - attr_mgr.add_instrument_global_attrs(instrument="lo") - attr_mgr.add_instrument_variable_attrs(instrument="enamaps", level="l2-common") - attr_mgr.add_instrument_variable_attrs(instrument="enamaps", level="l2-rectangular") - return attr_mgr +def minimal_pset_for_species(species_name): + """Create a minimal pointing set for a specific species.""" + # Create simple counts data + if species_name == "h": + counts = np.ones(PSET_SHAPE) + elif species_name == "o": + counts = np.ones(PSET_SHAPE) * 0.5 + elif species_name == "doubles": + counts = np.ones(PSET_SHAPE) * 0.2 + elif species_name == "triples": + counts = np.ones(PSET_SHAPE) * 0.1 + exposure_factor = np.full(PSET_SHAPE, 1.0) # 1 second exposure for easy math + + # Simple coordinate arrays + lons, lats = np.meshgrid( + SPIN_ANGLE_BIN_CENTERS, OFF_ANGLE_BIN_CENTERS, indexing="ij" + ) + hae_longitude = np.empty((1, N_SPIN_ANGLE_BINS, N_OFF_ANGLE_BINS)) + hae_latitude = np.empty((1, N_SPIN_ANGLE_BINS, N_OFF_ANGLE_BINS)) + hae_longitude[0, :, :] = lons + hae_latitude[0, :, :] = lats + + # Base dataset with coords and exposure time + dataset_dict = { + "counts": (PSET_DIMS, counts), + "exposure_factor": (PSET_DIMS, exposure_factor), + "hae_longitude": (("epoch", "spin_angle", "off_angle"), hae_longitude), + "hae_latitude": (("epoch", "spin_angle", "off_angle"), hae_latitude), + } + + # Add background rates for all species + bg_rate = np.full(PSET_SHAPE, 0.2 if species_name == "h" else 0.1) + bg_uncert = np.full(PSET_SHAPE, 0.02 if species_name == "h" else 0.01) + dataset_dict["background_rates"] = (PSET_DIMS, bg_rate) + dataset_dict["background_rates_stat_uncert"] = (PSET_DIMS, bg_uncert) + + dataset = xr.Dataset( + dataset_dict, + coords={ + "epoch": [8.1794907049e17], + "esa_energy_step": ESA_ENERGY_STEPS, + "spin_angle": SPIN_ANGLE_BIN_CENTERS, + "off_angle": OFF_ANGLE_BIN_CENTERS, + }, + ) + return dataset -@pytest.mark.external_kernel -def test_project_pset_to_rect_map(pset, imap_ena_sim_metakernel): - # Arrange - descriptor = "l090-ena-h-sf-nsp-ram-hae-6deg-3mo" - # Act - lo_rect_map = project_pset_to_sky_map([pset], descriptor) +@pytest.fixture +def sample_efficiency_data(): + """Create sample efficiency factor data for testing.""" + data = { + "Date": [np.datetime64("2025-01-01"), np.datetime64("2025-01-02")], + "E-Step1_eff": [0.8, 0.85], + "E-Step2_eff": [0.82, 0.87], + "E-Step3_eff": [0.84, 0.89], + "E-Step4_eff": [0.86, 0.91], + "E-Step5_eff": [0.88, 0.93], + "E-Step6_eff": [0.90, 0.95], + "E-Step7_eff": [0.92, 0.97], + } + return pd.DataFrame(data) - # Assert - assert isinstance(lo_rect_map, RectangularSkyMap) - assert lo_rect_map.spacing_deg == 6 - assert lo_rect_map.spice_reference_frame == geometry.SpiceFrame.IMAP_HAE - assert lo_rect_map.num_points == 1800 +@pytest.fixture +def sample_geometric_factor_data(): + """Create sample geometric factor data for testing.""" + h_gf_data = [] + o_gf_data = [] -@pytest.mark.external_kernel -def test_project_pset_to_healpix_map(pset, furnish_kernels): - # Arrange - descriptor = "l090-ena-h-sf-nsp-ram-hnu-nside2-3mo" - kernels = [ - "imap_sclk_0000.tsc", - "imap_science_100.tf", - "naif0012.tls", - "imap_spk_demo.bsp", - "sim_1yr_imap_pointing_frame.bc", - ] - with furnish_kernels(kernels): - # Act - lo_rect_map = project_pset_to_sky_map([pset], descriptor) - - # Assert - assert isinstance(lo_rect_map, HealpixSkyMap) - assert lo_rect_map.nside == 2 - assert lo_rect_map.spice_reference_frame == geometry.SpiceFrame.IMAP_HNU - assert lo_rect_map.num_points == 48 + for i in range(7): # 7 energy steps + h_gf_data.append( + { + "esa_mode": 0, + "Observed_E-Step": i + 1, + "incident_E-Step": i + 1, + "Cntr_E": 0.01 * (i + 1), # Simple energy values + "Cntr_E_unc": 0.001 * (i + 1), + "GF_Trpl_H": 1e-4 * (i + 1), + "GF_Trpl_H_unc": 1e-5 * (i + 1), + "GF_Dbl_all": 2e-4 * (i + 1), + "GF_Dbl_all_unc": 2e-5 * (i + 1), + "GF_Trpl_all": 3e-4 * (i + 1), + "GF_Trpl_all_unc": 3e-5 * (i + 1), + } + ) + o_gf_data.append( + { + "esa_mode": 0, + "Observed_E-Step": i + 1, + "incident_E-Step": i + 1, + "Cntr_E": 0.015 * (i + 1), # Slightly different for oxygen + "Cntr_E_unc": 0.0015 * (i + 1), + "GF_Trpl_O": 1.5e-4 * (i + 1), + "GF_Trpl_O_unc": 1.5e-5 * (i + 1), + } + ) -@pytest.mark.external_kernel -def test_calculate_rates(imap_ena_sim_metakernel): - # Arrange - counts = np.zeros((1, 7, 1800)) - counts[0, 0, 0] = 1 - counts[0, 0, 1] = 2 + return pd.DataFrame(h_gf_data), pd.DataFrame(o_gf_data) - exposure_time = np.full((1, 7, 1800), 0.5) - expected_rates = np.zeros((1, 7, 1800)) - expected_rates[0, 0, 0] = 2 - expected_rates[0, 0, 1] = 4 +@pytest.fixture +def sample_sky_map_dataset(): + """Create a sample sky map dataset for testing calculations.""" + # Create a simple rectangular map + n_lon, n_lat = 60, 30 + n_energy = 7 - # Act - h_rate = calculate_rates(counts, exposure_time) + dataset = xr.Dataset( + coords={ + "epoch": [8.1794907049e17], + "energy": list(range(n_energy)), + "longitude": np.linspace(0, 360, n_lon, endpoint=False), + "latitude": np.linspace(-90, 90, n_lat), + } + ) - # Assert - np.testing.assert_array_equal(h_rate, expected_rates) + # Current lo_l2.py uses generic variable names, not species-specific + counts = np.ones((1, n_energy, n_lon, n_lat)) * 10 # 10 counts for easy math + dataset["counts"] = (("epoch", "energy", "longitude", "latitude"), counts) + # Add efficiency-corrected quantities for intensity calculations + eff_corr = counts / 0.9 # Assuming 90% efficiency + dataset["counts_over_eff"] = ( + ("epoch", "energy", "longitude", "latitude"), + eff_corr, + ) + dataset["counts_over_eff_squared"] = ( + ("epoch", "energy", "longitude", "latitude"), + eff_corr, + ) -@pytest.mark.external_kernel -@pytest.mark.use_test_metakernel("imap_ena_sim_metakernel.template") -def test_calculate_fluxes(): - # Arrange - rates = np.zeros((1, 7, 1800)) - rates[0, 0, 0] = 2 - rates[0, 1, 0] = 12 + # Add exposure time using the current naming convention + exposure = np.ones((1, n_energy, n_lon, n_lat)) * 1.0 # 1 second + dataset["exposure_factor"] = ( + ("epoch", "energy", "longitude", "latitude"), + exposure, + ) - expected_fluxes = np.zeros((1, 7, 1800)) - expected_fluxes[0, 0, 0] = 2 - expected_fluxes[0, 1, 0] = 6 + return dataset - # Act - flux = calculate_fluxes(rates) - # Assert - np.testing.assert_array_equal(flux, expected_fluxes) +@pytest.fixture +def sample_dataset_with_geometric_factors(): + """Create a dataset with geometric factors for testing calculations.""" + dataset = xr.Dataset( + coords={ + "epoch": [8.1794907049e17], + "energy": list(range(7)), + } + ) + # Add current generic variable names used by lo_l2.py + dataset["counts_over_eff"] = (("epoch", "energy"), np.ones((1, 7)) * 100) + dataset["counts_over_eff_squared"] = (("epoch", "energy"), np.ones((1, 7)) * 100) + dataset["exposure_factor"] = (("epoch", "energy"), np.ones((1, 7)) * 1.0) + dataset["geometric_factor"] = (("energy",), np.ones(7) * 1e-4) + dataset["energy"] = (("energy",), np.ones(7) * 0.1) # Energy values + dataset["geometric_factor_stat_uncert"] = (("energy",), np.ones(7) * 1e-5) -@pytest.mark.external_kernel -def test_lo_l2(pset, imap_ena_sim_metakernel): - # Arrange - pset = {"imap_lo_l1c_pset": [pset]} - descriptor = "l090-ena-h-sf-nsp-ram-hae-6deg-3mo" - - # Act - hflux_map = lo_l2(pset, [], descriptor) - - # Assert - assert len(hflux_map) == 1 - assert ( - hflux_map[0].attrs["Logical_source"] - == "imap_lo_l2_l090-ena-h-sf-nsp-ram-hae-6deg-3mo" - ) - - data_vars = ["h_counts", "exposure_time", "h_rate", "h_flux", "solid_angle"] - for var in data_vars: - assert var in hflux_map[0].data_vars, f"Variable {var} not found in dataset" - assert hflux_map[0].data_vars["h_rate"].shape == (1, 7, 60, 30) - - -def test_add_attributes(map, attr_mgr): - # Arrange - logical_source = "imap_lo_l2_l090-ena-h-sf-nsp-ram-hae-6deg-3mo" - - map_fields = { - "epoch": "epoch", - "h_flux": "ena_intensity", - "h_rate": "ena_rate", - "h_counts": "ena_count", - "exposure_time": "exposure_factor", - "energy": "energy", - "solid_angle": "solid_angle", - "longitude": "longitude", - "latitude": "latitude", + return dataset + + +@pytest.fixture +def sample_dataset_with_background_intermediates(): + """Create a dataset with background intermediate variables for testing.""" + # Create a simple rectangular map with background data + n_energy = 7 + + dataset = xr.Dataset( + coords={ + "epoch": [8.1794907049e17], + "energy": list(range(n_energy)), + } + ) + + # Add the intermediate background variables using current naming convention + bg_rate_exposure_factor = np.ones((1, n_energy)) * 0.2 # 0.2 counts + dataset["bg_rate_exposure_factor"] = (("epoch", "energy"), bg_rate_exposure_factor) + + # Background uncertainty squared times exposure time squared + bg_rate_stat_uncert_exposure_factor2 = np.ones((1, n_energy)) * 0.004 # 0.02^2 + dataset["bg_rate_stat_uncert_exposure_factor2"] = ( + ("epoch", "energy"), + bg_rate_stat_uncert_exposure_factor2, + ) + + # Add exposure time (using current naming convention) + exposure = np.ones((1, n_energy)) * 1.0 # 1 second + dataset["exposure_factor"] = (("epoch", "energy"), exposure) + + # Add geometric factors for systematic uncertainty calculation + dataset["geometric_factor"] = (("energy",), np.ones(n_energy) * 1e-4) + dataset["geometric_factor_stat_uncert"] = (("energy",), np.ones(n_energy) * 1e-5) + + return dataset + + +@pytest.fixture +def sample_dataset_with_sputtering_data(): + """Create datasets with ENA intensities for sputtering correction testing.""" + # Create a simple map dataset with the required variables for sputtering correction + n_energy = 7 + n_lon, n_lat = 10, 5 # Smaller for testing + + coords = { + "epoch": [8.1794907049e17], + "energy": list(range(n_energy)), + "longitude": np.linspace(0, 360, n_lon, endpoint=False), + "latitude": np.linspace(-90, 90, n_lat), + } + + # Create hydrogen dataset + h_intensity_values = np.ones((1, n_energy, n_lon, n_lat)) * 1e6 # Base intensity + h_intensity_values[0, 4, :, :] *= 3 # Higher at energy level 4 (ESA level 5) + h_intensity_values[0, 5, :, :] *= 2 # Higher at energy level 5 (ESA level 6) + + h_dataset = xr.Dataset(coords=coords) + h_dataset["ena_intensity"] = ( + ("epoch", "energy", "longitude", "latitude"), + h_intensity_values, + ) + h_dataset["bg_intensity"] = h_dataset["ena_intensity"] * 0.1 # 10% background + + # Add statistical uncertainties + h_dataset["ena_intensity_stat_uncert"] = ( + ("epoch", "energy", "longitude", "latitude"), + np.sqrt(h_intensity_values) * 0.1, + ) + h_dataset["bg_intensity_stat_uncert"] = np.sqrt(h_dataset["bg_intensity"]) * 0.1 + + # Add systematic error + h_dataset["ena_intensity_sys_err"] = ( + ("epoch", "energy", "longitude", "latitude"), + h_intensity_values * 0.05, + ) + h_dataset["bg_intensity_sys_err"] = h_dataset["bg_intensity"] * 0.05 + + # Create oxygen dataset + o_intensity_values = np.ones((1, n_energy, n_lon, n_lat)) * 1e6 # Base intensity + o_intensity_values[0, 4, :, :] *= 5 # Higher at energy level 4 (ESA level 5) + o_intensity_values[0, 5, :, :] *= 3 # Higher at energy level 5 (ESA level 6) + + o_dataset = xr.Dataset(coords=coords) + o_dataset["ena_intensity"] = ( + ("epoch", "energy", "longitude", "latitude"), + o_intensity_values, + ) + o_dataset["bg_intensity"] = o_dataset["ena_intensity"] * 0.1 # 10% background + o_dataset["bg_intensity_stat_uncert"] = np.sqrt(o_dataset["bg_intensity"]) * 0.1 + + # Add statistical uncertainties + o_dataset["ena_intensity_stat_uncert"] = ( + ("epoch", "energy", "longitude", "latitude"), + np.sqrt(o_intensity_values) * 0.1, + ) + o_dataset["bg_intensity_stat_uncert"] = ( + np.sqrt(o_dataset["bg_intensity_stat_uncert"]) * 0.1 + ) + + # Add systematic error + o_dataset["ena_intensity_sys_err"] = ( + ("epoch", "energy", "longitude", "latitude"), + o_intensity_values * 0.05, + ) + o_dataset["bg_intensity_sys_err"] = o_dataset["bg_intensity"] * 0.05 + + # Add geometric factors for intensity calculations + o_dataset["geometric_factor"] = (("energy",), np.ones(n_energy)) + + return h_dataset, o_dataset + + +@pytest.fixture +def sample_dataset_with_bootstrap_data(): + """Create a dataset with ENA intensities for bootstrap correction testing.""" + # Create a simple map dataset with the required variables for bootstrap correction + n_energy = 7 + n_lon, n_lat = 10, 5 # Smaller for testing + + coords = { + "epoch": [8.1794907049e17], + "energy": list(range(n_energy)), + "longitude": np.linspace(0, 360, n_lon, endpoint=False), + "latitude": np.linspace(-90, 90, n_lat), + } + + # Create realistic energy values for hydrogen + energy_values = np.array([0.5, 1.0, 2.0, 4.0, 8.0, 16.0, 32.0]) # keV + + # Create intensity values that follow a power law distribution + # Higher intensities at lower energies + base_intensity = 1e6 # particles/(cm^2 sr s keV) + intensity_values = np.ones((1, n_energy, n_lon, n_lat)) + for i in range(n_energy): + # Power law: I = I0 * (E/E0)^(-2.5) + intensity_values[0, i, :, :] = base_intensity * (energy_values[i] / 1.0) ** ( + -2.5 + ) + + dataset = xr.Dataset(coords=coords) + dataset["ena_intensity"] = ( + ("epoch", "energy", "longitude", "latitude"), + intensity_values, + ) + dataset["energy"] = (("energy",), energy_values) + dataset["geometric_factor"] = (("energy",), np.ones(n_energy)) + + # Add background rates (much lower values) + dataset["bg_intensity"] = ( + dataset["ena_intensity"] + * 0.1 + / (dataset["geometric_factor"] * dataset["energy"]) + ) + + # Add statistical uncertainties (Poisson-like) + dataset["ena_intensity_stat_uncert"] = ( + ("epoch", "energy", "longitude", "latitude"), + np.sqrt(intensity_values) * 0.1, + ) + + # Add systematic error (5% of intensity) + dataset["ena_intensity_sys_err"] = ( + ("epoch", "energy", "longitude", "latitude"), + intensity_values * 0.05, + ) + + return dataset + + +@pytest.fixture +def lo_flux_factors_file(): + """Path to the LO flux factors test file.""" + # Use the actual test data file from the ena_maps test data + test_data_path = Path(__file__).parent.parent / "ena_maps" / "data" + return test_data_path / "imap_lo_esa-eta-fit-factors_20240101_v001.csv" + + +@pytest.fixture +def sample_dataset_with_intensities(): + """Create a dataset with intensities for flux correction testing.""" + n_energy = 7 + n_lon, n_lat = 6, 4 # Small for testing + + # Create realistic energy values matching the flux factors file + energy_values = np.array([16.35, 30.56, 56.4, 105, 199.8, 407.5, 795.3]) + + coords = { + "epoch": [8.1794907049e17], + "energy": energy_values, + "longitude": np.linspace(0, 360, n_lon, endpoint=False), + "latitude": np.linspace(-90, 90, n_lat), } - # Act - updated_map = add_attributes(map, attr_mgr, logical_source) + # Create intensity values with some spatial and energy structure + intensity_values = np.ones((1, n_energy, n_lon, n_lat)) + for i in range(n_energy): + # Power law: I = I0 * (E/E0)^(-2.0) + intensity_values[0, i, :, :] = 1e6 * (energy_values[i] / 100.0) ** (-2.0) + + # Add some spatial structure + for j in range(n_lon): + for k in range(n_lat): + intensity_values[0, :, j, k] *= 1.0 + 0.1 * np.sin(j) * np.cos(k) + + dataset = xr.Dataset(coords=coords) + dataset["ena_intensity"] = ( + ("epoch", "energy", "longitude", "latitude"), + intensity_values, + ) + + # Add statistical uncertainties (10% of intensity) + dataset["ena_intensity_stat_uncert"] = ( + ("epoch", "energy", "longitude", "latitude"), + intensity_values * 0.1, + ) + + dataset["bg_intensity"] = dataset["ena_intensity"] * 0.5 # 50% background + + # Add statistical uncertainties (10% of intensity) + dataset["bg_intensity_stat_uncert"] = dataset["bg_intensity"] * 0.1 + + return dataset + + +# ============================================================================= +# UNIT TESTS FOR INDIVIDUAL FUNCTIONS +# ============================================================================= + + +class TestLoadEfficiencyData: + """Tests for the load_efficiency_data function.""" + + def test_load_efficiency_data_with_files(self, tmp_path): + """Test loading efficiency data when files are present.""" + # Create temporary efficiency files + eff_file1 = tmp_path / "efficiency-factor_v001.csv" + eff_file2 = tmp_path / "efficiency-factor_v002.csv" + + # Create sample data + data1 = pd.DataFrame( + { + "Date": [np.datetime64("2025-01-01")], + "E-Step1_eff": [0.8], + "E-Step2_eff": [0.82], + "E-Step3_eff": [0.84], + "E-Step4_eff": [0.86], + "E-Step5_eff": [0.88], + "E-Step6_eff": [0.90], + "E-Step7_eff": [0.92], + } + ) + + data2 = pd.DataFrame( + { + "Date": [np.datetime64("2025-01-02")], + "E-Step1_eff": [0.85], + "E-Step2_eff": [0.87], + "E-Step3_eff": [0.89], + "E-Step4_eff": [0.91], + "E-Step5_eff": [0.93], + "E-Step6_eff": [0.95], + "E-Step7_eff": [0.97], + } + ) + + # Save to CSV + data1.to_csv(eff_file1, index=False) + data2.to_csv(eff_file2, index=False) + + # Mock the ancillary file reader + with patch( + "imap_processing.lo.l2.lo_l2.lo_ancillary.read_ancillary_file" + ) as mock_read: + mock_read.side_effect = [data1, data2] + + # Test the function + result = load_efficiency_data([str(eff_file1), str(eff_file2)]) + + # Verify results + assert len(result) == 2 + assert "Date" in result.columns + assert "E-Step1_eff" in result.columns + assert mock_read.call_count == 2 + + def test_load_efficiency_data_no_files(self): + """Test loading efficiency data when no files are present.""" + result = load_efficiency_data([]) + + assert isinstance(result, pd.DataFrame) + assert result.empty + + def test_load_efficiency_data_non_efficiency_files(self): + """Test that non-efficiency files are ignored.""" + files = ["some_other_file.csv", "another_file.txt"] + result = load_efficiency_data(files) + + assert isinstance(result, pd.DataFrame) + assert result.empty + + +class TestReduceGeometricFactor: + """Tests for the reduce_geometric_factor_dataset function.""" + + @pytest.mark.parametrize("species", ["h", "o"]) + @pytest.mark.parametrize("esa_mode", [0, 1]) + def test_reduce_geometric_factor_dataset( + self, + species, + esa_mode, + ): + """Test functionality of reduce_geometric_factor_dataset with real gf data.""" + + result = reduce_geometric_factor_dataset(species, esa_mode) + + # Verify it returns an xarray Dataset + assert isinstance(result, xr.Dataset) + + # Verify it has 7 energy steps + assert len(result["Observed_E-Step"]) == 7 + + # Verify the index is 1-7 + expected_indices = list(range(1, 8)) + np.testing.assert_array_equal( + result["Observed_E-Step"].values, expected_indices + ) + + # Verify that incident_E-Step == Observed_E-Step + np.testing.assert_array_equal( + result["incident_E-Step"].values, result["Observed_E-Step"].values + ) + + @patch("imap_processing.lo.l2.lo_l2.load_geometric_factor_data") + def test_reduce_geometric_factor_dataset_hydrogen( + self, mock_load_gf, sample_geometric_factor_data + ): + """Test that hydrogen geometric factors are correctly loaded and processed.""" + h_gf_data, _ = sample_geometric_factor_data + mock_load_gf.return_value = h_gf_data + + result = reduce_geometric_factor_dataset("h", esa_mode=0) + + # Check that hydrogen-specific columns are present + assert "Cntr_E" in result.data_vars + assert "GF_Trpl_H" in result.data_vars + assert "GF_Trpl_H_unc" in result.data_vars + + # Verify energy values match expected for hydrogen + expected_energies = [0.01 * (i + 1) for i in range(7)] + np.testing.assert_array_almost_equal(result["Cntr_E"].values, expected_energies) + + @patch("imap_processing.lo.l2.lo_l2.load_geometric_factor_data") + def test_reduce_geometric_factor_dataset_oxygen( + self, mock_load_gf, sample_geometric_factor_data + ): + """Test that oxygen geometric factors are correctly loaded and processed.""" + _, o_gf_data = sample_geometric_factor_data + mock_load_gf.return_value = o_gf_data + + result = reduce_geometric_factor_dataset("o", esa_mode=0) + + # Check that oxygen-specific columns are present + assert "Cntr_E" in result.data_vars + assert "GF_Trpl_O" in result.data_vars + assert "GF_Trpl_O_unc" in result.data_vars + + # Verify energy values match expected for oxygen + expected_energies = [0.015 * (i + 1) for i in range(7)] + np.testing.assert_array_almost_equal(result["Cntr_E"].values, expected_energies) + + @patch("imap_processing.lo.l2.lo_l2.load_geometric_factor_data") + def test_reduce_geometric_factor_dataset_esa_mode_filtering( + self, mock_load_gf, sample_geometric_factor_data + ): + """Test that ESA mode filtering works correctly.""" + h_gf_data, _ = sample_geometric_factor_data + + # Create data with two ESA modes + h_gf_mode_0 = h_gf_data.copy() + h_gf_mode_1 = h_gf_data.copy() + + # Modify mode 1 data to have different GF values + for col in ["GF_Trpl_H", "GF_Dbl_all", "GF_Trpl_all"]: + h_gf_mode_1[col] = h_gf_mode_1[col] * 1.5 + h_gf_mode_1["esa_mode"] = 1 + + combined_data = pd.concat([h_gf_mode_0, h_gf_mode_1], ignore_index=True) + mock_load_gf.return_value = combined_data + + # Get data for mode 0 + result_mode_0 = reduce_geometric_factor_dataset("h", esa_mode=0) + + # Get data for mode 1 + result_mode_1 = reduce_geometric_factor_dataset("h", esa_mode=1) + + # Verify that mode 1 has different (larger) GF values + assert np.all( + result_mode_1["GF_Trpl_H"].values > result_mode_0["GF_Trpl_H"].values + ) + + # Verify the ratio is approximately 1.5 + ratio = result_mode_1["GF_Trpl_H"].values / result_mode_0["GF_Trpl_H"].values + np.testing.assert_array_almost_equal(ratio, np.ones(7) * 1.5) + + @patch("imap_processing.lo.l2.lo_l2.load_geometric_factor_data") + def test_reduce_geometric_factor_dataset_duplicate_removal( + self, mock_load_gf, sample_geometric_factor_data + ): + """Test that duplicate Observed_E-Step values are handled correctly.""" + h_gf_data, _ = sample_geometric_factor_data + + # Add duplicate rows with same Observed_E-Step but different incident_E-Step + duplicates = h_gf_data.copy() + duplicates["incident_E-Step"] = [ + i + 8 for i in range(7) + ] # Different incident steps + + combined_data = pd.concat([h_gf_data, duplicates], ignore_index=True) + mock_load_gf.return_value = combined_data + + result = reduce_geometric_factor_dataset("h", esa_mode=0) + + # Should still have exactly 7 energy steps (duplicates removed) + assert len(result["Observed_E-Step"]) == 7 + + # Verify no duplicate indices + assert len(np.unique(result["Observed_E-Step"].values)) == 7 + + @patch("imap_processing.lo.l2.lo_l2.load_geometric_factor_data") + def test_reduce_geometric_factor_dataset_invalid_species(self, mock_load_gf): + """Test that invalid species raises appropriate error.""" + # Mock should raise ValueError for invalid species + mock_load_gf.side_effect = ValueError( + "Geometric factors only available for 'h' and 'o', got 'invalid'" + ) + + with pytest.raises(ValueError, match="Geometric factors only available"): + reduce_geometric_factor_dataset("invalid", esa_mode=0) + + @patch("imap_processing.lo.l2.lo_l2.load_geometric_factor_data") + def test_reduce_geometric_factor_dataset_no_esa_mode_column( + self, mock_load_gf, sample_geometric_factor_data + ): + """Test handling when esa_mode column is missing from data.""" + h_gf_data, _ = sample_geometric_factor_data + + # Remove esa_mode column if it exists + if "esa_mode" in h_gf_data.columns: + h_gf_data = h_gf_data.drop(columns=["esa_mode"]) + + mock_load_gf.return_value = h_gf_data - # Assert - for field, attr_name in map_fields.items(): - assert updated_map[field].attrs == attr_mgr.get_variable_attributes( - attr_name, check_schema=False + # Should still work, just won't filter by esa_mode + result = reduce_geometric_factor_dataset("h", esa_mode=0) + + # Should return 7 energy steps + assert len(result["Observed_E-Step"]) == 7 + assert isinstance(result, xr.Dataset) + + +class TestNormalizePsetCoordinates: + """Tests for the normalize_pset_coordinates function.""" + + @pytest.mark.parametrize("species", ["h", "o"]) + def test_normalize_coordinates_basic(self, species): + """Test basic coordinate normalization for a specific species.""" + # Create a pset with the specified species + pset = xr.Dataset( + { + f"{species}_counts": (PSET_DIMS, np.ones(PSET_SHAPE)), + "exposure_time": (PSET_DIMS, np.ones(PSET_SHAPE)), + f"{species}_background_rates": (PSET_DIMS, np.ones(PSET_SHAPE) * 0.1), + f"{species}_background_rates_stat_uncert": ( + PSET_DIMS, + np.ones(PSET_SHAPE) * 0.01, + ), + }, + coords={ + "epoch": [8.1794907049e17], + "esa_energy_step": ESA_ENERGY_STEPS, + "spin_angle": SPIN_ANGLE_BIN_CENTERS, + "off_angle": OFF_ANGLE_BIN_CENTERS, + }, + ) + + result = normalize_pset_coordinates(pset, species) + + # Check that dimensions were renamed + assert "energy" in result.dims + assert "esa_energy_step" not in result.dims + + # Check that energy coordinate is present + assert "energy" in result.coords + expected_energies = ( + np.array([0.01633, 0.03047, 0.05576, 0.1063, 0.2, 0.405, 0.7873]) + if species == "h" + else np.array([0.016, 0.032, 0.065, 0.135, 0.279, 0.601, 1.206]) + ) + np.testing.assert_array_equal(result.coords["energy"], expected_energies) + + # Check that old coordinate variable was dropped + assert "esa_energy_step" not in result.variables + + # Check that variables were renamed + assert "counts" in result.data_vars + assert "exposure_factor" in result.data_vars + assert "bg_rate" in result.data_vars + assert "bg_rate_stat_uncert" in result.data_vars + + # Check that old variable names are gone + assert f"{species}_counts" not in result.data_vars + assert "exposure_time" not in result.data_vars + + @pytest.mark.parametrize("species", ["doubles", "triples"]) + def test_normalize_coordinates_no_background(self, species): + """Test normalization for species without background rates.""" + # Create a pset with only counts and exposure time + pset = xr.Dataset( + { + f"{species}_counts": (PSET_DIMS, np.ones(PSET_SHAPE)), + "exposure_time": (PSET_DIMS, np.ones(PSET_SHAPE)), + }, + coords={ + "epoch": [8.1794907049e17], + "esa_energy_step": ESA_ENERGY_STEPS, + "spin_angle": SPIN_ANGLE_BIN_CENTERS, + "off_angle": OFF_ANGLE_BIN_CENTERS, + }, + ) + + # For species without background rates, the function should fail + # because geometric factors can only be retrieved for "h" and "o" + with pytest.raises(ValueError, match="Geometric factors only available"): + normalize_pset_coordinates(pset, species) + + def test_normalize_coordinates_removes_old_coordinate(self): + """Test that old esa_energy_step coordinate is removed.""" + species = "h" + pset = xr.Dataset( + { + f"{species}_counts": (PSET_DIMS, np.ones(PSET_SHAPE)), + "exposure_time": (PSET_DIMS, np.ones(PSET_SHAPE)), + f"{species}_background_rates": (PSET_DIMS, np.ones(PSET_SHAPE) * 0.1), + f"{species}_background_rates_stat_uncert": ( + PSET_DIMS, + np.ones(PSET_SHAPE) * 0.01, + ), + "esa_energy_step_var": xr.DataArray([1, 2, 3, 4, 5, 6, 7]), # Variable + }, + coords={ + "epoch": [8.1794907049e17], + "esa_energy_step": ESA_ENERGY_STEPS, + "spin_angle": SPIN_ANGLE_BIN_CENTERS, + "off_angle": OFF_ANGLE_BIN_CENTERS, + }, ) + + result = normalize_pset_coordinates(pset, species) + + # Should remove the esa_energy_step coordinate and variable + assert "esa_energy_step" not in result.variables + assert "esa_energy_step_var" in result.variables # Data variable should remain + + +class TestAddEfficiencyFactorsToPset: + """Tests for the add_efficiency_factors_to_pset function.""" + + def test_add_efficiency_factors_with_data( + self, minimal_pset, sample_efficiency_data + ): + """Test adding efficiency factors when data is available.""" + # Set the epoch to match our sample data + pset = minimal_pset.copy() + # Convert date to TT2000 nanoseconds (approximate) + epoch_ns = 8.1794907049e17 # This should correspond to 2025-01-01 + pset = pset.assign_coords(epoch=[epoch_ns]) + + with ( + patch("imap_processing.lo.l2.lo_l2.ttj2000ns_to_et") as mock_ttj2000_to_et, + patch("imap_processing.lo.l2.lo_l2.et_to_datetime64") as mock_et_to_dt64, + ): + # Mock the time conversion + mock_ttj2000_to_et.return_value = 1234567890.0 + mock_et_to_dt64.return_value = np.datetime64("2025-01-01") + + result = add_efficiency_factors_to_pset(pset, sample_efficiency_data) + + # Check that efficiency was added + assert "efficiency" in result.data_vars + assert result["efficiency"].dims == ("energy",) + assert len(result["efficiency"]) == 7 + + # Check efficiency values match expected (first row of sample data) + expected_eff = [0.8, 0.82, 0.84, 0.86, 0.88, 0.90, 0.92] + np.testing.assert_array_almost_equal( + result["efficiency"].values, expected_eff + ) + + def test_add_efficiency_factors_no_data(self, minimal_pset): + """Test adding efficiency factors when no data is available.""" + empty_df = pd.DataFrame() + + result = add_efficiency_factors_to_pset(minimal_pset, empty_df) + + # Should create unity efficiency + assert "efficiency" in result.data_vars + np.testing.assert_array_equal(result["efficiency"].values, np.ones(7)) + + def test_add_efficiency_factors_missing_date( + self, minimal_pset, sample_efficiency_data + ): + """Test error when efficiency factor not found for date.""" + pset = minimal_pset.copy() + + with ( + patch("imap_processing.lo.l2.lo_l2.ttj2000ns_to_et") as mock_ttj2000_to_et, + patch("imap_processing.lo.l2.lo_l2.et_to_datetime64") as mock_et_to_dt64, + ): + # Mock conversion to a date not in sample data + mock_ttj2000_to_et.return_value = 1234567890.0 + mock_et_to_dt64.return_value = np.datetime64("2025-12-31") + + with pytest.raises(ValueError, match="No efficiency factor found"): + add_efficiency_factors_to_pset(pset, sample_efficiency_data) + + +class TestCalculateEfficiencyCorrectedQuantities: + """Tests for the calculate_efficiency_corrected_quantities function.""" + + def test_calculate_efficiency_corrected_quantities(self): + """Test calculation of efficiency-corrected quantities.""" + # Create a dataset with the current generic variable names + pset = xr.Dataset( + { + "counts": (("energy",), np.ones(7) * 10), # 10 counts + "exposure_factor": (("energy",), np.ones(7) * 1.0), # 1 second + "bg_rate": (("energy",), np.ones(7) * 0.1), # 0.1 counts/s + "bg_rate_stat_uncert": (("energy",), np.ones(7) * 0.01), # uncertainty + "efficiency": ( + ("energy",), + np.array([0.8, 0.85, 0.9, 0.95, 0.88, 0.92, 0.87]), + ), + }, + coords={"energy": list(range(7))}, + ) + + result = calculate_efficiency_corrected_quantities(pset) + + # Check that corrected quantities were added + assert "counts_over_eff" in result.data_vars + assert "counts_over_eff_squared" in result.data_vars + assert "bg_rate_exposure_factor" in result.data_vars + assert "bg_rate_stat_uncert_exposure_factor2" in result.data_vars + + # Check dimensions + assert result["counts_over_eff"].dims == pset["counts"].dims + + # Check that division by efficiency happened correctly + expected_over_eff = pset["counts"] / pset["efficiency"] + xr.testing.assert_allclose(result["counts_over_eff"], expected_over_eff) + + # Check that division by efficiency squared happened correctly + expected_over_eff_sq = pset["counts"] / (pset["efficiency"] ** 2) + xr.testing.assert_allclose( + result["counts_over_eff_squared"], expected_over_eff_sq + ) + + # Check background rate calculations + expected_bg_exposure = pset["bg_rate"] * pset["exposure_factor"] + xr.testing.assert_allclose( + result["bg_rate_exposure_factor"], expected_bg_exposure + ) + + expected_bg_uncert_exposure = ( + pset["bg_rate_stat_uncert"] ** 2 * pset["exposure_factor"] ** 2 + ) + xr.testing.assert_allclose( + result["bg_rate_stat_uncert_exposure_factor2"], expected_bg_uncert_exposure + ) + + +class TestCalculateRates: + """Tests for the calculate_rates function.""" + + def test_calculate_rates_basic(self, sample_sky_map_dataset): + """Test rate calculation with current implementation.""" + result = calculate_rates(sample_sky_map_dataset) + + # Check that the expected output variables were created + assert "ena_count_rate" in result.data_vars + assert "ena_count_rate_stat_uncert" in result.data_vars + + # Check dimensions match input + assert result["ena_count_rate"].dims == sample_sky_map_dataset["counts"].dims + + # Check rate calculation (counts / exposure_factor) + # With counts=10 and exposure_factor=1, rate should be 10 + expected_rate = ( + sample_sky_map_dataset["counts"] / sample_sky_map_dataset["exposure_factor"] + ) + xr.testing.assert_allclose(result["ena_count_rate"], expected_rate) + + # Check uncertainty calculation (sqrt(counts) / exposure_factor) + expected_uncert = ( + np.sqrt(sample_sky_map_dataset["counts"]) + / sample_sky_map_dataset["exposure_factor"] + ) + xr.testing.assert_allclose( + result["ena_count_rate_stat_uncert"], expected_uncert + ) + + def test_calculate_rates_missing_variables(self): + """Rate calculation when required variables are missing.""" + # Create dataset missing required variables + dataset = xr.Dataset( + { + "counts": (("epoch", "energy"), np.ones((1, 7)) * 5), + # Missing exposure_factor + } + ) + + # Should raise KeyError for missing exposure_factor + with pytest.raises(KeyError, match="exposure_factor"): + calculate_rates(dataset) + + +class TestCalculateIntensities: + """Tests for the calculate_intensities function.""" + + def test_calculate_intensities_basic(self, sample_dataset_with_geometric_factors): + """Test intensity calculation with current implementation.""" + result = calculate_intensities(sample_dataset_with_geometric_factors) + + # Check that the expected output variables were created + assert "ena_intensity" in result.data_vars + assert "ena_intensity_stat_uncert" in result.data_vars + assert "ena_intensity_sys_err" in result.data_vars + + # Check intensity calculation: + # counts_over_eff / (geometric_factor * energy * exposure_factor) + # 100 / (1e-4 * 0.1 * 1.0) = 100 / 1e-5 = 1e7 + expected_intensity = sample_dataset_with_geometric_factors[ + "counts_over_eff" + ] / ( + sample_dataset_with_geometric_factors["geometric_factor"] + * sample_dataset_with_geometric_factors["energy"] + * sample_dataset_with_geometric_factors["exposure_factor"] + ) + xr.testing.assert_allclose(result["ena_intensity"], expected_intensity) + + # Check statistical uncertainty calculation + expected_stat_uncert = np.sqrt( + sample_dataset_with_geometric_factors["counts_over_eff_squared"] + ) / ( + sample_dataset_with_geometric_factors["geometric_factor"] + * sample_dataset_with_geometric_factors["energy"] + * sample_dataset_with_geometric_factors["exposure_factor"] + ) + xr.testing.assert_allclose( + result["ena_intensity_stat_uncert"], expected_stat_uncert + ) + + # Check systematic uncertainty calculation + expected_sys_err = ( + result["ena_intensity"] + * sample_dataset_with_geometric_factors["geometric_factor_stat_uncert"] + / sample_dataset_with_geometric_factors["geometric_factor"] + ) + xr.testing.assert_allclose(result["ena_intensity_sys_err"], expected_sys_err) + + def test_calculate_intensities_missing_variables(self): + """Test intensity calculation when required variables are missing.""" + # Create dataset missing geometric_factor + dataset = xr.Dataset( + { + "counts_over_eff": (("energy",), np.ones(7) * 100), + "counts_over_eff_squared": (("energy",), np.ones(7) * 100), + "exposure_factor": (("energy",), np.ones(7) * 1.0), + "energy": (("energy",), np.ones(7) * 0.1), + # Missing geometric_factor + } + ) + + # Should raise KeyError for missing geometric_factor + with pytest.raises(KeyError, match="geometric_factor"): + calculate_intensities(dataset) + + +class TestCalculateBackgrounds: + """Tests for the calculate_backgrounds function.""" + + def test_calculate_backgrounds_basic( + self, sample_dataset_with_background_intermediates + ): + """Test basic background calculations with standard data.""" + dataset = sample_dataset_with_background_intermediates + + result = calculate_backgrounds(dataset) + + # Check that background variables were calculated + assert "bg_rate" in result.data_vars + assert "bg_rate_stat_uncert" in result.data_vars + assert "bg_rate_sys_err" in result.data_vars + + # Check background rate calculation + # bg_rate_exposure_factor / exposure_factor = 0.2 / 1.0 = 0.2 + expected_bg_rate = ( + dataset["bg_rate_exposure_factor"] / dataset["exposure_factor"] + ) + xr.testing.assert_allclose(result["bg_rate"], expected_bg_rate) + + # Check statistical uncertainty calculation + # sqrt(bg_rate_stat_uncert_exposure_factor2) / exposure_factor^2 + expected_stat_uncert = np.sqrt( + dataset["bg_rate_stat_uncert_exposure_factor2"] + / dataset["exposure_factor"] ** 2 + ) + xr.testing.assert_allclose(result["bg_rate_stat_uncert"], expected_stat_uncert) + + # Check systematic uncertainty calculation + # (geometric_factor_stat_uncert / geometric_factor) * bg_rate + expected_sys_err = ( + result["bg_rate"] + * dataset["geometric_factor_stat_uncert"] + / dataset["geometric_factor"] + ) + xr.testing.assert_allclose(result["bg_rate_sys_err"], expected_sys_err) + + def test_calculate_backgrounds_zero_exposure(self): + """Test background calculations with zero exposure time.""" + dataset = xr.Dataset( + { + "bg_rate_exposure_factor": ( + ("epoch", "energy"), + np.ones((1, 7)) * 0.2, + ), + "bg_rate_stat_uncert_exposure_factor2": ( + ("epoch", "energy"), + np.ones((1, 7)) * 0.004, + ), + "exposure_factor": (("epoch", "energy"), np.zeros((1, 7))), + "geometric_factor": (("energy",), np.ones(7) * 1e-4), + "geometric_factor_stat_uncert": (("energy",), np.ones(7) * 1e-5), + }, + coords={"epoch": [8.1794907049e17], "energy": list(range(7))}, + ) + + result = calculate_backgrounds(dataset) + + # Should handle division by zero gracefully + assert "bg_rate" in result.data_vars + assert "bg_rate_stat_uncert" in result.data_vars + assert "bg_rate_sys_err" in result.data_vars + # Results should be infinite where exposure time is zero + assert np.all(np.isinf(result["bg_rate"].values)) + assert np.all(np.isinf(result["bg_rate_stat_uncert"].values)) + + +class TestCalculateFluxCorrections: + """Tests for the calculate_flux_corrections function.""" + + def test_calculate_flux_corrections_basic( + self, sample_dataset_with_intensities, lo_flux_factors_file + ): + """Test basic flux correction calculation.""" + # Make a copy to avoid modifying the original fixture + original_dataset = sample_dataset_with_intensities.copy(deep=True) + + # Run flux correction + result = calculate_flux_corrections(original_dataset, lo_flux_factors_file) + + # Verify that the function returns a dataset + assert isinstance(result, xr.Dataset) + + # Verify that intensity variables are present + assert "ena_intensity" in result.data_vars + assert "ena_intensity_stat_uncert" in result.data_vars + + # Verify that data shape is preserved + original_shape = sample_dataset_with_intensities["ena_intensity"].shape + assert result["ena_intensity"].shape == original_shape + + # Check that corrections were applied by comparing to the original fixture + # (not the potentially modified copy) + original_intensity = sample_dataset_with_intensities["ena_intensity"].values + corrected_intensity = result["ena_intensity"].values + + # Check for meaningful differences + relative_diff = np.abs( + (corrected_intensity - original_intensity) / original_intensity + ) + max_relative_diff = np.max(relative_diff) + # Should have at least 10% change somewhere + assert max_relative_diff > 0.1, ( + f"Max relative difference was only {max_relative_diff}" + ) + + # Verify that uncertainties were also corrected + original_uncert = sample_dataset_with_intensities[ + "ena_intensity_stat_uncert" + ].values + corrected_uncert = result["ena_intensity_stat_uncert"].values + uncert_relative_diff = np.abs( + (corrected_uncert - original_uncert) / original_uncert + ) + max_uncert_diff = np.max(uncert_relative_diff) + # Should have at least 10% change in uncertainties too + assert max_uncert_diff > 0.1, ( + f"Max uncertainty relative difference was only {max_uncert_diff}" + ) + + def test_calculate_flux_corrections_preserves_other_vars( + self, sample_dataset_with_intensities, lo_flux_factors_file + ): + """Test that flux correction preserves other variables in the dataset.""" + # Add an extra variable to the dataset + sample_dataset_with_intensities["extra_var"] = (("energy",), np.ones(7)) + + result = calculate_flux_corrections( + sample_dataset_with_intensities, lo_flux_factors_file + ) + + # Verify that other variables are preserved + assert "extra_var" in result.data_vars + np.testing.assert_array_equal( + result["extra_var"].values, + sample_dataset_with_intensities["extra_var"].values, + ) + + def test_calculate_flux_corrections_energy_dimension_handling( + self, lo_flux_factors_file + ): + """Test that flux correction properly handles energy dimension reshaping.""" + # Create a dataset with different spatial dimensions + n_energy = 7 + n_x, n_y = 12, 8 # Different spatial dimensions + + energy_values = np.array([16.35, 30.56, 56.4, 105, 199.8, 407.5, 795.3]) + + coords = { + "epoch": [8.1794907049e17], + "energy": energy_values, + "x": np.arange(n_x), + "y": np.arange(n_y), + } + + # Create intensity values with energy-dependent structure (power law) + intensity_values = np.ones((1, n_energy, n_x, n_y)) + for i in range(n_energy): + intensity_values[0, i, :, :] = 1e6 * (energy_values[i] / 100.0) ** (-2.0) + uncert_values = intensity_values * 0.1 + + original_dataset = xr.Dataset(coords=coords) + original_dataset["ena_intensity"] = ( + ("epoch", "energy", "x", "y"), + intensity_values.copy(), + ) + original_dataset["ena_intensity_stat_uncert"] = ( + ("epoch", "energy", "x", "y"), + uncert_values.copy(), + ) + original_dataset["bg_intensity"] = original_dataset["ena_intensity"] * 0.5 + original_dataset["bg_intensity_stat_uncert"] = ( + original_dataset["bg_intensity"] * 0.1 + ) + + # Run flux correction on a copy + dataset_copy = original_dataset.copy(deep=True) + result = calculate_flux_corrections(dataset_copy, lo_flux_factors_file) + + # Verify shape is preserved + assert result["ena_intensity"].shape == (1, n_energy, n_x, n_y) + assert result["ena_intensity_stat_uncert"].shape == (1, n_energy, n_x, n_y) + + # Verify corrections were applied by checking for meaningful differences + original_values = original_dataset["ena_intensity"].values + corrected_values = result["ena_intensity"].values + relative_diff = np.abs((corrected_values - original_values) / original_values) + max_relative_diff = np.max(relative_diff) + # Should have at least 10% change somewhere (flux corrections are significant) + assert max_relative_diff > 0.1, ( + f"Max relative difference was only {max_relative_diff}" + ) + + +class TestCalculateSputteringCorrections: + """Tests for the calculate_sputtering_corrections function.""" + + def test_calculate_sputtering_corrections_basic( + self, sample_dataset_with_sputtering_data + ): + """Test basic sputtering corrections for hydrogen and oxygen intensities.""" + h_dataset, o_dataset = sample_dataset_with_sputtering_data + + # Test with hydrogen dataset first + original_h_intensity = h_dataset["ena_intensity"].copy() + original_h_stat_uncert = h_dataset["ena_intensity_stat_uncert"].copy() + original_h_sys_err = h_dataset["ena_intensity_sys_err"].copy() + + result_h = calculate_sputtering_corrections(h_dataset, o_dataset) + + # Check that only energy levels 4 and 5 (ESA levels 5 and 6) were modified + # for hydrogen + for energy_idx in [0, 1, 2, 3, 6]: + np.testing.assert_array_equal( + result_h["ena_intensity"][0, energy_idx, :, :].values, + original_h_intensity[0, energy_idx, :, :].values, + err_msg=f"Hydrogen energy level {energy_idx} should not be modified", + ) + + # Check that energy levels 4 and 5 were modified (should be lower) + assert np.all( + result_h["ena_intensity"][0, 4, :, :].values + < original_h_intensity[0, 4, :, :].values + ), ( + "Hydrogen energy level 4 intensity should be reduced by sputtering " + "correction" + ) + + assert np.all( + result_h["ena_intensity"][0, 5, :, :].values + < original_h_intensity[0, 5, :, :].values + ), ( + "Hydrogen energy level 5 intensity should be reduced by sputtering " + "correction" + ) + + # Check that uncertainties were also updated for levels 4 and 5 + assert not np.array_equal( + result_h["ena_intensity_stat_uncert"][0, 4, :, :].values, + original_h_stat_uncert[0, 4, :, :].values, + ), "Statistical uncertainty should be updated for hydrogen energy level 4" + + assert not np.array_equal( + result_h["ena_intensity_sys_err"][0, 4, :, :].values, + original_h_sys_err[0, 4, :, :].values, + ), "Systematic error should be updated for hydrogen energy level 4" + + # Test with oxygen dataset + original_o_intensity = o_dataset["ena_intensity"].copy() + + result_o = calculate_sputtering_corrections(o_dataset, o_dataset) + + # Check that only energy levels 4 and 5 were modified for oxygen + for energy_idx in [0, 1, 2, 3, 6]: + np.testing.assert_array_equal( + result_o["ena_intensity"][0, energy_idx, :, :].values, + original_o_intensity[0, energy_idx, :, :].values, + err_msg=f"Oxygen energy level {energy_idx} should not be modified", + ) + + # Check that energy levels 4 and 5 were modified + assert np.all( + result_o["ena_intensity"][0, 4, :, :].values + < original_o_intensity[0, 4, :, :].values + ), "Oxygen energy level 4 intensity should be reduced by sputtering correction" + + assert np.all( + result_o["ena_intensity"][0, 5, :, :].values + < original_o_intensity[0, 5, :, :].values + ), "Oxygen energy level 5 intensity should be reduced by sputtering correction" + + def test_calculate_sputtering_corrections_equations( + self, sample_dataset_with_sputtering_data + ): + """Test that sputtering corrections follow the correct equations.""" + h_dataset, o_dataset = sample_dataset_with_sputtering_data + + # Get the subset that will be processed (energy levels 4 and 5) + o_small_dataset = o_dataset.isel(epoch=0, energy=[4, 5]) + + # Calculate expected j_o_prime (Equation 9) + expected_j_o_prime = ( + o_small_dataset["ena_intensity"] - o_small_dataset["bg_intensity"] + ) + expected_j_o_prime = expected_j_o_prime.where(expected_j_o_prime >= 0, 0) + + # Expected correction factors from the mapping document table 2 + sputter_correction_factor = np.array([0.15, 0.01]) + + # Calculate expected corrected intensity (Equation 11) for hydrogen + h_small_dataset = h_dataset.isel(epoch=0, energy=[4, 5]) + expected_corrected_intensity = ( + h_small_dataset["ena_intensity"] + - sputter_correction_factor[:, np.newaxis, np.newaxis] * expected_j_o_prime + ) + + # Run the function + result = calculate_sputtering_corrections(h_dataset, o_dataset) + + # Check that the corrected intensities match expected values + np.testing.assert_allclose( + result["ena_intensity"][0, [4, 5], :, :].values, + expected_corrected_intensity.values, + rtol=1e-10, + err_msg="Sputtering-corrected intensities don't match expected calculation", + ) + + def test_calculate_sputtering_corrections_negative_j_o_prime(self): + """Test handling when j_o_prime becomes negative.""" + # Create dataset where background > intensity (would give negative j_o_prime) + coords = { + "epoch": [8.1794907049e17], + "energy": list(range(7)), + "longitude": np.linspace(0, 360, 5, endpoint=False), + "latitude": np.linspace(-90, 90, 3), + } + + # Create hydrogen dataset + h_dataset = xr.Dataset(coords=coords) + h_dataset["ena_intensity"] = ( + ("epoch", "energy", "longitude", "latitude"), + np.ones((1, 7, 5, 3)) * 1e6, + ) + + # Add required uncertainty variables for hydrogen + h_dataset["ena_intensity_stat_uncert"] = ( + ("epoch", "energy", "longitude", "latitude"), + np.ones((1, 7, 5, 3)) * 0.1e6, + ) + h_dataset["ena_intensity_sys_err"] = ( + ("epoch", "energy", "longitude", "latitude"), + np.ones((1, 7, 5, 3)) * 0.05e6, + ) + + # Create oxygen dataset where background > intensity + o_dataset = xr.Dataset(coords=coords) + o_dataset["ena_intensity"] = ( + ("epoch", "energy", "longitude", "latitude"), + np.ones((1, 7, 5, 3)) * 1e6, + ) + o_dataset["bg_intensity"] = ( + ("epoch", "energy", "longitude", "latitude"), + np.ones((1, 7, 5, 3)) * 2e6, # Higher than signal + ) + + # Add required uncertainty variables for oxygen + o_dataset["ena_intensity_stat_uncert"] = ( + ("epoch", "energy", "longitude", "latitude"), + np.ones((1, 7, 5, 3)) * 0.1e6, + ) + o_dataset["bg_intensity_stat_uncert"] = ( + ("epoch", "energy", "longitude", "latitude"), + np.ones((1, 7, 5, 3)) * 0.1e6, + ) + o_dataset["ena_intensity_sys_err"] = ( + ("epoch", "energy", "longitude", "latitude"), + np.ones((1, 7, 5, 3)) * 0.05e6, + ) + o_dataset["geometric_factor"] = (("energy",), np.ones(7)) + + result = calculate_sputtering_corrections(h_dataset, o_dataset) + + # Function should handle negative j_o_prime by setting it to zero + # This means no sputtering correction should be applied + # The corrected intensity should equal the original intensity + np.testing.assert_allclose( + result["ena_intensity"][0, [4, 5], :, :].values, + h_dataset["ena_intensity"][0, [4, 5], :, :].values, + rtol=1e-10, + err_msg=( + "When background > signal, no sputtering correction should be applied" + ), + ) + + def test_calculate_sputtering_corrections_only_oxygen( + self, sample_dataset_with_sputtering_data + ): + """Test that sputtering corrections work for different species datasets.""" + h_dataset, o_dataset = sample_dataset_with_sputtering_data + + # Store original hydrogen values + original_h_intensity = h_dataset["ena_intensity"].copy() + original_h_stat_uncert = h_dataset["ena_intensity_stat_uncert"].copy() + original_h_sys_err = h_dataset["ena_intensity_sys_err"].copy() + + # Store original oxygen values + original_o_intensity = o_dataset["ena_intensity"].copy() + + # Test hydrogen dataset with oxygen reference + result_h = calculate_sputtering_corrections(h_dataset, o_dataset) + + # Check that hydrogen values changed for energy levels 4 and 5 + assert not np.array_equal( + result_h["ena_intensity"][0, 4, :, :].values, + original_h_intensity[0, 4, :, :].values, + ), "Hydrogen intensity should be affected by sputtering corrections" + + assert not np.array_equal( + result_h["ena_intensity_stat_uncert"][0, 4, :, :].values, + original_h_stat_uncert[0, 4, :, :].values, + ), "Hydrogen stat uncertainty should be updated" + + assert not np.array_equal( + result_h["ena_intensity_sys_err"][0, 4, :, :].values, + original_h_sys_err[0, 4, :, :].values, + ), "Hydrogen sys error should be updated" + + # Test oxygen dataset with itself as reference + result_o = calculate_sputtering_corrections(o_dataset, o_dataset) + + # Check that oxygen values also changed + assert not np.array_equal( + result_o["ena_intensity"][0, 4, :, :].values, + original_o_intensity[0, 4, :, :].values, + ), "Oxygen intensity should also be affected by sputtering corrections" + + def test_calculate_sputtering_corrections_uncertainty_propagation( + self, sample_dataset_with_sputtering_data + ): + """Test that uncertainties are properly propagated in sputtering corrections.""" + h_dataset, o_dataset = sample_dataset_with_sputtering_data + + # Get subset for manual calculation + o_small_dataset = o_dataset.isel(epoch=0, energy=[4, 5]) + h_small_dataset = h_dataset.isel(epoch=0, energy=[4, 5]) + + # Manual calculation following equations 10, 12 + j_o_prime = o_small_dataset["ena_intensity"] - o_small_dataset["bg_intensity"] + j_o_prime = j_o_prime.where(j_o_prime >= 0, 0) + + j_o_prime_var = ( + o_small_dataset["ena_intensity_stat_uncert"] ** 2 + + (o_small_dataset["bg_intensity_stat_uncert"]) ** 2 + ) + + sputter_correction_factor = np.array([0.15, 0.01])[:, np.newaxis, np.newaxis] + + expected_corrected_var = ( + h_small_dataset["ena_intensity_stat_uncert"] ** 2 + + (sputter_correction_factor**2) * j_o_prime_var + ) + + result = calculate_sputtering_corrections(h_dataset, o_dataset) + + # Check that statistical uncertainties match expected propagation + np.testing.assert_allclose( + result["ena_intensity_stat_uncert"][0, [4, 5], :, :].values ** 2, + expected_corrected_var.values, + rtol=1e-10, + err_msg="Statistical uncertainty propagation is incorrect", + ) + + def test_calculate_sputtering_corrections_energy_levels(self): + """Test that sputtering corrections are applied to correct energy levels.""" + # Create minimal dataset for testing specific energy level targeting + coords = { + "epoch": [8.1794907049e17], + "energy": list(range(7)), + "longitude": [0, 90, 180, 270], + "latitude": [-45, 0, 45], + } + + # Create hydrogen dataset + h_dataset = xr.Dataset(coords=coords) + h_intensity_data = np.zeros((1, 7, 4, 3)) + h_bg_rate_data = np.zeros((1, 7, 4, 3)) + + # Set specific values for energy levels 4 and 5 only + h_intensity_data[0, 4, :, :] = 200_000_000 # 200M for energy index 4 + h_intensity_data[0, 5, :, :] = 250_000_000 # 250M for energy index 5 + h_bg_rate_data[0, 4, :, :] = 20_000_000 # 20M background + h_bg_rate_data[0, 5, :, :] = 25_000_000 # 25M background + + h_dataset["ena_intensity"] = ( + ("epoch", "energy", "longitude", "latitude"), + h_intensity_data, + ) + h_dataset["bg_intensity"] = ( + ("epoch", "energy", "longitude", "latitude"), + h_bg_rate_data, + ) + h_dataset["ena_intensity_stat_uncert"] = ( + ("epoch", "energy", "longitude", "latitude"), + np.ones((1, 7, 4, 3)) * 100_000, + ) + h_dataset["bg_intensity_stat_uncert"] = ( + ("epoch", "energy", "longitude", "latitude"), + np.ones((1, 7, 4, 3)) * 10_000, + ) + h_dataset["ena_intensity_sys_err"] = ( + ("epoch", "energy", "longitude", "latitude"), + np.ones((1, 7, 4, 3)) * 50_000, + ) + + # Create oxygen dataset with higher values + o_dataset = xr.Dataset(coords=coords) + o_intensity_data = np.zeros((1, 7, 4, 3)) + o_bg_rate_data = np.zeros((1, 7, 4, 3)) + + # Set specific values for energy levels 4 and 5 only + o_intensity_data[0, 4, :, :] = 250_000_000 # 250M for energy index 4 + o_intensity_data[0, 5, :, :] = 300_000_000 # 300M for energy index 5 + o_bg_rate_data[0, 4, :, :] = 25_000_000 # 25M background + o_bg_rate_data[0, 5, :, :] = 30_000_000 # 30M background + + o_dataset["ena_intensity"] = ( + ("epoch", "energy", "longitude", "latitude"), + o_intensity_data, + ) + o_dataset["bg_intensity"] = ( + ("epoch", "energy", "longitude", "latitude"), + o_bg_rate_data, + ) + o_dataset["ena_intensity_stat_uncert"] = ( + ("epoch", "energy", "longitude", "latitude"), + np.ones((1, 7, 4, 3)) * 100_000, + ) + o_dataset["bg_intensity_stat_uncert"] = ( + ("epoch", "energy", "longitude", "latitude"), + np.ones((1, 7, 4, 3)) * 10_000, + ) + o_dataset["ena_intensity_sys_err"] = ( + ("epoch", "energy", "longitude", "latitude"), + np.ones((1, 7, 4, 3)) * 50_000, + ) + o_dataset["geometric_factor"] = (("energy",), np.ones(7)) + + # Make a copy to preserve original values for comparison + original_h_dataset = h_dataset.copy(deep=True) + result = calculate_sputtering_corrections(h_dataset, o_dataset) + + # Only energy indices 4 and 5 should be modified + modified_indices = [4, 5] + unchanged_indices = [0, 1, 2, 3, 6] + + for idx in unchanged_indices: + np.testing.assert_array_equal( + result["ena_intensity"][0, idx, :, :].values, + original_h_dataset["ena_intensity"][0, idx, :, :].values, + err_msg=f"Energy index {idx} should not be modified", + ) + + for idx in modified_indices: + # Check that values changed with some tolerance for numerical precision + original_values = original_h_dataset["ena_intensity"][0, idx, :, :].values + corrected_values = result["ena_intensity"][0, idx, :, :].values + + assert not np.allclose(corrected_values, original_values, rtol=1e-10), ( + f"Energy index {idx} should be modified" + ) + + def test_calculate_sputtering_corrections_no_csv_files( + self, sample_dataset_with_sputtering_data, caplog + ): + """Test that missing sputter CSV files raise a ValueError.""" + h_dataset, o_dataset = sample_dataset_with_sputtering_data + + with patch("imap_processing.lo.l2.lo_l2.Path.glob", return_value=iter([])): + with pytest.raises(ValueError, match="No sputter correction files found"): + calculate_sputtering_corrections(h_dataset, o_dataset) + + +class TestInitializeGeometricFactorVariables: + """Tests for the initialize_geometric_factor_variables function.""" + + def test_initialize_geometric_factor_variables(self): + """Test initialization of geometric factor variables.""" + # Create a simple dataset + dataset = xr.Dataset( + { + "test_var": (("energy",), np.ones(7)), + }, + coords={"energy": range(7)}, + ) + + result = initialize_geometric_factor_variables(dataset) + + # Check that all geometric factor variables were initialized + expected_vars = [ + "energy_delta_minus", + "energy_delta_plus", + "geometric_factor", + "geometric_factor_stat_uncert", + ] + + for var in expected_vars: + assert var in result.data_vars + assert result[var].dims == ("energy",) + assert result[var].shape == (7,) + assert np.all(result[var].values == 0) # Should be initialized to zeros + + # The energy coordinate should also be updated + assert "energy" in result.coords + assert result.coords["energy"].shape == (7,) + assert np.all(result.coords["energy"].values == 0) # Should be zeros + + +class TestPopulateGeometricFactors: + """Tests for the populate_geometric_factors function.""" + + @pytest.mark.parametrize("species", ["h", "o"]) + @patch("imap_processing.lo.l2.lo_l2.reduce_geometric_factor_dataset") + def test_populate_geometric_factors( + self, mock_get_geometric_factor_dataset, species, sample_geometric_factor_data + ): + """Test population of geometric factor values for a specific species.""" + h_gf_data, o_gf_data = sample_geometric_factor_data + gf_data = h_gf_data if species == "h" else o_gf_data + mock_get_geometric_factor_dataset.return_value = gf_data.to_xarray() + + # Create initialized dataset + dataset = xr.Dataset(coords={"energy": range(7)}) + dataset = initialize_geometric_factor_variables(dataset) + + result = populate_geometric_factors(dataset, species) + + # Check that values were populated correctly + for i in range(7): + if species == "h": + # Check hydrogen values + assert result["energy"].values[i] == 0.01 * (i + 1) + assert result["geometric_factor"].values[i] == 1e-4 * (i + 1) + assert result["geometric_factor_stat_uncert"].values[i] == ( + 1e-5 * (i + 1) + ) + else: # oxygen + assert result["energy"].values[i] == 0.015 * (i + 1) + assert result["geometric_factor"].values[i] == 1.5e-4 * (i + 1) + assert result["geometric_factor_stat_uncert"].values[i] == ( + 1.5e-5 * (i + 1) + ) + # Ensure that energy_deltas are in units of keV + assert np.all(result["energy_delta_plus"].values < 1) + assert np.all(result["energy_delta_minus"].values < 1) + + def test_populate_geometric_factors_no_gf_species(self): + """Test population for species without geometric factors.""" + # Create initialized dataset + dataset = xr.Dataset(coords={"energy": range(7)}) + dataset = initialize_geometric_factor_variables(dataset) + + # Test with doubles (no geometric factors) + result = populate_geometric_factors(dataset, "doubles") + + # Should return dataset unchanged (all zeros) + assert np.all(result["geometric_factor"].values == 0) + + +class TestCleanupIntermediateVariables: + """Tests for the cleanup_intermediate_variables function.""" + + def test_cleanup_intermediate_variables(self): + """Test removal of intermediate variables.""" + # Create dataset with intermediate variables using current naming + dataset = xr.Dataset( + { + "counts": (("energy",), np.ones(7)), + "counts_over_eff": (("energy",), np.ones(7)), + "counts_over_eff_squared": (("energy",), np.ones(7)), + "bg_rate_exposure_factor": (("energy",), np.ones(7)), + "bg_rate_stat_uncert_exposure_factor2": (("energy",), np.ones(7)), + "ena_intensity": (("energy",), np.ones(7)), # Should be kept + "exposure_factor": (("energy",), np.ones(7)), # Should be kept + } + ) + + result = cleanup_intermediate_variables(dataset) + + # Should keep these variables + assert "counts" in result.data_vars + assert "ena_intensity" in result.data_vars + assert "exposure_factor" in result.data_vars + + # Should remove these intermediate variables + assert "counts_over_eff" not in result.data_vars + assert "counts_over_eff_squared" not in result.data_vars + assert "bg_rate_exposure_factor" not in result.data_vars + assert "bg_rate_stat_uncert_exposure_factor2" not in result.data_vars + + def test_cleanup_partial_variables(self): + """Test cleanup when only some intermediate variables exist.""" + # Create dataset with only some intermediate variables + dataset = xr.Dataset( + { + "counts": (("energy",), np.ones(7)), + "counts_over_eff": (("energy",), np.ones(7)), + "exposure_factor": (("energy",), np.ones(7)), + } + ) + + result = cleanup_intermediate_variables(dataset) + + # Should keep these + assert "counts" in result.data_vars + assert "exposure_factor" in result.data_vars + + # Should remove only the existing intermediate variable + assert "counts_over_eff" not in result.data_vars + + +class TestCalculateBootstrapCorrections: + """Tests for the calculate_bootstrap_corrections function.""" + + def test_calculate_bootstrap_corrections_basic( + self, sample_dataset_with_bootstrap_data + ): + """Test basic bootstrap correction functionality.""" + dataset = sample_dataset_with_bootstrap_data.copy() + + # Store original values for comparison + original_intensity = dataset["ena_intensity"].copy() + + result = calculate_bootstrap_corrections(dataset) + + # Check that bootstrap corrections were applied + assert "ena_intensity" in result.data_vars + assert "ena_intensity_stat_uncert" in result.data_vars + assert "ena_intensity_sys_err" in result.data_vars + + # Check that intermediate bootstrap variables were removed + assert "bootstrap_intensity" not in result.data_vars + assert "bootstrap_intensity_stat_uncert" not in result.data_vars + assert "bootstrap_intensity_sys_err" not in result.data_vars + + # Check that corrected intensities are different from originals + # (bootstrap should reduce intensities due to spillover correction) + corrected_intensity = result["ena_intensity"] + assert not np.allclose( + corrected_intensity.values, original_intensity.values, rtol=1e-10 + ), "Bootstrap corrections should modify intensities" + + # Check that corrected intensities are generally lower + # (bootstrap removes spillover from higher to lower energies) + for energy_idx in range(5): # Lower energy channels should be reduced + assert np.all( + corrected_intensity[0, energy_idx, :, :].values + <= original_intensity[0, energy_idx, :, :].values + ), f"Bootstrap should reduce intensity at energy index {energy_idx}" + + # This is a spot check value to ensure we are getting actual + # corrected intensities. Previously we were missing the application + # of the lower energy channels in the summation. + np.testing.assert_allclose(corrected_intensity[0, 5, 0, 0], [895.96302438]) + + def test_calculate_bootstrap_corrections_equations( + self, sample_dataset_with_bootstrap_data + ): + """Test that bootstrap equations are correctly implemented.""" + dataset = sample_dataset_with_bootstrap_data.copy() + + # Calculate expected j_c_prime (equation 14) + j_c_prime_expected = dataset["ena_intensity"] - dataset["bg_intensity"] + j_c_prime_expected = j_c_prime_expected.where(j_c_prime_expected >= 0, 0) + + # Apply bootstrap corrections and check the calculation was done correctly + result = calculate_bootstrap_corrections(dataset) + + # Verify the final result makes sense given the bootstrap factors + # Higher energy channels should have less correction + assert np.all(result["ena_intensity"][0, 6, :, :] >= 0), ( + "Bootstrap intensities should be non-negative" + ) + + def test_calculate_bootstrap_corrections_negative_handling(self): + """Test proper handling of negative values during bootstrap calculation.""" + # Create dataset with some negative j_c_prime values + coords = { + "epoch": [8.1794907049e17], + "energy": list(range(7)), + "longitude": [0, 90], + "latitude": [0, 45], + } + + dataset = xr.Dataset(coords=coords) + + # Create energy values + energy_values = np.array([0.5, 1.0, 2.0, 4.0, 8.0, 16.0, 32.0]) + dataset["energy"] = (("energy",), energy_values) + dataset["geometric_factor"] = (("energy",), np.ones(7)) + + # Create intensities where some background > intensity (negative j_c_prime) + intensity_values = np.ones((1, 7, 2, 2)) * 1e6 + bg_intensity_values = np.ones((1, 7, 2, 2)) * 1.5e6 # Higher than intensity + + dataset["ena_intensity"] = ( + ("epoch", "energy", "longitude", "latitude"), + intensity_values, + ) + dataset["bg_intensity"] = ( + ("epoch", "energy", "longitude", "latitude"), + bg_intensity_values, + ) + dataset["ena_intensity_stat_uncert"] = ( + ("epoch", "energy", "longitude", "latitude"), + np.ones((1, 7, 2, 2)) * 1e5, + ) + dataset["ena_intensity_sys_err"] = ( + ("epoch", "energy", "longitude", "latitude"), + np.ones((1, 7, 2, 2)) * 5e4, + ) + + result = calculate_bootstrap_corrections(dataset) + + # All corrected intensities should be non-negative + assert np.all(result["ena_intensity"].values >= 0), ( + "Bootstrap corrections should not produce negative intensities" + ) + + def test_calculate_bootstrap_corrections_energy_dependence(self): + """Test that bootstrap corrections show proper energy dependence.""" + # Create dataset with realistic energy spectrum + coords = { + "epoch": [8.1794907049e17], + "energy": list(range(7)), + "longitude": [0], + "latitude": [0], + } + + dataset = xr.Dataset(coords=coords) + + # Create energy values + energy_values = np.array([0.5, 1.0, 2.0, 4.0, 8.0, 16.0, 32.0]) + dataset["energy"] = (("energy",), energy_values) + dataset["geometric_factor"] = (("energy",), np.ones(7)) + + # Create a steep power law spectrum (typical for ENAs) + base_intensity = 1e8 + intensity_values = np.ones((1, 7, 1, 1)) + for i in range(7): + intensity_values[0, i, 0, 0] = base_intensity * (energy_values[i]) ** (-3) + + dataset["ena_intensity"] = ( + ("epoch", "energy", "longitude", "latitude"), + intensity_values, + ) + + # Low background + dataset["bg_intensity"] = ( + ("epoch", "energy", "longitude", "latitude"), + intensity_values * 0.01, # 1% background + ) + dataset["ena_intensity_stat_uncert"] = ( + ("epoch", "energy", "longitude", "latitude"), + np.sqrt(intensity_values) * 0.1, + ) + dataset["ena_intensity_sys_err"] = ( + ("epoch", "energy", "longitude", "latitude"), + intensity_values * 0.05, + ) + + result = calculate_bootstrap_corrections(dataset) + + # Lower energy channels should show larger corrections + # because they receive spillover from higher energy channels + original_ratios = [] + corrected_ratios = [] + + for i in range(6): # Compare adjacent energy channels + original_ratio = ( + dataset["ena_intensity"][0, i, 0, 0].values + / dataset["ena_intensity"][0, i + 1, 0, 0].values + ) + corrected_ratio = ( + result["ena_intensity"][0, i, 0, 0].values + / result["ena_intensity"][0, i + 1, 0, 0].values + ) + original_ratios.append(original_ratio) + corrected_ratios.append(corrected_ratio) + + # Bootstrap should affect the intensities + # Check that the bootstrap corrections are actually being applied + + # For power law spectra with small backgrounds, corrections may be very small + # Let's check that the algorithm at least completes without error + # and produces reasonable output + + # Check that all intensities are finite and positive + assert np.all(np.isfinite(result["ena_intensity"].values)), ( + "All corrected intensities should be finite" + ) + assert np.all(result["ena_intensity"].values >= 0), ( + "All corrected intensities should be non-negative" + ) + + # Check that uncertainties are reasonable + assert np.all(np.isfinite(result["ena_intensity_stat_uncert"].values)), ( + "All statistical uncertainties should be finite" + ) + assert np.all(np.isfinite(result["ena_intensity_sys_err"].values)), ( + "All systematic errors should be finite" + ) + + def test_calculate_bootstrap_corrections_uncertainty_propagation(self): + """Test proper uncertainty propagation in bootstrap corrections.""" + # Create simple dataset for uncertainty testing + coords = { + "epoch": [8.1794907049e17], + "energy": list(range(7)), + "longitude": [0], + "latitude": [0], + } + + dataset = xr.Dataset(coords=coords) + + # Create energy values + energy_values = np.array([0.5, 1.0, 2.0, 4.0, 8.0, 16.0, 32.0]) + dataset["energy"] = (("energy",), energy_values) + dataset["geometric_factor"] = (("energy",), np.ones(7)) + + # Simple flat spectrum for easier uncertainty analysis + intensity_values = np.ones((1, 7, 1, 1)) * 1e6 + dataset["ena_intensity"] = ( + ("epoch", "energy", "longitude", "latitude"), + intensity_values, + ) + dataset["bg_intensity"] = ( + ("epoch", "energy", "longitude", "latitude"), + intensity_values * 0.1, # 10% background + ) + + # Known uncertainties + stat_uncert = np.ones((1, 7, 1, 1)) * 1e5 + sys_err = np.ones((1, 7, 1, 1)) * 5e4 + + dataset["ena_intensity_stat_uncert"] = ( + ("epoch", "energy", "longitude", "latitude"), + stat_uncert, + ) + dataset["ena_intensity_sys_err"] = ( + ("epoch", "energy", "longitude", "latitude"), + sys_err, + ) + + result = calculate_bootstrap_corrections(dataset) + + # Check that uncertainties are properly propagated + assert np.all(result["ena_intensity_stat_uncert"].values >= 0), ( + "Statistical uncertainties should be non-negative" + ) + assert np.all(result["ena_intensity_sys_err"].values >= 0), ( + "Systematic errors should be non-negative" + ) + + # Uncertainties should be reasonable relative to the intensities + relative_stat_uncert = ( + result["ena_intensity_stat_uncert"] / result["ena_intensity"] + ) + assert np.all(relative_stat_uncert.values < 1.0), ( + "Relative statistical uncertainty should be reasonable" + ) + + def test_calculate_bootstrap_corrections_virtual_channel(self): + """Test the virtual channel E8 calculation and its impact.""" + # Create dataset focused on energy channels 5 and 6 for E8 calculation + coords = { + "epoch": [8.1794907049e17], + "energy": list(range(7)), + "longitude": [0], + "latitude": [0], + } + + dataset = xr.Dataset(coords=coords) + + # Create energy values where E6/E7 ratio is well-defined + energy_values = np.array([0.5, 1.0, 2.0, 4.0, 8.0, 16.0, 32.0]) + dataset["energy"] = (("energy",), energy_values) + dataset["geometric_factor"] = (("energy",), np.ones(7)) + + # Create intensities with clear power law for gamma calculation + intensity_values = np.ones((1, 7, 1, 1)) + for i in range(7): + intensity_values[0, i, 0, 0] = 1e6 * (energy_values[i] / 1.0) ** (-2) + + dataset["ena_intensity"] = ( + ("epoch", "energy", "longitude", "latitude"), + intensity_values, + ) + dataset["bg_intensity"] = ( + ("epoch", "energy", "longitude", "latitude"), + intensity_values * 0.05, # 5% background + ) + dataset["ena_intensity_stat_uncert"] = ( + ("epoch", "energy", "longitude", "latitude"), + np.sqrt(intensity_values) * 0.1, + ) + dataset["ena_intensity_sys_err"] = ( + ("epoch", "energy", "longitude", "latitude"), + intensity_values * 0.03, + ) + + # Calculate expected E8 and gamma manually + j_c_prime = dataset["ena_intensity"] - dataset["bg_intensity"] + j_c_prime = j_c_prime.where(j_c_prime >= 0, 0) + + result = calculate_bootstrap_corrections(dataset) + + # E8 should follow the power law relationship + # The virtual channel should have meaningful impact on energy channel 6 + original_e6 = j_c_prime[0, 6, 0, 0].values + corrected_e6 = result["ena_intensity"][0, 6, 0, 0].values + + # Energy channel 6 should be reduced due to E8 spillover subtraction + assert corrected_e6 < original_e6, ( + "Energy channel 6 should be reduced by E8 virtual channel correction" + ) + + def test_calculate_bootstrap_corrections_bootstrap_factors(self): + """Test that the bootstrap factor matrix is applied correctly.""" + # Create a simple dataset to verify bootstrap factor application + coords = { + "epoch": [8.1794907049e17], + "energy": list(range(7)), + "longitude": [0], + "latitude": [0], + } + + dataset = xr.Dataset(coords=coords) + + energy_values = np.array([0.5, 1.0, 2.0, 4.0, 8.0, 16.0, 32.0]) + dataset["energy"] = (("energy",), energy_values) + dataset["geometric_factor"] = (("energy",), np.ones(7)) + + # Use unit intensities to make bootstrap factor effects clear + intensity_values = np.ones((1, 7, 1, 1)) * 1.0 + dataset["ena_intensity"] = ( + ("epoch", "energy", "longitude", "latitude"), + intensity_values, + ) + dataset["bg_intensity"] = ( + ("epoch", "energy", "longitude", "latitude"), + np.zeros((1, 7, 1, 1)), # No background + ) + dataset["ena_intensity_stat_uncert"] = ( + ("epoch", "energy", "longitude", "latitude"), + np.ones((1, 7, 1, 1)) * 0.1, + ) + dataset["ena_intensity_sys_err"] = ( + ("epoch", "energy", "longitude", "latitude"), + np.ones((1, 7, 1, 1)) * 0.05, + ) + + result = calculate_bootstrap_corrections(dataset) + + # With unit intensities and no background, the corrections should + # directly reflect the bootstrap factors + # The bootstrap algorithm is complex due to interdependencies + # Let's just verify that corrections are applied and reasonable + corrected_intensities = result["ena_intensity"][0, :, 0, 0].values + + # All channels should be reduced from their original value of 1.0 + for i in range(7): + assert corrected_intensities[i] < 1.0, ( + f"Energy {i} should be corrected (reduced from 1.0), " + f"got {corrected_intensities[i]}" + ) + + # Energy 6 should have the largest correction due to 0.75 factor + assert corrected_intensities[6] < 0.5, ( + f"Energy 6 should have large correction, got {corrected_intensities[6]}" + ) + + def test_calculate_bootstrap_corrections_edge_cases(self): + """Test edge cases in bootstrap correction calculation.""" + # Test with zero intensities + coords = { + "epoch": [8.1794907049e17], + "energy": list(range(7)), + "longitude": [0], + "latitude": [0], + } + + dataset = xr.Dataset(coords=coords) + + energy_values = np.array([0.5, 1.0, 2.0, 4.0, 8.0, 16.0, 32.0]) + dataset["energy"] = (("energy",), energy_values) + dataset["geometric_factor"] = (("energy",), np.ones(7)) + + # Zero intensities + intensity_values = np.zeros((1, 7, 1, 1)) + dataset["ena_intensity"] = ( + ("epoch", "energy", "longitude", "latitude"), + intensity_values, + ) + dataset["bg_intensity"] = ( + ("epoch", "energy", "longitude", "latitude"), + np.zeros((1, 7, 1, 1)), + ) + dataset["ena_intensity_stat_uncert"] = ( + ("epoch", "energy", "longitude", "latitude"), + np.zeros((1, 7, 1, 1)), + ) + dataset["ena_intensity_sys_err"] = ( + ("epoch", "energy", "longitude", "latitude"), + np.zeros((1, 7, 1, 1)), + ) + + result = calculate_bootstrap_corrections(dataset) + + # Should handle zero intensities gracefully + assert np.all(result["ena_intensity"].values >= 0), ( + "Zero intensities should remain non-negative" + ) + assert np.all(np.isfinite(result["ena_intensity"].values)), ( + "All intensities should be finite" + ) + + def test_calculate_bootstrap_corrections_no_csv_files( + self, sample_dataset_with_bootstrap_data, caplog + ): + """Test that missing bootstrap CSV files raise a ValueError.""" + dataset = sample_dataset_with_bootstrap_data.copy() + + with patch("imap_processing.lo.l2.lo_l2.Path.glob", return_value=iter([])): + with pytest.raises( + ValueError, match="No bootstrap correction factor files found" + ): + calculate_bootstrap_corrections(dataset) + + +# ============================================================================= +# INTEGRATION TESTS +# ============================================================================= + + +class TestCalculateAllRatesAndIntensities: + """Integration tests for the calculate_all_rates_and_intensities function.""" + + def test_calculate_all_rates_and_intensities_complete(self): + """Test the complete rates and intensities calculation pipeline.""" + # Create a comprehensive dataset with current naming convention + dataset = xr.Dataset( + { + # Count data (current generic naming) + "counts": (("energy",), np.ones(7) * 10), + # Efficiency corrected data + "counts_over_eff": (("energy",), np.ones(7) * 12), # 10/0.83 β‰ˆ 12 + "counts_over_eff_squared": (("energy",), np.ones(7) * 12), + # Other required data + "exposure_factor": (("energy",), np.ones(7) * 1.0), + "geometric_factor": (("energy",), np.ones(7) * 1e-4), + "energy": (("energy",), np.ones(7) * 0.1), + "geometric_factor_stat_uncert": (("energy",), np.ones(7) * 1e-5), + # Background intermediate data + "bg_rate_exposure_factor": (("energy",), np.ones(7) * 0.3), + "bg_rate_stat_uncert_exposure_factor2": ( + ("energy",), + np.ones(7) * 0.009, + ), + } + ) + + result = calculate_all_rates_and_intensities(dataset) + + # Check that rates were calculated + assert "ena_count_rate" in result.data_vars + assert "ena_count_rate_stat_uncert" in result.data_vars + + # Check that intensities were calculated + assert "ena_intensity" in result.data_vars + assert "ena_intensity_stat_uncert" in result.data_vars + assert "ena_intensity_sys_err" in result.data_vars + + # Check that background rates were calculated + assert "bg_rate" in result.data_vars + assert "bg_rate_stat_uncert" in result.data_vars + assert "bg_rate_sys_err" in result.data_vars + + # Check that intermediate variables were cleaned up + assert "counts_over_eff" not in result.data_vars + assert "counts_over_eff_squared" not in result.data_vars + assert "bg_rate_exposure_factor" not in result.data_vars + assert "bg_rate_stat_uncert_exposure_factor2" not in result.data_vars + + def test_calculate_all_rates_with_cg_correction( + self, sample_dataset_with_intensities + ): + """Test that CG correction is applied when cg_correction=True.""" + # Add necessary variables for the calculation + dataset = sample_dataset_with_intensities.copy(deep=True) + dataset["counts"] = (("epoch", "energy"), np.ones((1, 7)) * 10) + dataset["counts_over_eff"] = (("epoch", "energy"), np.ones((1, 7)) * 12) + dataset["counts_over_eff_squared"] = (("epoch", "energy"), np.ones((1, 7)) * 12) + dataset["exposure_factor"] = (("epoch", "energy"), np.ones((1, 7)) * 1.0) + dataset["geometric_factor"] = (("energy",), np.ones(7) * 1e-4) + dataset["geometric_factor_stat_uncert"] = (("energy",), np.ones(7) * 1e-5) + dataset["bg_rate_exposure_factor"] = ( + ("epoch", "energy"), + np.ones((1, 7)) * 0.3, + ) + dataset["bg_rate_stat_uncert_exposure_factor2"] = ( + ("epoch", "energy"), + np.ones((1, 7)) * 0.009, + ) + dataset["energy_sc_exposure_factor"] = xr.ones_like(dataset["ena_intensity"]) + + # Mock the interpolation function + with patch( + "imap_processing.lo.l2.lo_l2.interpolate_map_flux_to_helio_frame" + ) as mock_interp: + # Make the mock return the input dataset + mock_interp.side_effect = lambda ds, *args, **kwargs: ds + + # Call with CG correction enabled + _ = calculate_all_rates_and_intensities(dataset, cg_correction=True) + + # Verify that interpolation was called + mock_interp.assert_called_once() + + # Check the call arguments + call_args = mock_interp.call_args + assert call_args[0][1].equals( + dataset["energy"] + ) # spacecraft frame energies + assert call_args[0][2].equals(dataset["energy"]) # helio frame energies + # Check that s/c energies get computed in keV units + expected_sc_energies = ( + dataset["energy_sc_exposure_factor"] / dataset["exposure_factor"] / 1e3 + ) + xr.testing.assert_allclose( + call_args[0][0]["energy_sc"], expected_sc_energies + ) + assert "ena_intensity" in call_args[0][3] # variables to interpolate + assert "bg_intensity" in call_args[0][3] + + def test_calculate_all_rates_cg_with_other_corrections( + self, sample_dataset_with_intensities, lo_flux_factors_file + ): + """Test CG correction works alongside other corrections.""" + # Add necessary variables + dataset = sample_dataset_with_intensities.copy(deep=True) + dataset["counts"] = (("epoch", "energy"), np.ones((1, 7)) * 10) + dataset["counts_over_eff"] = (("epoch", "energy"), np.ones((1, 7)) * 12) + dataset["counts_over_eff_squared"] = (("epoch", "energy"), np.ones((1, 7)) * 12) + dataset["exposure_factor"] = (("epoch", "energy"), np.ones((1, 7)) * 1.0) + dataset["geometric_factor"] = (("energy",), np.ones(7) * 1e-4) + dataset["geometric_factor_stat_uncert"] = (("energy",), np.ones(7) * 1e-5) + dataset["bg_rate_exposure_factor"] = ( + ("epoch", "energy"), + np.ones((1, 7)) * 0.3, + ) + dataset["bg_rate_stat_uncert_exposure_factor2"] = ( + ("epoch", "energy"), + np.ones((1, 7)) * 0.009, + ) + dataset["energy_sc_exposure_factor"] = xr.ones_like(dataset["ena_intensity"]) + + with patch( + "imap_processing.lo.l2.lo_l2.interpolate_map_flux_to_helio_frame" + ) as mock_interp: + mock_interp.side_effect = lambda ds, *args, **kwargs: ds + + # Call with both flux correction and CG correction + result = calculate_all_rates_and_intensities( + dataset, + flux_correction=True, + flux_factors=lo_flux_factors_file, + cg_correction=True, + ) + + # Both corrections should be applied + assert "ena_intensity" in result.data_vars + mock_interp.assert_called_once() + + +@pytest.mark.external_kernel +class TestIntegrationWithMocks: + """Integration tests using mocked external dependencies.""" + + def test_lo_l2_integration_minimal( + self, minimal_pset_for_species, lo_flux_factors_file + ): + """Test the main lo_l2 function with minimal mocking.""" + # Test with hydrogen data + sci_dependencies = {"imap_lo_l1c_pset": [minimal_pset_for_species]} + anc_dependencies = [lo_flux_factors_file] # Include flux factors file + descriptor = "l090-ena-h-sf-nsp-ram-hae-6deg-3mo" + + # Mock the complex external dependencies to return simple results + with ( + patch( + "imap_processing.lo.l2.lo_l2.create_sky_map_from_psets" + ) as mock_create_map, + patch("imap_processing.lo.l2.lo_l2.add_geometric_factors") as mock_add_gf, + patch( + "imap_processing.lo.l2.lo_l2.calculate_all_rates_and_intensities" + ) as mock_calc_rates, + patch("imap_processing.lo.l2.lo_l2.finalize_dataset") as mock_finalize, + ): + # Setup mock returns + mock_sky_map = Mock() + mock_dataset = xr.Dataset({"test_var": (("energy",), np.ones(7))}) + mock_sky_map.to_dataset.return_value = mock_dataset + mock_sky_map.build_cdf_dataset.return_value = mock_dataset + mock_create_map.return_value = mock_sky_map + mock_add_gf.return_value = mock_dataset + mock_calc_rates.return_value = mock_dataset + mock_finalize.return_value = mock_dataset + + # Run the function - should not crash + result = lo_l2(sci_dependencies, anc_dependencies, descriptor) + + # Basic validation + assert isinstance(result, list) + assert len(result) == 1 + assert isinstance(result[0], xr.Dataset) + + # Mock the rates calculation to return the dataset unchanged + mock_calc_rates.side_effect = lambda x, **kwargs: x + + # Run the function - should not crash + result = lo_l2(sci_dependencies, anc_dependencies, descriptor) + + # Basic validation + assert isinstance(result, list) + assert len(result) == 1 + assert isinstance(result[0], xr.Dataset) + + +@pytest.fixture +def ibex_pset_file(): + """Path to the LO/IBEX pset test file.""" + # Use the actual test data file from the ena_maps test data + test_data_path = Path(__file__).parent / "test_cdfs" + return test_data_path / "imap_lo_l1c_pset_20260101-repoint01261_v001.cdf" + + +@pytest.mark.external_test_data +@pytest.mark.external_kernel +class TestIntegration: + """Integration tests using IBEX data and simulated kernels.""" + + def test_lo_l2_integration_full( + self, ibex_pset_file, imap_ena_sim_metakernel, lo_flux_factors_file + ): + """Test the main lo_l2 function with no mocking.""" + # Test with oxygen data to reduce test run-time + psets = load_cdf(ibex_pset_file) + psets.attrs["Logical_source"] = "imap_lo_l1c_pset" + psets = add_spacecraft_position_and_velocity_to_pset(psets) + + sci_dependencies = {"imap_lo_l1c_pset": [psets]} + anc_dependencies = [lo_flux_factors_file] # Include flux factors file + descriptor = "l090-ena-o-hf-nsp-ram-hae-6deg-3mo" + + # Run the function - should not crash + result = lo_l2(sci_dependencies, anc_dependencies, descriptor) + + # Basic validation + assert isinstance(result, list) + assert len(result) == 1 + assert isinstance(result[0], xr.Dataset) + + # Make sure that bg_rate variables are present + for var in ["bg_rate", "bg_rate_stat_uncert", "bg_rate_sys_err"]: + assert var in result[0].data_vars + + +# ============================================================================= +# ERROR HANDLING TESTS +# ============================================================================= + + +class TestErrorHandling: + """Tests for error handling in various functions.""" + + def test_lo_l2_no_pset_data(self): + """Test error when no pointing set data is provided.""" + sci_dependencies = {} # Missing imap_lo_l1c_pset + anc_dependencies = [] + descriptor = "l090-ena-h-sf-nsp-ram-hae-6deg-3mo" + + with pytest.raises(ValueError, match="No pointing set data found"): + lo_l2(sci_dependencies, anc_dependencies, descriptor) + + def test_create_sky_map_healpix_not_supported(self, minimal_pset_for_species): + """Test error when HEALPix map is requested.""" + with patch.object(MapDescriptor, "from_string") as mock_from_string: + mock_map_desc = Mock() + mock_healpix_map = Mock() # Not a RectangularSkyMap + mock_map_desc.to_empty_map.return_value = mock_healpix_map + mock_map_desc.species = "h" + mock_from_string.return_value = mock_map_desc + + with pytest.raises( + NotImplementedError, match="HEALPix map output not supported" + ): + create_sky_map_from_psets( + [minimal_pset_for_species], mock_map_desc, pd.DataFrame(), False + ) + + +# ============================================================================= +# PROPERTY-BASED AND EDGE CASE TESTS +# ============================================================================= + + +class TestEdgeCases: + """Tests for edge cases and boundary conditions.""" + + def test_empty_efficiency_data_handling(self, minimal_pset): + """Test handling of empty efficiency data.""" + empty_df = pd.DataFrame() + result = add_efficiency_factors_to_pset(minimal_pset, empty_df) + + # Should create unity efficiency + assert "efficiency" in result.data_vars + np.testing.assert_array_equal(result["efficiency"].values, np.ones(7)) + + def test_zero_exposure_time_handling(self): + """Test handling of zero exposure times.""" + dataset = xr.Dataset( + { + "counts": (("energy",), np.ones(7) * 10), + "exposure_factor": (("energy",), np.zeros(7)), # Zero exposure + } + ) + + result = calculate_rates(dataset) + + # Should handle division by zero gracefully + assert "ena_count_rate" in result.data_vars + # Rates should be infinite where exposure time is zero + assert np.all(np.isinf(result["ena_count_rate"].values)) + + def test_negative_counts_handling(self): + """Test handling of negative count values.""" + dataset = xr.Dataset( + { + "counts": (("energy",), np.array([-1, 0, 1, 2, 3, 4, 5])), + "exposure_factor": (("energy",), np.ones(7)), + } + ) + + result = calculate_rates(dataset) + + # Should calculate rates even with negative counts + assert "ena_count_rate" in result.data_vars + assert "ena_count_rate_stat_uncert" in result.data_vars + + # Uncertainty calculation should handle negative counts + # (sqrt of negative gives NaN, which is expected behavior) + assert np.isnan(result["ena_count_rate_stat_uncert"].values[0]) + + +# ============================================================================= +# TESTS FOR CG CORRECTION FUNCTIONALITY +# ============================================================================= + + +class TestPrepareCorrections: + """Tests for the _prepare_corrections function.""" + + def test_prepare_corrections_hf_frame(self, lo_flux_factors_file): + """Test that CG correction is enabled for heliocentric frame (hf).""" + # Create a map descriptor with heliocentric frame + descriptor = "ilo90-ena-h-hf-nsp-full-hae-6deg-3mo" + map_descriptor = MapDescriptor.from_string(descriptor) + + sci_dependencies = {"imap_lo_l1c_pset": []} + anc_dependencies = [lo_flux_factors_file] + + with patch("imap_processing.lo.l2.lo_l2.lo_l2") as mock_lo_l2: + mock_o_dataset = xr.Dataset() + mock_lo_l2.return_value = [mock_o_dataset] + result = _prepare_corrections( + map_descriptor, descriptor, sci_dependencies, anc_dependencies + ) + + # Unpack the tuple + ( + sputtering_correction, + bootstrap_correction, + flux_correction, + o_map_dataset, + flux_factors, + cg_correction, + ) = result + + # Check that CG correction is enabled for hf frame + assert cg_correction is True, "CG correction should be enabled for 'hf' frame" + + # Check other correction flags + assert flux_correction is True # ENA data should have flux correction + assert sputtering_correction is True # h-ena product, apply sputtering + assert bootstrap_correction is True # h-ena product, apply bootstrap + assert o_map_dataset is not None # oxygen dataset produced + assert flux_factors is not None # Flux factors should be found + + def test_prepare_corrections_sc_frame(self, lo_flux_factors_file): + """Test that CG correction is disabled for spacecraft frame (sc).""" + # Create a map descriptor with spacecraft frame + descriptor = "ilo90-ena-o-sf-nsp-full-hae-6deg-3mo" + map_descriptor = MapDescriptor.from_string(descriptor) + + sci_dependencies = {"imap_lo_l1c_pset": []} + anc_dependencies = [lo_flux_factors_file] + + result = _prepare_corrections( + map_descriptor, descriptor, sci_dependencies, anc_dependencies + ) + + # Unpack the tuple + ( + sputtering_correction, + bootstrap_correction, + flux_correction, + o_map_dataset, + flux_factors, + cg_correction, + ) = result + + # Check that CG correction is disabled for sc frame + assert cg_correction is False, ( + "CG correction should be disabled for non-'hf' frame" + ) + + def test_prepare_corrections_with_hydrogen_ena(self, lo_flux_factors_file): + """Test corrections for hydrogen ENA data.""" + descriptor = "ilo90-ena-h-sf-nsp-full-hae-6deg-3mo" + map_descriptor = MapDescriptor.from_string(descriptor) + + # Mock the recursive call to lo_l2 for oxygen + with patch("imap_processing.lo.l2.lo_l2.lo_l2") as mock_lo_l2: + mock_o_dataset = xr.Dataset({"test": (("energy",), np.ones(7))}) + mock_lo_l2.return_value = [mock_o_dataset] + + sci_dependencies = {"imap_lo_l1c_pset": []} + anc_dependencies = [lo_flux_factors_file] + + result = _prepare_corrections( + map_descriptor, descriptor, sci_dependencies, anc_dependencies + ) + + ( + sputtering_correction, + bootstrap_correction, + flux_correction, + o_map_dataset, + flux_factors, + cg_correction, + ) = result + + # Check that all corrections are enabled for hydrogen ENA + assert sputtering_correction is True + assert bootstrap_correction is True + assert flux_correction is True + assert o_map_dataset is not None + assert cg_correction is False # sf frame, not hf + + +class TestProcessSinglePset: + """Tests for the process_single_pset function with CG correction.""" + + def test_process_single_pset_hf_frame(self, minimal_pset, sample_efficiency_data): + """Test that CG correction is applied for heliocentric frame.""" + pset = minimal_pset.copy() + pset = pset.rename({"esa_energy_step": "energy"}) + # apply_compton_getting_correction gets mocked out so we need to add the + # energy_sc variable to the pset + pset["energy_sc"] = xr.ones_like(pset["counts"]) + + with ( + patch( + "imap_processing.lo.l2.lo_l2.normalize_pset_coordinates" + ) as mock_norm, + patch( + "imap_processing.lo.l2.lo_l2.add_efficiency_factors_to_pset" + ) as mock_add_ef, + patch( + "imap_processing.lo.l2.lo_l2.calculate_efficiency_corrected_quantities" + ) as mock_calc_ef, + patch( + "imap_processing.lo.l2.lo_l2.apply_compton_getting_correction" + ) as mock_cg, + patch("imap_processing.lo.l2.lo_l2.calculate_ram_mask") as mock_ram_mask, + ): + mock_norm.return_value = pset + mock_add_ef.return_value = pset + mock_calc_ef.return_value = pset + mock_cg.return_value = pset + mock_ram_mask.return_value = pset + + # Mock the spacecraft velocity + pset["sc_velocity"] = xr.DataArray( + data=[400, 0, 0], # 400 km/s in x direction + dims="component", + coords={"component": ["vx", "vy", "vz"]}, + ) + + # Process with hf frame + _ = process_single_pset(pset, sample_efficiency_data, "h", cg_correct=True) + + # Check that CG correction was called + mock_cg.assert_called_once() + assert mock_cg.call_args[0][0] is pset + # Energy should be passed as second argument + assert "energy" in mock_cg.call_args[0][1].dims + + # Check that calculate_ram_mask was called + mock_ram_mask.assert_called_once() + + def test_process_single_pset_sc_frame(self, minimal_pset, sample_efficiency_data): + """Test that CG correction is not applied for spacecraft frame.""" + pset = minimal_pset.copy() + pset = pset.rename({"esa_energy_step": "energy"}) + + with ( + patch( + "imap_processing.lo.l2.lo_l2.normalize_pset_coordinates" + ) as mock_norm, + patch( + "imap_processing.lo.l2.lo_l2.add_efficiency_factors_to_pset" + ) as mock_add_ef, + patch( + "imap_processing.lo.l2.lo_l2.calculate_efficiency_corrected_quantities" + ) as mock_calc_ef, + patch( + "imap_processing.lo.l2.lo_l2.apply_compton_getting_correction" + ) as mock_cg, + patch("imap_processing.lo.l2.lo_l2.calculate_ram_mask") as mock_ram_mask, + ): + mock_norm.return_value = pset + mock_add_ef.return_value = pset + mock_calc_ef.return_value = pset + mock_cg.return_value = pset + + # Mock the spacecraft velocity + pset["sc_velocity"] = xr.DataArray( + data=[400, 0, 0], # 400 km/s in x direction + dims="component", + coords={"component": ["vx", "vy", "vz"]}, + ) + + # Process with sc frame + _ = process_single_pset(pset, sample_efficiency_data, "h", cg_correct=False) + + # Check that CG correction was NOT called + mock_cg.assert_not_called() + + # Check that the ram mask was called instead + mock_ram_mask.assert_called_once() + + +class TestProjectPsetToMap: + """Tests for the project_pset_to_map function with directional mask.""" + + def test_project_pset_to_map_with_mask(self, minimal_pset_for_species): + """Test that directional mask is passed to projection.""" + # Create a mock sky map + mock_map = Mock(spec=RectangularSkyMap) + + # Create a directional mask + directional_mask = xr.DataArray( + np.ones(7, dtype=bool), + dims=["energy"], + coords={"energy": list(range(7))}, + ) + + # Call project_pset_to_map + project_pset_to_map(minimal_pset_for_species, mock_map, directional_mask) + + # Verify that project_pset_values_to_map was called with the mask + mock_map.project_pset_values_to_map.assert_called_once() + call_kwargs = mock_map.project_pset_values_to_map.call_args[1] + assert "pset_valid_mask" in call_kwargs + assert call_kwargs["pset_valid_mask"] is directional_mask + + def test_project_pset_to_map_value_keys(self, minimal_pset_for_species): + """Test that correct value keys are projected.""" + mock_map = Mock(spec=RectangularSkyMap) + directional_mask = xr.DataArray( + np.ones(7, dtype=bool), + dims=["energy"], + ) + + project_pset_to_map(minimal_pset_for_species, mock_map, directional_mask) + + # Check that the expected value keys are in the call + call_kwargs = mock_map.project_pset_values_to_map.call_args[1] + value_keys = call_kwargs["value_keys"] + + expected_keys = [ + "exposure_factor", + "counts", + "counts_over_eff", + "counts_over_eff_squared", + "bg_rate", + "bg_rate_stat_uncert", + "bg_rate_exposure_factor", + "bg_rate_stat_uncert_exposure_factor2", + ] + + for key in expected_keys: + assert key in value_keys, f"Expected key '{key}' not in value_keys" diff --git a/imap_processing/tests/lo/test_lo_science.py b/imap_processing/tests/lo/test_lo_science.py index 33e5e09bb0..eb48248ce7 100644 --- a/imap_processing/tests/lo/test_lo_science.py +++ b/imap_processing/tests/lo/test_lo_science.py @@ -9,12 +9,9 @@ from imap_processing.lo.l0.lo_science import ( combine_segmented_packets, organize_spin_data, - parse_de_bin, parse_events, - parse_fixed_fields, - parse_variable_fields, ) -from imap_processing.utils import convert_to_binary_string, packet_file_to_datasets +from imap_processing.utils import packet_file_to_datasets @pytest.fixture @@ -62,10 +59,14 @@ def fake_de_dataset(): + tof1_2 + pos_2 ) + + # Convert binary string to actual bytes for the new bytewise parsing + byte_data = bytes(int(de_data[i : i + 8], 2) for i in range(0, len(de_data), 8)) + dataset = xr.Dataset( data_vars=dict( count=(["time"], np.array([2])), - events=(["time"], np.array([de_data])), + data=(["time"], np.array([byte_data], dtype=object)), ) ) @@ -88,28 +89,35 @@ def sample_data(): @pytest.fixture def segmented_pkts_fake_data(): + # Convert string binary to bytes for each data entry + string_data = [ + "0000000001", + "0000000010", + "0000000100", + "0000001000", + "0000010000", + "0000100000", + "0001000000", + "0010000000", + "0100000000", + "1000000000", + ] + + # Pad strings to be divisible by 8 and convert to bytes + byte_data = [] + for s in string_data: + # Pad to nearest multiple of 8 + padded = s.ljust((len(s) + 7) // 8 * 8, "0") + byte_data.append( + bytes(int(padded[i : i + 8], 2) for i in range(0, len(padded), 8)) + ) + dataset = xr.Dataset( data_vars=dict( seq_flgs=(["epoch"], np.array([1, 0, 0, 2, 3, 1, 0, 2, 1, 2])), src_seq_ctr=(["epoch"], np.array([0, 1, 2, 3, 4, 5, 7, 8, 9, 10])), shcoarse=(["epoch"], np.array([0, 0, 0, 0, 10, 20, 20, 20, 30, 30])), - data=( - ["epoch"], - np.array( - [ - "0000000001", - "0000000010", - "0000000100", - "0000001000", - "0000010000", - "0000100000", - "0001000000", - "0010000000", - "0100000000", - "1000000000", - ] - ), - ), + data=(["epoch"], np.array(byte_data, dtype=object)), ), coords=dict(epoch=(["epoch"], np.array([0, 0, 0, 0, 10, 20, 20, 20, 30, 30]))), ) @@ -196,47 +204,6 @@ def test_parse_events(fake_de_dataset, attr_mgr): np.testing.assert_array_equal(dataset["pos"].values, np.array([255, 0])) -def test_parse_fixed_fields(initialized_dataset): - # Arrange - initialized_dataset.attrs["bit_pos"] = 48 - - # Act - dataset = parse_fixed_fields(initialized_dataset, 0, 0) - - # Assert - np.testing.assert_array_equal( - dataset["coincidence_type"].values, np.array([0, 255]) - ) - np.testing.assert_array_equal(dataset["de_time"].values, np.array([100, 65535])) - np.testing.assert_array_equal(dataset["esa_step"].values, np.array([2, 255])) - np.testing.assert_array_equal(dataset["mode"].values, np.array([1, 255])) - - -def test_parse_variable_fields(initialized_dataset): - # Arrange - initialized_dataset["coincidence_type"].values = np.array([0, 255]) - initialized_dataset["mode"].values = np.array([1, 255]) - initialized_dataset.attrs["bit_pos"] = 68 - - # Act - dataset = parse_variable_fields(initialized_dataset, 0, 0) - - # Assert - np.testing.assert_array_equal(dataset["tof0"].values, np.array([0 << 1, 65535])) - np.testing.assert_array_equal(dataset["tof1"].values, np.array([65535, 65535])) - np.testing.assert_array_equal(dataset["tof2"].values, np.array([2 << 1, 65535])) - np.testing.assert_array_equal(dataset["tof3"].values, np.array([3 << 1, 65535])) - np.testing.assert_array_equal(dataset["cksm"].values, np.array([0 << 1, 255])) - np.testing.assert_array_equal(dataset["pos"].values, np.array([255, 255])) - - -def test_parse_de_bin(initialized_dataset): - # Act - parsed_int = parse_de_bin(initialized_dataset, 0, 4, 0) - # Assert - assert parsed_int == 0 - - def test_combine_segmented_packets(segmented_pkts_fake_data): dataset = combine_segmented_packets(segmented_pkts_fake_data) @@ -249,20 +216,29 @@ def test_combine_segmented_packets(segmented_pkts_fake_data): np.testing.assert_array_equal( dataset["shcoarse"].values, np.array([0, 0, 0, 0, 10, 20, 20, 20, 30, 30]) ) - np.testing.assert_array_equal( - dataset["events"].values, - np.array( - [ - "0000000001000000001000000001000000001000", - "0000010000", - "01000000001000000000", - ] - ), - ) + + # Test that we have the expected number of combined data segments + assert len(dataset["data"].values) == 3 + assert dataset["data"].values[0] == b"\x00@\x00\x80\x01\x00\x02" + assert dataset["data"].values[1] == b"\x04" + assert dataset["data"].values[2] == b"@\x00\x80" + np.testing.assert_array_equal(dataset["epoch"].values, np.array([0, 10, 30])) np.testing.assert_array_equal(dataset["met"].values, np.array([0, 10, 30])) +def test_combin_segmented_packets_only_met(segmented_pkts_fake_data): + segmented_pkts_fake_data["seq_flgs"].values = np.full(10, 3) + dataset = combine_segmented_packets(segmented_pkts_fake_data) + + np.testing.assert_array_equal( + dataset["epoch"].values, segmented_pkts_fake_data["epoch"].values + ) + np.testing.assert_array_equal( + dataset["met"].values, segmented_pkts_fake_data["shcoarse"].values + ) + + def test_validate_parse_events(sample_data, attr_mgr): de_data = sample_data[LoAPID.ILO_SCI_DE] validation_path = ( @@ -284,11 +260,6 @@ def test_validate_parse_events(sample_data, attr_mgr): "pos", ] - de_data["data"] = xr.DataArray( - [convert_to_binary_string(data) for data in de_data["data"].values], - dims=de_data["data"].dims, - attrs=de_data["data"].attrs, - ) de_data = combine_segmented_packets(de_data) dataset = parse_events(de_data, attr_mgr) diff --git a/imap_processing/tests/mag/conftest.py b/imap_processing/tests/mag/conftest.py index 2bb3ceb762..de4aba5ce5 100644 --- a/imap_processing/tests/mag/conftest.py +++ b/imap_processing/tests/mag/conftest.py @@ -175,7 +175,11 @@ def norm_dataset(mag_test_l2_data): dataset.attrs["vectors_per_second"] = vectors_per_second_attr dataset["epoch"] = epoch_vals dataset.attrs["Logical_source"] = "imap_mag_l1c_norm-mago" - vectors = np.array([[i, i, i, 2] for i in range(1, 3505)]) + # Actual dataset is a CDF_FLOAT which is a float32. + vectors = np.array( + [[i, i, i, 2] for i in range(1, 3505)], + dtype=np.float64, + ) dataset["vectors"].data = vectors return dataset diff --git a/imap_processing/tests/mag/test_mag_l1b.py b/imap_processing/tests/mag/test_mag_l1b.py index 5d6b849f1a..e72b0a9902 100644 --- a/imap_processing/tests/mag/test_mag_l1b.py +++ b/imap_processing/tests/mag/test_mag_l1b.py @@ -11,6 +11,8 @@ mag_l1b, mag_l1b_processing, rescale_vector, + shift_time, + timeshift_vectors_per_second, ) from imap_processing.tests.mag.conftest import ( mag_l1a_dataset_generator, @@ -226,3 +228,30 @@ def test_l1a_to_l1b(validation_l1a, mag_l1b_cal_dataset): assert len(l1b[0]["vectors"].data) > 0 assert len(l1b[1]["vectors"].data) > 0 + + +def test_shift_time_preserves_int64_precision(): + # Issue #3102: TT2000 epochs near 8e17 ns must stay int64; float promotion + # silently quantizes them. + epoch = xr.DataArray( + np.array( + [813411068230810679, 813411068238623179, 813411068246435679], + dtype=np.int64, + ), + dims="epoch", + ) + + zero = shift_time(epoch, xr.DataArray(np.array([0.0]), dims="epoch")) + np.testing.assert_array_equal(zero.values, epoch.values) + + shifted = shift_time(epoch, xr.DataArray(np.array([1.2345e-5]), dims="epoch")) + assert shifted.dtype == np.int64 + np.testing.assert_array_equal(shifted.values, epoch.values + 12345) + + +def test_timeshift_vectors_per_second_preserves_int64_precision(): + shift = xr.DataArray(np.array([1.2345e-5]), dims="epoch") + out = timeshift_vectors_per_second( + "813411068230810679:128,813411500000000000:128", shift + ) + assert out == "813411068230823024:128,813411500000012345:128" diff --git a/imap_processing/tests/mag/test_mag_l1c.py b/imap_processing/tests/mag/test_mag_l1c.py index 462d4a1dfc..0f0020e35e 100644 --- a/imap_processing/tests/mag/test_mag_l1c.py +++ b/imap_processing/tests/mag/test_mag_l1c.py @@ -3,7 +3,7 @@ import xarray as xr from imap_processing.mag import imap_mag_sdc_configuration_v001 as configuration -from imap_processing.mag.constants import VecSec +from imap_processing.mag.constants import ModeFlags, VecSec from imap_processing.mag.l1c.interpolation_methods import ( InterpolationFunction, cic_filter, @@ -13,12 +13,14 @@ fill_normal_data, find_all_gaps, find_gaps, + generate_missing_timestamps, generate_timeline, interpolate_gaps, mag_l1c, process_mag_l1c, vectors_per_second_from_string, ) +from imap_processing.spice.time import et_to_ttj2000ns, str_to_et from imap_processing.tests.mag.conftest import ( generate_test_epoch, mag_l1a_dataset_generator, @@ -89,28 +91,61 @@ def test_interpolation_methods(): input_timestamps = np.arange(0, 50, step=0.25) * 1e9 output_timestamps = np.arange(10, 20, step=0.5) * 1e9 for method in InterpolationFunction: - output = method( + adjusted_time, output = method( vectors, input_timestamps, output_timestamps, input_rate=VecSec.FOUR_VECS_PER_S, output_rate=VecSec.TWO_VECS_PER_S, ) + assert len(adjusted_time) == 20 assert len(output) == 20 - output = method( + adjusted_time, output = method( vectors, input_timestamps, output_timestamps, input_rate=None, output_rate=None, ) + assert len(adjusted_time) == 20 assert len(output) == 20 +@pytest.mark.parametrize( + "method", + [ + InterpolationFunction.linear_filtered, + InterpolationFunction.quadratic_filtered, + InterpolationFunction.cubic_filtered, + ], +) +def test_filtered_interpolation_methods_drop_unsupported_tail_timestamp(method): + input_timestamps = np.arange(0.125, 8.001, step=0.125) * 1e9 + seconds = input_timestamps / 1e9 + input_vectors = np.column_stack( + [seconds, seconds, seconds, np.ones(input_timestamps.size)] + ) + # Tail boundary: 8.0 s is inside the original burst window but beyond the + # post-CIC filtered tail, so it should be dropped rather than extrapolated. + output_timestamps = np.array([7.5, 8.0]) * 1e9 + + adjusted_time, output = method( + input_vectors, + input_timestamps, + output_timestamps, + input_rate=VecSec.EIGHT_VECS_PER_S, + output_rate=VecSec.TWO_VECS_PER_S, + ) + + assert np.array_equal(adjusted_time, np.array([7.5]) * 1e9) + + def test_process_mag_l1c(norm_dataset, burst_dataset): l1c = process_mag_l1c(norm_dataset, burst_dataset, InterpolationFunction.linear) expected_output_timeline = ( - np.array([0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 4.25, 4.75, 5.25, 5.5, 5.75, 6]) + np.array( + [0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 4.25, 4.5, 4.75, 5, 5.25, 5.5, 5.75, 6] + ) * 1e9 ) assert np.array_equal(l1c[:, 0], expected_output_timeline) @@ -120,12 +155,12 @@ def test_process_mag_l1c(norm_dataset, burst_dataset): np.count_nonzero([np.sum(l1c[i, 1:4]) for i in range(l1c.shape[0])]) == l1c.shape[0] - 1 ) - expected_flags = np.zeros(15) + expected_flags = np.zeros(17) # filled sections should have 1 as a flag expected_flags[5:8] = 1 - expected_flags[10:11] = 1 + expected_flags[10:13] = 1 # last datapoint in the gap is missing a value - expected_flags[11] = -1 + expected_flags[13] = -1 assert np.array_equal(l1c[:, 5], expected_flags) assert np.array_equal(l1c[:5, 1:5], norm_dataset["vectors"].data[:5, :]) for i in range(5, 8): @@ -138,7 +173,7 @@ def test_process_mag_l1c(norm_dataset, burst_dataset): assert np.allclose(l1c[i, 1:5], burst_vectors, rtol=0, atol=1) assert np.array_equal(l1c[8:10, 1:5], norm_dataset["vectors"].data[5:7, :]) - for i in range(10, 11): + for i in range(10, 13): e = l1c[i, 0] burst_vectors = burst_dataset.sel(epoch=int(e), method="nearest")[ "vectors" @@ -147,14 +182,15 @@ def test_process_mag_l1c(norm_dataset, burst_dataset): # identical. assert np.allclose(l1c[i, 1:5], burst_vectors, rtol=0, atol=1) - assert np.array_equal(l1c[11, 1:5], [0, 0, 0, 0]) + assert np.array_equal(l1c[13, 1:5], [0, 0, 0, 0]) + assert np.array_equal(l1c[14:, 1:5], norm_dataset["vectors"].data[7:, :]) def test_interpolate_gaps(norm_dataset, mag_l1b_dataset): # np.array([0, 0.5, 1, 1.5, 2, 4, 4.25, 5.5, 5.75, 6]) * 1e9 gaps = np.array([[2 * 1e9, 4 * 1e9, 2], [4.25 * 1e9, 5.5 * 1e9, 2]]) generated_timeline = generate_timeline(norm_dataset["epoch"].data, gaps) - norm_timeline = fill_normal_data(norm_dataset, generated_timeline) + norm_timeline: np.ndarray = fill_normal_data(norm_dataset, generated_timeline) gaps = np.array([[2 * 1e9, 4 * 1e9, 2]]) output = interpolate_gaps( mag_l1b_dataset, gaps, norm_timeline, InterpolationFunction.linear @@ -201,8 +237,11 @@ def test_interpolate_gaps(norm_dataset, mag_l1b_dataset): assert np.allclose(output, expected_output) -def test_mag_l1c(norm_dataset, burst_dataset): - l1c = mag_l1c(burst_dataset, norm_dataset) +def test_mag_l1c(): + day = np.datetime64("2025-01-01") + norm_dataset, burst_dataset = _build_day_aligned_mixed_l1b(day) + + l1c = mag_l1c(burst_dataset, day, norm_dataset) assert l1c["vector_magnitude"].shape == (len(l1c["epoch"].data),) assert l1c["vector_magnitude"].data[0] == np.linalg.norm(l1c["vectors"].data[0][:4]) assert l1c["vector_magnitude"].data[-1] == np.linalg.norm( @@ -220,8 +259,11 @@ def test_mag_l1c(norm_dataset, burst_dataset): assert var in l1c.data_vars -def test_mag_attributes(norm_dataset, burst_dataset): - output = mag_l1c(norm_dataset, burst_dataset) +def test_mag_attributes(): + day = np.datetime64("2025-01-01") + norm_dataset, burst_dataset = _build_day_aligned_mixed_l1b(day) + + output = mag_l1c(norm_dataset, day, burst_dataset) assert output.attrs["Logical_source"] == "imap_mag_l1c_norm-mago" expected_attrs = ["missing_sequences", "interpolation_method"] @@ -229,9 +271,196 @@ def test_mag_attributes(norm_dataset, burst_dataset): assert attr in output.attrs +def _ttj2000_day_bounds(day: np.datetime64) -> tuple[int, int]: + day_start = day.astype("datetime64[s]") - np.timedelta64(30, "m") + day_end = ( + day.astype("datetime64[s]") + np.timedelta64(1, "D") + np.timedelta64(30, "m") + ) + return ( + int(et_to_ttj2000ns(str_to_et(str(day_start)))), + int(et_to_ttj2000ns(str_to_et(str(day_end)))), + ) + + +def _build_mag_l1b( + epochs: np.ndarray, logical_source: str, vps_attr: str +) -> xr.Dataset: + dataset = mag_l1a_dataset_generator(len(epochs)) + dataset["epoch"] = xr.DataArray( + epochs.astype(np.int64), name="epoch", dims=["epoch"] + ) + dataset.attrs["Logical_source"] = logical_source + dataset.attrs["vectors_per_second"] = vps_attr + vectors = np.array( + [[i, i, i, 2] for i in range(1, len(epochs) + 1)], dtype=np.float64 + ) + dataset["vectors"].data = vectors + return dataset + + +def _build_day_aligned_mixed_l1b(day: np.datetime64) -> tuple[xr.Dataset, xr.Dataset]: + day_start_ns, _ = _ttj2000_day_bounds(day) + + nm_start = day_start_ns + 300 * 1_000_000_000 + nm_end = nm_start + 120 * 1_000_000_000 + nm_epochs = np.arange(nm_start, nm_end + 1, step=500_000_000, dtype=np.int64) + norm = _build_mag_l1b(nm_epochs, "imap_mag_l1b_norm-mago", "0:2") + + burst_epochs = np.arange( + day_start_ns, + day_start_ns + 600 * 1_000_000_000 + 1, + step=125_000_000, + dtype=np.int64, + ) + burst = _build_mag_l1b(burst_epochs, "imap_mag_l1b_burst-mago", "0:8") + + return norm, burst + + +def test_process_mag_l1c_leading_burst_only_coverage(): + """Burst coverage before the NM window must be interpolated as BURST. + + Regression for issue 2925: with both norm and burst L1B inputs present, the + previous code forced ``day_to_process`` to None, so ``find_all_gaps`` did not + emit a leading day-boundary gap and burst samples preceding the NM file were + silently dropped. + """ + day = np.datetime64("2025-01-01") + day_start_ns, _ = _ttj2000_day_bounds(day) + + # NM starts 5 minutes into the day window and lasts 2 minutes at 2 vec/s. + nm_start = day_start_ns + 300 * 1_000_000_000 + nm_end = nm_start + 120 * 1_000_000_000 + nm_epochs = np.arange(nm_start, nm_end + 1, step=500_000_000, dtype=np.int64) + norm = _build_mag_l1b(nm_epochs, "imap_mag_l1b_norm-mago", "0:2") + + # Burst starts after the day window, so uncovered leading timestamps stay missing. + burst_start = day_start_ns + 10 * 1_000_000_000 + + # Burst covers 10 s through 10 minutes into the day at 8 vec/s. + burst_epochs = np.arange( + burst_start, + day_start_ns + 600 * 1_000_000_000 + 1, + step=125_000_000, + dtype=np.int64, + ) + burst = _build_mag_l1b(burst_epochs, "imap_mag_l1b_burst-mago", "0:8") + + result = process_mag_l1c(norm, burst, InterpolationFunction.linear, day) + epochs_out = result[:, 0] + flags = result[:, 5] + + pre_burst_mask = epochs_out < burst_start + assert pre_burst_mask.sum() > 0 + assert np.all(flags[pre_burst_mask] == ModeFlags.MISSING.value) + + leading_burst_mask = ( + (epochs_out >= burst_start) + & (epochs_out < nm_start) + & (flags == ModeFlags.BURST.value) + ) + assert leading_burst_mask.sum() > 0, ( + "leading burst-only coverage was dropped; day_to_process not honored" + ) + + nm_mask = np.isin(epochs_out, nm_epochs) + assert nm_mask.sum() == nm_epochs.size + assert np.all(flags[nm_mask] == ModeFlags.NORM.value) + + +def test_process_mag_l1c_trailing_burst_only_coverage(): + """Burst coverage after the NM window must be interpolated as BURST.""" + day = np.datetime64("2025-01-01") + day_start_ns, day_end_ns = _ttj2000_day_bounds(day) + + # NM sits mid-day, spanning 2 minutes at 2 vec/s. + nm_center = (day_start_ns + day_end_ns) // 2 + nm_start = nm_center - 60 * 1_000_000_000 + nm_end = nm_center + 60 * 1_000_000_000 + nm_epochs = np.arange(nm_start, nm_end + 1, step=500_000_000, dtype=np.int64) + norm = _build_mag_l1b(nm_epochs, "imap_mag_l1b_norm-mago", "0:2") + + # Burst picks up 30 s before NM end and continues 10 minutes past NM end. + burst_epochs = np.arange( + nm_end - 30 * 1_000_000_000, + nm_end + 600 * 1_000_000_000 + 1, + step=125_000_000, + dtype=np.int64, + ) + burst = _build_mag_l1b(burst_epochs, "imap_mag_l1b_burst-mago", "0:8") + + result = process_mag_l1c(norm, burst, InterpolationFunction.linear, day) + epochs_out = result[:, 0] + flags = result[:, 5] + + trailing_burst_mask = (epochs_out > nm_end) & (flags == ModeFlags.BURST.value) + assert trailing_burst_mask.sum() > 0, ( + "trailing burst-only coverage was dropped; day_to_process not honored" + ) + + nm_mask = np.isin(epochs_out, nm_epochs) + assert nm_mask.sum() == nm_epochs.size + assert np.all(flags[nm_mask] == ModeFlags.NORM.value) + + +def test_mag_l1c_mixed_input_uses_day_to_process(): + """Public mag_l1c entry point must honor day_to_process on mixed inputs. + + End-to-end regression that guards the ``day_to_process`` pass-through in + mag_l1c() against re-introduction of the old short-circuit to None. + """ + day = np.datetime64("2025-01-01") + day_start_ns, _ = _ttj2000_day_bounds(day) + + nm_start = day_start_ns + 600 * 1_000_000_000 + nm_end = nm_start + 60 * 1_000_000_000 + nm_epochs = np.arange(nm_start, nm_end + 1, step=500_000_000, dtype=np.int64) + norm = _build_mag_l1b(nm_epochs, "imap_mag_l1b_norm-mago", "0:2") + + burst_epochs = np.arange( + day_start_ns, + day_start_ns + 900 * 1_000_000_000 + 1, + step=125_000_000, + dtype=np.int64, + ) + burst = _build_mag_l1b(burst_epochs, "imap_mag_l1b_burst-mago", "0:8") + + output = mag_l1c(norm, day, burst) + epochs_out = output["epoch"].data + + assert epochs_out[0] < nm_start, ( + "mag_l1c output collapsed to NM window; day_to_process not honored" + ) + assert int((epochs_out < nm_start).sum()) > 0 + + +def test_mag_l1c_burst_only_generates_l1c_output(): + """Burst-only L1C generation still fills the day window from BM data.""" + day = np.datetime64("2025-01-01") + day_start_ns, _ = _ttj2000_day_bounds(day) + + # Burst covers the first 2 minutes of the day window at 8 vec/s. + burst_epochs = np.arange( + day_start_ns, + day_start_ns + 120 * 1_000_000_000 + 1, + step=125_000_000, + dtype=np.int64, + ) + burst = _build_mag_l1b(burst_epochs, "imap_mag_l1b_burst-magi", "0:8") + + output = mag_l1c(burst, day) + epochs_out = output["epoch"].data + + assert output.attrs["Logical_source"] == "imap_mag_l1c_norm-magi" + assert len(epochs_out) > 0 + assert epochs_out.min() >= burst_epochs.min() + assert epochs_out.max() <= burst_epochs.max() + assert np.all(output["generated_flag"].data == ModeFlags.BURST.value) + + def test_missing_burst_file(norm_dataset, burst_dataset): # Should run with only normal mode data or only burst mode data. - output = mag_l1c(norm_dataset, None) + output = mag_l1c(norm_dataset, np.datetime64("2025-01-01")) assert output.attrs["Logical_source"] == "imap_mag_l1c_norm-mago" # Should pass through normal mode data only @@ -239,11 +468,10 @@ def test_missing_burst_file(norm_dataset, burst_dataset): assert np.array_equal(output["epoch"].data, norm_dataset["epoch"].data) -@pytest.mark.xfail(reason="Burst mode only not implemented yet") -def test_missing_norm_file(norm_dataset, burst_dataset): +def test_missing_norm_file(burst_dataset): # Should run with only normal mode data or only burst mode data. burst_dataset.attrs["Logical_source"] = "imap_mag_l1b_burst-magi" - output = mag_l1c(burst_dataset, None) + output = mag_l1c(burst_dataset, np.datetime64("2025-01-01")) assert output.attrs["Logical_source"] == "imap_mag_l1c_norm-magi" # TODO: test that the output is downsampled @@ -251,22 +479,161 @@ def test_missing_norm_file(norm_dataset, burst_dataset): def test_find_all_gaps(): + # Test Case 1: Basic single gap with constant rate epoch_test = generate_test_epoch( 5.5, [VecSec.TWO_VECS_PER_S, VecSec.TWO_VECS_PER_S], 0, [[2, 5]] ) - vectors_per_second = vectors_per_second_from_string("0:2") - output = find_all_gaps(epoch_test, vectors_per_second) expected_gaps = np.array([[2 * 1e9, 5 * 1e9, 2]]) assert np.array_equal(output, expected_gaps) + # Test Case 2: Multiple gaps with rate transitions epoch_test = np.array([0, 0.5, 1, 1.5, 2, 4, 4.25, 4.5, 4.75, 5.5]) * 1e9 vectors_per_second_attr = vectors_per_second_from_string("0:2,4000000000:4") expected_gaps = np.array([[2 * 1e9, 4 * 1e9, 2], [4.75 * 1e9, 5.5 * 1e9, 4]]) output = find_all_gaps(epoch_test, vectors_per_second_attr) assert np.array_equal(output, expected_gaps) + # Test Case 3: No gaps - continuous timeline + continuous_epoch = generate_test_epoch(3, [VecSec.FOUR_VECS_PER_S], 0) + vectors_per_second_continuous = vectors_per_second_from_string("0:4") + output_no_gaps = find_all_gaps(continuous_epoch, vectors_per_second_continuous) + expected_no_gaps = np.zeros((0, 3)) + assert np.array_equal(output_no_gaps, expected_no_gaps) + + # Test Case 4: Multiple rate changes with gaps in each section + epoch_complex = generate_test_epoch( + 6, + [VecSec.TWO_VECS_PER_S, VecSec.FOUR_VECS_PER_S, VecSec.EIGHT_VECS_PER_S], + 0, + [[1, 2], [3.5, 4.5]], + ) + # Rate changes at t=2s and t=4s + vectors_per_second_complex = vectors_per_second_from_string( + "0:2,2000000000:4,4500000000:8" + ) + output_complex = find_all_gaps(epoch_complex, vectors_per_second_complex) + # Should find gaps: [1-2s at 2 vec/s], [3.5-4.5s at 4 vec/s] + expected_complex = np.array([[1 * 1e9, 2 * 1e9, 2], [3.5 * 1e9, 4.5 * 1e9, 4]]) + assert np.array_equal(output_complex, expected_complex) + + # Test Case 5: Gap at the beginning of timeline + epoch_start_gap = np.array([2, 2.5, 3, 3.5, 4]) * 1e9 + vectors_per_second_start = vectors_per_second_from_string("0:2") + output_start_gap = find_all_gaps( + epoch_start_gap, + vectors_per_second_start, + start_of_day_ns=0, + end_of_day_ns=4 * 1e9, + ) + expected_start_gap = np.array([[0 * 1e9, 2 * 1e9, 2]]) + assert np.array_equal(output_start_gap, expected_start_gap) + + # Test Case 7: Very small gap (single missing sample) + epoch_small_gap = np.array([0, 0.5, 1.5, 2, 2.5]) * 1e9 # Missing 1.0s + vectors_per_second_small = vectors_per_second_from_string("0:2") + output_small_gap = find_all_gaps(epoch_small_gap, vectors_per_second_small) + expected_small_gap = np.array([[0.5 * 1e9, 1.5 * 1e9, 2]]) + assert np.array_equal(output_small_gap, expected_small_gap) + + # Test Case 8: Default behavior (None vecsec_dict) - should assume 2 vec/s + epoch_default = generate_test_epoch(3, [VecSec.TWO_VECS_PER_S], 0, [[1, 2]]) + output_default = find_all_gaps(epoch_default, None) + expected_default = np.array([[1 * 1e9, 2 * 1e9, 2]]) + assert np.array_equal(output_default, expected_default) + + # Test Case 9: Multiple consecutive gaps + epoch_multi_gaps = np.array([0, 0.5, 2, 2.5, 4, 4.5]) * 1e9 + vectors_per_second_multi = vectors_per_second_from_string("0:2") + output_multi = find_all_gaps(epoch_multi_gaps, vectors_per_second_multi) + expected_multi = np.array([[0.5 * 1e9, 2 * 1e9, 2], [2.5 * 1e9, 4 * 1e9, 2]]) + assert np.array_equal(output_multi, expected_multi) + + # Test Case 10: Complex rate transition scenario + # Timeline with gaps before, during, and after rate changes + epoch_transition = np.array([0, 0.5, 2.5, 3, 3.25, 4.75, 5]) * 1e9 + # Rate changes from 2 vec/s to 4 vec/s at t=3s + vectors_per_second_transition = vectors_per_second_from_string("0:2,3000000000:4") + output_transition = find_all_gaps(epoch_transition, vectors_per_second_transition) + expected_transition = np.array( + [[0.5 * 1e9, 2.5 * 1e9, 2], [3.25 * 1e9, 4.75 * 1e9, 4]] + ) + assert np.array_equal(output_transition, expected_transition) + + # Test Case 11: Empty timeline + epoch_empty = np.array([]) + vectors_per_second_empty = vectors_per_second_from_string("0:2") + output_empty = find_all_gaps(epoch_empty, vectors_per_second_empty) + expected_empty = np.zeros((0, 3)) + assert np.array_equal(output_empty, expected_empty) + + # Test Case 12: Start and end of day gaps + epoch_partial_day = np.array([2, 2.5, 3, 3.5, 4]) * 1e9 + start_of_day_ns = 0 * 1e9 # Day starts at 0 + end_of_day_ns = 6 * 1e9 # Day ends at 6s + vectors_per_second_day = vectors_per_second_from_string("0:2") + output_day_gaps = find_all_gaps( + epoch_partial_day, vectors_per_second_day, start_of_day_ns, end_of_day_ns + ) + # Should find gaps at beginning (0-2s) and end (4-6s) + expected_day_gaps = np.array([[0 * 1e9, 2 * 1e9, 2], [4 * 1e9, 6 * 1e9, 2]]) + assert np.array_equal(output_day_gaps, expected_day_gaps) + + # Test Case 13: Timeline covers full day (no start/end gaps) + epoch_full_day = np.array([0, 0.5, 1, 1.5, 2, 2.5, 3]) * 1e9 + output_full_day = find_all_gaps( + epoch_full_day, vectors_per_second_from_string("0:2"), 0 * 1e9, 3 * 1e9 + ) + expected_full_day = np.zeros((0, 3)) # No gaps + assert np.array_equal(output_full_day, expected_full_day) + + # Test Case 14: Single timestamp timeline + epoch_single = np.array([1.5]) * 1e9 + vectors_per_second_single = vectors_per_second_from_string("0:2") + output_single = find_all_gaps( + epoch_single, + vectors_per_second_single, + start_of_day_ns=0, + end_of_day_ns=2.5 * 1e9, + ) + # Should find gap from previous expected timestamp to next + expected_single = np.array([[0, 1.5 * 1e9, 2], [1.5 * 1e9, 2.5 * 1e9, 2]]) + assert np.array_equal(output_single, expected_single) + + # Test Case 15: Rate transition at exact gap boundary + epoch_boundary = np.array([0, 0.5, 1, 1.5, 3, 3.25, 3.5, 3.75]) * 1e9 + # Rate changes from 2 to 4 vec/s exactly at the gap start (t=1.5s) + vectors_per_second_boundary = vectors_per_second_from_string("0:2,1500000000:4") + output_boundary = find_all_gaps(epoch_boundary, vectors_per_second_boundary) + # Gap should be detected with rate=4 + expected_boundary = np.array([[1.5 * 1e9, 3 * 1e9, 4]]) + assert np.array_equal(output_boundary, expected_boundary) + + # Test Case 18: Non-uniform timestamps within tolerance + # Test the 7.5% tolerance mentioned in find_gaps function + epoch_tolerance = np.array([0, 0.46, 0.93, 1.39, 1.86]) * 1e9 # ~6% deviation + vectors_per_second_tolerance = vectors_per_second_from_string("0:2") + output_tolerance = find_all_gaps(epoch_tolerance, vectors_per_second_tolerance) + expected_tolerance = np.zeros((0, 3)) # Should not detect gaps due to tolerance + assert np.array_equal(output_tolerance, expected_tolerance) + + # Test Case 19: Multiple rate sections without gaps + epoch_no_gaps_multi_rate = generate_test_epoch( + 4, [VecSec.TWO_VECS_PER_S, VecSec.FOUR_VECS_PER_S], 0, [] + ) + epoch_no_gaps_multi_rate = np.array( + [0.0, 0.5 * 1e9, 1 * 1e9, 1.5 * 1e9, 2 * 1e9, 2.25 * 1e9, 2.5 * 1e9, 2.75 * 1e9] + ) + vectors_per_second_multi_no_gaps = vectors_per_second_from_string( + "0:2,2000000000:4" + ) + output_no_gaps_multi = find_all_gaps( + epoch_no_gaps_multi_rate, vectors_per_second_multi_no_gaps + ) + expected_no_gaps_multi = np.zeros((0, 3)) + assert np.array_equal(output_no_gaps_multi, expected_no_gaps_multi) + def test_find_gaps(): # Test should be in ns @@ -295,6 +662,26 @@ def test_find_gaps(): assert np.array_equal(gaps, expected_return) +def test_find_all_gaps_uses_observed_transition_boundary(): + epoch_transition = np.array([0, 0.5, 1, 1.5, 2, 10, 11, 12, 13, 14, 15, 16]) * 1e9 + vectors_per_second_transition = vectors_per_second_from_string("0:2,15000000000:1") + output_transition = find_all_gaps(epoch_transition, vectors_per_second_transition) + expected_transition = np.array([[2 * 1e9, 10 * 1e9, 2]]) + assert np.array_equal(output_transition, expected_transition) + + +def test_generate_missing_timestamps_uses_gap_rate(): + gap = np.array([1_000_000_000, 2_000_000_000, 4], dtype=np.int64) + expected_output = np.array( + [1_000_000_000, 1_250_000_000, 1_500_000_000, 1_750_000_000], dtype=np.int64 + ) + assert np.array_equal(generate_missing_timestamps(gap), expected_output) + + legacy_gap = np.array([1_000_000_000, 2_000_000_000], dtype=np.int64) + legacy_expected = np.array([1_000_000_000, 1_500_000_000], dtype=np.int64) + assert np.array_equal(generate_missing_timestamps(legacy_gap), legacy_expected) + + def test_generate_timeline(): epoch_test = generate_test_epoch( 3, [VecSec.FOUR_VECS_PER_S], gaps=[[0.5, 1], [2, 3]] @@ -320,6 +707,232 @@ def test_generate_timeline(): output = generate_timeline(epoch_test, gaps) assert np.array_equal(output, expected_output) + # Test Case: Gap at beginning of day + # Timeline starts at 2s but day should start at 0s + epoch_beginning_gap = np.array([2, 2.5, 3, 3.5, 4]) * 1e9 + # Gap from 0s to 2s (beginning of day gap) + gaps_beginning = np.array([[0, 2 * 1e9, 2]]) + + output_beginning = generate_timeline(epoch_beginning_gap, gaps_beginning) + expected_beginning = np.array([0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4]) * 1e9 + assert np.array_equal(output_beginning, expected_beginning) + + # Test Case: Gap at end of day + # Timeline ends at 3s but day should end at 5s + epoch_end_gap = np.array([0, 0.5, 1, 1.5, 2, 2.5, 3]) * 1e9 + # Gap from 3s to 5s (end of day gap) + gaps_end = np.array([[3 * 1e9, 5 * 1e9, 2]]) + + output_end = generate_timeline(epoch_end_gap, gaps_end) + # Expected: 0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5 + expected_end = np.array([0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5]) * 1e9 + assert np.array_equal(output_end, expected_end) + + # Test Case: Both beginning and end of day gaps + epoch_middle_only = np.array([2, 2.5, 3]) * 1e9 + # Gaps at beginning (0-2s) and end (3-5s) + gaps_both_ends = np.array([[0, 2 * 1e9, 2], [3 * 1e9, 5 * 1e9, 2]]) + + output_both = generate_timeline(epoch_middle_only, gaps_both_ends) + # Expected: 0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5 + expected_both = np.array([0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5]) * 1e9 + assert np.array_equal(output_both, expected_both) + + # Test Case: Adjacent gaps that cause sorting issues (reproduces validation bug) + epoch_edge = np.array([0, 0.5, 1, 2, 3, 3.5, 4]) * 1e9 + gaps = find_all_gaps(epoch_edge, vectors_per_second_from_string("0:2")) + gaps_edge = np.array([[1 * 1e9, 2 * 1e9, 2], [2 * 1e9, 3 * 1e9, 2]]) # Adjacent + + # This test case reproduces the sorting bug from the validation test + # The function should work but currently fails due to sorting issue + output_edge = generate_timeline(epoch_edge, gaps_edge) + + # Expected result: properly sorted timeline with gap fills + expected_edge = np.array([0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4]) * 1e9 + assert np.array_equal(output_edge, expected_edge) + + # Test Case: Gap fill uses the gap rate instead of a fixed 0.5 second cadence + epoch_rate_gap = np.array([0, 0.25, 0.5, 0.75, 1, 4, 4.25, 4.5]) * 1e9 + gaps_rate_gap = np.array([[1_000_000_000, 4_000_000_000, 4]]) + output_rate_gap = generate_timeline(epoch_rate_gap, gaps_rate_gap) + expected_rate_gap = ( + np.array( + [ + 0, + 0.25, + 0.5, + 0.75, + 1, + 1.25, + 1.5, + 1.75, + 2, + 2.25, + 2.5, + 2.75, + 3, + 3.25, + 3.5, + 3.75, + 4, + 4.25, + 4.5, + ] + ) + * 1e9 + ) + assert np.array_equal(output_rate_gap, expected_rate_gap) + + # Test Case: Adjacent gaps share a real epoch boundary at gap[0]. + # generate_timeline() should not duplicate that boundary timestamp: + # np.arange() is end-exclusive for each generated segment, and the + # epoch-copy/final-append logic preserves the real boundary sample once. + epoch_adj = np.array([0, 0.5, 1, 2, 3, 3.5, 4]) * 1e9 + gaps_adj = np.array([[1e9, 2e9, 2], [2e9, 3e9, 4]]) + output_adj = generate_timeline(epoch_adj, gaps_adj) + expected_adj = np.array([0, 0.5, 1, 1.5, 2, 2.25, 2.5, 2.75, 3, 3.5, 4]) * 1e9 + assert np.array_equal(output_adj, expected_adj) + assert len(output_adj) == len(np.unique(output_adj)) + + +def test_gap_detection_timeline_generation_workflow(): + # Create a test dataset with gaps + # Timeline: 0, 0.5, 1, 1.5, [gap 2-4], 4, 4.5, 5, [gap 5.5-6.5], 6.5, 7 + original_epoch = np.array([0, 0.5, 1, 1.5, 4, 4.5, 5, 6.5, 7]) * 1e9 + + # Create a test normal mode dataset + dataset = mag_l1a_dataset_generator(len(original_epoch)) + dataset["epoch"] = xr.DataArray(original_epoch, name="epoch", dims=["epoch"]) + + # Set vectors to identifiable values for testing + vectors = np.array([[i, i + 1, i + 2, i + 3] for i in range(len(original_epoch))]) + dataset["vectors"].data = vectors + + # Set compression flags + compression_flags = np.array([[0, 0] for _ in range(len(original_epoch))]) + dataset["compression_flags"].data = compression_flags + + # Set vectors_per_second attribute (constant 2 vec/s) + dataset.attrs["vectors_per_second"] = "0:2" + + # Step 1: Find gaps in the timeline + normal_vecsec_dict = vectors_per_second_from_string( + dataset.attrs["vectors_per_second"] + ) + gaps = find_all_gaps(original_epoch, normal_vecsec_dict) + + # Verify gaps were found correctly + expected_gaps = np.array( + [ + [1.5 * 1e9, 4 * 1e9, 2], # Gap from 1.5s to 4s at 2 vec/s + [5 * 1e9, 6.5 * 1e9, 2], # Gap from 5s to 6.5s at 2 vec/s + ] + ) + assert np.array_equal(gaps, expected_gaps) + # Step 2: Generate new timeline with gaps filled + new_timeline = generate_timeline(original_epoch, gaps) + + # Verify new timeline includes original data plus gap-filling timestamps + expected_timeline = ( + np.array( + [ + 0, + 0.5, + 1, + 1.5, # Original data before first gap + 2, + 2.5, + 3, + 3.5, + 4, # Gap fill: 1.5-4s at 0.5s intervals + 4.5, + 5, # Original data between gaps + 5.5, + 6, + 6.5, # Gap fill: 5-6.5s at 0.5s intervals + 7, # Original data after last gap + ] + ) + * 1e9 + ) + + assert np.array_equal(new_timeline, expected_timeline), ( + f"Expected timeline {expected_timeline}, got {new_timeline}" + ) + + # Step 3: Fill the new timeline with normal mode data + norm_filled: np.ndarray = fill_normal_data(dataset, new_timeline) + print(norm_filled) + # Verify output shape: (n_timestamps, 8) where 8 = [epoch, x, y, z, range, flag, + # comp1, comp2] + expected_shape = (len(new_timeline), 8) + assert norm_filled.shape == expected_shape, ( + f"Expected shape {expected_shape}, got {norm_filled.shape}" + ) + + # Verify timestamps match new_timeline + assert np.array_equal(norm_filled[:, 0], new_timeline), ( + "Timeline column should match new_timeline" + ) + + # Verify original data points are correctly filled + original_indices = [0, 1, 2, 3, 8, 9, 10, 13, 14] # Indices of original data in + # new timeline + for i, orig_idx in enumerate(original_indices): + # Check vector data (columns 1-4) + expected_vector = vectors[i] + actual_vector = norm_filled[orig_idx, 1:5] + assert np.array_equal(actual_vector, expected_vector) + + # Check flag is set to NORM (0) + assert norm_filled[orig_idx, 5] == ModeFlags.NORM.value + + # Check compression flags (columns 6-7) + expected_compression = compression_flags[i] + actual_compression = norm_filled[orig_idx, 6:8] + assert np.array_equal(actual_compression, expected_compression) + + # Verify gap timestamps are marked as missing + gap_indices = [4, 5, 6, 7, 11, 12] # Indices of gap-fill timestamps in new timeline + for gap_idx in gap_indices: + # Check vectors are zero (no data filled yet) + assert np.all(norm_filled[gap_idx, 1:5] == 0), ( + f"Gap timestamp {gap_idx} should have zero vectors" + ) + + # Check flag is set to MISSING (-1) + assert norm_filled[gap_idx, 5] == ModeFlags.MISSING.value, ( + f"Gap timestamp {gap_idx} should have MISSING flag" + ) + + # Check compression flags are zero + assert np.all(norm_filled[gap_idx, 6:8] == 0), ( + f"Gap timestamp {gap_idx} should have zero compression flags" + ) + + # Test with multiple vector rates + # Create dataset with rate transition at t=3s + dataset_multi_rate = dataset.copy(deep=True) + dataset_multi_rate.attrs["vectors_per_second"] = "0:2,3000000000:4" + + # Find gaps with multiple rates + multi_rate_vecsec_dict = vectors_per_second_from_string( + dataset_multi_rate.attrs["vectors_per_second"] + ) + gaps_multi_rate = find_all_gaps(original_epoch, multi_rate_vecsec_dict) + + # Generate timeline and fill data + new_timeline_multi = generate_timeline(original_epoch, gaps_multi_rate) + norm_filled_multi: np.ndarray = fill_normal_data( + dataset_multi_rate, new_timeline_multi + ) + + # Verify the workflow completes successfully with multiple rates + assert norm_filled_multi.shape[1] == 8, "Multi-rate output should have 8 columns" + assert len(norm_filled_multi) >= len(original_epoch), ( + "Multi-rate output should include all original data" + ) + def test_fill_normal_data(mag_l1b_dataset): output_timeline = np.arange(0.1, 6.1, step=0.5) * 1e9 @@ -338,6 +951,14 @@ def test_fill_normal_data(mag_l1b_dataset): def test_cic_filter(): + """ + Comprehensive test of CIC filter implementation according to algorithm document. + + Tests decimation factor calculation, delay compensation, filter coefficients, + and proper array length handling for different input/output rate combinations. + """ + + # Test Case 1: Basic 4:2 decimation (decimation_factor = 2) input_vectors = np.array( [ [1, 1, 1], @@ -348,20 +969,137 @@ def test_cic_filter(): [6, 6, 6], [7, 7, 7], [8, 8, 8], + [9, 9, 9], ] ) input_timestamps = generate_test_epoch(2, [VecSec.FOUR_VECS_PER_S], 0) output_timestamps = generate_test_epoch(2, [VecSec.TWO_VECS_PER_S], 0) + timestamps_filtered, vectors_filtered = cic_filter( + input_vectors, + input_timestamps, + output_timestamps, + VecSec.FOUR_VECS_PER_S, + VecSec.TWO_VECS_PER_S, + ) + + # Basic output validation + assert len(vectors_filtered) != 0 + assert len(timestamps_filtered) != 0 + assert len(timestamps_filtered) == len(vectors_filtered) + + # Test Case 2: Verify decimation factor calculation and delay + # For 4:2 ratio, decimation_factor = 2, delay = (3-1)//2 = 1 + expected_delay = 1 + expected_filtered_length = len(input_vectors) - expected_delay + assert len(vectors_filtered) == expected_filtered_length + assert len(timestamps_filtered) == expected_filtered_length + + # Test Case 3: Higher decimation ratio (8:2 = 4x decimation) + input_vectors_8hz = np.array( + [ + [1, 1, 1], + [2, 2, 2], + [3, 3, 3], + [4, 4, 4], + [5, 5, 5], + [6, 6, 6], + [7, 7, 7], + [8, 8, 8], + [9, 9, 9], + [10, 10, 10], + [11, 11, 11], + [12, 12, 12], + [13, 13, 13], + [14, 14, 14], + [15, 15, 15], + [16, 16, 16], + [17, 17, 17], + ] + ) + input_timestamps_8hz = generate_test_epoch(2, [VecSec.EIGHT_VECS_PER_S], 0) + output_timestamps_2hz = generate_test_epoch(2, [VecSec.TWO_VECS_PER_S], 0) + + timestamps_filtered_8hz, vectors_filtered_8hz = cic_filter( + input_vectors_8hz, + input_timestamps_8hz, + output_timestamps_2hz, + VecSec.EIGHT_VECS_PER_S, + VecSec.TWO_VECS_PER_S, + ) + + # For 8:2 ratio, decimation_factor = 4, delay = (7-1)//2 = 3 + expected_delay_8hz = 3 + expected_filtered_length_8hz = len(input_vectors_8hz) - expected_delay_8hz + assert len(vectors_filtered_8hz) == expected_filtered_length_8hz + assert len(timestamps_filtered_8hz) == expected_filtered_length_8hz + + # Test Case 4: Test rate validation + with pytest.raises( + ValueError, match="Burst mode input rate.*should never be less than" + ): + cic_filter( + input_vectors, + input_timestamps, + output_timestamps, + VecSec.TWO_VECS_PER_S, # Lower input rate + VecSec.FOUR_VECS_PER_S, # Higher output rate + ) - output = cic_filter( + # Test Case 5: Test automatic rate estimation when rates are None + timestamps_filtered_auto, vectors_filtered_auto = cic_filter( input_vectors, input_timestamps, output_timestamps, + None, # Should estimate as 4 vecs/sec + None, # Should estimate as 2 vecs/sec + ) + + assert len(timestamps_filtered_auto) == len(vectors_filtered_auto) + assert len(vectors_filtered_auto) > 0 + + # Test Case 6: Test filter smoothing effect + # Create a simple step function input to verify filter smoothing + step_input = np.array( + [ + [0, 0, 0], + [0, 0, 0], + [0, 0, 0], + [0, 0, 0], + [10, 10, 10], + [10, 10, 10], + [10, 10, 10], + [10, 10, 10], + ] + ) + + timestamps_step, vectors_step = cic_filter( + step_input, + input_timestamps, + output_timestamps, VecSec.FOUR_VECS_PER_S, VecSec.TWO_VECS_PER_S, ) - assert len(output) != 0 - # TODO: How to test this? + + # CIC filter should smooth the step transition + # The filtered output should have intermediate values, not just 0s and 10s + unique_values = np.unique(vectors_step[:, 0]) + assert len(unique_values) > 2, "CIC filter should create intermediate values" + + # Test Case 7: Test vector shape preservation (should work with 3-component vectors) + assert vectors_filtered.shape[1] == 3, "Output vectors should maintain 3 components" + assert vectors_filtered_8hz.shape[1] == 3, ( + "Output vectors should maintain 3 components" + ) + + # Test Case 8: Test delay compensation consistency + # The delay should be consistently applied to both timestamps and vectors + if len(timestamps_filtered) > 1: + # Verify that timestamps are properly aligned with filtered vectors + original_timestamp_spacing = input_timestamps[1] - input_timestamps[0] + filtered_timestamp_spacing = timestamps_filtered[1] - timestamps_filtered[0] + assert filtered_timestamp_spacing == original_timestamp_spacing, ( + "Timestamp spacing should be preserved after filtering" + ) def test_estimate_rate(): @@ -373,3 +1111,39 @@ def test_estimate_rate(): output = estimate_rate(output_timestamps) assert output == VecSec.TWO_VECS_PER_S + + +def test_cic_filter_delay_compensation(): + # test that extra values are removed from CIC filter properly. + + input_vectors_case2 = np.array( + [ + [1, 1, 1], + [2, 2, 2], + [3, 3, 3], + [4, 4, 4], + [5, 5, 5], + [6, 6, 6], + [7, 7, 7], + [8, 8, 8], + [9, 9, 9], + ] + ) + input_timestamps_case2 = generate_test_epoch(2, [VecSec.FOUR_VECS_PER_S], 0) + + output_timestamps_case2 = generate_test_epoch(2, [VecSec.TWO_VECS_PER_S], 0) + + input_filtered_case2, vectors_filtered_case2 = cic_filter( + input_vectors_case2, + input_timestamps_case2, + output_timestamps_case2, + VecSec.FOUR_VECS_PER_S, + VecSec.TWO_VECS_PER_S, + ) + + # Arrays should still have matching lengths when delay > 0 + assert len(input_filtered_case2) == len(vectors_filtered_case2), ( + f"Array length mismatch in delay>0 case: input_filtered has " + f"{len(input_filtered_case2)} elements, vectors_filtered has " + f"{len(vectors_filtered_case2)} elements" + ) diff --git a/imap_processing/tests/mag/test_mag_l1d.py b/imap_processing/tests/mag/test_mag_l1d.py index bc9a66b5a5..2ebe5efe76 100644 --- a/imap_processing/tests/mag/test_mag_l1d.py +++ b/imap_processing/tests/mag/test_mag_l1d.py @@ -1,11 +1,15 @@ +import logging from unittest.mock import patch import numpy as np import pytest import xarray as xr +from imap_data_access.processing_input import ProcessingInputCollection from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes -from imap_processing.mag.constants import DataMode +from imap_processing.cdf.utils import write_cdf +from imap_processing.cli import Mag +from imap_processing.mag.constants import FILLVAL, DataMode from imap_processing.mag.l1d.mag_l1d import mag_l1d from imap_processing.mag.l1d.mag_l1d_data import MagL1d, MagL1dConfiguration from imap_processing.mag.l2.mag_l2_data import ValidFrames @@ -91,16 +95,131 @@ def test_mag_l1d(mag_test_l1d_data, norm_dataset, furnish_kernels, fake_mag_spin ) # Should have: 4 norm frames + 4 burst frames + spin offsets + 2 gradiometry offsets + frame = l1d[0].attrs["Logical_source"].split("-")[-1].lower() assert len(l1d) == 11 - assert "vectors" in l1d[0].data_vars + assert f"b_{frame}" in l1d[0].data_vars # Check that expected logical sources are present logical_sources = [ds.attrs.get("Logical_source", "") for ds in l1d] # Should include ancillary files - assert "imap_mag_l1d-spin-offsets" in logical_sources - assert "imap_mag_l1d-gradiometry-offsets-norm" in logical_sources - assert "imap_mag_l1d-gradiometry-offsets-burst" in logical_sources + assert "imap_mag_l1d_spin-offsets" in logical_sources + assert "imap_mag_l1d_gradiometry-offsets-norm" in logical_sources + assert "imap_mag_l1d_gradiometry-offsets-burst" in logical_sources + + +@pytest.mark.parametrize("data_mode", ["norm", "burst"]) +def test_mag_l1d_attributes( + mag_test_l1d_data, + norm_dataset, + furnish_kernels, + fake_mag_spin_data, + data_mode, +): + """Test that L1D datasets have correct attributes based on frame and mode.""" + # L1D always requires normal mode MAGO and MAGI datasets + norm_mago = norm_dataset.copy() + norm_mago.attrs["Logical_source"] = "imap_mag_l1c_norm-mago" + + norm_magi = norm_dataset.copy() + norm_magi.attrs["Logical_source"] = "imap_mag_l1c_norm-magi" + + input_datasets = [norm_mago, norm_magi] + + # If testing burst mode, add burst datasets as well + if data_mode == "burst": + burst_mago = norm_dataset.copy() + burst_mago.attrs["Logical_source"] = "imap_mag_l1c_burst-mago" + + burst_magi = norm_dataset.copy() + burst_magi.attrs["Logical_source"] = "imap_mag_l1c_burst-magi" + + input_datasets.extend([burst_mago, burst_magi]) + + with ( + patch( + "imap_processing.mag.l1d.mag_l1d_data.frame_transform", + side_effect=lambda *args, **kwargs: args[1], + ), + patch( + "imap_processing.mag.l2.mag_l2_data.frame_transform", + side_effect=lambda *args, **kwargs: args[1], + ), + patch( + "imap_processing.mag.l1d.mag_l1d_data.ttj2000ns_to_met", + side_effect=lambda *args, **kwargs: args[0], + ), + ): + l1d_datasets = mag_l1d( + input_datasets, + mag_test_l1d_data, + np.datetime64("2000-01-01"), + ) + + # Filter out ancillary datasets and select only datasets matching the data_mode + science_datasets = [ + ds + for ds in l1d_datasets + if "spin-offsets" not in ds.attrs.get("Logical_source", "") + and "gradiometry-offsets" not in ds.attrs.get("Logical_source", "") + and f"l1d_{data_mode}-" in ds.attrs.get("Logical_source", "") + ] + + # Verify we have the expected number of datasets for the mode + # Each mode produces 4 frames: SRF, DSRF, GSE, RTN + assert len(science_datasets) == 4, ( + f"Expected 4 L1D {data_mode} datasets, got {len(science_datasets)}" + ) + + for dataset in science_datasets: + assert "Logical_source" in dataset.attrs + assert "Data_type" in dataset.attrs + assert dataset.attrs["Logical_source"].startswith(f"imap_mag_l1d_{data_mode}-") + + # Verify that data_level is correctly set to "l1d" in logical source + logical_source_parts = dataset.attrs["Logical_source"].split("_") + assert logical_source_parts[2] == "l1d", ( + f"Expected data_level 'l1d' in Logical_source, " + f"got '{logical_source_parts[2]}'" + ) + + frame = dataset.attrs["Logical_source"].split("-")[-1].upper() + + vectors_attrs = dataset[f"b_{frame.lower()}"].attrs + assert "DICT_KEY" in vectors_attrs + + assert f"CoordinateSystemName:{frame}" in vectors_attrs["DICT_KEY"] + + assert "magnitude" in dataset.data_vars + assert "range" in dataset.data_vars + assert dataset["magnitude"].attrs["UNITS"] == "nT" + assert dataset["range"].attrs["DICT_KEY"] == ( + "SPASE>Support>SupportQuantity:InstrumentMode" + ) + + # Test that write_cdf can be called on all datasets + with patch("imap_processing.cdf.utils.xarray_to_cdf") as mock_xarray_to_cdf: + for dataset in l1d_datasets: + write_cdf(dataset) + + # Verify xarray_to_cdf was called for each dataset + assert mock_xarray_to_cdf.call_count == len(l1d_datasets) + + # Test that Mag.post_processing can be called on the datasets + mag_processor = Mag( + data_level="l1d", + data_descriptor="all", + dependency_str="[]", + start_date="20000101", + repointing=None, + version="v001", + upload_to_sdc=False, + ) + + mock_dependencies = ProcessingInputCollection() + + with patch("imap_processing.cdf.utils.xarray_to_cdf"): + mag_processor.post_processing(l1d_datasets, mock_dependencies) def test_offset_vector(): @@ -113,7 +232,7 @@ def test_offset_vector(): ) test_vector = np.array([1, 2, 3, 3]) - expected_vector = [-3, -2, -1, 3] + expected_vector = [5, 6, 7, 3] output_vector = MagL1d.apply_calibration_offset_single_vector( test_vector, offsets, False ) @@ -121,7 +240,7 @@ def test_offset_vector(): assert np.array_equal(expected_vector, output_vector) test_vector = np.array([1, 2, 3, 0]) - expected_vector = [2, 3, 4, 0] + expected_vector = [0, 1, 2, 0] output_vector = MagL1d.apply_calibration_offset_single_vector( test_vector, offsets, True ) @@ -142,8 +261,8 @@ def test_calculate_spin_offsets( kernels = [ "naif0012.tls", "imap_sclk_0000.tsc", - "imap_wkcp.tf", - "imap_science_100.tf", + "imap_130.tf", + "imap_science_120.tf", "sim_1yr_imap_attitude.bc", "sim_1yr_imap_pointing_frame.bc", ] @@ -173,6 +292,39 @@ def test_calculate_spin_offsets( np.testing.assert_allclose(offsets["y_offset"].data, expected_y_avg) +def test_calculate_spin_offsets_empty_chunk(mag_l1d_test_class, caplog): + # 166 points with 15-sample spin period produces 11 spin_starts. + # With spin_count_calibration=2, the last chunk (index 10) contains only + # one spin_start, making chunk_epoch empty and triggering the warning path. + n = 166 + mag_l1d_test_class.vectors = np.ones((n, 3)) + mag_l1d_test_class.epoch = np.arange(n, dtype=np.float64) * 1e9 + mag_l1d_test_class.frame = ValidFrames.SRF + mag_l1d_test_class.config.spin_count_calibration = 2 + + phase = (np.arange(n) % 15) / 15.0 + + with ( + patch( + "imap_processing.mag.l1d.mag_l1d_data.ttj2000ns_to_met", + side_effect=lambda *args, **kwargs: args[0] / 1e9, + ), + patch( + "imap_processing.mag.l1d.mag_l1d_data.spin.get_spacecraft_spin_phase", + return_value=phase, + ), + patch( + "imap_processing.mag.l1d.mag_l1d_data.spin.get_spin_data", + return_value={"spin_period_sec": np.array([15.0])}, + ), + caplog.at_level(logging.WARNING), + ): + offsets = mag_l1d_test_class.calculate_spin_offsets() + + assert "Skipping empty chunk" in caplog.text + assert len(offsets["epoch"]) == 5 + + def test_apply_spin_offsets(mag_l1d_test_class, fake_mag_spin_data, furnish_kernels): vectors = np.zeros((155, 3)) epoch = np.arange(155) @@ -365,7 +517,7 @@ def test_mago_magi_swap_functionality(mag_l1d_test_class): assert np.array_equal(mag_l1d_test_class.vectors, mago_vectors) assert np.array_equal(mag_l1d_test_class.epoch, mago_epoch) - assert np.array_equal(result["vectors"].data, magi_vectors) + assert np.array_equal(result[mag_l1d_test_class.frame.var_name].data, magi_vectors) assert np.array_equal(result["epoch"].data, magi_epoch) @@ -392,7 +544,7 @@ def test_mago_magi_no_swap_functionality(mag_l1d_test_class): assert np.array_equal(mag_l1d_test_class.vectors, mago_vectors) assert np.array_equal(mag_l1d_test_class.epoch, mago_epoch) - assert np.array_equal(result["vectors"].data, mago_vectors) + assert np.array_equal(result[mag_l1d_test_class.frame.var_name].data, mago_vectors) assert np.array_equal(result["epoch"].data, mago_epoch) @@ -451,3 +603,106 @@ def test_enhanced_gradiometry_with_quality_flags_detailed(): grad_ds["gradiometer_offset_magnitude"].data, expected_magnitudes, rtol=1e-10 ) assert np.array_equal(grad_ds["quality_flags"].data, expected_flags) + + +def test_rotate_frame_preserves_fillval_and_nan(mag_l1d_test_class): + """Test that L1D rotate_frame preserves FILLVAL and NaN vectors.""" + mag_l1d_test_class.frame = ValidFrames.MAGO + + vectors = mag_l1d_test_class.vectors.copy() + magi_vectors = mag_l1d_test_class.magi_vectors.copy() + + # Set some MAGO vectors to FILLVAL and NaN + vectors[0] = [FILLVAL, FILLVAL, FILLVAL] + vectors[2] = [np.nan, np.nan, np.nan] + vectors[4] = [1.0, np.nan, 3.0] + mag_l1d_test_class.vectors = vectors + + # Set some MAGI vectors to FILLVAL and NaN + magi_vectors[1] = [FILLVAL, FILLVAL, FILLVAL] + magi_vectors[3] = [np.nan, np.nan, np.nan] + mag_l1d_test_class.magi_vectors = magi_vectors + + def mock_frame_transform( + epoch_et, + vecs, + from_frame, + to_frame, + allow_spice_noframeconnect, + ): + return np.full(vecs.shape, 99.0) + + with patch( + "imap_processing.mag.l1d.mag_l1d_data.frame_transform", + side_effect=mock_frame_transform, + ): + mag_l1d_test_class.rotate_frame(ValidFrames.SRF) + + assert mag_l1d_test_class.frame == ValidFrames.SRF + + # MAGO: FILLVAL/NaN rows preserved as FILLVAL + assert np.all(mag_l1d_test_class.vectors[0] == FILLVAL) + assert np.all(mag_l1d_test_class.vectors[2] == FILLVAL) + assert mag_l1d_test_class.vectors[4, 1] == FILLVAL + # Normal MAGO vectors get rotated value + assert np.all(mag_l1d_test_class.vectors[1] == 99.0) + assert np.all(mag_l1d_test_class.vectors[3] == 99.0) + + # MAGI: FILLVAL/NaN rows preserved as FILLVAL + assert np.all(mag_l1d_test_class.magi_vectors[1] == FILLVAL) + assert np.all(mag_l1d_test_class.magi_vectors[3] == FILLVAL) + # Normal MAGI vectors get rotated value + assert np.all(mag_l1d_test_class.magi_vectors[0] == 99.0) + assert np.all(mag_l1d_test_class.magi_vectors[2] == 99.0) + + +def test_rotate_frames(mag_l1d_test_class): + # Reset to initial MAGO frame for this test + mag_l1d_test_class.frame = ValidFrames.MAGO + + initial_vectors = mag_l1d_test_class.vectors.copy() + initial_magi_vectors = mag_l1d_test_class.magi_vectors.copy() + + # Mock frame_transform to return identifiable transformed vectors + def mock_frame_transform( + epoch_et, vectors, from_frame, to_frame, allow_spice_noframeconnect + ): + if from_frame in [ValidFrames.MAGO.spice_frame, ValidFrames.MAGI.spice_frame]: + return vectors + 100 + else: + return vectors + 300 + + with patch( + "imap_processing.mag.l1d.mag_l1d_data.frame_transform", + side_effect=mock_frame_transform, + ) as mock_transform_l1d: + target_frame = ValidFrames.SRF + mag_l1d_test_class.rotate_frame(target_frame) + + # Verify frame_transform was called twice (once for MAGO, once for MAGI) + assert mock_transform_l1d.call_count == 2 + + # First call should be for MAGO vectors + first_call_args = mock_transform_l1d.call_args_list[0] + assert first_call_args[1]["from_frame"] == ValidFrames.MAGO.spice_frame + assert first_call_args[1]["to_frame"] == ValidFrames.SRF.spice_frame + + # Second call should be for MAGI vectors + second_call_args = mock_transform_l1d.call_args_list[1] + assert second_call_args[1]["from_frame"] == ValidFrames.MAGI.spice_frame + assert second_call_args[1]["to_frame"] == ValidFrames.SRF.spice_frame + + # MAGO frame and MAGi frame not necessarily different (and are now the same) + + # Check that MAGO vectors were transformed (+100) + expected_mago_vectors = initial_vectors + 100 + np.testing.assert_array_equal(mag_l1d_test_class.vectors, expected_mago_vectors) + + # Check that MAGI vectors were transformed (+100) + expected_magi_vectors = initial_magi_vectors + 100 + np.testing.assert_array_equal( + mag_l1d_test_class.magi_vectors, expected_magi_vectors + ) + + # Check that frame was updated + assert mag_l1d_test_class.frame == ValidFrames.SRF diff --git a/imap_processing/tests/mag/test_mag_l2.py b/imap_processing/tests/mag/test_mag_l2.py index 0612849bf9..12f26ffd12 100644 --- a/imap_processing/tests/mag/test_mag_l2.py +++ b/imap_processing/tests/mag/test_mag_l2.py @@ -5,7 +5,7 @@ import xarray as xr from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes -from imap_processing.mag.constants import DataMode +from imap_processing.mag.constants import FILLVAL, DataMode from imap_processing.mag.l2.mag_l2 import mag_l2, retrieve_matrix_from_l2_calibration from imap_processing.mag.l2.mag_l2_data import MagL2, ValidFrames from imap_processing.spice.time import ( @@ -18,6 +18,98 @@ from imap_processing.tests.mag.conftest import mag_l1a_dataset_generator +@pytest.mark.parametrize( + "data_mode,frames,expected_frames", + [ + ( + "norm", + [ + ValidFrames.SRF, + ValidFrames.GSE, + ValidFrames.GSM, + ValidFrames.RTN, + ValidFrames.DSRF, + ], + 5, + ), + ("norm", [], 5), + ("burst", [ValidFrames.SRF], 1), + ("burst", [], 5), + ], +) +def test_mag_l2_attributes( + norm_dataset, mag_test_l2_data, data_mode, frames, expected_frames +): + """Test that correct L2 datasets have correct attributes based on frame and mode.""" + calibration_dataset = mag_test_l2_data[0] + offset_dataset = mag_test_l2_data[1] + + # Create dataset for the appropriate mode + test_dataset = norm_dataset.copy() + test_dataset.attrs["Logical_source"] = f"imap_mag_l1c_{data_mode}-mago" + + # Convert data_mode string to DataMode enum + mode = DataMode.NORM if data_mode == "norm" else DataMode.BURST + + with patch( + "imap_processing.mag.l2.mag_l2_data.frame_transform", + side_effect=lambda *args, **kwargs: args[1], + ): + if frames: + # ensure when a subset of frames is needed only those are generated + l2_datasets = mag_l2( + calibration_dataset, + offset_dataset, + test_dataset, + np.datetime64("2025-10-17"), + mode=mode, + frames=frames, + ) + else: + # be default all frames are generated + l2_datasets = mag_l2( + calibration_dataset, + offset_dataset, + test_dataset, + np.datetime64("2025-10-17"), + mode=mode, + ) + + # Verify we have the expected number of datasets + # L2 produces 5 frames: SRF, GSE, GSM, RTN, DSRF + assert len(l2_datasets) == expected_frames, ( + f"Expected {expected_frames} {data_mode} datasets, got {len(l2_datasets)}" + ) + + for dataset in l2_datasets: + assert "Logical_source" in dataset.attrs + assert "Data_type" in dataset.attrs + assert dataset.attrs["Logical_source"].startswith(f"imap_mag_l2_{data_mode}-") + + # Verify that data_level is correctly set to "l2" in logical source + logical_source_parts = dataset.attrs["Logical_source"].split("_") + assert logical_source_parts[2] == "l2", ( + f"Expected data_level 'l2' in Logical_source, " + f"got '{logical_source_parts[2]}'" + ) + + # Extract frame from logical source + frame = dataset.attrs["Logical_source"].split("-")[-1].upper() + + vectors_attrs = dataset[f"b_{frame.lower()}"].attrs + assert "DICT_KEY" in vectors_attrs + + assert f"CoordinateSystemName:{frame}" in vectors_attrs["DICT_KEY"] + + assert "magnitude" in dataset.data_vars + assert "range" in dataset.data_vars + assert dataset["magnitude"].attrs["UNITS"] == "nT" + assert dataset["range"].attrs["DICT_KEY"] == ( + "SPASE>Support>SupportQuantity:InstrumentMode" + ) + assert vectors_attrs["CDF_DATA_TYPE"] == "CDF_FLOAT" + + def test_mag_l2(norm_dataset, mag_test_l2_data): calibration_dataset = mag_test_l2_data[0] @@ -32,7 +124,64 @@ def test_mag_l2(norm_dataset, mag_test_l2_data): norm_dataset, np.datetime64("2025-10-17"), ) - assert "vectors" in l2[0].data_vars + + expected_frames = [ + ValidFrames.SRF, + ValidFrames.GSE, + ValidFrames.GSM, + ValidFrames.RTN, + ValidFrames.DSRF, + ] + + assert len(l2) == len(expected_frames), ( + f"L2 should produce {len(expected_frames)} frames" + ) + + for i, dataset in enumerate(l2): + assert expected_frames[i].var_name in dataset.data_vars + assert expected_frames[i].name in dataset.attrs["Data_type"] + + +def test_mag_l2_some_epochs_not_in_spice(norm_dataset, mag_test_l2_data): + def return_some_nan_matrices_for_dsrf( + et, from_frame, to_frame, allow_spice_noframeconnect + ): + matrices = np.tile(np.eye(3), (len(et), 1, 1)) + if to_frame == ValidFrames.DSRF.spice_frame: + for i in range(10, matrices.shape[0], 10): # every 10th matrix is NaN + matrices[i] = np.full((3, 3), np.nan) + return matrices + + calibration_dataset = mag_test_l2_data[0] + offset_dataset = mag_test_l2_data[1] + + with patch( + "imap_processing.spice.geometry.get_rotation_matrix", + side_effect=return_some_nan_matrices_for_dsrf, + ): + l2 = mag_l2( + calibration_dataset, + offset_dataset, + norm_dataset, + np.datetime64("2025-10-17"), + ) + + assert len(l2) == 5, "L2 should produce 5 frames" + + all_vars = ["b_srf", "b_gse", "b_gsm", "b_rtn", "b_dsrf"] + + for dataset in l2: + assert len(set(all_vars) & set(dataset.data_vars)) == 1, ( + "Each dataset should have one of the expected vector variables" + ) + + assert ( + l2[-1].attrs["Data_type"] == "L2_norm-dsrf>Level 2 normal rate data in DSRF" + ), "Last frame should be DSRF" + + dsrf_vectors = l2[-1]["b_dsrf"].data + for i in range(10, len(dsrf_vectors), 10): + assert np.isnan(dsrf_vectors[i]).all(), f"Vectors at index {i} should be NaN" def test_offset_application(norm_dataset, mag_test_l2_data): @@ -91,7 +240,6 @@ def test_offset_application(norm_dataset, mag_test_l2_data): assert np.allclose(output.epoch, expected_timeshift, atol=1e-9) -@pytest.mark.xfail(reason="Error is too strict during testing") def test_error_raises(mag_test_l2_data): dataset = mag_l1a_dataset_generator(3504) with pytest.raises(ValueError, match="same timestamps"): @@ -156,6 +304,30 @@ def test_midnight_boundary(norm_dataset): assert midnight not in l2.epoch +def test_truncate_to_24h_no_data_raises(norm_dataset): + day = np.datetime64("2025-10-17").astype("datetime64[D]") + + # Shift all timestamps 5 days forward so none fall within the target day + shifted_timestamps = norm_dataset["epoch"].data + int(5 * 8.64e13) + + l2 = MagL2( + vectors=norm_dataset["vectors"].data[:, :3], + epoch=shifted_timestamps, + range=norm_dataset["vectors"].data[:, 3], + global_attributes={}, + quality_flags=np.zeros(len(norm_dataset["epoch"].data)), + quality_bitmask=np.zeros(len(norm_dataset["epoch"].data)), + data_mode=DataMode.NORM, + offsets=np.zeros((len(norm_dataset["epoch"].data), 3)), + timedelta=np.zeros(len(norm_dataset["epoch"].data)), + ) + + with pytest.raises( + ValueError, match="After truncating to 24 hours, no data remains." + ): + l2.truncate_to_24h(day) + + @pytest.mark.parametrize( ("time_shift", "start_diff", "end_diff"), # 3 hours in ns @@ -255,18 +427,6 @@ def test_magnitude(): assert output_magnitude.shape == (10,) -def test_expected_output_norm(norm_dataset): - # should return 4 files with correct attributes - # TODO: complete with L2 attributes - - pass - - -def test_expected_output_burst(): - # should return 4 files with correct attributes - pass - - @pytest.mark.parametrize( ("is_mago", "data_var"), [ @@ -331,7 +491,7 @@ def test_spice_returns(norm_dataset): timedelta=np.zeros(len(norm_dataset["epoch"].data)), ) - assert l2.frame.name == "MAG" + assert l2.frame.name == "MAGO" with patch( "imap_processing.mag.l2.mag_l2_data.frame_transform", @@ -343,6 +503,55 @@ def test_spice_returns(norm_dataset): assert np.array_equal(l2.vectors[0], [-1, -1, -1]) +def test_rotate_frame_preserves_fillval_and_nan(norm_dataset): + """Test that rotate_frame preserves FILLVAL and NaN vectors.""" + + vectors = norm_dataset["vectors"].data[:, :3].copy() + n = len(vectors) + + # Set some vectors to FILLVAL and NaN + vectors[0] = [FILLVAL, FILLVAL, FILLVAL] + vectors[2] = [np.nan, np.nan, np.nan] + # Partial NaN in a row + vectors[4] = [1.0, np.nan, 3.0] + # Partial FILLVAL in a row + vectors[5] = [FILLVAL, 2.0, 3.0] + + l2 = MagL2( + vectors=vectors, + epoch=norm_dataset["epoch"].data, + range=norm_dataset["vectors"].data[:, 3], + global_attributes={}, + quality_flags=np.zeros(n), + quality_bitmask=np.zeros(n), + data_mode=DataMode.NORM, + offsets=np.zeros((n, 3)), + timedelta=np.zeros(n), + ) + + rotated_values = np.full(vectors.shape, 99.0) + with patch( + "imap_processing.mag.l2.mag_l2_data.frame_transform", + return_value=rotated_values, + ): + l2.rotate_frame(ValidFrames.DSRF) + + assert l2.frame == ValidFrames.DSRF + + # Full FILLVAL row -> all components should be FILLVAL + assert np.all(l2.vectors[0] == FILLVAL) + # Full NaN row -> all components should be FILLVAL + assert np.all(l2.vectors[2] == FILLVAL) + # Partial NaN -> affected components should be FILLVAL + assert l2.vectors[4, 1] == FILLVAL + # Partial FILLVAL -> affected components should be FILLVAL + assert l2.vectors[5, 0] == FILLVAL + + # Normal vectors should get the rotated value + assert np.all(l2.vectors[1] == 99.0) + assert np.all(l2.vectors[3] == 99.0) + + def test_qf(norm_dataset): qf = np.zeros(len(norm_dataset["epoch"].data), dtype=int) qf[1:4] = 1 diff --git a/imap_processing/tests/mag/test_mag_validation.py b/imap_processing/tests/mag/test_mag_validation.py index 078b794f83..7d6f12c832 100644 --- a/imap_processing/tests/mag/test_mag_validation.py +++ b/imap_processing/tests/mag/test_mag_validation.py @@ -256,40 +256,57 @@ def test_mag_l1b_validation(test_number, mocks): assert np.allclose(expected_time, mago_time, atol=1e-6, rtol=0) -@pytest.mark.xfail(reason="All L1C edge cases are not yet complete") -@pytest.mark.parametrize(("test_number"), ["013", "014", "015", "016"]) +@pytest.mark.parametrize(("test_number"), ["013", "014", "015", "016", "024"]) @pytest.mark.parametrize(("sensor"), ["mago", "magi"]) @pytest.mark.external_test_data def test_mag_l1c_validation(test_number, sensor): - # We expect tests 013 and 014 to pass. 015 and 016 are not yet complete. # timestamp = ( # (np.datetime64("2025-03-11T12:22:50.706034") - np.datetime64(TTJ2000_EPOCH)) # / np.timedelta64(1, "ns") # ).astype(np.int64) # print(f"Time stamp shift: {timestamp }") - source_directory = Path(__file__).parent / "validation" / "L1c" / f"T{test_number}" norm_in = source_directory / f"mag-l1b-l1c-t{test_number}-{sensor}-normal-in.csv" burst_in = source_directory / f"mag-l1b-l1c-t{test_number}-{sensor}-burst-in.csv" - norm = mag_generate_l1b_from_csv( - pd.read_csv(norm_in), f"imap_mag_l1b_norm-{sensor}" - ) - burst = mag_generate_l1b_from_csv( - pd.read_csv(burst_in), f"imap_mag_l1b_burst-{sensor}" + norm_df = pd.read_csv(norm_in) if norm_in.exists() else None + burst_df = pd.read_csv(burst_in) + + norm = ( + mag_generate_l1b_from_csv(norm_df, f"imap_mag_l1b_norm-{sensor}") + if norm_df is not None + else None ) + burst = mag_generate_l1b_from_csv(burst_df, f"imap_mag_l1b_burst-{sensor}") + + # Extract day_to_process from the first timestamp in the data + if norm_df is not None: + first_timestamp = pd.to_datetime(norm_df["t"].iloc[0]).normalize() + else: + first_timestamp = pd.to_datetime(burst_df["t"].iloc[0]).normalize() + + day_to_process = np.datetime64(first_timestamp.date()) # out = np.int64(794968123760272000) # print(f"expected out {TTJ2000_EPOCH + out.astype('timedelta64[ns]')}") # For mago test 013: norm 2, burst 64 - norm.attrs["vectors_per_second"] = get_vecsec(test_number, sensor, "norm") + if norm is not None: + norm.attrs["vectors_per_second"] = get_vecsec(test_number, sensor, "norm") + first_dataset = norm + second_dataset = burst + else: + first_dataset = burst + second_dataset = None burst.attrs["vectors_per_second"] = get_vecsec(test_number, sensor, "burst") - l1c = mag_l1c(norm, burst) + l1c = mag_l1c(first_dataset, day_to_process, second_dataset) expected_output = pd.read_csv( source_directory / f"mag-l1b-l1c-t{test_number}-{sensor}-normal-out.csv" ) + # T016 intentionally omits the Config-mode boundary sample that would require + # extrapolating beyond the CIC-filtered burst support. + assert len(expected_output.index) == len(l1c["epoch"].data) for index in expected_output.index: assert np.allclose( @@ -380,19 +397,19 @@ def test_mag_l2_validation(test_number, mode): assert np.allclose( expected_output["x"].iloc[index], - l2["vectors"].data[index][0], + l2["b_srf"].data[index][0], atol=1e-5, rtol=0, ) assert np.allclose( expected_output["y"].iloc[index], - l2["vectors"].data[index][1], + l2["b_srf"].data[index][1], atol=1e-5, rtol=0, ) assert np.allclose( expected_output["z"].iloc[index], - l2["vectors"].data[index][2], + l2["b_srf"].data[index][2], atol=1e-5, rtol=0, ) @@ -416,14 +433,31 @@ def get_vecsec(test_number, sensor, mode): }, "015": { "mago": { - "norm": "794967514703783040:2,794968123760272000:4", - "burst": "794966835183206016:64", + "norm": "794967519703783040:2,794968128760272000:4", + "burst": "794967839890064896:64", + }, + "magi": { + "norm": "794967519703768064:2,794968128760256000:1", + "burst": "794967839890033920:8", + }, + }, + "016": { + "mago": { + "norm": "794968476204568960:4,794969095711198976:2", + "burst": "794968751184441984:64", + }, + "magi": { + "norm": "794968476204537984:1,794969095711168000:2", + "burst": "794968751200051968:8", + }, + }, + "024": { + "mago": { + "burst": "794968751184441984:64", }, "magi": { - "norm": "794967514703768064:2,794968123760256000:1", - "burst": "794967834198914944:64", + "burst": "794968751200051968:8", }, }, - "016": {"mago": {"norm": "", "burst": ""}, "magi": {"norm": "", "burst": ""}}, } return vecsec[test_number][sensor][mode] diff --git a/imap_processing/tests/mag/validation/L1c/T016/mag-l1b-l1c-t016-magi-normal-out.csv b/imap_processing/tests/mag/validation/L1c/T016/mag-l1b-l1c-t016-magi-normal-out.csv index 8bb18aa0a4..7662c54efc 100644 --- a/imap_processing/tests/mag/validation/L1c/T016/mag-l1b-l1c-t016-magi-normal-out.csv +++ b/imap_processing/tests/mag/validation/L1c/T016/mag-l1b-l1c-t016-magi-normal-out.csv @@ -617,7 +617,6 @@ t,coarse,fine,sequence,x,y,z,range,compression,compression_width,interp 2025-03-11 12:43:42.016372,,,,1.4597257843436746,-8.092748865726973,7.718317851756491,,,,True 2025-03-11 12:43:43.016372,,,,-3.891811237553603,4.09950238215284,-1.7190707500947102,,,,True 2025-03-11 12:43:44.016372,,,,-9.026964677527577,15.760758012366862,-10.74386109732374,,,,True -2025-03-11 12:43:45.016372,,,,-13.017460988794108,24.848120706236458,-17.785586915692342,,,,True 2025-03-11 12:43:46.527168,479393029.0,34548.0,49.0,-15.62096417508,30.735512417025,-22.367622735855,2.0,1.0,18.0,False 2025-03-11 12:43:47.027168,479393029.0,34548.0,49.0,-15.31503989928,30.019423596075,-21.80415464334,2.0,1.0,18.0,False 2025-03-11 12:43:47.527168,479393029.0,34548.0,49.0,-14.44433234508,28.046672328285,-20.26724078709,2.0,1.0,18.0,False diff --git a/imap_processing/tests/mag/validation/L1c/T016/mag-l1b-l1c-t016-mago-normal-out.csv b/imap_processing/tests/mag/validation/L1c/T016/mag-l1b-l1c-t016-mago-normal-out.csv index 3660aa2791..fb696f1e20 100644 --- a/imap_processing/tests/mag/validation/L1c/T016/mag-l1b-l1c-t016-mago-normal-out.csv +++ b/imap_processing/tests/mag/validation/L1c/T016/mag-l1b-l1c-t016-mago-normal-out.csv @@ -2474,7 +2474,6 @@ t,coarse,fine,sequence,x,y,z,range,compression,compression_width,interp 2025-03-11 12:43:45.016388,,,,-33.77221931833578,-39.3559802357737,60.64180756528237,,,,True 2025-03-11 12:43:45.266388,,,,-36.38501076311149,-41.955376573325665,65.40516872759466,,,,True 2025-03-11 12:43:45.516388,,,,-38.5533383475656,-44.129623779228986,69.35776556366213,,,,True -2025-03-11 12:43:45.766388,,,,-40.267078486879164,-45.83104691865952,72.46644263976481,,,,True 2025-03-11 12:43:46.527199,479393029.0,34550.0,49.0,-42.3608496138,-47.906009615925,76.22511836355,2.0,1.0,18.0,False 2025-03-11 12:43:47.027199,479393029.0,34550.0,49.0,-41.3006503743,-46.818223319925,74.24599056867,2.0,1.0,18.0,False 2025-03-11 12:43:47.527199,479393029.0,34550.0,49.0,-38.28026054088,-43.767710936685,68.71635468792,2.0,1.0,18.0,False diff --git a/imap_processing/tests/mag/validation/L1c/T024/mag-l1b-l1c-t024-magi-burst-in.csv b/imap_processing/tests/mag/validation/L1c/T024/mag-l1b-l1c-t024-magi-burst-in.csv new file mode 100644 index 0000000000..098cd6f3a7 --- /dev/null +++ b/imap_processing/tests/mag/validation/L1c/T024/mag-l1b-l1c-t024-magi-burst-in.csv @@ -0,0 +1,2753 @@ +t,coarse,fine,sequence,x,y,z,range,compression,compression_width +2025-03-11T12:38:02.016052,479392685,1052,171,-6.575018777,18.25180801333,-17.04333193014,2,1,18 +2025-03-11T12:38:02.141052,479392685,1052,171,-6.9044756894,18.986400092635,-17.597708062275,2,1,18 +2025-03-11T12:38:02.266052,479392685,1052,171,-7.19157385592,19.61473840297,-18.119092009485,2,1,18 +2025-03-11T12:38:02.391052,479392685,1052,171,-7.43631327656,20.182992503785,-18.566146056135,2,1,18 +2025-03-11T12:38:02.516052,479392685,1052,171,-7.67634616988,20.70045300229,-18.93438025455,2,1,18 +2025-03-11T12:38:02.641052,479392685,1052,171,-7.85519420804,21.10701442822,-19.255696832325,2,1,18 +2025-03-11T12:38:02.766052,479392685,1052,171,-8.0105096096,21.4442860804,-19.50267559296,2,1,18 +2025-03-11T12:38:02.891052,479392685,1052,171,-8.1281727926,21.70762974214,-19.702982341605,2,1,18 +2025-03-11T12:38:03.016052,479392685,1052,171,-8.20818375704,21.883194545605,-19.84730384298,2,1,18 +2025-03-11T12:38:03.141052,479392685,1052,171,-8.25054250292,21.961746578905,-19.92173107854,2,1,18 +2025-03-11T12:38:03.266052,479392685,1052,171,-8.25524903024,21.984838445545,-19.94034340308,2,1,18 +2025-03-11T12:38:03.391052,479392685,1052,171,-8.22700986632,21.91554158488,-19.88447586627,2,1,18 +2025-03-11T12:38:03.516052,479392685,1052,171,-8.1517054292,21.753834736165,-19.75409790492,2,1,18 +2025-03-11T12:38:03.641052,479392685,1052,171,-8.0575748828,21.51822824467,-19.563228331455,2,1,18 +2025-03-11T12:38:03.766052,479392685,1052,171,-7.9163790632,21.217913500795,-19.330335155055,2,1,18 +2025-03-11T12:38:03.891052,479392685,1052,171,-7.751650607,20.825224203445,-19.01836237575,2,1,18 +2025-03-11T12:38:04.016052,479392685,1052,171,-7.54456340492,20.353982872795,-18.659683062975,2,1,18 +2025-03-11T12:38:04.141052,479392685,1052,171,-7.29511745696,19.813423420735,-18.231245299155,2,1,18 +2025-03-11T12:38:04.266052,479392685,1052,171,-7.01272581776,19.17124132948,-17.76061982559,2,1,18 +2025-03-11T12:38:04.391052,479392685,1052,171,-6.71150806928,18.46901046328,-17.206475156085,2,1,18 +2025-03-11T12:38:04.516052,479392685,1052,171,-6.38205115688,17.71133360425,-16.59653595102,2,1,18 +2025-03-11T12:38:04.641052,479392685,1052,171,-6.01494202592,16.865877886945,-15.949091966745,2,1,18 +2025-03-11T12:38:04.766052,479392685,1052,171,-5.6101806764,15.92802635542,-15.231778050405,2,1,18 +2025-03-11T12:38:04.891052,479392685,1052,171,-5.2101258542,14.948629307305,-14.47267426491,2,1,18 +2025-03-11T12:38:05.016052,479392685,1052,171,-4.73476659488,13.9229493091,-13.6715830851,2,1,18 +2025-03-11T12:38:05.141052,479392685,1052,171,-4.24999428092,12.823383841945,-12.82388101968,2,1,18 +2025-03-11T12:38:05.266052,479392685,1052,171,-3.74168933036,11.668379468875,-11.934254957475,2,1,18 +2025-03-11T12:38:05.391052,479392685,1052,171,-3.20514521588,10.44407823514,-10.99800159249,2,1,18 +2025-03-11T12:38:05.516052,479392685,1052,171,-2.64036193748,9.16894796452,-10.024458493755,2,1,18 +2025-03-11T12:38:05.641052,479392685,1052,171,-2.06145907712,7.884562521265,-8.99539476015,2,1,18 +2025-03-11T12:38:05.766052,479392685,1052,171,-1.46373010748,6.540128303065,-7.9428733518,2,1,18 +2025-03-11T12:38:05.891052,479392685,1052,171,-0.86129461052,5.14028352661,-6.86232904863,2,1,18 +2025-03-11T12:38:06.015976,479392689,1047,172,-0.249446058919999,3.694255016875,-5.75380033041,2,1,18 +2025-03-11T12:38:06.140976,479392689,1047,172,0.38593512928,2.22510629284,-4.63585877076,2,1,18 +2025-03-11T12:38:06.265976,479392689,1047,172,1.04014242676,0.755929221145003,-3.4901557581,2,1,18 +2025-03-11T12:38:06.390976,479392689,1047,172,1.69905625156,-0.750190585024999,-2.311907068605,2,1,18 +2025-03-11T12:38:06.515976,479392689,1047,172,2.367383131,-2.26094152097,-1.1336136699,2,1,18 +2025-03-11T12:38:06.640976,479392689,1047,172,3.05453611972,-3.808656452135,0.054155383755,2,1,18 +2025-03-11T12:38:06.765976,479392689,1047,172,3.74639563576,-5.365612382105,1.265083877715,2,1,18 +2025-03-11T12:38:06.890976,479392689,1047,172,4.42413556984,-6.945631831055,2.494583945295,2,1,18 +2025-03-11T12:38:07.015976,479392689,1047,172,5.10187550392,-8.507183456225,3.714746443845,2,1,18 +2025-03-11T12:38:07.140976,479392689,1047,172,5.8031480746,-10.073387471915,4.93036409778,2,1,18 +2025-03-11T12:38:07.265976,479392689,1047,172,6.47618148136,-11.630315054225,6.14125184082,2,1,18 +2025-03-11T12:38:07.390976,479392689,1047,172,7.15862794276,-13.18263985442,7.338275274525,2,1,18 +2025-03-11T12:38:07.515976,479392689,1047,172,7.84107440416,-14.73034769867,8.51679390642,2,1,18 +2025-03-11T12:38:07.640976,479392689,1047,172,8.49057517432,-16.222602463175,9.67184863413,2,1,18 +2025-03-11T12:38:07.765976,479392689,1047,172,9.14948899912,-17.70563748962,10.831495186815,2,1,18 +2025-03-11T12:38:07.890976,479392689,1047,172,9.80840282392,-19.17482164823,11.96334803616,2,1,18 +2025-03-11T12:38:08.015976,479392689,1047,172,10.42025137552,-20.60699929013,13.08104398716,2,1,18 +2025-03-11T12:38:08.140976,479392689,1047,172,11.03209992712,-21.98377346069,14.147626645995,2,1,18 +2025-03-11T12:38:08.265976,479392689,1047,172,11.62041584212,-23.34666132884,15.200225013885,2,1,18 +2025-03-11T12:38:08.390976,479392689,1047,172,12.2040252298,-24.654138638735,16.206320018895,2,1,18 +2025-03-11T12:38:08.515976,479392689,1047,172,12.74998239892,-25.90615578197,17.184320814975,2,1,18 +2025-03-11T12:38:08.640976,479392689,1047,172,13.26770040412,-27.09810997643,18.12960332682,2,1,18 +2025-03-11T12:38:08.765976,479392689,1047,172,13.78541840932,-28.285447214945,19.028660334765,2,1,18 +2025-03-11T12:38:08.890976,479392689,1047,172,14.27960377792,-29.398877723765,19.86259542585,2,1,18 +2025-03-11T12:38:09.015976,479392689,1047,172,14.76437609188,-30.44303971958,20.67304455015,2,1,18 +2025-03-11T12:38:09.140976,479392689,1047,172,15.18796355068,-31.42247220227,21.441439508325,2,1,18 +2025-03-11T12:38:09.265976,479392689,1047,172,15.57389879092,-32.32797669452,22.13544175242,2,1,18 +2025-03-11T12:38:09.390976,479392689,1047,172,15.95512750384,-33.178070628515,22.80604121871,2,1,18 +2025-03-11T12:38:09.515976,479392689,1047,172,16.29399747088,-33.944995573265,23.40218911569,2,1,18 +2025-03-11T12:38:09.640976,479392689,1047,172,16.59992174668,-34.633382658545,23.95165085466,2,1,18 +2025-03-11T12:38:09.765976,479392689,1047,172,16.87760685856,-35.275557662885,24.440746608555,2,1,18 +2025-03-11T12:38:09.890976,479392689,1047,172,17.13175933384,-35.81612420186,24.869194560105,2,1,18 +2025-03-11T12:38:10.015930,479392693,1044,173,17.33884653592,-36.2965994444,25.232542657395,2,1,18 +2025-03-11T12:38:10.140930,479392693,1044,173,17.53181415604,-36.68933126324,25.530716212035,2,1,18 +2025-03-11T12:38:10.265930,479392693,1044,173,17.66830344832,-37.021957611815,25.782250005015,2,1,18 +2025-03-11T12:38:10.390930,479392693,1044,173,17.76714052204,-37.248337278335,25.968460981695,2,1,18 +2025-03-11T12:38:10.515930,479392693,1044,173,17.84244495916,-37.414661082995,26.08500292575,2,1,18 +2025-03-11T12:38:10.640930,479392693,1044,173,17.87068412308,-37.488574899605,26.14089479631,2,1,18 +2025-03-11T12:38:10.765930,479392693,1044,173,17.8518580138,-37.47469568411,26.126920693095,2,1,18 +2025-03-11T12:38:10.890930,479392693,1044,173,17.81891232256,-37.36845608897,26.052367830495,2,1,18 +2025-03-11T12:38:11.015930,479392693,1044,173,17.74360788544,-37.188281416475,25.921892534145,2,1,18 +2025-03-11T12:38:11.140930,479392693,1044,173,17.63535775708,-36.934185840455,25.72165482846,2,1,18 +2025-03-11T12:38:11.265930,479392693,1044,173,17.50357499212,-36.59694962285,25.44238618737,2,1,18 +2025-03-11T12:38:11.390930,479392693,1044,173,17.32472695396,-36.17192037314,25.13483262564,2,1,18 +2025-03-11T12:38:11.515930,479392693,1044,173,17.0988136426,-35.686799826995,24.757559092635,2,1,18 +2025-03-11T12:38:11.640930,479392693,1044,173,16.85407422196,-35.09084399051,24.30573892647,2,1,18 +2025-03-11T12:38:11.765930,479392693,1044,173,16.57168258276,-34.448661899255,23.8027726338,2,1,18 +2025-03-11T12:38:11.890930,479392693,1044,173,16.23281261572,-33.72328955801,23.248424793705,2,1,18 +2025-03-11T12:38:12.015930,479392693,1044,173,15.87041001208,-32.937861354905,22.642888389045,2,1,18 +2025-03-11T12:38:12.140930,479392693,1044,173,15.4985943538,-32.06931377096,21.93987114411,2,1,18 +2025-03-11T12:38:12.265930,479392693,1044,173,15.09383300428,-31.12684528349,21.227153011035,2,1,18 +2025-03-11T12:38:12.390930,479392693,1044,173,14.65612596352,-30.128923716275,20.454010037655,2,1,18 +2025-03-11T12:38:12.515930,479392693,1044,173,14.20900586812,-29.066350592,19.615824378105,2,1,18 +2025-03-11T12:38:12.640930,479392693,1044,173,13.70070091756,-27.943664910545,18.758709471255,2,1,18 +2025-03-11T12:38:12.765930,479392693,1044,173,13.192395967,-26.77480966964,17.84128970571,2,1,18 +2025-03-11T12:38:12.890930,479392693,1044,173,12.64643879788,-25.52740948235,16.895654062485,2,1,18 +2025-03-11T12:38:13.015930,479392693,1044,173,12.07694899216,-24.26612299265,15.917553660255,2,1,18 +2025-03-11T12:38:13.140930,479392693,1044,173,11.50275265912,-22.967893768475,14.88842711313,2,1,18 +2025-03-11T12:38:13.265930,479392693,1044,173,10.89090410752,-21.600353509805,13.821893121795,2,1,18 +2025-03-11T12:38:13.390930,479392693,1044,173,10.29317513788,-20.182047996485,12.722781203295,2,1,18 +2025-03-11T12:38:13.515930,479392693,1044,173,9.67662005896,-18.74986326767,11.595834830535,2,1,18 +2025-03-11T12:38:13.640930,479392693,1044,173,9.03182581612,-17.262232546025,10.48239567744,2,1,18 +2025-03-11T12:38:13.765930,479392693,1044,173,8.38703157328,-15.769984868435,9.31811090343,2,1,18 +2025-03-11T12:38:13.890930,479392693,1044,173,7.70458511188,-14.259212671745,8.139786941535,2,1,18 +2025-03-11T12:38:14.015869,479392697,1040,174,7.0268451778,-12.7207458263,6.95208693084,2,1,18 +2025-03-11T12:38:14.140869,479392697,1040,174,6.3443987164,-11.168421026105,5.755063497135,2,1,18 +2025-03-11T12:38:14.265869,479392697,1040,174,5.65724572768,-9.62994000683,4.562722993965,2,1,18 +2025-03-11T12:38:14.390869,479392697,1040,174,4.97009273896,-8.04990638405,3.342442784955,2,1,18 +2025-03-11T12:38:14.515869,479392697,1040,174,4.28293975024,-6.483723629105,2.13609592824,2,1,18 +2025-03-11T12:38:14.640869,479392697,1040,174,3.60990634348,-4.92217909085,0.91594361742,2,1,18 +2025-03-11T12:38:14.765869,479392697,1040,174,2.92275335476,-3.38831502752,-0.290232903045,2,1,18 +2025-03-11T12:38:14.890869,479392697,1040,174,2.23560036604,-1.83598314041,-1.48726652448,2,1,18 +2025-03-11T12:38:15.015869,479392697,1040,174,1.56256695928,-0.302140337824998,-2.684172247725,2,1,18 +2025-03-11T12:38:15.140869,479392697,1040,174,0.91777271644,1.180873427875,-3.83454800319,2,1,18 +2025-03-11T12:38:15.265869,479392697,1040,174,0.277685000920001,2.68234793044,-4.985010905925,2,1,18 +2025-03-11T12:38:15.390869,479392697,1040,174,-0.37652229656,4.12844022241,-6.093631313715,2,1,18 +2025-03-11T12:38:15.515869,479392697,1040,174,-1.00249043012,5.532937389385,-7.192731357345,2,1,18 +2025-03-11T12:38:15.640869,479392697,1040,174,-1.61433898172,6.905094604,-8.26852991646,2,1,18 +2025-03-11T12:38:15.765869,479392697,1040,174,-2.1979483694,8.2541245174,-9.29332439328,2,1,18 +2025-03-11T12:38:15.890869,479392697,1040,174,-2.77214470244,9.552353741575,-10.2901101213,2,1,18 +2025-03-11T12:38:16.015869,479392697,1040,174,-3.31810187156,10.80437088481,-11.25887068335,2,1,18 +2025-03-11T12:38:16.140869,479392697,1040,174,-3.84052640408,12.01018303402,-12.19037603313,2,1,18 +2025-03-11T12:38:16.265869,479392697,1040,174,-4.3394183,13.142088453535,-13.07523993411,2,1,18 +2025-03-11T12:38:16.390869,479392697,1040,174,-4.81477755932,14.218554967135,-13.927420072335,2,1,18 +2025-03-11T12:38:16.515869,479392697,1040,174,-5.26660418204,15.23958257482,-14.719195745715,2,1,18 +2025-03-11T12:38:16.640869,479392697,1040,174,-5.69019164084,16.195930277785,-15.464368450065,2,1,18 +2025-03-11T12:38:16.765869,479392697,1040,174,-6.09495299036,17.110697029585,-16.16770034661,2,1,18 +2025-03-11T12:38:16.890869,479392697,1040,174,-6.457355594,17.937677836195,-16.815036808155,2,1,18 +2025-03-11T12:38:17.015869,479392697,1040,174,-6.79622556104,18.704602780945,-17.392704237075,2,1,18 +2025-03-11T12:38:17.140869,479392697,1040,174,-7.10214983684,19.383755954335,-17.90977648944,2,1,18 +2025-03-11T12:38:17.265869,479392697,1040,174,-7.36571536676,19.97050622659,-18.380069207085,2,1,18 +2025-03-11T12:38:17.390869,479392697,1040,174,-7.59162867812,20.48794546435,-18.789853895445,2,1,18 +2025-03-11T12:38:17.515869,479392697,1040,174,-7.78930282556,20.936087841445,-19.14839116401,2,1,18 +2025-03-11T12:38:17.640869,479392697,1040,174,-7.97285739104,21.31495461862,-19.42799087388,2,1,18 +2025-03-11T12:38:17.765869,479392697,1040,174,-8.10934668332,21.601411407745,-19.64232039324,2,1,18 +2025-03-11T12:38:17.890869,479392697,1040,174,-8.20347722972,21.80931616357,-19.80994337913,2,1,18 +2025-03-11T12:38:18.015808,479392701,1036,175,-8.25054250292,21.943278755125,-19.917013626525,2,1,18 +2025-03-11T12:38:18.140808,479392701,1036,175,-8.2693686122,21.998710574125,-19.945067084535,2,1,18 +2025-03-11T12:38:18.265808,479392701,1036,175,-8.25524903024,21.96175366582,-19.91250103224,2,1,18 +2025-03-11T12:38:18.390808,479392701,1036,175,-8.21289028436,21.850882940905,-19.824043109385,2,1,18 +2025-03-11T12:38:18.515808,479392701,1036,175,-8.13758584724,21.666091312465,-19.665822777195,2,1,18 +2025-03-11T12:38:18.640808,479392701,1036,175,-8.00109655496,21.384251479285,-19.460757825615,2,1,18 +2025-03-11T12:38:18.765808,479392701,1036,175,-7.84107462608,21.014654048575,-19.172017487865,2,1,18 +2025-03-11T12:38:18.890808,479392701,1036,175,-7.64810700596,20.575752670285,-18.83201954259,2,1,18 +2025-03-11T12:38:19.015808,479392701,1036,175,-7.43160674924,20.058327606355,-18.43149546372,2,1,18 +2025-03-11T12:38:19.140808,479392701,1036,175,-7.163334692,19.453102423405,-17.970335457375,2,1,18 +2025-03-11T12:38:19.265808,479392701,1036,175,-6.85270388888,18.7739421631,-17.448632900265,2,1,18 +2025-03-11T12:38:19.390808,479392701,1036,175,-6.5279535038,18.03012325882,-16.8757378203,2,1,18 +2025-03-11T12:38:19.515808,479392701,1036,175,-6.1749639548,17.20315662604,-16.228421734215,2,1,18 +2025-03-11T12:38:19.640808,479392701,1036,175,-5.78432218724,16.32996373849,-15.548439989685,2,1,18 +2025-03-11T12:38:19.765808,479392701,1036,175,-5.38897389236,15.373658557015,-14.803328411715,2,1,18 +2025-03-11T12:38:19.890808,479392701,1036,175,-4.9512668516,14.34803525413,-14.02541931882,2,1,18 +2025-03-11T12:38:20.015808,479392701,1036,175,-4.4806141196,13.2669588715,-13.173225034575,2,1,18 +2025-03-11T12:38:20.140808,479392701,1036,175,-3.97230916904,12.125805366265,-12.28367197362,2,1,18 +2025-03-11T12:38:20.265808,479392701,1036,175,-3.45459116384,10.92923421586,-11.366085830115,2,1,18 +2025-03-11T12:38:20.390808,479392701,1036,175,-2.90863399472,9.704918808295,-10.415951738625,2,1,18 +2025-03-11T12:38:20.515808,479392701,1036,175,-2.33443766168,8.39745567223,-9.41449722609,2,1,18 +2025-03-11T12:38:20.640808,479392701,1036,175,-1.750828274,7.05765967072,-8.3989916508,2,1,18 +2025-03-11T12:38:20.765808,479392701,1036,175,-1.162512359,5.68553789068,-7.31862391332,2,1,18 +2025-03-11T12:38:20.890808,479392701,1036,175,-0.541250752759999,4.26257998684,-6.224056839435,2,1,18 +2025-03-11T12:38:21.015808,479392701,1036,175,0.0988369627600001,2.816508955615,-5.096986526775,2,1,18 +2025-03-11T12:38:21.140808,479392701,1036,175,0.74833773292,1.35195592678,-3.942077801565,2,1,18 +2025-03-11T12:38:21.265808,479392701,1036,175,1.42137113968,-0.131100360409999,-2.787020802705,2,1,18 +2025-03-11T12:38:21.390808,479392701,1036,175,2.07087190984,-1.678758596255,-1.613193601935,2,1,18 +2025-03-11T12:38:21.515808,479392701,1036,175,2.7439053166,-3.217218354785,-0.411643427925001,2,1,18 +2025-03-11T12:38:21.640808,479392701,1036,175,3.42164525068,-4.76491911212,0.79458571833,2,1,18 +2025-03-11T12:38:21.765808,479392701,1036,175,4.11350476672,-6.32187504209,1.98703374423,2,1,18 +2025-03-11T12:38:21.890808,479392701,1036,175,4.80065775544,-7.897291708925,3.184189034415,2,1,18 +2025-03-11T12:38:22.015732,479392705,1031,176,5.49251727148,-9.44039677106,4.39966464414,2,1,18 +2025-03-11T12:38:22.140732,479392705,1031,176,6.16555067824,-11.001941309315,5.61057672093,2,1,18 +2025-03-11T12:38:22.265732,479392705,1031,176,6.84329061232,-12.535791198815,6.816732865935,2,1,18 +2025-03-11T12:38:22.390732,479392705,1031,176,7.5210305464,-14.05579022048,7.999715424615,2,1,18 +2025-03-11T12:38:22.515732,479392705,1031,176,8.18935742584,-15.58039202426,9.1873220586,2,1,18 +2025-03-11T12:38:22.640732,479392705,1031,176,8.838858196,-17.10496548038,10.35178735659,2,1,18 +2025-03-11T12:38:22.765732,479392705,1031,176,9.4742393842,-18.592582028195,11.483686602285,2,1,18 +2025-03-11T12:38:22.890732,479392705,1031,176,10.1096205724,-20.029412060615,12.6060779427,2,1,18 +2025-03-11T12:38:23.015732,479392705,1031,176,10.73088217864,-21.43851909662,13.691331781305,2,1,18 +2025-03-11T12:38:23.140732,479392705,1031,176,11.34743725756,-22.815300354095,14.75792462787,2,1,18 +2025-03-11T12:38:23.265732,479392705,1031,176,11.93575317256,-24.150486486575,15.787276408185,2,1,18 +2025-03-11T12:38:23.390732,479392705,1031,176,12.50524297828,-25.41638993222,16.783881612225,2,1,18 +2025-03-11T12:38:23.515732,479392705,1031,176,13.0276675108,-26.65913772899,17.75716268514,2,1,18 +2025-03-11T12:38:23.640732,479392705,1031,176,13.545385516,-27.84185801156,18.67929594441,2,1,18 +2025-03-11T12:38:23.765732,479392705,1031,176,14.04898393924,-28.950685738265,19.54556789631,2,1,18 +2025-03-11T12:38:23.890732,479392705,1031,176,14.50551708928,-30.017889992315,20.37455803104,2,1,18 +2025-03-11T12:38:24.015732,479392705,1031,176,14.957343712,-31.015832820275,21.161591918655,2,1,18 +2025-03-11T12:38:24.140732,479392705,1031,176,15.38563769812,-31.981421522045,21.888343010175,2,1,18 +2025-03-11T12:38:24.265732,479392705,1031,176,15.77157293836,-32.85460732268,22.568314566975,2,1,18 +2025-03-11T12:38:24.390732,479392705,1031,176,16.12926901468,-33.64002843887,23.192321251965,2,1,18 +2025-03-11T12:38:24.515732,479392705,1031,176,16.4634324544,-34.3653936932,23.74665890433,2,1,18 +2025-03-11T12:38:24.640732,479392705,1031,176,16.7458240936,-35.026043608235,24.25896276603,2,1,18 +2025-03-11T12:38:24.765732,479392705,1031,176,16.99527004156,-35.612772619745,24.69688410138,2,1,18 +2025-03-11T12:38:24.890732,479392705,1031,176,17.2164768256,-36.107119990865,25.0880564652,2,1,18 +2025-03-11T12:38:25.015732,479392705,1031,176,17.41885750036,-36.55065249893,25.41423876864,2,1,18 +2025-03-11T12:38:25.140732,479392705,1031,176,17.57417290192,-36.892541107055,25.6843424481,2,1,18 +2025-03-11T12:38:25.265732,479392705,1031,176,17.69654261224,-37.1651257676,25.912428754065,2,1,18 +2025-03-11T12:38:25.390732,479392705,1031,176,17.77655357668,-37.359158394845,26.04760735641,2,1,18 +2025-03-11T12:38:25.515732,479392705,1031,176,17.81420579524,-37.45617116501,26.117501622225,2,1,18 +2025-03-11T12:38:25.640732,479392705,1031,176,17.8283253772,-37.474660249535,26.136109988475,2,1,18 +2025-03-11T12:38:25.765732,479392705,1031,176,17.80949926792,-37.42384538648,26.08498027914,2,1,18 +2025-03-11T12:38:25.890732,479392705,1031,176,17.75302094008,-37.271400797315,25.968552087255,2,1,18 +2025-03-11T12:38:26.015655,479392709,1026,177,17.6400642844,-37.04499987005,25.7869306644,2,1,18 +2025-03-11T12:38:26.140655,479392709,1026,177,17.51298804676,-36.72623856314,25.56321095022,2,1,18 +2025-03-11T12:38:26.265655,479392709,1026,177,17.3341400086,-36.324294093155,25.260399174255,2,1,18 +2025-03-11T12:38:26.390655,479392709,1026,177,17.13175933384,-35.8715276732,24.88334691615,2,1,18 +2025-03-11T12:38:26.515655,479392709,1026,177,16.89172644052,-35.34945021875,24.47350733085,2,1,18 +2025-03-11T12:38:26.640655,479392709,1026,177,16.62345438328,-34.711906344185,24.00755687124,2,1,18 +2025-03-11T12:38:26.765655,479392709,1026,177,16.34106274408,-34.02355469348,23.453525953905,2,1,18 +2025-03-11T12:38:26.890655,479392709,1026,177,15.98807319508,-33.22428979637,22.85255704047,2,1,18 +2025-03-11T12:38:27.015655,479392709,1026,177,15.60684448216,-32.38804673021,22.19127080946,2,1,18 +2025-03-11T12:38:27.140655,479392709,1026,177,15.21149618728,-31.49176197602,21.488056623375,2,1,18 +2025-03-11T12:38:27.265655,479392709,1026,177,14.78790872848,-30.53079731711,20.73823946826,2,1,18 +2025-03-11T12:38:27.390655,479392709,1026,177,14.33608210576,-29.4866849297,19.932481775085,2,1,18 +2025-03-11T12:38:27.515655,479392709,1026,177,13.86072284644,-28.37328276854,19.093967317905,2,1,18 +2025-03-11T12:38:27.640655,479392709,1026,177,13.36183095052,-27.22752648119,18.20441029866,2,1,18 +2025-03-11T12:38:27.765655,479392709,1026,177,12.83469989068,-26.0355581129,17.268347645385,2,1,18 +2025-03-11T12:38:27.890655,479392709,1026,177,12.26991661228,-24.78812957795,16.30419078318,2,1,18 +2025-03-11T12:38:28.015655,479392709,1026,177,11.70042680656,-23.476056572855,15.293481890595,2,1,18 +2025-03-11T12:38:28.140655,479392709,1026,177,11.10740436424,-22.13162944157,14.25483102102,2,1,18 +2025-03-11T12:38:28.265655,479392709,1026,177,10.51908844924,-20.74103983775,13.15588548048,2,1,18 +2025-03-11T12:38:28.390655,479392709,1026,177,9.88370726104,-19.31344371722,12.05664339264,2,1,18 +2025-03-11T12:38:28.515655,479392709,1026,177,9.24361954552,-17.858138774105,10.92952441248,2,1,18 +2025-03-11T12:38:28.640655,479392709,1026,177,8.58941224804,-16.37972779052,9.78377273232,2,1,18 +2025-03-11T12:38:28.765655,479392709,1026,177,7.93991147788,-14.887473026015,8.614857653565,2,1,18 +2025-03-11T12:38:28.890655,479392709,1026,177,7.25746501648,-13.34438213771,7.44560358945,2,1,18 +2025-03-11T12:38:29.015655,479392709,1026,177,6.58443160972,-11.79668846729,6.248624864955,2,1,18 +2025-03-11T12:38:29.140655,479392709,1026,177,5.90198514832,-10.23974671115,5.04233686347,2,1,18 +2025-03-11T12:38:29.265655,479392709,1026,177,5.21012563228,-8.687407737125,3.83143270326,2,1,18 +2025-03-11T12:38:29.390655,479392709,1026,177,4.52297264356,-7.12122498218,2.625085846545,2,1,18 +2025-03-11T12:38:29.515655,479392709,1026,177,3.85464576412,-5.57815535462,1.395800824425,2,1,18 +2025-03-11T12:38:29.640655,479392709,1026,177,3.16278624808,-3.99349768898,0.184726327965,2,1,18 +2025-03-11T12:38:29.765655,479392709,1026,177,2.48033978668,-2.43655593284,-0.99384097143,2,1,18 +2025-03-11T12:38:29.890655,479392709,1026,177,1.81201290724,-0.916571085004999,-2.17680315465,2,1,18 +2025-03-11T12:38:30.015594,479392713,1022,178,1.13897950048,0.58956998191,-3.35046229032,2,1,18 +2025-03-11T12:38:30.140594,479392713,1022,178,0.484772203,2.09106574522,-4.537916692365,2,1,18 +2025-03-11T12:38:30.265594,479392713,1022,178,-0.164728567159999,3.56946964189,-5.665177716735,2,1,18 +2025-03-11T12:38:30.390594,479392713,1022,178,-0.79540322804,4.987824763615,-6.755120715315,2,1,18 +2025-03-11T12:38:30.515594,479392713,1022,178,-1.40254525232,6.37382575915,-7.835602204965,2,1,18 +2025-03-11T12:38:30.640594,479392713,1022,178,-1.99556769464,7.73210375827,-8.888186426835,2,1,18 +2025-03-11T12:38:30.765594,479392713,1022,178,-2.58388360964,9.04882206697,-9.91744087215,2,1,18 +2025-03-11T12:38:30.890594,479392713,1022,178,-3.1392538334,10.310087295925,-10.90475094522,2,1,18 +2025-03-11T12:38:31.015594,479392713,1022,178,-3.66638489324,11.54360826772,-11.83641248523,2,1,18 +2025-03-11T12:38:31.140594,479392713,1022,178,-4.18410289844,12.69862681462,-12.744539390955,2,1,18 +2025-03-11T12:38:31.265594,479392713,1022,178,-4.67358173972,13.81666719247,-13.601589213135,2,1,18 +2025-03-11T12:38:31.390594,479392713,1022,178,-5.12540836244,14.865396535825,-14.411991357075,2,1,18 +2025-03-11T12:38:31.515594,479392713,1022,178,-5.5631154032,15.83561636737,-15.18036821094,2,1,18 +2025-03-11T12:38:31.640594,479392713,1022,178,-5.97258328004,16.76424107392,-15.90688388154,2,1,18 +2025-03-11T12:38:31.765594,479392713,1022,178,-6.35381199296,17.623568919805,-16.55905154727,2,1,18 +2025-03-11T12:38:31.890594,479392713,1022,178,-6.69738848732,18.39050095147,-17.159829748995,2,1,18 +2025-03-11T12:38:32.015594,479392713,1022,178,-7.00331276312,19.092738904585,-17.71398460623,2,1,18 +2025-03-11T12:38:32.140594,479392713,1022,178,-7.28570440232,19.73492099584,-18.20771066487,2,1,18 +2025-03-11T12:38:32.265594,479392713,1022,178,-7.53044382296,20.293941184765,-18.64547580999,2,1,18 +2025-03-11T12:38:32.390594,479392713,1022,178,-7.74223755236,20.78365742611,-19.022743113555,2,1,18 +2025-03-11T12:38:32.515594,479392713,1022,178,-7.92108559052,21.194835807985,-19.320983440005,2,1,18 +2025-03-11T12:38:32.640594,479392713,1022,178,-8.06698793744,21.50900850661,-19.563200039415,2,1,18 +2025-03-11T12:38:32.765594,479392713,1022,178,-8.16582501116,21.776940776635,-19.768110487905,2,1,18 +2025-03-11T12:38:32.890594,479392713,1022,178,-8.23171639364,21.93863345152,-19.89384795678,2,1,18 +2025-03-11T12:38:33.015594,479392713,1022,178,-8.2693686122,21.998710574125,-19.954307318565,2,1,18 +2025-03-11T12:38:33.140594,479392713,1022,178,-8.25995555756,22.00331335624,-19.94969115984,2,1,18 +2025-03-11T12:38:33.265594,479392713,1022,178,-8.24112944828,21.92017980157,-19.88453076321,2,1,18 +2025-03-11T12:38:33.390594,479392713,1022,178,-8.1752380658,21.73540234696,-19.74481127454,2,1,18 +2025-03-11T12:38:33.515594,479392713,1022,178,-8.06698793744,21.49054068283,-19.54924235337,2,1,18 +2025-03-11T12:38:33.640594,479392713,1022,178,-7.92108559052,21.15328320448,-19.293043734165,2,1,18 +2025-03-11T12:38:33.765594,479392713,1022,178,-7.73753102504,20.75133164758,-18.99022177047,2,1,18 +2025-03-11T12:38:33.890594,479392713,1022,178,-7.53515035028,20.26624653601,-18.612999176115,2,1,18 +2025-03-11T12:38:34.015548,479392717,1019,179,-7.28570440232,19.684134480445,-18.156621706455,2,1,18 +2025-03-11T12:38:34.140548,479392717,1019,179,-7.00331276312,19.046569345135,-17.662919981565,2,1,18 +2025-03-11T12:38:34.265548,479392717,1019,179,-6.67856237804,18.33506913247,-17.10867570591,2,1,18 +2025-03-11T12:38:34.390548,479392717,1019,179,-6.33498588368,17.54505232108,-16.507775835435,2,1,18 +2025-03-11T12:38:34.515548,479392717,1019,179,-5.95846369808,16.68573156211,-15.837137889375,2,1,18 +2025-03-11T12:38:34.640548,479392717,1019,179,-5.5631154032,15.747894204415,-15.10598399745,2,1,18 +2025-03-11T12:38:34.765548,479392717,1019,179,-5.12540836244,14.782291328815,-14.337631477335,2,1,18 +2025-03-11T12:38:34.890548,479392717,1019,179,-4.65475563044,13.71506581402,-13.52247113046,2,1,18 +2025-03-11T12:38:35.015548,479392717,1019,179,-4.17939637112,12.615514520695,-12.660929089455,2,1,18 +2025-03-11T12:38:35.140548,479392717,1019,179,-3.67109142056,11.44665927979,-11.76198979197,2,1,18 +2025-03-11T12:38:35.265548,479392717,1019,179,-3.13454730608,10.21774109011,-10.82109197622,2,1,18 +2025-03-11T12:38:35.390548,479392717,1019,179,-2.574470555,8.94723486235,-9.83372304792,2,1,18 +2025-03-11T12:38:35.515548,479392717,1019,179,-1.99556769464,7.6120629037,-8.81825199411,2,1,18 +2025-03-11T12:38:35.640548,479392717,1019,179,-1.39313219768,6.249153774805,-7.751762711985,2,1,18 +2025-03-11T12:38:35.765548,479392717,1019,179,-0.7624575368,4.835415609025,-6.68494463223,2,1,18 +2025-03-11T12:38:35.890548,479392717,1019,179,-0.1506089852,3.403237967125,-5.562628564215,2,1,18 +2025-03-11T12:38:36.015548,479392717,1019,179,0.49418525764,1.95254289304,-4.426283496045,2,1,18 +2025-03-11T12:38:36.140548,479392717,1019,179,1.1436860278,0.469522040425,-3.262037201805,2,1,18 +2025-03-11T12:38:36.265548,479392717,1019,179,1.81671943456,-1.059703806215,-2.07439604634,2,1,18 +2025-03-11T12:38:36.390548,479392717,1019,179,2.48975284132,-2.579695740965,-0.896043792405,2,1,18 +2025-03-11T12:38:36.515548,479392717,1019,179,3.16278624808,-4.118155499495,0.31936673265,2,1,18 +2025-03-11T12:38:36.640548,479392717,1019,179,3.84523270948,-5.684331167525,1.52108328462,2,1,18 +2025-03-11T12:38:36.765548,479392717,1019,179,4.52297264356,-7.245882792695,2.72276531511,2,1,18 +2025-03-11T12:38:36.890548,479392717,1019,179,5.21012563228,-8.825916415475,3.92456505606,2,1,18 +2025-03-11T12:38:37.015548,479392717,1019,179,5.91610473028,-10.38289360619,5.13552411321,2,1,18 +2025-03-11T12:38:37.140548,479392717,1019,179,6.58913813704,-11.92135336472,6.341694404235,2,1,18 +2025-03-11T12:38:37.265548,479392717,1019,179,7.2621715438,-13.464430079195,7.52016832692,2,1,18 +2025-03-11T12:38:37.390548,479392717,1019,179,7.93991147788,-14.99366301275,8.707819670115,2,1,18 +2025-03-11T12:38:37.515548,479392717,1019,179,8.60353183,-16.509023817725,9.881507097825,2,1,18 +2025-03-11T12:38:37.640548,479392717,1019,179,9.24832607284,-18.001271495315,11.027311403775,2,1,18 +2025-03-11T12:38:37.765548,479392717,1019,179,9.88841378836,-19.433491658705,12.154308715185,2,1,18 +2025-03-11T12:38:37.890548,479392717,1019,179,10.51908844924,-20.87031460421,13.253589282795,2,1,18 +2025-03-11T12:38:38.015472,479392721,1014,180,11.13093700084,-22.260939642605,14.334105293925,2,1,18 +2025-03-11T12:38:38.140472,479392721,1014,180,11.7098398612,-23.6007285572,15.377321383575,2,1,18 +2025-03-11T12:38:38.265472,479392721,1014,180,12.29344924888,-24.908205867095,16.3880365056,2,1,18 +2025-03-11T12:38:38.390472,479392721,1014,180,12.84881947264,-26.164854140105,17.361461893875,2,1,18 +2025-03-11T12:38:38.515472,479392721,1014,180,13.37595053248,-27.356822508395,18.28828431312,2,1,18 +2025-03-11T12:38:38.640472,479392721,1014,180,13.8748424284,-28.48872792791,19.177768331115,2,1,18 +2025-03-11T12:38:38.765472,479392721,1014,180,14.35961474236,-29.579059483175,20.016181495005,2,1,18 +2025-03-11T12:38:38.890472,479392721,1014,180,14.8161478924,-30.61394504561,20.81266047438,2,1,18 +2025-03-11T12:38:39.015472,479392721,1014,180,15.23032229656,-31.59336335447,21.562554589035,2,1,18 +2025-03-11T12:38:39.140472,479392721,1014,180,15.61155100948,-32.480392936025,22.270309661445,2,1,18 +2025-03-11T12:38:39.265472,479392721,1014,180,15.98807319508,-33.31662891527,22.92696558771,2,1,18 +2025-03-11T12:38:39.390472,479392721,1014,180,16.33164968944,-34.074327035045,23.509214653875,2,1,18 +2025-03-11T12:38:39.515472,479392721,1014,180,16.63757396524,-34.76733107627,24.04484037555,2,1,18 +2025-03-11T12:38:39.640472,479392721,1014,180,16.9105525498,-35.39564812586,24.51999258942,2,1,18 +2025-03-11T12:38:39.765472,479392721,1014,180,17.14117238848,-35.940796186205,24.934553585025,2,1,18 +2025-03-11T12:38:39.890472,479392721,1014,180,17.34825959056,-36.37971882524,25.27458209349,2,1,18 +2025-03-11T12:38:40.015472,479392721,1014,180,17.50357499212,-36.767776992815,25.577269929555,2,1,18 +2025-03-11T12:38:40.140472,479392721,1014,180,17.6400642844,-37.058850737885,25.800864016695,2,1,18 +2025-03-11T12:38:40.265472,479392721,1014,180,17.7341948308,-37.2759894056,25.968535670085,2,1,18 +2025-03-11T12:38:40.390472,479392721,1014,180,17.81420579524,-37.405384649615,26.089513248885,2,1,18 +2025-03-11T12:38:40.515472,479392721,1014,180,17.83303190452,-37.45619951267,26.117542373145,2,1,18 +2025-03-11T12:38:40.640472,479392721,1014,180,17.80008621328,-37.446915992375,26.09432180646,2,1,18 +2025-03-11T12:38:40.765472,479392721,1014,180,17.75302094008,-37.345272092435,26.01976271442,2,1,18 +2025-03-11T12:38:40.890472,479392721,1014,180,17.6871295576,-37.151260725935,25.866134207205,2,1,18 +2025-03-11T12:38:41.015472,479392721,1014,180,17.56475984728,-36.864825197555,25.651835251035,2,1,18 +2025-03-11T12:38:41.140472,479392721,1014,180,17.40944444572,-36.490617897815,25.372321001295,2,1,18 +2025-03-11T12:38:41.265472,479392721,1014,180,17.21177029828,-36.065560300445,25.0508663376,2,1,18 +2025-03-11T12:38:41.390472,479392721,1014,180,16.99056351424,-35.580446841215,24.655122524265,2,1,18 +2025-03-11T12:38:41.515472,479392721,1014,180,16.73641103896,-34.9844768309,24.198661865625,2,1,18 +2025-03-11T12:38:41.640472,479392721,1014,180,16.43519329048,-34.30994770037,23.69086436877,2,1,18 +2025-03-11T12:38:41.765472,479392721,1014,180,16.1104429054,-33.57536270798,23.127258190335,2,1,18 +2025-03-11T12:38:41.890472,479392721,1014,180,15.76686641104,-32.76687807281,22.493920165755,2,1,18 +2025-03-11T12:38:42.015396,479392725,1009,181,15.39505075276,-31.898330488865,21.80938338888,2,1,18 +2025-03-11T12:38:42.140396,479392725,1009,181,14.96675676664,-30.93735874304,21.068796280065,2,1,18 +2025-03-11T12:38:42.265396,479392725,1009,181,14.53846278052,-29.939451349655,20.267952980055,2,1,18 +2025-03-11T12:38:42.390396,479392725,1009,181,14.07722310316,-28.85377218491,19.43423520558,2,1,18 +2025-03-11T12:38:42.515396,479392725,1009,181,13.57362467992,-27.735710546315,18.55867435215,2,1,18 +2025-03-11T12:38:42.640396,479392725,1009,181,13.06061320204,-26.53452952688,17.64569417964,2,1,18 +2025-03-11T12:38:42.765396,479392725,1009,181,12.52877561488,-25.296384512225,16.681657299045,2,1,18 +2025-03-11T12:38:42.890396,479392725,1009,181,11.95928580916,-24.025864110635,15.685027761255,2,1,18 +2025-03-11T12:38:43.015396,479392725,1009,181,11.37567642148,-22.69991897696,14.65573483617,2,1,18 +2025-03-11T12:38:43.140396,479392725,1009,181,10.7685343972,-21.32776884926,13.607667166875,2,1,18 +2025-03-11T12:38:43.265396,479392725,1009,181,10.133153209,-19.914023596565,12.499257846255,2,1,18 +2025-03-11T12:38:43.390396,479392725,1009,181,9.50718507544,-18.47259078203,11.399963132625,2,1,18 +2025-03-11T12:38:43.515396,479392725,1009,181,8.85297777796,-16.984945886555,10.244922550935,2,1,18 +2025-03-11T12:38:43.640396,479392725,1009,181,8.19877048048,-15.50653490297,9.080690402715,2,1,18 +2025-03-11T12:38:43.765396,479392725,1009,181,7.55397623764,-13.981968533765,7.89313470738,2,1,18 +2025-03-11T12:38:43.890396,479392725,1009,181,6.89506241284,-12.44353003598,6.705475447605,2,1,18 +2025-03-11T12:38:44.015396,479392725,1009,181,6.19849636948,-10.88195006315,5.503752666195,2,1,18 +2025-03-11T12:38:44.140396,479392725,1009,181,5.50663685344,-9.329611089125,4.297468623,2,1,18 +2025-03-11T12:38:44.265396,479392725,1009,181,4.82419039204,-7.772669332985,3.091180621515,2,1,18 +2025-03-11T12:38:44.390396,479392725,1009,181,4.13703740332,-6.19725266615,1.880164980285,2,1,18 +2025-03-11T12:38:44.515396,479392725,1009,181,3.45459094192,-4.62184308623,0.66453940977,2,1,18 +2025-03-11T12:38:44.640396,479392725,1009,181,2.77214448052,-3.07413524198,-0.5370798072,2,1,18 +2025-03-11T12:38:44.765396,479392725,1009,181,2.0849914918,-1.535654222705,-1.72018007634,2,1,18 +2025-03-11T12:38:44.890396,479392725,1009,181,1.43078419432,-0.0156906356149999,-2.898491579355,2,1,18 +2025-03-11T12:38:45.015396,479392725,1009,181,0.77187036952,1.46734439083,-4.053518015025,2,1,18 +2025-03-11T12:38:45.140396,479392725,1009,181,0.136489181320001,2.936493114865,-5.189940042735,2,1,18 +2025-03-11T12:38:45.265396,479392725,1009,181,-0.50830506152,4.38718818895,-6.317044876875,2,1,18 +2025-03-11T12:38:45.390396,479392725,1009,181,-1.14368624972,5.819401265425,-7.41169118145,2,1,18 +2025-03-11T12:38:45.515396,479392725,1009,181,-1.74612174668,7.2007782181,-8.47365768156,2,1,18 +2025-03-11T12:38:45.640396,479392725,1009,181,-2.32973113436,8.526723351775,-9.49833048963,2,1,18 +2025-03-11T12:38:45.765396,479392725,1009,181,-2.89451441276,9.820321446175,-10.5135519765,2,1,18 +2025-03-11T12:38:45.890396,479392725,1009,181,-3.43105852724,11.03538876802,-11.47285725906,2,1,18 +2025-03-11T12:38:46.015350,479392729,1006,182,-3.95348305976,12.20426526967,-12.40416793884,2,1,18 +2025-03-11T12:38:46.140350,479392729,1006,182,-4.45237495568,13.354638512965,-13.27064870676,2,1,18 +2025-03-11T12:38:46.265350,479392729,1006,182,-4.91832116036,14.43570780868,-14.10897245223,2,1,18 +2025-03-11T12:38:46.390350,479392729,1006,182,-5.35602820112,15.44748024373,-14.90066889492,2,1,18 +2025-03-11T12:38:46.515350,479392729,1006,182,-5.7749091326,16.385353036,-15.641113959525,2,1,18 +2025-03-11T12:38:46.640350,479392729,1006,182,-6.17025742748,17.258553010465,-16.321105891785,2,1,18 +2025-03-11T12:38:46.765350,479392729,1006,182,-6.53266003112,18.085533817075,-16.94996188527,2,1,18 +2025-03-11T12:38:46.890350,479392729,1006,182,-6.87152999816,18.81090615832,-17.52741031044,2,1,18 +2025-03-11T12:38:47.015350,479392729,1006,182,-7.163334692,19.480804159075,-18.025922864055,2,1,18 +2025-03-11T12:38:47.140350,479392729,1006,182,-7.42690022192,20.081405299165,-18.48704834892,2,1,18 +2025-03-11T12:38:47.265350,479392729,1006,182,-7.6575200606,20.58961771195,-18.88755432348,2,1,18 +2025-03-11T12:38:47.390350,479392729,1006,182,-7.84107462608,21.0377388283,-19.236820794825,2,1,18 +2025-03-11T12:38:47.515350,479392729,1006,182,-8.00109655496,21.384251479285,-19.506958995765,2,1,18 +2025-03-11T12:38:47.640350,479392729,1006,182,-8.12346626528,21.67530396361,-19.712042051655,2,1,18 +2025-03-11T12:38:47.765350,479392729,1006,182,-8.1987707024,21.86009559205,-19.8564020328,2,1,18 +2025-03-11T12:38:47.890350,479392729,1006,182,-8.25054250292,21.961746578905,-19.954071897645,2,1,18 +2025-03-11T12:38:48.015350,479392729,1006,182,-8.28348819416,21.99873183487,-19.982058583845,2,1,18 +2025-03-11T12:38:48.140350,479392729,1006,182,-8.2693686122,21.94792405873,-19.935559179255,2,1,18 +2025-03-11T12:38:48.265350,479392729,1006,182,-8.19406417508,21.80930198974,-19.805302886655,2,1,18 +2025-03-11T12:38:48.390350,479392729,1006,182,-8.0811075194,21.58751801842,-19.637566148595,2,1,18 +2025-03-11T12:38:48.515350,479392729,1006,182,-7.9634443364,21.291855665065,-19.423228712655,2,1,18 +2025-03-11T12:38:48.640350,479392729,1006,182,-7.77988977092,20.903754976,-19.134340101255,2,1,18 +2025-03-11T12:38:48.765350,479392729,1006,182,-7.5869221508,20.42791795015,-18.780287134935,2,1,18 +2025-03-11T12:38:48.890350,479392729,1006,182,-7.36571536676,19.89663493147,-18.35657928201,2,1,18 +2025-03-11T12:38:49.015350,479392729,1006,182,-7.10685636416,19.30989174613,-17.87243640105,2,1,18 +2025-03-11T12:38:49.140350,479392729,1006,182,-6.810345143,18.626135790625,-17.364600424425,2,1,18 +2025-03-11T12:38:49.265350,479392729,1006,182,-6.47147517596,17.87306171371,-16.759285294665,2,1,18 +2025-03-11T12:38:49.390350,479392729,1006,182,-6.11377909964,17.027620170235,-16.11186168585,2,1,18 +2025-03-11T12:38:49.515350,479392729,1006,182,-5.73255038672,16.145207544625,-15.427231532265,2,1,18 +2025-03-11T12:38:49.640350,479392729,1006,182,-5.29484334596,15.18422162497,-14.672763696945,2,1,18 +2025-03-11T12:38:49.765350,479392729,1006,182,-4.84772325056,14.13549936853,-13.862371740735,2,1,18 +2025-03-11T12:38:49.890350,479392729,1006,182,-4.3629509366,13.04055085732,-13.023934243095,2,1,18 +2025-03-11T12:38:50.015274,479392733,1001,183,-3.85464598604,11.89478039614,-12.148217199435,2,1,18 +2025-03-11T12:38:50.140274,479392733,1001,183,-3.3275149262,10.70281202785,-11.23063501422,2,1,18 +2025-03-11T12:38:50.265274,479392733,1001,183,-2.79097081172,9.450809058445,-10.257274710615,2,1,18 +2025-03-11T12:38:50.390274,479392733,1001,183,-2.221481006,8.15720387713,-9.251283270045,2,1,18 +2025-03-11T12:38:50.515274,479392733,1001,183,-1.62845856368,6.82662761368,-8.198845050675,2,1,18 +2025-03-11T12:38:50.640274,479392733,1001,183,-1.0213165394,5.431392706255,-7.127555127555,2,1,18 +2025-03-11T12:38:50.765274,479392733,1001,183,-0.39534840584,4.003810759555,-6.02371329816,2,1,18 +2025-03-11T12:38:50.890274,479392733,1001,183,0.24003278236,2.54389594741,-4.891960054965,2,1,18 +2025-03-11T12:38:51.015274,479392733,1001,183,0.889533552520001,1.079342918575,-3.727811095725,2,1,18 +2025-03-11T12:38:51.140274,479392733,1001,183,1.54844737732,-0.44062775543,-2.54948940498,2,1,18 +2025-03-11T12:38:51.265274,479392733,1001,183,2.23089383872,-1.96063386401,-1.3757368926,2,1,18 +2025-03-11T12:38:51.390274,479392733,1001,183,2.90392724548,-3.48985971065,-0.178855503105,2,1,18 +2025-03-11T12:38:51.515274,479392733,1001,183,3.57696065224,-5.051404248905,1.022816339655,2,1,18 +2025-03-11T12:38:51.640274,479392733,1001,183,4.26411364096,-6.612970047905,2.21065839456,2,1,18 +2025-03-11T12:38:51.765274,479392733,1001,183,4.95126662968,-8.174535846905,3.42160103454,2,1,18 +2025-03-11T12:38:51.890274,479392733,1001,183,5.6384196184,-9.745335557795,4.637212459035,2,1,18 +2025-03-11T12:38:52.015274,479392733,1001,183,6.33498566176,-11.297681618735,5.838886572945,2,1,18 +2025-03-11T12:38:52.140274,479392733,1001,183,7.01743212316,-12.84077250704,7.049721690195,2,1,18 +2025-03-11T12:38:52.265274,479392733,1001,183,7.68105247528,-14.36998417985,8.232722353185,2,1,18 +2025-03-11T12:38:52.390274,479392733,1001,183,8.34937935472,-15.90381989552,9.406517303625,2,1,18 +2025-03-11T12:38:52.515274,479392733,1001,183,8.99417359756,-17.400684529055,10.570826411385,2,1,18 +2025-03-11T12:38:52.640274,479392733,1001,183,9.64367436772,-18.860620601945,11.69336998374,2,1,18 +2025-03-11T12:38:52.765274,479392733,1001,183,10.26964250128,-20.315904284315,12.82045840071,2,1,18 +2025-03-11T12:38:52.890274,479392733,1001,183,10.87678452556,-21.715756147685,13.91025312564,2,1,18 +2025-03-11T12:38:53.015274,479392733,1001,183,11.48863307716,-23.064828582575,14.9535891969,2,1,18 +2025-03-11T12:38:53.140274,479392733,1001,183,12.0628294102,-24.38152563053,15.96895272798,2,1,18 +2025-03-11T12:38:53.265274,479392733,1001,183,12.6276126886,-25.63818807737,16.960878959775,2,1,18 +2025-03-11T12:38:53.390274,479392733,1001,183,13.16415680308,-26.862489311105,17.90637255879,2,1,18 +2025-03-11T12:38:53.515274,479392733,1001,183,13.67716828096,-28.049819462705,18.814659613035,2,1,18 +2025-03-11T12:38:53.640274,479392733,1001,183,14.17606017688,-29.17249097033,19.671754144425,2,1,18 +2025-03-11T12:38:53.765274,479392733,1001,183,14.64671290888,-30.22586561729,20.48684149005,2,1,18 +2025-03-11T12:38:53.890274,479392733,1001,183,15.08441994964,-31.21917022856,21.264580246695,2,1,18 +2025-03-11T12:38:54.015213,479392737,997,184,15.4985943538,-32.15241897797,21.9680298537,2,1,18 +2025-03-11T12:38:54.140213,479392737,997,184,15.86570348476,-33.016342519055,22.63867175805,2,1,18 +2025-03-11T12:38:54.265213,479392737,997,184,16.21398650644,-33.801749461415,23.27189830161,2,1,18 +2025-03-11T12:38:54.390213,479392737,997,184,16.52932383688,-34.527086368085,23.826195203055,2,1,18 +2025-03-11T12:38:54.515213,479392737,997,184,16.81171547608,-35.16926845934,24.329161495725,2,1,18 +2025-03-11T12:38:54.640213,479392737,997,184,17.06116142404,-35.732912691125,24.77158127934,2,1,18 +2025-03-11T12:38:54.765213,479392737,997,184,17.27766168076,-36.19955123966,25.13487675084,2,1,18 +2025-03-11T12:38:54.890213,479392737,997,184,17.46121624624,-36.61997062034,25.46089663461,2,1,18 +2025-03-11T12:38:55.015213,479392737,997,184,17.63535775708,-36.971121488015,25.717229381445,2,1,18 +2025-03-11T12:38:55.140213,479392737,997,184,17.72948830348,-37.211344935455,25.90812328866,2,1,18 +2025-03-11T12:38:55.265213,479392737,997,184,17.80008621328,-37.3776616532,26.05699586409,2,1,18 +2025-03-11T12:38:55.390213,479392737,997,184,17.83773843184,-37.465440511475,26.117601228375,2,1,18 +2025-03-11T12:38:55.515213,479392737,997,184,17.8518580138,-37.470078728165,26.1130360083,2,1,18 +2025-03-11T12:38:55.640213,479392737,997,184,17.8283253772,-37.400788954415,26.05717865922,2,1,18 +2025-03-11T12:38:55.765213,479392737,997,184,17.76243399472,-37.24833019142,25.940730091875,2,1,18 +2025-03-11T12:38:55.890213,479392737,997,184,17.65889039368,-37.01732648204,25.75910471073,2,1,18 +2025-03-11T12:38:56.015213,479392737,997,184,17.5224011014,-36.68931708941,25.5075952515,2,1,18 +2025-03-11T12:38:56.140213,479392737,997,184,17.34825959056,-36.27814579445,25.19088464472,2,1,18 +2025-03-11T12:38:56.265213,479392737,997,184,17.12705280652,-35.806883203055,24.832174768755,2,1,18 +2025-03-11T12:38:56.390213,479392737,997,184,16.86819380392,-35.24322479744,24.403594960725,2,1,18 +2025-03-11T12:38:56.515213,479392737,997,184,16.59992174668,-34.60106396693,23.909899465275,2,1,18 +2025-03-11T12:38:56.640213,479392737,997,184,16.29399747088,-33.91267688165,23.341957258245,2,1,18 +2025-03-11T12:38:56.765213,479392737,997,184,15.95983403116,-33.118057288145,22.74105342948,2,1,18 +2025-03-11T12:38:56.890213,479392737,997,184,15.58331184556,-32.26335348512,22.075059934185,2,1,18 +2025-03-11T12:38:57.015213,479392737,997,184,15.17855049604,-31.343969777375,21.37170370389,2,1,18 +2025-03-11T12:38:57.140213,479392737,997,184,14.7455499826,-30.364523120855,20.6171487213,2,1,18 +2025-03-11T12:38:57.265213,479392737,997,184,14.30313641452,-29.32504186322,19.792955269275,2,1,18 +2025-03-11T12:38:57.390213,479392737,997,184,13.81365757324,-28.202384529425,18.926640879315,2,1,18 +2025-03-11T12:38:57.515213,479392737,997,184,13.29123304072,-27.04735889561,18.041604370935,2,1,18 +2025-03-11T12:38:57.640213,479392737,997,184,12.75468892624,-25.82767461782,17.091514988655,2,1,18 +2025-03-11T12:38:57.765213,479392737,997,184,12.19931870248,-24.54332460914,16.10870336385,2,1,18 +2025-03-11T12:38:57.890213,479392737,997,184,11.62512236944,-23.23124451713,15.088744049505,2,1,18 +2025-03-11T12:38:58.015136,479392741,992,185,11.0273933998,-21.882193342985,14.036198307405,2,1,18 +2025-03-11T12:38:58.140136,479392741,992,185,10.42025137552,-20.491575391505,12.95107236699,2,1,18 +2025-03-11T12:38:58.265136,479392741,992,185,9.78487018732,-19.04089449125,11.8517086104,2,1,18 +2025-03-11T12:38:58.390136,479392741,992,185,9.1447824718,-17.604057371915,10.70620649718,2,1,18 +2025-03-11T12:38:58.515136,479392741,992,185,8.49528170164,-16.10256869552,9.564963453015,2,1,18 +2025-03-11T12:38:58.640136,479392741,992,185,7.8269548222,-14.59643471552,8.38669438806,2,1,18 +2025-03-11T12:38:58.765136,479392741,992,185,7.1445083608,-13.053343827215,7.198959855885,2,1,18 +2025-03-11T12:38:58.890136,479392741,992,185,6.47147495404,-11.51026711274,6.015865816185,2,1,18 +2025-03-11T12:38:59.015136,479392741,992,185,5.79844154728,-9.948722574485,4.80033362238,2,1,18 +2025-03-11T12:38:59.140136,479392741,992,185,5.10658203124,-8.391766644515,3.575544777375,2,1,18 +2025-03-11T12:38:59.265136,479392741,992,185,4.42413556984,-6.825590976485,2.35996787436,2,1,18 +2025-03-11T12:38:59.390136,479392741,992,185,3.7322760538,-5.268635046515,1.16751984846,2,1,18 +2025-03-11T12:38:59.515136,479392741,992,185,3.04512306508,-3.697835335625,-0.0434714590200005,2,1,18 +2025-03-11T12:38:59.640136,479392741,992,185,2.37679618564,-2.15014875212,-1.25430034683,2,1,18 +2025-03-11T12:38:59.765136,479392741,992,185,1.7084693062,-0.630163904285,-2.45574299811,2,1,18 +2025-03-11T12:38:59.890136,479392741,992,185,1.04014242676,0.885203987605001,-3.62944061355,2,1,18 +2025-03-11T12:39:00.015136,479392741,992,185,0.37652207464,2.36362914502,-4.77521266917,2,1,18 +2025-03-11T12:39:00.140136,479392741,992,185,-0.25415258624,3.818919914305,-5.897691156855,2,1,18 +2025-03-11T12:39:00.265136,479392741,992,185,-0.880120719800001,5.246501861005,-6.987672635205,2,1,18 +2025-03-11T12:39:00.390136,479392741,992,185,-1.52020843532,6.641786376835,-8.05441375542,2,1,18 +2025-03-11T12:39:00.515136,479392741,992,185,-2.10852435032,7.967738597425,-9.11605768734,2,1,18 +2025-03-11T12:39:00.640136,479392741,992,185,-2.67330762872,9.28442147155,-10.1129203749,2,1,18 +2025-03-11T12:39:00.765136,479392741,992,185,-3.2333843798,10.541076831475,-11.09097606792,2,1,18 +2025-03-11T12:39:00.890136,479392741,992,185,-3.751102385,11.751498849715,-12.03173579775,2,1,18 +2025-03-11T12:39:01.015136,479392741,992,185,-4.25940733556,12.897269310895,-12.930553426485,2,1,18 +2025-03-11T12:39:01.140136,479392741,992,185,-4.74888617684,14.0106927328,-13.769098446855,2,1,18 +2025-03-11T12:39:01.265136,479392741,992,185,-5.20071279956,15.040954252375,-14.570163021765,2,1,18 +2025-03-11T12:39:01.390136,479392741,992,185,-5.62900678568,15.997309042255,-15.33844649892,2,1,18 +2025-03-11T12:39:01.515136,479392741,992,185,-6.03847466252,16.888998101245,-16.041666914445,2,1,18 +2025-03-11T12:39:01.640136,479392741,992,185,-6.41499684812,17.75293581616,-16.684608492165,2,1,18 +2025-03-11T12:39:01.765136,479392741,992,185,-6.74445376052,18.51984658708,-17.2853561307,2,1,18 +2025-03-11T12:39:01.890136,479392741,992,185,-7.045671509,19.21284354139,-17.82559178166,2,1,18 +2025-03-11T12:39:02.015075,479392745,988,186,-7.32335662088,19.859635501675,-18.323952103335,2,1,18 +2025-03-11T12:39:02.140075,479392745,988,186,-7.5633895142,20.390946868015,-18.74770070718,2,1,18 +2025-03-11T12:39:02.265075,479392745,988,186,-7.76577018896,20.85294719986,-19.115561398755,2,1,18 +2025-03-11T12:39:02.390075,479392745,988,186,-7.9399116998,21.241033715095,-19.39980951768,2,1,18 +2025-03-11T12:39:02.515075,479392745,988,186,-8.07169446476,21.564419064865,-19.65128445543,2,1,18 +2025-03-11T12:39:02.640075,479392745,988,186,-8.16111848384,21.78616760161,-19.823590371855,2,1,18 +2025-03-11T12:39:02.765075,479392745,988,186,-8.24112944828,21.94788153724,-19.907777350785,2,1,18 +2025-03-11T12:39:02.890075,479392745,988,186,-8.2693686122,22.00332753007,-19.96819200336,2,1,18 +2025-03-11T12:39:03.015075,479392745,988,186,-8.25054250292,21.970980490795,-19.94950044813,2,1,18 +2025-03-11T12:39:03.140075,479392745,988,186,-8.21289028436,21.860116852795,-19.861052713005,2,1,18 +2025-03-11T12:39:03.265075,479392745,988,186,-8.13758584724,21.66147435652,-19.71661973061,2,1,18 +2025-03-11T12:39:03.390075,479392745,988,186,-8.03874877352,21.39815904244,-19.525593966915,2,1,18 +2025-03-11T12:39:03.515075,479392745,988,186,-7.88813989928,21.070128389065,-19.26019359345,2,1,18 +2025-03-11T12:39:03.640075,479392745,988,186,-7.69987880648,20.645084965525,-18.94337942223,2,1,18 +2025-03-11T12:39:03.765075,479392745,988,186,-7.48808507708,20.1369009004,-18.556774549635,2,1,18 +2025-03-11T12:39:03.890075,479392745,988,186,-7.23863912912,19.545554932945,-18.100348412475,2,1,18 +2025-03-11T12:39:04.015075,479392745,988,186,-6.93742138064,18.91257840592,-17.58352968534,2,1,18 +2025-03-11T12:39:04.140075,479392745,988,186,-6.62679057752,18.18263163022,-17.019978403845,2,1,18 +2025-03-11T12:39:04.265075,479392745,988,186,-6.28321408316,17.37414699505,-16.39126049628,2,1,18 +2025-03-11T12:39:04.390075,479392745,988,186,-5.91139842488,16.51021636705,-15.734468755245,2,1,18 +2025-03-11T12:39:04.515075,479392745,988,186,-5.49722402072,15.572350661695,-14.998653995385,2,1,18 +2025-03-11T12:39:04.640075,479392745,988,186,-5.04069087068,14.56516683493,-14.2300417206,2,1,18 +2025-03-11T12:39:04.765075,479392745,988,186,-4.574744666,13.51641623083,-13.41036877944,2,1,18 +2025-03-11T12:39:04.890075,479392745,988,186,-4.08526582472,12.3799080292,-12.52550092017,2,1,18 +2025-03-11T12:39:05.015075,479392745,988,186,-3.56754781952,11.211038614465,-11.608060779165,2,1,18 +2025-03-11T12:39:05.140075,479392745,988,186,-3.0215906504,9.982106250955,-10.657902353925,2,1,18 +2025-03-11T12:39:05.265075,479392745,988,186,-2.46151389932,8.69774915536,-9.661220190345,2,1,18 +2025-03-11T12:39:05.390075,479392745,988,186,-1.868491457,7.34870506813,-8.627165104035,2,1,18 +2025-03-11T12:39:05.515075,479392745,988,186,-1.27546901468,5.99042706901,-7.56072053112,2,1,18 +2025-03-11T12:39:05.640075,479392745,988,186,-0.64950088112,4.585929902035,-6.475480838535,2,1,18 +2025-03-11T12:39:05.765075,479392745,988,186,-0.0188262202400002,3.13063913275,-5.35300235085,2,1,18 +2025-03-11T12:39:05.890075,479392745,988,186,0.60714191332,1.68458936227,-4.212102250335,2,1,18 +2025-03-11T12:39:06.015014,479392749,984,187,1.27076226544,0.18307942513,-3.06158840895,2,1,18 +2025-03-11T12:39:06.140014,479392749,984,187,1.94850219952,-1.34153655248,-1.88782175055,2,1,18 +2025-03-11T12:39:06.265014,479392749,984,187,2.62153560628,-2.87076239912,-0.7048007121,2,1,18 +2025-03-11T12:39:06.390014,479392749,984,187,3.29927554036,-4.4230801124,0.48759241686,2,1,18 +2025-03-11T12:39:06.515014,479392749,984,187,3.98642852908,-5.99387982329,1.703203841355,2,1,18 +2025-03-11T12:39:06.640014,479392749,984,187,4.6735815178,-7.5462117104,2.914097813835,2,1,18 +2025-03-11T12:39:06.765014,479392749,984,187,5.37014756116,-9.103174727285,4.1481370806,2,1,18 +2025-03-11T12:39:06.890014,479392749,984,187,6.04788749524,-10.6693433084,5.345223327825,2,1,18 +2025-03-11T12:39:07.015014,479392749,984,187,6.73504048396,-12.235526063345,6.54232995051,2,1,18 +2025-03-11T12:39:07.140014,479392749,984,187,7.41278041804,-13.78322682068,7.748559096765,2,1,18 +2025-03-11T12:39:07.265014,479392749,984,187,8.07169424284,-15.28934662685,8.940668137305,2,1,18 +2025-03-11T12:39:07.390014,479392749,984,187,8.73060806764,-16.80470034491,10.095864909225,2,1,18 +2025-03-11T12:39:07.515014,479392749,984,187,9.3801088378,-18.27387032969,11.24617785117,2,1,18 +2025-03-11T12:39:07.640014,479392749,984,187,10.02490308064,-19.72918235972,12.37330701906,2,1,18 +2025-03-11T12:39:07.765014,479392749,984,187,10.64616468688,-21.12443852789,13.458487856415,2,1,18 +2025-03-11T12:39:07.890014,479392749,984,187,11.25330671116,-22.49658865559,14.529656110785,2,1,18 +2025-03-11T12:39:08.015014,479392749,984,187,11.82279651688,-23.845597308245,15.563660258445,2,1,18 +2025-03-11T12:39:08.140014,479392749,984,187,12.3922863226,-25.153053357395,16.56510458325,2,1,18 +2025-03-11T12:39:08.265014,479392749,984,187,12.94295001904,-26.39122671971,17.510701746705,2,1,18 +2025-03-11T12:39:08.390014,479392749,984,187,13.46066802424,-27.56471309039,18.43740645549,2,1,18 +2025-03-11T12:39:08.515014,479392749,984,187,13.97367950212,-28.68740585876,19.326872369175,2,1,18 +2025-03-11T12:39:08.640014,479392749,984,187,14.4396257068,-29.76385819853,20.16055166388,2,1,18 +2025-03-11T12:39:08.765014,479392749,984,187,14.89145232952,-30.78950276216,20.947731553995,2,1,18 +2025-03-11T12:39:08.890014,479392749,984,187,15.310333261,-31.759694246045,21.683726837835,2,1,18 +2025-03-11T12:39:09.015014,479392749,984,187,15.69626850124,-32.646730914515,22.3683915129,2,1,18 +2025-03-11T12:39:09.140014,479392749,984,187,16.0633776322,-33.478335763985,23.006522261895,2,1,18 +2025-03-11T12:39:09.265014,479392749,984,187,16.38812801728,-34.21753771232,23.58863324214,2,1,18 +2025-03-11T12:39:09.390014,479392749,984,187,16.68934576576,-34.90130075474,24.114959874555,2,1,18 +2025-03-11T12:39:09.515014,479392749,984,187,16.957617823,-35.50652593769,24.58536011493,2,1,18 +2025-03-11T12:39:09.640014,479392749,984,187,17.20706377096,-36.024000610025,24.990575624925,2,1,18 +2025-03-11T12:39:09.765014,479392749,984,187,17.40944444572,-36.472150074035,25.335262730175,2,1,18 +2025-03-11T12:39:09.890014,479392749,984,187,17.55534679264,-36.83249233211,25.605443369175,2,1,18 +2025-03-11T12:39:10.014953,479392753,980,188,17.67771650296,-37.11892786049,25.828982559375,2,1,18 +2025-03-11T12:39:10.139953,479392753,980,188,17.76714052204,-37.312974661565,25.99190223927,2,1,18 +2025-03-11T12:39:10.264953,479392753,980,188,17.82361884988,-37.43771751506,26.07584360955,2,1,18 +2025-03-11T12:39:10.389953,479392753,980,188,17.83773843184,-37.483908335255,26.117698563375,2,1,18 +2025-03-11T12:39:10.514953,479392753,980,188,17.84715148648,-37.45160381747,26.08520778348,2,1,18 +2025-03-11T12:39:10.639953,479392753,980,188,17.78596663132,-37.322236921115,25.996611774705,2,1,18 +2025-03-11T12:39:10.764953,479392753,980,188,17.67771650296,-37.10046003671,25.838125458405,2,1,18 +2025-03-11T12:39:10.889953,479392753,980,188,17.57417290192,-36.809435900045,25.614602685375,2,1,18 +2025-03-11T12:39:11.014953,479392753,980,188,17.41415097304,-36.43522151339,25.325838013875,2,1,18 +2025-03-11T12:39:11.139953,479392753,980,188,17.20235724364,-36.010142655275,24.981252201915,2,1,18 +2025-03-11T12:39:11.264953,479392753,980,188,16.96703087764,-35.483455331795,24.57601858761,2,1,18 +2025-03-11T12:39:11.389953,479392753,980,188,16.70817187504,-34.878244322675,24.11025883971,2,1,18 +2025-03-11T12:39:11.514953,479392753,980,188,16.41166065388,-34.19448836717,23.565461926965,2,1,18 +2025-03-11T12:39:11.639953,479392753,980,188,16.09632332344,-33.446066680775,22.98332265468,2,1,18 +2025-03-11T12:39:11.764953,479392753,980,188,15.72921419248,-32.61907878725,22.335976005405,2,1,18 +2025-03-11T12:39:11.889953,479392753,980,188,15.34798547956,-31.73666616164,21.63286538376,2,1,18 +2025-03-11T12:39:12.014953,479392753,980,188,14.9338110754,-30.780332632505,20.901573405915,2,1,18 +2025-03-11T12:39:12.139953,479392753,980,188,14.47727792536,-29.740830114125,20.109690209805,2,1,18 +2025-03-11T12:39:12.264953,479392753,980,188,13.99721213872,-28.659739557665,19.262095667115,2,1,18 +2025-03-11T12:39:12.389953,479392753,980,188,13.50302677012,-27.527841225065,18.40034253894,2,1,18 +2025-03-11T12:39:12.514953,479392753,980,188,12.9806022376,-26.33587994369,17.455049839365,2,1,18 +2025-03-11T12:39:12.639953,479392753,980,188,12.42523201384,-25.07923167068,16.486244568105,2,1,18 +2025-03-11T12:39:12.764953,479392753,980,188,11.84632915348,-23.776378403645,15.480184084575,2,1,18 +2025-03-11T12:39:12.889953,479392753,980,188,11.27213282044,-22.43197962002,14.446194082935,2,1,18 +2025-03-11T12:39:13.014953,479392753,980,188,10.66499079616,-21.045978624485,13.38881317836,2,1,18 +2025-03-11T12:39:13.139953,479392753,980,188,10.04843571724,-19.627644763505,12.275800157895,2,1,18 +2025-03-11T12:39:13.264953,479392753,980,188,9.41305452904,-18.19543168703,11.18115385332,2,1,18 +2025-03-11T12:39:13.389953,479392753,980,188,8.77296681352,-16.72627587608,10.030861286835,2,1,18 +2025-03-11T12:39:13.514953,479392753,980,188,8.12346604336,-15.215553287795,8.857228756065,2,1,18 +2025-03-11T12:39:13.639953,479392753,980,188,7.4504326366,-13.677093529265,7.674159050115,2,1,18 +2025-03-11T12:39:13.764953,479392753,980,188,6.77269270252,-12.14786059571,6.472647355875,2,1,18 +2025-03-11T12:39:13.889953,479392753,980,188,6.07612665916,-10.581663666935,5.25703988967,2,1,18 +2025-03-11T12:39:14.014877,479392757,975,189,5.39368019776,-9.033955822685,4.0554206727,2,1,18 +2025-03-11T12:39:14.139877,479392757,975,189,4.71123373636,-7.467780154655,2.849084003715,2,1,18 +2025-03-11T12:39:14.264877,479392757,975,189,4.02408074764,-5.896980443765,1.638092696235,2,1,18 +2025-03-11T12:39:14.389877,479392757,975,189,3.33692775892,-4.344648556655,0.43181884077,2,1,18 +2025-03-11T12:39:14.514877,479392757,975,189,2.65918782484,-2.79694779932,-0.765170071455,2,1,18 +2025-03-11T12:39:14.639877,479392757,975,189,1.9908609454,-1.25387817176,-1.948253923425,2,1,18 +2025-03-11T12:39:14.764877,479392757,975,189,1.31782753864,0.256879851100001,-3.131177626875,2,1,18 +2025-03-11T12:39:14.889877,479392757,975,189,0.654207186520001,1.75838978824,-4.295551819305,2,1,18 +2025-03-11T12:39:15.014877,479392757,975,189,0.0188259983200005,3.199836776605,-5.422587610485,2,1,18 +2025-03-11T12:39:15.139877,479392757,975,189,-0.60243560792,4.65511337206,-6.531185371665,2,1,18 +2025-03-11T12:39:15.264877,479392757,975,189,-1.22369721416,6.05960345212,-7.630275227565,2,1,18 +2025-03-11T12:39:15.389877,479392757,975,189,-1.8449588204,7.422540928675,-8.701425377625,2,1,18 +2025-03-11T12:39:15.514877,479392757,975,189,-2.4332747354,8.757727061155,-9.707676572865,2,1,18 +2025-03-11T12:39:15.639877,479392757,975,189,-2.98393843184,10.04206998292,-10.708958478,2,1,18 +2025-03-11T12:39:15.764877,479392757,975,189,-3.52989560096,11.27100234643,-11.663737020255,2,1,18 +2025-03-11T12:39:15.889877,479392757,975,189,-4.04761360616,12.449105673055,-12.585845945775,2,1,18 +2025-03-11T12:39:16.014877,479392757,975,189,-4.54650550208,13.567160224735,-13.44753626043,2,1,18 +2025-03-11T12:39:16.139877,479392757,975,189,-5.01715823408,14.63438573953,-14.26731672432,2,1,18 +2025-03-11T12:39:16.264877,479392757,975,189,-5.46427832948,15.63693843652,-15.04050440691,2,1,18 +2025-03-11T12:39:16.389877,479392757,975,189,-5.86433315168,16.54708114546,-15.762282250035,2,1,18 +2025-03-11T12:39:16.514877,479392757,975,189,-6.24085533728,17.41563581632,-16.44682921464,2,1,18 +2025-03-11T12:39:16.639877,479392757,975,189,-6.5985514136,18.233375624125,-17.07100623588,2,1,18 +2025-03-11T12:39:16.764877,479392757,975,189,-6.928008326,18.963350747485,-17.625358034265,2,1,18 +2025-03-11T12:39:16.889877,479392757,975,189,-7.21981301984,19.61478092446,-18.11453301885,2,1,18 +2025-03-11T12:39:17.014877,479392757,975,189,-7.47396549512,20.18766615505,-18.57087200874,2,1,18 +2025-03-11T12:39:17.139877,479392757,975,189,-7.6810526972,20.681992265425,-18.948153458325,2,1,18 +2025-03-11T12:39:17.264877,479392757,975,189,-7.85990073536,21.107021515135,-19.274187488115,2,1,18 +2025-03-11T12:39:17.389877,479392757,975,189,-8.01521613692,21.43967621137,-19.535002266045,2,1,18 +2025-03-11T12:39:17.514877,479392757,975,189,-8.11875973796,21.693764700475,-19.739849901015,2,1,18 +2025-03-11T12:39:17.639877,479392757,975,189,-8.20347722972,21.878570502745,-19.888850374635,2,1,18 +2025-03-11T12:39:17.764877,479392757,975,189,-8.25524903024,21.9802214896,-19.963419654405,2,1,18 +2025-03-11T12:39:17.889877,479392757,975,189,-8.25995555756,21.98484553246,-19.972694409915,2,1,18 +2025-03-11T12:39:18.014816,479392761,971,190,-8.23642292096,21.929406626545,-19.9215301791,2,1,18 +2025-03-11T12:39:18.139816,479392761,971,190,-8.17994459312,21.772345081435,-19.795837419435,2,1,18 +2025-03-11T12:39:18.264816,479392761,971,190,-8.07640099208,21.52749050422,-19.62337927107,2,1,18 +2025-03-11T12:39:18.389816,479392761,971,190,-7.9399116998,21.24565067104,-19.376733266355,2,1,18 +2025-03-11T12:39:18.514816,479392761,971,190,-7.77047671628,20.852954286775,-19.060130182305,2,1,18 +2025-03-11T12:39:18.639816,479392761,971,190,-7.55868298688,20.38170586921,-18.71068091583,2,1,18 +2025-03-11T12:39:18.764816,479392761,971,190,-7.33747620284,19.82272111486,-18.26372647533,2,1,18 +2025-03-11T12:39:18.889816,479392761,971,190,-7.06449761828,19.18517015338,-17.77928535993,2,1,18 +2025-03-11T12:39:19.014816,479392761,971,190,-6.73033417856,18.47827272283,-17.243525510625,2,1,18 +2025-03-11T12:39:19.139816,479392761,971,190,-6.40087726616,17.725212819745,-16.64285087334,2,1,18 +2025-03-11T12:39:19.264816,479392761,971,190,-6.04318118984,16.87977127627,-15.986187030495,2,1,18 +2025-03-11T12:39:19.389816,479392761,971,190,-5.62430025836,15.964983263725,-15.278204453745,2,1,18 +2025-03-11T12:39:19.514816,479392761,971,190,-5.20071279956,14.99016773698,-14.523694180365,2,1,18 +2025-03-11T12:39:19.639816,479392761,971,190,-4.74417964952,13.9506652186,-13.713330516195,2,1,18 +2025-03-11T12:39:19.764816,479392761,971,190,-4.2688203902,12.851113925275,-12.856408592205,2,1,18 +2025-03-11T12:39:19.889816,479392761,971,190,-3.75580891232,11.69610246529,-11.952911991225,2,1,18 +2025-03-11T12:39:20.014816,479392761,971,190,-3.22397132516,10.48104223036,-11.03519794953,2,1,18 +2025-03-11T12:39:20.139816,479392761,971,190,-2.67801415604,9.229025087125,-10.07567762151,2,1,18 +2025-03-11T12:39:20.264816,479392761,971,190,-2.103817823,7.90309412728,-9.0510251889,2,1,18 +2025-03-11T12:39:20.389816,479392761,971,190,-1.515501908,6.54944017102,-7.99847548851,2,1,18 +2025-03-11T12:39:20.514816,479392761,971,190,-0.9036533564,5.168049044515,-6.89952767682,2,1,18 +2025-03-11T12:39:20.639816,479392761,971,190,-0.272978695519999,3.74969392279,-5.823445029285,2,1,18 +2025-03-11T12:39:20.764816,479392761,971,190,0.371815547320001,2.28514798087,-4.69164707688,2,1,18 +2025-03-11T12:39:20.889816,479392761,971,190,1.01660979016,0.797517259225,-3.532006753635,2,1,18 +2025-03-11T12:39:21.014816,479392761,971,190,1.67081708764,-0.713212415975001,-2.358364035135,2,1,18 +2025-03-11T12:39:21.139816,479392761,971,190,2.34855702172,-2.24244534953,-1.17995292597,2,1,18 +2025-03-11T12:39:21.264816,479392761,971,190,3.0262969558,-3.780912194975,0.00774708472500008,2,1,18 +2025-03-11T12:39:21.389816,479392761,971,190,3.7087434172,-5.33323699517,1.20477051843,2,1,18 +2025-03-11T12:39:21.514816,479392761,971,190,4.38648335128,-6.90402253223,2.448082269555,2,1,18 +2025-03-11T12:39:21.639816,479392761,971,190,5.06892981268,-8.47019820026,3.6728994066,2,1,18 +2025-03-11T12:39:21.764816,479392761,971,190,5.76549585604,-10.036395129035,4.87464652176,2,1,18 +2025-03-11T12:39:21.889816,479392761,971,190,6.45264884476,-11.597960928035,6.05786845965,2,1,18 +2025-03-11T12:39:22.014740,479392765,966,191,7.13509530616,-13.14105181634,7.25946334287,2,1,18 +2025-03-11T12:39:22.139740,479392765,966,191,7.81754176756,-14.656440968975,8.456292106575,2,1,18 +2025-03-11T12:39:22.264740,479392765,966,191,8.4623360104,-16.19024125007,9.630036118365,2,1,18 +2025-03-11T12:39:22.389740,479392765,966,191,9.1212498352,-17.68712714435,10.78051543827,2,1,18 +2025-03-11T12:39:22.514740,479392765,966,191,9.7566310234,-19.137808044605,11.893739545905,2,1,18 +2025-03-11T12:39:22.639740,479392765,966,191,10.37318610232,-20.56999277342,13.011445684635,2,1,18 +2025-03-11T12:39:22.764740,479392765,966,191,10.99444770856,-21.960631985645,14.101222305255,2,1,18 +2025-03-11T12:39:22.889740,479392765,966,191,11.60629626016,-23.2958535527,15.16758596034,2,1,18 +2025-03-11T12:39:23.014740,479392765,966,191,12.18990564784,-24.62641564232,16.169182517085,2,1,18 +2025-03-11T12:39:23.139740,479392765,966,191,12.74998239892,-25.90615578197,17.147359878855,2,1,18 +2025-03-11T12:39:23.264740,479392765,966,191,13.2865265134,-27.102755280035,18.08346724134,2,1,18 +2025-03-11T12:39:23.389740,479392765,966,191,13.78541840932,-28.266979391165,18.982361829615,2,1,18 +2025-03-11T12:39:23.514740,479392765,966,191,14.27019072328,-29.36654485832,19.85316448011,2,1,18 +2025-03-11T12:39:23.639740,479392765,966,191,14.73143040064,-30.424522287395,20.66363566701,2,1,18 +2025-03-11T12:39:23.764740,479392765,966,191,15.1691374414,-31.40397603083,21.432061188375,2,1,18 +2025-03-11T12:39:23.889740,479392765,966,191,15.57389879092,-32.32797669452,22.11696128436,2,1,18 +2025-03-11T12:39:24.014740,479392765,966,191,15.94100792188,-33.164198499935,22.77821695218,2,1,18 +2025-03-11T12:39:24.139740,479392765,966,191,16.28458441624,-33.944981399435,23.38368827217,2,1,18 +2025-03-11T12:39:24.264740,479392765,966,191,16.59992174668,-34.66570135016,23.93334072285,2,1,18 +2025-03-11T12:39:24.389740,479392765,966,191,16.87290033124,-35.26631666408,24.42682740228,2,1,18 +2025-03-11T12:39:24.514740,479392765,966,191,17.10822669724,-35.825322679175,24.841471586865,2,1,18 +2025-03-11T12:39:24.639740,479392765,966,191,17.3341400086,-36.31044322532,25.204884768825,2,1,18 +2025-03-11T12:39:24.764740,479392765,966,191,17.51298804676,-36.693919871525,25.51683944382,2,1,18 +2025-03-11T12:39:24.889740,479392765,966,191,17.65418386636,-37.008085483235,25.74980562147,2,1,18 +2025-03-11T12:39:25.014740,479392765,966,191,17.7577274674,-37.248323104505,25.93609978713,2,1,18 +2025-03-11T12:39:25.139740,479392765,966,191,17.8283253772,-37.400788954415,26.052558542205,2,1,18 +2025-03-11T12:39:25.264740,479392765,966,191,17.8753906504,-37.465497206795,26.108442496185,2,1,18 +2025-03-11T12:39:25.389740,479392765,966,191,17.8518580138,-37.46546177222,26.108391557535,2,1,18 +2025-03-11T12:39:25.514740,479392765,966,191,17.81891232256,-37.382306956805,26.0385804807,2,1,18 +2025-03-11T12:39:25.639740,479392765,966,191,17.75302094008,-37.20214645814,25.903505442795,2,1,18 +2025-03-11T12:39:25.764740,479392765,966,191,17.63535775708,-36.952653664235,25.68479122734,2,1,18 +2025-03-11T12:39:25.889740,479392765,966,191,17.4988684648,-36.62002731566,25.4147769663,2,1,18 +2025-03-11T12:39:26.014694,479392769,963,192,17.31531389932,-36.19037402309,25.10718888309,2,1,18 +2025-03-11T12:39:26.139694,479392769,963,192,17.0988136426,-35.705267650775,24.720695491515,2,1,18 +2025-03-11T12:39:26.264694,479392769,963,192,16.85407422196,-35.132396594015,24.282857345145,2,1,18 +2025-03-11T12:39:26.389694,479392769,963,192,16.5575630008,-34.47634237418,23.789027722065,2,1,18 +2025-03-11T12:39:26.514694,479392769,963,192,16.24222567036,-33.75100546751,23.220870469575,2,1,18 +2025-03-11T12:39:26.639694,479392769,963,192,15.89394264868,-32.98406634893,22.60160161206,2,1,18 +2025-03-11T12:39:26.764694,479392769,963,192,15.50330088112,-32.08317172571,21.944574450105,2,1,18 +2025-03-11T12:39:26.889694,479392769,963,192,15.08912647696,-31.16839080008,21.218121593025,2,1,18 +2025-03-11T12:39:27.014694,479392769,963,192,14.65612596352,-30.17971023167,20.44041735786,2,1,18 +2025-03-11T12:39:27.139694,479392769,963,192,14.18547323152,-29.10786776093,19.62985279425,2,1,18 +2025-03-11T12:39:27.264694,479392769,963,192,13.70070091756,-27.97598360216,18.76349992452,2,1,18 +2025-03-11T12:39:27.389694,479392769,963,192,13.18298291236,-26.788646363645,17.85058256553,2,1,18 +2025-03-11T12:39:27.514694,479392769,963,192,12.66055837984,-25.573600302545,16.91902854825,2,1,18 +2025-03-11T12:39:27.639694,479392769,963,192,12.09577510144,-24.30308698787,15.91316896416,2,1,18 +2025-03-11T12:39:27.764694,479392769,963,192,11.51687224108,-22.990999808945,14.883959228055,2,1,18 +2025-03-11T12:39:27.889694,479392769,963,192,10.92384979876,-21.614253986045,13.82665755417,2,1,18 +2025-03-11T12:39:28.014694,479392769,963,192,10.31200124716,-20.219011991705,12.750737326305,2,1,18 +2025-03-11T12:39:28.139694,479392769,963,192,9.66720700432,-18.76831691762,11.62825260918,2,1,18 +2025-03-11T12:39:28.264694,479392769,963,192,9.03653234344,-17.285324412665,10.49176776795,2,1,18 +2025-03-11T12:39:28.389694,479392769,963,192,8.368205464,-15.82074303617,9.341438408835,2,1,18 +2025-03-11T12:39:28.514694,479392769,963,192,7.70458511188,-14.30076527525,8.16310653036,2,1,18 +2025-03-11T12:39:28.639694,479392769,963,192,7.05508434172,-12.76695790724,6.966251745765,2,1,18 +2025-03-11T12:39:28.764694,479392769,963,192,6.37734440764,-11.20540628207,5.764569715275,2,1,18 +2025-03-11T12:39:28.889694,479392769,963,192,5.67607183696,-9.671520957995,4.54912239759,2,1,18 +2025-03-11T12:39:29.014694,479392769,963,192,4.96538621164,-8.10991972442,3.333508701945,2,1,18 +2025-03-11T12:39:29.139694,479392769,963,192,4.29235280488,-6.54375823022,2.131812525435,2,1,18 +2025-03-11T12:39:29.264694,479392769,963,192,3.6146128708,-4.977589649105,0.91624581015,2,1,18 +2025-03-11T12:39:29.389694,479392769,963,192,2.94157946404,-3.429895978685,-0.299213382405001,2,1,18 +2025-03-11T12:39:29.514694,479392769,963,192,2.25913300264,-1.88680509038,-1.473087563535,2,1,18 +2025-03-11T12:39:29.639694,479392769,963,192,1.58609959588,-0.36681315563,-2.646819700455,2,1,18 +2025-03-11T12:39:29.764694,479392769,963,192,0.91777271644,1.143937780315,-3.802012514085,2,1,18 +2025-03-11T12:39:29.889694,479392769,963,192,0.28239152824,2.62232041624,-4.95234356034,2,1,18 +2025-03-11T12:39:30.014618,479392773,958,193,-0.357696187279999,4.07300840341,-6.084058323765,2,1,18 +2025-03-11T12:39:30.139618,479392773,958,193,-1.00719695744,5.491391872795,-7.192522541325,2,1,18 +2025-03-11T12:39:30.264618,479392773,958,193,-1.6096324544,6.877385781415,-8.272993843245,2,1,18 +2025-03-11T12:39:30.389618,479392773,958,193,-2.19324184208,8.20333091509,-9.2930465343,2,1,18 +2025-03-11T12:39:30.514618,479392773,958,193,-2.74861206584,9.501531791605,-10.30827197946,2,1,18 +2025-03-11T12:39:30.639618,479392773,958,193,-3.29456923496,10.76278284673,-11.281701326025,2,1,18 +2025-03-11T12:39:30.764618,479392773,958,193,-3.8452329314,11.97787142932,-12.204076235655,2,1,18 +2025-03-11T12:39:30.889618,479392773,958,193,-4.34883135464,13.123634803585,-13.10288367666,2,1,18 +2025-03-11T12:39:31.014618,479392773,958,193,-4.81477755932,14.19547018741,-13.927298403585,2,1,18 +2025-03-11T12:39:31.139618,479392773,958,193,-5.27131070936,15.23497270579,-14.71456148268,2,1,18 +2025-03-11T12:39:31.264618,479392773,958,193,-5.69960469548,16.20979531945,-15.47832217782,2,1,18 +2025-03-11T12:39:31.389618,479392773,958,193,-6.07612688108,17.092200858145,-16.162942143675,2,1,18 +2025-03-11T12:39:31.514618,479392773,958,193,-6.44794253936,17.90534497075,-16.79174551137,2,1,18 +2025-03-11T12:39:31.639618,479392773,958,193,-6.79622556104,18.66305017744,-17.36938464825,2,1,18 +2025-03-11T12:39:31.764618,479392773,958,193,-7.08332372756,19.35140891506,-17.90032516824,2,1,18 +2025-03-11T12:39:31.889618,479392773,958,193,-7.34688925748,19.95201005515,-18.37531100415,2,1,18 +2025-03-11T12:39:32.014618,479392773,958,193,-7.59162867812,20.46947764057,-18.780516326415,2,1,18 +2025-03-11T12:39:32.139618,479392773,958,193,-7.78459629824,20.94531466642,-19.13918940975,2,1,18 +2025-03-11T12:39:32.264618,479392773,958,193,-7.95403128176,21.310309315015,-19.441786140255,2,1,18 +2025-03-11T12:39:32.389618,479392773,958,193,-8.08581404672,21.60137597317,-19.665370039665,2,1,18 +2025-03-11T12:39:32.514618,479392773,958,193,-8.17994459312,21.809280728995,-19.832993025555,2,1,18 +2025-03-11T12:39:32.639618,479392773,958,193,-8.2458359756,21.92480384443,-19.916906103795,2,1,18 +2025-03-11T12:39:32.764618,479392773,958,193,-8.26466208488,21.97100175154,-19.96801147938,2,1,18 +2025-03-11T12:39:32.889618,479392773,958,193,-8.25524903024,21.938668886095,-19.935479948565,2,1,18 +2025-03-11T12:39:33.014618,479392773,958,193,-8.21289028436,21.841649029015,-19.84709502696,2,1,18 +2025-03-11T12:39:33.139618,479392773,958,193,-8.12346626528,21.642985271995,-19.702631481375,2,1,18 +2025-03-11T12:39:33.264618,479392773,958,193,-8.00109655496,21.36116669956,-19.47449650791,2,1,18 +2025-03-11T12:39:33.389618,479392773,958,193,-7.85990073536,20.99159761651,-19.19503715511,2,1,18 +2025-03-11T12:39:33.514618,479392773,958,193,-7.65281353328,20.55729193342,-18.86889333144,2,1,18 +2025-03-11T12:39:33.639618,479392773,958,193,-7.43160674924,20.05371065041,-18.445331481015,2,1,18 +2025-03-11T12:39:33.764618,479392773,958,193,-7.17274774664,19.462350509125,-17.988884968395,2,1,18 +2025-03-11T12:39:33.889618,479392773,958,193,-6.87623652548,18.792445421455,-17.467261641975,2,1,18 +2025-03-11T12:39:34.014572,479392777,955,194,-6.5514861404,18.048626517175,-16.87588609395,2,1,18 +2025-03-11T12:39:34.139572,479392777,955,194,-6.19379006408,17.23088670937,-16.27018954077,2,1,18 +2025-03-11T12:39:34.264572,479392777,955,194,-5.80785482384,16.35308395279,-15.59019365022,2,1,18 +2025-03-11T12:39:34.389572,479392777,955,194,-5.38426736504,15.387502337935,-14.86345274643,2,1,18 +2025-03-11T12:39:34.514572,479392777,955,194,-4.927734215,14.3526167755,-14.066973767055,2,1,18 +2025-03-11T12:39:34.639572,479392777,955,194,-4.457081483,13.303859084485,-13.228810170105,2,1,18 +2025-03-11T12:39:34.764572,479392777,955,194,-3.95348305976,12.162712666165,-12.33926729688,2,1,18 +2025-03-11T12:39:34.889572,479392777,955,194,-3.4451781092,10.970772645535,-11.40786551154,2,1,18 +2025-03-11T12:39:35.014572,479392777,955,194,-2.9039274674,9.737230412995,-10.453072823265,2,1,18 +2025-03-11T12:39:35.139572,479392777,955,194,-2.33443766168,8.457476099515,-9.456394617975,2,1,18 +2025-03-11T12:39:35.264572,479392777,955,194,-1.76494785596,7.122318314695,-8.41784335455,2,1,18 +2025-03-11T12:39:35.389572,479392777,955,194,-1.15309930436,5.745544144135,-7.351260695715,2,1,18 +2025-03-11T12:39:35.514572,479392777,955,194,-0.531837698119999,4.322586240295,-6.27517408989,2,1,18 +2025-03-11T12:39:35.639572,479392777,955,194,0.11295654472,2.876508122155,-5.13885335547,2,1,18 +2025-03-11T12:39:35.764572,479392777,955,194,0.7671638422,1.402714094515,-4.006986360105,2,1,18 +2025-03-11T12:39:35.889572,479392777,955,194,1.41195808504,-0.0987674949649993,-2.833412684565,2,1,18 +2025-03-11T12:39:36.014572,479392777,955,194,2.08969801912,-1.614149560685,-1.64583434262,2,1,18 +2025-03-11T12:39:36.139572,479392777,955,194,2.77214448052,-3.152623493045,-0.458124144195,2,1,18 +2025-03-11T12:39:36.264572,479392777,955,194,3.45929746924,-4.71880624799,0.762083063565,2,1,18 +2025-03-11T12:39:36.389572,479392777,955,194,4.12291782136,-6.27571965647,1.9590900801,2,1,18 +2025-03-11T12:39:36.514572,479392777,955,194,4.81007081008,-7.84651936736,3.165461270565,2,1,18 +2025-03-11T12:39:36.639572,479392777,955,194,5.4972237988,-9.403468210415,4.367139342765,2,1,18 +2025-03-11T12:39:36.764572,479392777,955,194,6.18908331484,-10.960424140385,5.59192818777,2,1,18 +2025-03-11T12:39:36.889572,479392777,955,194,6.8621167216,-12.545053458365,6.79372169928,2,1,18 +2025-03-11T12:39:37.014572,479392777,955,194,7.53515012836,-14.074279305005,7.981362854745,2,1,18 +2025-03-11T12:39:37.139572,479392777,955,194,8.21289006244,-15.57581050289,9.15962796141,2,1,18 +2025-03-11T12:39:37.264572,479392777,955,194,8.87651041456,-17.06808652814,10.328573603355,2,1,18 +2025-03-11T12:39:37.389572,479392777,955,194,9.51189160276,-18.54185220812,11.465019964815,2,1,18 +2025-03-11T12:39:37.514572,479392777,955,194,10.15197931828,-19.99254019529,12.58749449421,2,1,18 +2025-03-11T12:39:37.639572,479392777,955,194,10.77324092452,-21.401647231295,13.691228800875,2,1,18 +2025-03-11T12:39:37.764572,479392777,955,194,11.37567642148,-22.778407228025,14.73931061619,2,1,18 +2025-03-11T12:39:37.889572,479392777,955,194,11.96399233648,-24.104359448615,15.777853963035,2,1,18 +2025-03-11T12:39:38.014511,479392781,951,195,12.52406908756,-25.393333500155,16.774560460365,2,1,18 +2025-03-11T12:39:38.139511,479392781,951,195,13.07002625668,-26.62688281961,17.72936333637,2,1,18 +2025-03-11T12:39:38.264511,479392781,951,195,13.58303773456,-27.81421297121,18.619169922555,2,1,18 +2025-03-11T12:39:38.389511,479392781,951,195,14.0866361578,-28.941508521695,19.49015932647,2,1,18 +2025-03-11T12:39:38.514511,479392781,951,195,14.57140847176,-30.00413834129,20.32842648786,2,1,18 +2025-03-11T12:39:38.639511,479392781,951,195,15.0044089852,-31.02052064537,21.11089684254,2,1,18 +2025-03-11T12:39:38.764511,479392781,951,195,15.41387686204,-31.95837926381,21.851321531685,2,1,18 +2025-03-11T12:39:38.889511,479392781,951,195,15.79981210228,-32.81771419661,22.52659997022,2,1,18 +2025-03-11T12:39:39.014511,479392781,951,195,16.15280165128,-33.62621300561,23.15071813623,2,1,18 +2025-03-11T12:39:39.139511,479392781,951,195,16.47284550904,-34.35617395514,23.70966967617,2,1,18 +2025-03-11T12:39:39.264511,479392781,951,195,16.78347631216,-35.016866391665,24.22203466425,2,1,18 +2025-03-11T12:39:39.389511,479392781,951,195,17.01880267816,-35.598957186485,24.67838157072,2,1,18 +2025-03-11T12:39:39.514511,479392781,951,195,17.24942251684,-36.111786555215,25.069671645,2,1,18 +2025-03-11T12:39:39.639511,479392781,951,195,17.44239013696,-36.550687933505,25.40504947326,2,1,18 +2025-03-11T12:39:39.764511,479392781,951,195,17.59770553852,-36.89257654163,25.68439338675,2,1,18 +2025-03-11T12:39:39.889511,479392781,951,195,17.72007524884,-37.15131033434,25.88006587236,2,1,18 +2025-03-11T12:39:40.014511,479392781,951,195,17.80949926792,-37.34074017947,26.01986063343,2,1,18 +2025-03-11T12:39:40.139511,479392781,951,195,17.8518580138,-37.451610904385,26.099078322255,2,1,18 +2025-03-11T12:39:40.264511,479392781,951,195,17.87068412308,-37.479340987715,26.13160589478,2,1,18 +2025-03-11T12:39:40.389511,479392781,951,195,17.84244495916,-37.433128906775,26.089720377765,2,1,18 +2025-03-11T12:39:40.514511,479392781,951,195,17.76714052204,-37.285272925895,25.98251600274,2,1,18 +2025-03-11T12:39:40.639511,479392781,951,195,17.663596921,-37.054269216515,25.810130855625,2,1,18 +2025-03-11T12:39:40.764511,479392781,951,195,17.53181415604,-36.749351690525,25.567993486905,2,1,18 +2025-03-11T12:39:40.889511,479392781,951,195,17.37649875448,-36.375144390785,25.260758535075,2,1,18 +2025-03-11T12:39:41.014511,479392781,951,195,17.17882460704,-35.92700201369,24.897601149495,2,1,18 +2025-03-11T12:39:41.139511,479392781,951,195,16.91996560444,-35.37719447591,24.487574810775,2,1,18 +2025-03-11T12:39:41.264511,479392781,951,195,16.6516935472,-34.7350336454,24.003119549355,2,1,18 +2025-03-11T12:39:41.389511,479392781,951,195,16.35518232604,-34.03742682206,23.453629518345,2,1,18 +2025-03-11T12:39:41.514511,479392781,951,195,16.03513846828,-33.29823196064,22.87152872583,2,1,18 +2025-03-11T12:39:41.639511,479392781,951,195,15.65861628268,-32.452762069505,22.23792471714,2,1,18 +2025-03-11T12:39:41.764511,479392781,951,195,15.25385493316,-31.565697053375,21.525498589065,2,1,18 +2025-03-11T12:39:41.889511,479392781,951,195,14.82085441972,-30.586250396855,20.770943606475,2,1,18 +2025-03-11T12:39:42.014435,479392785,946,196,14.36432126968,-29.56059874631,19.96527306057,2,1,18 +2025-03-11T12:39:42.139435,479392785,946,196,13.88425548304,-28.465657322015,19.112985399615,2,1,18 +2025-03-11T12:39:42.264435,479392785,946,196,13.39007011444,-27.306057253745,18.22336556685,2,1,18 +2025-03-11T12:39:42.389435,479392785,946,196,12.8629390546,-26.095621061675,17.29182569559,2,1,18 +2025-03-11T12:39:42.514435,479392785,946,196,12.31227535816,-24.834362919635,16.32300627831,2,1,18 +2025-03-11T12:39:42.639435,479392785,946,196,11.74278555244,-23.52228991454,15.303057151695,2,1,18 +2025-03-11T12:39:42.764435,479392785,946,196,11.1450565828,-22.18708960823,14.259824644875,2,1,18 +2025-03-11T12:39:42.889435,479392785,946,196,10.53791455852,-20.801088612695,13.17472303821,2,1,18 +2025-03-11T12:39:43.014435,479392785,946,196,9.90253337032,-19.35040771244,12.089219632665,2,1,18 +2025-03-11T12:39:43.139435,479392785,946,196,9.25303260016,-17.895088595495,10.980560745105,2,1,18 +2025-03-11T12:39:43.264435,479392785,946,196,8.61294488464,-16.41208191671,9.797854358265,2,1,18 +2025-03-11T12:39:43.389435,479392785,946,196,7.95403105984,-14.901345154595,8.614961218005,2,1,18 +2025-03-11T12:39:43.514435,479392785,946,196,7.28099765308,-13.390587131735,7.441277748585,2,1,18 +2025-03-11T12:39:43.639435,479392785,946,196,6.62208382828,-11.86138254584,6.25366715631,2,1,18 +2025-03-11T12:39:43.764435,479392785,946,196,5.9443438942,-10.295213964725,5.047340675055,2,1,18 +2025-03-11T12:39:43.889435,479392785,946,196,5.25248437816,-8.73364107881,3.84100796436,2,1,18 +2025-03-11T12:39:44.014435,479392785,946,196,4.57474444408,-7.176706409585,2.625489916575,2,1,18 +2025-03-11T12:39:44.139435,479392785,946,196,3.89229798268,-5.610530741555,1.40991301356,2,1,18 +2025-03-11T12:39:44.264435,479392785,946,196,3.19573193932,-4.05356772467,0.19897433187,2,1,18 +2025-03-11T12:39:44.389435,479392785,946,196,2.51799200524,-2.51048392328,-0.98412989556,2,1,18 +2025-03-11T12:39:44.514435,479392785,946,196,1.85437165312,-0.972038338579999,-2.17641946008,2,1,18 +2025-03-11T12:39:44.639435,479392785,946,196,1.19545782832,0.547932335425001,-3.345500916795,2,1,18 +2025-03-11T12:39:44.764435,479392785,946,196,0.51771789424,2.044846577365,-4.509881338665,2,1,18 +2025-03-11T12:39:44.889435,479392785,946,196,-0.11295676664,3.50937125854,-5.646268844895,2,1,18 +2025-03-11T12:39:45.014435,479392785,946,196,-0.734218372880001,4.927712206435,-6.754671936075,2,1,18 +2025-03-11T12:39:45.139435,479392785,946,196,-1.34606692448,6.32757115672,-7.84909696575,2,1,18 +2025-03-11T12:39:45.264435,479392785,946,196,-1.95320894876,7.67201954875,-8.90163874956,2,1,18 +2025-03-11T12:39:45.389435,479392785,946,196,-2.53681833644,8.988730770535,-9.903162305055,2,1,18 +2025-03-11T12:39:45.514435,479392785,946,196,-3.10630814216,10.277718995905,-10.89526906083,2,1,18 +2025-03-11T12:39:45.639435,479392785,946,196,-3.62873267468,11.501998968895,-11.83611197964,2,1,18 +2025-03-11T12:39:45.764435,479392785,946,196,-4.13703762524,12.6708542098,-12.73043116011,2,1,18 +2025-03-11T12:39:45.889435,479392785,946,196,-4.63122299384,13.75658298295,-13.58732083377,2,1,18 +2025-03-11T12:39:46.014358,479392789,941,197,-5.08304961656,14.786844502525,-14.40686587674,2,1,18 +2025-03-11T12:39:46.139358,479392789,941,197,-5.51134360268,15.798602763745,-15.166201124865,2,1,18 +2025-03-11T12:39:46.264358,479392789,941,197,-5.92551800684,16.72723455721,-15.88810686618,2,1,18 +2025-03-11T12:39:46.389358,479392789,941,197,-6.32086630172,17.572732796005,-16.54947232788,2,1,18 +2025-03-11T12:39:46.514358,479392789,941,197,-6.65502974144,18.371969345455,-17.14578037338,2,1,18 +2025-03-11T12:39:46.639358,479392789,941,197,-6.98919318116,19.06501590817,-17.699947689495,2,1,18 +2025-03-11T12:39:46.764358,479392789,941,197,-7.27158482036,19.725665823205,-18.20763143418,2,1,18 +2025-03-11T12:39:46.889358,479392789,941,197,-7.50691118636,20.289288794245,-18.63616030356,2,1,18 +2025-03-11T12:39:47.014358,479392789,941,197,-7.72341144308,20.769778210615,-19.01800924437,2,1,18 +2025-03-11T12:39:47.139358,479392789,941,197,-7.8928464266,21.185559374605,-19.330113880155,2,1,18 +2025-03-11T12:39:47.264358,479392789,941,197,-8.03874877352,21.50896598512,-19.581619381095,2,1,18 +2025-03-11T12:39:47.389358,479392789,941,197,-8.16111848384,21.744614998105,-19.786410431985,2,1,18 +2025-03-11T12:39:47.514358,479392789,941,197,-8.23642292096,21.91555575871,-19.90297670979,2,1,18 +2025-03-11T12:39:47.639358,479392789,941,197,-8.26466208488,22.003320443155,-19.96818181563,2,1,18 +2025-03-11T12:39:47.764358,479392789,941,197,-8.27878166684,21.989490836065,-19.9773796116,2,1,18 +2025-03-11T12:39:47.889358,479392789,941,197,-8.25054250292,21.9201939754,-19.907651723745,2,1,18 +2025-03-11T12:39:48.014358,479392789,941,197,-8.16582501116,21.740005129075,-19.767915817905,2,1,18 +2025-03-11T12:39:48.139358,479392789,941,197,-8.04345530084,21.490505248255,-19.590772467855,2,1,18 +2025-03-11T12:39:48.264358,479392789,941,197,-7.90696600856,21.14864498779,-19.32532965633,2,1,18 +2025-03-11T12:39:48.389358,479392789,941,197,-7.73282449772,20.7651754285,-19.013385169065,2,1,18 +2025-03-11T12:39:48.514358,479392789,941,197,-7.52103076832,20.27084223121,-18.64533376578,2,1,18 +2025-03-11T12:39:48.639358,479392789,941,197,-7.26687829304,19.70719091251,-18.20752391145,2,1,18 +2025-03-11T12:39:48.764358,479392789,941,197,-6.98448665384,19.074242733145,-17.699986169265,2,1,18 +2025-03-11T12:39:48.889358,479392789,941,197,-6.67856237804,18.35353695625,-17.141113860015,2,1,18 +2025-03-11T12:39:49.014358,479392789,941,197,-6.34910546564,17.57739227344,-16.54031755398,2,1,18 +2025-03-11T12:39:49.139358,479392789,941,197,-5.97728980736,16.708844689495,-15.86964112815,2,1,18 +2025-03-11T12:39:49.264358,479392789,941,197,-5.56782193052,15.78483693889,-15.157010142345,2,1,18 +2025-03-11T12:39:49.389358,479392789,941,197,-5.14423447172,14.800787500255,-14.374730499375,2,1,18 +2025-03-11T12:39:49.514358,479392789,941,197,-4.68770132168,13.742817158095,-13.555029266175,2,1,18 +2025-03-11T12:39:49.639358,479392789,941,197,-4.20292900772,12.64325169094,-12.707327200755,2,1,18 +2025-03-11T12:39:49.764358,479392789,941,197,-3.68991752984,11.46515545123,-11.78060834595,2,1,18 +2025-03-11T12:39:49.889358,479392789,941,197,-3.15337341536,10.23623726155,-10.8397105302,2,1,18 +2025-03-11T12:39:50.014312,479392793,938,198,-2.60270971892,8.95651129573,-9.85231330986,2,1,18 +2025-03-11T12:39:50.139312,479392793,938,198,-2.01439380392,7.63979298703,-8.832299098575,2,1,18 +2025-03-11T12:39:50.264312,479392793,938,198,-1.41195830696,6.267649946245,-7.78424161701,2,1,18 +2025-03-11T12:39:50.389312,479392793,938,198,-0.800109755360001,4.86779099596,-6.699056821365,2,1,18 +2025-03-11T12:39:50.514312,479392793,938,198,-0.1741416218,3.435592093315,-5.599810775235,2,1,18 +2025-03-11T12:39:50.639312,479392793,938,198,0.46594609372,1.994138018035,-4.46814467931,2,1,18 +2025-03-11T12:39:50.764312,479392793,938,198,1.12485991852,0.501869079700002,-3.308449459125,2,1,18 +2025-03-11T12:39:50.889312,479392793,938,198,1.79789332528,-1.022739810995,-2.143933222485,2,1,18 +2025-03-11T12:39:51.014312,479392793,938,198,2.46622020472,-2.54272465883,-0.970211273295,2,1,18 +2025-03-11T12:39:51.139312,479392793,938,198,3.14866666612,-4.09966641497,0.23607672819,2,1,18 +2025-03-11T12:39:51.264312,479392793,938,198,3.8264066002,-5.67045195203,1.45628789424,2,1,18 +2025-03-11T12:39:51.389312,479392793,938,198,4.50414653428,-7.208918797475,2.66708849001,2,1,18 +2025-03-11T12:39:51.514312,479392793,938,198,5.20071257764,-8.779732682195,3.873480055935,2,1,18 +2025-03-11T12:39:51.639312,479392793,938,198,5.87845251172,-10.33666735142,5.07975786969,2,1,18 +2025-03-11T12:39:51.764312,479392793,938,198,6.56089897312,-11.89360910756,6.276805637145,2,1,18 +2025-03-11T12:39:51.889312,479392793,938,198,7.24334543452,-13.44131695181,7.487665088145,2,1,18 +2025-03-11T12:39:52.014312,479392793,938,198,7.91637884128,-14.965925842505,8.66604167583,2,1,18 +2025-03-11T12:39:52.139312,479392793,938,198,8.57058613876,-16.458187693925,9.834966942315,2,1,18 +2025-03-11T12:39:52.264312,479392793,938,198,9.2389130182,-17.9412368942,10.98539363643,2,1,18 +2025-03-11T12:39:52.389312,479392793,938,198,9.8742942064,-19.41500257418,12.107979646845,2,1,18 +2025-03-11T12:39:52.514312,479392793,938,198,10.5096753946,-20.84259869471,13.225702202745,2,1,18 +2025-03-11T12:39:52.639312,479392793,938,198,11.11211089156,-22.205507823605,14.296811601885,2,1,18 +2025-03-11T12:39:52.764312,479392793,938,198,11.70042680656,-23.549927867975,15.330832166715,2,1,18 +2025-03-11T12:39:52.889312,479392793,938,198,12.2746231396,-24.862007959985,16.355411598075,2,1,18 +2025-03-11T12:39:53.014312,479392793,938,198,12.82058030872,-26.137109882945,17.31043347783,2,1,18 +2025-03-11T12:39:53.139312,479392793,938,198,13.35241789588,-27.33831925004,18.246554986335,2,1,18 +2025-03-11T12:39:53.264312,479392793,938,198,13.86542937376,-28.4702459303,19.13606956752,2,1,18 +2025-03-11T12:39:53.389312,479392793,938,198,14.35490821504,-29.574435440315,19.988426271435,2,1,18 +2025-03-11T12:39:53.514312,479392793,938,198,14.80673483776,-30.60469695989,20.789490846345,2,1,18 +2025-03-11T12:39:53.639312,479392793,938,198,15.22090924192,-31.570264400915,21.543932076765,2,1,18 +2025-03-11T12:39:53.764312,479392793,938,198,15.62567059144,-32.466563328935,22.23792640428,2,1,18 +2025-03-11T12:39:53.889312,479392793,938,198,15.99748624972,-33.3166430891,22.876164676005,2,1,18 +2025-03-11T12:39:54.014236,479392797,933,199,16.33635621676,-34.069717166015,23.481479805765,2,1,18 +2025-03-11T12:39:54.139236,479392797,933,199,16.63286743792,-34.76270703341,24.021705268995,2,1,18 +2025-03-11T12:39:54.264236,479392797,933,199,16.90113949516,-35.391016996085,24.47374671006,2,1,18 +2025-03-11T12:39:54.389236,479392797,933,199,17.13646586116,-35.9315551874,24.90215391069,2,1,18 +2025-03-11T12:39:54.514236,479392797,933,199,17.34825959056,-36.38895273713,25.251530175915,2,1,18 +2025-03-11T12:39:54.639236,479392797,933,199,17.50828151944,-36.763167123785,25.549535081445,2,1,18 +2025-03-11T12:39:54.764236,479392797,933,199,17.6400642844,-37.077318561665,25.77786076662,2,1,18 +2025-03-11T12:39:54.889236,479392797,933,199,17.74360788544,-37.29447140321,25.950172912485,2,1,18 +2025-03-11T12:39:55.014236,479392797,933,199,17.80949926792,-37.43307929837,26.06654847858,2,1,18 +2025-03-11T12:39:55.139236,479392797,933,199,17.83303190452,-37.497752116175,26.11314125988,2,1,18 +2025-03-11T12:39:55.264236,479392797,933,199,17.8283253772,-37.45157546981,26.099027383605,2,1,18 +2025-03-11T12:39:55.389236,479392797,933,199,17.77655357668,-37.349924482955,26.015217869805,2,1,18 +2025-03-11T12:39:55.514236,479392797,933,199,17.68242303028,-37.155870594965,25.87076847024,2,1,18 +2025-03-11T12:39:55.639236,479392797,933,199,17.57887942924,-36.897165149915,25.652036150475,2,1,18 +2025-03-11T12:39:55.764236,479392797,933,199,17.43768360964,-36.546063890645,25.36805401566,2,1,18 +2025-03-11T12:39:55.889236,479392797,933,199,17.25883557148,-36.121034640935,25.02353951781,2,1,18 +2025-03-11T12:39:56.014236,479392797,933,199,17.03292226012,-35.603595403175,24.62299506348,2,1,18 +2025-03-11T12:39:56.139236,479392797,933,199,16.7693567302,-34.99837730714,24.171085478895,2,1,18 +2025-03-11T12:39:56.264236,479392797,933,199,16.48225856368,-34.333103349245,23.68184768079,2,1,18 +2025-03-11T12:39:56.389236,479392797,933,199,16.16692123324,-33.617000354465,23.09525862774,2,1,18 +2025-03-11T12:39:56.514236,479392797,933,199,15.81393168424,-32.808501545465,22.466520344715,2,1,18 +2025-03-11T12:39:56.639236,479392797,933,199,15.42328991668,-31.93069170197,21.786514266435,2,1,18 +2025-03-11T12:39:56.764236,479392797,933,199,15.01852856716,-30.97898930261,21.050646880785,2,1,18 +2025-03-11T12:39:56.889236,479392797,933,199,14.5808215264,-29.971833823505,20.25435465483,2,1,18 +2025-03-11T12:39:57.014236,479392797,933,199,14.10546226708,-28.89998426585,19.44377990349,2,1,18 +2025-03-11T12:39:57.139236,479392797,933,199,13.60657037116,-27.768078846335,18.56815623654,2,1,18 +2025-03-11T12:39:57.264236,479392797,933,199,13.08414583864,-26.580734520905,17.650608572805,2,1,18 +2025-03-11T12:39:57.389236,479392797,933,199,12.54289519684,-25.337958376475,16.691147100015,2,1,18 +2025-03-11T12:39:57.514236,479392797,933,199,11.97811191844,-24.05821114991,15.69909919947,2,1,18 +2025-03-11T12:39:57.639236,479392797,933,199,11.39450253076,-22.741499928125,14.669854941885,2,1,18 +2025-03-11T12:39:57.764236,479392797,933,199,10.79677356112,-21.3739809302,13.607971630755,2,1,18 +2025-03-11T12:39:57.889236,479392797,933,199,10.17080542756,-19.95563289539,12.51341870289,2,1,18 +2025-03-11T12:39:58.014175,479392801,929,200,9.54954382132,-18.52344107966,11.391082259415,2,1,18 +2025-03-11T12:39:58.139175,479392801,929,200,8.90474957848,-17.054278181795,10.26850020729,2,1,18 +2025-03-11T12:39:58.264175,479392801,929,200,8.250542281,-15.543548506595,9.10409772282,2,1,18 +2025-03-11T12:39:58.389175,479392801,929,200,7.57280234692,-14.02354948493,7.92111516414,2,1,18 +2025-03-11T12:39:58.514175,479392801,929,200,6.90447546748,-12.485096813315,6.724195294875,2,1,18 +2025-03-11T12:39:58.639175,479392801,929,200,6.21261595144,-10.9235239274,5.52710281821,2,1,18 +2025-03-11T12:39:58.764175,479392801,929,200,5.52546296272,-9.385042908125,4.320901963995,2,1,18 +2025-03-11T12:39:58.889175,479392801,929,200,4.84772302864,-7.814257371065,3.10531091496,2,1,18 +2025-03-11T12:39:59.014175,479392801,929,200,4.16998309456,-6.22962096617,1.89426698169,2,1,18 +2025-03-11T12:39:59.139175,479392801,929,200,3.47812357852,-4.677281992145,0.687982938495,2,1,18 +2025-03-11T12:39:59.264175,479392801,929,200,2.80038364444,-3.12034732292,-0.504434524215,2,1,18 +2025-03-11T12:39:59.389175,479392801,929,200,2.11793718304,-1.58187339056,-1.696764839655,2,1,18 +2025-03-11T12:39:59.514175,479392801,929,200,1.46372988556,-0.0619098034699999,-2.8843165767,2,1,18 +2025-03-11T12:39:59.639175,479392801,929,200,0.80481606076,1.42574217892,-4.04860758015,2,1,18 +2025-03-11T12:39:59.764175,479392801,929,200,0.15060876328,2.885685338725,-5.198882042325,2,1,18 +2025-03-11T12:39:59.889175,479392801,929,200,-0.5035985342,4.350245454475,-6.31221990213,2,1,18 +2025-03-11T12:40:00.014175,479392801,929,200,-1.11074055848,5.77318209757,-7.415996646855,2,1,18 +2025-03-11T12:40:00.139175,479392801,929,200,-1.69905647348,7.13606996572,-8.48245536579,2,1,18 +2025-03-11T12:40:00.264175,479392801,929,200,-2.30149197044,8.462043447055,-9.51640915881,2,1,18 +2025-03-11T12:40:00.389175,479392801,929,200,-2.87098177616,9.751031672425,-10.50389579757,2,1,18 +2025-03-11T12:40:00.514175,479392801,929,200,-3.40752589064,11.007651597775,-11.458799966865,2,1,18 +2025-03-11T12:40:00.639175,479392801,929,200,-3.92053736852,12.185747837485,-12.37627858764,2,1,18 +2025-03-11T12:40:00.764175,479392801,929,200,-4.42413579176,13.326894255805,-13.256581226835,2,1,18 +2025-03-11T12:40:00.889175,479392801,929,200,-4.91832116036,14.39877216112,-14.0995375482,2,1,18 +2025-03-11T12:40:01.014175,479392801,929,200,-5.37014778308,15.41518281286,-14.877428536785,2,1,18 +2025-03-11T12:40:01.139175,479392801,929,200,-5.77961565992,16.357658387245,-15.59939709162,2,1,18 +2025-03-11T12:40:01.264175,479392801,929,200,-6.17025742748,17.258553010465,-16.28876507268,2,1,18 +2025-03-11T12:40:01.389175,479392801,929,200,-6.53266003112,18.07168294924,-16.9129279479,2,1,18 +2025-03-11T12:40:01.514175,479392801,929,200,-6.85270388888,18.815494766605,-17.49967319118,2,1,18 +2025-03-11T12:40:01.639175,479392801,929,200,-7.14921511004,19.48078289833,-18.035132534895,2,1,18 +2025-03-11T12:40:01.764175,479392801,929,200,-7.4221936946,20.08139821225,-18.48703816119,2,1,18 +2025-03-11T12:40:01.889175,479392801,929,200,-7.65281353328,20.608078448815,-18.873781119705,2,1,18 +2025-03-11T12:40:02.014114,479392805,925,201,-7.84107462608,21.042355784245,-19.19526407544,2,1,18 +2025-03-11T12:40:02.139114,479392805,925,201,-7.99168350032,21.37962034951,-19.45609299939,2,1,18 +2025-03-11T12:40:02.264114,479392805,925,201,-8.12346626528,21.642985271995,-19.684151013315,2,1,18 +2025-03-11T12:40:02.389114,479392805,925,201,-8.20818375704,21.8416419421,-19.84708483923,2,1,18 +2025-03-11T12:40:02.514114,479392805,925,201,-8.25524903024,21.94328584204,-19.935504282315,2,1,18 +2025-03-11T12:40:02.639114,479392805,925,201,-8.27407513952,21.984866793205,-19.963484739075,2,1,18 +2025-03-11T12:40:02.764114,479392805,925,201,-8.25524903024,21.929434974205,-19.926191047035,2,1,18 +2025-03-11T12:40:02.889114,479392805,925,201,-8.19406417508,21.79083416596,-19.823686019715,2,1,18 +2025-03-11T12:40:03.014114,479392805,925,201,-8.09522710136,21.601390147,-19.656150181095,2,1,18 +2025-03-11T12:40:03.139114,479392805,925,201,-7.95873780908,21.29184857815,-19.43707887597,2,1,18 +2025-03-11T12:40:03.264114,479392805,925,201,-7.80342240752,20.931492146245,-19.143777276435,2,1,18 +2025-03-11T12:40:03.389114,479392805,925,201,-7.60104173276,20.4694918144,-18.799017169935,2,1,18 +2025-03-11T12:40:03.514114,479392805,925,201,-7.3751284214,19.928967796915,-18.370630344765,2,1,18 +2025-03-11T12:40:03.639114,479392805,925,201,-7.12097594612,19.32376387471,-17.89102043355,2,1,18 +2025-03-11T12:40:03.764114,479392805,925,201,-6.80563861568,18.64459652749,-17.364687571695,2,1,18 +2025-03-11T12:40:03.889114,479392805,925,201,-6.46676864864,17.89613940652,-16.78249736076,2,1,18 +2025-03-11T12:40:04.014114,479392805,925,201,-6.11848562696,17.06456290471,-16.13978724567,2,1,18 +2025-03-11T12:40:04.139114,479392805,925,201,-5.73725691404,16.17291636721,-15.43200783951,2,1,18 +2025-03-11T12:40:04.264114,479392805,925,201,-5.3042564006,15.188852754745,-14.6866687572,2,1,18 +2025-03-11T12:40:04.389114,479392805,925,201,-4.8571363052,14.15398136614,-13.908690621345,2,1,18 +2025-03-11T12:40:04.514114,479392805,925,201,-4.37707051856,13.08212472157,-13.070384980185,2,1,18 +2025-03-11T12:40:04.639114,479392805,925,201,-3.868765568,11.931737304445,-12.185403368745,2,1,18 +2025-03-11T12:40:04.764114,479392805,925,201,-3.3510475628,10.749017021875,-11.263270109475,2,1,18 +2025-03-11T12:40:04.889114,479392805,925,201,-2.79567733904,9.501602660755,-10.2898933887,2,1,18 +2025-03-11T12:40:05.014114,479392805,925,201,-2.221481006,8.20337343658,-9.279247309635,2,1,18 +2025-03-11T12:40:05.139114,479392805,925,201,-1.633165091,6.854336436265,-8.235962177025,2,1,18 +2025-03-11T12:40:05.264114,479392805,925,201,-1.0213165394,5.459094441925,-7.1415614811,2,1,18 +2025-03-11T12:40:05.389114,479392805,925,201,-0.4094679878,4.05000157975,-6.056328017955,2,1,18 +2025-03-11T12:40:05.514114,479392805,925,201,0.230619727720001,2.59007968069,-4.94304505509,2,1,18 +2025-03-11T12:40:05.639114,479392805,925,201,0.8848270252,1.10705174116,-3.792648924165,2,1,18 +2025-03-11T12:40:05.764114,479392805,925,201,1.54374085,-0.394451109065001,-2.62366480245,2,1,18 +2025-03-11T12:40:05.889114,479392805,925,201,2.2261873114,-1.914457217645,-1.445292173055,2,1,18 +2025-03-11T12:40:06.014053,479392809,921,202,2.9086337728,-3.46678201784,-0.243648622335,2,1,18 +2025-03-11T12:40:06.139053,479392809,921,202,3.57696065224,-5.02831946918,0.97187338374,2,1,18 +2025-03-11T12:40:06.264053,479392809,921,202,4.25940711364,-6.580644269375,2.19199740252,2,1,18 +2025-03-11T12:40:06.389053,479392809,921,202,4.95126662968,-8.14221715529,3.40295023023,2,1,18 +2025-03-11T12:40:06.514053,479392809,921,202,5.62900656376,-9.699151824515,4.60460792697,2,1,18 +2025-03-11T12:40:06.639053,479392809,921,202,6.31145302516,-11.26994444849,5.820209163735,2,1,18 +2025-03-11T12:40:06.764053,479392809,921,202,6.98919295924,-12.82226216177,7.00798217568,2,1,18 +2025-03-11T12:40:06.889053,479392809,921,202,7.6857590026,-14.34690648704,8.195649936045,2,1,18 +2025-03-11T12:40:07.014053,479392809,921,202,8.35408588204,-15.85304046704,9.38315923503,2,1,18 +2025-03-11T12:40:07.139053,479392809,921,202,8.99417359756,-17.336047145825,10.533524802765,2,1,18 +2025-03-11T12:40:07.264053,479392809,921,202,9.62955478576,-18.791345002025,11.660633595195,2,1,18 +2025-03-11T12:40:07.389053,479392809,921,202,10.27905555592,-20.242047163025,12.769268149005,2,1,18 +2025-03-11T12:40:07.514053,479392809,921,202,10.90031716216,-21.65115419903,13.85452198761,2,1,18 +2025-03-11T12:40:07.639053,479392809,921,202,11.4745134952,-23.023254718325,14.911758576825,2,1,18 +2025-03-11T12:40:07.764053,479392809,921,202,12.06753593752,-24.33998011394,15.93178297584,2,1,18 +2025-03-11T12:40:07.889053,479392809,921,202,12.62290616128,-25.619713166675,16.92843061794,2,1,18 +2025-03-11T12:40:08.014053,479392809,921,202,13.1688633304,-26.848645530185,17.864728692135,2,1,18 +2025-03-11T12:40:08.139053,479392809,921,202,13.68187480828,-28.017507858005,18.77291841138,2,1,18 +2025-03-11T12:40:08.264053,479392809,921,202,14.1807667042,-29.135562409685,19.643848960065,2,1,18 +2025-03-11T12:40:08.389053,479392809,921,202,14.64200638156,-30.198156794705,20.46820483176,2,1,18 +2025-03-11T12:40:08.514053,479392809,921,202,15.07030036768,-31.1868302762,21.255139113225,2,1,18 +2025-03-11T12:40:08.639053,479392809,921,202,15.47976824452,-32.10622107086,21.96774576528,2,1,18 +2025-03-11T12:40:08.764053,479392809,921,202,15.86099695744,-32.9609319608,22.624509214275,2,1,18 +2025-03-11T12:40:08.889053,479392809,921,202,16.21869303376,-33.77405481266,23.230181433705,2,1,18 +2025-03-11T12:40:09.014053,479392809,921,202,16.5340303642,-34.49939171933,23.79371856918,2,1,18 +2025-03-11T12:40:09.139053,479392809,921,202,16.82583505804,-35.15543885225,24.28753800453,2,1,18 +2025-03-11T12:40:09.264053,479392809,921,202,17.06586795136,-35.72368586615,24.72534162942,2,1,18 +2025-03-11T12:40:09.389053,479392809,921,202,17.26824862612,-36.21800488961,25.111853125305,2,1,18 +2025-03-11T12:40:09.514053,479392809,921,202,17.44239013696,-36.606091404845,25.44230241438,2,1,18 +2025-03-11T12:40:09.639053,479392809,921,202,17.61182512048,-36.938767361825,25.7031477555,2,1,18 +2025-03-11T12:40:09.764053,479392809,921,202,17.7106621942,-37.19746571996,25.903389419475,2,1,18 +2025-03-11T12:40:09.889053,479392809,921,202,17.79067315864,-37.373030523425,26.052331037865,2,1,18 +2025-03-11T12:40:10.013992,479392813,917,203,17.84244495916,-37.48391542217,26.117708751105,2,1,18 +2025-03-11T12:40:10.138992,479392813,917,203,17.84715148648,-37.502390332865,26.12243639085,2,1,18 +2025-03-11T12:40:10.263992,479392813,917,203,17.80949926792,-37.400760606755,26.052517791285,2,1,18 +2025-03-11T12:40:10.388992,479392813,917,203,17.73890135812,-37.25291171279,25.931463252945,2,1,18 +2025-03-11T12:40:10.513992,479392813,917,203,17.63535775708,-37.008057135575,25.754384987565,2,1,18 +2025-03-11T12:40:10.638992,479392813,917,203,17.50357499212,-36.675437873915,25.50748149933,2,1,18 +2025-03-11T12:40:10.763992,479392813,917,203,17.32002042664,-36.282720228905,25.204708203135,2,1,18 +2025-03-11T12:40:10.888992,479392813,917,203,17.12705280652,-35.811500159,24.841439336535,2,1,18 +2025-03-11T12:40:11.013992,479392813,917,203,16.88231338588,-35.243246058185,24.3990054069,2,1,18 +2025-03-11T12:40:11.138992,479392813,917,203,16.59992174668,-34.61953179071,23.90537668326,2,1,18 +2025-03-11T12:40:11.263992,479392813,917,203,16.2987039982,-33.921917880455,23.351256347505,2,1,18 +2025-03-11T12:40:11.388992,479392813,917,203,15.95983403116,-33.154992935705,22.745868216495,2,1,18 +2025-03-11T12:40:11.513992,479392813,917,203,15.58801837288,-32.281828395815,22.075167456915,2,1,18 +2025-03-11T12:40:11.638992,479392813,917,203,15.18325702336,-31.37167859996,21.367239777105,2,1,18 +2025-03-11T12:40:11.763992,479392813,917,203,14.75025650992,-30.387614987495,20.61728057778,2,1,18 +2025-03-11T12:40:11.888992,479392813,917,203,14.28901683256,-29.33887147031,19.78837759032,2,1,18 +2025-03-11T12:40:12.013992,479392813,917,203,13.79953799128,-28.23929891624,18.945285454185,2,1,18 +2025-03-11T12:40:12.138992,479392813,917,203,13.29593956804,-27.07045076225,18.050976461445,2,1,18 +2025-03-11T12:40:12.263992,479392813,917,203,12.77351503552,-25.85540470115,17.10556209312,2,1,18 +2025-03-11T12:40:12.388992,479392813,917,203,12.2275578664,-24.61723842575,16.10915383023,2,1,18 +2025-03-11T12:40:12.513992,479392813,917,203,11.63453542408,-23.318980853915,15.09384688323,2,1,18 +2025-03-11T12:40:12.638992,479392813,917,203,11.0509260364,-21.9376322489,14.05964183613,2,1,18 +2025-03-11T12:40:12.763992,479392813,917,203,10.4390774848,-20.537773298615,12.974457040485,2,1,18 +2025-03-11T12:40:12.888992,479392813,917,203,9.8036962966,-19.119411089975,11.856783152085,2,1,18 +2025-03-11T12:40:13.013992,479392813,917,203,9.17302163572,-17.659503364745,10.711179745575,2,1,18 +2025-03-11T12:40:13.138992,479392813,917,203,8.52822739288,-16.16263873121,9.565351105875,2,1,18 +2025-03-11T12:40:13.263992,479392813,917,203,7.84578093148,-14.66110044641,8.391695928495,2,1,18 +2025-03-11T12:40:13.388992,479392813,917,203,7.17745405204,-13.131881686685,7.21330519479,2,1,18 +2025-03-11T12:40:13.513992,479392813,917,203,6.5091271726,-11.588812059125,6.02098110879,2,1,18 +2025-03-11T12:40:13.638992,479392813,917,203,5.81726765656,-10.022622217265,4.81000394733,2,1,18 +2025-03-11T12:40:13.763992,479392813,917,203,5.13011466784,-8.44720555043,3.603608423115,2,1,18 +2025-03-11T12:40:13.888992,479392813,917,203,4.44766820644,-6.885646838345,2.38805585385,2,1,18 +2025-03-11T12:40:14.013916,479392817,912,204,3.76051521772,-5.342548863125,1.1864507829,2,1,18 +2025-03-11T12:40:14.138916,479392817,912,204,3.073362229,-3.76713219629,-0.0199447413150002,2,1,18 +2025-03-11T12:40:14.263916,479392817,912,204,2.38620924028,-2.21480030918,-1.22621859678,2,1,18 +2025-03-11T12:40:14.388916,479392817,912,204,1.72729541548,-0.685595723284999,-2.404588955025,2,1,18 +2025-03-11T12:40:14.513916,479392817,912,204,1.07779464532,0.81589295311,-3.57355270128,2,1,18 +2025-03-11T12:40:14.638916,479392817,912,204,0.40946776588,2.29432519744,-4.742435529705,2,1,18 +2025-03-11T12:40:14.763916,479392817,912,204,-0.21650036768,3.772693659535,-5.869645615425,2,1,18 +2025-03-11T12:40:14.888916,479392817,912,204,-0.851881555879999,5.18643891223,-6.98267505306,2,1,18 +2025-03-11T12:40:15.013916,479392817,912,204,-1.45431705284,6.577049776795,-8.0539304547,2,1,18 +2025-03-11T12:40:15.138916,479392817,912,204,-2.03792644052,7.93069664614,-9.10646996736,2,1,18 +2025-03-11T12:40:15.263916,479392817,912,204,-2.6215358282,9.25202482387,-10.12187820765,2,1,18 +2025-03-11T12:40:15.388916,479392817,912,204,-3.18161257928,10.490212360015,-11.09983656567,2,1,18 +2025-03-11T12:40:15.513916,479392817,912,204,-3.71815669376,11.700662725915,-12.036016929405,2,1,18 +2025-03-11T12:40:15.638916,479392817,912,204,-4.21704858968,12.86950379299,-12.921075500385,2,1,18 +2025-03-11T12:40:15.763916,479392817,912,204,-4.68770132168,13.95981408751,-13.7640782181,2,1,18 +2025-03-11T12:40:15.888916,479392817,912,204,-5.15835405368,15.00395482258,-14.560636428165,2,1,18 +2025-03-11T12:40:16.013916,479392817,912,204,-5.5866480398,15.974160480295,-15.324372789555,2,1,18 +2025-03-11T12:40:16.138916,479392817,912,204,-5.986702862,16.87968623329,-16.023025713855,2,1,18 +2025-03-11T12:40:16.263916,479392817,912,204,-6.3632250476,17.72053916848,-16.6889462079,2,1,18 +2025-03-11T12:40:16.388916,479392817,912,204,-6.70209501464,18.48746411323,-17.28509410488,2,1,18 +2025-03-11T12:40:16.513916,479392817,912,204,-7.00801929044,19.1850851104,-17.820744160305,2,1,18 +2025-03-11T12:40:16.638916,479392817,912,204,-7.26687829304,19.8087639433,-18.30970182828,2,1,18 +2025-03-11T12:40:16.763916,479392817,912,204,-7.52103076832,20.367798306055,-18.7290068808,2,1,18 +2025-03-11T12:40:16.888916,479392817,912,204,-7.73282449772,20.83904672362,-19.10155673235,2,1,18 +2025-03-11T12:40:17.013916,479392817,912,204,-7.90225948124,21.22712615194,-19.404275131605,2,1,18 +2025-03-11T12:40:17.138916,479392817,912,204,-8.02933571888,21.541270502905,-19.637210746065,2,1,18 +2025-03-11T12:40:17.263916,479392817,912,204,-8.13287931992,21.77689116823,-19.80962022693,2,1,18 +2025-03-11T12:40:17.388916,479392817,912,204,-8.20818375704,21.90627932533,-19.92134738397,2,1,18 +2025-03-11T12:40:17.513916,479392817,912,204,-8.24112944828,21.980200228855,-19.97724944226,2,1,18 +2025-03-11T12:40:17.638916,479392817,912,204,-8.23642292096,21.95249140627,-19.967853018,2,1,18 +2025-03-11T12:40:17.763916,479392817,912,204,-8.1987707024,21.864712547995,-19.88414706864,2,1,18 +2025-03-11T12:40:17.888916,479392817,912,204,-8.11405321064,21.707608481395,-19.74453283155,2,1,18 +2025-03-11T12:40:18.013855,479392821,908,205,-8.00109655496,21.43503799468,-19.562668071195,2,1,18 +2025-03-11T12:40:18.138855,479392821,908,205,-7.85990073536,21.088553691355,-19.274090153115,2,1,18 +2025-03-11T12:40:18.263855,479392821,908,205,-7.67163964256,20.64965939998,-18.9433426296,2,1,18 +2025-03-11T12:40:18.388855,479392821,908,205,-7.45043285852,20.150695072915,-18.55214593203,2,1,18 +2025-03-11T12:40:18.513855,479392821,908,205,-7.20569343788,19.56397314832,-18.08651408232,2,1,18 +2025-03-11T12:40:18.638855,479392821,908,205,-6.91859527136,18.917167014205,-17.5927535022,2,1,18 +2025-03-11T12:40:18.763855,479392821,908,205,-6.5985514136,18.187206064675,-17.03380196226,2,1,18 +2025-03-11T12:40:18.888855,479392821,908,205,-6.25497491924,17.40180620923,-16.42830630852,2,1,18 +2025-03-11T12:40:19.013855,479392821,908,205,-5.88786578828,16.537882668145,-15.743804053125,2,1,18 +2025-03-11T12:40:19.138855,479392821,908,205,-5.45957180216,15.599995702045,-15.02181908112,2,1,18 +2025-03-11T12:40:19.263855,479392821,908,205,-5.03127781604,14.597471352715,-14.225571564375,2,1,18 +2025-03-11T12:40:19.388855,479392821,908,205,-4.574744666,13.5441179665,-13.415134898955,2,1,18 +2025-03-11T12:40:19.513855,479392821,908,205,-4.07114624276,12.40297154818,-12.55331272782,2,1,18 +2025-03-11T12:40:19.638855,479392821,908,205,-3.55813476488,11.229492264415,-11.64047855781,2,1,18 +2025-03-11T12:40:19.763855,479392821,908,205,-3.01217759576,10.009793812795,-10.676508449025,2,1,18 +2025-03-11T12:40:19.888855,479392821,908,205,-2.46151389932,8.72545089103,-9.67522654389,2,1,18 +2025-03-11T12:40:20.013855,479392821,908,205,-1.868491457,7.399491583525,-8.664393711405,2,1,18 +2025-03-11T12:40:20.138855,479392821,908,205,-1.26605596004,6.022731586795,-7.61631189609,2,1,18 +2025-03-11T12:40:20.263855,479392821,908,205,-0.64950088112,4.632099461485,-6.512685112155,2,1,18 +2025-03-11T12:40:20.388855,479392821,908,205,-0.0235327475599991,3.204517514785,-5.404223165745,2,1,18 +2025-03-11T12:40:20.513855,479392821,908,205,0.6259680226,1.73996448595,-4.258554674565,2,1,18 +2025-03-11T12:40:20.638855,479392821,908,205,1.2848818474,0.238461635725001,-3.10805102091,2,1,18 +2025-03-11T12:40:20.763855,479392821,908,205,1.93908914488,-1.2953528192,-1.92504639963,2,1,18 +2025-03-11T12:40:20.888855,479392821,908,205,2.60741602432,-2.84765635865,-0.746533997175,2,1,18 +2025-03-11T12:40:21.013855,479392821,908,205,3.27574290376,-4.39072598621,0.45041020584,2,1,18 +2025-03-11T12:40:21.138855,479392821,908,205,3.96289589248,-5.95229178521,1.675213196865,2,1,18 +2025-03-11T12:40:21.263855,479392821,908,205,4.63122277192,-7.499978368715,2.88142196766,2,1,18 +2025-03-11T12:40:21.388855,479392821,908,205,5.32778881528,-9.06617529749,4.106269667895,2,1,18 +2025-03-11T12:40:21.513855,479392821,908,205,6.02435485864,-10.641606138155,5.3219258016,2,1,18 +2025-03-11T12:40:21.638855,479392821,908,205,6.71621437468,-12.180094244345,6.518896609515,2,1,18 +2025-03-11T12:40:21.763855,479392821,908,205,7.38924778144,-13.71393704693,7.711182215745,2,1,18 +2025-03-11T12:40:21.888855,479392821,908,205,8.04816160624,-15.24775858877,8.875716556695,2,1,18 +2025-03-11T12:40:22.013778,479392825,903,206,8.721195013,-16.76775052352,10.0448285766,2,1,18 +2025-03-11T12:40:22.138778,479392825,903,206,9.37540231048,-18.22307672738,11.19045858801,2,1,18 +2025-03-11T12:40:22.263778,479392825,903,206,10.00137044404,-19.66912649786,12.31749833748,2,1,18 +2025-03-11T12:40:22.388778,479392825,903,206,10.61321899564,-21.096687183815,13.40744925264,2,1,18 +2025-03-11T12:40:22.513778,479392825,903,206,11.22036101992,-22.468837311515,14.464757155965,2,1,18 +2025-03-11T12:40:22.638778,479392825,903,206,11.82279651688,-23.81327861663,15.51266863503,2,1,18 +2025-03-11T12:40:22.763778,479392825,903,206,12.40169937724,-25.11151492772,16.51870478481,2,1,18 +2025-03-11T12:40:22.888778,479392825,903,206,12.957069601,-26.382014068565,17.473722706275,2,1,18 +2025-03-11T12:40:23.013778,479392825,903,206,13.48420066084,-27.5785993928,18.39132922524,2,1,18 +2025-03-11T12:40:23.138778,479392825,903,206,13.98309255676,-28.682803076645,19.27604712372,2,1,18 +2025-03-11T12:40:23.263778,479392825,903,206,14.45845181608,-29.768503502135,20.137516163475,2,1,18 +2025-03-11T12:40:23.388778,479392825,903,206,14.90557191148,-30.79414097885,20.92468586586,2,1,18 +2025-03-11T12:40:23.513778,479392825,903,206,15.32445284296,-31.745864638955,21.66982404873,2,1,18 +2025-03-11T12:40:23.638778,479392825,903,206,15.71980113784,-32.62829852531,22.354484765505,2,1,18 +2025-03-11T12:40:23.763778,479392825,903,206,16.07279068684,-33.45526515809,22.987940500545,2,1,18 +2025-03-11T12:40:23.888778,479392825,903,206,16.3928345446,-34.199076975455,23.556205275765,2,1,18 +2025-03-11T12:40:24.013778,479392825,903,206,16.68934576576,-34.887449886905,24.09178628823,2,1,18 +2025-03-11T12:40:24.138778,479392825,903,206,16.96232435032,-35.47421433299,24.562099381335,2,1,18 +2025-03-11T12:40:24.263778,479392825,903,206,17.18353113436,-35.99626343978,24.971898215715,2,1,18 +2025-03-11T12:40:24.388778,479392825,903,206,17.39532486376,-36.45366098951,25.335134831985,2,1,18 +2025-03-11T12:40:24.513778,479392825,903,206,17.55534679264,-36.827875376165,25.605419035425,2,1,18 +2025-03-11T12:40:24.638778,479392825,903,206,17.6871295576,-37.114325078375,25.810498133025,2,1,18 +2025-03-11T12:40:24.763778,479392825,903,206,17.77184704936,-37.32221566037,25.978100743455,2,1,18 +2025-03-11T12:40:24.888778,479392825,903,206,17.83773843184,-37.437738775805,26.06663393871,2,1,18 +2025-03-11T12:40:25.013778,479392825,903,206,17.8518580138,-37.470078728165,26.099175657255,2,1,18 +2025-03-11T12:40:25.138778,479392825,903,206,17.84715148648,-37.419285125855,26.052696628125,2,1,18 +2025-03-11T12:40:25.263778,479392825,903,206,17.78596663132,-37.313003009225,25.97346252213,2,1,18 +2025-03-11T12:40:25.388778,479392825,903,206,17.69183608492,-37.100481297455,25.828915787565,2,1,18 +2025-03-11T12:40:25.513778,479392825,903,206,17.5694663746,-36.823279680965,25.596185030835,2,1,18 +2025-03-11T12:40:25.638778,479392825,903,206,17.41885750036,-36.462930335975,25.316753970075,2,1,18 +2025-03-11T12:40:25.763778,479392825,903,206,17.22118335292,-36.00555404699,24.962788151025,2,1,18 +2025-03-11T12:40:25.888778,479392825,903,206,16.99527004156,-35.483497853285,24.552979128915,2,1,18 +2025-03-11T12:40:26.013717,479392829,899,207,16.75523714824,-34.90139997155,24.087381800685,2,1,18 +2025-03-11T12:40:26.138717,479392829,899,207,16.43519329048,-34.21760858147,23.57025465138,2,1,18 +2025-03-11T12:40:26.263717,479392829,899,207,16.1104429054,-33.47378967719,22.9927394544,2,1,18 +2025-03-11T12:40:26.388717,479392829,899,207,15.7339207198,-32.632936742,22.35915977946,2,1,18 +2025-03-11T12:40:26.513717,479392829,899,207,15.36210506152,-31.75053829022,21.66992988432,2,1,18 +2025-03-11T12:40:26.638717,479392829,899,207,14.95263718468,-30.81267967178,20.929505195175,2,1,18 +2025-03-11T12:40:26.763717,479392829,899,207,14.49139750732,-29.77778702243,20.137636145085,2,1,18 +2025-03-11T12:40:26.888717,479392829,899,207,14.01133172068,-28.70593037786,19.299330503925,2,1,18 +2025-03-11T12:40:27.013717,479392829,899,207,13.51714635208,-27.550947265535,18.41897523894,2,1,18 +2025-03-11T12:40:27.138717,479392829,899,207,12.97118918296,-26.340482725805,17.492014733775,2,1,18 +2025-03-11T12:40:27.263717,479392829,899,207,12.4393515958,-25.10233771115,16.51873761915,2,1,18 +2025-03-11T12:40:27.388717,479392829,899,207,11.86044873544,-23.799484444115,15.517297252635,2,1,18 +2025-03-11T12:40:27.513717,479392829,899,207,11.28154587508,-22.46892944141,14.483370064515,2,1,18 +2025-03-11T12:40:27.638717,479392829,899,207,10.6744038508,-21.101396269655,13.412226143895,2,1,18 +2025-03-11T12:40:27.763717,479392829,899,207,10.06726182652,-19.692310494395,12.30852240042,2,1,18 +2025-03-11T12:40:27.888717,479392829,899,207,9.43188063832,-18.24162959414,11.18143794174,2,1,18 +2025-03-11T12:40:28.013717,479392829,899,207,8.77767334084,-16.7678355665,10.0264703613,2,1,18 +2025-03-11T12:40:28.138717,479392829,899,207,8.12346604336,-15.24787197941,8.866639326345,2,1,18 +2025-03-11T12:40:28.263717,479392829,899,207,7.44101958196,-13.723248914885,7.6882423632,2,1,18 +2025-03-11T12:40:28.388717,479392829,899,207,6.77269270252,-12.180179287325,6.491298160185,2,1,18 +2025-03-11T12:40:28.513717,479392829,899,207,6.1090723504,-10.63711674668,5.298984261915,2,1,18 +2025-03-11T12:40:28.638717,479392829,899,207,5.41250630704,-9.07553677385,4.069540778415,2,1,18 +2025-03-11T12:40:28.763717,479392829,899,207,4.71594026368,-7.518573756965,2.867842330755,2,1,18 +2025-03-11T12:40:28.888717,479392829,899,207,4.03349380228,-5.961632000825,1.65231409524,2,1,18 +2025-03-11T12:40:29.013717,479392829,899,207,3.35104734088,-4.37237155307,0.445855757505,2,1,18 +2025-03-11T12:40:29.138717,479392829,899,207,2.66389435216,-2.82927357785,-0.75112919643,2,1,18 +2025-03-11T12:40:29.263717,479392829,899,207,1.98144789076,-1.29079964549,-1.94345951187,2,1,18 +2025-03-11T12:40:29.388717,479392829,899,207,1.32724059328,0.23839785349,-3.121819682385,2,1,18 +2025-03-11T12:40:29.513717,479392829,899,207,0.66362024116,1.735290834685,-4.286169541065,2,1,18 +2025-03-11T12:40:29.638717,479392829,899,207,0.00941294368000101,3.20446790638,-5.431872553725,2,1,18 +2025-03-11T12:40:29.763717,479392829,899,207,-0.625968244519999,4.62283011502,-6.54492632511,2,1,18 +2025-03-11T12:40:29.888717,479392829,899,207,-1.24252332344,6.03193006411,-7.634790093,2,1,18 +2025-03-11T12:40:30.013656,479392833,895,208,-1.84025229308,7.40406601798,-8.692077620865,2,1,18 +2025-03-11T12:40:30.138656,479392833,895,208,-2.41444862612,8.74384784566,-9.726043288755,2,1,18 +2025-03-11T12:40:30.263656,479392833,895,208,-2.96511232256,10.009722943645,-10.731847975905,2,1,18 +2025-03-11T12:40:30.388656,479392833,895,208,-3.50165643704,11.24325808927,-11.672770125405,2,1,18 +2025-03-11T12:40:30.513656,479392833,895,208,-4.01937444224,12.42597837184,-12.585663150645,2,1,18 +2025-03-11T12:40:30.638656,479392833,895,208,-4.51826633816,13.54403292352,-13.442733348285,2,1,18 +2025-03-11T12:40:30.763656,479392833,895,208,-4.99362559748,14.62049943712,-14.24871231636,2,1,18 +2025-03-11T12:40:30.888656,479392833,895,208,-5.43603916556,15.632278959085,-15.03117871275,2,1,18 +2025-03-11T12:40:31.013656,479392833,895,208,-5.85492009704,16.542450015685,-15.762237540825,2,1,18 +2025-03-11T12:40:31.138656,479392833,895,208,-6.23614880996,17.41101177346,-16.423694108085,2,1,18 +2025-03-11T12:40:31.263656,479392833,895,208,-6.58443183164,18.20565262771,-17.047729085115,2,1,18 +2025-03-11T12:40:31.388656,479392833,895,208,-6.89976916208,18.944840402215,-17.60209898781,2,1,18 +2025-03-11T12:40:31.513656,479392833,895,208,-7.18216080128,19.600873361305,-18.118998632775,2,1,18 +2025-03-11T12:40:31.638656,479392833,895,208,-7.44101980388,20.187616546645,-18.5615604606,2,1,18 +2025-03-11T12:40:31.763656,479392833,895,208,-7.6810526972,20.70507704515,-18.94365501006,2,1,18 +2025-03-11T12:40:31.888656,479392833,895,208,-7.85519420804,21.102397472275,-19.292633434695,2,1,18 +2025-03-11T12:40:32.013656,479392833,895,208,-8.01521613692,21.462760991095,-19.553604402855,2,1,18 +2025-03-11T12:40:32.138656,479392833,895,208,-8.13287931992,21.73995552067,-19.749364035735,2,1,18 +2025-03-11T12:40:32.263656,479392833,895,208,-8.21289028436,21.897052500355,-19.87510773405,2,1,18 +2025-03-11T12:40:32.388656,479392833,895,208,-8.25995555756,21.998696400295,-19.96814729415,2,1,18 +2025-03-11T12:40:32.513656,479392833,895,208,-8.25995555756,22.007930312185,-19.963575844635,2,1,18 +2025-03-11T12:40:32.638656,479392833,895,208,-8.22700986632,21.93400940866,-19.91229390336,2,1,18 +2025-03-11T12:40:32.763656,479392833,895,208,-8.1752380658,21.78157190641,-19.814356367265,2,1,18 +2025-03-11T12:40:32.888656,479392833,895,208,-8.07169446476,21.536717329195,-19.63265798487,2,1,18 +2025-03-11T12:40:33.013656,479392833,895,208,-7.9399116998,21.22718284726,-19.385876165385,2,1,18 +2025-03-11T12:40:33.138656,479392833,895,208,-7.74694407968,20.84368494031,-19.0738909272,2,1,18 +2025-03-11T12:40:33.263656,479392833,895,208,-7.5398568776,20.386294477495,-18.71990473269,2,1,18 +2025-03-11T12:40:33.388656,479392833,895,208,-7.3045305116,19.83652237429,-18.30068909859,2,1,18 +2025-03-11T12:40:33.513656,479392833,895,208,-7.04096498168,19.20821949853,-17.82555726018,2,1,18 +2025-03-11T12:40:33.638656,479392833,895,208,-6.7397472332,18.492137764495,-17.25747923838,2,1,18 +2025-03-11T12:40:33.763656,479392833,895,208,-6.39146421152,17.752900381585,-16.675317319485,2,1,18 +2025-03-11T12:40:33.888656,479392833,895,208,-6.02435508056,16.921295532115,-16.03718657049,2,1,18 +2025-03-11T12:40:34.013595,479392837,891,209,-5.633713313,16.001933085115,-15.333860903385,2,1,18 +2025-03-11T12:40:34.138595,479392837,891,209,-5.20071279956,15.03633729643,-14.565518571,2,1,18 +2025-03-11T12:40:34.263595,479392837,891,209,-4.74417964952,13.97836695427,-13.750437454815,2,1,18 +2025-03-11T12:40:34.388595,479392837,891,209,-4.2688203902,12.86496479311,-12.90730288062,2,1,18 +2025-03-11T12:40:34.513595,479392837,891,209,-3.76992849428,11.705357637925,-12.00381250908,2,1,18 +2025-03-11T12:40:34.638595,479392837,891,209,-3.24279743444,10.485687533965,-11.07222397032,2,1,18 +2025-03-11T12:40:34.763595,479392837,891,209,-2.68742721068,9.229039260955,-10.09417846503,2,1,18 +2025-03-11T12:40:34.888595,479392837,891,209,-2.12264393228,7.93082421061,-9.07893264441,2,1,18 +2025-03-11T12:40:35.013595,479392837,891,209,-1.52020843532,6.586382905495,-8.02640104833,2,1,18 +2025-03-11T12:40:35.138595,479392837,891,209,-0.908359883720001,5.200374823045,-6.959769721995,2,1,18 +2025-03-11T12:40:35.263595,479392837,891,209,-0.28239175016,3.772792876345,-5.8559278926,2,1,18 +2025-03-11T12:40:35.388595,479392837,891,209,0.35769596536,2.30825402134,-4.714899893895,2,1,18 +2025-03-11T12:40:35.513595,479392837,891,209,1.01660979016,0.820602038950001,-3.550608890445,2,1,18 +2025-03-11T12:40:35.638595,479392837,891,209,1.66611056032,-0.657801857719997,-2.395627163985,2,1,18 +2025-03-11T12:40:35.763595,479392837,891,209,2.33443743976,-2.205488441225,-1.194038510205,2,1,18 +2025-03-11T12:40:35.888595,479392837,891,209,3.0262969558,-3.76706132714,-0.0108063845850004,2,1,18 +2025-03-11T12:40:36.013595,479392837,891,209,3.7087434172,-5.31476917139,1.18619271537,2,1,18 +2025-03-11T12:40:36.138595,479392837,891,209,4.38648335128,-6.85785297278,2.392397527875,2,1,18 +2025-03-11T12:40:36.263595,479392837,891,209,5.07363634,-8.42865268367,3.612629069385,2,1,18 +2025-03-11T12:40:36.388595,479392837,891,209,5.74666974676,-9.98558026598,4.823516812425,2,1,18 +2025-03-11T12:40:36.513595,479392837,891,209,6.42911620816,-11.547138978065,6.02982914766,2,1,18 +2025-03-11T12:40:36.638595,479392837,891,209,7.12568225152,-13.108718950895,7.22231169504,2,1,18 +2025-03-11T12:40:36.763595,479392837,891,209,7.79400913096,-14.633320754675,8.4330189141,2,1,18 +2025-03-11T12:40:36.888595,479392837,891,209,8.46704253772,-16.144078777535,9.59746214949,2,1,18 +2025-03-11T12:40:37.013595,479392837,891,209,9.1212498352,-17.6409575849,10.74331116465,2,1,18 +2025-03-11T12:40:37.138595,479392837,891,209,9.75192449608,-19.087014442295,11.884221452895,2,1,18 +2025-03-11T12:40:37.263595,479392837,891,209,10.38730568428,-20.51922751877,12.97886775747,2,1,18 +2025-03-11T12:40:37.388595,479392837,891,209,10.98503465392,-21.9282991202,14.073310891455,2,1,18 +2025-03-11T12:40:37.513595,479392837,891,209,11.60158973284,-23.27276168606,15.11201269968,2,1,18 +2025-03-11T12:40:37.638595,479392837,891,209,12.1804925932,-24.594082776875,16.1458912203,2,1,18 +2025-03-11T12:40:37.763595,479392837,891,209,12.73586281696,-25.85534800583,17.128581176355,2,1,18 +2025-03-11T12:40:37.888595,479392837,891,209,13.28181998608,-27.06581254556,18.07402214958,2,1,18 +2025-03-11T12:40:38.013534,479392841,887,210,13.8042445186,-28.23468904721,18.963751776225,2,1,18 +2025-03-11T12:40:38.138534,479392841,887,210,14.29372335988,-29.35272942506,19.820801598405,2,1,18 +2025-03-11T12:40:38.263534,479392841,887,210,14.75025650992,-30.40146585533,20.62659381306,2,1,18 +2025-03-11T12:40:38.388534,479392841,887,210,15.17855049604,-31.39475629277,21.367351258125,2,1,18 +2025-03-11T12:40:38.513534,479392841,887,210,15.56448573628,-32.30026078502,22.102934555355,2,1,18 +2025-03-11T12:40:38.638534,479392841,887,210,15.95042097652,-33.136510938095,22.764230974095,2,1,18 +2025-03-11T12:40:38.763534,479392841,887,210,16.28929094356,-33.921903706625,23.35585608906,2,1,18 +2025-03-11T12:40:38.888534,479392841,887,210,16.59050869204,-34.61028370499,23.900687523285,2,1,18 +2025-03-11T12:40:39.013534,479392841,887,210,16.85878074928,-35.257061491445,24.394407352485,2,1,18 +2025-03-11T12:40:39.138534,479392841,887,210,17.11293322456,-35.802244986365,24.822879637785,2,1,18 +2025-03-11T12:40:39.263534,479392841,887,210,17.31531389932,-36.268862274155,25.204625014155,2,1,18 +2025-03-11T12:40:39.388534,479392841,887,210,17.49416193748,-36.666189788195,25.512032573385,2,1,18 +2025-03-11T12:40:39.513534,479392841,887,210,17.6400642844,-36.975745530875,25.74960472203,2,1,18 +2025-03-11T12:40:39.638534,479392841,887,210,17.73890135812,-37.229826933065,25.940581818225,2,1,18 +2025-03-11T12:40:39.763534,479392841,887,210,17.8047927406,-37.414604387675,26.061820838835,2,1,18 +2025-03-11T12:40:39.888534,479392841,887,210,17.85656454112,-37.48855363886,26.117763648045,2,1,18 +2025-03-11T12:40:40.013534,479392841,887,210,17.86127106844,-37.48394376983,26.108509267995,2,1,18 +2025-03-11T12:40:40.138534,479392841,887,210,17.81420579524,-37.368449002055,26.03849729172,2,1,18 +2025-03-11T12:40:40.263534,479392841,887,210,17.7341948308,-37.197501154535,25.894200124095,2,1,18 +2025-03-11T12:40:40.388534,479392841,887,210,17.62123817512,-36.948015447545,25.6847363304,2,1,18 +2025-03-11T12:40:40.513534,479392841,887,210,17.47062930088,-36.61075088228,25.43314764048,2,1,18 +2025-03-11T12:40:40.638534,479392841,887,210,17.30119431736,-36.190352762345,25.111778436915,2,1,18 +2025-03-11T12:40:40.763534,479392841,887,210,17.09410711528,-35.719111431695,24.72537842205,2,1,18 +2025-03-11T12:40:40.888534,479392841,887,210,16.83524811268,-35.1369852023,24.301321396035,2,1,18 +2025-03-11T12:40:41.013534,479392841,887,210,16.54344341884,-34.513256760995,23.81229241395,2,1,18 +2025-03-11T12:40:41.138534,479392841,887,210,16.22339956108,-33.80638059119,23.24422230873,2,1,18 +2025-03-11T12:40:41.263534,479392841,887,210,15.8751165394,-32.98403800127,22.633901680245,2,1,18 +2025-03-11T12:40:41.388534,479392841,887,210,15.48447477184,-32.115462069665,21.94932415245,2,1,18 +2025-03-11T12:40:41.513534,479392841,887,210,15.08441994964,-31.186851536945,21.24130932537,2,1,18 +2025-03-11T12:40:41.638534,479392841,887,210,14.64671290888,-30.184313013785,20.472762135255,2,1,18 +2025-03-11T12:40:41.763534,479392841,887,210,14.19017975884,-29.154044407295,19.653206904555,2,1,18 +2025-03-11T12:40:41.888534,479392841,887,210,13.7101139722,-28.017550379495,18.78221977179,2,1,18 +2025-03-11T12:40:42.013473,479392845,883,211,13.19710249432,-26.830220227895,17.883172951575,2,1,18 +2025-03-11T12:40:42.138473,479392845,883,211,12.66055837984,-25.610535950105,16.92846345228,2,1,18 +2025-03-11T12:40:42.263473,479392845,883,211,12.11460121072,-24.34928489498,15.94117375467,2,1,18 +2025-03-11T12:40:42.388473,479392845,883,211,11.55452445964,-23.04184301966,14.921269337265,2,1,18 +2025-03-11T12:40:42.513473,479392845,883,211,10.9332628534,-21.67428858716,13.8639552045,2,1,18 +2025-03-11T12:40:42.638473,479392845,883,211,10.32612082912,-20.251351944065,12.769418693805,2,1,18 +2025-03-11T12:40:42.763473,479392845,883,211,9.70015269556,-18.833003909255,11.661005414895,2,1,18 +2025-03-11T12:40:42.888473,479392845,883,211,9.0506519254,-17.363833924475,10.515312589965,2,1,18 +2025-03-11T12:40:43.013473,479392845,883,211,8.3917381006,-15.866948030195,9.35559303603,2,1,18 +2025-03-11T12:40:43.138473,479392845,883,211,7.7328242758,-14.3377434443,8.1818427948,2,1,18 +2025-03-11T12:40:43.263473,479392845,883,211,7.06449739636,-12.81314164052,6.994236160815,2,1,18 +2025-03-11T12:40:43.388473,479392845,883,211,6.38675746228,-11.256206971295,5.80643881512,2,1,18 +2025-03-11T12:40:43.513473,479392845,883,211,5.69489794624,-9.69463408538,4.58624575338,2,1,18 +2025-03-11T12:40:43.638473,479392845,883,211,5.03127759412,-8.12848676501,3.361469367255,2,1,18 +2025-03-11T12:40:43.763473,479392845,883,211,4.33941807808,-6.56229692315,2.15511232281,2,1,18 +2025-03-11T12:40:43.888473,479392845,883,211,3.64755856204,-4.99610708129,0.948755278365,2,1,18 +2025-03-11T12:40:44.013473,479392845,883,211,2.97452515528,-3.453030366815,-0.243578995365,2,1,18 +2025-03-11T12:40:44.138473,479392845,883,211,2.30149174852,-1.92842147612,-1.445056168125,2,1,18 +2025-03-11T12:40:44.263473,479392845,883,211,1.62375181444,-0.408422454454998,-2.63265884382,2,1,18 +2025-03-11T12:40:44.388473,479392845,883,211,0.96013146232,1.10693835052,-3.80634627153,2,1,18 +2025-03-11T12:40:44.513473,479392845,883,211,0.310630692160001,2.599193115025,-4.947540648195,2,1,18 +2025-03-11T12:40:44.638473,479392845,883,211,-0.324750496039999,4.0314061915,-6.06066742083,2,1,18 +2025-03-11T12:40:44.763473,479392845,883,211,-0.946012102279999,5.458981051285,-7.16911917951,2,1,18 +2025-03-11T12:40:44.888473,479392845,883,211,-1.55786065388,6.84037217779,-8.24958652314,2,1,18 +2025-03-11T12:40:45.013473,479392845,883,211,-2.15558962352,8.18480639599,-9.297487814475,2,1,18 +2025-03-11T12:40:45.138473,479392845,883,211,-2.72507942924,9.47379462136,-10.30807503831,2,1,18 +2025-03-11T12:40:45.263473,479392845,883,211,-3.27574312568,10.71658493962,-11.26755688656,2,1,18 +2025-03-11T12:40:45.388473,479392845,883,211,-3.82640682212,11.936290478155,-12.194576246955,2,1,18 +2025-03-11T12:40:45.513473,479392845,883,211,-4.3158856634,13.08664954762,-13.079517107475,2,1,18 +2025-03-11T12:40:45.638473,479392845,883,211,-4.7865383954,14.17695984214,-13.93176005922,2,1,18 +2025-03-11T12:40:45.763473,479392845,883,211,-5.2336584908,15.202597318855,-14.709689527575,2,1,18 +2025-03-11T12:40:45.888473,479392845,883,211,-5.65253942228,16.17278880274,-15.464165279475,2,1,18 +2025-03-11T12:40:46.013412,479392849,879,212,-6.03847466252,17.05059155932,-16.162641638085,2,1,18 +2025-03-11T12:40:46.138412,479392849,879,212,-6.40558379348,17.886813364735,-16.7915564868,2,1,18 +2025-03-11T12:40:46.263412,479392849,879,212,-6.73033417856,18.64448313685,-17.383005036075,2,1,18 +2025-03-11T12:40:46.388412,479392849,879,212,-7.05037803632,19.342125394765,-17.895585069615,2,1,18 +2025-03-11T12:40:46.513412,479392849,879,212,-7.31394356624,19.92887566702,-18.370497904275,2,1,18 +2025-03-11T12:40:46.638412,479392849,879,212,-7.54926993224,20.469413858335,-18.771184402815,2,1,18 +2025-03-11T12:40:46.763412,479392849,879,212,-7.75635713432,20.92680432115,-19.134410831355,2,1,18 +2025-03-11T12:40:46.888412,479392849,879,212,-7.90696600856,21.291770622085,-19.432346693925,2,1,18 +2025-03-11T12:40:47.013412,479392849,879,212,-8.04345530084,21.5874613231,-19.665205348845,2,1,18 +2025-03-11T12:40:47.138412,479392849,879,212,-8.1517054292,21.81385516345,-19.81909588188,2,1,18 +2025-03-11T12:40:47.263412,479392849,879,212,-8.20347722972,21.952441797865,-19.926200650755,2,1,18 +2025-03-11T12:40:47.388412,479392849,879,212,-8.22700986632,21.98941288,-19.94954684448,2,1,18 +2025-03-11T12:40:47.513412,479392849,879,212,-8.21759681168,21.947846102665,-19.926206880195,2,1,18 +2025-03-11T12:40:47.638412,479392849,879,212,-8.17053153848,21.836968290835,-19.85621923767,2,1,18 +2025-03-11T12:40:47.763412,479392849,879,212,-8.09052057404,21.65216957548,-19.711849068795,2,1,18 +2025-03-11T12:40:47.888412,479392849,879,212,-7.97756391836,21.36574822093,-19.47446990301,2,1,18 +2025-03-11T12:40:48.013412,479392849,879,212,-7.8222485168,21.01924265686,-19.199721772785,2,1,18 +2025-03-11T12:40:48.138412,479392849,879,212,-7.633987424,20.57573140954,-18.85046944746,2,1,18 +2025-03-11T12:40:48.263412,479392849,879,212,-7.40807411264,20.053675215835,-18.46838112744,2,1,18 +2025-03-11T12:40:48.388412,479392849,879,212,-7.13509552808,19.46691076975,-18.025788736425,2,1,18 +2025-03-11T12:40:48.513412,479392849,879,212,-6.8574104162,18.810884897575,-17.495038928145,2,1,18 +2025-03-11T12:40:48.638412,479392849,879,212,-6.53266003112,18.07168294924,-16.926788298945,2,1,18 +2025-03-11T12:40:48.763412,479392849,879,212,-6.16555090016,17.25854592355,-16.302615235995,2,1,18 +2025-03-11T12:40:48.888412,479392849,879,212,-5.77020260528,16.357644213415,-15.61785718422,2,1,18 +2025-03-11T12:40:49.013412,479392849,879,212,-5.36073472844,15.40593472714,-14.868119259795,2,1,18 +2025-03-11T12:40:49.138412,479392849,879,212,-4.90890810572,14.394141031345,-14.0717721369,2,1,18 +2025-03-11T12:40:49.263412,479392849,879,212,-4.457081483,13.3361777761,-13.2428408574,2,1,18 +2025-03-11T12:40:49.388412,479392849,879,212,-3.95818958708,12.20888931253,-12.362621407185,2,1,18 +2025-03-11T12:40:49.513412,479392849,879,212,-3.43576505456,11.016928031155,-11.449669526715,2,1,18 +2025-03-11T12:40:49.638412,479392849,879,212,-2.89451441276,9.764917974835,-10.490159386425,2,1,18 +2025-03-11T12:40:49.763412,479392849,879,212,-2.32031807972,8.462071794715,-9.47024873958,2,1,18 +2025-03-11T12:40:49.888412,479392849,879,212,-1.74612174668,7.12690692298,-8.44554763947,2,1,18 +2025-03-11T12:40:50.013336,479392853,874,213,-1.1389797224,5.75475679528,-7.38361961913,2,1,18 +2025-03-11T12:40:50.138336,479392853,874,213,-0.51301158884,4.341025716415,-6.284470908,2,1,18 +2025-03-11T12:40:50.263336,479392853,874,213,0.11295654472,2.904209857825,-5.171340177075,2,1,18 +2025-03-11T12:40:50.388336,479392853,874,213,0.75775078756,1.411962180235,-4.02091575411,2,1,18 +2025-03-11T12:40:50.513336,479392853,874,213,1.41195808504,-0.0802996711849993,-2.861230721655,2,1,18 +2025-03-11T12:40:50.638336,479392853,874,213,2.09440454644,-1.60492273571,-1.69207399254,2,1,18 +2025-03-11T12:40:50.763336,479392853,874,213,2.77685100784,-3.138779712125,-0.50900824488,2,1,18 +2025-03-11T12:40:50.888336,479392853,874,213,3.4498844146,-4.70032425038,0.69266359788,2,1,18 +2025-03-11T12:40:51.013336,479392853,874,213,4.12762434868,-6.26187587555,1.917446213445,2,1,18 +2025-03-11T12:40:51.138336,479392853,874,213,4.81948386472,-7.81883180552,3.12375459039,2,1,18 +2025-03-11T12:40:51.263336,479392853,874,213,5.50193032612,-9.380390517605,4.339307159655,2,1,18 +2025-03-11T12:40:51.388336,479392853,874,213,6.17496373288,-10.94193505586,5.559459470475,2,1,18 +2025-03-11T12:40:51.513336,479392853,874,213,6.86682324892,-12.503507941775,6.75655194714,2,1,18 +2025-03-11T12:40:51.638336,479392853,874,213,7.53985665568,-14.032733788415,7.953433336635,2,1,18 +2025-03-11T12:40:51.763336,479392853,874,213,8.2034770078,-15.56656241717,9.12259798233,2,1,18 +2025-03-11T12:40:51.888336,479392853,874,213,8.86709735992,-17.05883844242,10.28692350726,2,1,18 +2025-03-11T12:40:52.013336,479392853,874,213,9.51659813008,-18.51877451531,11.44180789872,2,1,18 +2025-03-11T12:40:52.138336,479392853,874,213,10.14256626364,-19.969441241735,12.55039151388,2,1,18 +2025-03-11T12:40:52.263336,479392853,874,213,10.77794745184,-21.38318649443,13.64032036644,2,1,18 +2025-03-11T12:40:52.388336,479392853,874,213,11.3803829488,-22.74147866738,14.69292496377,2,1,18 +2025-03-11T12:40:52.513336,479392853,874,213,11.95457928184,-24.085877451005,15.71767473138,2,1,18 +2025-03-11T12:40:52.638336,479392853,874,213,12.52877561488,-25.361021895455,16.728199141695,2,1,18 +2025-03-11T12:40:52.763336,479392853,874,213,13.07943931132,-26.59919525777,17.678416422165,2,1,18 +2025-03-11T12:40:52.888336,479392853,874,213,13.58774426188,-27.777284410565,18.591264738195,2,1,18 +2025-03-11T12:40:53.013336,479392853,874,213,14.09134268512,-28.93228169672,19.48088061267,2,1,18 +2025-03-11T12:40:53.138336,479392853,874,213,14.5808215264,-29.97645077945,20.30982039276,2,1,18 +2025-03-11T12:40:53.263336,479392853,874,213,15.01382203984,-30.997450039475,21.09231508119,2,1,18 +2025-03-11T12:40:53.388336,479392853,874,213,15.42328991668,-31.953776481695,21.80049628623,2,1,18 +2025-03-11T12:40:53.513336,479392853,874,213,15.82334473888,-32.82236658713,22.494334423515,2,1,18 +2025-03-11T12:40:53.638336,479392853,874,213,16.16692123324,-33.607766442575,23.118310545315,2,1,18 +2025-03-11T12:40:53.763336,479392853,874,213,16.49637814564,-34.346975477825,23.69119147926,2,1,18 +2025-03-11T12:40:53.888336,479392853,874,213,16.7928893668,-35.00302969766,24.19426133637,2,1,18 +2025-03-11T12:40:54.013275,479392857,870,214,17.0517483694,-35.59900679489,24.655352299755,2,1,18 +2025-03-11T12:40:54.138275,479392857,870,214,17.26824862612,-36.12566577071,25.037444578065,2,1,18 +2025-03-11T12:40:54.263275,479392857,870,214,17.4753358282,-36.564588409745,25.382093203545,2,1,18 +2025-03-11T12:40:54.388275,479392857,870,214,17.63535775708,-36.906484104785,25.63834671969,2,1,18 +2025-03-11T12:40:54.513275,479392857,870,214,17.74831441276,-37.1790545915,25.847932182135,2,1,18 +2025-03-11T12:40:54.638275,479392857,870,214,17.82361884988,-37.349995352105,26.006079513075,2,1,18 +2025-03-11T12:40:54.763275,479392857,870,214,17.88009717772,-37.45627038182,26.099163782385,2,1,18 +2025-03-11T12:40:54.888275,479392857,870,214,17.90362981432,-37.493241463955,26.12250997611,2,1,18 +2025-03-11T12:40:55.013275,479392857,870,214,17.86127106844,-37.423923342545,26.07585211014,2,1,18 +2025-03-11T12:40:55.138275,479392857,870,214,17.79067315864,-37.28530836047,25.96408647333,2,1,18 +2025-03-11T12:40:55.263275,479392857,870,214,17.72007524884,-37.07743903922,25.78727419206,2,1,18 +2025-03-11T12:40:55.388275,479392857,870,214,17.58358595656,-36.76789747037,25.53586206783,2,1,18 +2025-03-11T12:40:55.513275,479392857,870,214,17.41415097304,-36.36135021827,25.251526801635,2,1,18 +2025-03-11T12:40:55.638275,479392857,870,214,17.21177029828,-35.927051622095,24.89305234659,2,1,18 +2025-03-11T12:40:55.763275,479392857,870,214,16.97644393228,-35.38651343078,24.48312561402,2,1,18 +2025-03-11T12:40:55.888275,479392857,870,214,16.70346534772,-34.76743029308,24.01726230168,2,1,18 +2025-03-11T12:40:56.013275,479392857,870,214,16.3928345446,-34.060568297105,23.472313156995,2,1,18 +2025-03-11T12:40:56.138275,479392857,870,214,16.05867110488,-33.29365043927,22.885415681775,2,1,18 +2025-03-11T12:40:56.263275,479392857,870,214,15.69156197392,-32.466662545745,22.22882879847,2,1,18 +2025-03-11T12:40:56.388275,479392857,870,214,15.2868006244,-31.56574666178,21.53943025422,2,1,18 +2025-03-11T12:40:56.513275,479392857,870,214,14.88203927488,-30.60481035053,20.78503373301,2,1,18 +2025-03-11T12:40:56.638275,479392857,870,214,14.42550612484,-29.560690876205,19.98388596912,2,1,18 +2025-03-11T12:40:56.763275,479392857,870,214,13.95014686552,-28.484224362605,19.122465596865,2,1,18 +2025-03-11T12:40:56.888275,479392857,870,214,13.4512549696,-27.3430850312,18.246793262415,2,1,18 +2025-03-11T12:40:57.013275,479392857,870,214,12.91471085512,-26.1326346653,17.30137266465,2,1,18 +2025-03-11T12:40:57.138275,479392857,870,214,12.35463410404,-24.875979305375,16.327937088645,2,1,18 +2025-03-11T12:40:57.263275,479392857,870,214,11.780437771,-23.573133125255,15.31726667583,2,1,18 +2025-03-11T12:40:57.388275,479392857,870,214,11.19682838332,-22.224103211855,14.278611847965,2,1,18 +2025-03-11T12:40:57.513275,479392857,870,214,10.60851246832,-20.851981431815,13.207484344515,2,1,18 +2025-03-11T12:40:57.638275,479392857,870,214,9.98725086208,-19.429023527975,12.099056919585,2,1,18 +2025-03-11T12:40:57.763275,479392857,870,214,9.35186967388,-17.973725671775,10.9858084782,2,1,18 +2025-03-11T12:40:57.888275,479392857,870,214,8.68354279444,-16.48144255961,9.83071299957,2,1,18 +2025-03-11T12:40:58.013214,479392861,866,215,8.01992244232,-14.975315666525,8.6385937713,2,1,18 +2025-03-11T12:40:58.138214,479392861,866,215,7.3563020902,-13.436870081825,7.450924323795,2,1,18 +2025-03-11T12:40:58.263214,479392861,866,215,6.68326868344,-11.879942499515,6.276997516875,2,1,18 +2025-03-11T12:40:58.388214,479392861,866,215,5.98670264008,-10.34144730641,5.084636638245,2,1,18 +2025-03-11T12:40:58.513214,479392861,866,215,5.29954965136,-8.7891154193,3.873742665765,2,1,18 +2025-03-11T12:40:58.638214,479392861,866,215,4.61710318996,-7.22293975127,2.662785879765,2,1,18 +2025-03-11T12:40:58.763214,479392861,866,215,3.93465672856,-5.670614951075,1.42880150994,2,1,18 +2025-03-11T12:40:58.888214,479392861,866,215,3.23338415788,-4.09056006755,0.21773097177,2,1,18 +2025-03-11T12:40:59.013214,479392861,866,215,2.56035075112,-2.556717264965,-0.98379486849,2,1,18 +2025-03-11T12:40:59.138214,479392861,866,215,1.88261081704,-1.01825041952,-2.162254645155,2,1,18 +2025-03-11T12:40:59.263214,479392861,866,215,1.20487088296,0.492514690255,-3.32208795126,2,1,18 +2025-03-11T12:40:59.388214,479392861,866,215,0.564783167440001,1.98475528093,-4.46788206948,2,1,18 +2025-03-11T12:40:59.513214,479392861,866,215,-0.0753045480800001,3.44467717999,-5.599645500405,2,1,18 +2025-03-11T12:40:59.638214,479392861,866,215,-0.705979208960001,4.890734037385,-6.71283508656,2,1,18 +2025-03-11T12:40:59.763214,479392861,866,215,-1.31312123324,6.2952028567,-7.79341391121,2,1,18 +2025-03-11T12:40:59.888214,479392861,866,215,-1.92026325752,7.644268204675,-8.850600145785,2,1,18 +2025-03-11T12:41:00.013214,479392861,866,215,-2.4803400086,8.960943991885,-9.87979346472,2,1,18 +2025-03-11T12:41:00.138214,479392861,866,215,-3.045123287,10.23145730656,-10.853312229705,2,1,18 +2025-03-11T12:41:00.263214,479392861,866,215,-3.59578698344,11.460396756985,-11.79886072566,2,1,18 +2025-03-11T12:41:00.388214,479392861,866,215,-4.08997235204,12.6246137812,-12.73008594531,2,1,18 +2025-03-11T12:41:00.513214,479392861,866,215,-4.58415772064,13.733427334075,-13.57785705369,2,1,18 +2025-03-11T12:41:00.638214,479392861,866,215,-5.04069087068,14.7775468084,-14.383624934595,2,1,18 +2025-03-11T12:41:00.763214,479392861,866,215,-5.48781096608,15.7708655935,-15.175244417745,2,1,18 +2025-03-11T12:41:00.888214,479392861,866,215,-5.91139842488,16.72259634052,-15.892672086255,2,1,18 +2025-03-11T12:41:01.013214,479392861,866,215,-6.27850755584,17.55420118999,-16.55852353734,2,1,18 +2025-03-11T12:41:01.138214,479392861,866,215,-6.6220840502,18.339601045435,-17.159399074065,2,1,18 +2025-03-11T12:41:01.263214,479392861,866,215,-6.93271485332,19.06493086519,-17.709065670765,2,1,18 +2025-03-11T12:41:01.388214,479392861,866,215,-7.21510649252,19.697879044555,-18.202743061905,2,1,18 +2025-03-11T12:41:01.513214,479392861,866,215,-7.46455244048,20.25228936445,-18.640494061005,2,1,18 +2025-03-11T12:41:01.638214,479392861,866,215,-7.6810526972,20.72354486893,-19.0176742173,2,1,18 +2025-03-11T12:41:01.763214,479392861,866,215,-7.86460726268,21.157815117445,-19.339146985305,2,1,18 +2025-03-11T12:41:01.888214,479392861,866,215,-8.01992266424,21.485852857735,-19.57683684441,2,1,18 +2025-03-11T12:41:02.013153,479392865,862,216,-8.14229237456,21.735352738555,-19.77246066252,2,1,18 +2025-03-11T12:41:02.138153,479392865,862,216,-8.21289028436,21.915520324135,-19.907545888155,2,1,18 +2025-03-11T12:41:02.263153,479392865,862,216,-8.25054250292,21.99406527052,-19.972722701955,2,1,18 +2025-03-11T12:41:02.388153,479392865,862,216,-8.222303339,21.97555492525,-19.96794412356,2,1,18 +2025-03-11T12:41:02.513153,479392865,862,216,-8.19406417508,21.88317328486,-19.911954918,2,1,18 +2025-03-11T12:41:02.638153,479392865,862,216,-8.13287931992,21.716870740945,-19.78158318609,2,1,18 +2025-03-11T12:41:02.763153,479392865,862,216,-8.0340422462,21.481257162535,-19.590703424895,2,1,18 +2025-03-11T12:41:02.888153,479392865,862,216,-7.90225948124,21.157871812765,-19.339228487145,2,1,18 +2025-03-11T12:41:03.013153,479392865,862,216,-7.73282449772,20.760558472555,-19.022601069345,2,1,18 +2025-03-11T12:41:03.138153,479392865,862,216,-7.516324241,20.261601232405,-18.64527491055,2,1,18 +2025-03-11T12:41:03.263153,479392865,862,216,-7.26687829304,19.68872308873,-18.221286927495,2,1,18 +2025-03-11T12:41:03.388153,479392865,862,216,-6.98448665384,19.0696257772,-17.727682537605,2,1,18 +2025-03-11T12:41:03.513153,479392865,862,216,-6.67856237804,18.367387824085,-17.16428744634,2,1,18 +2025-03-11T12:41:03.638153,479392865,862,216,-6.339692411,17.572761143665,-16.563373429845,2,1,18 +2025-03-11T12:41:03.763153,479392865,862,216,-5.95846369808,16.718050253725,-15.901989863835,2,1,18 +2025-03-11T12:41:03.888153,479392865,862,216,-5.55840887588,15.798673632895,-15.194023704255,2,1,18 +2025-03-11T12:41:04.013153,479392865,862,216,-5.13011488976,14.8100001514,-14.43481012488,2,1,18 +2025-03-11T12:41:04.138153,479392865,862,216,-4.65946215776,13.761242460385,-13.60588676196,2,1,18 +2025-03-11T12:41:04.263153,479392865,862,216,-4.16527678916,12.65242890751,-12.73963518552,2,1,18 +2025-03-11T12:41:04.388153,479392865,862,216,-3.65226531128,11.488183535635,-11.84533015107,2,1,18 +2025-03-11T12:41:04.513153,479392865,862,216,-3.12513425144,10.268513431675,-10.909121495295,2,1,18 +2025-03-11T12:41:04.638153,479392865,862,216,-2.56976402768,9.01648211461,-9.931100323755,2,1,18 +2025-03-11T12:41:04.763153,479392865,862,216,-1.98615464,7.681303069045,-8.897138614155,2,1,18 +2025-03-11T12:41:04.888153,479392865,862,216,-1.397838725,6.309181289005,-7.83987146175,2,1,18 +2025-03-11T12:41:05.013153,479392865,862,216,-0.781283646079999,4.92316611964,-6.75936959664,2,1,18 +2025-03-11T12:41:05.138153,479392865,862,216,-0.13648940324,3.481704957445,-5.65079389806,2,1,18 +2025-03-11T12:41:05.263153,479392865,862,216,0.5083048396,2.02177597147,-4.537500747465,2,1,18 +2025-03-11T12:41:05.388153,479392865,862,216,1.16251213708,0.529514120050001,-3.37781571501,2,1,18 +2025-03-11T12:41:05.513153,479392865,862,216,1.8025998526,-0.995045162239999,-2.20413055845,2,1,18 +2025-03-11T12:41:05.638153,479392865,862,216,2.47092673204,-2.51041305413,-1.007332357935,2,1,18 +2025-03-11T12:41:05.763153,479392865,862,216,3.1439601388,-4.044255856715,0.194193482325,2,1,18 +2025-03-11T12:41:05.888153,479392865,862,216,3.83581965484,-5.61506265452,1.386714509475,2,1,18 +2025-03-11T12:41:06.013077,479392869,857,217,4.52297264356,-7.18586236541,2.611566168,2,1,18 +2025-03-11T12:41:06.138077,479392869,857,217,5.20541910496,-8.72433629777,3.8223769515,2,1,18 +2025-03-11T12:41:06.263077,479392869,857,217,5.88315903904,-10.28588792294,5.028679099005,2,1,18 +2025-03-11T12:41:06.388077,479392869,857,217,6.5797250824,-11.833617027935,6.24418923021,2,1,18 +2025-03-11T12:41:06.513077,479392869,857,217,7.26687807112,-13.37209804721,7.441149850395,2,1,18 +2025-03-11T12:41:06.638077,479392869,857,217,7.95873758716,-14.9105861534,8.642740775325,2,1,18 +2025-03-11T12:41:06.763077,479392869,857,217,8.63177099392,-16.425961132205,9.834929046555,2,1,18 +2025-03-11T12:41:06.888077,479392869,857,217,9.26715218212,-17.90434376813,10.962159507735,2,1,18 +2025-03-11T12:41:07.013077,479392869,857,217,9.90253337032,-19.355024668385,12.07538361537,2,1,18 +2025-03-11T12:41:07.138077,479392869,857,217,10.52379497656,-20.777982572225,13.179190923285,2,1,18 +2025-03-11T12:41:07.263077,479392869,857,217,11.12623047352,-22.17782734868,14.24587487541,2,1,18 +2025-03-11T12:41:07.388077,479392869,857,217,11.72395944316,-23.526878522825,15.284560266465,2,1,18 +2025-03-11T12:41:07.513077,479392869,857,217,12.29344924888,-24.82971761603,16.30446072558,2,1,18 +2025-03-11T12:41:07.638077,479392869,857,217,12.84881947264,-26.100216756875,17.29181946615,2,1,18 +2025-03-11T12:41:07.763077,479392869,857,217,13.3806570598,-27.31066003586,18.227989642155,2,1,18 +2025-03-11T12:41:07.888077,479392869,857,217,13.89366853768,-28.465671495845,19.12686612612,2,1,18 +2025-03-11T12:41:08.013077,479392869,857,217,14.37373432432,-29.56061292014,19.96529343603,2,1,18 +2025-03-11T12:41:08.138077,479392869,857,217,14.83026747436,-30.586264570685,20.770963981935,2,1,18 +2025-03-11T12:41:08.263077,479392869,857,217,15.24444187852,-31.54259809982,21.52073642784,2,1,18 +2025-03-11T12:41:08.388077,479392869,857,217,15.64920322804,-32.42966311595,22.23778267293,2,1,18 +2025-03-11T12:41:08.513077,479392869,857,217,16.016312359,-33.28896970109,22.876059424425,2,1,18 +2025-03-11T12:41:08.638077,479392869,857,217,16.36459538068,-34.06514273156,23.47689648138,2,1,18 +2025-03-11T12:41:08.763077,479392869,857,217,16.67993271112,-34.758160946615,24.003302344485,2,1,18 +2025-03-11T12:41:08.888077,479392869,857,217,16.94820476836,-35.391087865235,24.496949172435,2,1,18 +2025-03-11T12:41:09.013077,479392869,857,217,17.18353113436,-35.936243012495,24.91152035577,2,1,18 +2025-03-11T12:41:09.138077,479392869,857,217,17.4047379184,-36.384420824165,25.24700797791,2,1,18 +2025-03-11T12:41:09.263077,479392869,857,217,17.57417290192,-36.772500252485,25.540486143135,2,1,18 +2025-03-11T12:41:09.388077,479392869,857,217,17.70124913956,-37.072793735615,25.791829224405,2,1,18 +2025-03-11T12:41:09.513077,479392869,857,217,17.80949926792,-37.289953664075,25.964151558,2,1,18 +2025-03-11T12:41:09.638077,479392869,857,217,17.8753906504,-37.447029383015,26.06676410805,2,1,18 +2025-03-11T12:41:09.763077,479392869,857,217,17.898923287,-37.47476655326,26.108542102335,2,1,18 +2025-03-11T12:41:09.888077,479392869,857,217,17.88009717772,-37.451653425875,26.08527909759,2,1,18 +2025-03-11T12:41:10.013015,479392873,853,218,17.84244495916,-37.350023699765,26.006120263995,2,1,18 +2025-03-11T12:41:10.138015,479392873,853,218,17.74360788544,-37.160579680805,25.87092524448,2,1,18 +2025-03-11T12:41:10.263015,479392873,853,218,17.62123817512,-36.901845888095,25.652152173795,2,1,18 +2025-03-11T12:41:10.388015,479392873,853,218,17.46592277356,-36.55995727997,25.37742837732,2,1,18 +2025-03-11T12:41:10.513015,479392873,853,218,17.27766168076,-36.130296900485,25.037489287275,2,1,18 +2025-03-11T12:41:10.638015,479392873,853,218,17.06586795136,-35.59441109969,24.64149817815,2,1,18 +2025-03-11T12:41:10.763015,479392873,853,218,16.81171547608,-35.026142825045,24.189803639025,2,1,18 +2025-03-11T12:41:10.888015,479392873,853,218,16.54344341884,-34.3701311267,23.686794908295,2,1,18 +2025-03-11T12:41:11.013015,479392873,853,218,16.20927997912,-33.63553196048,23.1231683544,2,1,18 +2025-03-11T12:41:11.138015,479392873,853,218,15.85629043012,-32.81779923959,22.512861871935,2,1,18 +2025-03-11T12:41:11.263015,479392873,853,218,15.4750617172,-31.958471393705,21.83759362113,2,1,18 +2025-03-11T12:41:11.388015,479392873,853,218,15.075006895,-31.01600999315,21.09254485668,2,1,18 +2025-03-11T12:41:11.513015,479392873,853,218,14.63259332692,-30.00884742713,20.314722911055,2,1,18 +2025-03-11T12:41:11.638015,479392873,853,218,14.16194059492,-28.91853713261,19.48096042737,2,1,18 +2025-03-11T12:41:11.763015,479392873,853,218,13.66775522632,-27.7958727119,18.600775498635,2,1,18 +2025-03-11T12:41:11.888015,479392873,853,218,13.15003722112,-26.62238634122,17.68331102388,2,1,18 +2025-03-11T12:41:12.013015,479392873,853,218,12.59937352468,-25.37959602296,16.73306940966,2,1,18 +2025-03-11T12:41:12.138015,479392873,853,218,12.02988371896,-24.095224753535,15.740986987635,2,1,18 +2025-03-11T12:41:12.263015,479392873,853,218,11.44627433128,-22.77851353175,14.71174273005,2,1,18 +2025-03-11T12:41:12.388015,479392873,853,218,10.84854536164,-21.40637757788,13.6590753192,2,1,18 +2025-03-11T12:41:12.513015,479392873,853,218,10.2272837554,-19.997270541875,12.564581246565,2,1,18 +2025-03-11T12:41:12.638015,479392873,853,218,9.58719603988,-18.555816466595,11.437535267655,2,1,18 +2025-03-11T12:41:12.763015,479392873,853,218,8.96122790632,-17.091298872335,10.29653783214,2,1,18 +2025-03-11T12:41:12.888015,479392873,853,218,8.31643366348,-15.589817282855,9.127584273615,2,1,18 +2025-03-11T12:41:13.013015,479392873,853,218,7.64340025672,-14.07444230405,7.953876470445,2,1,18 +2025-03-11T12:41:13.138015,479392873,853,218,6.956247268,-12.54057824072,6.75694018401,2,1,18 +2025-03-11T12:41:13.263015,479392873,853,218,6.2738008066,-10.99287039647,5.569181318085,2,1,18 +2025-03-11T12:41:13.388015,479392873,853,218,5.58194129056,-9.42668055461,4.348963922595,2,1,18 +2025-03-11T12:41:13.513015,479392873,853,218,4.89949482916,-7.86050488658,3.138007136595,2,1,18 +2025-03-11T12:41:13.638015,479392873,853,218,4.20763531312,-6.298932000665,1.927054308885,2,1,18 +2025-03-11T12:41:13.763015,479392873,853,218,3.51577579708,-4.723508246915,0.716028479925,2,1,18 +2025-03-11T12:41:13.888015,479392873,853,218,2.838035863,-3.17580748958,-0.4809604323,2,1,18 +2025-03-11T12:41:14.012954,479392877,849,219,2.16500245624,-1.63734773105,-1.677890489295,2,1,18 +2025-03-11T12:41:14.137954,479392877,849,219,1.49196904948,-0.103504928465,-2.851695627465,2,1,18 +2025-03-11T12:41:14.262954,479392877,849,219,0.833055224680001,1.393380965815,-4.02065541543,2,1,18 +2025-03-11T12:41:14.387954,479392877,849,219,0.178847927200001,2.857941081565,-5.14785362628,2,1,18 +2025-03-11T12:41:14.512954,479392877,849,219,-0.45182673368,4.31323185085,-6.27495223098,2,1,18 +2025-03-11T12:41:14.637954,479392877,849,219,-1.05426223064,5.71769358325,-7.37400133596,2,1,18 +2025-03-11T12:41:14.762954,479392877,849,219,-1.67081730956,7.085240928835,-8.44516563204,2,1,18 +2025-03-11T12:41:14.887954,479392877,849,219,-2.26383975188,8.43890197201,-9.483865169115,2,1,18 +2025-03-11T12:41:15.012954,479392877,849,219,-2.82391650296,9.723259067605,-10.480547332695,2,1,18 +2025-03-11T12:41:15.137954,479392877,849,219,-3.3745801994,10.95219851803,-11.430715945665,2,1,18 +2025-03-11T12:41:15.262954,479392877,849,219,-3.8922982046,12.139535756545,-12.362113772715,2,1,18 +2025-03-11T12:41:15.387954,479392877,849,219,-4.37707051856,13.26680295937,-13.25154289377,2,1,18 +2025-03-11T12:41:15.512954,479392877,849,219,-4.86184283252,14.357134514635,-14.076095706615,2,1,18 +2025-03-11T12:41:15.637954,479392877,849,219,-5.30896292792,15.387388947295,-14.85404950872,2,1,18 +2025-03-11T12:41:15.762954,479392877,849,219,-5.7278438594,16.306793915785,-15.594397238325,2,1,18 +2025-03-11T12:41:15.887954,479392877,849,219,-6.12319215428,17.175376934305,-16.274364836835,2,1,18 +2025-03-11T12:41:16.012954,479392877,849,219,-6.46206212132,17.997705350395,-16.907765674935,2,1,18 +2025-03-11T12:41:16.137954,479392877,849,219,-6.79151903372,18.736914385645,-17.47140637485,2,1,18 +2025-03-11T12:41:16.262954,479392877,849,219,-7.10214983684,19.40684073406,-17.99306026446,2,1,18 +2025-03-11T12:41:16.387954,479392877,849,219,-7.37042189408,20.025916784845,-18.454293272055,2,1,18 +2025-03-11T12:41:16.512954,479392877,849,219,-7.59633520544,20.54797297855,-18.864102294165,2,1,18 +2025-03-11T12:41:16.637954,479392877,849,219,-7.7987158802,20.982271574725,-19.19485604712,2,1,18 +2025-03-11T12:41:16.762954,479392877,849,219,-7.9634443364,21.35187609235,-19.469746221555,2,1,18 +2025-03-11T12:41:16.887954,479392877,849,219,-8.09052057404,21.629084795755,-19.67938658094,2,1,18 +2025-03-11T12:41:17.012954,479392877,849,219,-8.16582501116,21.813876424195,-19.832986796115,2,1,18 +2025-03-11T12:41:17.137954,479392877,849,219,-8.21759681168,21.929378278885,-19.926109545195,2,1,18 +2025-03-11T12:41:17.262954,479392877,849,219,-8.23171639364,21.961718231245,-19.972511614785,2,1,18 +2025-03-11T12:41:17.387954,479392877,849,219,-8.20818375704,21.920130193165,-19.93066061925,2,1,18 +2025-03-11T12:41:17.512954,479392877,849,219,-8.15641195652,21.795394426585,-19.82824896864,2,1,18 +2025-03-11T12:41:17.637954,479392877,849,219,-8.07640099208,21.587510931505,-19.65141631191,2,1,18 +2025-03-11T12:41:17.762954,479392877,849,219,-7.9399116998,21.30105414238,-19.441706909565,2,1,18 +2025-03-11T12:41:17.887954,479392877,849,219,-7.77988977092,20.91298888789,-19.1482491198,2,1,18 +2025-03-11T12:41:18.012893,479392881,845,220,-7.57750909616,20.46483942388,-18.80356201455,2,1,18 +2025-03-11T12:41:18.137893,479392881,845,220,-7.33747620284,19.928911101595,-18.389029310985,2,1,18 +2025-03-11T12:41:18.262893,479392881,845,220,-7.0692041456,19.33753678648,-17.93718253992,2,1,18 +2025-03-11T12:41:18.387893,479392881,845,220,-6.77269292444,18.65839778692,-17.392409960925,2,1,18 +2025-03-11T12:41:18.512893,479392881,845,220,-6.457355594,17.891508276745,-16.796313002595,2,1,18 +2025-03-11T12:41:18.637893,479392881,845,220,-6.08553993572,17.07836416414,-16.172129751915,2,1,18 +2025-03-11T12:41:18.762893,479392881,845,220,-5.69019164084,16.186696365895,-15.48742036764,2,1,18 +2025-03-11T12:41:18.887893,479392881,845,220,-5.25248460008,15.193391754625,-14.737402313085,2,1,18 +2025-03-11T12:41:19.012893,479392881,845,220,-4.81948408664,14.158541626765,-13.927113921315,2,1,18 +2025-03-11T12:41:19.137893,479392881,845,220,-4.34883135464,13.068231332245,-13.088731320615,2,1,18 +2025-03-11T12:41:19.262893,479392881,845,220,-3.85464598604,11.9317160437,-12.203853273615,2,1,18 +2025-03-11T12:41:19.387893,479392881,845,220,-3.33222145352,10.72590389449,-11.281588157865,2,1,18 +2025-03-11T12:41:19.512893,479392881,845,220,-2.79097081172,9.49236166195,-10.30831500153,2,1,18 +2025-03-11T12:41:19.637893,479392881,845,220,-2.21677447868,8.203366349665,-9.297717589965,2,1,18 +2025-03-11T12:41:19.762893,479392881,845,220,-1.61904550904,6.8727829993,-8.27761000197,2,1,18 +2025-03-11T12:41:19.887893,479392881,845,220,-1.00719695744,5.47754100496,-7.18782942306,2,1,18 +2025-03-11T12:41:20.012893,479392881,845,220,-0.38122882388,4.054576014205,-6.0793918104,2,1,18 +2025-03-11T12:41:20.137893,479392881,845,220,0.244739309680001,2.608526243725,-4.96159229496,2,1,18 +2025-03-11T12:41:20.262893,479392881,845,220,0.90365313448,1.139342085115,-3.8251193286,2,1,18 +2025-03-11T12:41:20.387893,479392881,845,220,1.5672734866,-0.357550896079999,-2.65152923589,2,1,18 +2025-03-11T12:41:20.512893,479392881,845,220,2.24030689336,-1.909861522445,-1.473006645705,2,1,18 +2025-03-11T12:41:20.637893,479392881,845,220,2.9086337728,-3.452931150005,-0.289922793735,2,1,18 +2025-03-11T12:41:20.762893,479392881,845,220,3.57696065224,-4.996000777565,0.920881760325,2,1,18 +2025-03-11T12:41:20.887893,479392881,845,220,4.26411364096,-6.56218353251,2.12722861704,2,1,18 +2025-03-11T12:41:21.012893,479392881,845,220,4.955973157,-8.114522506535,3.33813277725,2,1,18 +2025-03-11T12:41:21.137893,479392881,845,220,5.64312614572,-9.676088305535,4.553695534245,2,1,18 +2025-03-11T12:41:21.262893,479392881,845,220,6.31615955248,-11.242249799735,5.75077159374,2,1,18 +2025-03-11T12:41:21.387893,479392881,845,220,6.99389948656,-12.785333601125,6.95235628923,2,1,18 +2025-03-11T12:41:21.512893,479392881,845,220,7.68105247528,-14.309963752565,8.15386402518,2,1,18 +2025-03-11T12:41:21.637893,479392881,845,220,8.32584671812,-15.81606229799,9.32746203447,2,1,18 +2025-03-11T12:41:21.762893,479392881,845,220,8.98946707024,-17.31757223513,10.47335575884,2,1,18 +2025-03-11T12:41:21.887893,479392881,845,220,9.62955478576,-18.782111090135,11.605143523515,2,1,18 +2025-03-11T12:41:22.012832,479392885,841,221,10.27905555592,-20.24666411897,12.741571780665,2,1,18 +2025-03-11T12:41:22.137832,479392885,841,221,10.87678452556,-21.632650940675,13.840513362915,2,1,18 +2025-03-11T12:41:22.262832,479392885,841,221,11.46980696788,-22.990928939795,14.883857350755,2,1,18 +2025-03-11T12:41:22.387832,479392885,841,221,12.04870982824,-24.307633074665,15.89461095255,2,1,18 +2025-03-11T12:41:22.512832,479392885,841,221,12.63231921592,-25.592025604835,16.88210382075,2,1,18 +2025-03-11T12:41:22.637832,479392885,841,221,13.17356985772,-26.825567837375,17.836896509025,2,1,18 +2025-03-11T12:41:22.762832,479392885,841,221,13.6865813356,-27.98981320925,18.76354236258,2,1,18 +2025-03-11T12:41:22.887832,479392885,841,221,14.18547323152,-29.11710167282,19.625281344735,2,1,18 +2025-03-11T12:41:23.012832,479392885,841,221,14.64671290888,-30.165845190005,20.44956421518,2,1,18 +2025-03-11T12:41:23.137832,479392885,841,221,15.08441994964,-31.15453284533,21.208798170015,2,1,18 +2025-03-11T12:41:23.262832,479392885,841,221,15.49388782648,-32.115476243495,21.93086405985,2,1,18 +2025-03-11T12:41:23.387832,479392885,841,221,15.88452959404,-32.9840521751,22.62006170466,2,1,18 +2025-03-11T12:41:23.512832,479392885,841,221,16.23281261572,-33.76022520557,23.23475911266,2,1,18 +2025-03-11T12:41:23.637832,479392885,841,221,16.54344341884,-34.47170415749,23.78435270811,2,1,18 +2025-03-11T12:41:23.762832,479392885,841,221,16.82583505804,-35.12773711658,24.282771885015,2,1,18 +2025-03-11T12:41:23.887832,479392885,841,221,17.06586795136,-35.700601086425,24.72521996067,2,1,18 +2025-03-11T12:41:24.012832,479392885,841,221,17.29178126272,-36.19495554446,25.12564274625,2,1,18 +2025-03-11T12:41:24.137832,479392885,841,221,17.49416193748,-36.610786316855,25.437818696145,2,1,18 +2025-03-11T12:41:24.262832,479392885,841,221,17.63535775708,-36.94803670829,25.689387010605,2,1,18 +2025-03-11T12:41:24.387832,479392885,841,221,17.7577274674,-37.211387456945,25.894324063995,2,1,18 +2025-03-11T12:41:24.512832,479392885,841,221,17.84244495916,-37.368491523545,26.033938301085,2,1,18 +2025-03-11T12:41:24.637832,479392885,841,221,17.87068412308,-37.479340987715,26.10388519269,2,1,18 +2025-03-11T12:41:24.762832,479392885,841,221,17.87068412308,-37.51165967933,26.10405552894,2,1,18 +2025-03-11T12:41:24.887832,479392885,841,221,17.84244495916,-37.433128906775,26.034278973585,2,1,18 +2025-03-11T12:41:25.012832,479392885,841,221,17.79067315864,-37.26684053669,25.913167851165,2,1,18 +2025-03-11T12:41:25.137832,479392885,841,221,17.67771650296,-37.031205697535,25.74073799484,2,1,18 +2025-03-11T12:41:25.262832,479392885,841,221,17.545933738,-36.70320339182,25.48923872334,2,1,18 +2025-03-11T12:41:25.387832,479392885,841,221,17.37649875448,-36.319740919445,25.177304423805,2,1,18 +2025-03-11T12:41:25.512832,479392885,841,221,17.15058544312,-35.839237329245,24.813915575595,2,1,18 +2025-03-11T12:41:25.637832,479392885,841,221,16.91996560444,-35.26638753323,24.38996834346,2,1,18 +2025-03-11T12:41:25.762832,479392885,841,221,16.64698701988,-34.65653830742,23.901053113545,2,1,18 +2025-03-11T12:41:25.887832,479392885,841,221,16.35047579872,-33.94969757219,23.342274181005,2,1,18 +2025-03-11T12:41:26.012756,479392889,836,222,16.00689930436,-33.1596807608,22.74137431053,2,1,18 +2025-03-11T12:41:26.137756,479392889,836,222,15.64920322804,-32.314239217325,22.0893305847,2,1,18 +2025-03-11T12:41:26.262756,479392889,836,222,15.23502882388,-31.399458291695,21.367497844635,2,1,18 +2025-03-11T12:41:26.387756,479392889,836,222,14.79732178312,-30.415387592315,20.61752845758,2,1,18 +2025-03-11T12:41:26.512756,479392889,836,222,14.34078863308,-29.37126811799,19.80714045966,2,1,18 +2025-03-11T12:41:26.637756,479392889,836,222,13.8513097918,-28.27169556392,18.954808089495,2,1,18 +2025-03-11T12:41:26.762756,479392889,836,222,13.34300484124,-27.102840323015,18.05586879201,2,1,18 +2025-03-11T12:41:26.887756,479392889,836,222,12.82528683604,-25.87856743694,17.1057958269,2,1,18 +2025-03-11T12:41:27.012756,479392889,836,222,12.26050355764,-24.635755857935,16.123182830385,2,1,18 +2025-03-11T12:41:27.137756,479392889,836,222,11.67218764264,-23.319037549235,15.1031686191,2,1,18 +2025-03-11T12:41:27.262756,479392889,836,222,11.07916520032,-21.96537650606,14.064469082025,2,1,18 +2025-03-11T12:41:27.387756,479392889,836,222,10.4626101214,-20.59321220453,12.984040218165,2,1,18 +2025-03-11T12:41:27.512756,479392889,836,222,9.84134851516,-19.174871256635,11.875637126985,2,1,18 +2025-03-11T12:41:27.637756,479392889,836,222,9.2153803816,-17.71497061832,10.75314449328,2,1,18 +2025-03-11T12:41:27.762756,479392889,836,222,8.56587961144,-16.20886498598,9.60725699835,2,1,18 +2025-03-11T12:41:27.887756,479392889,836,222,7.88813967736,-14.688865964315,8.428894556685,2,1,18 +2025-03-11T12:41:28.012756,479392889,836,222,7.22451932524,-13.168888203395,7.236702327165,2,1,18 +2025-03-11T12:41:28.137756,479392889,836,222,6.5326598092,-11.621166185315,6.044302968765,2,1,18 +2025-03-11T12:41:28.262756,479392889,836,222,5.8502133478,-10.064224429175,4.82877473325,2,1,18 +2025-03-11T12:41:28.387756,479392889,836,222,5.15835383176,-8.498034587315,3.613177454775,2,1,18 +2025-03-11T12:41:28.512756,479392889,836,222,4.46649431572,-6.9364617014,2.41608497811,2,1,18 +2025-03-11T12:41:28.637756,479392889,836,222,3.779341327,-5.379512858345,1.20516667188,2,1,18 +2025-03-11T12:41:28.762756,479392889,836,222,3.11572097488,-3.82721640581,-0.00567636195000043,2,1,18 +2025-03-11T12:41:28.887756,479392889,836,222,2.4379810408,-2.261047824695,-1.202762609175,2,1,18 +2025-03-11T12:41:29.012756,479392889,836,222,1.75082805208,-0.73180071731,-2.39043432783,2,1,18 +2025-03-11T12:41:29.137756,479392889,836,222,1.09191422728,0.78355300075,-3.559491450795,2,1,18 +2025-03-11T12:41:29.262756,479392889,836,222,0.437706929800001,2.261963984335,-4.719103482,2,1,18 +2025-03-11T12:41:29.387756,479392889,836,222,-0.20708731304,3.71265905842,-5.84620831614,2,1,18 +2025-03-11T12:41:29.512756,479392889,836,222,-0.82364239196,5.144843787235,-6.96391445487,2,1,18 +2025-03-11T12:41:29.637756,479392889,836,222,-1.44019747088,6.535475912545,-8.049060770745,2,1,18 +2025-03-11T12:41:29.762756,479392889,836,222,-2.0332199132,7.87990304383001,-9.083091523305,2,1,18 +2025-03-11T12:41:29.887756,479392889,836,222,-2.60270971892,9.20582691676,-10.08463318311,2,1,18 +2025-03-11T12:41:30.012695,479392893,832,223,-3.16749299732,10.467106319545,-11.06272339761,2,1,18 +2025-03-11T12:41:30.137695,479392893,832,223,-3.70874363912,11.682180728305,-12.008178516855,2,1,18 +2025-03-11T12:41:30.262695,479392893,832,223,-4.21234206236,12.83717801446,-12.90703462536,2,1,18 +2025-03-11T12:41:30.387695,479392893,832,223,-4.67358173972,13.932091091095,-13.759281535395,2,1,18 +2025-03-11T12:41:30.512695,479392893,832,223,-5.1395279444,14.97622473925,-14.56506979176,2,1,18 +2025-03-11T12:41:30.637695,479392893,832,223,-5.56782193052,15.937196485075,-15.314897134605,2,1,18 +2025-03-11T12:41:30.762695,479392893,832,223,-5.96787675272,16.847339194015,-16.032054860715,2,1,18 +2025-03-11T12:41:30.887695,479392893,832,223,-6.35851852028,17.702064257785,-16.684218568155,2,1,18 +2025-03-11T12:41:31.012695,479392893,832,223,-6.68326890536,18.48743576557,-17.28505335396,2,1,18 +2025-03-11T12:41:31.137695,479392893,832,223,-6.9986062358,19.161986156845,-17.839082584155,2,1,18 +2025-03-11T12:41:31.262695,479392893,832,223,-7.27629134768,19.794927249295,-18.314269319505,2,1,18 +2025-03-11T12:41:31.387695,479392893,832,223,-7.516324241,20.34932339536,-18.733519475085,2,1,18 +2025-03-11T12:41:31.512695,479392893,832,223,-7.74223755236,20.815976117725,-19.09221520503,2,1,18 +2025-03-11T12:41:31.637695,479392893,832,223,-7.91167253588,21.194821634155,-19.39026481977,2,1,18 +2025-03-11T12:41:31.762695,479392893,832,223,-8.04345530084,21.527440895815,-19.637168308005,2,1,18 +2025-03-11T12:41:31.887695,479392893,832,223,-8.14699890188,21.76306156114,-19.841918607975,2,1,18 +2025-03-11T12:41:32.012695,479392893,832,223,-8.21289028436,21.906286412245,-19.935217922745,2,1,18 +2025-03-11T12:41:32.137695,479392893,832,223,-8.2458359756,21.957122536045,-19.96789772721,2,1,18 +2025-03-11T12:41:32.262695,479392893,832,223,-8.25524903024,21.97098757771,-19.96799110392,2,1,18 +2025-03-11T12:41:32.387695,479392893,832,223,-8.20818375704,21.87857758966,-19.907341030425,2,1,18 +2025-03-11T12:41:32.512695,479392893,832,223,-8.13287931992,21.68455204933,-19.76293238178,2,1,18 +2025-03-11T12:41:32.637695,479392893,832,223,-8.0105096096,21.41658434473,-19.56721122867,2,1,18 +2025-03-11T12:41:32.762695,479392893,832,223,-7.87872684464,21.088582039015,-19.28799125508,2,1,18 +2025-03-11T12:41:32.887695,479392893,832,223,-7.69987880648,20.66816974525,-18.966601676055,2,1,18 +2025-03-11T12:41:33.012695,479392893,832,223,-7.47867202244,20.159971506295,-18.566116076955,2,1,18 +2025-03-11T12:41:33.137695,479392893,832,223,-7.22451954716,19.56400149598,-18.128135886375,2,1,18 +2025-03-11T12:41:33.262695,479392893,832,223,-6.9515409626,18.94491835828,-17.625311637915,2,1,18 +2025-03-11T12:41:33.387695,479392893,832,223,-6.63149710484,18.21495740875,-17.066360097975,2,1,18 +2025-03-11T12:41:33.512695,479392893,832,223,-6.2690945012,17.40644442592,-16.442221556505,2,1,18 +2025-03-11T12:41:33.637695,479392893,832,223,-5.8925723156,16.54712366695,-15.76696349343,2,1,18 +2025-03-11T12:41:33.762695,479392893,832,223,-5.45486527484,15.595371659185,-15.044885144715,2,1,18 +2025-03-11T12:41:33.887695,479392893,832,223,-5.0218647614,14.60207413483,-14.27639680983,2,1,18 +2025-03-11T12:41:34.012634,479392897,828,224,-4.57003813868,13.55796174742,-13.44753853158,2,1,18 +2025-03-11T12:41:34.137634,479392897,828,224,-4.07585277008,12.439914282655,-12.576618170625,2,1,18 +2025-03-11T12:41:34.262634,479392897,828,224,-3.55342823756,11.252569957225,-11.645210155845,2,1,18 +2025-03-11T12:41:34.387634,479392897,828,224,-3.0215906504,10.01442494257,-10.68117327525,2,1,18 +2025-03-11T12:41:34.512634,479392897,828,224,-2.45210084468,8.757755408815,-9.698477089755,2,1,18 +2025-03-11T12:41:34.637634,479392897,828,224,-1.87319798432,7.436434318,-8.692319271225,2,1,18 +2025-03-11T12:41:34.762634,479392897,828,224,-1.280175542,6.045837627265,-7.621084245045,2,1,18 +2025-03-11T12:41:34.887634,479392897,828,224,-0.67303351772,4.63213489606,-6.540456752895,2,1,18 +2025-03-11T12:41:35.012634,479392897,828,224,-0.0376523295199993,3.20453877553,-5.42735431401,2,1,18 +2025-03-11T12:41:35.137634,479392897,828,224,0.60714191332,1.7492267455,-4.295605029105,2,1,18 +2025-03-11T12:41:35.262634,479392897,828,224,1.27076226544,0.243099852415,-3.140446736955,2,1,18 +2025-03-11T12:41:35.387634,479392897,828,224,1.92967609024,-1.27687082159,-1.966745163225,2,1,18 +2025-03-11T12:41:35.512634,479392897,828,224,2.62153560628,-2.81535892778,-0.774394472325,2,1,18 +2025-03-11T12:41:35.637634,479392897,828,224,3.30398206768,-4.35383286014,0.43179619416,2,1,18 +2025-03-11T12:41:35.762634,479392897,828,224,3.98172200176,-5.9246183972,1.647387243195,2,1,18 +2025-03-11T12:41:35.887634,479392897,828,224,4.6735815178,-7.50004215095,2.86303318917,2,1,18 +2025-03-11T12:41:36.012634,479392897,828,224,5.36073450652,-9.06160794995,4.050875244075,2,1,18 +2025-03-11T12:41:36.137634,479392897,828,224,6.04318096792,-10.61854970609,5.271023596605,2,1,18 +2025-03-11T12:41:36.262634,479392897,828,224,6.720920902,-12.147782639645,6.47715540786,2,1,18 +2025-03-11T12:41:36.387634,479392897,828,224,7.39866083608,-13.70471730887,7.68805333863,2,1,18 +2025-03-11T12:41:36.512634,479392897,828,224,8.05757466088,-15.22007102693,8.87097081264,2,1,18 +2025-03-11T12:41:36.637634,479392897,828,224,8.72590154032,-16.70773718315,10.02604195752,2,1,18 +2025-03-11T12:41:36.762634,479392897,828,224,9.37540231048,-18.22307672738,11.176598236965,2,1,18 +2025-03-11T12:41:36.887634,479392897,828,224,10.02019655332,-19.664537889575,12.285173935545,2,1,18 +2025-03-11T12:41:37.012634,479392897,828,224,10.63204510492,-21.08286466364,13.375076183205,2,1,18 +2025-03-11T12:41:37.137634,479392897,828,224,11.2391871292,-22.45501479134,14.45086455459,2,1,18 +2025-03-11T12:41:37.262634,479392897,828,224,11.83220957152,-23.780974098845,15.49403820618,2,1,18 +2025-03-11T12:41:37.387634,479392897,828,224,12.40640590456,-25.07920332302,16.48158370017,2,1,18 +2025-03-11T12:41:37.512634,479392897,828,224,12.94765654636,-26.354298159065,17.44121550921,2,1,18 +2025-03-11T12:41:37.637634,479392897,828,224,13.4983202428,-27.54630196193,18.37270898412,2,1,18 +2025-03-11T12:41:37.762634,479392897,828,224,13.9925056114,-28.682817250475,19.25758703112,2,1,18 +2025-03-11T12:41:37.887634,479392897,828,224,14.47257139804,-29.77775867477,20.09601434103,2,1,18 +2025-03-11T12:41:38.012573,479392901,824,225,14.92439802076,-30.8034032384,20.89705458219,2,1,18 +2025-03-11T12:41:38.137573,479392901,824,225,15.34798547956,-31.76436789731,21.63301138626,2,1,18 +2025-03-11T12:41:38.262573,479392901,824,225,15.72921419248,-32.642163566975,22.317617206095,2,1,18 +2025-03-11T12:41:38.387573,479392901,824,225,16.07279068684,-33.450648202145,22.96481558172,2,1,18 +2025-03-11T12:41:38.512573,479392901,824,225,16.4163671812,-34.212963277865,23.547088981635,2,1,18 +2025-03-11T12:41:38.637573,479392901,824,225,16.73170451164,-34.882896713195,24.068753058975,2,1,18 +2025-03-11T12:41:38.762573,479392901,824,225,16.99527004156,-35.483497853285,24.543738894885,2,1,18 +2025-03-11T12:41:38.887573,479392901,824,225,17.20235724364,-36.010142655275,24.94891138281,2,1,18 +2025-03-11T12:41:39.012573,479392901,824,225,17.4047379184,-36.45367516334,25.298194271325,2,1,18 +2025-03-11T12:41:39.137573,479392901,824,225,17.58358595656,-36.8325348536,25.58240391048,2,1,18 +2025-03-11T12:41:39.262573,479392901,824,225,17.70595566688,-37.105119514145,25.819730450475,2,1,18 +2025-03-11T12:41:39.387573,479392901,824,225,17.81420579524,-37.322279442605,25.968952198995,2,1,18 +2025-03-11T12:41:39.512573,479392901,824,225,17.8753906504,-37.447029383015,26.06676410805,2,1,18 +2025-03-11T12:41:39.637573,479392901,824,225,17.88009717772,-37.497822985325,26.09476266912,2,1,18 +2025-03-11T12:41:39.762573,479392901,824,225,17.86127106844,-37.460858990105,26.052946195065,2,1,18 +2025-03-11T12:41:39.887573,479392901,824,225,17.81891232256,-37.3407543533,25.97367983874,2,1,18 +2025-03-11T12:41:40.012573,479392901,824,225,17.72478177616,-37.142083509365,25.829206105425,2,1,18 +2025-03-11T12:41:40.137573,479392901,824,225,17.60711859316,-36.860272023845,25.61032155372,2,1,18 +2025-03-11T12:41:40.262573,479392901,824,225,17.44239013696,-36.504518374055,25.30316356143,2,1,18 +2025-03-11T12:41:40.387573,479392901,824,225,17.24471598952,-36.04714208507,24.95843797641,2,1,18 +2025-03-11T12:41:40.512573,479392901,824,225,17.02350920548,-35.51585906639,24.580931293635,2,1,18 +2025-03-11T12:41:40.637573,479392901,824,225,16.7693567302,-34.919889056075,24.10137004992,2,1,18 +2025-03-11T12:41:40.762573,479392901,824,225,16.48225856368,-34.240764230345,23.556617846385,2,1,18 +2025-03-11T12:41:40.887573,479392901,824,225,16.15280165128,-33.492321283205,22.988308361955,2,1,18 +2025-03-11T12:41:41.012573,479392901,824,225,15.780985993,-32.68841108249,22.336453076685,2,1,18 +2025-03-11T12:41:41.137573,479392901,824,225,15.3809311708,-31.79673619733,21.647113387665,2,1,18 +2025-03-11T12:41:41.262573,479392901,824,225,14.97146329396,-30.83117584322,20.901922579005,2,1,18 +2025-03-11T12:41:41.387573,479392901,824,225,14.5337562532,-29.796318628445,20.119344701595,2,1,18 +2025-03-11T12:41:41.512573,479392901,824,225,14.05839699388,-28.73370298268,19.281097915665,2,1,18 +2025-03-11T12:41:41.637573,479392901,824,225,13.57362467992,-27.615669691745,18.405577813155,2,1,18 +2025-03-11T12:41:41.762573,479392901,824,225,13.04178709276,-26.42369423654,17.47874520618,2,1,18 +2025-03-11T12:41:41.887573,479392901,824,225,12.50053645096,-25.167067224275,16.50073026408,2,1,18 +2025-03-11T12:41:42.012497,479392905,819,226,11.92634011792,-23.864221044155,15.499300085295,2,1,18 +2025-03-11T12:41:42.137497,479392905,819,226,11.35214378488,-22.533673128365,14.46076296789,2,1,18 +2025-03-11T12:41:42.262497,479392905,819,226,10.74029523328,-21.156898957805,13.39880042607,2,1,18 +2025-03-11T12:41:42.387497,479392905,819,226,10.12844668168,-19.74780609563,12.29970661188,2,1,18 +2025-03-11T12:41:42.512497,479392905,819,226,9.47894591152,-18.283253066795,11.19099905682,2,1,18 +2025-03-11T12:41:42.637497,479392905,819,226,8.82003208672,-16.80021804035,10.04521285518,2,1,18 +2025-03-11T12:41:42.762497,479392905,819,226,8.16582478924,-15.294105321095,8.90855540655,2,1,18 +2025-03-11T12:41:42.887497,479392905,819,226,7.51161749176,-13.77875868995,7.72564812027,2,1,18 +2025-03-11T12:41:43.012497,479392905,819,226,6.84799713964,-12.24954701714,6.519546872205,2,1,18 +2025-03-11T12:41:43.137497,479392905,819,226,6.16555067824,-10.706456128835,5.317951988985,2,1,18 +2025-03-11T12:41:43.262497,479392905,819,226,5.46898463488,-9.135642244115,4.106940306045,2,1,18 +2025-03-11T12:41:43.387497,479392905,819,226,4.76300553688,-7.56019722962,2.88202356285,2,1,18 +2025-03-11T12:41:43.512497,479392905,819,226,4.07585254816,-5.99863143062,1.6803211569,2,1,18 +2025-03-11T12:41:43.637497,479392905,819,226,3.3792865048,-4.441668413735,0.46938247521,2,1,18 +2025-03-11T12:41:43.762497,479392905,819,226,2.70154657072,-2.889350700455,-0.727630770765,2,1,18 +2025-03-11T12:41:43.887497,479392905,819,226,2.04263274592,-1.337061334835,-1.910742914775,2,1,18 +2025-03-11T12:41:44.012497,479392905,819,226,1.38371892112,0.182909339170001,-3.09830483955,2,1,18 +2025-03-11T12:41:44.137497,479392905,819,226,0.720098569,1.670568408475,-4.2533657967,2,1,18 +2025-03-11T12:41:44.262497,479392905,819,226,0.0753043261599995,3.135114350395,-5.394403983135,2,1,18 +2025-03-11T12:41:44.387497,479392905,819,226,-0.54595728008,4.567306166125,-6.50750019258,2,1,18 +2025-03-11T12:41:44.512497,479392905,819,226,-1.17192541364,5.96256942121,-7.592691217665,2,1,18 +2025-03-11T12:41:44.637497,479392905,819,226,-1.7743609106,7.34856332983,-8.654682051525,2,1,18 +2025-03-11T12:41:44.762497,479392905,819,226,-2.36738335292,8.674522637335,-9.67475511804,2,1,18 +2025-03-11T12:41:44.887497,479392905,819,226,-2.92275357668,9.95425569007,-10.68064299417,2,1,18 +2025-03-11T12:41:45.012497,479392905,819,226,-3.47341727312,11.17857818455,-11.635407390405,2,1,18 +2025-03-11T12:41:45.137497,479392905,819,226,-3.98172222368,12.36128429329,-12.54365992317,2,1,18 +2025-03-11T12:41:45.262497,479392905,819,226,-4.4806141196,13.483955800915,-13.40999468859,2,1,18 +2025-03-11T12:41:45.387497,479392905,819,226,-4.927734215,14.54652892519,-14.22969988008,2,1,18 +2025-03-11T12:41:45.512497,479392905,819,226,-5.37956083772,15.55370566504,-14.998301967135,2,1,18 +2025-03-11T12:41:45.637497,479392905,819,226,-5.78432218724,16.500791108455,-15.724904785005,2,1,18 +2025-03-11T12:41:45.762497,479392905,819,226,-6.18908353676,17.378622212695,-16.404941426475,2,1,18 +2025-03-11T12:41:45.887497,479392905,819,226,-6.54677961308,18.173277240775,-17.03361689598,2,1,18 +2025-03-11T12:41:46.012436,479392909,815,227,-6.87623652548,18.903252364135,-17.59258881138,2,1,18 +2025-03-11T12:41:46.137436,479392909,815,227,-7.14921511004,19.56388810534,-18.10487229762,2,1,18 +2025-03-11T12:41:46.262436,479392909,815,227,-7.4221936946,20.150652551425,-18.556704922665,2,1,18 +2025-03-11T12:41:46.387436,479392909,815,227,-7.64340047864,20.63114905471,-18.95242440225,2,1,18 +2025-03-11T12:41:46.512436,479392909,815,227,-7.8222485168,21.051561348475,-19.273813981275,2,1,18 +2025-03-11T12:41:46.637436,479392909,815,227,-7.97285739104,21.39805982563,-19.53007145571,2,1,18 +2025-03-11T12:41:46.762436,479392909,815,227,-8.09052057404,21.67987131115,-19.7443358904,2,1,18 +2025-03-11T12:41:46.887436,479392909,815,227,-8.1752380658,21.86467711342,-19.88409612999,2,1,18 +2025-03-11T12:41:47.012436,479392909,815,227,-8.22700986632,21.957094188385,-19.94937650823,2,1,18 +2025-03-11T12:41:47.137436,479392909,815,227,-8.2458359756,21.97097340388,-19.96797072846,2,1,18 +2025-03-11T12:41:47.262436,479392909,815,227,-8.21289028436,21.9016694563,-19.92133323795,2,1,18 +2025-03-11T12:41:47.387436,479392909,815,227,-8.1517054292,21.753834736165,-19.8095393091,2,1,18 +2025-03-11T12:41:47.512436,479392909,815,227,-8.05286835548,21.54130593748,-19.6326415677,2,1,18 +2025-03-11T12:41:47.637436,479392909,815,227,-7.92108559052,21.21792058771,-19.40888733204,2,1,18 +2025-03-11T12:41:47.762436,479392909,815,227,-7.74223755236,20.834443941505,-19.09231254003,2,1,18 +2025-03-11T12:41:47.887436,479392909,815,227,-7.53044382296,20.36319552394,-18.715142571465,2,1,18 +2025-03-11T12:41:48.012436,479392909,815,227,-7.28570440232,19.822643158795,-18.30057534642,2,1,18 +2025-03-11T12:41:48.137436,479392909,815,227,-7.03155192704,19.18973750092,-17.830059666735,2,1,18 +2025-03-11T12:41:48.262436,479392909,815,227,-6.73504070588,18.478279809745,-17.280496634475,2,1,18 +2025-03-11T12:41:48.387436,479392909,815,227,-6.40087726616,17.715978907855,-16.68900337599,2,1,18 +2025-03-11T12:41:48.512436,479392909,815,227,-6.01964855324,16.89358670953,-16.041650497275,2,1,18 +2025-03-11T12:41:48.637436,479392909,815,227,-5.61959373104,15.988060956535,-15.324517104915,2,1,18 +2025-03-11T12:41:48.762436,479392909,815,227,-5.18188669028,15.01784112499,-14.560760368065,2,1,18 +2025-03-11T12:41:48.887436,479392909,815,227,-4.7394731222,13.9829768233,-13.76431195188,2,1,18 +2025-03-11T12:41:49.012436,479392909,815,227,-4.25940733556,12.87418453117,-12.921191523705,2,1,18 +2025-03-11T12:41:49.137436,479392909,815,227,-3.74639585768,11.709939159295,-12.017646255225,2,1,18 +2025-03-11T12:41:49.262436,479392909,815,227,-3.2098517432,10.52257357312,-11.1000680283,2,1,18 +2025-03-11T12:41:49.387436,479392909,815,227,-2.67330762872,9.261336691825,-10.117418823165,2,1,18 +2025-03-11T12:41:49.512436,479392909,815,227,-2.10852435032,7.96312164148,-9.10679311956,2,1,18 +2025-03-11T12:41:49.637436,479392909,815,227,-1.52020843532,6.60946768522,-8.049623302155,2,1,18 +2025-03-11T12:41:49.762436,479392909,815,227,-0.9036533564,5.214218603965,-6.97369288656,2,1,18 +2025-03-11T12:41:49.887436,479392909,815,227,-0.272978695519999,3.77739565846,-5.869792201935,2,1,18 +2025-03-11T12:41:50.012375,479392913,811,228,0.37652207464,2.33592740935,-4.73810573055,2,1,18 +2025-03-11T12:41:50.137375,479392913,811,228,1.02131631748,0.857530599595,-3.58313419182,2,1,18 +2025-03-11T12:41:50.262375,479392913,811,228,1.69434972424,-0.653227423264999,-2.4094507224,2,1,18 +2025-03-11T12:41:50.387375,479392913,811,228,2.367383131,-2.191687181795,-1.22638101645,2,1,18 +2025-03-11T12:41:50.512375,479392913,811,228,3.03571001044,-3.716288985575,-0.0341542654500002,2,1,18 +2025-03-11T12:41:50.637375,479392913,811,228,3.71344994452,-5.26398974291,1.16745476379,2,1,18 +2025-03-11T12:41:50.762375,479392913,811,228,4.40060293324,-6.830172497855,2.37842173752,2,1,18 +2025-03-11T12:41:50.887375,479392913,811,228,5.09246244928,-8.414830163495,3.594116350995,2,1,18 +2025-03-11T12:41:51.012375,479392913,811,228,5.779615438,-9.98101291844,4.79122297368,2,1,18 +2025-03-11T12:41:51.137375,479392913,811,228,6.45735537208,-11.519479763885,6.00202356945,2,1,18 +2025-03-11T12:41:51.262375,479392913,811,228,7.13980183348,-13.07180456408,7.20366712017,2,1,18 +2025-03-11T12:41:51.387375,479392913,811,228,7.82224829488,-14.596427628605,8.3774439663,2,1,18 +2025-03-11T12:41:51.512375,479392913,811,228,8.47645559236,-16.10254034786,9.56030258508,2,1,18 +2025-03-11T12:41:51.637375,479392913,811,228,9.13536941716,-17.59942624214,10.710781904985,2,1,18 +2025-03-11T12:41:51.762375,479392913,811,228,9.76604407804,-19.08703570304,11.847291079965,2,1,18 +2025-03-11T12:41:51.887375,479392913,811,228,10.40142526624,-20.51463182357,12.937292933775,2,1,18 +2025-03-11T12:41:52.012375,479392913,811,228,11.01798034516,-21.87756221321,14.008432896105,2,1,18 +2025-03-11T12:41:52.137375,479392913,811,228,11.62512236944,-23.23124451713,15.061023347415,2,1,18 +2025-03-11T12:41:52.262375,479392913,811,228,12.2040252298,-24.552565607945,16.076421399975,2,1,18 +2025-03-11T12:41:52.387375,479392913,811,228,12.7452758716,-25.823043488045,17.054509343325,2,1,18 +2025-03-11T12:41:52.512375,479392913,811,228,13.28181998608,-27.01964298611,17.995236822825,2,1,18 +2025-03-11T12:41:52.637375,479392913,811,228,13.79483146396,-28.18850531393,18.88494607401,2,1,18 +2025-03-11T12:41:52.762375,479392913,811,228,14.2748972506,-29.29729760606,19.755787204275,2,1,18 +2025-03-11T12:41:52.887375,479392913,811,228,14.73613692796,-30.346041123245,20.566209723675,2,1,18 +2025-03-11T12:41:53.012375,479392913,811,228,15.17855049604,-31.353203689265,21.33479143527,2,1,18 +2025-03-11T12:41:53.137375,479392913,811,228,15.5927249002,-32.286452438675,22.038241042275,2,1,18 +2025-03-11T12:41:53.262375,479392913,811,228,15.9457144492,-33.12726993929,22.699490480655,2,1,18 +2025-03-11T12:41:53.387375,479392913,811,228,16.28929094356,-33.884968059065,23.304840131895,2,1,18 +2025-03-11T12:41:53.512375,479392913,811,228,16.60933480132,-34.57337640509,23.84971231704,2,1,18 +2025-03-11T12:41:53.637375,479392913,811,228,16.89643296784,-35.22479949515,24.34349723091,2,1,18 +2025-03-11T12:41:53.762375,479392913,811,228,17.1458789158,-35.779209815045,24.78124823001,2,1,18 +2025-03-11T12:41:53.887375,479392913,811,228,17.36708569984,-36.27817414211,25.16320469355,2,1,18 +2025-03-11T12:41:54.012314,479392917,807,229,17.54122721068,-36.69857934896,25.4707237338,2,1,18 +2025-03-11T12:41:54.137314,479392917,807,229,17.6871295576,-37.03583682731,25.72230223599,2,1,18 +2025-03-11T12:41:54.262314,479392917,807,229,17.79537968596,-37.257613711715,25.89926902035,2,1,18 +2025-03-11T12:41:54.387314,479392917,807,229,17.86597759576,-37.419313473515,26.02963679397,2,1,18 +2025-03-11T12:41:54.512314,479392917,807,229,17.88951023236,-37.47475237943,26.099281492845,2,1,18 +2025-03-11T12:41:54.637314,479392917,807,229,17.88480370504,-37.465511380625,26.08536228657,2,1,18 +2025-03-11T12:41:54.762314,479392917,807,229,17.8518580138,-37.3915904771,26.01097976022,2,1,18 +2025-03-11T12:41:54.887314,479392917,807,229,17.781260104,-37.22065680341,25.875943202085,2,1,18 +2025-03-11T12:41:55.012314,479392917,807,229,17.66830344832,-36.96193718453,25.689531325965,2,1,18 +2025-03-11T12:41:55.137314,479392917,807,229,17.53181415604,-36.629310835955,25.42413718194,2,1,18 +2025-03-11T12:41:55.262314,479392917,807,229,17.3576726452,-36.236607364775,25.11676414419,2,1,18 +2025-03-11T12:41:55.387314,479392917,807,229,17.13646586116,-35.75611086149,24.730284898635,2,1,18 +2025-03-11T12:41:55.512314,479392917,807,229,16.89172644052,-35.19247371662,24.27863506872,2,1,18 +2025-03-11T12:41:55.637314,479392917,807,229,16.59992174668,-34.541043539645,23.789460084135,2,1,18 +2025-03-11T12:41:55.762314,479392917,807,229,16.2987039982,-33.82496180561,23.22600217935,2,1,18 +2025-03-11T12:41:55.887314,479392917,807,229,15.95512750384,-33.03494499422,22.615862074845,2,1,18 +2025-03-11T12:41:56.012314,479392917,807,229,15.57389879092,-32.166383236445,21.94978539057,2,1,18 +2025-03-11T12:41:56.137314,479392917,807,229,15.1691374414,-31.22853170492,21.218611123185,2,1,18 +2025-03-11T12:41:56.262314,479392917,807,229,14.7455499826,-30.226014442505,20.45009449626,2,1,18 +2025-03-11T12:41:56.387314,479392917,807,229,14.28431030524,-29.17727092532,19.625811625815,2,1,18 +2025-03-11T12:41:56.512314,479392917,807,229,13.79012493664,-28.0638404165,18.778016183685,2,1,18 +2025-03-11T12:41:56.637314,479392917,807,229,13.26770040412,-26.87649609107,17.86970875398,2,1,18 +2025-03-11T12:41:56.762314,479392917,807,229,12.721743235,-25.65679763945,16.914978879225,2,1,18 +2025-03-11T12:41:56.887314,479392917,807,229,12.16637301124,-24.40014936644,15.92307302289,2,1,18 +2025-03-11T12:41:57.012314,479392917,807,229,11.60158973284,-23.07884953637,14.903085416505,2,1,18 +2025-03-11T12:41:57.137314,479392917,807,229,11.00856729052,-21.725188493195,13.84590541137,2,1,18 +2025-03-11T12:41:57.262314,479392917,807,229,10.38259915696,-20.30222350244,12.769808617815,2,1,18 +2025-03-11T12:41:57.387314,479392917,807,229,9.75192449608,-18.865400556935,11.670528050205,2,1,18 +2025-03-11T12:41:57.512314,479392917,807,229,9.1212498352,-17.405492831705,10.53878499474,2,1,18 +2025-03-11T12:41:57.637314,479392917,807,229,8.46704253772,-15.91784793623,9.36526394499,2,1,18 +2025-03-11T12:41:57.762314,479392917,807,229,7.79400913096,-14.402472957425,8.177695790775,2,1,18 +2025-03-11T12:41:57.887314,479392917,807,229,7.11156266956,-12.854765113175,6.99917715888,2,1,18 +2025-03-11T12:41:58.012237,479392921,802,230,6.44323579012,-11.30707852967,5.802208622115,2,1,18 +2025-03-11T12:41:58.137237,479392921,802,230,5.77020238336,-9.75015094736,4.59594099609,2,1,18 +2025-03-11T12:41:58.262237,479392921,802,230,5.06422328536,-8.183939844755,3.38493327144,2,1,18 +2025-03-11T12:41:58.387237,479392921,802,230,4.38177682396,-6.63161504456,2.17404948669,2,1,18 +2025-03-11T12:41:58.512237,479392921,802,230,3.69933036256,-5.079290244365,0.958545584925,2,1,18 +2025-03-11T12:41:58.637237,479392921,802,230,3.01217737384,-3.52234140131,-0.252372721305,2,1,18 +2025-03-11T12:41:58.762237,479392921,802,230,2.32973091244,-1.98386746895,-1.44008291973,2,1,18 +2025-03-11T12:41:58.887237,479392921,802,230,1.661404033,-0.445414797334999,-2.637002788995,2,1,18 +2025-03-11T12:41:59.012237,479392921,802,230,1.00719673552,1.05146401003,-3.792092038185,2,1,18 +2025-03-11T12:41:59.137237,479392921,802,230,0.35769596536,2.5298679067,-4.956313998675,2,1,18 +2025-03-11T12:41:59.262237,479392921,802,230,-0.28709827748,3.980562980785,-6.06031824774,2,1,18 +2025-03-11T12:41:59.387237,479392921,802,230,-0.9036533564,5.39427988582,-7.164066700425,2,1,18 +2025-03-11T12:41:59.512237,479392921,802,230,-1.52020843532,6.78491201113,-8.235352665255,2,1,18 +2025-03-11T12:41:59.637237,479392921,802,230,-2.11323087764,8.13395609836,-9.269407751565,2,1,18 +2025-03-11T12:41:59.762237,479392921,802,230,-2.67330762872,9.45063188557,-10.284740719455,2,1,18 +2025-03-11T12:41:59.887237,479392921,802,230,-3.2333843798,10.69343637766,-11.24886306018,2,1,18 +2025-03-11T12:42:00.012237,479392921,802,230,-3.75580891232,11.913099394705,-12.18044141121,2,1,18 +2025-03-11T12:42:00.137237,479392921,802,230,-4.25470080824,13.040387858275,-13.069901095455,2,1,18 +2025-03-11T12:42:00.262237,479392921,802,230,-4.7394731222,14.126102457595,-13.908289925595,2,1,18 +2025-03-11T12:42:00.387237,479392921,802,230,-5.19129974492,15.151747021225,-14.700089932725,2,1,18 +2025-03-11T12:42:00.512237,479392921,802,230,-5.61959373104,16.13118659083,-15.4592548446,2,1,18 +2025-03-11T12:42:00.637237,479392921,802,230,-6.01964855324,17.03209538788,-16.153263318135,2,1,18 +2025-03-11T12:42:00.762237,479392921,802,230,-6.3867576842,17.86370023735,-16.80063430116,2,1,18 +2025-03-11T12:42:00.887237,479392921,802,230,-6.7162145966,18.616760140435,-17.392068704415,2,1,18 +2025-03-11T12:42:01.012237,479392921,802,230,-7.0221388724,19.30053026977,-17.913785407545,2,1,18 +2025-03-11T12:42:01.137237,479392921,802,230,-7.29511745696,19.91037949558,-18.39346040343,2,1,18 +2025-03-11T12:42:01.262237,479392921,802,230,-7.5398568776,20.45554881667,-18.808051962225,2,1,18 +2025-03-11T12:42:01.387237,479392921,802,230,-7.73753102504,20.912925105655,-19.162017781275,2,1,18 +2025-03-11T12:42:01.512237,479392921,802,230,-7.89755295392,21.282522536365,-19.45537823604,2,1,18 +2025-03-11T12:42:01.637237,479392921,802,230,-8.01992266424,21.568958064745,-19.692777777285,2,1,18 +2025-03-11T12:42:01.762237,479392921,802,230,-8.1281727926,21.77226712537,-19.860406992615,2,1,18 +2025-03-11T12:42:01.887237,479392921,802,230,-8.18465112044,21.92009475859,-19.972190733735,2,1,18 +2025-03-11T12:42:02.012176,479392925,798,231,-8.20818375704,21.975533664505,-20.000254379475,2,1,18 +2025-03-11T12:42:02.137176,479392925,798,231,-8.21289028436,21.92937119197,-19.98616087866,2,1,18 +2025-03-11T12:42:02.262176,479392925,798,231,-8.16111848384,21.82310324917,-19.897706914095,2,1,18 +2025-03-11T12:42:02.387176,479392925,798,231,-8.07640099208,21.6382974469,-19.74408632346,2,1,18 +2025-03-11T12:42:02.512176,479392925,798,231,-7.95403128176,21.3703297423,-19.52988470229,2,1,18 +2025-03-11T12:42:02.637176,479392925,798,231,-7.7987158802,21.01459026634,-19.24122755352,2,1,18 +2025-03-11T12:42:02.762176,479392925,798,231,-7.61986784204,20.57109319285,-18.88737548664,2,1,18 +2025-03-11T12:42:02.887176,479392925,798,231,-7.37983494872,20.062866606235,-18.49608937065,2,1,18 +2025-03-11T12:42:03.012176,479392925,798,231,-7.12568247344,19.471513551865,-18.03041281173,2,1,18 +2025-03-11T12:42:03.137176,479392925,798,231,-6.84329083424,18.806246680885,-17.522704733295,2,1,18 +2025-03-11T12:42:03.262176,479392925,798,231,-6.54207308576,18.048612343345,-16.954407707745,2,1,18 +2025-03-11T12:42:03.387176,479392925,798,231,-6.16555090016,17.24007809977,-16.320998369055,2,1,18 +2025-03-11T12:42:03.512176,479392925,798,231,-5.78902871456,16.348438649185,-15.640949852715,2,1,18 +2025-03-11T12:42:03.637176,479392925,798,231,-5.37956083772,15.42443089858,-14.91907863288,2,1,18 +2025-03-11T12:42:03.762176,479392925,798,231,-4.92302768768,14.40339620398,-14.12729277177,2,1,18 +2025-03-11T12:42:03.887176,479392925,798,231,-4.44766842836,13.322312734435,-13.29818888487,2,1,18 +2025-03-11T12:42:04.012176,479392925,798,231,-3.94877653244,12.2088751387,-12.418042435905,2,1,18 +2025-03-11T12:42:04.137176,479392925,798,231,-3.44047158188,11.00770120618,-11.49121210008,2,1,18 +2025-03-11T12:42:04.262176,479392925,798,231,-2.88980788544,9.760293931975,-10.527085801065,2,1,18 +2025-03-11T12:42:04.387176,479392925,798,231,-2.339144189,8.4851849221,-9.530472680445,2,1,18 +2025-03-11T12:42:04.512176,479392925,798,231,-1.76494785596,7.1638709182,-8.50122446457,2,1,18 +2025-03-11T12:42:04.637176,479392925,798,231,-1.15309930436,5.773245879805,-7.44842915553,2,1,18 +2025-03-11T12:42:04.762176,479392925,798,231,-0.531837698119999,4.37337275569,-6.353983750395,2,1,18 +2025-03-11T12:42:04.887176,479392925,798,231,0.103543490080001,2.931925767325,-5.236188193245,2,1,18 +2025-03-11T12:42:05.012176,479392925,798,231,0.762457314880001,1.43965682899,-4.090353324105,2,1,18 +2025-03-11T12:42:05.137176,479392925,798,231,1.41195808504,-0.0479809795699975,-2.9214625791,2,1,18 +2025-03-11T12:42:05.262176,479392925,798,231,2.08028496448,-1.577199739295,-1.74769196241,2,1,18 +2025-03-11T12:42:05.387176,479392925,798,231,2.76273142588,-3.115673671655,-0.555361646970001,2,1,18 +2025-03-11T12:42:05.512176,479392925,798,231,3.44517788728,-4.67723238374,0.650950688265,2,1,18 +2025-03-11T12:42:05.637176,479392925,798,231,4.13703740332,-6.23418831371,1.861879182225,2,1,18 +2025-03-11T12:42:05.762176,479392925,798,231,4.81948386472,-7.80959789363,3.07750475274,2,1,18 +2025-03-11T12:42:05.887176,479392925,798,231,5.51134338076,-9.38502164738,4.27005011364,2,1,18 +2025-03-11T12:42:06.012115,479392929,794,232,6.19849636948,-10.941970490435,5.4902086539,2,1,18 +2025-03-11T12:42:06.137115,479392929,794,232,6.87152977624,-12.489664160855,6.696427612425,2,1,18 +2025-03-11T12:42:06.262115,479392929,794,232,7.53985665568,-14.032733788415,7.888751698425,2,1,18 +2025-03-11T12:42:06.387115,479392929,794,232,8.21759658976,-15.52503107441,9.053107786545,2,1,18 +2025-03-11T12:42:06.512115,479392929,794,232,8.8859234692,-17.045015922245,10.20372915066,2,1,18 +2025-03-11T12:42:06.637115,479392929,794,232,9.53071771204,-18.50494490822,11.36784358842,2,1,18 +2025-03-11T12:42:06.762115,479392929,794,232,10.1566858456,-19.92329294303,12.490117218375,2,1,18 +2025-03-11T12:42:06.887115,479392929,794,232,10.78265397916,-21.337024021895,13.58464581249,2,1,18 +2025-03-11T12:42:07.012115,479392929,794,232,11.4039155854,-22.71842932223,14.65589329755,2,1,18 +2025-03-11T12:42:07.137115,479392929,794,232,11.9686988638,-24.072047843915,15.6806713572,2,1,18 +2025-03-11T12:42:07.262115,479392929,794,232,12.52406908756,-25.36101480854,16.672747549785,2,1,18 +2025-03-11T12:42:07.387115,479392929,794,232,13.074732784,-26.580720347075,17.62748761227,2,1,18 +2025-03-11T12:42:07.512115,479392929,794,232,13.60657037116,-27.76346189039,18.545031317715,2,1,18 +2025-03-11T12:42:07.637115,479392929,794,232,14.09604921244,-28.886119224185,19.402105473645,2,1,18 +2025-03-11T12:42:07.762115,479392929,794,232,14.56199541712,-29.953337652065,20.240356217865,2,1,18 +2025-03-11T12:42:07.887115,479392929,794,232,14.99499593056,-30.95586908831,21.031993805325,2,1,18 +2025-03-11T12:42:08.012115,479392929,794,232,15.43740949864,-31.912245138935,21.76334690955,2,1,18 +2025-03-11T12:42:08.137115,479392929,794,232,15.81393168424,-32.790033721685,22.438702307625,2,1,18 +2025-03-11T12:42:08.262115,479392929,794,232,16.16692123324,-33.607766442575,23.062869141135,2,1,18 +2025-03-11T12:42:08.387115,479392929,794,232,16.50108467296,-34.34698256474,23.64500049684,2,1,18 +2025-03-11T12:42:08.512115,479392929,794,232,16.7928893668,-35.016880565495,24.152753284485,2,1,18 +2025-03-11T12:42:08.637115,479392929,794,232,17.06116142404,-35.603637924665,24.6045757218,2,1,18 +2025-03-11T12:42:08.762115,479392929,794,232,17.28236820808,-36.12107007551,25.009730105415,2,1,18 +2025-03-11T12:42:08.887115,479392929,794,232,17.4753358282,-36.555354497855,25.335843365895,2,1,18 +2025-03-11T12:42:09.012115,479392929,794,232,17.62594470244,-36.897236019065,25.605936857625,2,1,18 +2025-03-11T12:42:09.137115,479392929,794,232,17.74360788544,-37.179047504585,25.829441526345,2,1,18 +2025-03-11T12:42:09.262115,479392929,794,232,17.84244495916,-37.368491523545,25.96463654586,2,1,18 +2025-03-11T12:42:09.387115,479392929,794,232,17.8753906504,-37.46088025085,26.052976758255,2,1,18 +2025-03-11T12:42:09.512115,479392929,794,232,17.88951023236,-37.48398629132,26.07622957527,2,1,18 +2025-03-11T12:42:09.637115,479392929,794,232,17.8753906504,-37.42394460329,26.043541854225,2,1,18 +2025-03-11T12:42:09.762115,479392929,794,232,17.8283253772,-37.29459896768,25.93649594058,2,1,18 +2025-03-11T12:42:09.887115,479392929,794,232,17.71536872152,-37.068198040415,25.75949463474,2,1,18 +2025-03-11T12:42:10.012054,479392933,790,233,17.5929990112,-36.772528600145,25.531286660025,2,1,18 +2025-03-11T12:42:10.137054,479392933,790,233,17.41885750036,-36.38444208491,25.251658658115,2,1,18 +2025-03-11T12:42:10.262054,479392933,790,233,17.20706377096,-35.922427579235,24.888397708095,2,1,18 +2025-03-11T12:42:10.387054,479392933,790,233,16.9811504596,-35.395754429585,24.46470400119,2,1,18 +2025-03-11T12:42:10.512054,479392933,790,233,16.71287840236,-34.78591229069,23.975798959005,2,1,18 +2025-03-11T12:42:10.637054,479392933,790,233,16.41166065388,-34.10214924827,23.44023209256,2,1,18 +2025-03-11T12:42:10.762054,479392933,790,233,16.0633776322,-33.34444404158,22.857972838665,2,1,18 +2025-03-11T12:42:10.887054,479392933,790,233,15.70097502856,-32.4897614993,22.205870257605,2,1,18 +2025-03-11T12:42:11.012054,479392933,790,233,15.30562673368,-31.579625877275,21.507203187285,2,1,18 +2025-03-11T12:42:11.137054,479392933,790,233,14.90086538416,-30.637157389805,20.771384469135,2,1,18 +2025-03-11T12:42:11.262054,479392933,790,233,14.4396257068,-29.59764778451,19.979491085295,2,1,18 +2025-03-11T12:42:11.387054,479392933,790,233,13.95014686552,-28.50730914233,19.131827499645,2,1,18 +2025-03-11T12:42:11.512054,479392933,790,233,13.44184191496,-27.34307085737,18.23291253591,2,1,18 +2025-03-11T12:42:11.637054,479392933,790,233,12.92412390976,-26.14188275102,17.31068194164,2,1,18 +2025-03-11T12:42:11.762054,479392933,790,233,12.38757979528,-24.880645869725,16.33265285352,2,1,18 +2025-03-11T12:42:11.887054,479392933,790,233,11.8039704076,-23.6008702955,15.322083733995,2,1,18 +2025-03-11T12:42:12.012054,479392933,790,233,11.19682838332,-22.261038859415,14.260326049905,2,1,18 +2025-03-11T12:42:12.137054,479392933,790,233,10.59439288636,-20.86119408296,13.179781746735,2,1,18 +2025-03-11T12:42:12.262054,479392933,790,233,9.9684247528,-19.45207996004,12.0945177204,2,1,18 +2025-03-11T12:42:12.387054,479392933,790,233,9.33775009192,-17.99217223481,10.97663501598,2,1,18 +2025-03-11T12:42:12.512054,479392933,790,233,8.68354279444,-16.49991038339,9.835430451585,2,1,18 +2025-03-11T12:42:12.637054,479392933,790,233,8.03404202428,-15.007655618885,8.661895255815,2,1,18 +2025-03-11T12:42:12.762054,479392933,790,233,7.37042167216,-13.47382699013,7.46500990803,2,1,18 +2025-03-11T12:42:12.887054,479392933,790,233,6.6973882654,-11.939984187545,6.268104184785,2,1,18 +2025-03-11T12:42:13.012054,479392933,790,233,5.99611569472,-10.392247995635,5.075684450925,2,1,18 +2025-03-11T12:42:13.137054,479392933,790,233,5.32778881528,-8.830710544295,3.864782561865,2,1,18 +2025-03-11T12:42:13.262054,479392933,790,233,4.64534235388,-7.273768788155,2.65849456038,2,1,18 +2025-03-11T12:42:13.387054,479392933,790,233,3.93936325588,-5.70755768555,1.452106952745,2,1,18 +2025-03-11T12:42:13.512054,479392933,790,233,3.25221026716,-4.150608842495,0.250428880545,2,1,18 +2025-03-11T12:42:13.637054,479392933,790,233,2.56976380576,-2.5982840423,-0.960454904205,2,1,18 +2025-03-11T12:42:13.762054,479392933,790,233,1.88731734436,-1.073660977775,-2.161952452425,2,1,18 +2025-03-11T12:42:13.887054,479392933,790,233,1.22840351956,0.450926652175001,-3.31257777483,2,1,18 +2025-03-11T12:42:14.011993,479392937,786,234,0.578902749400001,1.947798372625,-4.47689707032,2,1,18 +2025-03-11T12:42:14.136993,479392937,786,234,-0.0611849661199999,3.398486359795,-5.62247218479,2,1,18 +2025-03-11T12:42:14.261993,479392937,786,234,-0.67774004504,4.8399050005,-6.73098675699,2,1,18 +2025-03-11T12:42:14.386993,479392937,786,234,-1.29429512396,6.2397710377,-7.82080185738,2,1,18 +2025-03-11T12:42:14.511993,479392937,786,234,-1.89673062092,7.602680166595,-8.878050905475,2,1,18 +2025-03-11T12:42:14.636993,479392937,786,234,-2.49445959056,8.92402960507,-9.875009240895,2,1,18 +2025-03-11T12:42:14.761993,479392937,786,234,-3.04982981432,10.18991178997,-10.871583881745,2,1,18 +2025-03-11T12:42:14.886993,479392937,786,234,-3.57696087416,11.40958189393,-11.81703277155,2,1,18 +2025-03-11T12:42:15.011993,479392937,786,234,-4.09467887936,12.587685220555,-12.71142099498,2,1,18 +2025-03-11T12:42:15.136993,479392937,786,234,-4.57945119332,13.72418633527,-13.57779819846,2,1,18 +2025-03-11T12:42:15.261993,479392937,786,234,-5.045397398,14.76370302748,-14.40666270615,2,1,18 +2025-03-11T12:42:15.386993,479392937,786,234,-5.47369138412,15.74775955303,-15.165851951775,2,1,18 +2025-03-11T12:42:15.511993,479392937,786,234,-5.88315926096,16.67638425958,-15.892367622375,2,1,18 +2025-03-11T12:42:15.636993,479392937,786,234,-6.25497491924,17.53108097569,-16.544490578895,2,1,18 +2025-03-11T12:42:15.761993,479392937,786,234,-6.62679057752,18.325757264515,-17.150096026515,2,1,18 +2025-03-11T12:42:15.886993,479392937,786,234,-6.95624748992,19.04188152004,-17.71361505768,2,1,18 +2025-03-11T12:42:16.011993,479392937,786,234,-7.2339326018,19.688673480325,-18.20735526234,2,1,18 +2025-03-11T12:42:16.136993,479392937,786,234,-7.47396549512,20.25230353828,-18.649754670495,2,1,18 +2025-03-11T12:42:16.261993,479392937,786,234,-7.68575922452,20.714318043955,-19.013015620515,2,1,18 +2025-03-11T12:42:16.386993,479392937,786,234,-7.88343337196,21.12552477349,-19.3159168149,2,1,18 +2025-03-11T12:42:16.511993,479392937,786,234,-8.02462919156,21.45815820898,-19.581321146655,2,1,18 +2025-03-11T12:42:16.636993,479392937,786,234,-8.14229237456,21.71226795883,-19.776959110785,2,1,18 +2025-03-11T12:42:16.761993,479392937,786,234,-8.222303339,21.88321580635,-19.898155693335,2,1,18 +2025-03-11T12:42:16.886993,479392937,786,234,-8.2693686122,21.9756257944,-19.972666117875,2,1,18 +2025-03-11T12:42:17.011993,479392937,786,234,-8.25995555756,21.989462488405,-19.96809862665,2,1,18 +2025-03-11T12:42:17.136993,479392937,786,234,-8.21759681168,21.90629349916,-19.9121275254,2,1,18 +2025-03-11T12:42:17.261993,479392937,786,234,-8.1517054292,21.73074995644,-19.786317055275,2,1,18 +2025-03-11T12:42:17.386993,479392937,786,234,-8.04345530084,21.48588829231,-19.60460848515,2,1,18 +2025-03-11T12:42:17.511993,479392937,786,234,-7.90225948124,21.185573548435,-19.357854957705,2,1,18 +2025-03-11T12:42:17.636993,479392937,786,234,-7.71399838844,20.778997948675,-19.050378355515,2,1,18 +2025-03-11T12:42:17.761993,479392937,786,234,-7.50220465904,20.284664751385,-18.668466601185,2,1,18 +2025-03-11T12:42:17.886993,479392937,786,234,-7.26217176572,19.725651649375,-18.24457199484,2,1,18 +2025-03-11T12:42:18.011917,479392941,781,235,-6.98448665384,19.092710556925,-17.7416645574,2,1,18 +2025-03-11T12:42:18.136917,479392941,781,235,-6.68326890536,18.399713602615,-17.178328321365,2,1,18 +2025-03-11T12:42:18.261917,479392941,781,235,-6.339692411,17.609696791225,-16.572808333875,2,1,18 +2025-03-11T12:42:18.386917,479392941,781,235,-5.96787675272,16.75038311917,-15.92528116062,2,1,18 +2025-03-11T12:42:18.511917,479392941,781,235,-5.56782193052,15.83100649834,-15.20807476701,2,1,18 +2025-03-11T12:42:18.636917,479392941,781,235,-5.14423447172,14.85157401565,-14.43505969182,2,1,18 +2025-03-11T12:42:18.761917,479392941,781,235,-4.67828826704,13.798206455605,-13.619982533925,2,1,18 +2025-03-11T12:42:18.886917,479392941,781,235,-4.18410289844,12.694009858675,-12.74913517422,2,1,18 +2025-03-11T12:42:19.011917,479392941,781,235,-3.6805044752,11.52054474874,-11.8455616137,2,1,18 +2025-03-11T12:42:19.136917,479392941,781,235,-3.13454730608,10.29161238523,-10.909263539505,2,1,18 +2025-03-11T12:42:19.261917,479392941,781,235,-2.58388360964,9.0211203313,-9.921914986665,2,1,18 +2025-03-11T12:42:19.386917,479392941,781,235,-2.01439380392,7.727515149985,-8.915923546095,2,1,18 +2025-03-11T12:42:19.511917,479392941,781,235,-1.43078441624,6.37386828064,-7.881864501495,2,1,18 +2025-03-11T12:42:19.636917,479392941,781,235,-0.81893586464,4.96015846252,-6.810467055645,2,1,18 +2025-03-11T12:42:19.761917,479392941,781,235,-0.18355467644,3.53256234199,-5.674264031685,2,1,18 +2025-03-11T12:42:19.886917,479392941,781,235,0.461239566400001,2.072633356015,-4.537870296015,2,1,18 +2025-03-11T12:42:20.011917,479392941,781,235,1.11074033656,0.5896125034,-3.38748435282,2,1,18 +2025-03-11T12:42:20.136917,479392941,781,235,1.79318679796,-0.916542737344999,-2.218424958705,2,1,18 +2025-03-11T12:42:20.261917,479392941,781,235,2.46622020472,-2.45961945182,-1.03071080199,2,1,18 +2025-03-11T12:42:20.386917,479392941,781,235,3.13454708416,-4.00268907938,0.156993166995,2,1,18 +2025-03-11T12:42:20.511917,479392941,781,235,3.82170007288,-5.5457870546,1.37245858899,2,1,18 +2025-03-11T12:42:20.636917,479392941,781,235,4.51826611624,-7.121217895265,2.569634254635,2,1,18 +2025-03-11T12:42:20.761917,479392941,781,235,5.21012563228,-8.68279078118,3.780587082345,2,1,18 +2025-03-11T12:42:20.886917,479392941,781,235,5.89257209368,-10.244349493265,5.00537988564,2,1,18 +2025-03-11T12:42:21.011917,479392941,781,235,6.58443160972,-11.80592237918,6.20709247932,2,1,18 +2025-03-11T12:42:21.136917,479392941,781,235,7.25746501648,-13.367466917435,7.39028385402,2,1,18 +2025-03-11T12:42:21.261917,479392941,781,235,7.93049842324,-14.89207580813,8.59176102678,2,1,18 +2025-03-11T12:42:21.386917,479392941,781,235,8.59411877536,-16.398202701215,9.76539978699,2,1,18 +2025-03-11T12:42:21.511917,479392941,781,235,9.24361954552,-17.89045746572,10.915834397685,2,1,18 +2025-03-11T12:42:21.636917,479392941,781,235,9.88370726104,-19.35037936478,12.03835759458,2,1,18 +2025-03-11T12:42:21.761917,479392941,781,235,10.5096753946,-20.764110443645,13.132886188695,2,1,18 +2025-03-11T12:42:21.886917,479392941,781,235,11.13093700084,-22.14551574398,14.2179940248,2,1,18 +2025-03-11T12:42:22.011856,479392945,777,236,11.71925291584,-23.485318832405,15.26123048991,2,1,18 +2025-03-11T12:42:22.136856,479392945,777,236,12.26991661228,-24.78812957795,16.281090198105,2,1,18 +2025-03-11T12:42:22.261856,479392945,777,236,12.82528683604,-26.04477785096,17.26375582041,2,1,18 +2025-03-11T12:42:22.386856,479392945,777,236,13.34771136856,-27.264440868005,18.19533417144,2,1,18 +2025-03-11T12:42:22.511856,479392945,777,236,13.86072284644,-28.4102184161,19.103402221935,2,1,18 +2025-03-11T12:42:22.636856,479392945,777,236,14.35490821504,-29.50518110114,19.94648021205,2,1,18 +2025-03-11T12:42:22.761856,479392945,777,236,14.8161478924,-30.56777548616,20.73849526464,2,1,18 +2025-03-11T12:42:22.886856,479392945,777,236,15.24914840584,-31.54722214268,21.49305024723,2,1,18 +2025-03-11T12:42:23.011856,479392945,777,236,15.65390975536,-32.429670202865,22.19159169051,2,1,18 +2025-03-11T12:42:23.136856,479392945,777,236,16.02101888632,-33.261275052335,22.838962673535,2,1,18 +2025-03-11T12:42:23.261856,479392945,777,236,16.35988885336,-34.02358304114,23.444326470795,2,1,18 +2025-03-11T12:42:23.386856,479392945,777,236,16.6752261838,-34.716601256195,23.96149209987,2,1,18 +2025-03-11T12:42:23.511856,479392945,777,236,16.9340851864,-35.340280089095,24.45506988486,2,1,18 +2025-03-11T12:42:23.636856,479392945,777,236,17.15999849776,-35.88080410658,24.878836593015,2,1,18 +2025-03-11T12:42:23.761856,479392945,777,236,17.3812052818,-36.333598874195,25.23744913398,2,1,18 +2025-03-11T12:42:23.886856,479392945,777,236,17.545933738,-36.73090512749,25.53558589599,2,1,18 +2025-03-11T12:42:24.011856,479392945,777,236,17.66830344832,-37.021957611815,25.791490239045,2,1,18 +2025-03-11T12:42:24.136856,479392945,777,236,17.781260104,-37.24835853908,25.95463119384,2,1,18 +2025-03-11T12:42:24.261856,479392945,777,236,17.83773843184,-37.40542008419,26.061843485445,2,1,18 +2025-03-11T12:42:24.386856,479392945,777,236,17.88009717772,-37.470121249655,26.089996549605,2,1,18 +2025-03-11T12:42:24.511856,479392945,777,236,17.86597759576,-37.43316434135,26.07591096537,2,1,18 +2025-03-11T12:42:24.636856,479392945,777,236,17.8283253772,-37.33153461524,25.9736515467,2,1,18 +2025-03-11T12:42:24.761856,479392945,777,236,17.75302094008,-37.151359942745,25.829315899305,2,1,18 +2025-03-11T12:42:24.886856,479392945,777,236,17.62594470244,-36.897236019065,25.633657559715,2,1,18 +2025-03-11T12:42:25.011856,479392945,777,236,17.47062930088,-36.541496543105,25.35886076199,2,1,18 +2025-03-11T12:42:25.136856,479392945,777,236,17.27766168076,-36.11644603265,25.03279616901,2,1,18 +2025-03-11T12:42:25.261856,479392945,777,236,17.07057447868,-35.612886010385,24.64160570088,2,1,18 +2025-03-11T12:42:25.386856,479392945,777,236,16.79759589412,-35.030738520245,24.189797409585,2,1,18 +2025-03-11T12:42:25.511856,479392945,777,236,16.51520425492,-34.36085469332,23.6820649974,2,1,18 +2025-03-11T12:42:25.636856,479392945,777,236,16.19986692448,-33.64475169854,23.109336295395,2,1,18 +2025-03-11T12:42:25.761856,479392945,777,236,15.85629043012,-32.840884019315,22.48064272158,2,1,18 +2025-03-11T12:42:25.886856,479392945,777,236,15.46094213524,-31.963067088905,21.805246572585,2,1,18 +2025-03-11T12:42:26.011795,479392949,773,237,15.05618078572,-31.02521555738,21.069452188185,2,1,18 +2025-03-11T12:42:26.136795,479392949,773,237,14.604354163,-30.02727272942,20.30089876863,2,1,18 +2025-03-11T12:42:26.261795,479392949,773,237,14.14311448564,-28.95544443251,19.47187411242,2,1,18 +2025-03-11T12:42:26.386795,479392949,773,237,13.65363564436,-27.83740405466,18.600963939195,2,1,18 +2025-03-11T12:42:26.511795,479392949,773,237,13.13591763916,-26.640832904255,17.67413756166,2,1,18 +2025-03-11T12:42:26.636795,479392949,773,237,12.604080052,-25.41192180149,16.72400969961,2,1,18 +2025-03-11T12:42:26.761795,479392949,773,237,12.02047066432,-24.113678403485,15.722583479115,2,1,18 +2025-03-11T12:42:26.886795,479392949,773,237,11.44627433128,-22.80621526742,14.688788147475,2,1,18 +2025-03-11T12:42:27.011795,479392949,773,237,10.85325188896,-21.452554224245,13.626988025325,2,1,18 +2025-03-11T12:42:27.136795,479392949,773,237,10.24140333736,-20.029610494235,12.537061443915,2,1,18 +2025-03-11T12:42:27.261795,479392949,773,237,9.59660909452,-18.57891542015,11.409956609775,2,1,18 +2025-03-11T12:42:27.386795,479392949,773,237,8.96122790632,-17.10514974017,10.273510248315,2,1,18 +2025-03-11T12:42:27.511795,479392949,773,237,8.29290102688,-15.612866628005,9.10455441864,2,1,18 +2025-03-11T12:42:27.636795,479392949,773,237,7.62928067476,-14.08827191114,7.935438440445,2,1,18 +2025-03-11T12:42:27.761795,479392949,773,237,6.94683421336,-12.535947110945,6.74765524077,2,1,18 +2025-03-11T12:42:27.886795,479392949,773,237,6.26438775196,-10.98362231075,5.54601169005,2,1,18 +2025-03-11T12:42:28.011795,479392949,773,237,5.59606087252,-9.44055268319,4.35368760405,2,1,18 +2025-03-11T12:42:28.136795,479392949,773,237,4.91361441112,-7.888227882995,3.13356358527,2,1,18 +2025-03-11T12:42:28.261795,479392949,773,237,4.2264614224,-6.335895995885,1.918049495775,2,1,18 +2025-03-11T12:42:28.386795,479392949,773,237,3.53460190636,-4.76508919808,0.71166811758,2,1,18 +2025-03-11T12:42:28.511795,479392949,773,237,2.8615684996,-3.20816161577,-0.485359274415,2,1,18 +2025-03-11T12:42:28.636795,479392949,773,237,2.18382856552,-1.660460858435,-1.69158842067,2,1,18 +2025-03-11T12:42:28.761795,479392949,773,237,1.51079515876,-0.149702835574999,-2.869892007105,2,1,18 +2025-03-11T12:42:28.886795,479392949,773,237,0.847174806640001,1.33795623373,-4.02957308127,2,1,18 +2025-03-11T12:42:29.011795,479392949,773,237,0.18355445452,2.844083126815,-5.170871022375,2,1,18 +2025-03-11T12:42:29.136795,479392949,773,237,-0.447120206359999,4.28090607232,-6.297872292075,2,1,18 +2025-03-11T12:42:29.261795,479392949,773,237,-1.07308833992,5.69002019524,-7.378516201395,2,1,18 +2025-03-11T12:42:29.386795,479392949,773,237,-1.67552383688,7.08524801575,-8.43593558574,2,1,18 +2025-03-11T12:42:29.511795,479392949,773,237,-2.25442669724,8.425036930345,-9.456051090315,2,1,18 +2025-03-11T12:42:29.636795,479392949,773,237,-2.82391650296,9.714025155715,-10.47587854818,2,1,18 +2025-03-11T12:42:29.761795,479392949,773,237,-3.36046061744,10.93832638945,-11.439852615255,2,1,18 +2025-03-11T12:42:29.886795,479392949,773,237,-3.87817862264,12.1395144958,-12.36670332654,2,1,18 +2025-03-11T12:42:30.011734,479392953,769,238,-4.37707051856,13.280653827205,-13.246995778005,2,1,18 +2025-03-11T12:42:30.136734,479392953,769,238,-4.84772325056,14.347879342,-14.08987682697,2,1,18 +2025-03-11T12:42:30.261734,479392953,769,238,-5.31366945524,15.373545166375,-14.86322692923,2,1,18 +2025-03-11T12:42:30.386734,479392953,769,238,-5.71843080476,16.325247565735,-15.594474197865,2,1,18 +2025-03-11T12:42:30.511734,479392953,769,238,-6.10907257232,17.216908277065,-16.274553277395,2,1,18 +2025-03-11T12:42:30.636734,479392953,769,238,-6.46676864864,18.01618026109,-16.91249331468,2,1,18 +2025-03-11T12:42:30.761734,479392953,769,238,-6.79151903372,18.74153134159,-17.494531293675,2,1,18 +2025-03-11T12:42:30.886734,479392953,769,238,-7.0927367822,19.4345282959,-18.016286476575,2,1,18 +2025-03-11T12:42:31.011734,479392953,769,238,-7.36100883944,20.016668699125,-18.472704697155,2,1,18 +2025-03-11T12:42:31.136734,479392953,769,238,-7.60574826008,20.543370196435,-18.86871845289,2,1,18 +2025-03-11T12:42:31.261734,479392953,769,238,-7.78930282556,20.982257400895,-19.217936256735,2,1,18 +2025-03-11T12:42:31.386734,479392953,769,238,-7.93049864516,21.36567735178,-19.51132896183,2,1,18 +2025-03-11T12:42:31.511734,479392953,769,238,-8.0575748828,21.642886055185,-19.7163492042,2,1,18 +2025-03-11T12:42:31.636734,479392953,769,238,-8.16582501116,21.84619511581,-19.870118068485,2,1,18 +2025-03-11T12:42:31.761734,479392953,769,238,-8.222303339,21.970937969305,-19.97716002384,2,1,18 +2025-03-11T12:42:31.886734,479392953,769,238,-8.24112944828,21.99405109669,-19.97732244351,2,1,18 +2025-03-11T12:42:32.011734,479392953,769,238,-8.222303339,21.93861927769,-19.944648868485,2,1,18 +2025-03-11T12:42:32.136734,479392953,769,238,-8.16582501116,21.81849338014,-19.860731831955,2,1,18 +2025-03-11T12:42:32.261734,479392953,769,238,-8.09052057404,21.610616971975,-19.693149596985,2,1,18 +2025-03-11T12:42:32.386734,479392953,769,238,-7.94932475444,21.314919184045,-19.460280754335,2,1,18 +2025-03-11T12:42:32.511734,479392953,769,238,-7.7987158802,20.94995288311,-19.18544547684,2,1,18 +2025-03-11T12:42:32.636734,479392953,769,238,-7.60574826008,20.49258368104,-18.81300937746,2,1,18 +2025-03-11T12:42:32.761734,479392953,769,238,-7.37042189408,19.94742853378,-18.4215387792,2,1,18 +2025-03-11T12:42:32.886734,479392953,769,238,-7.09744330952,19.351430175805,-17.93731666755,2,1,18 +2025-03-11T12:42:33.011734,479392953,769,238,-6.79622556104,18.658433221495,-17.42480171868,2,1,18 +2025-03-11T12:42:33.136734,479392953,769,238,-6.47147517596,17.91923127316,-16.842690738435,2,1,18 +2025-03-11T12:42:33.261734,479392953,769,238,-6.104366045,17.083009467745,-16.209155772705,2,1,18 +2025-03-11T12:42:33.386734,479392953,769,238,-5.7043112228,16.200568494475,-15.51524463417,2,1,18 +2025-03-11T12:42:33.511734,479392953,769,238,-5.28543029132,15.23961092248,-14.756197432755,2,1,18 +2025-03-11T12:42:33.636734,479392953,769,238,-4.83831019592,14.20935648982,-13.964383279605,2,1,18 +2025-03-11T12:42:33.761734,479392953,769,238,-4.35824440928,13.123648977415,-13.13062475421,2,1,18 +2025-03-11T12:42:33.886734,479392953,769,238,-3.87347209532,11.97791395081,-12.24571841517,2,1,18 +2025-03-11T12:42:34.011657,479392957,764,239,-3.34634103548,10.77671167063,-11.31422721141,2,1,18 +2025-03-11T12:42:34.136657,479392957,764,239,-2.809796921,9.53855956906,-10.340939909055,2,1,18 +2025-03-11T12:42:34.261657,479392957,764,239,-2.2450136426,8.240344518715,-9.33955443948,2,1,18 +2025-03-11T12:42:34.386657,479392957,764,239,-1.64257814564,6.91437103738,-8.300980529445,2,1,18 +2025-03-11T12:42:34.511657,479392957,764,239,-1.03543612136,5.53298699779,-7.248244075635,2,1,18 +2025-03-11T12:42:34.636657,479392957,764,239,-0.41417451512,4.105412138005,-6.139792316955,2,1,18 +2025-03-11T12:42:34.761657,479392957,764,239,0.211793618440001,2.659362367525,-5.00813245047,2,1,18 +2025-03-11T12:42:34.886657,479392957,764,239,0.8612943886,1.16710760302,-3.86231795679,2,1,18 +2025-03-11T12:42:35.011657,479392957,764,239,1.52962126804,-0.334409421035,-2.6886933426,2,1,18 +2025-03-11T12:42:35.136657,479392957,764,239,2.19794814748,-1.85439426887,-1.519591510425,2,1,18 +2025-03-11T12:42:35.261657,479392957,764,239,2.86627502692,-3.402080852375,-0.336483324705001,2,1,18 +2025-03-11T12:42:35.386657,479392957,764,239,3.54872148832,-4.94517174068,0.874351792545,2,1,18 +2025-03-11T12:42:35.511657,479392957,764,239,4.24528753168,-6.502134757565,2.076050240205,2,1,18 +2025-03-11T12:42:35.636657,479392957,764,239,4.92773399308,-8.077544337485,3.29167581072,2,1,18 +2025-03-11T12:42:35.761657,479392957,764,239,5.62430003644,-9.639124310315,4.507258943175,2,1,18 +2025-03-11T12:42:35.886657,479392957,764,239,6.31145302516,-11.17760532959,5.71345979739,2,1,18 +2025-03-11T12:42:36.011657,479392957,764,239,6.97036684996,-12.70219295954,6.919526523975,2,1,18 +2025-03-11T12:42:36.136657,479392957,764,239,7.61986762012,-14.25446815133,8.08875794148,2,1,18 +2025-03-11T12:42:36.261657,479392957,764,239,8.29290102688,-15.797544865805,9.276472098195,2,1,18 +2025-03-11T12:42:36.386657,479392957,764,239,8.96593443364,-17.30368593272,10.43627088282,2,1,18 +2025-03-11T12:42:36.511657,479392957,764,239,9.62484825844,-18.76363617944,11.577315298695,2,1,18 +2025-03-11T12:42:36.636657,479392957,764,239,10.24610986468,-20.19582799517,12.69041150814,2,1,18 +2025-03-11T12:42:36.761657,479392957,764,239,10.8626649436,-21.59569403237,13.78946684256,2,1,18 +2025-03-11T12:42:36.886657,479392957,764,239,11.46510044056,-22.96322011721,14.83287987336,2,1,18 +2025-03-11T12:42:37.011657,479392957,764,239,12.05812288288,-24.28456246877,15.852928606125,2,1,18 +2025-03-11T12:42:37.136657,479392957,764,239,12.604080052,-25.564281347675,16.849555872765,2,1,18 +2025-03-11T12:42:37.261657,479392957,764,239,13.15003722112,-26.78859675524,17.808930198285,2,1,18 +2025-03-11T12:42:37.386657,479392957,764,239,13.68187480828,-27.95748743072,18.721780785465,2,1,18 +2025-03-11T12:42:37.511657,479392957,764,239,14.17135364956,-29.070910852625,19.57418615688,2,1,18 +2025-03-11T12:42:37.636657,479392957,764,239,14.6278867996,-30.128881194785,20.380027039035,2,1,18 +2025-03-11T12:42:37.761657,479392957,764,239,15.06088731304,-31.14064654292,21.153232825935,2,1,18 +2025-03-11T12:42:37.886657,479392957,764,239,15.47035518988,-32.08773907325,21.879845831535,2,1,18 +2025-03-11T12:42:38.011596,479392961,760,240,15.86570348476,-32.96555600366,22.56448221456,2,1,18 +2025-03-11T12:42:38.136596,479392961,760,240,16.21869303376,-33.76482090077,23.193171830085,2,1,18 +2025-03-11T12:42:38.261596,479392961,760,240,16.53873689152,-34.480930982465,23.73819001773,2,1,18 +2025-03-11T12:42:38.386596,479392961,760,240,16.82583505804,-35.11850320469,24.25038239841,2,1,18 +2025-03-11T12:42:38.511596,479392961,760,240,17.08940058796,-35.696019565055,24.68828562945,2,1,18 +2025-03-11T12:42:38.636596,479392961,760,240,17.29648779004,-36.17187785165,25.07008986105,2,1,18 +2025-03-11T12:42:38.761596,479392961,760,240,17.49416193748,-36.6154032728,25.40550221079,2,1,18 +2025-03-11T12:42:38.886596,479392961,760,240,17.62594470244,-36.97572427013,25.661791935555,2,1,18 +2025-03-11T12:42:39.011596,479392961,760,240,17.74360788544,-37.2113661962,25.8619526817,2,1,18 +2025-03-11T12:42:39.136596,479392961,760,240,17.8283253772,-37.3684702628,25.99232668476,2,1,18 +2025-03-11T12:42:39.261596,479392961,760,240,17.86127106844,-37.46547594605,26.05759064583,2,1,18 +2025-03-11T12:42:39.386596,479392961,760,240,17.87068412308,-37.49319185555,26.06699725782,2,1,18 +2025-03-11T12:42:39.511596,479392961,760,240,17.84715148648,-37.437752949635,26.025073261035,2,1,18 +2025-03-11T12:42:39.636596,479392961,760,240,17.77655357668,-37.28990405567,25.913258956725,2,1,18 +2025-03-11T12:42:39.761596,479392961,760,240,17.67771650296,-37.0173548297,25.726804642545,2,1,18 +2025-03-11T12:42:39.886596,479392961,760,240,17.53652068336,-36.698572262045,25.484573897115,2,1,18 +2025-03-11T12:42:40.011596,479392961,760,240,17.35296611788,-36.305854617035,25.158700015845,2,1,18 +2025-03-11T12:42:40.136596,479392961,760,240,17.15529197044,-35.843861372105,24.80008974603,2,1,18 +2025-03-11T12:42:40.261596,479392961,760,240,16.90113949516,-35.28482700935,24.376164576495,2,1,18 +2025-03-11T12:42:40.386596,479392961,760,240,16.64228049256,-34.647297308615,23.86865343921,2,1,18 +2025-03-11T12:42:40.511596,479392961,760,240,16.32694316212,-33.940428225725,23.33755445784,2,1,18 +2025-03-11T12:42:40.636596,479392961,760,240,15.98807319508,-33.16888632503,22.71366152502,2,1,18 +2025-03-11T12:42:40.761596,479392961,760,240,15.62096406412,-32.32804756367,22.066241874495,2,1,18 +2025-03-11T12:42:40.886596,479392961,760,240,15.22561576924,-31.408678029755,21.367526136675,2,1,18 +2025-03-11T12:42:41.011596,479392961,760,240,14.79732178312,-30.43847237204,20.603789775285,2,1,18 +2025-03-11T12:42:41.136596,479392961,760,240,14.35490821504,-29.389757202515,19.774927538745,2,1,18 +2025-03-11T12:42:41.261596,479392961,760,240,13.85601631912,-28.290170474615,18.93181502715,2,1,18 +2025-03-11T12:42:41.386596,479392961,760,240,13.34300484124,-27.130542058685,18.032914209435,2,1,18 +2025-03-11T12:42:41.511596,479392961,760,240,12.81116725408,-25.90163095592,17.09664669843,2,1,18 +2025-03-11T12:42:41.636596,479392961,760,240,12.2746231396,-24.64501103057,16.10940171003,2,1,18 +2025-03-11T12:42:41.761596,479392961,760,240,11.6863072246,-23.32829272187,15.098627732775,2,1,18 +2025-03-11T12:42:41.886596,479392961,760,240,11.0979913096,-21.99310658939,14.0507954844,2,1,18 +2025-03-11T12:42:42.011535,479392965,756,241,10.49555581264,-20.611729636715,12.98882898429,2,1,18 +2025-03-11T12:42:42.136535,479392965,756,241,9.86958767908,-19.17029682218,11.875673919615,2,1,18 +2025-03-11T12:42:42.261535,479392965,756,241,9.22479343624,-17.710367836205,10.73466006693,2,1,18 +2025-03-11T12:42:42.386535,479392965,756,241,8.57529266608,-16.222730027645,9.575009555955,2,1,18 +2025-03-11T12:42:42.511535,479392965,756,241,7.90696578664,-14.73044691548,8.42453419434,2,1,18 +2025-03-11T12:42:42.636535,479392965,756,241,7.2386389072,-13.18737728792,7.23221010834,2,1,18 +2025-03-11T12:42:42.761535,479392965,756,241,6.57501855508,-11.63969779133,6.026011525275,2,1,18 +2025-03-11T12:42:42.886535,479392965,756,241,5.86903945708,-10.08733755656,4.833557269935,2,1,18 +2025-03-11T12:42:43.011535,479392965,756,241,5.19600605032,-8.50270823858,3.622523524395,2,1,18 +2025-03-11T12:42:43.136535,479392965,756,241,4.51826611624,-6.955007481245,2.41629437814,2,1,18 +2025-03-11T12:42:43.261535,479392965,756,241,3.8264066002,-5.39343459533,1.20534155043,2,1,18 +2025-03-11T12:42:43.386535,479392965,756,241,3.13454708416,-3.841095621305,-0.00094249276500058,2,1,18 +2025-03-11T12:42:43.511535,479392965,756,241,2.47092673204,-2.293416124715,-1.193280724785,2,1,18 +2025-03-11T12:42:43.636535,479392965,756,241,1.79318679796,-0.745715367379997,-2.39026963701,2,1,18 +2025-03-11T12:42:43.761535,479392965,756,241,1.12956644584,0.765028481650001,-3.559312613955,2,1,18 +2025-03-11T12:42:43.886535,479392965,756,241,0.47065262104,2.248063508095,-4.705098815595,2,1,18 +2025-03-11T12:42:44.011535,479392965,756,241,-0.164728567159999,3.694127452405,-5.82753882351,2,1,18 +2025-03-11T12:42:44.136535,479392965,756,241,-0.804816282679999,5.135581527685,-6.92686410033,2,1,18 +2025-03-11T12:42:44.261535,479392965,756,241,-1.41195830696,6.52158252322,-8.002725472965,2,1,18 +2025-03-11T12:42:44.386535,479392965,756,241,-1.99086116732,7.86598839376,-9.055206130395,2,1,18 +2025-03-11T12:42:44.511535,479392965,756,241,-2.56505750036,9.16883457388,-10.07511677724,2,1,18 +2025-03-11T12:42:44.636535,479392965,756,241,-3.14396036072,10.443986105245,-11.05331055618,2,1,18 +2025-03-11T12:42:44.761535,479392965,756,241,-3.67109142056,11.66827316515,-11.99416366272,2,1,18 +2025-03-11T12:42:44.886535,479392965,756,241,-4.1746898438,12.832504363195,-12.893068438725,2,1,18 +2025-03-11T12:42:45.011535,479392965,756,241,-4.66416868508,13.92745996132,-13.731516124095,2,1,18 +2025-03-11T12:42:45.136535,479392965,756,241,-5.1395279444,14.97622473925,-14.5465893237,2,1,18 +2025-03-11T12:42:45.261535,479392965,756,241,-5.56782193052,15.94181344102,-15.305681234325,2,1,18 +2025-03-11T12:42:45.386535,479392965,756,241,-5.97728980736,16.8427364119,-15.99046984929,2,1,18 +2025-03-11T12:42:45.511535,479392965,756,241,-6.35381199296,17.688206303035,-16.64255432604,2,1,18 +2025-03-11T12:42:45.636535,479392965,756,241,-6.68326890536,18.46896794179,-17.271095667915,2,1,18 +2025-03-11T12:42:45.761535,479392965,756,241,-6.97978012652,19.15734085324,-17.81591691441,2,1,18 +2025-03-11T12:42:45.886535,479392965,756,241,-7.27158482036,19.79492016238,-18.30963901476,2,1,18 +2025-03-11T12:42:46.011474,479392969,752,242,-7.51161771368,20.349316308445,-18.7473696384,2,1,18 +2025-03-11T12:42:46.136474,479392969,752,242,-7.71870491576,20.83440850693,-19.106121952425,2,1,18 +2025-03-11T12:42:46.261474,479392969,752,242,-7.8928464266,21.240962845945,-19.385847289335,2,1,18 +2025-03-11T12:42:46.386474,479392969,752,242,-8.02933571888,21.550504414795,-19.637259413565,2,1,18 +2025-03-11T12:42:46.511474,479392969,752,242,-8.13287931992,21.78612508012,-19.81890912846,2,1,18 +2025-03-11T12:42:46.636474,479392969,752,242,-8.1987707024,21.93396688717,-19.93071324504,2,1,18 +2025-03-11T12:42:46.761474,479392969,752,242,-8.25524903024,22.003306269325,-19.98664190823,2,1,18 +2025-03-11T12:42:46.886474,479392969,752,242,-8.24112944828,21.970966316965,-19.98644100879,2,1,18 +2025-03-11T12:42:47.011474,479392969,752,242,-8.19406417508,21.85547154919,-19.916429032515,2,1,18 +2025-03-11T12:42:47.136474,479392969,752,242,-8.10934668332,21.684516614755,-19.776741794175,2,1,18 +2025-03-11T12:42:47.261474,479392969,752,242,-8.00580308228,21.444278993485,-19.56734704344,2,1,18 +2025-03-11T12:42:47.386474,479392969,752,242,-7.85519420804,21.102397472275,-19.320354136785,2,1,18 +2025-03-11T12:42:47.511474,479392969,752,242,-7.68575922452,20.68199935234,-18.975884348145,2,1,18 +2025-03-11T12:42:47.636474,479392969,752,242,-7.47867202244,20.206141065745,-18.58945999953,2,1,18 +2025-03-11T12:42:47.761474,479392969,752,242,-7.2103999652,19.619383706575,-18.156118030275,2,1,18 +2025-03-11T12:42:47.886474,479392969,752,242,-6.91859527136,18.97718744149,-17.653131362145,2,1,18 +2025-03-11T12:42:48.011474,479392969,752,242,-6.60796446824,18.261091533625,-17.0896530819,2,1,18 +2025-03-11T12:42:48.136474,479392969,752,242,-6.25497491924,17.45720968057,-16.470179366655,2,1,18 +2025-03-11T12:42:48.261474,479392969,752,242,-5.869039679,16.574789968045,-15.799399376385,2,1,18 +2025-03-11T12:42:48.386474,479392969,752,242,-5.47839791144,15.646193609155,-15.091404924765,2,1,18 +2025-03-11T12:42:48.511474,479392969,752,242,-5.05010392532,14.66675403955,-14.309139427815,2,1,18 +2025-03-11T12:42:48.636474,479392969,752,242,-4.574744666,13.59952143784,-13.480108542165,2,1,18 +2025-03-11T12:42:48.761474,479392969,752,242,-4.08526582472,12.46301323621,-12.613721150955,2,1,18 +2025-03-11T12:42:48.886474,479392969,752,242,-3.57696087416,11.29877495125,-11.71480618722,2,1,18 +2025-03-11T12:42:49.011474,479392969,752,242,-3.02629717772,10.060601588935,-10.750728555705,2,1,18 +2025-03-11T12:42:49.136474,479392969,752,242,-2.47092695396,8.79933635998,-9.781898950695,2,1,18 +2025-03-11T12:42:49.261474,479392969,752,242,-1.90143714824,7.46417857516,-8.747967804285,2,1,18 +2025-03-11T12:42:49.386474,479392969,752,242,-1.29429512396,6.087411491515,-7.686015450195,2,1,18 +2025-03-11T12:42:49.511474,479392969,752,242,-0.68715309968,4.669091804365,-6.58226303922,2,1,18 +2025-03-11T12:42:49.636474,479392969,752,242,-0.0282392748799998,3.24146024926,-5.459869427655,2,1,18 +2025-03-11T12:42:49.761474,479392969,752,242,0.60714191332,1.790779349005,-4.332784968975,2,1,18 +2025-03-11T12:42:49.886474,479392969,752,242,1.2613492108,0.280049673805001,-3.168382484505,2,1,18 +2025-03-11T12:42:50.011413,479392973,748,243,1.93438261756,-1.22609139311,-1.994723348835,2,1,18 +2025-03-11T12:42:50.136413,479392973,748,243,2.59800296968,-2.75530306592,-0.80710256883,2,1,18 +2025-03-11T12:42:50.261413,479392973,748,243,3.26632984912,-4.302989649425,0.389865967935,2,1,18 +2025-03-11T12:42:50.386413,479392973,748,243,3.9440697832,-5.883009098375,1.6147459185,2,1,18 +2025-03-11T12:42:50.511413,479392973,748,243,4.63122277192,-7.453808809265,2.81649699195,2,1,18 +2025-03-11T12:42:50.636413,479392973,748,243,5.32778881528,-9.00153791426,4.02738700614,2,1,18 +2025-03-11T12:42:50.761413,479392973,748,243,6.02435485864,-10.58158571087,5.243067473595,2,1,18 +2025-03-11T12:42:50.886413,479392973,748,243,6.71150784736,-12.120066730145,6.453888444825,2,1,18 +2025-03-11T12:42:51.011413,479392973,748,243,7.39395430876,-13.658540662505,7.646218760265,2,1,18 +2025-03-11T12:42:51.136413,479392973,748,243,8.05286813356,-15.183128292455,8.810704433715,2,1,18 +2025-03-11T12:42:51.261413,479392973,748,243,8.71648848568,-16.684638229595,9.965838392115,2,1,18 +2025-03-11T12:42:51.386413,479392973,748,243,9.38481536512,-18.17692134176,11.111693636715,2,1,18 +2025-03-11T12:42:51.511413,479392973,748,243,10.02960960796,-19.64146728368,12.22501112106,2,1,18 +2025-03-11T12:42:51.636413,479392973,748,243,10.6508712142,-21.059808231575,13.32417397821,2,1,18 +2025-03-11T12:42:51.761413,479392973,748,243,11.24860018384,-22.43656114139,14.39534619087,2,1,18 +2025-03-11T12:42:51.886413,479392973,748,243,11.81808998956,-23.76248501432,15.443089020825,2,1,18 +2025-03-11T12:42:52.011413,479392973,748,243,12.38287326796,-25.05608310872,16.449070273665,2,1,18 +2025-03-11T12:42:52.136413,479392973,748,243,12.9335369644,-26.294256471035,17.41314790518,2,1,18 +2025-03-11T12:42:52.261413,479392973,748,243,13.46066802424,-27.504692663105,18.340067659425,2,1,18 +2025-03-11T12:42:52.386413,479392973,748,243,13.9689729748,-28.64584616834,19.22962072038,2,1,18 +2025-03-11T12:42:52.511413,479392973,748,243,14.45374528876,-29.717709899825,20.063316432255,2,1,18 +2025-03-11T12:42:52.636413,479392973,748,243,14.9102784388,-30.757212418205,20.85057951135,2,1,18 +2025-03-11T12:42:52.761413,479392973,748,243,15.34798547956,-31.713581381915,21.600402895905,2,1,18 +2025-03-11T12:42:52.886413,479392973,748,243,15.72921419248,-32.60061096347,22.29429761727,2,1,18 +2025-03-11T12:42:53.011413,479392973,748,243,16.07279068684,-33.41832951053,22.932304426365,2,1,18 +2025-03-11T12:42:53.136413,479392973,748,243,16.42107370852,-34.171417761275,23.51453934651,2,1,18 +2025-03-11T12:42:53.261413,479392973,748,243,16.71287840236,-34.845932717975,24.03617681895,2,1,18 +2025-03-11T12:42:53.386413,479392973,748,243,16.97644393228,-35.44191690212,24.506518204095,2,1,18 +2025-03-11T12:42:53.511413,479392973,748,243,17.2164768256,-35.97322826846,24.925646690925,2,1,18 +2025-03-11T12:42:53.636413,479392973,748,243,17.40944444572,-36.453682250255,25.28434410801,2,1,18 +2025-03-11T12:42:53.761413,479392973,748,243,17.55534679264,-36.81402450833,25.586865566115,2,1,18 +2025-03-11T12:42:53.886413,479392973,748,243,17.69654261224,-37.10048838437,25.79658515619,2,1,18 +2025-03-11T12:42:54.011337,479392977,743,244,17.80949926792,-37.317655399745,25.950437209455,2,1,18 +2025-03-11T12:42:54.136337,479392977,743,244,17.86597759576,-37.437781297295,26.052834714045,2,1,18 +2025-03-11T12:42:54.261337,479392977,743,244,17.88009717772,-37.488589073435,26.099334118635,2,1,18 +2025-03-11T12:42:54.386337,479392977,743,244,17.87068412308,-37.442405340155,26.06672958657,2,1,18 +2025-03-11T12:42:54.511337,479392977,743,244,17.80949926792,-37.326889311635,25.968966345015,2,1,18 +2025-03-11T12:42:54.636337,479392977,743,244,17.7341948308,-37.12824681536,25.792192543515,2,1,18 +2025-03-11T12:42:54.761337,479392977,743,244,17.6165316478,-36.841818373895,25.568663541045,2,1,18 +2025-03-11T12:42:54.886337,479392977,743,244,17.45650971892,-36.490688766965,25.29388088934,2,1,18 +2025-03-11T12:42:55.011337,479392977,743,244,17.25412904416,-36.051773214845,24.953862568605,2,1,18 +2025-03-11T12:42:55.136337,479392977,743,244,17.03292226012,-35.51587324022,24.543990732975,2,1,18 +2025-03-11T12:42:55.261337,479392977,743,244,16.7693567302,-34.92450601202,24.08291391561,2,1,18 +2025-03-11T12:42:55.386337,479392977,743,244,16.47755203636,-34.254608011265,23.556680659905,2,1,18 +2025-03-11T12:42:55.511337,479392977,743,244,16.14809512396,-33.52001593196,22.969963708665,2,1,18 +2025-03-11T12:42:55.636337,479392977,743,244,15.79510557496,-32.697666255125,22.33191219036,2,1,18 +2025-03-11T12:42:55.761337,479392977,743,244,15.39505075276,-31.81060832591,21.65183706912,2,1,18 +2025-03-11T12:42:55.886337,479392977,743,244,14.9808763486,-30.84042392894,20.92509220704,2,1,18 +2025-03-11T12:42:56.011337,479392977,743,244,14.5337562532,-29.814786452225,20.137922504655,2,1,18 +2025-03-11T12:42:56.136337,479392977,743,244,14.05369046656,-28.75678067549,19.299689864745,2,1,18 +2025-03-11T12:42:56.261337,479392977,743,244,13.56421162528,-27.62027247386,18.41020188846,2,1,18 +2025-03-11T12:42:56.386337,479392977,743,244,13.05590667472,-26.432949409175,17.49730490493,2,1,18 +2025-03-11T12:42:56.511337,479392977,743,244,12.49112339632,-25.185520874225,16.52852792571,2,1,18 +2025-03-11T12:42:56.636337,479392977,743,244,11.93104664524,-23.896546822685,15.536441545395,2,1,18 +2025-03-11T12:42:56.761337,479392977,743,244,11.34273073024,-22.56597764615,14.511734215845,2,1,18 +2025-03-11T12:42:56.886337,479392977,743,244,10.74029523328,-21.184600693475,13.440527481705,2,1,18 +2025-03-11T12:42:57.011337,479392977,743,244,10.12374015436,-19.766266832495,12.3459949293,2,1,18 +2025-03-11T12:42:57.136337,479392977,743,244,9.48365243884,-18.31096188938,11.205015598095,2,1,18 +2025-03-11T12:42:57.261337,479392977,743,244,8.84356472332,-16.818721298705,10.05460136286,2,1,18 +2025-03-11T12:42:57.386337,479392977,743,244,8.17053131656,-15.31258023179,8.89942269525,2,1,18 +2025-03-11T12:42:57.511337,479392977,743,244,7.4974979098,-13.806439164875,7.71652332555,2,1,18 +2025-03-11T12:42:57.636337,479392977,743,244,6.83387755768,-12.27261053612,6.53349832881,2,1,18 +2025-03-11T12:42:57.761337,479392977,743,244,6.13731151432,-10.72026447518,5.34106444893,2,1,18 +2025-03-11T12:42:57.886337,479392977,743,244,5.44545199828,-9.158691589265,4.134731738235,2,1,18 +2025-03-11T12:42:58.011276,479392981,739,245,4.77241859152,-7.59714705101,2.9099593104,2,1,18 +2025-03-11T12:42:58.136276,479392981,739,245,4.09938518476,-6.03098555681,1.685162548815,2,1,18 +2025-03-11T12:42:58.261276,479392981,739,245,3.40752566872,-4.469412670895,0.483449955135,2,1,18 +2025-03-11T12:42:58.386276,479392981,739,245,2.72037268,-2.91246382784,-0.70436776602,2,1,18 +2025-03-11T12:42:58.511276,479392981,739,245,2.03321969128,-1.383216720455,-1.910519952735,2,1,18 +2025-03-11T12:42:58.636276,479392981,739,245,1.38371892112,0.109038044050001,-3.07943503149,2,1,18 +2025-03-11T12:42:58.761276,479392981,739,245,0.73421815096,1.63361150017,-4.248520446495,2,1,18 +2025-03-11T12:42:58.886276,479392981,739,245,0.0894239081200006,3.093540486145,-5.38953429918,2,1,18 +2025-03-11T12:42:59.011276,479392981,739,245,-0.541250752759999,4.53959734354,-6.502723885335,2,1,18 +2025-03-11T12:42:59.136276,479392981,739,245,-1.16721888632,5.93947755457,-7.601799595215,2,1,18 +2025-03-11T12:42:59.261276,479392981,739,245,-1.76965438328,7.311620595355,-8.654477193795,2,1,18 +2025-03-11T12:42:59.386276,479392981,739,245,-2.3626768256,8.64681381475,-9.679219044825,2,1,18 +2025-03-11T12:42:59.511276,479392981,739,245,-2.91804704936,9.935780779375,-10.666675120395,2,1,18 +2025-03-11T12:42:59.636276,479392981,739,245,-3.4687107458,11.1647202298,-11.62146385038,2,1,18 +2025-03-11T12:42:59.761276,479392981,739,245,-3.986428751,12.34744051237,-12.55283734368,2,1,18 +2025-03-11T12:42:59.886276,479392981,739,245,-4.49002717424,13.474736062855,-13.423826747595,2,1,18 +2025-03-11T12:43:00.011276,479392981,739,245,-4.97009296088,14.55120966337,-14.23905613743,2,1,18 +2025-03-11T12:43:00.136276,479392981,739,245,-5.398386947,15.5537340127,-15.035303654175,2,1,18 +2025-03-11T12:43:00.261276,479392981,739,245,-5.80314829652,16.48696858828,-15.761833470795,2,1,18 +2025-03-11T12:43:00.386276,479392981,739,245,-6.1984965914,17.350934650855,-16.432536501525,2,1,18 +2025-03-11T12:43:00.511276,479392981,739,245,-6.54677961308,18.154809416995,-17.05200002904,2,1,18 +2025-03-11T12:43:00.636276,479392981,739,245,-6.86682347084,18.894004278415,-17.62024047051,2,1,18 +2025-03-11T12:43:00.761276,479392981,739,245,-7.14921511004,19.559271149395,-18.12332843193,2,1,18 +2025-03-11T12:43:00.886276,479392981,739,245,-7.40807411264,20.146014334735,-18.5797506108,2,1,18 +2025-03-11T12:43:01.011276,479392981,739,245,-7.64340047864,20.644999922545,-18.984838222605,2,1,18 +2025-03-11T12:43:01.136276,479392981,739,245,-7.84107462608,21.070057519915,-19.310913003315,2,1,18 +2025-03-11T12:43:01.261276,479392981,739,245,-7.99639002764,21.42118003993,-19.57644523326,2,1,18 +2025-03-11T12:43:01.386276,479392981,739,245,-8.10934668332,21.67989965881,-19.776717460425,2,1,18 +2025-03-11T12:43:01.511276,479392981,739,245,-8.1752380658,21.85544320153,-19.916388281595,2,1,18 +2025-03-11T12:43:01.636276,479392981,739,245,-8.24112944828,21.96634936102,-20.009517260115,2,1,18 +2025-03-11T12:43:01.761276,479392981,739,245,-8.25995555756,21.98484553246,-20.01427546305,2,1,18 +2025-03-11T12:43:01.886276,479392981,739,245,-8.23642292096,21.9247896706,-19.9677070155,2,1,18 +2025-03-11T12:43:02.011215,479392985,735,246,-8.18465112044,21.767735212405,-19.869745145655,2,1,18 +2025-03-11T12:43:02.136215,479392985,735,246,-8.0811075194,21.55058237086,-19.683572648745,2,1,18 +2025-03-11T12:43:02.261215,479392985,735,246,-7.9399116998,21.231799803205,-19.441341903315,2,1,18 +2025-03-11T12:43:02.386215,479392985,735,246,-7.77988977092,20.862202372495,-19.12950098049,2,1,18 +2025-03-11T12:43:02.511215,479392985,735,246,-7.55868298688,20.386322825155,-18.761526536745,2,1,18 +2025-03-11T12:43:02.636215,479392985,735,246,-7.3280631482,19.836557808865,-18.35618144142,2,1,18 +2025-03-11T12:43:02.761215,479392985,735,246,-7.045671509,19.217460497335,-17.88105751959,2,1,18 +2025-03-11T12:43:02.886215,479392985,735,246,-6.73504070588,18.515215457305,-17.326892474625,2,1,18 +2025-03-11T12:43:03.011215,479392985,735,246,-6.4102903208,17.77601350897,-16.730921143335,2,1,18 +2025-03-11T12:43:03.136215,479392985,735,246,-6.05259424448,16.949039789275,-16.09283510355,2,1,18 +2025-03-11T12:43:03.261215,479392985,735,246,-5.65253942228,16.03428012439,-15.389513394735,2,1,18 +2025-03-11T12:43:03.386215,479392985,735,246,-5.2101258542,15.04558538215,-14.634889369185,2,1,18 +2025-03-11T12:43:03.511215,479392985,735,246,-4.75829923148,14.01070690663,-13.82918034351,2,1,18 +2025-03-11T12:43:03.636215,479392985,735,246,-4.28293997216,12.920389525195,-12.967686970005,2,1,18 +2025-03-11T12:43:03.761215,479392985,735,246,-3.77934154892,11.77462615093,-12.073499646015,2,1,18 +2025-03-11T12:43:03.886215,479392985,735,246,-3.25221048908,10.56418995886,-11.13733965774,2,1,18 +2025-03-11T12:43:04.011215,479392985,735,246,-2.70154679264,9.29369790493,-10.163851455945,2,1,18 +2025-03-11T12:43:04.136215,479392985,735,246,-2.13676351424,7.98163198675,-9.157772868105,2,1,18 +2025-03-11T12:43:04.261215,479392985,735,246,-1.52962148996,6.632566638775,-8.123687218605,2,1,18 +2025-03-11T12:43:04.386215,479392985,735,246,-0.93659904764,5.2789055956,-7.052646862425,2,1,18 +2025-03-11T12:43:04.511215,479392985,735,246,-0.324750496039999,3.83749404181,-5.944142477955,2,1,18 +2025-03-11T12:43:04.636215,479392985,735,246,0.32475027412,2.382174924865,-4.83086347338,2,1,18 +2025-03-11T12:43:04.761215,479392985,735,246,0.98837062624,0.899132811505,-3.69430731804,2,1,18 +2025-03-11T12:43:04.886215,479392985,735,246,1.64728445104,-0.616220906554998,-2.52987031209,2,1,18 +2025-03-11T12:43:05.011215,479392985,735,246,2.3203178578,-2.14082979725,-1.34687360739,2,1,18 +2025-03-11T12:43:05.136215,479392985,735,246,3.00747084652,-3.688544728415,-0.140624085675,2,1,18 +2025-03-11T12:43:05.261215,479392985,735,246,3.68991730792,-5.24086952861,1.051779231015,2,1,18 +2025-03-11T12:43:05.386215,479392985,735,246,4.367657242,-6.80242115378,2.262701495535,2,1,18 +2025-03-11T12:43:05.511215,479392985,735,246,5.0501037034,-8.363979865865,3.48749429883,2,1,18 +2025-03-11T12:43:05.636215,479392985,735,246,5.72784363748,-9.92091453509,4.70763246363,2,1,18 +2025-03-11T12:43:05.761215,479392985,735,246,6.42911620816,-11.491735506725,5.92789456833,2,1,18 +2025-03-11T12:43:05.886215,479392985,735,246,7.11626919688,-13.05791826167,7.13886154206,2,1,18 +2025-03-11T12:43:06.011154,479392989,731,247,7.78459607632,-14.58252006545,8.312607825,2,1,18 +2025-03-11T12:43:06.136154,479392989,731,247,8.44821642844,-16.08403000259,9.481602134445,2,1,18 +2025-03-11T12:43:06.261154,479392989,731,247,9.0977171986,-17.576284767095,10.636656862155,2,1,18 +2025-03-11T12:43:06.386154,479392989,731,247,9.74251144144,-19.040830709015,11.76845481456,2,1,18 +2025-03-11T12:43:06.511154,479392989,731,247,10.36377304768,-20.48687339258,12.87700390824,2,1,18 +2025-03-11T12:43:06.636154,479392989,731,247,10.9803281266,-21.882122473835,13.94831420682,2,1,18 +2025-03-11T12:43:06.761154,479392989,731,247,11.56393751428,-23.23576934318,15.005473836495,2,1,18 +2025-03-11T12:43:06.886154,479392989,731,247,12.15225342928,-24.55248765188,16.03472828181,2,1,18 +2025-03-11T12:43:07.011154,479392989,731,247,12.71703670768,-25.832234878445,17.00367559728,2,1,18 +2025-03-11T12:43:07.136154,479392989,731,247,13.24887429484,-27.047295113375,17.949110341065,2,1,18 +2025-03-11T12:43:07.261154,479392989,731,247,13.76188577272,-28.206923529305,18.871111743855,2,1,18 +2025-03-11T12:43:07.386154,479392989,731,247,14.24665808668,-29.31572290835,19.728102710805,2,1,18 +2025-03-11T12:43:07.511154,479392989,731,247,14.70789776404,-30.364466425535,20.520044762145,2,1,18 +2025-03-11T12:43:07.636154,479392989,731,247,15.13619175016,-31.330055127305,21.2883769068,2,1,18 +2025-03-11T12:43:07.761154,479392989,731,247,15.53624657236,-32.249431748135,22.00558330041,2,1,18 +2025-03-11T12:43:07.886154,479392989,731,247,15.91747528528,-33.09952568213,22.65770229864,2,1,18 +2025-03-11T12:43:08.011154,479392989,731,247,16.251638725,-33.884911363745,23.27241781095,2,1,18 +2025-03-11T12:43:08.136154,479392989,731,247,16.57168258276,-34.60102144544,23.826676232625,2,1,18 +2025-03-11T12:43:08.261154,479392989,731,247,16.8634872766,-35.243217710525,24.329662900755,2,1,18 +2025-03-11T12:43:08.386154,479392989,731,247,17.11763975188,-35.7837842495,24.76273096932,2,1,18 +2025-03-11T12:43:08.511154,479392989,731,247,17.32472695396,-36.268876447985,25.139963751405,2,1,18 +2025-03-11T12:43:08.636154,479392989,731,247,17.51298804676,-36.68930291558,25.438273120815,2,1,18 +2025-03-11T12:43:08.761154,479392989,731,247,17.64947733904,-37.00807839632,25.69435402956,2,1,18 +2025-03-11T12:43:08.886154,479392989,731,247,17.74360788544,-37.243684887815,25.88060348601,2,1,18 +2025-03-11T12:43:09.011154,479392989,731,247,17.82361884988,-37.41924969128,26.015684753355,2,1,18 +2025-03-11T12:43:09.136154,479392989,731,247,17.86127106844,-37.48394376983,26.062308097845,2,1,18 +2025-03-11T12:43:09.261154,479392989,731,247,17.87068412308,-37.488574899605,26.071593041085,2,1,18 +2025-03-11T12:43:09.386154,479392989,731,247,17.83773843184,-37.410037040135,26.001806298,2,1,18 +2025-03-11T12:43:09.511154,479392989,731,247,17.74360788544,-37.23906793187,25.875959035245,2,1,18 +2025-03-11T12:43:09.636154,479392989,731,247,17.62594470244,-36.980341226075,25.689536971395,2,1,18 +2025-03-11T12:43:09.761154,479392989,731,247,17.49416193748,-36.66157283225,25.41498578232,2,1,18 +2025-03-11T12:43:09.886154,479392989,731,247,17.310607372,-36.255004319405,25.07979866577,2,1,18 +2025-03-11T12:43:10.011001,479392993,721,248,17.10352016992,-35.75144429714,24.702468548685,2,1,18 +2025-03-11T12:43:10.136001,479392993,721,248,16.84936769464,-35.19702689033,24.255467127825,2,1,18 +2025-03-11T12:43:10.261001,479392993,721,248,16.57638911008,-34.554858972905,23.752521210615,2,1,18 +2025-03-11T12:43:10.386001,479392993,721,248,16.28458441624,-33.824940544865,23.193630797055,2,1,18 +2025-03-11T12:43:10.511001,479392993,721,248,15.93630139456,-33.030299690615,22.5926964051,2,1,18 +2025-03-11T12:43:10.636001,479392993,721,248,15.55977920896,-32.1663619757,21.91279389126,2,1,18 +2025-03-11T12:43:10.761001,479392993,721,248,15.16443091408,-31.237758529895,21.21402948594,2,1,18 +2025-03-11T12:43:10.886001,479392993,721,248,14.722017346,-30.249063787655,20.44092499233,2,1,18 +2025-03-11T12:43:11.011001,479392993,721,248,14.24195155936,-29.195674966865,19.63967762229,2,1,18 +2025-03-11T12:43:11.136001,479392993,721,248,13.74776619076,-28.08686141399,18.768805928835,2,1,18 +2025-03-11T12:43:11.261001,479392993,721,248,13.24416776752,-26.92724717189,17.85144501852,2,1,18 +2025-03-11T12:43:11.386001,479392993,721,248,12.70291712572,-25.689087983405,16.905868230525,2,1,18 +2025-03-11T12:43:11.511001,479392993,721,248,12.15225342928,-24.418595929475,15.90465932664,2,1,18 +2025-03-11T12:43:11.636001,479392993,721,248,11.58747015088,-23.097296099405,14.884671720255,2,1,18 +2025-03-11T12:43:11.761001,479392993,721,248,10.97562159928,-21.72513888479,13.83659386323,2,1,18 +2025-03-11T12:43:11.886001,479392993,721,248,10.35435999304,-20.325265760675,12.769869160185,2,1,18 +2025-03-11T12:43:12.011001,479392993,721,248,9.72368533216,-18.87920890328,11.642819222985,2,1,18 +2025-03-11T12:43:12.136001,479392993,721,248,9.09301067128,-17.41930117805,10.49259569946,2,1,18 +2025-03-11T12:43:12.261001,479392993,721,248,8.44821642844,-15.931670456405,9.3283352592,2,1,18 +2025-03-11T12:43:12.386001,479392993,721,248,7.78459607632,-14.430160519265,8.16396106677,2,1,18 +2025-03-11T12:43:12.511001,479392993,721,248,7.11156266956,-12.89631771668,6.97167546054,2,1,18 +2025-03-11T12:43:12.636001,479392993,721,248,6.42911620816,-11.34860987243,5.765436126555,2,1,18 +2025-03-11T12:43:12.761001,479392993,721,248,5.73725669212,-9.81012176624,4.55922508461,2,1,18 +2025-03-11T12:43:12.886001,479392993,721,248,5.0501037034,-8.24855596724,3.36676291269,2,1,18 +2025-03-11T12:43:13.011001,479392993,721,248,4.367657242,-6.668529431375,2.160353242455,2,1,18 +2025-03-11T12:43:13.136001,479392993,721,248,3.67579772596,-5.08848872168,0.958543313775,2,1,18 +2025-03-11T12:43:13.261001,479392993,721,248,3.0027643192,-3.53156113937,-0.23848407822,2,1,18 +2025-03-11T12:43:13.386001,479392993,721,248,2.32502438512,-1.99771124987,-1.44002010621,2,1,18 +2025-03-11T12:43:13.511001,479392993,721,248,1.66611056032,-0.477740575864999,-2.62296191397,2,1,18 +2025-03-11T12:43:13.636001,479392993,721,248,0.99778368088,1.04224427197,-3.792063746145,2,1,18 +2025-03-11T12:43:13.761001,479392993,721,248,0.33416332876,2.529903341275,-4.947124703295,2,1,18 +2025-03-11T12:43:13.886001,479392993,721,248,-0.291804804799999,3.957485287975,-6.064826883735,2,1,18 +2025-03-11T12:43:14.010956,479392997,718,249,-0.927185993,5.385081408505,-7.16868908859,2,1,18 +2025-03-11T12:43:14.135956,479392997,718,249,-1.54374107192,6.775713533815,-8.244595170435,2,1,18 +2025-03-11T12:43:14.260956,479392997,718,249,-2.13205698692,8.120133578185,-9.278615735265,2,1,18 +2025-03-11T12:43:14.385956,479392997,718,249,-2.7156663746,9.42761088808,-10.284710740275,2,1,18 +2025-03-11T12:43:14.510956,479392997,718,249,-3.26162354372,10.65654325159,-11.253349633575,2,1,18 +2025-03-11T12:43:14.635956,479392997,718,249,-3.7746350216,11.84387340319,-12.184737272895,2,1,18 +2025-03-11T12:43:14.760956,479392997,718,249,-4.30176608144,13.003523079865,-13.088288770815,2,1,18 +2025-03-11T12:43:14.885956,479392997,718,249,-4.78183186808,14.09846450416,-13.926716080725,2,1,18 +2025-03-11T12:43:15.010956,479392997,718,249,-5.22895196348,15.124101980875,-14.7416064852,2,1,18 +2025-03-11T12:43:15.135956,479392997,718,249,-5.6572459496,16.108158506425,-15.47769514575,2,1,18 +2025-03-11T12:43:15.260956,479392997,718,249,-6.0573007718,17.00445034753,-16.17629940255,2,1,18 +2025-03-11T12:43:15.385956,479392997,718,249,-6.4102903208,17.83141698031,-16.814375254605,2,1,18 +2025-03-11T12:43:15.510956,479392997,718,249,-6.75386681516,18.598349011975,-17.4059132223,2,1,18 +2025-03-11T12:43:15.635956,479392997,718,249,-7.06449761828,19.28674318417,-17.93690468094,2,1,18 +2025-03-11T12:43:15.760956,479392997,718,249,-7.33276967552,19.887351411175,-18.416520821595,2,1,18 +2025-03-11T12:43:15.885956,479392997,718,249,-7.56809604152,20.4186556906,-18.82177876965,2,1,18 +2025-03-11T12:43:16.010956,479392997,718,249,-7.76577018896,20.88988284742,-19.180437706965,2,1,18 +2025-03-11T12:43:16.135956,479392997,718,249,-7.93520517248,21.26872836385,-19.4461465026,2,1,18 +2025-03-11T12:43:16.260956,479392997,718,249,-8.07169446476,21.564419064865,-19.692865508565,2,1,18 +2025-03-11T12:43:16.385956,479392997,718,249,-8.17053153848,21.781564819495,-19.8651674667,2,1,18 +2025-03-11T12:43:16.510956,479392997,718,249,-8.23171639364,21.92016562774,-19.953812142975,2,1,18 +2025-03-11T12:43:16.635956,479392997,718,249,-8.25054250292,21.96636353485,-20.000297401545,2,1,18 +2025-03-11T12:43:16.760956,479392997,718,249,-8.222303339,21.952470145525,-19.97706268884,2,1,18 +2025-03-11T12:43:16.885956,479392997,718,249,-8.18935764776,21.846230550385,-19.907129943255,2,1,18 +2025-03-11T12:43:17.010956,479392997,718,249,-8.10934668332,21.64296401125,-19.76266243938,2,1,18 +2025-03-11T12:43:17.135956,479392997,718,249,-7.99639002764,21.36577656859,-19.543812409155,2,1,18 +2025-03-11T12:43:17.260956,479392997,718,249,-7.8457811534,21.01466113549,-19.25980989888,2,1,18 +2025-03-11T12:43:17.385956,479392997,718,249,-7.63869395132,20.584972408345,-18.919830057915,2,1,18 +2025-03-11T12:43:17.510956,479392997,718,249,-7.41278063996,20.058299258695,-18.51461681907,2,1,18 +2025-03-11T12:43:17.635956,479392997,718,249,-7.16804121932,19.457726466265,-18.06739243617,2,1,18 +2025-03-11T12:43:17.760956,479392997,718,249,-6.89035610744,18.82016841787,-17.54598019692,2,1,18 +2025-03-11T12:43:17.885956,479392997,718,249,-6.5514861404,18.085562164735,-16.963862987235,2,1,18 +2025-03-11T12:43:18.010925,479393001,716,250,-6.18908353676,17.28166613785,-16.348989013545,2,1,18 +2025-03-11T12:43:18.135925,479393001,716,250,-5.80785482384,16.40848742413,-15.669027644475,2,1,18 +2025-03-11T12:43:18.260925,479393001,716,250,-5.40780000164,15.447558199795,-14.93774189607,2,1,18 +2025-03-11T12:43:18.385925,479393001,716,250,-4.96067990624,14.42192072308,-14.1551923107,2,1,18 +2025-03-11T12:43:18.510925,479393001,716,250,-4.49944022888,13.35009242617,-13.33540788852,2,1,18 +2025-03-11T12:43:18.635925,479393001,716,250,-3.99113527832,12.24125761255,-12.464505631875,2,1,18 +2025-03-11T12:43:18.760925,479393001,716,250,-3.46400421848,11.063140112095,-11.542376330895,2,1,18 +2025-03-11T12:43:18.885925,479393001,716,250,-2.92275357668,9.838831791445,-10.57839207609,2,1,18 +2025-03-11T12:43:19.010925,479393001,716,250,-2.35797029828,8.535999785155,-9.576982272765,2,1,18 +2025-03-11T12:43:19.135925,479393001,716,250,-1.78377396524,7.205451869365,-8.543065272375,2,1,18 +2025-03-11T12:43:19.260925,479393001,716,250,-1.17663194096,5.82868478572,-7.490353152315,2,1,18 +2025-03-11T12:43:19.385925,479393001,716,250,-0.55537033472,4.43342861755,-6.400552197945,2,1,18 +2025-03-11T12:43:19.510925,479393001,716,250,0.0847173807999999,2.99197454227,-5.273506219035,2,1,18 +2025-03-11T12:43:19.635925,479393001,716,250,0.720098569,1.513591906345,-4.146275757855,2,1,18 +2025-03-11T12:43:19.760925,479393001,716,250,1.3790123938,0.0167060120650024,-2.97731596989,2,1,18 +2025-03-11T12:43:19.885925,479393001,716,250,2.04263274592,-1.503271748855,-1.789743857385,2,1,18 +2025-03-11T12:43:20.010925,479393001,716,250,2.70154657072,-3.037093290695,-0.59286869733,2,1,18 +2025-03-11T12:43:20.135925,479393001,716,250,3.39811261408,-4.589439351635,0.60880541658,2,1,18 +2025-03-11T12:43:20.260925,479393001,716,250,4.08055907548,-6.14176415183,1.8104489673,2,1,18 +2025-03-11T12:43:20.385925,479393001,716,250,4.77712511884,-7.71257803655,3.02146065024,2,1,18 +2025-03-11T12:43:20.510925,479393001,716,250,5.46898463488,-9.292618746245,4.21403034489,2,1,18 +2025-03-11T12:43:20.635925,479393001,716,250,6.14201804164,-10.849546328555,5.429538204945,2,1,18 +2025-03-11T12:43:20.760925,479393001,716,250,6.838584085,-12.401892389495,6.640452552885,2,1,18 +2025-03-11T12:43:20.885925,479393001,716,250,7.53515012836,-13.94962149449,7.823621864985,2,1,18 +2025-03-11T12:43:21.010925,479393001,716,250,8.18465089852,-15.478811906555,9.006591964785,2,1,18 +2025-03-11T12:43:21.135925,479393001,716,250,8.838858196,-16.980307669865,10.17556589877,2,1,18 +2025-03-11T12:43:21.260925,479393001,716,250,9.49306549348,-18.44025082967,11.335080594975,2,1,18 +2025-03-11T12:43:21.385925,479393001,716,250,10.12844668168,-19.90478259776,12.45761793789,2,1,18 +2025-03-11T12:43:21.510925,479393001,716,250,10.7450017606,-21.318499502795,13.533645688485,2,1,18 +2025-03-11T12:43:21.635925,479393001,716,250,11.3333176756,-22.672153459055,14.60005573992,2,1,18 +2025-03-11T12:43:21.760925,479393001,716,250,11.9216335906,-24.02119045937,15.629480521485,2,1,18 +2025-03-11T12:43:21.885925,479393001,716,250,12.50053645096,-25.31942677046,16.653997139325,2,1,18 +2025-03-11T12:43:22.010879,479393005,713,251,13.04178709276,-26.539118135165,17.60871682635,2,1,18 +2025-03-11T12:43:22.135879,479393005,713,251,13.55950509796,-27.72645537368,18.53087441937,2,1,18 +2025-03-11T12:43:22.260879,479393005,713,251,14.06781004852,-28.858374967025,19.40651846178,2,1,18 +2025-03-11T12:43:22.385879,479393005,713,251,14.54316930784,-29.944075392515,20.231026565415,2,1,18 +2025-03-11T12:43:22.510879,479393005,713,251,14.97616982128,-30.941989872815,21.013399585095,2,1,18 +2025-03-11T12:43:22.635879,479393005,713,251,15.39034422544,-31.89832340195,21.749311679955,2,1,18 +2025-03-11T12:43:22.760879,479393005,713,251,15.77627946568,-32.780743114475,22.42471178724,2,1,18 +2025-03-11T12:43:22.885879,479393005,713,251,16.13868206932,-33.57540522947,23.03953709343,2,1,18 +2025-03-11T12:43:23.010879,479393005,713,251,16.46813898172,-34.32384817661,23.60784657786,2,1,18 +2025-03-11T12:43:23.135879,479393005,713,251,16.75994367556,-34.984512265475,24.115550698005,2,1,18 +2025-03-11T12:43:23.260879,479393005,713,251,17.02350920548,-35.58049644962,24.57665184912,2,1,18 +2025-03-11T12:43:23.385879,479393005,713,251,17.24942251684,-36.09793568738,24.991056654495,2,1,18 +2025-03-11T12:43:23.510879,479393005,713,251,17.43297708232,-36.522972024005,25.33096122306,2,1,18 +2025-03-11T12:43:23.635879,479393005,713,251,17.5929990112,-36.892569454715,25.605841209765,2,1,18 +2025-03-11T12:43:23.760879,479393005,713,251,17.72007524884,-37.174395114065,25.80626566887,2,1,18 +2025-03-11T12:43:23.885879,479393005,713,251,17.80008621328,-37.363810785365,25.95528028851,2,1,18 +2025-03-11T12:43:24.010879,479393005,713,251,17.85656454112,-37.44238407941,26.03897832129,2,1,18 +2025-03-11T12:43:24.135879,479393005,713,251,17.85656454112,-37.474702771025,26.071489476645,2,1,18 +2025-03-11T12:43:24.260879,479393005,713,251,17.84244495916,-37.423894994885,26.034230306085,2,1,18 +2025-03-11T12:43:24.385879,479393005,713,251,17.80008621328,-37.280705578355,25.91788134489,2,1,18 +2025-03-11T12:43:24.510879,479393005,713,251,17.69183608492,-37.063545649895,25.75017912831,2,1,18 +2025-03-11T12:43:24.635879,479393005,713,251,17.5694663746,-36.777110121515,25.52663993811,2,1,18 +2025-03-11T12:43:24.760879,479393005,713,251,17.40944444572,-36.40289573486,25.224014915565,2,1,18 +2025-03-11T12:43:24.885879,479393005,713,251,17.2164768256,-35.959377400625,24.85627193445,2,1,18 +2025-03-11T12:43:25.010879,479393005,713,251,16.99056351424,-35.423470339085,24.451010028105,2,1,18 +2025-03-11T12:43:25.135879,479393005,713,251,16.70346534772,-34.78589811686,23.985018817575,2,1,18 +2025-03-11T12:43:25.260879,479393005,713,251,16.38812801728,-34.102113813695,23.44942138794,2,1,18 +2025-03-11T12:43:25.385879,479393005,713,251,16.05867110488,-33.335203042775,22.857913983435,2,1,18 +2025-03-11T12:43:25.510879,479393005,713,251,15.6868554466,-32.4943571945,22.20124391115,2,1,18 +2025-03-11T12:43:25.635879,479393005,713,251,15.310333261,-31.602717743915,21.507335043765,2,1,18 +2025-03-11T12:43:25.760879,479393005,713,251,14.87733274756,-30.64635586712,20.752901729925,2,1,18 +2025-03-11T12:43:25.885879,479393005,713,251,14.44433223412,-29.62073965115,19.9565223567,2,1,18 +2025-03-11T12:43:26.010818,479393009,709,252,13.96426644748,-28.52118127091,19.113450596025,2,1,18 +2025-03-11T12:43:26.135818,479393009,709,252,13.4512549696,-27.375403722815,18.237723364635,2,1,18 +2025-03-11T12:43:26.260818,479393009,709,252,12.92883043708,-26.160357661715,17.31078946437,2,1,18 +2025-03-11T12:43:26.385818,479393009,709,252,12.37816674064,-24.908333431565,16.337398597575,2,1,18 +2025-03-11T12:43:26.510818,479393009,709,252,11.81808998956,-23.61474242408,15.32680741545,2,1,18 +2025-03-11T12:43:26.635818,479393009,709,252,11.23448060188,-22.270329466625,14.278936687305,2,1,18 +2025-03-11T12:43:26.760818,479393009,709,252,10.63204510492,-20.912037293675,13.198611387885,2,1,18 +2025-03-11T12:43:26.885818,479393009,709,252,10.00607697136,-19.48907230292,12.108654243285,2,1,18 +2025-03-11T12:43:27.010818,479393009,709,252,9.36598925584,-18.033767359805,10.98615538014,2,1,18 +2025-03-11T12:43:27.135818,479393009,709,252,8.71178195836,-16.569207244055,9.826616350185,2,1,18 +2025-03-11T12:43:27.260818,479393009,709,252,8.04345507892,-15.053839352165,8.65753885176,2,1,18 +2025-03-11T12:43:27.385818,479393009,709,252,7.37042167216,-13.52923046147,7.48378238109,2,1,18 +2025-03-11T12:43:27.510818,479393009,709,252,6.70680132004,-12.004635744605,6.286945700805,2,1,18 +2025-03-11T12:43:27.635818,479393009,709,252,6.0384744406,-10.43848133732,5.085259712025,2,1,18 +2025-03-11T12:43:27.760818,479393009,709,252,5.34190839724,-8.8676674526,3.88810838013,2,1,18 +2025-03-11T12:43:27.885818,479393009,709,252,4.6500488812,-7.31071152263,2.663319535125,2,1,18 +2025-03-11T12:43:28.010818,479393009,709,252,3.9676024198,-5.7445358546,1.45698286614,2,1,18 +2025-03-11T12:43:28.135818,479393009,709,252,3.2851559584,-4.173743230625,0.22752127833,2,1,18 +2025-03-11T12:43:28.260818,479393009,709,252,2.59800296968,-2.63526221135,-0.96481922484,2,1,18 +2025-03-11T12:43:28.385818,479393009,709,252,1.92496956292,-1.09680245282,-2.15712916482,2,1,18 +2025-03-11T12:43:28.510818,479393009,709,252,1.27546879276,0.423154047355,-3.326190246075,2,1,18 +2025-03-11T12:43:28.635818,479393009,709,252,0.621261495280001,1.90156503094,-4.48580227728,2,1,18 +2025-03-11T12:43:28.760818,479393009,709,252,-0.04235885684,3.379990188355,-5.617713981855,2,1,18 +2025-03-11T12:43:28.885818,479393009,709,252,-0.68244657236,4.81682730769,-6.726255158955,2,1,18 +2025-03-11T12:43:29.010818,479393009,709,252,-1.3037081786,6.207466519915,-7.816031779575,2,1,18 +2025-03-11T12:43:29.135818,479393009,709,252,-1.89673062092,7.584212342815,-8.87333345346,2,1,18 +2025-03-11T12:43:29.260818,479393009,709,252,-2.47092695396,8.89167547888,-9.902508668085,2,1,18 +2025-03-11T12:43:29.385818,479393009,709,252,-3.0215906504,10.148316664975,-10.871303751615,2,1,18 +2025-03-11T12:43:29.510818,479393009,709,252,-3.55342823756,11.391078635575,-11.821504614915,2,1,18 +2025-03-11T12:43:29.635818,479393009,709,252,-4.08526582472,12.559969311055,-12.72049485105,2,1,18 +2025-03-11T12:43:29.760818,479393009,709,252,-4.56062508404,13.654903648435,-13.582012558305,2,1,18 +2025-03-11T12:43:29.885818,479393009,709,252,-5.0218647614,14.71288107751,-14.410964213265,2,1,18 +2025-03-11T12:43:30.010757,479393013,705,253,-5.45957180216,15.710802644725,-15.184107186645,2,1,18 +2025-03-11T12:43:30.135757,479393013,705,253,-5.869039679,16.62557648344,-15.88744927092,2,1,18 +2025-03-11T12:43:30.260757,479393013,705,253,-6.26438797388,17.498776457905,-16.553580852135,2,1,18 +2025-03-11T12:43:30.385757,479393013,705,253,-6.61737752288,18.288807443125,-17.159121215085,2,1,18 +2025-03-11T12:43:30.510757,479393013,705,253,-6.928008326,19.00490335099,-17.74107996339,2,1,18 +2025-03-11T12:43:30.635757,479393013,705,253,-7.20098691056,19.637837356525,-18.2439772131,2,1,18 +2025-03-11T12:43:30.760757,479393013,705,253,-7.4692589678,20.21997775975,-18.658814380545,2,1,18 +2025-03-11T12:43:30.885757,479393013,705,253,-7.68575922452,20.70970108801,-19.040711988855,2,1,18 +2025-03-11T12:43:31.010757,479393013,705,253,-7.85990073536,21.11163847108,-19.36199404515,2,1,18 +2025-03-11T12:43:31.135757,479393013,705,253,-8.00109655496,21.448888862515,-19.618182476625,2,1,18 +2025-03-11T12:43:31.260757,479393013,705,253,-8.11405321064,21.716842393285,-19.804643020245,2,1,18 +2025-03-11T12:43:31.385757,479393013,705,253,-8.18465112044,21.87392519914,-19.934986460115,2,1,18 +2025-03-11T12:43:31.510757,479393013,705,253,-8.21289028436,21.961689883585,-19.990951331925,2,1,18 +2025-03-11T12:43:31.635757,479393013,705,253,-8.23171639364,21.970952143135,-19.99566086736,2,1,18 +2025-03-11T12:43:31.760757,479393013,705,253,-8.20818375704,21.883194545605,-19.944326300295,2,1,18 +2025-03-11T12:43:31.885757,479393013,705,253,-8.13758584724,21.749196519475,-19.823344763205,2,1,18 +2025-03-11T12:43:32.010757,479393013,705,253,-8.0340422462,21.499724986315,-19.627761696015,2,1,18 +2025-03-11T12:43:32.135757,479393013,705,253,-7.89755295392,21.190183417465,-19.376349571785,2,1,18 +2025-03-11T12:43:32.260757,479393013,705,253,-7.71870491576,20.78823894748,-19.06429756179,2,1,18 +2025-03-11T12:43:32.385757,479393013,705,253,-7.516324241,20.298536879965,-18.696290867715,2,1,18 +2025-03-11T12:43:32.510757,479393013,705,253,-7.27629134768,19.72567291012,-18.27232326012,2,1,18 +2025-03-11T12:43:32.635757,479393013,705,253,-6.9750735992,19.10654725093,-17.792538470355,2,1,18 +2025-03-11T12:43:32.760757,479393013,705,253,-6.67385585072,18.408933340675,-17.24765836863,2,1,18 +2025-03-11T12:43:32.885757,479393013,705,253,-6.33498588368,17.623540572145,-16.646793019635,2,1,18 +2025-03-11T12:43:33.010757,479393013,705,253,-5.9631702254,16.77346081198,-15.985454162835,2,1,18 +2025-03-11T12:43:33.135757,479393013,705,253,-5.54899582124,15.844829018515,-15.29126912361,2,1,18 +2025-03-11T12:43:33.260757,479393013,705,253,-5.12070183512,14.851538581075,-14.522790976455,2,1,18 +2025-03-11T12:43:33.385757,479393013,705,253,-4.6688752124,13.807426193665,-13.703172932235,2,1,18 +2025-03-11T12:43:33.510757,479393013,705,253,-4.18410289844,12.712477682455,-12.84163484952,2,1,18 +2025-03-11T12:43:33.635757,479393013,705,253,-3.6805044752,11.552863440355,-11.94737452428,2,1,18 +2025-03-11T12:43:33.760757,479393013,705,253,-3.16278647,10.33782446617,-10.983489875625,2,1,18 +2025-03-11T12:43:33.885757,479393013,705,253,-2.5980031916,9.048843327715,-10.00063354161,2,1,18 +2025-03-11T12:43:34.010681,479393017,700,254,-2.01439380392,7.745982973765,-8.98532263632,2,1,18 +2025-03-11T12:43:34.135681,479393017,700,254,-1.4213713616,6.396938886535,-7.928166964935,2,1,18 +2025-03-11T12:43:34.260681,479393017,700,254,-0.81422933732,4.98323615533,-6.8521595898,2,1,18 +2025-03-11T12:43:34.385681,479393017,700,254,-0.178848149119999,3.54640612291,-5.739008483415,2,1,18 +2025-03-11T12:43:34.510681,479393017,700,254,0.47065262104,2.08647005002,-4.602604560015,2,1,18 +2025-03-11T12:43:34.635681,479393017,700,254,1.10603380924,0.594236546260001,-3.447580395495,2,1,18 +2025-03-11T12:43:34.760681,479393017,700,254,1.77436068868,-0.916514389684999,-2.283147347835,2,1,18 +2025-03-11T12:43:34.885681,479393017,700,254,2.4379810408,-2.436492150605,-1.090955118315,2,1,18 +2025-03-11T12:43:35.010681,479393017,700,254,3.1204275022,-3.9888169508,0.110688432404999,2,1,18 +2025-03-11T12:43:35.135681,479393017,700,254,3.80758049092,-5.54114883791,1.31696228787,2,1,18 +2025-03-11T12:43:35.260681,479393017,700,254,4.49473347964,-7.116565504745,2.514117578055,2,1,18 +2025-03-11T12:43:35.385681,479393017,700,254,5.17717994104,-8.66889030494,3.734241596835,2,1,18 +2025-03-11T12:43:35.510681,479393017,700,254,5.86433292976,-10.23969001583,4.94985302133,2,1,18 +2025-03-11T12:43:35.635681,479393017,700,254,6.52795328188,-11.801220380255,6.16074472266,2,1,18 +2025-03-11T12:43:35.760681,479393017,700,254,7.21981279792,-13.3350915305,7.34383084578,2,1,18 +2025-03-11T12:43:35.885681,479393017,700,254,7.90225925932,-14.859714595025,8.522227808925,2,1,18 +2025-03-11T12:43:36.010681,479393017,700,254,8.56587961144,-16.36584148811,9.677386101075,2,1,18 +2025-03-11T12:43:36.135681,479393017,700,254,9.21067385428,-17.853472209755,10.823166073275,2,1,18 +2025-03-11T12:43:36.260681,479393017,700,254,9.8507615698,-19.322628020705,11.978078756775,2,1,18 +2025-03-11T12:43:36.385681,479393017,700,254,10.48143623068,-20.75021705432,13.086550890915,2,1,18 +2025-03-11T12:43:36.510681,479393017,700,254,11.08857825496,-22.13160109391,14.148527578755,2,1,18 +2025-03-11T12:43:36.635681,479393017,700,254,11.70513333388,-23.471446703825,15.182584936215,2,1,18 +2025-03-11T12:43:36.760681,479393017,700,254,12.26991661228,-24.792746533895,16.2025725426,2,1,18 +2025-03-11T12:43:36.885681,479393017,700,254,12.82058030872,-26.063238587825,17.176060744395,2,1,18 +2025-03-11T12:43:37.010681,479393017,700,254,13.35241789588,-27.250597087085,18.116729368665,2,1,18 +2025-03-11T12:43:37.135681,479393017,700,254,13.8513097918,-28.405587286325,19.00633505541,2,1,18 +2025-03-11T12:43:37.260681,479393017,700,254,14.32666905112,-29.50513857965,19.867877096415,2,1,18 +2025-03-11T12:43:37.385681,479393017,700,254,14.80673483776,-30.53082566477,20.66435834694,2,1,18 +2025-03-11T12:43:37.510681,479393017,700,254,15.22561576924,-31.501017148655,21.414213981825,2,1,18 +2025-03-11T12:43:37.635681,479393017,700,254,15.63037711876,-32.41116694451,22.13600201268,2,1,18 +2025-03-11T12:43:37.760681,479393017,700,254,15.9927797224,-33.242764707065,22.774122573945,2,1,18 +2025-03-11T12:43:37.885681,479393017,700,254,16.33635621676,-34.005079782785,23.379496558935,2,1,18 +2025-03-11T12:43:38.010635,479393021,697,255,16.64228049256,-34.72578555968,23.92450851714,2,1,18 +2025-03-11T12:43:38.135635,479393021,697,255,16.9105525498,-35.3587124783,24.40891511106,2,1,18 +2025-03-11T12:43:38.260635,479393021,697,255,17.15058544312,-35.89002384464,24.83728383192,2,1,18 +2025-03-11T12:43:38.385635,479393021,697,255,17.37179222716,-36.342818612255,25.19127625587,2,1,18 +2025-03-11T12:43:38.510635,479393021,697,255,17.53652068336,-36.74012486555,25.494033134895,2,1,18 +2025-03-11T12:43:38.635635,479393021,697,255,17.65889039368,-37.04502821771,25.73153001114,2,1,18 +2025-03-11T12:43:38.760635,479393021,697,255,17.76243399472,-37.27603192709,25.89929504124,2,1,18 +2025-03-11T12:43:38.885635,479393021,697,255,17.84715148648,-37.419285125855,26.015735692005,2,1,18 +2025-03-11T12:43:39.010635,479393021,697,255,17.85656454112,-37.48855363886,26.071562477895,2,1,18 +2025-03-11T12:43:39.135635,479393021,697,255,17.86127106844,-37.48394376983,26.0484477468,2,1,18 +2025-03-11T12:43:39.260635,479393021,697,255,17.81420579524,-37.368449002055,25.978435770525,2,1,18 +2025-03-11T12:43:39.385635,479393021,697,255,17.74831441276,-37.174437635555,25.829427380325,2,1,18 +2025-03-11T12:43:39.510635,479393021,697,255,17.6400642844,-36.911108147645,25.615280656095,2,1,18 +2025-03-11T12:43:39.635635,479393021,697,255,17.48004235552,-36.56459549666,25.354382689185,2,1,18 +2025-03-11T12:43:39.760635,479393021,697,255,17.28236820808,-36.153388767125,25.02376079271,2,1,18 +2025-03-11T12:43:39.885635,479393021,697,255,17.06586795136,-35.64058065914,24.637121398635,2,1,18 +2025-03-11T12:43:40.010635,479393021,697,255,16.82583505804,-35.067716689295,24.19467332298,2,1,18 +2025-03-11T12:43:40.135635,479393021,697,255,16.53873689152,-34.407059687345,23.69159950758,2,1,18 +2025-03-11T12:43:40.260635,479393021,697,255,16.2281060884,-33.677112911645,23.118807992055,2,1,18 +2025-03-11T12:43:40.385635,479393021,697,255,15.88452959404,-32.88247914431,22.49016308574,2,1,18 +2025-03-11T12:43:40.510635,479393021,697,255,15.49388782648,-32.01852016865,21.814850125725,2,1,18 +2025-03-11T12:43:40.635635,479393021,697,255,15.075006895,-31.07141346449,21.08359662765,2,1,18 +2025-03-11T12:43:40.760635,479393021,697,255,14.6514194362,-30.068896202075,20.30121964968,2,1,18 +2025-03-11T12:43:40.885635,479393021,697,255,14.19017975884,-29.006301817055,19.467623543955,2,1,18 +2025-03-11T12:43:41.010635,479393021,697,255,13.6865813356,-27.865155398735,18.610421489835,2,1,18 +2025-03-11T12:43:41.135635,479393021,697,255,13.17356985772,-26.67320829119,17.688249750795,2,1,18 +2025-03-11T12:43:41.260635,479393021,697,255,12.63702574324,-25.458140969345,16.74280481928,2,1,18 +2025-03-11T12:43:41.385635,479393021,697,255,12.05341635556,-24.192216262955,15.741548935035,2,1,18 +2025-03-11T12:43:41.510635,479393021,697,255,11.4745134952,-22.87089517214,14.716910648445,2,1,18 +2025-03-11T12:43:41.635635,479393021,697,255,10.87207799824,-21.47566735163,13.654871147085,2,1,18 +2025-03-11T12:43:41.760635,479393021,697,255,10.24140333736,-20.057312229905,12.56030803149,2,1,18 +2025-03-11T12:43:41.885635,479393021,697,255,9.6154352038,-18.629730283205,11.45184608508,2,1,18 +2025-03-11T12:43:42.010574,479393025,693,256,8.97064096096,-17.16056738534,10.292303096835,2,1,18 +2025-03-11T12:43:42.135574,479393025,693,256,8.31643366348,-15.67753944581,9.14190696591,2,1,18 +2025-03-11T12:43:42.260574,479393025,693,256,7.65751983868,-14.157568771805,7.945104807105,2,1,18 +2025-03-11T12:43:42.385574,479393025,693,256,6.99389948656,-12.61450623116,6.762031142865,2,1,18 +2025-03-11T12:43:42.510574,479393025,693,256,6.31145302516,-11.06679838691,5.57427227694,2,1,18 +2025-03-11T12:43:42.635574,479393025,693,256,5.6148869818,-9.4867505903,4.358591809485,2,1,18 +2025-03-11T12:43:42.760574,479393025,693,256,4.91361441112,-7.915929618665,3.147569938815,2,1,18 +2025-03-11T12:43:42.885574,479393025,693,256,4.23116794972,-6.368221774415,1.92285013677,2,1,18 +2025-03-11T12:43:43.010574,479393025,693,256,3.55342801564,-4.78358536952,0.72104643753,2,1,18 +2025-03-11T12:43:43.135574,479393025,693,256,2.88039460888,-3.240508655045,-0.4712878362,2,1,18 +2025-03-11T12:43:43.260574,479393025,693,256,2.1791220382,-1.69738941908,-1.66368323631,2,1,18 +2025-03-11T12:43:43.385574,479393025,693,256,1.50608863144,-0.168163572439999,-2.842084157745,2,1,18 +2025-03-11T12:43:43.510574,479393025,693,256,0.847174806640001,1.33795623373,-4.006472496195,2,1,18 +2025-03-11T12:43:43.635574,479393025,693,256,0.19296750916,2.807133305425,-5.161415742885,2,1,18 +2025-03-11T12:43:43.760574,479393025,693,256,-0.44241367904,4.25781420568,-6.28388008455,2,1,18 +2025-03-11T12:43:43.885574,479393025,693,256,-1.06367528528,5.68077210952,-7.359966690375,2,1,18 +2025-03-11T12:43:44.010574,479393025,693,256,-1.67081730956,7.048305281275,-8.431110610995,2,1,18 +2025-03-11T12:43:44.135574,479393025,693,256,-2.2685462792,8.37888863164,-9.483559018095,2,1,18 +2025-03-11T12:43:44.260574,479393025,693,256,-2.81920997564,9.67708242124,-10.489534041495,2,1,18 +2025-03-11T12:43:44.385574,479393025,693,256,-3.35575409012,10.9244684347,-11.430529192245,2,1,18 +2025-03-11T12:43:44.510574,479393025,693,256,-3.88759167728,12.107209978015,-12.35731313172,2,1,18 +2025-03-11T12:43:44.635574,479393025,693,256,-4.39589662784,13.234512615415,-13.246793191425,2,1,18 +2025-03-11T12:43:44.760574,479393025,693,256,-4.86184283252,14.30634799924,-14.066587801335,2,1,18 +2025-03-11T12:43:44.885574,479393025,693,256,-5.29484334596,15.318113347375,-14.87213440734,2,1,18 +2025-03-11T12:43:45.010574,479393025,693,256,-5.71372427744,16.283687875315,-15.5988651234,2,1,18 +2025-03-11T12:43:45.135574,479393025,693,256,-6.09965951768,17.17534149973,-16.26969378117,2,1,18 +2025-03-11T12:43:45.260574,479393025,693,256,-6.48559475792,18.002357740915,-16.907840947335,2,1,18 +2025-03-11T12:43:45.385574,479393025,693,256,-6.80563861568,18.741552602335,-17.48994173985,2,1,18 +2025-03-11T12:43:45.510574,479393025,693,256,-7.09744330952,19.406833647145,-18.025390895835,2,1,18 +2025-03-11T12:43:45.635574,479393025,693,256,-7.36571536676,19.99820796226,-18.472617549885,2,1,18 +2025-03-11T12:43:45.760574,479393025,693,256,-7.60574826008,20.5295193286,-18.8871259197,2,1,18 +2025-03-11T12:43:45.885574,479393025,693,256,-7.78459629824,20.98225031398,-19.23178642005,2,1,18 diff --git a/imap_processing/tests/mag/validation/L1c/T024/mag-l1b-l1c-t024-magi-normal-out.csv b/imap_processing/tests/mag/validation/L1c/T024/mag-l1b-l1c-t024-magi-normal-out.csv new file mode 100644 index 0000000000..032ea96c71 --- /dev/null +++ b/imap_processing/tests/mag/validation/L1c/T024/mag-l1b-l1c-t024-magi-normal-out.csv @@ -0,0 +1,687 @@ +t,x,y,z,interp +2025-03-11 12:38:02.500,-7.5974498381915225,20.52915100616049,-18.810491316353644,True +2025-03-11 12:38:03.000,-8.15121351807476,21.75399710868527,-19.750455816872694,True +2025-03-11 12:38:03.500,-8.121413623111255,21.676324312266527,-19.69303241802073,True +2025-03-11 12:38:04.000,-7.523208928591237,20.316344368391707,-18.63031298767716,True +2025-03-11 12:38:04.500,-6.38407506948762,17.71231310197274,-16.610960767700632,True +2025-03-11 12:38:05.000,-4.761178353522875,13.977604663474239,-13.718859466081772,True +2025-03-11 12:38:05.500,-2.6891811898762907,9.289171770583298,-10.095132411254273,True +2025-03-11 12:38:06.000,-0.30623935828097015,3.844786907857575,-5.871135607260987,True +2025-03-11 12:38:06.500,2.2964858274729147,-2.0971072535999142,-1.2694439818458112,True +2025-03-11 12:38:07.000,5.021782066620676,-8.30450831317167,3.5533617008708562,True +2025-03-11 12:38:07.500,7.737556556045811,-14.495851890225541,8.345403143981713,True +2025-03-11 12:38:08.000,10.322529858085613,-20.373528502427245,12.896417789797749,True +2025-03-11 12:38:08.500,12.650813534885044,-25.68498040913448,17.01394293937608,True +2025-03-11 12:38:09.000,14.653503994212844,-30.225439230383422,20.514106503784532,True +2025-03-11 12:38:09.500,16.210681847239183,-33.75551037302372,23.25730576612781,True +2025-03-11 12:38:10.000,17.273198244073775,-36.13827324303241,25.109386307594217,True +2025-03-11 12:38:10.500,17.7835592660233,-37.28769542504499,25.989280408422474,True +2025-03-11 12:38:11.000,17.71209185336956,-37.114292936010244,25.856397707480802,True +2025-03-11 12:38:11.500,17.086874957527673,-35.64351825003212,24.72440848181263,True +2025-03-11 12:38:12.000,15.8897285296912,-32.94480207406829,22.638212845448752,True +2025-03-11 12:38:12.500,14.222705432696667,-29.12771323079869,19.671876467218624,True +2025-03-11 12:38:13.000,12.12880442083993,-24.375809627596063,15.989930297236851,True +2025-03-11 12:38:13.500,9.732154717021283,-18.88925274389048,11.723586739534541,True +2025-03-11 12:38:14.000,7.107296128813716,-12.899136283939493,7.092686436755526,True +2025-03-11 12:38:14.500,4.375096250656173,-6.691130283670234,2.28670497143628,True +2025-03-11 12:38:15.000,1.668698863707044,-0.5291867805033768,-2.502155734641479,True +2025-03-11 12:38:15.500,-0.9007461186780871,5.310946041424332,-7.0202358061901124,True +2025-03-11 12:38:16.000,-3.21915652988436,10.580683686033826,-11.090878216925061,True +2025-03-11 12:38:16.500,-5.177148150726174,15.036550333954327,-14.558083163942854,True +2025-03-11 12:38:17.000,-6.711738426875964,18.506099296900846,-17.24459967047254,True +2025-03-11 12:38:17.500,-7.731108139434885,20.786669017826313,-19.019139052530008,True +2025-03-11 12:38:18.000,-8.201257515868999,21.826535175350177,-19.81850749854673,True +2025-03-11 12:38:18.500,-8.092152596131845,21.58067754084435,-19.610995737869636,True +2025-03-11 12:38:19.000,-7.4087024676435,20.022768021019402,-18.407548234724732,True +2025-03-11 12:38:19.500,-6.184528695546571,17.2275583410261,-16.24786181203997,True +2025-03-11 12:38:20.000,-4.501228080631886,13.331795956907536,-13.225862391549063,True +2025-03-11 12:38:20.500,-2.387844414539602,8.506477662883952,-9.499285399203549,True +2025-03-11 12:38:21.000,0.035842839857668035,2.9694835585410893,-5.210979222834523,True +2025-03-11 12:38:21.500,2.669603665204762,-3.0340779415474413,-0.5538905220883024,True +2025-03-11 12:38:22.000,5.396682712827658,-9.241756057714998,4.247359673985569,True +2025-03-11 12:38:22.500,8.088409601403209,-15.377311412739887,9.015932879501982,True +2025-03-11 12:38:23.000,10.638244049472915,-21.21639193301497,13.521631465057638,True +2025-03-11 12:38:23.500,12.937599205301629,-26.43586902622794,17.5803880367904,True +2025-03-11 12:38:24.000,14.870186479329876,-30.821077283245156,20.997940401305012,True +2025-03-11 12:38:24.500,16.37270196532035,-34.18879489507616,23.607318774672038,True +2025-03-11 12:38:25.000,17.348133482672857,-36.39248162725082,25.30227076971917,True +2025-03-11 12:38:25.500,17.769858729262197,-37.34120502395258,26.031983549652676,True +2025-03-11 12:38:26.000,17.61277575016894,-36.96712000655053,25.737860957767317,True +2025-03-11 12:38:26.500,16.88479665759655,-35.30491459996916,24.453144176398755,True +2025-03-11 12:38:27.000,15.623920397950311,-32.41795853574927,22.213601828765412,True +2025-03-11 12:38:27.500,13.888561156804311,-28.452290578905853,19.142505317026234,True +2025-03-11 12:38:28.000,11.751783444469062,-23.58487062776951,15.373633019369292,True +2025-03-11 12:38:28.500,9.309479375424692,-18.009357140858633,11.045872357403828,True +2025-03-11 12:38:29.000,6.661405337418074,-11.97961441273152,6.383912437940822,True +2025-03-11 12:38:29.500,3.9335697668898923,-5.761377216920815,1.5609490812405056,True +2025-03-11 12:38:30.000,1.235853508635898,0.3828814716924042,-3.193632814839659,True +2025-03-11 12:38:30.500,-1.307132390583965,6.157498447898412,-7.670615508680615,True +2025-03-11 12:38:31.000,-3.575475227100667,11.31884055738373,-11.672151431886615,True +2025-03-11 12:38:31.500,-5.476078666125059,15.640229172538199,-15.02377052266865,True +2025-03-11 12:38:32.000,-6.926577895796847,18.92009529648842,-17.57509048226937,True +2025-03-11 12:38:32.500,-7.854355516189658,21.041250332859384,-19.209512214530783,True +2025-03-11 12:38:33.000,-8.22117216034908,21.894054277353252,-19.86487409405348,True +2025-03-11 12:38:33.500,-8.032471793649904,21.421208522645674,-19.500496440465458,True +2025-03-11 12:38:34.000,-7.271186215147173,19.66701739789589,-18.145315423308176,True +2025-03-11 12:38:34.500,-5.971285661629636,16.70747911156519,-15.849398459509127,True +2025-03-11 12:38:35.000,-4.207226808853207,12.677780523941498,-12.716342176996235,True +2025-03-11 12:38:35.500,-2.040768577823909,7.726344301518096,-8.899290461087705,True +2025-03-11 12:38:36.000,0.4304169794254158,2.0968502513714147,-4.537767121081721,True +2025-03-11 12:38:36.500,3.084147448059361,-3.9478348398057426,0.17064637111442685,True +2025-03-11 12:38:37.000,5.8158518510884605,-10.173521592898132,4.979082392274662,True +2025-03-11 12:38:37.500,8.504733776649553,-16.288548304738384,9.710043652162685,True +2025-03-11 12:38:38.000,11.029194064723391,-22.03542007406432,14.161204345009622,True +2025-03-11 12:38:38.500,13.278862986558124,-27.138291476988847,18.120823163947595,True +2025-03-11 12:38:39.000,15.142038242732232,-31.38134363850783,21.411892722105694,True +2025-03-11 12:38:39.500,16.555730119983835,-34.59314759871816,23.90513850067407,True +2025-03-11 12:38:40.000,17.44538756703927,-36.61723288417107,25.460876767629316,True +2025-03-11 12:38:40.500,17.776840151778014,-37.35774817820339,26.036461423707166,True +2025-03-11 12:38:41.000,17.53148530628526,-36.79864745717028,25.601890119312483,True +2025-03-11 12:38:41.500,16.72215929463301,-34.956722472414754,24.184292806224807,True +2025-03-11 12:38:42.000,15.396222727950512,-31.914109090453035,21.824268639138452,True +2025-03-11 12:38:42.500,13.608502505944884,-27.797760163605485,18.61581484322728,True +2025-03-11 12:38:43.000,11.420496228252508,-22.806062402873692,14.745594675671363,True +2025-03-11 12:38:43.500,8.927141866076946,-17.145910975494846,10.360373520232969,True +2025-03-11 12:38:44.000,6.276605328695349,-11.069182677793316,5.644513199726755,True +2025-03-11 12:38:44.500,3.5404480814492136,-4.833411872012617,0.8250677229653918,True +2025-03-11 12:38:45.000,0.8664185006725339,1.258849611110696,-3.889144470355345,True +2025-03-11 12:38:45.500,-1.6447131665326082,6.970126949862356,-8.30353251433025,True +2025-03-11 12:38:46.000,-3.8599158991738576,12.00979260401502,-12.230138229323119,True +2025-03-11 12:38:46.500,-5.6928367472967,16.18834195833622,-15.481385949050296,True +2025-03-11 12:38:47.000,-7.084894592176187,19.30868872873649,-17.898333796722948,True +2025-03-11 12:38:47.500,-7.936429310590306,21.24498467313455,-19.391506452842656,True +2025-03-11 12:38:48.000,-8.228294980572787,21.891800818502563,-19.889343580656433,True +2025-03-11 12:38:48.500,-7.930977677412591,21.222034012143364,-19.37013399605351,True +2025-03-11 12:38:49.000,-7.092564690990263,19.283146477300026,-17.869389030799955,True +2025-03-11 12:38:49.500,-5.733564365099591,16.166252634943515,-15.44127627006588,True +2025-03-11 12:38:50.000,-3.8916960965646283,11.972544409670935,-12.202733483256264,True +2025-03-11 12:38:50.500,-1.6781044580056532,6.9276962718125334,-8.290649523157649,True +2025-03-11 12:38:51.000,0.8255738418941468,1.2213082322493671,-3.849404960146236,True +2025-03-11 12:38:51.500,3.5022748901849776,-4.871463331518434,0.8768315426521717,True +2025-03-11 12:38:52.000,6.240460757869602,-11.095068611732085,5.686983810120747,True +2025-03-11 12:38:52.500,8.905030741897178,-17.18164596002559,10.399548627749759,True +2025-03-11 12:38:53.000,11.387980513740668,-22.846031380060737,14.785137003704914,True +2025-03-11 12:38:53.500,13.588639067613437,-27.834096904843793,18.647284889205665,True +2025-03-11 12:38:54.000,15.4048271773991,-31.95407706398851,21.825065192664567,True +2025-03-11 12:38:54.500,16.736272426915278,-34.99072911130536,24.190654089463564,True +2025-03-11 12:38:55.000,17.554809692202564,-36.81785670280432,25.60934366600164,True +2025-03-11 12:38:55.500,17.806688354863887,-37.37163466247919,26.03941450979525,True +2025-03-11 12:38:56.000,17.49116436270176,-36.62632034084375,25.46037106289435,True +2025-03-11 12:38:56.500,16.59566349967447,-34.59345532790523,23.890376074537677,True +2025-03-11 12:38:57.000,15.194551638641416,-31.377803958351933,21.392660082516294,True +2025-03-11 12:38:57.500,13.327496548358809,-27.117134510839264,18.092496761788105,True +2025-03-11 12:38:58.000,11.078984373168678,-21.99489128107067,14.126034429829547,True +2025-03-11 12:38:58.500,8.556929361841737,-16.25491569072281,9.677017063954944,True +2025-03-11 12:38:59.000,5.871344040914744,-10.133143320356712,4.9362605950035325,True +2025-03-11 12:38:59.500,3.139900104620728,-3.9046129432867467,0.10347936771728625,True +2025-03-11 12:39:00.000,0.4776581391807266,2.151612525414534,-4.603625049405249,True +2025-03-11 12:39:00.500,-2.0061239844786916,7.762182583539936,-8.939903235944438,True +2025-03-11 12:39:01.000,-4.1706698734090955,12.693327747533758,-12.760753805211884,True +2025-03-11 12:39:01.500,-5.949697540212718,16.712797381006656,-15.886366745421832,True +2025-03-11 12:39:02.000,-7.248202400850363,19.674156434629683,-18.18542826831783,True +2025-03-11 12:39:02.500,-8.011064280146611,21.42108549446353,-19.536499342649535,True +2025-03-11 12:39:03.000,-8.21367074678162,21.870429258869674,-19.86997891779857,True +2025-03-11 12:39:03.500,-7.859482028874295,21.004695828104893,-19.216340600845147,True +2025-03-11 12:39:04.000,-6.940580983696209,18.89179355373997,-17.57810465929299,True +2025-03-11 12:39:04.500,-5.504024053961409,15.603854965002276,-15.026974327355292,True +2025-03-11 12:39:05.000,-3.5981802782748495,11.28368706146825,-11.671552223810883,True +2025-03-11 12:39:05.500,-1.3241646276443175,6.107747772261053,-7.655863323977697,True +2025-03-11 12:39:06.000,1.2091368089221033,0.33183705249831214,-3.179056986000065,True +2025-03-11 12:39:06.500,3.9081418160390373,-5.803509254680154,1.565408983819336,True +2025-03-11 12:39:07.000,6.644011306003155,-12.028561852772125,6.395630799398707,True +2025-03-11 12:39:07.500,9.290318720288363,-18.061284248326324,11.079568590438974,True +2025-03-11 12:39:08.000,11.73581400987139,-23.630906795505773,15.394367230011484,True +2025-03-11 12:39:08.500,13.875410485603737,-28.490127082502376,19.16127873403907,True +2025-03-11 12:39:09.000,15.615437730107287,-32.45434105757707,22.22351132583766,True +2025-03-11 12:39:09.500,16.888625608847146,-35.33376210245354,24.451525092260418,True +2025-03-11 12:39:10.000,17.622042264009266,-36.98118686910866,25.726239483772826,True +2025-03-11 12:39:10.500,17.789385428008508,-37.34398373079969,26.01097563514326,True +2025-03-11 12:39:11.000,17.380002964517,-36.39193270581172,25.285581773258322,True +2025-03-11 12:39:11.500,16.41037334254383,-34.1872492217924,23.56216243071385,True +2025-03-11 12:39:12.000,14.941349304028451,-30.80713241575966,20.926911466298275,True +2025-03-11 12:39:12.500,13.009185421281806,-26.40580224902317,17.518222317889645,True +2025-03-11 12:39:13.000,10.718124710060383,-21.171687733691986,13.474596839339359,True +2025-03-11 12:39:13.500,8.182086561234167,-15.364748339779515,8.97570504044474,True +2025-03-11 12:39:14.000,5.476408205090859,-9.209896513369937,4.197770029282446,True +2025-03-11 12:39:14.500,2.7474974786499753,-2.9945984226237616,-0.6104808396178428,True +2025-03-11 12:39:15.000,0.11172425926786105,3.0037361608869464,-5.261473309265801,True +2025-03-11 12:39:15.500,-2.3290705327751446,8.541818072099888,-9.551084464345,True +2025-03-11 12:39:16.000,-4.45481411825175,13.362366099057974,-13.286301435790152,True +2025-03-11 12:39:16.500,-6.165514114827286,17.237893533732624,-16.295157518481076,True +2025-03-11 12:39:17.000,-7.394179766969181,20.022570119068668,-18.439696835607002,True +2025-03-11 12:39:17.500,-8.067958086205003,21.567540903384238,-19.640113391607457,True +2025-03-11 12:39:18.000,-8.195005005231447,21.828427630989356,-19.845711222102402,True +2025-03-11 12:39:18.500,-7.748131038464577,20.793158286718587,-19.027082407901922,True +2025-03-11 12:39:19.000,-6.740399501290359,18.482672108745987,-17.234752390001947,True +2025-03-11 12:39:19.500,-5.218651791994748,15.027188832182402,-14.54906559227215,True +2025-03-11 12:39:20.000,-3.2627289507695982,10.562417557174395,-11.094852452749109,True +2025-03-11 12:39:20.500,-0.9536943401755551,5.287466676712005,-7.012325846115859,True +2025-03-11 12:39:21.000,1.6100726293195198,-0.5568568444890688,-2.4851812630239842,True +2025-03-11 12:39:21.500,4.310594980965485,-6.721592038529875,2.2981907016108734,True +2025-03-11 12:39:22.000,7.044693343764492,-12.939224834484845,7.112042768206064,True +2025-03-11 12:39:22.500,9.665320188028618,-18.92689677900009,11.744316050385152,True +2025-03-11 12:39:23.000,12.09091036001904,-24.41290187984996,16.004591589613618,True +2025-03-11 12:39:23.500,14.184666580217968,-29.169403027863588,19.689529909364307,True +2025-03-11 12:39:24.000,15.86124153432828,-32.98198756779859,22.63769277059483,True +2025-03-11 12:39:24.500,17.0473385423166,-35.66666184392824,24.718380761127463,True +2025-03-11 12:39:25.000,17.702517851895543,-37.11708522670848,25.83589061734443,True +2025-03-11 12:39:25.500,17.781910679848185,-37.284810183814166,25.961315966249146,True +2025-03-11 12:39:26.000,17.29265427727301,-36.1480186054043,25.06672879039746,True +2025-03-11 12:39:26.500,16.239080507243536,-33.75274797600133,23.218560769924373,True +2025-03-11 12:39:27.000,14.672279980833832,-30.20698439688018,20.476243793782803,True +2025-03-11 12:39:27.500,12.68909249874007,-25.657887343016608,16.968668930997598,True +2025-03-11 12:39:28.000,10.359094223370512,-20.333252415137334,12.838185968979904,True +2025-03-11 12:39:28.500,7.7813661968732735,-14.451636024667627,8.279492593063244,True +2025-03-11 12:39:29.000,5.06502253332842,-8.285840316104286,3.4800863394741697,True +2025-03-11 12:39:29.500,2.34530865412084,-2.088423033113067,-1.3183838468045344,True +2025-03-11 12:39:30.000,-0.2750600144477708,3.8628417458423923,-5.922382945228382,True +2025-03-11 12:39:30.500,-2.6664383142979857,9.300427044329329,-10.145588182131378,True +2025-03-11 12:39:31.000,-4.730515882810448,14.003567890029771,-13.775345317523467,True +2025-03-11 12:39:31.500,-6.369570998192788,17.728746483215968,-16.651482175114534,True +2025-03-11 12:39:32.000,-7.517509388845106,20.323063694714378,-18.66336668708218,True +2025-03-11 12:39:32.500,-8.125817460179682,21.679645622780317,-19.729119155199587,True +2025-03-11 12:39:33.000,-8.16952969822148,21.743971300813833,-19.779211725148162,True +2025-03-11 12:39:33.500,-7.636967541314547,20.516428090120762,-18.82065962870871,True +2025-03-11 12:39:34.000,-6.549941061116819,18.044876171388882,-16.890769497969753,True +2025-03-11 12:39:34.500,-4.951912822428884,14.413115855843422,-14.096592928834523,True +2025-03-11 12:39:35.000,-2.9379569502928997,9.822054986143758,-10.518155163309329,True +2025-03-11 12:39:35.500,-0.5826170971012156,4.449698865124263,-6.358859242077145,True +2025-03-11 12:39:36.000,2.022151046054576,-1.463344981097529,-1.7704690075676155,True +2025-03-11 12:39:36.500,4.734960377169723,-7.6603781866782,3.0271318600641957,True +2025-03-11 12:39:37.000,7.4530918942737685,-13.862837446528205,7.8276130718009025,True +2025-03-11 12:39:37.500,10.060239619702593,-19.780661761445003,12.425610605200866,True +2025-03-11 12:39:38.000,12.433153627971274,-25.182162010693652,16.605070443842685,True +2025-03-11 12:39:38.500,14.47179901065138,-29.80725215890135,20.17381169023343,True +2025-03-11 12:39:39.000,16.07453380597073,-33.444427871249324,23.005833617942365,True +2025-03-11 12:39:39.500,17.182547627390363,-35.95507421397726,24.950170194185922,True +2025-03-11 12:39:40.000,17.751060168567754,-37.22195557458365,25.929782105580763,True +2025-03-11 12:39:40.500,17.733765214224203,-37.1967222611432,25.911762138251582,True +2025-03-11 12:39:41.000,17.147865336566568,-35.8676926569247,24.86952015128539,True +2025-03-11 12:39:41.500,16.02209095478627,-33.29010193922731,22.873246765740387,True +2025-03-11 12:39:42.000,14.388857059752846,-29.599606763014886,20.001302803777637,True +2025-03-11 12:39:42.500,12.348169836502215,-24.922714315237872,16.382781306920748,True +2025-03-11 12:39:43.000,9.959524206118246,-19.483966643419993,12.180376403383596,True +2025-03-11 12:39:43.500,7.356195975567253,-13.543593598515484,7.566590866834087,True +2025-03-11 12:39:44.000,4.6509062118632185,-7.355477730817753,2.7655923596162166,True +2025-03-11 12:39:44.500,1.9376712530649303,-1.1700957374563998,-2.0229306514292444,True +2025-03-11 12:39:45.000,-0.6480379603328749,4.722546505720976,-6.595560214782207,True +2025-03-11 12:39:45.500,-3.0030052221654464,10.063108753890294,-10.730829891084609,True +2025-03-11 12:39:46.000,-4.999454820547966,14.61043325543601,-14.251310048994775,True +2025-03-11 12:39:46.500,-6.582599543620671,18.18446075681925,-17.013341476807263,True +2025-03-11 12:39:47.000,-7.654632288783832,20.61822205135972,-18.896467185385603,True +2025-03-11 12:39:47.500,-8.178875340652828,21.794237078239323,-19.812319999315804,True +2025-03-11 12:39:48.000,-8.128123053692597,21.659075476751816,-19.711900139549073,True +2025-03-11 12:39:48.500,-7.4986547440057505,20.22994776043104,-18.607260072386914,True +2025-03-11 12:39:49.000,-6.343838218784374,17.57265962040486,-16.538122965196862,True +2025-03-11 12:39:49.500,-4.7048416758113625,13.792273711000234,-13.596930810632468,True +2025-03-11 12:39:50.000,-2.6338038212920356,9.047642985210448,-9.922581259554727,True +2025-03-11 12:39:50.500,-0.22748231275405267,3.5685853395917553,-5.6926894100217496,True +2025-03-11 12:39:51.000,2.3967842640649324,-2.393304156770507,-1.0796785369246313,True +2025-03-11 12:39:51.500,5.116557618747399,-8.598154410832917,3.7319603005607265,True +2025-03-11 12:39:52.000,7.827041198843343,-14.762375875081315,8.511431489760552,True +2025-03-11 12:39:52.500,10.41107701799482,-20.621107982630818,13.057702820833875,True +2025-03-11 12:39:53.000,12.734688486434777,-25.917057722086444,17.15594479382728,True +2025-03-11 12:39:53.500,14.715971772566604,-30.406211491733263,20.635256030449863,True +2025-03-11 12:39:54.000,16.25232040175499,-33.89649938055104,23.338385711442378,True +2025-03-11 12:39:54.500,17.276120125850618,-36.237162615603395,25.13705100729221,True +2025-03-11 12:39:55.000,17.75467649632658,-37.31427226725614,25.973354580432687,True +2025-03-11 12:39:55.500,17.66042152042559,-37.08261673256546,25.801667407541085,True +2025-03-11 12:39:56.000,17.01258006992865,-35.56095971363346,24.602835285146636,True +2025-03-11 12:39:56.500,15.813598561337045,-32.808518996958625,22.471387494963945,True +2025-03-11 12:39:57.000,14.125589276238195,-28.947226048545037,19.476664472388354,True +2025-03-11 12:39:57.500,12.018044596292917,-24.152137722046252,15.767798244605546,True +2025-03-11 12:39:58.000,9.601776610526294,-18.64570731172161,11.496582882998455,True +2025-03-11 12:39:58.500,6.968870319295407,-12.643112913682923,6.851291820201032,True +2025-03-11 12:39:59.000,4.242405104071861,-6.42150875033219,2.0380273983810886,True +2025-03-11 12:39:59.500,1.5442185321939517,-0.2661048675028665,-2.729343280710806,True +2025-03-11 12:40:00.000,-1.01852794598804,5.554365645701535,-7.2530916269577,True +2025-03-11 12:40:00.500,-3.318002989554208,10.79429468373994,-11.304487751066693,True +2025-03-11 12:40:01.000,-5.275120585685693,15.220192718824375,-14.72314728975548,True +2025-03-11 12:40:01.500,-6.7800839810133695,18.638595118220696,-17.363902516606686,True +2025-03-11 12:40:02.000,-7.7748577039236455,20.882617518437545,-19.087376175478724,True +2025-03-11 12:40:02.500,-8.207438404183604,21.835705725631097,-19.844289282564738,True +2025-03-11 12:40:03.000,-8.062714033730323,21.513034529897766,-19.600272275230765,True +2025-03-11 12:40:03.500,-7.357927050762957,19.899727787529347,-18.346089504907248,True +2025-03-11 12:40:04.000,-6.120832714448122,17.06887451572176,-16.141343845876907,True +2025-03-11 12:40:04.500,-4.399402448187908,13.13069289479311,-13.10586925801381,True +2025-03-11 12:40:05.000,-2.2639825876021544,8.288518622822739,-9.347710784573614,True +2025-03-11 12:40:05.500,0.17737602350869608,2.719862184464399,-5.034556535007723,True +2025-03-11 12:40:06.000,2.8293975617973697,-3.3070696478023867,-0.36246118235135344,True +2025-03-11 12:40:06.500,5.552282665482872,-9.525779454661404,4.467812545420144,True +2025-03-11 12:40:07.000,8.25548635730811,-15.655785373312595,9.221405467946212,True +2025-03-11 12:40:07.500,10.798158087096322,-21.44370694378934,13.697829166667292,True +2025-03-11 12:40:08.000,13.077196375720144,-26.64244151123635,17.71212286474656,True +2025-03-11 12:40:08.500,14.990535367636639,-30.99159549812853,21.09264160964538,True +2025-03-11 12:40:09.000,16.456381761386904,-34.32368282639563,23.657087474230174,True +2025-03-11 12:40:09.500,17.391102440813064,-36.47078602695346,25.326804832827374,True +2025-03-11 12:40:10.000,17.787367244095833,-37.36120707795767,26.025987673702016,True +2025-03-11 12:40:10.500,17.605438767786996,-36.93315337153157,25.696194908005324,True +2025-03-11 12:40:11.000,16.86509083179273,-35.218442278247984,24.37342701081341,True +2025-03-11 12:40:11.500,15.589500572199222,-32.30016306655765,22.090757945879048,True +2025-03-11 12:40:12.000,13.829678109454866,-28.289369736897523,18.984234859625246,True +2025-03-11 12:40:12.500,11.682792167103887,-23.390793180481907,15.172866652171336,True +2025-03-11 12:40:13.000,9.226757311902562,-17.784960877800906,10.821422871631084,True +2025-03-11 12:40:13.500,6.5724710938283835,-11.740325072973597,6.139452121623528,True +2025-03-11 12:40:14.000,3.8376809882877536,-5.508644352003875,1.3224251178462345,True +2025-03-11 12:40:14.500,1.1534047553554847,0.6215097645212366,-3.427960377626365,True +2025-03-11 12:40:15.000,-1.3658403622566953,6.376516911201769,-7.899506889581097,True +2025-03-11 12:40:15.500,-3.621166019515634,11.505831161037118,-11.874192553675345,True +2025-03-11 12:40:16.000,-5.502458896892492,15.78353492965668,-15.176272279960157,True +2025-03-11 12:40:16.500,-6.930164782316475,19.017773450140943,-17.6916270669144,True +2025-03-11 12:40:17.000,-7.835808078049909,21.0848741095203,-19.287878836580006,True +2025-03-11 12:40:17.500,-8.190461916205924,21.869495143347045,-19.891041710800092,True +2025-03-11 12:40:18.000,-7.972146488967251,21.35776398216929,-19.49006163516705,True +2025-03-11 12:40:18.500,-7.189316112673998,19.54057868307259,-18.077154714919498,True +2025-03-11 12:40:19.000,-5.882240025249782,16.54475836587877,-15.752631181946022,True +2025-03-11 12:40:19.500,-4.097585423075865,12.466126923358027,-12.588601656162052,True +2025-03-11 12:40:20.000,-1.9119999877607676,7.493750888154545,-8.7354549631298,True +2025-03-11 12:40:20.500,0.5669182408999979,1.8583508104888589,-4.363883668474154,True +2025-03-11 12:40:21.000,3.2110468111493295,-4.227402349032525,0.3359936506503917,True +2025-03-11 12:40:21.500,5.941523094569883,-10.44850366844517,5.172408374633045,True +2025-03-11 12:40:22.000,8.631526205888973,-16.555148355438348,9.894848108876865,True +2025-03-11 12:40:22.500,11.1412472330032,-22.27153815300221,14.317569472462802,True +2025-03-11 12:40:23.000,13.392302732498301,-27.361045344568662,18.246097216416736,True +2025-03-11 12:40:23.500,15.242263042315791,-31.556519193547963,21.518440777105127,True +2025-03-11 12:40:24.000,16.620643972655344,-34.71038386855186,23.96289438036749,True +2025-03-11 12:40:24.500,17.493163435073814,-36.68219329259597,25.493208144757137,True +2025-03-11 12:40:25.000,17.807556232319257,-37.366901241763316,26.015176790082684,True +2025-03-11 12:40:25.500,17.5427520112472,-36.7513935462299,25.54303275241967,True +2025-03-11 12:40:26.000,16.724136857693463,-34.86324447281484,24.070046536276884,True +2025-03-11 12:40:26.500,15.365035241202257,-31.7701012127484,21.680012409853408,True +2025-03-11 12:40:27.000,13.535739959695006,-27.60740799968067,18.459724899798267,True +2025-03-11 12:40:27.500,11.323200545800118,-22.56787104233643,14.55421326984856,True +2025-03-11 12:40:28.000,8.83594308323724,-16.89004243807484,10.134797001733267,True +2025-03-11 12:40:28.500,6.165795337059549,-10.795132935976868,5.413421782324871,True +2025-03-11 12:40:29.000,3.427012432599206,-4.565923374456629,0.5873059764299409,True +2025-03-11 12:40:29.500,0.7469434072971015,1.5324645005431612,-4.133459032272272,True +2025-03-11 12:40:30.000,-1.7478199403146717,7.204559550149507,-8.541191895414325,True +2025-03-11 12:40:30.500,-3.9377739979174264,12.22788081498887,-12.42656126115212,True +2025-03-11 12:40:31.000,-5.768030344291913,16.36344419161903,-15.61199540718308,True +2025-03-11 12:40:31.500,-7.117031845289558,19.436843491187698,-17.986451333635667,True +2025-03-11 12:40:32.000,-7.952814384408103,21.322970991212628,-19.440349434281103,True +2025-03-11 12:40:32.500,-8.216825539625512,21.902880493966876,-19.88982982956888,True +2025-03-11 12:40:33.000,-7.90112056783853,21.168674343207904,-19.335277868384136,True +2025-03-11 12:40:33.500,-7.025262221315952,19.18411746928212,-17.79486320574965,True +2025-03-11 12:40:34.000,-5.6362982460244835,16.017329811097575,-15.336420451521525,True +2025-03-11 12:40:34.500,-3.7921180815806785,11.766921433519018,-12.052727235254686,True +2025-03-11 12:40:35.000,-1.5642801513861453,6.679576094891459,-8.107779431610375,True +2025-03-11 12:40:35.500,0.9518218405474639,0.9610522748171552,-3.6628960376161803,True +2025-03-11 12:40:36.000,3.632487817079403,-5.1469217731387245,1.0668848828183932,True +2025-03-11 12:40:36.500,6.3585518130687255,-11.368441246087492,5.890149995252977,True +2025-03-11 12:40:37.000,9.030057880895841,-17.4385649958808,10.596052537084187,True +2025-03-11 12:40:37.500,11.508994407339324,-23.075600864163448,14.965858400532301,True +2025-03-11 12:40:38.000,13.711481460765729,-28.042655405945037,18.813255123608634,True +2025-03-11 12:40:38.500,15.494919858655807,-32.114088767042,21.95403180744831,True +2025-03-11 12:40:39.000,16.795269340656308,-35.08528737357904,24.268745587631315,True +2025-03-11 12:40:39.500,17.57653487198226,-36.85593891479773,25.650228659163318,True +2025-03-11 12:40:40.000,17.80603307037745,-37.37005220341312,26.02848452906991,True +2025-03-11 12:40:40.500,17.450507272058605,-36.54843843975041,25.38443159387665,True +2025-03-11 12:40:41.000,16.535571770910177,-34.481483143750786,23.78276637796592,True +2025-03-11 12:40:41.500,15.093660894394754,-31.209844844135834,21.254763947909385,True +2025-03-11 12:40:42.000,13.22407530408317,-26.903479726688396,17.92553232696024,True +2025-03-11 12:40:42.500,10.983840298428605,-21.765976167254305,13.937108413343822,True +2025-03-11 12:40:43.000,8.455263769481645,-15.996428763026838,9.461945276347627,True +2025-03-11 12:40:43.500,5.774545932263398,-9.856272888634035,4.709799156969971,True +2025-03-11 12:40:44.000,3.052050624412892,-3.6381758200737164,-0.11224815526915315,True +2025-03-11 12:40:44.500,0.3978968464286128,2.3924860357831874,-4.794814311894848,True +2025-03-11 12:40:45.000,-2.0653554578054254,7.980997698480323,-9.137369847412074,True +2025-03-11 12:40:45.500,-4.227243809016286,12.887242452875313,-12.931385830273953,True +2025-03-11 12:40:46.000,-5.9639828013246285,16.878808399342546,-16.015281851631602,True +2025-03-11 12:40:46.500,-7.242442857629922,19.776954333828968,-18.246182682903278,True +2025-03-11 12:40:47.000,-7.98878478396477,21.4610578107039,-19.554081131490037,True +2025-03-11 12:40:47.500,-8.174903513399604,21.85733383252701,-19.858361033888173,True +2025-03-11 12:40:48.000,-7.793129475500503,20.951699525889683,-19.155680930258153,True +2025-03-11 12:40:48.500,-6.842862989424278,18.784767840479976,-17.483016219286544,True +2025-03-11 12:40:49.000,-5.3705582825995375,15.43594035838496,-14.886716195487805,True +2025-03-11 12:40:49.500,-3.462518520244156,11.071410060325398,-11.492292338365164,True +2025-03-11 12:40:50.000,-1.1819553039267239,5.8547781253299735,-7.4583180547352494,True +2025-03-11 12:40:50.500,1.3624388703130719,0.0515755567410702,-2.9693213906112748,True +2025-03-11 12:40:51.000,4.061475037452768,-6.095993861239166,1.7866819754524907,True +2025-03-11 12:40:51.500,6.784452009672097,-12.316759617238791,6.6158210644293955,True +2025-03-11 12:40:52.000,9.429705545889428,-18.333229594615347,11.281813138011737,True +2025-03-11 12:40:52.500,11.874696738640639,-23.881223938123533,15.572785231092189,True +2025-03-11 12:40:53.000,14.010034485063372,-28.72338302527326,19.325419873933352,True +2025-03-11 12:40:53.500,15.737489235039742,-32.634831416637354,22.3531912764076,True +2025-03-11 12:40:54.000,16.98094064279955,-35.44494220979901,24.52832116730658,True +2025-03-11 12:40:54.500,17.69053136800854,-37.04321564366082,25.755649184442483,True +2025-03-11 12:40:55.000,17.823626769501097,-37.33217386181693,25.997105870008436,True +2025-03-11 12:40:55.500,17.388203326122127,-36.32250026586843,25.20725360064404,True +2025-03-11 12:40:56.000,16.388134565757206,-34.04992330133297,23.459899117327577,True +2025-03-11 12:40:56.500,14.885761051595946,-30.62324204762148,20.801123489456174,True +2025-03-11 12:40:57.000,12.941169178436018,-26.195304908981768,17.35346188355357,True +2025-03-11 12:40:57.500,10.64438937000992,-20.94763907054401,13.283998395043424,True +2025-03-11 12:40:58.000,8.085184763761957,-15.105198509024108,8.755212125740957,True +2025-03-11 12:40:58.500,5.374619491543273,-8.9441372830754,3.9908971043484067,True +2025-03-11 12:40:59.000,2.6374771902703866,-2.7347610788928196,-0.8337068518161339,True +2025-03-11 12:40:59.500,0.006386487526811958,3.2584921929934274,-5.454976091584506,True +2025-03-11 12:41:00.000,-2.403694033692114,8.767330441924997,-9.720918346994857,True +2025-03-11 12:41:00.500,-4.501651893016118,13.542676007151162,-13.430711644061946,True +2025-03-11 12:41:01.000,-6.198405126583844,17.38170133469427,-16.41404480713769,True +2025-03-11 12:41:01.500,-7.397651486438325,20.099805811809556,-18.52011143720294,True +2025-03-11 12:41:02.000,-8.07574935459969,21.607949031104063,-19.676976520712643,True +2025-03-11 12:41:02.500,-8.161597052217024,21.798709720214177,-19.83593488759351,True +2025-03-11 12:41:03.000,-7.69981015952241,20.694169883777054,-18.9814986996135,True +2025-03-11 12:41:03.500,-6.670917677317044,18.34137841487356,-17.158839042035883,True +2025-03-11 12:41:04.000,-5.133906612285132,14.836150594465101,-14.444653263431263,True +2025-03-11 12:41:04.500,-3.1515103169662755,10.33569476860602,-10.954283935101778,True +2025-03-11 12:41:05.000,-0.8203517791524211,5.022875688500425,-6.843935738479204,True +2025-03-11 12:41:05.500,1.7506058767671453,-0.8476929636776922,-2.305613734983779,True +2025-03-11 12:41:06.000,4.448469629904427,-7.010194489187516,2.483244507570091,True +2025-03-11 12:41:06.500,7.190096095124172,-13.200098448194046,7.308201102329765,True +2025-03-11 12:41:07.000,9.81997597178143,-19.16765261548968,11.933840423267188,True +2025-03-11 12:41:07.500,12.210448388910972,-24.63985005245171,16.156845805410374,True +2025-03-11 12:41:08.000,14.288212812095132,-29.36331194406337,19.822802311750788,True +2025-03-11 12:41:08.500,15.944714993740373,-33.11368519939628,22.74253802251907,True +2025-03-11 12:41:09.000,17.122734421962626,-35.77278192938267,24.78374079171896,True +2025-03-11 12:41:09.500,17.751970961943986,-37.16775019893906,25.861045053563345,True +2025-03-11 12:41:10.000,17.79405623884761,-37.26082250964595,25.937249085139513,True +2025-03-11 12:41:10.500,17.260542886601243,-36.06777211633861,25.00034505507483,True +2025-03-11 12:41:11.000,16.20499998177215,-33.61894160191163,23.113528924964843,True +2025-03-11 12:41:11.500,14.641397802716684,-30.02889914468927,20.334525446285152,True +2025-03-11 12:41:12.000,12.630026610316376,-25.449663195889414,16.784781679687814,True +2025-03-11 12:41:12.500,10.275086617866174,-20.1022052178329,12.640432749828875,True +2025-03-11 12:41:13.000,7.69614632124399,-14.209966626809246,8.059012263446862,True +2025-03-11 12:41:13.500,4.967805717333856,-8.023030738368302,3.2649379896180415,True +2025-03-11 12:41:14.000,2.240820562420686,-1.8147497667726618,-1.5356113217489815,True +2025-03-11 12:41:14.500,-0.364578566098134,4.117768585805133,-6.129977178082882,True +2025-03-11 12:41:15.000,-2.739561534637557,9.52332166604867,-10.328338196040459,True +2025-03-11 12:41:15.500,-4.77879305677001,14.164660992012703,-13.928977700085294,True +2025-03-11 12:41:16.000,-6.396287555722914,17.826699500222702,-16.769527787084893,True +2025-03-11 12:41:16.500,-7.532510725370725,20.38969975478831,-18.738682747380395,True +2025-03-11 12:41:17.000,-8.115153138090601,21.696111474774412,-19.74400842362748,True +2025-03-11 12:41:17.500,-8.11939866560823,21.705162263792857,-19.757942048540038,True +2025-03-11 12:41:18.000,-7.553702473153703,20.41574330958046,-18.762509346448653,True +2025-03-11 12:41:18.500,-6.441035914671345,17.88680669810955,-16.801045354114024,True +2025-03-11 12:41:19.000,-4.832798372176095,14.197402783876095,-13.958263537233528,True +2025-03-11 12:41:19.500,-2.813363545796184,9.559888953506318,-10.362634329668232,True +2025-03-11 12:41:20.000,-0.4325469986726295,4.167358343750581,-6.1706938690141095,True +2025-03-11 12:41:20.500,2.1724985330375834,-1.764042894383349,-1.581163065966946,True +2025-03-11 12:41:21.000,4.88175920278739,-7.957480368623788,3.213085400631948,True +2025-03-11 12:41:21.500,7.591376157892003,-14.131525637426556,8.006618893351641,True +2025-03-11 12:41:22.000,10.181019311527642,-20.038394521150504,12.588219586121955,True +2025-03-11 12:41:22.500,12.54042985060084,-25.399389826250633,16.74168619779137,True +2025-03-11 12:41:23.000,14.565791847078517,-29.985254272126078,20.300082617184923,True +2025-03-11 12:41:23.500,16.152143679327434,-33.59075755607822,23.094106970228385,True +2025-03-11 12:41:24.000,17.231896169436965,-36.04607112375093,24.999151213074924,True +2025-03-11 12:41:24.500,17.779729348957304,-37.26370025316685,25.935675654872018,True +2025-03-11 12:41:25.000,17.744368087134127,-37.183931365312006,25.852891612325582,True +2025-03-11 12:41:25.500,17.140429690558204,-35.78730278576522,24.776499991248986,True +2025-03-11 12:41:26.000,16.003578738053584,-33.155801423533376,22.736773735527063,True +2025-03-11 12:41:26.500,14.355463708445013,-29.402768159422113,19.831440212414275,True +2025-03-11 12:41:27.000,12.287467911369228,-24.6993413723604,16.181004338350288,True +2025-03-11 12:41:27.500,9.891659875739636,-19.268721171811485,11.961667017491886,True +2025-03-11 12:41:28.000,7.2789312283848995,-13.303649854561925,7.34611088575993,True +2025-03-11 12:41:28.500,4.543790603814055,-7.09934255360363,2.5361041948245817,True +2025-03-11 12:41:29.000,1.8354181521621529,-0.9156335197206259,-2.2504709379701646,True +2025-03-11 12:41:29.500,-0.7450318311177393,4.954772523904032,-6.811703638849054,True +2025-03-11 12:41:30.000,-3.0817955359571423,10.274155198854162,-10.921076690906037,True +2025-03-11 12:41:30.500,-5.060719858110734,14.786612438933293,-14.42171400924371,True +2025-03-11 12:41:31.000,-6.614023007296799,18.303788848397414,-17.154916985961254,True +2025-03-11 12:41:31.500,-7.66848708514646,20.66897788197019,-18.983505745965143,True +2025-03-11 12:41:32.000,-8.164866843035858,21.788188975767675,-19.84335764226465,True +2025-03-11 12:41:32.500,-8.095197066320486,21.603630569069978,-19.69654028472114,True +2025-03-11 12:41:33.000,-7.4587101903358,20.11529929410338,-18.539900490372954,True +2025-03-11 12:41:33.500,-6.267586190505668,17.403239252736203,-16.43841919436481,True +2025-03-11 12:41:34.000,-4.578383001584261,13.58267553985177,-13.469394383035404,True +2025-03-11 12:41:34.500,-2.488293512471868,8.819600670142997,-9.760051086069483,True +2025-03-11 12:41:35.000,-0.0828909704943424,3.313719811127587,-5.511934932707378,True +2025-03-11 12:41:35.500,2.5550076408271223,-2.6743573474991194,-0.877580803998346,True +2025-03-11 12:41:36.000,5.287196746132221,-8.892807888377941,3.938872065027457,True +2025-03-11 12:41:36.500,7.986438828816917,-15.04300801746344,8.723903862993566,True +2025-03-11 12:41:37.000,10.553133266692623,-20.887666883694074,13.237145587411522,True +2025-03-11 12:41:37.500,12.873526968707491,-26.15227109296532,17.301549340178195,True +2025-03-11 12:41:38.000,14.840809299881414,-30.61541587378417,20.749420811547576,True +2025-03-11 12:41:38.500,16.346753673193728,-34.042404328747686,23.416167092435696,True +2025-03-11 12:41:39.000,17.350438684606736,-36.31303603003082,25.187002717419503,True +2025-03-11 12:41:39.500,17.814260230736938,-37.33432495220909,25.975429040893072,True +2025-03-11 12:41:40.000,17.690740530708,-37.06051504098396,25.75527513977141,True +2025-03-11 12:41:40.500,17.00666724804446,-35.4781936868084,24.529531844520946,True +2025-03-11 12:41:41.000,15.782196210023717,-32.674633859983715,22.338629815932144,True +2025-03-11 12:41:41.500,14.076084386229848,-28.773224435717843,19.309374342378938,True +2025-03-11 12:41:42.000,11.96454216948571,-23.946766576904714,15.558961948684129,True +2025-03-11 12:41:42.500,9.528378111624066,-18.394098617423513,11.273640752635188,True +2025-03-11 12:41:43.000,6.896810740586002,-12.38272405836965,6.629446187878349,True +2025-03-11 12:41:43.500,4.148992523796543,-6.161969995469791,1.8045228450133721,True +2025-03-11 12:41:44.000,1.4541533870738141,-0.004521070534138333,-2.9557317032207147,True +2025-03-11 12:41:44.500,-1.0905471928251458,5.787758603706923,-7.449696804152623,True +2025-03-11 12:41:45.000,-3.3839183682572087,10.99440154158816,-11.484199867064437,True +2025-03-11 12:41:45.500,-5.301178639808753,15.375830800400317,-14.864386028968134,True +2025-03-11 12:41:46.000,-6.795405286450313,18.741008694862323,-17.46788475992418,True +2025-03-11 12:41:46.500,-7.762011791978751,20.91952607288793,-19.163368593388082,True +2025-03-11 12:41:47.000,-8.176586637025915,21.843261142710947,-19.868980511779395,True +2025-03-11 12:41:47.500,-8.017165484843114,21.452981150457347,-19.5734213027889,True +2025-03-11 12:41:48.000,-7.280170456530885,19.773703716174367,-18.27205282884161,True +2025-03-11 12:41:48.500,-6.020695378829445,16.886063455751522,-16.032475442305948,True +2025-03-11 12:41:49.000,-4.27092806307226,12.915511581398835,-12.94629951962434,True +2025-03-11 12:41:49.500,-2.1352960908637804,8.030971629898795,-9.160664128211783,True +2025-03-11 12:41:50.000,0.32268378377455825,2.442983191419315,-4.821288222994928,True +2025-03-11 12:41:50.500,2.9763460373822244,-3.5827167724218802,-0.14073167570750728,True +2025-03-11 12:41:51.000,5.70623101017939,-9.807621425000796,4.672174848355051,True +2025-03-11 12:41:51.500,8.40010606105106,-15.935009385245364,9.4186040097614,True +2025-03-11 12:41:52.000,10.937552919859902,-21.703352788479933,13.871503946938555,True +2025-03-11 12:41:52.500,13.201604385040747,-26.842055199406683,17.850361298184314,True +2025-03-11 12:41:53.000,15.096324361889929,-31.16679110918079,21.19046949738954,True +2025-03-11 12:41:53.500,16.540079606467447,-34.43070170700091,23.7274694767269,True +2025-03-11 12:41:54.000,17.480594724642227,-36.550497864411625,25.3613956090146,True +2025-03-11 12:41:54.500,17.84514050445595,-37.374747908017504,26.004207191630783,True +2025-03-11 12:41:55.000,17.638846070126128,-36.89166386388262,25.627247483878982,True +2025-03-11 12:41:55.500,16.87279802098157,-35.14590220176454,24.25586854149343,True +2025-03-11 12:41:56.000,15.57684409836013,-32.1647022099524,21.94504558374593,True +2025-03-11 12:41:56.500,13.80360522346668,-28.0977865701179,18.801615431884393,True +2025-03-11 12:41:57.000,11.629120686726294,-23.151415145712196,14.964656045033863,True +2025-03-11 12:41:57.500,9.164067690442685,-17.516586446534642,10.611657255633196,True +2025-03-11 12:41:58.000,6.50280168332476,-11.449102779359059,5.908253968224411,True +2025-03-11 12:41:58.500,3.7669581734739723,-5.233883925717794,1.0837499680695062,True +2025-03-11 12:41:59.000,1.081911228943454,0.8735183058099782,-3.659031346500682,True +2025-03-11 12:41:59.500,-1.4360620888496745,6.6028672168555635,-8.091654322148388,True +2025-03-11 12:42:00.000,-3.6746962530398344,11.713532676422894,-12.0364222450317,True +2025-03-11 12:42:00.500,-5.541800588232485,15.95026290255788,-15.319211061667737,True +2025-03-11 12:42:01.000,-6.953620280023771,19.143531099853014,-17.794687137982617,True +2025-03-11 12:42:01.500,-7.838773711079311,21.14237163534038,-19.351751158700992,True +2025-03-11 12:42:02.000,-8.166157886134801,21.860523491031575,-19.922879171411953,True +2025-03-11 12:42:02.500,-7.923865557984644,21.290255664963652,-19.466641125866815,True +2025-03-11 12:42:03.000,-7.1160795352511865,19.431762907270258,-18.0085896845042,True +2025-03-11 12:42:03.500,-5.788152468656102,16.361887106042403,-15.645283170737105,True +2025-03-11 12:42:04.000,-3.9734669819803106,12.238713909982614,-12.447762546936989,True +2025-03-11 12:42:04.500,-1.788743905871572,7.231544853912997,-8.564454819985885,True +2025-03-11 12:42:05.000,0.7058347699325441,1.559605826834079,-4.176046662947697,True +2025-03-11 12:42:05.500,3.3838454989055826,-4.53430634872019,0.5414830338522418,True +2025-03-11 12:42:06.000,6.122348828181617,-10.776435048967834,5.364962458332528,True +2025-03-11 12:42:06.500,8.80096795987277,-16.856251453073924,10.08261501928294,True +2025-03-11 12:42:07.000,11.306547317043956,-22.53940928023046,14.50586727684195,True +2025-03-11 12:42:07.500,13.516947672365994,-27.580395245511,18.399651813251126,True +2025-03-11 12:42:08.000,15.349120565609553,-31.736167722291594,21.624125040585078,True +2025-03-11 12:42:08.500,16.72445974154108,-34.85570179024048,24.03033907823064,True +2025-03-11 12:42:09.000,17.569178184974025,-36.76826233136363,25.506517436032535,True +2025-03-11 12:42:09.500,17.84934142738341,-37.383028972733946,25.996907232369182,True +2025-03-11 12:42:10.000,17.556588928519158,-36.69777876128624,25.47947847763787,True +2025-03-11 12:42:10.500,16.694149916597393,-34.74911243859994,23.956660971727192,True +2025-03-11 12:42:11.000,15.312665880992256,-31.598848523882914,21.517312132606634,True +2025-03-11 12:42:11.500,13.470288801155448,-27.39278204976314,18.271591190178853,True +2025-03-11 12:42:12.000,11.241784154652635,-22.33084389579011,14.331108080791033,True +2025-03-11 12:42:12.500,8.738339392004981,-16.62076665687726,9.911694572346242,True +2025-03-11 12:42:13.000,6.069612461154988,-10.529687753437418,5.181994857603824,True +2025-03-11 12:42:13.500,3.325980201484156,-4.311829452465117,0.36730586569437684,True +2025-03-11 12:42:14.000,0.65683970142927,1.76431502547082,-4.344202236293467,True +2025-03-11 12:42:14.500,-1.820555670663485,7.417987766637673,-8.727082766012805,True +2025-03-11 12:42:15.000,-4.0138867211428115,12.408573528088503,-12.57775032987609,True +2025-03-11 12:42:15.500,-5.810774312139258,16.504480940175824,-15.750495925556333,True +2025-03-11 12:42:16.000,-7.159547605142684,19.524676411456813,-18.084349543937563,True +2025-03-11 12:42:16.500,-7.969166312975494,21.32909050351838,-19.478797888085307,True +2025-03-11 12:42:17.000,-8.214570563540567,21.876357504932944,-19.892078381066607,True +2025-03-11 12:42:17.500,-7.868056264460592,21.105790203043853,-19.302601040657215,True +2025-03-11 12:42:18.000,-6.97251121535461,19.064416257245206,-17.715468000043867,True +2025-03-11 12:42:18.500,-5.570074484986411,15.839921783901666,-15.207109921977995,True +2025-03-11 12:42:19.000,-3.6961870611937977,11.564461401214873,-11.885433370395269,True +2025-03-11 12:42:19.500,-1.4582131786950798,6.443214362742423,-7.93356974999311,True +2025-03-11 12:42:20.000,1.0680229998033688,0.6995165874528646,-3.477425395634377,True +2025-03-11 12:42:20.500,3.765056422798973,-5.4147355595857345,1.2578269088191965,True +2025-03-11 12:42:21.000,6.508751824369006,-11.647332460224465,6.078881650057975,True +2025-03-11 12:42:21.500,9.167816905435206,-17.71091969684951,10.773919144881079,True +2025-03-11 12:42:22.000,11.630591539306174,-23.308814490663316,15.124048555022675,True +2025-03-11 12:42:22.500,13.786414335478334,-28.23502821670066,18.953953189605503,True +2025-03-11 12:42:23.000,15.574910389678157,-32.261425324261175,22.061125497861433,True +2025-03-11 12:42:23.500,16.867640324386535,-35.182824756647825,24.334488785749496,True +2025-03-11 12:42:24.000,17.620576248176373,-36.89960016496865,25.677778977741973,True +2025-03-11 12:42:24.500,17.824176860926308,-37.33927017240537,25.99385955309367,True +2025-03-11 12:42:25.000,17.443716832536946,-36.47628552202959,25.309183776227744,True +2025-03-11 12:42:25.500,16.50502133227276,-34.340756122061755,23.65505111167525,True +2025-03-11 12:42:26.000,15.055852695292021,-31.034962550964757,21.081868950245195,True +2025-03-11 12:42:26.500,13.154570895148968,-26.69149138676789,17.714431282869146,True +2025-03-11 12:42:27.000,10.886065205775608,-21.51734989403568,13.690539298954981,True +2025-03-11 12:42:27.500,8.345524034251763,-15.720886200660544,9.19939504243764,True +2025-03-11 12:42:28.000,5.6533575353020415,-9.582129502143303,4.452829472134466,True +2025-03-11 12:42:28.500,2.92889428956434,-3.3728818202429798,-0.3668632944052741,True +2025-03-11 12:42:29.000,0.26880666528870073,2.657080175731891,-5.035760995652315,True +2025-03-11 12:42:29.500,-2.1769016823437055,8.235228176132908,-9.331765336396542,True +2025-03-11 12:42:30.000,-4.30193093099663,13.096682424284417,-13.107132272987378,True +2025-03-11 12:42:30.500,-6.035026093453986,17.03641162142172,-16.15107998617909,True +2025-03-11 12:42:31.000,-7.293853397236177,19.87113312213716,-18.356405495071797,True +2025-03-11 12:42:31.500,-8.012599403382426,21.514013854853623,-19.620013148678346,True +2025-03-11 12:42:32.000,-8.179698373991716,21.84929685820728,-19.876151436890222,True +2025-03-11 12:42:32.500,-7.767821232264117,20.879128318343746,-19.126314402702665,True +2025-03-11 12:42:33.000,-6.787593715633097,18.638818064515736,-17.400884509162715,True +2025-03-11 12:42:33.500,-5.291916317619443,15.245995663782754,-14.771765643896273,True +2025-03-11 12:42:34.000,-3.368635620203503,10.830528081367374,-11.350234758262367,True +2025-03-11 12:42:34.500,-1.0767792177034847,5.609280107885069,-7.300171524880764,True +2025-03-11 12:42:35.000,1.4753707303377575,-0.21790440564287478,-2.7867886175459886,True +2025-03-11 12:42:35.500,4.179900381342332,-6.3670454330399355,1.9713565112445015,True +2025-03-11 12:42:36.000,6.900119114405994,-12.566233521413366,6.787246573101344,True +2025-03-11 12:42:36.500,9.53540384088363,-18.585589239525707,11.440528528106157,True +2025-03-11 12:42:37.000,11.970410844786555,-24.104821393263045,15.721494894250572,True +2025-03-11 12:42:37.500,14.086262345780309,-28.8993877268134,19.43582797408373,True +2025-03-11 12:42:38.000,15.78844065986025,-32.78876147087788,22.430728882957194,True +2025-03-11 12:42:38.500,17.01616517625047,-35.54634583924164,24.57500997410693,True +2025-03-11 12:42:39.000,17.690530761355685,-37.08290188466167,25.761307664051564,True +2025-03-11 12:42:39.500,17.801022830468078,-37.32716109341141,25.947729518088504,True +2025-03-11 12:42:40.000,17.332645343679097,-36.24890328697832,25.120967713074563,True +2025-03-11 12:42:40.500,16.317349573132454,-33.92067990445531,23.309900215372927,True +2025-03-11 12:42:41.000,14.802980127685881,-30.44574849809794,20.606972468476272,True +2025-03-11 12:42:41.500,12.838867662671404,-25.959431660295266,17.130659506360097,True +2025-03-11 12:42:42.000,10.52831793956959,-20.682967408440977,13.041999349544163,True +2025-03-11 12:42:42.500,7.961489349842871,-14.833193493137518,8.50450814318871,True +2025-03-11 12:42:43.000,5.258073061869482,-8.658453134898075,3.7320098389851784,True +2025-03-11 12:42:43.500,2.5353381309785026,-2.448379263823928,-1.0738599187475208,True +2025-03-11 12:42:44.000,-0.09245086795874008,3.5297518996900545,-5.694864454185237,True +2025-03-11 12:42:44.500,-2.4976836715859743,9.001545773915264,-9.934029623260908,True +2025-03-11 12:42:45.000,-4.592448026402955,13.75132020681725,-13.602331955264452,True +2025-03-11 12:42:45.500,-6.272195446406839,17.5261796311279,-16.5305391086459,True +2025-03-11 12:42:46.000,-7.445021088758106,20.205445865314005,-18.620045313427212,True +2025-03-11 12:42:46.500,-8.08237894631129,21.659402450389894,-19.722240480018723,True +2025-03-11 12:42:47.000,-8.154041804777068,21.779215182189176,-19.838695019236148,True +2025-03-11 12:42:47.500,-7.654282192854492,20.62804031502614,-18.93672966953784,True +2025-03-11 12:42:48.000,-6.595943620812215,18.22800065580362,-17.07122417623409,True +2025-03-11 12:42:48.500,-5.045993114838869,14.66851660711026,-14.318398464039149,True +2025-03-11 12:42:49.000,-3.055010262224783,10.117417890573835,-10.798329890677842,True +2025-03-11 12:42:49.500,-0.7136354415091434,4.769448691787436,-6.65486274929696,True +2025-03-11 12:42:50.000,1.8756880614542202,-1.1118837932802725,-2.0842960654764124,True +2025-03-11 12:42:50.500,4.57696111024061,-7.301984140024184,2.7087123847973515,True +2025-03-11 12:42:51.000,7.31701818209272,-13.50084289703768,7.51258458291958,True +2025-03-11 12:42:51.500,9.943463764400377,-19.459130181949718,12.097109054520333,True +2025-03-11 12:42:52.000,12.312695058317427,-24.88136287641549,16.307794189818637,True +2025-03-11 12:42:52.500,14.376887105839662,-29.552059128685666,19.92880674960254,True +2025-03-11 12:42:53.000,16.014138279026476,-33.25703319880485,22.803526572391714,True +2025-03-11 12:42:53.500,17.14626907913232,-35.837421878668955,24.81433877202158,True +2025-03-11 12:42:54.000,17.746003197585864,-37.19269892817905,25.864982296025325,True +2025-03-11 12:42:54.500,17.7776124467685,-37.23631316342211,25.89222030863748,True +2025-03-11 12:42:55.000,17.234245643173306,-35.98630377867102,24.90491707380034,True +2025-03-11 12:42:55.500,16.13912061909134,-33.490043774121595,22.95774610128707,True +2025-03-11 12:42:56.000,14.54082817603225,-29.844774468949183,20.144755187640158,True +2025-03-11 12:42:56.500,12.520155727221397,-25.239969786640046,16.574350909077246,True +2025-03-11 12:42:57.000,10.158586407669153,-19.84888691492199,12.404839109078596,True +2025-03-11 12:42:57.500,7.554074126831585,-13.920523307777891,7.812445627424271,True +2025-03-11 12:42:58.000,4.834572717229899,-7.735853888197062,3.0202629373996235,True +2025-03-11 12:42:58.500,2.1180007737538755,-1.5474347347197623,-1.782115218364568,True +2025-03-11 12:42:59.000,-0.47117462526221476,4.364397723574998,-6.371432361043765,True +2025-03-11 12:42:59.500,-2.8451166683693883,9.753883052113906,-10.536332210761143,True +2025-03-11 12:43:00.000,-4.882174371043876,14.371210086489926,-14.114115870369492,True +2025-03-11 12:43:00.500,-6.474314423981786,17.99941256018278,-16.92862827864531,True +2025-03-11 12:43:01.000,-7.578870993265929,20.502234925832457,-18.86511991854336,True +2025-03-11 12:43:01.500,-8.138954113297265,21.744027173956017,-19.83003378007071,True +2025-03-11 12:43:02.000,-8.13719862723101,21.685442078389197,-19.790199261003693,True +2025-03-11 12:43:02.500,-7.540225483819426,20.329682265124237,-18.729916441869598,True +2025-03-11 12:43:03.000,-6.40112229618062,17.74828799168085,-16.722837983320513,True +2025-03-11 12:43:03.500,-4.770730226084256,14.034707930480083,-13.839544096053059,True +2025-03-11 12:43:04.000,-2.7248292929839524,9.351738047794603,-10.20918727120497,True +2025-03-11 12:43:04.500,-0.34989809104483427,3.924829486717165,-6.020045962334498,True +2025-03-11 12:43:05.000,2.2706280880276886,-2.0246482348586294,-1.433830782022584,True +2025-03-11 12:43:05.500,4.991710144486763,-8.224875132704543,3.379678213925514,True +2025-03-11 12:43:06.000,7.7122614819709545,-14.416938614854761,8.189148383099969,True +2025-03-11 12:43:06.500,10.291013358440749,-20.308496040279543,12.742658423543116,True +2025-03-11 12:43:07.000,12.63467121988673,-25.6503147467945,16.874754978822015,True +2025-03-11 12:43:07.500,14.630580090077288,-30.185612771260974,20.396061064007338,True +2025-03-11 12:43:08.000,16.18974767169634,-33.72673487899222,23.149818589129314,True +2025-03-11 12:43:08.500,17.26414204473822,-36.13470318759671,25.024138087894517,True +2025-03-11 12:43:09.000,17.774776816373727,-37.295078483050624,25.917821582895865,True +2025-03-11 12:43:09.500,17.710988984297767,-37.15028280399206,25.804982699950067,True +2025-03-11 12:43:10.000,17.07760931638144,-35.70550029100127,24.661019712462497,True +2025-03-11 12:43:10.500,15.92558283408157,-33.01495509938174,22.57356732913508,True +2025-03-11 12:43:11.000,14.257021140878765,-29.215820409673274,19.642572172118555,True +2025-03-11 12:43:11.500,12.175141313894331,-24.471242254271523,15.955806586371512,True +2025-03-11 12:43:12.000,9.771153673246662,-18.975470756354085,11.706306627660599,True +2025-03-11 12:43:12.500,7.1590643319052525,-13.013539067841819,7.061151315791279,True +2025-03-11 12:43:13.000,4.427925485730065,-6.807292299705257,2.2672495395590033,True +2025-03-11 12:43:13.500,1.7268328276600977,-0.6283531818055027,-2.500319384274726,True +2025-03-11 12:43:14.000,-0.8531294283840993,5.220207656609823,-7.037033177313725,True +2025-03-11 12:43:14.500,-3.1837004175558032,10.488653361501301,-11.123148473242903,True +2025-03-11 12:43:15.000,-5.156378654022918,14.960270093711657,-14.59936432755761,True +2025-03-11 12:43:15.500,-6.6859401352405285,18.43723352523388,-17.283827653469835,True +2025-03-11 12:43:16.000,-7.708397889760155,20.747032314290156,-19.065952139109534,True +2025-03-11 12:43:16.500,-8.17620732898437,21.805128498575844,-19.872489583599126,True +2025-03-11 12:43:17.000,-8.070893937217932,21.56019731777173,-19.687719667255315,True +2025-03-11 12:43:17.500,-7.400260516026819,20.01248966500986,-18.481239786140883,True +2025-03-11 12:43:18.000,-6.190872438469123,17.25927177166295,-16.334825551457648,True +2025-03-11 12:43:18.500,-4.498867851609104,13.384389031359758,-13.347576097557635,True +2025-03-11 12:43:19.000,-2.3853849794005644,8.595375062299434,-9.624583505599622,True +2025-03-11 12:43:19.500,0.03836942429888346,3.07567398164404,-5.347530763118612,True +2025-03-11 12:43:20.000,2.6629315368460555,-2.9208942299548113,-0.6897800217108756,True +2025-03-11 12:43:20.500,5.402569841111367,-9.143568162702545,4.116252034453843,True +2025-03-11 12:43:21.000,8.11641739623753,-15.313681442089267,8.88832186490555,True +2025-03-11 12:43:21.500,10.667045009481322,-21.141158878599875,13.408863841271671,True +2025-03-11 12:43:22.000,12.965260321242894,-26.371944936561786,17.472203983901878,True +2025-03-11 12:43:22.500,14.904771259836155,-30.779472801530662,20.883997115726892,True +2025-03-11 12:43:23.000,16.39709444468938,-34.1667343164384,23.490679744158278,True +2025-03-11 12:43:23.500,17.37758431247468,-36.394697669853024,25.217537635366284,True +2025-03-11 12:43:24.000,17.80274261299831,-37.344360520353646,25.95763784555191,True +2025-03-11 12:43:24.500,17.661288939427312,-36.98830201359385,25.68837466188869,True +2025-03-11 12:43:25.000,16.954463671541316,-35.36229411882375,24.414684068093898,True +2025-03-11 12:43:25.500,15.6899907002499,-32.4906731338915,22.19659659047902,True +2025-03-11 12:43:26.000,13.968899678059971,-28.544009069716978,19.135658157484215,True +2025-03-11 12:43:26.500,11.841939951388833,-23.674617796720025,15.369599936956192,True +2025-03-11 12:43:27.000,9.403506684208027,-18.12752559103288,11.048731064603743,True +2025-03-11 12:43:27.500,6.757324131370283,-12.110658471597645,6.38019498007904,True +2025-03-11 12:43:28.000,4.02924674190494,-5.883360306058792,1.5594222595480698,True +2025-03-11 12:43:28.500,1.335766643127808,0.25921889944009713,-3.2048357634853155,True +2025-03-11 12:43:29.000,-1.220344660107781,6.0434612644740895,-7.685162573183662,True +2025-03-11 12:43:29.500,-3.4861194537560105,11.212057429972674,-11.688148387188987,True +2025-03-11 12:43:30.000,-5.391369228956331,15.54086967323401,-15.045488843020836,True +2025-03-11 12:43:30.500,-6.859537395795947,18.849194747352374,-17.61003957033725,True +2025-03-11 12:43:31.000,-7.80031000400761,20.98384809078889,-19.256076423743693,True +2025-03-11 12:43:31.500,-8.176846634783768,21.853618062439033,-19.912886834970934,True +2025-03-11 12:43:32.000,-7.998946144273827,21.422213065684637,-19.567287707900825,True +2025-03-11 12:43:32.500,-7.245824574698081,19.693309387597544,-18.23678034299798,True +2025-03-11 12:43:33.000,-5.95315354216306,16.756447577926085,-15.980779826905401,True +2025-03-11 12:43:33.500,-4.197445516918374,12.732496925377871,-12.862760502272426,True +2025-03-11 12:43:34.000,-2.0447121148749448,7.803526501115225,-9.029771127745585,True +2025-03-11 12:43:34.500,0.4204960855640316,2.1785302369831125,-4.675303916763881,True +2025-03-11 12:43:35.000,3.0697513307599342,-3.8702052964242952,0.014830234701418393,True +2025-03-11 12:43:35.500,5.798690040094537,-10.096491624287967,4.8368903307107445,True +2025-03-11 12:43:36.000,8.490473767110993,-16.213388390495403,9.565529868913414,True +2025-03-11 12:43:36.500,11.021958335701413,-21.965295487417514,14.018566793144208,True +2025-03-11 12:43:37.000,13.275505698243428,-27.085216642530884,17.982804448212075,True +2025-03-11 12:43:37.500,15.153450681928344,-31.338425737405704,21.293639863720113,True +2025-03-11 12:43:38.000,16.57390916737172,-34.566529266483535,23.804778362594593,True +2025-03-11 12:43:38.500,17.474351439659866,-36.60686183543207,25.389737201456885,True +2025-03-11 12:43:39.000,17.81697291241793,-37.38026739795392,25.98301483867295,True +2025-03-11 12:43:39.500,17.594986295710655,-36.83693484381521,25.561440757000888,True +2025-03-11 12:43:40.000,16.802640094540592,-35.01922540669391,24.156350724064595,True +2025-03-11 12:43:40.500,15.491142820503434,-32.0013208993687,21.806325091610752,True +2025-03-11 12:43:41.000,13.700725562003925,-27.896643184277075,18.625235943732644,True +2025-03-11 12:43:41.500,11.50097862001626,-22.913809752512556,14.762403790039132,True +2025-03-11 12:43:42.000,9.01317226410263,-17.254151925846937,10.370133855778144,True +2025-03-11 12:43:42.500,6.355083741153132,-11.178705525048189,5.658000078067355,True +2025-03-11 12:43:43.000,3.611332059715286,-4.934531466198769,0.8345216026072266,True +2025-03-11 12:43:43.500,0.9169633570392849,1.1751177253324456,-3.8870684623632004,True +2025-03-11 12:43:44.000,-1.5968616909143916,6.882325617468638,-8.309610914983212,True +2025-03-11 12:43:44.500,-3.8141568639239924,11.93548002304179,-12.230310128628481,True +2025-03-11 12:43:45.000,-5.648190886884708,16.11997983275573,-15.469676005700919,True diff --git a/imap_processing/tests/mag/validation/L1c/T024/mag-l1b-l1c-t024-mago-burst-in.csv b/imap_processing/tests/mag/validation/L1c/T024/mag-l1b-l1c-t024-mago-burst-in.csv new file mode 100644 index 0000000000..2a4b94777d --- /dev/null +++ b/imap_processing/tests/mag/validation/L1c/T024/mag-l1b-l1c-t024-mago-burst-in.csv @@ -0,0 +1,22017 @@ +t,coarse,fine,sequence,x,y,z,range,compression,compression_width +2025-03-11T12:38:02.000442,479392685,29,171,-35.8174537543,-48.05111960175,67.90490438989,2,1,18 +2025-03-11T12:38:02.016067,479392685,29,171,-35.97294964276,-48.199262947995,68.16912887776,2,1,18 +2025-03-11T12:38:02.031692,479392685,29,171,-36.11430954136,-48.34276076352,68.43793566568,2,1,18 +2025-03-11T12:38:02.047317,479392685,29,171,-36.25566943996,-48.486258579045,68.7067424536,2,1,18 +2025-03-11T12:38:02.062942,479392685,29,171,-36.40174133518,-48.63438561936,68.957089830265,2,1,18 +2025-03-11T12:38:02.078567,479392685,29,171,-36.55723722364,-48.773286821955,69.212034872005,2,1,18 +2025-03-11T12:38:02.094192,479392685,29,171,-36.69859712224,-48.90754249383,69.47618339686,2,1,18 +2025-03-11T12:38:02.109817,479392685,29,171,-36.84466901746,-49.037185246845,69.74956252885,2,1,18 +2025-03-11T12:38:02.125442,479392685,29,171,-36.96246893296,-49.17602122572,69.98596859029,2,1,18 +2025-03-11T12:38:02.141067,479392685,29,171,-37.0896928417,-49.30101029505,70.208469044545,2,1,18 +2025-03-11T12:38:02.156692,479392685,29,171,-37.21691675044,-49.421378292555,70.4309509588,2,1,18 +2025-03-11T12:38:02.172317,479392685,29,171,-37.33942866256,-49.55560135257,70.67196644431,2,1,18 +2025-03-11T12:38:02.187942,479392685,29,171,-37.45251658144,-49.680565963005,70.90368892168,2,1,18 +2025-03-11T12:38:02.203567,479392685,29,171,-37.57502849356,-49.810167951195,71.14468586719,2,1,18 +2025-03-11T12:38:02.219192,479392685,29,171,-37.7022524023,-49.949020236,71.357999575315,2,1,18 +2025-03-11T12:38:02.234817,479392685,29,171,-37.82947631104,-50.078630377155,71.585139752635,2,1,18 +2025-03-11T12:38:02.250442,479392685,29,171,-37.97083620964,-50.189780689905,71.8214684791,2,1,18 +2025-03-11T12:38:02.266067,479392685,29,171,-38.102772115,-50.300914696725,72.030056545165,2,1,18 +2025-03-11T12:38:02.281692,479392685,29,171,-38.22999602374,-50.40279840693,72.238600750225,2,1,18 +2025-03-11T12:38:02.297317,479392685,29,171,-38.338371946,-50.51851272075,72.456415817395,2,1,18 +2025-03-11T12:38:02.312942,479392685,29,171,-38.43732387502,-50.657316087765,72.66968883949,2,1,18 +2025-03-11T12:38:02.328567,479392685,29,171,-38.54098780066,-50.77302224862,72.8551488442,2,1,18 +2025-03-11T12:38:02.344192,479392685,29,171,-38.64936372292,-50.87949441879,73.06368446524,2,1,18 +2025-03-11T12:38:02.359817,479392685,29,171,-38.75302764856,-50.985958435995,73.25834975608,2,1,18 +2025-03-11T12:38:02.375442,479392685,29,171,-38.86611556744,-51.08319661548,73.457612711995,2,1,18 +2025-03-11T12:38:02.391067,479392685,29,171,-38.9744914897,-51.194289857475,73.666166873035,2,1,18 +2025-03-11T12:38:02.406692,479392685,29,171,-39.0687314221,-51.3099797124,73.84699213267,2,1,18 +2025-03-11T12:38:02.422317,479392685,29,171,-39.1629713545,-51.407185280025,74.009258500045,2,1,18 +2025-03-11T12:38:02.437942,479392685,29,171,-39.26192328352,-51.504399000615,74.19463756375,2,1,18 +2025-03-11T12:38:02.453567,479392685,29,171,-39.3514512193,-51.583112127975,74.35682299012,2,1,18 +2025-03-11T12:38:02.469192,479392685,29,171,-39.45511514494,-51.666470786055,74.528289665635,2,1,18 +2025-03-11T12:38:02.484817,479392685,29,171,-39.54935507734,-51.749813138205,74.69050041301,2,1,18 +2025-03-11T12:38:02.500442,479392685,29,171,-39.64359500974,-51.842397634005,74.84812705732,2,1,18 +2025-03-11T12:38:02.516067,479392685,29,171,-39.71898695566,-51.93032844612,75.001086854545,2,1,18 +2025-03-11T12:38:02.531692,479392685,29,171,-39.80380289482,-52.02289663599,75.149457570715,2,1,18 +2025-03-11T12:38:02.547317,479392685,29,171,-39.88861883398,-52.120085897685,75.316331559145,2,1,18 +2025-03-11T12:38:02.562942,479392685,29,171,-39.97814676976,-52.208041168695,75.46469051632,2,1,18 +2025-03-11T12:38:02.578567,479392685,29,171,-40.07709869878,-52.28214953016,75.61762859857,2,1,18 +2025-03-11T12:38:02.594192,479392685,29,171,-40.1524906447,-52.351596054975,75.779756601925,2,1,18 +2025-03-11T12:38:02.609817,479392685,29,171,-40.22788259062,-52.444147938915,75.92349257302,2,1,18 +2025-03-11T12:38:02.625442,479392685,29,171,-40.3174105264,-52.5089978508,76.08562237939,2,1,18 +2025-03-11T12:38:02.641067,479392685,29,171,-40.40222646556,-52.59232389702,76.220092466365,2,1,18 +2025-03-11T12:38:02.656692,479392685,29,171,-40.47290641486,-52.684867627995,76.336094558065,2,1,18 +2025-03-11T12:38:02.672317,479392685,29,171,-40.53416237092,-52.754289693915,76.451990387755,2,1,18 +2025-03-11T12:38:02.687942,479392685,29,171,-40.59541832698,-52.80984854436,76.577072963575,2,1,18 +2025-03-11T12:38:02.703567,479392685,29,171,-40.65196228642,-52.88388352914,76.688359369195,2,1,18 +2025-03-11T12:38:02.719192,479392685,29,171,-40.7179302391,-52.9302083889,76.79492691376,2,1,18 +2025-03-11T12:38:02.734817,479392685,29,171,-40.77918619516,-52.98114616752,76.91999094958,2,1,18 +2025-03-11T12:38:02.750442,479392685,29,171,-40.84986614446,-53.045963467545,77.04512416741,2,1,18 +2025-03-11T12:38:02.766067,479392685,29,171,-40.9064101039,-53.12461952415,77.1471867469,2,1,18 +2025-03-11T12:38:02.781692,479392685,29,171,-40.96766605996,-53.18479944642,77.26304549659,2,1,18 +2025-03-11T12:38:02.797317,479392685,29,171,-41.0242100194,-53.2218658566,77.360320033015,2,1,18 +2025-03-11T12:38:02.812942,479392685,29,171,-41.07604198222,-53.277408401115,77.4622831315,2,1,18 +2025-03-11T12:38:02.828567,479392685,29,171,-41.13258594166,-53.32833802677,77.559613287925,2,1,18 +2025-03-11T12:38:02.844192,479392685,29,171,-41.18441790448,-53.37001735581,77.64303603415,2,1,18 +2025-03-11T12:38:02.859817,479392685,29,171,-41.23153787068,-53.420930675535,77.712625530175,2,1,18 +2025-03-11T12:38:02.875442,479392685,29,171,-41.27394584026,-53.46721477047,77.782189705195,2,1,18 +2025-03-11T12:38:02.891067,479392685,29,171,-41.31164181322,-53.508869640615,77.865592108405,2,1,18 +2025-03-11T12:38:02.906692,479392685,29,171,-41.35876177942,-53.555161888515,77.9259206983,2,1,18 +2025-03-11T12:38:02.922317,479392685,29,171,-41.40588174562,-53.60607520824,78.004752560455,2,1,18 +2025-03-11T12:38:02.937942,479392685,29,171,-41.44357771858,-53.63386686291,78.078856977535,2,1,18 +2025-03-11T12:38:02.953567,479392685,29,171,-41.4718496983,-53.666263283475,78.14834518954,2,1,18 +2025-03-11T12:38:02.969192,479392685,29,171,-41.49069768478,-53.69864339811,78.21319865647,2,1,18 +2025-03-11T12:38:02.984817,479392685,29,171,-41.51425766788,-53.717168450235,78.278003284405,2,1,18 +2025-03-11T12:38:03.000442,479392685,29,171,-41.55666563746,-53.74496825787,78.3243873841,2,1,18 +2025-03-11T12:38:03.016067,479392685,29,171,-41.59436161042,-53.786623128015,78.393926238115,2,1,18 +2025-03-11T12:38:03.031692,479392685,29,171,-41.6132095969,-53.814382170825,78.458761165045,2,1,18 +2025-03-11T12:38:03.047317,479392685,29,171,-41.64148157662,-53.832915375915,78.49122429253,2,1,18 +2025-03-11T12:38:03.062942,479392685,29,171,-41.65561756648,-53.865287337585,78.523722697,2,1,18 +2025-03-11T12:38:03.078567,479392685,29,171,-41.66975355634,-53.89303822743,78.570066110665,2,1,18 +2025-03-11T12:38:03.094192,479392685,29,171,-41.67917754958,-53.897675605185,78.597825311065,2,1,18 +2025-03-11T12:38:03.109817,479392685,29,171,-41.69331353944,-53.90694220773,78.620988649405,2,1,18 +2025-03-11T12:38:03.125442,479392685,29,171,-41.72158551916,-53.92547541282,78.639588227695,2,1,18 +2025-03-11T12:38:03.141067,479392685,29,171,-41.74514550226,-53.93937939312,78.67664721724,2,1,18 +2025-03-11T12:38:03.156692,479392685,29,171,-41.7545694955,-53.9486378427,78.699803774575,2,1,18 +2025-03-11T12:38:03.172317,479392685,29,171,-41.7545694955,-53.962501058175,78.709101760705,2,1,18 +2025-03-11T12:38:03.187942,479392685,29,171,-41.7781294786,-53.97178396665,78.70917274573,2,1,18 +2025-03-11T12:38:03.203567,479392685,29,171,-41.78284147522,-53.981034263265,78.699974240605,2,1,18 +2025-03-11T12:38:03.219192,479392685,29,171,-41.77341748198,-53.981017957335,78.690718312465,2,1,18 +2025-03-11T12:38:03.234817,479392685,29,171,-41.76399348874,-53.953275220455,78.681351144325,2,1,18 +2025-03-11T12:38:03.250442,479392685,29,171,-41.76870548536,-53.93479908612,78.6720413992,2,1,18 +2025-03-11T12:38:03.266067,479392685,29,171,-41.77341748198,-53.934807239085,78.681290546335,2,1,18 +2025-03-11T12:38:03.281692,479392685,29,171,-41.76870548536,-53.94404122977,78.685942028395,2,1,18 +2025-03-11T12:38:03.297317,479392685,29,171,-41.75928149212,-53.939403852015,78.667425194125,2,1,18 +2025-03-11T12:38:03.312942,479392685,29,171,-41.74985749888,-53.92552433061,78.648871279855,2,1,18 +2025-03-11T12:38:03.328567,479392685,29,171,-41.7310095124,-53.8977652878,78.630248183575,2,1,18 +2025-03-11T12:38:03.344192,479392685,29,171,-41.71216152592,-53.893111604115,78.5978542381,2,1,18 +2025-03-11T12:38:03.359817,479392685,29,171,-41.6838895462,-53.8884416145,78.57006791368,2,1,18 +2025-03-11T12:38:03.375442,479392685,29,171,-41.6603295631,-53.851432275075,78.542158590265,2,1,18 +2025-03-11T12:38:03.391067,479392685,29,171,-41.63676958,-53.85139151025,78.50515522072,2,1,18 +2025-03-11T12:38:03.406692,479392685,29,171,-41.61792159352,-53.837495682915,78.444997096855,2,1,18 +2025-03-11T12:38:03.422317,479392685,29,171,-41.59907360704,-53.818978783755,78.38482043299,2,1,18 +2025-03-11T12:38:03.437942,479392685,29,171,-41.58493761718,-53.80047003756,78.35237764852,2,1,18 +2025-03-11T12:38:03.453567,479392685,29,171,-41.5660896307,-53.75422670745,78.29671092772,2,1,18 +2025-03-11T12:38:03.469192,479392685,29,171,-41.52368166112,-53.71256368434,78.24565002496,2,1,18 +2025-03-11T12:38:03.484817,479392685,29,171,-41.48127369154,-53.68014280488,78.18538383607,2,1,18 +2025-03-11T12:38:03.500442,479392685,29,171,-41.45300171182,-53.638504240665,78.13896445939,2,1,18 +2025-03-11T12:38:03.516067,479392685,29,171,-41.43415372534,-53.59688198238,78.078695095525,2,1,18 +2025-03-11T12:38:03.531692,479392685,29,171,-41.401169749,-53.54599312155,77.999883576385,2,1,18 +2025-03-11T12:38:03.547317,479392685,29,171,-41.36347377604,-53.52744361053,77.925816239305,2,1,18 +2025-03-11T12:38:03.562942,479392685,29,171,-41.32577780308,-53.485788740385,77.84703501916,2,1,18 +2025-03-11T12:38:03.578567,479392685,29,171,-41.2833698335,-53.453367860925,77.763662914945,2,1,18 +2025-03-11T12:38:03.594192,479392685,29,171,-41.24096186392,-53.402462694165,77.694080199925,2,1,18 +2025-03-11T12:38:03.609817,479392685,29,171,-41.18441790448,-53.337669853035,77.60593678963,2,1,18 +2025-03-11T12:38:03.625442,479392685,29,171,-41.12787394504,-53.27749808373,77.499327187075,2,1,18 +2025-03-11T12:38:03.641067,479392685,29,171,-41.07604198222,-53.231197682865,77.392779985525,2,1,18 +2025-03-11T12:38:03.656692,479392685,29,171,-41.03363401264,-53.18491358793,77.313973444375,2,1,18 +2025-03-11T12:38:03.672317,479392685,29,171,-40.95824206672,-53.14781456589,77.21667178393,2,1,18 +2025-03-11T12:38:03.687942,479392685,29,171,-40.89227411404,-53.09224756248,77.110067159365,2,1,18 +2025-03-11T12:38:03.703567,479392685,29,171,-40.84515414784,-53.022849955455,77.017297588015,2,1,18 +2025-03-11T12:38:03.719192,479392685,29,171,-40.78389819178,-52.95804896136,76.901420298325,2,1,18 +2025-03-11T12:38:03.734817,479392685,29,171,-40.72264223572,-52.90711118274,76.776356262505,2,1,18 +2025-03-11T12:38:03.750442,479392685,29,171,-40.66609827628,-52.828455126135,76.66967249995,2,1,18 +2025-03-11T12:38:03.766067,479392685,29,171,-40.59541832698,-52.759016754285,76.52603600986,2,1,18 +2025-03-11T12:38:03.781692,479392685,29,171,-40.53887436754,-52.68960284133,76.400904595045,2,1,18 +2025-03-11T12:38:03.797317,479392685,29,171,-40.46819441824,-52.61092232583,76.275715757215,2,1,18 +2025-03-11T12:38:03.812942,479392685,29,171,-40.39751446894,-52.54148395398,76.132079267125,2,1,18 +2025-03-11T12:38:03.828567,479392685,29,171,-40.32212252302,-52.472037429165,75.99767836216,2,1,18 +2025-03-11T12:38:03.844192,479392685,29,171,-40.2467305771,-52.397969832525,75.863258917195,2,1,18 +2025-03-11T12:38:03.859817,479392685,29,171,-40.17133863118,-52.305417948585,75.7195229461,2,1,18 +2025-03-11T12:38:03.875442,479392685,29,171,-40.08652269202,-52.222091902365,75.575810492995,2,1,18 +2025-03-11T12:38:03.891067,479392685,29,171,-40.0111307461,-52.138782162075,75.427490418835,2,1,18 +2025-03-11T12:38:03.906692,479392685,29,171,-39.93102680356,-52.060085340645,75.274560920605,2,1,18 +2025-03-11T12:38:03.922317,479392685,29,171,-39.86034685426,-51.97678375332,75.130868810515,2,1,18 +2025-03-11T12:38:03.937942,479392685,29,171,-39.77081891848,-51.89807062596,74.977925750275,2,1,18 +2025-03-11T12:38:03.953567,479392685,29,171,-39.6812909827,-51.8193574986,74.80187677471,2,1,18 +2025-03-11T12:38:03.969192,479392685,29,171,-39.57762705706,-51.73599884052,74.621167733065,2,1,18 +2025-03-11T12:38:03.984817,479392685,29,171,-39.48338712466,-51.63417220107,74.445019276495,2,1,18 +2025-03-11T12:38:04.000442,479392685,29,171,-39.38443519564,-51.532337408655,74.282727588115,2,1,18 +2025-03-11T12:38:04.016067,479392685,29,171,-39.29961925648,-51.44439029061,74.097405947425,2,1,18 +2025-03-11T12:38:04.031692,479392685,29,171,-39.19595533084,-51.33330520158,73.91658566578,2,1,18 +2025-03-11T12:38:04.047317,479392685,29,171,-39.08757940858,-51.212969815935,73.73572152313,2,1,18 +2025-03-11T12:38:04.062942,479392685,29,171,-38.99333947618,-51.10652210466,73.55031216043,2,1,18 +2025-03-11T12:38:04.078567,479392685,29,171,-38.89438754716,-51.00930838407,73.374175462855,2,1,18 +2025-03-11T12:38:04.094192,479392685,29,171,-38.78129962828,-50.90744913276,73.188757516135,2,1,18 +2025-03-11T12:38:04.109817,479392685,29,171,-38.67763570264,-50.782500828255,72.97091214997,2,1,18 +2025-03-11T12:38:04.125442,479392685,29,171,-38.57868377362,-50.66218174854,72.776198020135,2,1,18 +2025-03-11T12:38:04.141067,479392685,29,171,-38.46088385812,-50.55569327244,72.586133569345,2,1,18 +2025-03-11T12:38:04.156692,479392685,29,171,-38.338371946,-50.44457557155,72.372937882225,2,1,18 +2025-03-11T12:38:04.172317,479392685,29,171,-38.21586003388,-50.33345787066,72.159742195105,2,1,18 +2025-03-11T12:38:04.187942,479392685,29,171,-38.09334812176,-50.208476954295,71.946490887985,2,1,18 +2025-03-11T12:38:04.203567,479392685,29,171,-37.97083620964,-50.08349603793,71.723997214735,2,1,18 +2025-03-11T12:38:04.219192,479392685,29,171,-37.85774829076,-49.97239464297,71.4877091743,2,1,18 +2025-03-11T12:38:04.234817,479392685,29,171,-37.74466037188,-49.87053539166,71.269942946125,2,1,18 +2025-03-11T12:38:04.250442,479392685,29,171,-37.61272446652,-49.74091709754,71.05203835393,2,1,18 +2025-03-11T12:38:04.266067,479392685,29,171,-37.49492455102,-49.61594433414,70.820309095555,2,1,18 +2025-03-11T12:38:04.281692,479392685,29,171,-37.37712463552,-49.477108355265,70.583903034115,2,1,18 +2025-03-11T12:38:04.297317,479392685,29,171,-37.24518873016,-49.35211113297,70.333668700465,2,1,18 +2025-03-11T12:38:04.312942,479392685,29,171,-37.10382883156,-49.21323438927,70.083365184805,2,1,18 +2025-03-11T12:38:04.328567,479392685,29,171,-36.96718092958,-49.07898687036,69.846950539345,2,1,18 +2025-03-11T12:38:04.344192,479392685,29,171,-36.83995702084,-48.930892441905,69.610493835895,2,1,18 +2025-03-11T12:38:04.359817,479392685,29,171,-36.69859712224,-48.79663677003,69.341724127975,2,1,18 +2025-03-11T12:38:04.375442,479392685,29,171,-36.56194922026,-48.657768179295,69.096048576385,2,1,18 +2025-03-11T12:38:04.391067,479392685,29,171,-36.43943730814,-48.528166191105,68.827324532485,2,1,18 +2025-03-11T12:38:04.406692,479392685,29,171,-36.30750140278,-48.38468468151,68.558531306575,2,1,18 +2025-03-11T12:38:04.422317,479392685,29,171,-36.16142950756,-48.24117871302,68.303581286845,2,1,18 +2025-03-11T12:38:04.437942,479392685,29,171,-36.03420559882,-48.09770535639,68.0532795742,2,1,18 +2025-03-11T12:38:04.453567,479392685,29,171,-35.88342170698,-47.954191234935,67.7937015904,2,1,18 +2025-03-11T12:38:04.469192,479392685,29,171,-35.71850182528,-47.79678943911,67.524805277455,2,1,18 +2025-03-11T12:38:04.484817,479392685,29,171,-35.56300593682,-47.639403949215,67.251301343455,2,1,18 +2025-03-11T12:38:04.500442,479392685,29,171,-35.4169340416,-47.477413693425,66.9731712484,2,1,18 +2025-03-11T12:38:04.516067,479392685,29,171,-35.2520141599,-47.324632969425,66.695051109325,2,1,18 +2025-03-11T12:38:04.531692,479392685,29,171,-35.09180627482,-47.176481470215,66.389229192865,2,1,18 +2025-03-11T12:38:04.547317,479392685,29,171,-34.9457343796,-47.01911228625,66.097254088615,2,1,18 +2025-03-11T12:38:04.562942,479392685,29,171,-34.78552649452,-46.86171864339,65.809879824415,2,1,18 +2025-03-11T12:38:04.578567,479392685,29,171,-34.62531860944,-46.69508285688,65.513226114085,2,1,18 +2025-03-11T12:38:04.594192,479392685,29,171,-34.45568673112,-46.53767290809,65.216595921745,2,1,18 +2025-03-11T12:38:04.609817,479392685,29,171,-34.29076684942,-46.37565004044,64.915332787345,2,1,18 +2025-03-11T12:38:04.625442,479392685,29,171,-34.1211349711,-46.21824009165,64.60483904581,2,1,18 +2025-03-11T12:38:04.641067,479392685,29,171,-33.9562150894,-46.033111864875,64.308104394475,2,1,18 +2025-03-11T12:38:04.656692,479392685,29,171,-33.78187121446,-45.861830547645,64.002169435,2,1,18 +2025-03-11T12:38:04.672317,479392685,29,171,-33.61695133276,-45.709049823645,63.69170101447,2,1,18 +2025-03-11T12:38:04.687942,479392685,29,171,-33.44731945444,-45.533155587555,63.381133112935,2,1,18 +2025-03-11T12:38:04.703567,479392685,29,171,-33.26355158626,-45.33875260527,63.06584952532,2,1,18 +2025-03-11T12:38:04.719192,479392685,29,171,-33.08920771132,-45.14898700074,62.74597685665,2,1,18 +2025-03-11T12:38:04.734817,479392685,29,171,-32.92428782962,-44.97772198944,62.40770717773,2,1,18 +2025-03-11T12:38:04.750442,479392685,29,171,-32.7546559513,-44.806448825175,62.083294267,2,1,18 +2025-03-11T12:38:04.766067,479392685,29,171,-32.58031207636,-44.62130429247,61.786546053655,2,1,18 +2025-03-11T12:38:04.781692,479392685,29,171,-32.39183221156,-44.440756372695,61.443584206645,2,1,18 +2025-03-11T12:38:04.797317,479392685,29,171,-32.20335234676,-44.26020845292,61.100622359635,2,1,18 +2025-03-11T12:38:04.812942,479392685,29,171,-32.01958447858,-44.06118439881,60.75759313363,2,1,18 +2025-03-11T12:38:04.828567,479392685,29,171,-31.82168062054,-43.880620173105,60.43310245687,2,1,18 +2025-03-11T12:38:04.844192,479392685,29,171,-31.62848875912,-43.709306244015,60.10403445805,2,1,18 +2025-03-11T12:38:04.859817,479392685,29,171,-31.4588568808,-43.5287909361,59.75185736893,2,1,18 +2025-03-11T12:38:04.875442,479392685,29,171,-31.26566501938,-43.33899271971,59.390366928655,2,1,18 +2025-03-11T12:38:04.891067,479392685,29,171,-31.06776116134,-43.14456527853,59.0519570827,2,1,18 +2025-03-11T12:38:04.906692,479392685,29,171,-30.87928129654,-42.954775215105,58.685852240365,2,1,18 +2025-03-11T12:38:04.922317,479392685,29,171,-30.68608943512,-42.76959807054,58.32438034009,2,1,18 +2025-03-11T12:38:04.937942,479392685,29,171,-30.48818557708,-42.552065270235,57.967393061875,2,1,18 +2025-03-11T12:38:04.953567,479392685,29,171,-30.2808577258,-42.339137235825,57.605789578585,2,1,18 +2025-03-11T12:38:04.969192,479392685,29,171,-30.07352987452,-42.14007241689,57.2303781661,2,1,18 +2025-03-11T12:38:04.984817,479392685,29,171,-29.87091401986,-41.936394679095,56.859576177685,2,1,18 +2025-03-11T12:38:05.000442,479392685,29,171,-29.67772215844,-41.746596462705,56.511949286605,2,1,18 +2025-03-11T12:38:05.016067,479392685,29,171,-29.46568231054,-41.538281347155,56.15035756231,2,1,18 +2025-03-11T12:38:05.031692,479392685,29,171,-29.25835445926,-41.31149009727,55.76097136063,2,1,18 +2025-03-11T12:38:05.047317,479392685,29,171,-29.0557386046,-41.107812359475,55.37630582302,2,1,18 +2025-03-11T12:38:05.062942,479392685,29,171,-28.8672587398,-40.9087801524,54.99630035149,2,1,18 +2025-03-11T12:38:05.078567,479392685,29,171,-28.678778875,-40.7051268735,54.63476107222,2,1,18 +2025-03-11T12:38:05.094192,479392685,29,171,-28.4667390271,-40.482948542475,54.245386629535,2,1,18 +2025-03-11T12:38:05.109817,479392685,29,171,-28.22642719948,-40.274584509135,53.83754238856,2,1,18 +2025-03-11T12:38:05.125442,479392685,29,171,-28.00496335834,-40.04314772853,53.43425375467,2,1,18 +2025-03-11T12:38:05.141067,479392685,29,171,-27.79763550706,-39.83021969412,53.031059623795,2,1,18 +2025-03-11T12:38:05.156692,479392685,29,171,-27.58559565916,-39.617283506745,52.646343444175,2,1,18 +2025-03-11T12:38:05.172317,479392685,29,171,-27.37826780788,-39.404355472335,52.2431493133,2,1,18 +2025-03-11T12:38:05.187942,479392685,29,171,-27.16151596336,-39.200653275645,51.858463432675,2,1,18 +2025-03-11T12:38:05.203567,479392685,29,171,-26.94005212222,-38.98770078234,51.473733691045,2,1,18 +2025-03-11T12:38:05.219192,479392685,29,171,-26.71387628446,-38.770119064245,51.04276679776,2,1,18 +2025-03-11T12:38:05.234817,479392685,29,171,-26.4877004467,-38.520189843375,50.639397222865,2,1,18 +2025-03-11T12:38:05.250442,479392685,29,171,-26.26623660556,-38.274889847295,50.245295335105,2,1,18 +2025-03-11T12:38:05.266067,479392685,29,171,-26.03534877118,-38.05267890441,49.814303120815,2,1,18 +2025-03-11T12:38:05.281692,479392685,29,171,-25.80917293342,-37.82123397084,49.40176533979,2,1,18 +2025-03-11T12:38:05.297317,479392685,29,171,-25.58299709566,-37.603652252745,48.998525544895,2,1,18 +2025-03-11T12:38:05.312942,479392685,29,171,-25.36624525114,-37.38608684058,48.572193396685,2,1,18 +2025-03-11T12:38:05.328567,479392685,29,171,-25.14006941338,-37.150020835185,48.1411523434,2,1,18 +2025-03-11T12:38:05.344192,479392685,29,171,-24.89975758576,-36.91855144272,47.7101094871,2,1,18 +2025-03-11T12:38:05.359817,479392685,29,171,-24.66886975138,-36.668614068885,47.292869582005,2,1,18 +2025-03-11T12:38:05.375442,479392685,29,171,-24.42384592714,-36.437136523455,46.87106231083,2,1,18 +2025-03-11T12:38:05.391067,479392685,29,171,-24.18824609614,-36.205675283955,46.440026235535,2,1,18 +2025-03-11T12:38:05.406692,479392685,29,171,-23.95735826176,-35.969601125595,46.008978401245,2,1,18 +2025-03-11T12:38:05.422317,479392685,29,171,-23.71704643414,-35.71964744583,45.577861384945,2,1,18 +2025-03-11T12:38:05.437942,479392685,29,171,-23.4720226099,-35.47892775675,45.123668752315,2,1,18 +2025-03-11T12:38:05.453567,479392685,29,171,-23.24113477552,-35.238232526565,44.674117645765,2,1,18 +2025-03-11T12:38:05.469192,479392685,29,171,-22.99139895466,-35.00674682817,44.24768241052,2,1,18 +2025-03-11T12:38:05.484817,479392685,29,171,-22.73695113718,-34.761389761335,43.798078858945,2,1,18 +2025-03-11T12:38:05.500442,479392685,29,171,-22.50135130618,-34.52530745001,43.35778187752,2,1,18 +2025-03-11T12:38:05.516067,479392685,29,171,-22.26103947856,-34.266111626595,42.912764232025,2,1,18 +2025-03-11T12:38:05.531692,479392685,29,171,-22.0113036577,-34.002278425425,42.44922975226,2,1,18 +2025-03-11T12:38:05.547317,479392685,29,171,-21.76156783684,-33.75230843973,41.994993258625,2,1,18 +2025-03-11T12:38:05.562942,479392685,29,171,-21.52125600922,-33.511596903615,41.554670956195,2,1,18 +2025-03-11T12:38:05.578567,479392685,29,171,-21.27152018836,-33.26162691792,41.09119209643,2,1,18 +2025-03-11T12:38:05.594192,479392685,29,171,-21.02649636412,-33.01166508519,40.62772001767,2,1,18 +2025-03-11T12:38:05.609817,479392685,29,171,-20.78147253988,-32.75246110881,40.16421085891,2,1,18 +2025-03-11T12:38:05.625442,479392685,29,171,-20.52231272578,-32.50709588901,39.7053581602,2,1,18 +2025-03-11T12:38:05.641067,479392685,29,171,-20.2678649083,-32.25711775035,39.25111488556,2,1,18 +2025-03-11T12:38:05.656692,479392685,29,171,-20.01341709082,-31.98865532439,38.76907035253,2,1,18 +2025-03-11T12:38:05.672317,479392685,29,171,-19.75425727672,-31.710942601815,38.30084550769,2,1,18 +2025-03-11T12:38:05.687942,479392685,29,171,-19.490385466,-31.442463869925,37.832650961845,2,1,18 +2025-03-11T12:38:05.703567,479392685,29,171,-19.2312256519,-31.197098650125,37.373798263135,2,1,18 +2025-03-11T12:38:05.719192,479392685,29,171,-18.9720658378,-30.9286280712,36.905610498295,2,1,18 +2025-03-11T12:38:05.734817,479392685,29,171,-18.7129060237,-30.669399635925,36.428217447325,2,1,18 +2025-03-11T12:38:05.750442,479392685,29,171,-18.4537462096,-30.4194133443,35.950861476355,2,1,18 +2025-03-11T12:38:05.766067,479392685,29,171,-18.19929839212,-30.16019306199,35.48271757252,2,1,18 +2025-03-11T12:38:05.781692,479392685,29,171,-17.9354265814,-29.8917143301,35.005280660545,2,1,18 +2025-03-11T12:38:05.797317,479392685,29,171,-17.68097876392,-29.62325190414,34.51861494445,2,1,18 +2025-03-11T12:38:05.812942,479392685,29,171,-17.4171069532,-29.3640153159,34.031972746345,2,1,18 +2025-03-11T12:38:05.828567,479392685,29,171,-17.13909915262,-29.104754268765,33.54068902216,2,1,18 +2025-03-11T12:38:05.844192,479392685,29,171,-16.86580334866,-28.83163815912,33.026250543655,2,1,18 +2025-03-11T12:38:05.859817,479392685,29,171,-16.5925075447,-28.567764193125,32.53957624354,2,1,18 +2025-03-11T12:38:05.875442,479392685,29,171,-16.32392373736,-28.29927730827,32.05289018443,2,1,18 +2025-03-11T12:38:05.891067,479392685,29,171,-16.06476392326,-28.021564585695,31.5569382412,2,1,18 +2025-03-11T12:38:05.906692,479392685,29,171,-15.79618011592,-27.739214485365,31.084060111285,2,1,18 +2025-03-11T12:38:05.922317,479392685,29,171,-15.52759630858,-27.47072760051,30.59275286911,2,1,18 +2025-03-11T12:38:05.937942,479392685,29,171,-15.25430050462,-27.188369347215,30.0921408598,2,1,18 +2025-03-11T12:38:05.953567,479392685,29,171,-14.99514069052,-26.915277696465,29.591586273505,2,1,18 +2025-03-11T12:38:05.969192,479392685,29,171,-14.71713288994,-26.64677450568,29.08178073706,2,1,18 +2025-03-11T12:38:05.984817,479392685,29,171,-14.4485490826,-26.378287620825,28.571988762625,2,1,18 +2025-03-11T12:38:06.000381,479392689,25,172,-14.15640529216,-26.100517827495,28.089852901555,2,1,18 +2025-03-11T12:38:06.016006,479392689,25,172,-13.87839749158,-25.827393564885,27.575407642045,2,1,18 +2025-03-11T12:38:06.031631,479392689,25,172,-13.600389691,-25.54964823045,27.05632265947,2,1,18 +2025-03-11T12:38:06.047256,479392689,25,172,-13.30824590056,-25.276499508945,26.56496297227,2,1,18 +2025-03-11T12:38:06.062881,479392689,25,172,-13.0349500966,-25.0033833993,26.069009226025,2,1,18 +2025-03-11T12:38:06.078506,479392689,25,172,-12.76165429264,-24.72564621783,25.559173390585,2,1,18 +2025-03-11T12:38:06.094131,479392689,25,172,-12.48364649206,-24.43403766792,25.04927515414,2,1,18 +2025-03-11T12:38:06.109756,479392689,25,172,-12.19621469824,-24.156276027555,24.54404015875,2,1,18 +2025-03-11T12:38:06.125381,479392689,25,172,-11.91820689766,-23.855425333995,24.015620110045,2,1,18 +2025-03-11T12:38:06.141006,479392689,25,172,-11.6449110937,-23.5730670807,23.51038691767,2,1,18 +2025-03-11T12:38:06.156631,479392689,25,172,-11.34805530664,-23.29991020623,23.00515690027,2,1,18 +2025-03-11T12:38:06.172256,479392689,25,172,-11.06533550944,-23.017535647005,22.490667779755,2,1,18 +2025-03-11T12:38:06.187881,479392689,25,172,-10.78732770886,-22.72130602527,21.97150863718,2,1,18 +2025-03-11T12:38:06.203506,479392689,25,172,-10.51874390152,-22.434334853115,21.43853658742,2,1,18 +2025-03-11T12:38:06.219131,479392689,25,172,-10.23602410432,-22.165823509365,20.90099717158,2,1,18 +2025-03-11T12:38:06.234756,479392689,25,172,-9.93916831726,-21.86956127577,20.37718972192,2,1,18 +2025-03-11T12:38:06.250381,479392689,25,172,-9.63760053358,-21.58253303286,19.85803375432,2,1,18 +2025-03-11T12:38:06.266006,479392689,25,172,-9.35016873976,-21.295529248845,19.35276167893,2,1,18 +2025-03-11T12:38:06.281631,479392689,25,172,-9.0768729358,-21.01317099555,18.83366493736,2,1,18 +2025-03-11T12:38:06.297256,479392689,25,172,-8.79886513522,-20.716941373815,18.30064224559,2,1,18 +2025-03-11T12:38:06.312881,479392689,25,172,-8.51614533802,-20.420703599115,17.776855138945,2,1,18 +2025-03-11T12:38:06.328506,479392689,25,172,-8.22400154758,-20.13831273396,17.248488907225,2,1,18 +2025-03-11T12:38:06.344131,479392689,25,172,-7.91772176728,-19.86513955356,16.70165468023,2,1,18 +2025-03-11T12:38:06.359756,479392689,25,172,-7.62086598022,-19.559635176315,16.15932541831,2,1,18 +2025-03-11T12:38:06.375381,479392689,25,172,-7.35228217288,-19.26342186051,15.62631628855,2,1,18 +2025-03-11T12:38:06.391006,479392689,25,172,-7.0742743723,-18.96257116695,15.116380972105,2,1,18 +2025-03-11T12:38:06.406631,479392689,25,172,-6.80097856834,-18.670970770005,14.58338360134,2,1,18 +2025-03-11T12:38:06.422256,479392689,25,172,-6.50412278128,-18.38395068006,14.05961323168,2,1,18 +2025-03-11T12:38:06.437881,479392689,25,172,-6.19784300098,-18.087672140535,13.51730748775,2,1,18 +2025-03-11T12:38:06.453506,479392689,25,172,-5.91041120716,-17.796047284695,12.95656267558,2,1,18 +2025-03-11T12:38:06.469131,479392689,25,172,-5.63240340658,-17.495196591135,12.428142626875,2,1,18 +2025-03-11T12:38:06.484756,479392689,25,172,-5.33554761952,-17.19893435754,11.895092811085,2,1,18 +2025-03-11T12:38:06.500381,479392689,25,172,-5.02926783922,-16.91651903349,11.36670623635,2,1,18 +2025-03-11T12:38:06.516006,479392689,25,172,-4.73712404878,-16.62026495286,10.83828438463,2,1,18 +2025-03-11T12:38:06.531631,479392689,25,172,-4.44026826172,-16.333244862915,10.29602928271,2,1,18 +2025-03-11T12:38:06.547256,479392689,25,172,-4.14341247466,-16.032361557495,9.75371856079,2,1,18 +2025-03-11T12:38:06.562881,479392689,25,172,-3.82770870112,-15.740687783865,9.21141779485,2,1,18 +2025-03-11T12:38:06.578506,479392689,25,172,-3.52614091744,-15.44903846913,8.687622104185,2,1,18 +2025-03-11T12:38:06.594131,479392689,25,172,-3.233997127,-15.138921173025,8.13603871714,2,1,18 +2025-03-11T12:38:06.609756,479392689,25,172,-2.9512773298,-14.8565466138,7.593822498235,2,1,18 +2025-03-11T12:38:06.625381,479392689,25,172,-2.65442154274,-14.56490545203,7.042306490185,2,1,18 +2025-03-11T12:38:06.641006,479392689,25,172,-2.3622777523,-14.264030299575,6.50000254927,2,1,18 +2025-03-11T12:38:06.656631,479392689,25,172,-2.06542196524,-13.963146994155,5.96693419348,2,1,18 +2025-03-11T12:38:06.672256,479392689,25,172,-1.76385418156,-13.648392320295,5.415318704425,2,1,18 +2025-03-11T12:38:06.687881,479392689,25,172,-1.47642238774,-13.347525320805,4.88688509371,2,1,18 +2025-03-11T12:38:06.703506,479392689,25,172,-1.18899059392,-13.05127939314,4.339985290735,2,1,18 +2025-03-11T12:38:06.719131,479392689,25,172,-0.89213480686,-12.745775015895,3.80227721188,2,1,18 +2025-03-11T12:38:06.734756,479392689,25,172,-0.59056702318,-12.440262485685,3.25531998589,2,1,18 +2025-03-11T12:38:06.750381,479392689,25,172,-0.29371123612,-12.148621323915,2.70380397784,2,1,18 +2025-03-11T12:38:06.766006,479392689,25,172,0.00785654755999987,-11.84772986553,2.161486474915,2,1,18 +2025-03-11T12:38:06.781631,479392689,25,172,0.31413632786,-11.55607239783,1.63306282018,2,1,18 +2025-03-11T12:38:06.797256,479392689,25,172,0.62512810478,-11.264406777165,1.08614765218,2,1,18 +2025-03-11T12:38:06.812881,479392689,25,172,0.92669588846,-10.958894246955,0.534569243125,2,1,18 +2025-03-11T12:38:06.828506,479392689,25,172,1.2188396789,-10.6580190945,-0.0123558808549999,2,1,18 +2025-03-11T12:38:06.844131,479392689,25,172,1.52040746258,-10.37099085159,-0.56386012991,2,1,18 +2025-03-11T12:38:06.859756,479392689,25,172,1.82197524626,-10.070099393205,-1.096935266705,2,1,18 +2025-03-11T12:38:06.875381,479392689,25,172,2.12354302994,-9.746102575695,-1.63934546963,2,1,18 +2025-03-11T12:38:06.891006,479392689,25,172,2.41568682038,-9.440606351415,-2.181667950545,2,1,18 +2025-03-11T12:38:06.906631,479392689,25,172,2.70783061082,-9.14897334261,-2.73317717759,2,1,18 +2025-03-11T12:38:06.922256,479392689,25,172,2.99997440126,-8.848098190155,-3.303208216895,2,1,18 +2025-03-11T12:38:06.937881,479392689,25,172,3.30154218494,-8.542585659945,-3.859407809015,2,1,18 +2025-03-11T12:38:06.953506,479392689,25,172,3.61724595848,-8.250911886315,-4.392466208825,2,1,18 +2025-03-11T12:38:06.969131,479392689,25,172,3.91881374216,-7.954641499755,-4.930143988685,2,1,18 +2025-03-11T12:38:06.984756,479392689,25,172,4.21566952922,-7.653758194335,-5.47707589367,2,1,18 +2025-03-11T12:38:07.000381,479392689,25,172,4.50781331966,-7.348261970055,-6.010156008455,2,1,18 +2025-03-11T12:38:07.016006,479392689,25,172,4.80466910672,-7.047378664635,-6.56633027957,2,1,18 +2025-03-11T12:38:07.031631,479392689,25,172,5.09681289716,-6.760366727655,-7.12244214968,2,1,18 +2025-03-11T12:38:07.047256,479392689,25,172,5.39366868422,-6.459483422235,-7.669374054665,2,1,18 +2025-03-11T12:38:07.062881,479392689,25,172,5.68110047804,-6.149374279095,-8.230193026835,2,1,18 +2025-03-11T12:38:07.078506,479392689,25,172,5.97324426848,-5.83925698299,-8.777155230815,2,1,18 +2025-03-11T12:38:07.094131,479392689,25,172,6.27481205216,-5.556849811905,-9.296292658415,2,1,18 +2025-03-11T12:38:07.109756,479392689,25,172,6.57637983584,-5.27444264082,-9.8570207336,2,1,18 +2025-03-11T12:38:07.125381,479392689,25,172,6.90150760262,-4.98275256126,-10.422440976875,2,1,18 +2025-03-11T12:38:07.141006,479392689,25,172,7.2030753863,-4.67724003105,-10.98326175206,2,1,18 +2025-03-11T12:38:07.156631,479392689,25,172,7.50464316998,-4.37172750084,-11.516355428855,2,1,18 +2025-03-11T12:38:07.172256,479392689,25,172,7.80621095366,-4.052351755155,-12.05874709178,2,1,18 +2025-03-11T12:38:07.187881,479392689,25,172,8.10306674072,-3.74684737791,-12.6010763537,2,1,18 +2025-03-11T12:38:07.203506,479392689,25,172,8.39049853454,-3.44598037842,-13.147994696675,2,1,18 +2025-03-11T12:38:07.219131,479392689,25,172,8.69206631822,-3.14970999186,-13.676430110405,2,1,18 +2025-03-11T12:38:07.234756,479392689,25,172,8.9936341019,-2.848818533475,-14.204884064135,2,1,18 +2025-03-11T12:38:07.250381,479392689,25,172,9.29048988896,-2.53407201258,-14.75187158912,2,1,18 +2025-03-11T12:38:07.266006,479392689,25,172,9.5826336794,-2.23781793195,-15.2987781731,2,1,18 +2025-03-11T12:38:07.281631,479392689,25,172,9.87006547322,-1.93695093246,-15.83183296688,2,1,18 +2025-03-11T12:38:07.297256,479392689,25,172,10.1716332569,-1.6406805459,-16.37875311287,2,1,18 +2025-03-11T12:38:07.312881,479392689,25,172,10.45906505072,-1.344434618235,-16.916410549715,2,1,18 +2025-03-11T12:38:07.328506,479392689,25,172,10.74178484792,-1.057438987185,-17.454024125555,2,1,18 +2025-03-11T12:38:07.344131,479392689,25,172,11.02921664174,-0.76119305952,-18.00092392853,2,1,18 +2025-03-11T12:38:07.359756,479392689,25,172,11.33549642204,-0.464914519995,-18.547850855525,2,1,18 +2025-03-11T12:38:07.375381,479392689,25,172,11.64177620234,-0.16863598047,-19.08553541639,2,1,18 +2025-03-11T12:38:07.391006,479392689,25,172,11.9386319894,0.11376303765,-19.63701434444,2,1,18 +2025-03-11T12:38:07.406631,479392689,25,172,12.23548777646,0.410025271245,-20.174685343295,2,1,18 +2025-03-11T12:38:07.422256,479392689,25,172,12.50878358042,0.697004596365,-20.712285357125,2,1,18 +2025-03-11T12:38:07.437881,479392689,25,172,12.81506336072,0.99328313589,-21.24996991799,2,1,18 +2025-03-11T12:38:07.453506,479392689,25,172,13.1166311444,1.2803113788,-21.77836825172,2,1,18 +2025-03-11T12:38:07.469131,479392689,25,172,13.40406293822,1.585799450115,-22.316062768565,2,1,18 +2025-03-11T12:38:07.484756,479392689,25,172,13.69149473204,1.88204537778,-22.85372020541,2,1,18 +2025-03-11T12:38:07.500381,479392689,25,172,13.9883505191,2.178307611375,-23.382148838135,2,1,18 +2025-03-11T12:38:07.516006,479392689,25,172,14.28520630616,2.47456984497,-23.90133510473,2,1,18 +2025-03-11T12:38:07.531631,479392689,25,172,14.57263809998,2.770815772635,-24.42512899238,2,1,18 +2025-03-11T12:38:07.547256,479392689,25,172,14.8600698938,3.048577413,-24.971954635355,2,1,18 +2025-03-11T12:38:07.562881,479392689,25,172,15.14750168762,3.34020226884,-25.48186643381,2,1,18 +2025-03-11T12:38:07.578506,479392689,25,172,15.43022148482,3.62719789989,-26.005616460455,2,1,18 +2025-03-11T12:38:07.594131,479392689,25,172,15.72236527526,3.928073052345,-26.53867803524,2,1,18 +2025-03-11T12:38:07.609756,479392689,25,172,16.0145090657,4.2104639175,-27.080907816155,2,1,18 +2025-03-11T12:38:07.625381,479392689,25,172,16.30194085952,4.50208877334,-27.60006198074,2,1,18 +2025-03-11T12:38:07.641006,479392689,25,172,16.58937265334,4.779850413705,-28.128402891455,2,1,18 +2025-03-11T12:38:07.656631,479392689,25,172,16.88151644378,5.066862350685,-28.65216648011,2,1,18 +2025-03-11T12:38:07.672256,479392689,25,172,17.17366023422,5.353874287665,-29.16206651957,2,1,18 +2025-03-11T12:38:07.687881,479392689,25,172,17.4752280179,5.640902530575,-29.676601304105,2,1,18 +2025-03-11T12:38:07.703506,479392689,25,172,17.7579478151,5.937140305275,-30.195767227685,2,1,18 +2025-03-11T12:38:07.719131,479392689,25,172,18.0406676123,6.2195148645,-30.70101398207,2,1,18 +2025-03-11T12:38:07.734756,479392689,25,172,18.31867541288,6.50188127076,-31.21549632158,2,1,18 +2025-03-11T12:38:07.750381,479392689,25,172,18.60139521008,6.78887690181,-31.739246348225,2,1,18 +2025-03-11T12:38:07.766006,479392689,25,172,18.89825099714,7.08051806358,-32.26765644095,2,1,18 +2025-03-11T12:38:07.781631,479392689,25,172,19.17625879772,7.358263398015,-32.79136260659,2,1,18 +2025-03-11T12:38:07.797256,479392689,25,172,19.4542665983,7.631387660625,-33.31505023223,2,1,18 +2025-03-11T12:38:07.812881,479392689,25,172,19.7369863955,7.909141148025,-33.829520812745,2,1,18 +2025-03-11T12:38:07.828506,479392689,25,172,20.01028219946,8.205362616795,-34.348673174315,2,1,18 +2025-03-11T12:38:07.844131,479392689,25,172,20.29300199666,8.47849503237,-34.86312521483,2,1,18 +2025-03-11T12:38:07.859756,479392689,25,172,20.58043379048,8.765498816385,-35.382260839415,2,1,18 +2025-03-11T12:38:07.875381,479392689,25,172,20.84901759782,9.03398570124,-35.868946898525,2,1,18 +2025-03-11T12:38:07.891006,479392689,25,172,21.12231340178,9.30248073906,-36.36488210477,2,1,18 +2025-03-11T12:38:07.906631,479392689,25,172,21.40032120236,9.589468217145,-36.865519435085,2,1,18 +2025-03-11T12:38:07.922256,479392689,25,172,21.67832900294,9.86721355158,-37.37536205153,2,1,18 +2025-03-11T12:38:07.937881,479392689,25,172,21.96104880014,10.149588110805,-37.889851172045,2,1,18 +2025-03-11T12:38:07.953506,479392689,25,172,22.24376859734,10.427341598205,-38.362731104975,2,1,18 +2025-03-11T12:38:07.969131,479392689,25,172,22.52177639792,10.700465860815,-38.86331281529,2,1,18 +2025-03-11T12:38:07.984756,479392689,25,172,22.78093621202,10.97817858339,-39.373128307715,2,1,18 +2025-03-11T12:38:08.000381,479392689,25,172,23.04952001936,11.246665468245,-39.896783831345,2,1,18 +2025-03-11T12:38:08.016006,479392689,25,172,23.32281582332,11.51053943424,-40.378836948395,2,1,18 +2025-03-11T12:38:08.031631,479392689,25,172,23.59139963066,11.78364739092,-40.865541547505,2,1,18 +2025-03-11T12:38:08.047256,479392689,25,172,23.85055944476,12.052117969845,-41.342971678475,2,1,18 +2025-03-11T12:38:08.062881,479392689,25,172,24.11443125548,12.34370206086,-41.843607205775,2,1,18 +2025-03-11T12:38:08.078506,479392689,25,172,24.38772705944,12.62143924233,-42.33033712589,2,1,18 +2025-03-11T12:38:08.094131,479392689,25,172,24.6610228634,12.876071064675,-42.816974346005,2,1,18 +2025-03-11T12:38:08.109756,479392689,25,172,24.91075868426,13.130662122195,-43.29895647803,2,1,18 +2025-03-11T12:38:08.125381,479392689,25,172,25.17463049498,13.389898710435,-43.77173512694,2,1,18 +2025-03-11T12:38:08.141006,479392689,25,172,25.44321430232,13.66762773894,-44.25845826605,2,1,18 +2025-03-11T12:38:08.156631,479392689,25,172,25.70708611304,13.931485399005,-44.726634271895,2,1,18 +2025-03-11T12:38:08.172256,479392689,25,172,25.96624592714,14.19071383428,-45.204027322865,2,1,18 +2025-03-11T12:38:08.187881,479392689,25,172,26.22540574124,14.440700125905,-45.690625659965,2,1,18 +2025-03-11T12:38:08.203506,479392689,25,172,26.47985355872,14.70454148004,-46.163409286865,2,1,18 +2025-03-11T12:38:08.219131,479392689,25,172,26.75314936268,14.96379437421,-46.636201497785,2,1,18 +2025-03-11T12:38:08.234756,479392689,25,172,27.02173317002,15.213796971765,-47.113571030765,2,1,18 +2025-03-11T12:38:08.250381,479392689,25,172,27.29502897398,15.473049865935,-47.577120875555,2,1,18 +2025-03-11T12:38:08.266006,479392689,25,172,27.54947679146,15.72764907642,-48.02676150713,2,1,18 +2025-03-11T12:38:08.281631,479392689,25,172,27.80392460894,15.98686935873,-48.485663044835,2,1,18 +2025-03-11T12:38:08.297256,479392689,25,172,28.05837242642,16.241468569215,-48.95378840867,2,1,18 +2025-03-11T12:38:08.312881,479392689,25,172,28.27983626756,16.50063178077,-49.41264247934,2,1,18 +2025-03-11T12:38:08.328506,479392689,25,172,28.52014809518,16.76444867601,-49.885405763225,2,1,18 +2025-03-11T12:38:08.344131,479392689,25,172,28.7840199059,17.02368526425,-50.33507849681,2,1,18 +2025-03-11T12:38:08.359756,479392689,25,172,29.04317972,17.264429412225,-50.789291472455,2,1,18 +2025-03-11T12:38:08.375381,479392689,25,172,29.28349154762,17.50514094834,-51.24347732408,2,1,18 +2025-03-11T12:38:08.391006,479392689,25,172,29.5379393651,17.750498015175,-51.702323241785,2,1,18 +2025-03-11T12:38:08.406631,479392689,25,172,29.77825119272,17.995830623115,-52.161148816475,2,1,18 +2025-03-11T12:38:08.422256,479392689,25,172,30.03741100682,18.23657477109,-52.601498242925,2,1,18 +2025-03-11T12:38:08.437881,479392689,25,172,30.27772283444,18.486528450855,-53.03723644229,2,1,18 +2025-03-11T12:38:08.453506,479392689,25,172,30.5274586553,18.73649843655,-53.47760938673,2,1,18 +2025-03-11T12:38:08.469131,479392689,25,172,30.77248247954,18.97721812563,-53.917938470165,2,1,18 +2025-03-11T12:38:08.484756,479392689,25,172,31.00337031392,19.217913355815,-54.367489576715,2,1,18 +2025-03-11T12:38:08.500381,479392689,25,172,31.24368214154,19.444761676455,-54.78465034382,2,1,18 +2025-03-11T12:38:08.516006,479392689,25,172,31.47456997592,19.690077978465,-55.211114075045,2,1,18 +2025-03-11T12:38:08.531631,479392689,25,172,31.70074581368,19.92614398386,-55.646776311395,2,1,18 +2025-03-11T12:38:08.547256,479392689,25,172,31.95048163454,20.148387538605,-56.087038015835,2,1,18 +2025-03-11T12:38:08.562881,479392689,25,172,32.18136946892,20.37984062514,-56.51344612706,2,1,18 +2025-03-11T12:38:08.578506,479392689,25,172,32.41696929992,20.615922936465,-56.916773643965,2,1,18 +2025-03-11T12:38:08.594131,479392689,25,172,32.63843314106,20.84735971707,-57.338547010115,2,1,18 +2025-03-11T12:38:08.609756,479392689,25,172,32.84576099234,21.083393110605,-57.755697390185,2,1,18 +2025-03-11T12:38:08.625381,479392689,25,172,33.08136082334,21.31947542193,-58.18675200548,2,1,18 +2025-03-11T12:38:08.641006,479392689,25,172,33.31696065434,21.54169451778,-58.61312981771,2,1,18 +2025-03-11T12:38:08.656631,479392689,25,172,33.56198447858,21.76392991956,-59.03027882582,2,1,18 +2025-03-11T12:38:08.672256,479392689,25,172,33.78344831972,21.98150348469,-59.45199657197,2,1,18 +2025-03-11T12:38:08.687881,479392689,25,172,34.00020016424,22.217553184155,-59.85991814792,2,1,18 +2025-03-11T12:38:08.703506,479392689,25,172,34.21224001214,22.43973151518,-60.2631561398,2,1,18 +2025-03-11T12:38:08.719131,479392689,25,172,34.43370385328,22.661926152135,-60.66640769369,2,1,18 +2025-03-11T12:38:08.734756,479392689,25,172,34.65987969104,22.893371085705,-61.051218376325,2,1,18 +2025-03-11T12:38:08.750381,479392689,25,172,34.8860555288,23.115573875625,-61.44523434509,2,1,18 +2025-03-11T12:38:08.766006,479392689,25,172,35.0980953767,23.342373278475,-61.84849087697,2,1,18 +2025-03-11T12:38:08.781631,479392689,25,172,35.30071123136,23.55529315992,-62.24243586071,2,1,18 +2025-03-11T12:38:08.797256,479392689,25,172,35.50332708602,23.758970897715,-62.63634376445,2,1,18 +2025-03-11T12:38:08.812881,479392689,25,172,35.72479092716,23.967302319195,-63.02105496608,2,1,18 +2025-03-11T12:38:08.828506,479392689,25,172,35.95096676492,24.171020821815,-63.405754408715,2,1,18 +2025-03-11T12:38:08.844131,479392689,25,172,36.17243060606,24.379352243295,-63.799707976475,2,1,18 +2025-03-11T12:38:08.859756,479392689,25,172,36.38918245058,24.59691765546,-64.20293420936,2,1,18 +2025-03-11T12:38:08.875381,479392689,25,172,36.59651030186,24.814466761695,-64.587662147975,2,1,18 +2025-03-11T12:38:08.891006,479392689,25,172,36.80383815314,25.027394796105,-64.958507997395,2,1,18 +2025-03-11T12:38:08.906631,479392689,25,172,37.00174201118,25.231064380935,-65.31543965561,2,1,18 +2025-03-11T12:38:08.922256,479392689,25,172,37.20435786584,25.44398426238,-65.686278724025,2,1,18 +2025-03-11T12:38:08.937881,479392689,25,172,37.39283773064,25.65687968493,-66.05247626636,2,1,18 +2025-03-11T12:38:08.953506,479392689,25,172,37.60016558192,25.86980771934,-66.41407974965,2,1,18 +2025-03-11T12:38:08.969131,479392689,25,172,37.79806943996,26.059614088695,-66.78481933706,2,1,18 +2025-03-11T12:38:08.984756,479392689,25,172,37.99126130138,26.23554908961,-67.1508753404,2,1,18 +2025-03-11T12:38:09.000381,479392689,25,172,38.1844531628,26.448452665125,-67.503216114545,2,1,18 +2025-03-11T12:38:09.016006,479392689,25,172,38.3729330276,26.642863800375,-67.86009713075,2,1,18 +2025-03-11T12:38:09.031631,479392689,25,172,38.5849728755,26.8280735568,-68.21697497198,2,1,18 +2025-03-11T12:38:09.047256,479392689,25,172,38.78287673354,27.017879926155,-68.564608644065,2,1,18 +2025-03-11T12:38:09.062881,479392689,25,172,38.97135659834,27.20766998958,-68.91222875414,2,1,18 +2025-03-11T12:38:09.078506,479392689,25,172,39.15512446652,27.402072971865,-69.255239440145,2,1,18 +2025-03-11T12:38:09.094131,479392689,25,172,39.34360433132,27.58262089164,-69.588958921025,2,1,18 +2025-03-11T12:38:09.109756,479392689,25,172,39.53679619274,27.78166125168,-69.9504864413,2,1,18 +2025-03-11T12:38:09.125381,479392689,25,172,39.7158520643,27.976056081,-70.288869163235,2,1,18 +2025-03-11T12:38:09.141006,479392689,25,172,39.88548394262,28.14270817344,-70.6086423509,2,1,18 +2025-03-11T12:38:09.156631,479392689,25,172,40.07867580404,28.318643174355,-70.93772888972,2,1,18 +2025-03-11T12:38:09.172256,479392689,25,172,40.26715566884,28.48994895048,-71.28065365673,2,1,18 +2025-03-11T12:38:09.187881,479392689,25,172,40.4462115404,28.670480564325,-71.58663247721,2,1,18 +2025-03-11T12:38:09.203506,479392689,25,172,40.61584341872,28.864859087715,-71.89265335568,2,1,18 +2025-03-11T12:38:09.219131,479392689,25,172,40.7760513038,29.031494874225,-72.203170615205,2,1,18 +2025-03-11T12:38:09.234756,479392689,25,172,40.94568318212,29.22125232579,-72.527657685935,2,1,18 +2025-03-11T12:38:09.250381,479392689,25,172,41.12473905368,29.39716286781,-72.852102698675,2,1,18 +2025-03-11T12:38:09.266006,479392689,25,172,41.28965893538,29.563806807285,-73.16724792227,2,1,18 +2025-03-11T12:38:09.281631,479392689,25,172,41.4592908137,29.7258378279,-73.47313902074,2,1,18 +2025-03-11T12:38:09.297256,479392689,25,172,41.63363468864,29.883255929655,-73.779018360215,2,1,18 +2025-03-11T12:38:09.312881,479392689,25,172,41.79384257372,30.040649572515,-74.075634990545,2,1,18 +2025-03-11T12:38:09.328506,479392689,25,172,41.9540504588,30.2026642872,-74.36764897781,2,1,18 +2025-03-11T12:38:09.344131,479392689,25,172,42.12368233712,30.37855852329,-74.659732147085,2,1,18 +2025-03-11T12:38:09.359756,479392689,25,172,42.26504223572,30.55440384159,-74.9425322642,2,1,18 +2025-03-11T12:38:09.375381,479392689,25,172,42.42996211742,30.702563493765,-75.220633863275,2,1,18 +2025-03-11T12:38:09.391006,479392689,25,172,42.59488199912,30.855344217765,-75.51723873461,2,1,18 +2025-03-11T12:38:09.406631,479392689,25,172,42.75037788758,30.998866492185,-75.795308231675,2,1,18 +2025-03-11T12:38:09.422256,479392689,25,172,42.90116177942,31.156243829115,-76.05956301854,2,1,18 +2025-03-11T12:38:09.437881,479392689,25,172,43.04723367464,31.30437086943,-76.34225867666,2,1,18 +2025-03-11T12:38:09.453506,479392689,25,172,43.2027295631,31.470998502975,-76.620420873725,2,1,18 +2025-03-11T12:38:09.469131,479392689,25,172,43.3676494448,31.633021370625,-76.90782045893,2,1,18 +2025-03-11T12:38:09.484756,479392689,25,172,43.51843333664,31.76729334843,-77.171982545795,2,1,18 +2025-03-11T12:38:09.500381,479392689,25,172,43.650369242,31.9061537862,-77.43613604864,2,1,18 +2025-03-11T12:38:09.516006,479392689,25,172,43.77759315074,32.054248214655,-77.70031985048,2,1,18 +2025-03-11T12:38:09.531631,479392689,25,172,43.92366504596,32.19313311132,-77.969114879405,2,1,18 +2025-03-11T12:38:09.547256,479392689,25,172,44.0744489378,32.336647232775,-78.219450497075,2,1,18 +2025-03-11T12:38:09.562881,479392689,25,172,44.20638484316,32.475507670545,-78.46511926766,2,1,18 +2025-03-11T12:38:09.578506,479392689,25,172,44.34303274514,32.60513411763,-78.72924247151,2,1,18 +2025-03-11T12:38:09.594131,479392689,25,172,44.47025665388,32.725502115135,-78.97483030109,2,1,18 +2025-03-11T12:38:09.609756,479392689,25,172,44.61161655248,32.85975778701,-79.22511527675,2,1,18 +2025-03-11T12:38:09.625381,479392689,25,172,44.74826445446,33.01248959322,-79.46160408221,2,1,18 +2025-03-11T12:38:09.641006,479392689,25,172,44.88962435306,33.146745265095,-79.69340432561,2,1,18 +2025-03-11T12:38:09.656631,479392689,25,172,45.02156025842,33.26250034374,-79.911253297805,2,1,18 +2025-03-11T12:38:09.672256,479392689,25,172,45.12993618068,33.373593585735,-80.119807458845,2,1,18 +2025-03-11T12:38:09.687881,479392689,25,172,45.2524480928,33.493953430275,-80.33766140903,2,1,18 +2025-03-11T12:38:09.703506,479392689,25,172,45.37967200154,33.609700355955,-80.58323069861,2,1,18 +2025-03-11T12:38:09.719131,479392689,25,172,45.50218391366,33.730060200495,-80.79646346573,2,1,18 +2025-03-11T12:38:09.734756,479392689,25,172,45.61055983592,33.85039558614,-80.991191157575,2,1,18 +2025-03-11T12:38:09.750381,479392689,25,172,45.7236477548,33.97073912475,-81.21827391188,2,1,18 +2025-03-11T12:38:09.766006,479392689,25,172,45.8414476703,34.09571188815,-81.431518437995,2,1,18 +2025-03-11T12:38:09.781631,479392689,25,172,45.94511159594,34.20679697718,-81.644687001095,2,1,18 +2025-03-11T12:38:09.797256,479392689,25,172,46.06291151144,34.32252759693,-81.84865208108,2,1,18 +2025-03-11T12:38:09.812881,479392689,25,172,46.19013542018,34.43827452261,-82.052630723075,2,1,18 +2025-03-11T12:38:09.828506,479392689,25,172,46.2890873492,34.54473038685,-82.24728923291,2,1,18 +2025-03-11T12:38:09.844131,479392689,25,172,46.3833272816,34.628072739,-82.43260589561,2,1,18 +2025-03-11T12:38:09.859756,479392689,25,172,46.49170320386,34.74378705282,-82.608830315195,2,1,18 +2025-03-11T12:38:09.875381,479392689,25,172,46.59065513288,34.836379701585,-82.789569655835,2,1,18 +2025-03-11T12:38:09.891006,479392689,25,172,46.69431905852,34.956706934265,-82.975048200545,2,1,18 +2025-03-11T12:38:09.906631,479392689,25,172,46.77913499768,35.058517267785,-83.13731954591,2,1,18 +2025-03-11T12:38:09.922256,479392689,25,172,46.86866293346,35.15109361062,-83.32728769067,2,1,18 +2025-03-11T12:38:09.937881,479392689,25,172,46.95819086924,35.234427809805,-83.51721875543,2,1,18 +2025-03-11T12:38:09.953506,479392689,25,172,47.06185479488,35.32240753971,-83.69332515401,2,1,18 +2025-03-11T12:38:09.969131,479392689,25,172,47.15609472728,35.40574989186,-83.85091471832,2,1,18 +2025-03-11T12:38:09.984756,479392689,25,172,47.23619866982,35.48444671329,-84.017707765745,2,1,18 +2025-03-11T12:38:10.000335,479392693,22,173,47.3257266056,35.58164412795,-84.16610380292,2,1,18 +2025-03-11T12:38:10.015960,479392693,22,173,47.419966538,35.660365408275,-84.319053644165,2,1,18 +2025-03-11T12:38:10.031585,479392693,22,173,47.49535848392,35.73905407674,-84.46273399526,2,1,18 +2025-03-11T12:38:10.047210,479392693,22,173,47.56603843322,35.82697673589,-84.62492937761,2,1,18 +2025-03-11T12:38:10.062835,479392693,22,173,47.655566369,35.891826647775,-84.76857445172,2,1,18 +2025-03-11T12:38:10.078460,479392693,22,173,47.73095831492,35.96127317259,-84.893732990555,2,1,18 +2025-03-11T12:38:10.094085,479392693,22,173,47.80163826422,36.03995368809,-85.028164194515,2,1,18 +2025-03-11T12:38:10.109710,479392693,22,173,47.87231821352,36.11863420359,-85.162595398475,2,1,18 +2025-03-11T12:38:10.125335,479392693,22,173,47.94771015944,36.197322872055,-85.292412200375,2,1,18 +2025-03-11T12:38:10.140960,479392693,22,173,48.01839010874,36.266761243905,-85.4314275074,2,1,18 +2025-03-11T12:38:10.156585,479392693,22,173,48.08435806142,36.340812534615,-85.547348658095,2,1,18 +2025-03-11T12:38:10.172210,479392693,22,173,48.1503260141,36.41948489715,-85.649424799595,2,1,18 +2025-03-11T12:38:10.187835,479392693,22,173,48.22571796002,36.48431035014,-85.75608006617,2,1,18 +2025-03-11T12:38:10.203460,479392693,22,173,48.29639790932,36.52602229104,-85.876499400935,2,1,18 +2025-03-11T12:38:10.219085,479392693,22,173,48.34351787552,36.576935610765,-85.99230072761,2,1,18 +2025-03-11T12:38:10.234710,479392693,22,173,48.39534983834,36.64172029893,-86.094300906095,2,1,18 +2025-03-11T12:38:10.250335,479392693,22,173,48.45189379778,36.711134211885,-86.18246285639,2,1,18 +2025-03-11T12:38:10.265960,479392693,22,173,48.49430176736,36.752797234995,-86.2797355898,2,1,18 +2025-03-11T12:38:10.281585,479392693,22,173,48.54613373018,36.794476564035,-86.381643068285,2,1,18 +2025-03-11T12:38:10.297210,479392693,22,173,48.60267768962,36.85464833334,-86.46976793858,2,1,18 +2025-03-11T12:38:10.312835,479392693,22,173,48.65922164906,36.89171474352,-86.55317892581,2,1,18 +2025-03-11T12:38:10.328460,479392693,22,173,48.71105361188,36.95187835986,-86.636675832035,2,1,18 +2025-03-11T12:38:10.344085,479392693,22,173,48.74874958484,36.993533230005,-86.71545705218,2,1,18 +2025-03-11T12:38:10.359710,479392693,22,173,48.79115755442,37.03981732494,-86.798884776395,2,1,18 +2025-03-11T12:38:10.375335,479392693,22,173,48.83827752062,37.08610957284,-86.86845573242,2,1,18 +2025-03-11T12:38:10.390960,479392693,22,173,48.8806854902,37.123151524125,-86.942604010505,2,1,18 +2025-03-11T12:38:10.406585,479392693,22,173,48.90895746992,37.14630580104,-87.01205514251,2,1,18 +2025-03-11T12:38:10.422210,479392693,22,173,48.93722944964,37.17408114978,-87.072282448385,2,1,18 +2025-03-11T12:38:10.437835,479392693,22,173,48.96078943274,37.220332632855,-87.123334767125,2,1,18 +2025-03-11T12:38:10.453460,479392693,22,173,49.00319740232,37.25737458414,-87.18824067908,2,1,18 +2025-03-11T12:38:10.469085,479392693,22,173,49.02675738542,37.303626067215,-87.243914180885,2,1,18 +2025-03-11T12:38:10.484710,479392693,22,173,49.05031736852,37.336014334815,-87.285668513495,2,1,18 +2025-03-11T12:38:10.500335,479392693,22,173,49.08330134486,37.34531354922,-87.32272252505,2,1,18 +2025-03-11T12:38:10.515960,479392693,22,173,49.12570931444,37.35925014138,-87.378293370875,2,1,18 +2025-03-11T12:38:10.531585,479392693,22,173,49.15869329078,37.377791499435,-87.42462682856,2,1,18 +2025-03-11T12:38:10.547210,479392693,22,173,49.18225327388,37.400937623385,-87.461722898105,2,1,18 +2025-03-11T12:38:10.562835,479392693,22,173,49.19167726712,37.419438216615,-87.48491653544,2,1,18 +2025-03-11T12:38:10.578460,479392693,22,173,49.20110126036,37.41483345072,-87.51263865584,2,1,18 +2025-03-11T12:38:10.594085,479392693,22,173,49.22466124346,37.42873743102,-87.540455279255,2,1,18 +2025-03-11T12:38:10.609710,479392693,22,173,49.22466124346,37.43797957467,-87.549734725385,2,1,18 +2025-03-11T12:38:10.625335,479392693,22,173,49.22937324008,37.447229871285,-87.55902095252,2,1,18 +2025-03-11T12:38:10.640960,479392693,22,173,49.25293322318,37.45651277976,-87.58219785287,2,1,18 +2025-03-11T12:38:10.656585,479392693,22,173,49.26235721642,37.461150157515,-87.60071468714,2,1,18 +2025-03-11T12:38:10.672210,479392693,22,173,49.27649320628,37.47041676006,-87.59615092709,2,1,18 +2025-03-11T12:38:10.687835,479392693,22,173,49.27178120966,37.48427182257,-87.61930568141,2,1,18 +2025-03-11T12:38:10.703460,479392693,22,173,49.2576452198,37.484247363675,-87.619285338395,2,1,18 +2025-03-11T12:38:10.719085,479392693,22,173,49.23879723332,37.484214751815,-87.60539466518,2,1,18 +2025-03-11T12:38:10.734710,479392693,22,173,49.22466124346,37.470327077445,-87.596076336035,2,1,18 +2025-03-11T12:38:10.750335,479392693,22,173,49.22466124346,37.451842790145,-87.58213862684,2,1,18 +2025-03-11T12:38:10.765960,479392693,22,173,49.21994924684,37.447213565355,-87.55900739051,2,1,18 +2025-03-11T12:38:10.781585,479392693,22,173,49.21994924684,37.447213565355,-87.55900739051,2,1,18 +2025-03-11T12:38:10.797210,479392693,22,173,49.20110126036,37.42407559437,-87.54040283423,2,1,18 +2025-03-11T12:38:10.812835,479392693,22,173,49.1869652705,37.405566848175,-87.512581232825,2,1,18 +2025-03-11T12:38:10.828460,479392693,22,173,49.17754127726,37.396308398595,-87.47093994323,2,1,18 +2025-03-11T12:38:10.844085,479392693,22,173,49.1634052874,37.36855750875,-87.433838895695,2,1,18 +2025-03-11T12:38:10.859710,479392693,22,173,49.14926929754,37.331564475255,-87.38745840203,2,1,18 +2025-03-11T12:38:10.875335,479392693,22,173,49.12099731782,37.30841019834,-87.336492002285,2,1,18 +2025-03-11T12:38:10.890960,479392693,22,173,49.08801334148,37.28524776846,-87.294761187665,2,1,18 +2025-03-11T12:38:10.906585,479392693,22,173,49.069165355,37.271351941125,-87.257708979125,2,1,18 +2025-03-11T12:38:10.922210,479392693,22,173,49.05031736852,37.234350754665,-87.18821578913,2,1,18 +2025-03-11T12:38:10.937835,479392693,22,173,49.01733339218,37.192704037485,-87.12792608225,2,1,18 +2025-03-11T12:38:10.953460,479392693,22,173,48.9749254226,37.169525301675,-87.06769697336,2,1,18 +2025-03-11T12:38:10.969085,479392693,22,173,48.93251745302,37.146346565865,-86.993604315275,2,1,18 +2025-03-11T12:38:10.984710,479392693,22,173,48.89010948344,37.113925686405,-86.924095760255,2,1,18 +2025-03-11T12:38:11.000335,479392693,22,173,48.8571255071,37.063036825575,-86.87763252257,2,1,18 +2025-03-11T12:38:11.015960,479392693,22,173,48.83827752062,37.016793495465,-86.79423870338,2,1,18 +2025-03-11T12:38:11.031585,479392693,22,173,48.80058154766,36.97513862532,-86.71083630017,2,1,18 +2025-03-11T12:38:11.047210,479392693,22,173,48.74874958484,36.928838224455,-86.63201619701,2,1,18 +2025-03-11T12:38:11.062835,479392693,22,173,48.70162961864,36.882545976555,-86.553202874855,2,1,18 +2025-03-11T12:38:11.078460,479392693,22,173,48.66393364568,36.845512178235,-86.460576645515,2,1,18 +2025-03-11T12:38:11.094085,479392693,22,173,48.61210168286,36.78996963372,-86.3493711809,2,1,18 +2025-03-11T12:38:11.109710,479392693,22,173,48.55555772342,36.74366107989,-86.252059564475,2,1,18 +2025-03-11T12:38:11.125335,479392693,22,173,48.48958977074,36.68809407648,-86.159318489105,2,1,18 +2025-03-11T12:38:11.140960,479392693,22,173,48.44718180116,36.623325694245,-86.061953055695,2,1,18 +2025-03-11T12:38:11.156585,479392693,22,173,48.39063784172,36.558532853115,-85.959946096205,2,1,18 +2025-03-11T12:38:11.172210,479392693,22,173,48.32466988904,36.493723706055,-85.857925574705,2,1,18 +2025-03-11T12:38:11.187835,479392693,22,173,48.25870193636,36.447398846295,-85.74211566401,2,1,18 +2025-03-11T12:38:11.203460,479392693,22,173,48.20215797692,36.391848148815,-85.626282235325,2,1,18 +2025-03-11T12:38:11.219085,479392693,22,173,48.14090202086,36.331668226545,-85.49655993644,2,1,18 +2025-03-11T12:38:11.234710,479392693,22,173,48.06551007494,36.257600629905,-85.389867589865,2,1,18 +2025-03-11T12:38:11.250335,479392693,22,173,47.99954212226,36.17892826737,-85.25544316691,2,1,18 +2025-03-11T12:38:11.265960,479392693,22,173,47.9382861662,36.095642985975,-85.12100698496,2,1,18 +2025-03-11T12:38:11.281585,479392693,22,173,47.8676062169,36.03082568595,-84.972767851805,2,1,18 +2025-03-11T12:38:11.297210,479392693,22,173,47.78279027774,35.961362855205,-84.833732201765,2,1,18 +2025-03-11T12:38:11.312835,479392693,22,173,47.7026863352,35.873423890125,-84.71311390499,2,1,18 +2025-03-11T12:38:11.328460,479392693,22,173,47.6320063859,35.785501230975,-84.574024437965,2,1,18 +2025-03-11T12:38:11.344085,479392693,22,173,47.54719044674,35.702175184755,-84.434933167925,2,1,18 +2025-03-11T12:38:11.359710,479392693,22,173,47.46237450758,35.618849138535,-84.28197834869,2,1,18 +2025-03-11T12:38:11.375335,479392693,22,173,47.38227056504,35.53553124528,-84.124409127395,2,1,18 +2025-03-11T12:38:11.390960,479392693,22,173,47.28803063264,35.45218889313,-83.97144074615,2,1,18 +2025-03-11T12:38:11.406585,479392693,22,173,47.21263868672,35.355015937365,-83.81382268586,2,1,18 +2025-03-11T12:38:11.422210,479392693,22,173,47.13253474418,35.27169804411,-83.647011098435,2,1,18 +2025-03-11T12:38:11.437835,479392693,22,173,47.03829481178,35.183734620135,-83.470918261865,2,1,18 +2025-03-11T12:38:11.453460,479392693,22,173,46.92991888952,35.077262449965,-83.317836837605,2,1,18 +2025-03-11T12:38:11.469085,479392693,22,173,46.83567895712,34.984677954165,-83.15558901023,2,1,18 +2025-03-11T12:38:11.484710,479392693,22,173,46.7367270281,34.878222089925,-82.970172866525,2,1,18 +2025-03-11T12:38:11.500335,479392693,22,173,46.65191108894,34.785653900055,-82.7894538689,2,1,18 +2025-03-11T12:38:11.515960,479392693,22,173,46.55295915992,34.70230339494,-82.594888059065,2,1,18 +2025-03-11T12:38:11.531585,479392693,22,173,46.43987124104,34.586580928155,-82.400172126215,2,1,18 +2025-03-11T12:38:11.547210,479392693,22,173,46.31735932892,34.48008429909,-82.196237345225,2,1,18 +2025-03-11T12:38:11.562835,479392693,22,173,46.20898340666,34.37361212892,-81.99232290725,2,1,18 +2025-03-11T12:38:11.578460,479392693,22,173,46.10531948102,34.257905968065,-81.792999353345,2,1,18 +2025-03-11T12:38:11.594085,479392693,22,173,45.99223156214,34.15142564493,-81.59369931743,2,1,18 +2025-03-11T12:38:11.609710,479392693,22,173,45.8885676365,34.035719484075,-81.385133397395,2,1,18 +2025-03-11T12:38:11.625335,479392693,22,173,45.78490371086,33.92001332322,-81.17656747736,2,1,18 +2025-03-11T12:38:11.640960,479392693,22,173,45.65767980212,33.808887469365,-80.981849741495,2,1,18 +2025-03-11T12:38:11.656585,479392693,22,173,45.52103190014,33.68850316593,-80.763975448295,2,1,18 +2025-03-11T12:38:11.672210,479392693,22,173,45.39851998802,33.56814332139,-80.54612149811,2,1,18 +2025-03-11T12:38:11.687835,479392693,22,173,45.29014406576,33.46167115122,-80.342207060135,2,1,18 +2025-03-11T12:38:11.703460,479392693,22,173,45.18648014012,33.336722846715,-80.10587696171,2,1,18 +2025-03-11T12:38:11.719085,479392693,22,173,45.063968228,33.21174193035,-79.851035007005,2,1,18 +2025-03-11T12:38:11.734710,479392693,22,173,44.93203232264,33.09136577988,-79.62392512868,2,1,18 +2025-03-11T12:38:11.750335,479392693,22,173,44.8048084139,32.9571345669,-79.392145228295,2,1,18 +2025-03-11T12:38:11.765960,479392693,22,173,44.67758450516,32.81366121027,-79.146464698715,2,1,18 +2025-03-11T12:38:11.781585,479392693,22,173,44.55507259304,32.670196006605,-78.905412133205,2,1,18 +2025-03-11T12:38:11.797210,479392693,22,173,44.41842469106,32.535948487695,-78.659755121615,2,1,18 +2025-03-11T12:38:11.812835,479392693,22,173,44.28177678908,32.39707989696,-78.414079570025,2,1,18 +2025-03-11T12:38:11.828460,479392693,22,173,44.121568904,32.272033756875,-78.17766809954,2,1,18 +2025-03-11T12:38:11.844085,479392693,22,173,43.99905699188,32.123947481385,-77.9273546279,2,1,18 +2025-03-11T12:38:11.859710,479392693,22,173,43.87183308314,31.98509519658,-77.67245027219,2,1,18 +2025-03-11T12:38:11.875335,479392693,22,173,43.72576118792,31.836968156265,-77.422102895525,2,1,18 +2025-03-11T12:38:11.890960,479392693,22,173,43.59382528256,31.69348664667,-77.162552035745,2,1,18 +2025-03-11T12:38:11.906585,479392693,22,173,43.42419340424,31.549939913355,-76.8798410126,2,1,18 +2025-03-11T12:38:11.922210,479392693,22,173,43.25927352254,31.41102240483,-76.601776493525,2,1,18 +2025-03-11T12:38:11.937835,479392693,22,173,43.10377763408,31.244394771285,-76.328235479525,2,1,18 +2025-03-11T12:38:11.953460,479392693,22,173,42.94828174562,31.08700928139,-76.054731545525,2,1,18 +2025-03-11T12:38:11.969085,479392693,22,173,42.80692184702,30.94813253769,-75.77207974841,2,1,18 +2025-03-11T12:38:11.984710,479392693,22,173,42.67027394504,30.78615858783,-75.48009966617,2,1,18 +2025-03-11T12:38:12.000335,479392693,22,173,42.51006605996,30.633386016795,-75.19274394197,2,1,18 +2025-03-11T12:38:12.015960,479392693,22,173,42.34514617826,30.47598422097,-74.905362896765,2,1,18 +2025-03-11T12:38:12.031585,479392693,22,173,42.17080230332,30.318566119215,-74.613347106485,2,1,18 +2025-03-11T12:38:12.047210,479392693,22,173,42.00588242162,30.156543251565,-74.312083972085,2,1,18 +2025-03-11T12:38:12.062835,479392693,22,173,41.84567453654,29.98528639323,-74.006169355625,2,1,18 +2025-03-11T12:38:12.078460,479392693,22,173,41.68546665146,29.82789275037,-73.71417390836,2,1,18 +2025-03-11T12:38:12.094085,479392693,22,173,41.53468275962,29.656652197965,-73.403651670845,2,1,18 +2025-03-11T12:38:12.109710,479392693,22,173,41.3650508813,29.49462117735,-73.097760572375,2,1,18 +2025-03-11T12:38:12.125335,479392693,22,173,41.18599500974,29.332573850805,-72.801098278025,2,1,18 +2025-03-11T12:38:12.140960,479392693,22,173,41.01636313142,29.14281639924,-72.476611207295,2,1,18 +2025-03-11T12:38:12.156585,479392693,22,173,40.85144324972,28.957688172465,-72.175255372895,2,1,18 +2025-03-11T12:38:12.172210,479392693,22,173,40.6818113714,28.7864150082,-71.85546364523,2,1,18 +2025-03-11T12:38:12.187835,479392693,22,173,40.50746749646,28.60589154732,-71.540249239625,2,1,18 +2025-03-11T12:38:12.203460,479392693,22,173,40.33312362152,28.42536808644,-71.22503483402,2,1,18 +2025-03-11T12:38:12.219085,479392693,22,173,40.1634917432,28.244852778525,-70.89134247716,2,1,18 +2025-03-11T12:38:12.234710,479392693,22,173,39.98443587164,28.078184380155,-70.562313361355,2,1,18 +2025-03-11T12:38:12.250335,479392693,22,173,39.80066800346,27.897644613345,-70.223979478415,2,1,18 +2025-03-11T12:38:12.265960,479392693,22,173,39.60747614204,27.707846396955,-69.8809737704,2,1,18 +2025-03-11T12:38:12.281585,479392693,22,173,39.42842027048,27.522693711285,-69.52876457927,2,1,18 +2025-03-11T12:38:12.297210,479392693,22,173,39.23051641244,27.328266270105,-69.19497591638,2,1,18 +2025-03-11T12:38:12.312835,479392693,22,173,39.05146054088,27.143113584435,-68.86125145751,2,1,18 +2025-03-11T12:38:12.328460,479392693,22,173,38.87240466932,26.939476611465,-68.49972574025,2,1,18 +2025-03-11T12:38:12.344085,479392693,22,173,38.6792128079,26.740436251425,-68.15206176917,2,1,18 +2025-03-11T12:38:12.359710,479392693,22,173,38.47659695324,26.55524280093,-67.81368222221,2,1,18 +2025-03-11T12:38:12.375335,479392693,22,173,38.28811708844,26.37007380933,-67.466080652135,2,1,18 +2025-03-11T12:38:12.390960,479392693,22,173,38.09963722364,26.171041602255,-67.095317546735,2,1,18 +2025-03-11T12:38:12.406585,479392693,22,173,37.90644536222,25.95813802674,-66.738355589525,2,1,18 +2025-03-11T12:38:12.422210,479392693,22,173,37.70854150418,25.749847370085,-66.39064775744,2,1,18 +2025-03-11T12:38:12.437835,479392693,22,173,37.48236566642,25.55999208294,-66.019867484,2,1,18 +2025-03-11T12:38:12.453460,479392693,22,173,37.27503781514,25.37479047948,-65.635269325385,2,1,18 +2025-03-11T12:38:12.469085,479392693,22,173,37.09598194358,25.166532434685,-65.245997969735,2,1,18 +2025-03-11T12:38:12.484710,479392693,22,173,36.90750207878,24.944394868485,-64.875142164335,2,1,18 +2025-03-11T12:38:12.500335,479392693,22,173,36.7001742275,24.731466834075,-64.50891749798,2,1,18 +2025-03-11T12:38:12.515960,479392693,22,173,36.4881343796,24.5185306467,-64.138064867555,2,1,18 +2025-03-11T12:38:12.531585,479392693,22,173,36.26667053846,24.314820297045,-63.762614572055,2,1,18 +2025-03-11T12:38:12.547210,479392693,22,173,36.06876668042,24.09728749674,-63.37790019545,2,1,18 +2025-03-11T12:38:12.562835,479392693,22,173,35.85672683252,23.88897238119,-63.00244492196,2,1,18 +2025-03-11T12:38:12.578460,479392693,22,173,35.62583899814,23.67138251013,-62.603819529125,2,1,18 +2025-03-11T12:38:12.594085,479392693,22,173,35.39966316038,23.44917972021,-62.20056119423,2,1,18 +2025-03-11T12:38:12.609710,479392693,22,173,35.18762331248,23.245485676485,-61.811260911545,2,1,18 +2025-03-11T12:38:12.625335,479392693,22,173,34.97558346458,23.018686273635,-61.4033831966,2,1,18 +2025-03-11T12:38:12.640960,479392693,22,173,34.75411962344,22.801112708505,-61.00015018271,2,1,18 +2025-03-11T12:38:12.656585,479392693,22,173,34.53736777892,22.59278943999,-60.587718663695,2,1,18 +2025-03-11T12:38:12.672210,479392693,22,173,34.32532793102,22.370611108965,-60.184480671815,2,1,18 +2025-03-11T12:38:12.687835,479392693,22,173,34.10386408988,22.14841647201,-59.77660793486,2,1,18 +2025-03-11T12:38:12.703460,479392693,22,173,33.88240024874,21.93084290688,-59.37337492097,2,1,18 +2025-03-11T12:38:12.719085,479392693,22,173,33.66564840422,21.704035351065,-58.96549042502,2,1,18 +2025-03-11T12:38:12.734710,479392693,22,173,33.4253365766,21.458702743125,-58.557497864045,2,1,18 +2025-03-11T12:38:12.750335,479392693,22,173,33.19444874222,21.22724965659,-58.135710935885,2,1,18 +2025-03-11T12:38:12.765960,479392693,22,173,32.98712089094,21.000458406705,-57.71397645275,2,1,18 +2025-03-11T12:38:12.781585,479392693,22,173,32.76094505318,20.78287668861,-57.301494291725,2,1,18 +2025-03-11T12:38:12.797210,479392693,22,173,32.52063322556,20.560649439795,-56.86586733236,2,1,18 +2025-03-11T12:38:12.812835,479392693,22,173,32.28032139794,20.333801119155,-56.430221832995,2,1,18 +2025-03-11T12:38:12.828460,479392693,22,173,32.04000957032,20.08384743939,-55.99448363363,2,1,18 +2025-03-11T12:38:12.844085,479392693,22,173,31.7996977427,19.83851483145,-55.568006340395,2,1,18 +2025-03-11T12:38:12.859710,479392693,22,173,31.5640979117,19.593190376475,-55.141535828165,2,1,18 +2025-03-11T12:38:12.875335,479392693,22,173,31.32378608408,19.36172098401,-54.71511415493,2,1,18 +2025-03-11T12:38:12.890960,479392693,22,173,31.07876225984,19.116380223105,-54.293251263755,2,1,18 +2025-03-11T12:38:12.906585,479392693,22,173,30.84316242884,18.86181362448,-53.839016573135,2,1,18 +2025-03-11T12:38:12.922210,479392693,22,173,30.60756259784,18.63035238498,-53.394116948645,2,1,18 +2025-03-11T12:38:12.937835,479392693,22,173,30.37196276684,18.41737543278,-52.95391266722,2,1,18 +2025-03-11T12:38:12.953460,479392693,22,173,30.12222694598,18.176647590735,-52.508955619715,2,1,18 +2025-03-11T12:38:12.969085,479392693,22,173,29.8913391116,17.931331288725,-52.0547647901,2,1,18 +2025-03-11T12:38:12.984710,479392693,22,173,29.63689129412,17.68597422189,-51.60978242159,2,1,18 +2025-03-11T12:38:13.000335,479392693,22,173,29.37773148002,17.426745786615,-51.16011646901,2,1,18 +2025-03-11T12:38:13.015960,479392693,22,173,29.12328366254,17.167525504305,-50.701214931305,2,1,18 +2025-03-11T12:38:13.031585,479392693,22,173,28.86883584506,16.91292629382,-50.256195482795,2,1,18 +2025-03-11T12:38:13.047210,479392693,22,173,28.63323601406,16.65373862337,-49.801942252175,2,1,18 +2025-03-11T12:38:13.062835,479392693,22,173,28.39292418644,16.385300656305,-49.333781611355,2,1,18 +2025-03-11T12:38:13.078460,479392693,22,173,28.1479003622,16.135338823575,-48.87493071566,2,1,18 +2025-03-11T12:38:13.094085,479392693,22,173,27.89345254472,15.88998175674,-48.406842431825,2,1,18 +2025-03-11T12:38:13.109710,479392693,22,173,27.64842872048,15.635398852185,-47.92948826387,2,1,18 +2025-03-11T12:38:13.125335,479392693,22,173,27.38926890638,15.39465470421,-47.456790555965,2,1,18 +2025-03-11T12:38:13.140960,479392693,22,173,27.13010909228,15.135426268935,-47.01174578645,2,1,18 +2025-03-11T12:38:13.156585,479392693,22,173,26.8756612748,14.866963842975,-46.543564802615,2,1,18 +2025-03-11T12:38:13.172210,479392693,22,173,26.62592545394,14.612372785455,-46.047719121395,2,1,18 +2025-03-11T12:38:13.187835,479392693,22,173,26.36205364322,14.334651909915,-45.57948749555,2,1,18 +2025-03-11T12:38:13.203460,479392693,22,173,26.0981818325,14.075415321675,-45.129814761965,2,1,18 +2025-03-11T12:38:13.219085,479392693,22,173,25.83431002178,13.82079980526,-44.65243346999,2,1,18 +2025-03-11T12:38:13.234710,479392693,22,173,25.56101421782,13.55230476744,-44.15187708068,2,1,18 +2025-03-11T12:38:13.250335,479392693,22,173,25.28300641724,13.29766479213,-43.660611896495,2,1,18 +2025-03-11T12:38:13.265960,479392693,22,173,25.02855859976,13.01996022252,-43.178530283465,2,1,18 +2025-03-11T12:38:13.281585,479392693,22,173,24.76468678904,12.746860418805,-42.70107483149,2,1,18 +2025-03-11T12:38:13.297210,479392693,22,173,24.51495096818,12.48764828946,-42.228316525595,2,1,18 +2025-03-11T12:38:13.312835,479392693,22,173,24.25107915746,12.22841170122,-41.727810778295,2,1,18 +2025-03-11T12:38:13.328460,479392693,22,173,23.9777833535,11.973779878875,-41.236552375115,2,1,18 +2025-03-11T12:38:13.344085,479392693,22,173,23.69977555292,11.709897759915,-40.759113660125,2,1,18 +2025-03-11T12:38:13.359710,479392693,22,173,23.42647974896,11.422918434795,-40.29083139227,2,1,18 +2025-03-11T12:38:13.375335,479392693,22,173,23.15789594162,11.140568334465,-39.7856049809,2,1,18 +2025-03-11T12:38:13.390960,479392693,22,173,22.90344812414,10.87672698033,-39.280473072545,2,1,18 +2025-03-11T12:38:13.406585,479392693,22,173,22.6348643168,10.6128611673,-38.775320821175,2,1,18 +2025-03-11T12:38:13.422210,479392693,22,173,22.34272052636,10.33509137397,-38.27932141091,2,1,18 +2025-03-11T12:38:13.437835,479392693,22,173,22.06471272578,10.06196711136,-37.78336088366,2,1,18 +2025-03-11T12:38:13.453460,479392693,22,173,21.7867049252,9.784221776925,-37.292002999475,2,1,18 +2025-03-11T12:38:13.469085,479392693,22,173,21.503985128,9.497226145875,-36.772874155895,2,1,18 +2025-03-11T12:38:13.484710,479392693,22,173,21.23068932404,9.219488964405,-36.25841713739,2,1,18 +2025-03-11T12:38:13.500335,479392693,22,173,20.97152950994,8.955639457305,-35.7440360819,2,1,18 +2025-03-11T12:38:13.515960,479392693,22,173,20.69352170936,8.682515194695,-35.24807555465,2,1,18 +2025-03-11T12:38:13.531585,479392693,22,173,20.40608991554,8.39551141068,-34.74280347926,2,1,18 +2025-03-11T12:38:13.547210,479392693,22,173,20.13279411158,8.09928994191,-34.24213584995,2,1,18 +2025-03-11T12:38:13.562835,479392693,22,173,19.85949830762,7.826173832265,-33.746182103705,2,1,18 +2025-03-11T12:38:13.578460,479392693,22,173,19.58620250366,7.54381557897,-33.227085362135,2,1,18 +2025-03-11T12:38:13.594085,479392693,22,173,19.29877070984,7.27067501043,-32.703384174485,2,1,18 +2025-03-11T12:38:13.609710,479392693,22,173,19.0066269194,6.988284145275,-32.184260308895,2,1,18 +2025-03-11T12:38:13.625335,479392693,22,173,18.71919512558,6.71976464856,-31.66519884431,2,1,18 +2025-03-11T12:38:13.640960,479392693,22,173,18.43647532838,6.437390089335,-31.15533090686,2,1,18 +2025-03-11T12:38:13.656585,479392693,22,173,18.15375553118,6.141152314635,-30.62692261715,2,1,18 +2025-03-11T12:38:13.672210,479392693,22,173,17.88045972722,5.863415133165,-30.10784441558,2,1,18 +2025-03-11T12:38:13.687835,479392693,22,173,17.58831593678,5.56253998071,-29.574782840795,2,1,18 +2025-03-11T12:38:13.703460,479392693,22,173,17.30088414296,5.275536196695,-29.05564721621,2,1,18 +2025-03-11T12:38:13.719085,479392693,22,173,17.027588339,4.9931779434,-28.54579284077,2,1,18 +2025-03-11T12:38:13.734710,479392693,22,173,16.73544454856,4.692302790945,-28.040458364375,2,1,18 +2025-03-11T12:38:13.750335,479392693,22,173,16.44330075812,4.405290853965,-27.512073592655,2,1,18 +2025-03-11T12:38:13.765960,479392693,22,173,16.16058096092,4.12291629474,-26.97909973988,2,1,18 +2025-03-11T12:38:13.781585,479392693,22,173,15.85430118062,3.826637755215,-26.44603636208,2,1,18 +2025-03-11T12:38:13.797210,479392693,22,173,15.57158138342,3.539642124165,-25.9269075185,2,1,18 +2025-03-11T12:38:13.812835,479392693,22,173,15.29357358284,3.24341250243,-25.398506009795,2,1,18 +2025-03-11T12:38:13.828460,479392693,22,173,14.99200579916,2.942521044045,-24.865430873,2,1,18 +2025-03-11T12:38:13.844085,479392693,22,173,14.70457400534,2.641654044555,-24.34161844535,2,1,18 +2025-03-11T12:38:13.859710,479392693,22,173,14.41714221152,2.36389240419,-23.8178987177,2,1,18 +2025-03-11T12:38:13.875335,479392693,22,173,14.14384640756,2.072292007245,-23.266416614675,2,1,18 +2025-03-11T12:38:13.890960,479392693,22,173,13.85641461374,1.78528822323,-22.72879625783,2,1,18 +2025-03-11T12:38:13.906585,479392693,22,173,13.55013483344,1.48438861188,-22.19571434003,2,1,18 +2025-03-11T12:38:13.922210,479392693,22,173,13.26270303962,1.20200589969,-21.667354889315,2,1,18 +2025-03-11T12:38:13.937835,479392693,22,173,12.96584725256,0.91960688157,-21.125118327395,2,1,18 +2025-03-11T12:38:13.953460,479392693,22,173,12.6689914655,0.609481432500001,-20.59663407467,2,1,18 +2025-03-11T12:38:13.969085,479392693,22,173,12.36742368182,0.299347830465,-20.054279491745,2,1,18 +2025-03-11T12:38:13.984710,479392693,22,173,12.079991888,0.01234404645,-19.521280317965,2,1,18 +2025-03-11T12:38:14.000259,479392697,17,174,11.77842410432,-0.283926340110001,-18.974360171975,2,1,18 +2025-03-11T12:38:14.015884,479392697,17,174,11.48628031388,-0.584801492564999,-18.427435047995,2,1,18 +2025-03-11T12:38:14.031509,479392697,17,174,11.19413652344,-0.871813429545,-17.889807910145,2,1,18 +2025-03-11T12:38:14.047134,479392697,17,174,10.901992733,-1.158825366525,-17.3383172231,2,1,18 +2025-03-11T12:38:14.062759,479392697,17,174,10.60042494932,-1.47820111221,-16.795925560175,2,1,18 +2025-03-11T12:38:14.078384,479392697,17,174,10.29414516902,-1.76985857991,-16.24901717318,2,1,18 +2025-03-11T12:38:14.094009,479392697,17,174,9.99728938196,-2.056878669855,-15.711383254325,2,1,18 +2025-03-11T12:38:14.109634,479392697,17,174,9.70514559152,-2.35775382231,-15.155215764215,2,1,18 +2025-03-11T12:38:14.125259,479392697,17,174,9.4177137977,-2.64937867815,-14.6268192335,2,1,18 +2025-03-11T12:38:14.140884,479392697,17,174,9.1349940005,-2.94561645285,-14.10765330992,2,1,18 +2025-03-11T12:38:14.156509,479392697,17,174,8.83813821344,-3.25574190192,-13.565305508,2,1,18 +2025-03-11T12:38:14.172134,479392697,17,174,8.52714643652,-3.584376097185,-13.013620836935,2,1,18 +2025-03-11T12:38:14.187759,479392697,17,174,8.22557865284,-3.871404340095,-12.46211658788,2,1,18 +2025-03-11T12:38:14.203384,479392697,17,174,7.91458687592,-4.15382781711,-11.910617316815,2,1,18 +2025-03-11T12:38:14.219009,479392697,17,174,7.61773108886,-4.440847907055,-11.37298339796,2,1,18 +2025-03-11T12:38:14.234634,479392697,17,174,7.33501129166,-4.746327825405,-10.82605329599,2,1,18 +2025-03-11T12:38:14.250259,479392697,17,174,7.04286750122,-5.042581906035,-10.28838907814,2,1,18 +2025-03-11T12:38:14.265884,479392697,17,174,6.73658772092,-5.343481517385,-9.732201245015,2,1,18 +2025-03-11T12:38:14.281509,479392697,17,174,6.43501993724,-5.648994047595,-9.185244019025,2,1,18 +2025-03-11T12:38:14.297134,479392697,17,174,6.12874015694,-5.959135802595,-8.652125021225,2,1,18 +2025-03-11T12:38:14.312759,479392697,17,174,5.82717237326,-6.24154297368,-8.1098816783,2,1,18 +2025-03-11T12:38:14.328384,479392697,17,174,5.5303165862,-6.55166842275,-7.562912693315,2,1,18 +2025-03-11T12:38:14.344009,479392697,17,174,5.23817279576,-6.85716464703,-7.0205902124,2,1,18 +2025-03-11T12:38:14.359634,479392697,17,174,4.93189301546,-7.153443186555,-6.482905651535,2,1,18 +2025-03-11T12:38:14.375259,479392697,17,174,4.63032523178,-7.458955716765,-5.93132724248,2,1,18 +2025-03-11T12:38:14.390884,479392697,17,174,4.33346944472,-7.76446009401,-5.384376797495,2,1,18 +2025-03-11T12:38:14.406509,479392697,17,174,4.0224776678,-8.06998893015,-4.8235424603,2,1,18 +2025-03-11T12:38:14.422134,479392697,17,174,3.73504587398,-8.366234857815,-4.267400291195,2,1,18 +2025-03-11T12:38:14.437759,479392697,17,174,3.44761408016,-8.657859713655,-3.72976139435,2,1,18 +2025-03-11T12:38:14.453384,479392697,17,174,3.13662230324,-8.94028319067,-3.19212567248,2,1,18 +2025-03-11T12:38:14.469009,479392697,17,174,2.83034252294,-9.236561730195,-2.63133519629,2,1,18 +2025-03-11T12:38:14.484634,479392697,17,174,2.52877473926,-9.54669533223,-2.06587469804,2,1,18 +2025-03-11T12:38:14.500259,479392697,17,174,2.25076693868,-9.861409241265,-1.509671930945,2,1,18 +2025-03-11T12:38:14.515884,479392697,17,174,1.96804714148,-10.166889159615,-0.981226561235001,2,1,18 +2025-03-11T12:38:14.531509,479392697,17,174,1.65234336794,-10.45394186142,-0.45280788449,2,1,18 +2025-03-11T12:38:14.547134,479392697,17,174,1.35077558426,-10.764075463455,0.0941678814999998,2,1,18 +2025-03-11T12:38:14.562759,479392697,17,174,1.04920780058,-11.06496692184,0.654970116685,2,1,18 +2025-03-11T12:38:14.578384,479392697,17,174,0.75235201352,-11.35660808361,1.206486124735,2,1,18 +2025-03-11T12:38:14.594009,479392697,17,174,0.4413602366,-11.666757991575,1.753475452735,2,1,18 +2025-03-11T12:38:14.609634,479392697,17,174,0.14921644616,-11.963012072205,2.29576085365,2,1,18 +2025-03-11T12:38:14.625259,479392697,17,174,-0.14292734428,-12.259266152835,2.838046254565,2,1,18 +2025-03-11T12:38:14.640884,479392697,17,174,-0.44449512796,-12.56939975487,3.37115847136,2,1,18 +2025-03-11T12:38:14.656509,479392697,17,174,-0.74135091502,-12.87952520394,3.92274863941,2,1,18 +2025-03-11T12:38:14.672134,479392697,17,174,-1.05234269194,-13.19429618373,4.474377690475,2,1,18 +2025-03-11T12:38:14.687759,479392697,17,174,-1.35391047562,-13.476703354815,5.02586339953,2,1,18 +2025-03-11T12:38:14.703384,479392697,17,174,-1.64605426606,-13.76833636362,5.56350907738,2,1,18 +2025-03-11T12:38:14.719009,479392697,17,174,-1.94762204974,-14.069227822005,6.105826580305,2,1,18 +2025-03-11T12:38:14.734634,479392697,17,174,-2.2444778368,-14.370111127425,6.63427375303,2,1,18 +2025-03-11T12:38:14.750259,479392697,17,174,-2.54604562048,-14.657139370335,7.167293269825,2,1,18 +2025-03-11T12:38:14.765884,479392697,17,174,-2.83818941092,-14.94877237914,7.704938947675,2,1,18 +2025-03-11T12:38:14.781509,479392697,17,174,-3.12562120474,-15.245018306805,8.237975201455,2,1,18 +2025-03-11T12:38:14.797134,479392697,17,174,-3.4224769918,-15.536659468575,8.78487002644,2,1,18 +2025-03-11T12:38:14.812759,479392697,17,174,-3.71933277886,-15.837542773995,9.32718074836,2,1,18 +2025-03-11T12:38:14.828384,479392697,17,174,-4.02090056254,-16.14767637603,9.86491414822,2,1,18 +2025-03-11T12:38:14.844009,479392697,17,174,-4.30833235636,-16.443922303695,10.397950402,2,1,18 +2025-03-11T12:38:14.859634,479392697,17,174,-4.58634015694,-16.74015192543,10.9402154599,2,1,18 +2025-03-11T12:38:14.875259,479392697,17,174,-4.883195944,-17.027172015375,11.48247056182,2,1,18 +2025-03-11T12:38:14.890884,479392697,17,174,-5.1894757243,-17.33269269855,12.020192202685,2,1,18 +2025-03-11T12:38:14.906509,479392697,17,174,-5.4957555046,-17.60586587895,12.53929933129,2,1,18 +2025-03-11T12:38:14.922134,479392697,17,174,-5.79732328828,-17.90213626551,13.072355928085,2,1,18 +2025-03-11T12:38:14.937759,479392697,17,174,-6.0847550821,-18.189140049525,13.60997628493,2,1,18 +2025-03-11T12:38:14.953384,479392697,17,174,-6.37689887254,-18.485394130155,14.133776953585,2,1,18 +2025-03-11T12:38:14.969009,479392697,17,174,-6.65961866974,-18.790874048505,14.662222323295,2,1,18 +2025-03-11T12:38:14.984634,479392697,17,174,-6.95176246018,-19.087128129135,15.209128907275,2,1,18 +2025-03-11T12:38:15.000259,479392697,17,174,-7.24861824724,-19.37414821908,15.742141643065,2,1,18 +2025-03-11T12:38:15.015884,479392697,17,174,-7.54076203768,-19.66116015606,16.289011147045,2,1,18 +2025-03-11T12:38:15.031509,479392697,17,174,-7.82348183488,-19.952776858935,16.81277971369,2,1,18 +2025-03-11T12:38:15.047134,479392697,17,174,-8.09677763884,-20.239756184055,17.33189499526,2,1,18 +2025-03-11T12:38:15.062759,479392697,17,174,-8.38892142928,-20.54063133651,17.86957775311,2,1,18 +2025-03-11T12:38:15.078384,479392697,17,174,-8.68577721634,-20.82303035463,18.397950765835,2,1,18 +2025-03-11T12:38:15.094009,479392697,17,174,-8.97320901016,-21.10541306682,18.91706785042,2,1,18 +2025-03-11T12:38:15.109634,479392697,17,174,-9.25121681074,-21.38777947308,19.43155018993,2,1,18 +2025-03-11T12:38:15.125259,479392697,17,174,-9.53864860456,-21.684025400745,19.93685934532,2,1,18 +2025-03-11T12:38:15.140884,479392697,17,174,-9.830792395,-21.99414269685,20.460715633975,2,1,18 +2025-03-11T12:38:15.156509,479392697,17,174,-10.12764818206,-22.28578385862,20.993746909765,2,1,18 +2025-03-11T12:38:15.172134,479392697,17,174,-10.40565598264,-22.57739240853,21.499023963145,2,1,18 +2025-03-11T12:38:15.187759,479392697,17,174,-10.67423978998,-22.855121437035,22.01809538371,2,1,18 +2025-03-11T12:38:15.203384,479392697,17,174,-10.95224759056,-23.12362462782,22.54176446935,2,1,18 +2025-03-11T12:38:15.219009,479392697,17,174,-11.25381537424,-23.406031798905,23.065523080015,2,1,18 +2025-03-11T12:38:15.234634,479392697,17,174,-11.54124716806,-23.697656654745,23.589298427665,2,1,18 +2025-03-11T12:38:15.250259,479392697,17,174,-11.8333909585,-23.984668591725,24.108440833255,2,1,18 +2025-03-11T12:38:15.265884,479392697,17,174,-12.10668676246,-24.25778470137,24.618258128695,2,1,18 +2025-03-11T12:38:15.281509,479392697,17,174,-12.3752705698,-24.535513729875,25.14657191539,2,1,18 +2025-03-11T12:38:15.297134,479392697,17,174,-12.66741436024,-24.81790459503,25.65645341485,2,1,18 +2025-03-11T12:38:15.312759,479392697,17,174,-12.9407101642,-25.0956417765,26.15704688416,2,1,18 +2025-03-11T12:38:15.328384,479392697,17,174,-13.19515798168,-25.39183063341,26.66692975558,2,1,18 +2025-03-11T12:38:15.344009,479392697,17,174,-13.47787777888,-25.674205192635,27.15831296077,2,1,18 +2025-03-11T12:38:15.359634,479392697,17,174,-13.76059757608,-25.933474392735,27.64960346596,2,1,18 +2025-03-11T12:38:15.375259,479392697,17,174,-14.04331737328,-26.21584895196,28.145607854215,2,1,18 +2025-03-11T12:38:15.390884,479392697,17,174,-14.31190118062,-26.502820124115,28.669337537845,2,1,18 +2025-03-11T12:38:15.406509,479392697,17,174,-14.58519698458,-26.76669409011,29.179117753285,2,1,18 +2025-03-11T12:38:15.422134,479392697,17,174,-14.85378079192,-27.035180974965,29.684288544655,2,1,18 +2025-03-11T12:38:15.437759,479392697,17,174,-15.12707659588,-27.30829708461,30.175621107835,2,1,18 +2025-03-11T12:38:15.453384,479392697,17,174,-15.40508439646,-27.58142134722,30.680824001215,2,1,18 +2025-03-11T12:38:15.469009,479392697,17,174,-15.66895620718,-27.85914222276,31.17678272545,2,1,18 +2025-03-11T12:38:15.484634,479392697,17,174,-15.95167600438,-28.13689571016,31.672768573705,2,1,18 +2025-03-11T12:38:15.500259,479392697,17,174,-16.2155478151,-28.3961322984,32.173274321005,2,1,18 +2025-03-11T12:38:15.515884,479392697,17,174,-16.47941962582,-28.659989958465,32.683040974435,2,1,18 +2025-03-11T12:38:15.531509,479392697,17,174,-16.74329143654,-28.91460547488,33.16042226641,2,1,18 +2025-03-11T12:38:15.547134,479392697,17,174,-17.0165872405,-29.19234265635,33.64253100346,2,1,18 +2025-03-11T12:38:15.562759,479392697,17,174,-17.28988304446,-29.46083769417,34.129223843575,2,1,18 +2025-03-11T12:38:15.578384,479392697,17,174,-17.55375485518,-29.724695354235,34.61588458168,2,1,18 +2025-03-11T12:38:15.594009,479392697,17,174,-17.82233866252,-29.988561167265,35.079446185465,2,1,18 +2025-03-11T12:38:15.609634,479392697,17,174,-18.08149847662,-30.25703174619,35.5614974995,2,1,18 +2025-03-11T12:38:15.625259,479392697,17,174,-18.35008228396,-30.52089755922,36.034301469415,2,1,18 +2025-03-11T12:38:15.640884,479392697,17,174,-18.61395409468,-30.77089200381,36.51166422139,2,1,18 +2025-03-11T12:38:15.656509,479392697,17,174,-18.86368991554,-31.03472520498,36.98906225035,2,1,18 +2025-03-11T12:38:15.672134,479392697,17,174,-19.11813773302,-31.30318763094,37.457243234185,2,1,18 +2025-03-11T12:38:15.687759,479392697,17,174,-19.38672154036,-31.56705344397,37.92080483797,2,1,18 +2025-03-11T12:38:15.703384,479392697,17,174,-19.64588135446,-31.82166080742,38.384315799745,2,1,18 +2025-03-11T12:38:15.719009,479392697,17,174,-19.89561717532,-32.07625186494,38.8755402979,2,1,18 +2025-03-11T12:38:15.734634,479392697,17,174,-20.1500649928,-32.3262300036,39.352889487865,2,1,18 +2025-03-11T12:38:15.750259,479392697,17,174,-20.40451281028,-32.580829214085,39.81177248557,2,1,18 +2025-03-11T12:38:15.765884,479392697,17,174,-20.65896062776,-32.858533783695,40.279990549405,2,1,18 +2025-03-11T12:38:15.781509,479392697,17,174,-20.92283243848,-33.11314930011,40.752750658315,2,1,18 +2025-03-11T12:38:15.797134,479392697,17,174,-21.17256825934,-33.35849821398,41.202347428885,2,1,18 +2025-03-11T12:38:15.812759,479392697,17,174,-21.43172807344,-33.608484505605,41.661218667595,2,1,18 +2025-03-11T12:38:15.828384,479392697,17,174,-21.68617589092,-33.86308371609,42.11085929917,2,1,18 +2025-03-11T12:38:15.844009,479392697,17,174,-21.92648771854,-34.113037395855,42.5512186816,2,1,18 +2025-03-11T12:38:15.859634,479392697,17,174,-22.16208754954,-34.35836185083,42.991552743025,2,1,18 +2025-03-11T12:38:15.875259,479392697,17,174,-22.40711137378,-34.60832368356,43.427297723395,2,1,18 +2025-03-11T12:38:15.890884,479392697,17,174,-22.66627118788,-34.83520461606,43.88145507904,2,1,18 +2025-03-11T12:38:15.906509,479392697,17,174,-22.90187101888,-35.08515014286,44.340292412725,2,1,18 +2025-03-11T12:38:15.922134,479392697,17,174,-23.13747084988,-35.330474597835,44.78062647415,2,1,18 +2025-03-11T12:38:15.937759,479392697,17,174,-23.3777826775,-35.566565062125,45.22093023658,2,1,18 +2025-03-11T12:38:15.953384,479392697,17,174,-23.62280650174,-35.788800463905,45.65656397695,2,1,18 +2025-03-11T12:38:15.969009,479392697,17,174,-23.86311832936,-36.024890928195,46.09686773938,2,1,18 +2025-03-11T12:38:15.984634,479392697,17,174,-24.10343015698,-36.27484460796,46.532605938745,2,1,18 +2025-03-11T12:38:16.000259,479392697,17,174,-24.33431799136,-36.524781981795,46.954467026905,2,1,18 +2025-03-11T12:38:16.015884,479392697,17,174,-24.5557818325,-36.760839834225,47.37163774999,2,1,18 +2025-03-11T12:38:16.031509,479392697,17,174,-24.77724567364,-36.978413399355,47.770249580815,2,1,18 +2025-03-11T12:38:16.047134,479392697,17,174,-25.01284550464,-37.20525356703,48.196645933045,2,1,18 +2025-03-11T12:38:16.062759,479392697,17,174,-25.25786932888,-37.459836471585,48.63703063648,2,1,18 +2025-03-11T12:38:16.078384,479392697,17,174,-25.46990917678,-37.677393730785,49.04949245449,2,1,18 +2025-03-11T12:38:16.094009,479392697,17,174,-25.70079701116,-37.913467889145,49.457434373455,2,1,18 +2025-03-11T12:38:16.109634,479392697,17,174,-25.9458208354,-38.1495665064,49.874639001565,2,1,18 +2025-03-11T12:38:16.125259,479392697,17,174,-26.1814206664,-38.385648817725,50.29645125073,2,1,18 +2025-03-11T12:38:16.140884,479392697,17,174,-26.40288450754,-38.612464526505,50.695100161555,2,1,18 +2025-03-11T12:38:16.156509,479392697,17,174,-26.6055003622,-38.82538440795,51.107529877555,2,1,18 +2025-03-11T12:38:16.172134,479392697,17,174,-26.83167619996,-39.03834505422,51.53847823084,2,1,18 +2025-03-11T12:38:16.187759,479392697,17,174,-27.04371604786,-39.25590231342,51.93245531659,2,1,18 +2025-03-11T12:38:16.203384,479392697,17,174,-27.26046789238,-39.473467725585,52.32181800028,2,1,18 +2025-03-11T12:38:16.219009,479392697,17,174,-27.47250774028,-39.69564605661,52.7065712599,2,1,18 +2025-03-11T12:38:16.234634,479392697,17,174,-27.6892595848,-39.913211468775,53.10517630972,2,1,18 +2025-03-11T12:38:16.250259,479392697,17,174,-27.91543542256,-40.13079318687,53.508416104615,2,1,18 +2025-03-11T12:38:16.265884,479392697,17,174,-28.1368992637,-40.352987823825,53.911667658505,2,1,18 +2025-03-11T12:38:16.281509,479392697,17,174,-28.35365110822,-40.56131109234,54.29637207913,2,1,18 +2025-03-11T12:38:16.297134,479392697,17,174,-28.57511494936,-40.765021441995,54.685685923825,2,1,18 +2025-03-11T12:38:16.312759,479392697,17,174,-28.7965787905,-40.973352863475,55.070397125455,2,1,18 +2025-03-11T12:38:16.328384,479392697,17,174,-28.99919464516,-41.181651673095,55.445838836935,2,1,18 +2025-03-11T12:38:16.344009,479392697,17,174,-29.1970985032,-41.385321257925,55.83973995967,2,1,18 +2025-03-11T12:38:16.359634,479392697,17,174,-29.39971435786,-41.602862211195,56.21521875115,2,1,18 +2025-03-11T12:38:16.375259,479392697,17,174,-29.60704220914,-41.80192703013,56.572145431375,2,1,18 +2025-03-11T12:38:16.390884,479392697,17,174,-29.80494606718,-42.000975543135,56.94754328185,2,1,18 +2025-03-11T12:38:16.406509,479392697,17,174,-30.00284992522,-42.204645127965,57.32758085539,2,1,18 +2025-03-11T12:38:16.422134,479392697,17,174,-30.19604178664,-42.403685488005,57.689108375665,2,1,18 +2025-03-11T12:38:16.437759,479392697,17,174,-30.40808163454,-42.60737953173,58.04143919383,2,1,18 +2025-03-11T12:38:16.453384,479392697,17,174,-30.61540948582,-42.81106542249,58.39376323099,2,1,18 +2025-03-11T12:38:16.469009,479392697,17,174,-30.80860134724,-43.01934792618,58.7507066482,2,1,18 +2025-03-11T12:38:16.484634,479392697,17,174,-30.99708121204,-43.21375906143,59.107587664405,2,1,18 +2025-03-11T12:38:16.500259,479392697,17,174,-31.1761370836,-43.38966960345,59.450517409405,2,1,18 +2025-03-11T12:38:16.515884,479392697,17,174,-31.38346493488,-43.56562906326,59.80735138963,2,1,18 +2025-03-11T12:38:16.531509,479392697,17,174,-31.5766567963,-43.760048351475,60.168860369905,2,1,18 +2025-03-11T12:38:16.547134,479392697,17,174,-31.75571266786,-43.95906425262,60.50726163184,2,1,18 +2025-03-11T12:38:16.562759,479392697,17,174,-31.93476853942,-44.148838010115,60.85948936297,2,1,18 +2025-03-11T12:38:16.578384,479392697,17,174,-32.13267239746,-44.352507594945,61.1748303736,2,1,18 +2025-03-11T12:38:16.594009,479392697,17,174,-32.32115226226,-44.546918730195,61.522469023675,2,1,18 +2025-03-11T12:38:16.609634,479392697,17,174,-32.4954961372,-44.727442191075,61.85616816154,2,1,18 +2025-03-11T12:38:16.625259,479392697,17,174,-32.6604160189,-44.907949346025,62.16674782207,2,1,18 +2025-03-11T12:38:16.640884,479392697,17,174,-32.84418388708,-45.088489112835,62.500460521945,2,1,18 +2025-03-11T12:38:16.656509,479392697,17,174,-33.02323975864,-45.25053643938,62.82947109775,2,1,18 +2025-03-11T12:38:16.672134,479392697,17,174,-33.19758363358,-45.435680972085,63.135461677225,2,1,18 +2025-03-11T12:38:16.687759,479392697,17,174,-33.37192750852,-45.606962289315,63.45063900283,2,1,18 +2025-03-11T12:38:16.703384,479392697,17,174,-33.5556953767,-45.764396697,63.77039545351,2,1,18 +2025-03-11T12:38:16.719009,479392697,17,174,-33.7206152584,-45.931040636475,64.067055944845,2,1,18 +2025-03-11T12:38:16.734634,479392697,17,174,-33.88082314348,-46.106918566635,64.37761028437,2,1,18 +2025-03-11T12:38:16.750259,479392697,17,174,-34.0504550218,-46.273570659075,64.68351992284,2,1,18 +2025-03-11T12:38:16.765884,479392697,17,174,-34.2153749035,-46.42173031125,64.98472743724,2,1,18 +2025-03-11T12:38:16.781509,479392697,17,174,-34.38500678182,-46.593003475515,65.27217088345,2,1,18 +2025-03-11T12:38:16.797134,479392697,17,174,-34.55463866014,-46.768897711605,65.573496418855,2,1,18 +2025-03-11T12:38:16.812759,479392697,17,174,-34.71955854184,-46.91705736378,65.856219200995,2,1,18 +2025-03-11T12:38:16.828384,479392697,17,174,-34.87976642692,-47.06520886299,66.152798751325,2,1,18 +2025-03-11T12:38:16.844009,479392697,17,174,-35.03055031876,-47.23182834357,66.44481771658,2,1,18 +2025-03-11T12:38:16.859634,479392697,17,174,-35.1813342106,-47.3892056805,66.727557235705,2,1,18 +2025-03-11T12:38:16.875259,479392697,17,174,-35.33211810244,-47.53734087378,67.005638491765,2,1,18 +2025-03-11T12:38:16.890884,479392697,17,174,-35.4876139909,-47.6993474355,67.279160965765,2,1,18 +2025-03-11T12:38:16.906509,479392697,17,174,-35.63839788274,-47.852103700605,67.57112431102,2,1,18 +2025-03-11T12:38:16.922134,479392697,17,174,-35.79860576782,-48.01411841529,67.84927474909,2,1,18 +2025-03-11T12:38:16.937759,479392697,17,174,-35.94938965966,-48.166874680395,68.13661691128,2,1,18 +2025-03-11T12:38:16.953384,479392697,17,174,-36.08132556502,-48.30111404634,68.39613069106,2,1,18 +2025-03-11T12:38:16.969009,479392697,17,174,-36.22268546362,-48.43999079004,68.641813023655,2,1,18 +2025-03-11T12:38:16.984634,479392697,17,174,-36.35462136898,-48.56960908416,68.882823531175,2,1,18 +2025-03-11T12:38:17.000259,479392697,17,174,-36.49126927096,-48.71309874672,69.1238964397,2,1,18 +2025-03-11T12:38:17.015884,479392697,17,174,-36.64676515942,-48.861242092965,69.383499744505,2,1,18 +2025-03-11T12:38:17.031509,479392697,17,174,-36.78812505802,-48.98625562119,69.63836882323,2,1,18 +2025-03-11T12:38:17.047134,479392697,17,174,-36.91063697014,-49.129720824855,69.893284937935,2,1,18 +2025-03-11T12:38:17.062759,479392697,17,174,-37.05199686874,-49.268597568555,70.1297249044,2,1,18 +2025-03-11T12:38:17.078384,479392697,17,174,-37.17922077748,-49.402828781535,70.35688362172,2,1,18 +2025-03-11T12:38:17.094009,479392697,17,174,-37.31115668284,-49.532447075655,70.602515312305,2,1,18 +2025-03-11T12:38:17.109634,479392697,17,174,-37.43838059158,-49.66205721681,70.838897855755,2,1,18 +2025-03-11T12:38:17.125259,479392697,17,174,-37.5608925037,-49.787038133175,71.08449744433,2,1,18 +2025-03-11T12:38:17.140884,479392697,17,174,-37.69282840906,-49.92127749912,71.302420576525,2,1,18 +2025-03-11T12:38:17.156509,479392697,17,174,-37.82476431442,-50.03241150594,71.524872191785,2,1,18 +2025-03-11T12:38:17.172134,479392697,17,174,-37.94256422992,-50.14814212569,71.75656437016,2,1,18 +2025-03-11T12:38:17.187759,479392697,17,174,-38.0556521488,-50.273106736125,71.946696199945,2,1,18 +2025-03-11T12:38:17.203384,479392697,17,174,-38.16402807106,-50.388821049945,72.173753633245,2,1,18 +2025-03-11T12:38:17.219009,479392697,17,174,-38.28653998318,-50.518423038135,72.387023480365,2,1,18 +2025-03-11T12:38:17.234634,479392697,17,174,-38.39962790206,-50.62490336127,72.60480824854,2,1,18 +2025-03-11T12:38:17.250259,479392697,17,174,-38.5268518108,-50.7314081433,72.82261335973,2,1,18 +2025-03-11T12:38:17.265884,479392697,17,174,-38.63522773306,-50.84712245712,73.008080145445,2,1,18 +2025-03-11T12:38:17.281509,479392697,17,174,-38.75302764856,-50.967474148695,73.21206376543,2,1,18 +2025-03-11T12:38:17.297134,479392697,17,174,-38.86611556744,-51.07395447183,73.41598498441,2,1,18 +2025-03-11T12:38:17.312759,479392697,17,174,-38.96035549984,-51.17578111128,73.59213344098,2,1,18 +2025-03-11T12:38:17.328384,479392697,17,174,-39.04988343562,-51.268357454115,73.77285921961,2,1,18 +2025-03-11T12:38:17.344009,479392697,17,174,-39.14883536464,-51.37019224653,73.95363564025,2,1,18 +2025-03-11T12:38:17.359634,479392697,17,174,-39.25249929028,-51.467414120085,74.12977911883,2,1,18 +2025-03-11T12:38:17.375259,479392697,17,174,-39.3514512193,-51.5692489125,74.31055553947,2,1,18 +2025-03-11T12:38:17.390884,479392697,17,174,-39.45040314832,-51.661841561265,74.495916063175,2,1,18 +2025-03-11T12:38:17.406509,479392697,17,174,-39.54935507734,-51.740570994555,74.648872685425,2,1,18 +2025-03-11T12:38:17.422134,479392697,17,174,-39.64359500974,-51.82853441853,74.815723155865,2,1,18 +2025-03-11T12:38:17.437759,479392697,17,174,-39.73312294552,-51.921110761365,74.968721836105,2,1,18 +2025-03-11T12:38:17.453384,479392697,17,174,-39.81793888468,-52.013678951235,75.12171373534,2,1,18 +2025-03-11T12:38:17.469009,479392697,17,174,-39.90275482384,-52.12011035658,75.293245986835,2,1,18 +2025-03-11T12:38:17.484634,479392697,17,174,-39.987570763,-52.217299618275,75.47398352446,2,1,18 +2025-03-11T12:38:17.500259,479392697,17,174,-40.05353871568,-52.28672983716,75.63147678274,2,1,18 +2025-03-11T12:38:17.515884,479392697,17,174,-40.13364265822,-52.351563443115,75.77510829484,2,1,18 +2025-03-11T12:38:17.531509,479392697,17,174,-40.21845859738,-52.42102627386,75.92338631101,2,1,18 +2025-03-11T12:38:17.547134,479392697,17,174,-40.29856253992,-52.495102023465,76.053191353915,2,1,18 +2025-03-11T12:38:17.562759,479392697,17,174,-40.37395448584,-52.569169620105,76.17836843275,2,1,18 +2025-03-11T12:38:17.578384,479392697,17,174,-40.44934643176,-52.63861614492,76.303526971585,2,1,18 +2025-03-11T12:38:17.594009,479392697,17,174,-40.52473837768,-52.71268374156,76.433325233485,2,1,18 +2025-03-11T12:38:17.609634,479392697,17,174,-40.57185834388,-52.782081348585,76.563064269355,2,1,18 +2025-03-11T12:38:17.625259,479392697,17,174,-40.63311429994,-52.842261270855,76.69278656824,2,1,18 +2025-03-11T12:38:17.640884,479392697,17,174,-40.69908225262,-52.897828274265,76.79477000974,2,1,18 +2025-03-11T12:38:17.656509,479392697,17,174,-40.7650502053,-52.9580163495,76.89677199124,2,1,18 +2025-03-11T12:38:17.672134,479392697,17,174,-40.8357301546,-53.02745472135,76.998817833745,2,1,18 +2025-03-11T12:38:17.687759,479392697,17,174,-40.89227411404,-53.08300541883,77.11465126243,2,1,18 +2025-03-11T12:38:17.703384,479392697,17,174,-40.94410607686,-53.13392689152,77.23045937011,2,1,18 +2025-03-11T12:38:17.719009,479392697,17,174,-40.99593803968,-53.198711579685,77.332459548595,2,1,18 +2025-03-11T12:38:17.734634,479392697,17,174,-41.0477700025,-53.268117339675,77.42523590095,2,1,18 +2025-03-11T12:38:17.750259,479392697,17,174,-41.11373795518,-53.32830541491,77.51799551632,2,1,18 +2025-03-11T12:38:17.765884,479392697,17,174,-41.165569918,-53.374605815775,77.610679168675,2,1,18 +2025-03-11T12:38:17.781509,479392697,17,174,-41.21740188082,-53.416285144815,77.70334428103,2,1,18 +2025-03-11T12:38:17.797134,479392697,17,174,-41.25509785378,-53.434834655835,77.78665398424,2,1,18 +2025-03-11T12:38:17.812759,479392697,17,174,-41.30221781998,-53.481126903735,77.837740208005,2,1,18 +2025-03-11T12:38:17.828384,479392697,17,174,-41.3540497828,-53.53666944825,77.907355025035,2,1,18 +2025-03-11T12:38:17.844009,479392697,17,174,-41.39645775238,-53.58757461501,77.986180106185,2,1,18 +2025-03-11T12:38:17.859634,479392697,17,174,-41.41530573886,-53.61533365782,78.06487858231,2,1,18 +2025-03-11T12:38:17.875259,479392697,17,174,-41.46242570506,-53.67086804937,78.134486618335,2,1,18 +2025-03-11T12:38:17.890884,479392697,17,174,-41.4954096814,-53.717135838375,78.19941604828,2,1,18 +2025-03-11T12:38:17.906509,479392697,17,174,-41.52368166112,-53.744911187115,78.241158621895,2,1,18 +2025-03-11T12:38:17.922134,479392697,17,174,-41.5425296476,-53.772670229925,78.315235914955,2,1,18 +2025-03-11T12:38:17.937759,479392697,17,174,-41.5660896307,-53.79119528205,78.38004054289,2,1,18 +2025-03-11T12:38:17.953384,479392697,17,174,-41.59907360704,-53.81435771193,78.426392540575,2,1,18 +2025-03-11T12:38:17.969009,479392697,17,174,-41.63205758338,-53.823656926335,78.458825369065,2,1,18 +2025-03-11T12:38:17.984634,479392697,17,174,-41.65090556986,-53.842173825495,78.50051730067,2,1,18 +2025-03-11T12:38:18.000198,479392701,13,175,-41.6603295631,-53.8745376342,78.5376301072,2,1,18 +2025-03-11T12:38:18.015823,479392701,13,175,-41.6838895462,-53.8884416145,78.55158318142,2,1,18 +2025-03-11T12:38:18.031448,479392701,13,175,-41.70273753268,-53.88847422636,78.583958586895,2,1,18 +2025-03-11T12:38:18.047073,479392701,13,175,-41.7074495293,-53.897724522975,78.607108363225,2,1,18 +2025-03-11T12:38:18.062698,479392701,13,175,-41.71216152592,-53.920838035065,78.630313759555,2,1,18 +2025-03-11T12:38:18.078323,479392701,13,175,-41.72629751578,-53.93934678126,78.653514177895,2,1,18 +2025-03-11T12:38:18.093948,479392701,13,175,-41.75928149212,-53.939403852015,78.667425194125,2,1,18 +2025-03-11T12:38:18.109573,479392701,13,175,-41.76399348874,-53.934790933155,78.658171069,2,1,18 +2025-03-11T12:38:18.125198,479392701,13,175,-41.76399348874,-53.934790933155,78.653549885935,2,1,18 +2025-03-11T12:38:18.140823,479392701,13,175,-41.75928149212,-53.95326706749,78.66285963106,2,1,18 +2025-03-11T12:38:18.156448,479392701,13,175,-41.76870548536,-53.948662301595,78.6720970192,2,1,18 +2025-03-11T12:38:18.172073,479392701,13,175,-41.76870548536,-53.930178014295,78.676644042265,2,1,18 +2025-03-11T12:38:18.187698,479392701,13,175,-41.76399348874,-53.93016986133,78.672016078195,2,1,18 +2025-03-11T12:38:18.203323,479392701,13,175,-41.7545694955,-53.9301535554,78.64889660086,2,1,18 +2025-03-11T12:38:18.218948,479392701,13,175,-41.74514550226,-53.925516177645,78.63962213272,2,1,18 +2025-03-11T12:38:18.234573,479392701,13,175,-41.74043350564,-53.92550802468,78.62575180252,2,1,18 +2025-03-11T12:38:18.250198,479392701,13,175,-41.73572150902,-53.907015584415,78.59332258006,2,1,18 +2025-03-11T12:38:18.265823,479392701,13,175,-41.72629751578,-53.89313606301,78.5470415674,2,1,18 +2025-03-11T12:38:18.281448,479392701,13,175,-41.7074495293,-53.888482379325,78.533132354185,2,1,18 +2025-03-11T12:38:18.297073,479392701,13,175,-41.6838895462,-53.8699573272,78.5145395569,2,1,18 +2025-03-11T12:38:18.312698,479392701,13,175,-41.65090556986,-53.86527918462,78.50061000067,2,1,18 +2025-03-11T12:38:18.328323,479392701,13,175,-41.64148157662,-53.83753644774,78.449652184945,2,1,18 +2025-03-11T12:38:18.343948,479392701,13,175,-41.62734558676,-53.80516448607,78.398669048215,2,1,18 +2025-03-11T12:38:18.359573,479392701,13,175,-41.59436161042,-53.76351776889,78.356864073595,2,1,18 +2025-03-11T12:38:18.375198,479392701,13,175,-41.58022562056,-53.74038795087,78.305918016865,2,1,18 +2025-03-11T12:38:18.390823,479392701,13,175,-41.56137763408,-53.717249979885,78.245722813,2,1,18 +2025-03-11T12:38:18.406448,479392701,13,175,-41.52368166112,-53.689458325215,78.18086076205,2,1,18 +2025-03-11T12:38:18.422073,479392701,13,175,-41.48598568816,-53.63856131142,78.12514837723,2,1,18 +2025-03-11T12:38:18.437698,479392701,13,175,-41.46242570506,-53.60617304382,78.060288129295,2,1,18 +2025-03-11T12:38:18.453323,479392701,13,175,-41.42001773548,-53.58299430801,77.990816654275,2,1,18 +2025-03-11T12:38:18.468948,479392701,13,175,-41.3776097659,-53.5413312849,77.939755751515,2,1,18 +2025-03-11T12:38:18.484573,479392701,13,175,-41.33520179632,-53.49042611814,77.860930670365,2,1,18 +2025-03-11T12:38:18.500198,479392701,13,175,-41.30221781998,-53.444158329135,77.78675887429,2,1,18 +2025-03-11T12:38:18.515823,479392701,13,175,-41.25038585716,-53.40710007192,77.70797585113,2,1,18 +2025-03-11T12:38:18.531448,479392701,13,175,-41.19855389434,-53.360799671055,77.61067101571,2,1,18 +2025-03-11T12:38:18.547073,479392701,13,175,-41.15614592476,-53.30527343247,77.517963845365,2,1,18 +2025-03-11T12:38:18.562698,479392701,13,175,-41.11373795518,-53.249747193885,77.41601430889,2,1,18 +2025-03-11T12:38:18.578323,479392701,13,175,-41.06661798898,-53.19883387416,77.33256126367,2,1,18 +2025-03-11T12:38:18.593948,479392701,13,175,-41.0006500363,-53.1340247271,77.225919559105,2,1,18 +2025-03-11T12:38:18.609573,479392701,13,175,-40.93468208362,-53.073836651865,77.105432845345,2,1,18 +2025-03-11T12:38:18.625198,479392701,13,175,-40.87813812418,-53.027528098035,76.985015313595,2,1,18 +2025-03-11T12:38:18.640823,479392701,13,175,-40.80745817488,-52.967331869835,76.878385368025,2,1,18 +2025-03-11T12:38:18.656448,479392701,13,175,-40.75091421544,-52.911781172355,76.776415488535,2,1,18 +2025-03-11T12:38:18.672073,479392701,13,175,-40.68965825938,-52.85622232191,76.669817644975,2,1,18 +2025-03-11T12:38:18.687698,479392701,13,175,-40.61897831008,-52.78678395006,76.544665887145,2,1,18 +2025-03-11T12:38:18.703323,479392701,13,175,-40.54358636416,-52.72195849707,76.41952588831,2,1,18 +2025-03-11T12:38:18.718948,479392701,13,175,-40.49175440134,-52.647931665255,76.2943827145,2,1,18 +2025-03-11T12:38:18.734573,479392701,13,175,-40.42107445204,-52.569251149755,76.1784362428,2,1,18 +2025-03-11T12:38:18.750198,479392701,13,175,-40.35510649936,-52.49982093087,76.044048899845,2,1,18 +2025-03-11T12:38:18.765823,479392701,13,175,-40.28442655006,-52.42114041537,75.900375329755,2,1,18 +2025-03-11T12:38:18.781448,479392701,13,175,-40.18547462104,-52.337789910255,75.74277898444,2,1,18 +2025-03-11T12:38:18.797073,479392701,13,175,-40.09594668526,-52.259076782895,75.60832065646,2,1,18 +2025-03-11T12:38:18.812698,479392701,13,175,-40.01584274272,-52.189622105115,75.45542823823,2,1,18 +2025-03-11T12:38:18.828323,479392701,13,175,-39.94516279342,-52.092457302315,75.30243814201,2,1,18 +2025-03-11T12:38:18.843948,479392701,13,175,-39.86034685426,-52.00451018427,75.140222416645,2,1,18 +2025-03-11T12:38:18.859573,479392701,13,175,-39.76139492524,-51.92578075098,74.98264461133,2,1,18 +2025-03-11T12:38:18.875198,479392701,13,175,-39.6812909827,-51.833220714075,74.825038310035,2,1,18 +2025-03-11T12:38:18.890823,479392701,13,175,-39.60118704016,-51.745281748995,74.662829365675,2,1,18 +2025-03-11T12:38:18.906448,479392701,13,175,-39.50694710776,-51.65731832502,74.49135771217,2,1,18 +2025-03-11T12:38:18.922073,479392701,13,175,-39.40328318212,-51.560096451465,74.329077782785,2,1,18 +2025-03-11T12:38:18.937698,479392701,13,175,-39.30904324972,-51.45364874019,74.143668420085,2,1,18 +2025-03-11T12:38:18.953323,479392701,13,175,-39.22422731056,-51.37956483762,73.96302358246,2,1,18 +2025-03-11T12:38:18.968948,479392701,13,175,-39.12527538154,-51.29159326068,73.79154514795,2,1,18 +2025-03-11T12:38:18.984573,479392701,13,175,-39.02632345252,-51.17589525279,73.596849558115,2,1,18 +2025-03-11T12:38:19.000198,479392701,13,175,-38.90852353702,-51.064785704865,73.39290301813,2,1,18 +2025-03-11T12:38:19.015823,479392701,13,175,-38.7860116249,-50.962910147625,73.2074715094,2,1,18 +2025-03-11T12:38:19.031448,479392701,13,175,-38.68705969588,-50.87031749886,73.0082474365,2,1,18 +2025-03-11T12:38:19.047073,479392701,13,175,-38.59281976348,-50.75924871576,72.81357716767,2,1,18 +2025-03-11T12:38:19.062698,479392701,13,175,-38.48915583784,-50.62967933943,72.6095768107,2,1,18 +2025-03-11T12:38:19.078323,479392701,13,175,-38.39491590544,-50.50936841268,72.419490644935,2,1,18 +2025-03-11T12:38:19.093948,479392701,13,175,-38.2676919967,-50.38437934335,72.20623255681,2,1,18 +2025-03-11T12:38:19.109573,479392701,13,175,-38.1498920812,-50.264027651775,71.9791430215,2,1,18 +2025-03-11T12:38:19.125198,479392701,13,175,-38.03680416232,-50.143684113165,71.75668145026,2,1,18 +2025-03-11T12:38:19.140823,479392701,13,175,-37.9142922502,-50.02794534045,71.53422485701,2,1,18 +2025-03-11T12:38:19.156448,479392701,13,175,-37.78706834146,-49.90295627112,71.31634558582,2,1,18 +2025-03-11T12:38:19.172073,479392701,13,175,-37.67398042258,-49.787233804335,71.09390255458,2,1,18 +2025-03-11T12:38:19.187698,479392701,13,175,-37.54204451722,-49.666857653865,70.86217149319,2,1,18 +2025-03-11T12:38:19.203323,479392701,13,175,-37.41010861186,-49.527997216095,70.616502722605,2,1,18 +2025-03-11T12:38:19.218948,479392701,13,175,-37.28759669974,-49.389153084255,70.384711063225,2,1,18 +2025-03-11T12:38:19.234573,479392701,13,175,-37.17450878086,-49.259567401995,70.14834886279,2,1,18 +2025-03-11T12:38:19.250198,479392701,13,175,-37.04728487212,-49.12995726084,69.90272395321,2,1,18 +2025-03-11T12:38:19.265823,479392701,13,175,-36.9012129769,-48.991072364175,69.661656022675,2,1,18 +2025-03-11T12:38:19.281448,479392701,13,175,-36.75514108168,-48.866050682985,69.42064371214,2,1,18 +2025-03-11T12:38:19.297073,479392701,13,175,-36.61378118308,-48.70406858016,69.147141581155,2,1,18 +2025-03-11T12:38:19.312698,479392701,13,175,-36.48655727434,-48.56983736718,68.88763458238,2,1,18 +2025-03-11T12:38:19.328323,479392701,13,175,-36.34990937236,-48.421726632795,68.618816035465,2,1,18 +2025-03-11T12:38:19.343948,479392701,13,175,-36.20383747714,-48.27359959248,68.354605109605,2,1,18 +2025-03-11T12:38:19.359573,479392701,13,175,-36.0766135684,-48.134747307675,68.108943120025,2,1,18 +2025-03-11T12:38:19.375198,479392701,13,175,-35.92111767994,-47.981982889605,67.853942458285,2,1,18 +2025-03-11T12:38:19.390823,479392701,13,175,-35.75148580162,-47.843057228115,67.5897347074,2,1,18 +2025-03-11T12:38:19.406448,479392701,13,175,-35.6054139064,-47.68568804415,67.311623152345,2,1,18 +2025-03-11T12:38:19.422073,479392701,13,175,-35.44991801794,-47.537544697905,67.03353511528,2,1,18 +2025-03-11T12:38:19.437698,479392701,13,175,-35.30384612272,-47.375554442115,66.74154147103,2,1,18 +2025-03-11T12:38:19.453323,479392701,13,175,-35.14835023426,-47.20892680857,66.444894541705,2,1,18 +2025-03-11T12:38:19.468948,479392701,13,175,-34.97871835594,-47.04227471613,66.157469635495,2,1,18 +2025-03-11T12:38:19.484573,479392701,13,175,-34.83264646072,-46.866421244865,65.87928392044,2,1,18 +2025-03-11T12:38:19.500198,479392701,13,175,-34.66772657902,-46.71826159269,65.57807640604,2,1,18 +2025-03-11T12:38:19.515823,479392701,13,175,-34.4980947007,-46.574714859375,65.27225946757,2,1,18 +2025-03-11T12:38:19.531448,479392701,13,175,-34.34259881224,-46.40808722583,64.96174898905,2,1,18 +2025-03-11T12:38:19.547073,479392701,13,175,-34.1682549373,-46.250669124075,64.6789755649,2,1,18 +2025-03-11T12:38:19.562698,479392701,13,175,-33.99862305898,-46.07939595981,64.3638050203,2,1,18 +2025-03-11T12:38:19.578323,479392701,13,175,-33.83370317728,-45.912752020335,64.05328097977,2,1,18 +2025-03-11T12:38:19.593948,479392701,13,175,-33.66878329558,-45.750729152685,63.756639028435,2,1,18 +2025-03-11T12:38:19.609573,479392701,13,175,-33.49915141726,-45.56097170112,63.450636689965,2,1,18 +2025-03-11T12:38:19.625198,479392701,13,175,-33.32480754232,-45.375827168415,63.130782561295,2,1,18 +2025-03-11T12:38:19.640823,479392701,13,175,-33.14103967414,-45.20915061708,62.810989030615,2,1,18 +2025-03-11T12:38:19.656448,479392701,13,175,-32.95727180596,-45.04709513757,62.491214039935,2,1,18 +2025-03-11T12:38:19.672073,479392701,13,175,-32.7782159344,-44.866563523725,62.17137167026,2,1,18 +2025-03-11T12:38:19.687698,479392701,13,175,-32.61800804932,-44.67682237809,61.842276978475,2,1,18 +2025-03-11T12:38:19.703323,479392701,13,175,-32.43424018114,-44.500903683105,61.5085828186,2,1,18 +2025-03-11T12:38:19.718948,479392701,13,175,-32.24576031634,-44.31111361968,61.179447440785,2,1,18 +2025-03-11T12:38:19.734573,479392701,13,175,-32.08555243126,-44.12599354587,60.827265373675,2,1,18 +2025-03-11T12:38:19.750198,479392701,13,175,-31.89236056984,-43.950058544955,60.479694102595,2,1,18 +2025-03-11T12:38:19.765823,479392701,13,175,-31.70388070504,-43.764889553355,60.14133489865,2,1,18 +2025-03-11T12:38:19.781448,479392701,13,175,-31.52482483348,-43.579736867685,59.802989256715,2,1,18 +2025-03-11T12:38:19.797073,479392701,13,175,-31.32692097544,-43.38068835468,59.4460761385,2,1,18 +2025-03-11T12:38:19.812698,479392701,13,175,-31.12430512078,-43.167768473235,59.093721802345,2,1,18 +2025-03-11T12:38:19.828323,479392701,13,175,-30.9405372526,-42.968744419125,58.75069257634,2,1,18 +2025-03-11T12:38:19.843948,479392701,13,175,-30.74734539118,-42.788188346385,58.384618033,2,1,18 +2025-03-11T12:38:19.859573,479392701,13,175,-30.563577523,-42.598406435925,58.023141154735,2,1,18 +2025-03-11T12:38:19.875198,479392701,13,175,-30.35624967172,-42.403962688815,57.67547538064,2,1,18 +2025-03-11T12:38:19.890823,479392701,13,175,-30.15363381706,-42.20028495102,57.30005220916,2,1,18 +2025-03-11T12:38:19.906448,479392701,13,175,-29.95572995902,-41.98737322254,56.92921992175,2,1,18 +2025-03-11T12:38:19.922073,479392701,13,175,-29.77196209084,-41.783728096605,56.549202691225,2,1,18 +2025-03-11T12:38:19.937698,479392701,13,175,-29.55992224294,-41.584655124705,56.1784056808,2,1,18 +2025-03-11T12:38:19.953323,479392701,13,175,-29.36673038152,-41.39023583649,55.80303315133,2,1,18 +2025-03-11T12:38:19.968948,479392701,13,175,-29.16411452686,-41.17269488322,55.432175542915,2,1,18 +2025-03-11T12:38:19.984573,479392701,13,175,-28.92851469586,-40.964339002845,55.06592873053,2,1,18 +2025-03-11T12:38:20.000198,479392701,13,175,-28.72118684458,-40.75603204026,54.690480238045,2,1,18 +2025-03-11T12:38:20.015823,479392701,13,175,-28.51857098992,-40.54773323064,54.3104173435,2,1,18 +2025-03-11T12:38:20.031448,479392701,13,175,-28.30653114202,-40.32093382779,53.92564554388,2,1,18 +2025-03-11T12:38:20.047073,479392701,13,175,-28.08506730088,-40.107981334485,53.536294619185,2,1,18 +2025-03-11T12:38:20.062698,479392701,13,175,-27.8777394496,-39.89043222825,53.128460765245,2,1,18 +2025-03-11T12:38:20.078323,479392701,13,175,-27.67512359494,-39.659028059505,52.72057807231,2,1,18 +2025-03-11T12:38:20.093948,479392701,13,175,-27.46308374704,-39.44609187213,52.32661952656,2,1,18 +2025-03-11T12:38:20.109573,479392701,13,175,-27.2416199059,-39.233139378825,51.937268601865,2,1,18 +2025-03-11T12:38:20.125198,479392701,13,175,-27.0060200749,-39.0155413548,51.52477287883,2,1,18 +2025-03-11T12:38:20.140823,479392701,13,175,-26.78455623376,-38.793346717845,51.11227895881,2,1,18 +2025-03-11T12:38:20.156448,479392701,13,175,-26.56780438924,-38.58502344933,50.709089805925,2,1,18 +2025-03-11T12:38:20.172073,479392701,13,175,-26.3463405481,-38.3489655969,50.305782632035,2,1,18 +2025-03-11T12:38:20.187698,479392701,13,175,-26.11545271372,-38.11289143854,49.89784071307,2,1,18 +2025-03-11T12:38:20.203323,479392701,13,175,-25.88927687596,-37.895309720445,49.476116185915,2,1,18 +2025-03-11T12:38:20.218948,479392701,13,175,-25.67252503144,-37.673123236455,49.0636290469,2,1,18 +2025-03-11T12:38:20.234573,479392701,13,175,-25.43221320382,-37.43241170034,48.64179147673,2,1,18 +2025-03-11T12:38:20.250198,479392701,13,175,-25.1919013762,-37.191700164225,48.21071154043,2,1,18 +2025-03-11T12:38:20.265823,479392701,13,175,-24.96101354182,-36.96024707769,47.793545795335,2,1,18 +2025-03-11T12:38:20.281448,479392701,13,175,-24.7207017142,-36.738019828875,47.37640356823,2,1,18 +2025-03-11T12:38:20.297073,479392701,13,175,-24.48038988658,-36.492687220935,46.949926274995,2,1,18 +2025-03-11T12:38:20.312698,479392701,13,175,-24.2495020522,-36.247370918925,46.50497781151,2,1,18 +2025-03-11T12:38:20.328323,479392701,13,175,-23.99505423472,-36.015877067565,46.064672246065,2,1,18 +2025-03-11T12:38:20.343948,479392701,13,175,-23.75003041048,-35.77977845031,45.63360406876,2,1,18 +2025-03-11T12:38:20.359573,479392701,13,175,-23.51443057948,-35.543696138985,45.211791819595,2,1,18 +2025-03-11T12:38:20.375198,479392701,13,175,-23.28825474172,-35.293766918115,44.77145278018,2,1,18 +2025-03-11T12:38:20.390823,479392701,13,175,-23.0479429141,-35.048434310175,44.31262720549,2,1,18 +2025-03-11T12:38:20.406448,479392701,13,175,-22.80763108648,-34.79848063041,43.87226782306,2,1,18 +2025-03-11T12:38:20.422073,479392701,13,175,-22.55789526562,-34.56237386019,43.455056413945,2,1,18 +2025-03-11T12:38:20.437698,479392701,13,175,-22.32700743124,-34.32629970183,43.00090266433,2,1,18 +2025-03-11T12:38:20.453323,479392701,13,175,-22.081983607,-34.0763378691,42.560536500895,2,1,18 +2025-03-11T12:38:20.468948,479392701,13,175,-21.82753578952,-33.830980802265,42.10169058319,2,1,18 +2025-03-11T12:38:20.484573,479392701,13,175,-21.58251196528,-33.57639789771,41.642821147495,2,1,18 +2025-03-11T12:38:20.500198,479392701,13,175,-21.33277614442,-33.32180684019,41.17932374773,2,1,18 +2025-03-11T12:38:20.515823,479392701,13,175,-21.08775232018,-33.067223935635,40.71583312897,2,1,18 +2025-03-11T12:38:20.531448,479392701,13,175,-20.85215248918,-32.817278408835,40.256995795285,2,1,18 +2025-03-11T12:38:20.547073,479392701,13,175,-20.5977046717,-32.571921342,39.79814987758,2,1,18 +2025-03-11T12:38:20.562698,479392701,13,175,-20.33383286098,-32.30344261011,39.348440063995,2,1,18 +2025-03-11T12:38:20.578323,479392701,13,175,-20.08409704012,-32.04885155259,38.871079115035,2,1,18 +2025-03-11T12:38:20.593948,479392701,13,175,-19.83907321588,-31.803510791685,38.37527729482,2,1,18 +2025-03-11T12:38:20.609573,479392701,13,175,-19.5846253984,-31.544290509375,37.897891024855,2,1,18 +2025-03-11T12:38:20.625198,479392701,13,175,-19.3254655843,-31.2665777868,37.43428736308,2,1,18 +2025-03-11T12:38:20.640823,479392701,13,175,-19.0663057702,-31.007349351525,36.961515495175,2,1,18 +2025-03-11T12:38:20.656448,479392701,13,175,-18.79772196286,-30.74810461032,36.49797243139,2,1,18 +2025-03-11T12:38:20.672073,479392701,13,175,-18.52913815552,-30.498102012765,36.015981715345,2,1,18 +2025-03-11T12:38:20.687698,479392701,13,175,-18.26055434818,-30.23885727156,35.538575102365,2,1,18 +2025-03-11T12:38:20.703323,479392701,13,175,-17.99197054084,-29.961128243055,35.079579061645,2,1,18 +2025-03-11T12:38:20.718948,479392701,13,175,-17.73281072674,-29.69265766413,34.592906564545,2,1,18 +2025-03-11T12:38:20.734573,479392701,13,175,-17.47836290926,-29.419574166345,34.09697994232,2,1,18 +2025-03-11T12:38:20.750198,479392701,13,175,-17.2050671053,-29.164942344,33.6242062714,2,1,18 +2025-03-11T12:38:20.765823,479392701,13,175,-16.93177130134,-28.901068378005,33.146774337415,2,1,18 +2025-03-11T12:38:20.781448,479392701,13,175,-16.65376350076,-28.637186259045,32.65547207323,2,1,18 +2025-03-11T12:38:20.797073,479392701,13,175,-16.3804676968,-28.359449077575,32.14563623779,2,1,18 +2025-03-11T12:38:20.812698,479392701,13,175,-16.1213078827,-28.1002206423,31.6312737223,2,1,18 +2025-03-11T12:38:20.828323,479392701,13,175,-15.85743607198,-27.827120838585,31.13995472113,2,1,18 +2025-03-11T12:38:20.843948,479392701,13,175,-15.58885226464,-27.54014966643,30.65319450202,2,1,18 +2025-03-11T12:38:20.859573,479392701,13,175,-15.30613246744,-27.27163832268,30.157245733765,2,1,18 +2025-03-11T12:38:20.875198,479392701,13,175,-15.02341267024,-26.99388483528,29.656638702445,2,1,18 +2025-03-11T12:38:20.890823,479392701,13,175,-14.76425285614,-26.725414256355,29.15610265615,2,1,18 +2025-03-11T12:38:20.906448,479392701,13,175,-14.50038104542,-26.447693380815,28.669386298045,2,1,18 +2025-03-11T12:38:20.922073,479392701,13,175,-14.22708524146,-26.160714055695,28.168755748735,2,1,18 +2025-03-11T12:38:20.937698,479392701,13,175,-13.95850143412,-25.887606099015,27.66818760043,2,1,18 +2025-03-11T12:38:20.953323,479392701,13,175,-13.67578163692,-25.61447368344,27.162977926045,2,1,18 +2025-03-11T12:38:20.968948,479392701,13,175,-13.39777383634,-25.34134942083,26.657775032665,2,1,18 +2025-03-11T12:38:20.984573,479392701,13,175,-13.11976603576,-25.072846230045,26.134105947025,2,1,18 +2025-03-11T12:38:21.000198,479392701,13,175,-12.85589422504,-24.785883210855,25.633488959725,2,1,18 +2025-03-11T12:38:21.015823,479392701,13,175,-12.5873104177,-24.503533110525,25.128262548355,2,1,18 +2025-03-11T12:38:21.031448,479392701,13,175,-12.30930261712,-24.221166704265,24.623022574975,2,1,18 +2025-03-11T12:38:21.047073,479392701,13,175,-12.01715882668,-23.924912623635,24.103843089385,2,1,18 +2025-03-11T12:38:21.062698,479392701,13,175,-11.72972703286,-23.64715098327,23.589365727865,2,1,18 +2025-03-11T12:38:21.078323,479392701,13,175,-11.45171923228,-23.369405648835,23.084144294485,2,1,18 +2025-03-11T12:38:21.093948,479392701,13,175,-11.15957544184,-23.07777264003,22.58808926422,2,1,18 +2025-03-11T12:38:21.109573,479392701,13,175,-10.86271965478,-22.78613147826,22.059679171495,2,1,18 +2025-03-11T12:38:21.125198,479392701,13,175,-10.57999985758,-22.50837799086,21.53596622485,2,1,18 +2025-03-11T12:38:21.140823,479392701,13,175,-10.29728006038,-22.23062450346,21.01687446127,2,1,18 +2025-03-11T12:38:21.156448,479392701,13,175,-10.02869625304,-21.94827440313,20.488542134575,2,1,18 +2025-03-11T12:38:21.172073,479392701,13,175,-9.7365524626,-21.66126246615,19.960157362855,2,1,18 +2025-03-11T12:38:21.187698,479392701,13,175,-9.44440867216,-21.37425052917,19.431772591135,2,1,18 +2025-03-11T12:38:21.203323,479392701,13,175,-9.1475528851,-21.09185151105,18.90339957841,2,1,18 +2025-03-11T12:38:21.218948,479392701,13,175,-8.86012109128,-20.804847727035,18.393506319955,2,1,18 +2025-03-11T12:38:21.234573,479392701,13,175,-8.5821132907,-20.49937596165,17.87431009738,2,1,18 +2025-03-11T12:38:21.250198,479392701,13,175,-8.2993934935,-20.198517115125,17.34588326767,2,1,18 +2025-03-11T12:38:21.265823,479392701,13,175,-8.00253770644,-19.91149702518,16.81287053188,2,1,18 +2025-03-11T12:38:21.281448,479392701,13,175,-7.710393916,-19.638348303675,16.27529901403,2,1,18 +2025-03-11T12:38:21.297073,479392701,13,175,-7.41825012556,-19.37444172582,15.760870491505,2,1,18 +2025-03-11T12:38:21.312698,479392701,13,175,-7.13081833174,-19.078195798155,15.22321305466,2,1,18 +2025-03-11T12:38:21.328323,479392701,13,175,-6.82925054806,-18.763441124295,14.680839931735,2,1,18 +2025-03-11T12:38:21.343948,479392701,13,175,-6.54653075086,-18.46258227777,14.152413102025,2,1,18 +2025-03-11T12:38:21.359573,479392701,13,175,-6.26852295028,-18.16173158421,13.62399305332,2,1,18 +2025-03-11T12:38:21.375198,479392701,13,175,-5.97637915984,-17.87471964723,13.06788118321,2,1,18 +2025-03-11T12:38:21.390823,479392701,13,175,-5.67952337278,-17.59232062911,12.539508170485,2,1,18 +2025-03-11T12:38:21.406448,479392701,13,175,-5.39680357558,-17.29608285441,12.01572106384,2,1,18 +2025-03-11T12:38:21.422073,479392701,13,175,-5.10937178176,-17.00445799857,11.487324533125,2,1,18 +2025-03-11T12:38:21.437698,479392701,13,175,-4.8125159947,-16.70357469315,10.94963499427,2,1,18 +2025-03-11T12:38:21.453323,479392701,13,175,-4.51094821102,-16.40730430659,10.41195721441,2,1,18 +2025-03-11T12:38:21.468948,479392701,13,175,-4.20466843072,-16.101783623415,9.874235573545,2,1,18 +2025-03-11T12:38:21.484573,479392701,13,175,-3.89838865042,-15.800884012065,9.331911289615,2,1,18 +2025-03-11T12:38:21.500198,479392701,13,175,-3.60153286336,-15.49537963482,8.79420321076,2,1,18 +2025-03-11T12:38:21.515823,479392701,13,175,-3.31410106954,-15.208375850805,8.25196167085,2,1,18 +2025-03-11T12:38:21.531448,479392701,13,175,-3.01724528248,-14.91211361721,7.705048305865,2,1,18 +2025-03-11T12:38:21.547073,479392701,13,175,-2.72981348866,-14.615867689545,7.153527319825,2,1,18 +2025-03-11T12:38:21.562698,479392701,13,175,-2.43766969822,-14.328855752565,6.615900181975,2,1,18 +2025-03-11T12:38:21.578323,479392701,13,175,-2.1266779213,-14.032569060075,6.07358765704,2,1,18 +2025-03-11T12:38:21.593948,479392701,13,175,-1.82982213424,-13.72706468283,5.526637212055,2,1,18 +2025-03-11T12:38:21.609573,479392701,13,175,-1.54710233704,-13.435447979955,4.989005096215,2,1,18 +2025-03-11T12:38:21.625198,479392701,13,175,-1.2549585466,-13.12533068385,4.442042892235,2,1,18 +2025-03-11T12:38:21.640823,479392701,13,175,-0.95810275954,-12.82444737843,3.908974536445,2,1,18 +2025-03-11T12:38:21.656448,479392701,13,175,-0.65653497586,-12.53741913552,3.37595501965,2,1,18 +2025-03-11T12:38:21.672073,479392701,13,175,-0.3596791888,-12.231914758275,2.829004574665,2,1,18 +2025-03-11T12:38:21.687698,479392701,13,175,-0.06282340174,-11.931031452855,2.277451486615,2,1,18 +2025-03-11T12:38:21.703323,479392701,13,175,0.24816837518,-11.634744760365,1.73513896168,2,1,18 +2025-03-11T12:38:21.718948,479392701,13,175,0.54502416224,-11.32924038312,1.20205206589,2,1,18 +2025-03-11T12:38:21.734573,479392701,13,175,0.8418799493,-11.0283570777,0.664362527035,2,1,18 +2025-03-11T12:38:21.750198,479392701,13,175,1.13402373974,-10.727481925245,0.117437403055,2,1,18 +2025-03-11T12:38:21.765823,479392701,13,175,1.44030352004,-10.44044552937,-0.42945244394,2,1,18 +2025-03-11T12:38:21.781448,479392701,13,175,1.72773531386,-10.14882067353,-0.985576073045,2,1,18 +2025-03-11T12:38:21.797073,479392701,13,175,2.02459110092,-9.852558439935,-1.518625888835,2,1,18 +2025-03-11T12:38:21.812698,479392701,13,175,2.3261588846,-9.55166698155,-2.047079842565,2,1,18 +2025-03-11T12:38:21.828323,479392701,13,175,2.62772666828,-9.23691230769,-2.612558880815,2,1,18 +2025-03-11T12:38:21.843948,479392701,13,175,2.92929445196,-8.93139977748,-3.173379656,2,1,18 +2025-03-11T12:38:21.859573,479392701,13,175,3.2214382424,-8.630524625025,-3.724925963045,2,1,18 +2025-03-11T12:38:21.875198,479392701,13,175,3.51829402946,-8.32502024778,-4.27187640803,2,1,18 +2025-03-11T12:38:21.890823,479392701,13,175,3.82457380976,-8.028741708255,-4.82342451809,2,1,18 +2025-03-11T12:38:21.906448,479392701,13,175,4.12142959682,-7.737100546485,-5.361076976945,2,1,18 +2025-03-11T12:38:21.922073,479392701,13,175,4.41828538388,-7.436217241065,-5.8987665158,2,1,18 +2025-03-11T12:38:21.937698,479392701,13,175,4.71985316756,-7.130704710855,-6.450344924855,2,1,18 +2025-03-11T12:38:21.953323,479392701,13,175,5.011996958,-6.8298295584,-7.006512414965,2,1,18 +2025-03-11T12:38:21.968948,479392701,13,175,5.30885274506,-6.51970410933,-7.558102583015,2,1,18 +2025-03-11T12:38:21.984573,479392701,13,175,5.61984452198,-6.218796345015,-8.086570098755,2,1,18 +2025-03-11T12:38:22.000137,479392705,9,176,5.90256431918,-5.922558570315,-8.633463120725,2,1,18 +2025-03-11T12:38:22.015762,479392705,9,176,6.19942010624,-5.63553848037,-9.18033940571,2,1,18 +2025-03-11T12:38:22.031387,479392705,9,176,6.50098788992,-5.334647021985,-9.7272780917,2,1,18 +2025-03-11T12:38:22.047012,479392705,9,176,6.80726767022,-5.033747410635,-10.292708290955,2,1,18 +2025-03-11T12:38:22.062637,479392705,9,176,7.1088354539,-4.7420980959,-10.85347344614,2,1,18 +2025-03-11T12:38:22.078262,479392705,9,176,7.40569124096,-4.436593718655,-11.400423891125,2,1,18 +2025-03-11T12:38:22.093887,479392705,9,176,7.6978350314,-4.140339638025,-11.93346692591,2,1,18 +2025-03-11T12:38:22.109512,479392705,9,176,7.98997882184,-3.825601270095,-12.448099388435,2,1,18 +2025-03-11T12:38:22.125137,479392705,9,176,8.30568259538,-3.52930642464,-13.00428224357,2,1,18 +2025-03-11T12:38:22.140762,479392705,9,176,8.60725037906,-3.237657109905,-13.56966858182,2,1,18 +2025-03-11T12:38:22.156387,479392705,9,176,8.8993941695,-2.941403029275,-14.1165751658,2,1,18 +2025-03-11T12:38:22.172012,479392705,9,176,9.20096195318,-2.635890499065,-14.64504765953,2,1,18 +2025-03-11T12:38:22.187637,479392705,9,176,9.49781774024,-2.335007193645,-15.173494832255,2,1,18 +2025-03-11T12:38:22.203262,479392705,9,176,9.79938552392,-2.03411573526,-15.738918250505,2,1,18 +2025-03-11T12:38:22.218887,479392705,9,176,10.08681731774,-1.75173302307,-16.290383616545,2,1,18 +2025-03-11T12:38:22.234512,479392705,9,176,10.37896110818,-1.460100014265,-16.82340811133,2,1,18 +2025-03-11T12:38:22.250137,479392705,9,176,10.68052889186,-1.16845069953,-17.347203801995,2,1,18 +2025-03-11T12:38:22.265762,479392705,9,176,10.9726726823,-0.86295447525,-17.884905099845,2,1,18 +2025-03-11T12:38:22.281387,479392705,9,176,11.2553924795,-0.5574745569,-18.42721401875,2,1,18 +2025-03-11T12:38:22.297012,479392705,9,176,11.5616722598,-0.242711730074999,-18.97883628881,2,1,18 +2025-03-11T12:38:22.312637,479392705,9,176,11.85381605024,0.0443002069049996,-19.521084609725,2,1,18 +2025-03-11T12:38:22.328262,479392705,9,176,12.13653584744,0.335916909780001,-20.0540955425,2,1,18 +2025-03-11T12:38:22.343887,479392705,9,176,12.43810363112,0.62294515269,-20.5732515101,2,1,18 +2025-03-11T12:38:22.359512,479392705,9,176,12.74438341142,0.919223692215001,-21.12479962016,2,1,18 +2025-03-11T12:38:22.375137,479392705,9,176,13.02710320862,1.206219323265,-21.662413196,2,1,18 +2025-03-11T12:38:22.390762,479392705,9,176,13.31453500244,1.507086322755,-22.20471035591,2,1,18 +2025-03-11T12:38:22.406387,479392705,9,176,13.61610278612,1.803356709315,-22.737766952705,2,1,18 +2025-03-11T12:38:22.422012,479392705,9,176,13.91295857318,2.085755727435,-23.2568975993,2,1,18 +2025-03-11T12:38:22.437637,479392705,9,176,14.21452635686,2.372783970345,-23.78529593303,2,1,18 +2025-03-11T12:38:22.453262,479392705,9,176,14.50195815068,2.673650969835,-24.313729543745,2,1,18 +2025-03-11T12:38:22.468887,479392705,9,176,14.7893899445,2.9514126102,-24.846691637525,2,1,18 +2025-03-11T12:38:22.484512,479392705,9,176,15.08153373494,3.252287762655,-25.375132029245,2,1,18 +2025-03-11T12:38:22.500137,479392705,9,176,15.36425353214,3.55314660918,-25.903558858955,2,1,18 +2025-03-11T12:38:22.515762,479392705,9,176,15.6375493361,3.8401259343,-26.41805295746,2,1,18 +2025-03-11T12:38:22.531387,479392705,9,176,15.92969312654,4.12713787128,-26.91871063079,2,1,18 +2025-03-11T12:38:22.547012,479392705,9,176,16.21712492036,4.40952058347,-27.45169126457,2,1,18 +2025-03-11T12:38:22.562637,479392705,9,176,16.5092687108,4.69653252045,-27.993939585485,2,1,18 +2025-03-11T12:38:22.578262,479392705,9,176,16.80612449786,4.97893153857,-28.51307023208,2,1,18 +2025-03-11T12:38:22.593887,479392705,9,176,17.10298028492,5.265951628515,-29.02759823561,2,1,18 +2025-03-11T12:38:22.609512,479392705,9,176,17.3809880855,5.539075891125,-29.546664678185,2,1,18 +2025-03-11T12:38:22.625137,479392705,9,176,17.65428388946,5.844539503545,-30.07971766895,2,1,18 +2025-03-11T12:38:22.640762,479392705,9,176,17.93700368666,6.140777278245,-30.60812595866,2,1,18 +2025-03-11T12:38:22.656387,479392705,9,176,18.23385947372,6.42779736819,-31.118032779125,2,1,18 +2025-03-11T12:38:22.672012,479392705,9,176,18.51657927092,6.71479299924,-31.646403988835,2,1,18 +2025-03-11T12:38:22.687637,479392705,9,176,18.79929906812,6.997167558465,-32.165514292415,2,1,18 +2025-03-11T12:38:22.703262,479392705,9,176,19.08201886532,7.27954211769,-32.68000341293,2,1,18 +2025-03-11T12:38:22.718887,479392705,9,176,19.35531466928,7.56652144281,-33.194497511435,2,1,18 +2025-03-11T12:38:22.734512,479392705,9,176,19.63332246986,7.83964570542,-33.68583685562,2,1,18 +2025-03-11T12:38:22.750137,479392705,9,176,19.92075426368,8.12202841761,-34.195711574075,2,1,18 +2025-03-11T12:38:22.765762,479392705,9,176,20.2081860575,8.4044111298,-34.73331339092,2,1,18 +2025-03-11T12:38:22.781387,479392705,9,176,20.48619385808,8.682156464235,-35.243156007365,2,1,18 +2025-03-11T12:38:22.797012,479392705,9,176,20.76891365528,8.950667807985,-35.75758950788,2,1,18 +2025-03-11T12:38:22.812637,479392705,9,176,21.032785466,9.2237676117,-36.25815087518,2,1,18 +2025-03-11T12:38:22.828262,479392705,9,176,21.3155052632,9.5015210991,-36.74951554037,2,1,18 +2025-03-11T12:38:22.843887,479392705,9,176,21.59351306378,9.788508577185,-37.250152870685,2,1,18 +2025-03-11T12:38:22.859512,479392705,9,176,21.85267287788,10.07546344341,-37.755384260045,2,1,18 +2025-03-11T12:38:22.875137,479392705,9,176,22.13539267508,10.348595858985,-38.255972751365,2,1,18 +2025-03-11T12:38:22.890762,479392705,9,176,22.41811247228,10.61248613091,-38.75190297962,2,1,18 +2025-03-11T12:38:22.906387,479392705,9,176,22.69612027286,10.890231465345,-39.252503229935,2,1,18 +2025-03-11T12:38:22.922012,479392705,9,176,22.97412807344,11.15873465613,-39.73458166799,2,1,18 +2025-03-11T12:38:22.937637,479392705,9,176,23.24271188078,11.41335832551,-40.244318022425,2,1,18 +2025-03-11T12:38:22.953262,479392705,9,176,23.51129568812,11.681845210365,-40.758731179925,2,1,18 +2025-03-11T12:38:22.968887,479392705,9,176,23.77987949546,11.954953167045,-41.26854169436,2,1,18 +2025-03-11T12:38:22.984512,479392705,9,176,24.05317529942,12.22806927669,-41.746010708345,2,1,18 +2025-03-11T12:38:23.000137,479392705,9,176,24.3311831,12.496572467475,-42.20960441414,2,1,18 +2025-03-11T12:38:23.015762,479392705,9,176,24.5903429141,12.769664118225,-42.69629545124,2,1,18 +2025-03-11T12:38:23.031387,479392705,9,176,24.85421472482,13.038142850115,-43.18759591241,2,1,18 +2025-03-11T12:38:23.047012,479392705,9,176,25.12279853216,13.31587187862,-43.66507668539,2,1,18 +2025-03-11T12:38:23.062637,479392705,9,176,25.38667034288,13.598213825985,-44.151811583495,2,1,18 +2025-03-11T12:38:23.078262,479392705,9,176,25.64111816036,13.866676251945,-44.624613750395,2,1,18 +2025-03-11T12:38:23.093887,479392705,9,176,25.88142998798,14.121251003535,-45.08809758815,2,1,18 +2025-03-11T12:38:23.109512,479392705,9,176,26.1453017987,14.37586651995,-45.583963612385,2,1,18 +2025-03-11T12:38:23.125137,479392705,9,176,26.41388560604,14.62124804568,-46.0566934223,2,1,18 +2025-03-11T12:38:23.140762,479392705,9,176,26.68246941338,14.871250643235,-46.52482058915,2,1,18 +2025-03-11T12:38:23.156387,479392705,9,176,26.9463412241,15.148971518775,-46.98843103193,2,1,18 +2025-03-11T12:38:23.172012,479392705,9,176,27.19136504834,15.408175495155,-47.456561373755,2,1,18 +2025-03-11T12:38:23.187637,479392705,9,176,27.43638887258,15.667379471535,-47.93393408171,2,1,18 +2025-03-11T12:38:23.203262,479392705,9,176,27.69083669006,15.926599753845,-48.383593253285,2,1,18 +2025-03-11T12:38:23.218887,479392705,9,176,27.94528450754,16.185820036155,-48.85173715712,2,1,18 +2025-03-11T12:38:23.234512,479392705,9,176,28.20915631826,16.426572337095,-49.301335730705,2,1,18 +2025-03-11T12:38:23.250137,479392705,9,176,28.47302812898,16.66270356621,-49.76015813042,2,1,18 +2025-03-11T12:38:23.265762,479392705,9,176,28.71805195322,16.917286470765,-50.22364874918,2,1,18 +2025-03-11T12:38:23.281387,479392705,9,176,28.9724997707,17.167264609425,-50.70561912221,2,1,18 +2025-03-11T12:38:23.297012,479392705,9,176,29.22223559156,17.440339954245,-51.169190681975,2,1,18 +2025-03-11T12:38:23.312637,479392705,9,176,29.45783542256,17.68566440922,-51.614145926465,2,1,18 +2025-03-11T12:38:23.328262,479392705,9,176,29.7028592468,17.912520882825,-52.06366175603,2,1,18 +2025-03-11T12:38:23.343887,479392705,9,176,29.94317107442,18.157853490765,-52.499381415395,2,1,18 +2025-03-11T12:38:23.359512,479392705,9,176,30.17877090542,18.398556873915,-52.93045457069,2,1,18 +2025-03-11T12:38:23.375137,479392705,9,176,30.41908273304,18.653131625505,-53.375453676185,2,1,18 +2025-03-11T12:38:23.390762,479392705,9,176,30.6688185539,18.89385946755,-53.815789540625,2,1,18 +2025-03-11T12:38:23.406387,479392705,9,176,30.91384237814,19.139200228455,-54.242273614865,2,1,18 +2025-03-11T12:38:23.422012,479392705,9,176,31.16829019562,19.39379943894,-54.678050697245,2,1,18 +2025-03-11T12:38:23.437637,479392705,9,176,31.41802601648,19.62066406551,-55.118330941685,2,1,18 +2025-03-11T12:38:23.453262,479392705,9,176,31.64891385086,19.85673822387,-55.56324232517,2,1,18 +2025-03-11T12:38:23.468887,479392705,9,176,31.87508968862,20.092804229265,-56.00814692765,2,1,18 +2025-03-11T12:38:23.484512,479392705,9,176,32.09655352976,20.328862081695,-56.43918119993,2,1,18 +2025-03-11T12:38:23.500137,479392705,9,176,32.3180173709,20.564919934125,-56.865594289145,2,1,18 +2025-03-11T12:38:23.515762,479392705,9,176,32.5536172019,20.796381173625,-57.273524449115,2,1,18 +2025-03-11T12:38:23.531387,479392705,9,176,32.79864102614,21.03247979088,-57.709213809485,2,1,18 +2025-03-11T12:38:23.547012,479392705,9,176,33.0248168639,21.259303652625,-58.135596599705,2,1,18 +2025-03-11T12:38:23.562637,479392705,9,176,33.25570469828,21.495377810985,-58.538917335605,2,1,18 +2025-03-11T12:38:23.578262,479392705,9,176,33.48188053604,21.72220167273,-58.946815393565,2,1,18 +2025-03-11T12:38:23.593887,479392705,9,176,33.71748036704,21.958283984055,-59.3593852766,2,1,18 +2025-03-11T12:38:23.609512,479392705,9,176,33.9436562048,22.171244630325,-59.771848897625,2,1,18 +2025-03-11T12:38:23.625137,479392705,9,176,34.16040804932,22.37956789884,-60.18428041664,2,1,18 +2025-03-11T12:38:23.640762,479392705,9,176,34.3912958837,22.592536698075,-60.58750845254,2,1,18 +2025-03-11T12:38:23.656387,479392705,9,176,34.60804772822,22.81010211024,-60.99535586849,2,1,18 +2025-03-11T12:38:23.672012,479392705,9,176,34.82008757612,23.032280441265,-61.384730311175,2,1,18 +2025-03-11T12:38:23.687637,479392705,9,176,35.03212742402,23.249837700465,-61.806434495315,2,1,18 +2025-03-11T12:38:23.703262,479392705,9,176,35.24887926854,23.47664525628,-62.20045544207,2,1,18 +2025-03-11T12:38:23.718887,479392705,9,176,35.46091911644,23.717307874605,-62.58528286169,2,1,18 +2025-03-11T12:38:23.734512,479392705,9,176,35.6635349711,23.93022775605,-62.96074311317,2,1,18 +2025-03-11T12:38:23.750137,479392705,9,176,35.88499881224,24.12931703388,-63.331553685605,2,1,18 +2025-03-11T12:38:23.765762,479392705,9,176,36.10175065676,24.337640302395,-63.720879289295,2,1,18 +2025-03-11T12:38:23.781387,479392705,9,176,36.31379050466,24.545955417945,-64.105576928915,2,1,18 +2025-03-11T12:38:23.797012,479392705,9,176,36.53054234918,24.768141901935,-64.485715786475,2,1,18 +2025-03-11T12:38:23.812637,479392705,9,176,36.73787020046,24.981069936345,-64.86118281896,2,1,18 +2025-03-11T12:38:23.828262,479392705,9,176,36.92635006526,25.193965358895,-65.236622727425,2,1,18 +2025-03-11T12:38:23.843887,479392705,9,176,37.13367791654,25.397651249655,-65.598189130715,2,1,18 +2025-03-11T12:38:23.859512,479392705,9,176,37.3362937712,25.58284470015,-65.973538142195,2,1,18 +2025-03-11T12:38:23.875137,479392705,9,176,37.52948563262,25.777263988365,-66.348910671665,2,1,18 +2025-03-11T12:38:23.890762,479392705,9,176,37.72738949066,25.98555464502,-66.719724419075,2,1,18 +2025-03-11T12:38:23.906387,479392705,9,176,37.91115735884,26.17533655548,-67.067337748145,2,1,18 +2025-03-11T12:38:23.922012,479392705,9,176,38.10906121688,26.36052185301,-67.42419524636,2,1,18 +2025-03-11T12:38:23.937637,479392705,9,176,38.31638906816,26.57344988742,-67.76731399739,2,1,18 +2025-03-11T12:38:23.953262,479392705,9,176,38.52371691944,26.76789363453,-68.105737405355,2,1,18 +2025-03-11T12:38:23.968887,479392705,9,176,38.7263327741,26.9669503005,-68.47652085377,2,1,18 +2025-03-11T12:38:23.984512,479392705,9,176,38.92423663214,27.17061988533,-68.814967779725,2,1,18 +2025-03-11T12:38:24.000137,479392705,9,176,39.11742849356,27.355797029895,-69.15795494774,2,1,18 +2025-03-11T12:38:24.015762,479392705,9,176,39.29648436512,27.53632864374,-69.524009148065,2,1,18 +2025-03-11T12:38:24.031387,479392705,9,176,39.4802522333,27.721489482375,-69.8762251202,2,1,18 +2025-03-11T12:38:24.047012,479392705,9,176,39.65459610824,27.90663401508,-70.219185164195,2,1,18 +2025-03-11T12:38:24.062637,479392705,9,176,39.8336519798,28.09178670075,-70.562151989195,2,1,18 +2025-03-11T12:38:24.078262,479392705,9,176,40.01741984798,28.276947539385,-70.891262046005,2,1,18 +2025-03-11T12:38:24.093887,479392705,9,176,40.20118771616,28.43438194707,-71.220260862815,2,1,18 +2025-03-11T12:38:24.109512,479392705,9,176,40.38966758096,28.61955093867,-71.53089296837,2,1,18 +2025-03-11T12:38:24.125137,479392705,9,176,40.57814744576,28.79547778662,-71.85535154312,2,1,18 +2025-03-11T12:38:24.140762,479392705,9,176,40.7524913207,28.952895888375,-72.17509443179,2,1,18 +2025-03-11T12:38:24.156387,479392705,9,176,40.90798720916,29.13800780922,-72.499542619505,2,1,18 +2025-03-11T12:38:24.172012,479392705,9,176,41.07761908748,29.318523117135,-72.805507877975,2,1,18 +2025-03-11T12:38:24.187637,479392705,9,176,41.25196296242,29.489804434365,-73.097579288255,2,1,18 +2025-03-11T12:38:24.203262,479392705,9,176,41.42159484074,29.67031974228,-73.39892336366,2,1,18 +2025-03-11T12:38:24.218887,479392705,9,176,41.58180272582,29.841576600615,-73.709459163185,2,1,18 +2025-03-11T12:38:24.234512,479392705,9,176,41.7420106109,30.008212387125,-73.996870507385,2,1,18 +2025-03-11T12:38:24.250137,479392705,9,176,41.9069304926,30.16561418295,-74.288872735655,2,1,18 +2025-03-11T12:38:24.265762,479392705,9,176,42.08127436754,30.31841121288,-74.580869985935,2,1,18 +2025-03-11T12:38:24.281387,479392705,9,176,42.24148225262,30.48504699939,-74.88214487933,2,1,18 +2025-03-11T12:38:24.297012,479392705,9,176,42.39226614446,30.665529695445,-75.16959828152,2,1,18 +2025-03-11T12:38:24.312637,479392705,9,176,42.5430500363,30.81828596055,-75.46618280984,2,1,18 +2025-03-11T12:38:24.328262,479392705,9,176,42.69383392814,30.961800082005,-75.76273025816,2,1,18 +2025-03-11T12:38:24.343887,479392705,9,176,42.85875380984,31.11920187783,-76.031626571105,2,1,18 +2025-03-11T12:38:24.359512,479392705,9,176,43.00953770168,31.26733707111,-76.31432901023,2,1,18 +2025-03-11T12:38:24.375137,479392705,9,176,43.1556095969,31.42008518325,-76.583179659155,2,1,18 +2025-03-11T12:38:24.390762,479392705,9,176,43.31110548536,31.55436531402,-76.828863794765,2,1,18 +2025-03-11T12:38:24.406387,479392705,9,176,43.4618893772,31.7025005073,-77.088460318565,2,1,18 +2025-03-11T12:38:24.422012,479392705,9,176,43.60796127242,31.841385403965,-77.361876530555,2,1,18 +2025-03-11T12:38:24.437637,479392705,9,176,43.76345716088,31.975665534735,-77.63066658149,2,1,18 +2025-03-11T12:38:24.453262,479392705,9,176,43.89068106962,32.119138891365,-77.890210660265,2,1,18 +2025-03-11T12:38:24.468887,479392705,9,176,44.0273289716,32.26724962575,-78.154408024115,2,1,18 +2025-03-11T12:38:24.484512,479392705,9,176,44.17811286344,32.41538481903,-78.40014099872,2,1,18 +2025-03-11T12:38:24.500137,479392705,9,176,44.30533677218,32.54961603201,-78.631920899105,2,1,18 +2025-03-11T12:38:24.515762,479392705,9,176,44.4514086674,32.68387985685,-78.877591472705,2,1,18 +2025-03-11T12:38:24.531387,479392705,9,176,44.58334457276,32.82274029462,-79.12326024329,2,1,18 +2025-03-11T12:38:24.547012,479392705,9,176,44.71528047812,32.956979660565,-79.378152840005,2,1,18 +2025-03-11T12:38:24.562637,479392705,9,176,44.83308039362,33.081952423965,-79.614503281445,2,1,18 +2025-03-11T12:38:24.578262,479392705,9,176,44.96030430236,33.197699349645,-79.84620902183,2,1,18 +2025-03-11T12:38:24.593887,479392705,9,176,45.0875282111,33.322688418975,-80.08257302528,2,1,18 +2025-03-11T12:38:24.609512,479392705,9,176,45.2053281266,33.4522822542,-80.295836091395,2,1,18 +2025-03-11T12:38:24.625137,479392705,9,176,45.30428005562,33.57722240574,-80.532159408815,2,1,18 +2025-03-11T12:38:24.640762,479392705,9,176,45.42679196774,33.702203322105,-80.750031899,2,1,18 +2025-03-11T12:38:24.656387,479392705,9,176,45.55401587648,33.83181346326,-80.97717207632,2,1,18 +2025-03-11T12:38:24.672012,479392705,9,176,45.6765277886,33.94293116415,-81.185746580375,2,1,18 +2025-03-11T12:38:24.687637,479392705,9,176,45.79903970072,34.058669936865,-81.380476075235,2,1,18 +2025-03-11T12:38:24.703262,479392705,9,176,45.91683961622,34.16977948479,-81.598286164415,2,1,18 +2025-03-11T12:38:24.718887,479392705,9,176,46.02521553848,34.27625165496,-81.788337053195,2,1,18 +2025-03-11T12:38:24.734512,479392705,9,176,46.14301545398,34.387361202885,-81.978420043985,2,1,18 +2025-03-11T12:38:24.750137,479392705,9,176,46.24667937962,34.49382522009,-82.173085334825,2,1,18 +2025-03-11T12:38:24.765762,479392705,9,176,46.34091931202,34.59565185954,-82.358476157525,2,1,18 +2025-03-11T12:38:24.781387,479392705,9,176,46.44929523428,34.715987245185,-82.557825032435,2,1,18 +2025-03-11T12:38:24.797012,479392705,9,176,46.55767115654,34.794732984405,-82.75238586428,2,1,18 +2025-03-11T12:38:24.812637,479392705,9,176,46.66133508218,34.89195485796,-82.93777170899,2,1,18 +2025-03-11T12:38:24.828262,479392705,9,176,46.75557501458,34.989160425585,-83.10465925943,2,1,18 +2025-03-11T12:38:24.843887,479392705,9,176,46.84981494698,35.08636599321,-83.280789176,2,1,18 +2025-03-11T12:38:24.859512,479392705,9,176,46.94405487938,35.183571560835,-83.461540275635,2,1,18 +2025-03-11T12:38:24.875137,479392705,9,176,47.03358281516,35.28539004732,-83.6376819512,2,1,18 +2025-03-11T12:38:24.890762,479392705,9,176,47.13253474418,35.37336162426,-83.79991801958,2,1,18 +2025-03-11T12:38:24.906387,479392705,9,176,47.22206267996,35.45207475162,-83.948239896755,2,1,18 +2025-03-11T12:38:24.922012,479392705,9,176,47.31630261236,35.540038175595,-84.101226818,2,1,18 +2025-03-11T12:38:24.937637,479392705,9,176,47.3964065549,35.637219284325,-84.258851659295,2,1,18 +2025-03-11T12:38:24.953262,479392705,9,176,47.48593449068,35.72055348351,-84.421055625665,2,1,18 +2025-03-11T12:38:24.968887,479392705,9,176,47.5613264366,35.808484295625,-84.55553069063,2,1,18 +2025-03-11T12:38:24.984512,479392705,9,176,47.6320063859,35.89178588295,-84.703843983785,2,1,18 +2025-03-11T12:38:25.000137,479392705,9,176,47.70739833182,35.970474551415,-84.84752433488,2,1,18 +2025-03-11T12:38:25.015762,479392705,9,176,47.78279027774,36.04916321988,-84.991204685975,2,1,18 +2025-03-11T12:38:25.031387,479392705,9,176,47.85818222366,36.109367601045,-85.12556851094,2,1,18 +2025-03-11T12:38:25.047012,479392705,9,176,47.92886217296,36.16494275742,-85.255285831835,2,1,18 +2025-03-11T12:38:25.062637,479392705,9,176,48.01367811212,36.225163444515,-85.375799669615,2,1,18 +2025-03-11T12:38:25.078262,479392705,9,176,48.0796460648,36.299214735225,-85.49172082031,2,1,18 +2025-03-11T12:38:25.093887,479392705,9,176,48.14561401748,36.364023882285,-85.626089623265,2,1,18 +2025-03-11T12:38:25.109512,479392705,9,176,48.21629396678,36.44732546961,-85.76516055029,2,1,18 +2025-03-11T12:38:25.125137,479392705,9,176,48.26341393298,36.525965220285,-85.89493666616,2,1,18 +2025-03-11T12:38:25.140762,479392705,9,176,48.3152458958,36.595370980275,-85.99233420158,2,1,18 +2025-03-11T12:38:25.156387,479392705,9,176,48.37650185186,36.646308758895,-86.07118640675,2,1,18 +2025-03-11T12:38:25.172012,479392705,9,176,48.43775780792,36.69262546569,-86.173125987245,2,1,18 +2025-03-11T12:38:25.187637,479392705,9,176,48.48958977074,36.729683722905,-86.279636108795,2,1,18 +2025-03-11T12:38:25.203262,479392705,9,176,48.53670973694,36.77135489898,-86.381536806275,2,1,18 +2025-03-11T12:38:25.218887,479392705,9,176,48.58854169976,36.826897443495,-86.469636355565,2,1,18 +2025-03-11T12:38:25.234512,479392705,9,176,48.63094966934,36.877802610255,-86.55308261978,2,1,18 +2025-03-11T12:38:25.250137,479392705,9,176,48.68749362878,36.93797437956,-86.650449856205,2,1,18 +2025-03-11T12:38:25.265762,479392705,9,176,48.7393255916,36.98889585225,-86.73390968243,2,1,18 +2025-03-11T12:38:25.281387,479392705,9,176,48.78173356118,37.02131673171,-86.798797054385,2,1,18 +2025-03-11T12:38:25.297012,479392705,9,176,48.82414153076,37.06297975482,-86.868342689405,2,1,18 +2025-03-11T12:38:25.312637,479392705,9,176,48.86654950034,37.100021706105,-86.92400623523,2,1,18 +2025-03-11T12:38:25.328262,479392705,9,176,48.91366946654,37.13245073853,-86.98890038819,2,1,18 +2025-03-11T12:38:25.343887,479392705,9,176,48.96550142936,37.178751139395,-87.06772049135,2,1,18 +2025-03-11T12:38:25.359512,479392705,9,176,48.99377340908,37.215768631785,-87.12336369416,2,1,18 +2025-03-11T12:38:25.375137,479392705,9,176,49.02675738542,37.25279427714,-87.16515012878,2,1,18 +2025-03-11T12:38:25.390762,479392705,9,176,49.05974136176,37.280577778845,-87.239247764855,2,1,18 +2025-03-11T12:38:25.406387,479392705,9,176,49.08330134486,37.29910283097,-87.29481002666,2,1,18 +2025-03-11T12:38:25.422012,479392705,9,176,49.0927253381,37.3176034242,-87.327246030125,2,1,18 +2025-03-11T12:38:25.437637,479392705,9,176,49.10686132796,37.336112170395,-87.359688814595,2,1,18 +2025-03-11T12:38:25.453262,479392705,9,176,49.12570931444,37.363871213205,-87.39217546007,2,1,18 +2025-03-11T12:38:25.468887,479392705,9,176,49.14926929754,37.387017337155,-87.438513895745,2,1,18 +2025-03-11T12:38:25.484512,479392705,9,176,49.17754127726,37.40092947042,-87.475579666295,2,1,18 +2025-03-11T12:38:25.500137,479392705,9,176,49.19638926374,37.40096208228,-87.50795507177,2,1,18 +2025-03-11T12:38:25.515762,479392705,9,176,49.2105252536,37.419470828475,-87.517291940915,2,1,18 +2025-03-11T12:38:25.531387,479392705,9,176,49.21523725022,37.433342196915,-87.53583907418,2,1,18 +2025-03-11T12:38:25.547012,479392705,9,176,49.2340852367,37.442616952425,-87.549766827395,2,1,18 +2025-03-11T12:38:25.562637,479392705,9,176,49.23879723332,37.456488320865,-87.56831396066,2,1,18 +2025-03-11T12:38:25.578262,479392705,9,176,49.24822122656,37.47036784227,-87.5776255088,2,1,18 +2025-03-11T12:38:25.593887,479392705,9,176,49.2576452198,37.4703841482,-87.600744986135,2,1,18 +2025-03-11T12:38:25.609512,479392705,9,176,49.26235721642,37.470392301165,-87.60075176714,2,1,18 +2025-03-11T12:38:25.625137,479392705,9,176,49.25293322318,37.45651277976,-87.591440219,2,1,18 +2025-03-11T12:38:25.640762,479392705,9,176,49.24822122656,37.456504626795,-87.591433437995,2,1,18 +2025-03-11T12:38:25.656387,479392705,9,176,49.25293322318,37.44727063611,-87.591403139,2,1,18 +2025-03-11T12:38:25.672012,479392705,9,176,49.2576452198,37.447278789075,-87.57754637081,2,1,18 +2025-03-11T12:38:25.687637,479392705,9,176,49.22466124346,37.442600646495,-87.55437444845,2,1,18 +2025-03-11T12:38:25.703262,479392705,9,176,49.21523725022,37.433342196915,-87.55432380644,2,1,18 +2025-03-11T12:38:25.718887,479392705,9,176,49.21523725022,37.414857909615,-87.52652254805,2,1,18 +2025-03-11T12:38:25.734512,479392705,9,176,49.19638926374,37.39171993863,-87.494054442575,2,1,18 +2025-03-11T12:38:25.750137,479392705,9,176,49.17282928064,37.373194886505,-87.46621927916,2,1,18 +2025-03-11T12:38:25.765762,479392705,9,176,49.15398129416,37.35929905917,-87.41992470449,2,1,18 +2025-03-11T12:38:25.781387,479392705,9,176,49.1398453043,37.350032456625,-87.38751900002,2,1,18 +2025-03-11T12:38:25.797012,479392705,9,176,49.1162853212,37.317644189025,-87.368870582735,2,1,18 +2025-03-11T12:38:25.812637,479392705,9,176,49.11157332458,37.28066746146,-87.336367200275,2,1,18 +2025-03-11T12:38:25.828262,479392705,9,176,49.0927253381,37.27139270595,-87.290091165605,2,1,18 +2025-03-11T12:38:25.843887,479392705,9,176,49.0456053719,37.248205817175,-87.225234092645,2,1,18 +2025-03-11T12:38:25.859512,479392705,9,176,49.01262139556,37.21118017182,-87.155720559635,2,1,18 +2025-03-11T12:38:25.875137,479392705,9,176,48.98434941584,37.178783751255,-87.081611164565,2,1,18 +2025-03-11T12:38:25.890762,479392705,9,176,48.94665344288,37.12788673746,-87.035141145875,2,1,18 +2025-03-11T12:38:25.906387,479392705,9,176,48.91838146316,37.08162710142,-86.988703229195,2,1,18 +2025-03-11T12:38:25.922012,479392705,9,176,48.88539748682,37.072327887015,-86.91467975312,2,1,18 +2025-03-11T12:38:25.937637,479392705,9,176,48.83827752062,37.03065671094,-86.845127337095,2,1,18 +2025-03-11T12:38:25.953262,479392705,9,176,48.80529354428,36.97976785011,-86.775558184085,2,1,18 +2025-03-11T12:38:25.968887,479392705,9,176,48.75346158146,36.933467449245,-86.678253348665,2,1,18 +2025-03-11T12:38:25.984512,479392705,9,176,48.70634161526,36.88255412952,-86.59942148651,2,1,18 +2025-03-11T12:38:26.000061,479392709,4,177,48.66393364568,36.84089110641,-86.516012302295,2,1,18 +2025-03-11T12:38:26.015686,479392709,4,177,48.6215256761,36.77150165235,-86.40476477969,2,1,18 +2025-03-11T12:38:26.031311,479392709,4,177,48.5508457268,36.7205475678,-86.302793097185,2,1,18 +2025-03-11T12:38:26.046936,479392709,4,177,48.49901376398,36.674247166935,-86.223972994025,2,1,18 +2025-03-11T12:38:26.062561,479392709,4,177,48.44718180116,36.614083550595,-86.126612538605,2,1,18 +2025-03-11T12:38:26.078186,479392709,4,177,48.39063784172,36.567774996765,-86.015437372985,2,1,18 +2025-03-11T12:38:26.093811,479392709,4,177,48.32466988904,36.502965849705,-85.90879566842,2,1,18 +2025-03-11T12:38:26.109436,479392709,4,177,48.25398993974,36.45663283698,-85.81146370898,2,1,18 +2025-03-11T12:38:26.125061,479392709,4,177,48.1974459803,36.4010821395,-85.686387914165,2,1,18 +2025-03-11T12:38:26.140686,479392709,4,177,48.14090202086,36.32704715472,-85.547374410155,2,1,18 +2025-03-11T12:38:26.156311,479392709,4,177,48.07493406818,36.26223800766,-85.426869156395,2,1,18 +2025-03-11T12:38:26.171936,479392709,4,177,48.0089661155,36.18818671695,-85.3109480057,2,1,18 +2025-03-11T12:38:26.187561,479392709,4,177,47.9382861662,36.12799048875,-85.18583332787,2,1,18 +2025-03-11T12:38:26.203186,479392709,4,177,47.87231821352,36.058560269865,-85.04682480185,2,1,18 +2025-03-11T12:38:26.218811,479392709,4,177,47.79221427098,35.979863448435,-84.91238003588,2,1,18 +2025-03-11T12:38:26.234436,479392709,4,177,47.70739833182,35.896537402215,-84.77328876584,2,1,18 +2025-03-11T12:38:26.250061,479392709,4,177,47.62729438928,35.79473522166,-84.606403018415,2,1,18 +2025-03-11T12:38:26.265686,479392709,4,177,47.55661443998,35.72529684981,-84.44890297913,2,1,18 +2025-03-11T12:38:26.281311,479392709,4,177,47.47651049744,35.65584217203,-84.32373765929,2,1,18 +2025-03-11T12:38:26.296936,479392709,4,177,47.38698256166,35.56788690102,-84.184621068245,2,1,18 +2025-03-11T12:38:26.312561,479392709,4,177,47.29745462588,35.493794845485,-84.02707536494,2,1,18 +2025-03-11T12:38:26.328186,479392709,4,177,47.21735068334,35.396613736755,-83.860208157515,2,1,18 +2025-03-11T12:38:26.343811,479392709,4,177,47.13253474418,35.304045546885,-83.70721625828,2,1,18 +2025-03-11T12:38:26.359436,479392709,4,177,47.04771880502,35.192993069715,-83.53104428372,2,1,18 +2025-03-11T12:38:26.375061,479392709,4,177,46.95819086924,35.086553511405,-83.36874761735,2,1,18 +2025-03-11T12:38:26.390686,479392709,4,177,46.84981494698,35.00318670036,-83.17878942857,2,1,18 +2025-03-11T12:38:26.406311,479392709,4,177,46.75557501458,34.91060220456,-83.002678052,2,1,18 +2025-03-11T12:38:26.421936,479392709,4,177,46.65191108894,34.804138187355,-82.82649749342,2,1,18 +2025-03-11T12:38:26.437561,479392709,4,177,46.55767115654,34.69769047608,-82.645709313785,2,1,18 +2025-03-11T12:38:26.453186,479392709,4,177,46.4540072309,34.5958475307,-82.460304929075,2,1,18 +2025-03-11T12:38:26.468811,479392709,4,177,46.35505530188,34.503254881935,-82.251838490045,2,1,18 +2025-03-11T12:38:26.484436,479392709,4,177,46.23254338976,34.40600039652,-82.047940789055,2,1,18 +2025-03-11T12:38:26.500061,479392709,4,177,46.1241674675,34.304149298175,-81.848666074145,2,1,18 +2025-03-11T12:38:26.515686,479392709,4,177,46.006367552,34.19303975025,-81.65396190029,2,1,18 +2025-03-11T12:38:26.531311,479392709,4,177,45.89799162974,34.072704364605,-81.45461302538,2,1,18 +2025-03-11T12:38:26.546936,479392709,4,177,45.78961570748,33.947747907135,-81.232139695145,2,1,18 +2025-03-11T12:38:26.562561,479392709,4,177,45.6765277886,33.827404368525,-81.018920490035,2,1,18 +2025-03-11T12:38:26.578186,479392709,4,177,45.56343986972,33.716302973565,-80.81960191412,2,1,18 +2025-03-11T12:38:26.593811,479392709,4,177,45.44563995422,33.60519342564,-80.59254945881,2,1,18 +2025-03-11T12:38:26.609436,479392709,4,177,45.3231280421,33.480212509275,-80.37005578556,2,1,18 +2025-03-11T12:38:26.625061,479392709,4,177,45.19119213674,33.35521528698,-80.1475485503,2,1,18 +2025-03-11T12:38:26.640686,479392709,4,177,45.05454423476,33.234830983545,-79.90194715871,2,1,18 +2025-03-11T12:38:26.656311,479392709,4,177,44.92732032602,33.119084057865,-79.67486260139,2,1,18 +2025-03-11T12:38:26.671936,479392709,4,177,44.80952041052,32.98024807899,-79.461562455275,2,1,18 +2025-03-11T12:38:26.687561,479392709,4,177,44.69172049502,32.850654243765,-79.22057229077,2,1,18 +2025-03-11T12:38:26.703186,479392709,4,177,44.56449658628,32.716423030785,-78.97492884119,2,1,18 +2025-03-11T12:38:26.718811,479392709,4,177,44.4278486843,32.57755444005,-78.72001092347,2,1,18 +2025-03-11T12:38:26.734436,479392709,4,177,44.29120078232,32.438685849315,-78.46509300575,2,1,18 +2025-03-11T12:38:26.750061,479392709,4,177,44.14041689048,32.29517172786,-78.210136205015,2,1,18 +2025-03-11T12:38:26.765686,479392709,4,177,44.0037689885,32.14243992165,-77.973647399555,2,1,18 +2025-03-11T12:38:26.781311,479392709,4,177,43.86712108652,32.00819240274,-77.709505655705,2,1,18 +2025-03-11T12:38:26.796936,479392709,4,177,43.72576118792,31.864694587215,-77.43607768472,2,1,18 +2025-03-11T12:38:26.812561,479392709,4,177,43.58911328594,31.74431028378,-77.176612743935,2,1,18 +2025-03-11T12:38:26.828186,479392709,4,177,43.44775338734,31.591570324605,-76.917011242145,2,1,18 +2025-03-11T12:38:26.843811,479392709,4,177,43.28754550226,31.434176681745,-76.65274289327,2,1,18 +2025-03-11T12:38:26.859436,479392709,4,177,43.14618560366,31.276815650745,-76.388501668415,2,1,18 +2025-03-11T12:38:26.875061,479392709,4,177,43.0142496983,31.11484985385,-76.110391916375,2,1,18 +2025-03-11T12:38:26.890686,479392709,4,177,42.86346580646,30.952851445095,-75.832255040315,2,1,18 +2025-03-11T12:38:26.906311,479392709,4,177,42.69854592476,30.81393393657,-75.54494815511,2,1,18 +2025-03-11T12:38:26.921936,479392709,4,177,42.53362604306,30.67039535622,-75.25300154684,2,1,18 +2025-03-11T12:38:26.937561,479392709,4,177,42.36870616136,30.51761463222,-74.965639041635,2,1,18 +2025-03-11T12:38:26.953186,479392709,4,177,42.19907428304,30.346341467955,-74.678195595425,2,1,18 +2025-03-11T12:38:26.968811,479392709,4,177,42.0482903912,30.179721987375,-74.390797813235,2,1,18 +2025-03-11T12:38:26.984436,479392709,4,177,41.89750649936,30.01772357862,-74.103418571045,2,1,18 +2025-03-11T12:38:27.000061,479392709,4,177,41.7420106109,29.851095945075,-73.783665726395,2,1,18 +2025-03-11T12:38:27.015686,479392709,4,177,41.57237873258,29.68906492446,-73.49163817712,2,1,18 +2025-03-11T12:38:27.031311,479392709,4,177,41.39803485764,29.531646822705,-73.20886475297,2,1,18 +2025-03-11T12:38:27.046936,479392709,4,177,41.23782697256,29.38811639532,-72.91230374264,2,1,18 +2025-03-11T12:38:27.062561,479392709,4,177,41.06819509424,29.226085374705,-72.59717027804,2,1,18 +2025-03-11T12:38:27.078186,479392709,4,177,40.8938512193,29.045561913825,-72.272713506305,2,1,18 +2025-03-11T12:38:27.093811,479392709,4,177,40.71950734436,28.85117523747,-71.94820111457,2,1,18 +2025-03-11T12:38:27.109436,479392709,4,177,40.5404514728,28.661401479975,-71.628321664895,2,1,18 +2025-03-11T12:38:27.125061,479392709,4,177,40.37081959448,28.49012831571,-71.294666388035,2,1,18 +2025-03-11T12:38:27.140686,479392709,4,177,40.19176372292,28.29573348639,-70.970147215295,2,1,18 +2025-03-11T12:38:27.156311,479392709,4,177,40.01270785136,28.11058080072,-70.627180390295,2,1,18 +2025-03-11T12:38:27.171936,479392709,4,177,39.82422798656,27.939275024595,-70.29811917248,2,1,18 +2025-03-11T12:38:27.187561,479392709,4,177,39.63574812176,27.75872710482,-69.97364205773,2,1,18 +2025-03-11T12:38:27.203186,479392709,4,177,39.46140424682,27.56896150029,-69.639905839865,2,1,18 +2025-03-11T12:38:27.218811,479392709,4,177,39.27763637864,27.374558518005,-69.28765278773,2,1,18 +2025-03-11T12:38:27.234436,479392709,4,177,39.09386851046,27.18939767937,-68.935436815595,2,1,18 +2025-03-11T12:38:27.250061,479392709,4,177,38.89596465242,26.999591310015,-68.601666692705,2,1,18 +2025-03-11T12:38:27.265686,479392709,4,177,38.69806079438,26.80978494066,-68.267896569815,2,1,18 +2025-03-11T12:38:27.281311,479392709,4,177,38.51900492282,26.62463225499,-67.90182382949,2,1,18 +2025-03-11T12:38:27.296936,479392709,4,177,38.3258130614,26.439455110425,-67.51724601389,2,1,18 +2025-03-11T12:38:27.312561,479392709,4,177,38.12790920336,26.235785525595,-67.160314355675,2,1,18 +2025-03-11T12:38:27.328186,479392709,4,177,37.93471734194,26.027503021905,-66.803370938465,2,1,18 +2025-03-11T12:38:27.343811,479392709,4,177,37.74152548052,25.819220518215,-66.437185155125,2,1,18 +2025-03-11T12:38:27.359436,479392709,4,177,37.53890962586,25.629405995895,-66.071059969775,2,1,18 +2025-03-11T12:38:27.375061,479392709,4,177,37.33158177458,25.425720105135,-65.700251200355,2,1,18 +2025-03-11T12:38:27.390686,479392709,4,177,37.12896591992,25.22204236734,-65.343312761135,2,1,18 +2025-03-11T12:38:27.406311,479392709,4,177,36.93106206188,25.013751710685,-64.98636256292,2,1,18 +2025-03-11T12:38:27.421936,479392709,4,177,36.72844620722,24.81007397289,-64.59245465918,2,1,18 +2025-03-11T12:38:27.437561,479392709,4,177,36.51640635932,24.606379929165,-64.21701792569,2,1,18 +2025-03-11T12:38:27.453186,479392709,4,177,36.28551852494,24.39341112993,-63.83227462205,2,1,18 +2025-03-11T12:38:27.468811,479392709,4,177,36.07347867704,24.15736958343,-63.452086925495,2,1,18 +2025-03-11T12:38:27.484436,479392709,4,177,35.86143882914,23.944433396055,-63.067370745875,2,1,18 +2025-03-11T12:38:27.500061,479392709,4,177,35.6635349711,23.750005954875,-62.68274906927,2,1,18 +2025-03-11T12:38:27.515686,479392709,4,177,35.47034310968,23.54634452301,-62.28885472754,2,1,18 +2025-03-11T12:38:27.531311,479392709,4,177,35.2630152584,23.310311129475,-61.90867381199,2,1,18 +2025-03-11T12:38:27.546936,479392709,4,177,35.03683942064,23.10197155503,-61.505471097095,2,1,18 +2025-03-11T12:38:27.562561,479392709,4,177,34.81066358288,22.884389836935,-61.106852485265,2,1,18 +2025-03-11T12:38:27.578186,479392709,4,177,34.5797757485,22.657557822225,-60.6989476463,2,1,18 +2025-03-11T12:38:27.593811,479392709,4,177,34.35831190736,22.43536318527,-60.29569609241,2,1,18 +2025-03-11T12:38:27.609436,479392709,4,177,34.13684806622,22.21778962014,-59.878599529325,2,1,18 +2025-03-11T12:38:27.625061,479392709,4,177,33.91067222846,21.990965758395,-59.479943837495,2,1,18 +2025-03-11T12:38:27.640686,479392709,4,177,33.67978439408,21.76875481551,-59.05357280627,2,1,18 +2025-03-11T12:38:27.656311,479392709,4,177,33.45832055294,21.537318034905,-58.636420623185,2,1,18 +2025-03-11T12:38:27.671936,479392709,4,177,33.2368567118,21.3058812543,-58.223889623165,2,1,18 +2025-03-11T12:38:27.687561,479392709,4,177,33.01068087404,21.07443632073,-57.806730659075,2,1,18 +2025-03-11T12:38:27.703186,479392709,4,177,32.76094505318,20.842950622335,-57.39878015609,2,1,18 +2025-03-11T12:38:27.718811,479392709,4,177,32.53476921542,20.58840032964,-56.986149675065,2,1,18 +2025-03-11T12:38:27.734436,479392709,4,177,32.30388138104,20.36156831493,-56.55051773771,2,1,18 +2025-03-11T12:38:27.750061,479392709,4,177,32.07299354666,20.139357372045,-56.12876788955,2,1,18 +2025-03-11T12:38:27.765686,479392709,4,177,31.84210571228,19.89866214186,-55.70694388139,2,1,18 +2025-03-11T12:38:27.781311,479392709,4,177,31.61592987452,19.66721720829,-55.257436635845,2,1,18 +2025-03-11T12:38:27.796936,479392709,4,177,31.38033004352,19.42651382514,-54.812499931355,2,1,18 +2025-03-11T12:38:27.812561,479392709,4,177,31.1400182159,19.195044432675,-54.372214708925,2,1,18 +2025-03-11T12:38:27.828186,479392709,4,177,30.89970638828,18.93584860926,-53.95492416182,2,1,18 +2025-03-11T12:38:27.843811,479392709,4,177,30.66410655728,18.690524154285,-53.505347734265,2,1,18 +2025-03-11T12:38:27.859436,479392709,4,177,30.4096587398,18.449788159275,-53.060383905755,2,1,18 +2025-03-11T12:38:27.875061,479392709,4,177,30.1740589088,18.190600488825,-52.61999422433,2,1,18 +2025-03-11T12:38:27.890686,479392709,4,177,29.93374708118,17.94988895271,-52.16118718964,2,1,18 +2025-03-11T12:38:27.906311,479392709,4,177,29.69814725018,17.71842771321,-51.72552993128,2,1,18 +2025-03-11T12:38:27.921936,479392709,4,177,29.45783542256,17.468474033445,-51.280549365785,2,1,18 +2025-03-11T12:38:27.937561,479392709,4,177,29.19867560846,17.204624526345,-50.83548605627,2,1,18 +2025-03-11T12:38:27.953186,479392709,4,177,28.93951579436,16.95463823472,-50.38585718369,2,1,18 +2025-03-11T12:38:27.968811,479392709,4,177,28.70391596336,16.709313779745,-49.927038390005,2,1,18 +2025-03-11T12:38:27.984436,479392709,4,177,28.44946814588,16.450093497435,-49.463515669235,2,1,18 +2025-03-11T12:38:28.000061,479392709,4,177,28.18088433854,16.19084875623,-48.995351422385,2,1,18 +2025-03-11T12:38:28.015686,479392709,4,177,27.93114851768,15.950120914185,-48.536530825685,2,1,18 +2025-03-11T12:38:28.031311,479392709,4,177,27.68141269682,15.695529856665,-48.06379105979,2,1,18 +2025-03-11T12:38:28.046936,479392709,4,177,27.42696487934,15.43168850253,-47.595628615955,2,1,18 +2025-03-11T12:38:28.062561,479392709,4,177,27.16309306862,15.177072986115,-47.132110873175,2,1,18 +2025-03-11T12:38:28.078186,479392709,4,177,26.91335724776,14.913239784945,-46.654712844215,2,1,18 +2025-03-11T12:38:28.093811,479392709,4,177,26.65419743366,14.658632421495,-46.177338333245,2,1,18 +2025-03-11T12:38:28.109436,479392709,4,177,26.38561362632,14.40862982394,-45.718453532525,2,1,18 +2025-03-11T12:38:28.125061,479392709,4,177,26.13587780546,14.140175550945,-45.2364157805,2,1,18 +2025-03-11T12:38:28.140686,479392709,4,177,25.88142998798,13.87633419681,-44.768253336665,2,1,18 +2025-03-11T12:38:28.156311,479392709,4,177,25.61755817726,13.612476536745,-44.276971415495,2,1,18 +2025-03-11T12:38:28.171936,479392709,4,177,25.36311035978,13.34863518261,-43.78108187327,2,1,18 +2025-03-11T12:38:28.187561,479392709,4,177,25.10395054568,13.089406747335,-43.299067639235,2,1,18 +2025-03-11T12:38:28.203186,479392709,4,177,24.84007873496,12.83479123092,-42.817065164195,2,1,18 +2025-03-11T12:38:28.218811,479392709,4,177,24.56207093438,12.57090911196,-42.33500526614,2,1,18 +2025-03-11T12:38:28.234436,479392709,4,177,24.29819912366,12.29318823642,-41.839046541905,2,1,18 +2025-03-11T12:38:28.250061,479392709,4,177,24.03432731294,12.020088432705,-41.338485174605,2,1,18 +2025-03-11T12:38:28.265686,479392709,4,177,23.7657435056,11.737738332375,-40.860985861625,2,1,18 +2025-03-11T12:38:28.281311,479392709,4,177,23.49715969826,11.464630375695,-40.38814481171,2,1,18 +2025-03-11T12:38:28.296936,479392709,4,177,23.23799988416,11.200780868595,-39.887627305415,2,1,18 +2025-03-11T12:38:28.312561,479392709,4,177,22.9647040802,10.932285830775,-39.377828549975,2,1,18 +2025-03-11T12:38:28.328186,479392709,4,177,22.67256028976,10.64989496562,-38.886431782775,2,1,18 +2025-03-11T12:38:28.343811,479392709,4,177,22.40397648242,10.362923793465,-38.390429197535,2,1,18 +2025-03-11T12:38:28.359436,479392709,4,177,22.12125668522,10.085170306065,-37.899064532345,2,1,18 +2025-03-11T12:38:28.375061,479392709,4,177,21.84796088126,9.82129634007,-37.398526683035,2,1,18 +2025-03-11T12:38:28.390686,479392709,4,177,21.5746650773,9.529695943125,-36.888635227595,2,1,18 +2025-03-11T12:38:28.406311,479392709,4,177,21.30136927334,9.26582197713,-36.397339744415,2,1,18 +2025-03-11T12:38:28.421936,479392709,4,177,21.02807346938,8.992705867485,-35.89214363204,2,1,18 +2025-03-11T12:38:28.437561,479392709,4,177,20.75477766542,8.71958975784,-35.368462787405,2,1,18 +2025-03-11T12:38:28.453186,479392709,4,177,20.4673458716,8.451070261125,-34.863264872015,2,1,18 +2025-03-11T12:38:28.468811,479392709,4,177,20.17520208116,8.16867939597,-34.36724692175,2,1,18 +2025-03-11T12:38:28.484436,479392709,4,177,19.9019062772,7.867836855375,-33.861939569375,2,1,18 +2025-03-11T12:38:28.500061,479392709,4,177,19.60976248676,7.59468813387,-33.33823160072,2,1,18 +2025-03-11T12:38:28.515686,479392709,4,177,19.33175468618,7.31232172761,-32.82374926121,2,1,18 +2025-03-11T12:38:28.531311,479392709,4,177,19.05845888222,7.04382668979,-32.30470813964,2,1,18 +2025-03-11T12:38:28.546936,479392709,4,177,18.78516307826,6.76608950832,-31.790251121135,2,1,18 +2025-03-11T12:38:28.562561,479392709,4,177,18.50715527768,6.460617742935,-31.275676081625,2,1,18 +2025-03-11T12:38:28.578186,479392709,4,177,18.23857147034,6.16440442713,-30.761151684125,2,1,18 +2025-03-11T12:38:28.593811,479392709,4,177,17.9464276799,5.872771418325,-30.241990738535,2,1,18 +2025-03-11T12:38:28.609436,479392709,4,177,17.64957189284,5.58575132838,-29.708978002745,2,1,18 +2025-03-11T12:38:28.625061,479392709,4,177,17.36685209564,5.312618912805,-29.189904779165,2,1,18 +2025-03-11T12:38:28.640686,479392709,4,177,17.07942030182,5.04409941609,-28.66160094845,2,1,18 +2025-03-11T12:38:28.656311,479392709,4,177,16.791988508,4.7617167039,-28.142483863865,2,1,18 +2025-03-11T12:38:28.671936,479392709,4,177,16.5092687108,4.470100001025,-27.63720002948,2,1,18 +2025-03-11T12:38:28.687561,479392709,4,177,16.20770092712,4.17845068629,-27.10878315575,2,1,18 +2025-03-11T12:38:28.703186,479392709,4,177,15.92498112992,3.89145505524,-26.58965431217,2,1,18 +2025-03-11T12:38:28.718811,479392709,4,177,15.64697332934,3.59060436168,-26.04737071427,2,1,18 +2025-03-11T12:38:28.734436,479392709,4,177,15.36425353214,3.298987658805,-25.5004962323,2,1,18 +2025-03-11T12:38:28.750061,479392709,4,177,15.06739774508,3.01196756886,-24.981347045705,2,1,18 +2025-03-11T12:38:28.765686,479392709,4,177,14.77054195802,2.71108426344,-24.466763422175,2,1,18 +2025-03-11T12:38:28.781311,479392709,4,177,14.48782216082,2.428709704215,-23.9337895694,2,1,18 +2025-03-11T12:38:28.796936,479392709,4,177,14.200390367,2.127842704725,-23.40073477562,2,1,18 +2025-03-11T12:38:28.812561,479392709,4,177,13.90824657656,1.83620969592,-22.86308909777,2,1,18 +2025-03-11T12:38:28.828186,479392709,4,177,13.61610278612,1.544576687115,-22.33468578605,2,1,18 +2025-03-11T12:38:28.843811,479392709,4,177,13.3286709923,1.252951831275,-21.787804523075,2,1,18 +2025-03-11T12:38:28.859436,479392709,4,177,13.03652720186,0.970560966120001,-21.250195925225,2,1,18 +2025-03-11T12:38:28.875061,479392709,4,177,12.7396714148,0.674298732525001,-20.726388475565,2,1,18 +2025-03-11T12:38:28.890686,479392709,4,177,12.45223962098,0.382673876685,-20.18874957872,2,1,18 +2025-03-11T12:38:28.906311,479392709,4,177,12.1506718373,0.0956456337749998,-19.64186651273,2,1,18 +2025-03-11T12:38:28.921936,479392709,4,177,11.84910405362,-0.20524582461,-19.099549009805,2,1,18 +2025-03-11T12:38:28.937561,479392709,4,177,11.5616722598,-0.519976039575,-18.57105977909,2,1,18 +2025-03-11T12:38:28.953186,479392709,4,177,11.26952846936,-0.81160904838,-18.038035284305,2,1,18 +2025-03-11T12:38:28.968811,479392709,4,177,10.96796068568,-1.103258363115,-17.49575486138,2,1,18 +2025-03-11T12:38:28.984436,479392709,4,177,10.67110489862,-1.404141668535,-16.9349594072,2,1,18 +2025-03-11T12:38:29.000061,479392709,4,177,10.37424911156,-1.70040390213,-16.39266722528,2,1,18 +2025-03-11T12:38:29.015686,479392709,4,177,10.08210532112,-2.001279054585,-15.8457421013,2,1,18 +2025-03-11T12:38:29.031311,479392709,4,177,9.78996153068,-2.297533135215,-15.331183798775,2,1,18 +2025-03-11T12:38:29.046936,479392709,4,177,9.48368175038,-2.607674890215,-14.79344361791,2,1,18 +2025-03-11T12:38:29.062561,479392709,4,177,9.19153795994,-2.90855004267,-14.232654944735,2,1,18 +2025-03-11T12:38:29.078186,479392709,4,177,8.88054618302,-3.19559459151,-13.695000682865,2,1,18 +2025-03-11T12:38:29.093811,479392709,4,177,8.5931143892,-3.491840519175,-13.16658561215,2,1,18 +2025-03-11T12:38:29.109436,479392709,4,177,8.30568259538,-3.78808644684,-12.619685809175,2,1,18 +2025-03-11T12:38:29.125061,479392709,4,177,7.98526682522,-4.07514730161,-12.072775619165,2,1,18 +2025-03-11T12:38:29.140686,479392709,4,177,7.70254702802,-4.38062721996,-11.53046670026,2,1,18 +2025-03-11T12:38:29.156311,479392709,4,177,7.40097924434,-4.70462403747,-10.98343531427,2,1,18 +2025-03-11T12:38:29.171936,479392709,4,177,7.09941146066,-5.00089442403,-10.431893985215,2,1,18 +2025-03-11T12:38:29.187561,479392709,4,177,6.80726767022,-5.301769576485,-9.884968861235,2,1,18 +2025-03-11T12:38:29.203186,479392709,4,177,6.51041188316,-5.593410738255,-9.342695219315,2,1,18 +2025-03-11T12:38:29.218811,479392709,4,177,6.20884409948,-5.88506005299,-8.79117243026,2,1,18 +2025-03-11T12:38:29.234436,479392709,4,177,5.90256431918,-6.20444395164,-8.24877398633,2,1,18 +2025-03-11T12:38:29.250061,479392709,4,177,5.59628453888,-6.509964634815,-7.692567613205,2,1,18 +2025-03-11T12:38:29.265686,479392709,4,177,5.30885274506,-6.801589490655,-7.14568635023,2,1,18 +2025-03-11T12:38:29.281311,479392709,4,177,5.01670895462,-7.088601427635,-6.60805921238,2,1,18 +2025-03-11T12:38:29.296936,479392709,4,177,4.71042917432,-7.389501038985,-6.05649256232,2,1,18 +2025-03-11T12:38:29.312561,479392709,4,177,4.39472540078,-7.69503802809,-5.51413617638,2,1,18 +2025-03-11T12:38:29.328186,479392709,4,177,4.0931576171,-7.995929486475,-4.971818673455,2,1,18 +2025-03-11T12:38:29.343811,479392709,4,177,3.7868778368,-8.28296588235,-4.438792375655,2,1,18 +2025-03-11T12:38:29.359436,479392709,4,177,3.5041580396,-8.57920365705,-3.88727817062,2,1,18 +2025-03-11T12:38:29.375061,479392709,4,177,3.20730225254,-8.884708034295,-3.32646417644,2,1,18 +2025-03-11T12:38:29.390686,479392709,4,177,2.91044646548,-9.20869669884,-2.77481838839,2,1,18 +2025-03-11T12:38:29.406311,479392709,4,177,2.60416668518,-9.504975238365,-2.24175501059,2,1,18 +2025-03-11T12:38:29.421936,479392709,4,177,2.30731089812,-9.805858543785,-1.69020192254,2,1,18 +2025-03-11T12:38:29.437561,479392709,4,177,1.9963191212,-10.11600845175,-1.138591411475,2,1,18 +2025-03-11T12:38:29.453186,479392709,4,177,1.69946333414,-10.42613390082,-0.577758877295,2,1,18 +2025-03-11T12:38:29.468811,479392709,4,177,1.4073195437,-10.708524765975,-0.0493926455750007,2,1,18 +2025-03-11T12:38:29.484436,479392709,4,177,1.10575176002,-10.995553008885,0.50211160348,2,1,18 +2025-03-11T12:38:29.500061,479392709,4,177,0.79947197972,-11.31031583571,1.03524914128,2,1,18 +2025-03-11T12:38:29.515686,479392709,4,177,0.4884802028,-11.6066025282,1.57294048315,2,1,18 +2025-03-11T12:38:29.531311,479392709,4,177,0.19633641236,-11.90285660883,2.133710616325,2,1,18 +2025-03-11T12:38:29.546936,479392709,4,177,-0.0958073780800001,-12.194489617635,2.689841026435,2,1,18 +2025-03-11T12:38:29.562561,479392709,4,177,-0.39737516176,-12.500002147845,3.24141943549,2,1,18 +2025-03-11T12:38:29.578186,479392709,4,177,-0.69894294544,-12.796272534405,3.79758194761,2,1,18 +2025-03-11T12:38:29.593811,479392709,4,177,-1.00522272574,-13.11103536123,4.33996185154,2,1,18 +2025-03-11T12:38:29.609436,479392709,4,177,-1.30679050942,-13.41654789144,4.8776767114,2,1,18 +2025-03-11T12:38:29.625061,479392709,4,177,-1.59422230324,-13.70817274728,5.406073242115,2,1,18 +2025-03-11T12:38:29.640686,479392709,4,177,-1.87694210044,-13.999789450155,5.93908417489,2,1,18 +2025-03-11T12:38:29.656311,479392709,4,177,-2.16908589088,-14.28218031531,6.46745040661,2,1,18 +2025-03-11T12:38:29.671936,479392709,4,177,-2.46594167794,-14.59230576438,7.0005558424,2,1,18 +2025-03-11T12:38:29.687561,479392709,4,177,-2.76750946162,-14.902439366415,7.552152791455,2,1,18 +2025-03-11T12:38:29.703186,479392709,4,177,-3.0690772453,-15.19408868115,8.10367558051,2,1,18 +2025-03-11T12:38:29.718811,479392709,4,177,-3.3517970425,-15.49032645585,8.636705053285,2,1,18 +2025-03-11T12:38:29.734436,479392709,4,177,-3.64394083294,-15.80506482378,9.174443431135,2,1,18 +2025-03-11T12:38:29.750061,479392709,4,177,-3.94550861662,-16.10133521034,9.721363577125,2,1,18 +2025-03-11T12:38:29.765686,479392709,4,177,-4.24236440368,-16.39297637211,10.26825840211,2,1,18 +2025-03-11T12:38:29.781311,479392709,4,177,-4.53450819412,-16.693851524565,10.810562343025,2,1,18 +2025-03-11T12:38:29.796936,479392709,4,177,-4.8360759778,-16.99474298295,11.32515274756,2,1,18 +2025-03-11T12:38:29.812561,479392709,4,177,-5.12350777162,-17.27712569514,11.871996930535,2,1,18 +2025-03-11T12:38:29.828186,479392709,4,177,-5.4250755553,-17.5549117944,12.40497936733,2,1,18 +2025-03-11T12:38:29.843811,479392709,4,177,-5.72193134236,-17.83731081252,12.933352380055,2,1,18 +2025-03-11T12:38:29.859436,479392709,4,177,-6.03292311928,-18.119734289535,13.470988101925,2,1,18 +2025-03-11T12:38:29.875061,479392709,4,177,-6.3203549131,-18.4344645045,13.99947733264,2,1,18 +2025-03-11T12:38:29.890686,479392709,4,177,-6.6030747103,-18.735323351025,14.541767711545,2,1,18 +2025-03-11T12:38:29.906311,479392709,4,177,-6.87637051426,-19.022302676145,15.06550417618,2,1,18 +2025-03-11T12:38:29.921936,479392709,4,177,-7.1685143047,-19.300072469475,15.607715417095,2,1,18 +2025-03-11T12:38:29.937561,479392709,4,177,-7.46065809514,-19.596326550105,16.136137268815,2,1,18 +2025-03-11T12:38:29.953186,479392709,4,177,-7.76222587882,-19.89721800849,16.664591222545,2,1,18 +2025-03-11T12:38:29.968811,479392709,4,177,-8.04494567602,-20.198076855015,17.193018052255,2,1,18 +2025-03-11T12:38:29.984436,479392709,4,177,-8.32766547322,-20.48969355789,17.721407801965,2,1,18 +2025-03-11T12:38:30.000000,479392713,0,178,-8.61980926366,-20.78594763852,18.240587287555,2,1,18 +2025-03-11T12:38:30.015625,479392713,0,178,-8.90252906086,-21.068322197745,18.768939957265,2,1,18 +2025-03-11T12:38:30.031250,479392713,0,178,-9.18053686144,-21.34606753218,19.29726730597,2,1,18 +2025-03-11T12:38:30.046875,479392713,0,178,-9.48210464512,-21.63309577509,19.811802090505,2,1,18 +2025-03-11T12:38:30.062500,479392713,0,178,-9.77896043218,-21.910873721385,20.34015656323,2,1,18 +2025-03-11T12:38:30.078125,479392713,0,178,-10.05696823276,-22.183997983995,20.873086555,2,1,18 +2025-03-11T12:38:30.093750,479392713,0,178,-10.3491120232,-22.4756309928,21.40148986672,2,1,18 +2025-03-11T12:38:30.109375,479392713,0,178,-10.6318318204,-22.758005552025,21.9206001703,2,1,18 +2025-03-11T12:38:30.125000,479392713,0,178,-10.91926361422,-23.058872551515,22.43517023182,2,1,18 +2025-03-11T12:38:30.140625,479392713,0,178,-11.20198341142,-23.34124711074,22.958901718465,2,1,18 +2025-03-11T12:38:30.156250,479392713,0,178,-11.48470320862,-23.61900059814,23.46412993285,2,1,18 +2025-03-11T12:38:30.171875,479392713,0,178,-11.75328701596,-23.896729626645,23.97858017035,2,1,18 +2025-03-11T12:38:30.187500,479392713,0,178,-12.03600681316,-24.18834632952,24.49772755393,2,1,18 +2025-03-11T12:38:30.203125,479392713,0,178,-12.31401461374,-24.46147059213,25.01217281344,2,1,18 +2025-03-11T12:38:30.218750,479392713,0,178,-12.59673441094,-24.72998193588,25.508121581695,2,1,18 +2025-03-11T12:38:30.234375,479392713,0,178,-12.87474221152,-25.01234834214,26.031846287335,2,1,18 +2025-03-11T12:38:30.250000,479392713,0,178,-13.14803801548,-25.29932766726,26.54634038584,2,1,18 +2025-03-11T12:38:30.265625,479392713,0,178,-13.42133381944,-25.581685920555,27.051573578215,2,1,18 +2025-03-11T12:38:30.281250,479392713,0,178,-13.6946296234,-25.8732863175,27.542980301395,2,1,18 +2025-03-11T12:38:30.296875,479392713,0,178,-13.96792542736,-26.15102349897,28.043573770705,2,1,18 +2025-03-11T12:38:30.312500,479392713,0,178,-14.2365092347,-26.428752527475,28.558024008205,2,1,18 +2025-03-11T12:38:30.328125,479392713,0,178,-14.4956690488,-26.701844178225,29.072442143695,2,1,18 +2025-03-11T12:38:30.343750,479392713,0,178,-14.79252483586,-26.975001052695,29.568429794965,2,1,18 +2025-03-11T12:38:30.359375,479392713,0,178,-15.07995662968,-27.238899477585,30.05974562116,2,1,18 +2025-03-11T12:38:30.375000,479392713,0,178,-15.35796443026,-27.521265883845,30.55574322841,2,1,18 +2025-03-11T12:38:30.390625,479392713,0,178,-15.64068422746,-27.789777227595,31.042449630535,2,1,18 +2025-03-11T12:38:30.406250,479392713,0,178,-15.89984404156,-28.053626734695,31.5337247707,2,1,18 +2025-03-11T12:38:30.421875,479392713,0,178,-16.15900385566,-28.326718385445,32.025036990865,2,1,18 +2025-03-11T12:38:30.437500,479392713,0,178,-16.42287566638,-28.595197117335,32.5209586351,2,1,18 +2025-03-11T12:38:30.453125,479392713,0,178,-16.70088346696,-28.868321379945,33.003055613155,2,1,18 +2025-03-11T12:38:30.468750,479392713,0,178,-16.9694672743,-29.141429336625,33.49438139533,2,1,18 +2025-03-11T12:38:30.484375,479392713,0,178,-17.23333908502,-29.409908068515,33.97643949037,2,1,18 +2025-03-11T12:38:30.500000,479392713,0,178,-17.49721089574,-29.678386800405,34.46773995154,2,1,18 +2025-03-11T12:38:30.515625,479392713,0,178,-17.75165871322,-29.946849226365,34.954405667635,2,1,18 +2025-03-11T12:38:30.531250,479392713,0,178,-18.01553052394,-30.206085814605,35.45029023187,2,1,18 +2025-03-11T12:38:30.546875,479392713,0,178,-18.29353832452,-30.460725789915,35.93693423299,2,1,18 +2025-03-11T12:38:30.562500,479392713,0,178,-18.55741013524,-30.73382559363,36.40052613577,2,1,18 +2025-03-11T12:38:30.578125,479392713,0,178,-18.81656994934,-30.99767510073,36.85945299448,2,1,18 +2025-03-11T12:38:30.593750,479392713,0,178,-19.07572976344,-31.256903536005,37.322982496255,2,1,18 +2025-03-11T12:38:30.609375,479392713,0,178,-19.33960157416,-31.525382267895,37.795798225165,2,1,18 +2025-03-11T12:38:30.625000,479392713,0,178,-19.6081853815,-31.77538486545,38.273167758145,2,1,18 +2025-03-11T12:38:30.640625,479392713,0,178,-19.85792120236,-32.016112707495,38.750473087105,2,1,18 +2025-03-11T12:38:30.656250,479392713,0,178,-20.10765702322,-32.27532483684,39.21398902687,2,1,18 +2025-03-11T12:38:30.671875,479392713,0,178,-20.35268084746,-32.520665597745,39.67744256563,2,1,18 +2025-03-11T12:38:30.687500,479392713,0,178,-20.60241666832,-32.775256655265,40.150182331525,2,1,18 +2025-03-11T12:38:30.703125,479392713,0,178,-20.84744049256,-33.034460631645,40.59982794109,2,1,18 +2025-03-11T12:38:30.718750,479392713,0,178,-21.09717631342,-33.28443061734,41.05868561779,2,1,18 +2025-03-11T12:38:30.734375,479392713,0,178,-21.3516241309,-33.529787684175,41.517531535495,2,1,18 +2025-03-11T12:38:30.750000,479392713,0,178,-21.60607194838,-33.78438689466,41.96717216707,2,1,18 +2025-03-11T12:38:30.765625,479392713,0,178,-21.85580776924,-34.034356880355,42.430651026835,2,1,18 +2025-03-11T12:38:30.781250,479392713,0,178,-22.11967957996,-34.284351324945,42.88952904655,2,1,18 +2025-03-11T12:38:30.796875,479392713,0,178,-22.35527941096,-34.53891792357,43.329900187975,2,1,18 +2025-03-11T12:38:30.812500,479392713,0,178,-22.58616724534,-34.78423422558,43.760985102265,2,1,18 +2025-03-11T12:38:30.828125,479392713,0,178,-22.8359030662,-35.024962067625,44.201320966705,2,1,18 +2025-03-11T12:38:30.843750,479392713,0,178,-23.0715028972,-35.26104437895,44.65086031426,2,1,18 +2025-03-11T12:38:30.859375,479392713,0,178,-23.31652672144,-35.515627283505,45.09586620076,2,1,18 +2025-03-11T12:38:30.875000,479392713,0,178,-23.5662625423,-35.760976197375,45.531599422135,2,1,18 +2025-03-11T12:38:30.890625,479392713,0,178,-23.81128636654,-35.983211599155,45.99033907783,2,1,18 +2025-03-11T12:38:30.906250,479392713,0,178,-24.04688619754,-36.214672838655,46.421375153125,2,1,18 +2025-03-11T12:38:30.921875,479392713,0,178,-24.29191002178,-36.44152931226,46.85240625043,2,1,18 +2025-03-11T12:38:30.937500,479392713,0,178,-24.53693384602,-36.68224900134,47.27887178467,2,1,18 +2025-03-11T12:38:30.953125,479392713,0,178,-24.75368569054,-36.93216191628,47.709954895945,2,1,18 +2025-03-11T12:38:30.968750,479392713,0,178,-24.9798615283,-37.168227921675,48.1317535831,2,1,18 +2025-03-11T12:38:30.984375,479392713,0,178,-25.22017335592,-37.404318385965,48.54433024714,2,1,18 +2025-03-11T12:38:31.000000,479392713,0,178,-25.4510611903,-37.6357714725,48.95687480917,2,1,18 +2025-03-11T12:38:31.015625,479392713,0,178,-25.65838904158,-37.86718379421,49.378627832305,2,1,18 +2025-03-11T12:38:31.031250,479392713,0,178,-25.88456487934,-38.084765512305,49.80035235946,2,1,18 +2025-03-11T12:38:31.046875,479392713,0,178,-26.1107407171,-38.31158937405,50.19900805129,2,1,18 +2025-03-11T12:38:31.062500,479392713,0,178,-26.33220455824,-38.543026154655,50.606917868245,2,1,18 +2025-03-11T12:38:31.078125,479392713,0,178,-26.56780438924,-38.76986632233,51.014829488215,2,1,18 +2025-03-11T12:38:31.093750,479392713,0,178,-26.80340422024,-38.978222202705,51.41804576512,2,1,18 +2025-03-11T12:38:31.109375,479392713,0,178,-27.02486806138,-39.205037911485,51.81207349288,2,1,18 +2025-03-11T12:38:31.125000,479392713,0,178,-27.25575589576,-39.42724885437,52.219959791845,2,1,18 +2025-03-11T12:38:31.140625,479392713,0,178,-27.45837175042,-39.64478980764,52.61854449865,2,1,18 +2025-03-11T12:38:31.156250,479392713,0,178,-27.67041159832,-39.85310492319,53.007863321335,2,1,18 +2025-03-11T12:38:31.171875,479392713,0,178,-27.88245144622,-40.07990432604,53.383392754825,2,1,18 +2025-03-11T12:38:31.187500,479392713,0,178,-28.08506730088,-40.30668742296,53.786635724695,2,1,18 +2025-03-11T12:38:31.203125,479392713,0,178,-28.29239515216,-40.51037331372,54.18979277557,2,1,18 +2025-03-11T12:38:31.218750,479392713,0,178,-28.49972300344,-40.73254349178,54.56991807112,2,1,18 +2025-03-11T12:38:31.234375,479392713,0,178,-28.72118684458,-40.95011705691,54.93618162049,2,1,18 +2025-03-11T12:38:31.250000,479392713,0,178,-28.94265068572,-41.153827406565,55.32087428212,2,1,18 +2025-03-11T12:38:31.265625,479392713,0,178,-29.14526654038,-41.362126216185,55.710179542795,2,1,18 +2025-03-11T12:38:31.281250,479392713,0,178,-29.3620183849,-41.56120734105,56.09484688342,2,1,18 +2025-03-11T12:38:31.296875,479392713,0,178,-29.55992224294,-41.75563478223,56.4563626447,2,1,18 +2025-03-11T12:38:31.312500,479392713,0,178,-29.7625380976,-41.959312520025,56.845649365375,2,1,18 +2025-03-11T12:38:31.328125,479392713,0,178,-29.96515395226,-42.176853473295,57.202643424595,2,1,18 +2025-03-11T12:38:31.343750,479392713,0,178,-30.17248180354,-42.38516043588,57.545743635625,2,1,18 +2025-03-11T12:38:31.359375,479392713,0,178,-30.38452165144,-42.58423340778,57.921161829115,2,1,18 +2025-03-11T12:38:31.375000,479392713,0,178,-30.57771351286,-42.78327376782,58.287310532455,2,1,18 +2025-03-11T12:38:31.390625,479392713,0,178,-30.7756173709,-42.96845906535,58.66265276293,2,1,18 +2025-03-11T12:38:31.406250,479392713,0,178,-30.96880923232,-43.162878353565,59.01954056014,2,1,18 +2025-03-11T12:38:31.421875,479392713,0,178,-31.15728909712,-43.35266841699,59.376403036345,2,1,18 +2025-03-11T12:38:31.437500,479392713,0,178,-31.35048095854,-43.547087705205,59.73791201662,2,1,18 +2025-03-11T12:38:31.453125,479392713,0,178,-31.5295368301,-43.741482534525,60.067052372425,2,1,18 +2025-03-11T12:38:31.468750,479392713,0,178,-31.71330469828,-43.93588551681,60.41006305843,2,1,18 +2025-03-11T12:38:31.484375,479392713,0,178,-31.89236056984,-44.116417130655,60.75301134343,2,1,18 +2025-03-11T12:38:31.500000,479392713,0,178,-32.07612843802,-44.306199041115,61.09138230637,2,1,18 +2025-03-11T12:38:31.515625,479392713,0,178,-32.2598963062,-44.5006020234,61.434392992375,2,1,18 +2025-03-11T12:38:31.531250,479392713,0,178,-32.44366417438,-44.676520718385,61.76808715225,2,1,18 +2025-03-11T12:38:31.546875,479392713,0,178,-32.63214403918,-44.84782649451,62.07404245474,2,1,18 +2025-03-11T12:38:31.562500,479392713,0,178,-32.81591190736,-45.02836626132,62.38464923929,2,1,18 +2025-03-11T12:38:31.578125,479392713,0,178,-32.99967977554,-45.21814817178,62.718399019165,2,1,18 +2025-03-11T12:38:31.593750,479392713,0,178,-33.18344764372,-45.394066866765,63.03360844678,2,1,18 +2025-03-11T12:38:31.609375,479392713,0,178,-33.35779151866,-45.55148496852,63.339487786255,2,1,18 +2025-03-11T12:38:31.625000,479392713,0,178,-33.52271140036,-45.72274997982,63.67313628211,2,1,18 +2025-03-11T12:38:31.640625,479392713,0,178,-33.6970552753,-45.9032734407,64.00221423691,2,1,18 +2025-03-11T12:38:31.656250,479392713,0,178,-33.861975157,-46.088401667475,64.298948888245,2,1,18 +2025-03-11T12:38:31.671875,479392713,0,178,-34.03160703532,-46.255053759915,64.595616160585,2,1,18 +2025-03-11T12:38:31.687500,479392713,0,178,-34.20123891364,-46.403221565055,64.90607282212,2,1,18 +2025-03-11T12:38:31.703125,479392713,0,178,-34.37558278858,-46.56063966681,65.230436893855,2,1,18 +2025-03-11T12:38:31.718750,479392713,0,178,-34.53579067366,-46.72727545332,65.527090604185,2,1,18 +2025-03-11T12:38:31.734375,479392713,0,178,-34.69599855874,-46.88466909618,65.81908605145,2,1,18 +2025-03-11T12:38:31.750000,479392713,0,178,-34.86091844044,-47.042070892005,66.115709462785,2,1,18 +2025-03-11T12:38:31.765625,479392713,0,178,-35.02583832214,-47.21795697513,66.398543484925,2,1,18 +2025-03-11T12:38:31.781250,479392713,0,178,-35.17662221398,-47.370713240235,66.67202209792,2,1,18 +2025-03-11T12:38:31.796875,479392713,0,178,-35.33211810244,-47.514235514655,66.93622804579,2,1,18 +2025-03-11T12:38:31.812500,479392713,0,178,-35.48290199428,-47.67623392341,67.228228471045,2,1,18 +2025-03-11T12:38:31.828125,479392713,0,178,-35.62426189288,-47.819731738935,67.52014117429,2,1,18 +2025-03-11T12:38:31.843750,479392713,0,178,-35.76562179148,-47.95398741081,67.775047333015,2,1,18 +2025-03-11T12:38:31.859375,479392713,0,178,-35.91640568332,-48.115985819565,68.043941842945,2,1,18 +2025-03-11T12:38:31.875000,479392713,0,178,-36.06247757854,-48.268733931705,68.289686576545,2,1,18 +2025-03-11T12:38:31.890625,479392713,0,178,-36.20854947376,-48.402997756545,68.55846306547,2,1,18 +2025-03-11T12:38:31.906250,479392713,0,178,-36.34519737574,-48.55110849093,68.83190279545,2,1,18 +2025-03-11T12:38:31.921875,479392713,0,178,-36.48655727434,-48.703848450105,69.086883114175,2,1,18 +2025-03-11T12:38:31.937500,479392713,0,178,-36.6420531628,-48.8427496527,69.33720697285,2,1,18 +2025-03-11T12:38:31.953125,479392713,0,178,-36.78812505802,-48.97701347754,69.587498729515,2,1,18 +2025-03-11T12:38:31.968750,479392713,0,178,-36.91063697014,-49.111236537555,69.84237776422,2,1,18 +2025-03-11T12:38:31.984375,479392713,0,178,-37.02843688564,-49.24083037278,70.074125562595,2,1,18 +2025-03-11T12:38:32.000000,479392713,0,178,-37.160372791,-49.3889329542,70.31983141318,2,1,18 +2025-03-11T12:38:32.015625,479392713,0,178,-37.29230869636,-49.532414463795,70.55165517457,2,1,18 +2025-03-11T12:38:32.031250,479392713,0,178,-37.42895659834,-49.65279876723,70.783393016965,2,1,18 +2025-03-11T12:38:32.046875,479392713,0,178,-37.54204451722,-49.777763377665,71.0197366774,2,1,18 +2025-03-11T12:38:32.062500,479392713,0,178,-37.65984443272,-49.893493997415,71.25605003884,2,1,18 +2025-03-11T12:38:32.078125,479392713,0,178,-37.79178033808,-50.01849121971,71.473936091035,2,1,18 +2025-03-11T12:38:32.093750,479392713,0,178,-37.9142922502,-50.1296089206,71.68251059509,2,1,18 +2025-03-11T12:38:32.109375,479392713,0,178,-38.03680416232,-50.24996876514,71.88650099608,2,1,18 +2025-03-11T12:38:32.125000,479392713,0,178,-38.16402807106,-50.36571569082,72.118206736465,2,1,18 +2025-03-11T12:38:32.140625,479392713,0,178,-38.2676919967,-50.4860429235,72.3267911965,2,1,18 +2025-03-11T12:38:32.156250,479392713,0,178,-38.38077991558,-50.59714431846,72.535352138545,2,1,18 +2025-03-11T12:38:32.171875,479392713,0,178,-38.5032918277,-50.712883091175,72.7439451826,2,1,18 +2025-03-11T12:38:32.187500,479392713,0,178,-38.63051573644,-50.83325108868,72.94332118153,2,1,18 +2025-03-11T12:38:32.203125,479392713,0,178,-38.73417966208,-50.93509403406,73.142589115435,2,1,18 +2025-03-11T12:38:32.218750,479392713,0,178,-38.82370759786,-51.04153359237,73.332612880195,2,1,18 +2025-03-11T12:38:32.234375,479392713,0,178,-38.91794753026,-51.147981303645,73.518022242895,2,1,18 +2025-03-11T12:38:32.250000,479392713,0,178,-39.01689945928,-51.254437167885,73.71268075273,2,1,18 +2025-03-11T12:38:32.265625,479392713,0,178,-39.11113939168,-51.356263807335,73.902692758495,2,1,18 +2025-03-11T12:38:32.281250,479392713,0,178,-39.21951531394,-51.435009546555,74.074147675015,2,1,18 +2025-03-11T12:38:32.296875,479392713,0,178,-39.3278912362,-51.541481716725,74.23185028234,2,1,18 +2025-03-11T12:38:32.312500,479392713,0,178,-39.42684316522,-51.647937580965,74.39416051072,2,1,18 +2025-03-11T12:38:32.328125,479392713,0,178,-39.52579509424,-51.745151301555,74.570297208295,2,1,18 +2025-03-11T12:38:32.343750,479392713,0,178,-39.61532303002,-51.842348716215,74.74642034386,2,1,18 +2025-03-11T12:38:32.359375,479392713,0,178,-39.7048509658,-51.9256829154,74.91786667636,2,1,18 +2025-03-11T12:38:32.375000,479392713,0,178,-39.78966690496,-51.99976681797,75.080026781725,2,1,18 +2025-03-11T12:38:32.390625,479392713,0,178,-39.87448284412,-52.09233500784,75.256124596285,2,1,18 +2025-03-11T12:38:32.406250,479392713,0,178,-39.95929878328,-52.171039982235,75.40906087552,2,1,18 +2025-03-11T12:38:32.421875,479392713,0,178,-40.04882671906,-52.240510965945,75.538860940435,2,1,18 +2025-03-11T12:38:32.437500,479392713,0,178,-40.13835465484,-52.32384516513,75.673337808415,2,1,18 +2025-03-11T12:38:32.453125,479392713,0,178,-40.1996106109,-52.4025093747,75.83086136569,2,1,18 +2025-03-11T12:38:32.468750,479392713,0,178,-40.26557856358,-52.499666024535,75.97922349784,2,1,18 +2025-03-11T12:38:32.484375,479392713,0,178,-40.35039450274,-52.573749927105,76.11827768788,2,1,18 +2025-03-11T12:38:32.500000,479392713,0,178,-40.42578644866,-52.638575380095,76.25728123591,2,1,18 +2025-03-11T12:38:32.515625,479392713,0,178,-40.49646639796,-52.698771608295,76.387017096805,2,1,18 +2025-03-11T12:38:32.531250,479392713,0,178,-40.5765703405,-52.768226286075,76.502940050515,2,1,18 +2025-03-11T12:38:32.546875,479392713,0,178,-40.64253829318,-52.82841436131,76.60956321508,2,1,18 +2025-03-11T12:38:32.562500,479392713,0,178,-40.694370256,-52.902441193125,76.71622165663,2,1,18 +2025-03-11T12:38:32.578125,479392713,0,178,-40.76033820868,-52.98111355566,76.85526726265,2,1,18 +2025-03-11T12:38:32.593750,479392713,0,178,-40.82630616136,-53.03668055907,76.96649307028,2,1,18 +2025-03-11T12:38:32.609375,479392713,0,178,-40.89227411404,-53.10148970613,77.06851359178,2,1,18 +2025-03-11T12:38:32.625000,479392713,0,178,-40.94881807348,-53.15704040361,77.175104654335,2,1,18 +2025-03-11T12:38:32.640625,479392713,0,178,-41.00536203292,-53.217212172915,77.277093073825,2,1,18 +2025-03-11T12:38:32.656250,479392713,0,178,-41.0477700025,-53.26349626785,77.374384347235,2,1,18 +2025-03-11T12:38:32.671875,479392713,0,178,-41.09960196532,-53.309796668715,77.480931548785,2,1,18 +2025-03-11T12:38:32.687500,479392713,0,178,-41.15614592476,-53.356105222545,77.582864348275,2,1,18 +2025-03-11T12:38:32.703125,479392713,0,178,-41.20797788758,-53.42088991071,77.680243343695,2,1,18 +2025-03-11T12:38:32.718750,479392713,0,178,-41.2598098504,-53.4533270961,77.759007826855,2,1,18 +2025-03-11T12:38:32.734375,479392713,0,178,-41.30221781998,-53.481126903735,77.80539192655,2,1,18 +2025-03-11T12:38:32.750000,479392713,0,178,-41.34462578956,-53.53665314232,77.87499318157,2,1,18 +2025-03-11T12:38:32.765625,479392713,0,178,-41.38703375914,-53.56907402178,77.96298646885,2,1,18 +2025-03-11T12:38:32.781250,479392713,0,178,-41.41530573886,-53.60609151417,78.023250854725,2,1,18 +2025-03-11T12:38:32.796875,479392713,0,178,-41.4482897152,-53.652359303175,78.083559101605,2,1,18 +2025-03-11T12:38:32.812500,479392713,0,178,-41.49069768478,-53.68015911081,78.14842793356,2,1,18 +2025-03-11T12:38:32.828125,479392713,0,178,-41.52368166112,-53.717184756165,78.204077917375,2,1,18 +2025-03-11T12:38:32.843750,479392713,0,178,-41.56137763408,-53.74959748266,78.259716142195,2,1,18 +2025-03-11T12:38:32.859375,479392713,0,178,-41.58493761718,-53.78198575026,78.319955207065,2,1,18 +2025-03-11T12:38:32.875000,479392713,0,178,-41.61792159352,-53.81439032379,78.37558665088,2,1,18 +2025-03-11T12:38:32.890625,479392713,0,178,-41.64619357324,-53.837544600705,78.408068318365,2,1,18 +2025-03-11T12:38:32.906250,479392713,0,178,-41.66975355634,-53.851448581005,78.449748490975,2,1,18 +2025-03-11T12:38:32.921875,479392713,0,178,-41.67917754958,-53.86532810241,78.49140832057,2,1,18 +2025-03-11T12:38:32.937500,479392713,0,178,-41.69331353944,-53.874594704955,78.52381402504,2,1,18 +2025-03-11T12:38:32.953125,479392713,0,178,-41.71687352254,-53.88387761343,78.551612108455,2,1,18 +2025-03-11T12:38:32.968750,479392713,0,178,-41.74043350564,-53.911644809205,78.57948435187,2,1,18 +2025-03-11T12:38:32.984375,479392713,0,178,-41.74043350564,-53.920886952855,78.59800616413,2,1,18 +2025-03-11T12:38:33.000000,479392713,0,178,-41.74043350564,-53.92550802468,78.611888253325,2,1,18 +2025-03-11T12:38:33.015625,479392713,0,178,-41.74985749888,-53.930145402435,78.62578390453,2,1,18 +2025-03-11T12:38:33.031250,479392713,0,178,-41.76399348874,-53.93016986133,78.63966779674,2,1,18 +2025-03-11T12:38:33.046875,479392713,0,178,-41.75928149212,-53.939403852015,78.65356164493,2,1,18 +2025-03-11T12:38:33.062500,479392713,0,178,-41.76399348874,-53.95789629228,78.662884952065,2,1,18 +2025-03-11T12:38:33.078125,479392713,0,178,-41.78284147522,-53.953307832315,78.653651169955,2,1,18 +2025-03-11T12:38:33.093750,479392713,0,178,-41.76870548536,-53.94404122977,78.639730197745,2,1,18 +2025-03-11T12:38:33.109375,479392713,0,178,-41.76399348874,-53.93941200498,78.64894724287,2,1,18 +2025-03-11T12:38:33.125000,479392713,0,178,-41.75928149212,-53.939403852015,78.66280401106,2,1,18 +2025-03-11T12:38:33.140625,479392713,0,178,-41.74985749888,-53.94400861791,78.63508189066,2,1,18 +2025-03-11T12:38:33.156250,479392713,0,178,-41.74514550226,-53.93937939312,78.61195065433,2,1,18 +2025-03-11T12:38:33.171875,479392713,0,178,-41.73572150902,-53.93012094354,78.598036463125,2,1,18 +2025-03-11T12:38:33.187500,479392713,0,178,-41.71687352254,-53.90236190073,78.551686268455,2,1,18 +2025-03-11T12:38:33.203125,479392713,0,178,-41.70273753268,-53.86074779541,78.51452960092,2,1,18 +2025-03-11T12:38:33.218750,479392713,0,178,-41.69331353944,-53.85148934583,78.48675186052,2,1,18 +2025-03-11T12:38:33.234375,479392713,0,178,-41.66504155972,-53.846819356215,78.4589655361,2,1,18 +2025-03-11T12:38:33.250000,479392713,0,178,-41.65090556986,-53.832931681845,78.42654129163,2,1,18 +2025-03-11T12:38:33.265625,479392713,0,178,-41.62263359014,-53.805156333105,78.384798718015,2,1,18 +2025-03-11T12:38:33.281250,479392713,0,178,-41.60378560366,-53.79126050577,78.347746509475,2,1,18 +2025-03-11T12:38:33.296875,479392713,0,178,-41.58493761718,-53.786606822085,78.28762546561,2,1,18 +2025-03-11T12:38:33.312500,479392713,0,178,-41.55195364084,-53.754202248555,78.222751655665,2,1,18 +2025-03-11T12:38:33.328125,479392713,0,178,-41.53310565436,-53.72182213392,78.1625193718,2,1,18 +2025-03-11T12:38:33.343750,479392713,0,178,-41.4954096814,-53.689409407425,78.093017597785,2,1,18 +2025-03-11T12:38:33.359375,479392713,0,178,-41.46713770168,-53.64777084321,78.037355854975,2,1,18 +2025-03-11T12:38:33.375000,479392713,0,178,-41.42944172872,-53.59225275759,77.981624930155,2,1,18 +2025-03-11T12:38:33.390625,479392713,0,178,-41.38232176252,-53.54596050969,77.902811608,2,1,18 +2025-03-11T12:38:33.406250,479392713,0,178,-41.3304897997,-53.508902252475,77.83327095097,2,1,18 +2025-03-11T12:38:33.421875,479392713,0,178,-41.29750582336,-53.46263446347,77.759099154895,2,1,18 +2025-03-11T12:38:33.437500,479392713,0,178,-41.26452184702,-53.40250345899,77.680250555755,2,1,18 +2025-03-11T12:38:33.453125,479392713,0,178,-41.22211387744,-53.356219364055,77.57833809928,2,1,18 +2025-03-11T12:38:33.468750,479392713,0,178,-41.165569918,-53.300668666575,77.48561058592,2,1,18 +2025-03-11T12:38:33.484375,479392713,0,178,-41.10902595856,-53.254360112745,77.406783701755,2,1,18 +2025-03-11T12:38:33.500000,479392713,0,178,-41.05719399574,-53.203438640055,77.318702692465,2,1,18 +2025-03-11T12:38:33.515625,479392713,0,178,-41.00536203292,-53.161759311015,77.22603758011,2,1,18 +2025-03-11T12:38:33.531250,479392713,0,178,-40.96766605996,-53.106241225395,77.12409482464,2,1,18 +2025-03-11T12:38:33.546875,479392713,0,178,-40.91112210052,-53.06455374339,77.01293819902,2,1,18 +2025-03-11T12:38:33.562500,479392713,0,178,-40.8357301546,-52.995107218575,76.89240084325,2,1,18 +2025-03-11T12:38:33.578125,479392713,0,178,-40.76976220192,-52.930298071515,76.767274406425,2,1,18 +2025-03-11T12:38:33.593750,479392713,0,178,-40.72264223572,-52.86090046449,76.674504835075,2,1,18 +2025-03-11T12:38:33.609375,479392713,0,178,-40.66138627966,-52.78223625492,76.57243547458,2,1,18 +2025-03-11T12:38:33.625000,479392713,0,178,-40.58128233712,-52.717402648965,76.442667511675,2,1,18 +2025-03-11T12:38:33.640625,479392713,0,178,-40.51531438444,-52.66645671738,76.30835432872,2,1,18 +2025-03-11T12:38:33.656250,479392713,0,178,-40.43992243852,-52.59238912074,76.164692517625,2,1,18 +2025-03-11T12:38:33.671875,479392713,0,178,-40.35981849598,-52.518313371135,76.04412984085,2,1,18 +2025-03-11T12:38:33.687500,479392713,0,178,-40.28913854668,-52.439632855635,75.90969863689,2,1,18 +2025-03-11T12:38:33.703125,479392713,0,178,-40.20903460414,-52.34707281873,75.75671351866,2,1,18 +2025-03-11T12:38:33.718750,479392713,0,178,-40.13835465484,-52.263771231405,75.60377904244,2,1,18 +2025-03-11T12:38:33.734375,479392713,0,178,-40.06767470554,-52.18046964408,75.45084456622,2,1,18 +2025-03-11T12:38:33.750000,479392713,0,178,-39.99228275962,-52.11564419109,75.297977468995,2,1,18 +2025-03-11T12:38:33.765625,479392713,0,178,-39.88861883398,-52.036906604835,75.13577169961,2,1,18 +2025-03-11T12:38:33.781250,479392713,0,178,-39.78966690496,-51.948935027895,74.978156814295,2,1,18 +2025-03-11T12:38:33.796875,479392713,0,178,-39.70956296242,-51.870238206465,74.825227316065,2,1,18 +2025-03-11T12:38:33.812500,479392713,0,178,-39.62474702326,-51.768427872945,74.658334787635,2,1,18 +2025-03-11T12:38:33.828125,479392713,0,178,-39.53521908748,-51.65736724281,74.4913983982,2,1,18 +2025-03-11T12:38:33.843750,479392713,0,178,-39.43626715846,-51.56015352222,74.32912524982,2,1,18 +2025-03-11T12:38:33.859375,479392713,0,178,-39.34202722606,-51.47681117007,74.157672136315,2,1,18 +2025-03-11T12:38:33.875000,479392713,0,178,-39.24778729366,-51.361121315145,73.972225693615,2,1,18 +2025-03-11T12:38:33.890625,479392713,0,178,-39.15825935788,-51.25006068501,73.77756220579,2,1,18 +2025-03-11T12:38:33.906250,479392713,0,178,-39.05930742886,-51.157468036245,73.58758049902,2,1,18 +2025-03-11T12:38:33.921875,479392713,0,178,-38.95564350322,-51.06948830634,73.39298936818,2,1,18 +2025-03-11T12:38:33.937500,479392713,0,178,-38.85197957758,-50.963024289135,73.202945260405,2,1,18 +2025-03-11T12:38:33.953125,479392713,0,178,-38.74831565194,-50.85656027193,73.03138588489,2,1,18 +2025-03-11T12:38:33.968750,479392713,0,178,-38.63051573644,-50.754692867655,72.82285524184,2,1,18 +2025-03-11T12:38:33.984375,479392713,0,178,-38.51271582094,-50.62509903243,72.60497099266,2,1,18 +2025-03-11T12:38:33.999954,479392716,65532,179,-38.39962790206,-50.51399763747,72.40103123368,2,1,18 +2025-03-11T12:38:34.015579,479392716,65532,179,-38.2912519798,-50.402904395475,72.206340621835,2,1,18 +2025-03-11T12:38:34.031204,479392716,65532,179,-38.1734520643,-50.29179484755,72.007015264915,2,1,18 +2025-03-11T12:38:34.046829,479392716,65532,179,-38.0556521488,-50.1575799405,71.779870109605,2,1,18 +2025-03-11T12:38:34.062454,479392716,65532,179,-37.9378522333,-50.0326071771,71.55738321736,2,1,18 +2025-03-11T12:38:34.078079,479392716,65532,179,-37.82476431442,-49.926126853965,71.348840815315,2,1,18 +2025-03-11T12:38:34.093704,479392716,65532,179,-37.70696439892,-49.79653301874,71.121714200005,2,1,18 +2025-03-11T12:38:34.109329,479392716,65532,179,-37.57974049018,-49.67154394941,70.885350196555,2,1,18 +2025-03-11T12:38:34.124954,479392716,65532,179,-37.45251658144,-49.53731273643,70.667433845365,2,1,18 +2025-03-11T12:38:34.140579,479392716,65532,179,-37.32058067608,-49.38921015501,70.43097036091,2,1,18 +2025-03-11T12:38:34.156204,479392716,65532,179,-37.1839327741,-49.2734469234,70.19462987545,2,1,18 +2025-03-11T12:38:34.171829,479392716,65532,179,-37.05670886536,-49.14845785407,69.93978113974,2,1,18 +2025-03-11T12:38:34.187454,479392716,65532,179,-36.93419695324,-49.00037157858,69.694088851165,2,1,18 +2025-03-11T12:38:34.203079,479392716,65532,179,-36.79754905126,-48.852260844195,69.45299740264,2,1,18 +2025-03-11T12:38:34.218704,479392716,65532,179,-36.66090114928,-48.72263439711,69.202737747985,2,1,18 +2025-03-11T12:38:34.234329,479392716,65532,179,-36.51954125068,-48.60224194071,68.943266026195,2,1,18 +2025-03-11T12:38:34.249954,479392716,65532,179,-36.37346935546,-48.454114900395,68.6836762834,2,1,18 +2025-03-11T12:38:34.265579,479392716,65532,179,-36.22739746024,-48.31523000373,68.424123620605,2,1,18 +2025-03-11T12:38:34.281204,479392716,65532,179,-36.08603756164,-48.17635326003,68.146093006555,2,1,18 +2025-03-11T12:38:34.296829,479392716,65532,179,-35.92582967656,-48.023580688995,67.886464380745,2,1,18 +2025-03-11T12:38:34.312454,479392716,65532,179,-35.77504578472,-47.88006656754,67.62226521388,2,1,18 +2025-03-11T12:38:34.328079,479392716,65532,179,-35.61954989626,-47.722681077645,67.344140096815,2,1,18 +2025-03-11T12:38:34.343704,479392716,65532,179,-35.47347800104,-47.56531189368,67.07527090789,2,1,18 +2025-03-11T12:38:34.359329,479392716,65532,179,-35.3226941092,-47.4171767004,66.801810834895,2,1,18 +2025-03-11T12:38:34.374954,479392716,65532,179,-35.16719822074,-47.26441228233,66.5144618917,2,1,18 +2025-03-11T12:38:34.390579,479392716,65532,179,-35.01170233228,-47.11164786426,66.22249176544,2,1,18 +2025-03-11T12:38:34.406204,479392716,65532,179,-34.84678245058,-46.963488212085,65.93052661717,2,1,18 +2025-03-11T12:38:34.421829,479392716,65532,179,-34.67715057226,-46.78297290417,65.629182541765,2,1,18 +2025-03-11T12:38:34.437454,479392716,65532,179,-34.5216546838,-46.60248205515,65.33247999244,2,1,18 +2025-03-11T12:38:34.453079,479392716,65532,179,-34.3802947852,-46.4543631678,65.03592756613,2,1,18 +2025-03-11T12:38:34.468704,479392716,65532,179,-34.21066290688,-46.301574290835,64.725452364595,2,1,18 +2025-03-11T12:38:34.484329,479392716,65532,179,-34.0504550218,-46.125696360675,64.4241403912,2,1,18 +2025-03-11T12:38:34.499954,479392716,65532,179,-33.8855351401,-45.954431349375,64.118218993735,2,1,18 +2025-03-11T12:38:34.515579,479392716,65532,179,-33.71119126516,-45.77852896032,63.80302312813,2,1,18 +2025-03-11T12:38:34.531204,479392716,65532,179,-33.54627138346,-45.61650609267,63.497138810665,2,1,18 +2025-03-11T12:38:34.546829,479392716,65532,179,-33.37663950514,-45.454475072055,63.19586889526,2,1,18 +2025-03-11T12:38:34.562454,479392716,65532,179,-33.2022956302,-45.283193754825,62.871449203525,2,1,18 +2025-03-11T12:38:34.578079,479392716,65532,179,-33.02323975864,-45.09341999733,62.53308502159,2,1,18 +2025-03-11T12:38:34.593704,479392716,65532,179,-32.84418388708,-44.90826731166,62.194739379655,2,1,18 +2025-03-11T12:38:34.609329,479392716,65532,179,-32.66984001214,-44.732364922605,61.87030114792,2,1,18 +2025-03-11T12:38:34.624954,479392716,65532,179,-32.50020813382,-44.56109175834,61.541267054125,2,1,18 +2025-03-11T12:38:34.640579,479392716,65532,179,-32.31172826902,-44.380543838565,61.22141112244,2,1,18 +2025-03-11T12:38:34.656204,479392716,65532,179,-32.1185364076,-44.195366694,60.88304513749,2,1,18 +2025-03-11T12:38:34.671829,479392716,65532,179,-31.94419253266,-44.000980017645,60.558532745755,2,1,18 +2025-03-11T12:38:34.687454,479392716,65532,179,-31.75100067124,-43.81580287308,60.21554557774,2,1,18 +2025-03-11T12:38:34.703079,479392716,65532,179,-31.5530968132,-43.635238647375,59.86332780259,2,1,18 +2025-03-11T12:38:34.718704,479392716,65532,179,-31.35519295516,-43.440811206195,59.524917956635,2,1,18 +2025-03-11T12:38:34.734329,479392716,65532,179,-31.16200109374,-43.25563406163,59.17268842249,2,1,18 +2025-03-11T12:38:34.749954,479392716,65532,179,-30.9640972357,-43.0519644768,58.80189321508,2,1,18 +2025-03-11T12:38:34.765579,479392716,65532,179,-30.76148138104,-42.848286739005,58.449575958925,2,1,18 +2025-03-11T12:38:34.781204,479392716,65532,179,-30.56828951962,-42.649246378965,58.092669621715,2,1,18 +2025-03-11T12:38:34.796829,479392716,65532,179,-30.38452165144,-42.450222324855,57.735776846515,2,1,18 +2025-03-11T12:38:34.812454,479392716,65532,179,-30.20075378326,-42.251198270745,57.37426288825,2,1,18 +2025-03-11T12:38:34.828079,479392716,65532,179,-30.00284992522,-42.05214975774,56.998865037775,2,1,18 +2025-03-11T12:38:34.843704,479392716,65532,179,-29.80494606718,-41.862343388385,56.637367816495,2,1,18 +2025-03-11T12:38:34.859329,479392716,65532,179,-29.59290621928,-41.654028272835,56.261912543005,2,1,18 +2025-03-11T12:38:34.874954,479392716,65532,179,-29.385578368,-41.431858094775,55.88640843052,2,1,18 +2025-03-11T12:38:34.890579,479392716,65532,179,-29.18296251334,-41.20045392603,55.52011638517,2,1,18 +2025-03-11T12:38:34.906204,479392716,65532,179,-28.98034665868,-40.99215511641,55.13543230756,2,1,18 +2025-03-11T12:38:34.921829,479392716,65532,179,-28.75417082092,-40.783815541965,54.759956691055,2,1,18 +2025-03-11T12:38:34.937454,479392716,65532,179,-28.52799498316,-40.570854895695,54.38446253455,2,1,18 +2025-03-11T12:38:34.953079,479392716,65532,179,-28.32066713188,-40.36254793311,53.99515049287,2,1,18 +2025-03-11T12:38:34.968704,479392716,65532,179,-28.12276327384,-40.14963620463,53.61507583933,2,1,18 +2025-03-11T12:38:34.984329,479392716,65532,179,-27.91072342594,-39.94132108908,53.225757016645,2,1,18 +2025-03-11T12:38:34.999954,479392716,65532,179,-27.6892595848,-39.728368595775,52.813300176625,2,1,18 +2025-03-11T12:38:35.015579,479392716,65532,179,-27.46779574366,-39.50617395882,52.40542743967,2,1,18 +2025-03-11T12:38:35.031204,479392716,65532,179,-27.265179889,-39.27014871825,52.016010938995,2,1,18 +2025-03-11T12:38:35.046829,479392716,65532,179,-27.04842804448,-39.052583306085,51.61278470611,2,1,18 +2025-03-11T12:38:35.062454,479392716,65532,179,-26.82225220672,-38.83500158799,51.21416609428,2,1,18 +2025-03-11T12:38:35.078079,479392716,65532,179,-26.58665237572,-38.60354034849,50.81547830044,2,1,18 +2025-03-11T12:38:35.093704,479392716,65532,179,-26.37461252782,-38.36749880199,50.416805871625,2,1,18 +2025-03-11T12:38:35.109329,479392716,65532,179,-26.17199667316,-38.14995784872,49.99973643256,2,1,18 +2025-03-11T12:38:35.124954,479392716,65532,179,-25.93639684216,-37.932359824695,49.59186189259,2,1,18 +2025-03-11T12:38:35.140579,479392716,65532,179,-25.7102210044,-37.700914891125,49.188566477695,2,1,18 +2025-03-11T12:38:35.156204,479392716,65532,179,-25.48404516664,-37.47409102938,48.762183687475,2,1,18 +2025-03-11T12:38:35.171829,479392716,65532,179,-25.24373333902,-37.242621636915,48.32651964811,2,1,18 +2025-03-11T12:38:35.187454,479392716,65532,179,-25.00813350802,-37.020402541065,47.895520652815,2,1,18 +2025-03-11T12:38:35.203079,479392716,65532,179,-24.77724567364,-36.793570526355,47.47837344772,2,1,18 +2025-03-11T12:38:35.218704,479392716,65532,179,-24.55106983588,-36.552883449135,47.06117740363,2,1,18 +2025-03-11T12:38:35.234329,479392716,65532,179,-24.32489399812,-36.312196371915,46.62549662728,2,1,18 +2025-03-11T12:38:35.249954,479392716,65532,179,-24.08929416712,-36.05762977329,46.18050430279,2,1,18 +2025-03-11T12:38:35.265579,479392716,65532,179,-23.85840633274,-35.83079775858,45.744872365435,2,1,18 +2025-03-11T12:38:35.281204,479392716,65532,179,-23.61809450512,-35.58546515064,45.304531523005,2,1,18 +2025-03-11T12:38:35.296829,479392716,65532,179,-23.37307068088,-35.330882246085,44.868768002635,2,1,18 +2025-03-11T12:38:35.312454,479392716,65532,179,-23.1186228634,-35.099388394725,44.423841254125,2,1,18 +2025-03-11T12:38:35.328079,479392716,65532,179,-22.86888704254,-34.854039480855,43.96962330049,2,1,18 +2025-03-11T12:38:35.343704,479392716,65532,179,-22.61915122168,-34.61331163881,43.524666252985,2,1,18 +2025-03-11T12:38:35.359329,479392716,65532,179,-22.38355139068,-34.36336611201,43.07507128543,2,1,18 +2025-03-11T12:38:35.374954,479392716,65532,179,-22.14795155968,-34.13190487251,42.63941402707,2,1,18 +2025-03-11T12:38:35.390579,479392716,65532,179,-21.8935037422,-33.886547805675,42.189810475495,2,1,18 +2025-03-11T12:38:35.406204,479392716,65532,179,-21.62963193148,-33.63193228926,41.74015628191,2,1,18 +2025-03-11T12:38:35.421829,479392716,65532,179,-21.38460810724,-33.38197045653,41.29516893541,2,1,18 +2025-03-11T12:38:35.437454,479392716,65532,179,-21.139584283,-33.136629695625,40.83171539665,2,1,18 +2025-03-11T12:38:35.453079,479392716,65532,179,-20.89927245538,-32.86819172856,40.37279712196,2,1,18 +2025-03-11T12:38:35.468704,479392716,65532,179,-20.64953663452,-32.618221742865,39.909318262195,2,1,18 +2025-03-11T12:38:35.484329,479392716,65532,179,-20.39508881704,-32.368243604205,39.445832621425,2,1,18 +2025-03-11T12:38:35.499954,479392716,65532,179,-20.13121700632,-32.11362808779,38.97769369558,2,1,18 +2025-03-11T12:38:35.515579,479392716,65532,179,-19.87676918884,-31.849786733655,38.50491006868,2,1,18 +2025-03-11T12:38:35.531204,479392716,65532,179,-19.62232137136,-31.60442966682,38.036821784845,2,1,18 +2025-03-11T12:38:35.546829,479392716,65532,179,-19.35844956064,-31.349814150405,37.582546408195,2,1,18 +2025-03-11T12:38:35.562454,479392716,65532,179,-19.09457774992,-31.08595649034,37.118991585415,2,1,18 +2025-03-11T12:38:35.578079,479392716,65532,179,-18.82599394258,-30.826711749135,36.62772142324,2,1,18 +2025-03-11T12:38:35.593704,479392716,65532,179,-18.5715461251,-30.549007179525,36.14563981021,2,1,18 +2025-03-11T12:38:35.609329,479392716,65532,179,-18.32181030424,-30.285173978355,35.691347696575,2,1,18 +2025-03-11T12:38:35.624954,479392716,65532,179,-18.06736248676,-30.03057476787,35.218601149675,2,1,18 +2025-03-11T12:38:35.640579,479392716,65532,179,-17.8176266659,-29.77598371035,34.72737665152,2,1,18 +2025-03-11T12:38:35.656204,479392716,65532,179,-17.5584668518,-29.489028844125,34.226766445225,2,1,18 +2025-03-11T12:38:35.671829,479392716,65532,179,-17.28517104784,-29.20667059083,33.73077561898,2,1,18 +2025-03-11T12:38:35.687454,479392716,65532,179,-17.0165872405,-28.938183705975,33.22560482761,2,1,18 +2025-03-11T12:38:35.703079,479392716,65532,179,-16.74329143654,-28.669688668155,32.748154353625,2,1,18 +2025-03-11T12:38:35.718704,479392716,65532,179,-16.46999563258,-28.41505684581,32.26151713351,2,1,18 +2025-03-11T12:38:35.734329,479392716,65532,179,-16.191987832,-28.1419325832,31.760935423195,2,1,18 +2025-03-11T12:38:35.749954,479392716,65532,179,-15.92811602128,-27.868832779485,31.269616422025,2,1,18 +2025-03-11T12:38:35.765579,479392716,65532,179,-15.66895620718,-27.614225416035,30.792241911055,2,1,18 +2025-03-11T12:38:35.781204,479392716,65532,179,-15.40037239984,-27.32725424388,30.29161814275,2,1,18 +2025-03-11T12:38:35.796829,479392716,65532,179,-15.11294060602,-27.058734747165,29.781799044295,2,1,18 +2025-03-11T12:38:35.812454,479392716,65532,179,-14.83493280544,-26.785610484555,29.285838517045,2,1,18 +2025-03-11T12:38:35.828079,479392716,65532,179,-14.56163700148,-26.50325223126,28.785226507735,2,1,18 +2025-03-11T12:38:35.843704,479392716,65532,179,-14.28834119752,-26.23475719344,28.284670118425,2,1,18 +2025-03-11T12:38:35.859329,479392716,65532,179,-13.99619740708,-25.952366328285,27.78865216816,2,1,18 +2025-03-11T12:38:35.874954,479392716,65532,179,-13.72761359974,-25.68387944343,27.28348137679,2,1,18 +2025-03-11T12:38:35.890579,479392716,65532,179,-13.46374178902,-25.410779639715,26.796783558685,2,1,18 +2025-03-11T12:38:35.906204,479392716,65532,179,-13.18573398844,-25.12379216163,26.291525045305,2,1,18 +2025-03-11T12:38:35.921829,479392716,65532,179,-12.91243818448,-24.84605498016,25.763204477605,2,1,18 +2025-03-11T12:38:35.937454,479392716,65532,179,-12.64385437714,-24.57294702348,25.248772780105,2,1,18 +2025-03-11T12:38:35.953079,479392716,65532,179,-12.36584657656,-24.28133847357,24.743495726725,2,1,18 +2025-03-11T12:38:35.968704,479392716,65532,179,-12.07841478274,-23.994334689555,24.247466017465,2,1,18 +2025-03-11T12:38:35.984329,479392716,65532,179,-11.79569498554,-23.725823345805,23.72379015082,2,1,18 +2025-03-11T12:38:35.999954,479392716,65532,179,-11.51297518834,-23.45269093023,23.209338110305,2,1,18 +2025-03-11T12:38:36.015579,479392716,65532,179,-11.23496738776,-23.17032452397,22.69947695386,2,1,18 +2025-03-11T12:38:36.031204,479392716,65532,179,-10.94282359732,-22.869449371515,22.166415379075,2,1,18 +2025-03-11T12:38:36.046829,479392716,65532,179,-10.65067980688,-22.563953147235,21.66106236268,2,1,18 +2025-03-11T12:38:36.062454,479392716,65532,179,-10.36796000968,-22.27233644436,21.137293796035,2,1,18 +2025-03-11T12:38:36.078079,479392716,65532,179,-10.07581621924,-21.99456665103,20.58584018899,2,1,18 +2025-03-11T12:38:36.093704,479392716,65532,179,-9.79780841866,-21.71220024477,20.057494300285,2,1,18 +2025-03-11T12:38:36.109329,479392716,65532,179,-9.51508862146,-21.439067829195,19.547663442835,2,1,18 +2025-03-11T12:38:36.124954,479392716,65532,179,-9.23236882426,-21.14745112632,19.037758425385,2,1,18 +2025-03-11T12:38:36.140579,479392716,65532,179,-8.95436102368,-20.860463648235,18.514015179745,2,1,18 +2025-03-11T12:38:36.156204,479392716,65532,179,-8.67164122648,-20.55960480171,17.985588350035,2,1,18 +2025-03-11T12:38:36.171829,479392716,65532,179,-8.36536144618,-20.26794733401,17.443301146105,2,1,18 +2025-03-11T12:38:36.187454,479392716,65532,179,-8.0873536456,-19.990201999575,16.90573143127,2,1,18 +2025-03-11T12:38:36.203079,479392716,65532,179,-7.8046338484,-19.730932799475,16.382092644625,2,1,18 +2025-03-11T12:38:36.218704,479392716,65532,179,-7.51720205458,-19.44392901546,15.86295702004,2,1,18 +2025-03-11T12:38:36.234329,479392716,65532,179,-7.22034626752,-19.12456142274,15.325193321185,2,1,18 +2025-03-11T12:38:36.249954,479392716,65532,179,-6.92820247708,-18.832928413935,14.806032375595,2,1,18 +2025-03-11T12:38:36.265579,479392716,65532,179,-6.63134669002,-18.53666618034,14.25911901061,2,1,18 +2025-03-11T12:38:36.281204,479392716,65532,179,-6.33449090296,-18.22654073127,13.712150025625,2,1,18 +2025-03-11T12:38:36.296829,479392716,65532,179,-6.02349912604,-17.925632966955,13.18830369295,2,1,18 +2025-03-11T12:38:36.312454,479392716,65532,179,-5.74077932884,-17.65250055138,12.655366920175,2,1,18 +2025-03-11T12:38:36.328079,479392716,65532,179,-5.45805953164,-17.36550492033,12.1223745274,2,1,18 +2025-03-11T12:38:36.343704,479392716,65532,179,-5.16120374458,-17.07386375856,11.593964434675,2,1,18 +2025-03-11T12:38:36.359329,479392716,65532,179,-4.87377195076,-16.786859974545,11.03785934557,2,1,18 +2025-03-11T12:38:36.374954,479392716,65532,179,-4.58162816032,-16.48598482209,10.50017658772,2,1,18 +2025-03-11T12:38:36.390579,479392716,65532,179,-4.29890836312,-16.17126276009,9.97169413801,2,1,18 +2025-03-11T12:38:36.406204,479392716,65532,179,-3.99734057944,-15.86575022988,9.447842827345,2,1,18 +2025-03-11T12:38:36.421829,479392716,65532,179,-3.70048479238,-15.560245852635,8.90089238236,2,1,18 +2025-03-11T12:38:36.437454,479392716,65532,179,-3.39420501208,-15.27320945676,8.36786608456,2,1,18 +2025-03-11T12:38:36.453079,479392716,65532,179,-3.09734922502,-14.986189366815,7.83485334877,2,1,18 +2025-03-11T12:38:36.468704,479392716,65532,179,-2.80520543458,-14.67607207071,7.301754693985,2,1,18 +2025-03-11T12:38:36.484329,479392716,65532,179,-2.5036376509,-14.3890438278,6.75949281106,2,1,18 +2025-03-11T12:38:36.499954,479392716,65532,179,-2.19264587398,-14.09275713531,6.207937919995,2,1,18 +2025-03-11T12:38:36.515579,479392716,65532,179,-1.9146380734,-13.805769657225,5.66108875903,2,1,18 +2025-03-11T12:38:36.531204,479392716,65532,179,-1.61778228634,-13.50950742363,5.123417760175,2,1,18 +2025-03-11T12:38:36.546829,479392716,65532,179,-1.3256384959,-13.1947690557,4.58105819926,2,1,18 +2025-03-11T12:38:36.562454,479392716,65532,179,-1.02407071222,-12.88925652549,4.03410097327,2,1,18 +2025-03-11T12:38:36.578079,479392716,65532,179,-0.74135091502,-12.588397678965,3.47794704517,2,1,18 +2025-03-11T12:38:36.593704,479392716,65532,179,-0.4539191212,-12.287530679475,2.931028702195,2,1,18 +2025-03-11T12:38:36.609329,479392716,65532,179,-0.14292734428,-11.991243986985,2.393337360325,2,1,18 +2025-03-11T12:38:36.624954,479392716,65532,179,0.16806443264,-11.704199438145,1.846440732325,2,1,18 +2025-03-11T12:38:36.640579,479392716,65532,179,0.47905620956,-11.39404953018,1.30407258739,2,1,18 +2025-03-11T12:38:36.656204,479392716,65532,179,0.7712,-11.0885533059,0.75712892341,2,1,18 +2025-03-11T12:38:36.671829,479392716,65532,179,1.06334379044,-10.778436009795,0.21940908556,2,1,18 +2025-03-11T12:38:36.687454,479392716,65532,179,1.34606358764,-10.482198235095,-0.322862753345,2,1,18 +2025-03-11T12:38:36.703079,479392716,65532,179,1.64763137132,-10.19054892036,-0.85590081014,2,1,18 +2025-03-11T12:38:36.718704,479392716,65532,179,1.95391115162,-9.88964930901,-1.38898272794,2,1,18 +2025-03-11T12:38:36.734329,479392716,65532,179,2.25076693868,-9.593387075415,-1.95900200825,2,1,18 +2025-03-11T12:38:36.749954,479392716,65532,179,2.54762272574,-9.292503769995,-2.524418645495,2,1,18 +2025-03-11T12:38:36.765579,479392716,65532,179,2.83976651618,-8.99162861754,-3.071343769475,2,1,18 +2025-03-11T12:38:36.781204,479392716,65532,179,3.14604629648,-8.695350078015,-3.613649513405,2,1,18 +2025-03-11T12:38:36.796829,479392716,65532,179,3.44290208354,-8.40832998807,-4.15128343226,2,1,18 +2025-03-11T12:38:36.812454,479392716,65532,179,3.74918186384,-8.102809304895,-4.68438389006,2,1,18 +2025-03-11T12:38:36.828079,479392716,65532,179,4.04132565428,-7.778828793315,-5.236022897105,2,1,18 +2025-03-11T12:38:36.843704,479392716,65532,179,4.34760543458,-7.477929181965,-5.796831913295,2,1,18 +2025-03-11T12:38:36.859329,479392716,65532,179,4.64917321826,-7.172416651755,-6.34841032235,2,1,18 +2025-03-11T12:38:36.874954,479392716,65532,179,4.96016499518,-6.88999317474,-6.881424861155,2,1,18 +2025-03-11T12:38:36.890579,479392716,65532,179,5.26173277886,-6.59372278818,-7.42372382408,2,1,18 +2025-03-11T12:38:36.906204,479392716,65532,179,5.54445257606,-6.28824286983,-7.99838102444,2,1,18 +2025-03-11T12:38:36.921829,479392716,65532,179,5.83188436988,-5.982754798515,-8.536075541285,2,1,18 +2025-03-11T12:38:36.937454,479392716,65532,179,6.12402816032,-5.668016430585,-9.08767746833,2,1,18 +2025-03-11T12:38:36.953079,479392716,65532,179,6.43501993724,-5.37635080992,-9.620729087135,2,1,18 +2025-03-11T12:38:36.968704,479392716,65532,179,6.74129971754,-5.080072270395,-10.158413648,2,1,18 +2025-03-11T12:38:36.984329,479392716,65532,179,7.0381555046,-4.779188964975,-10.714587919115,2,1,18 +2025-03-11T12:38:36.999954,479392716,65532,179,7.33029929504,-4.482934884345,-11.270736869225,2,1,18 +2025-03-11T12:38:37.015579,479392716,65532,179,7.6271550821,-4.18667265075,-11.81765023421,2,1,18 +2025-03-11T12:38:37.031204,479392716,65532,179,7.93814685902,-3.89962810191,-12.350683313015,2,1,18 +2025-03-11T12:38:37.046829,479392716,65532,179,8.24442663932,-3.594107418735,-12.89764732001,2,1,18 +2025-03-11T12:38:37.062454,479392716,65532,179,8.55070641962,-3.28858673556,-13.435368960875,2,1,18 +2025-03-11T12:38:37.078079,479392716,65532,179,8.8522742033,-2.98307420535,-13.98694736993,2,1,18 +2025-03-11T12:38:37.093704,479392716,65532,179,9.14912999036,-2.68219089993,-14.52925809185,2,1,18 +2025-03-11T12:38:37.109329,479392716,65532,179,9.4412737808,-2.399800034775,-15.07610905583,2,1,18 +2025-03-11T12:38:37.124954,479392716,65532,179,9.71928158138,-2.117433628515,-15.61831849373,2,1,18 +2025-03-11T12:38:37.140579,479392716,65532,179,10.01142537182,-1.81655847606,-16.151380068515,2,1,18 +2025-03-11T12:38:37.156204,479392716,65532,179,10.3129931555,-1.5202880895,-16.689057848375,2,1,18 +2025-03-11T12:38:37.171829,479392716,65532,179,10.62869692904,-1.214751100395,-17.231414234315,2,1,18 +2025-03-11T12:38:37.187454,479392716,65532,179,10.93026471272,-0.927722857485,-17.778297300305,2,1,18 +2025-03-11T12:38:37.203079,479392716,65532,179,11.22240850316,-0.63608984868,-18.32056416122,2,1,18 +2025-03-11T12:38:37.218704,479392716,65532,179,11.50512830036,-0.325988858505,-18.862891620125,2,1,18 +2025-03-11T12:38:37.234329,479392716,65532,179,11.79256009418,-0.0158797153650001,-19.40060467697,2,1,18 +2025-03-11T12:38:37.249954,479392716,65532,179,12.08941588124,0.275761446405,-19.94287831889,2,1,18 +2025-03-11T12:38:37.265579,479392716,65532,179,12.38155967168,0.562773383385,-20.475884273675,2,1,18 +2025-03-11T12:38:37.281204,479392716,65532,179,12.68783945198,0.86829406656,-21.01360591454,2,1,18 +2025-03-11T12:38:37.296829,479392716,65532,179,12.98469523904,1.164556300155,-21.542034547265,2,1,18 +2025-03-11T12:38:37.312454,479392716,65532,179,13.2815510261,1.44233424645,-22.065767836925,2,1,18 +2025-03-11T12:38:37.328079,479392716,65532,179,13.56898281992,1.73395910229,-22.598785550705,2,1,18 +2025-03-11T12:38:37.343704,479392716,65532,179,13.85641461374,2.030205029955,-23.12720062142,2,1,18 +2025-03-11T12:38:37.359329,479392716,65532,179,14.13442241432,2.321813579865,-23.66020477319,2,1,18 +2025-03-11T12:38:37.374954,479392716,65532,179,14.44070219462,2.61809211939,-24.18402578486,2,1,18 +2025-03-11T12:38:37.390579,479392716,65532,179,14.7187099952,2.895837453825,-24.71697431663,2,1,18 +2025-03-11T12:38:37.406204,479392716,65532,179,15.01085378564,3.18747046263,-25.249998811415,2,1,18 +2025-03-11T12:38:37.421829,479392716,65532,179,15.29828557946,3.47909531847,-25.792258891325,2,1,18 +2025-03-11T12:38:37.437454,479392716,65532,179,15.59514136652,3.766115408415,-26.31140807792,2,1,18 +2025-03-11T12:38:37.453079,479392716,65532,179,15.88728515696,4.053127345395,-26.83979284964,2,1,18 +2025-03-11T12:38:37.468704,479392716,65532,179,16.17471695078,4.35861541671,-27.368245000355,2,1,18 +2025-03-11T12:38:37.484329,479392716,65532,179,16.46686074122,4.63638521004,-27.915077424335,2,1,18 +2025-03-11T12:38:37.499954,479392716,65532,179,16.75900453166,4.937260362495,-28.42965426686,2,1,18 +2025-03-11T12:38:37.515579,479392716,65532,179,17.04643632548,5.23350629016,-28.94420578838,2,1,18 +2025-03-11T12:38:37.531204,479392716,65532,179,17.3338681193,5.520510074175,-29.472583779095,2,1,18 +2025-03-11T12:38:37.546829,479392716,65532,179,17.59773993002,5.816715237015,-29.991722578655,2,1,18 +2025-03-11T12:38:37.562454,479392716,65532,179,17.8757477306,6.108323786925,-30.52010554736,2,1,18 +2025-03-11T12:38:37.578079,479392716,65532,179,18.16317952442,6.37684328364,-31.04378819501,2,1,18 +2025-03-11T12:38:37.593704,479392716,65532,179,18.46945930472,6.663879679515,-31.562950943615,2,1,18 +2025-03-11T12:38:37.609329,479392716,65532,179,18.75689109854,6.96012560718,-32.0821236482,2,1,18 +2025-03-11T12:38:37.624954,479392716,65532,179,19.0301869025,7.23786278865,-32.596580666705,2,1,18 +2025-03-11T12:38:37.640579,479392716,65532,179,19.3129066997,7.501753060575,-33.12023799335,2,1,18 +2025-03-11T12:38:37.656204,479392716,65532,179,19.58620250366,7.78411131387,-33.606986453465,2,1,18 +2025-03-11T12:38:37.671829,479392716,65532,179,19.86421030424,8.071098791955,-34.11686614991,2,1,18 +2025-03-11T12:38:37.687454,479392716,65532,179,20.15635409468,8.34424751346,-34.6359529355,2,1,18 +2025-03-11T12:38:37.703079,479392716,65532,179,20.44849788512,8.63125945044,-35.131989425765,2,1,18 +2025-03-11T12:38:37.718704,479392716,65532,179,20.73592967894,8.909021090805,-35.627982055025,2,1,18 +2025-03-11T12:38:37.734329,479392716,65532,179,21.02336147276,9.18678273117,-36.133217050415,2,1,18 +2025-03-11T12:38:37.749954,479392716,65532,179,21.28252128686,9.464495453745,-36.656896092035,2,1,18 +2025-03-11T12:38:37.765579,479392716,65532,179,21.54168110096,9.746829248145,-37.171351307525,2,1,18 +2025-03-11T12:38:37.781204,479392716,65532,179,21.81968890154,10.029195654405,-37.67197009784,2,1,18 +2025-03-11T12:38:37.796829,479392716,65532,179,22.08827270888,10.29768253926,-38.154034973885,2,1,18 +2025-03-11T12:38:37.812454,479392716,65532,179,22.36156851284,10.570798648905,-38.65923108626,2,1,18 +2025-03-11T12:38:37.828079,479392716,65532,179,22.6348643168,10.8346726149,-39.155147752505,2,1,18 +2025-03-11T12:38:37.843704,479392716,65532,179,22.90344812414,11.10778057158,-39.660337083875,2,1,18 +2025-03-11T12:38:37.859329,479392716,65532,179,23.18616792134,11.380912987155,-40.160925575195,2,1,18 +2025-03-11T12:38:37.874954,479392716,65532,179,23.46417572192,11.654037249765,-40.647643736315,2,1,18 +2025-03-11T12:38:37.890579,479392716,65532,179,23.72333553602,11.93174997234,-41.14821686261,2,1,18 +2025-03-11T12:38:37.906204,479392716,65532,179,23.98720734674,12.195607632405,-41.625635234585,2,1,18 +2025-03-11T12:38:37.921829,479392716,65532,179,24.25107915746,12.46870743612,-42.116954235755,2,1,18 +2025-03-11T12:38:37.937454,479392716,65532,179,24.51023897156,12.737178015045,-42.60824791592,2,1,18 +2025-03-11T12:38:37.953079,479392716,65532,179,24.7788227789,13.010285971725,-43.090331331965,2,1,18 +2025-03-11T12:38:37.968704,479392716,65532,179,25.05211858286,13.269538865895,-43.572365909015,2,1,18 +2025-03-11T12:38:37.984329,479392716,65532,179,25.3207023902,13.53802575075,-44.04518841893,2,1,18 +2025-03-11T12:38:37.999877,479392720,65527,180,25.58457420092,13.80650448264,-44.513382964775,2,1,18 +2025-03-11T12:38:38.015502,479392720,65527,180,25.83431002178,14.07033768381,-44.990780993735,2,1,18 +2025-03-11T12:38:38.031127,479392720,65527,180,26.08875783926,14.324936894295,-45.49587582209,2,1,18 +2025-03-11T12:38:38.046752,479392720,65527,180,26.35262964998,14.574931338885,-45.95937502487,2,1,18 +2025-03-11T12:38:38.062377,479392720,65527,180,26.61178946408,14.848022989635,-46.42758132971,2,1,18 +2025-03-11T12:38:38.078002,479392720,65527,180,26.8756612748,15.116501721525,-46.895775875555,2,1,18 +2025-03-11T12:38:38.093627,479392720,65527,180,27.13953308552,15.366496166115,-47.368517444465,2,1,18 +2025-03-11T12:38:38.109252,479392720,65527,180,27.393980903,15.6210953766,-47.822779259105,2,1,18 +2025-03-11T12:38:38.124877,479392720,65527,180,27.64371672386,15.880307505945,-48.281674015805,2,1,18 +2025-03-11T12:38:38.140502,479392720,65527,180,27.90758853458,16.139544094185,-48.74983148165,2,1,18 +2025-03-11T12:38:38.156127,479392720,65527,180,28.15732435544,16.384893008055,-49.222534167545,2,1,18 +2025-03-11T12:38:38.171752,479392720,65527,180,28.40234817968,16.625612697135,-49.695211532435,2,1,18 +2025-03-11T12:38:38.187377,479392720,65527,180,28.66150799378,16.880220060585,-50.144858945015,2,1,18 +2025-03-11T12:38:38.203002,479392720,65527,180,28.91595581126,17.12557712742,-50.60370486272,2,1,18 +2025-03-11T12:38:38.218627,479392720,65527,180,29.16569163212,17.384789256765,-51.048736070225,2,1,18 +2025-03-11T12:38:38.234252,479392720,65527,180,29.40600345974,17.630121864705,-51.498319278785,2,1,18 +2025-03-11T12:38:38.249877,479392720,65527,180,29.65102728398,17.87546262561,-51.943288085285,2,1,18 +2025-03-11T12:38:38.265502,479392720,65527,180,29.90547510146,18.130061836095,-52.40217108299,2,1,18 +2025-03-11T12:38:38.281127,479392720,65527,180,30.14578692908,18.37077337221,-52.847114568485,2,1,18 +2025-03-11T12:38:38.296752,479392720,65527,180,30.3860987567,18.6068638365,-53.296660697045,2,1,18 +2025-03-11T12:38:38.312377,479392720,65527,180,30.6216985877,18.852188291475,-53.732373575405,2,1,18 +2025-03-11T12:38:38.328002,479392720,65527,180,30.87143440856,19.11140042082,-54.17740478291,2,1,18 +2025-03-11T12:38:38.343627,479392720,65527,180,31.11174623618,19.352111956935,-54.60848471921,2,1,18 +2025-03-11T12:38:38.359252,479392720,65527,180,31.3520580638,19.578960277575,-55.04875140164,2,1,18 +2025-03-11T12:38:38.374877,479392720,65527,180,31.5876578948,19.819663660725,-55.48444574,2,1,18 +2025-03-11T12:38:38.390502,479392720,65527,180,31.83268171904,20.04652013433,-55.906234471175,2,1,18 +2025-03-11T12:38:38.406127,479392720,65527,180,32.06828155004,20.29646566113,-56.323481157275,2,1,18 +2025-03-11T12:38:38.421752,479392720,65527,180,32.28503339456,20.52789428877,-56.75449010855,2,1,18 +2025-03-11T12:38:38.437377,479392720,65527,180,32.50178523908,20.75932291641,-57.176256693695,2,1,18 +2025-03-11T12:38:38.453002,479392720,65527,180,32.74680906332,20.976937246365,-57.611871894065,2,1,18 +2025-03-11T12:38:38.468627,479392720,65527,180,32.98712089094,21.203785567005,-58.033653844235,2,1,18 +2025-03-11T12:38:38.484252,479392720,65527,180,33.21800872532,21.430617581715,-58.446179866265,2,1,18 +2025-03-11T12:38:38.499877,479392720,65527,180,33.4488965597,21.6713128119,-58.849519142165,2,1,18 +2025-03-11T12:38:38.515502,479392720,65527,180,33.67507239746,21.898136673645,-59.26203838319,2,1,18 +2025-03-11T12:38:38.531127,479392720,65527,180,33.90124823522,22.111097319915,-59.66988082115,2,1,18 +2025-03-11T12:38:38.546752,479392720,65527,180,34.1321360696,22.347171478275,-60.07320155705,2,1,18 +2025-03-11T12:38:38.562377,479392720,65527,180,34.3677359006,22.569390574125,-60.47185227089,2,1,18 +2025-03-11T12:38:38.578002,479392720,65527,180,34.58448774512,22.800819201765,-60.884376489905,2,1,18 +2025-03-11T12:38:38.593627,479392720,65527,180,34.78710359978,23.018360155035,-61.30144592897,2,1,18 +2025-03-11T12:38:38.609252,479392720,65527,180,35.0038554443,23.231304495375,-61.704653621855,2,1,18 +2025-03-11T12:38:38.624877,479392720,65527,180,35.23003128206,23.44888621347,-62.094029867555,2,1,18 +2025-03-11T12:38:38.640502,479392720,65527,180,35.44207112996,23.66644347267,-62.48338577024,2,1,18 +2025-03-11T12:38:38.656127,479392720,65527,180,35.65882297448,23.884008884835,-62.8635060878,2,1,18 +2025-03-11T12:38:38.671752,479392720,65527,180,35.88499881224,24.087727387455,-63.248205530435,2,1,18 +2025-03-11T12:38:38.687377,479392720,65527,180,36.09232666352,24.30527649369,-63.637554652115,2,1,18 +2025-03-11T12:38:38.703002,479392720,65527,180,36.28551852494,24.518180069205,-64.022243707715,2,1,18 +2025-03-11T12:38:38.718627,479392720,65527,180,36.48342238298,24.721849654035,-64.38841773206,2,1,18 +2025-03-11T12:38:38.734252,479392720,65527,180,36.68603823764,24.930148463655,-64.77310180967,2,1,18 +2025-03-11T12:38:38.749877,479392720,65527,180,36.90750207878,25.12461666966,-65.16699975743,2,1,18 +2025-03-11T12:38:38.765502,479392720,65527,180,37.11011793344,25.319052263805,-65.55162821504,2,1,18 +2025-03-11T12:38:38.781127,479392720,65527,180,37.30330979486,25.53195583932,-65.931696087575,2,1,18 +2025-03-11T12:38:38.796752,479392720,65527,180,37.49650165628,25.744859414835,-66.29327922785,2,1,18 +2025-03-11T12:38:38.812377,479392720,65527,180,37.70382950756,25.930061018295,-66.65477147114,2,1,18 +2025-03-11T12:38:38.828002,479392720,65527,180,37.91115735884,26.115262621755,-66.99777898217,2,1,18 +2025-03-11T12:38:38.843627,479392720,65527,180,38.09963722364,26.318915900655,-67.35931826144,2,1,18 +2025-03-11T12:38:38.859252,479392720,65527,180,38.29754108168,26.50872227001,-67.725436665785,2,1,18 +2025-03-11T12:38:38.874877,479392720,65527,180,38.50015693634,26.712400007805,-68.082375105005,2,1,18 +2025-03-11T12:38:38.890502,479392720,65527,180,38.702772791,26.920698817425,-68.43471090116,2,1,18 +2025-03-11T12:38:38.906127,479392720,65527,180,38.88182866256,27.11971471857,-68.782354529225,2,1,18 +2025-03-11T12:38:38.921752,479392720,65527,180,39.06559653074,27.314117700855,-69.1161228491,2,1,18 +2025-03-11T12:38:38.937377,479392720,65527,180,39.25407639554,27.49466562063,-69.463705879175,2,1,18 +2025-03-11T12:38:38.953002,479392720,65527,180,39.44255626034,27.67983461223,-69.81130744925,2,1,18 +2025-03-11T12:38:38.968627,479392720,65527,180,39.63103612514,27.84651931653,-70.15421367626,2,1,18 +2025-03-11T12:38:38.984252,479392720,65527,180,39.8100919967,28.027050930375,-70.474056045935,2,1,18 +2025-03-11T12:38:38.999877,479392720,65527,180,39.99385986488,28.216832840835,-70.79856345968,2,1,18 +2025-03-11T12:38:39.015502,479392720,65527,180,40.1870517263,28.406631057225,-71.132326801565,2,1,18 +2025-03-11T12:38:39.031127,479392720,65527,180,40.36610759786,28.591783742895,-71.456808894305,2,1,18 +2025-03-11T12:38:39.046752,479392720,65527,180,40.53573947618,28.767677978985,-71.76737679584,2,1,18 +2025-03-11T12:38:39.062377,479392720,65527,180,40.71008335112,28.96206465534,-72.082646821445,2,1,18 +2025-03-11T12:38:39.078002,479392720,65527,180,40.8702912362,29.133321513675,-72.407046170165,2,1,18 +2025-03-11T12:38:39.093627,479392720,65527,180,41.03992311452,29.28611039064,-72.70827900557,2,1,18 +2025-03-11T12:38:39.109252,479392720,65527,180,41.2236909827,29.44816587015,-73.032675179315,2,1,18 +2025-03-11T12:38:39.124877,479392720,65527,180,41.39332286102,29.62406010624,-73.338621897785,2,1,18 +2025-03-11T12:38:39.140502,479392720,65527,180,41.54881874948,29.772203452485,-73.62595230098,2,1,18 +2025-03-11T12:38:39.156127,479392720,65527,180,41.7184506278,29.94347661675,-73.927259296385,2,1,18 +2025-03-11T12:38:39.171752,479392720,65527,180,41.87865851288,30.11935454691,-74.22857126978,2,1,18 +2025-03-11T12:38:39.187377,479392720,65527,180,42.03886639796,30.281369261595,-74.53444880624,2,1,18 +2025-03-11T12:38:39.203002,479392720,65527,180,42.20378627966,30.43877105742,-74.840314583705,2,1,18 +2025-03-11T12:38:39.218627,479392720,65527,180,42.36399416474,30.59616470028,-75.136931214035,2,1,18 +2025-03-11T12:38:39.234252,479392720,65527,180,42.52420204982,30.76280048679,-75.4289637413,2,1,18 +2025-03-11T12:38:39.249877,479392720,65527,180,42.68912193152,30.910960138965,-75.71168652344,2,1,18 +2025-03-11T12:38:39.265502,479392720,65527,180,42.8493298166,31.07297485365,-75.985215778445,2,1,18 +2025-03-11T12:38:39.281127,479392720,65527,180,43.00482570506,31.239602487195,-76.267999158575,2,1,18 +2025-03-11T12:38:39.296752,479392720,65527,180,43.15089760028,31.383108455685,-76.5368127275,2,1,18 +2025-03-11T12:38:39.312377,479392720,65527,180,43.30168149212,31.531243648965,-76.801030434365,2,1,18 +2025-03-11T12:38:39.328002,479392720,65527,180,43.45246538396,31.660894554945,-77.06517398123,2,1,18 +2025-03-11T12:38:39.343627,479392720,65527,180,43.59853727918,31.804400523435,-77.32936636709,2,1,18 +2025-03-11T12:38:39.359252,479392720,65527,180,43.73989717778,31.95714048261,-77.59821023501,2,1,18 +2025-03-11T12:38:39.374877,479392720,65527,180,43.88125707638,32.109880441785,-77.8578117368,2,1,18 +2025-03-11T12:38:39.390502,479392720,65527,180,44.02261697498,32.25337825731,-78.11737615859,2,1,18 +2025-03-11T12:38:39.406127,479392720,65527,180,44.15455288034,32.387617623255,-78.363026389175,2,1,18 +2025-03-11T12:38:39.421752,479392720,65527,180,44.29591277894,32.517252223305,-78.59942927564,2,1,18 +2025-03-11T12:38:39.437377,479392720,65527,180,44.43727267754,32.637644679705,-78.85890099743,2,1,18 +2025-03-11T12:38:39.453002,479392720,65527,180,44.5692085829,32.7811261893,-79.09996712495,2,1,18 +2025-03-11T12:38:39.468627,479392720,65527,180,44.69643249164,32.919978474105,-79.3363867484,2,1,18 +2025-03-11T12:38:39.484252,479392720,65527,180,44.81894440376,33.049580462295,-79.582004876975,2,1,18 +2025-03-11T12:38:39.499877,479392720,65527,180,44.95559230574,33.174585837555,-79.80451889324,2,1,18 +2025-03-11T12:38:39.515502,479392720,65527,180,45.07810421786,33.304187825745,-80.031652289555,2,1,18 +2025-03-11T12:38:39.531127,479392720,65527,180,45.19590413336,33.429160589145,-80.268002730995,2,1,18 +2025-03-11T12:38:39.546752,479392720,65527,180,45.31841604548,33.558762577335,-80.48589376118,2,1,18 +2025-03-11T12:38:39.562377,479392720,65527,180,45.4409279576,33.679122421875,-80.703747711365,2,1,18 +2025-03-11T12:38:39.578002,479392720,65527,180,45.56815186634,33.794869347555,-80.93545345175,2,1,18 +2025-03-11T12:38:39.593627,479392720,65527,180,45.69066377846,33.90136597662,-81.13938823274,2,1,18 +2025-03-11T12:38:39.609252,479392720,65527,180,45.79903970072,34.00783814679,-81.343302670715,2,1,18 +2025-03-11T12:38:39.624877,479392720,65527,180,45.90741562298,34.128173532435,-81.561136277885,2,1,18 +2025-03-11T12:38:39.640502,479392720,65527,180,46.02050354186,34.230032783745,-81.765038956865,2,1,18 +2025-03-11T12:38:39.656127,479392720,65527,180,46.12887946412,34.336504953915,-81.96895339484,2,1,18 +2025-03-11T12:38:39.671752,479392720,65527,180,46.2184073999,34.452186655875,-82.1590142396,2,1,18 +2025-03-11T12:38:39.687377,479392720,65527,180,46.32207132554,34.55865067308,-82.35367953044,2,1,18 +2025-03-11T12:38:39.703002,479392720,65527,180,46.41631125794,34.66047731253,-82.534449170075,2,1,18 +2025-03-11T12:38:39.718627,479392720,65527,180,46.51997518358,34.77156240156,-82.72451181785,2,1,18 +2025-03-11T12:38:39.734252,479392720,65527,180,46.62835110584,34.873413499905,-82.919165349695,2,1,18 +2025-03-11T12:38:39.749877,479392720,65527,180,46.72730303486,34.989111507795,-83.08613384114,2,1,18 +2025-03-11T12:38:39.765502,479392720,65527,180,46.81211897402,35.09554291314,-83.266908458765,2,1,18 +2025-03-11T12:38:39.781127,479392720,65527,180,46.89693491318,35.174247887535,-83.442950653325,2,1,18 +2025-03-11T12:38:39.796752,479392720,65527,180,46.98646284896,35.243718871245,-83.61896254889,2,1,18 +2025-03-11T12:38:39.812377,479392720,65527,180,47.08541477798,35.32706937636,-83.776558894205,2,1,18 +2025-03-11T12:38:39.828002,479392720,65527,180,47.20321469348,35.43355785246,-83.93427506354,2,1,18 +2025-03-11T12:38:39.843627,479392720,65527,180,47.29274262926,35.535376338945,-84.091932006845,2,1,18 +2025-03-11T12:38:39.859252,479392720,65527,180,47.36813457518,35.609443935585,-84.2540785502,2,1,18 +2025-03-11T12:38:39.874877,479392720,65527,180,47.45766251096,35.678914919295,-84.40698453044,2,1,18 +2025-03-11T12:38:39.890502,479392720,65527,180,47.54247845012,35.762240965515,-84.559939349675,2,1,18 +2025-03-11T12:38:39.906127,479392720,65527,180,47.61787039604,35.836308562155,-84.680495245445,2,1,18 +2025-03-11T12:38:39.921752,479392720,65527,180,47.69797433858,35.91038431176,-84.833406203675,2,1,18 +2025-03-11T12:38:39.937377,479392720,65527,180,47.76394229126,35.998298817945,-84.972488889695,2,1,18 +2025-03-11T12:38:39.953002,479392720,65527,180,47.8440462338,36.0631324239,-85.12074158486,2,1,18 +2025-03-11T12:38:39.968627,479392720,65527,180,47.91943817972,36.14644216419,-85.245955743695,2,1,18 +2025-03-11T12:38:39.984252,479392720,65527,180,47.98069413578,36.220485301935,-85.371112479515,2,1,18 +2025-03-11T12:38:39.999877,479392720,65527,180,48.04666208846,36.29915766447,-85.482430987145,2,1,18 +2025-03-11T12:38:40.015502,479392720,65527,180,48.11734203776,36.35935389267,-85.58443974965,2,1,18 +2025-03-11T12:38:40.031127,479392720,65527,180,48.19273398368,36.42417934566,-85.691095016225,2,1,18 +2025-03-11T12:38:40.046752,479392720,65527,180,48.25398993974,36.488980339755,-85.816214672045,2,1,18 +2025-03-11T12:38:40.062377,479392720,65527,180,48.31995789242,36.553789486815,-85.936719925805,2,1,18 +2025-03-11T12:38:40.078002,479392720,65527,180,48.37178985524,36.613953103155,-86.043322747355,2,1,18 +2025-03-11T12:38:40.093627,479392720,65527,180,48.42362181806,36.66025350402,-86.159112315035,2,1,18 +2025-03-11T12:38:40.109252,479392720,65527,180,48.49430176736,36.697344373095,-86.265649560605,2,1,18 +2025-03-11T12:38:40.124877,479392720,65527,180,48.5508457268,36.725168639625,-86.36288701703,2,1,18 +2025-03-11T12:38:40.140502,479392720,65527,180,48.59325369638,36.776073806385,-86.446333281245,2,1,18 +2025-03-11T12:38:40.156127,479392720,65527,180,48.64037366258,36.85471355706,-86.529897566465,2,1,18 +2025-03-11T12:38:40.171752,479392720,65527,180,48.6922056254,36.910256101575,-86.608754749625,2,1,18 +2025-03-11T12:38:40.187377,479392720,65527,180,48.73461359498,36.95654019651,-86.706046023035,2,1,18 +2025-03-11T12:38:40.203002,479392720,65527,180,48.77230956794,37.00281613848,-86.79408814931,2,1,18 +2025-03-11T12:38:40.218627,479392720,65527,180,48.8100055409,37.053713152275,-86.863664083325,2,1,18 +2025-03-11T12:38:40.234252,479392720,65527,180,48.84298951724,37.076875582155,-86.91925844714,2,1,18 +2025-03-11T12:38:40.249877,479392720,65527,180,48.87597349358,37.100038012035,-86.98871636015,2,1,18 +2025-03-11T12:38:40.265502,479392720,65527,180,48.92309345978,37.137088116285,-87.049007870045,2,1,18 +2025-03-11T12:38:40.281127,479392720,65527,180,48.9513654395,37.1787266805,-87.123154345115,2,1,18 +2025-03-11T12:38:40.296752,479392720,65527,180,48.99377340908,37.22038970361,-87.174215247875,2,1,18 +2025-03-11T12:38:40.312377,479392720,65527,180,49.01733339218,37.24353582756,-87.215932500485,2,1,18 +2025-03-11T12:38:40.328002,479392720,65527,180,49.05031736852,37.271319329265,-87.276166587365,2,1,18 +2025-03-11T12:38:40.343627,479392720,65527,180,49.06445335838,37.30831236276,-87.327168264095,2,1,18 +2025-03-11T12:38:40.359252,479392720,65527,180,49.09743733472,37.336095864465,-87.36429643565,2,1,18 +2025-03-11T12:38:40.374877,479392720,65527,180,49.1162853212,37.35923383545,-87.406006907255,2,1,18 +2025-03-11T12:38:40.390502,479392720,65527,180,49.13042131106,37.38236365347,-87.45233178092,2,1,18 +2025-03-11T12:38:40.406127,479392720,65527,180,49.15869329078,37.405517930385,-87.484813448405,2,1,18 +2025-03-11T12:38:40.421752,479392720,65527,180,49.17754127726,37.41941375772,-87.521865656945,2,1,18 +2025-03-11T12:38:40.437377,479392720,65527,180,49.20581325698,37.433325890985,-87.558931427495,2,1,18 +2025-03-11T12:38:40.453002,479392720,65527,180,49.21994924684,37.447213565355,-87.554386207445,2,1,18 +2025-03-11T12:38:40.468627,479392720,65527,180,49.22466124346,37.46570600562,-87.577573063775,2,1,18 +2025-03-11T12:38:40.484252,479392720,65527,180,49.22466124346,37.470327077445,-87.586833969905,2,1,18 +2025-03-11T12:38:40.499877,479392720,65527,180,49.22466124346,37.47494814927,-87.605337242165,2,1,18 +2025-03-11T12:38:40.515502,479392720,65527,180,49.21994924684,37.46107678083,-87.628380756485,2,1,18 +2025-03-11T12:38:40.531127,479392720,65527,180,49.22466124346,37.461084933795,-87.64687226975,2,1,18 +2025-03-11T12:38:40.546752,479392720,65527,180,49.23879723332,37.465730464515,-87.637668786635,2,1,18 +2025-03-11T12:38:40.562377,479392720,65527,180,49.24350922994,37.451875402005,-87.623756398445,2,1,18 +2025-03-11T12:38:40.578002,479392720,65527,180,49.23879723332,37.44262510539,-87.61447017131,2,1,18 +2025-03-11T12:38:40.593627,479392720,65527,180,49.22937324008,37.447229871285,-87.582126867845,2,1,18 +2025-03-11T12:38:40.609252,479392720,65527,180,49.22466124346,37.442600646495,-87.558995631515,2,1,18 +2025-03-11T12:38:40.624877,479392720,65527,180,49.21994924684,37.428729278055,-87.54969086438,2,1,18 +2025-03-11T12:38:40.640502,479392720,65527,180,49.20581325698,37.41022053186,-87.549596361365,2,1,18 +2025-03-11T12:38:40.656127,479392720,65527,180,49.17282928064,37.39630024563,-87.53100854207,2,1,18 +2025-03-11T12:38:40.671752,479392720,65527,180,49.15869329078,37.377791499435,-87.503186940665,2,1,18 +2025-03-11T12:38:40.687377,479392720,65527,180,49.15869329078,37.368549355785,-87.46155921308,2,1,18 +2025-03-11T12:38:40.703002,479392720,65527,180,49.15869329078,37.350065068485,-87.410652039365,2,1,18 +2025-03-11T12:38:40.718627,479392720,65527,180,49.13042131106,37.331531863395,-87.37818891188,2,1,18 +2025-03-11T12:38:40.734252,479392720,65527,180,49.10686132796,37.317627883095,-87.341129922335,2,1,18 +2025-03-11T12:38:40.749877,479392720,65527,180,49.069165355,37.271351941125,-87.30854199284,2,1,18 +2025-03-11T12:38:40.765502,479392720,65527,180,49.03618137866,37.23432629577,-87.24827082596,2,1,18 +2025-03-11T12:38:40.781127,479392720,65527,180,49.01733339218,37.211188324785,-87.188075622095,2,1,18 +2025-03-11T12:38:40.796752,479392720,65527,180,48.9984854057,37.183429281975,-87.132483061295,2,1,18 +2025-03-11T12:38:40.812377,479392720,65527,180,48.95607743612,37.141766258865,-87.07680097547,2,1,18 +2025-03-11T12:38:40.828002,479392720,65527,180,48.91838146316,37.11859567602,-87.016578647585,2,1,18 +2025-03-11T12:38:40.843627,479392720,65527,180,48.8806854902,37.086182949525,-86.9563192397,2,1,18 +2025-03-11T12:38:40.859252,479392720,65527,180,48.83827752062,37.053762070065,-86.891431867745,2,1,18 +2025-03-11T12:38:40.874877,479392720,65527,180,48.8100055409,37.007502434025,-86.817266852675,2,1,18 +2025-03-11T12:38:40.890502,479392720,65527,180,48.77230956794,36.95660542023,-86.724585003335,2,1,18 +2025-03-11T12:38:40.906127,479392720,65527,180,48.72047760512,36.90568394754,-86.654988726305,2,1,18 +2025-03-11T12:38:40.921752,479392720,65527,180,48.67806963554,36.859399852605,-86.566939819025,2,1,18 +2025-03-11T12:38:40.937377,479392720,65527,180,48.63566166596,36.81311575767,-86.47426972868,2,1,18 +2025-03-11T12:38:40.953002,479392720,65527,180,48.58854169976,36.771444581595,-86.3723690312,2,1,18 +2025-03-11T12:38:40.968627,479392720,65527,180,48.53199774032,36.725136027765,-86.275057414775,2,1,18 +2025-03-11T12:38:40.984252,479392720,65527,180,48.48487777412,36.660359492565,-86.191548749555,2,1,18 +2025-03-11T12:38:40.999877,479392720,65527,180,48.43775780792,36.577098670065,-86.080238825945,2,1,18 +2025-03-11T12:38:41.015502,479392720,65527,180,48.37650185186,36.52153981962,-85.973640982385,2,1,18 +2025-03-11T12:38:41.031127,479392720,65527,180,48.33409388228,36.466013581035,-85.84396434752,2,1,18 +2025-03-11T12:38:41.046752,479392720,65527,180,48.25870193636,36.42429348717,-85.718917048685,2,1,18 +2025-03-11T12:38:41.062377,479392720,65527,180,48.18330999044,36.36871017783,-85.607677679045,2,1,18 +2025-03-11T12:38:41.078002,479392720,65527,180,48.1032060479,36.2715290691,-85.491643485335,2,1,18 +2025-03-11T12:38:41.093627,479392720,65527,180,48.03723809522,36.19747777839,-85.361858785445,2,1,18 +2025-03-11T12:38:41.109252,479392720,65527,180,47.9618461493,36.109546966275,-85.241247269675,2,1,18 +2025-03-11T12:38:41.124877,479392720,65527,180,47.88645420338,36.053963656935,-85.093038435515,2,1,18 +2025-03-11T12:38:41.140502,479392720,65527,180,47.80163826422,35.989121898015,-84.95864250854,2,1,18 +2025-03-11T12:38:41.156127,479392720,65527,180,47.73095831492,35.91506245434,-84.819608661515,2,1,18 +2025-03-11T12:38:41.171752,479392720,65527,180,47.655566369,35.836373785875,-84.66668594429,2,1,18 +2025-03-11T12:38:41.187377,479392720,65527,180,47.58017442308,35.74844297376,-84.522968513195,2,1,18 +2025-03-11T12:38:41.203002,479392720,65527,180,47.50007048054,35.66050400868,-84.360759568835,2,1,18 +2025-03-11T12:38:41.218627,479392720,65527,180,47.41525454138,35.591041177935,-84.193996820405,2,1,18 +2025-03-11T12:38:41.234252,479392720,65527,180,47.32101460898,35.516940969435,-84.05955025142,2,1,18 +2025-03-11T12:38:41.249877,479392720,65527,180,47.22677467658,35.41973540181,-83.91114743324,2,1,18 +2025-03-11T12:38:41.265502,479392720,65527,180,47.1372467408,35.32253798715,-83.74888784687,2,1,18 +2025-03-11T12:38:41.281127,479392720,65527,180,47.06185479488,35.22998610321,-83.59128832658,2,1,18 +2025-03-11T12:38:41.296752,479392720,65527,180,46.98646284896,35.160539578395,-83.41529677403,2,1,18 +2025-03-11T12:38:41.312377,479392720,65527,180,46.88751091994,35.05870478598,-83.239141536455,2,1,18 +2025-03-11T12:38:41.328002,479392720,65527,180,46.79798298416,34.94302308402,-83.06294424089,2,1,18 +2025-03-11T12:38:41.343627,479392720,65527,180,46.69903105514,34.85505150708,-82.886844623315,2,1,18 +2025-03-11T12:38:41.359252,479392720,65527,180,46.5718071464,34.753167796875,-82.70140633358,2,1,18 +2025-03-11T12:38:41.374877,479392720,65527,180,46.477567214,34.651341157425,-82.51601551088,2,1,18 +2025-03-11T12:38:41.390502,479392720,65527,180,46.3833272816,34.549514517975,-82.33986705431,2,1,18 +2025-03-11T12:38:41.406127,479392720,65527,180,46.27966335596,34.447671572595,-82.1544626696,2,1,18 +2025-03-11T12:38:41.421752,479392720,65527,180,46.17599943032,34.32272326809,-81.9412384865,2,1,18 +2025-03-11T12:38:41.437377,479392720,65527,180,46.06291151144,34.21162187313,-81.73729872752,2,1,18 +2025-03-11T12:38:41.453002,479392720,65527,180,45.94511159594,34.10513339703,-81.524128361405,2,1,18 +2025-03-11T12:38:41.468627,479392720,65527,180,45.84615966692,33.98943538914,-81.315569222375,2,1,18 +2025-03-11T12:38:41.484252,479392720,65527,180,45.72835975142,33.85522048209,-81.10228761626,2,1,18 +2025-03-11T12:38:41.499877,479392720,65527,180,45.61055983592,33.74873200599,-80.89373843321,2,1,18 +2025-03-11T12:38:41.515502,479392720,65527,180,45.4880479238,33.6191300178,-80.675847403025,2,1,18 +2025-03-11T12:38:41.531127,479392720,65527,180,45.35140002182,33.50336678619,-80.439506917565,2,1,18 +2025-03-11T12:38:41.546752,479392720,65527,180,45.23831210294,33.40150753488,-80.207877140195,2,1,18 +2025-03-11T12:38:41.562377,479392720,65527,180,45.11580019082,33.27190554669,-79.985364926945,2,1,18 +2025-03-11T12:38:41.578002,479392720,65527,180,44.98857628208,33.151537549185,-79.776746561885,2,1,18 +2025-03-11T12:38:41.593627,479392720,65527,180,44.86606436996,33.012693417345,-79.544954902505,2,1,18 +2025-03-11T12:38:41.609252,479392720,65527,180,44.72941646798,32.859961611135,-79.317708463175,2,1,18 +2025-03-11T12:38:41.624877,479392720,65527,180,44.60219255924,32.734972541805,-79.07672327666,2,1,18 +2025-03-11T12:38:41.640502,479392720,65527,180,44.47025665388,32.614596391335,-78.831128666075,2,1,18 +2025-03-11T12:38:41.656127,479392720,65527,180,44.34303274514,32.48498625018,-78.585503756495,2,1,18 +2025-03-11T12:38:41.671752,479392720,65527,180,44.21109683978,32.359989027885,-78.33064823978,2,1,18 +2025-03-11T12:38:41.687377,479392720,65527,180,44.07916093442,32.21650751829,-78.06185501387,2,1,18 +2025-03-11T12:38:41.703002,479392720,65527,180,43.92366504596,32.06374310022,-77.811475535195,2,1,18 +2025-03-11T12:38:41.718627,479392720,65527,180,43.78230514736,31.91562421287,-77.542650207275,2,1,18 +2025-03-11T12:38:41.734252,479392720,65527,180,43.64565724538,31.776755622135,-77.29235347262,2,1,18 +2025-03-11T12:38:41.749877,479392720,65527,180,43.49958535016,31.63787072547,-77.01893726063,2,1,18 +2025-03-11T12:38:41.765502,479392720,65527,180,43.33937746508,31.485098154435,-76.736202719495,2,1,18 +2025-03-11T12:38:41.781127,479392720,65527,180,43.19330556986,31.332350042295,-76.471973253635,2,1,18 +2025-03-11T12:38:41.796752,479392720,65527,180,43.05194567126,31.184231154945,-76.212390291845,2,1,18 +2025-03-11T12:38:41.812377,479392720,65527,180,42.8964497828,31.04532995235,-75.92509696865,2,1,18 +2025-03-11T12:38:41.828002,479392720,65527,180,42.75037788758,30.887960768385,-75.637743047465,2,1,18 +2025-03-11T12:38:41.843627,479392720,65527,180,42.59959399574,30.71672021598,-75.35494790834,2,1,18 +2025-03-11T12:38:41.859252,479392720,65527,180,42.45823409714,30.55935918498,-75.07684313429,2,1,18 +2025-03-11T12:38:41.874877,479392720,65527,180,42.29331421544,30.411199532805,-74.789499169085,2,1,18 +2025-03-11T12:38:41.890502,479392720,65527,180,42.12839433374,30.24455559333,-74.506702226945,2,1,18 +2025-03-11T12:38:41.906127,479392720,65527,180,41.96347445204,30.08253272568,-74.214681458675,2,1,18 +2025-03-11T12:38:41.921752,479392720,65527,180,41.79855457034,29.906646642555,-73.89949915508,2,1,18 +2025-03-11T12:38:41.937377,479392720,65527,180,41.61949869878,29.72611502871,-73.588899151535,2,1,18 +2025-03-11T12:38:41.953002,479392720,65527,180,41.4592908137,29.5409949549,-73.28755009814,2,1,18 +2025-03-11T12:38:41.968627,479392720,65527,180,41.30379492524,29.36974624953,-72.990884628815,2,1,18 +2025-03-11T12:38:41.984252,479392720,65527,180,41.13416304692,29.198473085265,-72.67109290115,2,1,18 +2025-03-11T12:38:41.999816,479392724,65523,181,40.9645311686,29.041063136475,-72.34673561042,2,1,18 +2025-03-11T12:38:42.015441,479392724,65523,181,40.7760513038,28.883620575825,-72.02235119567,2,1,18 +2025-03-11T12:38:42.031066,479392724,65523,181,40.59228343562,28.721565096315,-71.71181857112,2,1,18 +2025-03-11T12:38:42.046691,479392724,65523,181,40.40380357082,28.53177503289,-71.382683193305,2,1,18 +2025-03-11T12:38:42.062316,479392724,65523,181,40.22003570264,28.337372050605,-71.04891487343,2,1,18 +2025-03-11T12:38:42.077941,479392724,65523,181,40.05040382432,28.161477814515,-70.710619873505,2,1,18 +2025-03-11T12:38:42.093566,479392724,65523,181,39.87605994938,27.980954353635,-70.390784284835,2,1,18 +2025-03-11T12:38:42.109191,479392724,65523,181,39.67815609134,27.805011199755,-70.057069781945,2,1,18 +2025-03-11T12:38:42.124816,479392724,65523,181,39.48967622654,27.610600064505,-69.732537047195,2,1,18 +2025-03-11T12:38:42.140441,479392724,65523,181,39.30119636174,27.42081000108,-69.380295754055,2,1,18 +2025-03-11T12:38:42.156066,479392724,65523,181,39.12214049018,27.24489945906,-69.02350245986,2,1,18 +2025-03-11T12:38:42.171691,479392724,65523,181,38.94779661524,27.068997070005,-68.680579495865,2,1,18 +2025-03-11T12:38:42.187316,479392724,65523,181,38.76402874706,26.879215159545,-68.332966166795,2,1,18 +2025-03-11T12:38:42.202941,479392724,65523,181,38.5614128924,26.670916349925,-67.985251553705,2,1,18 +2025-03-11T12:38:42.218566,479392724,65523,181,38.36822103098,26.46725491806,-67.646811408755,2,1,18 +2025-03-11T12:38:42.234191,479392724,65523,181,38.1844531628,26.272851935775,-67.29455835662,2,1,18 +2025-03-11T12:38:42.249816,479392724,65523,181,37.98183730814,26.064553126155,-66.92835901127,2,1,18 +2025-03-11T12:38:42.265441,479392724,65523,181,37.79335744334,25.86552091908,-66.562217088935,2,1,18 +2025-03-11T12:38:42.281066,479392724,65523,181,37.5954535853,25.666472406075,-66.209925153785,2,1,18 +2025-03-11T12:38:42.296691,479392724,65523,181,37.39283773064,25.467415740105,-65.83914170537,2,1,18 +2025-03-11T12:38:42.312316,479392724,65523,181,37.19022187598,25.27298014596,-65.459134430825,2,1,18 +2025-03-11T12:38:42.327941,479392724,65523,181,36.99231801794,25.06006841748,-65.097544509545,2,1,18 +2025-03-11T12:38:42.343566,479392724,65523,181,36.78499016666,24.84714038307,-64.717456293995,2,1,18 +2025-03-11T12:38:42.359191,479392724,65523,181,36.57295031876,24.63882526752,-64.33737983744,2,1,18 +2025-03-11T12:38:42.374816,479392724,65523,181,36.36562246748,24.43513937676,-63.961949884955,2,1,18 +2025-03-11T12:38:42.390441,479392724,65523,181,36.16300661282,24.22684056714,-63.577265807345,2,1,18 +2025-03-11T12:38:42.406066,479392724,65523,181,35.95567876154,24.009291460905,-63.197159051795,2,1,18 +2025-03-11T12:38:42.421691,479392724,65523,181,35.72479092716,23.800943733495,-62.80781310509,2,1,18 +2025-03-11T12:38:42.437316,479392724,65523,181,35.50332708602,23.58799124019,-62.41384099733,2,1,18 +2025-03-11T12:38:42.452941,479392724,65523,181,35.29128723812,23.37043398099,-62.01986391158,2,1,18 +2025-03-11T12:38:42.468566,479392724,65523,181,35.0745353936,23.1667317843,-61.607450932565,2,1,18 +2025-03-11T12:38:42.484191,479392724,65523,181,34.8624955457,22.963037740575,-61.20890828375,2,1,18 +2025-03-11T12:38:42.499816,479392724,65523,181,34.65987969104,22.73163357183,-60.82413150614,2,1,18 +2025-03-11T12:38:42.515441,479392724,65523,181,34.44312784652,22.504826016015,-60.43473174245,2,1,18 +2025-03-11T12:38:42.531066,479392724,65523,181,34.226376002,22.282639532025,-60.031486969565,2,1,18 +2025-03-11T12:38:42.546691,479392724,65523,181,34.00020016424,22.06505781393,-59.61900480854,2,1,18 +2025-03-11T12:38:42.562316,479392724,65523,181,33.76931232986,21.83822579922,-59.21572115264,2,1,18 +2025-03-11T12:38:42.577941,479392724,65523,181,33.52900050224,21.615998550405,-58.77547301021,2,1,18 +2025-03-11T12:38:42.593566,479392724,65523,181,33.29811266786,21.379924392045,-58.358288725115,2,1,18 +2025-03-11T12:38:42.609191,479392724,65523,181,33.08607281996,21.143882845545,-57.954995113235,2,1,18 +2025-03-11T12:38:42.624816,479392724,65523,181,32.8598969822,20.893953624675,-57.528519623015,2,1,18 +2025-03-11T12:38:42.640441,479392724,65523,181,32.62900914782,20.66250053814,-57.11135387792,2,1,18 +2025-03-11T12:38:42.656066,479392724,65523,181,32.40283331006,20.435676676395,-56.6849710877,2,1,18 +2025-03-11T12:38:42.671691,479392724,65523,181,32.16723347906,20.22732079602,-56.263270078535,2,1,18 +2025-03-11T12:38:42.687316,479392724,65523,181,31.92220965482,19.991222178765,-55.836823084295,2,1,18 +2025-03-11T12:38:42.702941,479392724,65523,181,31.67718583058,19.73663927421,-55.39643838086,2,1,18 +2025-03-11T12:38:42.718566,479392724,65523,181,31.45100999282,19.491331125165,-54.956117881445,2,1,18 +2025-03-11T12:38:42.734191,479392724,65523,181,31.21541016182,19.24600667019,-54.52502618615,2,1,18 +2025-03-11T12:38:42.749816,479392724,65523,181,30.97038633758,19.019150196585,-54.093995088845,2,1,18 +2025-03-11T12:38:42.765441,479392724,65523,181,30.73007450996,18.773817588645,-53.653654246415,2,1,18 +2025-03-11T12:38:42.781066,479392724,65523,181,30.48505068572,18.53771897139,-53.208722519915,2,1,18 +2025-03-11T12:38:42.796691,479392724,65523,181,30.25416285134,18.278539453905,-52.7544760703,2,1,18 +2025-03-11T12:38:42.812316,479392724,65523,181,29.99971503386,18.019319171595,-52.30943808179,2,1,18 +2025-03-11T12:38:42.827941,479392724,65523,181,29.74526721638,17.778583176585,-51.85523188715,2,1,18 +2025-03-11T12:38:42.843566,479392724,65523,181,29.50024339214,17.528621343855,-51.40100217452,2,1,18 +2025-03-11T12:38:42.859191,479392724,65523,181,29.25993156452,17.283288735915,-50.946797782895,2,1,18 +2025-03-11T12:38:42.874816,479392724,65523,181,29.0196197369,17.03333505615,-50.51105958353,2,1,18 +2025-03-11T12:38:42.890441,479392724,65523,181,28.77459591266,16.78337322342,-50.052208687835,2,1,18 +2025-03-11T12:38:42.906066,479392724,65523,181,28.52957208842,16.54265353434,-49.588773689075,2,1,18 +2025-03-11T12:38:42.921691,479392724,65523,181,28.28454826418,16.278828486135,-49.125245990315,2,1,18 +2025-03-11T12:38:42.937316,479392724,65523,181,28.02067645346,16.019591897895,-48.67557325673,2,1,18 +2025-03-11T12:38:42.952941,479392724,65523,181,27.75209264612,15.755726084865,-48.202769286815,2,1,18 +2025-03-11T12:38:42.968566,479392724,65523,181,27.49764482864,15.50112687438,-47.73464392298,2,1,18 +2025-03-11T12:38:42.984191,479392724,65523,181,27.24319701116,15.25114873572,-47.28040064834,2,1,18 +2025-03-11T12:38:42.999816,479392724,65523,181,26.98874919368,15.005791668885,-46.821554730635,2,1,18 +2025-03-11T12:38:43.015441,479392724,65523,181,26.72958937958,14.732700018135,-46.35796960886,2,1,18 +2025-03-11T12:38:43.031066,479392724,65523,181,26.47985355872,14.46424574514,-45.88979540603,2,1,18 +2025-03-11T12:38:43.046691,479392724,65523,181,26.22069374462,14.20963838169,-45.398557345865,2,1,18 +2025-03-11T12:38:43.062316,479392724,65523,181,25.94739794066,13.955006559345,-44.90267775962,2,1,18 +2025-03-11T12:38:43.077941,479392724,65523,181,25.66939014008,13.69574551221,-44.411394035435,2,1,18 +2025-03-11T12:38:43.093566,479392724,65523,181,25.41023032598,13.427274933285,-43.93858508753,2,1,18 +2025-03-11T12:38:43.109191,479392724,65523,181,25.1557825085,13.1541914355,-43.4565220145,2,1,18 +2025-03-11T12:38:43.124816,479392724,65523,181,24.88248670454,12.890317469505,-42.96522653132,2,1,18 +2025-03-11T12:38:43.140441,479392724,65523,181,24.61861489382,12.640323024915,-42.450894314825,2,1,18 +2025-03-11T12:38:43.156066,479392724,65523,181,24.35003108648,12.37183614006,-41.96882943878,2,1,18 +2025-03-11T12:38:43.171691,479392724,65523,181,24.09087127238,12.08026020201,-41.486685424745,2,1,18 +2025-03-11T12:38:43.187316,479392724,65523,181,23.8128634718,11.802514867575,-41.01381227282,2,1,18 +2025-03-11T12:38:43.202941,479392724,65523,181,23.52071968136,11.543229361545,-40.52250820562,2,1,18 +2025-03-11T12:38:43.218566,479392724,65523,181,23.25213587402,11.26550033304,-40.031163883445,2,1,18 +2025-03-11T12:38:43.234191,479392724,65523,181,22.99768805654,11.001658978905,-39.52603197509,2,1,18 +2025-03-11T12:38:43.249816,479392724,65523,181,22.73381624582,10.75628560614,-39.02558184779,2,1,18 +2025-03-11T12:38:43.265441,479392724,65523,181,22.46523243848,10.48317764946,-38.52963488255,2,1,18 +2025-03-11T12:38:43.281066,479392724,65523,181,22.20136062776,10.200835702095,-38.024415252185,2,1,18 +2025-03-11T12:38:43.296691,479392724,65523,181,21.9280648238,9.923098520625,-37.51920059981,2,1,18 +2025-03-11T12:38:43.312316,479392724,65523,181,21.6689050097,9.640764726225,-37.01398775045,2,1,18 +2025-03-11T12:38:43.327941,479392724,65523,181,21.39560920574,9.34916432928,-36.49485392888,2,1,18 +2025-03-11T12:38:43.343566,479392724,65523,181,21.11288940854,9.066789770055,-35.989607174495,2,1,18 +2025-03-11T12:38:43.359191,479392724,65523,181,20.83016961134,8.807520569955,-35.489074303175,2,1,18 +2025-03-11T12:38:43.374816,479392724,65523,181,20.54273781752,8.534380001415,-34.974615481655,2,1,18 +2025-03-11T12:38:43.390441,479392724,65523,181,20.2553060237,8.251997289225,-34.4647407632,2,1,18 +2025-03-11T12:38:43.406066,479392724,65523,181,19.98201021974,7.974260107755,-33.95490492776,2,1,18 +2025-03-11T12:38:43.421691,479392724,65523,181,19.70400241916,7.682651557845,-33.445006691315,2,1,18 +2025-03-11T12:38:43.437316,479392724,65523,181,19.41185862872,7.386397477215,-32.93969075492,2,1,18 +2025-03-11T12:38:43.452941,479392724,65523,181,19.13385082814,7.10865214278,-32.429848138475,2,1,18 +2025-03-11T12:38:43.468566,479392724,65523,181,18.85113103094,6.826277583555,-31.910737834895,2,1,18 +2025-03-11T12:38:43.484191,479392724,65523,181,18.5825472236,6.53006426775,-31.40083462046,2,1,18 +2025-03-11T12:38:43.499816,479392724,65523,181,18.31396341626,6.24771416742,-30.890987026025,2,1,18 +2025-03-11T12:38:43.515441,479392724,65523,181,18.03595561568,5.97458990481,-30.367299400385,2,1,18 +2025-03-11T12:38:43.531066,479392724,65523,181,17.75323581848,5.692215345585,-29.848189096805,2,1,18 +2025-03-11T12:38:43.546691,479392724,65523,181,17.44695603818,5.40517894971,-29.3290263482,2,1,18 +2025-03-11T12:38:43.562316,479392724,65523,181,17.15010025112,5.12277993159,-28.819138067735,2,1,18 +2025-03-11T12:38:43.577941,479392724,65523,181,16.87209245054,4.84965566898,-28.30007162516,2,1,18 +2025-03-11T12:38:43.593566,479392724,65523,181,16.6035086432,4.56730556865,-27.753254566205,2,1,18 +2025-03-11T12:38:43.609191,479392724,65523,181,16.32550084262,4.271075946915,-27.229474240565,2,1,18 +2025-03-11T12:38:43.624816,479392724,65523,181,16.02864505556,3.988676928795,-26.696480044775,2,1,18 +2025-03-11T12:38:43.640441,479392724,65523,181,15.72236527526,3.687777317445,-26.172640493105,2,1,18 +2025-03-11T12:38:43.656066,479392724,65523,181,15.4255094882,3.414620442975,-25.648925743445,2,1,18 +2025-03-11T12:38:43.671691,479392724,65523,181,15.13807769438,3.10913237166,-25.125094775795,2,1,18 +2025-03-11T12:38:43.687316,479392724,65523,181,14.85064590056,2.80826537217,-24.592039982015,2,1,18 +2025-03-11T12:38:43.702941,479392724,65523,181,14.55850211012,2.498148076065,-24.063562510295,2,1,18 +2025-03-11T12:38:43.718566,479392724,65523,181,14.26164632306,2.19264369882,-23.52585443144,2,1,18 +2025-03-11T12:38:43.734191,479392724,65523,181,13.964790536,1.905623608875,-22.99284169565,2,1,18 +2025-03-11T12:38:43.749816,479392724,65523,181,13.66793474894,1.62784566258,-22.455244856795,2,1,18 +2025-03-11T12:38:43.765441,479392724,65523,181,13.38050295512,1.340841878565,-21.90838213382,2,1,18 +2025-03-11T12:38:43.781066,479392724,65523,181,13.10249515454,1.04461225683,-21.34763234366,2,1,18 +2025-03-11T12:38:43.796691,479392724,65523,181,12.80092737086,0.743720798445,-20.805314840735,2,1,18 +2025-03-11T12:38:43.812316,479392724,65523,181,12.50878358042,0.456708861465,-20.267687702885,2,1,18 +2025-03-11T12:38:43.827941,479392724,65523,181,12.22606378322,0.160471086765001,-19.73465823011,2,1,18 +2025-03-11T12:38:43.843566,479392724,65523,181,11.94334398602,-0.140387759759999,-19.201610217335,2,1,18 +2025-03-11T12:38:43.859191,479392724,65523,181,11.6323522091,-0.450537667724999,-18.68696917079,2,1,18 +2025-03-11T12:38:43.874816,479392724,65523,181,11.33078442542,-0.746808054285,-18.172397306255,2,1,18 +2025-03-11T12:38:43.890441,479392724,65523,181,11.04806462822,-1.03842475716,-17.63014400735,2,1,18 +2025-03-11T12:38:43.906066,479392724,65523,181,10.75592083778,-1.320815622315,-17.097156592565,2,1,18 +2025-03-11T12:38:43.921691,479392724,65523,181,10.45906505072,-1.612456784085,-16.55026176758,2,1,18 +2025-03-11T12:38:43.937316,479392724,65523,181,10.15749726704,-1.92259038612,-16.007907184655,2,1,18 +2025-03-11T12:38:43.952941,479392724,65523,181,9.86064147998,-2.228094763365,-15.456335556605,2,1,18 +2025-03-11T12:38:43.968566,479392724,65523,181,9.5590736963,-2.5382283654,-14.909359790615,2,1,18 +2025-03-11T12:38:43.984191,479392724,65523,181,9.252793916,-2.834506904925,-14.38091759588,2,1,18 +2025-03-11T12:38:43.999816,479392724,65523,181,8.96065012556,-3.112276698255,-13.85256990416,2,1,18 +2025-03-11T12:38:44.015441,479392724,65523,181,8.68264232498,-3.394643104515,-13.305739283195,2,1,18 +2025-03-11T12:38:44.031066,479392724,65523,181,8.3810745413,-3.709397778375,-12.74488142801,2,1,18 +2025-03-11T12:38:44.046691,479392724,65523,181,8.074794761,-4.028781677025,-12.207104167145,2,1,18 +2025-03-11T12:38:44.062316,479392724,65523,181,7.77322697732,-4.334294207235,-11.660146941155,2,1,18 +2025-03-11T12:38:44.077941,479392724,65523,181,7.47637119026,-4.625935369005,-11.09476738391,2,1,18 +2025-03-11T12:38:44.093566,479392724,65523,181,7.17009140996,-4.93145605218,-10.55242455998,2,1,18 +2025-03-11T12:38:44.109191,479392724,65523,181,6.86381162966,-5.23235566353,-10.02858500831,2,1,18 +2025-03-11T12:38:44.124816,479392724,65523,181,6.58109183246,-5.51935129458,-9.5002137986,2,1,18 +2025-03-11T12:38:44.140441,479392724,65523,181,6.29366003864,-5.806355078595,-8.944108709495,2,1,18 +2025-03-11T12:38:44.156066,479392724,65523,181,5.99209225496,-6.10724653698,-8.4110335727,2,1,18 +2025-03-11T12:38:44.171691,479392724,65523,181,5.69052447128,-6.417380139015,-7.868678989775,2,1,18 +2025-03-11T12:38:44.187316,479392724,65523,181,5.39838068084,-6.71825529147,-7.321753865795,2,1,18 +2025-03-11T12:38:44.202941,479392724,65523,181,5.09681289716,-7.01452567803,-6.76097017061,2,1,18 +2025-03-11T12:38:44.218566,479392724,65523,181,4.79524511348,-7.306174992765,-6.20482619849,2,1,18 +2025-03-11T12:38:44.234191,479392724,65523,181,4.48896533318,-7.616316747765,-5.65322246843,2,1,18 +2025-03-11T12:38:44.249816,479392724,65523,181,4.18268555288,-7.93107957459,-5.12932729676,2,1,18 +2025-03-11T12:38:44.265441,479392724,65523,181,3.88582976582,-8.25044716731,-4.591563597905,2,1,18 +2025-03-11T12:38:44.281066,479392724,65523,181,3.59368597538,-8.53745910429,-4.03083054473,2,1,18 +2025-03-11T12:38:44.296691,479392724,65523,181,3.2921181917,-8.838350562675,-3.47464949261,2,1,18 +2025-03-11T12:38:44.312316,479392724,65523,181,2.9858384114,-9.139250174025,-2.93232520868,2,1,18 +2025-03-11T12:38:44.327941,479392724,65523,181,2.68427062772,-9.435520560585,-2.38540506269,2,1,18 +2025-03-11T12:38:44.343566,479392724,65523,181,2.38741484066,-9.73178279418,-1.820006965445,2,1,18 +2025-03-11T12:38:44.359191,479392724,65523,181,2.10469504346,-10.041883784355,-1.27767950654,2,1,18 +2025-03-11T12:38:44.374816,479392724,65523,181,1.8078392564,-10.3473881616,-0.73535024462,2,1,18 +2025-03-11T12:38:44.390441,479392724,65523,181,1.49684747948,-10.666780213215,-0.192945019685,2,1,18 +2025-03-11T12:38:44.406066,479392724,65523,181,1.20941568566,-10.96302614088,0.349333600225,2,1,18 +2025-03-11T12:38:44.421691,479392724,65523,181,0.9125598986,-11.259288374475,0.89624696521,2,1,18 +2025-03-11T12:38:44.437316,479392724,65523,181,0.6062801183,-11.555566914,1.443173892205,2,1,18 +2025-03-11T12:38:44.452941,479392724,65523,181,0.29528834138,-11.84261146284,1.999312886335,2,1,18 +2025-03-11T12:38:44.468566,479392724,65523,181,-0.00156744568000011,-12.138873696435,2.53698388519,2,1,18 +2025-03-11T12:38:44.484191,479392724,65523,181,-0.30313522936,-12.43976515482,3.07468020505,2,1,18 +2025-03-11T12:38:44.499816,479392724,65523,181,-0.59999101642,-12.72216417294,3.621537950035,2,1,18 +2025-03-11T12:38:44.515441,479392724,65523,181,-0.9015588001,-13.013813487675,4.177681922155,2,1,18 +2025-03-11T12:38:44.531066,479392724,65523,181,-1.2078385804,-13.314713099025,4.710763839955,2,1,18 +2025-03-11T12:38:44.546691,479392724,65523,181,-1.49527037422,-13.62020117034,5.243837173735,2,1,18 +2025-03-11T12:38:44.562316,479392724,65523,181,-1.78270216804,-13.91182602618,5.786097253645,2,1,18 +2025-03-11T12:38:44.577941,479392724,65523,181,-2.08898194834,-14.217346709355,6.34230362677,2,1,18 +2025-03-11T12:38:44.593566,479392724,65523,181,-2.39054973202,-14.522859239565,6.884639669695,2,1,18 +2025-03-11T12:38:44.609191,479392724,65523,181,-2.69682951232,-14.82837992274,7.417740127495,2,1,18 +2025-03-11T12:38:44.624816,479392724,65523,181,-2.99368529938,-15.133884299985,7.95544820635,2,1,18 +2025-03-11T12:38:44.640441,479392724,65523,181,-3.27169309996,-15.42087177807,8.511539733445,2,1,18 +2025-03-11T12:38:44.656066,479392724,65523,181,-3.55912489378,-15.726359849385,9.03999188416,2,1,18 +2025-03-11T12:38:44.671691,479392724,65523,181,-3.86540467408,-16.03188053256,9.577713525025,2,1,18 +2025-03-11T12:38:44.687316,479392724,65523,181,-4.17168445438,-16.32353800026,10.11537954589,2,1,18 +2025-03-11T12:38:44.702941,479392724,65523,181,-4.46382824482,-16.596686721765,10.666814612935,2,1,18 +2025-03-11T12:38:44.718566,479392724,65523,181,-4.74654804202,-16.902166640115,11.20912353184,2,1,18 +2025-03-11T12:38:44.734191,479392724,65523,181,-5.03397983584,-17.203033639605,11.728314776425,2,1,18 +2025-03-11T12:38:44.749816,479392724,65523,181,-5.32612362628,-17.47618236111,12.256643928145,2,1,18 +2025-03-11T12:38:44.765441,479392724,65523,181,-5.62769140996,-17.758589532195,12.803508454135,2,1,18 +2025-03-11T12:38:44.781066,479392724,65523,181,-5.93397119026,-18.059489143545,13.35969628726,2,1,18 +2025-03-11T12:38:44.796691,479392724,65523,181,-6.21669098746,-18.374211205545,13.8974211031,2,1,18 +2025-03-11T12:38:44.812316,479392724,65523,181,-6.51825877114,-18.67510266393,14.439738606025,2,1,18 +2025-03-11T12:38:44.827941,479392724,65523,181,-6.8151145582,-18.95750168205,14.95886925262,2,1,18 +2025-03-11T12:38:44.843566,479392724,65523,181,-7.08841036216,-19.24448100717,15.482605717255,2,1,18 +2025-03-11T12:38:44.859191,479392724,65523,181,-7.37584215598,-19.522242647535,16.006325444905,2,1,18 +2025-03-11T12:38:44.874816,479392724,65523,181,-7.6632739498,-19.8184885752,16.53474051562,2,1,18 +2025-03-11T12:38:44.890441,479392724,65523,181,-7.96012973686,-20.114750808795,17.063169148345,2,1,18 +2025-03-11T12:38:44.906066,479392724,65523,181,-8.24284953406,-20.39712536802,17.58690063499,2,1,18 +2025-03-11T12:38:44.921691,479392724,65523,181,-8.5349933245,-20.67489516135,18.11524832671,2,1,18 +2025-03-11T12:38:44.937316,479392724,65523,181,-8.82713711494,-20.97114924198,18.657533727625,2,1,18 +2025-03-11T12:38:44.952941,479392724,65523,181,-9.10985691214,-21.262765944855,19.195165843465,2,1,18 +2025-03-11T12:38:44.968566,479392724,65523,181,-9.3831527161,-21.568229557275,19.714355285035,2,1,18 +2025-03-11T12:38:44.984191,479392724,65523,181,-9.66116051668,-21.859838107185,20.23349588761,2,1,18 +2025-03-11T12:38:44.999816,479392724,65523,181,-9.95801630374,-22.14685819713,20.75726625727,2,1,18 +2025-03-11T12:38:45.015441,479392724,65523,181,-10.24544809756,-22.42924090932,21.26251979266,2,1,18 +2025-03-11T12:38:45.031066,479392724,65523,181,-10.537591888,-22.70701070265,21.78162511825,2,1,18 +2025-03-11T12:38:45.046691,479392724,65523,181,-10.8203116852,-22.989385261875,22.286871872635,2,1,18 +2025-03-11T12:38:45.062316,479392724,65523,181,-11.1030314824,-23.267138749275,22.815206002345,2,1,18 +2025-03-11T12:38:45.077941,479392724,65523,181,-11.37632728636,-23.54949700257,23.32968156085,2,1,18 +2025-03-11T12:38:45.093566,479392724,65523,181,-11.65904708356,-23.831871561795,23.84879186443,2,1,18 +2025-03-11T12:38:45.109191,479392724,65523,181,-11.94176688076,-24.12348826467,24.37718161414,2,1,18 +2025-03-11T12:38:45.124816,479392724,65523,181,-12.21506268472,-24.405846517965,24.88703598958,2,1,18 +2025-03-11T12:38:45.140441,479392724,65523,181,-12.4930704853,-24.69283399605,25.38305213683,2,1,18 +2025-03-11T12:38:45.156066,479392724,65523,181,-12.78521427574,-24.97060378938,25.888293913225,2,1,18 +2025-03-11T12:38:45.171691,479392724,65523,181,-13.07264606956,-25.239123286095,26.40735537781,2,1,18 +2025-03-11T12:38:45.187316,479392724,65523,181,-13.35536586676,-25.51225570167,26.91718623526,2,1,18 +2025-03-11T12:38:45.202941,479392724,65523,181,-13.63808566396,-25.79925133272,27.42707271271,2,1,18 +2025-03-11T12:38:45.218566,479392724,65523,181,-13.91138146792,-26.072367442365,27.941511191215,2,1,18 +2025-03-11T12:38:45.234191,479392724,65523,181,-14.17525327864,-26.350088317905,28.432848732385,2,1,18 +2025-03-11T12:38:45.249816,479392724,65523,181,-14.43912508936,-26.627809193445,28.92880745662,2,1,18 +2025-03-11T12:38:45.265441,479392724,65523,181,-14.72655688318,-26.90557083381,29.420178902815,2,1,18 +2025-03-11T12:38:45.281066,479392724,65523,181,-14.99985268714,-27.17406587163,29.92535647519,2,1,18 +2025-03-11T12:38:45.296691,479392724,65523,181,-15.26843649448,-27.451794900135,30.425943163495,2,1,18 +2025-03-11T12:38:45.312316,479392724,65523,181,-15.55115629168,-27.729548387535,30.917307828685,2,1,18 +2025-03-11T12:38:45.327941,479392724,65523,181,-15.82445209564,-27.998043425355,31.408621851865,2,1,18 +2025-03-11T12:38:45.343566,479392724,65523,181,-16.08832390636,-28.248037869945,31.909090519165,2,1,18 +2025-03-11T12:38:45.359191,479392724,65523,181,-16.3569077137,-28.521145826625,32.414279850535,2,1,18 +2025-03-11T12:38:45.374816,479392724,65523,181,-16.60193153794,-28.80345516213,32.88250289236,2,1,18 +2025-03-11T12:38:45.390441,479392724,65523,181,-16.87051534528,-29.08580526246,33.364623388405,2,1,18 +2025-03-11T12:38:45.406066,479392724,65523,181,-17.14381114924,-29.331194941155,33.855844711585,2,1,18 +2025-03-11T12:38:45.421691,479392724,65523,181,-17.4171069532,-29.5858267635,34.328618382505,2,1,18 +2025-03-11T12:38:45.437316,479392724,65523,181,-17.69040275716,-29.85432180132,34.78758412423,2,1,18 +2025-03-11T12:38:45.452941,479392724,65523,181,-17.9589865645,-30.11818761435,35.2927363756,2,1,18 +2025-03-11T12:38:45.468566,479392724,65523,181,-18.23228236846,-30.38668265217,35.770186849585,2,1,18 +2025-03-11T12:38:45.484191,479392724,65523,181,-18.49144218256,-30.64129001562,36.25218254362,2,1,18 +2025-03-11T12:38:45.499816,479392724,65523,181,-18.74117800342,-30.900502144965,36.72956203258,2,1,18 +2025-03-11T12:38:45.515441,479392724,65523,181,-18.9956258209,-31.178206714575,37.20240127948,2,1,18 +2025-03-11T12:38:45.531066,479392724,65523,181,-19.25949763162,-31.44206437464,37.68444083452,2,1,18 +2025-03-11T12:38:45.546691,479392724,65523,181,-19.5139454491,-31.705905728775,38.152603278355,2,1,18 +2025-03-11T12:38:45.562316,479392724,65523,181,-19.75896927334,-31.965109705155,38.62073362018,2,1,18 +2025-03-11T12:38:45.577941,479392724,65523,181,-20.02755308068,-32.210491230885,39.074978697835,2,1,18 +2025-03-11T12:38:45.593566,479392724,65523,181,-20.28671289478,-32.483582881635,39.543185002675,2,1,18 +2025-03-11T12:38:45.609191,479392724,65523,181,-20.54116071226,-32.73818209212,39.997446817315,2,1,18 +2025-03-11T12:38:45.624816,479392724,65523,181,-20.80503252298,-32.974313321235,40.46551158316,2,1,18 +2025-03-11T12:38:45.640441,479392724,65523,181,-21.05948034046,-33.21042824442,40.92894160393,2,1,18 +2025-03-11T12:38:45.656066,479392724,65523,181,-21.30921616132,-33.460398230115,41.3785569145,2,1,18 +2025-03-11T12:38:45.671691,479392724,65523,181,-21.54481599232,-33.71496482874,41.83279160512,2,1,18 +2025-03-11T12:38:45.687316,479392724,65523,181,-21.78512781994,-33.964918508505,42.29163571981,2,1,18 +2025-03-11T12:38:45.702941,479392724,65523,181,-22.02543964756,-34.219493260095,42.75974074063,2,1,18 +2025-03-11T12:38:45.718566,479392724,65523,181,-22.27517546842,-34.46946324579,43.20011368507,2,1,18 +2025-03-11T12:38:45.734191,479392724,65523,181,-22.53433528252,-34.719449537415,43.64974255765,2,1,18 +2025-03-11T12:38:45.749816,479392724,65523,181,-22.77935910676,-34.97403244197,44.108611993345,2,1,18 +2025-03-11T12:38:45.765441,479392724,65523,181,-22.99611095128,-35.21470321326,44.562763939945,2,1,18 +2025-03-11T12:38:45.781066,479392724,65523,181,-23.24113477552,-35.44618075869,45.00305594338,2,1,18 +2025-03-11T12:38:45.796691,479392724,65523,181,-23.48615859976,-35.68690044777,45.43876384375,2,1,18 +2025-03-11T12:38:45.812316,479392724,65523,181,-23.72175843076,-35.932224902745,45.879097905175,2,1,18 +2025-03-11T12:38:45.827941,479392724,65523,181,-23.95264626514,-36.186783348405,46.31484108253,2,1,18 +2025-03-11T12:38:45.843566,479392724,65523,181,-24.18824609614,-36.427486731555,46.736671871695,2,1,18 +2025-03-11T12:38:45.859191,479392724,65523,181,-24.42384592714,-36.649705827405,47.14918613473,2,1,18 +2025-03-11T12:38:45.874816,479392724,65523,181,-24.68771773786,-36.871973841045,47.58484699912,2,1,18 +2025-03-11T12:38:45.890441,479392724,65523,181,-24.9327415621,-37.09883031465,48.00201454723,2,1,18 +2025-03-11T12:38:45.906066,479392724,65523,181,-25.14478141,-37.348735076625,48.419227328305,2,1,18 +2025-03-11T12:38:45.921691,479392724,65523,181,-25.37566924438,-37.594051378635,48.8364486934,2,1,18 +2025-03-11T12:38:45.937316,479392724,65523,181,-25.58770909228,-37.82547185331,49.25820849754,2,1,18 +2025-03-11T12:38:45.952941,479392724,65523,181,-25.82330892328,-38.05693309281,49.6938657559,2,1,18 +2025-03-11T12:38:45.968566,479392724,65523,181,-26.05890875428,-38.27915218866,50.106380018935,2,1,18 +2025-03-11T12:38:45.984191,479392724,65523,181,-26.28508459204,-38.505976050405,50.514278076895,2,1,18 +2025-03-11T12:38:45.999771,479392728,65520,182,-26.50183643656,-38.73278360622,50.922162572845,2,1,18 +2025-03-11T12:38:46.015396,479392728,65520,182,-26.72801227432,-38.950365324315,51.330023550805,2,1,18 +2025-03-11T12:38:46.031021,479392728,65520,182,-26.95418811208,-39.172568114235,51.728660702635,2,1,18 +2025-03-11T12:38:46.046646,479392728,65520,182,-27.1709399566,-39.385512454575,52.127247212455,2,1,18 +2025-03-11T12:38:46.062271,479392728,65520,182,-27.38769180112,-39.58459357944,52.516535736145,2,1,18 +2025-03-11T12:38:46.077896,479392728,65520,182,-27.60915564226,-39.81140928822,52.9244270131,2,1,18 +2025-03-11T12:38:46.093521,479392728,65520,182,-27.8306194834,-40.04746714065,53.32773418699,2,1,18 +2025-03-11T12:38:46.109146,479392728,65520,182,-28.05208332454,-40.269661777605,53.707879825555,2,1,18 +2025-03-11T12:38:46.124771,479392728,65520,182,-28.25941117582,-40.47796874019,54.097191867235,2,1,18 +2025-03-11T12:38:46.140396,479392728,65520,182,-28.4667390271,-40.658549271825,54.49101385198,2,1,18 +2025-03-11T12:38:46.156021,479392728,65520,182,-28.67406687838,-40.86685623441,54.88032589366,2,1,18 +2025-03-11T12:38:46.171646,479392728,65520,182,-28.88610672628,-41.089034565435,55.260457970215,2,1,18 +2025-03-11T12:38:46.187271,479392728,65520,182,-29.09814657418,-41.306591824635,55.645192689835,2,1,18 +2025-03-11T12:38:46.202896,479392728,65520,182,-29.30076242884,-41.514890634255,56.01601321825,2,1,18 +2025-03-11T12:38:46.218521,479392728,65520,182,-29.5033782835,-41.723189443875,56.39145492973,2,1,18 +2025-03-11T12:38:46.234146,479392728,65520,182,-29.72013012802,-41.91302842509,56.748358091965,2,1,18 +2025-03-11T12:38:46.249771,479392728,65520,182,-29.92274598268,-42.125948306535,57.11919716038,2,1,18 +2025-03-11T12:38:46.265396,479392728,65520,182,-30.1159378441,-42.3296097384,57.471500854525,2,1,18 +2025-03-11T12:38:46.281021,479392728,65520,182,-30.3044177089,-42.5332630173,57.83766131686,2,1,18 +2025-03-11T12:38:46.296646,479392728,65520,182,-30.50232156694,-42.73693260213,58.19921415814,2,1,18 +2025-03-11T12:38:46.312271,479392728,65520,182,-30.70022542498,-42.94060218696,58.565388182485,2,1,18 +2025-03-11T12:38:46.327896,479392728,65520,182,-30.89812928302,-43.121166412665,58.917605957635,2,1,18 +2025-03-11T12:38:46.343521,479392728,65520,182,-31.10074513768,-43.30635986316,59.26984905379,2,1,18 +2025-03-11T12:38:46.359146,479392728,65520,182,-31.2939369991,-43.491537007725,59.603593855675,2,1,18 +2025-03-11T12:38:46.374771,479392728,65520,182,-31.46828087404,-43.681302612255,59.960435988865,2,1,18 +2025-03-11T12:38:46.390396,479392728,65520,182,-31.65204874222,-43.87570559454,60.317310224065,2,1,18 +2025-03-11T12:38:46.406021,479392728,65520,182,-31.84995260026,-44.074754107545,60.65573861002,2,1,18 +2025-03-11T12:38:46.421646,479392728,65520,182,-32.03372046844,-44.264536018005,60.98486720683,2,1,18 +2025-03-11T12:38:46.437271,479392728,65520,182,-32.22220033324,-44.46356822508,61.314039664645,2,1,18 +2025-03-11T12:38:46.452896,479392728,65520,182,-32.39654420818,-44.648712757785,61.652378525575,2,1,18 +2025-03-11T12:38:46.468521,479392728,65520,182,-32.5661760865,-44.8292280657,61.98144969937,2,1,18 +2025-03-11T12:38:46.484146,479392728,65520,182,-32.7546559513,-45.000533841825,62.31513210025,2,1,18 +2025-03-11T12:38:46.499771,479392728,65520,182,-32.95255980934,-45.17185592388,62.644206880075,2,1,18 +2025-03-11T12:38:46.515396,479392728,65520,182,-33.12690368428,-45.357000456585,62.954818642615,2,1,18 +2025-03-11T12:38:46.531021,479392728,65520,182,-33.28239957274,-45.519007018305,63.27917413033,2,1,18 +2025-03-11T12:38:46.546646,479392728,65520,182,-33.44731945444,-45.68565095778,63.59894053699,2,1,18 +2025-03-11T12:38:46.562271,479392728,65520,182,-33.62166332938,-45.85693227501,63.904875496465,2,1,18 +2025-03-11T12:38:46.577896,479392728,65520,182,-33.79600720432,-46.02821359224,64.206189272875,2,1,18 +2025-03-11T12:38:46.593521,479392728,65520,182,-33.96563908264,-46.217971043805,64.52605516054,2,1,18 +2025-03-11T12:38:46.609146,479392728,65520,182,-34.13527096096,-46.384623136245,64.85044953127,2,1,18 +2025-03-11T12:38:46.624771,479392728,65520,182,-34.30490283928,-46.551275228685,65.142495620545,2,1,18 +2025-03-11T12:38:46.640396,479392728,65520,182,-34.47924671422,-46.69945118679,65.425231964695,2,1,18 +2025-03-11T12:38:46.656021,479392728,65520,182,-34.6394545993,-46.85684482965,65.70798504583,2,1,18 +2025-03-11T12:38:46.671646,479392728,65520,182,-34.77139050466,-47.02343169837,65.995355704,2,1,18 +2025-03-11T12:38:46.687271,479392728,65520,182,-34.91746239988,-47.18542195416,66.29659171438,2,1,18 +2025-03-11T12:38:46.702896,479392728,65520,182,-35.09651827144,-47.347469280705,66.588632825665,2,1,18 +2025-03-11T12:38:46.718521,479392728,65520,182,-35.24730216328,-47.486362330335,66.875919367855,2,1,18 +2025-03-11T12:38:46.734146,479392728,65520,182,-35.40279805174,-47.63450567658,67.177113320245,2,1,18 +2025-03-11T12:38:46.749771,479392728,65520,182,-35.56300593682,-47.787278247615,67.455226678315,2,1,18 +2025-03-11T12:38:46.765396,479392728,65520,182,-35.70907783204,-47.940026359755,67.710213778045,2,1,18 +2025-03-11T12:38:46.781021,479392728,65520,182,-35.85514972726,-48.08815340007,67.974424703905,2,1,18 +2025-03-11T12:38:46.796646,479392728,65520,182,-36.01064561572,-48.236296746315,68.23402800871,2,1,18 +2025-03-11T12:38:46.812271,479392728,65520,182,-36.16142950756,-48.375189795945,68.498208635575,2,1,18 +2025-03-11T12:38:46.827896,479392728,65520,182,-36.30278940616,-48.514066539645,68.76237570043,2,1,18 +2025-03-11T12:38:46.843521,479392728,65520,182,-36.45828529462,-48.65296774224,69.012699559105,2,1,18 +2025-03-11T12:38:46.859146,479392728,65520,182,-36.59964519322,-48.805707701415,69.263058694765,2,1,18 +2025-03-11T12:38:46.874771,479392728,65520,182,-36.7362930952,-48.94457629215,69.517976612485,2,1,18 +2025-03-11T12:38:46.890396,479392728,65520,182,-36.87294099718,-49.083444882885,69.782136896335,2,1,18 +2025-03-11T12:38:46.906021,479392728,65520,182,-37.01430089578,-49.21770055476,70.02780068893,2,1,18 +2025-03-11T12:38:46.921646,479392728,65520,182,-37.14623680114,-49.333455633405,70.273376759515,2,1,18 +2025-03-11T12:38:46.937271,479392728,65520,182,-37.26403671664,-49.46304946863,70.500503374825,2,1,18 +2025-03-11T12:38:46.952896,479392728,65520,182,-37.40068461862,-49.59729698754,70.72305447109,2,1,18 +2025-03-11T12:38:46.968521,479392728,65520,182,-37.53262052398,-49.72691528166,70.96406497861,2,1,18 +2025-03-11T12:38:46.984146,479392728,65520,182,-37.65042043948,-49.838024829585,71.177253884725,2,1,18 +2025-03-11T12:38:46.999771,479392728,65520,182,-37.7729323516,-49.9537636023,71.38584692878,2,1,18 +2025-03-11T12:38:47.015396,479392728,65520,182,-37.87659627724,-50.087954050455,71.612971741075,2,1,18 +2025-03-11T12:38:47.031021,479392728,65520,182,-37.99439619274,-50.21754788568,71.83547717332,2,1,18 +2025-03-11T12:38:47.046646,479392728,65520,182,-38.11690810486,-50.314802371095,72.04861724044,2,1,18 +2025-03-11T12:38:47.062271,479392728,65520,182,-38.22528402712,-50.439758828565,72.26646938761,2,1,18 +2025-03-11T12:38:47.077896,479392728,65520,182,-38.33365994938,-50.55085207056,72.479644731715,2,1,18 +2025-03-11T12:38:47.093521,479392728,65520,182,-38.46088385812,-50.671220068065,72.68364191371,2,1,18 +2025-03-11T12:38:47.109146,479392728,65520,182,-38.56454778376,-50.782305157095,72.892189293745,2,1,18 +2025-03-11T12:38:47.124771,479392728,65520,182,-38.67292370602,-50.898019470915,73.082277262525,2,1,18 +2025-03-11T12:38:47.140396,479392728,65520,182,-38.7860116249,-50.999878722225,73.286179941505,2,1,18 +2025-03-11T12:38:47.156021,479392728,65520,182,-38.9038115404,-51.1017461265,73.485468218425,2,1,18 +2025-03-11T12:38:47.171646,479392728,65520,182,-39.01689945928,-51.217468593285,73.652457052885,2,1,18 +2025-03-11T12:38:47.187271,479392728,65520,182,-39.1158513883,-51.333166601175,73.824046727395,2,1,18 +2025-03-11T12:38:47.202896,479392728,65520,182,-39.2100913207,-51.425751096975,74.01402165316,2,1,18 +2025-03-11T12:38:47.218521,479392728,65520,182,-39.29961925648,-51.504464224335,74.199312994855,2,1,18 +2025-03-11T12:38:47.234146,479392728,65520,182,-39.38914719226,-51.58779842352,74.370759327355,2,1,18 +2025-03-11T12:38:47.249771,479392728,65520,182,-39.50694710776,-51.69428689962,74.542339045885,2,1,18 +2025-03-11T12:38:47.265396,479392728,65520,182,-39.6106110334,-51.796129845,74.73236461366,2,1,18 +2025-03-11T12:38:47.281021,479392728,65520,182,-39.69071497594,-51.87482666643,74.899157661085,2,1,18 +2025-03-11T12:38:47.296646,479392728,65520,182,-39.7755309151,-51.953531640825,75.06133630645,2,1,18 +2025-03-11T12:38:47.312271,479392728,65520,182,-39.86034685426,-52.04147875887,75.20968848262,2,1,18 +2025-03-11T12:38:47.327896,479392728,65520,182,-39.9404507968,-52.1201755803,75.357996797785,2,1,18 +2025-03-11T12:38:47.343521,479392728,65520,182,-40.01584274272,-52.22196960789,75.52949694727,2,1,18 +2025-03-11T12:38:47.359146,479392728,65520,182,-40.10065868188,-52.31453779776,75.664004114245,2,1,18 +2025-03-11T12:38:47.374771,479392728,65520,182,-40.1760506278,-52.37936325075,75.80762884534,2,1,18 +2025-03-11T12:38:47.390396,479392728,65520,182,-40.2467305771,-52.45804376625,75.96054478156,2,1,18 +2025-03-11T12:38:47.406021,479392728,65520,182,-40.32683451964,-52.53674058768,76.108853096725,2,1,18 +2025-03-11T12:38:47.421646,479392728,65520,182,-40.40693846218,-52.62467955276,76.234092576565,2,1,18 +2025-03-11T12:38:47.437271,479392728,65520,182,-40.47290641486,-52.69873084347,76.36849845952,2,1,18 +2025-03-11T12:38:47.452896,479392728,65520,182,-40.54829836078,-52.758935224635,76.48899873529,2,1,18 +2025-03-11T12:38:47.468521,479392728,65520,182,-40.63311429994,-52.82839805538,76.6187920192,2,1,18 +2025-03-11T12:38:47.484146,479392728,65520,182,-40.694370256,-52.8978201213,76.73468784889,2,1,18 +2025-03-11T12:38:47.499771,479392728,65520,182,-40.7650502053,-52.9580163495,76.845938977525,2,1,18 +2025-03-11T12:38:47.515396,479392728,65520,182,-40.8357301546,-53.00897043405,76.971016575355,2,1,18 +2025-03-11T12:38:47.531021,479392728,65520,182,-40.89227411404,-53.07376327518,77.07764471791,2,1,18 +2025-03-11T12:38:47.546646,479392728,65520,182,-40.93939408024,-53.13853981038,77.17963811539,2,1,18 +2025-03-11T12:38:47.562271,479392728,65520,182,-40.99122604306,-53.184840211245,77.263079401615,2,1,18 +2025-03-11T12:38:47.577896,479392728,65520,182,-41.03834600926,-53.240374602795,77.365035719095,2,1,18 +2025-03-11T12:38:47.593521,479392728,65520,182,-41.09017797208,-53.291296075485,77.44849554532,2,1,18 +2025-03-11T12:38:47.609146,479392728,65520,182,-41.14672193152,-53.346846772965,77.54122305868,2,1,18 +2025-03-11T12:38:47.624771,479392728,65520,182,-41.19855389434,-53.388526102005,77.643130537165,2,1,18 +2025-03-11T12:38:47.640396,479392728,65520,182,-41.2362498673,-53.4394231158,77.73119120344,2,1,18 +2025-03-11T12:38:47.656021,479392728,65520,182,-41.26452184702,-53.481061680015,77.79609531238,2,1,18 +2025-03-11T12:38:47.671646,479392728,65520,182,-41.31635380984,-53.495014578105,77.87478563554,2,1,18 +2025-03-11T12:38:47.687271,479392728,65520,182,-41.36347377604,-53.541306826005,77.94897777463,2,1,18 +2025-03-11T12:38:47.702896,479392728,65520,182,-41.41059374224,-53.59222014573,78.01394608759,2,1,18 +2025-03-11T12:38:47.718521,479392728,65520,182,-41.44357771858,-53.62462471926,78.078819897535,2,1,18 +2025-03-11T12:38:47.734146,479392728,65520,182,-41.48127369154,-53.647795302105,78.15752695768,2,1,18 +2025-03-11T12:38:47.749771,479392728,65520,182,-41.52368166112,-53.680216181565,78.222414329635,2,1,18 +2025-03-11T12:38:47.765396,479392728,65520,182,-41.56137763408,-53.72187105171,78.26422608526,2,1,18 +2025-03-11T12:38:47.781021,479392728,65520,182,-41.5896496138,-53.7588885441,78.324490471135,2,1,18 +2025-03-11T12:38:47.796646,479392728,65520,182,-41.59907360704,-53.800494496455,78.37550390686,2,1,18 +2025-03-11T12:38:47.812271,479392728,65520,182,-41.59907360704,-53.837463071055,78.417242874445,2,1,18 +2025-03-11T12:38:47.827896,479392728,65520,182,-41.62734558676,-53.86061734797,78.4404821758,2,1,18 +2025-03-11T12:38:47.843521,479392728,65520,182,-41.6603295631,-53.8745376342,78.477554727355,2,1,18 +2025-03-11T12:38:47.859146,479392728,65520,182,-41.6838895462,-53.874578399025,78.509936913835,2,1,18 +2025-03-11T12:38:47.874771,479392728,65520,182,-41.71687352254,-53.87463546978,78.542332662325,2,1,18 +2025-03-11T12:38:47.890396,479392728,65520,182,-41.74514550226,-53.888547603045,78.579398432875,2,1,18 +2025-03-11T12:38:47.906021,479392728,65520,182,-41.76870548536,-53.902451583345,78.61645742242,2,1,18 +2025-03-11T12:38:47.921646,479392728,65520,182,-41.77341748198,-53.92094402361,78.63040191262,2,1,18 +2025-03-11T12:38:47.937271,479392728,65520,182,-41.77341748198,-53.94867045456,78.63051315262,2,1,18 +2025-03-11T12:38:47.952896,479392728,65520,182,-41.78755347184,-53.94407384163,78.66286323709,2,1,18 +2025-03-11T12:38:47.968521,479392728,65520,182,-41.78284147522,-53.93944461684,78.66745909915,2,1,18 +2025-03-11T12:38:47.984146,479392728,65520,182,-41.77341748198,-53.93018616726,78.66740845714,2,1,18 +2025-03-11T12:38:47.999771,479392728,65520,182,-41.77341748198,-53.925565095435,78.672011100205,2,1,18 +2025-03-11T12:38:48.015396,479392728,65520,182,-41.78284147522,-53.92096032954,78.66738493915,2,1,18 +2025-03-11T12:38:48.031021,479392728,65520,182,-41.78755347184,-53.94407384163,78.66286323709,2,1,18 +2025-03-11T12:38:48.046646,479392728,65520,182,-41.76399348874,-53.953275220455,78.658245229,2,1,18 +2025-03-11T12:38:48.062271,479392728,65520,182,-41.74043350564,-53.93475016833,78.639652431715,2,1,18 +2025-03-11T12:38:48.077896,479392728,65520,182,-41.7310095124,-53.9162495751,78.611837611315,2,1,18 +2025-03-11T12:38:48.093521,479392728,65520,182,-41.73572150902,-53.907015584415,78.588701396995,2,1,18 +2025-03-11T12:38:48.109146,479392728,65520,182,-41.72158551916,-53.893127910045,78.57014070172,2,1,18 +2025-03-11T12:38:48.124771,479392728,65520,182,-41.70273753268,-53.874611010885,78.546933502375,2,1,18 +2025-03-11T12:38:48.140396,479392728,65520,182,-41.68860154282,-53.869965480165,78.514546337905,2,1,18 +2025-03-11T12:38:48.156021,479392728,65520,182,-41.67917754958,-53.851464886935,78.47286796831,2,1,18 +2025-03-11T12:38:48.171646,479392728,65520,182,-41.66504155972,-53.828335068915,78.445027826905,2,1,18 +2025-03-11T12:38:48.187271,479392728,65520,182,-41.64148157662,-53.80056787314,78.39867085123,2,1,18 +2025-03-11T12:38:48.202896,479392728,65520,182,-41.61792159352,-53.763558533715,78.352276795555,2,1,18 +2025-03-11T12:38:48.218521,479392728,65520,182,-41.59436161042,-53.74503348159,78.301335716815,2,1,18 +2025-03-11T12:38:48.234146,479392728,65520,182,-41.5660896307,-53.71725813285,78.25035077707,2,1,18 +2025-03-11T12:38:48.249771,479392728,65520,182,-41.53310565436,-53.689474631145,78.203980239385,2,1,18 +2025-03-11T12:38:48.265396,479392728,65520,182,-41.50012167802,-53.66169112944,78.14836733557,2,1,18 +2025-03-11T12:38:48.281021,479392728,65520,182,-41.47656169492,-53.624681790015,78.09735209683,2,1,18 +2025-03-11T12:38:48.296646,479392728,65520,182,-41.4482897152,-53.578422153975,78.01394471563,2,1,18 +2025-03-11T12:38:48.312271,479392728,65520,182,-41.41059374224,-53.559872642955,77.935256195485,2,1,18 +2025-03-11T12:38:48.327896,479392728,65520,182,-41.35876177942,-53.50433009844,77.87026256152,2,1,18 +2025-03-11T12:38:48.343521,479392728,65520,182,-41.31164181322,-53.45803785054,77.791449239365,2,1,18 +2025-03-11T12:38:48.359146,479392728,65520,182,-41.27394584026,-53.41176190857,77.708028296155,2,1,18 +2025-03-11T12:38:48.374771,479392728,65520,182,-41.2126898842,-53.3515819863,77.629139010985,2,1,18 +2025-03-11T12:38:48.390396,479392728,65520,182,-41.16085792138,-53.296039441785,77.53641827863,2,1,18 +2025-03-11T12:38:48.406021,479392728,65520,182,-41.1184499518,-53.254376418675,77.443766728285,2,1,18 +2025-03-11T12:38:48.421646,479392728,65520,182,-41.06190599236,-53.22193108032,77.341889548795,2,1,18 +2025-03-11T12:38:48.437271,479392728,65520,182,-41.01478602616,-53.16639668877,77.23531204825,2,1,18 +2025-03-11T12:38:48.452896,479392728,65520,182,-40.96295406334,-53.11547521608,77.151852222025,2,1,18 +2025-03-11T12:38:48.468521,479392728,65520,182,-40.89698611066,-53.055287140845,77.068334972785,2,1,18 +2025-03-11T12:38:48.484146,479392728,65520,182,-40.84044215122,-52.999736443365,76.966365093295,2,1,18 +2025-03-11T12:38:48.499771,479392728,65520,182,-40.77447419854,-52.944169439955,76.845896919535,2,1,18 +2025-03-11T12:38:48.515396,479392728,65520,182,-40.694370256,-52.87009369035,76.71609187663,2,1,18 +2025-03-11T12:38:48.531021,479392728,65520,182,-40.6236903067,-52.805276390325,76.58171629267,2,1,18 +2025-03-11T12:38:48.546646,479392728,65520,182,-40.56714634726,-52.73586247737,76.456584877855,2,1,18 +2025-03-11T12:38:48.562271,479392728,65520,182,-40.51060238782,-52.666448564415,76.336074646105,2,1,18 +2025-03-11T12:38:48.577896,479392728,65520,182,-40.44934643176,-52.59240542667,76.20629672722,2,1,18 +2025-03-11T12:38:48.593521,479392728,65520,182,-40.38337847908,-52.50911199231,76.071853764265,2,1,18 +2025-03-11T12:38:48.609146,479392728,65520,182,-40.3174105264,-52.4165764143,75.941994904375,2,1,18 +2025-03-11T12:38:48.624771,479392728,65520,182,-40.24201858048,-52.347129889485,75.78910926715,2,1,18 +2025-03-11T12:38:48.640396,479392728,65520,182,-40.16191463794,-52.28229628353,75.64547775505,2,1,18 +2025-03-11T12:38:48.656021,479392728,65520,182,-40.0818106954,-52.2035994621,75.50179062295,2,1,18 +2025-03-11T12:38:48.671646,479392728,65520,182,-39.99228275962,-52.120265262915,75.371934938035,2,1,18 +2025-03-11T12:38:48.687271,479392728,65520,182,-39.91217881708,-52.02770522601,75.218949819805,2,1,18 +2025-03-11T12:38:48.702896,479392728,65520,182,-39.81793888468,-51.94436287386,75.061360255495,2,1,18 +2025-03-11T12:38:48.718521,479392728,65520,182,-39.7284109489,-51.861028674675,74.89453510606,2,1,18 +2025-03-11T12:38:48.734146,479392728,65520,182,-39.64359500974,-51.768460484805,74.741543206825,2,1,18 +2025-03-11T12:38:48.749771,479392728,65520,182,-39.55406707396,-51.68512628562,74.570096874325,2,1,18 +2025-03-11T12:38:48.765396,479392728,65520,182,-39.45982714156,-51.615647148945,74.38021464856,2,1,18 +2025-03-11T12:38:48.781021,479392728,65520,182,-39.36087521254,-51.52305450018,74.204096490985,2,1,18 +2025-03-11T12:38:48.796646,479392728,65520,182,-39.27134727676,-51.421236013695,74.00022771703,2,1,18 +2025-03-11T12:38:48.812271,479392728,65520,182,-39.18181934098,-51.305554311735,73.83789397066,2,1,18 +2025-03-11T12:38:48.827896,479392728,65520,182,-39.08286741196,-51.208340591145,73.64789372389,2,1,18 +2025-03-11T12:38:48.843521,479392728,65520,182,-38.96977949308,-51.10186026801,73.46245723717,2,1,18 +2025-03-11T12:38:48.859146,479392728,65520,182,-38.86611556744,-50.99077517898,73.27701577246,2,1,18 +2025-03-11T12:38:48.874771,479392728,65520,182,-38.75773964518,-50.89354515246,73.07775959755,2,1,18 +2025-03-11T12:38:48.890396,479392728,65520,182,-38.65878771616,-50.763983929095,72.883008387715,2,1,18 +2025-03-11T12:38:48.906021,479392728,65520,182,-38.54569979728,-50.652882534135,72.69293217793,2,1,18 +2025-03-11T12:38:48.921646,479392728,65520,182,-38.44203587164,-50.551039588755,72.502906610155,2,1,18 +2025-03-11T12:38:48.937271,479392728,65520,182,-38.338371946,-50.44457557155,72.30362013625,2,1,18 +2025-03-11T12:38:48.952896,479392728,65520,182,-38.22999602374,-50.324240185905,72.06730179682,2,1,18 +2025-03-11T12:38:48.968521,479392728,65520,182,-38.10748411162,-50.19925926954,71.8540504897,2,1,18 +2025-03-11T12:38:48.984146,479392728,65520,182,-37.98968419612,-50.08352864979,71.640843043585,2,1,18 +2025-03-11T12:38:48.999771,479392728,65520,182,-37.867172284,-49.958547733425,71.409107004205,2,1,18 +2025-03-11T12:38:49.015396,479392728,65520,182,-37.73994837526,-49.82893759227,71.17734564382,2,1,18 +2025-03-11T12:38:49.031021,479392728,65520,182,-37.61272446652,-49.690085307465,70.945547203435,2,1,18 +2025-03-11T12:38:49.046646,479392728,65520,182,-37.48550055778,-49.56971730996,70.71382292305,2,1,18 +2025-03-11T12:38:49.062271,479392728,65520,182,-37.3488526558,-49.4447119347,70.482066540655,2,1,18 +2025-03-11T12:38:49.077896,479392728,65520,182,-37.23576473692,-49.328989467915,70.241138777155,2,1,18 +2025-03-11T12:38:49.093521,479392728,65520,182,-37.10854082818,-49.194758254935,70.004737693705,2,1,18 +2025-03-11T12:38:49.109146,479392728,65520,182,-36.97660492282,-49.055897817165,69.763690106185,2,1,18 +2025-03-11T12:38:49.124771,479392728,65520,182,-36.83524502422,-48.917021073465,69.504144224395,2,1,18 +2025-03-11T12:38:49.140396,479392728,65520,182,-36.70330911886,-48.778160635695,69.27696018607,2,1,18 +2025-03-11T12:38:49.156021,479392728,65520,182,-36.5713732135,-48.64392126975,69.012825223225,2,1,18 +2025-03-11T12:38:49.171646,479392728,65520,182,-36.41116532842,-48.518875129665,68.73944428822,2,1,18 +2025-03-11T12:38:49.187271,479392728,65520,182,-36.26980542982,-48.361514098665,68.493687795625,2,1,18 +2025-03-11T12:38:49.202896,479392728,65520,182,-36.12844553122,-48.20877413949,68.224843927705,2,1,18 +2025-03-11T12:38:49.218521,479392728,65520,182,-35.97294964276,-48.05600972142,67.9652220829,2,1,18 +2025-03-11T12:38:49.234146,479392728,65520,182,-35.82687774754,-47.907882681105,67.705632340105,2,1,18 +2025-03-11T12:38:49.249771,479392728,65520,182,-35.69494184218,-47.74591688421,67.446007320325,2,1,18 +2025-03-11T12:38:49.265396,479392728,65520,182,-35.54415795034,-47.602402762755,67.17256578733,2,1,18 +2025-03-11T12:38:49.281021,479392728,65520,182,-35.38395006526,-47.45887233537,66.880625960065,2,1,18 +2025-03-11T12:38:49.296646,479392728,65520,182,-35.22374218018,-47.30147869251,66.57014578054,2,1,18 +2025-03-11T12:38:49.312271,479392728,65520,182,-35.05411030186,-47.15331088737,66.278173851265,2,1,18 +2025-03-11T12:38:49.327896,479392728,65520,182,-34.90332641002,-46.982070334965,65.98613634601,2,1,18 +2025-03-11T12:38:49.343521,479392728,65520,182,-34.74311852494,-46.82005562028,65.68950117568,2,1,18 +2025-03-11T12:38:49.359146,479392728,65520,182,-34.58762263648,-46.66729120221,65.392909866355,2,1,18 +2025-03-11T12:38:49.374771,479392728,65520,182,-34.4274147514,-46.5006554157,65.10087733909,2,1,18 +2025-03-11T12:38:49.390396,479392728,65520,182,-34.26720686632,-46.329398557365,64.80420508876,2,1,18 +2025-03-11T12:38:49.406021,479392728,65520,182,-34.08815099476,-46.16735123082,64.502921611345,2,1,18 +2025-03-11T12:38:49.421646,479392728,65520,182,-33.92323111306,-45.991465147695,64.192360490815,2,1,18 +2025-03-11T12:38:49.437271,479392728,65520,182,-33.74888723812,-45.810941686815,63.89563081747,2,1,18 +2025-03-11T12:38:49.452896,479392728,65520,182,-33.59810334628,-45.644322206235,63.594369486085,2,1,18 +2025-03-11T12:38:49.468521,479392728,65520,182,-33.42375947134,-45.482283032655,63.29771397274,2,1,18 +2025-03-11T12:38:49.484146,479392728,65520,182,-33.25412759302,-45.306388796565,62.977903705075,2,1,18 +2025-03-11T12:38:49.499771,479392728,65520,182,-33.07507172146,-45.121236110895,62.63955806314,2,1,18 +2025-03-11T12:38:49.515396,479392728,65520,182,-32.8960158499,-44.95918878435,62.29668393814,2,1,18 +2025-03-11T12:38:49.531021,479392728,65520,182,-32.71695997834,-44.77403609868,61.98144421153,2,1,18 +2025-03-11T12:38:49.546646,479392728,65520,182,-32.53790410678,-44.584262341185,61.652322395725,2,1,18 +2025-03-11T12:38:49.562271,479392728,65520,182,-32.36356023184,-44.39911780848,61.31860471786,2,1,18 +2025-03-11T12:38:49.577896,479392728,65520,182,-32.18450436028,-44.22320726646,60.971053789795,2,1,18 +2025-03-11T12:38:49.593521,479392728,65520,182,-32.00544848872,-44.033433508965,60.637310790925,2,1,18 +2025-03-11T12:38:49.609146,479392728,65520,182,-31.80754463068,-43.839006067785,60.294279761905,2,1,18 +2025-03-11T12:38:49.624771,479392728,65520,182,-31.61435276926,-43.658449995045,59.96055350002,2,1,18 +2025-03-11T12:38:49.640396,479392728,65520,182,-31.43058490108,-43.45480486911,59.617505734015,2,1,18 +2025-03-11T12:38:49.656021,479392728,65520,182,-31.23268104304,-43.26037742793,59.265232338865,2,1,18 +2025-03-11T12:38:49.671646,479392728,65520,182,-31.034777185,-43.061328914925,58.91756158678,2,1,18 +2025-03-11T12:38:49.687271,479392728,65520,182,-30.85100931682,-42.871547004465,58.55146352545,2,1,18 +2025-03-11T12:38:49.702896,479392728,65520,182,-30.66252945202,-42.68175694104,58.194601049245,2,1,18 +2025-03-11T12:38:49.718521,479392728,65520,182,-30.47404958722,-42.501209021265,57.851639202235,2,1,18 +2025-03-11T12:38:49.734146,479392728,65520,182,-30.28556972242,-42.29293467054,57.499323749095,2,1,18 +2025-03-11T12:38:49.749771,479392728,65520,182,-30.07824187114,-42.075385564305,57.11459581048,2,1,18 +2025-03-11T12:38:49.765396,479392728,65520,182,-29.86620202324,-41.87169152058,56.743780260055,2,1,18 +2025-03-11T12:38:49.781021,479392728,65520,182,-29.65887417196,-41.66800562982,56.3775926737,2,1,18 +2025-03-11T12:38:49.796646,479392728,65520,182,-29.4562583173,-41.46894896385,55.997566859155,2,1,18 +2025-03-11T12:38:49.812271,479392728,65520,182,-29.2442184694,-41.265254920125,55.62675130873,2,1,18 +2025-03-11T12:38:49.827896,479392728,65520,182,-29.03689061812,-41.061569029365,55.242078990115,2,1,18 +2025-03-11T12:38:49.843521,479392728,65520,182,-28.8436987567,-40.862528669325,54.857445554515,2,1,18 +2025-03-11T12:38:49.859146,479392728,65520,182,-28.6316589088,-40.6588346256,54.47738763796,2,1,18 +2025-03-11T12:38:49.874771,479392728,65520,182,-28.42433105752,-40.432043375715,54.083380253215,2,1,18 +2025-03-11T12:38:49.890396,479392728,65520,182,-28.207579213,-40.2237201072,53.675569917265,2,1,18 +2025-03-11T12:38:49.906021,479392728,65520,182,-27.99082736848,-40.02001791051,53.286262853575,2,1,18 +2025-03-11T12:38:49.921646,479392728,65520,182,-27.7834995172,-39.793226660625,52.89225546883,2,1,18 +2025-03-11T12:38:49.937271,479392728,65520,182,-27.5714596693,-39.5710483296,52.50750220921,2,1,18 +2025-03-11T12:38:49.952896,479392728,65520,182,-27.34999582816,-39.35347476447,52.10426919532,2,1,18 +2025-03-11T12:38:49.968521,479392728,65520,182,-27.12853198702,-39.131280127515,51.6917752753,2,1,18 +2025-03-11T12:38:49.984146,479392728,65520,182,-26.90706814588,-38.89984334691,51.283865458345,2,1,18 +2025-03-11T12:38:49.999694,479392732,65515,183,-26.6761803115,-38.6914956195,50.871413596315,2,1,18 +2025-03-11T12:38:50.015319,479392732,65515,183,-26.44529247712,-38.460042532965,50.46349021735,2,1,18 +2025-03-11T12:38:50.030944,479392732,65515,183,-26.22382863598,-38.21936360871,50.064785686525,2,1,18 +2025-03-11T12:38:50.046569,479392732,65515,183,-26.00707679146,-37.98793498107,49.67074619977,2,1,18 +2025-03-11T12:38:50.062194,479392732,65515,183,-25.77147696046,-37.75647374157,49.25357367367,2,1,18 +2025-03-11T12:38:50.077819,479392732,65515,183,-25.53587712946,-37.529633573895,48.83641968757,2,1,18 +2025-03-11T12:38:50.093444,479392732,65515,183,-25.31441328832,-37.29819679329,48.428509870615,2,1,18 +2025-03-11T12:38:50.109069,479392732,65515,183,-25.07881345732,-37.05749341014,47.98819434919,2,1,18 +2025-03-11T12:38:50.124694,479392732,65515,183,-24.85734961618,-36.82143555771,47.55716007691,2,1,18 +2025-03-11T12:38:50.140319,479392732,65515,183,-24.62174978518,-36.58997431821,47.13998755081,2,1,18 +2025-03-11T12:38:50.155944,479392732,65515,183,-24.38143795756,-36.358504925745,46.70894469451,2,1,18 +2025-03-11T12:38:50.171569,479392732,65515,183,-24.14583812656,-36.136285829895,46.27332451615,2,1,18 +2025-03-11T12:38:50.187194,479392732,65515,183,-23.9196622888,-35.9002198245,45.85614701206,2,1,18 +2025-03-11T12:38:50.202819,479392732,65515,183,-23.66521447132,-35.65948382949,45.415804366615,2,1,18 +2025-03-11T12:38:50.218444,479392732,65515,183,-23.42961464032,-35.41878044634,44.95700411293,2,1,18 +2025-03-11T12:38:50.234069,479392732,65515,183,-23.1893028127,-35.168826766575,44.5166447305,2,1,18 +2025-03-11T12:38:50.249694,479392732,65515,183,-22.94427898846,-34.93272814932,44.076334187065,2,1,18 +2025-03-11T12:38:50.265319,479392732,65515,183,-22.69925516422,-34.705871675715,43.63606072363,2,1,18 +2025-03-11T12:38:50.280944,479392732,65515,183,-22.4589433366,-34.442054780475,43.20488808733,2,1,18 +2025-03-11T12:38:50.296569,479392732,65515,183,-22.20920751574,-34.17360050748,42.76444098289,2,1,18 +2025-03-11T12:38:50.312194,479392732,65515,183,-21.95475969826,-33.93286451247,42.314855971315,2,1,18 +2025-03-11T12:38:50.327819,479392732,65515,183,-21.70973587402,-33.67366053609,41.84672562949,2,1,18 +2025-03-11T12:38:50.343444,479392732,65515,183,-21.4694240464,-33.4190857845,41.392484157865,2,1,18 +2025-03-11T12:38:50.359069,479392732,65515,183,-21.21497622892,-33.16910764584,40.938240883225,2,1,18 +2025-03-11T12:38:50.374694,479392732,65515,183,-20.95581641482,-32.928363497865,40.451679626125,2,1,18 +2025-03-11T12:38:50.390319,479392732,65515,183,-20.70608059396,-32.673772440345,40.020530507815,2,1,18 +2025-03-11T12:38:50.405944,479392732,65515,183,-20.43749678662,-32.42376984279,39.56626689016,2,1,18 +2025-03-11T12:38:50.421569,479392732,65515,183,-20.16891297928,-32.18763046071,39.093574160245,2,1,18 +2025-03-11T12:38:50.437194,479392732,65515,183,-19.91917715842,-31.91455511589,38.60227550209,2,1,18 +2025-03-11T12:38:50.452819,479392732,65515,183,-19.6553053477,-31.65531852765,38.12025448705,2,1,18 +2025-03-11T12:38:50.468444,479392732,65515,183,-19.3961455336,-31.3822268769,37.638184633015,2,1,18 +2025-03-11T12:38:50.484069,479392732,65515,183,-19.15583370598,-31.12765212531,37.170079612195,2,1,18 +2025-03-11T12:38:50.499694,479392732,65515,183,-18.89667389188,-30.87304476186,36.72505338268,2,1,18 +2025-03-11T12:38:50.515319,479392732,65515,183,-18.63751407778,-30.60919525476,36.270747707035,2,1,18 +2025-03-11T12:38:50.530944,479392732,65515,183,-18.38777825692,-30.36384634089,35.793423838075,2,1,18 +2025-03-11T12:38:50.546569,479392732,65515,183,-18.11919444958,-30.09998052786,35.315998685095,2,1,18 +2025-03-11T12:38:50.562194,479392732,65515,183,-17.85532263886,-29.82225965232,34.82928232699,2,1,18 +2025-03-11T12:38:50.577819,479392732,65515,183,-17.59616282476,-29.55841014522,34.338007186825,2,1,18 +2025-03-11T12:38:50.593444,479392732,65515,183,-17.33700301066,-29.29456063812,33.85597441279,2,1,18 +2025-03-11T12:38:50.609069,479392732,65515,183,-17.06841920332,-29.03993696874,33.364722790615,2,1,18 +2025-03-11T12:38:50.624694,479392732,65515,183,-16.8045473926,-28.7622160932,32.86876406638,2,1,18 +2025-03-11T12:38:50.640319,479392732,65515,183,-16.52653959202,-28.484470758765,32.39126973139,2,1,18 +2025-03-11T12:38:50.655944,479392732,65515,183,-16.25324378806,-28.215975720945,31.89995570821,2,1,18 +2025-03-11T12:38:50.671569,479392732,65515,183,-16.0035079672,-27.942900376125,31.417899416185,2,1,18 +2025-03-11T12:38:50.687194,479392732,65515,183,-15.73963615648,-27.674421644235,30.92197777195,2,1,18 +2025-03-11T12:38:50.702819,479392732,65515,183,-15.46634035252,-27.40130553459,30.398296927315,2,1,18 +2025-03-11T12:38:50.718444,479392732,65515,183,-15.18362055532,-27.109688831715,29.869907177605,2,1,18 +2025-03-11T12:38:50.734069,479392732,65515,183,-14.91032475136,-26.82733057842,29.38315871749,2,1,18 +2025-03-11T12:38:50.749694,479392732,65515,183,-14.63231695078,-26.568069531285,28.88725381024,2,1,18 +2025-03-11T12:38:50.765319,479392732,65515,183,-14.3778691333,-26.2949860335,28.391327188015,2,1,18 +2025-03-11T12:38:50.780944,479392732,65515,183,-14.0951493361,-26.021853617925,27.899981062825,2,1,18 +2025-03-11T12:38:50.796569,479392732,65515,183,-13.8124295389,-25.753342274175,27.40403229457,2,1,18 +2025-03-11T12:38:50.812194,479392732,65515,183,-13.5297097417,-25.4802098586,26.908064986315,2,1,18 +2025-03-11T12:38:50.827819,479392732,65515,183,-13.25641393774,-25.197851605305,26.407452977005,2,1,18 +2025-03-11T12:38:50.843444,479392732,65515,183,-12.98311813378,-24.920114423835,25.897617141565,2,1,18 +2025-03-11T12:38:50.859069,479392732,65515,183,-12.71924632306,-24.633151404645,25.37389423894,2,1,18 +2025-03-11T12:38:50.874694,479392732,65515,183,-12.422390536,-24.359994530175,24.85017948928,2,1,18 +2025-03-11T12:38:50.890319,479392732,65515,183,-12.13495874218,-24.086853961635,24.33572066776,2,1,18 +2025-03-11T12:38:50.905944,479392732,65515,183,-11.8569509416,-23.79986648355,23.83046215438,2,1,18 +2025-03-11T12:38:50.921569,479392732,65515,183,-11.56480715116,-23.508233474745,23.315922391855,2,1,18 +2025-03-11T12:38:50.937194,479392732,65515,183,-11.28208735396,-23.230479987345,22.80145181134,2,1,18 +2025-03-11T12:38:50.952819,479392732,65515,183,-11.00407955338,-22.94349250926,22.263845016505,2,1,18 +2025-03-11T12:38:50.968444,479392732,65515,183,-10.73078374942,-22.66575532779,21.744766814935,2,1,18 +2025-03-11T12:38:50.984069,479392732,65515,183,-10.44806395222,-22.36951755309,21.23022207442,2,1,18 +2025-03-11T12:38:50.999694,479392732,65515,183,-10.16534415502,-22.07327977839,20.71105615084,2,1,18 +2025-03-11T12:38:51.015319,479392732,65515,183,-9.88262435782,-21.78628414734,20.205790856455,2,1,18 +2025-03-11T12:38:51.030944,479392732,65515,183,-9.595192564,-21.50390143515,19.68667377187,2,1,18 +2025-03-11T12:38:51.046569,479392732,65515,183,-9.30304877356,-21.212268426345,19.162891643215,2,1,18 +2025-03-11T12:38:51.062194,479392732,65515,183,-9.02504097298,-20.90679666096,18.63445305451,2,1,18 +2025-03-11T12:38:51.077819,479392732,65515,183,-8.72818518592,-20.61515549919,18.11066414485,2,1,18 +2025-03-11T12:38:51.093444,479392732,65515,183,-8.43604139548,-20.33738570586,17.577695270065,2,1,18 +2025-03-11T12:38:51.109069,479392732,65515,183,-8.14860960166,-20.05500299367,17.04933581935,2,1,18 +2025-03-11T12:38:51.124694,479392732,65515,183,-7.8517538146,-19.7633618319,16.53478927582,2,1,18 +2025-03-11T12:38:51.140319,479392732,65515,183,-7.55961002416,-19.462486679445,16.02483361636,2,1,18 +2025-03-11T12:38:51.155944,479392732,65515,183,-7.2627542371,-19.180087661325,15.49183942057,2,1,18 +2025-03-11T12:38:51.171569,479392732,65515,183,-6.97532244328,-18.888462805485,14.954200523725,2,1,18 +2025-03-11T12:38:51.187194,479392732,65515,183,-6.68789064946,-18.58297473417,14.430369556075,2,1,18 +2025-03-11T12:38:51.202819,479392732,65515,183,-6.40988284888,-18.29136618426,13.897365404305,2,1,18 +2025-03-11T12:38:51.218444,479392732,65515,183,-6.11302706182,-17.99972502249,13.34122821319,2,1,18 +2025-03-11T12:38:51.234069,479392732,65515,183,-5.80674728152,-17.71730969844,12.80822045539,2,1,18 +2025-03-11T12:38:51.249694,479392732,65515,183,-5.50517949784,-17.434902527355,12.275219478595,2,1,18 +2025-03-11T12:38:51.265319,479392732,65515,183,-5.21774770402,-17.134035527865,11.751407050945,2,1,18 +2025-03-11T12:38:51.280944,479392732,65515,183,-4.93973990344,-16.82856376248,11.209104913045,2,1,18 +2025-03-11T12:38:51.296569,479392732,65515,183,-4.64288411638,-16.52768045706,10.65293064193,2,1,18 +2025-03-11T12:38:51.312194,479392732,65515,183,-4.34602832932,-16.240660367115,10.106054356945,2,1,18 +2025-03-11T12:38:51.327819,479392732,65515,183,-4.05388453888,-15.944406286485,9.56376895603,2,1,18 +2025-03-11T12:38:51.343444,479392732,65515,183,-3.76645274506,-15.634297143345,9.026055899185,2,1,18 +2025-03-11T12:38:51.359069,479392732,65515,183,-3.469596958,-15.351898125225,8.502304069525,2,1,18 +2025-03-11T12:38:51.374694,479392732,65515,183,-3.18216516418,-15.051031125735,7.969249275745,2,1,18 +2025-03-11T12:38:51.390319,479392732,65515,183,-2.89002137374,-14.75939811693,7.422361231765,2,1,18 +2025-03-11T12:38:51.405944,479392732,65515,183,-2.59316558668,-14.45851481151,6.889292875975,2,1,18 +2025-03-11T12:38:51.421569,479392732,65515,183,-2.27274981652,-14.166832884915,6.34698532903,2,1,18 +2025-03-11T12:38:51.437194,479392732,65515,183,-1.97118203284,-13.879804642005,5.795481079975,2,1,18 +2025-03-11T12:38:51.452819,479392732,65515,183,-1.67432624578,-13.578921336585,5.26703390725,2,1,18 +2025-03-11T12:38:51.468444,479392732,65515,183,-1.37747045872,-13.27341695934,4.70621991307,2,1,18 +2025-03-11T12:38:51.484069,479392732,65515,183,-1.08532666828,-12.972541806885,4.15929478909,2,1,18 +2025-03-11T12:38:51.499694,479392732,65515,183,-0.77904688798,-12.680884339185,3.62624995129,2,1,18 +2025-03-11T12:38:51.515319,479392732,65515,183,-0.46805511106,-12.393839790345,3.07011095716,2,1,18 +2025-03-11T12:38:51.530944,479392732,65515,183,-0.18062331724,-12.083730647205,2.504670801925,2,1,18 +2025-03-11T12:38:51.546569,479392732,65515,183,0.11623246982,-11.773605198135,1.95770181694,2,1,18 +2025-03-11T12:38:51.562194,479392732,65515,183,0.42251225012,-11.45884237131,1.419943096075,2,1,18 +2025-03-11T12:38:51.577819,479392732,65515,183,0.70994404394,-11.171838587295,0.886943922295,2,1,18 +2025-03-11T12:38:51.593444,479392732,65515,183,0.99266384114,-10.87097974077,0.33541117726,2,1,18 +2025-03-11T12:38:51.609069,479392732,65515,183,1.29423162482,-10.55622506691,-0.19309839647,2,1,18 +2025-03-11T12:38:51.624694,479392732,65515,183,1.60051140512,-10.250704383735,-0.740062403465,2,1,18 +2025-03-11T12:38:51.640319,479392732,65515,183,1.90679118542,-9.959046916035,-1.29621315659,2,1,18 +2025-03-11T12:38:51.655944,479392732,65515,183,2.21307096572,-9.676631591985,-1.852326829715,2,1,18 +2025-03-11T12:38:51.671569,479392732,65515,183,2.49579076292,-9.371151673635,-2.39463574862,2,1,18 +2025-03-11T12:38:51.687194,479392732,65515,183,2.7973585466,-9.065639143425,-2.93235060848,2,1,18 +2025-03-11T12:38:51.702819,479392732,65515,183,3.09421433366,-8.764755838005,-3.49314606266,2,1,18 +2025-03-11T12:38:51.718444,479392732,65515,183,3.40520611058,-8.459227001865,-4.05860158292,2,1,18 +2025-03-11T12:38:51.734069,479392732,65515,183,3.70206189764,-8.167585840095,-4.60087522484,2,1,18 +2025-03-11T12:38:51.749694,479392732,65515,183,4.00362968132,-7.862073309885,-5.14783245083,2,1,18 +2025-03-11T12:38:51.765319,479392732,65515,183,4.29106147514,-7.551964166745,-5.704030239935,2,1,18 +2025-03-11T12:38:51.780944,479392732,65515,183,4.57849326896,-7.260339310905,-6.246290319845,2,1,18 +2025-03-11T12:38:51.796569,479392732,65515,183,4.88006105264,-6.954826780695,-6.793247545835,2,1,18 +2025-03-11T12:38:51.812194,479392732,65515,183,5.19105282956,-6.649297944555,-7.3448395169,2,1,18 +2025-03-11T12:38:51.827819,479392732,65515,183,5.50204460648,-6.35763232389,-7.8917546849,2,1,18 +2025-03-11T12:38:51.843444,479392732,65515,183,5.80361239016,-6.065983009155,-8.434035107825,2,1,18 +2025-03-11T12:38:51.859069,479392732,65515,183,6.10046817722,-5.77896291921,-8.994774942005,2,1,18 +2025-03-11T12:38:51.874694,479392732,65515,183,6.39732396428,-5.47807961379,-9.555570396185,2,1,18 +2025-03-11T12:38:51.890319,479392732,65515,183,6.68946775472,-5.167962317685,-10.10715378323,2,1,18 +2025-03-11T12:38:51.905944,479392732,65515,183,6.98161154516,-4.86708716523,-10.65407890721,2,1,18 +2025-03-11T12:38:51.921569,479392732,65515,183,7.2737553356,-4.5708330846,-11.1732583928,2,1,18 +2025-03-11T12:38:51.937194,479392732,65515,183,7.57061112266,-4.28843406648,-11.71549495472,2,1,18 +2025-03-11T12:38:51.952819,479392732,65515,183,7.87217890634,-3.987542608095,-12.27167600684,2,1,18 +2025-03-11T12:38:51.968444,479392732,65515,183,8.1690346934,-3.68203823085,-12.80476290263,2,1,18 +2025-03-11T12:38:51.984069,479392732,65515,183,8.46117848384,-3.371920934745,-13.337861557415,2,1,18 +2025-03-11T12:38:51.999694,479392732,65515,183,8.76274626752,-3.08027162001,-13.88938434647,2,1,18 +2025-03-11T12:38:52.015319,479392732,65515,183,9.0643140512,-2.788622305275,-14.440907135525,2,1,18 +2025-03-11T12:38:52.030944,479392732,65515,183,9.3470338484,-2.48776345875,-14.969333965235,2,1,18 +2025-03-11T12:38:52.046569,479392732,65515,183,9.64860163208,-2.20073521584,-15.516217031225,2,1,18 +2025-03-11T12:38:52.062194,479392732,65515,183,9.94074542252,-1.918344350685,-16.053825629075,2,1,18 +2025-03-11T12:38:52.077819,479392732,65515,183,10.22817721634,-1.608235207545,-16.59153868592,2,1,18 +2025-03-11T12:38:52.093444,479392732,65515,183,10.52974500002,-1.28885946186,-17.12930916578,2,1,18 +2025-03-11T12:38:52.109069,479392732,65515,183,10.8313127837,-0.997210147124999,-17.662347222575,2,1,18 +2025-03-11T12:38:52.124694,479392732,65515,183,11.137592564,-0.69168946395,-18.2185535957,2,1,18 +2025-03-11T12:38:52.140319,479392732,65515,183,11.42973635444,-0.381572167845,-18.751652250485,2,1,18 +2025-03-11T12:38:52.155944,479392732,65515,183,11.7265921415,-0.0945520779000004,-19.28004380321,2,1,18 +2025-03-11T12:38:52.171569,479392732,65515,183,12.03758391842,0.20173461459,-19.822356328145,2,1,18 +2025-03-11T12:38:52.187194,479392732,65515,183,12.32501571224,0.51184375773,-20.355448201925,2,1,18 +2025-03-11T12:38:52.202819,479392732,65515,183,12.60773550944,0.803460460605,-20.902322683895,2,1,18 +2025-03-11T12:38:52.218444,479392732,65515,183,12.89987929988,1.10433561306,-21.44462662481,2,1,18 +2025-03-11T12:38:52.234069,479392732,65515,183,13.1873110937,1.4144447562,-21.991582047785,2,1,18 +2025-03-11T12:38:52.249694,479392732,65515,183,13.49830287062,1.687626089565,-22.519938323525,2,1,18 +2025-03-11T12:38:52.265319,479392732,65515,183,13.7998706543,1.97003326065,-23.05293930032,2,1,18 +2025-03-11T12:38:52.280944,479392732,65515,183,14.08730244812,2.266279188315,-23.599839103295,2,1,18 +2025-03-11T12:38:52.296569,479392732,65515,183,14.37944623856,2.55791219712,-24.11437886582,2,1,18 +2025-03-11T12:38:52.312194,479392732,65515,183,14.67630202562,2.844932287065,-24.633528052415,2,1,18 +2025-03-11T12:38:52.327819,479392732,65515,183,14.96844581606,3.13656529587,-25.161931364135,2,1,18 +2025-03-11T12:38:52.343444,479392732,65515,183,15.25587760988,3.423569079885,-25.704172904045,2,1,18 +2025-03-11T12:38:52.359069,479392732,65515,183,15.5433094037,3.7290571512,-26.22338268863,2,1,18 +2025-03-11T12:38:52.374694,479392732,65515,183,15.83545319414,4.020690160005,-26.756407183415,2,1,18 +2025-03-11T12:38:52.390319,479392732,65515,183,16.11817299134,4.30306471923,-27.284759853125,2,1,18 +2025-03-11T12:38:52.405944,479392732,65515,183,16.39618079192,4.590052197315,-27.817745464895,2,1,18 +2025-03-11T12:38:52.421569,479392732,65515,183,16.67890058912,4.867805684715,-28.35070077767,2,1,18 +2025-03-11T12:38:52.437194,479392732,65515,183,16.96633238294,5.15480946873,-28.869836402255,2,1,18 +2025-03-11T12:38:52.452819,479392732,65515,183,17.24434018352,5.44641801864,-29.384355821765,2,1,18 +2025-03-11T12:38:52.468444,479392732,65515,183,17.52705998072,5.728792577865,-29.903466125345,2,1,18 +2025-03-11T12:38:52.484069,479392732,65515,183,17.81920377116,6.02042558667,-30.427248254,2,1,18 +2025-03-11T12:38:52.499694,479392732,65515,183,18.1113475616,6.3166796673,-30.941806556525,2,1,18 +2025-03-11T12:38:52.515319,479392732,65515,183,18.3940673588,6.5944331547,-31.4747618693,2,1,18 +2025-03-11T12:38:52.530944,479392732,65515,183,18.67207515938,6.881420632785,-32.003126298005,2,1,18 +2025-03-11T12:38:52.546569,479392732,65515,183,18.96421894982,7.168432569765,-32.5084051544,2,1,18 +2025-03-11T12:38:52.562194,479392732,65515,183,19.24693874702,7.46004927264,-33.01831017185,2,1,18 +2025-03-11T12:38:52.577819,479392732,65515,183,19.53437054084,7.728568769355,-33.53275045337,2,1,18 +2025-03-11T12:38:52.593444,479392732,65515,183,19.81709033804,7.997080113105,-34.056426320015,2,1,18 +2025-03-11T12:38:52.609069,479392732,65515,183,20.08567414538,8.28405128526,-34.55705008832,2,1,18 +2025-03-11T12:38:52.624694,479392732,65515,183,20.36368194596,8.561796619695,-35.066892704765,2,1,18 +2025-03-11T12:38:52.640319,479392732,65515,183,20.64640174316,8.848792250745,-35.586021548345,2,1,18 +2025-03-11T12:38:52.655944,479392732,65515,183,20.93383353698,9.12655389111,-36.0958777268,2,1,18 +2025-03-11T12:38:52.671569,479392732,65515,183,21.20712934094,9.40429107258,-36.591850013045,2,1,18 +2025-03-11T12:38:52.687194,479392732,65515,183,21.4804251449,9.6727861104,-37.092406402355,2,1,18 +2025-03-11T12:38:52.702819,479392732,65515,183,21.74900895224,9.941272995255,-37.606819559855,2,1,18 +2025-03-11T12:38:52.718444,479392732,65515,183,22.01288076296,10.228236014445,-38.11205773022,2,1,18 +2025-03-11T12:38:52.734069,479392732,65515,183,22.28617656692,10.51059426774,-38.608048556465,2,1,18 +2025-03-11T12:38:52.749694,479392732,65515,183,22.55947237088,10.792952521035,-39.09479701658,2,1,18 +2025-03-11T12:38:52.765319,479392732,65515,183,22.83748017146,11.06145571182,-39.59998136996,2,1,18 +2025-03-11T12:38:52.780944,479392732,65515,183,23.11077597542,11.33919289329,-40.105196022335,2,1,18 +2025-03-11T12:38:52.796569,479392732,65515,183,23.38407177938,11.61693007476,-40.596547125515,2,1,18 +2025-03-11T12:38:52.812194,479392732,65515,183,23.65265558672,11.885416959615,-41.064748452365,2,1,18 +2025-03-11T12:38:52.827819,479392732,65515,183,23.92123939406,12.149282772645,-41.55603715454,2,1,18 +2025-03-11T12:38:52.843444,479392732,65515,183,24.19453519802,12.408535666815,-42.04731409772,2,1,18 +2025-03-11T12:38:52.859069,479392732,65515,183,24.46783100198,12.67240963281,-42.524746031705,2,1,18 +2025-03-11T12:38:52.874694,479392732,65515,183,24.73641480932,12.940896517665,-43.01605327388,2,1,18 +2025-03-11T12:38:52.890319,479392732,65515,183,25.00028662004,13.218617393205,-43.493527265855,2,1,18 +2025-03-11T12:38:52.905944,479392732,65515,183,25.26415843076,13.496338268745,-43.98948599009,2,1,18 +2025-03-11T12:38:52.921569,479392732,65515,183,25.52331824486,13.750945632195,-44.471481684125,2,1,18 +2025-03-11T12:38:52.937194,479392732,65515,183,25.7919020522,13.987085014275,-44.967280329365,2,1,18 +2025-03-11T12:38:52.952819,479392732,65515,183,26.04634986968,14.255547440235,-45.45394604546,2,1,18 +2025-03-11T12:38:52.968444,479392732,65515,183,26.30079768716,14.52863093802,-45.922145569295,2,1,18 +2025-03-11T12:38:52.984069,479392732,65515,183,26.56466949788,14.801730741735,-46.394979838205,2,1,18 +2025-03-11T12:38:52.999694,479392732,65515,183,26.81440531874,15.06094287108,-46.863116961035,2,1,18 +2025-03-11T12:38:53.015319,479392732,65515,183,27.07827712946,15.287831956545,-47.317281097685,2,1,18 +2025-03-11T12:38:53.030944,479392732,65515,183,27.34214894018,15.55168961661,-47.799320652725,2,1,18 +2025-03-11T12:38:53.046569,479392732,65515,183,27.5824607678,15.8247486555,-48.276742199675,2,1,18 +2025-03-11T12:38:53.062194,479392732,65515,183,27.83219658866,16.083960784845,-48.71253104105,2,1,18 +2025-03-11T12:38:53.077819,479392732,65515,183,28.09606839938,16.32009201396,-49.171353440765,2,1,18 +2025-03-11T12:38:53.093444,479392732,65515,183,28.3599402101,16.574707530375,-49.64873473274,2,1,18 +2025-03-11T12:38:53.109069,479392732,65515,183,28.61438802758,16.82006459721,-50.107580650445,2,1,18 +2025-03-11T12:38:53.124694,479392732,65515,183,28.85941185182,17.07002642994,-50.54794681388,2,1,18 +2025-03-11T12:38:53.140319,479392732,65515,183,29.10443567606,17.333851478145,-51.006853329575,2,1,18 +2025-03-11T12:38:53.155944,479392732,65515,183,29.34003550706,17.583797004945,-51.46569066326,2,1,18 +2025-03-11T12:38:53.171569,479392732,65515,183,29.58034733468,17.82450854106,-51.92449769795,2,1,18 +2025-03-11T12:38:53.187194,479392732,65515,183,29.83008315554,18.06985745493,-52.36485210239,2,1,18 +2025-03-11T12:38:53.202819,479392732,65515,183,30.07039498316,18.32443220652,-52.80523002482,2,1,18 +2025-03-11T12:38:53.218444,479392732,65515,183,30.32013080402,18.565160048565,-53.24556588926,2,1,18 +2025-03-11T12:38:53.234069,479392732,65515,183,30.56044263164,18.81511372833,-53.68592527169,2,1,18 +2025-03-11T12:38:53.249694,479392732,65515,183,30.80546645588,19.05583341741,-54.12163317206,2,1,18 +2025-03-11T12:38:53.265319,479392732,65515,183,31.0457782835,19.2919238817,-54.585042849815,2,1,18 +2025-03-11T12:38:53.280944,479392732,65515,183,31.27195412126,19.54185310257,-55.020760706165,2,1,18 +2025-03-11T12:38:53.296569,479392732,65515,183,31.51226594888,19.791806782335,-55.4472565394,2,1,18 +2025-03-11T12:38:53.312194,479392732,65515,183,31.7525777765,20.027897246625,-55.86907556957,2,1,18 +2025-03-11T12:38:53.327819,479392732,65515,183,31.99288960412,20.25012449544,-56.286217796675,2,1,18 +2025-03-11T12:38:53.343444,479392732,65515,183,32.23320143174,20.48621495973,-56.726521559105,2,1,18 +2025-03-11T12:38:53.359069,479392732,65515,183,32.4593772695,20.713038821475,-57.15752553239,2,1,18 +2025-03-11T12:38:53.374694,479392732,65515,183,32.68555310726,20.93986268322,-57.579287139545,2,1,18 +2025-03-11T12:38:53.390319,479392732,65515,183,32.92586493488,21.15746886021,-57.982547277455,2,1,18 +2025-03-11T12:38:53.405944,479392732,65515,183,33.16146476588,21.384309027885,-58.38583771436,2,1,18 +2025-03-11T12:38:53.421569,479392732,65515,183,33.39706459688,21.62039133921,-58.81227114659,2,1,18 +2025-03-11T12:38:53.437194,479392732,65515,183,33.62324043464,21.847215200955,-59.224790387615,2,1,18 +2025-03-11T12:38:53.452819,479392732,65515,183,33.8494162724,22.069417990875,-59.62804872251,2,1,18 +2025-03-11T12:38:53.468444,479392732,65515,183,34.07559211016,22.29624185262,-60.02670441434,2,1,18 +2025-03-11T12:38:53.484069,479392732,65515,183,34.29234395468,22.513807264785,-60.429930647225,2,1,18 +2025-03-11T12:38:53.499694,479392732,65515,183,34.49967180596,22.745219586495,-60.837820121165,2,1,18 +2025-03-11T12:38:53.515319,479392732,65515,183,34.71171165386,22.96739791752,-61.241058113045,2,1,18 +2025-03-11T12:38:53.530944,479392732,65515,183,34.92846349838,23.17110011421,-61.639607542865,2,1,18 +2025-03-11T12:38:53.546569,479392732,65515,183,35.1452153429,23.3932865982,-62.038231132685,2,1,18 +2025-03-11T12:38:53.562194,479392732,65515,183,35.3572551908,23.62008600105,-62.41838174924,2,1,18 +2025-03-11T12:38:53.577819,479392732,65515,183,35.56458304208,23.846877250935,-62.80776795092,2,1,18 +2025-03-11T12:38:53.593444,479392732,65515,183,35.7813348866,24.0644426631,-63.19713063461,2,1,18 +2025-03-11T12:38:53.609069,479392732,65515,183,35.98866273788,24.263507482035,-63.591026779355,2,1,18 +2025-03-11T12:38:53.624694,479392732,65515,183,36.21483857564,24.467225984655,-63.971105038925,2,1,18 +2025-03-11T12:38:53.640319,479392732,65515,183,36.43159042016,24.67554925317,-64.35580945955,2,1,18 +2025-03-11T12:38:53.655944,479392732,65515,183,36.64834226468,24.88849359351,-64.740532420175,2,1,18 +2025-03-11T12:38:53.671569,479392732,65515,183,36.83682212948,25.087525800585,-65.129780257835,2,1,18 +2025-03-11T12:38:53.687194,479392732,65515,183,37.04886197738,25.29121984431,-65.52832290665,2,1,18 +2025-03-11T12:38:53.702819,479392732,65515,183,37.25147783204,25.494897582105,-65.889882528935,2,1,18 +2025-03-11T12:38:53.718444,479392732,65515,183,37.4540936867,25.703196391725,-66.256081874285,2,1,18 +2025-03-11T12:38:53.734069,479392732,65515,183,37.65670954136,25.911495201345,-66.58993293818,2,1,18 +2025-03-11T12:38:53.749694,479392732,65515,183,37.84518940616,26.096664192945,-66.946776874385,2,1,18 +2025-03-11T12:38:53.765319,479392732,65515,183,38.04780526082,26.30034193074,-67.3175788628,2,1,18 +2025-03-11T12:38:53.780944,479392732,65515,183,38.25984510872,26.49017275899,-67.669854060965,2,1,18 +2025-03-11T12:38:53.796569,479392732,65515,183,38.46246096338,26.675366209485,-68.03133952325,2,1,18 +2025-03-11T12:38:53.812194,479392732,65515,183,38.63680483832,26.874373957665,-68.383597553375,2,1,18 +2025-03-11T12:38:53.827819,479392732,65515,183,38.8205727065,27.064155868125,-68.731210882445,2,1,18 +2025-03-11T12:38:53.843444,479392732,65515,183,39.01376456792,27.24933301269,-69.09268278272,2,1,18 +2025-03-11T12:38:53.859069,479392732,65515,183,39.20695642934,27.46685766003,-69.445042096865,2,1,18 +2025-03-11T12:38:53.874694,479392732,65515,183,39.39072429752,27.64739742684,-69.76951243061,2,1,18 +2025-03-11T12:38:53.890319,479392732,65515,183,39.57920416232,27.82332427479,-70.10321337149,2,1,18 +2025-03-11T12:38:53.905944,479392732,65515,183,39.7629720305,28.008485113425,-70.45080816056,2,1,18 +2025-03-11T12:38:53.921569,479392732,65515,183,39.94673989868,28.189024880235,-70.77989967737,2,1,18 +2025-03-11T12:38:53.937194,479392732,65515,183,40.12108377362,28.35568512564,-71.113543195235,2,1,18 +2025-03-11T12:38:53.952819,479392732,65515,183,40.3048516418,28.540845964275,-71.42878970285,2,1,18 +2025-03-11T12:38:53.968444,479392732,65515,183,40.49804350322,28.72602310884,-71.744049772475,2,1,18 +2025-03-11T12:38:53.984069,479392732,65515,183,40.69123536464,28.90657918158,-72.073154851295,2,1,18 +2025-03-11T12:38:53.999618,479392736,65510,184,40.8702912362,29.087110795425,-72.388376037905,2,1,18 +2025-03-11T12:38:54.015243,479392736,65510,184,41.03992311452,29.263005031515,-72.694322756375,2,1,18 +2025-03-11T12:38:54.030868,479392736,65510,184,41.19070700636,29.42500344027,-73.000186730825,2,1,18 +2025-03-11T12:38:54.046493,479392736,65510,184,41.36033888468,29.58241338906,-73.315301655425,2,1,18 +2025-03-11T12:38:54.062118,479392736,65510,184,41.529970763,29.7490654815,-73.621211293895,2,1,18 +2025-03-11T12:38:54.077743,479392736,65510,184,41.6948906447,29.906467277325,-73.92707707136,2,1,18 +2025-03-11T12:38:54.093368,479392736,65510,184,41.84567453654,30.091571045205,-74.228412562745,2,1,18 +2025-03-11T12:38:54.108993,479392736,65510,184,42.00588242162,30.26282790354,-74.52970599614,2,1,18 +2025-03-11T12:38:54.124618,479392736,65510,184,42.1660903067,30.4202215464,-74.81708026034,2,1,18 +2025-03-11T12:38:54.140243,479392736,65510,184,42.32158619516,30.577607036295,-75.113690109665,2,1,18 +2025-03-11T12:38:54.155868,479392736,65510,184,42.472370087,30.734984373225,-75.40567199492,2,1,18 +2025-03-11T12:38:54.171493,479392736,65510,184,42.6372899687,30.887765097225,-75.683792133995,2,1,18 +2025-03-11T12:38:54.187118,479392736,65510,184,42.78336186392,31.04513428119,-75.96190368905,2,1,18 +2025-03-11T12:38:54.202743,479392736,65510,184,42.943569749,31.1932857804,-76.235377324055,2,1,18 +2025-03-11T12:38:54.218368,479392736,65510,184,43.10377763408,31.346058351435,-76.49962713293,2,1,18 +2025-03-11T12:38:54.233993,479392736,65510,184,43.2498495293,31.498806463575,-76.777720147985,2,1,18 +2025-03-11T12:38:54.249618,479392736,65510,184,43.40534541776,31.642328737995,-77.051168461985,2,1,18 +2025-03-11T12:38:54.265243,479392736,65510,184,43.5561293096,31.799706074925,-77.310802065785,2,1,18 +2025-03-11T12:38:54.280868,479392736,65510,184,43.70691320144,31.93397805273,-77.579585335715,2,1,18 +2025-03-11T12:38:54.296493,479392736,65510,184,43.84356110342,32.045120212515,-77.834392013435,2,1,18 +2025-03-11T12:38:54.312118,479392736,65510,184,43.97078501216,32.188593569145,-78.10317845834,2,1,18 +2025-03-11T12:38:54.327743,479392736,65510,184,44.10272091752,32.34131722239,-78.348902848925,2,1,18 +2025-03-11T12:38:54.343368,479392736,65510,184,44.24879281274,32.48482319088,-78.613095234785,2,1,18 +2025-03-11T12:38:54.358993,479392736,65510,184,44.38544071472,32.632933925265,-78.849565500245,2,1,18 +2025-03-11T12:38:54.374618,479392736,65510,184,44.51737662008,32.76717329121,-79.10445809696,2,1,18 +2025-03-11T12:38:54.390243,479392736,65510,184,44.65402452206,32.896799738295,-79.35009656855,2,1,18 +2025-03-11T12:38:54.405868,479392736,65510,184,44.7812484308,33.031030951275,-79.572634102805,2,1,18 +2025-03-11T12:38:54.421493,479392736,65510,184,44.90376034292,33.16525401129,-79.813649588315,2,1,18 +2025-03-11T12:38:54.437118,479392736,65510,184,45.03569624828,33.29487230541,-80.03155418051,2,1,18 +2025-03-11T12:38:54.452743,479392736,65510,184,45.16292015702,33.41061923109,-80.254017554765,2,1,18 +2025-03-11T12:38:54.468368,479392736,65510,184,45.29014406576,33.512502941295,-80.490288858215,2,1,18 +2025-03-11T12:38:54.483993,479392736,65510,184,45.42679196774,33.646750460205,-80.71283995448,2,1,18 +2025-03-11T12:38:54.499618,479392736,65510,184,45.54459188324,33.771723223605,-80.926084480595,2,1,18 +2025-03-11T12:38:54.515243,479392736,65510,184,45.64825580888,33.88742938446,-81.139271583695,2,1,18 +2025-03-11T12:38:54.530868,479392736,65510,184,45.7472077379,33.998506320525,-81.338569816595,2,1,18 +2025-03-11T12:38:54.546493,479392736,65510,184,45.85558366016,34.10035741887,-81.54246571457,2,1,18 +2025-03-11T12:38:54.562118,479392736,65510,184,45.96395958242,34.21607173269,-81.75103841561,2,1,18 +2025-03-11T12:38:54.577743,479392736,65510,184,46.07233550468,34.34102819016,-81.96889056278,2,1,18 +2025-03-11T12:38:54.593368,479392736,65510,184,46.19955941342,34.45677511584,-82.172869204775,2,1,18 +2025-03-11T12:38:54.608993,479392736,65510,184,46.32207132554,34.563271744905,-82.3721828027,2,1,18 +2025-03-11T12:38:54.624618,479392736,65510,184,46.42102325456,34.660485465495,-82.56218304947,2,1,18 +2025-03-11T12:38:54.640243,479392736,65510,184,46.51055119034,34.77154609563,-82.73374062197,2,1,18 +2025-03-11T12:38:54.655868,479392736,65510,184,46.61421511598,34.87338904101,-82.914523823615,2,1,18 +2025-03-11T12:38:54.671493,479392736,65510,184,46.71787904162,34.961368770915,-83.10449377139,2,1,18 +2025-03-11T12:38:54.687118,479392736,65510,184,46.82154296726,35.05859064447,-83.276016066905,2,1,18 +2025-03-11T12:38:54.702743,479392736,65510,184,46.91578289966,35.14193299662,-83.452090363475,2,1,18 +2025-03-11T12:38:54.718368,479392736,65510,184,47.00531083544,35.23913041128,-83.61897113291,2,1,18 +2025-03-11T12:38:54.733993,479392736,65510,184,47.0901267746,35.336319672975,-83.79508748747,2,1,18 +2025-03-11T12:38:54.749618,479392736,65510,184,47.17494271376,35.43350893467,-83.966582658965,2,1,18 +2025-03-11T12:38:54.765243,479392736,65510,184,47.25975865292,35.52607712454,-84.114953375135,2,1,18 +2025-03-11T12:38:54.780868,479392736,65510,184,47.34457459208,35.595539955285,-84.2770949405,2,1,18 +2025-03-11T12:38:54.796493,479392736,65510,184,47.4435265211,35.66964831675,-84.43927538888,2,1,18 +2025-03-11T12:38:54.812118,479392736,65510,184,47.5377664535,35.7529906689,-84.573759037865,2,1,18 +2025-03-11T12:38:54.827743,479392736,65510,184,47.61787039604,35.854792849455,-84.708296503835,2,1,18 +2025-03-11T12:38:54.843368,479392736,65510,184,47.68855034534,35.933473364955,-84.85659125699,2,1,18 +2025-03-11T12:38:54.858993,479392736,65510,184,47.76865428788,35.99830697091,-84.986359219895,2,1,18 +2025-03-11T12:38:54.874618,479392736,65510,184,47.8440462338,36.0816167112,-85.134679294055,2,1,18 +2025-03-11T12:38:54.890243,479392736,65510,184,47.9147261831,36.1418129394,-85.26441515495,2,1,18 +2025-03-11T12:38:54.905868,479392736,65510,184,47.98069413578,36.20662208646,-85.38492040871,2,1,18 +2025-03-11T12:38:54.921493,479392736,65510,184,48.05137408508,36.27606045831,-85.505450983475,2,1,18 +2025-03-11T12:38:54.937118,479392736,65510,184,48.12205403438,36.34549883016,-85.639845107435,2,1,18 +2025-03-11T12:38:54.952743,479392736,65510,184,48.18330999044,36.40567875243,-85.764946223255,2,1,18 +2025-03-11T12:38:54.968368,479392736,65510,184,48.25398993974,36.48435926793,-85.871650328825,2,1,18 +2025-03-11T12:38:54.983993,479392736,65510,184,48.32466988904,36.558418711605,-85.97371471133,2,1,18 +2025-03-11T12:38:54.999618,479392736,65510,184,48.37178985524,36.604710959505,-86.089497498005,2,1,18 +2025-03-11T12:38:55.015243,479392736,65510,184,48.43775780792,36.660277962915,-86.172996207245,2,1,18 +2025-03-11T12:38:55.030868,479392736,65510,184,48.4801657775,36.7158042015,-86.27494574372,2,1,18 +2025-03-11T12:38:55.046493,479392736,65510,184,48.53670973694,36.76211275533,-86.390742092405,2,1,18 +2025-03-11T12:38:55.062118,479392736,65510,184,48.56498171666,36.812993463195,-86.47878919667,2,1,18 +2025-03-11T12:38:55.077743,479392736,65510,184,48.60738968624,36.863898629955,-86.57609901008,2,1,18 +2025-03-11T12:38:55.093368,479392736,65510,184,48.65922164906,36.924062246295,-86.650353550175,2,1,18 +2025-03-11T12:38:55.108993,479392736,65510,184,48.72047760512,36.965757881265,-86.719926309215,2,1,18 +2025-03-11T12:38:55.124618,479392736,65510,184,48.77230956794,37.007437210305,-86.798727872375,2,1,18 +2025-03-11T12:38:55.140243,479392736,65510,184,48.82414153076,37.04449546752,-86.86364734634,2,1,18 +2025-03-11T12:38:55.155868,479392736,65510,184,48.86654950034,37.090779562455,-86.9147267891,2,1,18 +2025-03-11T12:38:55.171493,479392736,65510,184,48.90895746992,37.132442585565,-86.979651241055,2,1,18 +2025-03-11T12:38:55.187118,479392736,65510,184,48.94665344288,37.16485531206,-87.0583953812,2,1,18 +2025-03-11T12:38:55.202743,479392736,65510,184,48.97963741922,37.20650202924,-87.10944272195,2,1,18 +2025-03-11T12:38:55.218368,479392736,65510,184,49.00790939894,37.24351952163,-87.16508592476,2,1,18 +2025-03-11T12:38:55.233993,479392736,65510,184,49.03146938204,37.262044573755,-87.23451173576,2,1,18 +2025-03-11T12:38:55.249618,479392736,65510,184,49.05502936514,37.285190697705,-87.2854713545,2,1,18 +2025-03-11T12:38:55.265243,479392736,65510,184,49.069165355,37.3036994439,-87.322535322035,2,1,18 +2025-03-11T12:38:55.280868,479392736,65510,184,49.08801334148,37.32221634306,-87.359606070575,2,1,18 +2025-03-11T12:38:55.296493,479392736,65510,184,49.1162853212,37.32226526085,-87.415100953385,2,1,18 +2025-03-11T12:38:55.312118,479392736,65510,184,49.1398453043,37.340790312975,-87.45217848293,2,1,18 +2025-03-11T12:38:55.327743,479392736,65510,184,49.15869329078,37.377791499435,-87.48008102534,2,1,18 +2025-03-11T12:38:55.343368,479392736,65510,184,49.17754127726,37.41017161407,-87.50796502775,2,1,18 +2025-03-11T12:38:55.358993,479392736,65510,184,49.19638926374,37.42868851323,-87.53579341016,2,1,18 +2025-03-11T12:38:55.374618,479392736,65510,184,49.20581325698,37.44718910646,-87.58209296282,2,1,18 +2025-03-11T12:38:55.390243,479392736,65510,184,49.2105252536,37.456439403075,-87.609863922215,2,1,18 +2025-03-11T12:38:55.405868,479392736,65510,184,49.22466124346,37.461084933795,-87.605281622165,2,1,18 +2025-03-11T12:38:55.421493,479392736,65510,184,49.22937324008,37.47033523041,-87.60532548317,2,1,18 +2025-03-11T12:38:55.437118,479392736,65510,184,49.2340852367,37.44723802425,-87.632966662565,2,1,18 +2025-03-11T12:38:55.452743,479392736,65510,184,49.22937324008,37.45185094311,-87.63297842156,2,1,18 +2025-03-11T12:38:55.468368,479392736,65510,184,49.23879723332,37.45186724904,-87.62374961744,2,1,18 +2025-03-11T12:38:55.483993,479392736,65510,184,49.24822122656,37.46112569862,-87.600694344125,2,1,18 +2025-03-11T12:38:55.499618,479392736,65510,184,49.25293322318,37.44727063611,-87.605266688195,2,1,18 +2025-03-11T12:38:55.515243,479392736,65510,184,49.24822122656,37.438020339495,-87.600601644125,2,1,18 +2025-03-11T12:38:55.530868,479392736,65510,184,49.24822122656,37.438020339495,-87.5774957288,2,1,18 +2025-03-11T12:38:55.546493,479392736,65510,184,49.22937324008,37.437987727635,-87.56822623865,2,1,18 +2025-03-11T12:38:55.562118,479392736,65510,184,49.21523725022,37.414857909615,-87.5727343787,2,1,18 +2025-03-11T12:38:55.577743,479392736,65510,184,49.20581325698,37.39173624456,-87.540279835235,2,1,18 +2025-03-11T12:38:55.593368,479392736,65510,184,49.18225327388,37.38707440791,-87.498636742625,2,1,18 +2025-03-11T12:38:55.608993,479392736,65510,184,49.16811728402,37.37318673354,-87.466212498155,2,1,18 +2025-03-11T12:38:55.624618,479392736,65510,184,49.15398129416,37.354677987345,-87.43839089675,2,1,18 +2025-03-11T12:38:55.640243,479392736,65510,184,49.12570931444,37.32228156678,-87.405872149265,2,1,18 +2025-03-11T12:38:55.655868,479392736,65510,184,49.1162853212,37.30378097355,-87.359572596605,2,1,18 +2025-03-11T12:38:55.671493,479392736,65510,184,49.10214933134,37.28065115553,-87.308626539875,2,1,18 +2025-03-11T12:38:55.687118,479392736,65510,184,49.08330134486,37.24364996907,-87.24837571601,2,1,18 +2025-03-11T12:38:55.702743,479392736,65510,184,49.04089337528,37.21122908961,-87.17886716099,2,1,18 +2025-03-11T12:38:55.718368,479392736,65510,184,48.9984854057,37.192671425625,-87.114035409035,2,1,18 +2025-03-11T12:38:55.733993,479392736,65510,184,48.95607743612,37.15562947434,-87.05837186321,2,1,18 +2025-03-11T12:38:55.749618,479392736,65510,184,48.90895746992,37.113958298265,-87.00268299638,2,1,18 +2025-03-11T12:38:55.765243,479392736,65510,184,48.87126149696,37.076924499945,-86.95626859769,2,1,18 +2025-03-11T12:38:55.780868,479392736,65510,184,48.84298951724,37.030664863905,-86.89134594875,2,1,18 +2025-03-11T12:38:55.796493,479392736,65510,184,48.80529354428,36.98900999376,-86.812564728605,2,1,18 +2025-03-11T12:38:55.812118,479392736,65510,184,48.74874958484,36.95194358358,-86.72453255831,2,1,18 +2025-03-11T12:38:55.827743,479392736,65510,184,48.7157656085,36.9102968664,-86.63651575304,2,1,18 +2025-03-11T12:38:55.843368,479392736,65510,184,48.68749362878,36.86403723036,-86.55310837184,2,1,18 +2025-03-11T12:38:55.858993,479392736,65510,184,48.6450856592,36.808510991775,-86.47426475069,2,1,18 +2025-03-11T12:38:55.874618,479392736,65510,184,48.59325369638,36.757589519085,-86.381562558335,2,1,18 +2025-03-11T12:38:55.890243,479392736,65510,184,48.53670973694,36.692796677955,-86.298040331105,2,1,18 +2025-03-11T12:38:55.905868,479392736,65510,184,48.48958977074,36.64188335823,-86.205344919755,2,1,18 +2025-03-11T12:38:55.921493,479392736,65510,184,48.42833381468,36.595566651435,-86.098784156195,2,1,18 +2025-03-11T12:38:55.937118,479392736,65510,184,48.36707785862,36.54924994464,-85.973738660375,2,1,18 +2025-03-11T12:38:55.952743,479392736,65510,184,48.30110990594,36.479819725755,-85.87632078194,2,1,18 +2025-03-11T12:38:55.968368,479392736,65510,184,48.2445659465,36.424269028275,-85.769729719385,2,1,18 +2025-03-11T12:38:55.983993,479392736,65510,184,48.17859799382,36.35483880939,-85.64458474256,2,1,18 +2025-03-11T12:38:55.999618,479392736,65510,184,48.1032060479,36.285392284575,-85.500941471465,2,1,18 +2025-03-11T12:38:56.015243,479392736,65510,184,48.03723809522,36.20671992204,-85.361895865445,2,1,18 +2025-03-11T12:38:56.030868,479392736,65510,184,47.97598213916,36.132676784295,-85.23211794656,2,1,18 +2025-03-11T12:38:56.046493,479392736,65510,184,47.90530218986,36.05861734062,-85.102326465665,2,1,18 +2025-03-11T12:38:56.062118,479392736,65510,184,47.82991024394,35.98454974398,-84.972528203765,2,1,18 +2025-03-11T12:38:56.077743,479392736,65510,184,47.7498063014,35.9150950662,-84.84274170086,2,1,18 +2025-03-11T12:38:56.093368,479392736,65510,184,47.66970235886,35.84564038842,-84.70833401489,2,1,18 +2025-03-11T12:38:56.108993,479392736,65510,184,47.58959841632,35.762322495165,-84.56462834279,2,1,18 +2025-03-11T12:38:56.124618,479392736,65510,184,47.52834246026,35.66979507012,-84.407049165515,2,1,18 +2025-03-11T12:38:56.140243,479392736,65510,184,47.46237450758,35.591122707585,-84.268003559495,2,1,18 +2025-03-11T12:38:56.155868,479392736,65510,184,47.36342257856,35.49853005882,-84.114991317245,2,1,18 +2025-03-11T12:38:56.171493,479392736,65510,184,47.2550466563,35.4197843196,-83.952778766855,2,1,18 +2025-03-11T12:38:56.187118,479392736,65510,184,47.17023071714,35.322595057905,-83.79052596149,2,1,18 +2025-03-11T12:38:56.202743,479392736,65510,184,47.07599078474,35.239252705755,-83.61445166492,2,1,18 +2025-03-11T12:38:56.218368,479392736,65510,184,47.00059883882,35.165185109115,-83.433820389305,2,1,18 +2025-03-11T12:38:56.233993,479392736,65510,184,46.9016469098,35.081834604,-83.253118128665,2,1,18 +2025-03-11T12:38:56.249618,479392736,65510,184,46.81211897402,34.98463718934,-83.08623735923,2,1,18 +2025-03-11T12:38:56.265243,479392736,65510,184,46.71787904162,34.878189478065,-82.92855509492,2,1,18 +2025-03-11T12:38:56.280868,479392736,65510,184,46.61421511598,34.78096760451,-82.74316925021,2,1,18 +2025-03-11T12:38:56.296493,479392736,65510,184,46.50583919372,34.679116506165,-82.557758084495,2,1,18 +2025-03-11T12:38:56.312118,479392736,65510,184,46.38803927822,34.554143742765,-82.36299829064,2,1,18 +2025-03-11T12:38:56.327743,479392736,65510,184,46.28437535258,34.443058653735,-82.15907209367,2,1,18 +2025-03-11T12:38:56.343368,479392736,65510,184,46.17599943032,34.345828627215,-81.95981591876,2,1,18 +2025-03-11T12:38:56.358993,479392736,65510,184,46.07233550468,34.253227825485,-81.75596388179,2,1,18 +2025-03-11T12:38:56.374618,479392736,65510,184,45.96395958242,34.12365029619,-81.54733556075,2,1,18 +2025-03-11T12:38:56.390243,479392736,65510,184,45.85558366016,33.994072766895,-81.34794960584,2,1,18 +2025-03-11T12:38:56.405868,479392736,65510,184,45.74249574128,33.873729228285,-81.130109217665,2,1,18 +2025-03-11T12:38:56.421493,479392736,65510,184,45.63883181564,33.771886282905,-80.907735368435,2,1,18 +2025-03-11T12:38:56.437118,479392736,65510,184,45.5116079069,33.66076042905,-80.689911717245,2,1,18 +2025-03-11T12:38:56.452743,479392736,65510,184,45.38909599478,33.54040058451,-80.46281540093,2,1,18 +2025-03-11T12:38:56.468368,479392736,65510,184,45.2760080759,33.4200570459,-80.25883856195,2,1,18 +2025-03-11T12:38:56.483993,479392736,65510,184,45.14407217054,33.304301967255,-80.050231955885,2,1,18 +2025-03-11T12:38:56.499618,479392736,65510,184,45.0168482618,33.160828610625,-79.82765734163,2,1,18 +2025-03-11T12:38:56.515243,479392736,65510,184,44.88491235644,33.040452460155,-79.591305097175,2,1,18 +2025-03-11T12:38:56.530868,479392736,65510,184,44.74826445446,32.91082601307,-79.36877254091,2,1,18 +2025-03-11T12:38:56.546493,479392736,65510,184,44.62575254234,32.785845096705,-79.1277941354,2,1,18 +2025-03-11T12:38:56.562118,479392736,65510,184,44.48910464036,32.642355434145,-78.868236494615,2,1,18 +2025-03-11T12:38:56.577743,479392736,65510,184,44.36188073162,32.50350314934,-78.61795332197,2,1,18 +2025-03-11T12:38:56.593368,479392736,65510,184,44.22523282964,32.38773991773,-78.376991653445,2,1,18 +2025-03-11T12:38:56.608993,479392736,65510,184,44.09329692428,32.235016264485,-78.1127825306,2,1,18 +2025-03-11T12:38:56.624618,479392736,65510,184,43.96136101892,32.086913683065,-77.85321313082,2,1,18 +2025-03-11T12:38:56.640243,479392736,65510,184,43.82942511356,31.95267431712,-77.6121840833,2,1,18 +2025-03-11T12:38:56.655868,479392736,65510,184,43.68335321834,31.813789420455,-77.33876787131,2,1,18 +2025-03-11T12:38:56.671493,479392736,65510,184,43.52785732988,31.66564607421,-77.06530101731,2,1,18 +2025-03-11T12:38:56.687118,479392736,65510,184,43.38178543466,31.499034746595,-76.796394748385,2,1,18 +2025-03-11T12:38:56.702743,479392736,65510,184,43.23571353944,31.346286634455,-76.532165282525,2,1,18 +2025-03-11T12:38:56.718368,479392736,65510,184,43.07079365774,31.193505910455,-76.27252987571,2,1,18 +2025-03-11T12:38:56.733993,479392736,65510,184,42.9200097659,31.04074964535,-76.00367244578,2,1,18 +2025-03-11T12:38:56.749618,479392736,65510,184,42.77393787068,30.892622605035,-75.72097678766,2,1,18 +2025-03-11T12:38:56.765243,479392736,65510,184,42.60901798898,30.73522080921,-75.424353376325,2,1,18 +2025-03-11T12:38:56.780868,479392736,65510,184,42.45823409714,30.591706687755,-75.12318474494,2,1,18 +2025-03-11T12:38:56.796493,479392736,65510,184,42.29802621206,30.434313044895,-74.83581048074,2,1,18 +2025-03-11T12:38:56.812118,479392736,65510,184,42.13781832698,30.267677258385,-74.553020319605,2,1,18 +2025-03-11T12:38:56.827743,479392736,65510,184,41.98703443514,30.110299921455,-74.256417251285,2,1,18 +2025-03-11T12:38:56.843368,479392736,65510,184,41.82211455344,29.948277053805,-73.955154116885,2,1,18 +2025-03-11T12:38:56.858993,479392736,65510,184,41.6477706785,29.786237880225,-73.64001387128,2,1,18 +2025-03-11T12:38:56.874618,479392736,65510,184,41.47813880018,29.62420685961,-73.338743955875,2,1,18 +2025-03-11T12:38:56.890243,479392736,65510,184,41.30850692186,29.462175838995,-73.032852857405,2,1,18 +2025-03-11T12:38:56.905868,479392736,65510,184,41.13416304692,29.272410234465,-72.722222554865,2,1,18 +2025-03-11T12:38:56.921493,479392736,65510,184,40.95981917198,29.08726570176,-72.41623197539,2,1,18 +2025-03-11T12:38:56.937118,479392736,65510,184,40.7996112869,28.9298720589,-72.07340351441,2,1,18 +2025-03-11T12:38:56.952743,479392736,65510,184,40.62997940858,28.75397782281,-71.74897206368,2,1,18 +2025-03-11T12:38:56.968368,479392736,65510,184,40.46034753026,28.57808358672,-71.447646528275,2,1,18 +2025-03-11T12:38:56.983993,479392736,65510,184,40.29542764856,28.39757643177,-71.118582135485,2,1,18 +2025-03-11T12:38:56.999618,479392736,65510,184,40.0928117939,28.221625124925,-70.78486085159,2,1,18 +2025-03-11T12:38:57.015243,479392736,65510,184,39.91375592234,28.036472439255,-70.46962112498,2,1,18 +2025-03-11T12:38:57.030868,479392736,65510,184,39.74412404402,27.851336059515,-70.131289045055,2,1,18 +2025-03-11T12:38:57.046493,479392736,65510,184,39.55564417922,27.67078813974,-69.80219074724,2,1,18 +2025-03-11T12:38:57.062118,479392736,65510,184,39.35774032118,27.48560284221,-69.454575615155,2,1,18 +2025-03-11T12:38:57.077743,479392736,65510,184,39.16926045638,27.29119170696,-69.111558148145,2,1,18 +2025-03-11T12:38:57.093368,479392736,65510,184,38.97135659834,27.09676426578,-68.759284752995,2,1,18 +2025-03-11T12:38:57.108993,479392736,65510,184,38.78287673354,26.888489915055,-68.397726933725,2,1,18 +2025-03-11T12:38:57.124618,479392736,65510,184,38.60382086198,26.69871615756,-68.036256836465,2,1,18 +2025-03-11T12:38:57.140243,479392736,65510,184,38.41534099718,26.50430502231,-67.68861818639,2,1,18 +2025-03-11T12:38:57.155868,479392736,65510,184,38.21272514252,26.300627284515,-67.3409221133,2,1,18 +2025-03-11T12:38:57.171493,479392736,65510,184,38.0195332811,26.110829068125,-66.979431673025,2,1,18 +2025-03-11T12:38:57.187118,479392736,65510,184,37.83576541292,25.90718394219,-66.62714154089,2,1,18 +2025-03-11T12:38:57.202743,479392736,65510,184,37.6190135684,25.7034817455,-66.28404630785,2,1,18 +2025-03-11T12:38:57.218368,479392736,65510,184,37.42110971036,25.49981216067,-65.92249346657,2,1,18 +2025-03-11T12:38:57.233993,479392736,65510,184,37.22320585232,25.291521504015,-65.556300902225,2,1,18 +2025-03-11T12:38:57.249618,479392736,65510,184,37.01587800104,25.106319900555,-65.176323926675,2,1,18 +2025-03-11T12:38:57.265243,479392736,65510,184,36.81326214638,24.91188430641,-64.791695469065,2,1,18 +2025-03-11T12:38:57.280868,479392736,65510,184,36.61064629172,24.70358549679,-64.41163257452,2,1,18 +2025-03-11T12:38:57.296493,479392736,65510,184,36.40331844044,24.48141531873,-64.02226491284,2,1,18 +2025-03-11T12:38:57.312118,479392736,65510,184,36.2054145824,24.273124662075,-63.6422087993,2,1,18 +2025-03-11T12:38:57.327743,479392736,65510,184,35.99808673112,24.05557555584,-63.275965592945,2,1,18 +2025-03-11T12:38:57.343368,479392736,65510,184,35.7813348866,23.838010143675,-62.886602909255,2,1,18 +2025-03-11T12:38:57.358993,479392736,65510,184,35.57400703532,23.615839965615,-62.50185643064,2,1,18 +2025-03-11T12:38:57.374618,479392736,65510,184,35.3572551908,23.412137768925,-62.10330700082,2,1,18 +2025-03-11T12:38:57.390243,479392736,65510,184,35.1216553598,23.199160816725,-61.700072183915,2,1,18 +2025-03-11T12:38:57.405868,479392736,65510,184,34.90019151866,22.972345107945,-61.31066563922,2,1,18 +2025-03-11T12:38:57.421493,479392736,65510,184,34.68343967414,22.74553755213,-60.92126587553,2,1,18 +2025-03-11T12:38:57.437118,479392736,65510,184,34.47139982624,22.523359221105,-60.49954315139,2,1,18 +2025-03-11T12:38:57.452743,479392736,65510,184,34.25464798172,22.301172737115,-60.10091956157,2,1,18 +2025-03-11T12:38:57.468368,479392736,65510,184,34.03318414058,22.083599171985,-59.702307730745,2,1,18 +2025-03-11T12:38:57.483993,479392736,65510,184,33.8022963062,21.866009300925,-59.28519760565,2,1,18 +2025-03-11T12:38:57.499618,479392736,65510,184,33.58554446168,21.634580673285,-58.86805220357,2,1,18 +2025-03-11T12:38:57.515243,479392736,65510,184,33.34994463068,21.38925621831,-58.473929972795,2,1,18 +2025-03-11T12:38:57.530868,479392736,65510,184,33.1190567963,21.15318205995,-58.06598805383,2,1,18 +2025-03-11T12:38:57.546493,479392736,65510,184,32.89288095854,20.94022141368,-57.662766798935,2,1,18 +2025-03-11T12:38:57.562118,479392736,65510,184,32.65256913092,20.717994164865,-57.2363822057,2,1,18 +2025-03-11T12:38:57.577743,479392736,65510,184,32.4122573033,20.491145844225,-56.809979072465,2,1,18 +2025-03-11T12:38:57.593368,479392736,65510,184,32.18608146554,20.26432198248,-56.36973273305,2,1,18 +2025-03-11T12:38:57.608993,479392736,65510,184,31.95048163454,20.02361859933,-55.92479602856,2,1,18 +2025-03-11T12:38:57.624618,479392736,65510,184,31.7290177934,19.773697531425,-55.48446377015,2,1,18 +2025-03-11T12:38:57.640243,479392736,65510,184,31.50755395226,19.537639678995,-55.05342949787,2,1,18 +2025-03-11T12:38:57.655868,479392736,65510,184,31.26253012802,19.30154106174,-54.62698250363,2,1,18 +2025-03-11T12:38:57.671493,479392736,65510,184,31.03164229364,19.06546690338,-54.17744993708,2,1,18 +2025-03-11T12:38:57.687118,479392736,65510,184,30.79133046602,18.82013429544,-53.72786672852,2,1,18 +2025-03-11T12:38:57.702743,479392736,65510,184,30.54159464516,18.56554323792,-53.301338793275,2,1,18 +2025-03-11T12:38:57.718368,479392736,65510,184,30.30128281754,18.324831701805,-52.87488004004,2,1,18 +2025-03-11T12:38:57.733993,479392736,65510,184,30.06097098992,18.088741237515,-52.42533391148,2,1,18 +2025-03-11T12:38:57.749618,479392736,65510,184,29.81123516906,17.83877125182,-51.980339783975,2,1,18 +2025-03-11T12:38:57.765243,479392736,65510,184,29.5614993482,17.579559122475,-51.53530857647,2,1,18 +2025-03-11T12:38:57.780868,479392736,65510,184,29.31647552396,17.329597289745,-51.08107886384,2,1,18 +2025-03-11T12:38:57.796493,479392736,65510,184,29.0667397031,17.0888694477,-50.62225826714,2,1,18 +2025-03-11T12:38:57.812118,479392736,65510,184,28.82171587886,16.862012974095,-50.163500071445,2,1,18 +2025-03-11T12:38:57.827743,479392736,65510,184,28.571980058,16.6120429884,-49.70002121168,2,1,18 +2025-03-11T12:38:57.843368,479392736,65510,184,28.30810824728,16.348185328335,-49.241087571965,2,1,18 +2025-03-11T12:38:57.858993,479392736,65510,184,28.05837242642,16.093594270815,-48.7775901722,2,1,18 +2025-03-11T12:38:57.874618,479392736,65510,184,27.79921261232,15.838986907365,-48.30021566123,2,1,18 +2025-03-11T12:38:57.890243,479392736,65510,184,27.5353408016,15.58437139095,-47.841319101515,2,1,18 +2025-03-11T12:38:57.905868,479392736,65510,184,27.29031697736,15.320546342745,-47.38241258582,2,1,18 +2025-03-11T12:38:57.921493,479392736,65510,184,27.03115716326,15.056696835645,-46.91424336098,2,1,18 +2025-03-11T12:38:57.937118,479392736,65510,184,26.77199734916,14.77898411307,-46.422912600815,2,1,18 +2025-03-11T12:38:57.952743,479392736,65510,184,26.5222615283,14.510529840075,-45.945496031855,2,1,18 +2025-03-11T12:38:57.968368,479392736,65510,184,26.26781371082,14.269793845065,-45.48666865415,2,1,18 +2025-03-11T12:38:57.983993,479392736,65510,184,26.00865389672,14.01980755344,-45.013933866245,2,1,18 +2025-03-11T12:38:57.999557,479392740,65506,185,25.75420607924,13.74210298383,-44.52723107015,2,1,18 +2025-03-11T12:38:58.015182,479392740,65506,185,25.49033426852,13.47362425194,-44.05441534124,2,1,18 +2025-03-11T12:38:58.030807,479392740,65506,185,25.22175046118,13.195895223435,-43.56769220213,2,1,18 +2025-03-11T12:38:58.046432,479392740,65506,185,24.95316665384,12.91816619493,-43.09021142915,2,1,18 +2025-03-11T12:38:58.062057,479392740,65506,185,24.68929484312,12.663550678515,-42.59896658798,2,1,18 +2025-03-11T12:38:58.077682,479392740,65506,185,24.4254230324,12.404314090275,-42.103082023745,2,1,18 +2025-03-11T12:38:58.093307,479392740,65506,185,24.15212722844,12.145061196105,-41.61642626363,2,1,18 +2025-03-11T12:38:58.108932,479392740,65506,185,23.87411942786,11.871936933495,-41.143571651705,2,1,18 +2025-03-11T12:38:58.124557,479392740,65506,185,23.60553562052,11.598828976815,-40.647624686465,2,1,18 +2025-03-11T12:38:58.140182,479392740,65506,185,23.33695181318,11.32109994831,-40.160901547355,2,1,18 +2025-03-11T12:38:58.155807,479392740,65506,185,23.0825039957,11.048016450525,-39.66497492513,2,1,18 +2025-03-11T12:38:58.171432,479392740,65506,185,22.81392018836,10.774908493845,-39.15978559376,2,1,18 +2025-03-11T12:38:58.187057,479392740,65506,185,22.53591238778,10.492542087585,-38.659166803445,2,1,18 +2025-03-11T12:38:58.202682,479392740,65506,185,22.2814645703,10.224079661625,-38.167879904285,2,1,18 +2025-03-11T12:38:58.218307,479392740,65506,185,22.00345676972,9.95557647084,-37.6765591001,2,1,18 +2025-03-11T12:38:58.233932,479392740,65506,185,21.72073697252,9.68706512709,-37.18523151491,2,1,18 +2025-03-11T12:38:58.249557,479392740,65506,185,21.43801717532,9.41855378334,-36.66617683133,2,1,18 +2025-03-11T12:38:58.265182,479392740,65506,185,21.17885736122,9.140841060765,-36.156361338905,2,1,18 +2025-03-11T12:38:58.280807,479392740,65506,185,20.8914255674,8.867700492225,-35.65576606658,2,1,18 +2025-03-11T12:38:58.296432,479392740,65506,185,20.60399377358,8.56221242091,-35.15041983119,2,1,18 +2025-03-11T12:38:58.312057,479392740,65506,185,20.32127397638,8.279837861685,-34.64055189374,2,1,18 +2025-03-11T12:38:58.327682,479392740,65506,185,20.0432661758,8.015955742725,-34.13538608036,2,1,18 +2025-03-11T12:38:58.343307,479392740,65506,185,19.76525837522,7.74745255194,-33.63020172698,2,1,18 +2025-03-11T12:38:58.358932,479392740,65506,185,19.5013865645,7.46048953275,-33.115721190485,2,1,18 +2025-03-11T12:38:58.374557,479392740,65506,185,19.23280275716,7.155034073295,-32.61502326218,2,1,18 +2025-03-11T12:38:58.390182,479392740,65506,185,18.94065896672,6.877264279965,-32.10516030272,2,1,18 +2025-03-11T12:38:58.405807,479392740,65506,185,18.64380317966,6.59948633367,-31.57218464693,2,1,18 +2025-03-11T12:38:58.421432,479392740,65506,185,18.3705073757,6.3032648649,-31.06227465149,2,1,18 +2025-03-11T12:38:58.437057,479392740,65506,185,18.08307558188,6.025503224535,-30.533933740775,2,1,18 +2025-03-11T12:38:58.452682,479392740,65506,185,17.79093179144,5.756975574855,-30.01024431212,2,1,18 +2025-03-11T12:38:58.468307,479392740,65506,185,17.50349999762,5.46997179084,-29.463381589145,2,1,18 +2025-03-11T12:38:58.483932,479392740,65506,185,17.22078020042,5.169112944315,-28.916470027175,2,1,18 +2025-03-11T12:38:58.499557,479392740,65506,185,16.9333484066,4.8821091603,-28.401955585655,2,1,18 +2025-03-11T12:38:58.515182,479392740,65506,185,16.6506286094,4.590492457425,-27.882808202075,2,1,18 +2025-03-11T12:38:58.530807,479392740,65506,185,16.36319681558,4.31273081706,-27.36370965749,2,1,18 +2025-03-11T12:38:58.546432,479392740,65506,185,16.07576502176,4.03959024852,-26.853872019035,2,1,18 +2025-03-11T12:38:58.562057,479392740,65506,185,15.79775722118,3.73873955496,-26.339315519525,2,1,18 +2025-03-11T12:38:58.577682,479392740,65506,185,15.50090143412,3.45634053684,-25.815563689865,2,1,18 +2025-03-11T12:38:58.593307,479392740,65506,185,15.19933365044,3.183175509405,-25.287220976135,2,1,18 +2025-03-11T12:38:58.608932,479392740,65506,185,14.91190185662,2.88692958174,-24.75880590542,2,1,18 +2025-03-11T12:38:58.624557,479392740,65506,185,14.6244700628,2.5768204386,-24.20722929938,2,1,18 +2025-03-11T12:38:58.640182,479392740,65506,185,14.33232627236,2.28980850162,-23.67884452766,2,1,18 +2025-03-11T12:38:58.655807,479392740,65506,185,14.05431847178,2.00744209536,-23.15511982202,2,1,18 +2025-03-11T12:38:58.671432,479392740,65506,185,13.76688667796,1.701954024045,-22.626667671305,2,1,18 +2025-03-11T12:38:58.687057,479392740,65506,185,13.46531889428,1.39182042201,-22.088934271445,2,1,18 +2025-03-11T12:38:58.702682,479392740,65506,185,13.15432711736,1.11401801682,-21.560559455705,2,1,18 +2025-03-11T12:38:58.718307,479392740,65506,185,12.8574713303,0.817755783225,-21.03213082298,2,1,18 +2025-03-11T12:38:58.733932,479392740,65506,185,12.56061554324,0.53073569328,-20.49911808719,2,1,18 +2025-03-11T12:38:58.749557,479392740,65506,185,12.28260774266,0.23912714337,-19.952250386225,2,1,18 +2025-03-11T12:38:58.765182,479392740,65506,185,12.0093119387,-0.0755786127000002,-19.41916031546,2,1,18 +2025-03-11T12:38:58.780807,479392740,65506,185,11.7030321584,-0.37647822405,-18.872214848465,2,1,18 +2025-03-11T12:38:58.796432,479392740,65506,185,11.373192395,-0.6727975284,-18.33911756564,2,1,18 +2025-03-11T12:38:58.812057,479392740,65506,185,11.08104860456,-0.964430537205,-17.80147188779,2,1,18 +2025-03-11T12:38:58.827682,479392740,65506,185,10.8077528006,-1.2652730778,-17.2453315217,2,1,18 +2025-03-11T12:38:58.843307,479392740,65506,185,10.52032100678,-1.56614007729,-16.70303436179,2,1,18 +2025-03-11T12:38:58.858932,479392740,65506,185,10.21404122648,-1.85779754499,-16.15150479173,2,1,18 +2025-03-11T12:38:58.874557,479392740,65506,185,9.92660943266,-2.14942240083,-15.613865894885,2,1,18 +2025-03-11T12:38:58.890182,479392740,65506,185,9.6297536456,-2.445684634425,-15.05771016377,2,1,18 +2025-03-11T12:38:58.905807,479392740,65506,185,9.33289785854,-2.746567939845,-14.52464180798,2,1,18 +2025-03-11T12:38:58.921432,479392740,65506,185,9.02190608162,-3.024370345035,-13.99626699224,2,1,18 +2025-03-11T12:38:58.937057,479392740,65506,185,8.72976229118,-3.34372978479,-13.45851007439,2,1,18 +2025-03-11T12:38:58.952682,479392740,65506,185,8.43761850074,-3.64922600907,-12.90232404428,2,1,18 +2025-03-11T12:38:58.968307,479392740,65506,185,8.15018670692,-3.954714080385,-12.355387161305,2,1,18 +2025-03-11T12:38:58.983932,479392740,65506,185,7.85804291648,-4.24634708919,-11.817741483455,2,1,18 +2025-03-11T12:38:58.999557,479392740,65506,185,7.56118712942,-4.542609322785,-11.27082811847,2,1,18 +2025-03-11T12:38:59.015182,479392740,65506,185,7.2737553356,-4.8480973941,-10.714648869365,2,1,18 +2025-03-11T12:38:59.030807,479392740,65506,185,6.97218755192,-5.158230996135,-10.167673103375,2,1,18 +2025-03-11T12:38:59.046432,479392740,65506,185,6.64705978514,-5.459163219345,-9.62070051236,2,1,18 +2025-03-11T12:38:59.062057,479392740,65506,185,6.3313560116,-5.750836992975,-9.07839974642,2,1,18 +2025-03-11T12:38:59.077682,479392740,65506,185,6.03450022454,-6.05634137022,-8.54531285063,2,1,18 +2025-03-11T12:38:59.093307,479392740,65506,185,5.74706843072,-6.361829441535,-8.01223951685,2,1,18 +2025-03-11T12:38:59.108932,479392740,65506,185,5.44550064704,-6.658099828095,-7.469940553925,2,1,18 +2025-03-11T12:38:59.124557,479392740,65506,185,5.15806885322,-6.95434575576,-6.90455601869,2,1,18 +2025-03-11T12:38:59.140182,479392740,65506,185,4.85178907292,-7.250624295285,-6.348386725565,2,1,18 +2025-03-11T12:38:59.155807,479392740,65506,185,4.54550929262,-7.560766050285,-5.78291944631,2,1,18 +2025-03-11T12:38:59.171432,479392740,65506,185,4.25336550218,-7.85239905909,-5.222167853135,2,1,18 +2025-03-11T12:38:59.187057,479392740,65506,185,3.95650971512,-8.14404022086,-4.679894211215,2,1,18 +2025-03-11T12:38:59.202682,479392740,65506,185,3.65022993482,-8.440318760385,-4.137588467285,2,1,18 +2025-03-11T12:38:59.218307,479392740,65506,185,3.3392381579,-8.75046866835,-3.590599139285,2,1,18 +2025-03-11T12:38:59.233932,479392740,65506,185,3.04238237084,-9.06059411742,-3.06211488656,2,1,18 +2025-03-11T12:38:59.249557,479392740,65506,185,2.73139059392,-9.36612295356,-2.50590173243,2,1,18 +2025-03-11T12:38:59.265182,479392740,65506,185,2.42982281024,-9.667014411945,-1.95896304644,2,1,18 +2025-03-11T12:38:59.280807,479392740,65506,185,2.14239101642,-9.967881411435,-1.402802337335,2,1,18 +2025-03-11T12:38:59.296432,479392740,65506,185,1.85024722598,-10.264135492065,-0.855895753355,2,1,18 +2025-03-11T12:38:59.312057,479392740,65506,185,1.56281543216,-10.55113927608,-0.31827539651,2,1,18 +2025-03-11T12:38:59.327682,479392740,65506,185,1.2659596451,-10.847401509675,0.22401678541,2,1,18 +2025-03-11T12:38:59.343307,479392740,65506,185,0.96910385804,-11.15290588692,0.770967230395,2,1,18 +2025-03-11T12:38:59.358932,479392740,65506,185,0.65811208112,-11.453813651235,1.317919478395,2,1,18 +2025-03-11T12:38:59.374557,479392740,65506,185,0.36125629406,-11.763939100305,1.869509646445,2,1,18 +2025-03-11T12:38:59.390182,479392740,65506,185,0.06911250362,-12.06481425276,2.425677136555,2,1,18 +2025-03-11T12:38:59.405807,479392740,65506,185,-0.22774328344,-12.361076486355,2.958726952345,2,1,18 +2025-03-11T12:38:59.421432,479392740,65506,185,-0.5245990705,-12.661959791775,3.48717412507,2,1,18 +2025-03-11T12:38:59.437057,479392740,65506,185,-0.83559084742,-12.95362541244,4.029468110005,2,1,18 +2025-03-11T12:38:59.452682,479392740,65506,185,-1.12773463786,-13.263742708545,4.58105149705,2,1,18 +2025-03-11T12:38:59.468307,479392740,65506,185,-1.42930242154,-13.569255238755,5.12800872304,2,1,18 +2025-03-11T12:38:59.483932,479392740,65506,185,-1.73087020522,-13.856283481665,5.670270605965,2,1,18 +2025-03-11T12:38:59.499557,479392740,65506,185,-2.0324379889,-14.161796011875,6.217227831955,2,1,18 +2025-03-11T12:38:59.515182,479392740,65506,185,-2.32458177934,-14.467292236155,6.754929129805,2,1,18 +2025-03-11T12:38:59.530807,479392740,65506,185,-2.62614956302,-14.76818369454,7.27876190047,2,1,18 +2025-03-11T12:38:59.546432,479392740,65506,185,-2.92300535008,-15.06906699996,7.81183025626,2,1,18 +2025-03-11T12:38:59.562057,479392740,65506,185,-3.21514914052,-15.360700008765,8.354097117175,2,1,18 +2025-03-11T12:38:59.577682,479392740,65506,185,-3.49786893772,-15.66155885529,8.901008679145,2,1,18 +2025-03-11T12:38:59.593307,479392740,65506,185,-3.79472472478,-15.95320001706,9.44790350413,2,1,18 +2025-03-11T12:38:59.608932,479392740,65506,185,-4.09158051184,-16.249462250655,9.98095331992,2,1,18 +2025-03-11T12:38:59.624557,479392740,65506,185,-4.39786029214,-16.53649864653,10.51397961772,2,1,18 +2025-03-11T12:38:59.640182,479392740,65506,185,-4.6947160792,-16.809655521,11.04693673351,2,1,18 +2025-03-11T12:38:59.655807,479392740,65506,185,-4.97272387978,-17.11050621456,11.59846269754,2,1,18 +2025-03-11T12:38:59.671432,479392740,65506,185,-5.26486767022,-17.41600243884,12.13616399539,2,1,18 +2025-03-11T12:38:59.687057,479392740,65506,185,-5.55701146066,-17.71225651947,12.669207030175,2,1,18 +2025-03-11T12:38:59.702682,479392740,65506,185,-5.83973125786,-18.003873222345,13.206839146015,2,1,18 +2025-03-11T12:38:59.718307,479392740,65506,185,-6.12716305168,-18.29087700636,13.730595953665,2,1,18 +2025-03-11T12:38:59.733932,479392740,65506,185,-6.42401883874,-18.587139239955,14.26826695252,2,1,18 +2025-03-11T12:38:59.749557,479392740,65506,185,-6.71616262918,-18.874151176935,14.819757639565,2,1,18 +2025-03-11T12:38:59.765182,479392740,65506,185,-7.00830641962,-19.16578418574,15.37126686661,2,1,18 +2025-03-11T12:38:59.780807,479392740,65506,185,-7.29573821344,-19.45740904158,15.89504221426,2,1,18 +2025-03-11T12:38:59.796432,479392740,65506,185,-7.58788200388,-19.75366312221,16.418842882915,2,1,18 +2025-03-11T12:38:59.812057,479392740,65506,185,-7.89416178418,-20.040699518085,16.94724799765,2,1,18 +2025-03-11T12:38:59.827682,479392740,65506,185,-8.181593578,-20.3277033021,17.48024717143,2,1,18 +2025-03-11T12:38:59.843307,479392740,65506,185,-8.45960137858,-20.63779613931,18.00408311707,2,1,18 +2025-03-11T12:38:59.858932,479392740,65506,185,-8.7470331724,-20.9386631388,18.53713791085,2,1,18 +2025-03-11T12:38:59.874557,479392740,65506,185,-9.03446496622,-21.207182635515,19.05157819237,2,1,18 +2025-03-11T12:38:59.890182,479392740,65506,185,-9.32660875666,-21.484952428845,19.566062334895,2,1,18 +2025-03-11T12:38:59.905807,479392740,65506,185,-9.61404055048,-21.758092997385,20.07589997335,2,1,18 +2025-03-11T12:38:59.921432,479392740,65506,185,-9.91089633754,-22.049734159155,20.604310066075,2,1,18 +2025-03-11T12:38:59.937057,479392740,65506,185,-10.19832813136,-22.34598008682,21.14196750292,2,1,18 +2025-03-11T12:38:59.952682,479392740,65506,185,-10.48104792856,-22.637596789695,21.656493703435,2,1,18 +2025-03-11T12:38:59.968307,479392740,65506,185,-10.75905572914,-22.929205339605,22.17563430601,2,1,18 +2025-03-11T12:38:59.983932,479392740,65506,185,-11.04177552634,-23.197716683355,22.708552538785,2,1,18 +2025-03-11T12:38:59.999557,479392740,65506,185,-11.32449532354,-23.48009124258,23.2230416593,2,1,18 +2025-03-11T12:39:00.015182,479392740,65506,185,-11.61663911398,-23.77634532321,23.73297877876,2,1,18 +2025-03-11T12:39:00.030807,479392740,65506,185,-11.9040709078,-24.072591250875,24.24753030028,2,1,18 +2025-03-11T12:39:00.046432,479392740,65506,185,-12.18207870838,-24.34109444166,24.74347228753,2,1,18 +2025-03-11T12:39:00.062057,479392740,65506,185,-12.46008650896,-24.609597632445,25.271762556235,2,1,18 +2025-03-11T12:39:00.077682,479392740,65506,185,-12.73809430954,-24.88734296688,25.786226355745,2,1,18 +2025-03-11T12:39:00.093307,479392740,65506,185,-13.0113901135,-25.178943363825,26.30073899425,2,1,18 +2025-03-11T12:39:00.108932,479392740,65506,185,-13.27997392084,-25.46591453598,26.81522631175,2,1,18 +2025-03-11T12:39:00.124557,479392740,65506,185,-13.55798172142,-25.743659870415,27.311205379,2,1,18 +2025-03-11T12:39:00.140182,479392740,65506,185,-13.84541351524,-26.016800438955,27.80717946826,2,1,18 +2025-03-11T12:39:00.155807,479392740,65506,185,-14.1187093192,-26.2899165486,28.303133214505,2,1,18 +2025-03-11T12:39:00.171432,479392740,65506,185,-14.39200512316,-26.56765373007,28.78986313462,2,1,18 +2025-03-11T12:39:00.187057,479392740,65506,185,-14.6605889305,-26.836140614925,29.29503392599,2,1,18 +2025-03-11T12:39:00.202682,479392740,65506,185,-14.93859673108,-27.09540166206,29.8094235655,2,1,18 +2025-03-11T12:39:00.218307,479392740,65506,185,-15.21660453166,-27.363904852845,30.32385028501,2,1,18 +2025-03-11T12:39:00.233932,479392740,65506,185,-15.485188339,-27.6323917377,30.81053634412,2,1,18 +2025-03-11T12:39:00.249557,479392740,65506,185,-15.74906014972,-27.91011261324,31.288010336095,2,1,18 +2025-03-11T12:39:00.265182,479392740,65506,185,-16.01293196044,-28.18783348878,31.760863145005,2,1,18 +2025-03-11T12:39:00.280807,479392740,65506,185,-16.29093976102,-28.465578823215,32.26146339532,2,1,18 +2025-03-11T12:39:00.296432,479392740,65506,185,-16.56423556498,-28.734073861035,32.77126215076,2,1,18 +2025-03-11T12:39:00.312057,479392740,65506,185,-16.83753136894,-29.002568898855,33.24409144168,2,1,18 +2025-03-11T12:39:00.327682,479392740,65506,185,-17.10140317966,-29.26642655892,33.721509813655,2,1,18 +2025-03-11T12:39:00.343307,479392740,65506,185,-17.36056299376,-29.534897137845,34.21280349382,2,1,18 +2025-03-11T12:39:00.358932,479392740,65506,185,-17.63385879772,-29.79877110384,34.67637187861,2,1,18 +2025-03-11T12:39:00.374557,479392740,65506,185,-17.90244260506,-30.076500132345,35.16309501772,2,1,18 +2025-03-11T12:39:00.390182,479392740,65506,185,-18.16160241916,-30.331107495795,35.65895426095,2,1,18 +2025-03-11T12:39:00.405807,479392740,65506,185,-18.41605023664,-30.58570670628,36.154806723175,2,1,18 +2025-03-11T12:39:00.421432,479392740,65506,185,-18.67992204736,-30.840322222695,36.646051564345,2,1,18 +2025-03-11T12:39:00.437057,479392740,65506,185,-18.94379385808,-31.108800954585,37.137352025515,2,1,18 +2025-03-11T12:39:00.452682,479392740,65506,185,-19.19824167556,-31.377263380545,37.59629064322,2,1,18 +2025-03-11T12:39:00.468307,479392740,65506,185,-19.45268949304,-31.627241519205,38.05977628399,2,1,18 +2025-03-11T12:39:00.483932,479392740,65506,185,-19.71184930714,-31.87722781083,38.523268705765,2,1,18 +2025-03-11T12:39:00.499557,479392740,65506,185,-19.98043311448,-32.136472552035,38.991432952615,2,1,18 +2025-03-11T12:39:00.515182,479392740,65506,185,-20.23959292858,-32.40494313096,39.44575716826,2,1,18 +2025-03-11T12:39:00.530807,479392740,65506,185,-20.48461675282,-32.659526035515,39.90924778702,2,1,18 +2025-03-11T12:39:00.546432,479392740,65506,185,-20.7390645703,-32.90488310235,40.358851338595,2,1,18 +2025-03-11T12:39:00.562057,479392740,65506,185,-20.98880039116,-33.154853088045,40.81308783223,2,1,18 +2025-03-11T12:39:00.577682,479392740,65506,185,-21.22440022216,-33.39093539937,41.281111912045,2,1,18 +2025-03-11T12:39:00.593307,479392740,65506,185,-21.46471204978,-33.640889079135,41.73533484367,2,1,18 +2025-03-11T12:39:00.608932,479392740,65506,185,-21.70973587402,-33.90471412734,42.18037781017,2,1,18 +2025-03-11T12:39:00.624557,479392740,65506,185,-21.97360768474,-34.15470857193,42.639255829885,2,1,18 +2025-03-11T12:39:00.640182,479392740,65506,185,-22.2233435056,-34.404678557625,43.107355872715,2,1,18 +2025-03-11T12:39:00.655807,479392740,65506,185,-22.46836732984,-34.66850360583,43.561641205345,2,1,18 +2025-03-11T12:39:00.671432,479392740,65506,185,-22.71339115408,-34.904602223085,44.02043648104,2,1,18 +2025-03-11T12:39:00.687057,479392740,65506,185,-22.96312697494,-35.140708993305,44.43302670709,2,1,18 +2025-03-11T12:39:00.702682,479392740,65506,185,-23.19872680594,-35.399896663755,44.864174022385,2,1,18 +2025-03-11T12:39:00.718307,479392740,65506,185,-23.42961464032,-35.645212965765,45.29063775361,2,1,18 +2025-03-11T12:39:00.733932,479392740,65506,185,-23.67463846456,-35.885932654845,45.73558802011,2,1,18 +2025-03-11T12:39:00.749557,479392740,65506,185,-23.9196622888,-36.13127341575,46.194420375805,2,1,18 +2025-03-11T12:39:00.765182,479392740,65506,185,-24.15997411642,-36.36736388004,46.63010295517,2,1,18 +2025-03-11T12:39:00.780807,479392740,65506,185,-24.38614995418,-36.59880881361,47.04726191926,2,1,18 +2025-03-11T12:39:00.796432,479392740,65506,185,-24.62174978518,-36.83027005311,47.47367681149,2,1,18 +2025-03-11T12:39:00.812057,479392740,65506,185,-24.85263761956,-37.05710206782,47.88620283352,2,1,18 +2025-03-11T12:39:00.827682,479392740,65506,185,-25.08352545394,-37.288555154355,48.312610944745,2,1,18 +2025-03-11T12:39:00.843307,479392740,65506,185,-25.31912528494,-37.51539532203,48.729764930845,2,1,18 +2025-03-11T12:39:00.858932,479392740,65506,185,-25.55943711256,-37.756106858145,49.11925421956,2,1,18 +2025-03-11T12:39:00.874557,479392740,65506,185,-25.79503694356,-37.98294702582,49.53640820566,2,1,18 +2025-03-11T12:39:00.890182,479392740,65506,185,-26.02592477794,-38.214400112355,49.94895276769,2,1,18 +2025-03-11T12:39:00.905807,479392740,65506,185,-26.24267662246,-38.44120766817,50.3753219959,2,1,18 +2025-03-11T12:39:00.921432,479392740,65506,185,-26.45942846698,-38.65415200851,50.806256787175,2,1,18 +2025-03-11T12:39:00.937057,479392740,65506,185,-26.67146831488,-38.88095141136,51.20489213599,2,1,18 +2025-03-11T12:39:00.952682,479392740,65506,185,-26.8882201594,-39.126243254475,51.617471975005,2,1,18 +2025-03-11T12:39:00.968307,479392740,65506,185,-27.12853198702,-39.32998621599,52.01605530985,2,1,18 +2025-03-11T12:39:00.983932,479392740,65506,185,-27.35470782478,-39.556810077735,52.40546863555,2,1,18 +2025-03-11T12:39:00.999557,479392740,65506,185,-27.56674767268,-39.77898840876,52.804085444365,2,1,18 +2025-03-11T12:39:01.015182,479392740,65506,185,-27.76465153072,-39.99190013724,53.202644830165,2,1,18 +2025-03-11T12:39:01.030807,479392740,65506,185,-27.96726738538,-40.21868323416,53.60126661697,2,1,18 +2025-03-11T12:39:01.046432,479392740,65506,185,-28.19815521976,-40.422409889745,53.990594023675,2,1,18 +2025-03-11T12:39:01.062057,479392740,65506,185,-28.42904305414,-40.62613654533,54.37992143038,2,1,18 +2025-03-11T12:39:01.077682,479392740,65506,185,-28.6552188919,-40.84833933525,54.76007384995,2,1,18 +2025-03-11T12:39:01.093307,479392740,65506,185,-28.8436987567,-41.05199261415,55.14009786148,2,1,18 +2025-03-11T12:39:01.108932,479392740,65506,185,-29.02746662488,-41.26950095556,55.520170712005,2,1,18 +2025-03-11T12:39:01.124557,479392740,65506,185,-29.23008247954,-41.47779976518,55.89099124042,2,1,18 +2025-03-11T12:39:01.140182,479392740,65506,185,-29.42798633758,-41.676848278185,56.26176790783,2,1,18 +2025-03-11T12:39:01.155807,479392740,65506,185,-29.6447381821,-41.8851715467,56.637229962325,2,1,18 +2025-03-11T12:39:01.171432,479392740,65506,185,-29.85677803,-42.0842445186,57.012648155815,2,1,18 +2025-03-11T12:39:01.187057,479392740,65506,185,-30.0688178779,-42.278696418675,57.406532541565,2,1,18 +2025-03-11T12:39:01.202682,479392740,65506,185,-30.27614572918,-42.482382309435,57.76347776179,2,1,18 +2025-03-11T12:39:01.218307,479392740,65506,185,-30.45991359736,-42.672164219895,58.115712273925,2,1,18 +2025-03-11T12:39:01.233932,479392740,65506,185,-30.66252945202,-42.861978742215,58.49570100847,2,1,18 +2025-03-11T12:39:01.249557,479392740,65506,185,-30.85100931682,-43.06101094929,58.85722174774,2,1,18 +2025-03-11T12:39:01.265182,479392740,65506,185,-31.04891317486,-43.250817318645,59.20023423676,2,1,18 +2025-03-11T12:39:01.280807,479392740,65506,185,-31.2468170329,-43.445244759825,59.557128814975,2,1,18 +2025-03-11T12:39:01.296432,479392740,65506,185,-31.43058490108,-43.63964774211,59.90013950098,2,1,18 +2025-03-11T12:39:01.312057,479392740,65506,185,-31.61906476588,-43.838679949185,60.229311958795,2,1,18 +2025-03-11T12:39:01.327682,479392740,65506,185,-31.80754463068,-44.023848940785,60.54918643048,2,1,18 +2025-03-11T12:39:01.343307,479392740,65506,185,-31.98660050224,-44.218243770105,60.906053884675,2,1,18 +2025-03-11T12:39:01.358932,479392740,65506,185,-32.17508036704,-44.39879168988,61.25363691475,2,1,18 +2025-03-11T12:39:01.374557,479392740,65506,185,-32.36827222846,-44.57010561897,61.587326096635,2,1,18 +2025-03-11T12:39:01.390182,479392740,65506,185,-32.55204009664,-44.74140324213,61.91175935038,2,1,18 +2025-03-11T12:39:01.405807,479392740,65506,185,-32.7310959682,-44.93579807145,62.231657340055,2,1,18 +2025-03-11T12:39:01.421432,479392740,65506,185,-32.91015183976,-45.12095075712,62.55151824973,2,1,18 +2025-03-11T12:39:01.437057,479392740,65506,185,-33.0844957147,-45.301474218,62.8713538384,2,1,18 +2025-03-11T12:39:01.452682,479392740,65506,185,-33.25883958964,-45.45427124793,63.19107818707,2,1,18 +2025-03-11T12:39:01.468307,479392740,65506,185,-33.42847146796,-45.63016548402,63.52475200393,2,1,18 +2025-03-11T12:39:01.483932,479392740,65506,185,-33.60752733952,-45.81531816969,63.83999173054,2,1,18 +2025-03-11T12:39:01.499557,479392740,65506,185,-33.78187121446,-45.98659948692,64.164411422275,2,1,18 +2025-03-11T12:39:01.515182,479392740,65506,185,-33.95150309278,-46.157872651185,64.47496078381,2,1,18 +2025-03-11T12:39:01.530807,479392740,65506,185,-34.12584696772,-46.319911824765,64.762373931025,2,1,18 +2025-03-11T12:39:01.546432,479392740,65506,185,-34.30019084266,-46.48657207017,65.05904798437,2,1,18 +2025-03-11T12:39:01.562057,479392740,65506,185,-34.46511072436,-46.643973865995,65.364913761835,2,1,18 +2025-03-11T12:39:01.577682,479392740,65506,185,-34.63003060606,-46.79213351817,65.65225772704,2,1,18 +2025-03-11T12:39:01.593307,479392740,65506,185,-34.78552649452,-46.95414007989,65.9442649333,2,1,18 +2025-03-11T12:39:01.608932,479392740,65506,185,-34.92688639312,-47.13922754184,66.236344496545,2,1,18 +2025-03-11T12:39:01.624557,479392740,65506,185,-35.08238228158,-47.31047624721,66.51452523361,2,1,18 +2025-03-11T12:39:01.640182,479392740,65506,185,-35.23787817004,-47.477103880755,66.792687430675,2,1,18 +2025-03-11T12:39:01.655807,479392740,65506,185,-35.40279805174,-47.611400317455,67.084596958945,2,1,18 +2025-03-11T12:39:01.671432,479392740,65506,185,-35.55358194358,-47.74567229526,67.33951667968,2,1,18 +2025-03-11T12:39:01.687057,479392740,65506,185,-35.70436583542,-47.889186416715,67.631442944935,2,1,18 +2025-03-11T12:39:01.702682,479392740,65506,185,-35.85514972726,-48.046563753645,67.90494009793,2,1,18 +2025-03-11T12:39:01.718307,479392740,65506,185,-36.0059336191,-48.1900778751,68.17376044786,2,1,18 +2025-03-11T12:39:01.733932,479392740,65506,185,-36.15671751094,-48.342834140205,68.44261787779,2,1,18 +2025-03-11T12:39:01.749557,479392740,65506,185,-36.28394141968,-48.477065353185,68.70674605963,2,1,18 +2025-03-11T12:39:01.765182,479392740,65506,185,-36.41587732504,-48.62054686278,68.95705455328,2,1,18 +2025-03-11T12:39:01.780807,479392740,65506,185,-36.56666121688,-48.75943991241,69.211992814015,2,1,18 +2025-03-11T12:39:01.796432,479392740,65506,185,-36.71744510872,-48.88909081839,69.45765162862,2,1,18 +2025-03-11T12:39:01.812057,479392740,65506,185,-36.84938101408,-49.01870911251,69.712525685335,2,1,18 +2025-03-11T12:39:01.827682,479392740,65506,185,-36.98131691944,-49.17605383758,69.95826861592,2,1,18 +2025-03-11T12:39:01.843307,479392740,65506,185,-37.1132528248,-49.301051059875,70.203881766505,2,1,18 +2025-03-11T12:39:01.858932,479392740,65506,185,-37.23576473692,-49.42603197624,70.43099662282,2,1,18 +2025-03-11T12:39:01.874557,479392740,65506,185,-37.35827664904,-49.560255036255,70.667390925265,2,1,18 +2025-03-11T12:39:01.890182,479392740,65506,185,-37.49963654764,-49.689889636305,70.917657360925,2,1,18 +2025-03-11T12:39:01.905807,479392740,65506,185,-37.631572453,-49.810265786775,71.158630788445,2,1,18 +2025-03-11T12:39:01.921432,479392740,65506,185,-37.76350835836,-49.930641937245,71.38574066677,2,1,18 +2025-03-11T12:39:01.937057,479392740,65506,185,-37.88130827386,-50.04175148517,71.598929572885,2,1,18 +2025-03-11T12:39:01.952682,479392740,65506,185,-38.00382018598,-50.166732401535,71.79831733081,2,1,18 +2025-03-11T12:39:01.968307,479392740,65506,185,-38.10748411162,-50.296301777865,72.00231768778,2,1,18 +2025-03-11T12:39:01.983932,479392740,65506,185,-38.20172404402,-50.42123377644,72.229391858065,2,1,18 +2025-03-11T12:39:01.999496,479392744,65502,186,-38.31009996628,-50.52770594661,72.44254866217,2,1,18 +2025-03-11T12:39:02.015121,479392744,65502,186,-38.43732387502,-50.648073944115,72.646545844165,2,1,18 +2025-03-11T12:39:02.030746,479392744,65502,186,-38.573971777,-50.7592161039,72.855140691235,2,1,18 +2025-03-11T12:39:02.046371,479392744,65502,186,-38.68234769926,-50.851825058595,73.06824187534,2,1,18 +2025-03-11T12:39:02.061996,479392744,65502,186,-38.77658763166,-50.962893841695,73.249048594975,2,1,18 +2025-03-11T12:39:02.077621,479392744,65502,186,-38.87553956068,-51.08321292141,73.411414443355,2,1,18 +2025-03-11T12:39:02.093246,479392744,65502,186,-38.98391548294,-51.19892723523,73.59688122907,2,1,18 +2025-03-11T12:39:02.108871,479392744,65502,186,-39.09700340182,-51.28230219924,73.814573297245,2,1,18 +2025-03-11T12:39:02.124496,479392744,65502,186,-39.20066732746,-51.379524072795,74.009201508085,2,1,18 +2025-03-11T12:39:02.140121,479392744,65502,186,-39.29490725986,-51.47672964042,74.185331424655,2,1,18 +2025-03-11T12:39:02.155746,479392744,65502,186,-39.37972319902,-51.57853997394,74.342981586955,2,1,18 +2025-03-11T12:39:02.171371,479392744,65502,186,-39.47396313142,-51.67112446974,74.509850597395,2,1,18 +2025-03-11T12:39:02.186996,479392744,65502,186,-39.5634910672,-51.754458668925,74.67667574683,2,1,18 +2025-03-11T12:39:02.202621,479392744,65502,186,-39.6577309996,-51.847043164725,74.83430239114,2,1,18 +2025-03-11T12:39:02.218246,479392744,65502,186,-39.74254693876,-51.94423242642,74.987312830375,2,1,18 +2025-03-11T12:39:02.233871,479392744,65502,186,-39.8226508813,-52.027550319675,75.1541244178,2,1,18 +2025-03-11T12:39:02.249496,479392744,65502,186,-39.90275482384,-52.10162606928,75.31627774216,2,1,18 +2025-03-11T12:39:02.265121,479392744,65502,186,-39.98285876638,-52.19880717801,75.46003903426,2,1,18 +2025-03-11T12:39:02.280746,479392744,65502,186,-40.07709869878,-52.296012745635,75.613063035505,2,1,18 +2025-03-11T12:39:02.296371,479392744,65502,186,-40.15720264132,-52.383951710715,75.756787247605,2,1,18 +2025-03-11T12:39:02.311996,479392744,65502,186,-40.23730658386,-52.462648532145,75.891232013575,2,1,18 +2025-03-11T12:39:02.327621,479392744,65502,186,-40.2938505433,-52.527441373275,76.04407198678,2,1,18 +2025-03-11T12:39:02.343246,479392744,65502,186,-40.3645304926,-52.596879745125,76.183087293805,2,1,18 +2025-03-11T12:39:02.358871,479392744,65502,186,-40.43992243852,-52.670947341765,76.31750673877,2,1,18 +2025-03-11T12:39:02.374496,479392744,65502,186,-40.51060238782,-52.749627857265,76.4426955766,2,1,18 +2025-03-11T12:39:02.390121,479392744,65502,186,-40.58599433374,-52.81907438208,76.55399056624,2,1,18 +2025-03-11T12:39:02.405746,479392744,65502,186,-40.65196228642,-52.879262457315,76.68371964613,2,1,18 +2025-03-11T12:39:02.421371,479392744,65502,186,-40.71321824248,-52.939442379585,76.794957212755,2,1,18 +2025-03-11T12:39:02.436996,479392744,65502,186,-40.77918619516,-52.99038831117,76.89230093119,2,1,18 +2025-03-11T12:39:02.452621,479392744,65502,186,-40.84986614446,-53.055205611195,77.01743414902,2,1,18 +2025-03-11T12:39:02.468246,479392744,65502,186,-40.91583409714,-53.12463583008,77.12871557665,2,1,18 +2025-03-11T12:39:02.483871,479392744,65502,186,-40.98180204982,-53.175581761665,77.25840757654,2,1,18 +2025-03-11T12:39:02.499496,479392744,65502,186,-41.03363401264,-53.22188216253,77.36495477809,2,1,18 +2025-03-11T12:39:02.515121,479392744,65502,186,-41.07604198222,-53.28202947294,77.448438122305,2,1,18 +2025-03-11T12:39:02.530746,479392744,65502,186,-41.12787394504,-53.33295094563,77.54114031466,2,1,18 +2025-03-11T12:39:02.546371,479392744,65502,186,-41.17970590786,-53.38387241832,77.615357774755,2,1,18 +2025-03-11T12:39:02.561996,479392744,65502,186,-41.23153787068,-53.43479389101,77.703438784045,2,1,18 +2025-03-11T12:39:02.577621,479392744,65502,186,-41.2598098504,-53.485674598875,77.786864705245,2,1,18 +2025-03-11T12:39:02.593246,479392744,65502,186,-41.29750582336,-53.53657161267,77.86568300539,2,1,18 +2025-03-11T12:39:02.608871,479392744,65502,186,-41.33520179632,-53.568984339165,77.916700047145,2,1,18 +2025-03-11T12:39:02.624496,479392744,65502,186,-41.37289776928,-53.596775993835,77.97694091503,2,1,18 +2025-03-11T12:39:02.640121,479392744,65502,186,-41.42001773548,-53.624583954435,78.05105889412,2,1,18 +2025-03-11T12:39:02.655746,479392744,65502,186,-41.46713770168,-53.643149771385,78.120518610145,2,1,18 +2025-03-11T12:39:02.671371,479392744,65502,186,-41.50483367464,-53.66632035423,78.1714985719,2,1,18 +2025-03-11T12:39:02.686996,479392744,65502,186,-41.5425296476,-53.689490937075,78.222478533655,2,1,18 +2025-03-11T12:39:02.702621,479392744,65502,186,-41.5660896307,-53.721879204675,78.291959964655,2,1,18 +2025-03-11T12:39:02.718246,479392744,65502,186,-41.58493761718,-53.777364678435,78.347663765455,2,1,18 +2025-03-11T12:39:02.733871,479392744,65502,186,-41.60849760028,-53.81437401786,78.380194271935,2,1,18 +2025-03-11T12:39:02.749496,479392744,65502,186,-41.63205758338,-53.823656926335,78.42647708761,2,1,18 +2025-03-11T12:39:02.765121,479392744,65502,186,-41.65090556986,-53.83755275367,78.468150479215,2,1,18 +2025-03-11T12:39:02.780746,479392744,65502,186,-41.66975355634,-53.860690724655,78.505239767755,2,1,18 +2025-03-11T12:39:02.796371,479392744,65502,186,-41.68860154282,-53.860723336515,78.542236356295,2,1,18 +2025-03-11T12:39:02.811996,479392744,65502,186,-41.71216152592,-53.883869460465,78.57009005971,2,1,18 +2025-03-11T12:39:02.827621,479392744,65502,186,-41.72158551916,-53.89774898187,78.60712870624,2,1,18 +2025-03-11T12:39:02.843246,479392744,65502,186,-41.74043350564,-53.911644809205,78.630317365585,2,1,18 +2025-03-11T12:39:02.858871,479392744,65502,186,-41.74985749888,-53.939387546085,78.630442167595,2,1,18 +2025-03-11T12:39:02.874496,479392744,65502,186,-41.75928149212,-53.939403852015,78.648940461865,2,1,18 +2025-03-11T12:39:02.890121,479392744,65502,186,-41.7781294786,-53.93481539205,78.676676144275,2,1,18 +2025-03-11T12:39:02.905746,479392744,65502,186,-41.79226546846,-53.93946092277,78.662851478095,2,1,18 +2025-03-11T12:39:02.921371,479392744,65502,186,-41.7781294786,-53.93481539205,78.64432786282,2,1,18 +2025-03-11T12:39:02.936996,479392744,65502,186,-41.75928149212,-53.93478278019,78.648921921865,2,1,18 +2025-03-11T12:39:02.952621,479392744,65502,186,-41.76399348874,-53.92092771768,78.64887308287,2,1,18 +2025-03-11T12:39:02.968246,479392744,65502,186,-41.76870548536,-53.911693726995,78.63497923468,2,1,18 +2025-03-11T12:39:02.983871,479392744,65502,186,-41.76870548536,-53.930178014295,78.639674577745,2,1,18 +2025-03-11T12:39:02.999496,479392744,65502,186,-41.7545694955,-53.925532483575,78.635014511665,2,1,18 +2025-03-11T12:39:03.015121,479392744,65502,186,-41.74514550226,-53.897789746695,78.607162611265,2,1,18 +2025-03-11T12:39:03.030746,479392744,65502,186,-41.7310095124,-53.902386359625,78.593297259055,2,1,18 +2025-03-11T12:39:03.046371,479392744,65502,186,-41.71687352254,-53.89311975708,78.570133920715,2,1,18 +2025-03-11T12:39:03.061996,479392744,65502,186,-41.69802553606,-53.869981786095,78.542286998305,2,1,18 +2025-03-11T12:39:03.077621,479392744,65502,186,-41.67446555296,-53.85145673397,78.49596710263,2,1,18 +2025-03-11T12:39:03.093246,479392744,65502,186,-41.66975355634,-53.83758536553,78.449692870975,2,1,18 +2025-03-11T12:39:03.108871,479392744,65502,186,-41.65090556986,-53.823689538195,78.40801947937,2,1,18 +2025-03-11T12:39:03.124496,479392744,65502,186,-41.61792159352,-53.80514818014,78.370928387815,2,1,18 +2025-03-11T12:39:03.140121,479392744,65502,186,-41.5896496138,-53.7773728314,78.3291858142,2,1,18 +2025-03-11T12:39:03.155746,479392744,65502,186,-41.56137763408,-53.735734267185,78.278145254455,2,1,18 +2025-03-11T12:39:03.171371,479392744,65502,186,-41.53781765098,-53.694103855935,78.217869109585,2,1,18 +2025-03-11T12:39:03.186996,479392744,65502,186,-41.5189696645,-53.666344813125,78.15765536572,2,1,18 +2025-03-11T12:39:03.202621,479392744,65502,186,-41.48598568816,-53.63856131142,78.111284828035,2,1,18 +2025-03-11T12:39:03.218246,479392744,65502,186,-41.4482897152,-53.59228536945,78.04172743402,2,1,18 +2025-03-11T12:39:03.233871,479392744,65502,186,-41.40588174562,-53.555243418165,77.976821522065,2,1,18 +2025-03-11T12:39:03.249496,479392744,65502,186,-41.3776097659,-53.527468069425,77.89810948393,2,1,18 +2025-03-11T12:39:03.265121,479392744,65502,186,-41.3304897997,-53.481175821525,77.810053795645,2,1,18 +2025-03-11T12:39:03.280746,479392744,65502,186,-41.27865783688,-53.421012205185,77.73579925555,2,1,18 +2025-03-11T12:39:03.296371,479392744,65502,186,-41.24096186392,-53.374736263215,77.66162067847,2,1,18 +2025-03-11T12:39:03.311996,479392744,65502,186,-41.20797788758,-53.342331689685,77.596746868525,2,1,18 +2025-03-11T12:39:03.327621,479392744,65502,186,-41.165569918,-53.29604759475,77.490213228985,2,1,18 +2025-03-11T12:39:03.343246,479392744,65502,186,-41.12316194842,-53.23590028434,77.383623969445,2,1,18 +2025-03-11T12:39:03.358871,479392744,65502,186,-41.05248199912,-53.15721976884,77.286162230005,2,1,18 +2025-03-11T12:39:03.374496,479392744,65502,186,-40.99122604306,-53.09703984657,77.170303480315,2,1,18 +2025-03-11T12:39:03.390121,479392744,65502,186,-40.92054609376,-53.050706833845,77.04986560555,2,1,18 +2025-03-11T12:39:03.405746,479392744,65502,186,-40.84986614446,-53.00437382112,76.92480654772,2,1,18 +2025-03-11T12:39:03.421371,479392744,65502,186,-40.79803418164,-52.930346989305,76.822769289235,2,1,18 +2025-03-11T12:39:03.436996,479392744,65502,186,-40.73206622896,-52.884022129545,76.711580561605,2,1,18 +2025-03-11T12:39:03.452621,479392744,65502,186,-40.67552226952,-52.809987144765,76.600294155985,2,1,18 +2025-03-11T12:39:03.468246,479392744,65502,186,-40.60484232022,-52.74516984474,76.47978212122,2,1,18 +2025-03-11T12:39:03.483871,479392744,65502,186,-40.52002638106,-52.684949157645,76.35926828344,2,1,18 +2025-03-11T12:39:03.499496,479392744,65502,186,-40.44463443514,-52.61550263283,76.224867378475,2,1,18 +2025-03-11T12:39:03.515121,479392744,65502,186,-40.38337847908,-52.541459495085,76.09508945959,2,1,18 +2025-03-11T12:39:03.530746,479392744,65502,186,-40.3174105264,-52.467408204375,75.969925942765,2,1,18 +2025-03-11T12:39:03.546371,479392744,65502,186,-40.25615457034,-52.379501851155,75.84009240388,2,1,18 +2025-03-11T12:39:03.561996,479392744,65502,186,-40.18076262442,-52.305434254515,75.687188226655,2,1,18 +2025-03-11T12:39:03.577621,479392744,65502,186,-40.11008267512,-52.226753739015,75.534272290435,2,1,18 +2025-03-11T12:39:03.593246,479392744,65502,186,-40.02526673596,-52.12956447732,75.385883034265,2,1,18 +2025-03-11T12:39:03.608871,479392744,65502,186,-39.92631480694,-52.046213972205,75.22828668895,2,1,18 +2025-03-11T12:39:03.624496,479392744,65502,186,-39.8462108644,-51.967517150775,75.089220739915,2,1,18 +2025-03-11T12:39:03.640121,479392744,65502,186,-39.76139492524,-51.884191104555,74.931644737615,2,1,18 +2025-03-11T12:39:03.655746,479392744,65502,186,-39.67186698946,-51.80085690537,74.760198405115,2,1,18 +2025-03-11T12:39:03.671371,479392744,65502,186,-39.5870510503,-51.703667643675,74.58870323362,2,1,18 +2025-03-11T12:39:03.686996,479392744,65502,186,-39.47867512804,-51.597195473505,74.412515894035,2,1,18 +2025-03-11T12:39:03.702621,479392744,65502,186,-39.38914719226,-51.499998058845,74.231771575405,2,1,18 +2025-03-11T12:39:03.718246,479392744,65502,186,-39.29961925648,-51.402800644185,74.060269622905,2,1,18 +2025-03-11T12:39:03.733871,479392744,65502,186,-39.19124333422,-51.305570617665,73.888740546385,2,1,18 +2025-03-11T12:39:03.749496,479392744,65502,186,-39.0922914052,-51.199114753425,73.70332440268,2,1,18 +2025-03-11T12:39:03.765121,479392744,65502,186,-39.00276346942,-51.09729626694,73.517940360985,2,1,18 +2025-03-11T12:39:03.780746,479392744,65502,186,-38.89438754716,-51.00930838407,73.33258481527,2,1,18 +2025-03-11T12:39:03.796371,479392744,65502,186,-38.79072362152,-50.921328654165,73.142614867495,2,1,18 +2025-03-11T12:39:03.811996,479392744,65502,186,-38.67763570264,-50.800985115555,72.938638028515,2,1,18 +2025-03-11T12:39:03.827621,479392744,65502,186,-38.573971777,-50.699142170175,72.734748911545,2,1,18 +2025-03-11T12:39:03.843246,479392744,65502,186,-38.44674786826,-50.58801631632,72.526167626485,2,1,18 +2025-03-11T12:39:03.858871,479392744,65502,186,-38.34308394262,-50.44920479634,72.31750900645,2,1,18 +2025-03-11T12:39:03.874496,479392744,65502,186,-38.22999602374,-50.314998042255,72.09499181521,2,1,18 +2025-03-11T12:39:03.890121,479392744,65502,186,-38.102772115,-50.2038721884,71.881789347085,2,1,18 +2025-03-11T12:39:03.905746,479392744,65502,186,-38.00382018598,-50.083553108685,71.65934811886,2,1,18 +2025-03-11T12:39:03.921371,479392744,65502,186,-37.8907322671,-49.9678306419,71.43690508762,2,1,18 +2025-03-11T12:39:03.936996,479392744,65502,186,-37.75879636174,-49.86593877873,71.209869369295,2,1,18 +2025-03-11T12:39:03.952621,479392744,65502,186,-37.631572453,-49.736328637575,70.982729191975,2,1,18 +2025-03-11T12:39:03.968246,479392744,65502,186,-37.50434854426,-49.59747635277,70.746309568525,2,1,18 +2025-03-11T12:39:03.983871,479392744,65502,186,-37.38183663214,-49.463253292755,70.514536449145,2,1,18 +2025-03-11T12:39:03.999496,479392744,65502,186,-37.24047673354,-49.33823976453,70.282773285745,2,1,18 +2025-03-11T12:39:04.015121,479392744,65502,186,-37.10382883156,-49.217855461095,70.064898992545,2,1,18 +2025-03-11T12:39:04.030746,479392744,65502,186,-36.97660492282,-49.083624248115,69.828497909095,2,1,18 +2025-03-11T12:39:04.046371,479392744,65502,186,-36.83524502422,-48.935505360765,69.578157313435,2,1,18 +2025-03-11T12:39:04.061996,479392744,65502,186,-36.69388512562,-48.80124968889,69.327872337775,2,1,18 +2025-03-11T12:39:04.077621,479392744,65502,186,-36.56194922026,-48.657768179295,69.08218502719,2,1,18 +2025-03-11T12:39:04.093246,479392744,65502,186,-36.42058932166,-48.51427036377,68.8226206054,2,1,18 +2025-03-11T12:39:04.108871,479392744,65502,186,-36.27922942306,-48.370772548245,68.549192634415,2,1,18 +2025-03-11T12:39:04.124496,479392744,65502,186,-36.1472935177,-48.241154254125,68.280455028505,2,1,18 +2025-03-11T12:39:04.140121,479392744,65502,186,-36.01535761234,-48.10691488818,68.01632006566,2,1,18 +2025-03-11T12:39:04.155746,479392744,65502,186,-35.85514972726,-47.954142317145,67.761312622915,2,1,18 +2025-03-11T12:39:04.171371,479392744,65502,186,-35.71378982866,-47.81064450162,67.48788465193,2,1,18 +2025-03-11T12:39:04.186996,479392744,65502,186,-35.56771793344,-47.653275317655,67.200530730745,2,1,18 +2025-03-11T12:39:04.202621,479392744,65502,186,-35.40751004836,-47.49126060297,66.91775910961,2,1,18 +2025-03-11T12:39:04.218246,479392744,65502,186,-35.2520141599,-47.333875113075,66.630391626415,2,1,18 +2025-03-11T12:39:04.233871,479392744,65502,186,-35.09180627482,-47.18110254204,66.33841471915,2,1,18 +2025-03-11T12:39:04.249496,479392744,65502,186,-34.92688639312,-47.02832181804,66.041809847815,2,1,18 +2025-03-11T12:39:04.265121,479392744,65502,186,-34.76667850804,-46.857064959705,65.75900114668,2,1,18 +2025-03-11T12:39:04.280746,479392744,65502,186,-34.61118261958,-46.685816254335,65.471578043485,2,1,18 +2025-03-11T12:39:04.296371,479392744,65502,186,-34.4509747345,-46.514559396,65.17952697622,2,1,18 +2025-03-11T12:39:04.311996,479392744,65502,186,-34.29547884604,-46.36179497793,64.882935666895,2,1,18 +2025-03-11T12:39:04.327621,479392744,65502,186,-34.13055896434,-46.19977211028,64.58629371556,2,1,18 +2025-03-11T12:39:04.343246,479392744,65502,186,-33.96563908264,-46.02850709898,64.280372318095,2,1,18 +2025-03-11T12:39:04.358871,479392744,65502,186,-33.79600720432,-45.857233934715,63.96982295656,2,1,18 +2025-03-11T12:39:04.374496,479392744,65502,186,-33.62166332938,-45.69057368931,63.65928535402,2,1,18 +2025-03-11T12:39:04.390121,479392744,65502,186,-33.4614554443,-45.519316830975,63.34412837143,2,1,18 +2025-03-11T12:39:04.405746,479392744,65502,186,-33.29182356598,-45.343422594885,63.02893928683,2,1,18 +2025-03-11T12:39:04.421371,479392744,65502,186,-33.09863170456,-45.172108665795,62.713734837205,2,1,18 +2025-03-11T12:39:04.436996,479392744,65502,186,-32.91015183976,-44.986939674195,62.37537563326,2,1,18 +2025-03-11T12:39:04.452621,479392744,65502,186,-32.74051996144,-44.811045438105,62.046322999465,2,1,18 +2025-03-11T12:39:04.468246,479392744,65502,186,-32.56146408988,-44.625892752435,61.71721972366,2,1,18 +2025-03-11T12:39:04.483871,479392744,65502,186,-32.38240821832,-44.440740066765,61.388116447855,2,1,18 +2025-03-11T12:39:04.499496,479392744,65502,186,-32.20806434338,-44.260216605885,61.068280859185,2,1,18 +2025-03-11T12:39:04.515121,479392744,65502,186,-32.0007364921,-44.093499289725,60.706862775895,2,1,18 +2025-03-11T12:39:04.530746,479392744,65502,186,-31.82168062054,-43.908346604055,60.3500324017,2,1,18 +2025-03-11T12:39:04.546371,479392744,65502,186,-31.6473367456,-43.700096712225,60.01160084077,2,1,18 +2025-03-11T12:39:04.561996,479392744,65502,186,-31.4588568808,-43.51954879245,59.68712372602,2,1,18 +2025-03-11T12:39:04.577621,479392744,65502,186,-31.27508901262,-43.334387953815,59.33952893695,2,1,18 +2025-03-11T12:39:04.593246,479392744,65502,186,-31.07247315796,-43.135331287845,58.99185140386,2,1,18 +2025-03-11T12:39:04.608871,479392744,65502,186,-30.87928129654,-42.945533071455,58.64422451278,2,1,18 +2025-03-11T12:39:04.624496,479392744,65502,186,-30.69080143174,-42.760364079855,58.29200175964,2,1,18 +2025-03-11T12:39:04.640121,479392744,65502,186,-30.48347358046,-42.53357282997,57.925721473285,2,1,18 +2025-03-11T12:39:04.655746,479392744,65502,186,-30.28556972242,-42.32066110149,57.545646819745,2,1,18 +2025-03-11T12:39:04.671371,479392744,65502,186,-30.08766586438,-42.13547580396,57.18878932153,2,1,18 +2025-03-11T12:39:04.686996,479392744,65502,186,-29.9038979962,-41.931830678025,56.827256823265,2,1,18 +2025-03-11T12:39:04.702621,479392744,65502,186,-29.72484212464,-41.71433048958,56.45181193681,2,1,18 +2025-03-11T12:39:04.718246,479392744,65502,186,-29.5033782835,-41.5059990681,56.071721918245,2,1,18 +2025-03-11T12:39:04.733871,479392744,65502,186,-29.2913384356,-41.302305024375,55.69166400169,2,1,18 +2025-03-11T12:39:04.749496,479392744,65502,186,-29.06516259784,-41.09396544993,55.316188385185,2,1,18 +2025-03-11T12:39:04.765121,479392744,65502,186,-28.84841075332,-40.89950539689,54.93153958456,2,1,18 +2025-03-11T12:39:04.780746,479392744,65502,186,-28.6316589088,-40.70504534385,54.546890783935,2,1,18 +2025-03-11T12:39:04.796371,479392744,65502,186,-28.41490706428,-40.478237788035,54.175975752505,2,1,18 +2025-03-11T12:39:04.811996,479392744,65502,186,-28.21229120962,-40.26531790659,53.782030768765,2,1,18 +2025-03-11T12:39:04.827621,479392744,65502,186,-28.01438735158,-40.06164832176,53.392750829095,2,1,18 +2025-03-11T12:39:04.843246,479392744,65502,186,-27.82590748678,-39.83951075556,53.0080314745,2,1,18 +2025-03-11T12:39:04.858871,479392744,65502,186,-27.59973164902,-39.612686893815,52.604754599605,2,1,18 +2025-03-11T12:39:04.874496,479392744,65502,186,-27.35470782478,-39.38583042021,52.206071783755,2,1,18 +2025-03-11T12:39:04.890121,479392744,65502,186,-27.11910799378,-39.168232396185,51.798197243785,2,1,18 +2025-03-11T12:39:04.905746,479392744,65502,186,-26.91649213912,-38.959933586565,51.39964961698,2,1,18 +2025-03-11T12:39:04.921371,479392744,65502,186,-26.69502829798,-38.71925466231,50.98708153696,2,1,18 +2025-03-11T12:39:04.936996,479392744,65502,186,-26.4641404636,-38.497043719425,50.58381642106,2,1,18 +2025-03-11T12:39:04.952621,479392744,65502,186,-26.24738861908,-38.284099379085,50.18522991124,2,1,18 +2025-03-11T12:39:04.968246,479392744,65502,186,-26.02592477794,-38.04342045483,49.76341946509,2,1,18 +2025-03-11T12:39:04.983871,479392744,65502,186,-25.8044609368,-37.8073626024,49.337006375875,2,1,18 +2025-03-11T12:39:04.999496,479392744,65502,186,-25.57828509904,-37.599023027955,48.89683419646,2,1,18 +2025-03-11T12:39:05.015121,479392744,65502,186,-25.3568212579,-37.372207319175,48.461215821115,2,1,18 +2025-03-11T12:39:05.030746,479392744,65502,186,-25.12593342352,-37.12226994534,48.04397591602,2,1,18 +2025-03-11T12:39:05.046371,479392744,65502,186,-24.89033359252,-36.87232441854,47.622108046855,2,1,18 +2025-03-11T12:39:05.061996,479392744,65502,186,-24.66415775476,-36.65936377227,47.19115969357,2,1,18 +2025-03-11T12:39:05.077621,479392744,65502,186,-24.42855792376,-36.432523604595,46.76476334134,2,1,18 +2025-03-11T12:39:05.093246,479392744,65502,186,-24.17411010628,-36.191787609585,46.33828424509,2,1,18 +2025-03-11T12:39:05.108871,479392744,65502,186,-23.9432222719,-35.9695766667,45.89804966467,2,1,18 +2025-03-11T12:39:05.124496,479392744,65502,186,-23.69819844766,-35.733478049445,45.45311793817,2,1,18 +2025-03-11T12:39:05.140121,479392744,65502,186,-23.46259861666,-35.474290378995,45.01734943981,2,1,18 +2025-03-11T12:39:05.155746,479392744,65502,186,-23.20815079918,-35.224312240335,44.59083326356,2,1,18 +2025-03-11T12:39:05.171371,479392744,65502,186,-22.96312697494,-34.974350407605,44.141224733995,2,1,18 +2025-03-11T12:39:05.186996,479392744,65502,186,-22.73223914056,-34.738276249245,43.700934533575,2,1,18 +2025-03-11T12:39:05.202621,479392744,65502,186,-22.48721531632,-34.51141977564,43.256039887075,2,1,18 +2025-03-11T12:39:05.218246,479392744,65502,186,-22.2469034887,-34.25684502405,42.80179841545,2,1,18 +2025-03-11T12:39:05.233871,479392744,65502,186,-22.00659166108,-33.997649200635,42.347538403825,2,1,18 +2025-03-11T12:39:05.249496,479392744,65502,186,-21.76627983346,-33.74769552087,41.88407310607,2,1,18 +2025-03-11T12:39:05.265121,479392744,65502,186,-21.52125600922,-33.50697583179,41.434501656505,2,1,18 +2025-03-11T12:39:05.280746,479392744,65502,186,-21.26209619512,-33.256989540165,40.98949396699,2,1,18 +2025-03-11T12:39:05.296371,479392744,65502,186,-21.01707237088,-33.00240663561,40.530624531295,2,1,18 +2025-03-11T12:39:05.311996,479392744,65502,186,-20.76733655002,-32.74781557809,40.071748314595,2,1,18 +2025-03-11T12:39:05.327621,479392744,65502,186,-20.50817673592,-32.49320821464,39.62672208508,2,1,18 +2025-03-11T12:39:05.343246,479392744,65502,186,-20.25372891844,-32.23398793233,39.16319936431,2,1,18 +2025-03-11T12:39:05.358871,479392744,65502,186,-19.99456910434,-31.96089628158,38.68575069334,2,1,18 +2025-03-11T12:39:05.374496,479392744,65502,186,-19.74012128686,-31.706297071095,38.22224651257,2,1,18 +2025-03-11T12:39:05.390121,479392744,65502,186,-19.490385466,-31.460948157225,37.75416500974,2,1,18 +2025-03-11T12:39:05.405746,479392744,65502,186,-19.23593764852,-31.19710680309,37.286002565905,2,1,18 +2025-03-11T12:39:05.421371,479392744,65502,186,-18.9956258209,-30.928668836025,36.82246310815,2,1,18 +2025-03-11T12:39:05.436996,479392744,65502,186,-18.73175401018,-30.669432247785,36.345063276175,2,1,18 +2025-03-11T12:39:05.452621,479392744,65502,186,-18.46788219946,-30.40557458772,35.853781355005,2,1,18 +2025-03-11T12:39:05.468246,479392744,65502,186,-18.19929839212,-30.13246663104,35.357834389765,2,1,18 +2025-03-11T12:39:05.483871,479392744,65502,186,-17.9354265814,-29.877851114625,34.87121073166,2,1,18 +2025-03-11T12:39:05.499496,479392744,65502,186,-17.66684277406,-29.61860637342,34.398425301745,2,1,18 +2025-03-11T12:39:05.515121,479392744,65502,186,-17.3935469701,-29.35935347925,33.93025427389,2,1,18 +2025-03-11T12:39:05.530746,479392744,65502,186,-17.12967515938,-29.086253675535,33.43893527272,2,1,18 +2025-03-11T12:39:05.546371,479392744,65502,186,-16.86109135204,-28.813145718855,32.93374594135,2,1,18 +2025-03-11T12:39:05.561996,479392744,65502,186,-16.58779554808,-28.54002960921,32.437792195105,2,1,18 +2025-03-11T12:39:05.577621,479392744,65502,186,-16.31921174074,-28.271542724355,31.96496968519,2,1,18 +2025-03-11T12:39:05.593246,479392744,65502,186,-16.06005192664,-28.00307214543,31.45981245583,2,1,18 +2025-03-11T12:39:05.608871,479392744,65502,186,-15.80089211254,-27.725359422855,30.977724061795,2,1,18 +2025-03-11T12:39:05.624496,479392744,65502,186,-15.52288431196,-27.461477303895,30.48642179761,2,1,18 +2025-03-11T12:39:05.640121,479392744,65502,186,-15.25901250124,-27.202240715655,29.990537233375,2,1,18 +2025-03-11T12:39:05.655746,479392744,65502,186,-14.98100470066,-26.929116453045,29.494576706125,2,1,18 +2025-03-11T12:39:05.671371,479392744,65502,186,-14.72184488656,-26.637540514995,28.970842044505,2,1,18 +2025-03-11T12:39:05.686996,479392744,65502,186,-14.4485490826,-26.369045477175,28.456422106,2,1,18 +2025-03-11T12:39:05.702621,479392744,65502,186,-14.16111728878,-26.105147052285,27.946621547545,2,1,18 +2025-03-11T12:39:05.718246,479392744,65502,186,-13.87839749158,-25.82277249306,27.44137479316,2,1,18 +2025-03-11T12:39:05.733871,479392744,65502,186,-13.58625370114,-25.540381627905,26.945356842895,2,1,18 +2025-03-11T12:39:05.749496,479392744,65502,186,-13.3176698938,-25.2626525994,26.430906605395,2,1,18 +2025-03-11T12:39:05.765121,479392744,65502,186,-13.05379808308,-24.97568958021,25.92566843503,2,1,18 +2025-03-11T12:39:05.780746,479392744,65502,186,-12.78521427574,-24.688718408055,25.425044666725,2,1,18 +2025-03-11T12:39:05.796371,479392744,65502,186,-12.49778248192,-24.40171462404,24.91515140827,2,1,18 +2025-03-11T12:39:05.811996,479392744,65502,186,-12.2103506881,-24.123952983675,24.40067404675,2,1,18 +2025-03-11T12:39:05.827621,479392744,65502,186,-11.92291889428,-23.850812415135,23.89545759136,2,1,18 +2025-03-11T12:39:05.843246,479392744,65502,186,-11.65433508694,-23.559220171155,23.39019409999,2,1,18 +2025-03-11T12:39:05.858871,479392744,65502,186,-11.3621912965,-23.26758716235,22.884896703595,2,1,18 +2025-03-11T12:39:05.874496,479392744,65502,186,-11.07475950268,-22.989825521985,22.37504052514,2,1,18 +2025-03-11T12:39:05.890121,479392744,65502,186,-10.79203970548,-22.702829890935,21.8374269493,2,1,18 +2025-03-11T12:39:05.905746,479392744,65502,186,-10.50460791166,-22.42506825057,21.309086038585,2,1,18 +2025-03-11T12:39:05.921371,479392744,65502,186,-10.21717611784,-22.14268553838,20.794590137065,2,1,18 +2025-03-11T12:39:05.936996,479392744,65502,186,-9.9250323274,-21.8556736014,20.28006891454,2,1,18 +2025-03-11T12:39:05.952621,479392744,65502,186,-9.6423125302,-21.58716225765,19.774877780155,2,1,18 +2025-03-11T12:39:05.968246,479392744,65502,186,-9.35488073638,-21.290916329985,19.23722034331,2,1,18 +2025-03-11T12:39:05.983871,479392744,65502,186,-9.06744894256,-20.980807186845,18.71337083566,2,1,18 +2025-03-11T12:39:05.999435,479392748,65498,187,-8.78944114198,-20.679956493285,18.18032960389,2,1,18 +2025-03-11T12:39:06.015060,479392748,65498,187,-8.48316136168,-20.40216224106,17.661203935285,2,1,18 +2025-03-11T12:39:06.030685,479392748,65498,187,-8.19572956786,-20.11977952887,17.137465667635,2,1,18 +2025-03-11T12:39:06.046310,479392748,65498,187,-7.91772176728,-19.83741312261,16.595256229735,2,1,18 +2025-03-11T12:39:06.061935,479392748,65498,187,-7.64913795994,-19.550441950455,16.053041813845,2,1,18 +2025-03-11T12:39:06.077560,479392748,65498,187,-7.34757017626,-19.244929420245,15.543054052375,2,1,18 +2025-03-11T12:39:06.093185,479392748,65498,187,-7.06956237568,-18.953320870335,15.01467108367,2,1,18 +2025-03-11T12:39:06.108810,479392748,65498,187,-6.78213058186,-18.661696014495,14.48165336989,2,1,18 +2025-03-11T12:39:06.124435,479392748,65498,187,-6.49941078466,-18.374700383445,13.94403979405,2,1,18 +2025-03-11T12:39:06.140060,479392748,65498,187,-6.21197899084,-18.07845445578,13.40176117414,2,1,18 +2025-03-11T12:39:06.155685,479392748,65498,187,-5.90569921054,-17.782175916255,12.873318979405,2,1,18 +2025-03-11T12:39:06.171310,479392748,65498,187,-5.59470743362,-17.49975243924,12.354167989795,2,1,18 +2025-03-11T12:39:06.186935,479392748,65498,187,-5.31669963304,-17.20814388933,11.821163838025,2,1,18 +2025-03-11T12:39:06.202560,479392748,65498,187,-5.0245558426,-16.916510880525,11.26965461098,2,1,18 +2025-03-11T12:39:06.218185,479392748,65498,187,-4.72298805892,-16.61561942214,10.727337108055,2,1,18 +2025-03-11T12:39:06.233810,479392748,65498,187,-4.42142027524,-16.305485820105,10.20346725739,2,1,18 +2025-03-11T12:39:06.249435,479392748,65498,187,-4.12456448818,-15.99073929921,9.65185854934,2,1,18 +2025-03-11T12:39:06.265060,479392748,65498,187,-3.83713269436,-15.694493371545,9.123443478625,2,1,18 +2025-03-11T12:39:06.280685,479392748,65498,187,-3.54498890392,-15.398239290915,8.58115807771,2,1,18 +2025-03-11T12:39:06.296310,479392748,65498,187,-3.233997127,-15.1158158139,8.0620070881,2,1,18 +2025-03-11T12:39:06.311935,479392748,65498,187,-2.93242934332,-14.824166499165,7.51510548211,2,1,18 +2025-03-11T12:39:06.327560,479392748,65498,187,-2.6449975495,-14.5279205715,6.968205679135,2,1,18 +2025-03-11T12:39:06.343185,479392748,65498,187,-2.3387177692,-14.231642031975,6.41203638601,2,1,18 +2025-03-11T12:39:06.358810,479392748,65498,187,-2.055997972,-13.926162113625,5.85586391791,2,1,18 +2025-03-11T12:39:06.374435,479392748,65498,187,-1.7732781748,-13.629924338925,5.3274556282,2,1,18 +2025-03-11T12:39:06.390060,479392748,65498,187,-1.47642238774,-13.338283177155,4.78518198628,2,1,18 +2025-03-11T12:39:06.405685,479392748,65498,187,-1.17485460406,-13.04663386242,4.23828038029,2,1,18 +2025-03-11T12:39:06.421310,479392748,65498,187,-0.87328682038,-12.754984547685,3.6913787743,2,1,18 +2025-03-11T12:39:06.436935,479392748,65498,187,-0.5717190367,-12.4540930893,3.1721671867,2,1,18 +2025-03-11T12:39:06.452560,479392748,65498,187,-0.27015125302,-12.162443774565,2.639129129905,2,1,18 +2025-03-11T12:39:06.468185,479392748,65498,187,0.0314165306599999,-11.856931244355,2.082929537785,2,1,18 +2025-03-11T12:39:06.483810,479392748,65498,187,0.3235603211,-11.5375718046,1.526687887675,2,1,18 +2025-03-11T12:39:06.499435,479392748,65498,187,0.62041610816,-11.23668849918,0.965892433495,2,1,18 +2025-03-11T12:39:06.515060,479392748,65498,187,0.91727189522,-10.931184121935,0.414320805445,2,1,18 +2025-03-11T12:39:06.530685,479392748,65498,187,1.21412768228,-10.639542960165,-0.118710470345,2,1,18 +2025-03-11T12:39:06.546310,479392748,65498,187,1.52040746258,-10.34326442064,-0.661016214275,2,1,18 +2025-03-11T12:39:06.561935,479392748,65498,187,1.82197524626,-10.051615105905,-1.207917820265,2,1,18 +2025-03-11T12:39:06.577560,479392748,65498,187,2.12354302994,-9.75072364752,-1.75023532319,2,1,18 +2025-03-11T12:39:06.593185,479392748,65498,187,2.420398817,-9.426734982975,-2.315744660435,2,1,18 +2025-03-11T12:39:06.608810,479392748,65498,187,2.71254260744,-9.121238758695,-2.85806714135,2,1,18 +2025-03-11T12:39:06.624435,479392748,65498,187,3.01882238774,-8.84344450647,-3.40954109141,2,1,18 +2025-03-11T12:39:06.640060,479392748,65498,187,3.32510216804,-8.547165966945,-3.94260446921,2,1,18 +2025-03-11T12:39:06.655685,479392748,65498,187,3.6219579551,-8.25090373335,-4.48489665113,2,1,18 +2025-03-11T12:39:06.671310,479392748,65498,187,3.92352573878,-7.950012274965,-5.03183533712,2,1,18 +2025-03-11T12:39:06.686935,479392748,65498,187,4.22980551908,-7.649112663615,-5.578780804115,2,1,18 +2025-03-11T12:39:06.702560,479392748,65498,187,4.53137330276,-7.362084420705,-6.12104268704,2,1,18 +2025-03-11T12:39:06.718185,479392748,65498,187,4.80938110334,-7.05661265532,-6.667966008005,2,1,18 +2025-03-11T12:39:06.733810,479392748,65498,187,5.11566088364,-6.74647090032,-7.22419092113,2,1,18 +2025-03-11T12:39:06.749435,479392748,65498,187,5.4125166707,-6.4455875949,-7.79422874144,2,1,18 +2025-03-11T12:39:06.765060,479392748,65498,187,5.718796451,-6.1354458399,-8.32734773924,2,1,18 +2025-03-11T12:39:06.780685,479392748,65498,187,6.0250762313,-5.8253040849,-8.86046673704,2,1,18 +2025-03-11T12:39:06.796310,479392748,65498,187,6.33606800822,-5.533638464235,-9.41662427117,2,1,18 +2025-03-11T12:39:06.811935,479392748,65498,187,6.62821179866,-5.23276331178,-9.968170578215,2,1,18 +2025-03-11T12:39:06.827560,479392748,65498,187,6.9203555891,-4.941130302975,-10.515058622195,2,1,18 +2025-03-11T12:39:06.843185,479392748,65498,187,7.22192337278,-4.64948098824,-11.05733904512,2,1,18 +2025-03-11T12:39:06.858810,479392748,65498,187,7.52820315308,-4.343960305065,-11.585818319855,2,1,18 +2025-03-11T12:39:06.874435,479392748,65498,187,7.8156349469,-4.0292300901,-12.128171099765,2,1,18 +2025-03-11T12:39:06.890060,479392748,65498,187,8.11249073396,-3.72834678468,-12.68434537088,2,1,18 +2025-03-11T12:39:06.905685,479392748,65498,187,8.41877051426,-3.43668931698,-13.23587494094,2,1,18 +2025-03-11T12:39:06.921310,479392748,65498,187,8.71562630132,-3.14504815521,-13.78739094899,2,1,18 +2025-03-11T12:39:06.936935,479392748,65498,187,9.00305809514,-2.83493901207,-14.343588738095,2,1,18 +2025-03-11T12:39:06.952560,479392748,65498,187,9.29048988896,-2.54331415623,-14.885848818005,2,1,18 +2025-03-11T12:39:06.968185,479392748,65498,187,9.57792168278,-2.25168930039,-15.409624165655,2,1,18 +2025-03-11T12:39:06.983810,479392748,65498,187,9.87006547322,-1.95543521976,-15.94266720044,2,1,18 +2025-03-11T12:39:06.999435,479392748,65498,187,10.1480732738,-1.668447741675,-16.480273995275,2,1,18 +2025-03-11T12:39:07.015060,479392748,65498,187,10.43550506762,-1.358338598535,-17.02722941825,2,1,18 +2025-03-11T12:39:07.030685,479392748,65498,187,10.74649684454,-1.03894654692,-17.55577109399,2,1,18 +2025-03-11T12:39:07.046310,479392748,65498,187,11.05748862146,-0.738038782605,-18.088859792795,2,1,18 +2025-03-11T12:39:07.061935,479392748,65498,187,11.35905640514,-0.44638946787,-18.635761398785,2,1,18 +2025-03-11T12:39:07.077560,479392748,65498,187,11.6559121922,-0.154748306099999,-19.18265622377,2,1,18 +2025-03-11T12:39:07.093185,479392748,65498,187,11.95747997588,0.127658864985,-19.72952074976,2,1,18 +2025-03-11T12:39:07.108810,479392748,65498,187,12.24019977308,0.414654496035,-20.25789195947,2,1,18 +2025-03-11T12:39:07.124435,479392748,65498,187,12.53234356352,0.710908576665,-20.790934994255,2,1,18 +2025-03-11T12:39:07.140060,479392748,65498,187,12.82448735396,1.007162657295,-21.33322039517,2,1,18 +2025-03-11T12:39:07.155685,479392748,65498,187,13.1166311444,1.303416737925,-21.857021063825,2,1,18 +2025-03-11T12:39:07.171310,479392748,65498,187,13.42762292132,1.590461286765,-22.394675325695,2,1,18 +2025-03-11T12:39:07.186935,479392748,65498,187,13.71505471514,1.87746507078,-22.9507804148,2,1,18 +2025-03-11T12:39:07.202560,479392748,65498,187,14.00248650896,2.182953142095,-23.47461138245,2,1,18 +2025-03-11T12:39:07.218185,479392748,65498,187,14.28520630616,2.479190916795,-23.998398489095,2,1,18 +2025-03-11T12:39:07.233810,479392748,65498,187,14.5773500966,2.766202853775,-24.53140444388,2,1,18 +2025-03-11T12:39:07.249435,479392748,65498,187,14.8600698938,3.053198484825,-25.055154470525,2,1,18 +2025-03-11T12:39:07.265060,479392748,65498,187,15.1663496741,3.354098096175,-25.60209993752,2,1,18 +2025-03-11T12:39:07.280685,479392748,65498,187,15.46320546116,3.65036032977,-26.10742265492,2,1,18 +2025-03-11T12:39:07.296310,479392748,65498,187,15.75063725498,3.937364113785,-26.62193709644,2,1,18 +2025-03-11T12:39:07.311935,479392748,65498,187,16.03335705218,4.21973867301,-27.15953213228,2,1,18 +2025-03-11T12:39:07.327560,479392748,65498,187,16.30665285614,4.511339069955,-27.67866595385,2,1,18 +2025-03-11T12:39:07.343185,479392748,65498,187,16.6035086432,4.802980231725,-28.197833680445,2,1,18 +2025-03-11T12:39:07.358810,479392748,65498,187,16.89094043702,5.085362943915,-28.740056680355,2,1,18 +2025-03-11T12:39:07.374435,479392748,65498,187,17.18779622408,5.377004105685,-29.273087956145,2,1,18 +2025-03-11T12:39:07.390060,479392748,65498,187,17.47994001452,5.664016042665,-29.782987995605,2,1,18 +2025-03-11T12:39:07.405685,479392748,65498,187,17.75323581848,5.932511080485,-30.29740793411,2,1,18 +2025-03-11T12:39:07.421310,479392748,65498,187,18.03124361906,6.22874070222,-30.835051808945,2,1,18 +2025-03-11T12:39:07.436935,479392748,65498,187,18.32809940612,6.525002935815,-31.34499570941,2,1,18 +2025-03-11T12:39:07.452560,479392748,65498,187,18.6061072067,6.7935061266,-31.84093769666,2,1,18 +2025-03-11T12:39:07.468185,479392748,65498,187,18.88411500728,7.071251461035,-32.37388622843,2,1,18 +2025-03-11T12:39:07.483810,479392748,65498,187,19.16683480448,7.358247092085,-32.916120987335,2,1,18 +2025-03-11T12:39:07.499435,479392748,65498,187,19.44484260506,7.640613498345,-33.421360960715,2,1,18 +2025-03-11T12:39:07.515060,479392748,65498,187,19.72756240226,7.918366985745,-33.93583154123,2,1,18 +2025-03-11T12:39:07.530685,479392748,65498,187,20.01028219946,8.205362616795,-34.441096835615,2,1,18 +2025-03-11T12:39:07.546310,479392748,65498,187,20.29300199666,8.492358247845,-34.950983313065,2,1,18 +2025-03-11T12:39:07.561935,479392748,65498,187,20.57100979724,8.765482510455,-35.437701474185,2,1,18 +2025-03-11T12:39:07.577560,479392748,65498,187,20.84901759782,9.038606773065,-35.933662001435,2,1,18 +2025-03-11T12:39:07.593185,479392748,65498,187,21.11288940854,9.316327648605,-36.44810545793,2,1,18 +2025-03-11T12:39:07.608810,479392748,65498,187,21.38147321588,9.60329882076,-36.967213958495,2,1,18 +2025-03-11T12:39:07.624435,479392748,65498,187,21.65005702322,9.871785705615,-37.463142383735,2,1,18 +2025-03-11T12:39:07.640060,479392748,65498,187,21.93277682042,10.158781336665,-37.95916531199,2,1,18 +2025-03-11T12:39:07.655685,479392748,65498,187,22.20136062776,10.431889293345,-38.450491094165,2,1,18 +2025-03-11T12:39:07.671310,479392748,65498,187,22.48408042496,10.718884924395,-38.96499875468,2,1,18 +2025-03-11T12:39:07.686935,479392748,65498,187,22.75737622892,11.005864249515,-39.470250487055,2,1,18 +2025-03-11T12:39:07.702560,479392748,65498,187,23.02596003626,11.278972206195,-39.9523339031,2,1,18 +2025-03-11T12:39:07.718185,479392748,65498,187,23.30396783684,11.52899110968,-40.434338181155,2,1,18 +2025-03-11T12:39:07.733810,479392748,65498,187,23.57255164418,11.79285692271,-40.930248066395,2,1,18 +2025-03-11T12:39:07.749435,479392748,65498,187,23.85055944476,12.06598118532,-41.43082977671,2,1,18 +2025-03-11T12:39:07.765060,479392748,65498,187,24.12385524872,12.329855151315,-41.935988809085,2,1,18 +2025-03-11T12:39:07.780685,479392748,65498,187,24.39243905606,12.58909989252,-42.41801660513,2,1,18 +2025-03-11T12:39:07.796310,479392748,65498,187,24.67515885326,12.86685337992,-42.90013890419,2,1,18 +2025-03-11T12:39:07.811935,479392748,65498,187,24.9201826775,13.13529949995,-43.396033424405,2,1,18 +2025-03-11T12:39:07.827560,479392748,65498,187,25.17463049498,13.41300406956,-43.878115037435,2,1,18 +2025-03-11T12:39:07.843185,479392748,65498,187,25.44321430232,13.68611202624,-44.355577270415,2,1,18 +2025-03-11T12:39:07.858810,479392748,65498,187,25.70237411642,13.954582605165,-44.84687095058,2,1,18 +2025-03-11T12:39:07.874435,479392748,65498,187,25.97566992038,14.204593355685,-45.32886844763,2,1,18 +2025-03-11T12:39:07.890060,479392748,65498,187,26.24425372772,14.459217025065,-45.783150605285,2,1,18 +2025-03-11T12:39:07.905685,479392748,65498,187,26.48927755196,14.70455778597,-46.2789524255,2,1,18 +2025-03-11T12:39:07.921310,479392748,65498,187,26.74843736606,14.973028364895,-46.742519007275,2,1,18 +2025-03-11T12:39:07.936935,479392748,65498,187,27.01230917678,15.23688602496,-47.21993737925,2,1,18 +2025-03-11T12:39:07.952560,479392748,65498,187,27.26675699426,15.48686416362,-47.68342302002,2,1,18 +2025-03-11T12:39:07.968185,479392748,65498,187,27.53062880498,15.74610075186,-48.142338119735,2,1,18 +2025-03-11T12:39:07.983810,479392748,65498,187,27.78507662246,16.009942105995,-48.60125819744,2,1,18 +2025-03-11T12:39:07.999435,479392748,65498,187,28.02538845008,16.26913792941,-49.06938175826,2,1,18 +2025-03-11T12:39:08.015060,479392748,65498,187,28.27983626756,16.51911606807,-49.53286739903,2,1,18 +2025-03-11T12:39:08.030685,479392748,65498,187,28.52957208842,16.759843910115,-49.987066812665,2,1,18 +2025-03-11T12:39:08.046310,479392748,65498,187,28.77459591266,17.000563599195,-50.41815352997,2,1,18 +2025-03-11T12:39:08.061935,479392748,65498,187,29.01019574366,17.25513019782,-50.86314585446,2,1,18 +2025-03-11T12:39:08.077560,479392748,65498,187,29.2552195679,17.50509203055,-51.31737556709,2,1,18 +2025-03-11T12:39:08.093185,479392748,65498,187,29.50966738538,17.75507016921,-51.78086120786,2,1,18 +2025-03-11T12:39:08.108810,479392748,65498,187,29.76882719948,18.01891967631,-52.235166883505,2,1,18 +2025-03-11T12:39:08.124435,479392748,65498,187,30.01856302034,18.278131805655,-52.66171335875,2,1,18 +2025-03-11T12:39:08.140060,479392748,65498,187,30.2682988412,18.523480719525,-53.097446580125,2,1,18 +2025-03-11T12:39:08.155685,479392748,65498,187,30.5038986722,18.764184102675,-53.52851973542,2,1,18 +2025-03-11T12:39:08.171310,479392748,65498,187,30.73478650658,19.00487933286,-53.95958610971,2,1,18 +2025-03-11T12:39:08.186935,479392748,65498,187,30.96096234434,19.23632426643,-54.399850989125,2,1,18 +2025-03-11T12:39:08.202560,479392748,65498,187,31.20127417196,19.47241473072,-54.85401830075,2,1,18 +2025-03-11T12:39:08.218185,479392748,65498,187,31.4462979962,19.699271204325,-55.285049398055,2,1,18 +2025-03-11T12:39:08.233810,479392748,65498,187,31.69603381706,19.94924119002,-55.725422342495,2,1,18 +2025-03-11T12:39:08.249435,479392748,65498,187,31.94576963792,20.189969032065,-56.165758206935,2,1,18 +2025-03-11T12:39:08.265060,479392748,65498,187,32.19550545878,20.416833658635,-56.578311352985,2,1,18 +2025-03-11T12:39:08.280685,479392748,65498,187,32.42168129654,20.64365752038,-57.004694143205,2,1,18 +2025-03-11T12:39:08.296310,479392748,65498,187,32.65256913092,20.87973167874,-57.4218784283,2,1,18 +2025-03-11T12:39:08.311935,479392748,65498,187,32.87403297206,21.111168459345,-57.839030611385,2,1,18 +2025-03-11T12:39:08.327560,479392748,65498,187,33.08607281996,21.34258893402,-58.260790415525,2,1,18 +2025-03-11T12:39:08.343185,479392748,65498,187,33.30282466448,21.55553327436,-58.67324047454,2,1,18 +2025-03-11T12:39:08.358810,479392748,65498,187,33.52900050224,21.791599279755,-59.113523893955,2,1,18 +2025-03-11T12:39:08.374435,479392748,65498,187,33.76460033324,22.013818375605,-59.50755342473,2,1,18 +2025-03-11T12:39:08.390060,479392748,65498,187,33.99548816762,22.222166103015,-59.91076292063,2,1,18 +2025-03-11T12:39:08.405685,479392748,65498,187,34.22166400538,22.45823210841,-60.31869805859,2,1,18 +2025-03-11T12:39:08.421310,479392748,65498,187,34.43370385328,22.698894726735,-60.72201021047,2,1,18 +2025-03-11T12:39:08.436935,479392748,65498,187,34.6504556978,22.921081210725,-61.12063380029,2,1,18 +2025-03-11T12:39:08.452560,479392748,65498,187,34.8860555288,23.143300306575,-61.514663331065,2,1,18 +2025-03-11T12:39:08.468185,479392748,65498,187,35.09338338008,23.37009155646,-61.894807166615,2,1,18 +2025-03-11T12:39:08.483810,479392748,65498,187,35.29599923474,23.57839036608,-62.297975976485,2,1,18 +2025-03-11T12:39:08.499435,479392748,65498,187,35.50803908264,23.782084409805,-62.70576099143,2,1,18 +2025-03-11T12:39:08.515060,479392748,65498,187,35.71536693392,23.98114922874,-63.099657136175,2,1,18 +2025-03-11T12:39:08.530685,479392748,65498,187,35.93211877844,24.198714640905,-63.47515627067,2,1,18 +2025-03-11T12:39:08.546310,479392748,65498,187,36.14415862634,24.425514043755,-63.84144333803,2,1,18 +2025-03-11T12:39:08.561935,479392748,65498,187,36.346774481,24.62919178155,-64.2445936079,2,1,18 +2025-03-11T12:39:08.577560,479392748,65498,187,36.56352632552,24.83289397824,-64.638521854655,2,1,18 +2025-03-11T12:39:08.593185,479392748,65498,187,36.76614218018,25.04119278786,-65.013963566135,2,1,18 +2025-03-11T12:39:08.608810,479392748,65498,187,36.97347003146,25.240257606795,-65.38013261249,2,1,18 +2025-03-11T12:39:08.624435,479392748,65498,187,37.18079788274,25.43932242573,-65.737059292715,2,1,18 +2025-03-11T12:39:08.640060,479392748,65498,187,37.38812573402,25.64300831649,-66.10324687907,2,1,18 +2025-03-11T12:39:08.655685,479392748,65498,187,37.60016558192,25.837460216565,-66.474025349495,2,1,18 +2025-03-11T12:39:08.671310,479392748,65498,187,37.80278143658,26.045759026185,-66.82636114565,2,1,18 +2025-03-11T12:39:08.686935,479392748,65498,187,38.00068529462,26.26329182649,-67.174106057735,2,1,18 +2025-03-11T12:39:08.702560,479392748,65498,187,38.18916515942,26.44846081809,-67.544813543135,2,1,18 +2025-03-11T12:39:08.718185,479392748,65498,187,38.37764502422,26.629008737865,-67.91088130547,2,1,18 +2025-03-11T12:39:08.733810,479392748,65498,187,38.57083688564,26.82342802608,-68.25852673655,2,1,18 +2025-03-11T12:39:08.749435,479392748,65498,187,38.76402874706,27.027089457945,-68.61545161376,2,1,18 +2025-03-11T12:39:08.765060,479392748,65498,187,38.94779661524,27.226113512055,-68.939996107505,2,1,18 +2025-03-11T12:39:08.780685,479392748,65498,187,39.12214049018,27.415879116585,-69.26448995924,2,1,18 +2025-03-11T12:39:08.796310,479392748,65498,187,39.31062035498,27.601048108185,-69.61671271238,2,1,18 +2025-03-11T12:39:08.811935,479392748,65498,187,39.51323620964,27.790862630505,-69.950489616275,2,1,18 +2025-03-11T12:39:08.827560,479392748,65498,187,39.6922920812,27.976015316175,-70.28883525821,2,1,18 +2025-03-11T12:39:08.843185,479392748,65498,187,39.87605994938,28.16117615481,-70.641051230345,2,1,18 +2025-03-11T12:39:08.858810,479392748,65498,187,40.0692518108,28.34173222755,-70.979398675295,2,1,18 +2025-03-11T12:39:08.874435,479392748,65498,187,40.25301967898,28.52227199436,-71.299247825975,2,1,18 +2025-03-11T12:39:08.890060,479392748,65498,187,40.43678754716,28.698190689345,-71.609836070525,2,1,18 +2025-03-11T12:39:08.905685,479392748,65498,187,40.62526741196,28.86949646547,-71.934276105275,2,1,18 +2025-03-11T12:39:08.921310,479392748,65498,187,40.7996112869,29.026914567225,-72.24939781088,2,1,18 +2025-03-11T12:39:08.936935,479392748,65498,187,40.95981917198,29.19817142556,-72.55531242734,2,1,18 +2025-03-11T12:39:08.952560,479392748,65498,187,41.11531506044,29.37866227458,-72.86587852586,2,1,18 +2025-03-11T12:39:08.968185,479392748,65498,187,41.28494693876,29.549935438845,-73.17180670433,2,1,18 +2025-03-11T12:39:08.983810,479392748,65498,187,41.44986682046,29.71657937832,-73.49157311099,2,1,18 +2025-03-11T12:39:08.999435,479392748,65498,187,41.61949869878,29.897094686235,-73.811401918655,2,1,18 +2025-03-11T12:39:09.015060,479392748,65498,187,41.77499458724,30.059101247955,-74.11727267411,2,1,18 +2025-03-11T12:39:09.030685,479392748,65498,187,41.94462646556,30.207269053095,-74.40462342032,2,1,18 +2025-03-11T12:39:09.046310,479392748,65498,187,42.1189703405,30.369308226675,-74.701278933665,2,1,18 +2025-03-11T12:39:09.061935,479392748,65498,187,42.27917822558,30.517459725885,-75.00247966706,2,1,18 +2025-03-11T12:39:09.077560,479392748,65498,187,42.43467411404,30.688708431255,-75.30376631945,2,1,18 +2025-03-11T12:39:09.093185,479392748,65498,187,42.5901700025,30.84609392115,-75.581891436515,2,1,18 +2025-03-11T12:39:09.108810,479392748,65498,187,42.7550898842,31.003495716975,-75.85078774946,2,1,18 +2025-03-11T12:39:09.124435,479392748,65498,187,42.91058577266,31.15163906322,-76.128875786525,2,1,18 +2025-03-11T12:39:09.140060,479392748,65498,187,43.0613696645,31.30901640015,-76.41161530565,2,1,18 +2025-03-11T12:39:09.155685,479392748,65498,187,43.22157754958,31.461788971185,-76.68972866372,2,1,18 +2025-03-11T12:39:09.171310,479392748,65498,187,43.3676494448,31.6099160115,-76.949318406515,2,1,18 +2025-03-11T12:39:09.186935,479392748,65498,187,43.50429734678,31.76264781771,-77.213534310365,2,1,18 +2025-03-11T12:39:09.202560,479392748,65498,187,43.650369242,31.929259145325,-77.468577030095,2,1,18 +2025-03-11T12:39:09.218185,479392748,65498,187,43.78230514736,32.06349851127,-77.737333176005,2,1,18 +2025-03-11T12:39:09.233810,479392748,65498,187,43.92837704258,32.19776233611,-77.992246115735,2,1,18 +2025-03-11T12:39:09.249435,479392748,65498,187,44.06502494456,32.34125199867,-78.237940207325,2,1,18 +2025-03-11T12:39:09.265060,479392748,65498,187,44.20638484316,32.46164445507,-78.497411929115,2,1,18 +2025-03-11T12:39:09.280685,479392748,65498,187,44.33832074852,32.595883821015,-78.729198610505,2,1,18 +2025-03-11T12:39:09.296310,479392748,65498,187,44.46083266064,32.72086473738,-78.95631346682,2,1,18 +2025-03-11T12:39:09.311935,479392748,65498,187,44.60219255924,32.84125719378,-79.201921639415,2,1,18 +2025-03-11T12:39:09.327560,479392748,65498,187,44.73884046122,32.99398899999,-79.4615163602,2,1,18 +2025-03-11T12:39:09.343185,479392748,65498,187,44.86606436996,33.13746235662,-79.702575706715,2,1,18 +2025-03-11T12:39:09.358810,479392748,65498,187,44.99800027532,33.25783850709,-79.934306768105,2,1,18 +2025-03-11T12:39:09.374435,479392748,65498,187,45.12051218744,33.36895620798,-80.156744821355,2,1,18 +2025-03-11T12:39:09.390060,479392748,65498,187,45.2524480928,33.4800902148,-80.37457525355,2,1,18 +2025-03-11T12:39:09.405685,479392748,65498,187,45.38438399816,33.61895065257,-80.61562284107,2,1,18 +2025-03-11T12:39:09.421310,479392748,65498,187,45.52103190014,33.739334956005,-80.847360683465,2,1,18 +2025-03-11T12:39:09.436935,479392748,65498,187,45.62469582578,33.85504111686,-81.042063054305,2,1,18 +2025-03-11T12:39:09.452560,479392748,65498,187,45.7236477548,33.9614969811,-81.232100381075,2,1,18 +2025-03-11T12:39:09.468185,479392748,65498,187,45.8414476703,34.081848672675,-81.440705184125,2,1,18 +2025-03-11T12:39:09.483810,479392748,65498,187,45.94982359256,34.206805130145,-81.65393614823,2,1,18 +2025-03-11T12:39:09.499435,479392748,65498,187,46.04877552158,34.313260994385,-81.86245820726,2,1,18 +2025-03-11T12:39:09.515060,479392748,65498,187,46.15243944722,34.41048286794,-82.061707601165,2,1,18 +2025-03-11T12:39:09.530685,479392748,65498,187,46.25610337286,34.52156795697,-82.26101261507,2,1,18 +2025-03-11T12:39:09.546310,479392748,65498,187,46.36447929512,34.63728227079,-82.42337348546,2,1,18 +2025-03-11T12:39:09.561935,479392748,65498,187,46.477567214,34.7391415221,-82.604170249115,2,1,18 +2025-03-11T12:39:09.577560,479392748,65498,187,46.58123113964,34.85022661113,-82.808096446085,2,1,18 +2025-03-11T12:39:09.593185,479392748,65498,187,46.68018306866,34.952061403545,-82.98425168366,2,1,18 +2025-03-11T12:39:09.608810,479392748,65498,187,46.77442300106,35.035403755695,-83.16032598023,2,1,18 +2025-03-11T12:39:09.624435,479392748,65498,187,46.86866293346,35.13260932332,-83.35494062906,2,1,18 +2025-03-11T12:39:09.640060,479392748,65498,187,46.97703885572,35.22059720619,-83.531053808645,2,1,18 +2025-03-11T12:39:09.655685,479392748,65498,187,47.0665667915,35.313173549025,-83.69791603808,2,1,18 +2025-03-11T12:39:09.671310,479392748,65498,187,47.14667073404,35.391870370455,-83.86008790244,2,1,18 +2025-03-11T12:39:09.686935,479392748,65498,187,47.23619866982,35.479825641465,-84.02231040881,2,1,18 +2025-03-11T12:39:09.702560,479392748,65498,187,47.34457459208,35.567813524335,-84.16607530694,2,1,18 +2025-03-11T12:39:09.718185,479392748,65498,187,47.42939053124,35.63727635508,-84.318974506175,2,1,18 +2025-03-11T12:39:09.733810,479392748,65498,187,47.50007048054,35.729820086055,-84.47656724546,2,1,18 +2025-03-11T12:39:09.749435,479392748,65498,187,47.5848864197,35.8177672041,-84.6156770555,2,1,18 +2025-03-11T12:39:09.765060,479392748,65498,187,47.655566369,35.891826647775,-84.754710902525,2,1,18 +2025-03-11T12:39:09.780685,479392748,65498,187,47.73567031154,35.970523469205,-84.90301921769,2,1,18 +2025-03-11T12:39:09.796310,479392748,65498,187,47.81106225746,36.03996999402,-85.046662488785,2,1,18 +2025-03-11T12:39:09.811935,479392748,65498,187,47.87703021014,36.10477914108,-85.17178892561,2,1,18 +2025-03-11T12:39:09.827560,479392748,65498,187,47.94299816282,36.17883043179,-85.306194808565,2,1,18 +2025-03-11T12:39:09.843185,479392748,65498,187,48.01367811212,36.26675309094,-85.412935994135,2,1,18 +2025-03-11T12:39:09.858810,479392748,65498,187,48.08435806142,36.340812534615,-85.528863925835,2,1,18 +2025-03-11T12:39:09.874435,479392748,65498,187,48.15503801072,36.410250906465,-85.6493945006,2,1,18 +2025-03-11T12:39:09.890060,479392748,65498,187,48.21629396678,36.461188685085,-85.751352621095,2,1,18 +2025-03-11T12:39:09.905685,479392748,65498,187,48.28226191946,36.51213461667,-85.87642343792,2,1,18 +2025-03-11T12:39:09.921310,479392748,65498,187,48.3388058789,36.572306385975,-86.010760138865,2,1,18 +2025-03-11T12:39:09.936935,479392748,65498,187,48.40477383158,36.627873389385,-86.112743580365,2,1,18 +2025-03-11T12:39:09.952560,479392748,65498,187,48.46602978764,36.688053311655,-86.1962540486,2,1,18 +2025-03-11T12:39:09.968185,479392748,65498,187,48.50843775722,36.757442765715,-86.29363802201,2,1,18 +2025-03-11T12:39:09.983810,479392748,65498,187,48.55555772342,36.80835608544,-86.38633343336,2,1,18 +2025-03-11T12:39:09.999359,479392752,65493,188,48.60738968624,36.854656486305,-86.479017085715,2,1,18 +2025-03-11T12:39:10.014984,479392752,65493,188,48.67335763892,36.900981346065,-86.54861516576,2,1,18 +2025-03-11T12:39:10.030609,479392752,65493,188,48.7157656085,36.93802329735,-86.650490542235,2,1,18 +2025-03-11T12:39:10.046234,479392752,65493,188,48.74874958484,36.965806799055,-86.729209361375,2,1,18 +2025-03-11T12:39:10.061859,479392752,65493,188,48.7864455578,37.01670381285,-86.803406478455,2,1,18 +2025-03-11T12:39:10.077484,479392752,65493,188,48.81942953414,37.053729458205,-86.85905646227,2,1,18 +2025-03-11T12:39:10.093109,479392752,65493,188,48.8571255071,37.100005400175,-86.91475030709,2,1,18 +2025-03-11T12:39:10.108734,479392752,65493,188,48.88539748682,37.137022892565,-86.97963587603,2,1,18 +2025-03-11T12:39:10.124359,479392752,65493,188,48.93722944964,37.17408114978,-87.05841889919,2,1,18 +2025-03-11T12:39:10.139984,479392752,65493,188,48.98434941584,37.19264696673,-87.13249979828,2,1,18 +2025-03-11T12:39:10.155609,479392752,65493,188,49.01262139556,37.225043387295,-87.201988010285,2,1,18 +2025-03-11T12:39:10.171234,479392752,65493,188,49.03618137866,37.27129487037,-87.262282695155,2,1,18 +2025-03-11T12:39:10.186859,479392752,65493,188,49.06445335838,37.29907021911,-87.308646451835,2,1,18 +2025-03-11T12:39:10.202484,479392752,65493,188,49.0927253381,37.30836128055,-87.33183013319,2,1,18 +2025-03-11T12:39:10.218109,479392752,65493,188,49.12099731782,37.33613662929,-87.37819388987,2,1,18 +2025-03-11T12:39:10.233734,479392752,65493,188,49.14455730092,37.363903825065,-87.424550865545,2,1,18 +2025-03-11T12:39:10.249359,479392752,65493,188,49.14926929754,37.387017337155,-87.44313507881,2,1,18 +2025-03-11T12:39:10.264984,479392752,65493,188,49.1634052874,37.410147155175,-87.470975220215,2,1,18 +2025-03-11T12:39:10.280609,479392752,65493,188,49.17282928064,37.39630024563,-87.50328144368,2,1,18 +2025-03-11T12:39:10.296234,479392752,65493,188,49.19167726712,37.39633285749,-87.535656849155,2,1,18 +2025-03-11T12:39:10.311859,479392752,65493,188,49.20110126036,37.410212378895,-87.554210763425,2,1,18 +2025-03-11T12:39:10.327484,479392752,65493,188,49.20581325698,37.43794696281,-87.568192333625,2,1,18 +2025-03-11T12:39:10.343109,479392752,65493,188,49.2340852367,37.433374808775,-87.586699211915,2,1,18 +2025-03-11T12:39:10.358734,479392752,65493,188,49.23879723332,37.447246177215,-87.591382795985,2,1,18 +2025-03-11T12:39:10.374359,479392752,65493,188,49.23879723332,37.456488320865,-87.58679869292,2,1,18 +2025-03-11T12:39:10.389984,479392752,65493,188,49.23879723332,37.474972608165,-87.58687285292,2,1,18 +2025-03-11T12:39:10.405609,479392752,65493,188,49.2340852367,37.4749644552,-87.58224488885,2,1,18 +2025-03-11T12:39:10.421234,479392752,65493,188,49.22937324008,37.47033523041,-87.56835601865,2,1,18 +2025-03-11T12:39:10.436859,479392752,65493,188,49.21994924684,37.465697852655,-87.563702733575,2,1,18 +2025-03-11T12:39:10.452484,479392752,65493,188,49.2105252536,37.45181833125,-87.554391185435,2,1,18 +2025-03-11T12:39:10.468109,479392752,65493,188,49.19638926374,37.43793065688,-87.531209307095,2,1,18 +2025-03-11T12:39:10.483734,479392752,65493,188,49.18225327388,37.428664054335,-87.526530701015,2,1,18 +2025-03-11T12:39:10.499359,479392752,65493,188,49.18225327388,37.40555869521,-87.51257445182,2,1,18 +2025-03-11T12:39:10.514984,479392752,65493,188,49.18225327388,37.391695479735,-87.489412916495,2,1,18 +2025-03-11T12:39:10.530609,479392752,65493,188,49.16811728402,37.37318673354,-87.45234894896,2,1,18 +2025-03-11T12:39:10.546234,479392752,65493,188,49.14926929754,37.36391197803,-87.410694097355,2,1,18 +2025-03-11T12:39:10.561859,479392752,65493,188,49.12099731782,37.340757701115,-87.387454796,2,1,18 +2025-03-11T12:39:10.577484,479392752,65493,188,49.0927253381,37.322224496025,-87.34112811932,2,1,18 +2025-03-11T12:39:10.593109,479392752,65493,188,49.06445335838,37.294449147285,-87.28552199651,2,1,18 +2025-03-11T12:39:10.608734,479392752,65493,188,49.03618137866,37.26205272672,-87.22065496757,2,1,18 +2025-03-11T12:39:10.624359,479392752,65493,188,49.01733339218,37.229672612085,-87.169665049835,2,1,18 +2025-03-11T12:39:10.639984,479392752,65493,188,48.99377340908,37.197284344485,-87.127910717225,2,1,18 +2025-03-11T12:39:10.655609,479392752,65493,188,48.96550142936,37.17413006757,-87.07694431748,2,1,18 +2025-03-11T12:39:10.671234,479392752,65493,188,48.9278054564,37.1463384129,-87.0028399004,2,1,18 +2025-03-11T12:39:10.686859,479392752,65493,188,48.89482148006,37.100070623895,-86.94253165352,2,1,18 +2025-03-11T12:39:10.702484,479392752,65493,188,48.85241351048,37.07227081626,-86.88228400463,2,1,18 +2025-03-11T12:39:10.718109,479392752,65493,188,48.8100055409,37.0398499368,-86.78504835122,2,1,18 +2025-03-11T12:39:10.733734,479392752,65493,188,48.76759757132,36.993565841865,-86.69699944394,2,1,18 +2025-03-11T12:39:10.749359,479392752,65493,188,48.72518960174,36.92879745963,-86.60887637666,2,1,18 +2025-03-11T12:39:10.764984,479392752,65493,188,48.6686456423,36.8824889058,-86.539291858625,2,1,18 +2025-03-11T12:39:10.780609,479392752,65493,188,48.61681367948,36.854672792235,-86.460545915465,2,1,18 +2025-03-11T12:39:10.796234,479392752,65493,188,48.5744057099,36.8083886973,-86.372497008185,2,1,18 +2025-03-11T12:39:10.811859,479392752,65493,188,48.54142173356,36.73901554917,-86.312096061305,2,1,18 +2025-03-11T12:39:10.827484,479392752,65493,188,48.48958977074,36.66036764553,-86.233146178145,2,1,18 +2025-03-11T12:39:10.843109,479392752,65493,188,48.4330458113,36.60481694805,-86.121933932525,2,1,18 +2025-03-11T12:39:10.858734,479392752,65493,188,48.38121384848,36.549274403535,-86.01997083404,2,1,18 +2025-03-11T12:39:10.874359,479392752,65493,188,48.31053389918,36.49369924716,-85.91335942847,2,1,18 +2025-03-11T12:39:10.889984,479392752,65493,188,48.23985394988,36.44274516261,-85.802145379835,2,1,18 +2025-03-11T12:39:10.905609,479392752,65493,188,48.19273398368,36.38721077106,-85.681704330095,2,1,18 +2025-03-11T12:39:10.921234,479392752,65493,188,48.126766031,36.3039173367,-85.55650373327,2,1,18 +2025-03-11T12:39:10.936859,479392752,65493,188,48.06079807832,36.23910818964,-85.43599847951,2,1,18 +2025-03-11T12:39:10.952484,479392752,65493,188,47.99483012564,36.17429904258,-85.292387310425,2,1,18 +2025-03-11T12:39:10.968109,479392752,65493,188,47.92886217296,36.104868823695,-85.13951523521,2,1,18 +2025-03-11T12:39:10.983734,479392752,65493,188,47.84875823042,36.026172002265,-85.000449286175,2,1,18 +2025-03-11T12:39:10.999359,479392752,65493,188,47.77807828112,35.95211255859,-84.893763720605,2,1,18 +2025-03-11T12:39:11.014984,479392752,65493,188,47.71682232506,35.87344834902,-84.76396726172,2,1,18 +2025-03-11T12:39:11.030609,479392752,65493,188,47.6320063859,35.8086065901,-84.61570778555,2,1,18 +2025-03-11T12:39:11.046234,479392752,65493,188,47.5377664535,35.7160220943,-84.481187056565,2,1,18 +2025-03-11T12:39:11.061859,479392752,65493,188,47.45295051434,35.628074976255,-84.33745606346,2,1,18 +2025-03-11T12:39:11.077484,479392752,65493,188,47.3728465718,35.544757083,-84.18450802523,2,1,18 +2025-03-11T12:39:11.093109,479392752,65493,188,47.29745462588,35.447584127235,-84.02688996494,2,1,18 +2025-03-11T12:39:11.108734,479392752,65493,188,47.20321469348,35.373483918735,-83.84161038224,2,1,18 +2025-03-11T12:39:11.124359,479392752,65493,188,47.09483877122,35.29011710769,-83.674758108785,2,1,18 +2025-03-11T12:39:11.139984,479392752,65493,188,47.00059883882,35.202153683715,-83.517150004475,2,1,18 +2025-03-11T12:39:11.155609,479392752,65493,188,46.91107090304,35.114198412705,-83.345685131975,2,1,18 +2025-03-11T12:39:11.171234,479392752,65493,188,46.81683097064,35.012371773255,-83.160294309275,2,1,18 +2025-03-11T12:39:11.186859,479392752,65493,188,46.713167045,34.901286684225,-82.99795875989,2,1,18 +2025-03-11T12:39:11.202484,479392752,65493,188,46.60479112274,34.79943558588,-82.812547594175,2,1,18 +2025-03-11T12:39:11.218109,479392752,65493,188,46.51055119034,34.69760894643,-82.627156771475,2,1,18 +2025-03-11T12:39:11.233734,479392752,65493,188,46.41159926132,34.605016297665,-82.44179624777,2,1,18 +2025-03-11T12:39:11.249359,479392752,65493,188,46.31735932892,34.50781073004,-82.261045148135,2,1,18 +2025-03-11T12:39:11.264984,479392752,65493,188,46.21369540328,34.392104569185,-82.047858045035,2,1,18 +2025-03-11T12:39:11.280609,479392752,65493,188,46.11003147764,34.25791412103,-81.84846033113,2,1,18 +2025-03-11T12:39:11.296234,479392752,65493,188,46.00165555538,34.156063022685,-81.635322067025,2,1,18 +2025-03-11T12:39:11.311859,479392752,65493,188,45.8885676365,34.063445915025,-81.431456468045,2,1,18 +2025-03-11T12:39:11.327484,479392752,65493,188,45.75663173114,33.96617512368,-81.23216638811,2,1,18 +2025-03-11T12:39:11.343109,479392752,65493,188,45.63411981902,33.83657313549,-80.995790625665,2,1,18 +2025-03-11T12:39:11.358734,479392752,65493,188,45.52103190014,33.70698745323,-80.78715552362,2,1,18 +2025-03-11T12:39:11.374359,479392752,65493,188,45.40794398126,33.572780699145,-80.58312306464,2,1,18 +2025-03-11T12:39:11.389984,479392752,65493,188,45.29014406576,33.438565792095,-80.35597790933,2,1,18 +2025-03-11T12:39:11.405609,479392752,65493,188,45.17234415026,33.31821410052,-80.133509557085,2,1,18 +2025-03-11T12:39:11.421234,479392752,65493,188,45.0404082449,33.19783795005,-79.901778495695,2,1,18 +2025-03-11T12:39:11.436859,479392752,65493,188,44.91318433616,33.07284888072,-79.665414492245,2,1,18 +2025-03-11T12:39:11.452484,479392752,65493,188,44.79067242404,32.947867964355,-79.433678452865,2,1,18 +2025-03-11T12:39:11.468109,479392752,65493,188,44.6634485153,32.832121038675,-79.20197271248,2,1,18 +2025-03-11T12:39:11.483734,479392752,65493,188,44.52680061332,32.69325244794,-78.94705479476,2,1,18 +2025-03-11T12:39:11.499359,479392752,65493,188,44.4042887012,32.559029387925,-78.68755457699,2,1,18 +2025-03-11T12:39:11.514984,479392752,65493,188,44.2629288026,32.40628942875,-78.43719544133,2,1,18 +2025-03-11T12:39:11.530609,479392752,65493,188,44.11214491076,32.25815423547,-78.191462466725,2,1,18 +2025-03-11T12:39:11.546234,479392752,65493,188,43.96607301554,32.12389041063,-77.945791893125,2,1,18 +2025-03-11T12:39:11.561859,479392752,65493,188,43.82471311694,31.998876882405,-77.714028729725,2,1,18 +2025-03-11T12:39:11.577484,479392752,65493,188,43.68806521496,31.84152400437,-77.46365783507,2,1,18 +2025-03-11T12:39:11.593109,479392752,65493,188,43.54670531636,31.70264726067,-77.18562722102,2,1,18 +2025-03-11T12:39:11.608734,479392752,65493,188,43.41948140762,31.554552832215,-76.92144341918,2,1,18 +2025-03-11T12:39:11.624359,479392752,65493,188,43.27812150902,31.40181287304,-76.657220734325,2,1,18 +2025-03-11T12:39:11.639984,479392752,65493,188,43.11791362394,31.26290351748,-76.40226891158,2,1,18 +2025-03-11T12:39:11.655609,479392752,65493,188,42.96241773548,31.11938124306,-76.124199414515,2,1,18 +2025-03-11T12:39:11.671234,479392752,65493,188,42.81163384364,30.96200390613,-75.846081078455,2,1,18 +2025-03-11T12:39:11.686859,479392752,65493,188,42.6608499518,30.79538442555,-75.567925662395,2,1,18 +2025-03-11T12:39:11.702484,479392752,65493,188,42.50535406334,30.63337786383,-75.26205490694,2,1,18 +2025-03-11T12:39:11.718109,479392752,65493,188,42.34514617826,30.47598422097,-74.95619591048,2,1,18 +2025-03-11T12:39:11.733734,479392752,65493,188,42.18022629656,30.318582425145,-74.67343604834,2,1,18 +2025-03-11T12:39:11.749359,479392752,65493,188,42.01530641486,30.16118062932,-74.386055003135,2,1,18 +2025-03-11T12:39:11.764984,479392752,65493,188,41.84567453654,29.99452853688,-74.080145364665,2,1,18 +2025-03-11T12:39:11.780609,479392752,65493,188,41.67604265822,29.82787644444,-73.764993360065,2,1,18 +2025-03-11T12:39:11.796234,479392752,65493,188,41.52054676976,29.67511202637,-73.463780867675,2,1,18 +2025-03-11T12:39:11.811859,479392752,65493,188,41.36976287792,29.494629330315,-73.17170628242,2,1,18 +2025-03-11T12:39:11.827484,479392752,65493,188,41.2001309996,29.309492950575,-72.86572248395,2,1,18 +2025-03-11T12:39:11.843109,479392752,65493,188,41.03049912128,29.124356570835,-72.54125395322,2,1,18 +2025-03-11T12:39:11.858734,479392752,65493,188,40.86086724296,28.95308340657,-72.19835631023,2,1,18 +2025-03-11T12:39:11.874359,479392752,65493,188,40.70065935788,28.78644762006,-71.887839050705,2,1,18 +2025-03-11T12:39:11.889984,479392752,65493,188,40.52631548294,28.610545231005,-71.568022002035,2,1,18 +2025-03-11T12:39:11.905609,479392752,65493,188,40.33312362152,28.43461023009,-71.229693097085,2,1,18 +2025-03-11T12:39:11.921234,479392752,65493,188,40.14464375672,28.263304453965,-70.914495428465,2,1,18 +2025-03-11T12:39:11.936859,479392752,65493,188,39.95616389192,28.07351439054,-70.59460241678,2,1,18 +2025-03-11T12:39:11.952484,479392752,65493,188,39.76768402712,27.87910325529,-70.265448498965,2,1,18 +2025-03-11T12:39:11.968109,479392752,65493,188,39.5980521488,27.670861516425,-69.92702371904,2,1,18 +2025-03-11T12:39:11.983734,479392752,65493,188,39.409572284,27.49031359665,-69.58406187203,2,1,18 +2025-03-11T12:39:11.999359,479392752,65493,188,39.21638042258,27.323620739385,-69.25501241321,2,1,18 +2025-03-11T12:39:12.014984,479392752,65493,188,39.02318856116,27.143064666645,-68.902801419065,2,1,18 +2025-03-11T12:39:12.030609,479392752,65493,188,38.83942069298,26.93941954071,-68.545890103865,2,1,18 +2025-03-11T12:39:12.046234,479392752,65493,188,38.64151683494,26.74499209953,-68.202859074845,2,1,18 +2025-03-11T12:39:12.061859,479392752,65493,188,38.45303697014,26.54133882063,-67.85518334477,2,1,18 +2025-03-11T12:39:12.077484,479392752,65493,188,38.2551331121,26.3561535231,-67.49370466349,2,1,18 +2025-03-11T12:39:12.093109,479392752,65493,188,38.06194125068,26.17559745036,-67.113766570955,2,1,18 +2025-03-11T12:39:12.108734,479392752,65493,188,37.87346138588,25.985807386935,-66.74766172862,2,1,18 +2025-03-11T12:39:12.124359,479392752,65493,188,37.68498152108,25.782154108035,-66.390743632415,2,1,18 +2025-03-11T12:39:12.139984,479392752,65493,188,37.48707766304,25.560000235905,-66.0337378142,2,1,18 +2025-03-11T12:39:12.155609,479392752,65493,188,37.28446180838,25.360943569935,-65.672196731915,2,1,18 +2025-03-11T12:39:12.171234,479392752,65493,188,37.07242196048,25.161870598035,-65.306020904555,2,1,18 +2025-03-11T12:39:12.186859,479392752,65493,188,36.86980610582,24.94895071659,-64.92593947001,2,1,18 +2025-03-11T12:39:12.202484,479392752,65493,188,36.67190224778,24.72679684446,-64.541206553405,2,1,18 +2025-03-11T12:39:12.218109,479392752,65493,188,36.45515040326,24.518473575945,-64.15650213278,2,1,18 +2025-03-11T12:39:12.233734,479392752,65493,188,36.24782255198,24.32865090066,-63.771885434165,2,1,18 +2025-03-11T12:39:12.249359,479392752,65493,188,36.0404947007,24.138828225375,-63.37802636942,2,1,18 +2025-03-11T12:39:12.264984,479392752,65493,188,35.84259084266,23.93053756872,-62.993349072815,2,1,18 +2025-03-11T12:39:12.280609,479392752,65493,188,35.63055099476,23.71298030952,-62.62247790239,2,1,18 +2025-03-11T12:39:12.296234,479392752,65493,188,35.41379915024,23.476930610055,-62.24228342483,2,1,18 +2025-03-11T12:39:12.311859,479392752,65493,188,35.19704730572,23.25012305424,-61.85288366114,2,1,18 +2025-03-11T12:39:12.327484,479392752,65493,188,34.97087146796,23.014057048845,-61.449569706245,2,1,18 +2025-03-11T12:39:12.343109,479392752,65493,188,34.7446956302,22.801096402575,-61.04634845135,2,1,18 +2025-03-11T12:39:12.358734,479392752,65493,188,34.52794378568,22.588152062235,-60.643140758465,2,1,18 +2025-03-11T12:39:12.374359,479392752,65493,188,34.30176794792,22.375191415965,-60.253783052765,2,1,18 +2025-03-11T12:39:12.389984,479392752,65493,188,34.0850161034,22.14838386015,-59.836656190685,2,1,18 +2025-03-11T12:39:12.405609,479392752,65493,188,33.86355226226,21.907704935895,-59.424088110665,2,1,18 +2025-03-11T12:39:12.421234,479392752,65493,188,33.6373764245,21.676260002325,-59.02079269577,2,1,18 +2025-03-11T12:39:12.436859,479392752,65493,188,33.42062457998,21.472557805635,-58.60375853369,2,1,18 +2025-03-11T12:39:12.452484,479392752,65493,188,33.19916073884,21.23187888138,-58.168084538345,2,1,18 +2025-03-11T12:39:12.468109,479392752,65493,188,32.9776968977,20.99582102895,-57.764777364455,2,1,18 +2025-03-11T12:39:12.483734,479392752,65493,188,32.7420970667,20.778223004925,-57.347660458355,2,1,18 +2025-03-11T12:39:12.499359,479392752,65493,188,32.5064972357,20.55138283725,-56.912021739995,2,1,18 +2025-03-11T12:39:12.514984,479392752,65493,188,32.27560940132,20.31530867889,-56.490216271835,2,1,18 +2025-03-11T12:39:12.530609,479392752,65493,188,32.04000957032,20.08384743939,-56.06842256267,2,1,18 +2025-03-11T12:39:12.546234,479392752,65493,188,31.80912173594,19.83853113738,-55.641958831445,2,1,18 +2025-03-11T12:39:12.561859,479392752,65493,188,31.5640979117,19.593190376475,-55.20161120801,2,1,18 +2025-03-11T12:39:12.577484,479392752,65493,188,31.31907408746,19.343228543745,-54.75662386151,2,1,18 +2025-03-11T12:39:12.593109,479392752,65493,188,31.08347425646,19.102525160595,-54.32092952315,2,1,18 +2025-03-11T12:39:12.608734,479392752,65493,188,30.83845043222,18.861805471515,-53.899085171975,2,1,18 +2025-03-11T12:39:12.624359,479392752,65493,188,30.59342660798,18.63494899791,-53.454190525475,2,1,18 +2025-03-11T12:39:12.639984,479392752,65493,188,30.34369078712,18.403463299515,-52.995407008775,2,1,18 +2025-03-11T12:39:12.655609,479392752,65493,188,30.09395496626,18.148872241995,-52.55039434127,2,1,18 +2025-03-11T12:39:12.671234,479392752,65493,188,29.85364313864,17.912781777705,-52.114711761905,2,1,18 +2025-03-11T12:39:12.686859,479392752,65493,188,29.60390731778,17.66281179201,-51.6697176344,2,1,18 +2025-03-11T12:39:12.702484,479392752,65493,188,29.35417149692,17.39897859084,-51.2108043377,2,1,18 +2025-03-11T12:39:12.718109,479392752,65493,188,29.1138596693,17.149024911075,-50.75196022301,2,1,18 +2025-03-11T12:39:12.733734,479392752,65493,188,28.86883584506,16.908305221995,-50.30700995651,2,1,18 +2025-03-11T12:39:12.749359,479392752,65493,188,28.62381202082,16.67220660474,-49.848214680815,2,1,18 +2025-03-11T12:39:12.764984,479392752,65493,188,28.37878819658,16.408381556535,-49.38930816512,2,1,18 +2025-03-11T12:39:12.780609,479392752,65493,188,28.12905237572,16.126064068065,-48.93032070842,2,1,18 +2025-03-11T12:39:12.796234,479392752,65493,188,27.86989256162,15.871456704615,-48.466809746645,2,1,18 +2025-03-11T12:39:12.811859,479392752,65493,188,27.62015674076,15.62148671892,-47.99408852075,2,1,18 +2025-03-11T12:39:12.827484,479392752,65493,188,27.35628493004,15.385355489805,-47.5398873041,2,1,18 +2025-03-11T12:39:12.843109,479392752,65493,188,27.10183711256,15.13075627932,-47.05789839107,2,1,18 +2025-03-11T12:39:12.858734,479392752,65493,188,26.8521012917,14.880786293625,-46.594419531305,2,1,18 +2025-03-11T12:39:12.874359,479392752,65493,188,26.5929414776,14.616936786525,-46.14011385566,2,1,18 +2025-03-11T12:39:12.889984,479392752,65493,188,26.33849366012,14.35309543239,-45.66733022876,2,1,18 +2025-03-11T12:39:12.905609,479392752,65493,188,26.07933384602,14.075382709815,-45.18986301779,2,1,18 +2025-03-11T12:39:12.921234,479392752,65493,188,25.82017403192,13.802291059065,-44.70317198069,2,1,18 +2025-03-11T12:39:12.936859,479392752,65493,188,25.56101421782,13.55230476744,-44.21657364359,2,1,18 +2025-03-11T12:39:12.952484,479392752,65493,188,25.2971424071,13.288447107375,-43.74377645468,2,1,18 +2025-03-11T12:39:12.968109,479392752,65493,188,25.02855859976,13.015339150695,-43.24782948944,2,1,18 +2025-03-11T12:39:12.983734,479392752,65493,188,24.76468678904,12.76072363428,-42.742721099075,2,1,18 +2025-03-11T12:39:12.999359,479392752,65493,188,24.50081497832,12.487623830565,-42.25602328097,2,1,18 +2025-03-11T12:39:13.014984,479392752,65493,188,24.25107915746,12.22841170122,-41.77864379201,2,1,18 +2025-03-11T12:39:13.030609,479392752,65493,188,23.97307135688,11.96452958226,-41.278099161695,2,1,18 +2025-03-11T12:39:13.046234,479392752,65493,188,23.69977555292,11.682171328965,-40.80059306771,2,1,18 +2025-03-11T12:39:13.061859,479392752,65493,188,23.4359037422,11.40907152525,-40.30927406654,2,1,18 +2025-03-11T12:39:13.077484,479392752,65493,188,23.15789594162,11.12670511899,-39.799412910095,2,1,18 +2025-03-11T12:39:13.093109,479392752,65493,188,22.87988814104,10.84433871273,-39.294172936715,2,1,18 +2025-03-11T12:39:13.108734,479392752,65493,188,22.61601633032,10.589723196315,-38.78906454635,2,1,18 +2025-03-11T12:39:13.124359,479392752,65493,188,22.35685651622,10.33049476104,-38.31167149538,2,1,18 +2025-03-11T12:39:13.139984,479392752,65493,188,22.08356071226,10.057378651395,-37.82958129833,2,1,18 +2025-03-11T12:39:13.155609,479392752,65493,188,21.81497690492,9.77964962289,-37.32437342696,2,1,18 +2025-03-11T12:39:13.171234,479392752,65493,188,21.54168110096,9.497291369595,-36.828382600715,2,1,18 +2025-03-11T12:39:13.186859,479392752,65493,188,21.25424930714,9.224150801055,-36.323166145325,2,1,18 +2025-03-11T12:39:13.202484,479392752,65493,188,20.97152950994,8.94177624183,-35.79943465868,2,1,18 +2025-03-11T12:39:13.218109,479392752,65493,188,20.68880971274,8.659401682605,-35.28956672123,2,1,18 +2025-03-11T12:39:13.233734,479392752,65493,188,20.40137791892,8.377018970415,-34.78431318584,2,1,18 +2025-03-11T12:39:13.249359,479392752,65493,188,20.12337011834,8.10851577963,-34.27912883246,2,1,18 +2025-03-11T12:39:13.264984,479392752,65493,188,19.84065032114,7.826141220405,-33.77850326114,2,1,18 +2025-03-11T12:39:13.280609,479392752,65493,188,19.55793052394,7.539145589355,-33.27785914982,2,1,18 +2025-03-11T12:39:13.296234,479392752,65493,188,19.28463471998,7.24754519241,-32.75872532825,2,1,18 +2025-03-11T12:39:13.311859,479392752,65493,188,19.0066269194,6.9744209298,-32.23503770261,2,1,18 +2025-03-11T12:39:13.327484,479392752,65493,188,18.72861911882,6.69205452354,-31.70207063084,2,1,18 +2025-03-11T12:39:13.343109,479392752,65493,188,18.45532331486,6.409696270245,-31.18297388927,2,1,18 +2025-03-11T12:39:13.358734,479392752,65493,188,18.1584675278,6.118055108475,-30.66842734574,2,1,18 +2025-03-11T12:39:13.374359,479392752,65493,188,17.86632373736,5.83566424332,-30.153924663215,2,1,18 +2025-03-11T12:39:13.389984,479392752,65493,188,17.59773993002,5.530208783865,-29.639363185715,2,1,18 +2025-03-11T12:39:13.405609,479392752,65493,188,17.30559613958,5.24781791871,-29.11561813706,2,1,18 +2025-03-11T12:39:13.421234,479392752,65493,188,17.01345234914,4.965427053555,-28.591873088405,2,1,18 +2025-03-11T12:39:13.436859,479392752,65493,188,16.71188456546,4.687640954295,-28.05889065161,2,1,18 +2025-03-11T12:39:13.452484,479392752,65493,188,16.42445277164,4.396016098455,-27.52587293783,2,1,18 +2025-03-11T12:39:13.468109,479392752,65493,188,16.15115696768,4.09517355786,-27.00670203626,2,1,18 +2025-03-11T12:39:13.483734,479392752,65493,188,15.86372517386,3.79430655837,-26.469026059415,2,1,18 +2025-03-11T12:39:13.499359,479392752,65493,188,15.57629338004,3.498060630705,-25.935989805635,2,1,18 +2025-03-11T12:39:13.514984,479392752,65493,188,15.28886158622,3.22029899034,-25.393785345725,2,1,18 +2025-03-11T12:39:13.530609,479392752,65493,188,15.0014297924,2.93791627815,-24.86542589501,2,1,18 +2025-03-11T12:39:13.546234,479392752,65493,188,14.7187099952,2.646299575275,-24.350899694495,2,1,18 +2025-03-11T12:39:13.561859,479392752,65493,188,14.4124302149,2.345399963925,-23.82243895976,2,1,18 +2025-03-11T12:39:13.577484,479392752,65493,188,14.1297104177,2.05378326105,-23.27556447779,2,1,18 +2025-03-11T12:39:13.593109,479392752,65493,188,13.83285463064,1.739036740155,-22.737819318935,2,1,18 +2025-03-11T12:39:13.608734,479392752,65493,188,13.53599884358,1.45201665021,-22.223291315405,2,1,18 +2025-03-11T12:39:13.624359,479392752,65493,188,13.2344310599,1.17423055095,-21.685687695545,2,1,18 +2025-03-11T12:39:13.639984,479392752,65493,188,12.94699926608,0.887226766935,-21.1480673387,2,1,18 +2025-03-11T12:39:13.655609,479392752,65493,188,12.65956747226,0.577117623795001,-20.62421783105,2,1,18 +2025-03-11T12:39:13.671234,479392752,65493,188,12.36742368182,0.29472675864,-20.07736686707,2,1,18 +2025-03-11T12:39:13.686859,479392752,65493,188,12.07056789476,-0.00615654677999977,-19.539677328215,2,1,18 +2025-03-11T12:39:13.702484,479392752,65493,188,11.7737121077,-0.316281995850001,-19.01119307549,2,1,18 +2025-03-11T12:39:13.718109,479392752,65493,188,11.48156831726,-0.598672861004999,-18.47358447764,2,1,18 +2025-03-11T12:39:13.733734,479392752,65493,188,11.18942452682,-0.904169085285,-17.92664081366,2,1,18 +2025-03-11T12:39:13.749359,479392752,65493,188,10.89256873976,-1.20967346253,-17.370448002545,2,1,18 +2025-03-11T12:39:13.764984,479392752,65493,188,10.60042494932,-1.49668539951,-16.823578498565,2,1,18 +2025-03-11T12:39:13.780609,479392752,65493,188,10.29414516902,-1.774479651735,-16.281346914635,2,1,18 +2025-03-11T12:39:13.796234,479392752,65493,188,9.99257738534,-2.07537111012,-15.734408228645,2,1,18 +2025-03-11T12:39:13.811859,479392752,65493,188,9.70514559152,-2.38548025326,-15.192073988735,2,1,18 +2025-03-11T12:39:13.827484,479392752,65493,188,9.40357780784,-2.677129567995,-14.645172382745,2,1,18 +2025-03-11T12:39:13.843109,479392752,65493,188,9.1114340174,-2.97800472045,-14.116731991025,2,1,18 +2025-03-11T12:39:13.858734,479392752,65493,188,8.81929022696,-3.288122016555,-13.588254519305,2,1,18 +2025-03-11T12:39:13.874359,479392752,65493,188,8.52714643652,-3.584376097185,-13.05521148452,2,1,18 +2025-03-11T12:39:13.889984,479392752,65493,188,8.23500264608,-3.87600910599,-12.512944623605,2,1,18 +2025-03-11T12:39:13.905609,479392752,65493,188,7.92401086916,-4.158432583005,-11.975308901735,2,1,18 +2025-03-11T12:39:13.921234,479392752,65493,188,7.61301909224,-4.454719275495,-11.41451164454,2,1,18 +2025-03-11T12:39:13.936859,479392752,65493,188,7.31616330518,-4.75098150909,-10.86297709649,2,1,18 +2025-03-11T12:39:13.952484,479392752,65493,188,7.00988352488,-5.047260048615,-10.325292535625,2,1,18 +2025-03-11T12:39:13.968109,479392752,65493,188,6.72245173106,-5.36199026358,-9.773697389585,2,1,18 +2025-03-11T12:39:13.983734,479392752,65493,188,6.43501993724,-5.667478334895,-9.231381689675,2,1,18 +2025-03-11T12:39:13.999298,479392756,65489,189,6.13816415018,-5.97298271214,-8.70291597695,2,1,18 +2025-03-11T12:39:14.014923,479392756,65489,189,5.83188436988,-6.278503395315,-8.16057315302,2,1,18 +2025-03-11T12:39:14.030548,479392756,65489,189,5.5303165862,-6.5793948537,-7.59514973477,2,1,18 +2025-03-11T12:39:14.046173,479392756,65489,189,5.23817279576,-6.861785718855,-7.043677587725,2,1,18 +2025-03-11T12:39:14.061798,479392756,65489,189,4.9413170087,-7.162669024275,-6.510609231935,2,1,18 +2025-03-11T12:39:14.077423,479392756,65489,189,4.63974922502,-7.468181554485,-5.972894372075,2,1,18 +2025-03-11T12:39:14.093048,479392756,65489,189,4.3287574481,-7.773710390625,-5.407438851815,2,1,18 +2025-03-11T12:39:14.108673,479392756,65489,189,4.03190166104,-8.06997262422,-4.846661937635,2,1,18 +2025-03-11T12:39:14.124298,479392756,65489,189,3.7397578706,-8.36622670485,-4.31361890285,2,1,18 +2025-03-11T12:39:14.139923,479392756,65489,189,3.44290208354,-8.690215369395,-3.757351931735,2,1,18 +2025-03-11T12:39:14.155548,479392756,65489,189,3.14604629648,-9.000340818465,-3.22886767901,2,1,18 +2025-03-11T12:39:14.171173,479392756,65489,189,2.84919050942,-9.29660305206,-2.691196680155,2,1,18 +2025-03-11T12:39:14.186798,479392756,65489,189,2.55233472236,-9.59748635748,-2.148885958235,2,1,18 +2025-03-11T12:39:14.202423,479392756,65489,189,2.2554789353,-9.884506447425,-1.60200967325,2,1,18 +2025-03-11T12:39:14.218048,479392756,65489,189,1.93977516176,-10.16231700558,-1.027416245855,2,1,18 +2025-03-11T12:39:14.233673,479392756,65489,189,1.63349538146,-10.47245876058,-0.47119133273,2,1,18 +2025-03-11T12:39:14.249298,479392756,65489,189,1.33192759778,-10.78721343444,0.0711817901949998,2,1,18 +2025-03-11T12:39:14.264923,479392756,65489,189,1.03507181072,-11.092717811685,0.613511052115,2,1,18 +2025-03-11T12:39:14.280548,479392756,65489,189,0.74292802028,-11.38435082049,1.160399096095,2,1,18 +2025-03-11T12:39:14.296173,479392756,65489,189,0.45549622646,-11.67597567633,1.702659176005,2,1,18 +2025-03-11T12:39:14.311798,479392756,65489,189,0.17277642926,-11.97221345103,2.24493101491,2,1,18 +2025-03-11T12:39:14.327423,479392756,65489,189,-0.13350335104,-12.27311306238,2.782634115775,2,1,18 +2025-03-11T12:39:14.343048,479392756,65489,189,-0.4303591381,-12.578617439625,3.32034219463,2,1,18 +2025-03-11T12:39:14.358673,479392756,65489,189,-0.73192692178,-12.884129969835,3.87654178675,2,1,18 +2025-03-11T12:39:14.374298,479392756,65489,189,-1.03349470546,-13.189642500045,4.42349901274,2,1,18 +2025-03-11T12:39:14.389923,479392756,65489,189,-1.349198479,-13.472074130025,4.95652033255,2,1,18 +2025-03-11T12:39:14.405548,479392756,65489,189,-1.64605426606,-13.76833636362,5.503433697535,2,1,18 +2025-03-11T12:39:14.421173,479392756,65489,189,-1.93348605988,-14.05996121946,6.036451411315,2,1,18 +2025-03-11T12:39:14.436798,479392756,65489,189,-2.2209178537,-14.356207147125,6.587972397355,2,1,18 +2025-03-11T12:39:14.452423,479392756,65489,189,-2.52248563738,-14.661719677335,7.12106607415,2,1,18 +2025-03-11T12:39:14.468048,479392756,65489,189,-2.81934142444,-14.971845126405,7.668035059135,2,1,18 +2025-03-11T12:39:14.483673,479392756,65489,189,-3.1161972115,-15.26810736,8.238054339445,2,1,18 +2025-03-11T12:39:14.499298,479392756,65489,189,-3.41305299856,-15.56899066542,8.761880329105,2,1,18 +2025-03-11T12:39:14.514923,479392756,65489,189,-3.705196789,-15.8560026024,9.281022734695,2,1,18 +2025-03-11T12:39:14.530548,479392756,65489,189,-4.00676457268,-16.147651917135,9.81406079149,2,1,18 +2025-03-11T12:39:14.546173,479392756,65489,189,-4.30833235636,-16.43930123187,10.356341214415,2,1,18 +2025-03-11T12:39:14.561798,479392756,65489,189,-4.6004761468,-16.730934240675,10.903229258395,2,1,18 +2025-03-11T12:39:14.577423,479392756,65489,189,-4.88790794062,-17.013316952865,11.44083107524,2,1,18 +2025-03-11T12:39:14.593048,479392756,65489,189,-5.18005173106,-17.32343424897,11.983172096155,2,1,18 +2025-03-11T12:39:14.608673,479392756,65489,189,-5.47690751812,-17.628938626215,12.516258991945,2,1,18 +2025-03-11T12:39:14.624298,479392756,65489,189,-5.78789929504,-17.925225318705,13.04932915075,2,1,18 +2025-03-11T12:39:14.639923,479392756,65489,189,-6.07061909224,-18.21684202158,13.591582449655,2,1,18 +2025-03-11T12:39:14.655548,479392756,65489,189,-6.36276288268,-18.51309610221,14.138489033635,2,1,18 +2025-03-11T12:39:14.671173,479392756,65489,189,-6.63605868664,-18.80007542733,14.666846681335,2,1,18 +2025-03-11T12:39:14.686798,479392756,65489,189,-6.92349048046,-19.087079211345,15.20446703818,2,1,18 +2025-03-11T12:39:14.702423,479392756,65489,189,-7.22505826414,-19.383349597905,15.719038902715,2,1,18 +2025-03-11T12:39:14.718048,479392756,65489,189,-7.51249005796,-19.674974453745,16.233571884235,2,1,18 +2025-03-11T12:39:14.733673,479392756,65489,189,-7.8046338484,-19.980470678025,16.75740963289,2,1,18 +2025-03-11T12:39:14.749298,479392756,65489,189,-8.09206564222,-20.25823231839,17.28112936054,2,1,18 +2025-03-11T12:39:14.764923,479392756,65489,189,-8.37949743604,-20.545236102405,17.80488616819,2,1,18 +2025-03-11T12:39:14.780548,479392756,65489,189,-8.66692922986,-20.846103101895,18.333319778905,2,1,18 +2025-03-11T12:39:14.796173,479392756,65489,189,-8.94964902706,-21.13771980477,18.852467162485,2,1,18 +2025-03-11T12:39:14.811798,479392756,65489,189,-9.23708082088,-21.433965732435,19.376261050135,2,1,18 +2025-03-11T12:39:14.827423,479392756,65489,189,-9.52922461132,-21.71635659759,19.895384915725,2,1,18 +2025-03-11T12:39:14.843048,479392756,65489,189,-9.82136840176,-21.998747462745,20.423751147445,2,1,18 +2025-03-11T12:39:14.858673,479392756,65489,189,-10.11822418882,-22.28576755269,20.947521517105,2,1,18 +2025-03-11T12:39:14.874298,479392756,65489,189,-10.3962319894,-22.581997174425,21.46668065968,2,1,18 +2025-03-11T12:39:14.889923,479392756,65489,189,-10.68366378322,-22.873622030265,21.99045600733,2,1,18 +2025-03-11T12:39:14.905548,479392756,65489,189,-10.96638358042,-23.142133374015,22.514131873975,2,1,18 +2025-03-11T12:39:14.921173,479392756,65489,189,-11.25852737086,-23.419903167345,23.033237199565,2,1,18 +2025-03-11T12:39:14.936798,479392756,65489,189,-11.54595916468,-23.693043735885,23.55231720415,2,1,18 +2025-03-11T12:39:14.952423,479392756,65489,189,-11.82867896188,-23.989281510585,24.066861944665,2,1,18 +2025-03-11T12:39:14.968048,479392756,65489,189,-12.10668676246,-24.27626898867,24.56749927498,2,1,18 +2025-03-11T12:39:14.983673,479392756,65489,189,-12.37998256642,-24.558627241965,25.081974833485,2,1,18 +2025-03-11T12:39:14.999298,479392756,65489,189,-12.64856637376,-24.840977342295,25.605685977115,2,1,18 +2025-03-11T12:39:15.014923,479392756,65489,189,-12.92657417434,-25.11872267673,26.10628622743,2,1,18 +2025-03-11T12:39:15.030548,479392756,65489,189,-13.1998699783,-25.36873342725,26.611389639805,2,1,18 +2025-03-11T12:39:15.046173,479392756,65489,189,-13.50143776198,-25.651140598335,27.11666351821,2,1,18 +2025-03-11T12:39:15.061798,479392756,65489,189,-13.77944556256,-25.924264860945,27.635729960785,2,1,18 +2025-03-11T12:39:15.077423,479392756,65489,189,-14.06216535976,-26.21588156382,28.14101379517,2,1,18 +2025-03-11T12:39:15.093048,479392756,65489,189,-14.34488515696,-26.50287719487,28.64165790649,2,1,18 +2025-03-11T12:39:15.108673,479392756,65489,189,-14.60404497106,-26.77596884562,29.132970126655,2,1,18 +2025-03-11T12:39:15.124298,479392756,65489,189,-14.86320478516,-27.04906049637,29.638145896015,2,1,18 +2025-03-11T12:39:15.139923,479392756,65489,189,-15.13650058912,-27.31755553419,30.13408110226,2,1,18 +2025-03-11T12:39:15.155548,479392756,65489,189,-15.40979639308,-27.58605057201,30.6438798577,2,1,18 +2025-03-11T12:39:15.171173,479392756,65489,189,-15.68309219704,-27.85454560983,31.139815063945,2,1,18 +2025-03-11T12:39:15.186798,479392756,65489,189,-15.956388001,-28.109177432175,31.63569465019,2,1,18 +2025-03-11T12:39:15.202423,479392756,65489,189,-16.2391077982,-28.377688775925,32.113158686185,2,1,18 +2025-03-11T12:39:15.218048,479392756,65489,189,-16.4982676123,-28.64615935485,32.60445236635,2,1,18 +2025-03-11T12:39:15.233673,479392756,65489,189,-16.76685141964,-28.923888383355,33.095796688525,2,1,18 +2025-03-11T12:39:15.249298,479392756,65489,189,-17.02601123374,-29.20160110593,33.573263899495,2,1,18 +2025-03-11T12:39:15.264923,479392756,65489,189,-17.28517104784,-29.470071684855,34.0460728474,2,1,18 +2025-03-11T12:39:15.280548,479392756,65489,189,-17.56317884842,-29.74781701929,34.52356718239,2,1,18 +2025-03-11T12:39:15.296173,479392756,65489,189,-17.841186649,-30.0209412819,35.00104297738,2,1,18 +2025-03-11T12:39:15.311798,479392756,65489,189,-18.09092246986,-30.26629019577,35.48760921247,2,1,18 +2025-03-11T12:39:15.327423,479392756,65489,189,-18.35008228396,-30.52089755922,35.99271082183,2,1,18 +2025-03-11T12:39:15.343048,479392756,65489,189,-18.60924209806,-30.79398920997,36.4701594928,2,1,18 +2025-03-11T12:39:15.358673,479392756,65489,189,-18.87311390878,-31.057846870035,36.938335498645,2,1,18 +2025-03-11T12:39:15.374298,479392756,65489,189,-19.1369857195,-31.3032202428,37.40643734449,2,1,18 +2025-03-11T12:39:15.389923,479392756,65489,189,-19.38672154036,-31.553190228495,37.89302211958,2,1,18 +2025-03-11T12:39:15.405548,479392756,65489,189,-19.63645736122,-31.826265573315,38.36121486241,2,1,18 +2025-03-11T12:39:15.421173,479392756,65489,189,-19.88619318208,-32.090098774485,38.82937052524,2,1,18 +2025-03-11T12:39:15.436798,479392756,65489,189,-20.14535299618,-32.344706137935,39.292881487015,2,1,18 +2025-03-11T12:39:15.452423,479392756,65489,189,-20.4092248069,-32.59932165435,39.747156863665,2,1,18 +2025-03-11T12:39:15.468048,479392756,65489,189,-20.65896062776,-32.86315485552,40.206070160365,2,1,18 +2025-03-11T12:39:15.483673,479392756,65489,189,-20.90869644862,-33.122366984865,40.655722550935,2,1,18 +2025-03-11T12:39:15.499298,479392756,65489,189,-21.15843226948,-33.367715898735,41.114561687635,2,1,18 +2025-03-11T12:39:15.514923,479392756,65489,189,-21.41759208358,-33.622323262185,41.57807264941,2,1,18 +2025-03-11T12:39:15.530548,479392756,65489,189,-21.66732790444,-33.86305110423,42.023029696915,2,1,18 +2025-03-11T12:39:15.546173,479392756,65489,189,-21.93119971516,-34.117666620645,42.486547439695,2,1,18 +2025-03-11T12:39:15.561798,479392756,65489,189,-22.17151154278,-34.35837815676,42.936112108255,2,1,18 +2025-03-11T12:39:15.577423,479392756,65489,189,-22.40711137378,-34.61756582721,43.39498652194,2,1,18 +2025-03-11T12:39:15.593048,479392756,65489,189,-22.64271120478,-34.862890282185,43.853805315625,2,1,18 +2025-03-11T12:39:15.608673,479392756,65489,189,-22.89244702564,-35.09437598058,44.27099818474,2,1,18 +2025-03-11T12:39:15.624298,479392756,65489,189,-23.1421828465,-35.33972489445,44.697489039985,2,1,18 +2025-03-11T12:39:15.639923,479392756,65489,189,-23.38249467412,-35.58505750239,45.14245106548,2,1,18 +2025-03-11T12:39:15.655548,479392756,65489,189,-23.60867051188,-35.839607795085,45.59667219409,2,1,18 +2025-03-11T12:39:15.671173,479392756,65489,189,-23.84427034288,-36.071069034585,46.03232945245,2,1,18 +2025-03-11T12:39:15.686798,479392756,65489,189,-24.08929416712,-36.302546580015,46.454136723625,2,1,18 +2025-03-11T12:39:15.702423,479392756,65489,189,-24.33431799136,-36.534024125445,46.899049910125,2,1,18 +2025-03-11T12:39:15.718048,479392756,65489,189,-24.56991782236,-36.774727508595,47.325501882355,2,1,18 +2025-03-11T12:39:15.733673,479392756,65489,189,-24.7913816635,-37.01540643285,47.738069962375,2,1,18 +2025-03-11T12:39:15.749298,479392756,65489,189,-25.03640548774,-37.233020762805,48.17830634581,2,1,18 +2025-03-11T12:39:15.764923,479392756,65489,189,-25.27671731536,-37.459869083445,48.604709479045,2,1,18 +2025-03-11T12:39:15.780548,479392756,65489,189,-25.4981811565,-37.686684792225,49.035706671325,2,1,18 +2025-03-11T12:39:15.796173,479392756,65489,189,-25.71964499764,-37.895016213705,49.46200852054,2,1,18 +2025-03-11T12:39:15.811798,479392756,65489,189,-25.95053283202,-38.140332515715,49.86536633644,2,1,18 +2025-03-11T12:39:15.827423,479392756,65489,189,-26.17199667316,-38.38101143997,50.264070867265,2,1,18 +2025-03-11T12:39:15.843048,479392756,65489,189,-26.39817251092,-38.61245637354,50.67660864829,2,1,18 +2025-03-11T12:39:15.858673,479392756,65489,189,-26.61492435544,-38.830021785705,51.09369843037,2,1,18 +2025-03-11T12:39:15.874298,479392756,65489,189,-26.83638819658,-39.05221642266,51.501571167325,2,1,18 +2025-03-11T12:39:15.889923,479392756,65489,189,-27.0531400411,-39.279023978475,51.89559211408,2,1,18 +2025-03-11T12:39:15.905548,479392756,65489,189,-27.265179889,-39.496581237675,52.2803268337,2,1,18 +2025-03-11T12:39:15.921173,479392756,65489,189,-27.48664373014,-39.714154802805,52.688181030655,2,1,18 +2025-03-11T12:39:15.936798,479392756,65489,189,-27.71753156452,-39.931744673865,53.082185240425,2,1,18 +2025-03-11T12:39:15.952423,479392756,65489,189,-27.93428340904,-40.144689014205,53.46690820105,2,1,18 +2025-03-11T12:39:15.968048,479392756,65489,189,-28.14632325694,-40.35762520158,53.8608667468,2,1,18 +2025-03-11T12:39:15.983673,479392756,65489,189,-28.35365110822,-40.56131109234,54.25016024848,2,1,18 +2025-03-11T12:39:15.999298,479392756,65489,189,-28.56569095612,-40.765005136065,54.639460531165,2,1,18 +2025-03-11T12:39:16.014923,479392756,65489,189,-28.77773080402,-40.982562395265,55.014952884655,2,1,18 +2025-03-11T12:39:16.030548,479392756,65489,189,-28.9850586553,-41.195490429675,55.395041100205,2,1,18 +2025-03-11T12:39:16.046173,479392756,65489,189,-29.19238650658,-41.408418464085,55.784371681885,2,1,18 +2025-03-11T12:39:16.061798,479392756,65489,189,-29.39971435786,-41.621346498495,56.1690810805,2,1,18 +2025-03-11T12:39:16.077423,479392756,65489,189,-29.60233021252,-41.829645308115,56.53528042585,2,1,18 +2025-03-11T12:39:16.093048,479392756,65489,189,-29.81437006042,-42.037960423665,56.90149333321,2,1,18 +2025-03-11T12:39:16.108673,479392756,65489,189,-30.01227391846,-42.241630008495,57.258424991425,2,1,18 +2025-03-11T12:39:16.124298,479392756,65489,189,-30.2101777765,-42.43143637785,57.6337857619,2,1,18 +2025-03-11T12:39:16.139923,479392756,65489,189,-30.4222176244,-42.61202506245,57.99064506313,2,1,18 +2025-03-11T12:39:16.155548,479392756,65489,189,-30.60598549258,-42.81104911656,58.34753783833,2,1,18 +2025-03-11T12:39:16.171173,479392756,65489,189,-30.79446535738,-43.019323467285,58.69061092534,2,1,18 +2025-03-11T12:39:16.186798,479392756,65489,189,-30.99708121204,-43.23224334873,59.042965261495,2,1,18 +2025-03-11T12:39:16.202423,479392756,65489,189,-31.19027307346,-43.42204156512,59.39521333564,2,1,18 +2025-03-11T12:39:16.218048,479392756,65489,189,-31.38346493488,-43.607218709685,59.747442869785,2,1,18 +2025-03-11T12:39:16.233673,479392756,65489,189,-31.57194479968,-43.78776662946,60.10426826599,2,1,18 +2025-03-11T12:39:16.249298,479392756,65489,189,-31.76984865772,-43.968330855165,60.451864858075,2,1,18 +2025-03-11T12:39:16.264923,479392756,65489,189,-31.94890452928,-44.14886246901,60.79019196001,2,1,18 +2025-03-11T12:39:16.280548,479392756,65489,189,-32.12796040084,-44.347878370155,61.128593221945,2,1,18 +2025-03-11T12:39:16.296173,479392756,65489,189,-32.3070162724,-44.533031055825,61.44845413162,2,1,18 +2025-03-11T12:39:16.311798,479392756,65489,189,-32.4954961372,-44.70433683195,61.777515349435,2,1,18 +2025-03-11T12:39:16.327423,479392756,65489,189,-32.67455200876,-44.88948951762,62.111239808305,2,1,18 +2025-03-11T12:39:16.343048,479392756,65489,189,-32.83475989384,-45.060746375955,62.43101797396,2,1,18 +2025-03-11T12:39:16.358673,479392756,65489,189,-33.00910376878,-45.250511980485,62.75089064263,2,1,18 +2025-03-11T12:39:16.374298,479392756,65489,189,-33.18344764372,-45.41717222589,63.066049428235,2,1,18 +2025-03-11T12:39:16.389923,479392756,65489,189,-33.3672155119,-45.583848777225,63.367358226655,2,1,18 +2025-03-11T12:39:16.405548,479392756,65489,189,-33.55098338008,-45.764388544035,63.68258619427,2,1,18 +2025-03-11T12:39:16.421173,479392756,65489,189,-33.7206152584,-45.9356617083,64.002377921935,2,1,18 +2025-03-11T12:39:16.436798,479392756,65489,189,-33.89024713672,-46.08382951344,64.3220769496,2,1,18 +2025-03-11T12:39:16.452423,479392756,65489,189,-34.06459101166,-46.259731902495,64.6511363644,2,1,18 +2025-03-11T12:39:16.468048,479392756,65489,189,-34.22951089336,-46.43561798562,64.947833935735,2,1,18 +2025-03-11T12:39:16.483673,479392756,65489,189,-34.38971877844,-46.588390556655,65.253674392195,2,1,18 +2025-03-11T12:39:16.499298,479392756,65489,189,-34.54992666352,-46.75040527134,65.541067196395,2,1,18 +2025-03-11T12:39:16.514923,479392756,65489,189,-34.72427053846,-46.91244444492,65.833101526675,2,1,18 +2025-03-11T12:39:16.530548,479392756,65489,189,-34.89390241678,-47.065233321885,66.11584962982,2,1,18 +2025-03-11T12:39:16.546173,479392756,65489,189,-35.039974312,-47.2318446495,66.39861944794,2,1,18 +2025-03-11T12:39:16.561798,479392756,65489,189,-35.20018219708,-47.384617220535,66.681353989075,2,1,18 +2025-03-11T12:39:16.577423,479392756,65489,189,-35.35567808554,-47.537381638605,66.96870293227,2,1,18 +2025-03-11T12:39:16.593048,479392756,65489,189,-35.50646197738,-47.69013790371,67.251423911395,2,1,18 +2025-03-11T12:39:16.608673,479392756,65489,189,-35.65724586922,-47.842894168815,67.520281341325,2,1,18 +2025-03-11T12:39:16.624298,479392756,65489,189,-35.80802976106,-47.99565043392,67.78451758819,2,1,18 +2025-03-11T12:39:16.639923,479392756,65489,189,-35.95410165628,-48.153019617885,68.053386777115,2,1,18 +2025-03-11T12:39:16.655548,479392756,65489,189,-36.1001735515,-48.296525586375,68.326821529105,2,1,18 +2025-03-11T12:39:16.671173,479392756,65489,189,-36.23210945686,-48.435386024145,68.60021739808,2,1,18 +2025-03-11T12:39:16.686798,479392756,65489,189,-36.37346935546,-48.57888383967,68.85978181987,2,1,18 +2025-03-11T12:39:16.702423,479392756,65489,189,-36.52896524392,-48.72240611409,69.11474540161,2,1,18 +2025-03-11T12:39:16.718048,479392756,65489,189,-36.67974913576,-48.85205702007,69.369646582345,2,1,18 +2025-03-11T12:39:16.733673,479392756,65489,189,-36.82110903436,-48.995554835595,69.62458982107,2,1,18 +2025-03-11T12:39:16.749298,479392756,65489,189,-36.96246893296,-49.12981050747,69.870253613665,2,1,18 +2025-03-11T12:39:16.764923,479392756,65489,189,-37.09440483832,-49.25018665794,70.10660585812,2,1,18 +2025-03-11T12:39:16.780548,479392756,65489,189,-37.21691675044,-49.38903078978,70.3383975175,2,1,18 +2025-03-11T12:39:16.796173,479392756,65489,189,-37.33000466932,-49.523237543865,70.574778257935,2,1,18 +2025-03-11T12:39:16.811798,479392756,65489,189,-37.45722857806,-49.648226613195,70.792657529125,2,1,18 +2025-03-11T12:39:16.827423,479392756,65489,189,-37.5844524868,-49.763973538875,71.00587853725,2,1,18 +2025-03-11T12:39:16.843048,479392756,65489,189,-37.71167639554,-49.888962608205,71.256106089895,2,1,18 +2025-03-11T12:39:16.858673,479392756,65489,189,-37.83418830766,-50.02318566822,71.47401566008,2,1,18 +2025-03-11T12:39:16.874298,479392756,65489,189,-37.96612421302,-50.148182890515,71.69652289534,2,1,18 +2025-03-11T12:39:16.889923,479392756,65489,189,-38.07450013528,-50.254655060685,71.91430088251,2,1,18 +2025-03-11T12:39:16.905548,479392756,65489,189,-38.17816406092,-50.37960336519,72.132146248675,2,1,18 +2025-03-11T12:39:16.921173,479392756,65489,189,-38.30067597304,-50.50920535338,72.345416095795,2,1,18 +2025-03-11T12:39:16.936798,479392756,65489,189,-38.41847588854,-50.620314901305,72.54936263578,2,1,18 +2025-03-11T12:39:16.952423,479392756,65489,189,-38.53156380742,-50.722174152615,72.739401765565,2,1,18 +2025-03-11T12:39:16.968048,479392756,65489,189,-38.6446517263,-50.842517691225,72.943378604545,2,1,18 +2025-03-11T12:39:16.983673,479392756,65489,189,-38.74360365532,-50.948973555465,73.151900663575,2,1,18 +2025-03-11T12:39:16.999298,479392756,65489,189,-38.84726758096,-51.04619542902,73.346528874415,2,1,18 +2025-03-11T12:39:17.014923,479392756,65489,189,-38.95564350322,-51.15266759919,73.545822129325,2,1,18 +2025-03-11T12:39:17.030548,479392756,65489,189,-39.05459543224,-51.25912346343,73.71275354077,2,1,18 +2025-03-11T12:39:17.046173,479392756,65489,189,-39.15825935788,-51.36096640881,73.902779108545,2,1,18 +2025-03-11T12:39:17.061798,479392756,65489,189,-39.25249929028,-51.44430876096,74.08347458818,2,1,18 +2025-03-11T12:39:17.077423,479392756,65489,189,-39.34673922268,-51.54613540041,74.245759495555,2,1,18 +2025-03-11T12:39:17.093048,479392756,65489,189,-39.43155516184,-51.64794573393,74.40803084092,2,1,18 +2025-03-11T12:39:17.108673,479392756,65489,189,-39.516371101,-51.735892851975,74.570246566285,2,1,18 +2025-03-11T12:39:17.124298,479392756,65489,189,-39.6106110334,-51.828477347775,74.727873210595,2,1,18 +2025-03-11T12:39:17.139923,479392756,65489,189,-39.68600297932,-51.930271375365,74.903994543145,2,1,18 +2025-03-11T12:39:17.155548,479392756,65489,189,-39.78024291172,-52.00899265569,75.080050299715,2,1,18 +2025-03-11T12:39:17.171173,479392756,65489,189,-39.87919484074,-52.09696423263,75.242286368095,2,1,18 +2025-03-11T12:39:17.186798,479392756,65489,189,-39.97343477314,-52.184927656605,75.40451565547,2,1,18 +2025-03-11T12:39:17.202423,479392756,65489,189,-40.06767470554,-52.268270008755,75.57134758591,2,1,18 +2025-03-11T12:39:17.218048,479392756,65489,189,-40.14777864808,-52.35158790201,75.701189708815,2,1,18 +2025-03-11T12:39:17.233673,479392756,65489,189,-40.22788259062,-52.434905795265,75.84027419785,2,1,18 +2025-03-11T12:39:17.249298,479392756,65489,189,-40.30798653316,-52.49973940122,75.988526893015,2,1,18 +2025-03-11T12:39:17.264923,479392756,65489,189,-40.35981849598,-52.573766233035,76.113670066825,2,1,18 +2025-03-11T12:39:17.280548,479392756,65489,189,-40.44463443514,-52.647850135605,76.22037597541,2,1,18 +2025-03-11T12:39:17.296173,479392756,65489,189,-40.52473837768,-52.708062669735,76.34550421525,2,1,18 +2025-03-11T12:39:17.311798,479392756,65489,189,-40.6001303236,-52.7867513382,76.479942200215,2,1,18 +2025-03-11T12:39:17.327423,479392756,65489,189,-40.66609827628,-52.87004477256,76.619006346235,2,1,18 +2025-03-11T12:39:17.343048,479392756,65489,189,-40.72264223572,-52.93483761369,76.74411922105,2,1,18 +2025-03-11T12:39:17.358673,479392756,65489,189,-40.79332218502,-52.98579169824,76.855333269685,2,1,18 +2025-03-11T12:39:17.374298,479392756,65489,189,-40.8592901377,-53.045979773475,76.97119880038,2,1,18 +2025-03-11T12:39:17.389923,479392756,65489,189,-40.92054609376,-53.096917552095,77.082399287005,2,1,18 +2025-03-11T12:39:17.405548,479392756,65489,189,-40.96766605996,-53.13858872817,77.16119406916,2,1,18 +2025-03-11T12:39:17.421173,479392756,65489,189,-41.02892201602,-53.18028436314,77.24925156046,2,1,18 +2025-03-11T12:39:17.436798,479392756,65489,189,-41.0948899687,-53.2266092229,77.35119792196,2,1,18 +2025-03-11T12:39:17.452423,479392756,65489,189,-41.12316194842,-53.27286885894,77.44384766929,2,1,18 +2025-03-11T12:39:17.468048,479392756,65489,189,-41.17028191462,-53.333024322315,77.541201343705,2,1,18 +2025-03-11T12:39:17.483673,479392756,65489,189,-41.21740188082,-53.39317978569,77.633933835055,2,1,18 +2025-03-11T12:39:17.499298,479392756,65489,189,-41.2598098504,-53.430221736975,77.712703296205,2,1,18 +2025-03-11T12:39:17.514923,479392756,65489,189,-41.3069298166,-53.476513984875,77.786895435295,2,1,18 +2025-03-11T12:39:17.530548,479392756,65489,189,-41.34933778618,-53.518177007985,77.87030461951,2,1,18 +2025-03-11T12:39:17.546173,479392756,65489,189,-41.38703375914,-53.564452949955,77.93524083046,2,1,18 +2025-03-11T12:39:17.561798,479392756,65489,189,-41.42001773548,-53.606099667135,77.981666988145,2,1,18 +2025-03-11T12:39:17.577423,479392756,65489,189,-41.46242570506,-53.638520546595,78.03731199397,2,1,18 +2025-03-11T12:39:17.593048,479392756,65489,189,-41.50483367464,-53.66632035423,78.111423192055,2,1,18 +2025-03-11T12:39:17.608673,479392756,65489,189,-41.53781765098,-53.703345999585,78.176315542,2,1,18 +2025-03-11T12:39:17.624298,479392756,65489,189,-41.5660896307,-53.73574242015,78.22269783868,2,1,18 +2025-03-11T12:39:17.639923,479392756,65489,189,-41.5896496138,-53.76813068775,78.287558086615,2,1,18 +2025-03-11T12:39:17.655548,479392756,65489,189,-41.60849760028,-53.78664758691,78.34773475048,2,1,18 +2025-03-11T12:39:17.671173,479392756,65489,189,-41.63676958,-53.809801863825,78.380216417965,2,1,18 +2025-03-11T12:39:17.686798,479392756,65489,189,-41.67917754958,-53.82835952781,78.39883633927,2,1,18 +2025-03-11T12:39:17.702423,479392756,65489,189,-41.68860154282,-53.842239049215,78.431253802735,2,1,18 +2025-03-11T12:39:17.718048,479392756,65489,189,-41.69802553606,-53.851497498795,78.477516275395,2,1,18 +2025-03-11T12:39:17.733673,479392756,65489,189,-41.72158551916,-53.865401479095,78.519196448005,2,1,18 +2025-03-11T12:39:17.749298,479392756,65489,189,-41.73572150902,-53.888531297115,78.55627895554,2,1,18 +2025-03-11T12:39:17.764923,479392756,65489,189,-41.74985749888,-53.911661115135,78.556391998555,2,1,18 +2025-03-11T12:39:17.780548,479392756,65489,189,-41.75928149212,-53.930161708365,78.574964452825,2,1,18 +2025-03-11T12:39:17.796173,479392756,65489,189,-41.7545694955,-53.934774627225,78.58421857795,2,1,18 +2025-03-11T12:39:17.811798,479392756,65489,189,-41.76870548536,-53.92555694247,78.593444207095,2,1,18 +2025-03-11T12:39:17.827423,479392756,65489,189,-41.7781294786,-53.930194320225,78.6073398583,2,1,18 +2025-03-11T12:39:17.843048,479392756,65489,189,-41.76870548536,-53.94404122977,78.602760733225,2,1,18 +2025-03-11T12:39:17.858673,479392756,65489,189,-41.75928149212,-53.95326706749,78.60740543428,2,1,18 +2025-03-11T12:39:17.874298,479392756,65489,189,-41.76870548536,-53.957904445245,78.61667990242,2,1,18 +2025-03-11T12:39:17.889923,479392756,65489,189,-41.75928149212,-53.94402492384,78.62585308654,2,1,18 +2025-03-11T12:39:17.905548,479392756,65489,189,-41.74514550226,-53.934758321295,78.616553297395,2,1,18 +2025-03-11T12:39:17.921173,479392756,65489,189,-41.74514550226,-53.92089510582,78.607255311265,2,1,18 +2025-03-11T12:39:17.936798,479392756,65489,189,-41.73572150902,-53.907015584415,78.58408021393,2,1,18 +2025-03-11T12:39:17.952423,479392756,65489,189,-41.72158551916,-53.902370053695,78.55169304946,2,1,18 +2025-03-11T12:39:17.968048,479392756,65489,189,-41.7074495293,-53.888482379325,78.496162889665,2,1,18 +2025-03-11T12:39:17.983673,479392756,65489,189,-41.69331353944,-53.88845792043,78.449930716,2,1,18 +2025-03-11T12:39:17.999237,479392760,65485,190,-41.6838895462,-53.86071518355,78.435942364795,2,1,18 +2025-03-11T12:39:18.014862,479392760,65485,190,-41.66504155972,-53.83295614074,78.398834536255,2,1,18 +2025-03-11T12:39:18.030487,479392760,65485,190,-41.64619357324,-53.81443924158,78.37562733691,2,1,18 +2025-03-11T12:39:18.046112,479392760,65485,190,-41.62263359014,-53.79129311763,78.357015999625,2,1,18 +2025-03-11T12:39:18.061737,479392760,65485,190,-41.59907360704,-53.75890485003,78.324504033145,2,1,18 +2025-03-11T12:39:18.077362,479392760,65485,190,-41.57551362394,-53.73575872608,78.25968086521,2,1,18 +2025-03-11T12:39:18.092987,479392760,65485,190,-41.54724164422,-53.703362305515,78.18557147014,2,1,18 +2025-03-11T12:39:18.108612,479392760,65485,190,-41.51425766788,-53.65709451651,78.120642040195,2,1,18 +2025-03-11T12:39:18.124237,479392760,65485,190,-41.46713770168,-53.62928655591,78.05114524417,2,1,18 +2025-03-11T12:39:18.139862,479392760,65485,190,-41.43415372534,-53.583018766905,77.986215814225,2,1,18 +2025-03-11T12:39:18.155487,479392760,65485,190,-41.39645775238,-53.545984968585,77.921316683275,2,1,18 +2025-03-11T12:39:18.171112,479392760,65485,190,-41.36818577266,-53.49510426072,77.8609966774,2,1,18 +2025-03-11T12:39:18.186737,479392760,65485,190,-41.32577780308,-53.467304453085,77.777643113185,2,1,18 +2025-03-11T12:39:18.202362,479392760,65485,190,-41.2833698335,-53.434883573625,77.68502864284,2,1,18 +2025-03-11T12:39:18.217987,479392760,65485,190,-41.2598098504,-53.402495306025,77.61554721184,2,1,18 +2025-03-11T12:39:18.233612,479392760,65485,190,-41.21740188082,-53.342347995615,77.55516978295,2,1,18 +2025-03-11T12:39:18.249237,479392760,65485,190,-41.17028191462,-53.28219253224,77.476300840795,2,1,18 +2025-03-11T12:39:18.264862,479392760,65485,190,-41.1184499518,-53.2405132032,77.369772179245,2,1,18 +2025-03-11T12:39:18.280487,479392760,65485,190,-41.05248199912,-53.19418834344,77.27244700081,2,1,18 +2025-03-11T12:39:18.296112,479392760,65485,190,-40.99122604306,-53.129387349345,77.16581207725,2,1,18 +2025-03-11T12:39:18.311737,479392760,65485,190,-40.93939408024,-53.07384480483,77.04074306344,2,1,18 +2025-03-11T12:39:18.327362,479392760,65485,190,-40.8828501208,-53.004430891875,76.934096380885,2,1,18 +2025-03-11T12:39:18.342987,479392760,65485,190,-40.82630616136,-52.95350126622,76.83676622446,2,1,18 +2025-03-11T12:39:18.358612,479392760,65485,190,-40.76976220192,-52.902571640565,76.72557251884,2,1,18 +2025-03-11T12:39:18.374237,479392760,65485,190,-40.71321824248,-52.84239987126,76.609720550155,2,1,18 +2025-03-11T12:39:18.389862,479392760,65485,190,-40.65196228642,-52.777598877165,76.4892220774,2,1,18 +2025-03-11T12:39:18.405487,479392760,65485,190,-40.56243435064,-52.69426467798,76.359366392485,2,1,18 +2025-03-11T12:39:18.421112,479392760,65485,190,-40.4823304081,-52.6248100002,76.224958706515,2,1,18 +2025-03-11T12:39:18.436737,479392760,65485,190,-40.4116504588,-52.550750556525,76.09516722562,2,1,18 +2025-03-11T12:39:18.452362,479392760,65485,190,-40.33625851288,-52.476682959885,75.969990146785,2,1,18 +2025-03-11T12:39:18.467987,479392760,65485,190,-40.25615457034,-52.407228282105,75.83096127775,2,1,18 +2025-03-11T12:39:18.483612,479392760,65485,190,-40.1760506278,-52.328531460675,75.682652962585,2,1,18 +2025-03-11T12:39:18.499237,479392760,65485,190,-40.11008267512,-52.23137481084,75.52966964737,2,1,18 +2025-03-11T12:39:18.514862,479392760,65485,190,-40.0346907292,-52.152686142375,75.385989296275,2,1,18 +2025-03-11T12:39:18.530487,479392760,65485,190,-39.94987479004,-52.069360096155,75.23303447704,2,1,18 +2025-03-11T12:39:18.546112,479392760,65485,190,-39.85563485764,-51.98139667218,75.080047555795,2,1,18 +2025-03-11T12:39:18.561737,479392760,65485,190,-39.76610692186,-51.90268354482,74.91324094636,2,1,18 +2025-03-11T12:39:18.577362,479392760,65485,190,-39.68600297932,-51.81474457974,74.737168452805,2,1,18 +2025-03-11T12:39:18.592987,479392760,65485,190,-39.60589903678,-51.71756347101,74.574922428445,2,1,18 +2025-03-11T12:39:18.608612,479392760,65485,190,-39.51165910438,-51.62497897521,74.408053418005,2,1,18 +2025-03-11T12:39:18.624237,479392760,65485,190,-39.40328318212,-51.523127876865,74.236505801485,2,1,18 +2025-03-11T12:39:18.639862,479392760,65485,190,-39.31375524634,-51.43979367768,74.055817102855,2,1,18 +2025-03-11T12:39:18.655487,479392760,65485,190,-39.22422731056,-51.33335411937,73.865793338095,2,1,18 +2025-03-11T12:39:18.671112,479392760,65485,190,-39.1158513883,-51.231503021025,73.694245721575,2,1,18 +2025-03-11T12:39:18.686737,479392760,65485,190,-39.01218746266,-51.14352329112,73.51351813993,2,1,18 +2025-03-11T12:39:18.702362,479392760,65485,190,-38.90852353702,-51.046301417565,73.332753478285,2,1,18 +2025-03-11T12:39:18.717987,479392760,65485,190,-38.79543561814,-50.92133680713,73.13337928237,2,1,18 +2025-03-11T12:39:18.733612,479392760,65485,190,-38.6917716925,-50.814872789925,72.924850442335,2,1,18 +2025-03-11T12:39:18.749237,479392760,65485,190,-38.58339577024,-50.69453740428,72.707016835165,2,1,18 +2025-03-11T12:39:18.764862,479392760,65485,190,-38.47030785136,-50.58343600932,72.50769825925,2,1,18 +2025-03-11T12:39:18.780487,479392760,65485,190,-38.3619319291,-50.47696383915,72.30840500434,2,1,18 +2025-03-11T12:39:18.796112,479392760,65485,190,-38.24884401022,-50.361241372365,72.10444670536,2,1,18 +2025-03-11T12:39:18.811737,479392760,65485,190,-38.13575609134,-50.24551890558,71.895867223315,2,1,18 +2025-03-11T12:39:18.827362,479392760,65485,190,-38.02266817246,-50.14365965427,71.6965857274,2,1,18 +2025-03-11T12:39:18.842987,479392760,65485,190,-37.89544426372,-50.023291656765,71.47872499621,2,1,18 +2025-03-11T12:39:18.858612,479392760,65485,190,-37.7729323516,-49.893689668575,71.251591599895,2,1,18 +2025-03-11T12:39:18.874237,479392760,65485,190,-37.65984443272,-49.75948291449,71.029074408655,2,1,18 +2025-03-11T12:39:18.889862,479392760,65485,190,-37.51848453412,-49.62984831444,70.80191388832,2,1,18 +2025-03-11T12:39:18.905487,479392760,65485,190,-37.38183663214,-49.49560079553,70.56549924286,2,1,18 +2025-03-11T12:39:18.921112,479392760,65485,190,-37.26403671664,-49.35214374483,70.33831700755,2,1,18 +2025-03-11T12:39:18.936737,479392760,65485,190,-37.14152480452,-49.22254175664,70.06959296365,2,1,18 +2025-03-11T12:39:18.952362,479392760,65485,190,-37.0190128924,-49.097560840275,69.83785692427,2,1,18 +2025-03-11T12:39:18.967987,479392760,65485,190,-36.88707698704,-48.967942546155,69.60608878288,2,1,18 +2025-03-11T12:39:18.983612,479392760,65485,190,-36.74100509182,-48.833678721315,69.346554660085,2,1,18 +2025-03-11T12:39:18.999237,479392760,65485,190,-36.59022119998,-48.694785671685,69.068510484025,2,1,18 +2025-03-11T12:39:19.014862,479392760,65485,190,-36.46299729124,-48.560554458705,68.822867034445,2,1,18 +2025-03-11T12:39:19.030487,479392760,65485,190,-36.3357733825,-48.4032178866,68.56326733567,2,1,18 +2025-03-11T12:39:19.046112,479392760,65485,190,-36.18498949066,-48.27356698062,68.312987338,2,1,18 +2025-03-11T12:39:19.061737,479392760,65485,190,-36.03891759544,-48.13006101213,68.062658501335,2,1,18 +2025-03-11T12:39:19.077362,479392760,65485,190,-35.89284570022,-47.981933971815,67.779962843215,2,1,18 +2025-03-11T12:39:19.092987,479392760,65485,190,-35.74206180838,-47.82917770671,67.50648423022,2,1,18 +2025-03-11T12:39:19.108612,479392760,65485,190,-35.59127791654,-47.69028465708,67.196091772705,2,1,18 +2025-03-11T12:39:19.124237,479392760,65485,190,-35.42635803484,-47.52826178943,66.92717691976,2,1,18 +2025-03-11T12:39:19.139862,479392760,65485,190,-35.28028613962,-47.35702938999,66.65363092777,2,1,18 +2025-03-11T12:39:19.155487,479392760,65485,190,-35.1342142444,-47.199660206025,66.366277006585,2,1,18 +2025-03-11T12:39:19.171112,479392760,65485,190,-34.97871835594,-47.046895787955,66.08817042952,2,1,18 +2025-03-11T12:39:19.186737,479392760,65485,190,-34.81851047086,-46.90336536057,65.796230602255,2,1,18 +2025-03-11T12:39:19.202362,479392760,65485,190,-34.65830258578,-46.741350645885,65.508837798055,2,1,18 +2025-03-11T12:39:19.217987,479392760,65485,190,-34.48867070746,-46.57931962527,65.22605261491,2,1,18 +2025-03-11T12:39:19.233612,479392760,65485,190,-34.32846282238,-46.408062766935,64.924759181515,2,1,18 +2025-03-11T12:39:19.249237,479392760,65485,190,-34.16354294068,-46.236797755635,64.63732251631,2,1,18 +2025-03-11T12:39:19.264862,479392760,65485,190,-33.99391106236,-46.07476673502,64.31294668558,2,1,18 +2025-03-11T12:39:19.280487,479392760,65485,190,-33.82427918404,-45.90811464258,63.983931131785,2,1,18 +2025-03-11T12:39:19.296112,479392760,65485,190,-33.65935930234,-45.722986415805,63.664090565125,2,1,18 +2025-03-11T12:39:19.311737,479392760,65485,190,-33.49443942064,-45.54710033268,63.34890826153,2,1,18 +2025-03-11T12:39:19.327362,479392760,65485,190,-33.31538354908,-45.38043193431,63.038363877985,2,1,18 +2025-03-11T12:39:19.342987,479392760,65485,190,-33.12219168766,-45.20911800522,62.72315942836,2,1,18 +2025-03-11T12:39:19.358612,479392760,65485,190,-32.94784781272,-45.005489185215,62.389367590495,2,1,18 +2025-03-11T12:39:19.374237,479392760,65485,190,-32.7782159344,-44.829594949125,62.0603149567,2,1,18 +2025-03-11T12:39:19.389862,479392760,65485,190,-32.60858405608,-44.65832178486,61.72665967984,2,1,18 +2025-03-11T12:39:19.405487,479392760,65485,190,-32.4248161879,-44.4685398744,61.40677344916,2,1,18 +2025-03-11T12:39:19.421112,479392760,65485,190,-32.2363363231,-44.2833708828,61.086898977475,2,1,18 +2025-03-11T12:39:19.436737,479392760,65485,190,-32.06199244816,-44.098226350095,60.74393893348,2,1,18 +2025-03-11T12:39:19.452362,479392760,65485,190,-31.8829365766,-43.91769473625,60.405611831545,2,1,18 +2025-03-11T12:39:19.467987,479392760,65485,190,-31.67560872532,-43.718629917315,60.07641224971,2,1,18 +2025-03-11T12:39:19.483612,479392760,65485,190,-31.48712886052,-43.533460925715,59.738053045765,2,1,18 +2025-03-11T12:39:19.499237,479392760,65485,190,-31.30336099234,-43.352921158905,59.399719162825,2,1,18 +2025-03-11T12:39:19.514862,479392760,65485,190,-31.11488112754,-43.149267880005,59.04280106662,2,1,18 +2025-03-11T12:39:19.530487,479392760,65485,190,-30.93582525598,-42.95949412251,58.667467420165,2,1,18 +2025-03-11T12:39:19.546112,479392760,65485,190,-30.73320940132,-42.765058528365,58.30594487788,2,1,18 +2025-03-11T12:39:19.561737,479392760,65485,190,-30.53059354666,-42.57062293422,57.953664701725,2,1,18 +2025-03-11T12:39:19.577362,479392760,65485,190,-30.33740168524,-42.366961502355,57.60136100758,2,1,18 +2025-03-11T12:39:19.592987,479392760,65485,190,-30.14420982382,-42.18178435779,57.24451029037,2,1,18 +2025-03-11T12:39:19.608612,479392760,65485,190,-29.94630596578,-41.982735844785,56.90146072135,2,1,18 +2025-03-11T12:39:19.624237,479392760,65485,190,-29.7389781145,-41.779049954025,56.51216721967,2,1,18 +2025-03-11T12:39:19.639862,479392760,65485,190,-29.53165026322,-41.575364063265,56.13211608412,2,1,18 +2025-03-11T12:39:19.655487,479392760,65485,190,-29.32432241194,-41.36705710068,55.77053114083,2,1,18 +2025-03-11T12:39:19.671112,479392760,65485,190,-29.11228256404,-41.16798412878,55.38587058121,2,1,18 +2025-03-11T12:39:19.686737,479392760,65485,190,-28.89553071952,-40.95503978844,54.99652643752,2,1,18 +2025-03-11T12:39:19.702362,479392760,65485,190,-28.7023388581,-40.74675728475,54.607234738855,2,1,18 +2025-03-11T12:39:19.717987,479392760,65485,190,-28.50914699668,-40.51999049376,54.20862651406,2,1,18 +2025-03-11T12:39:19.733612,479392760,65485,190,-28.29239515216,-40.311667225245,53.8285432765,2,1,18 +2025-03-11T12:39:19.749237,479392760,65485,190,-28.0662193144,-40.098706578975,53.4391855708,2,1,18 +2025-03-11T12:39:19.764862,479392760,65485,190,-27.84475547326,-39.881133013845,53.04519492304,2,1,18 +2025-03-11T12:39:19.780487,479392760,65485,190,-27.62800362874,-39.658946529855,52.651192516285,2,1,18 +2025-03-11T12:39:19.796112,479392760,65485,190,-27.40182779098,-39.44136481176,52.243331538325,2,1,18 +2025-03-11T12:39:19.811737,479392760,65485,190,-27.18507594646,-39.214557255945,51.84006822544,2,1,18 +2025-03-11T12:39:19.827362,479392760,65485,190,-26.96832410194,-38.992370771955,51.427581086425,2,1,18 +2025-03-11T12:39:19.842987,479392760,65485,190,-26.7468602608,-38.77941827865,51.01050306334,2,1,18 +2025-03-11T12:39:19.858612,479392760,65485,190,-26.52068442304,-38.55721548873,50.607244728445,2,1,18 +2025-03-11T12:39:19.874237,479392760,65485,190,-26.29450858528,-38.321149483335,50.21317313968,2,1,18 +2025-03-11T12:39:19.889862,479392760,65485,190,-26.0636207509,-38.09893854045,49.81915038991,2,1,18 +2025-03-11T12:39:19.905487,479392760,65485,190,-25.83273291652,-37.89059081304,49.40669852788,2,1,18 +2025-03-11T12:39:19.921112,479392760,65485,190,-25.615981072,-37.6591621854,48.975689576605,2,1,18 +2025-03-11T12:39:19.936737,479392760,65485,190,-25.380381241,-37.41845880225,48.539995238245,2,1,18 +2025-03-11T12:39:19.952362,479392760,65485,190,-25.15420540324,-37.182392796855,48.113575368025,2,1,18 +2025-03-11T12:39:19.967987,479392760,65485,190,-24.92802956548,-36.94632679146,47.69177668087,2,1,18 +2025-03-11T12:39:19.983612,479392760,65485,190,-24.6971417311,-36.70101048945,47.26069176658,2,1,18 +2025-03-11T12:39:19.999237,479392760,65485,190,-24.4615419001,-36.464928178125,46.83425833435,2,1,18 +2025-03-11T12:39:20.014862,479392760,65485,190,-24.23065406572,-36.23347509159,46.417092589255,2,1,18 +2025-03-11T12:39:20.030487,479392760,65485,190,-23.99505423472,-35.997392780265,45.97679560783,2,1,18 +2025-03-11T12:39:20.046112,479392760,65485,190,-23.74531841386,-35.761286010045,45.541099466455,2,1,18 +2025-03-11T12:39:20.061737,479392760,65485,190,-23.50029458962,-35.529808464615,45.105428646085,2,1,18 +2025-03-11T12:39:20.077362,479392760,65485,190,-23.26469475862,-35.27524186599,44.678921053855,2,1,18 +2025-03-11T12:39:20.092987,479392760,65485,190,-23.02909492762,-35.02529633919,44.24781081856,2,1,18 +2025-03-11T12:39:20.108612,479392760,65485,190,-22.79349509662,-34.80307724334,43.8121906402,2,1,18 +2025-03-11T12:39:20.124237,479392760,65485,190,-22.54847127238,-34.566978626085,43.3672589137,2,1,18 +2025-03-11T12:39:20.139862,479392760,65485,190,-22.30344744814,-34.307774649705,42.91299212107,2,1,18 +2025-03-11T12:39:20.155487,479392760,65485,190,-22.05371162728,-34.062425735835,42.4633953505,2,1,18 +2025-03-11T12:39:20.171112,479392760,65485,190,-21.80868780304,-33.80784283128,41.995283548675,2,1,18 +2025-03-11T12:39:20.186737,479392760,65485,190,-21.55895198218,-33.557872845585,41.55028942117,2,1,18 +2025-03-11T12:39:20.202362,479392760,65485,190,-21.29508017146,-33.317120544645,41.08682729839,2,1,18 +2025-03-11T12:39:20.217987,479392760,65485,190,-21.05476834384,-33.05792472123,40.6279461037,2,1,18 +2025-03-11T12:39:20.233612,479392760,65485,190,-20.8097445196,-32.79872074485,40.17367931107,2,1,18 +2025-03-11T12:39:20.249237,479392760,65485,190,-20.56000869874,-32.539508615505,39.70554218824,2,1,18 +2025-03-11T12:39:20.264862,479392760,65485,190,-20.31027287788,-32.28953862981,39.223578596215,2,1,18 +2025-03-11T12:39:20.280487,479392760,65485,190,-20.04168907054,-32.021051744955,38.75999845243,2,1,18 +2025-03-11T12:39:20.296112,479392760,65485,190,-19.7966652463,-31.761847768575,38.29648929367,2,1,18 +2025-03-11T12:39:20.311737,479392760,65485,190,-19.55635341868,-31.49340980151,37.814465103655,2,1,18 +2025-03-11T12:39:20.327362,479392760,65485,190,-19.2783456181,-31.224906610725,37.34162903173,2,1,18 +2025-03-11T12:39:20.342987,479392760,65485,190,-19.00976181076,-30.979525084995,36.87352040488,2,1,18 +2025-03-11T12:39:20.358612,479392760,65485,190,-18.74589000004,-30.729530640405,36.405400019035,2,1,18 +2025-03-11T12:39:20.374237,479392760,65485,190,-18.48673018594,-30.474923276955,35.93264669113,2,1,18 +2025-03-11T12:39:20.389862,479392760,65485,190,-18.22285837522,-30.21106561689,35.455228319155,2,1,18 +2025-03-11T12:39:20.405487,479392760,65485,190,-17.97312255436,-29.933369200245,34.98239585326,2,1,18 +2025-03-11T12:39:20.421112,479392760,65485,190,-17.71867473688,-29.66952784611,34.50961222636,2,1,18 +2025-03-11T12:39:20.436737,479392760,65485,190,-17.45009092954,-29.42414632038,34.018397684185,2,1,18 +2025-03-11T12:39:20.452362,479392760,65485,190,-17.1815071222,-29.164901579175,33.531748705075,2,1,18 +2025-03-11T12:39:20.467987,479392760,65485,190,-16.92705930472,-28.90106022504,33.05434389511,2,1,18 +2025-03-11T12:39:20.483612,479392760,65485,190,-16.663187494,-28.627960421325,32.558403710875,2,1,18 +2025-03-11T12:39:20.499237,479392760,65485,190,-16.38989169004,-28.36408645533,32.08097177689,2,1,18 +2025-03-11T12:39:20.514862,479392760,65485,190,-16.11188388946,-28.077098977245,31.589576812705,2,1,18 +2025-03-11T12:39:20.530487,479392760,65485,190,-15.84801207874,-27.799378101705,31.079754539275,2,1,18 +2025-03-11T12:39:20.546112,479392760,65485,190,-15.57000427816,-27.52163276727,30.58839665509,2,1,18 +2025-03-11T12:39:20.561737,479392760,65485,190,-15.29199647758,-27.262371720135,30.10173411397,2,1,18 +2025-03-11T12:39:20.577362,479392760,65485,190,-15.013988677,-26.99386852935,29.59654976059,2,1,18 +2025-03-11T12:39:20.592987,479392760,65485,190,-14.75011686628,-26.720768725635,29.091367210225,2,1,18 +2025-03-11T12:39:20.608612,479392760,65485,190,-14.46739706908,-26.43839416641,28.590741638905,2,1,18 +2025-03-11T12:39:20.624237,479392760,65485,190,-14.17996527526,-26.142148238745,28.08081130045,2,1,18 +2025-03-11T12:39:20.639862,479392760,65485,190,-13.90195747468,-25.88288719161,27.589527576265,2,1,18 +2025-03-11T12:39:20.655487,479392760,65485,190,-13.63808566396,-25.61440845972,27.079742382835,2,1,18 +2025-03-11T12:39:20.671112,479392760,65485,190,-13.36478986,-25.332050206425,26.579130373525,2,1,18 +2025-03-11T12:39:20.686737,479392760,65485,190,-13.09149405604,-25.04969195313,26.05541244889,2,1,18 +2025-03-11T12:39:20.702362,479392760,65485,190,-12.81348625546,-24.771946618695,25.55019101551,2,1,18 +2025-03-11T12:39:20.717987,479392760,65485,190,-12.52605446164,-24.49418497833,25.05419838625,2,1,18 +2025-03-11T12:39:20.733612,479392760,65485,190,-12.24804666106,-24.20257642842,24.562784882065,2,1,18 +2025-03-11T12:39:20.749237,479392760,65485,190,-11.98417485034,-23.91561340923,24.03906197944,2,1,18 +2025-03-11T12:39:20.764862,479392760,65485,190,-11.70616704976,-23.637868074795,23.510734630735,2,1,18 +2025-03-11T12:39:20.780487,479392760,65485,190,-11.41873525594,-23.35086429078,22.977735456955,2,1,18 +2025-03-11T12:39:20.796112,479392760,65485,190,-11.14543945198,-23.059263893835,22.467844001515,2,1,18 +2025-03-11T12:39:20.811737,479392760,65485,190,-10.85800765816,-22.76301796617,21.981019578385,2,1,18 +2025-03-11T12:39:20.827362,479392760,65485,190,-10.57057586434,-22.485256325805,21.4619210338,2,1,18 +2025-03-11T12:39:20.842987,479392760,65485,190,-10.28785606714,-22.20288176658,20.938189547155,2,1,18 +2025-03-11T12:39:20.858612,479392760,65485,190,-10.00513626994,-21.938991494655,20.400668671315,2,1,18 +2025-03-11T12:39:20.874237,479392760,65485,190,-9.7129924795,-21.651979557675,19.863041533465,2,1,18 +2025-03-11T12:39:20.889862,479392760,65485,190,-9.41142469582,-21.346467027465,19.343811405865,2,1,18 +2025-03-11T12:39:20.905487,479392760,65485,190,-9.11456890876,-21.054825865695,18.829264862335,2,1,18 +2025-03-11T12:39:20.921112,479392760,65485,190,-8.8177131217,-20.7770479194,18.314773938805,2,1,18 +2025-03-11T12:39:20.936737,479392760,65485,190,-8.53028132788,-20.49466520721,17.781793305025,2,1,18 +2025-03-11T12:39:20.952362,479392760,65485,190,-8.26169752054,-20.198451891405,17.26264772446,2,1,18 +2025-03-11T12:39:20.967987,479392760,65485,190,-7.98368971996,-19.91146441332,16.73890447882,2,1,18 +2025-03-11T12:39:20.983612,479392760,65485,190,-7.69154592952,-19.63369461999,16.205935604035,2,1,18 +2025-03-11T12:39:20.999237,479392760,65485,190,-7.38997814584,-19.31893994613,15.677426030305,2,1,18 +2025-03-11T12:39:21.014862,479392760,65485,190,-7.08369836554,-19.022661406605,15.14898383557,2,1,18 +2025-03-11T12:39:21.030487,479392760,65485,190,-6.7915545751,-18.74027054145,14.61137523772,2,1,18 +2025-03-11T12:39:21.046112,479392760,65485,190,-6.5088347779,-18.448653838575,14.069121938815,2,1,18 +2025-03-11T12:39:21.061737,479392760,65485,190,-6.24025097056,-18.157061594595,13.52226779986,2,1,18 +2025-03-11T12:39:21.077362,479392760,65485,190,-5.95753117336,-17.860823819895,12.979995960955,2,1,18 +2025-03-11T12:39:21.092987,479392760,65485,190,-5.6606753863,-17.559940514475,12.456169971295,2,1,18 +2025-03-11T12:39:21.108612,479392760,65485,190,-5.36853159586,-17.272928577495,11.927785199575,2,1,18 +2025-03-11T12:39:21.124237,479392760,65485,190,-5.06696381218,-16.985900334585,11.390144499715,2,1,18 +2025-03-11T12:39:21.139862,479392760,65485,190,-4.75597203526,-16.689613642095,10.852453157845,2,1,18 +2025-03-11T12:39:21.155487,479392760,65485,190,-4.46854024144,-16.38412557078,10.314758641,2,1,18 +2025-03-11T12:39:21.171112,479392760,65485,190,-4.18110844762,-16.097121786765,9.78175946722,2,1,18 +2025-03-11T12:39:21.186737,479392760,65485,190,-3.88425266056,-15.81934384047,9.2395414453,2,1,18 +2025-03-11T12:39:21.202362,479392760,65485,190,-3.58268487688,-15.52307345391,8.69262129931,2,1,18 +2025-03-11T12:39:21.217987,479392760,65485,190,-3.29996507968,-15.21759353556,8.159554746535,2,1,18 +2025-03-11T12:39:21.233612,479392760,65485,190,-3.00782128924,-14.90285516763,7.61719518562,2,1,18 +2025-03-11T12:39:21.249237,479392760,65485,190,-2.70625350556,-14.59734263742,7.074859142695,2,1,18 +2025-03-11T12:39:21.264862,479392760,65485,190,-2.39997372526,-14.31492731337,6.53723020183,2,1,18 +2025-03-11T12:39:21.280487,479392760,65485,190,-2.09840594158,-14.032520142285,5.99036567584,2,1,18 +2025-03-11T12:39:21.296112,479392760,65485,190,-1.80626215114,-13.717781774355,5.448006114925,2,1,18 +2025-03-11T12:39:21.311737,479392760,65485,190,-1.5141183607,-13.3984223346,4.89638564788,2,1,18 +2025-03-11T12:39:21.327362,479392760,65485,190,-1.22197457026,-13.11141039762,4.3495161439,2,1,18 +2025-03-11T12:39:21.342987,479392760,65485,190,-0.92040678658,-12.801276795585,3.80254037791,2,1,18 +2025-03-11T12:39:21.358612,479392760,65485,190,-0.62826299614,-12.505022714955,3.269497343125,2,1,18 +2025-03-11T12:39:21.374237,479392760,65485,190,-0.32669521246,-12.217994472045,2.73647782633,2,1,18 +2025-03-11T12:39:21.389862,479392760,65485,190,-0.0204154321600001,-11.92171593252,2.189550899335,2,1,18 +2025-03-11T12:39:21.405487,479392760,65485,190,0.28586434814,-11.616195249345,1.637965709275,2,1,18 +2025-03-11T12:39:21.421112,479392760,65485,190,0.5827201352,-11.30144872845,1.095599367355,2,1,18 +2025-03-11T12:39:21.436737,479392760,65485,190,0.87015192902,-11.005202800785,0.562563113575,2,1,18 +2025-03-11T12:39:21.452362,479392760,65485,190,1.16229571946,-10.71356979198,0.0110538865299996,2,1,18 +2025-03-11T12:39:21.467987,479392760,65485,190,1.45915150652,-10.417307558385,-0.517374746195,2,1,18 +2025-03-11T12:39:21.483612,479392760,65485,190,1.77014328344,-10.121020865895,-1.073550820325,2,1,18 +2025-03-11T12:39:21.499237,479392760,65485,190,2.05757507726,-9.83401708188,-1.6204135433,2,1,18 +2025-03-11T12:39:21.514862,479392760,65485,190,2.3497188677,-9.514657642125,-2.172034010345,2,1,18 +2025-03-11T12:39:21.530487,479392760,65485,190,2.64657465476,-9.204532193055,-2.72824536146,2,1,18 +2025-03-11T12:39:21.546112,479392760,65485,190,2.95756643168,-8.90362442874,-3.27519760946,2,1,18 +2025-03-11T12:39:21.561737,479392760,65485,190,3.25913421536,-8.60735404218,-3.82211775545,2,1,18 +2025-03-11T12:39:21.577362,479392760,65485,190,3.54656600918,-8.30648704269,-4.35517254923,2,1,18 +2025-03-11T12:39:21.592987,479392760,65485,190,3.84342179624,-8.000982665445,-4.902122994215,2,1,18 +2025-03-11T12:39:21.608612,479392760,65485,190,4.14970157654,-7.709325197745,-5.481379662665,2,1,18 +2025-03-11T12:39:21.624237,479392760,65485,190,4.44184536698,-7.41769218894,-6.028267706645,2,1,18 +2025-03-11T12:39:21.639862,479392760,65485,190,4.73870115404,-7.121429955345,-6.5659387055,2,1,18 +2025-03-11T12:39:21.655487,479392760,65485,190,5.04026893772,-6.815917425135,-7.10365356536,2,1,18 +2025-03-11T12:39:21.671112,479392760,65485,190,5.3418367214,-6.510404894925,-7.65061079135,2,1,18 +2025-03-11T12:39:21.686737,479392760,65485,190,5.64340450508,-6.21875558019,-8.2159971296,2,1,18 +2025-03-11T12:39:21.702362,479392760,65485,190,5.95910827862,-5.91783966291,-8.744471426345,2,1,18 +2025-03-11T12:39:21.717987,479392760,65485,190,6.26538805892,-5.621561123385,-9.27291362108,2,1,18 +2025-03-11T12:39:21.733612,479392760,65485,190,6.55753184936,-5.343791330055,-9.81974604506,2,1,18 +2025-03-11T12:39:21.749237,479392760,65485,190,6.85909963304,-5.038278799845,-10.380566820245,2,1,18 +2025-03-11T12:39:21.764862,479392760,65485,190,7.14653142686,-4.718927513055,-10.92755932322,2,1,18 +2025-03-11T12:39:21.780487,479392760,65485,190,7.4386752173,-4.40881021695,-11.469900344135,2,1,18 +2025-03-11T12:39:21.796112,479392760,65485,190,7.73553100436,-4.094063696055,-11.993781953795,2,1,18 +2025-03-11T12:39:21.811737,479392760,65485,190,8.03709878804,-3.788551165845,-12.53611799672,2,1,18 +2025-03-11T12:39:21.827362,479392760,65485,190,8.3339545751,-3.5015310759,-13.073751915575,2,1,18 +2025-03-11T12:39:21.842987,479392760,65485,190,8.63081036216,-3.205268842305,-13.62990764669,2,1,18 +2025-03-11T12:39:21.858612,479392760,65485,190,8.92766614922,-2.90900660871,-14.16295746248,2,1,18 +2025-03-11T12:39:21.874237,479392760,65485,190,9.22452193628,-2.59888115964,-14.71454763053,2,1,18 +2025-03-11T12:39:21.889862,479392760,65485,190,9.52608971996,-2.30261077308,-15.266088959585,2,1,18 +2025-03-11T12:39:21.905487,479392760,65485,190,9.8182335104,-2.001735620625,-15.803771717435,2,1,18 +2025-03-11T12:39:21.921112,479392760,65485,190,10.11037730084,-1.71934475547,-16.33675913222,2,1,18 +2025-03-11T12:39:21.936737,479392760,65485,190,10.40252109128,-1.427711746665,-16.87440481007,2,1,18 +2025-03-11T12:39:21.952362,479392760,65485,190,10.69937687834,-1.12220736942,-17.421355255055,2,1,18 +2025-03-11T12:39:21.967987,479392760,65485,190,10.99152066878,-0.821332216965,-17.968280379035,2,1,18 +2025-03-11T12:39:21.983612,479392760,65485,190,11.29308845246,-0.543546117705,-18.50126281583,2,1,18 +2025-03-11T12:39:21.999160,479392764,65480,191,11.59465623614,-0.238033587494999,-19.043598858755,2,1,18 +2025-03-11T12:39:22.014785,479392764,65480,191,11.88680002658,0.0628415649599994,-19.599766348865,2,1,18 +2025-03-11T12:39:22.030410,479392764,65480,191,12.1742318204,0.359087492625,-20.132802602645,2,1,18 +2025-03-11T12:39:22.046035,479392764,65480,191,12.47579960408,0.655357879185,-20.661238016375,2,1,18 +2025-03-11T12:39:22.061660,479392764,65480,191,12.77736738776,0.960870409395,-21.2035740593,2,1,18 +2025-03-11T12:39:22.077285,479392764,65480,191,13.07893517144,1.25251972413,-21.74123329916,2,1,18 +2025-03-11T12:39:22.092910,479392764,65480,191,13.38050295512,1.53030582339,-22.274215735955,2,1,18 +2025-03-11T12:39:22.108535,479392764,65480,191,13.6585107557,1.835777588775,-22.82113905692,2,1,18 +2025-03-11T12:39:22.124160,479392764,65480,191,13.9412305529,2.12739429165,-23.354149989695,2,1,18 +2025-03-11T12:39:22.139785,479392764,65480,191,14.23337434334,2.409785156805,-23.87789503835,2,1,18 +2025-03-11T12:39:22.155410,479392764,65480,191,14.53494212702,2.696813399715,-24.401672189015,2,1,18 +2025-03-11T12:39:22.171035,479392764,65480,191,14.81766192422,2.993051174415,-24.94394402792,2,1,18 +2025-03-11T12:39:22.186660,479392764,65480,191,15.10509371804,3.29853924573,-25.463153812505,2,1,18 +2025-03-11T12:39:22.202285,479392764,65480,191,15.39723750848,3.59479332636,-25.973090931965,2,1,18 +2025-03-11T12:39:22.217910,479392764,65480,191,15.68938129892,3.88180526334,-26.48761215449,2,1,18 +2025-03-11T12:39:22.233535,479392764,65480,191,15.97210109612,4.16880089439,-27.020604547265,2,1,18 +2025-03-11T12:39:22.249160,479392764,65480,191,16.25953288994,4.465046822055,-27.55826198411,2,1,18 +2025-03-11T12:39:22.264785,479392764,65480,191,16.54225268714,4.74742138128,-28.09585701995,2,1,18 +2025-03-11T12:39:22.280410,479392764,65480,191,16.8391084742,5.02057825575,-28.61957176961,2,1,18 +2025-03-11T12:39:22.296035,479392764,65480,191,17.1453882545,5.307614651625,-29.12487096902,2,1,18 +2025-03-11T12:39:22.311660,479392764,65480,191,17.41868405846,5.60845719222,-29.65328423672,2,1,18 +2025-03-11T12:39:22.327285,479392764,65480,191,17.70611585228,5.895460976235,-30.190904593565,2,1,18 +2025-03-11T12:39:22.342910,479392764,65480,191,17.98883564948,6.173214463635,-30.69613280795,2,1,18 +2025-03-11T12:39:22.358535,479392764,65480,191,18.25741945682,6.46018563579,-31.205998942385,2,1,18 +2025-03-11T12:39:22.374160,479392764,65480,191,18.54956324726,6.742576500945,-31.725122807975,2,1,18 +2025-03-11T12:39:22.389785,479392764,65480,191,18.83228304446,7.03419320382,-32.24889137462,2,1,18 +2025-03-11T12:39:22.405410,479392764,65480,191,19.11500284166,7.316567763045,-32.7680016782,2,1,18 +2025-03-11T12:39:22.421035,479392764,65480,191,19.39772263886,7.603563394095,-33.25016105726,2,1,18 +2025-03-11T12:39:22.436660,479392764,65480,191,19.6898664293,7.88595425925,-33.76004255672,2,1,18 +2025-03-11T12:39:22.452285,479392764,65480,191,19.96787422988,8.182183880985,-34.27458051623,2,1,18 +2025-03-11T12:39:22.467910,479392764,65480,191,20.2553060237,8.4507033777,-34.784399614685,2,1,18 +2025-03-11T12:39:22.483535,479392764,65480,191,20.53331382428,8.719206568485,-35.280341601935,2,1,18 +2025-03-11T12:39:22.499160,479392764,65480,191,20.81132162486,8.99695190292,-35.785563035315,2,1,18 +2025-03-11T12:39:22.514785,479392764,65480,191,21.0799054322,9.274680931425,-36.28614972362,2,1,18 +2025-03-11T12:39:22.530410,479392764,65480,191,21.35320123616,9.543175969245,-36.809812028255,2,1,18 +2025-03-11T12:39:22.546035,479392764,65480,191,21.62649704012,9.820913150715,-37.3057843145,2,1,18 +2025-03-11T12:39:22.561660,479392764,65480,191,21.9045048407,10.103279556975,-37.787918372555,2,1,18 +2025-03-11T12:39:22.577285,479392764,65480,191,22.16837665142,10.37637936069,-38.269995007595,2,1,18 +2025-03-11T12:39:22.592910,479392764,65480,191,22.43696045876,10.65872946102,-38.7706002359,2,1,18 +2025-03-11T12:39:22.608535,479392764,65480,191,22.71025626272,10.941087714315,-39.285075794405,2,1,18 +2025-03-11T12:39:22.624160,479392764,65480,191,22.97884007006,11.204953527345,-39.77636449658,2,1,18 +2025-03-11T12:39:22.639785,479392764,65480,191,23.25213587402,11.473448565165,-40.272299702825,2,1,18 +2025-03-11T12:39:22.655410,479392764,65480,191,23.52071968136,11.746556521845,-40.786731400325,2,1,18 +2025-03-11T12:39:22.671035,479392764,65480,191,23.7893034887,12.019664478525,-41.28729954863,2,1,18 +2025-03-11T12:39:22.686660,479392764,65480,191,24.06259929266,12.278917372695,-41.746228210355,2,1,18 +2025-03-11T12:39:22.702285,479392764,65480,191,24.33589509662,12.547412410515,-42.22367868434,2,1,18 +2025-03-11T12:39:22.717910,479392764,65480,191,24.60447890396,12.811278223545,-42.71034620345,2,1,18 +2025-03-11T12:39:22.733535,479392764,65480,191,24.8730627113,13.084386180225,-43.22477790095,2,1,18 +2025-03-11T12:39:22.749160,479392764,65480,191,25.11808653554,13.343590156605,-43.692908242775,2,1,18 +2025-03-11T12:39:22.764785,479392764,65480,191,25.37253435302,13.60743151074,-44.17031305274,2,1,18 +2025-03-11T12:39:22.780410,479392764,65480,191,25.64111816036,13.88053946742,-44.670881201045,2,1,18 +2025-03-11T12:39:22.796035,479392764,65480,191,25.91441396432,14.135171289765,-45.152897238095,2,1,18 +2025-03-11T12:39:22.811660,479392764,65480,191,26.17828577504,14.38054466253,-45.616377900875,2,1,18 +2025-03-11T12:39:22.827285,479392764,65480,191,26.43273359252,14.625901729365,-46.107572100035,2,1,18 +2025-03-11T12:39:22.842910,479392764,65480,191,26.69189340662,14.89437230829,-46.58038104794,2,1,18 +2025-03-11T12:39:22.858535,479392764,65480,191,26.96518921058,15.158246274285,-47.030085883535,2,1,18 +2025-03-11T12:39:22.874160,479392764,65480,191,27.2290610213,15.408240718875,-47.521312184705,2,1,18 +2025-03-11T12:39:22.889785,479392764,65480,191,27.47408484554,15.667444695255,-47.9802001604,2,1,18 +2025-03-11T12:39:22.905410,479392764,65480,191,27.7238206664,15.922035752775,-48.44831874323,2,1,18 +2025-03-11T12:39:22.921035,479392764,65480,191,27.96884449064,16.18586080098,-48.91184644199,2,1,18 +2025-03-11T12:39:22.936660,479392764,65480,191,28.21386831488,16.449685849185,-49.37537414075,2,1,18 +2025-03-11T12:39:22.952285,479392764,65480,191,28.47302812898,16.69967214081,-49.82500301333,2,1,18 +2025-03-11T12:39:22.967910,479392764,65480,191,28.72276394984,16.96350534198,-50.288537493095,2,1,18 +2025-03-11T12:39:22.983535,479392764,65480,191,28.97721176732,17.199620265165,-50.71961923241,2,1,18 +2025-03-11T12:39:22.999160,479392764,65480,191,29.2316595848,17.45421947565,-51.150775131725,2,1,18 +2025-03-11T12:39:23.014785,479392764,65480,191,29.48610740228,17.70419761431,-51.623503138625,2,1,18 +2025-03-11T12:39:23.030410,479392764,65480,191,29.73113122652,17.95415944704,-52.07311166819,2,1,18 +2025-03-11T12:39:23.046035,479392764,65480,191,29.985579044,18.190274370225,-52.52729932283,2,1,18 +2025-03-11T12:39:23.061660,479392764,65480,191,30.23060286824,18.43561513113,-52.986131678525,2,1,18 +2025-03-11T12:39:23.077285,479392764,65480,191,30.47562669248,18.690198035685,-53.43575874809,2,1,18 +2025-03-11T12:39:23.092910,479392764,65480,191,30.71122652348,18.940143562485,-53.866868983385,2,1,18 +2025-03-11T12:39:23.108535,479392764,65480,191,30.927978368,19.1669511183,-54.28861702853,2,1,18 +2025-03-11T12:39:23.124160,479392764,65480,191,31.15415420576,19.393774980045,-54.72424218488,2,1,18 +2025-03-11T12:39:23.139785,479392764,65480,191,31.39446603338,19.64372865981,-55.16460156731,2,1,18 +2025-03-11T12:39:23.155410,479392764,65480,191,31.65362584748,19.87985173596,-55.600311270695,2,1,18 +2025-03-11T12:39:23.171035,479392764,65480,191,31.89864967172,20.115950353215,-56.036000631065,2,1,18 +2025-03-11T12:39:23.186660,479392764,65480,191,32.12011351286,20.342766061995,-56.44389190802,2,1,18 +2025-03-11T12:39:23.202285,479392764,65480,191,32.341577354,20.58344498625,-56.879565903365,2,1,18 +2025-03-11T12:39:23.217910,479392764,65480,191,32.56775319176,20.81488991982,-57.315209599715,2,1,18 +2025-03-11T12:39:23.233535,479392764,65480,191,32.80806501938,21.046359312285,-57.73238890682,2,1,18 +2025-03-11T12:39:23.249160,479392764,65480,191,33.048376847,21.27782870475,-58.158810580055,2,1,18 +2025-03-11T12:39:23.264785,479392764,65480,191,33.27455268476,21.51851578197,-58.57138544108,2,1,18 +2025-03-11T12:39:23.280410,479392764,65480,191,33.51015251576,21.754598093295,-58.974712957985,2,1,18 +2025-03-11T12:39:23.296035,479392764,65480,191,33.75046434338,21.98606748576,-59.387271082025,2,1,18 +2025-03-11T12:39:23.311660,479392764,65480,191,33.97664018114,22.203649203855,-59.79975324305,2,1,18 +2025-03-11T12:39:23.327285,479392764,65480,191,34.19810402228,22.421222768985,-60.216849806135,2,1,18 +2025-03-11T12:39:23.342910,479392764,65480,191,34.4148558668,22.6480303248,-60.624734302085,2,1,18 +2025-03-11T12:39:23.358535,479392764,65480,191,34.63631970794,22.870224961755,-61.027985855975,2,1,18 +2025-03-11T12:39:23.374160,479392764,65480,191,34.85307155246,23.09703251757,-61.426627985795,2,1,18 +2025-03-11T12:39:23.389785,479392764,65480,191,35.06511140036,23.309968704945,-61.829828897675,2,1,18 +2025-03-11T12:39:23.405410,479392764,65480,191,35.27243925164,23.532138883005,-62.219196559355,2,1,18 +2025-03-11T12:39:23.421035,479392764,65480,191,35.48447909954,23.76355935768,-62.61785044817,2,1,18 +2025-03-11T12:39:23.436660,479392764,65480,191,35.70594294068,23.958027563685,-62.988642480605,2,1,18 +2025-03-11T12:39:23.452285,479392764,65480,191,35.92740678182,24.17098005699,-63.373372222235,2,1,18 +2025-03-11T12:39:23.467910,479392764,65480,191,36.14415862634,24.360819038205,-63.762623665925,2,1,18 +2025-03-11T12:39:23.483535,479392764,65480,191,36.346774481,24.55525463235,-64.128767391275,2,1,18 +2025-03-11T12:39:23.499160,479392764,65480,191,36.54467833904,24.782029576305,-64.518140030945,2,1,18 +2025-03-11T12:39:23.514785,479392764,65480,191,36.75671818694,24.990344691855,-64.8982164875,2,1,18 +2025-03-11T12:39:23.530410,479392764,65480,191,36.96404603822,25.20789379809,-65.264459693855,2,1,18 +2025-03-11T12:39:23.546035,479392764,65480,191,37.15723789964,25.42541844543,-65.639924923325,2,1,18 +2025-03-11T12:39:23.561660,479392764,65480,191,37.35042976106,25.61521666182,-66.015278912795,2,1,18 +2025-03-11T12:39:23.577285,479392764,65480,191,37.55775761234,25.80041826528,-66.376771156085,2,1,18 +2025-03-11T12:39:23.592910,479392764,65480,191,37.760373467,26.0087170749,-66.73834931837,2,1,18 +2025-03-11T12:39:23.608535,479392764,65480,191,37.9488533318,26.216991425625,-67.09990713764,2,1,18 +2025-03-11T12:39:23.624160,479392764,65480,191,38.1373331966,26.4160236327,-67.47067024304,2,1,18 +2025-03-11T12:39:23.639785,479392764,65480,191,38.33994905126,26.601217083195,-67.822913339195,2,1,18 +2025-03-11T12:39:23.655410,479392764,65480,191,38.53314091268,26.800257443235,-68.170577310275,2,1,18 +2025-03-11T12:39:23.671035,479392764,65480,191,38.72162077748,26.994668578485,-68.51821596035,2,1,18 +2025-03-11T12:39:23.686660,479392764,65480,191,38.9148126389,27.17984572305,-68.84733957917,2,1,18 +2025-03-11T12:39:23.702285,479392764,65480,191,39.11271649694,27.369652092405,-69.19959443432,2,1,18 +2025-03-11T12:39:23.717910,479392764,65480,191,39.29648436512,27.559434002865,-69.551828946455,2,1,18 +2025-03-11T12:39:23.733535,479392764,65480,191,39.48496422992,27.744602994465,-69.8901881504,2,1,18 +2025-03-11T12:39:23.749160,479392764,65480,191,39.67815609134,27.952885498155,-70.224025652285,2,1,18 +2025-03-11T12:39:23.764785,479392764,65480,191,39.86663595614,28.13343341793,-70.548502767035,2,1,18 +2025-03-11T12:39:23.780410,479392764,65480,191,40.05511582094,28.30936026588,-70.88682489098,2,1,18 +2025-03-11T12:39:23.796035,479392764,65480,191,40.22003570264,28.47138313353,-71.21581512377,2,1,18 +2025-03-11T12:39:23.811660,479392764,65480,191,40.39437957758,28.64266445076,-71.53561363244,2,1,18 +2025-03-11T12:39:23.827285,479392764,65480,191,40.57343544914,28.813953920955,-71.85079773905,2,1,18 +2025-03-11T12:39:23.842910,479392764,65480,191,40.7524913207,28.9944855348,-72.161397742595,2,1,18 +2025-03-11T12:39:23.858535,479392764,65480,191,40.92212319902,29.17962191454,-72.48124509026,2,1,18 +2025-03-11T12:39:23.874160,479392764,65480,191,41.08704308072,29.36012906949,-72.80106711692,2,1,18 +2025-03-11T12:39:23.889785,479392764,65480,191,41.25667495904,29.512917946455,-73.111542318455,2,1,18 +2025-03-11T12:39:23.905410,479392764,65480,191,41.42630683736,29.679570038895,-73.417451956925,2,1,18 +2025-03-11T12:39:23.921035,479392764,65480,191,41.58651472244,29.855447969055,-73.71876393032,2,1,18 +2025-03-11T12:39:23.936660,479392764,65480,191,41.75614660076,30.01747898967,-74.038518577985,2,1,18 +2025-03-11T12:39:23.952285,479392764,65480,191,41.91635448584,30.18411477618,-74.344414654445,2,1,18 +2025-03-11T12:39:23.967910,479392764,65480,191,42.06713837768,30.336871041285,-74.622514450505,2,1,18 +2025-03-11T12:39:23.983535,479392764,65480,191,42.23205825938,30.50351498076,-74.905311392645,2,1,18 +2025-03-11T12:39:23.999160,479392764,65480,191,42.41111413094,30.665562307305,-75.20659487006,2,1,18 +2025-03-11T12:39:24.014785,479392764,65480,191,42.57603401264,30.827585174955,-75.4893732722,2,1,18 +2025-03-11T12:39:24.030410,479392764,65480,191,42.7315299011,30.989591736675,-75.767516929265,2,1,18 +2025-03-11T12:39:24.046035,479392764,65480,191,42.88702578956,31.142356154745,-76.050244689395,2,1,18 +2025-03-11T12:39:24.061660,479392764,65480,191,43.0378096814,31.290491348025,-76.328325945455,2,1,18 +2025-03-11T12:39:24.077285,479392764,65480,191,43.18859357324,31.44324761313,-76.60180455845,2,1,18 +2025-03-11T12:39:24.092910,479392764,65480,191,43.3205294786,31.59135019455,-76.87985869049,2,1,18 +2025-03-11T12:39:24.108535,479392764,65480,191,43.45717738058,31.74408200076,-77.139453411275,2,1,18 +2025-03-11T12:39:24.124160,479392764,65480,191,43.60796127242,31.89221719404,-77.4221558504,2,1,18 +2025-03-11T12:39:24.139785,479392764,65480,191,43.77288115412,32.031134702565,-77.690978003345,2,1,18 +2025-03-11T12:39:24.155410,479392764,65480,191,43.90010506286,32.17922913102,-77.945919439055,2,1,18 +2025-03-11T12:39:24.171035,479392764,65480,191,44.03204096822,32.30884742514,-78.18230876351,2,1,18 +2025-03-11T12:39:24.186660,479392764,65480,191,44.1922488533,32.45699892435,-78.43267648319,2,1,18 +2025-03-11T12:39:24.202285,479392764,65480,191,44.357168735,32.5820532174,-78.682958283875,2,1,18 +2025-03-11T12:39:24.217910,479392764,65480,191,44.48910464036,32.70242936787,-78.923931711395,2,1,18 +2025-03-11T12:39:24.233535,479392764,65480,191,44.60219255924,32.818151834655,-79.155617108765,2,1,18 +2025-03-11T12:39:24.249160,479392764,65480,191,44.7105684815,32.952350435775,-79.378127519,2,1,18 +2025-03-11T12:39:24.264785,479392764,65480,191,44.84250438686,33.091210873545,-79.623796289585,2,1,18 +2025-03-11T12:39:24.280410,479392764,65480,191,44.9697282956,33.243926373825,-79.869513899165,2,1,18 +2025-03-11T12:39:24.296035,479392764,65480,191,45.09695220434,33.359673299505,-80.10121963955,2,1,18 +2025-03-11T12:39:24.311660,479392764,65480,191,45.22417611308,33.493904512485,-80.332999539935,2,1,18 +2025-03-11T12:39:24.327285,479392764,65480,191,45.3466880252,33.61888542885,-80.56011439625,2,1,18 +2025-03-11T12:39:24.342910,479392764,65480,191,45.4644879407,33.757721407725,-80.79652045769,2,1,18 +2025-03-11T12:39:24.358535,479392764,65480,191,45.58699985282,33.86421803679,-81.01893997094,2,1,18 +2025-03-11T12:39:24.374160,479392764,65480,191,45.70479976832,33.966085441065,-81.22747061399,2,1,18 +2025-03-11T12:39:24.389785,479392764,65480,191,45.83202367706,34.081832366745,-81.440691622115,2,1,18 +2025-03-11T12:39:24.405410,479392764,65480,191,45.94982359256,34.179078699195,-81.639961359035,2,1,18 +2025-03-11T12:39:24.421035,479392764,65480,191,46.0534875182,34.2855427164,-81.84849019907,2,1,18 +2025-03-11T12:39:24.436660,479392764,65480,191,46.15243944722,34.405861796115,-82.033961962775,2,1,18 +2025-03-11T12:39:24.452285,479392764,65480,191,46.26081536948,34.521576109935,-82.23791348075,2,1,18 +2025-03-11T12:39:24.467910,479392764,65480,191,46.3833272816,34.623451667175,-82.42334498948,2,1,18 +2025-03-11T12:39:24.483535,479392764,65480,191,46.49170320386,34.69757633457,-82.594781366,2,1,18 +2025-03-11T12:39:24.499160,479392764,65480,191,46.58123113964,34.790152677405,-82.761643595435,2,1,18 +2025-03-11T12:39:24.514785,479392764,65480,191,46.67075907542,34.896592235715,-82.942424994065,2,1,18 +2025-03-11T12:39:24.530410,479392764,65480,191,46.7602870112,35.00765286585,-83.123224932695,2,1,18 +2025-03-11T12:39:24.546035,479392764,65480,191,46.86395093684,35.11873795488,-83.29480284821,2,1,18 +2025-03-11T12:39:24.561660,479392764,65480,191,46.96290286586,35.202088459995,-83.470883925785,2,1,18 +2025-03-11T12:39:24.577285,479392764,65480,191,47.05714279826,35.28080974032,-83.637697316225,2,1,18 +2025-03-11T12:39:24.592910,479392764,65480,191,47.1372467408,35.3687487054,-83.80452744365,2,1,18 +2025-03-11T12:39:24.608535,479392764,65480,191,47.22677467658,35.470567191885,-83.962184386955,2,1,18 +2025-03-11T12:39:24.624160,479392764,65480,191,47.31630261236,35.567764606545,-84.124443973325,2,1,18 +2025-03-11T12:39:24.639785,479392764,65480,191,47.41525454138,35.646494039835,-84.268158229445,2,1,18 +2025-03-11T12:39:24.655410,479392764,65480,191,47.4906464873,35.729803780125,-84.40261475441,2,1,18 +2025-03-11T12:39:24.671035,479392764,65480,191,47.57075042984,35.80387952973,-84.55552571264,2,1,18 +2025-03-11T12:39:24.686660,479392764,65480,191,47.64614237576,35.89643141367,-84.690019317605,2,1,18 +2025-03-11T12:39:24.702285,479392764,65480,191,47.73095831492,35.98899960354,-84.829147667645,2,1,18 +2025-03-11T12:39:24.717910,479392764,65480,191,47.79221427098,36.053800597635,-84.96813087266,2,1,18 +2025-03-11T12:39:24.733535,479392764,65480,191,47.87231821352,36.11863420359,-85.107141201695,2,1,18 +2025-03-11T12:39:24.749160,479392764,65480,191,47.94299816282,36.18807257544,-85.26464124098,2,1,18 +2025-03-11T12:39:24.764785,479392764,65480,191,48.00425411888,36.24825249771,-85.394363539865,2,1,18 +2025-03-11T12:39:24.780410,479392764,65480,191,48.07493406818,36.313069797735,-85.510254391565,2,1,18 +2025-03-11T12:39:24.796035,479392764,65480,191,48.1503260141,36.377895250725,-85.630773207335,2,1,18 +2025-03-11T12:39:24.811660,479392764,65480,191,48.2210059634,36.4519546944,-85.746701139035,2,1,18 +2025-03-11T12:39:24.827285,479392764,65480,191,48.27283792622,36.52136045439,-85.853341040585,2,1,18 +2025-03-11T12:39:24.842910,479392764,65480,191,48.32466988904,36.57228192708,-85.9645279652,2,1,18 +2025-03-11T12:39:24.858535,479392764,65480,191,48.37650185186,36.637066615245,-86.08039169288,2,1,18 +2025-03-11T12:39:24.874160,479392764,65480,191,48.42833381468,36.697230231585,-86.182373331365,2,1,18 +2025-03-11T12:39:24.889785,479392764,65480,191,48.49901376398,36.74356324431,-86.26584174161,2,1,18 +2025-03-11T12:39:24.905410,479392764,65480,191,48.56026972004,36.78525887928,-86.34465686678,2,1,18 +2025-03-11T12:39:24.921035,479392764,65480,191,48.61210168286,36.85466463927,-86.465160317525,2,1,18 +2025-03-11T12:39:24.936660,479392764,65480,191,48.65922164906,36.91019903082,-86.55325308581,2,1,18 +2025-03-11T12:39:24.952285,479392764,65480,191,48.70634161526,36.951870206895,-86.641290234095,2,1,18 +2025-03-11T12:39:24.967910,479392764,65480,191,48.75346158146,37.01202567027,-86.752507457705,2,1,18 +2025-03-11T12:39:24.983535,479392764,65480,191,48.8100055409,37.044471008625,-86.840521088,2,1,18 +2025-03-11T12:39:24.999160,479392764,65480,191,48.85241351048,37.06302867261,-86.886868107695,2,1,18 +2025-03-11T12:39:25.014785,479392764,65480,191,48.8806854902,37.104667236825,-86.951772216635,2,1,18 +2025-03-11T12:39:25.030410,479392764,65480,191,48.91838146316,37.160185322445,-87.03060905678,2,1,18 +2025-03-11T12:39:25.046035,479392764,65480,191,48.95607743612,37.18335590529,-87.081589018535,2,1,18 +2025-03-11T12:39:25.061660,479392764,65480,191,48.97963741922,37.20650202924,-87.12792745421,2,1,18 +2025-03-11T12:39:25.077285,479392764,65480,191,49.01733339218,37.24353582756,-87.20206895129,2,1,18 +2025-03-11T12:39:25.092910,479392764,65480,191,49.05502936514,37.285190697705,-87.26698662224,2,1,18 +2025-03-11T12:39:25.108535,479392764,65480,191,49.07387735162,37.30832866869,-87.299454727715,2,1,18 +2025-03-11T12:39:25.124160,479392764,65480,191,49.08801334148,37.34070063036,-87.322710766055,2,1,18 +2025-03-11T12:39:25.139785,479392764,65480,191,49.11157332458,37.36384675431,-87.373670384795,2,1,18 +2025-03-11T12:39:25.155410,479392764,65480,191,49.14455730092,37.363903825065,-87.41992968248,2,1,18 +2025-03-11T12:39:25.171035,479392764,65480,191,49.16811728402,37.368565661715,-87.456951592025,2,1,18 +2025-03-11T12:39:25.186660,479392764,65480,191,49.1869652705,37.396324704525,-87.494059420565,2,1,18 +2025-03-11T12:39:25.202285,479392764,65480,191,49.19167726712,37.41481714479,-87.53110982609,2,1,18 +2025-03-11T12:39:25.217910,479392764,65480,191,49.2105252536,37.437955115775,-87.54047201624,2,1,18 +2025-03-11T12:39:25.233535,479392764,65480,191,49.21994924684,37.437971421705,-87.572833859705,2,1,18 +2025-03-11T12:39:25.249160,479392764,65480,191,49.2340852367,37.442616952425,-87.577493925785,2,1,18 +2025-03-11T12:39:25.264785,479392764,65480,191,49.24350922994,37.46573861748,-87.568357821665,2,1,18 +2025-03-11T12:39:25.280410,479392764,65480,191,49.24822122656,37.47036784227,-87.591489057995,2,1,18 +2025-03-11T12:39:25.296035,479392764,65480,191,49.24822122656,37.465746770445,-87.60533406719,2,1,18 +2025-03-11T12:39:25.311660,479392764,65480,191,49.24350922994,37.47498076113,-87.61922791538,2,1,18 +2025-03-11T12:39:25.327285,479392764,65480,191,49.24350922994,37.48422290478,-87.61002262925,2,1,18 +2025-03-11T12:39:25.342910,479392764,65480,191,49.24350922994,37.488843976605,-87.596177620055,2,1,18 +2025-03-11T12:39:25.358535,479392764,65480,191,49.22937324008,37.47957737406,-87.573014281715,2,1,18 +2025-03-11T12:39:25.374160,479392764,65480,191,49.22937324008,37.47033523041,-87.563734835585,2,1,18 +2025-03-11T12:39:25.389785,479392764,65480,191,49.21994924684,37.465697852655,-87.554460367445,2,1,18 +2025-03-11T12:39:25.405410,479392764,65480,191,49.2105252536,37.447197259425,-87.545130279305,2,1,18 +2025-03-11T12:39:25.421035,479392764,65480,191,49.20581325698,37.433325890985,-87.51734077991,2,1,18 +2025-03-11T12:39:25.436660,479392764,65480,191,49.19638926374,37.414825297755,-87.47104122725,2,1,18 +2025-03-11T12:39:25.452285,479392764,65480,191,49.17282928064,37.37781595833,-87.4477530869,2,1,18 +2025-03-11T12:39:25.467910,479392764,65480,191,49.14926929754,37.36391197803,-87.429178829615,2,1,18 +2025-03-11T12:39:25.483535,479392764,65480,191,49.14455730092,37.35004060959,-87.40138933022,2,1,18 +2025-03-11T12:39:25.499160,479392764,65480,191,49.12570931444,37.33152371043,-87.350455032485,2,1,18 +2025-03-11T12:39:25.514785,479392764,65480,191,49.0927253381,37.2991191369,-87.3040659548,2,1,18 +2025-03-11T12:39:25.530410,479392764,65480,191,49.07858934824,37.262126103405,-87.2623066442,2,1,18 +2025-03-11T12:39:25.546035,479392764,65480,191,49.05502936514,37.25284319493,-87.206781462395,2,1,18 +2025-03-11T12:39:25.561660,479392764,65480,191,49.01733339218,37.229672612085,-87.160422683705,2,1,18 +2025-03-11T12:39:25.577285,479392764,65480,191,48.97963741922,37.18801774194,-87.095505012755,2,1,18 +2025-03-11T12:39:25.592910,479392764,65480,191,48.93722944964,37.141733647005,-87.02131965467,2,1,18 +2025-03-11T12:39:25.608535,479392764,65480,191,48.91366946654,37.118587523055,-86.956496486735,2,1,18 +2025-03-11T12:39:25.624160,479392764,65480,191,48.86654950034,37.07691634698,-86.87770170458,2,1,18 +2025-03-11T12:39:25.639785,479392764,65480,191,48.82885352738,37.03988254866,-86.81280257363,2,1,18 +2025-03-11T12:39:25.655410,479392764,65480,191,48.7864455578,37.002840597375,-86.738654295545,2,1,18 +2025-03-11T12:39:25.671035,479392764,65480,191,48.74403758822,36.942693286965,-86.6459285852,2,1,18 +2025-03-11T12:39:25.686660,479392764,65480,191,48.70162961864,36.891788120205,-86.553239954855,2,1,18 +2025-03-11T12:39:25.702285,479392764,65480,191,48.64979765582,36.82700343204,-86.474345691695,2,1,18 +2025-03-11T12:39:25.717910,479392764,65480,191,48.61210168286,36.776106418245,-86.38628502542,2,1,18 +2025-03-11T12:39:25.733535,479392764,65480,191,48.5508457268,36.72978971145,-86.27972426186,2,1,18 +2025-03-11T12:39:25.749160,479392764,65480,191,48.50843775722,36.683505616515,-86.19167535458,2,1,18 +2025-03-11T12:39:25.764785,479392764,65480,191,48.45189379778,36.627954919035,-86.094326658155,2,1,18 +2025-03-11T12:39:25.780410,479392764,65480,191,48.39063784172,36.57239606859,-85.978486448465,2,1,18 +2025-03-11T12:39:25.796035,479392764,65480,191,48.34351787552,36.52610382069,-85.86270366179,2,1,18 +2025-03-11T12:39:25.811660,479392764,65480,191,48.28226191946,36.461302826595,-85.760689921295,2,1,18 +2025-03-11T12:39:25.827285,479392764,65480,191,48.20686997354,36.377993086305,-85.65396049472,2,1,18 +2025-03-11T12:39:25.842910,479392764,65480,191,48.14090202086,36.303941795595,-85.528796977895,2,1,18 +2025-03-11T12:39:25.858535,479392764,65480,191,48.07493406818,36.25299586401,-85.408347344135,2,1,18 +2025-03-11T12:39:25.874160,479392764,65480,191,48.01839010874,36.18820302288,-85.29247683545,2,1,18 +2025-03-11T12:39:25.889785,479392764,65480,191,47.94771015944,36.10028036373,-85.171872100685,2,1,18 +2025-03-11T12:39:25.905410,479392764,65480,191,47.87231821352,36.02621276709,-85.02821028959,2,1,18 +2025-03-11T12:39:25.921035,479392764,65480,191,47.8204862507,35.961428078925,-84.889240646585,2,1,18 +2025-03-11T12:39:25.936660,479392764,65480,191,47.73567031154,35.878102032705,-84.750149376545,2,1,18 +2025-03-11T12:39:25.952285,479392764,65480,191,47.655566369,35.817889498575,-84.615778770575,2,1,18 +2025-03-11T12:39:25.967910,479392764,65480,191,47.57546242646,35.74381374897,-84.462867812345,2,1,18 +2025-03-11T12:39:25.983535,479392764,65480,191,47.4906464873,35.646624487275,-84.314478556175,2,1,18 +2025-03-11T12:39:25.999114,479392768,65477,192,47.40111855152,35.558669216265,-84.166119599,2,1,18 +2025-03-11T12:39:26.014739,479392768,65477,192,47.31630261236,35.47996424187,-83.994698587505,2,1,18 +2025-03-11T12:39:26.030364,479392768,65477,192,47.22677467658,35.38276682721,-83.82781781807,2,1,18 +2025-03-11T12:39:26.045989,479392768,65477,192,47.12311075094,35.276302810005,-83.64239489336,2,1,18 +2025-03-11T12:39:26.061614,479392768,65477,192,47.02887081854,35.19758152968,-83.47558150292,2,1,18 +2025-03-11T12:39:26.077239,479392768,65477,192,46.93934288276,35.10962625867,-83.290253081225,2,1,18 +2025-03-11T12:39:26.092864,479392768,65477,192,46.84510295036,35.021662834695,-83.114160244655,2,1,18 +2025-03-11T12:39:26.108489,479392768,65477,192,46.75086301796,34.919836195245,-82.965738886475,2,1,18 +2025-03-11T12:39:26.124114,479392768,65477,192,46.6660470788,34.8318890772,-82.77579606272,2,1,18 +2025-03-11T12:39:26.139739,479392768,65477,192,46.5718071464,34.73006243775,-82.604268789215,2,1,18 +2025-03-11T12:39:26.155364,479392768,65477,192,46.46343122414,34.609727052105,-82.4187834635,2,1,18 +2025-03-11T12:39:26.170989,479392768,65477,192,46.3597672985,34.4847787476,-82.219422829595,2,1,18 +2025-03-11T12:39:26.186614,479392768,65477,192,46.25139137624,34.392169792905,-82.020185194685,2,1,18 +2025-03-11T12:39:26.202239,479392768,65477,192,46.13359146074,34.285681316805,-81.820878377765,2,1,18 +2025-03-11T12:39:26.217864,479392768,65477,192,46.03463953172,34.160741165265,-81.62614570793,2,1,18 +2025-03-11T12:39:26.233489,479392768,65477,192,45.94039959932,34.05429345399,-81.445357528295,2,1,18 +2025-03-11T12:39:26.249114,479392768,65477,192,45.8178876872,33.93393360945,-81.23674594424,2,1,18 +2025-03-11T12:39:26.264739,479392768,65477,192,45.7000877717,33.8182029897,-81.01891731506,2,1,18 +2025-03-11T12:39:26.280364,479392768,65477,192,45.57286386296,33.70245606402,-80.796453940805,2,1,18 +2025-03-11T12:39:26.295989,479392768,65477,192,45.45506394746,33.56824115697,-80.578551151625,2,1,18 +2025-03-11T12:39:26.311614,479392768,65477,192,45.33726403196,33.466373752695,-80.37464169164,2,1,18 +2025-03-11T12:39:26.327239,479392768,65477,192,45.22417611308,33.346030214085,-80.1521801204,2,1,18 +2025-03-11T12:39:26.342864,479392768,65477,192,45.0875282111,33.211782695175,-79.91576547494,2,1,18 +2025-03-11T12:39:26.358489,479392768,65477,192,44.96030430236,33.08217255402,-79.67938293149,2,1,18 +2025-03-11T12:39:26.374114,479392768,65477,192,44.84721638348,32.95258687176,-79.43839954799,2,1,18 +2025-03-11T12:39:26.389739,479392768,65477,192,44.7105684815,32.83682364015,-79.197437879465,2,1,18 +2025-03-11T12:39:26.405364,479392768,65477,192,44.58334457276,32.688729211695,-78.96560235908,2,1,18 +2025-03-11T12:39:26.420989,479392768,65477,192,44.46083266064,32.53602186438,-78.72451271357,2,1,18 +2025-03-11T12:39:26.436614,479392768,65477,192,44.31947276204,32.401766192505,-78.46498537178,2,1,18 +2025-03-11T12:39:26.452239,479392768,65477,192,44.17340086682,32.285986654965,-78.196283042855,2,1,18 +2025-03-11T12:39:26.467864,479392768,65477,192,44.0273289716,32.15634390195,-77.94600982619,2,1,18 +2025-03-11T12:39:26.483489,479392768,65477,192,43.88125707638,32.02208007711,-77.695718069525,2,1,18 +2025-03-11T12:39:26.499114,479392768,65477,192,43.74932117102,31.86473535204,-77.44073277281,2,1,18 +2025-03-11T12:39:26.514739,479392768,65477,192,43.61267326904,31.707382474005,-77.199604244285,2,1,18 +2025-03-11T12:39:26.530364,479392768,65477,192,43.47131337044,31.56388465848,-76.93541863943,2,1,18 +2025-03-11T12:39:26.545989,479392768,65477,192,43.31110548536,31.41573315927,-76.671187370555,2,1,18 +2025-03-11T12:39:26.561614,479392768,65477,192,43.16503359014,31.27222719078,-76.379267886305,2,1,18 +2025-03-11T12:39:26.577239,479392768,65477,192,43.01896169492,31.124100150465,-76.11967814351,2,1,18 +2025-03-11T12:39:26.592864,479392768,65477,192,42.85875380984,30.975948651255,-75.846204508505,2,1,18 +2025-03-11T12:39:26.608489,479392768,65477,192,42.70325792138,30.813942089535,-75.544954936115,2,1,18 +2025-03-11T12:39:26.624114,479392768,65477,192,42.5430500363,30.6611695185,-75.25297802885,2,1,18 +2025-03-11T12:39:26.639739,479392768,65477,192,42.38755414784,30.48067866948,-74.965517845655,2,1,18 +2025-03-11T12:39:26.655364,479392768,65477,192,42.23205825938,30.323293179585,-74.673529179395,2,1,18 +2025-03-11T12:39:26.670989,479392768,65477,192,42.06713837768,30.16589138376,-74.381526951125,2,1,18 +2025-03-11T12:39:26.686614,479392768,65477,192,41.89279450274,30.01309435383,-74.06642378552,2,1,18 +2025-03-11T12:39:26.702239,479392768,65477,192,41.73258661766,29.85570071097,-73.76980715519,2,1,18 +2025-03-11T12:39:26.717864,479392768,65477,192,41.57237873258,29.69830706811,-73.487054074055,2,1,18 +2025-03-11T12:39:26.733489,479392768,65477,192,41.41688284412,29.52705836274,-73.176525055535,2,1,18 +2025-03-11T12:39:26.749114,479392768,65477,192,41.2472509658,29.346543054825,-72.861317430935,2,1,18 +2025-03-11T12:39:26.764739,479392768,65477,192,41.06348309762,29.17986650349,-72.550766266385,2,1,18 +2025-03-11T12:39:26.780364,479392768,65477,192,40.87971522944,29.022432095805,-72.23563099877,2,1,18 +2025-03-11T12:39:26.795989,479392768,65477,192,40.7053713545,28.851150778575,-71.920453673165,2,1,18 +2025-03-11T12:39:26.811614,479392768,65477,192,40.54987546604,28.670659929555,-71.600645208515,2,1,18 +2025-03-11T12:39:26.827239,479392768,65477,192,40.36139560124,28.48086986613,-71.276131013765,2,1,18 +2025-03-11T12:39:26.842864,479392768,65477,192,40.1870517263,28.28186211795,-70.965463631225,2,1,18 +2025-03-11T12:39:26.858489,479392768,65477,192,40.01741984798,28.101346810035,-70.64563482356,2,1,18 +2025-03-11T12:39:26.874114,479392768,65477,192,39.83836397642,27.925436268015,-70.307326261625,2,1,18 +2025-03-11T12:39:26.889739,479392768,65477,192,39.65930810486,27.75414679782,-69.964415056625,2,1,18 +2025-03-11T12:39:26.905364,479392768,65477,192,39.4802522333,27.573615183975,-69.62608795469,2,1,18 +2025-03-11T12:39:26.920989,479392768,65477,192,39.29648436512,27.38845434534,-69.283114348685,2,1,18 +2025-03-11T12:39:26.936614,479392768,65477,192,39.1032925037,27.212519344425,-68.94016426067,2,1,18 +2025-03-11T12:39:26.952239,479392768,65477,192,38.90538864566,27.008849759595,-68.59709615165,2,1,18 +2025-03-11T12:39:26.967864,479392768,65477,192,38.71690878086,26.80981755252,-68.267923693835,2,1,18 +2025-03-11T12:39:26.983489,479392768,65477,192,38.5142929262,26.6200030302,-67.911040874615,2,1,18 +2025-03-11T12:39:26.999114,479392768,65477,192,38.31638906816,26.41633344537,-67.5541092164,2,1,18 +2025-03-11T12:39:27.014739,479392768,65477,192,38.12319720674,26.21729308533,-67.20644524532,2,1,18 +2025-03-11T12:39:27.030364,479392768,65477,192,37.9252933487,26.0136235005,-66.84489240404,2,1,18 +2025-03-11T12:39:27.045989,479392768,65477,192,37.72738949066,25.80071177202,-66.469438933565,2,1,18 +2025-03-11T12:39:27.061614,479392768,65477,192,37.52006163938,25.59702588126,-66.107872530275,2,1,18 +2025-03-11T12:39:27.077239,479392768,65477,192,37.33158177458,25.41185688966,-65.74178622794,2,1,18 +2025-03-11T12:39:27.092864,479392768,65477,192,37.13838991316,25.19433224232,-65.361699815405,2,1,18 +2025-03-11T12:39:27.108489,479392768,65477,192,36.91692607202,24.99524296449,-64.96316214458,2,1,18 +2025-03-11T12:39:27.124114,479392768,65477,192,36.71431021736,24.791565226695,-64.5877389731,2,1,18 +2025-03-11T12:39:27.139739,479392768,65477,192,36.51640635932,24.578653498215,-64.212285502625,2,1,18 +2025-03-11T12:39:27.155364,479392768,65477,192,36.31850250128,24.37036284156,-63.832229389085,2,1,18 +2025-03-11T12:39:27.170989,479392768,65477,192,36.11588664662,24.17130617559,-63.438340025345,2,1,18 +2025-03-11T12:39:27.186614,479392768,65477,192,35.90384679872,23.958369988215,-63.053623845725,2,1,18 +2025-03-11T12:39:27.202239,479392768,65477,192,35.68238295758,23.740796423085,-62.68273911329,2,1,18 +2025-03-11T12:39:27.217864,479392768,65477,192,35.46091911644,23.51860178613,-62.284108742465,2,1,18 +2025-03-11T12:39:27.233489,479392768,65477,192,35.24887926854,23.287181311455,-61.890076036715,2,1,18 +2025-03-11T12:39:27.249114,479392768,65477,192,35.03212742402,23.064994827465,-61.50531599609,2,1,18 +2025-03-11T12:39:27.264739,479392768,65477,192,34.80595158626,22.85665525302,-61.10673446426,2,1,18 +2025-03-11T12:39:27.280364,479392768,65477,192,34.57506375188,22.643686453785,-60.69426406223,2,1,18 +2025-03-11T12:39:27.295989,479392768,65477,192,34.36302390398,22.41226597911,-60.286367807285,2,1,18 +2025-03-11T12:39:27.311614,479392768,65477,192,34.14627205946,22.194700566945,-59.8831415744,2,1,18 +2025-03-11T12:39:27.327239,479392768,65477,192,33.93423221156,21.967901164095,-59.484506225585,2,1,18 +2025-03-11T12:39:27.342864,479392768,65477,192,33.70334437718,21.731827005735,-59.07656430662,2,1,18 +2025-03-11T12:39:27.358489,479392768,65477,192,33.47716853942,21.51424528764,-58.65946096253,2,1,18 +2025-03-11T12:39:27.374114,479392768,65477,192,33.24628070504,21.28741327293,-58.233071391305,2,1,18 +2025-03-11T12:39:27.389739,479392768,65477,192,33.01068087404,21.04670988978,-57.825104151335,2,1,18 +2025-03-11T12:39:27.405364,479392768,65477,192,32.77508104304,20.819869722105,-57.4125713483,2,1,18 +2025-03-11T12:39:27.420989,479392768,65477,192,32.54419320866,20.583795563745,-56.995387063205,2,1,18 +2025-03-11T12:39:27.436614,479392768,65477,192,32.32272936752,20.35235878314,-56.573613697055,2,1,18 +2025-03-11T12:39:27.452239,479392768,65477,192,32.105977523,20.107066940025,-56.137927942715,2,1,18 +2025-03-11T12:39:27.467864,479392768,65477,192,31.87980168524,19.88024307828,-55.68843923717,2,1,18 +2025-03-11T12:39:27.483489,479392768,65477,192,31.634777861,19.644144461025,-55.26199224293,2,1,18 +2025-03-11T12:39:27.499114,479392768,65477,192,31.38975403676,19.39880370012,-54.82626580256,2,1,18 +2025-03-11T12:39:27.514739,479392768,65477,192,31.14944220914,19.16271323583,-54.39520440626,2,1,18 +2025-03-11T12:39:27.530364,479392768,65477,192,30.92326637138,18.92202615861,-53.954902446845,2,1,18 +2025-03-11T12:39:27.545989,479392768,65477,192,30.67824254714,18.685927541355,-53.519213086475,2,1,18 +2025-03-11T12:39:27.561614,479392768,65477,192,30.42850672628,18.43595755566,-53.078840142035,2,1,18 +2025-03-11T12:39:27.577239,479392768,65477,192,30.18348290204,18.190616794755,-52.633871335535,2,1,18 +2025-03-11T12:39:27.592864,479392768,65477,192,29.94317107442,17.954526330465,-52.17970402391,2,1,18 +2025-03-11T12:39:27.608489,479392768,65477,192,29.68872325694,17.70916926363,-51.711615740075,2,1,18 +2025-03-11T12:39:27.624114,479392768,65477,192,29.44841142932,17.45459451204,-51.26661663458,2,1,18 +2025-03-11T12:39:27.639739,479392768,65477,192,29.20338760508,17.218495894785,-50.82168490808,2,1,18 +2025-03-11T12:39:27.655364,479392768,65477,192,28.94422779098,16.96850960316,-50.38129840163,2,1,18 +2025-03-11T12:39:27.670989,479392768,65477,192,28.6897799735,16.72777360815,-49.8993651086,2,1,18 +2025-03-11T12:39:27.686614,479392768,65477,192,28.43533215602,16.473174397665,-49.440482110895,2,1,18 +2025-03-11T12:39:27.702239,479392768,65477,192,28.18088433854,16.21857518718,-48.98159911319,2,1,18 +2025-03-11T12:39:27.717864,479392768,65477,192,27.93114851768,15.95474198601,-48.52268581649,2,1,18 +2025-03-11T12:39:27.733489,479392768,65477,192,27.6767007002,15.6955217037,-48.054541912655,2,1,18 +2025-03-11T12:39:27.749114,479392768,65477,192,27.43167687596,15.44555987097,-47.572585101635,2,1,18 +2025-03-11T12:39:27.764739,479392768,65477,192,27.17251706186,15.195573579345,-47.10909267986,2,1,18 +2025-03-11T12:39:27.780364,479392768,65477,192,26.91335724776,14.91786085677,-46.645489018085,2,1,18 +2025-03-11T12:39:27.795989,479392768,65477,192,26.65419743366,14.649390277845,-46.16343770405,2,1,18 +2025-03-11T12:39:27.811614,479392768,65477,192,26.4044616128,14.39942029215,-45.68609529509,2,1,18 +2025-03-11T12:39:27.827239,479392768,65477,192,26.1453017987,14.140191856875,-45.21794461025,2,1,18 +2025-03-11T12:39:27.842864,479392768,65477,192,25.89085398122,13.88559264639,-44.73595569722,2,1,18 +2025-03-11T12:39:27.858489,479392768,65477,192,25.62227017388,13.607863617885,-44.263096107305,2,1,18 +2025-03-11T12:39:27.874114,479392768,65477,192,25.35839836316,13.348627029645,-43.790317458395,2,1,18 +2025-03-11T12:39:27.889739,479392768,65477,192,25.0851025592,13.07551092,-43.29436371215,2,1,18 +2025-03-11T12:39:27.905364,479392768,65477,192,24.81180675524,12.811636954005,-42.807689412035,2,1,18 +2025-03-11T12:39:27.920989,479392768,65477,192,24.5432229479,12.5523922128,-42.33490398212,2,1,18 +2025-03-11T12:39:27.936614,479392768,65477,192,24.27463914056,12.27928425612,-41.852820566075,2,1,18 +2025-03-11T12:39:27.952239,479392768,65477,192,24.00605533322,12.001555227615,-41.3614762439,2,1,18 +2025-03-11T12:39:27.967864,479392768,65477,192,23.75160751574,11.733092801655,-40.87018934474,2,1,18 +2025-03-11T12:39:27.983489,479392768,65477,192,23.49244770164,11.469243294555,-40.397398936835,2,1,18 +2025-03-11T12:39:27.999114,479392768,65477,192,23.21915189768,11.191506113085,-39.91991138285,2,1,18 +2025-03-11T12:39:28.014739,479392768,65477,192,22.94585609372,10.941495362565,-39.405565604345,2,1,18 +2025-03-11T12:39:28.030364,479392768,65477,192,22.67256028976,10.663758181095,-38.89110858584,2,1,18 +2025-03-11T12:39:28.045989,479392768,65477,192,22.40397648242,10.381408080765,-38.399745723665,2,1,18 +2025-03-11T12:39:28.061614,479392768,65477,192,22.13068067846,10.103670899295,-37.90377343742,2,1,18 +2025-03-11T12:39:28.077239,479392768,65477,192,21.87152086436,9.830579248545,-37.412461217255,2,1,18 +2025-03-11T12:39:28.092864,479392768,65477,192,21.60293705702,9.55285022004,-36.91187452895,2,1,18 +2025-03-11T12:39:28.108489,479392768,65477,192,21.31079326658,9.279701498535,-36.41127247562,2,1,18 +2025-03-11T12:39:28.124114,479392768,65477,192,21.02807346938,8.98808479566,-35.905988641235,2,1,18 +2025-03-11T12:39:28.139739,479392768,65477,192,20.75477766542,8.714968686015,-35.377686613535,2,1,18 +2025-03-11T12:39:28.155364,479392768,65477,192,20.47676986484,8.44646549523,-34.863259894025,2,1,18 +2025-03-11T12:39:28.170989,479392768,65477,192,20.19405006764,8.17795415148,-34.36731112577,2,1,18 +2025-03-11T12:39:28.186614,479392768,65477,192,19.9019062772,7.90018435815,-33.852826983245,2,1,18 +2025-03-11T12:39:28.202239,479392768,65477,192,19.60976248676,7.608551349345,-33.33828722072,2,1,18 +2025-03-11T12:39:28.217864,479392768,65477,192,19.33175468618,7.316942799435,-32.819146618145,2,1,18 +2025-03-11T12:39:28.233489,479392768,65477,192,19.0537468856,7.039197465,-32.29081926944,2,1,18 +2025-03-11T12:39:28.249114,479392768,65477,192,18.77573908502,6.761452130565,-31.762491920735,2,1,18 +2025-03-11T12:39:28.264739,479392768,65477,192,18.49773128444,6.479085724305,-31.25263076429,2,1,18 +2025-03-11T12:39:28.280364,479392768,65477,192,18.2291474771,6.1828724085,-30.75659109905,2,1,18 +2025-03-11T12:39:28.295989,479392768,65477,192,17.95113967652,5.88202171494,-30.25127696567,2,1,18 +2025-03-11T12:39:28.311614,479392768,65477,192,17.6637078827,5.604260074575,-29.72755723802,2,1,18 +2025-03-11T12:39:28.327239,479392768,65477,192,17.37156409226,5.317248137595,-29.194551283235,2,1,18 +2025-03-11T12:39:28.342864,479392768,65477,192,17.09355629168,5.025639587685,-28.6569259484,2,1,18 +2025-03-11T12:39:28.358489,479392768,65477,192,16.81083649448,4.729401812985,-28.133138841755,2,1,18 +2025-03-11T12:39:28.374114,479392768,65477,192,16.51869270404,4.42852666053,-27.623183182295,2,1,18 +2025-03-11T12:39:28.389739,479392768,65477,192,16.21712492036,4.146119489445,-27.094803388565,2,1,18 +2025-03-11T12:39:28.405364,479392768,65477,192,15.92498112992,3.877591839765,-26.584977509105,2,1,18 +2025-03-11T12:39:28.420989,479392768,65477,192,15.64226133272,3.57673299324,-26.05192949633,2,1,18 +2025-03-11T12:39:28.436614,479392768,65477,192,15.35011754228,3.275857840785,-25.51424673848,2,1,18 +2025-03-11T12:39:28.452239,479392768,65477,192,15.06739774508,2.98424113791,-25.008962904095,2,1,18 +2025-03-11T12:39:28.467864,479392768,65477,192,14.77525395464,2.70647134458,-24.48523639544,2,1,18 +2025-03-11T12:39:28.483489,479392768,65477,192,14.4831101642,2.4194594076,-23.942988074525,2,1,18 +2025-03-11T12:39:28.499114,479392768,65477,192,14.20510236362,2.13709300134,-23.39615745356,2,1,18 +2025-03-11T12:39:28.514739,479392768,65477,192,13.90353457994,1.845443686605,-22.853877030635,2,1,18 +2025-03-11T12:39:28.530364,479392768,65477,192,13.5878308064,1.5399066975,-22.330005376955,2,1,18 +2025-03-11T12:39:28.545989,479392768,65477,192,13.2815510261,1.262112445275,-21.806258525285,2,1,18 +2025-03-11T12:39:28.561614,479392768,65477,192,13.01296721876,0.97514127312,-21.26866529246,2,1,18 +2025-03-11T12:39:28.577239,479392768,65477,192,12.73495941818,0.660427364085001,-20.730947257625,2,1,18 +2025-03-11T12:39:28.592864,479392768,65477,192,12.44752762436,0.368802508244999,-20.197929543845,2,1,18 +2025-03-11T12:39:28.608489,479392768,65477,192,12.14124784406,0.077145040545,-19.655642339915,2,1,18 +2025-03-11T12:39:28.624114,479392768,65477,192,11.85381605024,-0.22834303077,-19.113326640005,2,1,18 +2025-03-11T12:39:28.639739,479392768,65477,192,11.55696026318,-0.53846847984,-18.570978838085,2,1,18 +2025-03-11T12:39:28.655364,479392768,65477,192,11.27424046598,-0.83470625454,-18.042570548375,2,1,18 +2025-03-11T12:39:28.670989,479392768,65477,192,10.97738467892,-1.121726344485,-17.48645189726,2,1,18 +2025-03-11T12:39:28.686614,479392768,65477,192,10.67110489862,-1.43648917131,-16.92558726107,2,1,18 +2025-03-11T12:39:28.702239,479392768,65477,192,10.36482511832,-1.723525567185,-16.37407623101,2,1,18 +2025-03-11T12:39:28.717864,479392768,65477,192,10.07268132788,-2.019779647815,-15.850275562355,2,1,18 +2025-03-11T12:39:28.733489,479392768,65477,192,9.77582554082,-2.311420809585,-15.317244286565,2,1,18 +2025-03-11T12:39:28.749114,479392768,65477,192,9.4648337639,-2.6123285739,-14.788776770825,2,1,18 +2025-03-11T12:39:28.764739,479392768,65477,192,9.17268997346,-2.903961582705,-14.251131092975,2,1,18 +2025-03-11T12:39:28.780364,479392768,65477,192,8.88525817964,-3.19096536672,-13.70426837,2,1,18 +2025-03-11T12:39:28.795989,479392768,65477,192,8.58369039596,-3.48723575328,-13.17583295627,2,1,18 +2025-03-11T12:39:28.811614,479392768,65477,192,8.27269861904,-3.788143517595,-12.615017159075,2,1,18 +2025-03-11T12:39:28.827239,479392768,65477,192,7.9805548286,-4.08901867005,-12.058849668965,2,1,18 +2025-03-11T12:39:28.842864,479392768,65477,192,7.68841103816,-4.389893822505,-11.50730336192,2,1,18 +2025-03-11T12:39:28.858489,479392768,65477,192,7.38684325448,-4.695406352715,-10.964967318995,2,1,18 +2025-03-11T12:39:28.874114,479392768,65477,192,7.0852754708,-4.98705566745,-10.41344452994,2,1,18 +2025-03-11T12:39:28.889739,479392768,65477,192,6.78370768712,-5.297189269485,-9.85722639782,2,1,18 +2025-03-11T12:39:28.905364,479392768,65477,192,6.46800391358,-5.607347330415,-9.32409383801,2,1,18 +2025-03-11T12:39:28.920989,479392768,65477,192,6.18528411638,-5.903585105115,-8.77720081604,2,1,18 +2025-03-11T12:39:28.936614,479392768,65477,192,5.90256431918,-6.199822879815,-8.2395501602,2,1,18 +2025-03-11T12:39:28.952239,479392768,65477,192,5.6009965355,-6.505335410025,-7.69259293421,2,1,18 +2025-03-11T12:39:28.967864,479392768,65477,192,5.30414074844,-6.81083978727,-7.136400123095,2,1,18 +2025-03-11T12:39:28.983489,479392768,65477,192,5.00257296476,-7.111731245655,-6.6033249863,2,1,18 +2025-03-11T12:39:28.999114,479392768,65477,192,4.7057171777,-7.412614551075,-6.06101426438,2,1,18 +2025-03-11T12:39:29.014739,479392768,65477,192,4.3994373974,-7.704272018775,-5.50024232819,2,1,18 +2025-03-11T12:39:29.030364,479392768,65477,192,4.09786961372,-8.00516347716,-4.94406127607,2,1,18 +2025-03-11T12:39:29.045989,479392768,65477,192,3.80101382666,-8.29680463893,-4.41103000028,2,1,18 +2025-03-11T12:39:29.061614,479392768,65477,192,3.5041580396,-8.61617223165,-3.86864511836,2,1,18 +2025-03-11T12:39:29.077239,479392768,65477,192,3.20259025592,-8.917063690035,-3.317085249305,2,1,18 +2025-03-11T12:39:29.092864,479392768,65477,192,2.88688648238,-9.20411639184,-2.756318291105,2,1,18 +2025-03-11T12:39:29.108489,479392768,65477,192,2.59003069532,-9.500378625435,-2.20016255999,2,1,18 +2025-03-11T12:39:29.124114,479392768,65477,192,2.29788690488,-9.81049592154,-1.657821539075,2,1,18 +2025-03-11T12:39:29.139739,479392768,65477,192,1.9963191212,-10.102145236275,-1.110919933085,2,1,18 +2025-03-11T12:39:29.155364,479392768,65477,192,1.70417533076,-10.40302038873,-0.582479541365,2,1,18 +2025-03-11T12:39:29.170989,479392768,65477,192,1.4073195437,-10.727009053275,-0.0262125702500002,2,1,18 +2025-03-11T12:39:29.186614,479392768,65477,192,1.10575176002,-11.01865836801,0.52068903574,2,1,18 +2025-03-11T12:39:29.202239,479392768,65477,192,0.79947197972,-11.324179051185,1.076895408865,2,1,18 +2025-03-11T12:39:29.217864,479392768,65477,192,0.49319219942,-11.63894187801,1.619275312795,2,1,18 +2025-03-11T12:39:29.233489,479392768,65477,192,0.19633641236,-11.93982518343,2.15696485165,2,1,18 +2025-03-11T12:39:29.249114,479392768,65477,192,-0.0958073780800001,-12.22683712041,2.699213172565,2,1,18 +2025-03-11T12:39:29.264739,479392768,65477,192,-0.39737516176,-12.518486435145,3.23225122936,2,1,18 +2025-03-11T12:39:29.280364,479392768,65477,192,-0.69894294544,-12.81937789353,3.76994754922,2,1,18 +2025-03-11T12:39:29.295989,479392768,65477,192,-1.00522272574,-13.124898576705,4.307669190085,2,1,18 +2025-03-11T12:39:29.311614,479392768,65477,192,-1.31150250604,-13.41193497258,4.84531667095,2,1,18 +2025-03-11T12:39:29.327239,479392768,65477,192,-1.59893429986,-13.717423043895,5.37839000473,2,1,18 +2025-03-11T12:39:29.342864,479392768,65477,192,-1.88165409706,-14.022902962245,5.90683537444,2,1,18 +2025-03-11T12:39:29.358489,479392768,65477,192,-2.16437389426,-14.32376180877,6.45374693641,2,1,18 +2025-03-11T12:39:29.374114,479392768,65477,192,-2.46594167794,-14.61079005168,7.023735917725,2,1,18 +2025-03-11T12:39:29.389739,479392768,65477,192,-2.76750946162,-14.89781829459,7.57524016678,2,1,18 +2025-03-11T12:39:29.405364,479392768,65477,192,-3.06436524868,-15.19870160001,8.094444973375,2,1,18 +2025-03-11T12:39:29.420989,479392768,65477,192,-3.37064502898,-15.48111692406,8.64131628037,2,1,18 +2025-03-11T12:39:29.436614,479392768,65477,192,-3.6580768228,-15.7727417799,9.188197543345,2,1,18 +2025-03-11T12:39:29.452239,479392768,65477,192,-3.95022061324,-16.073616932355,9.72125911813,2,1,18 +2025-03-11T12:39:29.467864,479392768,65477,192,-4.2470764003,-16.365258094125,10.26353276005,2,1,18 +2025-03-11T12:39:29.483489,479392768,65477,192,-4.53922019074,-16.66613324658,10.778109602575,2,1,18 +2025-03-11T12:39:29.499114,479392768,65477,192,-4.84078797442,-16.96240363314,11.31116619937,2,1,18 +2025-03-11T12:39:29.514739,479392768,65477,192,-5.13764376148,-17.26328693856,11.848855738225,2,1,18 +2025-03-11T12:39:29.530364,479392768,65477,192,-5.42978755192,-17.554919947365,12.386501416075,2,1,18 +2025-03-11T12:39:29.545989,479392768,65477,192,-5.71721934574,-17.837302659555,12.947209148245,2,1,18 +2025-03-11T12:39:29.561614,479392768,65477,192,-6.00936313618,-18.13817781201,13.484891906095,2,1,18 +2025-03-11T12:39:29.577239,479392768,65477,192,-6.29208293338,-18.43441558671,14.00867901274,2,1,18 +2025-03-11T12:39:29.592864,479392768,65477,192,-6.59365071706,-18.71220168597,14.51855553421,2,1,18 +2025-03-11T12:39:29.608489,479392768,65477,192,-6.87165851764,-19.01305237953,15.046975582915,2,1,18 +2025-03-11T12:39:29.624114,479392768,65477,192,-7.15909031146,-19.327782594495,15.589328362825,2,1,18 +2025-03-11T12:39:29.639739,479392768,65477,192,-7.45594609852,-19.62404482809,16.12699936168,2,1,18 +2025-03-11T12:39:29.655364,479392768,65477,192,-7.7575138822,-19.915694142825,16.641552686215,2,1,18 +2025-03-11T12:39:29.670989,479392768,65477,192,-8.04965767264,-20.211948223455,17.15611098874,2,1,18 +2025-03-11T12:39:29.686614,479392768,65477,192,-8.33237746984,-20.498943854505,17.689103381515,2,1,18 +2025-03-11T12:39:29.702239,479392768,65477,192,-8.61509726704,-20.785939485555,18.235959323485,2,1,18 +2025-03-11T12:39:29.717864,479392768,65477,192,-8.89781706424,-21.07755618843,18.75972789013,2,1,18 +2025-03-11T12:39:29.733489,479392768,65477,192,-9.18053686144,-21.359930747655,19.283459376775,2,1,18 +2025-03-11T12:39:29.749114,479392768,65477,192,-9.47268065188,-21.63307946916,19.80716734543,2,1,18 +2025-03-11T12:39:29.764739,479392768,65477,192,-9.76953643894,-21.91547848728,20.33091917509,2,1,18 +2025-03-11T12:39:29.780364,479392768,65477,192,-10.0428322429,-22.216321027875,20.85933244279,2,1,18 +2025-03-11T12:39:29.795989,479392768,65477,192,-10.3255520401,-22.494074515275,21.392287755565,2,1,18 +2025-03-11T12:39:29.811614,479392768,65477,192,-10.59884784406,-22.790295984045,21.88833420181,2,1,18 +2025-03-11T12:39:29.827239,479392768,65477,192,-10.88156764126,-23.09115483057,22.39827629926,2,1,18 +2025-03-11T12:39:29.842864,479392768,65477,192,-11.16428743846,-23.364287246145,22.921970705905,2,1,18 +2025-03-11T12:39:29.858489,479392768,65477,192,-11.44700723566,-23.642040733545,23.450304835615,2,1,18 +2025-03-11T12:39:29.874114,479392768,65477,192,-11.7391510261,-23.929052670525,23.96482605814,2,1,18 +2025-03-11T12:39:29.889739,479392768,65477,192,-12.03129481654,-24.216064607505,24.479347280665,2,1,18 +2025-03-11T12:39:29.905364,479392768,65477,192,-12.32343860698,-24.484592257185,24.998415526255,2,1,18 +2025-03-11T12:39:29.920989,479392768,65477,192,-12.59673441094,-24.74846622318,25.50357455863,2,1,18 +2025-03-11T12:39:29.936614,479392768,65477,192,-12.87474221152,-25.04007477309,26.022715161205,2,1,18 +2025-03-11T12:39:29.952239,479392768,65477,192,-13.14803801548,-25.322433026385,26.52794835358,2,1,18 +2025-03-11T12:39:29.967864,479392768,65477,192,-13.42133381944,-25.59554913603,27.01003855063,2,1,18 +2025-03-11T12:39:29.983489,479392768,65477,192,-13.70405361664,-25.868681551605,27.53835414034,2,1,18 +2025-03-11T12:39:29.999038,479392772,65472,193,-13.98677341384,-26.14181396718,28.043563814725,2,1,18 +2025-03-11T12:39:30.014663,479392772,65472,193,-14.26478121442,-26.41493822979,28.54414552504,2,1,18 +2025-03-11T12:39:30.030288,479392772,65472,193,-14.52865302514,-26.68341696168,29.0631730846,2,1,18 +2025-03-11T12:39:30.045913,479392772,65472,193,-14.81137282234,-26.96117044908,29.56378011592,2,1,18 +2025-03-11T12:39:30.061538,479392772,65472,193,-15.0846686263,-27.234286558725,30.03662794684,2,1,18 +2025-03-11T12:39:30.077163,479392772,65472,193,-15.35796443026,-27.512023740195,30.532600233085,2,1,18 +2025-03-11T12:39:30.092788,479392772,65472,193,-15.62183624098,-27.789744615735,31.042422506515,2,1,18 +2025-03-11T12:39:30.108413,479392772,65472,193,-15.89984404156,-28.053626734695,31.547588319895,2,1,18 +2025-03-11T12:39:30.124038,479392772,65472,193,-16.17313984552,-28.331363916165,32.048181789205,2,1,18 +2025-03-11T12:39:30.139663,479392772,65472,193,-16.43229965962,-28.59983449509,32.525611920175,2,1,18 +2025-03-11T12:39:30.155288,479392772,65472,193,-16.69145947372,-28.86368400219,32.99840232808,2,1,18 +2025-03-11T12:39:30.170913,479392772,65472,193,-16.95533128444,-29.146025949555,33.457410127795,2,1,18 +2025-03-11T12:39:30.186538,479392772,65472,193,-17.20977910192,-29.41910944734,33.939473200825,2,1,18 +2025-03-11T12:39:30.202163,479392772,65472,193,-17.46893891602,-29.68295895444,34.42150597486,2,1,18 +2025-03-11T12:39:30.217788,479392772,65472,193,-17.74223471998,-29.937590776785,34.898900828845,2,1,18 +2025-03-11T12:39:30.233413,479392772,65472,193,-18.01081852732,-30.19683551799,35.376307441825,2,1,18 +2025-03-11T12:39:30.249038,479392772,65472,193,-18.2888263279,-30.465338708775,35.853764696815,2,1,18 +2025-03-11T12:39:30.264663,479392772,65472,193,-18.55741013524,-30.719962378155,36.36350105125,2,1,18 +2025-03-11T12:39:30.280288,479392772,65472,193,-18.8071459561,-30.9976587948,36.845575883275,2,1,18 +2025-03-11T12:39:30.295913,479392772,65472,193,-19.0663057702,-31.25226615825,37.32757157731,2,1,18 +2025-03-11T12:39:30.311538,479392772,65472,193,-19.31604159106,-31.51609935942,37.800348423205,2,1,18 +2025-03-11T12:39:30.327163,479392772,65472,193,-19.57520140516,-31.77070672287,38.259238201915,2,1,18 +2025-03-11T12:39:30.342788,479392772,65472,193,-19.82964922264,-32.02992700518,38.713518556555,2,1,18 +2025-03-11T12:39:30.358413,479392772,65472,193,-20.0793850435,-32.279896990875,39.181618599385,2,1,18 +2025-03-11T12:39:30.374038,479392772,65472,193,-20.3385448576,-32.53912542615,39.649769284225,2,1,18 +2025-03-11T12:39:30.389663,479392772,65472,193,-20.61184066156,-32.78913617667,40.113282049015,2,1,18 +2025-03-11T12:39:30.405288,479392772,65472,193,-20.86628847904,-33.02987217168,40.57210942672,2,1,18 +2025-03-11T12:39:30.420913,479392772,65472,193,-21.10188831004,-33.284438770305,41.03558648347,2,1,18 +2025-03-11T12:39:30.436538,479392772,65472,193,-21.33748814104,-33.543626440755,41.48059734796,2,1,18 +2025-03-11T12:39:30.452163,479392772,65472,193,-21.57308797204,-33.79819303938,41.92558967245,2,1,18 +2025-03-11T12:39:30.467788,479392772,65472,193,-21.81339979966,-34.048146719145,42.389054970205,2,1,18 +2025-03-11T12:39:30.483413,479392772,65472,193,-22.07255961376,-34.293511938945,42.829422936655,2,1,18 +2025-03-11T12:39:30.499038,479392772,65472,193,-22.3411434211,-34.55275668015,43.297587183505,2,1,18 +2025-03-11T12:39:30.514663,479392772,65472,193,-22.60972722844,-34.78889606223,43.77027991342,2,1,18 +2025-03-11T12:39:30.530288,479392772,65472,193,-22.8594630493,-35.0342449761,44.21063431786,2,1,18 +2025-03-11T12:39:30.545913,479392772,65472,193,-23.09035088368,-35.27031913446,44.664788067475,2,1,18 +2025-03-11T12:39:30.561538,479392772,65472,193,-23.32595071468,-35.515643589435,45.1051221289,2,1,18 +2025-03-11T12:39:30.577163,479392772,65472,193,-23.55683854906,-35.760959891445,45.52696467706,2,1,18 +2025-03-11T12:39:30.592788,479392772,65472,193,-23.79715037668,-36.006292499385,45.962684336425,2,1,18 +2025-03-11T12:39:30.608413,479392772,65472,193,-24.0374622043,-36.242382963675,46.39836691579,2,1,18 +2025-03-11T12:39:30.624038,479392772,65472,193,-24.28248602854,-36.48772372458,46.83409335616,2,1,18 +2025-03-11T12:39:30.639663,479392772,65472,193,-24.51808585954,-36.723806035905,47.25128442226,2,1,18 +2025-03-11T12:39:30.655288,479392772,65472,193,-24.75368569054,-36.955267275405,47.663835765295,2,1,18 +2025-03-11T12:39:30.670913,479392772,65472,193,-24.97043753506,-37.17283268757,48.090167913505,2,1,18 +2025-03-11T12:39:30.686538,479392772,65472,193,-25.20132536944,-37.40890684593,48.51659456473,2,1,18 +2025-03-11T12:39:30.702163,479392772,65472,193,-25.43692520044,-37.635747013605,48.93374855083,2,1,18 +2025-03-11T12:39:30.717788,479392772,65472,193,-25.66781303482,-37.862579028315,49.350895755925,2,1,18 +2025-03-11T12:39:30.733413,479392772,65472,193,-25.88456487934,-38.094007655955,49.777283524135,2,1,18 +2025-03-11T12:39:30.749038,479392772,65472,193,-26.11545271372,-38.33470288614,50.208349898425,2,1,18 +2025-03-11T12:39:30.764663,479392772,65472,193,-26.33691655486,-38.56151859492,50.61624117538,2,1,18 +2025-03-11T12:39:30.780288,479392772,65472,193,-26.558380396,-38.7698500164,51.024058292335,2,1,18 +2025-03-11T12:39:30.795913,479392772,65472,193,-26.78455623376,-38.987431734495,51.43654045336,2,1,18 +2025-03-11T12:39:30.811538,479392772,65472,193,-26.99659608166,-39.22809435282,51.825989056045,2,1,18 +2025-03-11T12:39:30.827163,479392772,65472,193,-27.21334792618,-39.45028083681,52.23847619506,2,1,18 +2025-03-11T12:39:30.842788,479392772,65472,193,-27.43952376394,-39.649378267605,52.623157097695,2,1,18 +2025-03-11T12:39:30.858413,479392772,65472,193,-27.66098760508,-39.866951832735,52.998663013195,2,1,18 +2025-03-11T12:39:30.874038,479392772,65472,193,-27.86360345974,-40.102977073305,53.401943063065,2,1,18 +2025-03-11T12:39:30.889663,479392772,65472,193,-28.07564330764,-40.30667111703,53.80048571188,2,1,18 +2025-03-11T12:39:30.905288,479392772,65472,193,-28.28768315554,-40.501123017105,54.198991280695,2,1,18 +2025-03-11T12:39:30.920913,479392772,65472,193,-28.50914699668,-40.727938725885,54.59764019152,2,1,18 +2025-03-11T12:39:30.936538,479392772,65472,193,-28.72118684458,-40.954738128735,54.977790808075,2,1,18 +2025-03-11T12:39:30.952163,479392772,65472,193,-28.9379386891,-41.1538192536,55.35321578257,2,1,18 +2025-03-11T12:39:30.967788,479392772,65472,193,-29.14526654038,-41.35750514436,55.728645735055,2,1,18 +2025-03-11T12:39:30.983413,479392772,65472,193,-29.3384584018,-41.561166576225,56.09019179533,2,1,18 +2025-03-11T12:39:30.999038,479392772,65472,193,-29.5269382666,-41.7786830706,56.4517866946,2,1,18 +2025-03-11T12:39:31.014663,479392772,65472,193,-29.73426611788,-41.98236896136,56.82259546402,2,1,18 +2025-03-11T12:39:31.030288,479392772,65472,193,-29.93688197254,-42.176804555505,57.17025445711,2,1,18 +2025-03-11T12:39:31.045913,479392772,65472,193,-30.14892182044,-42.385119671055,57.531846181405,2,1,18 +2025-03-11T12:39:31.061538,479392772,65472,193,-30.33740168524,-42.598015093605,57.89804372374,2,1,18 +2025-03-11T12:39:31.077163,479392772,65472,193,-30.52588155004,-42.801668372505,58.282688918335,2,1,18 +2025-03-11T12:39:31.092788,479392772,65472,193,-30.7284974047,-42.986861823,58.65341674675,2,1,18 +2025-03-11T12:39:31.108413,479392772,65472,193,-30.93582525598,-43.17206342646,59.019530173105,2,1,18 +2025-03-11T12:39:31.124038,479392772,65472,193,-31.14315310726,-43.36650717357,59.362574764135,2,1,18 +2025-03-11T12:39:31.139663,479392772,65472,193,-31.33634496868,-43.54706324631,59.700922209085,2,1,18 +2025-03-11T12:39:31.155288,479392772,65472,193,-31.5295368301,-43.732240390875,60.03466701097,2,1,18 +2025-03-11T12:39:31.170913,479392772,65472,193,-31.70859270166,-43.926635220195,60.382292099035,2,1,18 +2025-03-11T12:39:31.186538,479392772,65472,193,-31.89236056984,-44.12103820248,60.729923968105,2,1,18 +2025-03-11T12:39:31.202163,479392772,65472,193,-32.0714164414,-44.3154330318,61.05906432391,2,1,18 +2025-03-11T12:39:31.217788,479392772,65472,193,-32.24576031634,-44.50519863633,61.38817935871,2,1,18 +2025-03-11T12:39:31.233413,479392772,65472,193,-32.42952818452,-44.67649625949,61.71723379552,2,1,18 +2025-03-11T12:39:31.249038,479392772,65472,193,-32.6132960527,-44.852414954475,62.069412687655,2,1,18 +2025-03-11T12:39:31.264663,479392772,65472,193,-32.8017759175,-45.037583946075,62.393908342405,2,1,18 +2025-03-11T12:39:31.280288,479392772,65472,193,-32.98554378568,-45.208881569235,62.722962779215,2,1,18 +2025-03-11T12:39:31.295913,479392772,65472,193,-33.16931165386,-45.389421336045,63.03819074683,2,1,18 +2025-03-11T12:39:31.311538,479392772,65472,193,-33.33894353218,-45.56069450031,63.339497742235,2,1,18 +2025-03-11T12:39:31.327163,479392772,65472,193,-33.50386341388,-45.718096296135,63.668469435025,2,1,18 +2025-03-11T12:39:31.342788,479392772,65472,193,-33.66878329558,-45.898603451085,63.979049095555,2,1,18 +2025-03-11T12:39:31.358413,479392772,65472,193,-33.8384151739,-46.06987661535,64.294219640155,2,1,18 +2025-03-11T12:39:31.374038,479392772,65472,193,-34.0033350556,-46.25962591395,64.604836380685,2,1,18 +2025-03-11T12:39:31.389663,479392772,65472,193,-34.15883094406,-46.42163247567,64.91070713614,2,1,18 +2025-03-11T12:39:31.405288,479392772,65472,193,-34.32846282238,-46.583663496285,65.184249953155,2,1,18 +2025-03-11T12:39:31.420913,479392772,65472,193,-34.4980947007,-46.750315588725,65.471674859365,2,1,18 +2025-03-11T12:39:31.436538,479392772,65472,193,-34.67243857564,-46.89849154683,65.763653569645,2,1,18 +2025-03-11T12:39:31.452163,479392772,65472,193,-34.83264646072,-47.03740090239,66.06481722304,2,1,18 +2025-03-11T12:39:31.467788,479392772,65472,193,-34.98343035256,-47.199399311145,66.347575282165,2,1,18 +2025-03-11T12:39:31.483413,479392772,65472,193,-35.1342142444,-47.366018791725,66.63035188129,2,1,18 +2025-03-11T12:39:31.499038,479392772,65472,193,-35.28028613962,-47.53263011934,66.926985248605,2,1,18 +2025-03-11T12:39:31.514663,479392772,65472,193,-35.43107003146,-47.694628528095,67.21898567386,2,1,18 +2025-03-11T12:39:31.530288,479392772,65472,193,-35.57714192668,-47.838134496585,67.47393569359,2,1,18 +2025-03-11T12:39:31.545913,479392772,65472,193,-35.7232138219,-47.990882608725,67.74740752558,2,1,18 +2025-03-11T12:39:31.561538,479392772,65472,193,-35.87399771374,-48.148259945655,68.020904678575,2,1,18 +2025-03-11T12:39:31.577163,479392772,65472,193,-36.02006960896,-48.29638698597,68.275873238305,2,1,18 +2025-03-11T12:39:31.592788,479392772,65472,193,-36.16614150418,-48.44913509811,68.540102704165,2,1,18 +2025-03-11T12:39:31.608413,479392772,65472,193,-36.32163739264,-48.578794157055,68.8088742151,2,1,18 +2025-03-11T12:39:31.624038,479392772,65472,193,-36.46770928786,-48.71767905372,69.0545633287,2,1,18 +2025-03-11T12:39:31.639663,479392772,65472,193,-36.60435718984,-48.847305500805,69.295580617225,2,1,18 +2025-03-11T12:39:31.655288,479392772,65472,193,-36.75514108168,-48.99081962226,69.545916234895,2,1,18 +2025-03-11T12:39:31.670913,479392772,65472,193,-36.88236499042,-49.13429297889,69.800839130605,2,1,18 +2025-03-11T12:39:31.686538,479392772,65472,193,-37.01430089578,-49.26391127301,70.05571318732,2,1,18 +2025-03-11T12:39:31.702163,479392772,65472,193,-37.14623680114,-49.39352956713,70.30596606097,2,1,18 +2025-03-11T12:39:31.717788,479392772,65472,193,-37.26403671664,-49.53698661783,70.54239066241,2,1,18 +2025-03-11T12:39:31.733413,479392772,65472,193,-37.38654862876,-49.661967534195,70.769505518725,2,1,18 +2025-03-11T12:39:31.749038,479392772,65472,193,-37.52319653074,-49.78235183763,70.987379811925,2,1,18 +2025-03-11T12:39:31.764663,479392772,65472,193,-37.64570844286,-49.907332753995,71.219115851305,2,1,18 +2025-03-11T12:39:31.780288,479392772,65472,193,-37.76350835836,-50.013821230095,71.44152858355,2,1,18 +2025-03-11T12:39:31.795913,479392772,65472,193,-37.8907322671,-50.138810299425,71.65940785474,2,1,18 +2025-03-11T12:39:31.811538,479392772,65472,193,-38.01324417922,-50.268412287615,71.886541251055,2,1,18 +2025-03-11T12:39:31.827163,479392772,65472,193,-38.1263320981,-50.37489261075,72.11356838536,2,1,18 +2025-03-11T12:39:31.842788,479392772,65472,193,-38.2441320136,-50.4906232305,72.32215464841,2,1,18 +2025-03-11T12:39:31.858413,479392772,65472,193,-38.36664392572,-50.61098307504,72.54462978166,2,1,18 +2025-03-11T12:39:31.874038,479392772,65472,193,-38.49386783446,-50.72673000072,72.748608423655,2,1,18 +2025-03-11T12:39:31.889663,479392772,65472,193,-38.60695575334,-50.823968180205,72.934007830375,2,1,18 +2025-03-11T12:39:31.905288,479392772,65472,193,-38.72004367222,-50.935069575165,73.14256877242,2,1,18 +2025-03-11T12:39:31.920913,479392772,65472,193,-38.81899560124,-51.041525439405,73.327984916125,2,1,18 +2025-03-11T12:39:31.936538,479392772,65472,193,-38.9273715235,-51.157239753225,73.518072884905,2,1,18 +2025-03-11T12:39:31.952163,479392772,65472,193,-39.02632345252,-51.26831668929,73.698886385545,2,1,18 +2025-03-11T12:39:31.967788,479392772,65472,193,-39.13469937478,-51.370167787635,73.88429755126,2,1,18 +2025-03-11T12:39:31.983413,479392772,65472,193,-39.23836330042,-51.46738966119,74.055819846775,2,1,18 +2025-03-11T12:39:31.999038,479392772,65472,193,-39.3278912362,-51.5553449322,74.24114826847,2,1,18 +2025-03-11T12:39:32.014663,479392772,65472,193,-39.4221311686,-51.647929428,74.42650201117,2,1,18 +2025-03-11T12:39:32.030288,479392772,65472,193,-39.51165910438,-51.740505770835,74.57950069141,2,1,18 +2025-03-11T12:39:32.045913,479392772,65472,193,-39.60589903678,-51.823848122985,74.74633262185,2,1,18 +2025-03-11T12:39:32.061538,479392772,65472,193,-39.70956296242,-51.92106999654,74.899370185105,2,1,18 +2025-03-11T12:39:32.077163,479392772,65472,193,-39.7990908982,-52.0182674112,75.06625095454,2,1,18 +2025-03-11T12:39:32.092788,479392772,65472,193,-39.8933308306,-52.10160976335,75.24232525111,2,1,18 +2025-03-11T12:39:32.108413,479392772,65472,193,-39.987570763,-52.17570997185,75.386014186225,2,1,18 +2025-03-11T12:39:32.124038,479392772,65472,193,-40.0582507123,-52.263632631,75.538967202445,2,1,18 +2025-03-11T12:39:32.139663,479392772,65472,193,-40.13364265822,-52.342321299465,75.687268736605,2,1,18 +2025-03-11T12:39:32.155288,479392772,65472,193,-40.1996106109,-52.420993662,75.82169315956,2,1,18 +2025-03-11T12:39:32.170913,479392772,65472,193,-40.2702905602,-52.4996741775,75.942260814325,2,1,18 +2025-03-11T12:39:32.186538,479392772,65472,193,-40.34568250612,-52.56449963049,76.090506728485,2,1,18 +2025-03-11T12:39:32.202163,479392772,65472,193,-40.42578644866,-52.638575380095,76.23879650365,2,1,18 +2025-03-11T12:39:32.217788,479392772,65472,193,-40.49646639796,-52.69415053647,76.38237737374,2,1,18 +2025-03-11T12:39:32.233413,479392772,65472,193,-40.5530103574,-52.754322305775,76.51209289162,2,1,18 +2025-03-11T12:39:32.249038,479392772,65472,193,-40.6236903067,-52.842244964925,76.61883407719,2,1,18 +2025-03-11T12:39:32.264663,479392772,65472,193,-40.68494626276,-52.911667030845,76.739351089945,2,1,18 +2025-03-11T12:39:32.280288,479392772,65472,193,-40.74620221882,-52.96722588129,76.836706567375,2,1,18 +2025-03-11T12:39:32.295913,479392772,65472,193,-40.80745817488,-53.02740580356,76.947944134,2,1,18 +2025-03-11T12:39:32.311538,479392772,65472,193,-40.87342612756,-53.09221495062,77.054585838565,2,1,18 +2025-03-11T12:39:32.327163,479392772,65472,193,-40.92525809038,-53.15237856696,77.161188660115,2,1,18 +2025-03-11T12:39:32.342788,479392772,65472,193,-40.9770900532,-53.2125421833,77.267791481665,2,1,18 +2025-03-11T12:39:32.358413,479392772,65472,193,-41.0477700025,-53.277359483325,77.36057641804,2,1,18 +2025-03-11T12:39:32.374038,479392772,65472,193,-41.11373795518,-53.31906327126,77.47174660567,2,1,18 +2025-03-11T12:39:32.389663,479392772,65472,193,-41.17028191462,-53.351508609615,77.56438141903,2,1,18 +2025-03-11T12:39:32.405288,479392772,65472,193,-41.19855389434,-53.41163146113,77.64784442023,2,1,18 +2025-03-11T12:39:32.420913,479392772,65472,193,-41.23153787068,-53.45327817831,77.731240042435,2,1,18 +2025-03-11T12:39:32.436538,479392772,65472,193,-41.26923384364,-53.485690904805,77.805362999515,2,1,18 +2025-03-11T12:39:32.452163,479392772,65472,193,-41.3069298166,-53.5181036313,77.88410713966,2,1,18 +2025-03-11T12:39:32.467788,479392772,65472,193,-41.3540497828,-53.5643958792,77.972162827945,2,1,18 +2025-03-11T12:39:32.483413,479392772,65472,193,-41.39174575576,-53.58294539022,78.036987798895,2,1,18 +2025-03-11T12:39:32.499038,479392772,65472,193,-41.41530573886,-53.629196873295,78.097282483765,2,1,18 +2025-03-11T12:39:32.514663,479392772,65472,193,-41.46242570506,-53.675489121195,78.14836870753,2,1,18 +2025-03-11T12:39:32.530288,479392772,65472,193,-41.5189696645,-53.712555531375,78.20405259637,2,1,18 +2025-03-11T12:39:32.545913,479392772,65472,193,-41.55666563746,-53.75421040152,78.255106718125,2,1,18 +2025-03-11T12:39:32.561538,479392772,65472,193,-41.56137763408,-53.77732391361,78.296796846715,2,1,18 +2025-03-11T12:39:32.577163,479392772,65472,193,-41.58493761718,-53.795848965735,78.347737925455,2,1,18 +2025-03-11T12:39:32.592788,479392772,65472,193,-41.60378560366,-53.823608008545,78.38946693706,2,1,18 +2025-03-11T12:39:32.608413,479392772,65472,193,-41.62263359014,-53.842124907705,78.449643600925,2,1,18 +2025-03-11T12:39:32.624038,479392772,65472,193,-41.65090556986,-53.860658112795,78.49134909454,2,1,18 +2025-03-11T12:39:32.639663,479392772,65472,193,-41.67917754958,-53.85608595876,78.5006136067,2,1,18 +2025-03-11T12:39:32.655288,479392772,65472,193,-41.6838895462,-53.874578399025,78.5145580969,2,1,18 +2025-03-11T12:39:32.670913,479392772,65472,193,-41.69331353944,-53.893078992255,78.546994100365,2,1,18 +2025-03-11T12:39:32.686538,479392772,65472,193,-41.7074495293,-53.91158773845,78.570194518705,2,1,18 +2025-03-11T12:39:32.702163,479392772,65472,193,-41.71687352254,-53.916225116205,78.59333253604,2,1,18 +2025-03-11T12:39:32.717788,479392772,65472,193,-41.74514550226,-53.93013724947,78.63039830659,2,1,18 +2025-03-11T12:39:32.733413,479392772,65472,193,-41.74514550226,-53.944000464945,78.64893865885,2,1,18 +2025-03-11T12:39:32.749038,479392772,65472,193,-41.74514550226,-53.944000464945,78.644317475785,2,1,18 +2025-03-11T12:39:32.764663,479392772,65472,193,-41.74043350564,-53.94399231198,78.630447145585,2,1,18 +2025-03-11T12:39:32.780288,479392772,65472,193,-41.74985749888,-53.95325076156,78.62587660453,2,1,18 +2025-03-11T12:39:32.795913,479392772,65472,193,-41.76870548536,-53.939420157945,78.63509047468,2,1,18 +2025-03-11T12:39:32.811538,479392772,65472,193,-41.75928149212,-53.939403852015,78.648940461865,2,1,18 +2025-03-11T12:39:32.827163,479392772,65472,193,-41.74043350564,-53.939371240155,78.630428605585,2,1,18 +2025-03-11T12:39:32.842788,479392772,65472,193,-41.7310095124,-53.9347338624,78.621154137445,2,1,18 +2025-03-11T12:39:32.858413,479392772,65472,193,-41.71687352254,-53.93008833168,78.60263052217,2,1,18 +2025-03-11T12:39:32.874038,479392772,65472,193,-41.70273753268,-53.911579585485,78.5701877377,2,1,18 +2025-03-11T12:39:32.889663,479392772,65472,193,-41.67917754958,-53.89305453336,78.542352574285,2,1,18 +2025-03-11T12:39:32.905288,479392772,65472,193,-41.66975355634,-53.89303822743,78.514611913885,2,1,18 +2025-03-11T12:39:32.920913,479392772,65472,193,-41.66504155972,-53.893030074465,78.49612040062,2,1,18 +2025-03-11T12:39:32.936538,479392772,65472,193,-41.66504155972,-53.856061499865,78.482108531425,2,1,18 +2025-03-11T12:39:32.952163,479392772,65472,193,-41.64148157662,-53.82829430409,78.41726682349,2,1,18 +2025-03-11T12:39:32.967788,479392772,65472,193,-41.6132095969,-53.795897883525,78.347778611485,2,1,18 +2025-03-11T12:39:32.983413,479392772,65472,193,-41.59907360704,-53.772768065505,78.306074920885,2,1,18 +2025-03-11T12:39:32.999038,479392772,65472,193,-41.57551362394,-53.749621941555,78.25049411908,2,1,18 +2025-03-11T12:39:33.014663,479392772,65472,193,-41.5425296476,-53.72183843985,78.1902600322,2,1,18 +2025-03-11T12:39:33.030288,479392772,65472,193,-41.51425766788,-53.67557880381,78.12533738326,2,1,18 +2025-03-11T12:39:33.045913,479392772,65472,193,-41.47656169492,-53.643166077315,78.083562707635,2,1,18 +2025-03-11T12:39:33.061538,479392772,65472,193,-41.43886572196,-53.606132278995,78.03252712588,2,1,18 +2025-03-11T12:39:33.077163,479392772,65472,193,-41.40588174562,-53.56910663364,77.976877142065,2,1,18 +2025-03-11T12:39:33.092788,479392772,65472,193,-41.37289776928,-53.53670206011,77.916624515185,2,1,18 +2025-03-11T12:39:33.108413,479392772,65472,193,-41.32577780308,-53.504273027685,77.8286244469,2,1,18 +2025-03-11T12:39:33.124038,479392772,65472,193,-41.27394584026,-53.444109411345,77.735885174545,2,1,18 +2025-03-11T12:39:33.139663,479392772,65472,193,-41.2362498673,-53.4024545412,77.652482771335,2,1,18 +2025-03-11T12:39:33.155288,479392772,65472,193,-41.17970590786,-53.370009202845,77.569090324105,2,1,18 +2025-03-11T12:39:33.170913,479392772,65472,193,-41.13258594166,-53.323716954945,77.48103463582,2,1,18 +2025-03-11T12:39:33.186538,479392772,65472,193,-41.0948899687,-53.258956725675,77.39753953261,2,1,18 +2025-03-11T12:39:33.202163,479392772,65472,193,-41.0477700025,-53.18955911865,77.30476996126,2,1,18 +2025-03-11T12:39:33.217788,479392772,65472,193,-40.98651404644,-53.14786348368,77.193606554635,2,1,18 +2025-03-11T12:39:33.233413,479392772,65472,193,-40.92054609376,-53.11078076757,77.100939639265,2,1,18 +2025-03-11T12:39:33.249038,479392772,65472,193,-40.87813812418,-53.046012385335,76.99895302279,2,1,18 +2025-03-11T12:39:33.264663,479392772,65472,193,-40.82159416474,-52.962735256905,76.901493086365,2,1,18 +2025-03-11T12:39:33.280288,479392772,65472,193,-40.74620221882,-52.91177301939,76.799514622855,2,1,18 +2025-03-11T12:39:33.295913,479392772,65472,193,-40.68023426614,-52.870069231455,76.697586801355,2,1,18 +2025-03-11T12:39:33.311538,479392772,65472,193,-40.63311429994,-52.79142948078,76.567810685485,2,1,18 +2025-03-11T12:39:33.327163,479392772,65472,193,-40.56243435064,-52.70350682163,76.43796358459,2,1,18 +2025-03-11T12:39:33.342788,479392772,65472,193,-40.48704240472,-52.634060296815,76.31742622882,2,1,18 +2025-03-11T12:39:33.358413,479392772,65472,193,-40.40222646556,-52.57383960972,76.19691239104,2,1,18 +2025-03-11T12:39:33.374038,479392772,65472,193,-40.32683451964,-52.513635228555,76.05792738301,2,1,18 +2025-03-11T12:39:33.389663,479392772,65472,193,-40.26557856358,-52.444213162635,75.909683271865,2,1,18 +2025-03-11T12:39:33.405288,479392772,65472,193,-40.19489861428,-52.374774790785,75.76142559871,2,1,18 +2025-03-11T12:39:33.420913,479392772,65472,193,-40.12421866498,-52.29147320346,75.603869939425,2,1,18 +2025-03-11T12:39:33.436538,479392772,65472,193,-40.0346907292,-52.20351793245,75.450889799185,2,1,18 +2025-03-11T12:39:33.452163,479392772,65472,193,-39.94516279342,-52.120183733265,75.31179174814,2,1,18 +2025-03-11T12:39:33.467788,479392772,65472,193,-39.86505885088,-52.041486911835,75.14961988378,2,1,18 +2025-03-11T12:39:33.483413,479392772,65472,193,-39.7755309151,-51.944289497175,74.99660266354,2,1,18 +2025-03-11T12:39:33.499038,479392772,65472,193,-39.70013896918,-51.84711654141,74.834363420185,2,1,18 +2025-03-11T12:39:33.514663,479392772,65472,193,-39.61532303002,-51.76379049519,74.667545051755,2,1,18 +2025-03-11T12:39:33.530288,479392772,65472,193,-39.52579509424,-51.680456296005,74.50996226845,2,1,18 +2025-03-11T12:39:33.545913,479392772,65472,193,-39.4456911517,-51.583275187275,74.343095061025,2,1,18 +2025-03-11T12:39:33.561538,479392772,65472,193,-39.3514512193,-51.4953117633,74.14389630913,2,1,18 +2025-03-11T12:39:33.577163,479392772,65472,193,-39.24778729366,-51.37498453062,73.96766013055,2,1,18 +2025-03-11T12:39:33.592788,479392772,65472,193,-39.14883536464,-51.25928652273,73.79607045604,2,1,18 +2025-03-11T12:39:33.608413,479392772,65472,193,-39.04988343562,-51.16207280214,73.60607020927,2,1,18 +2025-03-11T12:39:33.624038,479392772,65472,193,-38.93679551674,-51.064834622655,73.42067080255,2,1,18 +2025-03-11T12:39:33.639663,479392772,65472,193,-38.81899560124,-50.97220936203,73.2121772395,2,1,18 +2025-03-11T12:39:33.655288,479392772,65472,193,-38.71061967898,-50.879600407335,73.017560787655,2,1,18 +2025-03-11T12:39:33.670913,479392772,65472,193,-38.61166774996,-50.773144543095,72.799796362495,2,1,18 +2025-03-11T12:39:33.686538,479392772,65472,193,-38.50800382432,-50.643575166765,72.586553639395,2,1,18 +2025-03-11T12:39:33.702163,479392772,65472,193,-38.39491590544,-50.532473771805,72.38723506348,2,1,18 +2025-03-11T12:39:33.717788,479392772,65472,193,-38.26298000008,-50.40747654951,72.187833743545,2,1,18 +2025-03-11T12:39:33.733413,479392772,65472,193,-38.14518008458,-50.29174592976,71.979247480495,2,1,18 +2025-03-11T12:39:33.749038,479392772,65472,193,-38.02266817246,-50.16214394157,71.76135645031,2,1,18 +2025-03-11T12:39:33.764663,479392772,65472,193,-37.9142922502,-50.041808555925,71.548144026205,2,1,18 +2025-03-11T12:39:33.780288,479392772,65472,193,-37.80120433132,-49.91684394549,71.3210427319,2,1,18 +2025-03-11T12:39:33.795913,479392772,65472,193,-37.66455642934,-49.79183857023,71.089286349505,2,1,18 +2025-03-11T12:39:33.811538,479392772,65472,193,-37.54204451722,-49.666857653865,70.86217149319,2,1,18 +2025-03-11T12:39:33.827163,479392772,65472,193,-37.41482060848,-49.560352871835,70.658229931195,2,1,18 +2025-03-11T12:39:33.842788,479392772,65472,193,-37.27346070988,-49.430718271785,70.426448227795,2,1,18 +2025-03-11T12:39:33.858413,479392772,65472,193,-37.15094879776,-49.28725306812,70.18077447922,2,1,18 +2025-03-11T12:39:33.874038,479392772,65472,193,-37.02372488902,-49.14377971149,69.92585158351,2,1,18 +2025-03-11T12:39:33.889663,479392772,65472,193,-36.89178898366,-49.009540345545,69.68482253599,2,1,18 +2025-03-11T12:39:33.905288,479392772,65472,193,-36.75042908506,-48.870663601845,69.43451902033,2,1,18 +2025-03-11T12:39:33.920913,479392772,65472,193,-36.60435718984,-48.727157633355,69.1795690006,2,1,18 +2025-03-11T12:39:33.936538,479392772,65472,193,-36.4771332811,-48.592926420375,68.929304367955,2,1,18 +2025-03-11T12:39:33.952163,479392772,65472,193,-36.34048537912,-48.42633139869,68.66965402717,2,1,18 +2025-03-11T12:39:33.967788,479392772,65472,193,-36.18970148728,-48.27819620541,68.40081513724,2,1,18 +2025-03-11T12:39:33.983413,479392772,65472,193,-36.04834158868,-48.153182677185,68.136703692385,2,1,18 +2025-03-11T12:39:33.998977,479392776,65468,194,-35.89755769684,-48.00966855573,67.86326215939,2,1,18 +2025-03-11T12:39:34.014602,479392776,65468,194,-35.75148580162,-47.870783659065,67.585224764335,2,1,18 +2025-03-11T12:39:34.030227,479392776,65468,194,-35.6054139064,-47.72265661875,67.311771472345,2,1,18 +2025-03-11T12:39:34.045852,479392776,65468,194,-35.45463001456,-47.56527928182,67.03827431935,2,1,18 +2025-03-11T12:39:34.061477,479392776,65468,194,-35.28971013286,-47.407877485995,66.769378006405,2,1,18 +2025-03-11T12:39:34.077102,479392776,65468,194,-35.13892624102,-47.26436336454,66.482072924215,2,1,18 +2025-03-11T12:39:34.092727,479392776,65468,194,-34.99756634242,-47.12548662084,66.204042310165,2,1,18 +2025-03-11T12:39:34.108352,479392776,65468,194,-34.8514944472,-46.96349636505,65.912048665915,2,1,18 +2025-03-11T12:39:34.123977,479392776,65468,194,-34.68186256888,-46.79684427261,65.61076021051,2,1,18 +2025-03-11T12:39:34.139602,479392776,65468,194,-34.53107867704,-46.625603720205,65.309480339125,2,1,18 +2025-03-11T12:39:34.155227,479392776,65468,194,-34.37558278858,-46.45897608666,65.02207577593,2,1,18 +2025-03-11T12:39:34.170852,479392776,65468,194,-34.21066290688,-46.283090003535,64.72999938766,2,1,18 +2025-03-11T12:39:34.186477,479392776,65468,194,-34.03631903194,-46.121050829955,64.42872269125,2,1,18 +2025-03-11T12:39:34.202102,479392776,65468,194,-33.85726316038,-45.954382431585,64.12279949077,2,1,18 +2025-03-11T12:39:34.217727,479392776,65468,194,-33.68763128206,-45.769246051845,63.784467410845,2,1,18 +2025-03-11T12:39:34.233352,479392776,65468,194,-33.5085754105,-45.588714438,63.48310977343,2,1,18 +2025-03-11T12:39:34.248977,479392776,65468,194,-33.33894353218,-45.417441273735,63.181802778025,2,1,18 +2025-03-11T12:39:34.264602,479392776,65468,194,-33.16931165386,-45.26465239677,62.87132757649,2,1,18 +2025-03-11T12:39:34.280227,479392776,65468,194,-33.00439177216,-45.088766313645,62.5422817237,2,1,18 +2025-03-11T12:39:34.295852,479392776,65468,194,-32.8253359006,-44.894371484325,62.213141367895,2,1,18 +2025-03-11T12:39:34.311477,479392776,65468,194,-32.64628002904,-44.70459772683,61.89326191822,2,1,18 +2025-03-11T12:39:34.327102,479392776,65468,194,-32.45780016424,-44.533291950705,61.55033715121,2,1,18 +2025-03-11T12:39:34.342727,479392776,65468,194,-32.27874429268,-44.348139265035,61.20737032621,2,1,18 +2025-03-11T12:39:34.358352,479392776,65468,194,-32.0949764245,-44.158357354575,60.882862912465,2,1,18 +2025-03-11T12:39:34.373977,479392776,65468,194,-31.92063254956,-43.959349606395,60.5490896146,2,1,18 +2025-03-11T12:39:34.389602,479392776,65468,194,-31.72744068814,-43.77417246183,60.20148126352,2,1,18 +2025-03-11T12:39:34.405227,479392776,65468,194,-31.53424882672,-43.579753173615,59.839972283245,2,1,18 +2025-03-11T12:39:34.420852,479392776,65468,194,-31.35990495178,-43.39460864091,59.48776987312,2,1,18 +2025-03-11T12:39:34.436477,479392776,65468,194,-31.17142508698,-43.20943964931,59.140168303045,2,1,18 +2025-03-11T12:39:34.452102,479392776,65468,194,-30.97823322556,-43.02888357657,58.79719967503,2,1,18 +2025-03-11T12:39:34.467727,479392776,65468,194,-30.7756173709,-42.83906905425,58.426453306615,2,1,18 +2025-03-11T12:39:34.483352,479392776,65468,194,-30.58242550948,-42.653891909685,58.069602589405,2,1,18 +2025-03-11T12:39:34.498977,479392776,65468,194,-30.38452165144,-42.468706612155,57.70350272506,2,1,18 +2025-03-11T12:39:34.514602,479392776,65468,194,-30.1866177934,-42.2604159555,57.36041607604,2,1,18 +2025-03-11T12:39:34.530227,479392776,65468,194,-29.98871393536,-42.05674637067,57.021969150085,2,1,18 +2025-03-11T12:39:34.545852,479392776,65468,194,-29.77667408746,-41.84843125512,56.65113505966,2,1,18 +2025-03-11T12:39:34.561477,479392776,65468,194,-29.5504982497,-41.630849537025,56.284864729285,2,1,18 +2025-03-11T12:39:34.577102,479392776,65468,194,-29.34788239504,-41.422550727405,55.89555946861,2,1,18 +2025-03-11T12:39:34.592727,479392776,65468,194,-29.15940253024,-41.21427637668,55.520138100145,2,1,18 +2025-03-11T12:39:34.608352,479392776,65468,194,-28.94265068572,-41.01057417999,55.13545221952,2,1,18 +2025-03-11T12:39:34.623977,479392776,65468,194,-28.71647484796,-40.80685567737,54.73688922769,2,1,18 +2025-03-11T12:39:34.639602,479392776,65468,194,-28.51857098992,-40.580080733415,54.342895404955,2,1,18 +2025-03-11T12:39:34.655227,479392776,65468,194,-28.32066713188,-40.367169004935,53.94895720222,2,1,18 +2025-03-11T12:39:34.670852,479392776,65468,194,-28.12747527046,-40.15426542942,53.58275287888,2,1,18 +2025-03-11T12:39:34.686477,479392776,65468,194,-27.91543542256,-39.932087098395,53.20724198539,2,1,18 +2025-03-11T12:39:34.702102,479392776,65468,194,-27.67983559156,-39.719110146195,52.79938598542,2,1,18 +2025-03-11T12:39:34.717727,479392776,65468,194,-27.4536597538,-39.515391643575,52.386959444395,2,1,18 +2025-03-11T12:39:34.733352,479392776,65468,194,-27.23690790928,-39.28858408776,51.979074948445,2,1,18 +2025-03-11T12:39:34.748977,479392776,65468,194,-27.02015606476,-39.061776531945,51.58505400169,2,1,18 +2025-03-11T12:39:34.764602,479392776,65468,194,-26.793980227,-38.830331598375,51.191000952925,2,1,18 +2025-03-11T12:39:34.780227,479392776,65468,194,-26.57722838248,-38.598902970735,50.783097916975,2,1,18 +2025-03-11T12:39:34.795852,479392776,65468,194,-26.35105254472,-38.385942324465,50.375255479015,2,1,18 +2025-03-11T12:39:34.811477,479392776,65468,194,-26.12016471034,-38.159110309755,49.97659300618,2,1,18 +2025-03-11T12:39:34.827102,479392776,65468,194,-25.8987008692,-37.9369156728,49.559477903095,2,1,18 +2025-03-11T12:39:34.842727,479392776,65468,194,-25.67252503144,-37.700849667405,49.151542765135,2,1,18 +2025-03-11T12:39:34.858352,479392776,65468,194,-25.44163719706,-37.46939658087,48.72513465391,2,1,18 +2025-03-11T12:39:34.873977,479392776,65468,194,-25.20603736606,-37.242556413195,48.312601850875,2,1,18 +2025-03-11T12:39:34.889602,479392776,65468,194,-24.98928552154,-37.00650671373,47.89081672573,2,1,18 +2025-03-11T12:39:34.905227,479392776,65468,194,-24.76310968378,-36.75657749286,47.45509886938,2,1,18 +2025-03-11T12:39:34.920852,479392776,65468,194,-24.5322218494,-36.515882262675,47.00554776283,2,1,18 +2025-03-11T12:39:34.936477,479392776,65468,194,-24.2966220184,-36.289042095,46.574530227535,2,1,18 +2025-03-11T12:39:34.952102,479392776,65468,194,-24.05631019078,-36.05295163071,46.13884764817,2,1,18 +2025-03-11T12:39:34.967727,479392776,65468,194,-23.81128636654,-35.82147408528,45.69393446167,2,1,18 +2025-03-11T12:39:34.983352,479392776,65468,194,-23.57097453892,-35.590004692815,45.2721339715,2,1,18 +2025-03-11T12:39:34.998977,479392776,65468,194,-23.32595071468,-35.349285003735,44.827183705,2,1,18 +2025-03-11T12:39:35.014602,479392776,65468,194,-23.08563888706,-35.09933132397,44.3960666887,2,1,18 +2025-03-11T12:39:35.030227,479392776,65468,194,-22.8594630493,-34.8678863904,43.965044175415,2,1,18 +2025-03-11T12:39:35.045852,479392776,65468,194,-22.62857521492,-34.617949016565,43.515455988865,2,1,18 +2025-03-11T12:39:35.061477,479392776,65468,194,-22.37883939406,-34.363357959045,43.07044332136,2,1,18 +2025-03-11T12:39:35.077102,479392776,65468,194,-22.1291035732,-34.122630117,42.63010745692,2,1,18 +2025-03-11T12:39:35.092727,479392776,65468,194,-21.87465575572,-33.868030906515,42.161982093085,2,1,18 +2025-03-11T12:39:35.108352,479392776,65468,194,-21.6343439281,-33.604214011275,41.703082358395,2,1,18 +2025-03-11T12:39:35.123977,479392776,65468,194,-21.38932010386,-33.34963110672,41.258076471895,2,1,18 +2025-03-11T12:39:35.139602,479392776,65468,194,-21.12544829314,-33.09963666213,40.785334902985,2,1,18 +2025-03-11T12:39:35.155227,479392776,65468,194,-20.86628847904,-32.858892514155,40.33112192734,2,1,18 +2025-03-11T12:39:35.170852,479392776,65468,194,-20.60241666832,-32.61351914139,39.86764126456,2,1,18 +2025-03-11T12:39:35.186477,479392776,65468,194,-20.34796885084,-32.349677787255,39.399478820725,2,1,18 +2025-03-11T12:39:35.202102,479392776,65468,194,-20.09352103336,-32.081215361295,38.94978256915,2,1,18 +2025-03-11T12:39:35.217727,479392776,65468,194,-19.83907321588,-31.821995078985,38.472396299185,2,1,18 +2025-03-11T12:39:35.233352,479392776,65468,194,-19.59404939164,-31.581275389905,37.99509775123,2,1,18 +2025-03-11T12:39:35.248977,479392776,65468,194,-19.3490255674,-31.3174503417,37.526948869405,2,1,18 +2025-03-11T12:39:35.264602,479392776,65468,194,-19.09928974654,-31.05361714053,37.058793206575,2,1,18 +2025-03-11T12:39:35.280227,479392776,65468,194,-18.83541793582,-30.79438055229,36.59063574073,2,1,18 +2025-03-11T12:39:35.295852,479392776,65468,194,-18.57625812172,-30.544394260665,36.14100686815,2,1,18 +2025-03-11T12:39:35.311477,479392776,65468,194,-18.31709830762,-30.28516582539,35.668235000245,2,1,18 +2025-03-11T12:39:35.327102,479392776,65468,194,-18.04851450028,-30.03054215601,35.15849864581,2,1,18 +2025-03-11T12:39:35.342727,479392776,65468,194,-17.77521869632,-29.75280497454,34.68563227489,2,1,18 +2025-03-11T12:39:35.358352,479392776,65468,194,-17.51605888222,-29.47971332379,34.18969887166,2,1,18 +2025-03-11T12:39:35.373977,479392776,65468,194,-17.24747507488,-29.22508965441,33.70306843255,2,1,18 +2025-03-11T12:39:35.389602,479392776,65468,194,-16.97889126754,-28.947360625905,33.230208842635,2,1,18 +2025-03-11T12:39:35.405227,479392776,65468,194,-16.70559546358,-28.67424451626,32.73425509639,2,1,18 +2025-03-11T12:39:35.420852,479392776,65468,194,-16.43701165624,-28.405757631405,32.24756903728,2,1,18 +2025-03-11T12:39:35.436477,479392776,65468,194,-16.16371585228,-28.118778306285,31.770044403295,2,1,18 +2025-03-11T12:39:35.452102,479392776,65468,194,-15.89042004832,-27.841041124815,31.27407211705,2,1,18 +2025-03-11T12:39:35.467727,479392776,65468,194,-15.61712424436,-27.54944072787,30.75493829548,2,1,18 +2025-03-11T12:39:35.483352,479392776,65468,194,-15.35325243364,-27.294825211455,30.268314637375,2,1,18 +2025-03-11T12:39:35.498977,479392776,65468,194,-15.0846686263,-27.021717254775,29.76774648907,2,1,18 +2025-03-11T12:39:35.514602,479392776,65468,194,-14.81137282234,-26.753222216955,29.26719009976,2,1,18 +2025-03-11T12:39:35.530227,479392776,65468,194,-14.55221300824,-26.49399378168,28.775933499595,2,1,18 +2025-03-11T12:39:35.545852,479392776,65468,194,-14.27891720428,-26.220877672035,28.27997975335,2,1,18 +2025-03-11T12:39:35.561477,479392776,65468,194,-14.0009094037,-25.947753409425,27.779398043035,2,1,18 +2025-03-11T12:39:35.577102,479392776,65468,194,-13.73232559636,-25.67002438092,27.274190171665,2,1,18 +2025-03-11T12:39:35.592727,479392776,65468,194,-13.44960579916,-25.39227089352,26.755098408085,2,1,18 +2025-03-11T12:39:35.608352,479392776,65468,194,-13.16688600196,-25.109896334295,26.226745738375,2,1,18 +2025-03-11T12:39:35.623977,479392776,65468,194,-12.88416620476,-24.82752177507,25.716877800925,2,1,18 +2025-03-11T12:39:35.639602,479392776,65468,194,-12.59202241432,-24.545130909915,25.216238667595,2,1,18 +2025-03-11T12:39:35.655227,479392776,65468,194,-12.30930261712,-24.267377422515,24.724874002405,2,1,18 +2025-03-11T12:39:35.670852,479392776,65468,194,-12.03129481654,-23.994253159905,24.219671109025,2,1,18 +2025-03-11T12:39:35.686477,479392776,65468,194,-11.75328701596,-23.702644609995,23.69128814032,2,1,18 +2025-03-11T12:39:35.702102,479392776,65468,194,-11.479991212,-23.4202863567,23.18143376488,2,1,18 +2025-03-11T12:39:35.717727,479392776,65468,194,-11.20198341142,-23.12867780679,22.6761567115,2,1,18 +2025-03-11T12:39:35.733352,479392776,65468,194,-10.91926361422,-22.846303247565,22.14780404179,2,1,18 +2025-03-11T12:39:35.748977,479392776,65468,194,-10.64125581364,-22.55931576948,21.63330316228,2,1,18 +2025-03-11T12:39:35.764602,479392776,65468,194,-10.34440002658,-22.281537823185,21.104948689555,2,1,18 +2025-03-11T12:39:35.780227,479392776,65468,194,-10.04754423952,-22.00375987689,20.57659421683,2,1,18 +2025-03-11T12:39:35.795852,479392776,65468,194,-9.77424843556,-21.72602269542,20.062137198325,2,1,18 +2025-03-11T12:39:35.811477,479392776,65468,194,-9.49152863836,-21.42978492072,19.542971274745,2,1,18 +2025-03-11T12:39:35.827102,479392776,65468,194,-9.21352083778,-21.14741851446,19.019246569105,2,1,18 +2025-03-11T12:39:35.842727,479392776,65468,194,-8.92137704734,-20.846543362005,18.49542736045,2,1,18 +2025-03-11T12:39:35.858352,479392776,65468,194,-8.63394525352,-20.564160649815,17.94396199441,2,1,18 +2025-03-11T12:39:35.873977,479392776,65468,194,-8.34180146308,-20.28176978466,17.42483812882,2,1,18 +2025-03-11T12:39:35.889602,479392776,65468,194,-8.0402336794,-19.990120469925,16.910284804285,2,1,18 +2025-03-11T12:39:35.905227,479392776,65468,194,-7.7339538991,-19.6938419304,16.40032734181,2,1,18 +2025-03-11T12:39:35.920852,479392776,65468,194,-7.46537009176,-19.39300754277,15.86729967205,2,1,18 +2025-03-11T12:39:35.936477,479392776,65468,194,-7.1920742878,-19.1152703613,15.325115555155,2,1,18 +2025-03-11T12:39:35.952102,479392776,65468,194,-6.89521850074,-18.828250271355,14.792102819365,2,1,18 +2025-03-11T12:39:35.967727,479392776,65468,194,-6.61249870354,-18.50890713753,14.282086561915,2,1,18 +2025-03-11T12:39:35.983352,479392776,65468,194,-6.31093091986,-18.217257822795,13.735184955925,2,1,18 +2025-03-11T12:39:35.998977,479392776,65468,194,-6.00936313618,-17.939471723535,13.192960153,2,1,18 +2025-03-11T12:39:36.014602,479392776,65468,194,-5.72193134236,-17.64322579587,12.664545082285,2,1,18 +2025-03-11T12:39:36.030227,479392776,65468,194,-5.4250755553,-17.337721418625,12.10835227117,2,1,18 +2025-03-11T12:39:36.045852,479392776,65468,194,-5.13764376148,-17.04147549096,11.570694834325,2,1,18 +2025-03-11T12:39:36.061477,479392776,65468,194,-4.85021196766,-16.74060849147,11.06074595587,2,1,18 +2025-03-11T12:39:36.077102,479392776,65468,194,-4.5533561806,-16.444346257875,10.532317323145,2,1,18 +2025-03-11T12:39:36.092727,479392776,65468,194,-4.2470764003,-16.14806771835,9.98539039615,2,1,18 +2025-03-11T12:39:36.108352,479392776,65468,194,-3.95964460648,-15.851821790685,9.447732959305,2,1,18 +2025-03-11T12:39:36.123977,479392776,65468,194,-3.67221281266,-15.56481800667,8.905491419395,2,1,18 +2025-03-11T12:39:36.139602,479392776,65468,194,-3.37064502898,-15.263926548285,8.340068001145,2,1,18 +2025-03-11T12:39:36.155227,479392776,65468,194,-3.07378924192,-14.96766431469,7.807018185355,2,1,18 +2025-03-11T12:39:36.170852,479392776,65468,194,-2.78164545148,-14.666789162235,7.278577793635,2,1,18 +2025-03-11T12:39:36.186477,479392776,65468,194,-2.49892565428,-14.37517245936,6.73632449473,2,1,18 +2025-03-11T12:39:36.202102,479392776,65468,194,-2.20678186384,-14.074297306905,6.18939937075,2,1,18 +2025-03-11T12:39:36.217727,479392776,65468,194,-1.9146380734,-13.768801082625,5.6516980729,2,1,18 +2025-03-11T12:39:36.233352,479392776,65468,194,-1.61307028972,-13.46790962424,5.12324411917,2,1,18 +2025-03-11T12:39:36.248977,479392776,65468,194,-1.3020785128,-13.17162293175,4.5855527773,2,1,18 +2025-03-11T12:39:36.264602,479392776,65468,194,-1.00522272574,-12.87073962633,4.038620872315,2,1,18 +2025-03-11T12:39:36.280227,479392776,65468,194,-0.70365494206,-12.579090311595,3.47785571713,2,1,18 +2025-03-11T12:39:36.295852,479392776,65468,194,-0.406799155,-12.27358593435,2.921662906015,2,1,18 +2025-03-11T12:39:36.311477,479392776,65468,194,-0.11465536456,-11.97733185372,2.3793775051,2,1,18 +2025-03-11T12:39:36.327102,479392776,65468,194,0.1822004225,-11.671827476475,1.83704824318,2,1,18 +2025-03-11T12:39:36.342727,479392776,65468,194,0.49319219942,-11.366298640335,1.29007745518,2,1,18 +2025-03-11T12:39:36.358352,479392776,65468,194,0.78533598986,-11.070044559705,0.747792054265,2,1,18 +2025-03-11T12:39:36.373977,479392776,65468,194,1.08690377354,-10.77839524497,0.210132814405,2,1,18 +2025-03-11T12:39:36.389602,479392776,65468,194,1.3837595606,-10.4867540832,-0.322898461385,2,1,18 +2025-03-11T12:39:36.405227,479392776,65468,194,1.68532734428,-10.185862624815,-0.87445833044,2,1,18 +2025-03-11T12:39:36.420852,479392776,65468,194,1.98689512796,-9.898834381905,-1.407477847235,2,1,18 +2025-03-11T12:39:36.436477,479392776,65468,194,2.28846291164,-9.59794292352,-1.95903771629,2,1,18 +2025-03-11T12:39:36.452102,479392776,65468,194,2.58060670208,-9.30168884289,-2.5151866664,2,1,18 +2025-03-11T12:39:36.467727,479392776,65468,194,2.88688648238,-8.996168159715,-3.07601422259,2,1,18 +2025-03-11T12:39:36.483352,479392776,65468,194,3.18374226944,-8.695284854295,-3.622946127575,2,1,18 +2025-03-11T12:39:36.498977,479392776,65468,194,3.4805980565,-8.38978047705,-4.156033023365,2,1,18 +2025-03-11T12:39:36.514602,479392776,65468,194,3.78216584018,-8.06578365954,-4.69844322629,2,1,18 +2025-03-11T12:39:36.530227,479392776,65468,194,4.08373362386,-7.783376488455,-5.249928935345,2,1,18 +2025-03-11T12:39:36.545852,479392776,65468,194,4.38058941092,-7.482493183035,-5.819966755655,2,1,18 +2025-03-11T12:39:36.561477,479392776,65468,194,4.67273320136,-7.158512671455,-6.38084812883,2,1,18 +2025-03-11T12:39:36.577102,479392776,65468,194,4.97430098504,-6.86686335672,-6.92774973482,2,1,18 +2025-03-11T12:39:36.592727,479392776,65468,194,5.2711567721,-6.570601123125,-7.47004191674,2,1,18 +2025-03-11T12:39:36.608352,479392776,65468,194,5.58214854902,-6.26969335881,-8.012372981675,2,1,18 +2025-03-11T12:39:36.623977,479392776,65468,194,5.87429233946,-5.959576062705,-8.550092819525,2,1,18 +2025-03-11T12:39:36.639602,479392776,65468,194,6.17114812652,-5.66331382911,-9.101627367575,2,1,18 +2025-03-11T12:39:36.655227,479392776,65468,194,6.45386792372,-5.371697126235,-9.680850131,2,1,18 +2025-03-11T12:39:36.670852,479392776,65468,194,6.7554357074,-5.0985320988,-10.22767757699,2,1,18 +2025-03-11T12:39:36.686477,479392776,65468,194,7.05700349108,-4.797640640415,-10.760752713785,2,1,18 +2025-03-11T12:39:36.702102,479392776,65468,194,7.36328327138,-4.487498885415,-11.29849289465,2,1,18 +2025-03-11T12:39:36.717727,479392776,65468,194,7.65542706182,-4.18662373296,-11.8361756525,2,1,18 +2025-03-11T12:39:36.733352,479392776,65468,194,7.94757085226,-3.885748580505,-12.387721959545,2,1,18 +2025-03-11T12:39:36.748977,479392776,65468,194,8.24442663932,-3.57100205961,-12.920845935335,2,1,18 +2025-03-11T12:39:36.764602,479392776,65468,194,8.545994423,-3.27473167305,-13.458523715195,2,1,18 +2025-03-11T12:39:36.780227,479392776,65468,194,8.8522742033,-2.978453133525,-14.01469300832,2,1,18 +2025-03-11T12:39:36.795852,479392776,65468,194,9.14441799374,-2.672956909245,-14.547773123105,2,1,18 +2025-03-11T12:39:36.811477,479392776,65468,194,9.44598577742,-2.37206545086,-15.09933299216,2,1,18 +2025-03-11T12:39:36.827102,479392776,65468,194,9.73812956786,-2.06656922658,-15.63703429001,2,1,18 +2025-03-11T12:39:36.842727,479392776,65468,194,10.0302733583,-1.774936217775,-16.17467996786,2,1,18 +2025-03-11T12:39:36.858352,479392776,65468,194,10.33184114198,-1.497150118515,-16.72152595385,2,1,18 +2025-03-11T12:39:36.873977,479392776,65468,194,10.63340892566,-1.19625866013,-17.24997990758,2,1,18 +2025-03-11T12:39:36.889602,479392776,65468,194,10.9255527161,-0.904625651325,-17.792246768495,2,1,18 +2025-03-11T12:39:36.905227,479392776,65468,194,11.22240850316,-0.60836341773,-18.334538950415,2,1,18 +2025-03-11T12:39:36.920852,479392776,65468,194,11.52397628684,-0.30285088752,-18.863011444145,2,1,18 +2025-03-11T12:39:36.936477,479392776,65468,194,11.83025606714,-0.00195127617000068,-19.405335728075,2,1,18 +2025-03-11T12:39:36.952102,479392776,65468,194,12.1271118542,0.303553101075001,-19.96152853919,2,1,18 +2025-03-11T12:39:36.967727,479392776,65468,194,12.41925564464,0.60442825353,-20.485347747845,2,1,18 +2025-03-11T12:39:36.983352,479392776,65468,194,12.7161114317,0.886827271650001,-21.0229631267,2,1,18 +2025-03-11T12:39:36.998977,479392776,65468,194,12.9988312289,1.1738229027,-21.56981906867,2,1,18 +2025-03-11T12:39:37.014602,479392776,65468,194,13.27683902948,1.47467359626,-22.107481483505,2,1,18 +2025-03-11T12:39:37.030227,479392776,65468,194,13.55955882668,1.77091137096,-22.64051095628,2,1,18 +2025-03-11T12:39:37.045852,479392776,65468,194,13.86583860698,2.057947766835,-23.17353725408,2,1,18 +2025-03-11T12:39:37.061477,479392776,65468,194,14.16269439404,2.358831072255,-23.70660560987,2,1,18 +2025-03-11T12:39:37.077102,479392776,65468,194,14.45012618786,2.641213784445,-24.234965060585,2,1,18 +2025-03-11T12:39:37.092727,479392776,65468,194,14.75169397154,2.928242027355,-24.75874221125,2,1,18 +2025-03-11T12:39:37.108352,479392776,65468,194,15.03912576536,3.229109026845,-25.2825546389,2,1,18 +2025-03-11T12:39:37.123977,479392776,65468,194,15.32184556256,3.52996787337,-25.815602651675,2,1,18 +2025-03-11T12:39:37.139602,479392776,65468,194,15.59985336314,3.81233427963,-26.348569723445,2,1,18 +2025-03-11T12:39:37.155227,479392776,65468,194,15.88728515696,4.09471699182,-26.881550357225,2,1,18 +2025-03-11T12:39:37.170852,479392776,65468,194,16.1794289474,4.386350000625,-27.39609011975,2,1,18 +2025-03-11T12:39:37.186477,479392776,65468,194,16.47628473446,4.66412794692,-27.915202226345,2,1,18 +2025-03-11T12:39:37.202102,479392776,65468,194,16.75900453166,4.95112357797,-28.434331069925,2,1,18 +2025-03-11T12:39:37.217727,479392776,65468,194,17.04643632548,5.247369505635,-28.958124957575,2,1,18 +2025-03-11T12:39:37.233352,479392776,65468,194,17.34800410916,5.52977667672,-29.47264120211,2,1,18 +2025-03-11T12:39:37.248977,479392776,65468,194,17.64485989622,5.82141783849,-30.001051294835,2,1,18 +2025-03-11T12:39:37.264602,479392776,65468,194,17.93229169004,6.10380055068,-30.52016837942,2,1,18 +2025-03-11T12:39:37.280227,479392776,65468,194,18.20087549738,6.37690850736,-31.039221259985,2,1,18 +2025-03-11T12:39:37.295852,479392776,65468,194,18.4647473081,6.64538723925,-31.567491185675,2,1,18 +2025-03-11T12:39:37.311477,479392776,65468,194,18.75689109854,6.927778104405,-32.09123623433,2,1,18 +2025-03-11T12:39:37.327102,479392776,65468,194,19.03489889912,7.237870941615,-32.582723898515,2,1,18 +2025-03-11T12:39:37.342727,479392776,65468,194,19.30348270646,7.53408425742,-33.08338474682,2,1,18 +2025-03-11T12:39:37.358352,479392776,65468,194,19.58149050704,7.81645066368,-33.593245903265,2,1,18 +2025-03-11T12:39:37.373977,479392776,65468,194,19.85949830762,8.094195998115,-34.116952068905,2,1,18 +2025-03-11T12:39:37.389602,479392776,65468,194,20.14693010144,8.376578710305,-34.631447970425,2,1,18 +2025-03-11T12:39:37.405227,479392776,65468,194,20.43907389188,8.65896957546,-35.150571836015,2,1,18 +2025-03-11T12:39:37.420852,479392776,65468,194,20.71708169246,8.93209383807,-35.646532363265,2,1,18 +2025-03-11T12:39:37.436477,479392776,65468,194,20.9856654998,9.20520179475,-36.1563428777,2,1,18 +2025-03-11T12:39:37.452102,479392776,65468,194,21.268385297,9.48295528215,-36.66619227515,2,1,18 +2025-03-11T12:39:37.467727,479392776,65468,194,21.54168110096,9.756071391795,-37.171388387525,2,1,18 +2025-03-11T12:39:37.483352,479392776,65468,194,21.81968890154,10.019953510755,-37.66269065171,2,1,18 +2025-03-11T12:39:37.498977,479392776,65468,194,22.10240869874,10.30232806998,-38.158695039965,2,1,18 +2025-03-11T12:39:37.514602,479392776,65468,194,22.38512849594,10.593944772855,-38.65473650822,2,1,18 +2025-03-11T12:39:37.530227,479392776,65468,194,22.64900030666,10.871665648395,-39.15531641552,2,1,18 +2025-03-11T12:39:37.545852,479392776,65468,194,22.90816012076,11.14937837097,-39.67899545714,2,1,18 +2025-03-11T12:39:37.561477,479392776,65468,194,23.1767439281,11.408623112175,-40.188750351575,2,1,18 +2025-03-11T12:39:37.577102,479392776,65468,194,23.44532773544,11.672488925205,-40.666175504555,2,1,18 +2025-03-11T12:39:37.592727,479392776,65468,194,23.72333553602,11.94099211599,-41.14825394261,2,1,18 +2025-03-11T12:39:37.608352,479392776,65468,194,23.98720734674,12.21871299153,-41.64883384991,2,1,18 +2025-03-11T12:39:37.623977,479392776,65468,194,24.24636716084,12.50104678593,-42.130940783945,2,1,18 +2025-03-11T12:39:37.639602,479392776,65468,194,24.5196629648,12.7787839674,-42.603807154865,2,1,18 +2025-03-11T12:39:37.655227,479392776,65468,194,24.78353477552,13.02877841199,-43.0996546391,2,1,18 +2025-03-11T12:39:37.670852,479392776,65468,194,25.05211858286,13.28340208137,-43.56780034595,2,1,18 +2025-03-11T12:39:37.686477,479392776,65468,194,25.31127839696,13.54725158847,-44.06369666918,2,1,18 +2025-03-11T12:39:37.702102,479392776,65468,194,25.5798622043,13.80187525785,-44.55032710829,2,1,18 +2025-03-11T12:39:37.717727,479392776,65468,194,25.84373401502,14.074975061565,-45.027782560265,2,1,18 +2025-03-11T12:39:37.733352,479392776,65468,194,26.10760582574,14.34807486528,-45.51448037837,2,1,18 +2025-03-11T12:39:37.748977,479392776,65468,194,26.36676563984,14.60268222873,-45.97337015708,2,1,18 +2025-03-11T12:39:37.764602,479392776,65468,194,26.63063745056,14.857297745145,-46.441509082925,2,1,18 +2025-03-11T12:39:37.780227,479392776,65468,194,26.8756612748,15.130364937,-46.914316227815,2,1,18 +2025-03-11T12:39:37.795852,479392776,65468,194,27.1348210889,15.38497230045,-47.382448372655,2,1,18 +2025-03-11T12:39:37.811477,479392776,65468,194,27.39869289962,15.639587816865,-47.855208481565,2,1,18 +2025-03-11T12:39:37.827102,479392776,65468,194,27.6531407171,15.898808099175,-48.318731202335,2,1,18 +2025-03-11T12:39:37.842727,479392776,65468,194,27.9123005312,16.162657606275,-48.768415694915,2,1,18 +2025-03-11T12:39:37.858352,479392776,65468,194,28.16674834868,16.403393601285,-49.23648543875,2,1,18 +2025-03-11T12:39:37.873977,479392776,65468,194,28.42590816278,16.63489560561,-49.70452488359,2,1,18 +2025-03-11T12:39:37.889602,479392776,65468,194,28.67564398364,16.884865591305,-50.158761377225,2,1,18 +2025-03-11T12:39:37.905227,479392776,65468,194,28.92066780788,17.14869063951,-50.613046709855,2,1,18 +2025-03-11T12:39:37.920852,479392776,65468,194,29.17040362874,17.40328169703,-51.071922926555,2,1,18 +2025-03-11T12:39:37.936477,479392776,65468,194,29.41071545636,17.653235376795,-51.512282308985,2,1,18 +2025-03-11T12:39:37.952102,479392776,65468,194,29.66987527046,17.889358452945,-51.9572343785,2,1,18 +2025-03-11T12:39:37.967727,479392776,65468,194,29.91961109132,18.13932843864,-52.42533442133,2,1,18 +2025-03-11T12:39:37.983352,479392776,65468,194,30.1504989257,18.389265812475,-52.861059058685,2,1,18 +2025-03-11T12:39:37.998916,479392780,65464,195,30.39081075332,18.643840564065,-53.301436981115,2,1,18 +2025-03-11T12:39:38.014541,479392780,65464,195,30.63583457756,18.903044540445,-53.76032495681,2,1,18 +2025-03-11T12:39:38.030166,479392780,65464,195,30.87143440856,19.125263636295,-54.21442986743,2,1,18 +2025-03-11T12:39:38.045791,479392780,65464,195,31.12588222604,19.356757487655,-54.636250700615,2,1,18 +2025-03-11T12:39:38.061416,479392780,65464,195,31.35677006042,19.59745271784,-55.076559441035,2,1,18 +2025-03-11T12:39:38.077041,479392780,65464,195,31.60179388466,19.83817240692,-55.50764615834,2,1,18 +2025-03-11T12:39:38.092666,479392780,65464,195,31.8468177089,20.0604078087,-55.938658715645,2,1,18 +2025-03-11T12:39:38.108291,479392780,65464,195,32.07299354666,20.287231670445,-56.38814742119,2,1,18 +2025-03-11T12:39:38.123916,479392780,65464,195,32.29916938442,20.53253981949,-56.800740822215,2,1,18 +2025-03-11T12:39:38.139541,479392780,65464,195,32.5300572188,20.791719336975,-57.204154258115,2,1,18 +2025-03-11T12:39:38.155166,479392780,65464,195,32.74680906332,21.032390108265,-57.621336740195,2,1,18 +2025-03-11T12:39:38.170791,479392780,65464,195,32.9776968977,21.2453589075,-58.04767069142,2,1,18 +2025-03-11T12:39:38.186416,479392780,65464,195,33.21800872532,21.458344012665,-58.474018204655,2,1,18 +2025-03-11T12:39:38.202041,479392780,65464,195,33.45360855632,21.67594203669,-58.872650378495,2,1,18 +2025-03-11T12:39:38.217666,479392780,65464,195,33.6844963907,21.898152979575,-59.27129431133,2,1,18 +2025-03-11T12:39:38.233291,479392780,65464,195,33.92480821832,22.12962237204,-59.688473618435,2,1,18 +2025-03-11T12:39:38.248916,479392780,65464,195,34.14627205946,22.35643808082,-60.09636489539,2,1,18 +2025-03-11T12:39:38.264541,479392780,65464,195,34.35359991074,22.583229330705,-60.48575109707,2,1,18 +2025-03-11T12:39:38.280166,479392780,65464,195,34.56092776202,22.796157365115,-60.888945227945,2,1,18 +2025-03-11T12:39:38.295791,479392780,65464,195,34.77767960654,23.018343849105,-61.296811183895,2,1,18 +2025-03-11T12:39:38.311416,479392780,65464,195,34.99914344768,23.235917414235,-61.70466538085,2,1,18 +2025-03-11T12:39:38.327041,479392780,65464,195,35.22531928544,23.448878060505,-62.117129001875,2,1,18 +2025-03-11T12:39:38.342666,479392780,65464,195,35.44207112996,23.64795918537,-62.51103870863,2,1,18 +2025-03-11T12:39:38.358291,479392780,65464,195,35.66824696772,23.865540903465,-62.886551405135,2,1,18 +2025-03-11T12:39:38.373916,479392780,65464,195,35.88028681562,24.083098162665,-63.27590730782,2,1,18 +2025-03-11T12:39:38.389541,479392780,65464,195,36.07347867704,24.29600173818,-63.66059636342,2,1,18 +2025-03-11T12:39:38.405166,479392780,65464,195,36.2760945317,24.499679475975,-64.040640717965,2,1,18 +2025-03-11T12:39:38.420791,479392780,65464,195,36.47871038636,24.717220429245,-64.41149832638,2,1,18 +2025-03-11T12:39:38.436416,479392780,65464,195,36.68603823764,24.939390607305,-64.796244804995,2,1,18 +2025-03-11T12:39:38.452041,479392780,65464,195,36.89807808554,25.15232679468,-65.16709743542,2,1,18 +2025-03-11T12:39:38.467666,479392780,65464,195,37.10540593682,25.351391613615,-65.551751214035,2,1,18 +2025-03-11T12:39:38.483291,479392780,65464,195,37.30802179148,25.56431149506,-65.93183264858,2,1,18 +2025-03-11T12:39:38.498916,479392780,65464,195,37.51534964276,25.78648167312,-66.279609662675,2,1,18 +2025-03-11T12:39:38.514541,479392780,65464,195,37.71796549742,25.98553833909,-66.64115074496,2,1,18 +2025-03-11T12:39:38.530166,479392780,65464,195,37.92058135208,26.17535286141,-67.01651829644,2,1,18 +2025-03-11T12:39:38.545791,479392780,65464,195,38.10906121688,26.365142924835,-67.36875958958,2,1,18 +2025-03-11T12:39:38.561416,479392780,65464,195,38.31638906816,26.55496560012,-67.72102800674,2,1,18 +2025-03-11T12:39:38.577041,479392780,65464,195,38.50958092958,26.74476381651,-68.06865489782,2,1,18 +2025-03-11T12:39:38.592666,479392780,65464,195,38.69806079438,26.916069592635,-68.406958481765,2,1,18 +2025-03-11T12:39:38.608291,479392780,65464,195,38.88182866256,27.115093646745,-68.754608890835,2,1,18 +2025-03-11T12:39:38.623916,479392780,65464,195,39.07502052398,27.30027079131,-69.09759605885,2,1,18 +2025-03-11T12:39:38.639541,479392780,65464,195,39.25878839216,27.494673773595,-69.45447029405,2,1,18 +2025-03-11T12:39:38.655166,479392780,65464,195,39.44726825696,27.698327052495,-69.78828247493,2,1,18 +2025-03-11T12:39:38.670791,479392780,65464,195,39.63574812176,27.87887497227,-70.13124432194,2,1,18 +2025-03-11T12:39:38.686416,479392780,65464,195,39.80066800346,28.05938212722,-70.46955108086,2,1,18 +2025-03-11T12:39:38.702041,479392780,65464,195,39.99385986488,28.23069605631,-70.80786144581,2,1,18 +2025-03-11T12:39:38.717666,479392780,65464,195,40.19176372292,28.402018138365,-71.1415574087,2,1,18 +2025-03-11T12:39:38.733291,479392780,65464,195,40.36139560124,28.59177558993,-71.470665662495,2,1,18 +2025-03-11T12:39:38.748916,479392780,65464,195,40.53102747956,28.772290897845,-71.79973683629,2,1,18 +2025-03-11T12:39:38.764541,479392780,65464,195,40.69123536464,28.95278989983,-72.110309715815,2,1,18 +2025-03-11T12:39:38.780166,479392780,65464,195,40.8702912362,29.124079370025,-72.43011500549,2,1,18 +2025-03-11T12:39:38.795791,479392780,65464,195,41.05405910438,29.29999806501,-72.754566799235,2,1,18 +2025-03-11T12:39:38.811416,479392780,65464,195,41.22840297932,29.466658310415,-73.06048321871,2,1,18 +2025-03-11T12:39:38.827041,479392780,65464,195,41.40274685426,29.63331855582,-73.375642004315,2,1,18 +2025-03-11T12:39:38.842666,479392780,65464,195,41.5770907292,29.80459987305,-73.676955780725,2,1,18 +2025-03-11T12:39:38.858291,479392780,65464,195,41.75143460414,29.980502262105,-73.97366691407,2,1,18 +2025-03-11T12:39:38.873916,479392780,65464,195,41.91635448584,30.133282986105,-74.27489296847,2,1,18 +2025-03-11T12:39:38.889541,479392780,65464,195,42.0718503743,30.290668476,-74.571502817795,2,1,18 +2025-03-11T12:39:38.905166,479392780,65464,195,42.22263426614,30.43880366928,-74.849584073855,2,1,18 +2025-03-11T12:39:38.920791,479392780,65464,195,42.35928216812,30.605398690965,-75.1277191469,2,1,18 +2025-03-11T12:39:38.936416,479392780,65464,195,42.51006605996,30.772018171545,-75.42435929522,2,1,18 +2025-03-11T12:39:38.952041,479392780,65464,195,42.67027394504,30.929411814405,-75.707112376355,2,1,18 +2025-03-11T12:39:38.967666,479392780,65464,195,42.81163384364,31.096014989055,-75.98987541347,2,1,18 +2025-03-11T12:39:38.983291,479392780,65464,195,42.96241773548,31.24877125416,-76.272596392595,2,1,18 +2025-03-11T12:39:38.998916,479392780,65464,195,43.1320496138,31.38769691565,-76.54604650961,2,1,18 +2025-03-11T12:39:39.014541,479392780,65464,195,43.28754550226,31.535840261895,-76.814892180545,2,1,18 +2025-03-11T12:39:39.030166,479392780,65464,195,43.43361739748,31.69320944586,-77.069897820275,2,1,18 +2025-03-11T12:39:39.045791,479392780,65464,195,43.57026529946,31.84594125207,-77.32949254106,2,1,18 +2025-03-11T12:39:39.061416,479392780,65464,195,43.70691320144,31.994051986455,-77.607553454105,2,1,18 +2025-03-11T12:39:39.077041,479392780,65464,195,43.85298509666,32.13293688312,-77.85786375077,2,1,18 +2025-03-11T12:39:39.092666,479392780,65464,195,44.01319298174,32.27184623868,-78.122057939645,2,1,18 +2025-03-11T12:39:39.108291,479392780,65464,195,44.16397687358,32.396876072835,-78.372319397315,2,1,18 +2025-03-11T12:39:39.123916,479392780,65464,195,44.30062477556,32.53574466357,-78.627237315035,2,1,18 +2025-03-11T12:39:39.139541,479392780,65464,195,44.41842469106,32.66995957062,-78.87748838567,2,1,18 +2025-03-11T12:39:39.155166,479392780,65464,195,44.55507259304,32.808828161355,-79.12316393726,2,1,18 +2025-03-11T12:39:39.170791,479392780,65464,195,44.67758450516,32.94305122137,-79.36417942277,2,1,18 +2025-03-11T12:39:39.186416,479392780,65464,195,44.81894440376,33.06344367777,-79.59592404617,2,1,18 +2025-03-11T12:39:39.202041,479392780,65464,195,44.95088030912,33.188440900065,-79.823052464495,2,1,18 +2025-03-11T12:39:39.217666,479392780,65464,195,45.0875282111,33.31806734715,-80.059448569955,2,1,18 +2025-03-11T12:39:39.233291,479392780,65464,195,45.2053281266,33.4337979669,-80.277277199135,2,1,18 +2025-03-11T12:39:39.248916,479392780,65464,195,45.30899205224,33.55412519958,-80.490482842235,2,1,18 +2025-03-11T12:39:39.264541,479392780,65464,195,45.42679196774,33.674476891155,-80.71295119448,2,1,18 +2025-03-11T12:39:39.280166,479392780,65464,195,45.54459188324,33.790207510905,-80.92153745753,2,1,18 +2025-03-11T12:39:39.295791,479392780,65464,195,45.65767980212,33.90592997769,-81.12549575651,2,1,18 +2025-03-11T12:39:39.311416,479392780,65464,195,45.78490371086,34.03091904702,-81.3433750277,2,1,18 +2025-03-11T12:39:39.327041,479392780,65464,195,45.90270362636,34.13740752312,-81.57040894301,2,1,18 +2025-03-11T12:39:39.342666,479392780,65464,195,46.02521553848,34.24852522401,-81.78360463013,2,1,18 +2025-03-11T12:39:39.358291,479392780,65464,195,46.1477274506,34.373506140375,-81.97837120499,2,1,18 +2025-03-11T12:39:39.373916,479392780,65464,195,46.241967383,34.484574923475,-82.17304147382,2,1,18 +2025-03-11T12:39:39.389541,479392780,65464,195,46.34563130864,34.58179679703,-82.372290867725,2,1,18 +2025-03-11T12:39:39.405166,479392780,65464,195,46.44929523428,34.69288188606,-82.548489966305,2,1,18 +2025-03-11T12:39:39.420791,479392780,65464,195,46.55767115654,34.794732984405,-82.720037582825,2,1,18 +2025-03-11T12:39:39.436416,479392780,65464,195,46.64719909232,34.891930399065,-82.900781901455,2,1,18 +2025-03-11T12:39:39.452041,479392780,65464,195,46.7367270281,34.989127813725,-83.09538976928,2,1,18 +2025-03-11T12:39:39.467666,479392780,65464,195,46.8309669605,35.081712309525,-83.27150114585,2,1,18 +2025-03-11T12:39:39.483291,479392780,65464,195,46.92991888952,35.169683886465,-83.45222194649,2,1,18 +2025-03-11T12:39:39.498916,479392780,65464,195,47.01002283206,35.27148606702,-83.619107693915,2,1,18 +2025-03-11T12:39:39.514541,479392780,65464,195,47.1136867577,35.3548447251,-83.76284727104,2,1,18 +2025-03-11T12:39:39.530166,479392780,65464,195,47.20321469348,35.43355785246,-83.92503269741,2,1,18 +2025-03-11T12:39:39.545791,479392780,65464,195,47.28803063264,35.51688389868,-84.08260869971,2,1,18 +2025-03-11T12:39:39.561416,479392780,65464,195,47.37755856842,35.618702385165,-84.231023276885,2,1,18 +2025-03-11T12:39:39.577041,479392780,65464,195,47.46237450758,35.73437593416,-84.388729059185,2,1,18 +2025-03-11T12:39:39.592666,479392780,65464,195,47.53305445688,35.80381430601,-84.532365549275,2,1,18 +2025-03-11T12:39:39.608291,479392780,65464,195,47.61315839942,35.868647911965,-84.685239427505,2,1,18 +2025-03-11T12:39:39.623916,479392780,65464,195,47.69797433858,35.970458245485,-84.81978367448,2,1,18 +2025-03-11T12:39:39.639541,479392780,65464,195,47.79221427098,36.044558453985,-84.954230243465,2,1,18 +2025-03-11T12:39:39.655166,479392780,65464,195,47.8676062169,36.109383906975,-85.0793702423,2,1,18 +2025-03-11T12:39:39.670791,479392780,65464,195,47.9382861662,36.174201207,-85.20450346013,2,1,18 +2025-03-11T12:39:39.686416,479392780,65464,195,48.0089661155,36.239018507025,-85.334257861025,2,1,18 +2025-03-11T12:39:39.702041,479392780,65464,195,48.07022207156,36.30381950112,-85.46399869991,2,1,18 +2025-03-11T12:39:39.717666,479392780,65464,195,48.13619002424,36.36862864818,-85.58450395367,2,1,18 +2025-03-11T12:39:39.733291,479392780,65464,195,48.19273398368,36.438042561135,-85.718877734615,2,1,18 +2025-03-11T12:39:39.748916,479392780,65464,195,48.23985394988,36.51668231181,-85.83479030129,2,1,18 +2025-03-11T12:39:39.764541,479392780,65464,195,48.3152458958,36.57226562115,-85.94602967093,2,1,18 +2025-03-11T12:39:39.780166,479392780,65464,195,48.40006183496,36.62786523642,-86.04804023645,2,1,18 +2025-03-11T12:39:39.795791,479392780,65464,195,48.4566057944,36.688037005725,-86.154649839005,2,1,18 +2025-03-11T12:39:39.811416,479392780,65464,195,48.51786175046,36.757459071645,-86.2566821195,2,1,18 +2025-03-11T12:39:39.827041,479392780,65464,195,48.56969371328,36.808380544335,-86.36324786105,2,1,18 +2025-03-11T12:39:39.842666,479392780,65464,195,48.61210168286,36.840801423795,-86.46048351446,2,1,18 +2025-03-11T12:39:39.858291,479392780,65464,195,48.65450965244,36.882464446905,-86.553135064805,2,1,18 +2025-03-11T12:39:39.873916,479392780,65464,195,48.70634161526,36.933385919595,-86.641216074095,2,1,18 +2025-03-11T12:39:39.889541,479392780,65464,195,48.76759757132,36.97046048274,-86.73387620846,2,1,18 +2025-03-11T12:39:39.905166,479392780,65464,195,48.81942953414,37.00289766813,-86.81264069162,2,1,18 +2025-03-11T12:39:39.920791,479392780,65464,195,48.8571255071,37.0491736101,-86.87757690257,2,1,18 +2025-03-11T12:39:39.936416,479392780,65464,195,48.88539748682,37.10467538979,-86.937915448445,2,1,18 +2025-03-11T12:39:39.952041,479392780,65464,195,48.91838146316,37.11859567602,-87.00271509839,2,1,18 +2025-03-11T12:39:39.967666,479392780,65464,195,48.9513654395,37.1417581059,-87.086036560595,2,1,18 +2025-03-11T12:39:39.983291,479392780,65464,195,48.97963741922,37.183396670115,-87.14631948647,2,1,18 +2025-03-11T12:39:39.998916,479392780,65464,195,49.01262139556,37.225043387295,-87.17888209496,2,1,18 +2025-03-11T12:39:40.014541,479392780,65464,195,49.0456053719,37.257447960825,-87.23913472184,2,1,18 +2025-03-11T12:39:40.030166,479392780,65464,195,49.069165355,37.271351941125,-87.294678443645,2,1,18 +2025-03-11T12:39:40.045791,479392780,65464,195,49.09743733472,37.326853720815,-87.341153440325,2,1,18 +2025-03-11T12:39:40.061416,479392780,65464,195,49.12099731782,37.34537877294,-87.387473336,2,1,18 +2025-03-11T12:39:40.077041,479392780,65464,195,49.13513330768,37.354645375485,-87.406015491275,2,1,18 +2025-03-11T12:39:40.092666,479392780,65464,195,49.15398129416,37.373162274645,-87.443086239815,2,1,18 +2025-03-11T12:39:40.108291,479392780,65464,195,49.17754127726,37.377824111295,-87.48935051549,2,1,18 +2025-03-11T12:39:40.123916,479392780,65464,195,49.19167726712,37.38709071384,-87.507892670765,2,1,18 +2025-03-11T12:39:40.139541,479392780,65464,195,49.20110126036,37.40559130707,-87.535707491165,2,1,18 +2025-03-11T12:39:40.155166,479392780,65464,195,49.21994924684,37.42410820623,-87.56815705664,2,1,18 +2025-03-11T12:39:40.170791,479392780,65464,195,49.24350922994,37.442633258355,-87.595992220055,2,1,18 +2025-03-11T12:39:40.186416,479392780,65464,195,49.24350922994,37.470359689305,-87.61920937538,2,1,18 +2025-03-11T12:39:40.202041,479392780,65464,195,49.24822122656,37.47036784227,-87.61459497332,2,1,18 +2025-03-11T12:39:40.217666,479392780,65464,195,49.25293322318,37.461133851585,-87.60994349126,2,1,18 +2025-03-11T12:39:40.233291,479392780,65464,195,49.2576452198,37.46114200455,-87.609950272265,2,1,18 +2025-03-11T12:39:40.248916,479392780,65464,195,49.24822122656,37.46112569862,-87.61455789332,2,1,18 +2025-03-11T12:39:40.264541,479392780,65464,195,49.23879723332,37.456488320865,-87.62376815744,2,1,18 +2025-03-11T12:39:40.280166,479392780,65464,195,49.24350922994,37.44725433018,-87.60987430925,2,1,18 +2025-03-11T12:39:40.295791,479392780,65464,195,49.22466124346,37.442600646495,-87.59134391297,2,1,18 +2025-03-11T12:39:40.311416,479392780,65464,195,49.21994924684,37.44259249353,-87.5867159489,2,1,18 +2025-03-11T12:39:40.327041,479392780,65464,195,49.2105252536,37.4240919003,-87.572764677695,2,1,18 +2025-03-11T12:39:40.342666,479392780,65464,195,49.20581325698,37.39173624456,-87.540279835235,2,1,18 +2025-03-11T12:39:40.358291,479392780,65464,195,49.19638926374,37.387098866805,-87.512520634835,2,1,18 +2025-03-11T12:39:40.373916,479392780,65464,195,49.18225327388,37.38707440791,-87.48477319343,2,1,18 +2025-03-11T12:39:40.389541,479392780,65464,195,49.17282928064,37.363952742855,-87.4476974669,2,1,18 +2025-03-11T12:39:40.405166,479392780,65464,195,49.15869329078,37.32695970936,-87.4059381563,2,1,18 +2025-03-11T12:39:40.420791,479392780,65464,195,49.13513330768,37.31305572906,-87.34577325143,2,1,18 +2025-03-11T12:39:40.436416,479392780,65464,195,49.1162853212,37.289917758075,-87.313305145955,2,1,18 +2025-03-11T12:39:40.452041,479392780,65464,195,49.08330134486,37.26213425637,-87.271555791335,2,1,18 +2025-03-11T12:39:40.467666,479392780,65464,195,49.05031736852,37.234350754665,-87.211321704455,2,1,18 +2025-03-11T12:39:40.483291,479392780,65464,195,49.0220453888,37.2019543341,-87.155697041645,2,1,18 +2025-03-11T12:39:40.498916,479392780,65464,195,48.98906141246,37.164928688745,-87.095425874765,2,1,18 +2025-03-11T12:39:40.514541,479392780,65464,195,48.95607743612,37.14638733069,-87.03060768482,2,1,18 +2025-03-11T12:39:40.530166,479392780,65464,195,48.92309345978,37.12322490081,-86.975013321005,2,1,18 +2025-03-11T12:39:40.545791,479392780,65464,195,48.8806854902,37.086182949525,-86.914728592115,2,1,18 +2025-03-11T12:39:40.561416,479392780,65464,195,48.84298951724,37.049149151205,-86.82672354584,2,1,18 +2025-03-11T12:39:40.577041,479392780,65464,195,48.8100055409,37.0028813622,-86.7479305667,2,1,18 +2025-03-11T12:39:40.592666,479392780,65464,195,48.76759757132,36.95197619544,-86.66910548555,2,1,18 +2025-03-11T12:39:40.608291,479392780,65464,195,48.72990159836,36.90570025347,-86.608790457665,2,1,18 +2025-03-11T12:39:40.623916,479392780,65464,195,48.68278163216,36.873271221045,-86.52079038938,2,1,18 +2025-03-11T12:39:40.639541,479392780,65464,195,48.62623767272,36.83158373904,-86.423497312955,2,1,18 +2025-03-11T12:39:40.655166,479392780,65464,195,48.56498171666,36.776024888595,-86.335384201655,2,1,18 +2025-03-11T12:39:40.670791,479392780,65464,195,48.51314975384,36.71124020043,-86.238005206235,2,1,18 +2025-03-11T12:39:40.686416,479392780,65464,195,48.46602978764,36.651084737055,-86.136030348755,2,1,18 +2025-03-11T12:39:40.702041,479392780,65464,195,48.41890982144,36.60017141733,-86.024850205145,2,1,18 +2025-03-11T12:39:40.717666,479392780,65464,195,48.37178985524,36.53539488213,-85.89975089234,2,1,18 +2025-03-11T12:39:40.733291,479392780,65464,195,48.31053389918,36.461351744385,-85.79307888878,2,1,18 +2025-03-11T12:39:40.748916,479392780,65464,195,48.23985394988,36.40577658801,-85.69570984934,2,1,18 +2025-03-11T12:39:40.764541,479392780,65464,195,48.1738859972,36.345588512775,-85.57522313558,2,1,18 +2025-03-11T12:39:40.780166,479392780,65464,195,48.11263004114,36.27154537503,-85.45930876589,2,1,18 +2025-03-11T12:39:40.795791,479392780,65464,195,48.04666208846,36.202115156145,-85.343406155195,2,1,18 +2025-03-11T12:39:40.811416,479392780,65464,195,47.95713415268,36.14650738791,-85.22290407641,2,1,18 +2025-03-11T12:39:40.827041,479392780,65464,195,47.8911662,36.077077169025,-85.070032001195,2,1,18 +2025-03-11T12:39:40.842666,479392780,65464,195,47.8204862507,35.998396653525,-84.926358431105,2,1,18 +2025-03-11T12:39:40.858291,479392780,65464,195,47.7498063014,35.910473994375,-84.791890147145,2,1,18 +2025-03-11T12:39:40.873916,479392780,65464,195,47.6791263521,35.822551335225,-84.657421863185,2,1,18 +2025-03-11T12:39:40.889541,479392780,65464,195,47.59902240956,35.753096657445,-84.504529444955,2,1,18 +2025-03-11T12:39:40.905166,479392780,65464,195,47.50478247716,35.669754305295,-84.34231869758,2,1,18 +2025-03-11T12:39:40.920791,479392780,65464,195,47.41525454138,35.591041177935,-84.175512088145,2,1,18 +2025-03-11T12:39:40.936416,479392780,65464,195,47.3257266056,35.5169491224,-84.01796638484,2,1,18 +2025-03-11T12:39:40.952041,479392780,65464,195,47.22677467658,35.41973540181,-83.869556785655,2,1,18 +2025-03-11T12:39:40.967666,479392780,65464,195,47.14195873742,35.331788283765,-83.711962243355,2,1,18 +2025-03-11T12:39:40.983291,479392780,65464,195,47.05714279826,35.24384116572,-83.53126178573,2,1,18 +2025-03-11T12:39:40.998916,479392780,65464,195,46.9723268591,35.128167616725,-83.34582890504,2,1,18 +2025-03-11T12:39:41.014541,479392780,65464,195,46.88279892332,35.012485914765,-83.178873975605,2,1,18 +2025-03-11T12:39:41.030166,479392780,65464,195,46.7838469943,34.915272194175,-83.01197964416,2,1,18 +2025-03-11T12:39:41.045791,479392780,65464,195,46.67547107204,34.827284311305,-82.835866464575,2,1,18 +2025-03-11T12:39:41.061416,479392780,65464,195,46.58594313626,34.74395011212,-82.655177765945,2,1,18 +2025-03-11T12:39:41.077041,479392780,65464,195,46.48227921062,34.646728238565,-82.451307188975,2,1,18 +2025-03-11T12:39:41.092666,479392780,65464,195,46.37390328836,34.53563499657,-82.261237760195,2,1,18 +2025-03-11T12:39:41.108291,479392780,65464,195,46.27023936272,34.42454990754,-82.08041747855,2,1,18 +2025-03-11T12:39:41.123916,479392780,65464,195,46.15715144384,34.31344851258,-81.89496245183,2,1,18 +2025-03-11T12:39:41.139541,479392780,65464,195,46.0534875182,34.2116055672,-81.677209785665,2,1,18 +2025-03-11T12:39:41.155166,479392780,65464,195,45.94511159594,34.100512325205,-81.47327680769,2,1,18 +2025-03-11T12:39:41.170791,479392780,65464,195,45.82731168044,33.994023849105,-81.269348807705,2,1,18 +2025-03-11T12:39:41.186416,479392780,65464,195,45.71893575818,33.878309535285,-81.06539728973,2,1,18 +2025-03-11T12:39:41.202041,479392780,65464,195,45.6058478393,33.767208140325,-80.84297279849,2,1,18 +2025-03-11T12:39:41.217666,479392780,65464,195,45.47391193394,33.637589846205,-80.652795304685,2,1,18 +2025-03-11T12:39:41.233291,479392780,65464,195,45.36082401506,33.517246307595,-80.458060831835,2,1,18 +2025-03-11T12:39:41.248916,479392780,65464,195,45.2524480928,33.369184491,-80.26322189999,2,1,18 +2025-03-11T12:39:41.264541,479392780,65464,195,45.12522418406,33.26267970897,-80.031553239605,2,1,18 +2025-03-11T12:39:41.280166,479392780,65464,195,44.98386428546,33.146908324395,-79.78596360701,2,1,18 +2025-03-11T12:39:41.295791,479392780,65464,195,44.86135237334,33.017306336205,-79.577314942955,2,1,18 +2025-03-11T12:39:41.311416,479392780,65464,195,44.73884046122,32.887704348015,-79.35018154664,2,1,18 +2025-03-11T12:39:41.327041,479392780,65464,195,44.60690455586,32.748843910245,-79.10913395912,2,1,18 +2025-03-11T12:39:41.342666,479392780,65464,195,44.46554465726,32.60534609472,-78.863433086525,2,1,18 +2025-03-11T12:39:41.358291,479392780,65464,195,44.31476076542,32.471074116915,-78.613134548855,2,1,18 +2025-03-11T12:39:41.373916,479392780,65464,195,44.18753685668,32.346085047585,-78.358285813145,2,1,18 +2025-03-11T12:39:41.389541,479392780,65464,195,44.06031294794,32.221095978255,-78.103437077435,2,1,18 +2025-03-11T12:39:41.405166,479392780,65464,195,43.91895304934,32.082219234555,-77.84851237871,2,1,18 +2025-03-11T12:39:41.420791,479392780,65464,195,43.7681691575,31.934084041275,-77.593537037975,2,1,18 +2025-03-11T12:39:41.436416,479392780,65464,195,43.63152125552,31.772110091415,-77.31542050493,2,1,18 +2025-03-11T12:39:41.452041,479392780,65464,195,43.49958535016,31.61938643817,-77.041969015955,2,1,18 +2025-03-11T12:39:41.467666,479392780,65464,195,43.35351345494,31.47588046968,-76.768534263965,2,1,18 +2025-03-11T12:39:41.483291,479392780,65464,195,43.21215355634,31.313898366855,-76.50427449911,2,1,18 +2025-03-11T12:39:41.498916,479392780,65464,195,43.0613696645,31.156521029925,-76.21691379692,2,1,18 +2025-03-11T12:39:41.514541,479392780,65464,195,42.91058577266,30.99452262117,-75.92953455473,2,1,18 +2025-03-11T12:39:41.530166,479392780,65464,195,42.74566589096,30.85098404082,-75.65607267872,2,1,18 +2025-03-11T12:39:41.545791,479392780,65464,195,42.57132201602,30.693565939065,-75.37329925457,2,1,18 +2025-03-11T12:39:41.561416,479392780,65464,195,42.41111413094,30.53155122438,-75.099769999565,2,1,18 +2025-03-11T12:39:41.577041,479392780,65464,195,42.26504223572,30.37880311224,-74.81243461838,2,1,18 +2025-03-11T12:39:41.592666,479392780,65464,195,42.10483435064,30.23065161303,-74.50661270192,2,1,18 +2025-03-11T12:39:41.608291,479392780,65464,195,41.94462646556,30.068636898345,-74.214598714655,2,1,18 +2025-03-11T12:39:41.623916,479392780,65464,195,41.78441858048,29.902001111835,-73.92256618739,2,1,18 +2025-03-11T12:39:41.639541,479392780,65464,195,41.6242106954,29.7307442535,-73.612030387865,2,1,18 +2025-03-11T12:39:41.655166,479392780,65464,195,41.4592908137,29.5594792422,-73.3061089904,2,1,18 +2025-03-11T12:39:41.670791,479392780,65464,195,41.28494693876,29.383576853145,-73.00477667399,2,1,18 +2025-03-11T12:39:41.686416,479392780,65464,195,41.11531506044,29.21230368888,-72.67112139713,2,1,18 +2025-03-11T12:39:41.702041,479392780,65464,195,40.9409711855,29.045643443475,-72.35134142846,2,1,18 +2025-03-11T12:39:41.717666,479392780,65464,195,40.77133930718,28.86512813556,-72.06386090225,2,1,18 +2025-03-11T12:39:41.733291,479392780,65464,195,40.60170742886,28.675370683995,-71.73013146539,2,1,18 +2025-03-11T12:39:41.748916,479392780,65464,195,40.41793956068,28.50869413266,-71.387232019385,2,1,18 +2025-03-11T12:39:41.764541,479392780,65464,195,40.23888368912,28.34202573429,-71.053581720515,2,1,18 +2025-03-11T12:39:41.780166,479392780,65464,195,40.0692518108,28.170752570025,-70.729168809785,2,1,18 +2025-03-11T12:39:41.795791,479392780,65464,195,39.880771946,27.97172036295,-70.39999635197,2,1,18 +2025-03-11T12:39:41.811416,479392780,65464,195,39.69700407782,27.768075237015,-70.084675684355,2,1,18 +2025-03-11T12:39:41.827041,479392780,65464,195,39.5038122164,27.596761307925,-69.75098650247,2,1,18 +2025-03-11T12:39:41.842666,479392780,65464,195,39.32475634484,27.420850765905,-69.4172991236,2,1,18 +2025-03-11T12:39:41.858291,479392780,65464,195,39.14098847666,27.24493207092,-69.07898378066,2,1,18 +2025-03-11T12:39:41.873916,479392780,65464,195,38.95722060848,27.050529088635,-68.726730728525,2,1,18 +2025-03-11T12:39:41.889541,479392780,65464,195,38.75931675044,26.85148057563,-68.36981761031,2,1,18 +2025-03-11T12:39:41.905166,479392780,65464,195,38.57083688564,26.633964081255,-68.022086260235,2,1,18 +2025-03-11T12:39:41.920791,479392780,65464,195,38.3729330276,26.448778783725,-67.66522876202,2,1,18 +2025-03-11T12:39:41.936416,479392780,65464,195,38.1608931797,26.258947955475,-67.30833238079,2,1,18 +2025-03-11T12:39:41.952041,479392780,65464,195,37.96770131828,26.05528652361,-66.95140750358,2,1,18 +2025-03-11T12:39:41.967666,479392780,65464,195,37.78864544672,25.856270622465,-66.59914269245,2,1,18 +2025-03-11T12:39:41.983291,479392780,65464,195,37.59074158868,25.671085324935,-66.22842164504,2,1,18 +2025-03-11T12:39:41.998840,479392784,65459,196,37.3834137374,25.472020506,-65.85763141562,2,1,18 +2025-03-11T12:39:42.014465,479392784,65459,196,37.17608588612,25.254471399765,-65.463661110875,2,1,18 +2025-03-11T12:39:42.030090,479392784,65459,196,36.97347003146,25.05079366197,-65.0743743902,2,1,18 +2025-03-11T12:39:42.045715,479392784,65459,196,36.78027817004,24.847132230105,-64.71744951299,2,1,18 +2025-03-11T12:39:42.061340,479392784,65459,196,36.56823832214,24.64343818638,-64.337391596435,2,1,18 +2025-03-11T12:39:42.076965,479392784,65459,196,36.346774481,24.421243549425,-63.952624774805,2,1,18 +2025-03-11T12:39:42.092590,479392784,65459,196,36.12531063986,24.20829105612,-63.58175858237,2,1,18 +2025-03-11T12:39:42.108215,479392784,65459,196,35.9226947852,23.9999922465,-63.201695687825,2,1,18 +2025-03-11T12:39:42.123840,479392784,65459,196,35.7106549373,23.787056059125,-62.789252409815,2,1,18 +2025-03-11T12:39:42.139465,479392784,65459,196,35.50332708602,23.574128024715,-62.4045430112,2,1,18 +2025-03-11T12:39:42.155090,479392784,65459,196,35.29128723812,23.36119183734,-62.02906919771,2,1,18 +2025-03-11T12:39:42.170715,479392784,65459,196,35.07924739022,23.12515029084,-61.639639135025,2,1,18 +2025-03-11T12:39:42.186340,479392784,65459,196,34.85778354908,22.91681886936,-61.236443201135,2,1,18 +2025-03-11T12:39:42.201965,479392784,65459,196,34.64103170456,22.708495600845,-60.83325404825,2,1,18 +2025-03-11T12:39:42.217590,479392784,65459,196,34.40071987694,22.481647280205,-60.43919919647,2,1,18 +2025-03-11T12:39:42.233215,479392784,65459,196,34.1792560358,22.254831571425,-60.03592910258,2,1,18 +2025-03-11T12:39:42.248840,479392784,65459,196,33.96250419128,22.032645087435,-59.632684329695,2,1,18 +2025-03-11T12:39:42.264465,479392784,65459,196,33.73632835352,21.81506336934,-59.215580985605,2,1,18 +2025-03-11T12:39:42.280090,479392784,65459,196,33.51015251576,21.59286057942,-58.79383791845,2,1,18 +2025-03-11T12:39:42.295715,479392784,65459,196,33.27926468138,21.342923205585,-58.37197683029,2,1,18 +2025-03-11T12:39:42.311340,479392784,65459,196,33.05780084024,21.11148642498,-57.9686881964,2,1,18 +2025-03-11T12:39:42.326965,479392784,65459,196,32.83162500248,20.893904706885,-57.556206035375,2,1,18 +2025-03-11T12:39:42.342590,479392784,65459,196,32.6007371681,20.657830548525,-57.12977938415,2,1,18 +2025-03-11T12:39:42.358215,479392784,65459,196,32.3651373371,20.417127165375,-56.71256977805,2,1,18 +2025-03-11T12:39:42.373840,479392784,65459,196,32.13896149934,20.18106115998,-56.28614990783,2,1,18 +2025-03-11T12:39:42.389465,479392784,65459,196,31.9174976582,19.949624379375,-55.85513417555,2,1,18 +2025-03-11T12:39:42.405090,479392784,65459,196,31.68660982382,19.72741343649,-55.41489959513,2,1,18 +2025-03-11T12:39:42.420715,479392784,65459,196,31.45100999282,19.49595219699,-54.983863519835,2,1,18 +2025-03-11T12:39:42.436340,479392784,65459,196,31.20598616858,19.25523250791,-54.538913253335,2,1,18 +2025-03-11T12:39:42.451965,479392784,65459,196,30.97038633758,18.99604483746,-54.10776593804,2,1,18 +2025-03-11T12:39:42.467590,479392784,65459,196,30.73478650658,18.74609931066,-53.68127688581,2,1,18 +2025-03-11T12:39:42.483215,479392784,65459,196,30.47091469586,18.51458915337,-53.22709420916,2,1,18 +2025-03-11T12:39:42.498840,479392784,65459,196,30.221178875,18.264619167675,-52.77747889859,2,1,18 +2025-03-11T12:39:42.514465,479392784,65459,196,29.98086704738,18.010044416085,-52.33710097616,2,1,18 +2025-03-11T12:39:42.530090,479392784,65459,196,29.74055521976,17.76933287997,-51.882915124535,2,1,18 +2025-03-11T12:39:42.545715,479392784,65459,196,29.49553139552,17.533234262715,-51.4426045811,2,1,18 +2025-03-11T12:39:42.561340,479392784,65459,196,29.2552195679,17.28328058295,-50.988381649475,2,1,18 +2025-03-11T12:39:42.576965,479392784,65459,196,29.01490774028,17.02870583136,-50.51565544559,2,1,18 +2025-03-11T12:39:42.592590,479392784,65459,196,28.77459591266,16.787994295245,-50.0568484109,2,1,18 +2025-03-11T12:39:42.608215,479392784,65459,196,28.52014809518,16.528774012935,-49.607189239325,2,1,18 +2025-03-11T12:39:42.623840,479392784,65459,196,28.2657002777,16.269553730625,-49.143666518555,2,1,18 +2025-03-11T12:39:42.639465,479392784,65459,196,28.02538845008,16.01960005086,-48.684822403865,2,1,18 +2025-03-11T12:39:42.655090,479392784,65459,196,27.7709406326,15.765000840375,-48.212075856965,2,1,18 +2025-03-11T12:39:42.670715,479392784,65459,196,27.49764482864,15.50112687438,-47.757749838305,2,1,18 +2025-03-11T12:39:42.686340,479392784,65459,196,27.23377301792,15.246511357965,-47.30809564472,2,1,18 +2025-03-11T12:39:42.701965,479392784,65459,196,26.96047721396,14.987258463795,-46.839924616865,2,1,18 +2025-03-11T12:39:42.717590,479392784,65459,196,26.69189340662,14.71877157894,-46.37634447308,2,1,18 +2025-03-11T12:39:42.733215,479392784,65459,196,26.44686958238,14.464188674385,-45.889747938995,2,1,18 +2025-03-11T12:39:42.748840,479392784,65459,196,26.18770976828,14.209581310935,-45.39850987883,2,1,18 +2025-03-11T12:39:42.764465,479392784,65459,196,25.9332619508,13.950361028625,-44.94422952419,2,1,18 +2025-03-11T12:39:42.780090,479392784,65459,196,25.6741021367,13.69113259335,-44.46683647322,2,1,18 +2025-03-11T12:39:42.795715,479392784,65459,196,25.41023032598,13.41341171781,-43.970877748985,2,1,18 +2025-03-11T12:39:42.811340,479392784,65459,196,25.15107051188,13.14032006706,-43.493429078015,2,1,18 +2025-03-11T12:39:42.826965,479392784,65459,196,24.88719870116,12.876462406995,-43.01601070604,2,1,18 +2025-03-11T12:39:42.842590,479392784,65459,196,24.60919090058,12.60795921621,-42.52006871879,2,1,18 +2025-03-11T12:39:42.858215,479392784,65459,196,24.34060709324,12.35333554683,-42.028817096615,2,1,18 +2025-03-11T12:39:42.873840,479392784,65459,196,24.0720232859,12.0894697338,-41.560634309765,2,1,18 +2025-03-11T12:39:42.889465,479392784,65459,196,23.80815147518,11.807127786435,-41.069278228595,2,1,18 +2025-03-11T12:39:42.905090,479392784,65459,196,23.54899166108,11.543278279335,-40.582624271495,2,1,18 +2025-03-11T12:39:42.920715,479392784,65459,196,23.28040785374,11.28403353813,-40.077490560125,2,1,18 +2025-03-11T12:39:42.936340,479392784,65459,196,23.00240005316,11.02015141917,-39.572324746745,2,1,18 +2025-03-11T12:39:42.951965,479392784,65459,196,22.71968025596,10.747019003595,-39.05787270623,2,1,18 +2025-03-11T12:39:42.967590,479392784,65459,196,22.46523243848,10.45545121851,-38.534144825615,2,1,18 +2025-03-11T12:39:42.983215,479392784,65459,196,22.20607262438,10.177738495935,-38.038192882385,2,1,18 +2025-03-11T12:39:42.998840,479392784,65459,196,21.92335282718,9.909227152185,-37.537622931065,2,1,18 +2025-03-11T12:39:43.014465,479392784,65459,196,21.6453450266,9.63148181775,-37.060128596075,2,1,18 +2025-03-11T12:39:43.030090,479392784,65459,196,21.37204922264,9.35374463628,-36.559535126765,2,1,18 +2025-03-11T12:39:43.045715,479392784,65459,196,21.09875341868,9.062144239335,-36.026537756,2,1,18 +2025-03-11T12:39:43.061340,479392784,65459,196,20.8207456181,8.8028831922,-35.507526933425,2,1,18 +2025-03-11T12:39:43.076965,479392784,65459,196,20.53331382428,8.52050048001,-34.97916748271,2,1,18 +2025-03-11T12:39:43.092590,479392784,65459,196,20.25059402708,8.23350484896,-34.46928100526,2,1,18 +2025-03-11T12:39:43.108215,479392784,65459,196,19.9725862265,7.96038058635,-33.959456928815,2,1,18 +2025-03-11T12:39:43.123840,479392784,65459,196,19.69929042254,7.69188554853,-33.44503699031,2,1,18 +2025-03-11T12:39:43.139465,479392784,65459,196,19.42128262196,7.40027699862,-32.944381119995,2,1,18 +2025-03-11T12:39:43.155090,479392784,65459,196,19.15269881462,7.12716904194,-32.439191788625,2,1,18 +2025-03-11T12:39:43.170715,479392784,65459,196,18.86997901742,6.844794482715,-31.920081485045,2,1,18 +2025-03-11T12:39:43.186340,479392784,65459,196,18.5825472236,6.553169626875,-31.405548503525,2,1,18 +2025-03-11T12:39:43.201965,479392784,65459,196,18.29511542978,6.24768155556,-30.872475169745,2,1,18 +2025-03-11T12:39:43.217590,479392784,65459,196,17.99825964272,5.951419321965,-30.36253126928,2,1,18 +2025-03-11T12:39:43.233215,479392784,65459,196,17.7108278489,5.6736576816,-29.852675090825,2,1,18 +2025-03-11T12:39:43.248840,479392784,65459,196,17.41868405846,5.38664574462,-29.31042676991,2,1,18 +2025-03-11T12:39:43.264465,479392784,65459,196,17.12654026802,5.113497023115,-28.786718801255,2,1,18 +2025-03-11T12:39:43.280090,479392784,65459,196,16.84853246744,4.83575168868,-28.26763381868,2,1,18 +2025-03-11T12:39:43.295715,479392784,65459,196,16.56581267024,4.54875605763,-27.753126158165,2,1,18 +2025-03-11T12:39:43.311340,479392784,65459,196,16.28780486966,4.25714750772,-27.21550082333,2,1,18 +2025-03-11T12:39:43.326965,479392784,65459,196,16.00979706908,3.960917885985,-26.68247813156,2,1,18 +2025-03-11T12:39:43.342590,479392784,65459,196,15.7082292854,3.6600264276,-26.16326654396,2,1,18 +2025-03-11T12:39:43.358215,479392784,65459,196,15.41608549496,3.35453020332,-25.639428795305,2,1,18 +2025-03-11T12:39:43.373840,479392784,65459,196,15.13807769438,3.067542725235,-25.1110643666,2,1,18 +2025-03-11T12:39:43.389465,479392784,65459,196,14.8365099107,2.780514482325,-24.587287215935,2,1,18 +2025-03-11T12:39:43.405090,479392784,65459,196,14.54436612026,2.47963932987,-24.058846824215,2,1,18 +2025-03-11T12:39:43.420715,479392784,65459,196,14.26164632306,2.20188584247,-23.512027962245,2,1,18 +2025-03-11T12:39:43.436340,479392784,65459,196,13.96950253262,1.891768546365,-22.974308124395,2,1,18 +2025-03-11T12:39:43.451965,479392784,65459,196,13.67735874218,1.59089339391,-22.44124654961,2,1,18 +2025-03-11T12:39:43.467590,479392784,65459,196,13.37107896188,1.30847806986,-21.90823879181,2,1,18 +2025-03-11T12:39:43.483215,479392784,65459,196,13.07893517144,1.035329348355,-21.38915200622,2,1,18 +2025-03-11T12:39:43.498840,479392784,65459,196,12.79621537424,0.73447050183,-20.85148281038,2,1,18 +2025-03-11T12:39:43.514465,479392784,65459,196,12.49935958718,0.42434505276,-20.30913500846,2,1,18 +2025-03-11T12:39:43.530090,479392784,65459,196,12.20250380012,0.123461747340001,-19.76682428654,2,1,18 +2025-03-11T12:39:43.545715,479392784,65459,196,11.91036000968,-0.177413405115,-19.215277979495,2,1,18 +2025-03-11T12:39:43.561340,479392784,65459,196,11.63706420572,-0.464392730235,-18.686920331795,2,1,18 +2025-03-11T12:39:43.576965,479392784,65459,196,11.34492041528,-0.75602573904,-18.149274653945,2,1,18 +2025-03-11T12:39:43.592590,479392784,65459,196,11.0433526316,-1.0522961256,-17.59773332489,2,1,18 +2025-03-11T12:39:43.608215,479392784,65459,196,10.7370728513,-1.325469306,-17.069383830155,2,1,18 +2025-03-11T12:39:43.623840,479392784,65459,196,10.44021706424,-1.62635261142,-16.5316942913,2,1,18 +2025-03-11T12:39:43.639465,479392784,65459,196,10.1480732738,-1.94109097935,-15.998577096515,2,1,18 +2025-03-11T12:39:43.655090,479392784,65459,196,9.85121748674,-2.237353212945,-15.437800182335,2,1,18 +2025-03-11T12:39:43.670715,479392784,65459,196,9.54493770644,-2.529010680645,-14.89089179534,2,1,18 +2025-03-11T12:39:43.686340,479392784,65459,196,9.23865792614,-2.83453136382,-14.34854897141,2,1,18 +2025-03-11T12:39:43.701965,479392784,65459,196,8.93709014246,-3.13080175038,-13.81087119155,2,1,18 +2025-03-11T12:39:43.717590,479392784,65459,196,8.64494635202,-3.42705583101,-13.26396460757,2,1,18 +2025-03-11T12:39:43.733215,479392784,65459,196,8.35280256158,-3.71406776799,-12.72633746972,2,1,18 +2025-03-11T12:39:43.748840,479392784,65459,196,8.06065877114,-4.024185064095,-12.197859998,2,1,18 +2025-03-11T12:39:43.764465,479392784,65459,196,7.7685149807,-4.3343023602,-11.65089779402,2,1,18 +2025-03-11T12:39:43.780090,479392784,65459,196,7.47165919364,-4.621322450145,-11.104021509035,2,1,18 +2025-03-11T12:39:43.795715,479392784,65459,196,7.17480340658,-4.931447899215,-10.561673707115,2,1,18 +2025-03-11T12:39:43.811340,479392784,65459,196,6.88265961614,-5.246186267145,-10.01007178007,2,1,18 +2025-03-11T12:39:43.826965,479392784,65459,196,6.5669558426,-5.528617897125,-9.458565728,2,1,18 +2025-03-11T12:39:43.842590,479392784,65459,196,6.27010005554,-5.820259058895,-8.939398001405,2,1,18 +2025-03-11T12:39:43.858215,479392784,65459,196,5.97324426848,-6.12576343614,-8.39244755642,2,1,18 +2025-03-11T12:39:43.873840,479392784,65459,196,5.6716764848,-6.43127596635,-7.831626781235,2,1,18 +2025-03-11T12:39:43.889465,479392784,65459,196,5.3653967045,-6.7321755777,-7.27543894811,2,1,18 +2025-03-11T12:39:43.905090,479392784,65459,196,5.07325291406,-7.042292873805,-6.72847674413,2,1,18 +2025-03-11T12:39:43.920715,479392784,65459,196,4.76697313376,-7.32932926968,-6.200071629395,2,1,18 +2025-03-11T12:39:43.936340,479392784,65459,196,4.4701173467,-7.634833646925,-5.65312118441,2,1,18 +2025-03-11T12:39:43.951965,479392784,65459,196,4.17326155964,-7.935716952345,-5.078462181035,2,1,18 +2025-03-11T12:39:43.967590,479392784,65459,196,3.8811177692,-8.241213176625,-4.54538206625,2,1,18 +2025-03-11T12:39:43.983215,479392784,65459,196,3.57012599228,-8.56060522824,-3.99835565825,2,1,18 +2025-03-11T12:39:43.998840,479392784,65459,196,3.25913421536,-8.861512992555,-3.46064577638,2,1,18 +2025-03-11T12:39:44.014465,479392784,65459,196,2.97170242154,-9.143895704745,-2.923043959535,2,1,18 +2025-03-11T12:39:44.030090,479392784,65459,196,2.68427062772,-9.44938377606,-2.371485893495,2,1,18 +2025-03-11T12:39:44.045715,479392784,65459,196,2.3968388339,-9.754871847375,-1.819927827455,2,1,18 +2025-03-11T12:39:44.061340,479392784,65459,196,2.0905590536,-10.04190824325,-1.27303798046,2,1,18 +2025-03-11T12:39:44.076965,479392784,65459,196,1.77956727668,-10.333573863915,-0.721501629395001,2,1,18 +2025-03-11T12:39:44.092590,479392784,65459,196,1.477999493,-10.639086394125,-0.193029135665,2,1,18 +2025-03-11T12:39:44.108215,479392784,65459,196,1.19056769918,-10.95381660909,0.36318719344,2,1,18 +2025-03-11T12:39:44.123840,479392784,65459,196,0.89371191212,-11.259320986335,0.919380004555,2,1,18 +2025-03-11T12:39:44.139465,479392784,65459,196,0.59685612506,-11.55558321993,1.452429820345,2,1,18 +2025-03-11T12:39:44.155090,479392784,65459,196,0.29057634476,-11.83799854398,2.003922310405,2,1,18 +2025-03-11T12:39:44.170715,479392784,65459,196,-0.0157034355400002,-12.134277083505,2.546228054335,2,1,18 +2025-03-11T12:39:44.186340,479392784,65459,196,-0.30313522936,-12.435144082995,3.09314639731,2,1,18 +2025-03-11T12:39:44.201965,479392784,65459,196,-0.60470301304,-12.72679339773,3.65853273556,2,1,18 +2025-03-11T12:39:44.217590,479392784,65459,196,-0.90627079672,-13.03230592794,4.21473232768,2,1,18 +2025-03-11T12:39:44.233215,479392784,65459,196,-1.21255057702,-13.319342323815,4.76624335774,2,1,18 +2025-03-11T12:39:44.248840,479392784,65459,196,-1.49998237084,-13.61558825148,5.29927961152,2,1,18 +2025-03-11T12:39:44.264465,479392784,65459,196,-1.80626215114,-13.911866791005,5.82310062319,2,1,18 +2025-03-11T12:39:44.280090,479392784,65459,196,-2.09840594158,-14.198878727985,6.356106577975,2,1,18 +2025-03-11T12:39:44.295715,479392784,65459,196,-2.39054973202,-14.504374952265,6.88918669276,2,1,18 +2025-03-11T12:39:44.311340,479392784,65459,196,-2.69682951232,-14.81913777909,7.436187779755,2,1,18 +2025-03-11T12:39:44.326965,479392784,65459,196,-2.998397296,-15.129271381125,7.96929999655,2,1,18 +2025-03-11T12:39:44.342590,479392784,65459,196,-3.29525308306,-15.420912542895,8.516194821535,2,1,18 +2025-03-11T12:39:44.358215,479392784,65459,196,-3.5873968735,-15.72178769535,9.06774112858,2,1,18 +2025-03-11T12:39:44.373840,479392784,65459,196,-3.88425266056,-16.018049928945,9.596169761305,2,1,18 +2025-03-11T12:39:44.389465,479392784,65459,196,-4.18110844762,-16.309691090715,10.129201037095,2,1,18 +2025-03-11T12:39:44.405090,479392784,65459,196,-4.46382824482,-16.61054993724,10.66224904987,2,1,18 +2025-03-11T12:39:44.420715,479392784,65459,196,-4.75126003864,-16.906795864905,11.199906486715,2,1,18 +2025-03-11T12:39:44.436340,479392784,65459,196,-5.03397983584,-17.184549352305,11.728240616425,2,1,18 +2025-03-11T12:39:44.451965,479392784,65459,196,-5.33554761952,-17.480819738865,12.265918396285,2,1,18 +2025-03-11T12:39:44.467590,479392784,65459,196,-5.64182739982,-17.77709827839,12.817466506345,2,1,18 +2025-03-11T12:39:44.483215,479392784,65459,196,-5.93397119026,-18.08259450267,13.364410170325,2,1,18 +2025-03-11T12:39:44.498840,479392784,65459,196,-6.2261149807,-18.3788485833,13.88821083898,2,1,18 +2025-03-11T12:39:44.514465,479392784,65459,196,-6.52297076776,-18.684352960545,14.42129773477,2,1,18 +2025-03-11T12:39:44.530090,479392784,65459,196,-6.82925054806,-18.98987364372,14.940534643375,2,1,18 +2025-03-11T12:39:44.545715,479392784,65459,196,-7.12610633512,-19.26303051819,15.473491759165,2,1,18 +2025-03-11T12:39:44.561340,479392784,65459,196,-7.39940213908,-19.54076769966,16.00643350993,2,1,18 +2025-03-11T12:39:44.576965,479392784,65459,196,-7.66798594642,-19.83235994364,16.525560550495,2,1,18 +2025-03-11T12:39:44.592590,479392784,65459,196,-7.9695537301,-20.124009258375,17.06784097342,2,1,18 +2025-03-11T12:39:44.608215,479392784,65459,196,-8.24756153068,-20.42023888011,17.60086366519,2,1,18 +2025-03-11T12:39:44.623840,479392784,65459,196,-8.5349933245,-20.716484807775,18.12465755284,2,1,18 +2025-03-11T12:39:44.639465,479392784,65459,196,-8.82713711494,-20.994254601105,18.657626427625,2,1,18 +2025-03-11T12:39:44.655090,479392784,65459,196,-9.12870489862,-21.272040700365,19.18136649829,2,1,18 +2025-03-11T12:39:44.670715,479392784,65459,196,-9.41613669244,-21.56828662803,19.68667565368,2,1,18 +2025-03-11T12:39:44.686340,479392784,65459,196,-9.7129924795,-21.86916993345,20.21050164334,2,1,18 +2025-03-11T12:39:44.701965,479392784,65459,196,-9.98628828346,-22.14690711492,20.73882221104,2,1,18 +2025-03-11T12:39:44.717590,479392784,65459,196,-10.26429608404,-22.42003137753,21.257888653615,2,1,18 +2025-03-11T12:39:44.733215,479392784,65459,196,-10.55172787786,-22.707035161545,21.79550901046,2,1,18 +2025-03-11T12:39:44.748840,479392784,65459,196,-10.82973567844,-23.00326478328,22.305425786905,2,1,18 +2025-03-11T12:39:44.764465,479392784,65459,196,-11.11716747226,-23.299510710945,22.80611375923,2,1,18 +2025-03-11T12:39:44.780090,479392784,65459,196,-11.39517527284,-23.591119260855,23.32063317874,2,1,18 +2025-03-11T12:39:44.795715,479392784,65459,196,-11.67789507004,-23.86425167643,23.83970640232,2,1,18 +2025-03-11T12:39:44.811340,479392784,65459,196,-11.97946285372,-24.14203777569,24.35882528992,2,1,18 +2025-03-11T12:39:44.826965,479392784,65459,196,-12.26218265092,-24.424412334915,24.882556776565,2,1,18 +2025-03-11T12:39:44.842590,479392784,65459,196,-12.5401904515,-24.716020884825,25.40169737914,2,1,18 +2025-03-11T12:39:44.858215,479392784,65459,196,-12.80877425884,-25.00299205698,25.902321147445,2,1,18 +2025-03-11T12:39:44.873840,479392784,65459,196,-13.07264606956,-25.276091860695,26.393640148615,2,1,18 +2025-03-11T12:39:44.889465,479392784,65459,196,-13.33651788028,-25.53994952076,26.903406802045,2,1,18 +2025-03-11T12:39:44.905090,479392784,65459,196,-13.6239496741,-25.8130900893,27.4132444405,2,1,18 +2025-03-11T12:39:44.920715,479392784,65459,196,-13.92551745778,-26.095497260385,27.918518318905,2,1,18 +2025-03-11T12:39:44.936340,479392784,65459,196,-14.19881326174,-26.363992298205,28.43293825741,2,1,18 +2025-03-11T12:39:44.951965,479392784,65459,196,-14.45797307584,-26.63246287713,28.93809548677,2,1,18 +2025-03-11T12:39:44.967590,479392784,65459,196,-14.74540486966,-26.90560344567,29.45255430829,2,1,18 +2025-03-11T12:39:44.983215,479392784,65459,196,-15.02812466686,-27.19259907672,29.948577236545,2,1,18 +2025-03-11T12:39:44.998840,479392784,65459,196,-15.30142047082,-27.46109411454,30.44451244279,2,1,18 +2025-03-11T12:39:45.014465,479392784,65459,196,-15.56529228154,-27.71108855913,30.93573874396,2,1,18 +2025-03-11T12:39:45.030090,479392784,65459,196,-15.84330008212,-27.99345496539,31.417872802015,2,1,18 +2025-03-11T12:39:45.045715,479392784,65459,196,-16.11659588608,-28.27119214686,31.90460272213,2,1,18 +2025-03-11T12:39:45.061340,479392784,65459,196,-16.37575570018,-28.548904869435,32.3820699331,2,1,18 +2025-03-11T12:39:45.076965,479392784,65459,196,-16.62549152104,-28.821980214255,32.87798977432,2,1,18 +2025-03-11T12:39:45.092590,479392784,65459,196,-16.898787325,-29.08585418025,33.3692852575,2,1,18 +2025-03-11T12:39:45.108215,479392784,65459,196,-17.17679512558,-29.345115227385,33.85594779862,2,1,18 +2025-03-11T12:39:45.123840,479392784,65459,196,-17.43595493968,-29.608964734485,34.35184412185,2,1,18 +2025-03-11T12:39:45.139465,479392784,65459,196,-17.69040275716,-29.868185016795,34.838472757945,2,1,18 +2025-03-11T12:39:45.155090,479392784,65459,196,-17.96369856112,-30.136680054615,35.32516559806,2,1,18 +2025-03-11T12:39:45.170715,479392784,65459,196,-18.22757037184,-30.395916642855,35.79794424697,2,1,18 +2025-03-11T12:39:45.186340,479392784,65459,196,-18.49144218256,-30.664395374745,36.28000234201,2,1,18 +2025-03-11T12:39:45.201965,479392784,65459,196,-18.75060199666,-30.93286595367,36.75743247298,2,1,18 +2025-03-11T12:39:45.217590,479392784,65459,196,-19.01447380738,-31.19210254191,37.244074671085,2,1,18 +2025-03-11T12:39:45.233215,479392784,65459,196,-19.28305761472,-31.442105139465,37.721444204065,2,1,18 +2025-03-11T12:39:45.248840,479392784,65459,196,-19.5375054322,-31.692083278125,38.17106629564,2,1,18 +2025-03-11T12:39:45.264465,479392784,65459,196,-19.79195324968,-31.951303560435,38.62534665028,2,1,18 +2025-03-11T12:39:45.280090,479392784,65459,196,-20.03697707392,-32.210507536815,39.102719358235,2,1,18 +2025-03-11T12:39:45.295715,479392784,65459,196,-20.29613688802,-32.465114900265,39.570851503075,2,1,18 +2025-03-11T12:39:45.311340,479392784,65459,196,-20.5505847055,-32.733577326225,40.034411303845,2,1,18 +2025-03-11T12:39:45.326965,479392784,65459,196,-20.79560852974,-33.00664451808,40.497976082605,2,1,18 +2025-03-11T12:39:45.342590,479392784,65459,196,-21.0453443506,-33.2612355756,40.956852299305,2,1,18 +2025-03-11T12:39:45.358215,479392784,65459,196,-21.29508017146,-33.501963417645,41.415672896005,2,1,18 +2025-03-11T12:39:45.373840,479392784,65459,196,-21.53539199908,-33.75191709741,41.85141109537,2,1,18 +2025-03-11T12:39:45.389465,479392784,65459,196,-21.78983981656,-34.006516307895,42.29643054388,2,1,18 +2025-03-11T12:39:45.405090,479392784,65459,196,-22.04428763404,-34.26111551838,42.755313541585,2,1,18 +2025-03-11T12:39:45.420715,479392784,65459,196,-22.2940234549,-34.501843360425,43.21875532135,2,1,18 +2025-03-11T12:39:45.436340,479392784,65459,196,-22.53433528252,-34.747175968365,43.66833852991,2,1,18 +2025-03-11T12:39:45.451965,479392784,65459,196,-22.77464711014,-34.983266432655,44.09939992621,2,1,18 +2025-03-11T12:39:45.467590,479392784,65459,196,-23.01024694114,-35.233211959455,44.5443737107,2,1,18 +2025-03-11T12:39:45.483215,479392784,65459,196,-23.24584677214,-35.47853641443,44.975465405995,2,1,18 +2025-03-11T12:39:45.498840,479392784,65459,196,-23.49087059638,-35.714635031685,45.42501831556,2,1,18 +2025-03-11T12:39:45.514465,479392784,65459,196,-23.731182424,-35.9553465678,45.87458298412,2,1,18 +2025-03-11T12:39:45.530090,479392784,65459,196,-23.97620624824,-36.19606625688,46.31953325062,2,1,18 +2025-03-11T12:39:45.545715,479392784,65459,196,-24.21180607924,-36.42752749638,46.750569325915,2,1,18 +2025-03-11T12:39:45.561340,479392784,65459,196,-24.44740591024,-36.663609807705,47.158518025885,2,1,18 +2025-03-11T12:39:45.576965,479392784,65459,196,-24.68771773786,-36.90432134382,47.57573441299,2,1,18 +2025-03-11T12:39:45.592590,479392784,65459,196,-24.92802956548,-37.135790736285,47.99753490316,2,1,18 +2025-03-11T12:39:45.608215,479392784,65459,196,-25.16362939648,-37.376494119435,48.41474450926,2,1,18 +2025-03-11T12:39:45.623840,479392784,65459,196,-25.38980523424,-37.598696909355,48.84110875948,2,1,18 +2025-03-11T12:39:45.639465,479392784,65459,196,-25.62069306862,-37.82090785224,49.258237424575,2,1,18 +2025-03-11T12:39:45.655090,479392784,65459,196,-25.86100489624,-38.04775617288,49.66615582555,2,1,18 +2025-03-11T12:39:45.670715,479392784,65459,196,-26.07304474414,-38.28379771938,50.08793416969,2,1,18 +2025-03-11T12:39:45.686340,479392784,65459,196,-26.29450858528,-38.51061342816,50.49120426358,2,1,18 +2025-03-11T12:39:45.701965,479392784,65459,196,-26.52068442304,-38.73281621808,50.9175685138,2,1,18 +2025-03-11T12:39:45.717590,479392784,65459,196,-26.75157225742,-38.94116394549,51.325399192765,2,1,18 +2025-03-11T12:39:45.733215,479392784,65459,196,-26.97303609856,-39.14949536697,51.728595126655,2,1,18 +2025-03-11T12:39:45.748840,479392784,65459,196,-27.18978794308,-39.37168185096,52.145703448735,2,1,18 +2025-03-11T12:39:45.764465,479392784,65459,196,-27.4065397876,-39.607731550425,52.54900384162,2,1,18 +2025-03-11T12:39:45.780090,479392784,65459,196,-27.61386763888,-39.839143872135,52.9384085833,2,1,18 +2025-03-11T12:39:45.795715,479392784,65459,196,-27.82590748678,-40.056701131335,53.318522119855,2,1,18 +2025-03-11T12:39:45.811340,479392784,65459,196,-28.0426593313,-40.241919040725,53.707755023545,2,1,18 +2025-03-11T12:39:45.826965,479392784,65459,196,-28.25941117582,-40.454863381065,54.1017203503,2,1,18 +2025-03-11T12:39:45.842590,479392784,65459,196,-28.48558701358,-40.69092938646,54.50965548826,2,1,18 +2025-03-11T12:39:45.858215,479392784,65459,196,-28.7023388581,-40.908494798625,54.88977580582,2,1,18 +2025-03-11T12:39:45.873840,479392784,65459,196,-28.914378706,-41.11218884235,55.25597017318,2,1,18 +2025-03-11T12:39:45.889465,479392784,65459,196,-29.11228256404,-41.311237355355,55.612883291395,2,1,18 +2025-03-11T12:39:45.905090,479392784,65459,196,-29.31961041532,-41.51954431794,55.992952966945,2,1,18 +2025-03-11T12:39:45.920715,479392784,65459,196,-29.53636225984,-41.75097294558,56.36850772144,2,1,18 +2025-03-11T12:39:45.936340,479392784,65459,196,-29.72955412126,-41.95001330562,56.75314115704,2,1,18 +2025-03-11T12:39:45.951965,479392784,65459,196,-29.93216997592,-42.144448899765,57.11928488239,2,1,18 +2025-03-11T12:39:45.967590,479392784,65459,196,-30.13478583058,-42.34812663756,57.46698095548,2,1,18 +2025-03-11T12:39:45.983215,479392784,65459,196,-30.33740168524,-42.55642544718,57.8239379347,2,1,18 +2025-03-11T12:39:45.998779,479392788,65455,197,-30.53530554328,-42.76009503201,58.190111959045,2,1,18 +2025-03-11T12:39:46.014404,479392788,65455,197,-30.71436141484,-42.949868789505,58.560824422435,2,1,18 +2025-03-11T12:39:46.030029,479392788,65455,197,-30.90755327626,-43.13504593407,58.93153868884,2,1,18 +2025-03-11T12:39:46.045654,479392788,65455,197,-31.10074513768,-43.320223078635,59.283768222985,2,1,18 +2025-03-11T12:39:46.061279,479392788,65455,197,-31.2939369991,-43.5054002232,59.622134207935,2,1,18 +2025-03-11T12:39:46.076904,479392788,65455,197,-31.47299287066,-43.70903719617,59.955932826805,2,1,18 +2025-03-11T12:39:46.092529,479392788,65455,197,-31.66618473208,-43.903456484385,60.294335891755,2,1,18 +2025-03-11T12:39:46.108154,479392788,65455,197,-31.8593765935,-44.084012557125,60.63730451977,2,1,18 +2025-03-11T12:39:46.123779,479392788,65455,197,-32.0478564583,-44.2645604769,60.97102400065,2,1,18 +2025-03-11T12:39:46.139404,479392788,65455,197,-32.24104831972,-44.458979765115,61.304805882535,2,1,18 +2025-03-11T12:39:46.155029,479392788,65455,197,-32.43424018114,-44.648777981505,61.64781159055,2,1,18 +2025-03-11T12:39:46.170654,479392788,65455,197,-32.60858405608,-44.829301442385,61.972268362285,2,1,18 +2025-03-11T12:39:46.186279,479392788,65455,197,-32.78763992764,-44.99134876893,62.315142487285,2,1,18 +2025-03-11T12:39:46.201904,479392788,65455,197,-32.97140779582,-45.17188853574,62.63961282103,2,1,18 +2025-03-11T12:39:46.217529,479392788,65455,197,-33.155175664,-45.35242830255,62.945598422515,2,1,18 +2025-03-11T12:39:46.233154,479392788,65455,197,-33.32951953894,-45.52370961978,63.27001811425,2,1,18 +2025-03-11T12:39:46.248779,479392788,65455,197,-33.49915141726,-45.68111956857,63.60361777111,2,1,18 +2025-03-11T12:39:46.264404,479392788,65455,197,-33.67820728882,-45.85703011059,63.904956868525,2,1,18 +2025-03-11T12:39:46.280029,479392788,65455,197,-33.83370317728,-46.032899887785,64.20164087785,2,1,18 +2025-03-11T12:39:46.295654,479392788,65455,197,-33.98919906574,-46.19952752133,64.49366662411,2,1,18 +2025-03-11T12:39:46.311279,479392788,65455,197,-34.15411894744,-46.34306610168,64.799476781575,2,1,18 +2025-03-11T12:39:46.326904,479392788,65455,197,-34.32375082576,-46.495854978645,65.096088433915,2,1,18 +2025-03-11T12:39:46.342529,479392788,65455,197,-34.47924671422,-46.67172475584,65.40201480937,2,1,18 +2025-03-11T12:39:46.358154,479392788,65455,197,-34.65359058916,-46.847627144895,65.71258949191,2,1,18 +2025-03-11T12:39:46.373779,479392788,65455,197,-34.82322246748,-47.023521380985,66.004672661185,2,1,18 +2025-03-11T12:39:46.389404,479392788,65455,197,-34.97400635932,-47.171656574265,66.27813273418,2,1,18 +2025-03-11T12:39:46.405029,479392788,65455,197,-35.12007825454,-47.333646830055,66.5608840123,2,1,18 +2025-03-11T12:39:46.420654,479392788,65455,197,-35.275574143,-47.495653391775,66.839027669365,2,1,18 +2025-03-11T12:39:46.436279,479392788,65455,197,-35.42635803484,-47.653030728705,67.135630737685,2,1,18 +2025-03-11T12:39:46.451904,479392788,65455,197,-35.57242993006,-47.80115776902,67.427568761935,2,1,18 +2025-03-11T12:39:46.467529,479392788,65455,197,-35.71378982866,-47.935413440895,67.68247492066,2,1,18 +2025-03-11T12:39:46.483154,479392788,65455,197,-35.85514972726,-48.06966911277,67.93275989632,2,1,18 +2025-03-11T12:39:46.498779,479392788,65455,197,-36.01535761234,-48.22706275563,68.17392232987,2,1,18 +2025-03-11T12:39:46.514404,479392788,65455,197,-36.15671751094,-48.39366593028,68.42433708553,2,1,18 +2025-03-11T12:39:46.530029,479392788,65455,197,-36.29336541292,-48.532534521015,68.69773973551,2,1,18 +2025-03-11T12:39:46.545654,479392788,65455,197,-36.43943730814,-48.68066156133,68.966571844435,2,1,18 +2025-03-11T12:39:46.561279,479392788,65455,197,-36.58079720674,-48.824159376855,69.21227271703,2,1,18 +2025-03-11T12:39:46.576904,479392788,65455,197,-36.71744510872,-48.967649039415,69.45796680862,2,1,18 +2025-03-11T12:39:46.592529,479392788,65455,197,-36.8540930107,-49.0972754865,69.708226463275,2,1,18 +2025-03-11T12:39:46.608154,479392788,65455,197,-36.9954529093,-49.222289014725,69.939989626675,2,1,18 +2025-03-11T12:39:46.623779,479392788,65455,197,-37.13210081128,-49.35191546181,70.1810069152,2,1,18 +2025-03-11T12:39:46.639404,479392788,65455,197,-37.26403671664,-49.495396971405,70.43131540885,2,1,18 +2025-03-11T12:39:46.655029,479392788,65455,197,-37.395972622,-49.62963633735,70.67234445637,2,1,18 +2025-03-11T12:39:46.670654,479392788,65455,197,-37.51848453412,-49.74999618189,70.91330432188,2,1,18 +2025-03-11T12:39:46.686279,479392788,65455,197,-37.631572453,-49.8703397205,71.131144710055,2,1,18 +2025-03-11T12:39:46.701904,479392788,65455,197,-37.75879636174,-49.96760235888,71.35353392431,2,1,18 +2025-03-11T12:39:46.717529,479392788,65455,197,-37.88130827386,-50.09720434707,71.57604613756,2,1,18 +2025-03-11T12:39:46.733154,479392788,65455,197,-37.99910818936,-50.217556038645,71.79389330674,2,1,18 +2025-03-11T12:39:46.748779,479392788,65455,197,-38.11690810486,-50.32866558657,72.007082212855,2,1,18 +2025-03-11T12:39:46.764404,479392788,65455,197,-38.22999602374,-50.44900912518,72.23416496716,2,1,18 +2025-03-11T12:39:46.780029,479392788,65455,197,-38.34779593924,-50.58322403223,72.428961841015,2,1,18 +2025-03-11T12:39:46.795654,479392788,65455,197,-38.46559585474,-50.694333580155,72.609802465675,2,1,18 +2025-03-11T12:39:46.811279,479392788,65455,197,-38.57868377362,-50.805434975115,72.822984590785,2,1,18 +2025-03-11T12:39:46.826904,479392788,65455,197,-38.68234769926,-50.89341470502,73.017575721625,2,1,18 +2025-03-11T12:39:46.842529,479392788,65455,197,-38.79543561814,-50.981410740855,73.21680159754,2,1,18 +2025-03-11T12:39:46.858154,479392788,65455,197,-38.89909954378,-51.08787475806,73.41146688838,2,1,18 +2025-03-11T12:39:46.873779,479392788,65455,197,-39.00276346942,-51.194338775265,73.601510996155,2,1,18 +2025-03-11T12:39:46.889404,479392788,65455,197,-39.10171539844,-51.30541571133,73.773082130665,2,1,18 +2025-03-11T12:39:46.905029,479392788,65455,197,-39.20066732746,-51.41187157557,73.963119457435,2,1,18 +2025-03-11T12:39:46.920654,479392788,65455,197,-39.29961925648,-51.49984315251,74.13921907501,2,1,18 +2025-03-11T12:39:46.936279,479392788,65455,197,-39.3985711855,-51.5970568731,74.306113406455,2,1,18 +2025-03-11T12:39:46.951904,479392788,65455,197,-39.48338712466,-51.68962506297,74.482211221015,2,1,18 +2025-03-11T12:39:46.967529,479392788,65455,197,-39.56820306382,-51.78219325284,74.65368785251,2,1,18 +2025-03-11T12:39:46.983154,479392788,65455,197,-39.66715499284,-51.87016482978,74.82516628702,2,1,18 +2025-03-11T12:39:46.998779,479392788,65455,197,-39.76139492524,-51.96274932558,74.968929382135,2,1,18 +2025-03-11T12:39:47.014404,479392788,65455,197,-39.85563485764,-52.07381810868,75.12200900338,2,1,18 +2025-03-11T12:39:47.030029,479392788,65455,197,-39.9404507968,-52.1571441549,75.293448554875,2,1,18 +2025-03-11T12:39:47.045654,479392788,65455,197,-40.02997873258,-52.231236210435,75.446373075115,2,1,18 +2025-03-11T12:39:47.061279,479392788,65455,197,-40.11008267512,-52.31455410369,75.57621519802,2,1,18 +2025-03-11T12:39:47.076904,479392788,65455,197,-40.19018661766,-52.379387709645,75.73833144238,2,1,18 +2025-03-11T12:39:47.092529,479392788,65455,197,-40.2702905602,-52.458084531075,75.89126094061,2,1,18 +2025-03-11T12:39:47.108154,479392788,65455,197,-40.3409705095,-52.536765046575,76.030313327635,2,1,18 +2025-03-11T12:39:47.123779,479392788,65455,197,-40.41636245542,-52.62469585869,76.169409575665,2,1,18 +2025-03-11T12:39:47.139404,479392788,65455,197,-40.47761841148,-52.689496852785,76.28990804842,2,1,18 +2025-03-11T12:39:47.155029,479392788,65455,197,-40.53887436754,-52.76353999053,76.40582241811,2,1,18 +2025-03-11T12:39:47.170654,479392788,65455,197,-40.61897831008,-52.828373596485,76.52172683182,2,1,18 +2025-03-11T12:39:47.186279,479392788,65455,197,-40.68494626276,-52.88856167172,76.628349996385,2,1,18 +2025-03-11T12:39:47.201904,479392788,65455,197,-40.74620221882,-52.94874159399,76.75807229527,2,1,18 +2025-03-11T12:39:47.217529,479392788,65455,197,-40.8121701715,-53.018171812875,76.87859608903,2,1,18 +2025-03-11T12:39:47.233154,479392788,65455,197,-40.86871413094,-53.07834358218,76.98982687465,2,1,18 +2025-03-11T12:39:47.248779,479392788,65455,197,-40.92525809038,-53.147757495135,77.10109474027,2,1,18 +2025-03-11T12:39:47.264404,479392788,65455,197,-40.99593803968,-53.180227292385,77.184507530515,2,1,18 +2025-03-11T12:39:47.280029,479392788,65455,197,-41.05248199912,-53.235777989865,77.277235043875,2,1,18 +2025-03-11T12:39:47.295654,479392788,65455,197,-41.10902595856,-53.28670761552,77.3745652003,2,1,18 +2025-03-11T12:39:47.311279,479392788,65455,197,-41.1420099349,-53.332975404525,77.467221728635,2,1,18 +2025-03-11T12:39:47.326904,479392788,65455,197,-41.19384189772,-53.365412589915,77.55060739486,2,1,18 +2025-03-11T12:39:47.342529,479392788,65455,197,-41.25038585716,-53.411721143745,77.638676645155,2,1,18 +2025-03-11T12:39:47.358154,479392788,65455,197,-41.3069298166,-53.467271841225,77.731404158515,2,1,18 +2025-03-11T12:39:47.373779,479392788,65455,197,-41.35876177942,-53.518193313915,77.810242801675,2,1,18 +2025-03-11T12:39:47.389404,479392788,65455,197,-41.39645775238,-53.555227112235,77.88900548182,2,1,18 +2025-03-11T12:39:47.405029,479392788,65455,197,-41.42001773548,-53.60147859531,77.96778489895,2,1,18 +2025-03-11T12:39:47.420654,479392788,65455,197,-41.43886572196,-53.64772192542,78.04193635201,2,1,18 +2025-03-11T12:39:47.436279,479392788,65455,197,-41.4718496983,-53.6708843553,78.097530715825,2,1,18 +2025-03-11T12:39:47.451904,479392788,65455,197,-41.50954567126,-53.70791815362,78.13932393145,2,1,18 +2025-03-11T12:39:47.467529,479392788,65455,197,-41.5425296476,-53.74032272715,78.185713009135,2,1,18 +2025-03-11T12:39:47.483154,479392788,65455,197,-41.57551362394,-53.76348515703,78.23206500682,2,1,18 +2025-03-11T12:39:47.498779,479392788,65455,197,-41.59907360704,-53.78663128098,78.287645808625,2,1,18 +2025-03-11T12:39:47.514404,479392788,65455,197,-41.62734558676,-53.809785557895,78.352475757565,2,1,18 +2025-03-11T12:39:47.530029,479392788,65455,197,-41.64619357324,-53.837544600705,78.389583586105,2,1,18 +2025-03-11T12:39:47.545654,479392788,65455,197,-41.66504155972,-53.846819356215,78.426617254645,2,1,18 +2025-03-11T12:39:47.561279,479392788,65455,197,-41.69802553606,-53.869981786095,78.459105703135,2,1,18 +2025-03-11T12:39:47.576904,479392788,65455,197,-41.71216152592,-53.883869460465,78.473045215345,2,1,18 +2025-03-11T12:39:47.592529,479392788,65455,197,-41.71216152592,-53.911595891415,78.491641187605,2,1,18 +2025-03-11T12:39:47.608154,479392788,65455,197,-41.72629751578,-53.91162035031,78.524009812075,2,1,18 +2025-03-11T12:39:47.623779,479392788,65455,197,-41.7310095124,-53.911628503275,78.53325895921,2,1,18 +2025-03-11T12:39:47.639404,479392788,65455,197,-41.74043350564,-53.920886952855,78.547173150415,2,1,18 +2025-03-11T12:39:47.655029,479392788,65455,197,-41.74985749888,-53.939387546085,78.56112442162,2,1,18 +2025-03-11T12:39:47.670654,479392788,65455,197,-41.76870548536,-53.957904445245,78.584331620965,2,1,18 +2025-03-11T12:39:47.686279,479392788,65455,197,-41.75928149212,-53.95326706749,78.59816306815,2,1,18 +2025-03-11T12:39:47.701904,479392788,65455,197,-41.74985749888,-53.939387546085,78.584230336945,2,1,18 +2025-03-11T12:39:47.717529,479392788,65455,197,-41.7545694955,-53.93939569905,78.579615934885,2,1,18 +2025-03-11T12:39:47.733154,479392788,65455,197,-41.75928149212,-53.939403852015,78.575001532825,2,1,18 +2025-03-11T12:39:47.748779,479392788,65455,197,-41.77341748198,-53.934807239085,78.551897420515,2,1,18 +2025-03-11T12:39:47.764404,479392788,65455,197,-41.75928149212,-53.92554063654,78.54259763137,2,1,18 +2025-03-11T12:39:47.780029,479392788,65455,197,-41.75928149212,-53.920919564715,78.51485199298,2,1,18 +2025-03-11T12:39:47.795654,479392788,65455,197,-41.74985749888,-53.911661115135,78.500937801775,2,1,18 +2025-03-11T12:39:47.811279,479392788,65455,197,-41.7310095124,-53.902386359625,78.49625241469,2,1,18 +2025-03-11T12:39:47.826904,479392788,65455,197,-41.71216152592,-53.902353747765,78.482361741475,2,1,18 +2025-03-11T12:39:47.842529,479392788,65455,197,-41.68860154282,-53.87458655199,78.468353047255,2,1,18 +2025-03-11T12:39:47.858154,479392788,65455,197,-41.66975355634,-53.84682750918,78.412760486455,2,1,18 +2025-03-11T12:39:47.873779,479392788,65455,197,-41.65090556986,-53.82831061002,78.36182618872,2,1,18 +2025-03-11T12:39:47.889404,479392788,65455,197,-41.64619357324,-53.809818169755,78.33863933239,2,1,18 +2025-03-11T12:39:47.905029,479392788,65455,197,-41.60849760028,-53.79588973056,78.28307526757,2,1,18 +2025-03-11T12:39:47.920654,479392788,65455,197,-41.58493761718,-53.77274360661,78.23211564883,2,1,18 +2025-03-11T12:39:47.936279,479392788,65455,197,-41.54724164422,-53.74495195194,78.181117147075,2,1,18 +2025-03-11T12:39:47.951904,479392788,65455,197,-41.5189696645,-53.70793445955,78.1208527612,2,1,18 +2025-03-11T12:39:47.967529,479392788,65455,197,-41.4954096814,-53.670925120125,78.0513527902,2,1,18 +2025-03-11T12:39:47.983154,479392788,65455,197,-41.4718496983,-53.6339157807,77.99109518533,2,1,18 +2025-03-11T12:39:47.998779,479392788,65455,197,-41.4482897152,-53.596906441275,77.94007994659,2,1,18 +2025-03-11T12:39:48.014404,479392788,65455,197,-41.39174575576,-53.56446110292,77.870551048555,2,1,18 +2025-03-11T12:39:48.030029,479392788,65455,197,-41.33991379294,-53.52278177388,77.80561303459,2,1,18 +2025-03-11T12:39:48.045654,479392788,65455,197,-41.29279382674,-53.47648952598,77.736042078565,2,1,18 +2025-03-11T12:39:48.061279,479392788,65455,197,-41.25509785378,-53.416350368535,77.643323149225,2,1,18 +2025-03-11T12:39:48.076904,479392788,65455,197,-41.20797788758,-53.370058120635,77.56450982707,2,1,18 +2025-03-11T12:39:48.092529,479392788,65455,197,-41.165569918,-53.33301616935,77.49498273205,2,1,18 +2025-03-11T12:39:48.108154,479392788,65455,197,-41.1184499518,-53.2774817778,77.406889963765,2,1,18 +2025-03-11T12:39:48.123779,479392788,65455,197,-41.0713299856,-53.2127052426,77.30027538322,2,1,18 +2025-03-11T12:39:48.139404,479392788,65455,197,-41.00536203292,-53.152517167365,77.175167486395,2,1,18 +2025-03-11T12:39:48.155029,479392788,65455,197,-40.93939408024,-53.09232909213,77.073165504895,2,1,18 +2025-03-11T12:39:48.170654,479392788,65455,197,-40.87813812418,-53.04139131351,76.975828567465,2,1,18 +2025-03-11T12:39:48.186279,479392788,65455,197,-40.83101815798,-52.990477993785,76.86002724079,2,1,18 +2025-03-11T12:39:48.201904,479392788,65455,197,-40.7650502053,-52.953395277675,76.73963322703,2,1,18 +2025-03-11T12:39:48.217529,479392788,65455,197,-40.70850624586,-52.888602436545,76.633005084475,2,1,18 +2025-03-11T12:39:48.233154,479392788,65455,197,-40.66138627966,-52.82844697317,76.512545494735,2,1,18 +2025-03-11T12:39:48.248779,479392788,65455,197,-40.59541832698,-52.749774610635,76.38736343791,2,1,18 +2025-03-11T12:39:48.264404,479392788,65455,197,-40.5058903912,-52.661819339625,76.27135276219,2,1,18 +2025-03-11T12:39:48.280029,479392788,65455,197,-40.43049844528,-52.59237281481,76.15081540642,2,1,18 +2025-03-11T12:39:48.295654,479392788,65455,197,-40.35510649936,-52.52754736182,76.02105422452,2,1,18 +2025-03-11T12:39:48.311279,479392788,65455,197,-40.27500255682,-52.453471612215,75.87738563242,2,1,18 +2025-03-11T12:39:48.326904,479392788,65455,197,-40.21374660076,-52.374807402645,75.73372562434,2,1,18 +2025-03-11T12:39:48.342529,479392788,65455,197,-40.13835465484,-52.28687659053,75.60387174244,2,1,18 +2025-03-11T12:39:48.358154,479392788,65455,197,-40.05353871568,-52.20355054431,75.460159289335,2,1,18 +2025-03-11T12:39:48.373779,479392788,65455,197,-39.96872277652,-52.115603426265,75.3071859301,2,1,18 +2025-03-11T12:39:48.389404,479392788,65455,197,-39.87919484074,-52.046132442555,75.1357952176,2,1,18 +2025-03-11T12:39:48.405029,479392788,65455,197,-39.79437890158,-51.962806396335,74.96897684917,2,1,18 +2025-03-11T12:39:48.420654,479392788,65455,197,-39.71898695566,-51.879496656045,74.816035591945,2,1,18 +2025-03-11T12:39:48.436279,479392788,65455,197,-39.62945901988,-51.773057097735,74.64911774251,2,1,18 +2025-03-11T12:39:48.451904,479392788,65455,197,-39.54935507734,-51.685118132655,74.48690879815,2,1,18 +2025-03-11T12:39:48.467529,479392788,65455,197,-39.45982714156,-51.587920717995,74.31540684565,2,1,18 +2025-03-11T12:39:48.483154,479392788,65455,197,-39.35616321592,-51.486077772615,74.134623644005,2,1,18 +2025-03-11T12:39:48.498779,479392788,65455,197,-39.2572112869,-51.37500083655,73.972294875625,2,1,18 +2025-03-11T12:39:48.514404,479392788,65455,197,-39.15825935788,-51.273166044135,73.782276088855,2,1,18 +2025-03-11T12:39:48.530029,479392788,65455,197,-39.05930742886,-51.18057339537,73.57843083289,2,1,18 +2025-03-11T12:39:48.545654,479392788,65455,197,-38.95564350322,-51.06948830634,73.41147410044,2,1,18 +2025-03-11T12:39:48.561279,479392788,65455,197,-38.84255558434,-50.97687119868,73.221472050655,2,1,18 +2025-03-11T12:39:48.576904,479392788,65455,197,-38.7388916587,-50.888891468775,73.017638553685,2,1,18 +2025-03-11T12:39:48.592529,479392788,65455,197,-38.6446517263,-50.777822685675,72.832210650985,2,1,18 +2025-03-11T12:39:48.608154,479392788,65455,197,-38.53627580404,-50.652866228205,72.614358503815,2,1,18 +2025-03-11T12:39:48.623779,479392788,65455,197,-38.42789988178,-50.537151914385,72.40116461971,2,1,18 +2025-03-11T12:39:48.639404,479392788,65455,197,-38.31009996628,-50.41680022281,72.21104454892,2,1,18 +2025-03-11T12:39:48.655029,479392788,65455,197,-38.18758805416,-50.319545737395,71.98866211567,2,1,18 +2025-03-11T12:39:48.670654,479392788,65455,197,-38.0792121319,-50.19921035175,71.7708285085,2,1,18 +2025-03-11T12:39:48.686279,479392788,65455,197,-37.96612421302,-50.074245741315,71.543727214195,2,1,18 +2025-03-11T12:39:48.701904,479392788,65455,197,-37.83418830766,-49.944627447195,71.321201438935,2,1,18 +2025-03-11T12:39:48.717529,479392788,65455,197,-37.70696439892,-49.80577516239,71.103266547745,2,1,18 +2025-03-11T12:39:48.733154,479392788,65455,197,-37.58916448342,-49.666939183515,70.876102852435,2,1,18 +2025-03-11T12:39:48.748779,479392788,65455,197,-37.47136456792,-49.551208563765,70.649031857125,2,1,18 +2025-03-11T12:39:48.764404,479392788,65455,197,-37.33000466932,-49.430816107365,70.408044867595,2,1,18 +2025-03-11T12:39:48.780029,479392788,65455,197,-37.18864477072,-49.282697220015,70.176189004195,2,1,18 +2025-03-11T12:39:48.795654,479392788,65455,197,-37.05670886536,-49.162321069545,69.916730844415,2,1,18 +2025-03-11T12:39:48.811279,479392788,65455,197,-36.93890894986,-49.03272723432,69.65725594765,2,1,18 +2025-03-11T12:39:48.826904,479392788,65455,197,-36.8069730445,-48.9031089402,69.41624544013,2,1,18 +2025-03-11T12:39:48.842529,479392788,65455,197,-36.6656131459,-48.75499005285,69.179768393665,2,1,18 +2025-03-11T12:39:48.858154,479392788,65455,197,-36.5242532473,-48.620734380975,68.947968150265,2,1,18 +2025-03-11T12:39:48.873779,479392788,65455,197,-36.37346935546,-48.481841331345,68.697651072595,2,1,18 +2025-03-11T12:39:48.889404,479392788,65455,197,-36.22268546362,-48.342948281715,68.438091628795,2,1,18 +2025-03-11T12:39:48.905029,479392788,65455,197,-36.1001735515,-48.1902409344,68.178517251025,2,1,18 +2025-03-11T12:39:48.920654,479392788,65455,197,-35.95410165628,-48.032871750435,67.905026879035,2,1,18 +2025-03-11T12:39:48.936279,479392788,65455,197,-35.80802976106,-47.88474471012,67.63619477011,2,1,18 +2025-03-11T12:39:48.951904,479392788,65455,197,-35.66195786584,-47.74123874163,67.348896468925,2,1,18 +2025-03-11T12:39:48.967529,479392788,65455,197,-35.50646197738,-47.59771646721,67.07082697186,2,1,18 +2025-03-11T12:39:48.983154,479392788,65455,197,-35.36039008216,-47.44496835507,66.792733956805,2,1,18 +2025-03-11T12:39:48.998779,479392788,65455,197,-35.2048941937,-47.28296179335,66.50534793361,2,1,18 +2025-03-11T12:39:49.014404,479392788,65455,197,-35.039974312,-47.1024546384,66.227116554535,2,1,18 +2025-03-11T12:39:49.030029,479392788,65455,197,-34.88919042016,-46.94507730147,65.93513466928,2,1,18 +2025-03-11T12:39:49.045654,479392788,65455,197,-34.72427053846,-46.806159792945,65.64320660101,2,1,18 +2025-03-11T12:39:49.061279,479392788,65455,197,-34.56877465,-46.662637518525,65.365137103945,2,1,18 +2025-03-11T12:39:49.076904,479392788,65455,197,-34.38971877844,-46.49134804833,65.04533181427,2,1,18 +2025-03-11T12:39:49.092529,479392788,65455,197,-34.22951089336,-46.320091189995,64.73941719781,2,1,18 +2025-03-11T12:39:49.108154,479392788,65455,197,-34.0740150049,-46.139600340975,64.42885109929,2,1,18 +2025-03-11T12:39:49.123779,479392788,65455,197,-33.90438312658,-45.96832717671,64.11368055469,2,1,18 +2025-03-11T12:39:49.139404,479392788,65455,197,-33.7441752415,-45.8016913902,63.81702684436,2,1,18 +2025-03-11T12:39:49.155029,479392788,65455,197,-33.56983136656,-45.63041007297,63.501849518755,2,1,18 +2025-03-11T12:39:49.170654,479392788,65455,197,-33.40019948824,-45.459136908705,63.195921340285,2,1,18 +2025-03-11T12:39:49.186279,479392788,65455,197,-33.22114361668,-45.292468510335,62.880755773675,2,1,18 +2025-03-11T12:39:49.201904,479392788,65455,197,-33.05622373498,-45.10734028356,62.570157573145,2,1,18 +2025-03-11T12:39:49.217529,479392788,65455,197,-32.87716786342,-44.93142974154,62.236470194275,2,1,18 +2025-03-11T12:39:49.233154,479392788,65455,197,-32.69339999524,-44.746268902905,61.91198132053,2,1,18 +2025-03-11T12:39:49.248779,479392788,65455,197,-32.50492013044,-44.561099911305,61.56900093352,2,1,18 +2025-03-11T12:39:49.264404,479392788,65455,197,-32.32586425888,-44.38056829746,61.230673831585,2,1,18 +2025-03-11T12:39:49.280029,479392788,65455,197,-32.1656563738,-44.190827151825,60.887715590605,2,1,18 +2025-03-11T12:39:49.295654,479392788,65455,197,-31.98188850562,-44.001045241365,60.549344627665,2,1,18 +2025-03-11T12:39:49.311279,479392788,65455,197,-31.7886966442,-43.80662595315,60.20632037965,2,1,18 +2025-03-11T12:39:49.326904,479392788,65455,197,-31.6002167794,-43.626078033375,59.87260089877,2,1,18 +2025-03-11T12:39:49.342529,479392788,65455,197,-31.4117369146,-43.4455301136,59.52963905176,2,1,18 +2025-03-11T12:39:49.358154,479392788,65455,197,-31.21854505318,-43.260352969035,59.18203070068,2,1,18 +2025-03-11T12:39:49.373779,479392788,65455,197,-31.03006518838,-43.056699690135,58.80200668915,2,1,18 +2025-03-11T12:39:49.389404,479392788,65455,197,-30.83687332696,-42.86228040192,58.45436125807,2,1,18 +2025-03-11T12:39:49.405029,479392788,65455,197,-30.6342574723,-42.686329095075,58.111397608045,2,1,18 +2025-03-11T12:39:49.420654,479392788,65455,197,-30.43164161764,-42.48265135728,57.754459168825,2,1,18 +2025-03-11T12:39:49.436279,479392788,65455,197,-30.2337377596,-42.283602844275,57.392924867545,2,1,18 +2025-03-11T12:39:49.451904,479392788,65455,197,-30.02640990832,-42.079916953515,57.01749491506,2,1,18 +2025-03-11T12:39:49.467529,479392788,65455,197,-29.82850605028,-41.87162629686,56.64668116765,2,1,18 +2025-03-11T12:39:49.483154,479392788,65455,197,-29.62589019562,-41.658706415415,56.285084465365,2,1,18 +2025-03-11T12:39:49.498779,479392788,65455,197,-29.4326983342,-41.450423911725,55.93276223122,2,1,18 +2025-03-11T12:39:49.514404,479392788,65455,197,-29.23479447616,-41.25137539872,55.557364380745,2,1,18 +2025-03-11T12:39:49.530029,479392788,65455,197,-29.01804263164,-41.052294273855,55.168075857055,2,1,18 +2025-03-11T12:39:49.545654,479392788,65455,197,-28.80129078712,-40.830107789865,54.78331581643,2,1,18 +2025-03-11T12:39:49.561279,479392788,65455,197,-28.59867493246,-40.621808980245,54.38938937269,2,1,18 +2025-03-11T12:39:49.576904,479392788,65455,197,-28.39134708118,-40.41350201766,53.99083496488,2,1,18 +2025-03-11T12:39:49.592529,479392788,65455,197,-28.17930723328,-40.20518690211,53.610758508325,2,1,18 +2025-03-11T12:39:49.608154,479392788,65455,197,-27.95784339214,-39.982992265155,53.22137050363,2,1,18 +2025-03-11T12:39:49.623779,479392788,65455,197,-27.736379551,-39.77003977185,52.832019578935,2,1,18 +2025-03-11T12:39:49.639404,479392788,65455,197,-27.51491570986,-39.55246620672,52.43340774811,2,1,18 +2025-03-11T12:39:49.655029,479392788,65455,197,-27.30287586196,-39.339530019345,52.03020683623,2,1,18 +2025-03-11T12:39:49.670654,479392788,65455,197,-27.08141202082,-39.121956454215,51.63621618847,2,1,18 +2025-03-11T12:39:49.686279,479392788,65455,197,-26.8646601763,-38.8951488984,51.21908932639,2,1,18 +2025-03-11T12:39:49.701904,479392788,65455,197,-26.64319633516,-38.67757533327,50.801992763305,2,1,18 +2025-03-11T12:39:49.717529,479392788,65455,197,-26.4170204974,-38.4461303997,50.384833799215,2,1,18 +2025-03-11T12:39:49.733154,479392788,65455,197,-26.20026865288,-38.22394391571,49.9723466602,2,1,18 +2025-03-11T12:39:49.748779,479392788,65455,197,-25.97880481174,-38.001749278755,49.564473923245,2,1,18 +2025-03-11T12:39:49.764404,479392788,65455,197,-25.74791697736,-37.765675120395,49.14728963815,2,1,18 +2025-03-11T12:39:49.780029,479392788,65455,197,-25.50760514974,-37.52496358428,48.730073251045,2,1,18 +2025-03-11T12:39:49.795654,479392788,65455,197,-25.28142931198,-37.28427650706,48.31749839002,2,1,18 +2025-03-11T12:39:49.811279,479392788,65455,197,-25.05996547084,-37.052839726455,47.89572502387,2,1,18 +2025-03-11T12:39:49.826904,479392788,65455,197,-24.83378963308,-36.81677372106,47.464683970585,2,1,18 +2025-03-11T12:39:49.842529,479392788,65455,197,-24.59347780546,-36.585304328595,47.052125846545,2,1,18 +2025-03-11T12:39:49.858154,479392788,65455,197,-24.34845398122,-36.34920571134,46.62105766924,2,1,18 +2025-03-11T12:39:49.873779,479392788,65455,197,-24.1081421536,-36.1223573907,46.19003335294,2,1,18 +2025-03-11T12:39:49.889404,479392788,65455,197,-23.86783032598,-35.89550907006,45.754387853575,2,1,18 +2025-03-11T12:39:49.905029,479392788,65455,197,-23.6369424916,-35.664055983525,45.304873827025,2,1,18 +2025-03-11T12:39:49.920654,479392788,65455,197,-23.41076665384,-35.414126762655,44.859913604545,2,1,18 +2025-03-11T12:39:49.936279,479392788,65455,197,-23.17045482622,-35.17341522654,44.43345485131,2,1,18 +2025-03-11T12:39:49.951904,479392788,65455,197,-22.92543100198,-34.94193768111,43.97929929868,2,1,18 +2025-03-11T12:39:49.967529,479392788,65455,197,-22.68040717774,-34.687354776555,43.52505104605,2,1,18 +2025-03-11T12:39:49.983154,479392788,65455,197,-22.44009535012,-34.432780024965,43.098536672815,2,1,18 +2025-03-11T12:39:49.998718,479392792,65451,198,-22.18564753264,-34.17818081448,42.64889604124,2,1,18 +2025-03-11T12:39:50.014343,479392792,65451,198,-21.93591171178,-33.937452972435,42.18083307841,2,1,18 +2025-03-11T12:39:50.029968,479392792,65451,198,-21.69088788754,-33.696733283355,41.731261628845,2,1,18 +2025-03-11T12:39:50.045593,479392792,65451,198,-21.44115206668,-33.432900082185,41.281590698275,2,1,18 +2025-03-11T12:39:50.061218,479392792,65451,198,-21.19141624582,-33.19217224014,40.822770101575,2,1,18 +2025-03-11T12:39:50.076843,479392792,65451,198,-20.94168042496,-32.942202254445,40.382397157135,2,1,18 +2025-03-11T12:39:50.092468,479392792,65451,198,-20.70136859734,-32.69224857468,39.932795408575,2,1,18 +2025-03-11T12:39:50.108093,479392792,65451,198,-20.44220878324,-32.43764121123,39.455420897605,2,1,18 +2025-03-11T12:39:50.123718,479392792,65451,198,-20.17833697252,-32.16916247934,38.991847534825,2,1,18 +2025-03-11T12:39:50.139343,479392792,65451,198,-19.91917715842,-31.90531297224,38.52829949305,2,1,18 +2025-03-11T12:39:50.154968,479392792,65451,198,-19.6788653308,-31.646117148825,38.0509335661,2,1,18 +2025-03-11T12:39:50.170593,479392792,65451,198,-19.4197055167,-31.38688871355,37.578161698195,2,1,18 +2025-03-11T12:39:50.186218,479392792,65451,198,-19.15112170936,-31.127643972345,37.11461863441,2,1,18 +2025-03-11T12:39:50.201843,479392792,65451,198,-18.89196189526,-30.88689982437,36.660405658765,2,1,18 +2025-03-11T12:39:50.217468,479392792,65451,198,-18.6422260744,-30.618445551375,36.18761027287,2,1,18 +2025-03-11T12:39:50.233093,479392792,65451,198,-18.3830662603,-30.3407328288,35.705521878835,2,1,18 +2025-03-11T12:39:50.248718,479392792,65451,198,-18.11919444958,-30.067633025085,35.19109696234,2,1,18 +2025-03-11T12:39:50.264343,479392792,65451,198,-17.83176265576,-29.812976743845,34.69519703308,2,1,18 +2025-03-11T12:39:50.279968,479392792,65451,198,-17.57260284166,-29.54450616492,34.22700926824,2,1,18 +2025-03-11T12:39:50.295593,479392792,65451,198,-17.30873103094,-29.27602743303,33.749572356265,2,1,18 +2025-03-11T12:39:50.311218,479392792,65451,198,-17.0401472236,-29.007540548175,33.26750748022,2,1,18 +2025-03-11T12:39:50.326843,479392792,65451,198,-16.79041140274,-28.74832841883,32.776264442065,2,1,18 +2025-03-11T12:39:50.342468,479392792,65451,198,-16.53125158864,-28.48447891173,32.2849893019,2,1,18 +2025-03-11T12:39:50.358093,479392792,65451,198,-16.26737977792,-28.220621251665,31.81219211299,2,1,18 +2025-03-11T12:39:50.373718,479392792,65451,198,-16.0035079672,-27.9567635916,31.325531374885,2,1,18 +2025-03-11T12:39:50.389343,479392792,65451,198,-15.73021216324,-27.683647481955,30.82957762864,2,1,18 +2025-03-11T12:39:50.404968,479392792,65451,198,-15.4616283559,-27.401297381625,30.3335935834,2,1,18 +2025-03-11T12:39:50.420593,479392792,65451,198,-15.18833255194,-27.12818127198,29.846882203285,2,1,18 +2025-03-11T12:39:50.436218,479392792,65451,198,-14.91032475136,-26.850435937545,29.31855485458,2,1,18 +2025-03-11T12:39:50.451843,479392792,65451,198,-14.6370289474,-26.581940899725,28.80875609914,2,1,18 +2025-03-11T12:39:50.467468,479392792,65451,198,-14.36844514006,-26.31345401487,28.308206490835,2,1,18 +2025-03-11T12:39:50.483093,479392792,65451,198,-14.08572534286,-26.031079455645,27.82144446871,2,1,18 +2025-03-11T12:39:50.498718,479392792,65451,198,-13.79829354904,-25.73483352798,27.31613531332,2,1,18 +2025-03-11T12:39:50.514343,479392792,65451,198,-13.51086175522,-25.447829743965,26.815484420995,2,1,18 +2025-03-11T12:39:50.529968,479392792,65451,198,-13.23285395464,-25.165463337705,26.30562326455,2,1,18 +2025-03-11T12:39:50.545593,479392792,65451,198,-12.95484615406,-24.892339075095,25.814283920365,2,1,18 +2025-03-11T12:39:50.561218,479392792,65451,198,-12.67212635686,-24.61920665952,25.304453062915,2,1,18 +2025-03-11T12:39:50.576843,479392792,65451,198,-12.38940655966,-24.34145317212,24.77149775014,2,1,18 +2025-03-11T12:39:50.592468,479392792,65451,198,-12.1161107557,-24.054473847,24.2616248347,2,1,18 +2025-03-11T12:39:50.608093,479392792,65451,198,-11.83810295512,-23.78134958439,23.761043124385,2,1,18 +2025-03-11T12:39:50.623718,479392792,65451,198,-11.55538315792,-23.498975025165,23.24655400387,2,1,18 +2025-03-11T12:39:50.639343,479392792,65451,198,-11.25852737086,-23.20271279157,22.72274655421,2,1,18 +2025-03-11T12:39:50.654968,479392792,65451,198,-10.96638358042,-22.92494299824,22.189777679425,2,1,18 +2025-03-11T12:39:50.670593,479392792,65451,198,-10.69308777646,-22.633342601295,21.66602267479,2,1,18 +2025-03-11T12:39:50.686218,479392792,65451,198,-10.41507997588,-22.360218338685,21.16081978141,2,1,18 +2025-03-11T12:39:50.701843,479392792,65451,198,-10.12293618544,-22.05934318623,20.655485305015,2,1,18 +2025-03-11T12:39:50.717468,479392792,65451,198,-9.84964038148,-21.758500645635,20.14093558651,2,1,18 +2025-03-11T12:39:50.733093,479392792,65451,198,-9.58105657414,-21.48077161713,19.60800061675,2,1,18 +2025-03-11T12:39:50.748718,479392792,65451,198,-9.30304877356,-21.19840521087,19.061169995785,2,1,18 +2025-03-11T12:39:50.764343,479392792,65451,198,-9.0061929865,-20.911385120925,18.53277844306,2,1,18 +2025-03-11T12:39:50.779968,479392792,65451,198,-8.6999132062,-20.62434872505,18.013615694455,2,1,18 +2025-03-11T12:39:50.795593,479392792,65451,198,-8.43604139548,-20.332764634035,17.49911661796,2,1,18 +2025-03-11T12:39:50.811218,479392792,65451,198,-8.14389760504,-20.05037376888,16.97075038624,2,1,18 +2025-03-11T12:39:50.826843,479392792,65451,198,-7.84232982136,-19.76334552597,16.44235205251,2,1,18 +2025-03-11T12:39:50.842468,479392792,65451,198,-7.5454740343,-19.4717043642,15.923184325915,2,1,18 +2025-03-11T12:39:50.858093,479392792,65451,198,-7.2627542371,-19.170845517675,15.39013631314,2,1,18 +2025-03-11T12:39:50.873718,479392792,65451,198,-6.98474643652,-18.87461589594,14.843250072175,2,1,18 +2025-03-11T12:39:50.889343,479392792,65451,198,-6.68317865284,-18.573724437555,14.296311386185,2,1,18 +2025-03-11T12:39:50.904968,479392792,65451,198,-6.38632286578,-18.28670434761,13.754056284265,2,1,18 +2025-03-11T12:39:50.920593,479392792,65451,198,-6.09417907534,-18.00893455428,13.244193324805,2,1,18 +2025-03-11T12:39:50.936218,479392792,65451,198,-5.8020352849,-17.70343833,12.724976759215,2,1,18 +2025-03-11T12:39:50.951843,479392792,65451,198,-5.51460349108,-17.397950258685,12.182661059305,2,1,18 +2025-03-11T12:39:50.967468,479392792,65451,198,-5.21774770402,-17.115551240565,11.621939765125,2,1,18 +2025-03-11T12:39:50.983093,479392792,65451,198,-4.92089191696,-16.833152222445,11.079703203205,2,1,18 +2025-03-11T12:39:50.998718,479392792,65451,198,-4.6240361299,-16.523026773375,10.55121895048,2,1,18 +2025-03-11T12:39:51.014343,479392792,65451,198,-4.33189233946,-16.23139376457,10.0043309065,2,1,18 +2025-03-11T12:39:51.029968,479392792,65451,198,-4.0350365524,-15.93051045915,9.466641367645,2,1,18 +2025-03-11T12:39:51.045593,479392792,65451,198,-3.73346876872,-15.629619000765,8.928945047785,2,1,18 +2025-03-11T12:39:51.061218,479392792,65451,198,-3.4460369749,-15.347236288575,8.39134323094,2,1,18 +2025-03-11T12:39:51.076843,479392792,65451,198,-3.15389318446,-15.06484542342,7.84449226696,2,1,18 +2025-03-11T12:39:51.092468,479392792,65451,198,-2.86174939402,-14.754728127315,7.29753006298,2,1,18 +2025-03-11T12:39:51.108093,479392792,65451,198,-2.5507576171,-14.467683578475,6.764496984175,2,1,18 +2025-03-11T12:39:51.123718,479392792,65451,198,-2.2444778368,-14.1621628953,6.23601770944,2,1,18 +2025-03-11T12:39:51.139343,479392792,65451,198,-1.94762204974,-13.865900661705,5.69372552752,2,1,18 +2025-03-11T12:39:51.154968,479392792,65451,198,-1.66961424916,-13.56042889632,5.16066575575,2,1,18 +2025-03-11T12:39:51.170593,479392792,65451,198,-1.38689445196,-13.23646469067,4.63214622604,2,1,18 +2025-03-11T12:39:51.186218,479392792,65451,198,-1.08532666828,-12.95867859141,4.09454260618,2,1,18 +2025-03-11T12:39:51.201843,479392792,65451,198,-0.7837588846,-12.694755707625,3.54775224019,2,1,18 +2025-03-11T12:39:51.217468,479392792,65451,198,-0.49632709078,-12.38926763631,3.010057723345,2,1,18 +2025-03-11T12:39:51.233093,479392792,65451,198,-0.20418330034,-12.08377141203,2.463114059365,2,1,18 +2025-03-11T12:39:51.248718,479392792,65451,198,0.0973844833399998,-11.782879953645,1.91155419031,2,1,18 +2025-03-11T12:39:51.264343,479392792,65451,198,0.39895226702,-11.47274635161,1.369199607385,2,1,18 +2025-03-11T12:39:51.279968,479392792,65451,198,0.7005200507,-11.17647596505,0.79917354607,2,1,18 +2025-03-11T12:39:51.295593,479392792,65451,198,0.99737583776,-10.870971587805,0.252223101085,2,1,18 +2025-03-11T12:39:51.311218,479392792,65451,198,1.30836761468,-10.565442751665,-0.271641771590001,2,1,18 +2025-03-11T12:39:51.326843,479392792,65451,198,1.60051140512,-10.250704383735,-0.81862251557,2,1,18 +2025-03-11T12:39:51.342468,479392792,65451,198,1.90679118542,-9.95442584421,-1.37941299176,2,1,18 +2025-03-11T12:39:51.358093,479392792,65451,198,2.21307096572,-9.667389448335,-1.93092402182,2,1,18 +2025-03-11T12:39:51.373718,479392792,65451,198,2.4910787663,-9.3711598266,-2.487052628915,2,1,18 +2025-03-11T12:39:51.389343,479392792,65451,198,2.78793455336,-9.065655449355,-3.0340030739,2,1,18 +2025-03-11T12:39:51.404968,479392792,65451,198,3.09892633028,-8.74626339774,-3.56254474964,2,1,18 +2025-03-11T12:39:51.420593,479392792,65451,198,3.40520611058,-8.459227001865,-4.118676962765,2,1,18 +2025-03-11T12:39:51.436218,479392792,65451,198,3.69734990102,-8.16759399306,-4.65170145755,2,1,18 +2025-03-11T12:39:51.451843,479392792,65451,198,3.99420568808,-7.852847472165,-5.19406779947,2,1,18 +2025-03-11T12:39:51.467468,479392792,65451,198,4.30048546838,-7.56581107629,-5.759442378725,2,1,18 +2025-03-11T12:39:51.483093,479392792,65451,198,4.6114772453,-7.2695243838,-6.315618452855,2,1,18 +2025-03-11T12:39:51.498718,479392792,65451,198,4.90833303236,-6.96864107838,-6.857929174775,2,1,18 +2025-03-11T12:39:51.514343,479392792,65451,198,5.18162883632,-6.677040681435,-7.40016891167,2,1,18 +2025-03-11T12:39:51.529968,479392792,65451,198,5.46906063014,-6.376173681945,-7.93322370545,2,1,18 +2025-03-11T12:39:51.545593,479392792,65451,198,5.7894764003,-6.061386396225,-8.47100276933,2,1,18 +2025-03-11T12:39:51.561218,479392792,65451,198,6.10518017384,-5.75584940712,-9.027222704465,2,1,18 +2025-03-11T12:39:51.576843,479392792,65451,198,6.40674795752,-5.46882116421,-9.56948458739,2,1,18 +2025-03-11T12:39:51.592468,479392792,65451,198,6.68946775472,-5.167962317685,-10.121017332425,2,1,18 +2025-03-11T12:39:51.608093,479392792,65451,198,6.98632354178,-4.86245794044,-10.672588960475,2,1,18 +2025-03-11T12:39:51.623718,479392792,65451,198,7.28789132546,-4.57542969753,-11.22409320953,2,1,18 +2025-03-11T12:39:51.639343,479392792,65451,198,7.59888310238,-4.27914300504,-11.78026928366,2,1,18 +2025-03-11T12:39:51.654968,479392792,65451,198,7.91458687592,-3.964363872285,-12.34114748186,2,1,18 +2025-03-11T12:39:51.670593,479392792,65451,198,8.22086665622,-3.66808533276,-12.888074408855,2,1,18 +2025-03-11T12:39:51.686218,479392792,65451,198,8.50358645342,-3.37184755806,-13.425725064695,2,1,18 +2025-03-11T12:39:51.701843,479392792,65451,198,8.8051542371,-3.070956099675,-13.94955783536,2,1,18 +2025-03-11T12:39:51.717468,479392792,65451,198,9.09729802754,-2.746975588095,-14.473469744015,2,1,18 +2025-03-11T12:39:51.733093,479392792,65451,198,9.38001782474,-2.44611674157,-15.01576012292,2,1,18 +2025-03-11T12:39:51.748718,479392792,65451,198,9.67216161518,-2.14986266094,-15.54418197464,2,1,18 +2025-03-11T12:39:51.764343,479392792,65451,198,9.96430540562,-1.867471795785,-16.10027530475,2,1,18 +2025-03-11T12:39:51.779968,479392792,65451,198,10.26116119268,-1.566588490365,-16.647207209735,2,1,18 +2025-03-11T12:39:51.795593,479392792,65451,198,10.55801697974,-1.27032625677,-17.171014659395,2,1,18 +2025-03-11T12:39:51.811218,479392792,65451,198,10.8548727668,-0.974064023175,-17.722549207445,2,1,18 +2025-03-11T12:39:51.826843,479392792,65451,198,11.1611525471,-0.66854334,-18.292619129765,2,1,18 +2025-03-11T12:39:51.842468,479392792,65451,198,11.46272033078,-0.37227295344,-18.81643336043,2,1,18 +2025-03-11T12:39:51.858093,479392792,65451,198,11.75957611784,-0.0852528634950005,-19.34020373009,2,1,18 +2025-03-11T12:39:51.873718,479392792,65451,198,12.06114390152,0.197154307590001,-19.87782588995,2,1,18 +2025-03-11T12:39:51.889343,479392792,65451,198,12.3627116852,0.4841825505,-20.420087772875,2,1,18 +2025-03-11T12:39:51.904968,479392792,65451,198,12.65956747226,0.78506585592,-20.962398494795,2,1,18 +2025-03-11T12:39:51.920593,479392792,65451,198,12.9517112627,1.085941008375,-21.48621770345,2,1,18 +2025-03-11T12:39:51.936218,479392792,65451,198,13.24385505314,1.38681616083,-22.028521644365,2,1,18 +2025-03-11T12:39:51.951843,479392792,65451,198,13.54542283682,1.678465475565,-22.575423250355,2,1,18 +2025-03-11T12:39:51.967468,479392792,65451,198,13.8234306374,1.9746950973,-23.108445942125,2,1,18 +2025-03-11T12:39:51.983093,479392792,65451,198,14.1061504346,2.270932872,-23.636854231835,2,1,18 +2025-03-11T12:39:51.998718,479392792,65451,198,14.39829422504,2.56718695263,-24.174518449685,2,1,18 +2025-03-11T12:39:52.014343,479392792,65451,198,14.6951500121,2.863449186225,-24.698325899345,2,1,18 +2025-03-11T12:39:52.029968,479392792,65451,198,14.98258180592,3.15045297024,-25.222082706995,2,1,18 +2025-03-11T12:39:52.045593,479392792,65451,198,15.25587760988,3.442053367185,-25.74583771163,2,1,18 +2025-03-11T12:39:52.061218,479392792,65451,198,15.53388541046,3.71979870162,-26.2787862434,2,1,18 +2025-03-11T12:39:52.076843,479392792,65451,198,15.82131720428,4.016044629285,-26.80258013105,2,1,18 +2025-03-11T12:39:52.092468,479392792,65451,198,16.10403700148,4.29841918851,-27.32169043463,2,1,18 +2025-03-11T12:39:52.108093,479392792,65451,198,16.39618079192,4.571567910015,-27.84077722022,2,1,18 +2025-03-11T12:39:52.123718,479392792,65451,198,16.69303657898,4.85858799996,-28.38303232214,2,1,18 +2025-03-11T12:39:52.139343,479392792,65451,198,16.98989236604,5.154850233555,-28.920703320995,2,1,18 +2025-03-11T12:39:52.154968,479392792,65451,198,17.26790016662,5.45107985529,-29.4491048297,2,1,18 +2025-03-11T12:39:52.170593,479392792,65451,198,17.53648397396,5.747293171095,-29.968250410265,2,1,18 +2025-03-11T12:39:52.186218,479392792,65451,198,17.8286277644,6.0389261799,-30.46430544053,2,1,18 +2025-03-11T12:39:52.201843,479392792,65451,198,18.11605955822,6.31206674844,-30.983385445115,2,1,18 +2025-03-11T12:39:52.217468,479392792,65451,198,18.39877935542,6.58982023584,-31.511719574825,2,1,18 +2025-03-11T12:39:52.233093,479392792,65451,198,18.67207515938,6.85831527366,-32.03538187946,2,1,18 +2025-03-11T12:39:52.248718,479392792,65451,198,18.95008295996,7.136060608095,-32.53136094671,2,1,18 +2025-03-11T12:39:52.264343,479392792,65451,198,19.22809076054,7.418427014355,-33.02735855396,2,1,18 +2025-03-11T12:39:52.279968,479392792,65451,198,19.51552255436,7.71467294202,-33.54191007548,2,1,18 +2025-03-11T12:39:52.295593,479392792,65451,198,19.8076663448,8.01092702265,-34.037983645745,2,1,18 +2025-03-11T12:39:52.311218,479392792,65451,198,20.08567414538,8.288672357085,-34.533962712995,2,1,18 +2025-03-11T12:39:52.326843,479392792,65451,198,20.36839394258,8.57104691631,-35.03920946738,2,1,18 +2025-03-11T12:39:52.342468,479392792,65451,198,20.64640174316,8.85341332257,-35.55369180689,2,1,18 +2025-03-11T12:39:52.358093,479392792,65451,198,20.9149855505,9.1357634229,-36.06816058439,2,1,18 +2025-03-11T12:39:52.373718,479392792,65451,198,21.18356935784,9.40887137958,-36.587213464955,2,1,18 +2025-03-11T12:39:52.389343,479392792,65451,198,21.4568651618,9.681987489225,-37.10165194346,2,1,18 +2025-03-11T12:39:52.404968,479392792,65451,198,21.739584959,9.959740976625,-37.60225897478,2,1,18 +2025-03-11T12:39:52.420593,479392792,65451,198,22.02701675282,10.23750261699,-38.09825160404,2,1,18 +2025-03-11T12:39:52.436218,479392792,65451,198,22.3050245534,10.506005807775,-38.589572408225,2,1,18 +2025-03-11T12:39:52.451843,479392792,65451,198,22.58303235398,10.78375114221,-39.085551475475,2,1,18 +2025-03-11T12:39:52.467468,479392792,65451,198,22.85161616132,11.06610124254,-39.600020252975,2,1,18 +2025-03-11T12:39:52.483093,479392792,65451,198,23.12019996866,11.31148276827,-40.095855978215,2,1,18 +2025-03-11T12:39:52.498718,479392792,65451,198,23.39349577262,11.593841021565,-40.5733620722,2,1,18 +2025-03-11T12:39:52.514343,479392792,65451,198,23.67621556982,11.86697343714,-41.069329380455,2,1,18 +2025-03-11T12:39:52.529968,479392792,65451,198,23.94008738054,12.11696788173,-41.55593449856,2,1,18 +2025-03-11T12:39:52.545593,479392792,65451,198,24.18511120478,12.408519360885,-42.033436986515,2,1,18 +2025-03-11T12:39:52.561218,479392792,65451,198,24.45369501212,12.681627317565,-42.510899219495,2,1,18 +2025-03-11T12:39:52.576843,479392792,65451,198,24.73641480932,12.96400187679,-43.00690360775,2,1,18 +2025-03-11T12:39:52.592468,479392792,65451,198,24.99557462342,13.22785138389,-43.507421114045,2,1,18 +2025-03-11T12:39:52.608093,479392792,65451,198,25.25944643414,13.482466900305,-43.989423589085,2,1,18 +2025-03-11T12:39:52.623718,479392792,65451,198,25.52803024148,13.73246949786,-44.466793122065,2,1,18 +2025-03-11T12:39:52.639343,479392792,65451,198,25.7919020522,14.0101903734,-44.958130663235,2,1,18 +2025-03-11T12:39:52.654968,479392792,65451,198,26.06048585954,14.278677258255,-45.435574356215,2,1,18 +2025-03-11T12:39:52.670593,479392792,65451,198,26.31964567364,14.533284621705,-45.922191233315,2,1,18 +2025-03-11T12:39:52.686218,479392792,65451,198,26.58351748436,14.77865799447,-46.39953544529,2,1,18 +2025-03-11T12:39:52.701843,479392792,65451,198,26.8285413086,15.042483042675,-46.83533604566,2,1,18 +2025-03-11T12:39:52.717468,479392792,65451,198,27.08298912608,15.29708225316,-47.303461409495,2,1,18 +2025-03-11T12:39:52.733093,479392792,65451,198,27.3468609368,15.5378345541,-47.78078708147,2,1,18 +2025-03-11T12:39:52.748718,479392792,65451,198,27.60130875428,15.78781269276,-48.230409173045,2,1,18 +2025-03-11T12:39:52.764343,479392792,65451,198,27.85575657176,16.05627511872,-48.684726607685,2,1,18 +2025-03-11T12:39:52.779968,479392792,65451,198,28.11491638586,16.324745697645,-49.143672006395,2,1,18 +2025-03-11T12:39:52.795593,479392792,65451,198,28.36936420334,16.583965979955,-49.616437093295,2,1,18 +2025-03-11T12:39:52.811218,479392792,65451,198,28.62381202082,16.83856519044,-50.079941274065,2,1,18 +2025-03-11T12:39:52.826843,479392792,65451,198,28.88768383154,17.08855963503,-50.543440476845,2,1,18 +2025-03-11T12:39:52.842468,479392792,65451,198,29.13270765578,17.343142539585,-50.988446363345,2,1,18 +2025-03-11T12:39:52.858093,479392792,65451,198,29.36359549016,17.59307991342,-51.438034549895,2,1,18 +2025-03-11T12:39:52.873718,479392792,65451,198,29.6086193144,17.829178530675,-51.87834509333,2,1,18 +2025-03-11T12:39:52.889343,479392792,65451,198,29.85835513526,18.06990637272,-52.31868095777,2,1,18 +2025-03-11T12:39:52.904968,479392792,65451,198,30.09866696288,18.310617908835,-52.763624443265,2,1,18 +2025-03-11T12:39:52.920593,479392792,65451,198,30.3389787905,18.555950516775,-53.222450017955,2,1,18 +2025-03-11T12:39:52.936218,479392792,65451,198,30.57929061812,18.810525268365,-53.672070306515,2,1,18 +2025-03-11T12:39:52.951843,479392792,65451,198,30.82902643898,19.055874182235,-54.112424710955,2,1,18 +2025-03-11T12:39:52.967468,479392792,65451,198,31.0693382666,19.301206790175,-54.53890200419,2,1,18 +2025-03-11T12:39:52.983093,479392792,65451,198,31.3049380976,19.52804695785,-54.979161905615,2,1,18 +2025-03-11T12:39:52.998718,479392792,65451,198,31.5405379286,19.764129269175,-55.424080070105,2,1,18 +2025-03-11T12:39:53.014343,479392792,65451,198,31.78084975622,20.009461877115,-55.84131499721,2,1,18 +2025-03-11T12:39:53.029968,479392792,65451,198,32.0117375906,20.245536035475,-56.2723628315,2,1,18 +2025-03-11T12:39:53.045593,479392792,65451,198,32.24262542498,20.463125906535,-56.71257887192,2,1,18 +2025-03-11T12:39:53.061218,479392792,65451,198,32.47351325936,20.699200064895,-57.129763157015,2,1,18 +2025-03-11T12:39:53.076843,479392792,65451,198,32.70440109374,20.93989529508,-57.53772361598,2,1,18 +2025-03-11T12:39:53.092468,479392792,65451,198,32.94000092474,21.175977606405,-57.96415704821,2,1,18 +2025-03-11T12:39:53.108093,479392792,65451,198,33.17088875912,21.40743069294,-58.37670161024,2,1,18 +2025-03-11T12:39:53.123718,479392792,65451,198,33.40648859012,21.625028716965,-58.78457615021,2,1,18 +2025-03-11T12:39:53.139343,479392792,65451,198,33.6373764245,21.84723965985,-59.19708363224,2,1,18 +2025-03-11T12:39:53.154968,479392792,65451,198,33.85412826902,22.074047215665,-59.618831677385,2,1,18 +2025-03-11T12:39:53.170593,479392792,65451,198,34.08030410678,22.305492149235,-60.045233007605,2,1,18 +2025-03-11T12:39:53.186218,479392792,65451,198,34.31119194116,22.523082020295,-60.439237217375,2,1,18 +2025-03-11T12:39:53.201843,479392792,65451,198,34.52794378568,22.736026360635,-60.828581361065,2,1,18 +2025-03-11T12:39:53.217468,479392792,65451,198,34.73527163696,22.96281761052,-61.22258874581,2,1,18 +2025-03-11T12:39:53.233093,479392792,65451,198,34.94731148486,23.175753797895,-61.639653206885,2,1,18 +2025-03-11T12:39:53.248718,479392792,65451,198,35.17348732262,23.397956587815,-62.038290358715,2,1,18 +2025-03-11T12:39:53.264343,479392792,65451,198,35.38552717052,23.62013491884,-62.423043618335,2,1,18 +2025-03-11T12:39:53.279968,479392792,65451,198,35.59756701842,23.84693432169,-62.81243660102,2,1,18 +2025-03-11T12:39:53.295593,479392792,65451,198,35.81431886294,24.05063651838,-63.215607213905,2,1,18 +2025-03-11T12:39:53.311218,479392792,65451,198,36.02164671422,24.268185624615,-63.604956335585,2,1,18 +2025-03-11T12:39:53.326843,479392792,65451,198,36.22426256888,24.485726577885,-63.99429867626,2,1,18 +2025-03-11T12:39:53.342468,479392792,65451,198,36.42687842354,24.68940431568,-64.383585396935,2,1,18 +2025-03-11T12:39:53.358093,479392792,65451,198,36.6294942782,24.902324197125,-64.75442446535,2,1,18 +2025-03-11T12:39:53.373718,479392792,65451,198,36.84624612272,25.09216317834,-65.129812359845,2,1,18 +2025-03-11T12:39:53.389343,479392792,65451,198,37.06299796724,25.291244303205,-65.500616151275,2,1,18 +2025-03-11T12:39:53.404968,479392792,65451,198,37.27032581852,25.513414481265,-65.871499080695,2,1,18 +2025-03-11T12:39:53.420593,479392792,65451,198,37.48236566642,25.73559281229,-66.25163115725,2,1,18 +2025-03-11T12:39:53.436218,479392792,65451,198,37.69911751094,25.93005286533,-66.608552859485,2,1,18 +2025-03-11T12:39:53.451843,479392792,65451,198,37.88759737574,26.11522185693,-66.97463916182,2,1,18 +2025-03-11T12:39:53.467468,479392792,65451,198,38.07136524392,26.309624839215,-67.336134580085,2,1,18 +2025-03-11T12:39:53.483093,479392792,65451,198,38.26926910196,26.513294424045,-67.679202689105,2,1,18 +2025-03-11T12:39:53.498718,479392792,65451,198,38.44832497352,26.707689253365,-68.0360701433,2,1,18 +2025-03-11T12:39:53.514343,479392792,65451,198,38.63680483832,26.902100388615,-68.383708793375,2,1,18 +2025-03-11T12:39:53.529968,479392792,65451,198,38.83470869636,27.09190675797,-68.745206014655,2,1,18 +2025-03-11T12:39:53.545593,479392792,65451,198,39.03732455102,27.277100208465,-69.092827927745,2,1,18 +2025-03-11T12:39:53.561218,479392792,65451,198,39.22580441582,27.46689027189,-69.408099756365,2,1,18 +2025-03-11T12:39:53.576843,479392792,65451,198,39.41899627724,27.66593063193,-69.73265781212,2,1,18 +2025-03-11T12:39:53.592468,479392792,65451,198,39.5980521488,27.84184117395,-70.061724007925,2,1,18 +2025-03-11T12:39:53.608093,479392792,65451,198,39.78182001698,28.017759868935,-70.40466053393,2,1,18 +2025-03-11T12:39:53.623718,479392792,65451,198,39.9514518953,28.19827517685,-70.73835289079,2,1,18 +2025-03-11T12:39:53.639343,479392792,65451,198,40.12579577024,28.383419709555,-71.05820701946,2,1,18 +2025-03-11T12:39:53.654968,479392792,65451,198,40.30013964518,28.573185314085,-71.37807968813,2,1,18 +2025-03-11T12:39:53.670593,479392792,65451,198,40.47919551674,28.75371692793,-71.716406790065,2,1,18 +2025-03-11T12:39:53.686218,479392792,65451,198,40.66296338492,28.92501455109,-72.04084004381,2,1,18 +2025-03-11T12:39:53.701843,479392792,65451,198,40.84201925648,29.096304021285,-72.34678178429,2,1,18 +2025-03-11T12:39:53.717468,479392792,65451,198,41.02578712466,29.258359500795,-72.65731440884,2,1,18 +2025-03-11T12:39:53.733093,479392792,65451,198,41.19541900298,29.42963266506,-72.977106136505,2,1,18 +2025-03-11T12:39:53.748718,479392792,65451,198,41.36033888468,29.596276604535,-73.28300899397,2,1,18 +2025-03-11T12:39:53.764343,479392792,65451,198,41.52525876638,29.767541615835,-73.588930391435,2,1,18 +2025-03-11T12:39:53.779968,479392792,65451,198,41.68075465484,29.920306033905,-73.899385249955,2,1,18 +2025-03-11T12:39:53.795593,479392792,65451,198,41.84567453654,30.08694997338,-74.21453047355,2,1,18 +2025-03-11T12:39:53.811218,479392792,65451,198,42.001170425,30.25819867875,-74.50657475981,2,1,18 +2025-03-11T12:39:53.826843,479392792,65451,198,42.15195431684,30.420197087505,-74.780090452805,2,1,18 +2025-03-11T12:39:53.842468,479392792,65451,198,42.31216220192,30.58221180219,-75.05361970781,2,1,18 +2025-03-11T12:39:53.858093,479392792,65451,198,42.49121807348,30.73963805691,-75.35950582829,2,1,18 +2025-03-11T12:39:53.873718,479392792,65451,198,42.65142595856,30.892410627945,-75.66534628475,2,1,18 +2025-03-11T12:39:53.889343,479392792,65451,198,42.79278585716,31.049771658945,-75.93420869267,2,1,18 +2025-03-11T12:39:53.904968,479392792,65451,198,42.943569749,31.20252792405,-76.207687305665,2,1,18 +2025-03-11T12:39:53.920593,479392792,65451,198,43.1084896307,31.3460665044,-76.490391547805,2,1,18 +2025-03-11T12:39:53.936218,479392792,65451,198,43.25927352254,31.489580625855,-76.768454263865,2,1,18 +2025-03-11T12:39:53.951843,479392792,65451,198,43.41005741438,31.63309474731,-77.04189579686,2,1,18 +2025-03-11T12:39:53.967468,479392792,65451,198,43.54670531636,31.771963338045,-77.31529844684,2,1,18 +2025-03-11T12:39:53.983093,479392792,65451,198,43.68335321834,31.92931621608,-77.565669341495,2,1,18 +2025-03-11T12:39:53.998657,479392796,65447,199,43.82000112032,32.07280587864,-77.79749988389,2,1,18 +2025-03-11T12:39:54.014282,479392796,65447,199,43.96136101892,32.216303694165,-78.04782193955,2,1,18 +2025-03-11T12:39:54.029907,479392796,65447,199,44.0980089209,32.3551722849,-78.3119822234,2,1,18 +2025-03-11T12:39:54.045532,479392796,65447,199,44.22523282964,32.49864564153,-78.580768668305,2,1,18 +2025-03-11T12:39:54.061157,479392796,65447,199,44.357168735,32.619021792,-78.812499729695,2,1,18 +2025-03-11T12:39:54.076782,479392796,65447,199,44.4985286336,32.7578985357,-79.04893969616,2,1,18 +2025-03-11T12:39:54.092407,479392796,65447,199,44.63046453896,32.90600111712,-79.29002436368,2,1,18 +2025-03-11T12:39:54.108032,479392796,65447,199,44.77653643418,33.035643870135,-79.531055214215,2,1,18 +2025-03-11T12:39:54.123657,479392796,65447,199,44.91789633278,33.15141525471,-79.762781297615,2,1,18 +2025-03-11T12:39:54.139282,479392796,65447,199,45.04512024152,33.271783252215,-79.994505578,2,1,18 +2025-03-11T12:39:54.154907,479392796,65447,199,45.16292015702,33.396756015615,-80.22161365331,2,1,18 +2025-03-11T12:39:54.170532,479392796,65447,199,45.26658408266,33.526325391945,-80.439477559475,2,1,18 +2025-03-11T12:39:54.186157,479392796,65447,199,45.38438399816,33.651298155345,-80.68044918398,2,1,18 +2025-03-11T12:39:54.201782,479392796,65447,199,45.5116079069,33.77166615285,-80.893688732105,2,1,18 +2025-03-11T12:39:54.217407,479392796,65447,199,45.62469582578,33.88276754781,-81.106870857215,2,1,18 +2025-03-11T12:39:54.233032,479392796,65447,199,45.74249574128,33.993877095735,-81.30157503107,2,1,18 +2025-03-11T12:39:54.248657,479392796,65447,199,45.85558366016,34.114220634345,-81.50555187005,2,1,18 +2025-03-11T12:39:54.264282,479392796,65447,199,45.96867157904,34.22994310113,-81.723373718225,2,1,18 +2025-03-11T12:39:54.279907,479392796,65447,199,46.09118349116,34.345681873845,-81.936587945345,2,1,18 +2025-03-11T12:39:54.295532,479392796,65447,199,46.19955941342,34.442911900365,-82.126601754125,2,1,18 +2025-03-11T12:39:54.311157,479392796,65447,199,46.30322333906,34.54937591757,-82.3166458619,2,1,18 +2025-03-11T12:39:54.326782,479392796,65447,199,46.41159926132,34.65584808774,-82.50669675068,2,1,18 +2025-03-11T12:39:54.342407,479392796,65447,199,46.51997518358,34.766941329735,-82.682902630265,2,1,18 +2025-03-11T12:39:54.358032,479392796,65447,199,46.6189271126,34.86877612215,-82.85905786784,2,1,18 +2025-03-11T12:39:54.373657,479392796,65447,199,46.71787904162,34.961368770915,-83.035176025415,2,1,18 +2025-03-11T12:39:54.389282,479392796,65447,199,46.81211897402,35.072437554015,-83.220603928115,2,1,18 +2025-03-11T12:39:54.404907,479392796,65447,199,46.91107090304,35.17427234643,-83.410622714885,2,1,18 +2025-03-11T12:39:54.420532,479392796,65447,199,47.00059883882,35.266848689265,-83.582106127385,2,1,18 +2025-03-11T12:39:54.436157,479392796,65447,199,47.09483877122,35.359433185065,-83.739732771695,2,1,18 +2025-03-11T12:39:54.451782,479392796,65447,199,47.19379070024,35.42429940288,-83.91573968927,2,1,18 +2025-03-11T12:39:54.467407,479392796,65447,199,47.2786066394,35.521488664575,-84.0826136777,2,1,18 +2025-03-11T12:39:54.483032,479392796,65447,199,47.36813457518,35.60482286376,-84.22633291181,2,1,18 +2025-03-11T12:39:54.498657,479392796,65447,199,47.43881452448,35.697366594735,-84.37930446803,2,1,18 +2025-03-11T12:39:54.514282,479392796,65447,199,47.52834246026,35.776079722095,-84.5414898944,2,1,18 +2025-03-11T12:39:54.529907,479392796,65447,199,47.61787039604,35.85941392128,-84.69445149464,2,1,18 +2025-03-11T12:39:54.545532,479392796,65447,199,47.69797433858,35.924247527235,-84.833461823675,2,1,18 +2025-03-11T12:39:54.561157,479392796,65447,199,47.75451829802,35.998282512015,-84.963232961555,2,1,18 +2025-03-11T12:39:54.576782,479392796,65447,199,47.83462224056,36.076979333445,-85.088435361395,2,1,18 +2025-03-11T12:39:54.592407,479392796,65447,199,47.91001418648,36.15566800191,-85.21363098023,2,1,18 +2025-03-11T12:39:54.608032,479392796,65447,199,47.99483012564,36.22050976083,-85.35264809027,2,1,18 +2025-03-11T12:39:54.623657,479392796,65447,199,48.06079807832,36.28531890789,-85.468532160965,2,1,18 +2025-03-11T12:39:54.639282,479392796,65447,199,48.126766031,36.35012805495,-85.589037414725,2,1,18 +2025-03-11T12:39:54.654907,479392796,65447,199,48.19273398368,36.410316130185,-85.71414531155,2,1,18 +2025-03-11T12:39:54.670532,479392796,65447,199,48.25870193636,36.47050420542,-85.81614729305,2,1,18 +2025-03-11T12:39:54.686157,479392796,65447,199,48.31053389918,36.544531037235,-85.918184551535,2,1,18 +2025-03-11T12:39:54.701782,479392796,65447,199,48.37178985524,36.61857417498,-86.04796247042,2,1,18 +2025-03-11T12:39:54.717407,479392796,65447,199,48.42833381468,36.678745944285,-86.14995088991,2,1,18 +2025-03-11T12:39:54.733032,479392796,65447,199,48.46602978764,36.72040081443,-86.23335329312,2,1,18 +2025-03-11T12:39:54.748657,479392796,65447,199,48.53199774032,36.75748353054,-86.330641391555,2,1,18 +2025-03-11T12:39:54.764282,479392796,65447,199,48.59325369638,36.794558093685,-86.43254389205,2,1,18 +2025-03-11T12:39:54.779907,479392796,65447,199,48.62623767272,36.854689098165,-86.534498406515,2,1,18 +2025-03-11T12:39:54.795532,479392796,65447,199,48.67335763892,36.910223489715,-86.617969991735,2,1,18 +2025-03-11T12:39:54.811157,479392796,65447,199,48.7157656085,36.961128656475,-86.696795072885,2,1,18 +2025-03-11T12:39:54.826782,479392796,65447,199,48.75817357808,37.012033823235,-86.775620154035,2,1,18 +2025-03-11T12:39:54.842407,479392796,65447,199,48.80058154766,37.04907577452,-86.845147249055,2,1,18 +2025-03-11T12:39:54.858032,479392796,65447,199,48.84770151386,37.08612587877,-86.92392349121,2,1,18 +2025-03-11T12:39:54.873657,479392796,65447,199,48.89010948344,37.123167830055,-86.9842082201,2,1,18 +2025-03-11T12:39:54.889282,479392796,65447,199,48.9278054564,37.1648227002,-87.06761062331,2,1,18 +2025-03-11T12:39:54.904907,479392796,65447,199,48.97963741922,37.20650202924,-87.12792745421,2,1,18 +2025-03-11T12:39:54.920532,479392796,65447,199,49.01262139556,37.234285530945,-87.202025090285,2,1,18 +2025-03-11T12:39:54.936157,479392796,65447,199,49.03618137866,37.248189511245,-87.243705262895,2,1,18 +2025-03-11T12:39:54.951782,479392796,65447,199,49.07858934824,37.28523146253,-87.2623993442,2,1,18 +2025-03-11T12:39:54.967407,479392796,65447,199,49.0927253381,37.32684556785,-87.290313645605,2,1,18 +2025-03-11T12:39:54.983032,479392796,65447,199,49.1162853212,37.34074954815,-87.350478550475,2,1,18 +2025-03-11T12:39:54.998657,479392796,65447,199,49.14455730092,37.363903825065,-87.41068731635,2,1,18 +2025-03-11T12:39:55.014282,479392796,65447,199,49.15869329078,37.377791499435,-87.45235392695,2,1,18 +2025-03-11T12:39:55.029907,479392796,65447,199,49.1634052874,37.391662867875,-87.48476460941,2,1,18 +2025-03-11T12:39:55.045532,479392796,65447,199,49.1869652705,37.40094577635,-87.521805058955,2,1,18 +2025-03-11T12:39:55.061157,479392796,65447,199,49.19638926374,37.424067441405,-87.549638419355,2,1,18 +2025-03-11T12:39:55.076782,479392796,65447,199,49.2105252536,37.43333404395,-87.57742294076,2,1,18 +2025-03-11T12:39:55.092407,479392796,65447,199,49.21523725022,37.44720541239,-87.586727707895,2,1,18 +2025-03-11T12:39:55.108032,479392796,65447,199,49.20581325698,37.45643125011,-87.60061477508,2,1,18 +2025-03-11T12:39:55.123657,479392796,65447,199,49.20581325698,37.461052321935,-87.623739230405,2,1,18 +2025-03-11T12:39:55.139282,479392796,65447,199,49.22937324008,37.465714158585,-87.6145493093,2,1,18 +2025-03-11T12:39:55.154907,479392796,65447,199,49.2340852367,37.470343383375,-87.633059362565,2,1,18 +2025-03-11T12:39:55.170532,479392796,65447,199,49.23879723332,37.47035153634,-87.63306614357,2,1,18 +2025-03-11T12:39:55.186157,479392796,65447,199,49.23879723332,37.47959367999,-87.61461849131,2,1,18 +2025-03-11T12:39:55.201782,479392796,65447,199,49.2340852367,37.461101239725,-87.605295184175,2,1,18 +2025-03-11T12:39:55.217407,479392796,65447,199,49.22937324008,37.456472014935,-87.591406313975,2,1,18 +2025-03-11T12:39:55.233032,479392796,65447,199,49.23879723332,37.45186724904,-87.58678015292,2,1,18 +2025-03-11T12:39:55.248657,479392796,65447,199,49.2340852367,37.442616952425,-87.568251559655,2,1,18 +2025-03-11T12:39:55.264282,479392796,65447,199,49.21994924684,37.42410820623,-87.554293507445,2,1,18 +2025-03-11T12:39:55.279907,479392796,65447,199,49.20110126036,37.400970235245,-87.544931317295,2,1,18 +2025-03-11T12:39:55.295532,479392796,65447,199,49.17754127726,37.40092947042,-87.50792794775,2,1,18 +2025-03-11T12:39:55.311157,479392796,65447,199,49.14455730092,37.38700918419,-87.47547657926,2,1,18 +2025-03-11T12:39:55.326782,479392796,65447,199,49.1162853212,37.3684759791,-87.44763463484,2,1,18 +2025-03-11T12:39:55.342407,479392796,65447,199,49.09743733472,37.35920122359,-87.396737417105,2,1,18 +2025-03-11T12:39:55.358032,479392796,65447,199,49.08801334148,37.33145848671,-87.341158418315,2,1,18 +2025-03-11T12:39:55.373657,479392796,65447,199,49.05031736852,37.299045760215,-87.30862610882,2,1,18 +2025-03-11T12:39:55.389282,479392796,65447,199,49.02675738542,37.248173205315,-87.271418799275,2,1,18 +2025-03-11T12:39:55.404907,479392796,65447,199,48.9984854057,37.220397856575,-87.215812676465,2,1,18 +2025-03-11T12:39:55.420532,479392796,65447,199,48.97021342598,37.201864651485,-87.141758901395,2,1,18 +2025-03-11T12:39:55.436157,479392796,65447,199,48.93722944964,37.178702221605,-87.081543354515,2,1,18 +2025-03-11T12:39:55.451782,479392796,65447,199,48.9042454733,37.137055504425,-87.01663246457,2,1,18 +2025-03-11T12:39:55.467407,479392796,65447,199,48.87126149696,37.10002985907,-86.942497748495,2,1,18 +2025-03-11T12:39:55.483032,479392796,65447,199,48.833565524,37.06299606075,-86.868356251415,2,1,18 +2025-03-11T12:39:55.498657,479392796,65447,199,48.79115755442,37.02133303764,-86.789568250265,2,1,18 +2025-03-11T12:39:55.514282,479392796,65447,199,48.75817357808,36.97044417681,-86.72462028032,2,1,18 +2025-03-11T12:39:55.529907,479392796,65447,199,48.73461359498,36.91957162191,-86.63657995706,2,1,18 +2025-03-11T12:39:55.545532,479392796,65447,199,48.68749362878,36.85479508671,-86.539207742645,2,1,18 +2025-03-11T12:39:55.561157,479392796,65447,199,48.6215256761,36.813091298775,-86.46038583647,2,1,18 +2025-03-11T12:39:55.576782,479392796,65447,199,48.56498171666,36.77140381677,-86.363092760045,2,1,18 +2025-03-11T12:39:55.592407,479392796,65447,199,48.51786175046,36.720490497045,-86.270397348695,2,1,18 +2025-03-11T12:39:55.608032,479392796,65447,199,48.47074178426,36.66033503367,-86.16380130815,2,1,18 +2025-03-11T12:39:55.623657,479392796,65447,199,48.41890982144,36.59092927368,-86.0571614066,2,1,18 +2025-03-11T12:39:55.639282,479392796,65447,199,48.35294186876,36.52612012662,-85.969004434295,2,1,18 +2025-03-11T12:39:55.654907,479392796,65447,199,48.2916859127,36.46594020435,-85.8670092338,2,1,18 +2025-03-11T12:39:55.670532,479392796,65447,199,48.23514195326,36.405768435045,-85.751157265115,2,1,18 +2025-03-11T12:39:55.686157,479392796,65447,199,48.1738859972,36.345588512775,-85.6121926001,2,1,18 +2025-03-11T12:39:55.701782,479392796,65447,199,48.10791804452,36.271537222065,-85.496271449405,2,1,18 +2025-03-11T12:39:55.717407,479392796,65447,199,48.04666208846,36.20673622797,-85.39425770891,2,1,18 +2025-03-11T12:39:55.733032,479392796,65447,199,47.97127014254,36.146531846805,-85.250651517815,2,1,18 +2025-03-11T12:39:55.748657,479392796,65447,199,47.90059019324,36.067851331305,-85.09311439853,2,1,18 +2025-03-11T12:39:55.764282,479392796,65447,199,47.83462224056,35.97993682512,-84.949410529445,2,1,18 +2025-03-11T12:39:55.779907,479392796,65447,199,47.7498063014,35.901231850725,-84.81495898247,2,1,18 +2025-03-11T12:39:55.795532,479392796,65447,199,47.66970235886,35.83639824477,-84.675948653435,2,1,18 +2025-03-11T12:39:55.811157,479392796,65447,199,47.58017442308,35.76692726106,-84.53690622239,2,1,18 +2025-03-11T12:39:55.826782,479392796,65447,199,47.50007048054,35.67898829598,-84.40242437642,2,1,18 +2025-03-11T12:39:55.842407,479392796,65447,199,47.41054254476,35.586411953145,-84.254046879245,2,1,18 +2025-03-11T12:39:55.858032,479392796,65447,199,47.33043860222,35.50309405989,-84.11496239021,2,1,18 +2025-03-11T12:39:55.873657,479392796,65447,199,47.2550466563,35.4197843196,-83.97588468218,2,1,18 +2025-03-11T12:39:55.889282,479392796,65447,199,47.16551872052,35.336450120415,-83.81368071581,2,1,18 +2025-03-11T12:39:55.904907,479392796,65447,199,47.08070278136,35.24850300237,-83.642222624315,2,1,18 +2025-03-11T12:39:55.920532,479392796,65447,199,46.98646284896,35.16516065022,-83.484633060005,2,1,18 +2025-03-11T12:39:55.936157,479392796,65447,199,46.88751091994,35.072568001455,-83.33624200082,2,1,18 +2025-03-11T12:39:55.951782,479392796,65447,199,46.79798298416,34.96150737132,-83.15544206219,2,1,18 +2025-03-11T12:39:55.967407,479392796,65447,199,46.69903105514,34.868914722555,-82.96546035542,2,1,18 +2025-03-11T12:39:55.983032,479392796,65447,199,46.60479112274,34.767088083105,-82.775448349655,2,1,18 +2025-03-11T12:39:55.998657,479392796,65447,199,46.50583919372,34.669874362515,-82.58082691982,2,1,18 +2025-03-11T12:39:56.014282,479392796,65447,199,46.4068872647,34.572660641925,-82.395447856115,2,1,18 +2025-03-11T12:39:56.029907,479392796,65447,199,46.30793533568,34.456962634035,-82.186888717085,2,1,18 +2025-03-11T12:39:56.045532,479392796,65447,199,46.1948474168,34.336619095425,-82.00601779343,2,1,18 +2025-03-11T12:39:56.061157,479392796,65447,199,46.08647149454,34.220904781605,-81.802066275455,2,1,18 +2025-03-11T12:39:56.076782,479392796,65447,199,45.9828075689,34.10519862075,-81.598121538485,2,1,18 +2025-03-11T12:39:56.092407,479392796,65447,199,45.87443164664,33.994105378755,-81.39418856051,2,1,18 +2025-03-11T12:39:56.108032,479392796,65447,199,45.75663173114,33.88299583083,-81.18562083746,2,1,18 +2025-03-11T12:39:56.123657,479392796,65447,199,45.6294078224,33.762627833325,-80.96776010627,2,1,18 +2025-03-11T12:39:56.139282,479392796,65447,199,45.50689591028,33.65613120426,-80.75458295915,2,1,18 +2025-03-11T12:39:56.154907,479392796,65447,199,45.37967200154,33.54038427858,-80.541361951025,2,1,18 +2025-03-11T12:39:56.170532,479392796,65447,199,45.26187208604,33.39692722788,-80.30955853265,2,1,18 +2025-03-11T12:39:56.186157,479392796,65447,199,45.13936017392,33.281188455165,-80.073238390205,2,1,18 +2025-03-11T12:39:56.201782,479392796,65447,199,45.01213626518,33.146957242185,-79.846079672885,2,1,18 +2025-03-11T12:39:56.217407,479392796,65447,199,44.89433634968,33.02660555061,-79.61436895451,2,1,18 +2025-03-11T12:39:56.233032,479392796,65447,199,44.77182443756,32.901624634245,-79.39187528126,2,1,18 +2025-03-11T12:39:56.248657,479392796,65447,199,44.63517653558,32.758134971685,-79.141560006605,2,1,18 +2025-03-11T12:39:56.264282,479392796,65447,199,44.4985286336,32.623887452775,-78.886660628885,2,1,18 +2025-03-11T12:39:56.279907,479392796,65447,199,44.36188073162,32.48501886204,-78.65484862649,2,1,18 +2025-03-11T12:39:56.295532,479392796,65447,199,44.2393688195,32.350795802025,-78.418454324045,2,1,18 +2025-03-11T12:39:56.311157,479392796,65447,199,44.11214491076,32.21194351722,-78.1681711514,2,1,18 +2025-03-11T12:39:56.326782,479392796,65447,199,43.9566490223,32.063800170975,-77.91318902966,2,1,18 +2025-03-11T12:39:56.342407,479392796,65447,199,43.80586513046,31.924907121345,-77.639766036665,2,1,18 +2025-03-11T12:39:56.358032,479392796,65447,199,43.66450523186,31.776788233995,-77.36631952568,2,1,18 +2025-03-11T12:39:56.373657,479392796,65447,199,43.52314533326,31.64253256212,-77.111413366955,2,1,18 +2025-03-11T12:39:56.389282,479392796,65447,199,43.40063342114,31.49444628663,-76.861099895315,2,1,18 +2025-03-11T12:39:56.404907,479392796,65447,199,43.26869751578,31.34634370521,-76.592288129405,2,1,18 +2025-03-11T12:39:56.420532,479392796,65447,199,43.1084896307,31.1797079187,-76.314119151335,2,1,18 +2025-03-11T12:39:56.436157,479392796,65447,199,42.95299374224,31.031564572455,-76.031409931205,2,1,18 +2025-03-11T12:39:56.451782,479392796,65447,199,42.78336186392,30.892638910965,-75.734853898865,2,1,18 +2025-03-11T12:39:56.467407,479392796,65447,199,42.62786597546,30.730632349245,-75.44746787567,2,1,18 +2025-03-11T12:39:56.483032,479392796,65447,199,42.48179408024,30.568642093455,-75.16471659755,2,1,18 +2025-03-11T12:39:56.498657,479392796,65447,199,42.32629819178,30.406635531735,-74.877330574355,2,1,18 +2025-03-11T12:39:56.514282,479392796,65447,199,42.1660903067,30.2538629607,-74.58535366709,2,1,18 +2025-03-11T12:39:56.529907,479392796,65447,199,42.01059441824,30.087235327155,-74.297949103895,2,1,18 +2025-03-11T12:39:56.545532,479392796,65447,199,41.84096253992,29.911341091065,-73.992002385425,2,1,18 +2025-03-11T12:39:56.561157,479392796,65447,199,41.66190666836,29.744672692695,-73.68145800188,2,1,18 +2025-03-11T12:39:56.576782,479392796,65447,199,41.48756279342,29.601117806415,-73.366391916275,2,1,18 +2025-03-11T12:39:56.592407,479392796,65447,199,41.32735490834,29.434482019905,-73.08360175514,2,1,18 +2025-03-11T12:39:56.608032,479392796,65447,199,41.1530110334,29.235474271725,-72.7729343726,2,1,18 +2025-03-11T12:39:56.623657,479392796,65447,199,40.99280314832,29.06421741339,-72.46701975614,2,1,18 +2025-03-11T12:39:56.639282,479392796,65447,199,40.82317127,28.89756532095,-72.15186775154,2,1,18 +2025-03-11T12:39:56.654907,479392796,65447,199,40.64411539844,28.72165477893,-71.83666510493,2,1,18 +2025-03-11T12:39:56.670532,479392796,65447,199,40.46034753026,28.55035715577,-71.530716583445,2,1,18 +2025-03-11T12:39:56.686157,479392796,65447,199,40.30013964518,28.379100297435,-71.19245368553,2,1,18 +2025-03-11T12:39:56.701782,479392796,65447,199,40.13521976348,28.19397207066,-70.867991935805,2,1,18 +2025-03-11T12:39:56.717407,479392796,65447,199,39.94202790206,28.01341599792,-70.529644490855,2,1,18 +2025-03-11T12:39:56.733032,479392796,65447,199,39.74883604064,27.85134421248,-70.182128839775,2,1,18 +2025-03-11T12:39:56.748657,479392796,65447,199,39.56035617584,27.661554149055,-69.84375109583,2,1,18 +2025-03-11T12:39:56.764282,479392796,65447,199,39.38130030428,27.47178039156,-69.505386913895,2,1,18 +2025-03-11T12:39:56.779907,479392796,65447,199,39.20695642934,27.28201478703,-69.17165069603,2,1,18 +2025-03-11T12:39:56.795532,479392796,65447,199,39.02790055778,27.082998885885,-68.83787061716,2,1,18 +2025-03-11T12:39:56.811157,479392796,65447,199,38.83470869636,26.883958525845,-68.467100730755,2,1,18 +2025-03-11T12:39:56.826782,479392796,65447,199,38.63680483832,26.680288941015,-68.11941143867,2,1,18 +2025-03-11T12:39:56.842407,479392796,65447,199,38.43418898366,26.47661120322,-67.78095773171,2,1,18 +2025-03-11T12:39:56.858032,479392796,65447,199,38.23628512562,26.28218376204,-67.40095723817,2,1,18 +2025-03-11T12:39:56.873657,479392796,65447,199,38.03838126758,26.092377392685,-67.03946001689,2,1,18 +2025-03-11T12:39:56.889282,479392796,65447,199,37.84518940616,25.893337032645,-66.66406894742,2,1,18 +2025-03-11T12:39:56.904907,479392796,65447,199,37.64728554812,25.68504637599,-66.288634016945,2,1,18 +2025-03-11T12:39:56.920532,479392796,65447,199,37.45880568332,25.486014168915,-65.936355643805,2,1,18 +2025-03-11T12:39:56.936157,479392796,65447,199,37.2656138219,25.2915948807,-65.560983114335,2,1,18 +2025-03-11T12:39:56.951782,479392796,65447,199,37.053573974,25.087900836975,-65.194788746975,2,1,18 +2025-03-11T12:39:56.967407,479392796,65447,199,36.83682212948,24.874956496635,-64.81930815248,2,1,18 +2025-03-11T12:39:56.983032,479392796,65447,199,36.6294942782,24.66664953405,-64.453102026125,2,1,18 +2025-03-11T12:39:56.998657,479392796,65447,199,36.41274243368,24.458326265535,-64.0683976055,2,1,18 +2025-03-11T12:39:57.014282,479392796,65447,199,36.20070258578,24.250011149985,-63.697563515075,2,1,18 +2025-03-11T12:39:57.029907,479392796,65447,199,35.9933747345,24.05094633105,-63.30366737033,2,1,18 +2025-03-11T12:39:57.045532,479392796,65447,199,35.77662288998,23.83800199071,-62.900459677445,2,1,18 +2025-03-11T12:39:57.061157,479392796,65447,199,35.55515904884,23.625049497405,-62.51110875275,2,1,18 +2025-03-11T12:39:57.076782,479392796,65447,199,35.32427121446,23.407459626345,-62.121725726045,2,1,18 +2025-03-11T12:39:57.092407,479392796,65447,199,35.11223136656,23.18528129532,-61.727730100295,2,1,18 +2025-03-11T12:39:57.108032,479392796,65447,199,34.9096155119,22.953877126575,-61.333710956555,2,1,18 +2025-03-11T12:39:57.123657,479392796,65447,199,34.69286366738,22.731690642585,-60.944329732865,2,1,18 +2025-03-11T12:39:57.139282,479392796,65447,199,34.49024781272,22.52801290479,-60.53655827993,2,1,18 +2025-03-11T12:39:57.154907,479392796,65447,199,34.27820796482,22.324318861065,-60.128773264985,2,1,18 +2025-03-11T12:39:57.170532,479392796,65447,199,34.04260813382,22.083615477915,-59.720806025015,2,1,18 +2025-03-11T12:39:57.186157,479392796,65447,199,33.81643229606,21.84754947252,-59.30824970399,2,1,18 +2025-03-11T12:39:57.201782,479392796,65447,199,33.58554446168,21.62071745781,-58.891102498895,2,1,18 +2025-03-11T12:39:57.217407,479392796,65447,199,33.3546566273,21.3938854431,-58.478576476865,2,1,18 +2025-03-11T12:39:57.233032,479392796,65447,199,33.13319278616,21.162448662495,-58.05218192765,2,1,18 +2025-03-11T12:39:57.248657,479392796,65447,199,32.9070169484,20.93562480075,-57.611935588235,2,1,18 +2025-03-11T12:39:57.264282,479392796,65447,199,32.68084111064,20.69493772353,-57.21784545947,2,1,18 +2025-03-11T12:39:57.279907,479392796,65447,199,32.44995327626,20.472726780645,-56.791474428245,2,1,18 +2025-03-11T12:39:57.295532,479392796,65447,199,32.2237774385,20.241281847075,-56.37893664722,2,1,18 +2025-03-11T12:39:57.311157,479392796,65447,199,31.98346561088,20.005191382785,-55.961738800115,2,1,18 +2025-03-11T12:39:57.326782,479392796,65447,199,31.7290177934,19.755213244125,-55.5306014408,2,1,18 +2025-03-11T12:39:57.342407,479392796,65447,199,31.48399396916,19.523735698695,-55.090309437365,2,1,18 +2025-03-11T12:39:57.358032,479392796,65447,199,31.24368214154,19.287645234405,-54.640763308805,2,1,18 +2025-03-11T12:39:57.373657,479392796,65447,199,31.01279430716,19.042328932395,-54.21429957758,2,1,18 +2025-03-11T12:39:57.389282,479392796,65447,199,30.77719447616,18.801625549245,-53.78784760535,2,1,18 +2025-03-11T12:39:57.404907,479392796,65447,199,30.54630664178,18.556309247235,-53.342899141865,2,1,18 +2025-03-11T12:39:57.420532,479392796,65447,199,30.2918588243,18.324815395875,-52.897972393355,2,1,18 +2025-03-11T12:39:57.436157,479392796,65447,199,30.04683500006,18.07947463497,-52.453003586855,2,1,18 +2025-03-11T12:39:57.451782,479392796,65447,199,29.80181117582,17.843376017715,-52.00345067729,2,1,18 +2025-03-11T12:39:57.467407,479392796,65447,199,29.55207535496,17.60264817567,-51.54463008059,2,1,18 +2025-03-11T12:39:57.483032,479392796,65447,199,29.31176352734,17.34807342408,-51.099630975095,2,1,18 +2025-03-11T12:39:57.498657,479392796,65447,199,29.07616369634,17.093506825455,-50.654638650605,2,1,18 +2025-03-11T12:39:57.514282,479392796,65447,199,28.84527586196,16.838948379795,-50.195789557925,2,1,18 +2025-03-11T12:39:57.529907,479392796,65447,199,28.58611604786,16.584341016345,-49.72303623002,2,1,18 +2025-03-11T12:39:57.545532,479392796,65447,199,28.32695623376,16.338975796545,-49.25494116518,2,1,18 +2025-03-11T12:39:57.561157,479392796,65447,199,28.06308442304,16.08436028013,-48.814529337725,2,1,18 +2025-03-11T12:39:57.576782,479392796,65447,199,27.79921261232,15.820502620065,-48.360216881075,2,1,18 +2025-03-11T12:39:57.592407,479392796,65447,199,27.54947679146,15.56129049072,-47.86897384292,2,1,18 +2025-03-11T12:39:57.608032,479392796,65447,199,27.28560498074,15.297432830655,-47.400797837075,2,1,18 +2025-03-11T12:39:57.623657,479392796,65447,199,27.03586915988,15.04746284496,-46.941940160375,2,1,18 +2025-03-11T12:39:57.639282,479392796,65447,199,26.8049813255,14.797525471125,-46.464624875435,2,1,18 +2025-03-11T12:39:57.654907,479392796,65447,199,26.55053350802,14.538305188815,-45.98723860547,2,1,18 +2025-03-11T12:39:57.670532,479392796,65447,199,26.29608569054,14.269842762855,-45.53292117083,2,1,18 +2025-03-11T12:39:57.686157,479392796,65447,199,26.0275018832,13.996734806175,-45.060080120915,2,1,18 +2025-03-11T12:39:57.701782,479392796,65447,199,25.76363007248,13.72363500246,-44.568761119745,2,1,18 +2025-03-11T12:39:57.717407,479392796,65447,199,25.50447025838,13.45978549536,-44.072864796515,2,1,18 +2025-03-11T12:39:57.733032,479392796,65447,199,25.23588645104,13.20516182598,-43.59085554047,2,1,18 +2025-03-11T12:39:57.748657,479392796,65447,199,24.9673026437,12.94129601295,-43.11343038749,2,1,18 +2025-03-11T12:39:57.764282,479392796,65447,199,24.69871883636,12.691293415395,-42.63606085451,2,1,18 +2025-03-11T12:39:57.779907,479392796,65447,199,24.43955902226,12.427443908295,-42.163270446605,2,1,18 +2025-03-11T12:39:57.795532,479392796,65447,199,24.17097521492,12.145093807965,-41.67190758443,2,1,18 +2025-03-11T12:39:57.811157,479392796,65447,199,23.89767941096,11.876598770145,-41.17135119512,2,1,18 +2025-03-11T12:39:57.826782,479392796,65447,199,23.63380760024,11.60349896643,-40.68003219395,2,1,18 +2025-03-11T12:39:57.842407,479392796,65447,199,23.35108780304,11.33498762268,-40.18870460876,2,1,18 +2025-03-11T12:39:57.858032,479392796,65447,199,23.06836800584,11.05723413528,-39.69733994357,2,1,18 +2025-03-11T12:39:57.873657,479392796,65447,199,22.7997841985,10.7841261786,-39.1921506122,2,1,18 +2025-03-11T12:39:57.889282,479392796,65447,199,22.53591238778,10.50640530306,-38.705434254095,2,1,18 +2025-03-11T12:39:57.904907,479392796,65447,199,22.25319259058,10.24713610296,-38.214143748905,2,1,18 +2025-03-11T12:39:57.920532,479392796,65447,199,21.97989678662,9.97864106514,-37.713587359595,2,1,18 +2025-03-11T12:39:57.936157,479392796,65447,199,21.70660098266,9.69166174002,-37.203714444155,2,1,18 +2025-03-11T12:39:57.951782,479392796,65447,199,21.4333051787,9.41392455855,-36.70774215791,2,1,18 +2025-03-11T12:39:57.967407,479392796,65447,199,21.16943336798,9.13620368301,-36.18867751835,2,1,18 +2025-03-11T12:39:57.983032,479392796,65447,199,20.90556155726,8.844619591995,-35.674178441855,2,1,18 +2025-03-11T12:39:57.998580,479392800,65442,200,20.61341776682,8.566849798665,-35.164315482395,2,1,18 +2025-03-11T12:39:58.014205,479392800,65442,200,20.32127397638,8.298322148985,-34.64986841987,2,1,18 +2025-03-11T12:39:58.029830,479392800,65442,200,20.03855417918,8.020568661585,-34.14926138855,2,1,18 +2025-03-11T12:39:58.045455,479392800,65442,200,19.76525837522,7.73821040829,-33.63016464698,2,1,18 +2025-03-11T12:39:58.061080,479392800,65442,200,19.48725057464,7.469707217505,-33.11573792747,2,1,18 +2025-03-11T12:39:58.076705,479392800,65442,200,19.19981878082,7.19194557714,-32.605881749015,2,1,18 +2025-03-11T12:39:58.092330,479392800,65442,200,18.92181098024,6.90033702723,-32.100604695635,2,1,18 +2025-03-11T12:39:58.107955,479392800,65442,200,18.64380317966,6.60872847732,-31.58146409306,2,1,18 +2025-03-11T12:39:58.123580,479392800,65442,200,18.36108338246,6.32173284627,-31.048471700285,2,1,18 +2025-03-11T12:39:58.139205,479392800,65442,200,18.07836358526,6.03473721522,-30.53396403977,2,1,18 +2025-03-11T12:39:58.154830,479392800,65442,200,17.7815077982,5.756959268925,-30.033336665435,2,1,18 +2025-03-11T12:39:58.170455,479392800,65442,200,17.49407600438,5.46995548491,-29.509579857785,2,1,18 +2025-03-11T12:39:58.186080,479392800,65442,200,17.2160682038,5.173725863175,-28.99042071521,2,1,18 +2025-03-11T12:39:58.201705,479392800,65442,200,16.92863640998,4.882101007335,-28.462024184495,2,1,18 +2025-03-11T12:39:58.217330,479392800,65442,200,16.64591661278,4.576621088985,-27.942821180915,2,1,18 +2025-03-11T12:39:58.232955,479392800,65442,200,16.36319681558,4.289625457935,-27.41907115427,2,1,18 +2025-03-11T12:39:58.248580,479392800,65442,200,16.07576502176,4.016484889395,-26.89536996662,2,1,18 +2025-03-11T12:39:58.264205,479392800,65442,200,15.78362123132,3.720230808765,-26.362326931835,2,1,18 +2025-03-11T12:39:58.279830,479392800,65442,200,15.51032542736,3.42863041182,-25.82932956107,2,1,18 +2025-03-11T12:39:58.295455,479392800,65442,200,15.2134696403,3.141610321875,-25.30555919141,2,1,18 +2025-03-11T12:39:58.311080,479392800,65442,200,14.90718986,2.84533178235,-24.78173817974,2,1,18 +2025-03-11T12:39:58.326705,479392800,65442,200,14.61033407294,2.55369062058,-24.23946453782,2,1,18 +2025-03-11T12:39:58.342330,479392800,65442,200,14.32761427574,2.271316061355,-23.70186950198,2,1,18 +2025-03-11T12:39:58.357955,479392800,65442,200,14.04018248192,1.979691205515,-23.154988239005,2,1,18 +2025-03-11T12:39:58.373580,479392800,65442,200,13.74332669486,1.69267111557,-22.61735432015,2,1,18 +2025-03-11T12:39:58.389205,479392800,65442,200,13.44175891118,1.401021800835,-22.102800995615,2,1,18 +2025-03-11T12:39:58.404830,479392800,65442,200,13.1401911275,1.095509270625,-21.565086135755,2,1,18 +2025-03-11T12:39:58.420455,479392800,65442,200,12.84333534044,0.80848918068,-21.01820985077,2,1,18 +2025-03-11T12:39:58.436080,479392800,65442,200,12.55590354662,0.51686432484,-20.46670740473,2,1,18 +2025-03-11T12:39:58.451705,479392800,65442,200,12.28260774266,0.216021784245,-19.91980940477,2,1,18 +2025-03-11T12:39:58.467330,479392800,65442,200,12.00459994208,-0.0802078374899997,-19.400650262195,2,1,18 +2025-03-11T12:39:58.482955,479392800,65442,200,11.71716814826,-0.367211621505001,-18.876893454545,2,1,18 +2025-03-11T12:39:58.498580,479392800,65442,200,11.4203123612,-0.67271599875,-18.334564192625,2,1,18 +2025-03-11T12:39:58.514205,479392800,65442,200,11.12816857076,-0.968970079379999,-17.80152115784,2,1,18 +2025-03-11T12:39:58.529830,479392800,65442,200,10.8313127837,-1.26061124115,-17.273111065115,2,1,18 +2025-03-11T12:39:58.545455,479392800,65442,200,10.53916899326,-1.561486393605,-16.744670673395,2,1,18 +2025-03-11T12:39:58.561080,479392800,65442,200,10.2423132062,-1.862369699025,-16.19773876841,2,1,18 +2025-03-11T12:39:58.576705,479392800,65442,200,9.94074542252,-2.16326115741,-15.64155771629,2,1,18 +2025-03-11T12:39:58.592330,479392800,65442,200,9.6297536456,-2.4595478499,-15.09462400829,2,1,18 +2025-03-11T12:39:58.607955,479392800,65442,200,9.33289785854,-2.765052227145,-14.547673563305,2,1,18 +2025-03-11T12:39:58.623580,479392800,65442,200,9.0407540681,-3.061306307775,-14.019251711585,2,1,18 +2025-03-11T12:39:58.639205,479392800,65442,200,8.7344742878,-3.362205919125,-13.476927427655,2,1,18 +2025-03-11T12:39:58.654830,479392800,65442,200,8.44704249398,-3.64920970314,-12.93006470468,2,1,18 +2025-03-11T12:39:58.670455,479392800,65442,200,8.15018670692,-3.95009300856,-12.410859898085,2,1,18 +2025-03-11T12:39:58.686080,479392800,65442,200,7.84861892324,-4.25560553877,-11.84079675677,2,1,18 +2025-03-11T12:39:58.701705,479392800,65442,200,7.5564751328,-4.5703439067,-11.279952463595,2,1,18 +2025-03-11T12:39:58.717330,479392800,65442,200,7.25490734912,-4.86661429326,-10.75613823293,2,1,18 +2025-03-11T12:39:58.732955,479392800,65442,200,6.94862756882,-5.14902961731,-10.218509292065,2,1,18 +2025-03-11T12:39:58.748580,479392800,65442,200,6.65648377838,-5.44528369794,-9.67622389115,2,1,18 +2025-03-11T12:39:58.764205,479392800,65442,200,6.3549159947,-5.75079622815,-9.12002429903,2,1,18 +2025-03-11T12:39:58.779830,479392800,65442,200,6.05806020764,-6.065542749045,-8.573036774045,2,1,18 +2025-03-11T12:39:58.795455,479392800,65442,200,5.75649242396,-6.36643420743,-8.02147690499,2,1,18 +2025-03-11T12:39:58.811080,479392800,65442,200,5.4596366369,-6.6580753692,-7.483824446135,2,1,18 +2025-03-11T12:39:58.826705,479392800,65442,200,5.15806885322,-6.958966827585,-6.936885760145,2,1,18 +2025-03-11T12:39:58.842330,479392800,65442,200,4.85178907292,-7.25524536711,-6.376095283955,2,1,18 +2025-03-11T12:39:58.857955,479392800,65442,200,4.55022128924,-7.546894681845,-5.819951311835,2,1,18 +2025-03-11T12:39:58.873580,479392800,65442,200,4.2580774988,-7.852390906125,-5.291492380115,2,1,18 +2025-03-11T12:39:58.889205,479392800,65442,200,3.9753577016,-8.15324975265,-4.75844436734,2,1,18 +2025-03-11T12:39:58.904830,479392800,65442,200,3.6690779213,-8.46339150765,-4.211461820345,2,1,18 +2025-03-11T12:39:58.920455,479392800,65442,200,3.362798141,-8.75504897535,-3.64606870109,2,1,18 +2025-03-11T12:39:58.936080,479392800,65442,200,3.0565183607,-9.0559485867,-3.099123234095,2,1,18 +2025-03-11T12:39:58.951705,479392800,65442,200,2.76437457026,-9.35220266733,-2.53835310092,2,1,18 +2025-03-11T12:39:58.967330,479392800,65442,200,2.48636676968,-9.657674432715,-2.009914512215,2,1,18 +2025-03-11T12:39:58.982955,479392800,65442,200,2.18008698938,-9.96319511589,-1.476814054415,2,1,18 +2025-03-11T12:39:58.998580,479392800,65442,200,1.8785192057,-10.2687076461,-0.93447801149,2,1,18 +2025-03-11T12:39:59.014205,479392800,65442,200,1.57695142202,-10.56497803266,-0.382936682435,2,1,18 +2025-03-11T12:39:59.029830,479392800,65442,200,1.27067164172,-10.86587764401,0.17325115069,2,1,18 +2025-03-11T12:39:59.045455,479392800,65442,200,0.97852785128,-11.18061601194,0.75720135919,2,1,18 +2025-03-11T12:39:59.061080,479392800,65442,200,0.66753607436,-11.48614484808,1.29492978106,2,1,18 +2025-03-11T12:39:59.076705,479392800,65442,200,0.36596829068,-11.787036306465,1.83262610092,2,1,18 +2025-03-11T12:39:59.092330,479392800,65442,200,0.0738245002399999,-12.07866931527,2.374892961835,2,1,18 +2025-03-11T12:39:59.107955,479392800,65442,200,-0.21360729358,-12.384157386585,2.91258747868,2,1,18 +2025-03-11T12:39:59.123580,479392800,65442,200,-0.51988707388,-12.68967806976,3.44568793648,2,1,18 +2025-03-11T12:39:59.139205,479392800,65442,200,-0.82145485756,-12.990569528145,3.969520707145,2,1,18 +2025-03-11T12:39:59.154830,479392800,65442,200,-1.11831064462,-13.291452833565,4.507210246,2,1,18 +2025-03-11T12:39:59.170455,479392800,65442,200,-1.40574243844,-13.592319833055,5.054128588975,2,1,18 +2025-03-11T12:39:59.186080,479392800,65442,200,-1.69788622888,-13.888573913685,5.601035172955,2,1,18 +2025-03-11T12:39:59.201705,479392800,65442,200,-1.99003001932,-14.184827994315,6.16180530613,2,1,18 +2025-03-11T12:39:59.217330,479392800,65442,200,-2.30102179624,-14.471872543155,6.704080751065,2,1,18 +2025-03-11T12:39:59.232955,479392800,65442,200,-2.61201357316,-14.758917091995,7.250977379065,2,1,18 +2025-03-11T12:39:59.248580,479392800,65442,200,-2.9041573636,-15.05979224445,7.80252368611,2,1,18 +2025-03-11T12:39:59.264205,479392800,65442,200,-3.20101315066,-15.356054478045,8.3355735019,2,1,18 +2025-03-11T12:39:59.279830,479392800,65442,200,-3.50258093434,-15.64770379278,8.859369192565,2,1,18 +2025-03-11T12:39:59.295455,479392800,65442,200,-3.80414871802,-15.94397417934,9.40166815549,2,1,18 +2025-03-11T12:39:59.311080,479392800,65442,200,-4.09629250846,-16.24022825997,9.943953556405,2,1,18 +2025-03-11T12:39:59.326705,479392800,65442,200,-4.3884362989,-16.5364823406,10.481617774255,2,1,18 +2025-03-11T12:39:59.342330,479392800,65442,200,-4.68058008934,-16.82349427758,11.02386609517,2,1,18 +2025-03-11T12:39:59.357955,479392800,65442,200,-4.96801188316,-17.110498061595,11.56610763508,2,1,18 +2025-03-11T12:39:59.373580,479392800,65442,200,-5.26957966684,-17.41138951998,12.09456158881,2,1,18 +2025-03-11T12:39:59.389205,479392800,65442,200,-5.58057144376,-17.70767621247,12.609147015355,2,1,18 +2025-03-11T12:39:59.404830,479392800,65442,200,-5.8727152342,-18.008551364925,13.165314505465,2,1,18 +2025-03-11T12:39:59.420455,479392800,65442,200,-6.1554350314,-18.29092592415,13.712151907435,2,1,18 +2025-03-11T12:39:59.436080,479392800,65442,200,-6.45229081846,-18.58256708592,14.25904673242,2,1,18 +2025-03-11T12:39:59.451705,479392800,65442,200,-6.73972261228,-18.878813013585,14.787461803135,2,1,18 +2025-03-11T12:39:59.467330,479392800,65442,200,-7.01773041286,-19.198147994445,15.311334828775,2,1,18 +2025-03-11T12:39:59.482955,479392800,65442,200,-7.30045021006,-19.485143625495,15.839706038485,2,1,18 +2025-03-11T12:39:59.498580,479392800,65442,200,-7.57845801064,-19.77213110358,16.35882810106,2,1,18 +2025-03-11T12:39:59.514205,479392800,65442,200,-7.8753137977,-20.068393337175,16.887256733785,2,1,18 +2025-03-11T12:39:59.529830,479392800,65442,200,-8.16274559152,-20.360018193015,17.420274447565,2,1,18 +2025-03-11T12:39:59.545455,479392800,65442,200,-8.45488938196,-20.637787986345,17.94400095622,2,1,18 +2025-03-11T12:39:59.561080,479392800,65442,200,-8.75174516902,-20.92480807629,18.46777132588,2,1,18 +2025-03-11T12:39:59.576705,479392800,65442,200,-9.0297529696,-21.2164166262,18.99153311152,2,1,18 +2025-03-11T12:39:59.592330,479392800,65442,200,-9.31718476342,-21.512662553865,19.51532699917,2,1,18 +2025-03-11T12:39:59.607955,479392800,65442,200,-9.60932855386,-21.80429556267,20.029866761695,2,1,18 +2025-03-11T12:39:59.623580,479392800,65442,200,-9.89676034768,-22.10516256216,20.54905800628,2,1,18 +2025-03-11T12:39:59.639205,479392800,65442,200,-10.18890413812,-22.39217449914,21.072821594935,2,1,18 +2025-03-11T12:39:59.654830,479392800,65442,200,-10.48575992518,-22.67457351726,21.605815790725,2,1,18 +2025-03-11T12:39:59.670455,479392800,65442,200,-10.76847972238,-22.938463789185,22.115609568175,2,1,18 +2025-03-11T12:39:59.686080,479392800,65442,200,-11.04648752296,-23.211588051795,22.62543364462,2,1,18 +2025-03-11T12:39:59.701705,479392800,65442,200,-11.32449532354,-23.49857552988,23.153798073325,2,1,18 +2025-03-11T12:39:59.717330,479392800,65442,200,-11.60721512074,-23.78557116093,23.66830573384,2,1,18 +2025-03-11T12:39:59.732955,479392800,65442,200,-11.88522292132,-24.063316495365,24.205875448675,2,1,18 +2025-03-11T12:39:59.748580,479392800,65442,200,-12.17265471514,-24.345699207555,24.748098448585,2,1,18 +2025-03-11T12:39:59.764205,479392800,65442,200,-12.4459505191,-24.623436389025,25.239449551765,2,1,18 +2025-03-11T12:39:59.779830,479392800,65442,200,-12.72395831968,-24.91042386711,25.73084451595,2,1,18 +2025-03-11T12:39:59.795455,479392800,65442,200,-12.99725412364,-25.192782120405,26.24069889139,2,1,18 +2025-03-11T12:39:59.811080,479392800,65442,200,-13.28468591746,-25.47054376077,26.75517625291,2,1,18 +2025-03-11T12:39:59.826705,479392800,65442,200,-13.5532697248,-25.76213600475,27.246576195085,2,1,18 +2025-03-11T12:39:59.842330,479392800,65442,200,-13.82185353214,-26.04448610508,27.72869669113,2,1,18 +2025-03-11T12:39:59.857955,479392800,65442,200,-14.10928532596,-26.30838452997,28.247739615715,2,1,18 +2025-03-11T12:39:59.873580,479392800,65442,200,-14.39200512316,-26.57689587372,28.76217311623,2,1,18 +2025-03-11T12:39:59.889205,479392800,65442,200,-14.67001292374,-26.845399064505,29.253493920415,2,1,18 +2025-03-11T12:39:59.904830,479392800,65442,200,-14.9433087277,-27.123136245975,29.735602657465,2,1,18 +2025-03-11T12:39:59.920455,479392800,65442,200,-15.20718053842,-27.382372834215,30.22224485557,2,1,18 +2025-03-11T12:39:59.936080,479392800,65442,200,-15.485188339,-27.637012809525,30.722752405885,2,1,18 +2025-03-11T12:39:59.951705,479392800,65442,200,-15.7679081362,-27.914766296925,31.223359437205,2,1,18 +2025-03-11T12:39:59.967330,479392800,65442,200,-16.03649194354,-28.187874253605,31.719306402445,2,1,18 +2025-03-11T12:39:59.982955,479392800,65442,200,-16.29565175764,-28.46558697618,32.21987952874,2,1,18 +2025-03-11T12:39:59.998580,479392800,65442,200,-16.55009957512,-28.738670473965,32.72042733403,2,1,18 +2025-03-11T12:40:00.014205,479392800,65442,200,-16.82339537908,-29.016407655435,33.22102080334,2,1,18 +2025-03-11T12:40:00.029830,479392800,65442,200,-17.09669118304,-29.294144836905,33.716993089585,2,1,18 +2025-03-11T12:40:00.045455,479392800,65442,200,-17.37469898362,-29.57189017134,34.185245058445,2,1,18 +2025-03-11T12:40:00.061080,479392800,65442,200,-17.64328279096,-29.83575598437,34.65804902836,2,1,18 +2025-03-11T12:40:00.076705,479392800,65442,200,-17.90715460168,-30.09499257261,35.144691226465,2,1,18 +2025-03-11T12:40:00.092330,479392800,65442,200,-18.16631441578,-30.354221007885,35.61746309437,2,1,18 +2025-03-11T12:40:00.107955,479392800,65442,200,-18.41133824002,-30.60880391244,36.071711347,2,1,18 +2025-03-11T12:40:00.123580,479392800,65442,200,-18.6657860575,-30.863403122925,36.549079076965,2,1,18 +2025-03-11T12:40:00.139205,479392800,65442,200,-18.93908186146,-31.13651923257,37.031169274015,2,1,18 +2025-03-11T12:40:00.154830,479392800,65442,200,-19.2076656688,-31.39114290195,37.51317853006,2,1,18 +2025-03-11T12:40:00.170455,479392800,65442,200,-19.45740148966,-31.650355031295,37.976694469825,2,1,18 +2025-03-11T12:40:00.186080,479392800,65442,200,-19.7024253139,-31.900316864025,38.458651280845,2,1,18 +2025-03-11T12:40:00.201705,479392800,65442,200,-19.95687313138,-32.15491607451,38.91753427855,2,1,18 +2025-03-11T12:40:00.217330,479392800,65442,200,-20.21603294548,-32.423386653435,39.39496440952,2,1,18 +2025-03-11T12:40:00.232955,479392800,65442,200,-20.4799047562,-32.6687600262,39.83996034004,2,1,18 +2025-03-11T12:40:00.248580,479392800,65442,200,-20.73435257368,-32.91873816486,40.308067163875,2,1,18 +2025-03-11T12:40:00.264205,479392800,65442,200,-20.98880039116,-33.201063806295,40.762440218515,2,1,18 +2025-03-11T12:40:00.279830,479392800,65442,200,-21.23853621202,-33.45103379199,41.230540261345,2,1,18 +2025-03-11T12:40:00.295455,479392800,65442,200,-21.4929840295,-33.68252764335,41.693951742115,2,1,18 +2025-03-11T12:40:00.311080,479392800,65442,200,-21.73800785374,-33.93248947608,42.14356027168,2,1,18 +2025-03-11T12:40:00.326705,479392800,65442,200,-21.97831968136,-34.173201012195,42.59312494024,2,1,18 +2025-03-11T12:40:00.342330,479392800,65442,200,-22.21863150898,-34.42315469196,43.05196905493,2,1,18 +2025-03-11T12:40:00.357955,479392800,65442,200,-22.47779132308,-34.673140983585,43.50159792751,2,1,18 +2025-03-11T12:40:00.373580,479392800,65442,200,-22.7181031507,-34.94157895065,43.928167920745,2,1,18 +2025-03-11T12:40:00.389205,479392800,65442,200,-22.95841497832,-35.182290486765,44.37311140624,2,1,18 +2025-03-11T12:40:00.404830,479392800,65442,200,-23.19401480932,-35.41837279809,44.82727193686,2,1,18 +2025-03-11T12:40:00.420455,479392800,65442,200,-23.42961464032,-35.663697253065,45.276848364415,2,1,18 +2025-03-11T12:40:00.436080,479392800,65442,200,-23.67463846456,-35.895174798495,45.712519184785,2,1,18 +2025-03-11T12:40:00.451705,479392800,65442,200,-23.90081430232,-36.12199866024,46.129659608875,2,1,18 +2025-03-11T12:40:00.467330,479392800,65442,200,-24.1317021367,-36.36731496225,46.560744523165,2,1,18 +2025-03-11T12:40:00.482955,479392800,65442,200,-24.37672596094,-36.603413579505,46.99181270047,2,1,18 +2025-03-11T12:40:00.498580,479392800,65442,200,-24.61703778856,-36.848746187445,47.41366881064,2,1,18 +2025-03-11T12:40:00.514205,479392800,65442,200,-24.8385016297,-37.0894251117,47.830858073725,2,1,18 +2025-03-11T12:40:00.529830,479392800,65442,200,-25.07881345732,-37.311652360515,48.261863850025,2,1,18 +2025-03-11T12:40:00.545455,479392800,65442,200,-25.3097012917,-37.538484375225,48.68825342125,2,1,18 +2025-03-11T12:40:00.561080,479392800,65442,200,-25.53116513284,-37.74219472488,49.086809632075,2,1,18 +2025-03-11T12:40:00.576705,479392800,65442,200,-25.76205296722,-37.96902673959,49.508578020235,2,1,18 +2025-03-11T12:40:00.592330,479392800,65442,200,-25.9929408016,-38.20510089795,49.92576230533,2,1,18 +2025-03-11T12:40:00.607955,479392800,65442,200,-26.21911663936,-38.431924759695,50.329039180225,2,1,18 +2025-03-11T12:40:00.623580,479392800,65442,200,-26.44529247712,-38.654127549615,50.75078224738,2,1,18 +2025-03-11T12:40:00.639205,479392800,65442,200,-26.68089230812,-38.89020986094,51.15873094735,2,1,18 +2025-03-11T12:40:00.654830,479392800,65442,200,-26.90706814588,-39.135518009985,51.57594553144,2,1,18 +2025-03-11T12:40:00.670455,479392800,65442,200,-27.11439599716,-39.35306711622,51.96529465312,2,1,18 +2025-03-11T12:40:00.686080,479392800,65442,200,-27.32643584506,-39.566003303595,52.368495565,2,1,18 +2025-03-11T12:40:00.701705,479392800,65442,200,-27.5478996862,-39.774334725075,52.78093386502,2,1,18 +2025-03-11T12:40:00.717330,479392800,65442,200,-27.76465153072,-39.996521209065,53.156451539515,2,1,18 +2025-03-11T12:40:00.732955,479392800,65442,200,-27.99082736848,-40.218723998985,53.53198277602,2,1,18 +2025-03-11T12:40:00.748580,479392800,65442,200,-28.21700320624,-40.43630571708,53.944464937045,2,1,18 +2025-03-11T12:40:00.764205,479392800,65442,200,-28.43375505076,-40.653871129245,54.352312352995,2,1,18 +2025-03-11T12:40:00.779830,479392800,65442,200,-28.63637090542,-40.85754886704,54.72311434141,2,1,18 +2025-03-11T12:40:00.795455,479392800,65442,200,-28.8436987567,-41.07047690145,55.107823740025,2,1,18 +2025-03-11T12:40:00.811080,479392800,65442,200,-29.06045060122,-41.28342124179,55.497167883715,2,1,18 +2025-03-11T12:40:00.826705,479392800,65442,200,-29.27720244574,-41.491744510305,55.87262993821,2,1,18 +2025-03-11T12:40:00.842330,479392800,65442,200,-29.49395429026,-41.70006777882,56.229607260445,2,1,18 +2025-03-11T12:40:00.857955,479392800,65442,200,-29.68714615168,-41.894487067035,56.586495057655,2,1,18 +2025-03-11T12:40:00.873580,479392800,65442,200,-29.87562601648,-42.09351927411,56.966500529185,2,1,18 +2025-03-11T12:40:00.889205,479392800,65442,200,-30.08295386776,-42.292584093045,57.32342720941,2,1,18 +2025-03-11T12:40:00.904830,479392800,65442,200,-30.2808577258,-42.496253677875,57.680358867625,2,1,18 +2025-03-11T12:40:00.920455,479392800,65442,200,-30.47876158384,-42.69530219088,58.041893168905,2,1,18 +2025-03-11T12:40:00.936080,479392800,65442,200,-30.66252945202,-42.889705173165,58.408009770235,2,1,18 +2025-03-11T12:40:00.951705,479392800,65442,200,-30.85572131344,-43.09336660503,58.76031346438,2,1,18 +2025-03-11T12:40:00.967330,479392800,65442,200,-31.07247315796,-43.29706880172,59.126514612745,2,1,18 +2025-03-11T12:40:00.982955,479392800,65442,200,-31.26095302276,-43.486858865145,59.47413472282,2,1,18 +2025-03-11T12:40:00.998580,479392800,65442,200,-31.44000889432,-43.672011550815,59.82634391395,2,1,18 +2025-03-11T12:40:01.014205,479392800,65442,200,-31.62848875912,-43.866422686065,60.16936138096,2,1,18 +2025-03-11T12:40:01.029830,479392800,65442,200,-31.80754463068,-44.05619644356,60.516967929025,2,1,18 +2025-03-11T12:40:01.045455,479392800,65442,200,-31.99131249886,-44.25522049767,60.855375971965,2,1,18 +2025-03-11T12:40:01.061080,479392800,65442,200,-32.17036837042,-44.42188889604,61.189026270835,2,1,18 +2025-03-11T12:40:01.076705,479392800,65442,200,-32.3541362386,-44.5931865192,61.518080707645,2,1,18 +2025-03-11T12:40:01.092330,479392800,65442,200,-32.5426161034,-44.7598712235,61.842502202395,2,1,18 +2025-03-11T12:40:01.107955,479392800,65442,200,-32.7310959682,-44.958903430575,62.17167466021,2,1,18 +2025-03-11T12:40:01.123580,479392800,65442,200,-32.919575833,-45.13945135035,62.491530591895,2,1,18 +2025-03-11T12:40:01.139205,479392800,65442,200,-33.09863170456,-45.310740820545,62.81133588157,2,1,18 +2025-03-11T12:40:01.154830,479392800,65442,200,-33.26826358288,-45.48201398481,63.12650642617,2,1,18 +2025-03-11T12:40:01.170455,479392800,65442,200,-33.44731945444,-45.662545598655,63.44172761278,2,1,18 +2025-03-11T12:40:01.186080,479392800,65442,200,-33.61223933614,-45.83843168178,63.75228873331,2,1,18 +2025-03-11T12:40:01.201705,479392800,65442,200,-33.75831123136,-46.00042193757,64.067388292885,2,1,18 +2025-03-11T12:40:01.217330,479392800,65442,200,-33.92323111306,-46.167065877045,64.387154699545,2,1,18 +2025-03-11T12:40:01.232955,479392800,65442,200,-34.09286299138,-46.324475825835,64.69764844108,2,1,18 +2025-03-11T12:40:01.248580,479392800,65442,200,-34.25778287308,-46.48187762166,64.994271852415,2,1,18 +2025-03-11T12:40:01.264205,479392800,65442,200,-34.42270275478,-46.65314263296,65.277087334555,2,1,18 +2025-03-11T12:40:01.279830,479392800,65442,200,-34.5923346331,-46.815173653575,65.582978433025,2,1,18 +2025-03-11T12:40:01.295455,479392800,65442,200,-34.7572545148,-46.977196521225,65.87962038436,2,1,18 +2025-03-11T12:40:01.311080,479392800,65442,200,-34.92688639312,-47.14846968549,66.16706383057,2,1,18 +2025-03-11T12:40:01.326705,479392800,65442,200,-35.08238228158,-47.296613031735,66.4497730507,2,1,18 +2025-03-11T12:40:01.342330,479392800,65442,200,-35.2284541768,-47.449361143875,66.727866065755,2,1,18 +2025-03-11T12:40:01.357955,479392800,65442,200,-35.38866206188,-47.606754786735,67.005997963825,2,1,18 +2025-03-11T12:40:01.373580,479392800,65442,200,-35.53002196048,-47.764115817735,67.274860371745,2,1,18 +2025-03-11T12:40:01.389205,479392800,65442,200,-35.6760938557,-47.9030007144,67.5528977668,2,1,18 +2025-03-11T12:40:01.404830,479392800,65442,200,-35.81274175768,-48.051111448785,67.821716313715,2,1,18 +2025-03-11T12:40:01.420455,479392800,65442,200,-35.95410165628,-48.199230336135,68.090541641635,2,1,18 +2025-03-11T12:40:01.436080,479392800,65442,200,-36.09546155488,-48.35197029531,68.350143143425,2,1,18 +2025-03-11T12:40:01.451705,479392800,65442,200,-36.2415334501,-48.509339479275,68.60976996622,2,1,18 +2025-03-11T12:40:01.467330,479392800,65442,200,-36.37818135208,-48.662071285485,68.85550113781,2,1,18 +2025-03-11T12:40:01.482955,479392800,65442,200,-36.52896524392,-48.791722191465,69.10578113548,2,1,18 +2025-03-11T12:40:01.498580,479392800,65442,200,-36.67032514252,-48.912114647865,69.3744952234,2,1,18 +2025-03-11T12:40:01.514205,479392800,65442,200,-36.8069730445,-49.04174109495,69.62013369499,2,1,18 +2025-03-11T12:40:01.529830,479392800,65442,200,-36.9483329431,-49.175996766825,69.875039853715,2,1,18 +2025-03-11T12:40:01.545455,479392800,65442,200,-37.07084485522,-49.314840898665,70.11145269616,2,1,18 +2025-03-11T12:40:01.561080,479392800,65442,200,-37.19806876396,-49.458314255295,70.35713322574,2,1,18 +2025-03-11T12:40:01.576705,479392800,65442,200,-37.34414065918,-49.592578080135,70.598182616275,2,1,18 +2025-03-11T12:40:01.592330,479392800,65442,200,-37.48078856116,-49.70372023992,70.8391257448,2,1,18 +2025-03-11T12:40:01.607955,479392800,65442,200,-37.6080124699,-49.81022502195,71.06617322212,2,1,18 +2025-03-11T12:40:01.623580,479392800,65442,200,-37.73052438202,-49.93058486649,71.284027172305,2,1,18 +2025-03-11T12:40:01.639205,479392800,65442,200,-37.8436123009,-50.055549476925,71.506507283545,2,1,18 +2025-03-11T12:40:01.654830,479392800,65442,200,-37.95670021978,-50.185135159185,71.729005934785,2,1,18 +2025-03-11T12:40:01.670455,479392800,65442,200,-38.07450013528,-50.291623635285,71.937555117835,2,1,18 +2025-03-11T12:40:01.686080,479392800,65442,200,-38.19230005078,-50.398112111385,72.146104300885,2,1,18 +2025-03-11T12:40:01.701705,479392800,65442,200,-38.30538796966,-50.527697793645,72.36398176906,2,1,18 +2025-03-11T12:40:01.717330,479392800,65442,200,-38.4326118784,-50.652686862975,72.58186104025,2,1,18 +2025-03-11T12:40:01.732955,479392800,65442,200,-38.54569979728,-50.773030401585,72.7765955131,2,1,18 +2025-03-11T12:40:01.748580,479392800,65442,200,-38.64936372292,-50.89797870609,72.96209259781,2,1,18 +2025-03-11T12:40:01.764205,479392800,65442,200,-38.74360365532,-50.995184273715,73.170570795835,2,1,18 +2025-03-11T12:40:01.779830,479392800,65442,200,-38.8566915742,-51.097043525025,73.365231108685,2,1,18 +2025-03-11T12:40:01.795455,479392800,65442,200,-38.96035549984,-51.180402183105,73.5366977842,2,1,18 +2025-03-11T12:40:01.811080,479392800,65442,200,-39.06401942548,-51.29610834396,73.717536605845,2,1,18 +2025-03-11T12:40:01.826705,479392800,65442,200,-39.16768335112,-51.402572361165,73.902959530555,2,1,18 +2025-03-11T12:40:01.842330,479392800,65442,200,-39.27605927338,-51.499802387685,74.06986742401,2,1,18 +2025-03-11T12:40:01.857955,479392800,65442,200,-39.37029920578,-51.592386883485,74.23673643445,2,1,18 +2025-03-11T12:40:01.873580,479392800,65442,200,-39.48338712466,-51.68038291932,74.4313411273,2,1,18 +2025-03-11T12:40:01.889205,479392800,65442,200,-39.57291506044,-51.763717118505,74.6027874598,2,1,18 +2025-03-11T12:40:01.904830,479392800,65442,200,-39.65301900298,-51.851656083585,74.75575403803,2,1,18 +2025-03-11T12:40:01.920455,479392800,65442,200,-39.73312294552,-51.95345826414,74.92726096852,2,1,18 +2025-03-11T12:40:01.936080,479392800,65442,200,-39.81322688806,-52.046018301045,75.08948845288,2,1,18 +2025-03-11T12:40:01.951705,479392800,65442,200,-39.8933308306,-52.1478204816,75.22402591885,2,1,18 +2025-03-11T12:40:01.967330,479392800,65442,200,-39.98285876638,-52.231154680785,75.38622988522,2,1,18 +2025-03-11T12:40:01.982955,479392800,65442,200,-40.06767470554,-52.295996439705,75.54373172752,2,1,18 +2025-03-11T12:40:01.998535,479392804,65439,201,-40.16191463794,-52.379338791855,75.6920789257,2,1,18 +2025-03-11T12:40:02.014160,479392804,65439,201,-40.23730658386,-52.44878531667,75.8218586476,2,1,18 +2025-03-11T12:40:02.029785,479392804,65439,201,-40.31269852978,-52.52285291331,75.96089927563,2,1,18 +2025-03-11T12:40:02.045410,479392804,65439,201,-40.39280247232,-52.59230759109,76.10454932773,2,1,18 +2025-03-11T12:40:02.061035,479392804,65439,201,-40.44934643176,-52.661721504045,76.24354429174,2,1,18 +2025-03-11T12:40:02.076660,479392804,65439,201,-40.5058903912,-52.735756488825,76.37331542962,2,1,18 +2025-03-11T12:40:02.092285,479392804,65439,201,-40.59070633036,-52.80521931957,76.4938663474,2,1,18 +2025-03-11T12:40:02.107910,479392804,65439,201,-40.66609827628,-52.87928691621,76.609801060105,2,1,18 +2025-03-11T12:40:02.123535,479392804,65439,201,-40.72735423234,-52.94870898213,76.716454523665,2,1,18 +2025-03-11T12:40:02.139160,479392804,65439,201,-40.77918619516,-53.013493670295,76.82769706828,2,1,18 +2025-03-11T12:40:02.154785,479392804,65439,201,-40.84044215122,-53.064431448915,76.93427637184,2,1,18 +2025-03-11T12:40:02.170410,479392804,65439,201,-40.9064101039,-53.110756308675,77.04546509947,2,1,18 +2025-03-11T12:40:02.186035,479392804,65439,201,-40.97237805658,-53.166323312085,77.161312090165,2,1,18 +2025-03-11T12:40:02.201660,479392804,65439,201,-41.0242100194,-53.244971215725,77.25412552252,2,1,18 +2025-03-11T12:40:02.217285,479392804,65439,201,-41.08075397884,-53.29590084138,77.351455678945,2,1,18 +2025-03-11T12:40:02.232910,479392804,65439,201,-41.1420099349,-53.3283543327,77.43485490718,2,1,18 +2025-03-11T12:40:02.248535,479392804,65439,201,-41.18441790448,-53.38850164311,77.53220180059,2,1,18 +2025-03-11T12:40:02.264160,479392804,65439,201,-41.22211387744,-53.42553544143,77.62482802993,2,1,18 +2025-03-11T12:40:02.279785,479392804,65439,201,-41.27865783688,-53.47184399526,77.694412547965,2,1,18 +2025-03-11T12:40:02.295410,479392804,65439,201,-41.32577780308,-53.50889409951,77.74546169173,2,1,18 +2025-03-11T12:40:02.311035,479392804,65439,201,-41.3540497828,-53.53666944825,77.8195525468,2,1,18 +2025-03-11T12:40:02.326660,479392804,65439,201,-41.39645775238,-53.58757461501,77.902998811015,2,1,18 +2025-03-11T12:40:02.342285,479392804,65439,201,-41.4247297321,-53.638455322875,77.96331881689,2,1,18 +2025-03-11T12:40:02.357910,479392804,65439,201,-41.45300171182,-53.666230671615,78.023546122765,2,1,18 +2025-03-11T12:40:02.373535,479392804,65439,201,-41.48598568816,-53.698635245145,78.093041115775,2,1,18 +2025-03-11T12:40:02.389160,479392804,65439,201,-41.52368166112,-53.735669043465,78.15331906366,2,1,18 +2025-03-11T12:40:02.404785,479392804,65439,201,-41.54724164422,-53.76343623924,78.199676039335,2,1,18 +2025-03-11T12:40:02.420410,479392804,65439,201,-41.56137763408,-53.791187129085,78.25526181913,2,1,18 +2025-03-11T12:40:02.436035,479392804,65439,201,-41.5896496138,-53.80509926235,78.29232758968,2,1,18 +2025-03-11T12:40:02.451660,479392804,65439,201,-41.6132095969,-53.8282453863,78.329423659225,2,1,18 +2025-03-11T12:40:02.467285,479392804,65439,201,-41.63676958,-53.846770438425,78.38498592103,2,1,18 +2025-03-11T12:40:02.482910,479392804,65439,201,-41.66975355634,-53.851448581005,78.422021392585,2,1,18 +2025-03-11T12:40:02.498535,479392804,65439,201,-41.67917754958,-53.87457024606,78.449854752985,2,1,18 +2025-03-11T12:40:02.514160,479392804,65439,201,-41.69802553606,-53.90232928887,78.47309903233,2,1,18 +2025-03-11T12:40:02.529785,479392804,65439,201,-41.71687352254,-53.91160404438,78.505511517805,2,1,18 +2025-03-11T12:40:02.545410,479392804,65439,201,-41.71687352254,-53.93008833168,78.519449227,2,1,18 +2025-03-11T12:40:02.561035,479392804,65439,201,-41.7310095124,-53.9347338624,78.528730476145,2,1,18 +2025-03-11T12:40:02.576660,479392804,65439,201,-41.74514550226,-53.944000464945,78.54727263142,2,1,18 +2025-03-11T12:40:02.592285,479392804,65439,201,-41.7545694955,-53.95787998635,78.570447728755,2,1,18 +2025-03-11T12:40:02.607910,479392804,65439,201,-41.7545694955,-53.95787998635,78.58431127795,2,1,18 +2025-03-11T12:40:02.623535,479392804,65439,201,-41.7545694955,-53.95787998635,78.57506891182,2,1,18 +2025-03-11T12:40:02.639160,479392804,65439,201,-41.75928149212,-53.957888139315,78.584318058955,2,1,18 +2025-03-11T12:40:02.654785,479392804,65439,201,-41.74985749888,-53.96249290521,78.584323036945,2,1,18 +2025-03-11T12:40:02.670410,479392804,65439,201,-41.74514550226,-53.94862153677,78.55653353755,2,1,18 +2025-03-11T12:40:02.686035,479392804,65439,201,-41.7310095124,-53.939354934225,78.528749016145,2,1,18 +2025-03-11T12:40:02.701660,479392804,65439,201,-41.71687352254,-53.934709403505,78.514846583935,2,1,18 +2025-03-11T12:40:02.717285,479392804,65439,201,-41.71216152592,-53.930080178715,78.510200079865,2,1,18 +2025-03-11T12:40:02.732910,479392804,65439,201,-41.71216152592,-53.91621696324,78.49628091067,2,1,18 +2025-03-11T12:40:02.748535,479392804,65439,201,-41.70273753268,-53.90695851366,78.463881987205,2,1,18 +2025-03-11T12:40:02.764160,479392804,65439,201,-41.6838895462,-53.8699573272,78.435979444795,2,1,18 +2025-03-11T12:40:02.779785,479392804,65439,201,-41.66975355634,-53.83758536553,78.41734458952,2,1,18 +2025-03-11T12:40:02.795410,479392804,65439,201,-41.6603295631,-53.8190847723,78.394150952185,2,1,18 +2025-03-11T12:40:02.811035,479392804,65439,201,-41.63205758338,-53.814414782685,78.35250107857,2,1,18 +2025-03-11T12:40:02.826660,479392804,65439,201,-41.60378560366,-53.805123721245,78.28772674963,2,1,18 +2025-03-11T12:40:02.842285,479392804,65439,201,-41.58493761718,-53.777364678435,78.24137655496,2,1,18 +2025-03-11T12:40:02.857910,479392804,65439,201,-41.56137763408,-53.74035533901,78.194982499285,2,1,18 +2025-03-11T12:40:02.873535,479392804,65439,201,-41.53781765098,-53.712588143235,78.13014079135,2,1,18 +2025-03-11T12:40:02.889160,479392804,65439,201,-41.51425766788,-53.67557880381,78.07912555261,2,1,18 +2025-03-11T12:40:02.904785,479392804,65439,201,-41.49069768478,-53.638569464385,78.02811031387,2,1,18 +2025-03-11T12:40:02.920410,479392804,65439,201,-41.44357771858,-53.59689828831,77.95393671478,2,1,18 +2025-03-11T12:40:02.936035,479392804,65439,201,-41.41059374224,-53.559872642955,77.88442318177,2,1,18 +2025-03-11T12:40:02.951660,479392804,65439,201,-41.38232176252,-53.51823407874,77.805655523635,2,1,18 +2025-03-11T12:40:02.967285,479392804,65439,201,-41.34462578956,-53.467337064945,77.71759485736,2,1,18 +2025-03-11T12:40:02.982910,479392804,65439,201,-41.27394584026,-53.42100405222,77.652611179375,2,1,18 +2025-03-11T12:40:02.998535,479392804,65439,201,-41.21740188082,-53.39317978569,77.578479638275,2,1,18 +2025-03-11T12:40:03.014160,479392804,65439,201,-41.17499391124,-53.35151676258,77.48582808793,2,1,18 +2025-03-11T12:40:03.029785,479392804,65439,201,-41.12316194842,-53.295974218065,77.374622623315,2,1,18 +2025-03-11T12:40:03.045410,479392804,65439,201,-41.08546597546,-53.24507720427,77.28656195704,2,1,18 +2025-03-11T12:40:03.061035,479392804,65439,201,-41.03834600926,-53.18954281272,77.179984456495,2,1,18 +2025-03-11T12:40:03.076660,479392804,65439,201,-40.9770900532,-53.133983962275,77.073386612935,2,1,18 +2025-03-11T12:40:03.092285,479392804,65439,201,-40.91112210052,-53.07379588704,76.962142265305,2,1,18 +2025-03-11T12:40:03.107910,479392804,65439,201,-40.8592901377,-53.018253342525,76.86942153295,2,1,18 +2025-03-11T12:40:03.123535,479392804,65439,201,-40.79332218502,-52.95806526729,76.744313636125,2,1,18 +2025-03-11T12:40:03.139160,479392804,65439,201,-40.72264223572,-52.88862689544,76.628404244425,2,1,18 +2025-03-11T12:40:03.154785,479392804,65439,201,-40.65667428304,-52.819196676555,76.535607549055,2,1,18 +2025-03-11T12:40:03.170410,479392804,65439,201,-40.59070633036,-52.75900860132,76.424363201425,2,1,18 +2025-03-11T12:40:03.186035,479392804,65439,201,-40.53416237092,-52.68497361654,76.294592063545,2,1,18 +2025-03-11T12:40:03.201660,479392804,65439,201,-40.46348242162,-52.61553524469,76.141713207325,2,1,18 +2025-03-11T12:40:03.217285,479392804,65439,201,-40.3880904757,-52.546088719875,76.002691119295,2,1,18 +2025-03-11T12:40:03.232910,479392804,65439,201,-40.3174105264,-52.476650348025,75.8729181784,2,1,18 +2025-03-11T12:40:03.248535,479392804,65439,201,-40.24201858048,-52.402582751385,75.73387755037,2,1,18 +2025-03-11T12:40:03.264160,479392804,65439,201,-40.15720264132,-52.31463563334,75.59476774033,2,1,18 +2025-03-11T12:40:03.279785,479392804,65439,201,-40.06767470554,-52.23592250598,75.455688229285,2,1,18 +2025-03-11T12:40:03.295410,479392804,65439,201,-39.987570763,-52.134120325425,75.28880248186,2,1,18 +2025-03-11T12:40:03.311035,479392804,65439,201,-39.90275482384,-52.050794279205,75.135847662625,2,1,18 +2025-03-11T12:40:03.326660,479392804,65439,201,-39.81793888468,-51.96284716116,74.98287430339,2,1,18 +2025-03-11T12:40:03.342285,479392804,65439,201,-39.72369895228,-51.874883737185,74.81602383295,2,1,18 +2025-03-11T12:40:03.357910,479392804,65439,201,-39.64830700636,-51.79619506872,74.63075283427,2,1,18 +2025-03-11T12:40:03.373535,479392804,65439,201,-39.55877907058,-51.71748194136,74.47780977403,2,1,18 +2025-03-11T12:40:03.389160,479392804,65439,201,-39.46453913818,-51.62489744556,74.32018312972,2,1,18 +2025-03-11T12:40:03.404785,479392804,65439,201,-39.3750112024,-51.51845788725,74.144022914155,2,1,18 +2025-03-11T12:40:03.420410,479392804,65439,201,-39.27605927338,-51.416623094835,73.97711004271,2,1,18 +2025-03-11T12:40:03.436035,479392804,65439,201,-39.17710734436,-51.319409374245,73.800973345135,2,1,18 +2025-03-11T12:40:03.451660,479392804,65439,201,-39.07344341872,-51.22218750069,73.615587500425,2,1,18 +2025-03-11T12:40:03.467285,479392804,65439,201,-38.96506749646,-51.11571533052,73.407051879385,2,1,18 +2025-03-11T12:40:03.482910,479392804,65439,201,-38.86611556744,-51.00925946628,73.207772186485,2,1,18 +2025-03-11T12:40:03.498535,479392804,65439,201,-38.7624516418,-50.902795449075,73.031591627905,2,1,18 +2025-03-11T12:40:03.514160,479392804,65439,201,-38.66349971278,-50.77323422571,72.83684041807,2,1,18 +2025-03-11T12:40:03.529785,479392804,65439,201,-38.55512379052,-50.65751991189,72.63751008316,2,1,18 +2025-03-11T12:40:03.545410,479392804,65439,201,-38.44674786826,-50.546426669895,72.433577105185,2,1,18 +2025-03-11T12:40:03.561035,479392804,65439,201,-38.32894795276,-50.43531712197,72.20190346681,2,1,18 +2025-03-11T12:40:03.576660,479392804,65439,201,-38.20172404402,-50.32881233994,71.979477172555,2,1,18 +2025-03-11T12:40:03.592285,479392804,65439,201,-38.08863612514,-50.213089873155,71.78014005664,2,1,18 +2025-03-11T12:40:03.607910,479392804,65439,201,-37.97554820626,-50.09736740637,71.580802940725,2,1,18 +2025-03-11T12:40:03.623535,479392804,65439,201,-37.84832429752,-49.967757265215,71.3675263126,2,1,18 +2025-03-11T12:40:03.639160,479392804,65439,201,-37.73052438202,-49.84740557364,71.15892150955,2,1,18 +2025-03-11T12:40:03.654785,479392804,65439,201,-37.59858847666,-49.72702942317,70.922569265095,2,1,18 +2025-03-11T12:40:03.670410,479392804,65439,201,-37.4666525713,-49.59741112905,70.672316391445,2,1,18 +2025-03-11T12:40:03.686035,479392804,65439,201,-37.35356465242,-49.472446518615,70.431351547945,2,1,18 +2025-03-11T12:40:03.701660,479392804,65439,201,-37.23576473692,-49.34285268339,70.194982566505,2,1,18 +2025-03-11T12:40:03.717285,479392804,65439,201,-37.10382883156,-49.20399224562,69.953934978985,2,1,18 +2025-03-11T12:40:03.732910,479392804,65439,201,-36.95775693634,-49.07897056443,69.72216503458,2,1,18 +2025-03-11T12:40:03.748535,479392804,65439,201,-36.82582103098,-48.953973342135,69.48117306706,2,1,18 +2025-03-11T12:40:03.764160,479392804,65439,201,-36.68446113238,-48.81047552661,69.24009337753,2,1,18 +2025-03-11T12:40:03.779785,479392804,65439,201,-36.53367724054,-48.66234033333,68.985118036795,2,1,18 +2025-03-11T12:40:03.795410,479392804,65439,201,-36.40174133518,-48.52347989556,68.725585717015,2,1,18 +2025-03-11T12:40:03.811035,479392804,65439,201,-36.2650934332,-48.366127017525,68.4567300901,2,1,18 +2025-03-11T12:40:03.826660,479392804,65439,201,-36.11902153798,-48.21799997721,68.20176153037,2,1,18 +2025-03-11T12:40:03.842285,479392804,65439,201,-35.982373636,-48.079131386475,67.91911651426,2,1,18 +2025-03-11T12:40:03.857910,479392804,65439,201,-35.83158974416,-47.940238336845,67.6410723382,2,1,18 +2025-03-11T12:40:03.873535,479392804,65439,201,-35.6760938557,-47.787473918775,67.362965761135,2,1,18 +2025-03-11T12:40:03.889160,479392804,65439,201,-35.53002196048,-47.63010473481,67.10333893834,2,1,18 +2025-03-11T12:40:03.904785,479392804,65439,201,-35.38866206188,-47.45425941651,66.83440237042,2,1,18 +2025-03-11T12:40:03.920410,479392804,65439,201,-35.24259016666,-47.30151130437,66.556309355365,2,1,18 +2025-03-11T12:40:03.936035,479392804,65439,201,-35.07767028496,-47.13024629307,66.264251507095,2,1,18 +2025-03-11T12:40:03.951660,479392804,65439,201,-34.91746239988,-46.958989434735,65.9629580737,2,1,18 +2025-03-11T12:40:03.967285,479392804,65439,201,-34.7572545148,-46.820080079175,65.661794420305,2,1,18 +2025-03-11T12:40:03.982910,479392804,65439,201,-34.58291063986,-46.676525192895,65.37445543309,2,1,18 +2025-03-11T12:40:03.998535,479392804,65439,201,-34.4274147514,-46.519139703,65.06398203457,2,1,18 +2025-03-11T12:40:04.014160,479392804,65439,201,-34.27663085956,-46.36176236607,64.753515417055,2,1,18 +2025-03-11T12:40:04.029785,479392804,65439,201,-34.11171097786,-46.195118426595,64.44761255959,2,1,18 +2025-03-11T12:40:04.045410,479392804,65439,201,-33.94207909954,-46.019224190505,64.155529390315,2,1,18 +2025-03-11T12:40:04.061035,479392804,65439,201,-33.7912952077,-45.843362566275,63.85423097893,2,1,18 +2025-03-11T12:40:04.076660,479392804,65439,201,-33.60752733952,-45.66744387129,63.53440036825,2,1,18 +2025-03-11T12:40:04.092285,479392804,65439,201,-33.42375947134,-45.48690410448,63.2237935837,2,1,18 +2025-03-11T12:40:04.107910,479392804,65439,201,-33.23999160316,-45.31560648132,62.91322387915,2,1,18 +2025-03-11T12:40:04.123535,479392804,65439,201,-33.07035972484,-45.135091173405,62.593395071485,2,1,18 +2025-03-11T12:40:04.139160,479392804,65439,201,-32.90072784652,-44.95457586549,62.27356626382,2,1,18 +2025-03-11T12:40:04.154785,479392804,65439,201,-32.72638397158,-44.769431332785,61.94446976902,2,1,18 +2025-03-11T12:40:04.170410,479392804,65439,201,-32.54732810002,-44.59814186259,61.62004329628,2,1,18 +2025-03-11T12:40:04.186035,479392804,65439,201,-32.36356023184,-44.42684423943,61.3002312256,2,1,18 +2025-03-11T12:40:04.201660,479392804,65439,201,-32.17508036704,-44.237054176005,60.96647466472,2,1,18 +2025-03-11T12:40:04.217285,479392804,65439,201,-31.99602449548,-44.051901490335,60.64199257198,2,1,18 +2025-03-11T12:40:04.232910,479392804,65439,201,-31.80283263406,-43.871345417595,60.27591802864,2,1,18 +2025-03-11T12:40:04.248535,479392804,65439,201,-31.60492877602,-43.68153904824,59.937526722685,2,1,18 +2025-03-11T12:40:04.264160,479392804,65439,201,-31.43058490108,-43.49177344371,59.599169321755,2,1,18 +2025-03-11T12:40:04.279785,479392804,65439,201,-31.23739303966,-43.306596299145,59.25618215374,2,1,18 +2025-03-11T12:40:04.295410,479392804,65439,201,-31.02535319176,-43.116765470895,58.90852813864,2,1,18 +2025-03-11T12:40:04.311035,479392804,65439,201,-30.84158532358,-42.936225704085,58.528603608115,2,1,18 +2025-03-11T12:40:04.326660,479392804,65439,201,-30.66252945202,-42.74645194659,58.17175469392,2,1,18 +2025-03-11T12:40:04.342285,479392804,65439,201,-30.47404958722,-42.53355652404,57.824041883845,2,1,18 +2025-03-11T12:40:04.357910,479392804,65439,201,-30.27614572918,-42.32988693921,57.480973774825,2,1,18 +2025-03-11T12:40:04.373535,479392804,65439,201,-30.07352987452,-42.13083027324,57.124053875605,2,1,18 +2025-03-11T12:40:04.389160,479392804,65439,201,-29.8803380131,-41.92254776955,56.767110458395,2,1,18 +2025-03-11T12:40:04.404785,479392804,65439,201,-29.67301016182,-41.72810402244,56.38247521978,2,1,18 +2025-03-11T12:40:04.420410,479392804,65439,201,-29.47510630378,-41.51519229396,55.99315820011,2,1,18 +2025-03-11T12:40:04.436035,479392804,65439,201,-29.25835445926,-41.31149009727,55.599229953355,2,1,18 +2025-03-11T12:40:04.451660,479392804,65439,201,-29.04631461136,-41.117038197195,55.214587933735,2,1,18 +2025-03-11T12:40:04.467285,479392804,65439,201,-28.83427476346,-40.89485986617,54.829834674115,2,1,18 +2025-03-11T12:40:04.482910,479392804,65439,201,-28.61281092232,-40.681907372865,54.454347298615,2,1,18 +2025-03-11T12:40:04.498535,479392804,65439,201,-28.3960590778,-40.482826248,54.065058774925,2,1,18 +2025-03-11T12:40:04.514160,479392804,65439,201,-28.19815521976,-40.26991451952,53.666499389125,2,1,18 +2025-03-11T12:40:04.529785,479392804,65439,201,-27.9955393651,-40.047752494425,53.291002057645,2,1,18 +2025-03-11T12:40:04.545410,479392804,65439,201,-27.77878752058,-39.83018708226,52.901639373955,2,1,18 +2025-03-11T12:40:04.561035,479392804,65439,201,-27.56203567606,-39.59875845462,52.512221070265,2,1,18 +2025-03-11T12:40:04.576660,479392804,65439,201,-27.34528383154,-39.371950898805,52.122821306575,2,1,18 +2025-03-11T12:40:04.592285,479392804,65439,201,-27.12853198702,-39.159006558465,51.71961361369,2,1,18 +2025-03-11T12:40:04.607910,479392804,65439,201,-26.90706814588,-38.941432993335,51.30713823367,2,1,18 +2025-03-11T12:40:04.623535,479392804,65439,201,-26.69031630136,-38.719246509345,50.89927227772,2,1,18 +2025-03-11T12:40:04.639160,479392804,65439,201,-26.45471647036,-38.497027413495,50.50062156388,2,1,18 +2025-03-11T12:40:04.654785,479392804,65439,201,-26.23325262922,-38.279453848365,50.08814618386,2,1,18 +2025-03-11T12:40:04.670410,479392804,65439,201,-26.00707679146,-38.05262998662,49.684869308965,2,1,18 +2025-03-11T12:40:04.686035,479392804,65439,201,-25.79503694356,-37.811967368295,49.272314790955,2,1,18 +2025-03-11T12:40:04.701660,479392804,65439,201,-25.55943711256,-37.580506128795,48.845899898725,2,1,18 +2025-03-11T12:40:04.717285,479392804,65439,201,-25.32854927818,-37.35829518591,48.396422952175,2,1,18 +2025-03-11T12:40:04.732910,479392804,65439,201,-25.0976614438,-37.1314631712,47.97927574708,2,1,18 +2025-03-11T12:40:04.748535,479392804,65439,201,-24.86677360942,-36.89538901284,47.54822791279,2,1,18 +2025-03-11T12:40:04.764160,479392804,65439,201,-24.63117377842,-36.659306701515,47.135658029755,2,1,18 +2025-03-11T12:40:04.779785,479392804,65439,201,-24.40028594404,-36.423232543155,46.723094927725,2,1,18 +2025-03-11T12:40:04.795410,479392804,65439,201,-24.15997411642,-36.187142078865,46.29665471449,2,1,18 +2025-03-11T12:40:04.811035,479392804,65439,201,-23.93379827866,-35.96031821712,45.87027192427,2,1,18 +2025-03-11T12:40:04.826660,479392804,65439,201,-23.71233443752,-35.710397149215,45.4114549336,2,1,18 +2025-03-11T12:40:04.842285,479392804,65439,201,-23.48144660314,-35.45121763173,44.98031439931,2,1,18 +2025-03-11T12:40:04.857910,479392804,65439,201,-23.2364227789,-35.224361158125,44.558525668135,2,1,18 +2025-03-11T12:40:04.873535,479392804,65439,201,-22.9772629648,-34.997480225625,44.10436831249,2,1,18 +2025-03-11T12:40:04.889160,479392804,65439,201,-22.7181031507,-34.747493934,43.631633524585,2,1,18 +2025-03-11T12:40:04.904785,479392804,65439,201,-22.4589433366,-34.49288657055,43.17736492894,2,1,18 +2025-03-11T12:40:04.920410,479392804,65439,201,-22.20449551912,-34.25215057554,42.727779917365,2,1,18 +2025-03-11T12:40:04.936035,479392804,65439,201,-21.96889568812,-33.997583976915,42.292029959005,2,1,18 +2025-03-11T12:40:04.951660,479392804,65439,201,-21.73329585712,-33.74301737829,41.847037634515,2,1,18 +2025-03-11T12:40:04.967285,479392804,65439,201,-21.4929840295,-33.4884426267,41.38355379676,2,1,18 +2025-03-11T12:40:04.982910,479392804,65439,201,-21.24324820864,-33.238472641005,40.89696902167,2,1,18 +2025-03-11T12:40:04.998535,479392804,65439,201,-20.97937639792,-32.98385712459,40.43345127889,2,1,18 +2025-03-11T12:40:05.014160,479392804,65439,201,-20.72492858044,-32.729257914105,40.011537745705,2,1,18 +2025-03-11T12:40:05.029785,479392804,65439,201,-20.48932874944,-32.470070243655,39.57114806428,2,1,18 +2025-03-11T12:40:05.045410,479392804,65439,201,-20.23959292858,-32.206237042485,39.11223476758,2,1,18 +2025-03-11T12:40:05.061035,479392804,65439,201,-19.98985710772,-31.951645984965,38.639495001685,2,1,18 +2025-03-11T12:40:05.076660,479392804,65439,201,-19.73069729362,-31.70165969334,38.15751784765,2,1,18 +2025-03-11T12:40:05.092285,479392804,65439,201,-19.45740148966,-31.44240679917,37.70321036899,2,1,18 +2025-03-11T12:40:05.107910,479392804,65439,201,-19.19824167556,-31.183178363895,37.239680867215,2,1,18 +2025-03-11T12:40:05.123535,479392804,65439,201,-18.95321785132,-30.923974387515,36.766929342325,2,1,18 +2025-03-11T12:40:05.139160,479392804,65439,201,-18.69877003384,-30.66937517703,36.28031924623,2,1,18 +2025-03-11T12:40:05.154785,479392804,65439,201,-18.44432221636,-30.41015489472,35.7983117932,2,1,18 +2025-03-11T12:40:05.170410,479392804,65439,201,-18.18516240226,-30.150926459445,35.33016110836,2,1,18 +2025-03-11T12:40:05.186035,479392804,65439,201,-17.90715460168,-29.896286484135,34.84351710724,2,1,18 +2025-03-11T12:40:05.201660,479392804,65439,201,-17.6527067842,-29.637066201825,34.34302492195,2,1,18 +2025-03-11T12:40:05.217285,479392804,65439,201,-17.39825896672,-29.368603775865,33.86098038892,2,1,18 +2025-03-11T12:40:05.232910,479392804,65439,201,-17.12025116614,-29.095479513255,33.388125776995,2,1,18 +2025-03-11T12:40:05.248535,479392804,65439,201,-16.84695536218,-28.82236340361,32.924520312205,2,1,18 +2025-03-11T12:40:05.264160,479392804,65439,201,-16.57365955822,-28.558489437615,32.43784601209,2,1,18 +2025-03-11T12:40:05.279785,479392804,65439,201,-16.30036375426,-28.27613118432,31.932612819715,2,1,18 +2025-03-11T12:40:05.295410,479392804,65439,201,-16.03649194354,-27.99841030878,31.413548180155,2,1,18 +2025-03-11T12:40:05.311035,479392804,65439,201,-15.77262013282,-27.71144728959,30.912931192855,2,1,18 +2025-03-11T12:40:05.326660,479392804,65439,201,-15.50403632548,-27.452202548385,30.426282213745,2,1,18 +2025-03-11T12:40:05.342285,479392804,65439,201,-15.2260285249,-27.19294150125,29.94424085569,2,1,18 +2025-03-11T12:40:05.357910,479392804,65439,201,-14.94802072432,-26.91981723864,29.44828032844,2,1,18 +2025-03-11T12:40:05.373535,479392804,65439,201,-14.68886091022,-26.651346659715,28.956986648275,2,1,18 +2025-03-11T12:40:05.389160,479392804,65439,201,-14.41556510626,-26.373609478245,28.4517719959,2,1,18 +2025-03-11T12:40:05.404785,479392804,65439,201,-14.12813331244,-26.091226766055,27.960382009705,2,1,18 +2025-03-11T12:40:05.420410,479392804,65439,201,-13.84541351524,-25.80885220683,27.44589288919,2,1,18 +2025-03-11T12:40:05.436035,479392804,65439,201,-13.57211771128,-25.517251809885,26.94524379988,2,1,18 +2025-03-11T12:40:05.451660,479392804,65439,201,-13.31295789718,-25.23953908731,26.444670673585,2,1,18 +2025-03-11T12:40:05.467285,479392804,65439,201,-13.0349500966,-24.971035896525,25.930243954075,2,1,18 +2025-03-11T12:40:05.482910,479392804,65439,201,-12.7522302994,-24.6886613373,25.411133650495,2,1,18 +2025-03-11T12:40:05.498535,479392804,65439,201,-12.48364649206,-24.401690165145,24.90126751606,2,1,18 +2025-03-11T12:40:05.514160,479392804,65439,201,-12.20092669486,-24.11931560592,24.396020761675,2,1,18 +2025-03-11T12:40:05.529785,479392804,65439,201,-11.9040709078,-23.8369165878,23.853784199755,2,1,18 +2025-03-11T12:40:05.545410,479392804,65439,201,-11.62606310722,-23.56379232519,23.33471775718,2,1,18 +2025-03-11T12:40:05.561035,479392804,65439,201,-11.34805530664,-23.295289134405,22.83877576993,2,1,18 +2025-03-11T12:40:05.576660,479392804,65439,201,-11.06062351282,-23.003664278565,22.319621605345,2,1,18 +2025-03-11T12:40:05.592285,479392804,65439,201,-10.78261571224,-22.702813585005,21.814307471965,2,1,18 +2025-03-11T12:40:05.607910,479392804,65439,201,-10.49989591504,-22.415817953955,21.295178628385,2,1,18 +2025-03-11T12:40:05.623535,479392804,65439,201,-10.21246412122,-22.12881416994,20.75755827154,2,1,18 +2025-03-11T12:40:05.639160,479392804,65439,201,-9.92974432402,-21.84181853889,20.233808244895,2,1,18 +2025-03-11T12:40:05.654785,479392804,65439,201,-9.63760053358,-21.55480660191,19.705423473175,2,1,18 +2025-03-11T12:40:05.670410,479392804,65439,201,-9.35488073638,-21.25856882721,19.195499915725,2,1,18 +2025-03-11T12:40:05.686035,479392804,65439,201,-9.06744894256,-20.97618611502,18.671761648075,2,1,18 +2025-03-11T12:40:05.701660,479392804,65439,201,-8.78001714874,-20.698424474655,18.14342073736,2,1,18 +2025-03-11T12:40:05.717285,479392804,65439,201,-8.48316136168,-20.42064652836,17.60120271544,2,1,18 +2025-03-11T12:40:05.732910,479392804,65439,201,-8.19572956786,-20.13826381617,17.05897971553,2,1,18 +2025-03-11T12:40:05.748535,479392804,65439,201,-7.90829777404,-19.842017888505,16.530564644815,2,1,18 +2025-03-11T12:40:05.764160,479392804,65439,201,-7.61144198698,-19.53651351126,16.02058366435,2,1,18 +2025-03-11T12:40:05.779785,479392804,65439,201,-7.31929819654,-19.244880502455,15.49218035263,2,1,18 +2025-03-11T12:40:05.795410,479392804,65439,201,-7.03657839934,-18.948642727755,14.95452969679,2,1,18 +2025-03-11T12:40:05.811035,479392804,65439,201,-6.7444346089,-18.643146503475,14.4353131312,2,1,18 +2025-03-11T12:40:05.826660,479392804,65439,201,-6.45229081846,-18.35151349467,13.911531002545,2,1,18 +2025-03-11T12:40:05.842285,479392804,65439,201,-6.1554350314,-18.073735548375,13.369312980625,2,1,18 +2025-03-11T12:40:05.857910,479392804,65439,201,-5.8727152342,-17.77287670185,12.822401418655,2,1,18 +2025-03-11T12:40:05.873535,479392804,65439,201,-5.58057144376,-17.481243693045,12.28937692387,2,1,18 +2025-03-11T12:40:05.889160,479392804,65439,201,-5.2837156567,-17.189602531275,11.74710328195,2,1,18 +2025-03-11T12:40:05.904785,479392804,65439,201,-4.99628386288,-16.90259874726,11.200240558975,2,1,18 +2025-03-11T12:40:05.920410,479392804,65439,201,-4.6947160792,-16.6063283607,10.662562779115,2,1,18 +2025-03-11T12:40:05.936035,479392804,65439,201,-4.40257228876,-16.30083213642,10.143346213525,2,1,18 +2025-03-11T12:40:05.951660,479392804,65439,201,-4.11042849832,-16.00457805579,9.624166727935,2,1,18 +2025-03-11T12:40:05.967285,479392804,65439,201,-3.81357271126,-15.71293689402,9.07727190295,2,1,18 +2025-03-11T12:40:05.982910,479392804,65439,201,-3.52142892082,-15.412061741565,8.544210328165,2,1,18 +2025-03-11T12:40:05.998458,479392808,65434,202,-3.22457313376,-15.11579950797,7.98805459705,2,1,18 +2025-03-11T12:40:06.014083,479392808,65434,202,-2.93242934332,-14.814924355515,7.45961420533,2,1,18 +2025-03-11T12:40:06.029708,479392808,65434,202,-2.62614956302,-14.523266887815,6.92656936753,2,1,18 +2025-03-11T12:40:06.045333,479392808,65434,202,-2.33400577258,-14.23163387901,6.37043895742,2,1,18 +2025-03-11T12:40:06.060958,479392808,65434,202,-2.0324379889,-13.921500276975,5.828084374495,2,1,18 +2025-03-11T12:40:06.076583,479392808,65434,202,-1.7261582086,-13.620600665625,5.29962363976,2,1,18 +2025-03-11T12:40:06.092208,479392808,65434,202,-1.4434384114,-13.32898396275,4.748127974725,2,1,18 +2025-03-11T12:40:06.107833,479392808,65434,202,-1.1371586311,-13.01884220775,4.21963015999,2,1,18 +2025-03-11T12:40:06.123458,479392808,65434,202,-0.81674286094,-12.727160281155,3.66345906385,2,1,18 +2025-03-11T12:40:06.139083,479392808,65434,202,-0.51988707388,-12.44014019121,3.107340412735,2,1,18 +2025-03-11T12:40:06.154708,479392808,65434,202,-0.23245528006,-12.12078890442,2.57883264202,2,1,18 +2025-03-11T12:40:06.170333,479392808,65434,202,0.06911250362,-11.819897446035,2.036515139095,2,1,18 +2025-03-11T12:40:06.185958,479392808,65434,202,0.38010428054,-11.52823182537,1.480357604965,2,1,18 +2025-03-11T12:40:06.201583,479392808,65434,202,0.68167206422,-11.245824654285,0.92887189591,2,1,18 +2025-03-11T12:40:06.217208,479392808,65434,202,0.96910385804,-10.94033658297,0.381935012935,2,1,18 +2025-03-11T12:40:06.232833,479392808,65434,202,1.25182365524,-10.630235592795,-0.16039244597,2,1,18 +2025-03-11T12:40:06.248458,479392808,65434,202,1.53925544906,-10.33398966513,-0.698049882815,2,1,18 +2025-03-11T12:40:06.264083,479392808,65434,202,1.8313992395,-10.023872369025,-1.24039090373,2,1,18 +2025-03-11T12:40:06.279708,479392808,65434,202,2.12354302994,-9.71375507292,-1.79659547384,2,1,18 +2025-03-11T12:40:06.295333,479392808,65434,202,2.43453480686,-9.422089452255,-2.34351064184,2,1,18 +2025-03-11T12:40:06.310958,479392808,65434,202,2.74081458716,-9.11656876908,-2.88585346577,2,1,18 +2025-03-11T12:40:06.326583,479392808,65434,202,3.03767037422,-8.820306535485,-3.432766830755,2,1,18 +2025-03-11T12:40:06.342208,479392808,65434,202,3.3392381579,-8.524036148925,-3.998171709005,2,1,18 +2025-03-11T12:40:06.357833,479392808,65434,202,3.63138194834,-8.21391885282,-4.54975509605,2,1,18 +2025-03-11T12:40:06.373458,479392808,65434,202,3.92352573878,-7.91766477219,-5.092040496965,2,1,18 +2025-03-11T12:40:06.389083,479392808,65434,202,4.22980551908,-7.621386232665,-5.625103874765,2,1,18 +2025-03-11T12:40:06.404708,479392808,65434,202,4.5172373129,-7.31589816135,-6.18128312387,2,1,18 +2025-03-11T12:40:06.420333,479392808,65434,202,4.82822908982,-7.005748253385,-6.737514818,2,1,18 +2025-03-11T12:40:06.435958,479392808,65434,202,5.13450887012,-6.704848642035,-7.265975552735,2,1,18 +2025-03-11T12:40:06.451583,479392808,65434,202,5.43136465718,-6.39934426479,-7.82216836385,2,1,18 +2025-03-11T12:40:06.467208,479392808,65434,202,5.74706843072,-6.103049419335,-8.369108852855,2,1,18 +2025-03-11T12:40:06.482833,479392808,65434,202,6.03921222116,-5.81141641053,-8.915996896835,2,1,18 +2025-03-11T12:40:06.498458,479392808,65434,202,6.3313560116,-5.5151623299,-9.453661114685,2,1,18 +2025-03-11T12:40:06.514083,479392808,65434,202,6.63292379528,-5.21889194334,-9.99596007761,2,1,18 +2025-03-11T12:40:06.529708,479392808,65434,202,6.93920357558,-4.922613403815,-10.52902345541,2,1,18 +2025-03-11T12:40:06.545333,479392808,65434,202,7.22192337278,-4.617133485465,-11.080574740445,2,1,18 +2025-03-11T12:40:06.560958,479392808,65434,202,7.51406716322,-4.32550047666,-11.636705150555,2,1,18 +2025-03-11T12:40:06.576583,479392808,65434,202,7.80149895704,-4.038496692645,-12.1743255074,2,1,18 +2025-03-11T12:40:06.592208,479392808,65434,202,8.0983547441,-3.728371243575,-12.70743094319,2,1,18 +2025-03-11T12:40:06.607833,479392808,65434,202,8.40934652102,-3.413600263785,-13.27292354345,2,1,18 +2025-03-11T12:40:06.623458,479392808,65434,202,8.71562630132,-3.10807958061,-13.810645184315,2,1,18 +2025-03-11T12:40:06.639083,479392808,65434,202,9.01248208838,-2.82568056249,-14.34826056317,2,1,18 +2025-03-11T12:40:06.654708,479392808,65434,202,9.30462587882,-2.534047553685,-14.88590624102,2,1,18 +2025-03-11T12:40:06.670333,479392808,65434,202,9.61090565912,-2.242390085985,-15.40970871269,2,1,18 +2025-03-11T12:40:06.685958,479392808,65434,202,9.90776144618,-1.93688570874,-15.95203797461,2,1,18 +2025-03-11T12:40:06.701583,479392808,65434,202,10.19990523662,-1.62214734081,-16.48977635246,2,1,18 +2025-03-11T12:40:06.717208,479392808,65434,202,10.47320104058,-1.330546943865,-17.03663727242,2,1,18 +2025-03-11T12:40:06.732833,479392808,65434,202,10.7606328344,-1.0343010162,-17.57891589233,2,1,18 +2025-03-11T12:40:06.748458,479392808,65434,202,11.06220061808,-0.733409557815,-18.130475761385,2,1,18 +2025-03-11T12:40:06.764083,479392808,65434,202,11.36376840176,-0.44176024308,-18.66351381818,2,1,18 +2025-03-11T12:40:06.779708,479392808,65434,202,11.67004818206,-0.140860631729999,-19.210459285175,2,1,18 +2025-03-11T12:40:06.795333,479392808,65434,202,11.95747997588,0.155385295935001,-19.752737905085,2,1,18 +2025-03-11T12:40:06.810958,479392808,65434,202,12.24962376632,0.442397232914999,-20.28574385987,2,1,18 +2025-03-11T12:40:06.826583,479392808,65434,202,12.54647955338,0.72017517921,-20.814098332595,2,1,18 +2025-03-11T12:40:06.842208,479392808,65434,202,12.84804733706,1.01644556577,-21.361018478585,2,1,18 +2025-03-11T12:40:06.857833,479392808,65434,202,13.14961512074,1.33120023963,-21.917255150705,2,1,18 +2025-03-11T12:40:06.873458,479392808,65434,202,13.44175891118,1.632075392085,-22.45955909162,2,1,18 +2025-03-11T12:40:06.889083,479392808,65434,202,13.73861469824,1.91909548203,-22.99257182741,2,1,18 +2025-03-11T12:40:06.904708,479392808,65434,202,14.03075848868,2.20610741901,-23.507093049935,2,1,18 +2025-03-11T12:40:06.920333,479392808,65434,202,14.30876628926,2.49771596892,-24.030854835575,2,1,18 +2025-03-11T12:40:06.935958,479392808,65434,202,14.60562207632,2.79859927434,-24.56854437443,2,1,18 +2025-03-11T12:40:06.951583,479392808,65434,202,14.90247786338,3.09948257976,-25.096991547155,2,1,18 +2025-03-11T12:40:06.967208,479392808,65434,202,15.18519766058,3.39572035446,-25.625399836865,2,1,18 +2025-03-11T12:40:06.982833,479392808,65434,202,15.46791745778,3.678094913685,-26.14913132351,2,1,18 +2025-03-11T12:40:06.998458,479392808,65434,202,15.76006124822,3.96048577884,-26.663634006035,2,1,18 +2025-03-11T12:40:07.014083,479392808,65434,202,16.05691703528,4.24288479696,-27.187385835695,2,1,18 +2025-03-11T12:40:07.029708,479392808,65434,202,16.33963683248,4.52063828436,-27.715719965405,2,1,18 +2025-03-11T12:40:07.045333,479392808,65434,202,16.62235662968,4.821497130885,-28.24876797818,2,1,18 +2025-03-11T12:40:07.060958,479392808,65434,202,16.91450042012,5.108509067865,-28.79563748216,2,1,18 +2025-03-11T12:40:07.076583,479392808,65434,202,17.21135620718,5.39552915781,-29.31940785182,2,1,18 +2025-03-11T12:40:07.092208,479392808,65434,202,17.49407600438,5.69176693251,-29.8385737754,2,1,18 +2025-03-11T12:40:07.107833,479392808,65434,202,17.79093179144,5.969544878805,-30.366928248125,2,1,18 +2025-03-11T12:40:07.123458,479392808,65434,202,18.07836358526,6.25654866282,-30.87682150658,2,1,18 +2025-03-11T12:40:07.139083,479392808,65434,202,18.34223539598,6.538890610185,-31.38666232001,2,1,18 +2025-03-11T12:40:07.154708,479392808,65434,202,18.6061072067,6.807369342075,-31.89644751344,2,1,18 +2025-03-11T12:40:07.170333,479392808,65434,202,18.8888270039,7.103607116775,-32.420234620085,2,1,18 +2025-03-11T12:40:07.185958,479392808,65434,202,19.18097079434,7.39524012558,-32.930153199545,2,1,18 +2025-03-11T12:40:07.201583,479392808,65434,202,19.46369059154,7.677614684805,-33.421536404735,2,1,18 +2025-03-11T12:40:07.217208,479392808,65434,202,19.74169839212,7.959981091065,-33.93139756118,2,1,18 +2025-03-11T12:40:07.232833,479392808,65434,202,20.01499419608,8.22385505706,-34.45966250888,2,1,18 +2025-03-11T12:40:07.248458,479392808,65434,202,20.29300199666,8.501600391495,-34.97412630839,2,1,18 +2025-03-11T12:40:07.264083,479392808,65434,202,20.57100979724,8.802451085055,-35.47944044177,2,1,18 +2025-03-11T12:40:07.279708,479392808,65434,202,20.85372959444,9.08482564428,-35.975444830025,2,1,18 +2025-03-11T12:40:07.295333,479392808,65434,202,21.13644939164,9.357958059855,-36.48065450441,2,1,18 +2025-03-11T12:40:07.310958,479392808,65434,202,21.4097451956,9.6310741695,-36.98122943372,2,1,18 +2025-03-11T12:40:07.326583,479392808,65434,202,21.69717698942,9.908835809865,-37.48646442911,2,1,18 +2025-03-11T12:40:07.342208,479392808,65434,202,21.97518479,10.17733900065,-37.99164878249,2,1,18 +2025-03-11T12:40:07.357833,479392808,65434,202,22.24848059396,10.45507618212,-38.50148461793,2,1,18 +2025-03-11T12:40:07.373458,479392808,65434,202,22.51235240468,10.728175985835,-39.00204598523,2,1,18 +2025-03-11T12:40:07.389083,479392808,65434,202,22.7762242154,11.00127578955,-39.48412262027,2,1,18 +2025-03-11T12:40:07.404708,479392808,65434,202,23.04009602612,11.28823880874,-39.970876058375,2,1,18 +2025-03-11T12:40:07.420333,479392808,65434,202,23.3181038267,11.556741999525,-40.47143922869,2,1,18 +2025-03-11T12:40:07.435958,479392808,65434,202,23.59611162728,11.81600304666,-40.97658650207,2,1,18 +2025-03-11T12:40:07.451583,479392808,65434,202,23.86469543462,12.066005644215,-41.477061950375,2,1,18 +2025-03-11T12:40:07.467208,479392808,65434,202,24.14741523182,12.343759131615,-41.968426615565,2,1,18 +2025-03-11T12:40:07.482833,479392808,65434,202,24.4254230324,12.62150446605,-42.45978449975,2,1,18 +2025-03-11T12:40:07.498458,479392808,65434,202,24.69400683974,12.89461242273,-42.941867915795,2,1,18 +2025-03-11T12:40:07.514083,479392808,65434,202,24.9437426606,13.16768776755,-43.428545390885,2,1,18 +2025-03-11T12:40:07.529708,479392808,65434,202,25.2029024747,13.436158346475,-43.915217887985,2,1,18 +2025-03-11T12:40:07.545333,479392808,65434,202,25.46677428542,13.68153171924,-44.39256209996,2,1,18 +2025-03-11T12:40:07.560958,479392808,65434,202,25.73535809276,13.93615538862,-44.86070780681,2,1,18 +2025-03-11T12:40:07.576583,479392808,65434,202,25.99451790686,14.22773132667,-45.32898827165,2,1,18 +2025-03-11T12:40:07.592208,479392808,65434,202,26.25838971758,14.47772577126,-45.82021457282,2,1,18 +2025-03-11T12:40:07.607833,479392808,65434,202,26.5222615283,14.72772021585,-46.288334958665,2,1,18 +2025-03-11T12:40:07.623458,479392808,65434,202,26.78613333902,14.973093588615,-46.76567917064,2,1,18 +2025-03-11T12:40:07.639083,479392808,65434,202,27.03586915988,15.246168933435,-47.2431142796,2,1,18 +2025-03-11T12:40:07.654708,479392808,65434,202,27.29031697736,15.51925243122,-47.720556169565,2,1,18 +2025-03-11T12:40:07.670333,479392808,65434,202,27.54476479484,15.783093785355,-48.193339796465,2,1,18 +2025-03-11T12:40:07.685958,479392808,65434,202,27.78978861908,16.02843454626,-48.65217215216,2,1,18 +2025-03-11T12:40:07.701583,479392808,65434,202,28.04894843318,16.27379976606,-49.106403667805,2,1,18 +2025-03-11T12:40:07.717208,479392808,65434,202,28.30339625066,16.52377790472,-49.560646942445,2,1,18 +2025-03-11T12:40:07.732833,479392808,65434,202,28.5484200749,16.778360809275,-50.02875874427,2,1,18 +2025-03-11T12:40:07.748458,479392808,65434,202,28.79815589576,17.03757293862,-50.48765350097,2,1,18 +2025-03-11T12:40:07.764083,479392808,65434,202,29.05731570986,17.30142244572,-50.94658035968,2,1,18 +2025-03-11T12:40:07.779708,479392808,65434,202,29.31176352734,17.55140058438,-51.377717718995,2,1,18 +2025-03-11T12:40:07.795333,479392808,65434,202,29.55678735158,17.79212027346,-51.831910351625,2,1,18 +2025-03-11T12:40:07.810958,479392808,65434,202,29.80181117582,18.03283996254,-52.276860618125,2,1,18 +2025-03-11T12:40:07.826583,479392808,65434,202,30.05154699668,18.282809948235,-52.717233562565,2,1,18 +2025-03-11T12:40:07.842208,479392808,65434,202,30.29657082092,18.523529637315,-53.157562646,2,1,18 +2025-03-11T12:40:07.857833,479392808,65434,202,30.54159464516,18.773491470045,-53.6025499925,2,1,18 +2025-03-11T12:40:07.873458,479392808,65434,202,30.77719447616,19.014194853195,-54.03824433086,2,1,18 +2025-03-11T12:40:07.889083,479392808,65434,202,31.01750630378,19.241043173835,-54.483132196355,2,1,18 +2025-03-11T12:40:07.904708,479392808,65434,202,31.25310613478,19.481746556985,-54.918826534715,2,1,18 +2025-03-11T12:40:07.920333,479392808,65434,202,31.4934179624,19.708594877625,-55.34522966795,2,1,18 +2025-03-11T12:40:07.935958,479392808,65434,202,31.74786577988,19.94470980081,-55.776311407265,2,1,18 +2025-03-11T12:40:07.951583,479392808,65434,202,31.98346561088,20.180792112135,-56.21660838869,2,1,18 +2025-03-11T12:40:07.967208,479392808,65434,202,32.2002174554,20.40759966795,-56.6429776169,2,1,18 +2025-03-11T12:40:07.982833,479392808,65434,202,32.44052928302,20.66217441954,-57.060249624005,2,1,18 +2025-03-11T12:40:07.998458,479392808,65434,202,32.66199312416,20.912095487445,-57.47747596709,2,1,18 +2025-03-11T12:40:08.014083,479392808,65434,202,32.88816896192,21.134298277365,-57.880734301985,2,1,18 +2025-03-11T12:40:08.029708,479392808,65434,202,33.13319278616,21.356533679145,-58.32098922542,2,1,18 +2025-03-11T12:40:08.045333,479392808,65434,202,33.3546566273,21.58797045975,-58.738141408505,2,1,18 +2025-03-11T12:40:08.060958,479392808,65434,202,33.57612046844,21.81478616853,-59.122926770135,2,1,18 +2025-03-11T12:40:08.076583,479392808,65434,202,33.79287231296,22.03697265252,-59.52617154302,2,1,18 +2025-03-11T12:40:08.092208,479392808,65434,202,34.01904815072,22.254554370615,-59.957138436305,2,1,18 +2025-03-11T12:40:08.107833,479392808,65434,202,34.2499359851,22.472144241675,-60.3742485614,2,1,18 +2025-03-11T12:40:08.123458,479392808,65434,202,34.47611182286,22.69896810342,-60.777525436295,2,1,18 +2025-03-11T12:40:08.139083,479392808,65434,202,34.69286366738,22.916533515585,-61.185372852245,2,1,18 +2025-03-11T12:40:08.154708,479392808,65434,202,34.90019151866,23.157187980945,-61.593299406185,2,1,18 +2025-03-11T12:40:08.170333,479392808,65434,202,35.13579134966,23.388649220445,-62.001229566155,2,1,18 +2025-03-11T12:40:08.185958,479392808,65434,202,35.35254319418,23.58773034531,-62.390518089845,2,1,18 +2025-03-11T12:40:08.201583,479392808,65434,202,35.57400703532,23.80530391044,-62.775266371475,2,1,18 +2025-03-11T12:40:08.217208,479392808,65434,202,35.79547087646,24.018256403745,-63.169238479235,2,1,18 +2025-03-11T12:40:08.232833,479392808,65434,202,35.99808673112,24.23117628519,-63.55856227991,2,1,18 +2025-03-11T12:40:08.248458,479392808,65434,202,36.19599058916,24.439466941845,-63.933997210385,2,1,18 +2025-03-11T12:40:08.264083,479392808,65434,202,36.41274243368,24.643169138535,-64.30944072488,2,1,18 +2025-03-11T12:40:08.279708,479392808,65434,202,36.61064629172,24.85145979519,-64.69873920455,2,1,18 +2025-03-11T12:40:08.295333,479392808,65434,202,36.81326214638,25.064379676635,-65.088063005225,2,1,18 +2025-03-11T12:40:08.310958,479392808,65434,202,37.01587800104,25.281920629905,-65.435814698315,2,1,18 +2025-03-11T12:40:08.326583,479392808,65434,202,37.20435786584,25.476331765155,-65.797316897585,2,1,18 +2025-03-11T12:40:08.342208,479392808,65434,202,37.40226172388,25.680001349985,-66.177354471125,2,1,18 +2025-03-11T12:40:08.357833,479392808,65434,202,37.61430157178,25.888316465535,-66.55743092768,2,1,18 +2025-03-11T12:40:08.373458,479392808,65434,202,37.81220542982,26.08736497854,-66.92820759509,2,1,18 +2025-03-11T12:40:08.389083,479392808,65434,202,38.0195332811,26.28180872565,-67.28049455225,2,1,18 +2025-03-11T12:40:08.404708,479392808,65434,202,38.22214913576,26.485486463445,-67.62819062534,2,1,18 +2025-03-11T12:40:08.420333,479392808,65434,202,38.4200529938,26.66605068915,-67.98040840049,2,1,18 +2025-03-11T12:40:08.435958,479392808,65434,202,38.61324485522,26.860469977365,-68.341917380765,2,1,18 +2025-03-11T12:40:08.451583,479392808,65434,202,38.7970127234,27.068736175125,-68.680362503705,2,1,18 +2025-03-11T12:40:08.467208,479392808,65434,202,38.97606859496,27.26775207627,-69.023384948705,2,1,18 +2025-03-11T12:40:08.482833,479392808,65434,202,39.16454845976,27.439057852395,-69.357067349585,2,1,18 +2025-03-11T12:40:08.498458,479392808,65434,202,39.35302832456,27.61036362852,-69.72309803192,2,1,18 +2025-03-11T12:40:08.514083,479392808,65434,202,39.5509321826,27.781685710575,-70.04755162868,2,1,18 +2025-03-11T12:40:08.529708,479392808,65434,202,39.75354803726,27.971500232895,-70.37670734951,2,1,18 +2025-03-11T12:40:08.545333,479392808,65434,202,39.92317991558,28.14277339716,-70.7196049925,2,1,18 +2025-03-11T12:40:08.560958,479392808,65434,202,40.09752379052,28.32329685804,-71.053304130365,2,1,18 +2025-03-11T12:40:08.576583,479392808,65434,202,40.27657966208,28.51769168736,-71.38244448617,2,1,18 +2025-03-11T12:40:08.592208,479392808,65434,202,40.45092353702,28.70745729189,-71.71155952097,2,1,18 +2025-03-11T12:40:08.607833,479392808,65434,202,40.62055541534,28.89259367163,-72.022164502505,2,1,18 +2025-03-11T12:40:08.623458,479392808,65434,202,40.7996112869,29.06850421365,-72.337367149115,2,1,18 +2025-03-11T12:40:08.639083,479392808,65434,202,40.97866715846,29.239793683845,-72.66641480492,2,1,18 +2025-03-11T12:40:08.654708,479392808,65434,202,41.1530110334,29.40645392925,-72.97695240746,2,1,18 +2025-03-11T12:40:08.670333,479392808,65434,202,41.33206690496,29.57312232762,-73.287496791005,2,1,18 +2025-03-11T12:40:08.685958,479392808,65434,202,41.49227479004,29.744379185955,-73.593411407465,2,1,18 +2025-03-11T12:40:08.701583,479392808,65434,202,41.66190666836,29.911031278395,-73.890078679805,2,1,18 +2025-03-11T12:40:08.717208,479392808,65434,202,41.82211455344,30.068424921255,-74.1913164932,2,1,18 +2025-03-11T12:40:08.732833,479392808,65434,202,41.98232243852,30.244302851415,-74.474143734335,2,1,18 +2025-03-11T12:40:08.748458,479392808,65434,202,42.14724232022,30.406325719065,-74.775406868735,2,1,18 +2025-03-11T12:40:08.764083,479392808,65434,202,42.3074502053,30.563719361925,-75.05815994987,2,1,18 +2025-03-11T12:40:08.779708,479392808,65434,202,42.46294609376,30.716483779995,-75.35013007613,2,1,18 +2025-03-11T12:40:08.795333,479392808,65434,202,42.61844198222,30.860006054415,-75.65130548852,2,1,18 +2025-03-11T12:40:08.810958,479392808,65434,202,42.77393787068,31.01739154431,-75.938672971715,2,1,18 +2025-03-11T12:40:08.826583,479392808,65434,202,42.92472176252,31.17476888124,-76.226033673905,2,1,18 +2025-03-11T12:40:08.842208,479392808,65434,202,43.0849296476,31.327541452275,-76.49952584891,2,1,18 +2025-03-11T12:40:08.857833,479392808,65434,202,43.23571353944,31.466434501905,-76.7868123911,2,1,18 +2025-03-11T12:40:08.873458,479392808,65434,202,43.38649743128,31.60994862336,-77.06487510716,2,1,18 +2025-03-11T12:40:08.889083,479392808,65434,202,43.52785732988,31.762688582535,-77.30599187669,2,1,18 +2025-03-11T12:40:08.904708,479392808,65434,202,43.66921722848,31.920049613535,-77.560990735415,2,1,18 +2025-03-11T12:40:08.920333,479392808,65434,202,43.82000112032,32.06356373499,-77.829811085345,2,1,18 +2025-03-11T12:40:08.935958,479392808,65434,202,43.9566490223,32.1978112539,-78.08008928,2,1,18 +2025-03-11T12:40:08.951583,479392808,65434,202,44.0980089209,32.34593014125,-78.335051058725,2,1,18 +2025-03-11T12:40:08.967208,479392808,65434,202,44.2393688195,32.48480688495,-78.566869842125,2,1,18 +2025-03-11T12:40:08.982833,479392808,65434,202,44.37130472486,32.619046250895,-78.81252007271,2,1,18 +2025-03-11T12:40:08.998458,479392808,65434,202,44.48910464036,32.74864008612,-79.071994969475,2,1,18 +2025-03-11T12:40:09.014083,479392808,65434,202,44.63046453896,32.873653614345,-79.322242865135,2,1,18 +2025-03-11T12:40:09.029708,479392808,65434,202,44.79067242404,33.012562969905,-79.563331138685,2,1,18 +2025-03-11T12:40:09.045333,479392808,65434,202,44.91789633278,33.137552039235,-79.79507395907,2,1,18 +2025-03-11T12:40:09.060958,479392808,65434,202,45.0404082449,33.267154027425,-80.01758617232,2,1,18 +2025-03-11T12:40:09.076583,479392808,65434,202,45.16292015702,33.39213494379,-80.2493222117,2,1,18 +2025-03-11T12:40:09.092208,479392808,65434,202,45.2760080759,33.52172062605,-80.46257849681,2,1,18 +2025-03-11T12:40:09.107833,479392808,65434,202,45.3938079914,33.651314461275,-80.6527356476,2,1,18 +2025-03-11T12:40:09.123458,479392808,65434,202,45.50689591028,33.76703692806,-80.870557495775,2,1,18 +2025-03-11T12:40:09.139083,479392808,65434,202,45.61998382916,33.87813832302,-81.08836080395,2,1,18 +2025-03-11T12:40:09.154708,479392808,65434,202,45.7472077379,33.989264176875,-81.310805638205,2,1,18 +2025-03-11T12:40:09.170333,479392808,65434,202,45.87443164664,34.10039003073,-81.519386923265,2,1,18 +2025-03-11T12:40:09.185958,479392808,65434,202,45.97809557228,34.216096191585,-81.732574026365,2,1,18 +2025-03-11T12:40:09.201583,479392808,65434,202,46.08647149454,34.313326218105,-81.941072567405,2,1,18 +2025-03-11T12:40:09.217208,479392808,65434,202,46.19955941342,34.41980654124,-82.13113023719,2,1,18 +2025-03-11T12:40:09.232833,479392808,65434,202,46.32678332216,34.54479561057,-82.33052477612,2,1,18 +2025-03-11T12:40:09.248458,479392808,65434,202,46.41631125794,34.646614097055,-82.52977236701,2,1,18 +2025-03-11T12:40:09.264083,479392808,65434,202,46.51055119034,34.74381966468,-82.71514464971,2,1,18 +2025-03-11T12:40:09.279708,479392808,65434,202,46.61421511598,34.85490475371,-82.90058611442,2,1,18 +2025-03-11T12:40:09.295333,479392808,65434,202,46.70845504838,34.97521568046,-83.099914646315,2,1,18 +2025-03-11T12:40:09.310958,479392808,65434,202,46.8309669605,35.081712309525,-83.27150114585,2,1,18 +2025-03-11T12:40:09.326583,479392808,65434,202,46.94405487938,35.165087273535,-83.433739017245,2,1,18 +2025-03-11T12:40:09.342208,479392808,65434,202,47.02887081854,35.25303439158,-83.591333559545,2,1,18 +2025-03-11T12:40:09.357833,479392808,65434,202,47.09483877122,35.34556996959,-83.76278306702,2,1,18 +2025-03-11T12:40:09.373458,479392808,65434,202,47.17965471038,35.43813815946,-83.934259698515,2,1,18 +2025-03-11T12:40:09.389083,479392808,65434,202,47.25033465968,35.512197603135,-84.096399460865,2,1,18 +2025-03-11T12:40:09.404708,479392808,65434,202,47.33515059884,35.586281505705,-84.253938383165,2,1,18 +2025-03-11T12:40:09.420333,479392808,65434,202,47.42467853462,35.66961570489,-84.40227880034,2,1,18 +2025-03-11T12:40:09.435958,479392808,65434,202,47.49535848392,35.74829622039,-84.559815919625,2,1,18 +2025-03-11T12:40:09.451583,479392808,65434,202,47.57546242646,35.813129826345,-84.712689797855,2,1,18 +2025-03-11T12:40:09.467208,479392808,65434,202,47.66970235886,35.90109325032,-84.83794962071,2,1,18 +2025-03-11T12:40:09.482833,479392808,65434,202,47.75451829802,35.96593500924,-84.96772436462,2,1,18 +2025-03-11T12:40:09.498458,479392808,65434,202,47.83462224056,36.03538968702,-85.106753233655,2,1,18 +2025-03-11T12:40:09.514083,479392808,65434,202,47.91001418648,36.10945728366,-85.245793861685,2,1,18 +2025-03-11T12:40:09.529708,479392808,65434,202,47.98069413578,36.202001014635,-85.36641713645,2,1,18 +2025-03-11T12:40:09.545333,479392808,65434,202,48.04666208846,36.276052305345,-85.500823019405,2,1,18 +2025-03-11T12:40:09.560958,479392808,65434,202,48.11263004114,36.331619308755,-85.630533559295,2,1,18 +2025-03-11T12:40:09.576583,479392808,65434,202,48.1738859972,36.410283518325,-85.737224102855,2,1,18 +2025-03-11T12:40:09.592208,479392808,65434,202,48.2445659465,36.479721890175,-85.853133494555,2,1,18 +2025-03-11T12:40:09.607833,479392808,65434,202,48.28697391608,36.530627056935,-85.959685674095,2,1,18 +2025-03-11T12:40:09.623458,479392808,65434,202,48.34822987214,36.609291266505,-86.07099740072,2,1,18 +2025-03-11T12:40:09.639083,479392808,65434,202,48.41890982144,36.67410856653,-86.182267069355,2,1,18 +2025-03-11T12:40:09.654708,479392808,65434,202,48.48487777412,36.706570210815,-86.27953662779,2,1,18 +2025-03-11T12:40:09.670333,479392808,65434,202,48.53670973694,36.75287061168,-86.362977914015,2,1,18 +2025-03-11T12:40:09.685958,479392808,65434,202,48.59325369638,36.822284524635,-86.465003413505,2,1,18 +2025-03-11T12:40:09.701583,479392808,65434,202,48.63566166596,36.87781076322,-86.562331766915,2,1,18 +2025-03-11T12:40:09.717208,479392808,65434,202,48.67335763892,36.92408670519,-86.66885862545,2,1,18 +2025-03-11T12:40:09.732833,479392808,65434,202,48.72047760512,36.96113680944,-86.756877233735,2,1,18 +2025-03-11T12:40:09.748458,479392808,65434,202,48.76759757132,36.99818691369,-86.831032292825,2,1,18 +2025-03-11T12:40:09.764083,479392808,65434,202,48.81942953414,37.03986624273,-86.90521267292,2,1,18 +2025-03-11T12:40:09.779708,479392808,65434,202,48.84770151386,37.09536802242,-86.974793584925,2,1,18 +2025-03-11T12:40:09.795333,479392808,65434,202,48.89010948344,37.13703104553,-87.03047567075,2,1,18 +2025-03-11T12:40:09.810958,479392808,65434,202,48.93722944964,37.169460077955,-87.099991006775,2,1,18 +2025-03-11T12:40:09.826583,479392808,65434,202,48.9749254226,37.20187280445,-87.164871597725,2,1,18 +2025-03-11T12:40:09.842208,479392808,65434,202,49.00319740232,37.22964815319,-87.220477720535,2,1,18 +2025-03-11T12:40:09.857833,479392808,65434,202,49.03146938204,37.271286717405,-87.276139463345,2,1,18 +2025-03-11T12:40:09.873458,479392808,65434,202,49.0456053719,37.28055331995,-87.32240871701,2,1,18 +2025-03-11T12:40:09.889083,479392808,65434,202,49.06445335838,37.31755450641,-87.36879599168,2,1,18 +2025-03-11T12:40:09.904708,479392808,65434,202,49.09743733472,37.34995907994,-87.41980625243,2,1,18 +2025-03-11T12:40:09.920333,479392808,65434,202,49.12099731782,37.377726275715,-87.475405594235,2,1,18 +2025-03-11T12:40:09.935958,479392808,65434,202,49.15398129416,37.382404418295,-87.49395633353,2,1,18 +2025-03-11T12:40:09.951583,479392808,65434,202,49.17754127726,37.39168732677,-87.52637560001,2,1,18 +2025-03-11T12:40:09.967208,479392808,65434,202,49.20110126036,37.40559130707,-87.572676955685,2,1,18 +2025-03-11T12:40:09.982833,479392808,65434,202,49.21994924684,37.419487134405,-87.59586561503,2,1,18 +2025-03-11T12:40:09.998397,479392812,65430,203,49.21523725022,37.424100053265,-87.61898328935,2,1,18 +2025-03-11T12:40:10.014022,479392812,65430,203,49.22937324008,37.44260879946,-87.6144566093,2,1,18 +2025-03-11T12:40:10.029647,479392812,65430,203,49.26235721642,37.451908013865,-87.62840470553,2,1,18 +2025-03-11T12:40:10.045272,479392812,65430,203,49.27178120966,37.470408607095,-87.65621952593,2,1,18 +2025-03-11T12:40:10.060897,479392812,65430,203,49.27178120966,37.479650750745,-87.660877788995,2,1,18 +2025-03-11T12:40:10.076522,479392812,65430,203,49.26706921304,37.465779382305,-87.66081538799,2,1,18 +2025-03-11T12:40:10.092147,479392812,65430,203,49.26235721642,37.47501337299,-87.66546687005,2,1,18 +2025-03-11T12:40:10.107772,479392812,65430,203,49.25293322318,37.47499706706,-87.66545330804,2,1,18 +2025-03-11T12:40:10.123397,479392812,65430,203,49.23879723332,37.465730464515,-87.67925943422,2,1,18 +2025-03-11T12:40:10.139022,479392812,65430,203,49.23879723332,37.46110939269,-87.68848326035,2,1,18 +2025-03-11T12:40:10.154647,479392812,65430,203,49.2340852367,37.4564801679,-87.679215573215,2,1,18 +2025-03-11T12:40:10.170272,479392812,65430,203,49.23879723332,37.44262510539,-87.656060818895,2,1,18 +2025-03-11T12:40:10.185897,479392812,65430,203,49.22937324008,37.43336665581,-87.63290426156,2,1,18 +2025-03-11T12:40:10.201522,479392812,65430,203,49.21994924684,37.419487134405,-87.60510798116,2,1,18 +2025-03-11T12:40:10.217147,479392812,65430,203,49.20581325698,37.39173624456,-87.568006933625,2,1,18 +2025-03-11T12:40:10.232772,479392812,65430,203,49.18225327388,37.36859012061,-87.526289681015,2,1,18 +2025-03-11T12:40:10.248397,479392812,65430,203,49.17282928064,37.36857381468,-87.48468547142,2,1,18 +2025-03-11T12:40:10.264022,479392812,65430,203,49.14455730092,37.354661681415,-87.461483250065,2,1,18 +2025-03-11T12:40:10.279647,479392812,65430,203,49.13042131106,37.322289719745,-87.419742479465,2,1,18 +2025-03-11T12:40:10.295272,479392812,65430,203,49.10214933134,37.303756514655,-87.37803698585,2,1,18 +2025-03-11T12:40:10.310897,479392812,65430,203,49.07858934824,37.280610390705,-87.31783500098,2,1,18 +2025-03-11T12:40:10.326522,479392812,65430,203,49.06445335838,37.24361735721,-87.243727408925,2,1,18 +2025-03-11T12:40:10.342147,479392812,65430,203,49.02675738542,37.21582570254,-87.21121363943,2,1,18 +2025-03-11T12:40:10.357772,479392812,65430,203,48.98434941584,37.169541607605,-87.16013419667,2,1,18 +2025-03-11T12:40:10.373397,479392812,65430,203,48.94194144626,37.12325751267,-87.09981238778,2,1,18 +2025-03-11T12:40:10.389022,479392812,65430,203,48.90895746992,37.09085293914,-87.016453845575,2,1,18 +2025-03-11T12:40:10.404647,479392812,65430,203,48.87126149696,37.067682356295,-86.94698915156,2,1,18 +2025-03-11T12:40:10.420272,479392812,65430,203,48.833565524,37.0352696298,-86.877487377545,2,1,18 +2025-03-11T12:40:10.435897,479392812,65430,203,48.78173356118,36.998211372585,-86.807946720515,2,1,18 +2025-03-11T12:40:10.451522,479392812,65430,203,48.72518960174,36.951902818755,-86.715256287155,2,1,18 +2025-03-11T12:40:10.467147,479392812,65430,203,48.68278163216,36.910239795645,-86.64108946907,2,1,18 +2025-03-11T12:40:10.482772,479392812,65430,203,48.64037366258,36.84547141341,-86.55296640179,2,1,18 +2025-03-11T12:40:10.498397,479392812,65430,203,48.60267768962,36.794574399615,-86.46028455245,2,1,18 +2025-03-11T12:40:10.514022,479392812,65430,203,48.5508457268,36.74827399875,-86.3537373509,2,1,18 +2025-03-11T12:40:10.529647,479392812,65430,203,48.48958977074,36.701957291955,-86.25641895347,2,1,18 +2025-03-11T12:40:10.545272,479392812,65430,203,48.4330458113,36.627922307175,-86.149753730915,2,1,18 +2025-03-11T12:40:10.560897,479392812,65430,203,48.3859258451,36.55852470015,-86.047741793435,2,1,18 +2025-03-11T12:40:10.576522,479392812,65430,203,48.31995789242,36.507578768565,-85.950398075,2,1,18 +2025-03-11T12:40:10.592147,479392812,65430,203,48.26341393298,36.45664914291,-85.825340820185,2,1,18 +2025-03-11T12:40:10.607772,479392812,65430,203,48.1974459803,36.387218924025,-85.704817026425,2,1,18 +2025-03-11T12:40:10.623397,479392812,65430,203,48.126766031,36.317780552175,-85.58428645166,2,1,18 +2025-03-11T12:40:10.639022,479392812,65430,203,48.05137408508,36.252955099185,-85.47301000202,2,1,18 +2025-03-11T12:40:10.654647,479392812,65430,203,47.9854061324,36.178903808475,-85.338604119065,2,1,18 +2025-03-11T12:40:10.670272,479392812,65430,203,47.91001418648,36.10945728366,-85.208824397165,2,1,18 +2025-03-11T12:40:10.685897,479392812,65430,203,47.8440462338,36.0261638493,-85.06513906808,2,1,18 +2025-03-11T12:40:10.701522,479392812,65430,203,47.7733662845,35.961346549275,-84.935384667185,2,1,18 +2025-03-11T12:40:10.717147,479392812,65430,203,47.69326234196,35.86878651237,-84.810126647345,2,1,18 +2025-03-11T12:40:10.732772,479392812,65430,203,47.6084464028,35.790081537975,-84.661811551175,2,1,18 +2025-03-11T12:40:10.748397,479392812,65430,203,47.53305445688,35.70215072586,-84.50885175395,2,1,18 +2025-03-11T12:40:10.764022,479392812,65430,203,47.45766251096,35.61884098557,-84.36053167979,2,1,18 +2025-03-11T12:40:10.779647,479392812,65430,203,47.36813457518,35.53088571456,-84.19830917342,2,1,18 +2025-03-11T12:40:10.795272,479392812,65430,203,47.28331863602,35.42907538104,-84.036037828055,2,1,18 +2025-03-11T12:40:10.810897,479392812,65430,203,47.19379070024,35.345741181855,-83.87845504475,2,1,18 +2025-03-11T12:40:10.826522,479392812,65430,203,47.10426276446,35.26240698267,-83.711629895315,2,1,18 +2025-03-11T12:40:10.842147,479392812,65430,203,47.02415882192,35.169846945765,-83.530917678695,2,1,18 +2025-03-11T12:40:10.857772,479392812,65430,203,46.92991888952,35.08188352179,-83.35020365906,2,1,18 +2025-03-11T12:40:10.873397,479392812,65430,203,46.82625496388,34.975419504585,-83.187886649675,2,1,18 +2025-03-11T12:40:10.889022,479392812,65430,203,46.72730303486,34.878205783995,-83.016371135165,2,1,18 +2025-03-11T12:40:10.904647,479392812,65430,203,46.62835110584,34.78561313523,-82.83101061146,2,1,18 +2025-03-11T12:40:10.920272,479392812,65430,203,46.54353516668,34.68380280171,-82.631769801575,2,1,18 +2025-03-11T12:40:10.935897,479392812,65430,203,46.43515924442,34.57733063154,-82.44634009586,2,1,18 +2025-03-11T12:40:10.951522,479392812,65430,203,46.3126473323,34.470834002475,-82.256268864065,2,1,18 +2025-03-11T12:40:10.967147,479392812,65430,203,46.19955941342,34.368974751165,-82.052366185085,2,1,18 +2025-03-11T12:40:10.982772,479392812,65430,203,46.09118349116,34.253260437345,-81.86689939937,2,1,18 +2025-03-11T12:40:10.998397,479392812,65430,203,45.9828075689,34.1329250517,-81.672171707525,2,1,18 +2025-03-11T12:40:11.014022,479392812,65430,203,45.87914364326,34.02183996267,-81.46362432749,2,1,18 +2025-03-11T12:40:11.029647,479392812,65430,203,45.77547971762,33.91075487364,-81.25969813052,2,1,18 +2025-03-11T12:40:11.045272,479392812,65430,203,45.6765277886,33.7858147221,-81.037238362295,2,1,18 +2025-03-11T12:40:11.060897,479392812,65430,203,45.54459188324,33.670059643455,-80.8193893901,2,1,18 +2025-03-11T12:40:11.076522,479392812,65430,203,45.42207997112,33.558941942565,-80.610814886045,2,1,18 +2025-03-11T12:40:11.092147,479392812,65430,203,45.29014406576,33.420081504795,-80.388252030785,2,1,18 +2025-03-11T12:40:11.107772,479392812,65430,203,45.16763215364,33.28585844478,-80.147236545275,2,1,18 +2025-03-11T12:40:11.123397,479392812,65430,203,45.04512024152,33.18398288754,-79.92945675509,2,1,18 +2025-03-11T12:40:11.139022,479392812,65430,203,44.9461683125,33.06828487965,-79.71165524993,2,1,18 +2025-03-11T12:40:11.154647,479392812,65430,203,44.82365640038,32.93868289146,-79.46141593829,2,1,18 +2025-03-11T12:40:11.170272,479392812,65430,203,44.67287250854,32.79978984183,-79.215720043685,2,1,18 +2025-03-11T12:40:11.185897,479392812,65430,203,44.52680061332,32.66552601699,-78.979291836215,2,1,18 +2025-03-11T12:40:11.201522,479392812,65430,203,44.39486470796,32.531286651045,-78.719778056435,2,1,18 +2025-03-11T12:40:11.217147,479392812,65430,203,44.25821680598,32.38317591666,-78.483307790975,2,1,18 +2025-03-11T12:40:11.232772,479392812,65430,203,44.11685690738,32.248920244785,-78.223780449185,2,1,18 +2025-03-11T12:40:11.248397,479392812,65430,203,43.97549700878,32.11466457291,-77.945768375135,2,1,18 +2025-03-11T12:40:11.264022,479392812,65430,203,43.83413711018,31.98502997286,-77.70012312254,2,1,18 +2025-03-11T12:40:11.279647,479392812,65430,203,43.70220120482,31.841548463265,-77.44057226276,2,1,18 +2025-03-11T12:40:11.295272,479392812,65430,203,43.56555330284,31.707300944355,-77.171809335845,2,1,18 +2025-03-11T12:40:11.310897,479392812,65430,203,43.41948140762,31.54068961674,-76.90290306692,2,1,18 +2025-03-11T12:40:11.326522,479392812,65430,203,43.2734095124,31.392562576425,-76.63869214106,2,1,18 +2025-03-11T12:40:11.342147,479392812,65430,203,43.11791362394,31.25366137383,-76.360641183995,2,1,18 +2025-03-11T12:40:11.357772,479392812,65430,203,42.95299374224,31.105501721655,-76.105645500245,2,1,18 +2025-03-11T12:40:11.373397,479392812,65430,203,42.79278585716,30.948108078795,-75.845998334435,2,1,18 +2025-03-11T12:40:11.389022,479392812,65430,203,42.65613795518,30.786134128935,-75.563260618325,2,1,18 +2025-03-11T12:40:11.404647,479392812,65430,203,42.50064206672,30.614885423565,-75.27583751513,2,1,18 +2025-03-11T12:40:11.420272,479392812,65430,203,42.34043418164,30.45287070888,-74.965338795605,2,1,18 +2025-03-11T12:40:11.435897,479392812,65430,203,42.17080230332,30.28621861644,-74.668671523265,2,1,18 +2025-03-11T12:40:11.451522,479392812,65430,203,42.00588242162,30.12419574879,-74.385893121125,2,1,18 +2025-03-11T12:40:11.467147,479392812,65430,203,41.84096253992,29.96217288114,-74.09849353592,2,1,18 +2025-03-11T12:40:11.482772,479392812,65430,203,41.67604265822,29.80939215714,-73.78802511539,2,1,18 +2025-03-11T12:40:11.498397,479392812,65430,203,41.52054676976,29.63814345177,-73.47749609687,2,1,18 +2025-03-11T12:40:11.514022,479392812,65430,203,41.35562688806,29.462257368645,-73.17617734247,2,1,18 +2025-03-11T12:40:11.529647,479392812,65430,203,41.18128301312,29.29559712324,-72.86563973993,2,1,18 +2025-03-11T12:40:11.545272,479392812,65430,203,41.00693913818,29.12431580601,-72.550462414325,2,1,18 +2025-03-11T12:40:11.560897,479392812,65430,203,40.82788326662,28.953026335815,-72.244520673845,2,1,18 +2025-03-11T12:40:11.576522,479392812,65430,203,40.64411539844,28.77710764083,-71.92931124623,2,1,18 +2025-03-11T12:40:11.592147,479392812,65430,203,40.46505952688,28.596576026985,-71.60484769349,2,1,18 +2025-03-11T12:40:11.607772,479392812,65430,203,40.3048516418,28.44380345595,-71.275901321705,2,1,18 +2025-03-11T12:40:11.623397,479392812,65430,203,40.1399317601,28.258675229175,-70.946818388915,2,1,18 +2025-03-11T12:40:11.639022,479392812,65430,203,39.9514518953,28.0596430221,-70.6176459311,2,1,18 +2025-03-11T12:40:11.654647,479392812,65430,203,39.75826003388,27.865223733885,-70.283864049215,2,1,18 +2025-03-11T12:40:11.670272,479392812,65430,203,39.58391615894,27.675458129355,-69.94088546522,2,1,18 +2025-03-11T12:40:11.685897,479392812,65430,203,39.39543629414,27.50415235323,-69.593339515145,2,1,18 +2025-03-11T12:40:11.701522,479392812,65430,203,39.20695642934,27.31898336163,-69.259601494265,2,1,18 +2025-03-11T12:40:11.717147,479392812,65430,203,39.02318856116,27.11995930752,-68.911951085195,2,1,18 +2025-03-11T12:40:11.732772,479392812,65430,203,38.82999669974,26.93016109113,-68.555081827985,2,1,18 +2025-03-11T12:40:11.748397,479392812,65430,203,38.64151683494,26.740371027705,-68.20746171791,2,1,18 +2025-03-11T12:40:11.764022,479392812,65430,203,38.42947698704,26.550540199455,-67.845944153615,2,1,18 +2025-03-11T12:40:11.779647,479392812,65430,203,38.23628512562,26.36536305489,-67.479851070275,2,1,18 +2025-03-11T12:40:11.795272,479392812,65430,203,38.04780526082,26.18943620694,-67.109180664875,2,1,18 +2025-03-11T12:40:11.810897,479392812,65430,203,37.84990140278,25.999629837585,-66.738441077465,2,1,18 +2025-03-11T12:40:11.826522,479392812,65430,203,37.6661335346,25.791363639825,-66.39537477146,2,1,18 +2025-03-11T12:40:11.842147,479392812,65430,203,37.47294167318,25.56921792066,-66.04761810038,2,1,18 +2025-03-11T12:40:11.857772,479392812,65430,203,37.27032581852,25.36091911104,-65.6721763889,2,1,18 +2025-03-11T12:40:11.873397,479392812,65430,203,37.053573974,25.161837986175,-65.305993780535,2,1,18 +2025-03-11T12:40:11.889022,479392812,65430,203,36.85095811934,24.96740239203,-64.921365322925,2,1,18 +2025-03-11T12:40:11.904647,479392812,65430,203,36.63420627482,24.77294233899,-64.5367165223,2,1,18 +2025-03-11T12:40:11.920272,479392812,65430,203,36.4410144134,24.5646598353,-64.156667189765,2,1,18 +2025-03-11T12:40:11.935897,479392812,65430,203,36.23368656212,24.35173180089,-63.785821340345,2,1,18 +2025-03-11T12:40:11.951522,479392812,65430,203,36.02164671422,24.12493239804,-63.391807174595,2,1,18 +2025-03-11T12:40:11.967147,479392812,65430,203,35.81903085956,23.90739144477,-63.025570749245,2,1,18 +2025-03-11T12:40:11.982772,479392812,65430,203,35.62112700152,23.69447971629,-62.64087491264,2,1,18 +2025-03-11T12:40:11.998397,479392812,65430,203,35.39495116376,23.48151907002,-62.22379010855,2,1,18 +2025-03-11T12:40:12.014022,479392812,65430,203,35.168775326,23.25007413645,-61.820494693655,2,1,18 +2025-03-11T12:40:12.029647,479392812,65430,203,34.94731148486,23.03250057132,-61.417261679765,2,1,18 +2025-03-11T12:40:12.045272,479392812,65430,203,34.75411962344,22.828839139455,-61.032609704165,2,1,18 +2025-03-11T12:40:12.060897,479392812,65430,203,34.54207977554,22.60666080843,-60.64323526148,2,1,18 +2025-03-11T12:40:12.076522,479392812,65430,203,34.31119194116,22.38907093737,-60.23074631945,2,1,18 +2025-03-11T12:40:12.092147,479392812,65430,203,34.08030410678,22.166859994485,-59.813617654355,2,1,18 +2025-03-11T12:40:12.107772,479392812,65430,203,33.85884026564,21.930802142055,-59.41493166353,2,1,18 +2025-03-11T12:40:12.123397,479392812,65430,203,33.62795243126,21.69010691187,-58.997728838435,2,1,18 +2025-03-11T12:40:12.139022,479392812,65430,203,33.39235260026,21.463266744195,-58.5851960354,2,1,18 +2025-03-11T12:40:12.154647,479392812,65430,203,33.1661767625,21.23644288245,-58.163434428245,2,1,18 +2025-03-11T12:40:12.170272,479392812,65430,203,32.94000092474,21.01424009253,-57.74169136109,2,1,18 +2025-03-11T12:40:12.185897,479392812,65430,203,32.7185370836,20.764319024625,-57.31060146881,2,1,18 +2025-03-11T12:40:12.201522,479392812,65430,203,32.49707324246,20.54212438767,-56.884243999595,2,1,18 +2025-03-11T12:40:12.217147,479392812,65430,203,32.26147341146,20.31990529182,-56.467108553495,2,1,18 +2025-03-11T12:40:12.232772,479392812,65430,203,32.03058557708,20.088452205285,-56.045321625335,2,1,18 +2025-03-11T12:40:12.248397,479392812,65430,203,31.80912173594,19.83853113738,-55.60961054999,2,1,18 +2025-03-11T12:40:12.264022,479392812,65430,203,31.56880990832,19.59319852944,-55.173890890625,2,1,18 +2025-03-11T12:40:12.279647,479392812,65430,203,31.32378608408,19.357099912185,-54.738201530255,2,1,18 +2025-03-11T12:40:12.295272,479392812,65430,203,31.08347425646,19.121009447895,-54.307140133955,2,1,18 +2025-03-11T12:40:12.310897,479392812,65430,203,30.84316242884,18.875676839955,-53.866799291525,2,1,18 +2025-03-11T12:40:12.326522,479392812,65430,203,30.60756259784,18.63959452863,-53.43574467623,2,1,18 +2025-03-11T12:40:12.342147,479392812,65430,203,30.38138676008,18.38966530776,-53.004648002945,2,1,18 +2025-03-11T12:40:12.357772,479392812,65430,203,30.14578692908,18.135098709135,-52.56427686152,2,1,18 +2025-03-11T12:40:12.373397,479392812,65430,203,29.88662711498,17.898975632985,-52.09621887668,2,1,18 +2025-03-11T12:40:12.389022,479392812,65430,203,29.62746730088,17.653610413185,-51.641987361035,2,1,18 +2025-03-11T12:40:12.404647,479392812,65430,203,29.38244347664,17.412890724105,-51.197037094535,2,1,18 +2025-03-11T12:40:12.420272,479392812,65430,203,29.1138596693,17.167509198375,-50.747413199945,2,1,18 +2025-03-11T12:40:12.435897,479392812,65430,203,28.85941185182,16.908288916065,-50.293132845305,2,1,18 +2025-03-11T12:40:12.451522,479392812,65430,203,28.60967603096,16.63983464307,-49.8480645578,2,1,18 +2025-03-11T12:40:12.467147,479392812,65430,203,28.35522821348,16.39909864806,-49.379994813965,2,1,18 +2025-03-11T12:40:12.482772,479392812,65430,203,28.11491638586,16.149144968295,-48.90728715008,2,1,18 +2025-03-11T12:40:12.498397,479392812,65430,203,27.88402855148,15.903828666285,-48.43923277127,2,1,18 +2025-03-11T12:40:12.514022,479392812,65430,203,27.629580734,15.6492294558,-47.989592139695,2,1,18 +2025-03-11T12:40:12.529647,479392812,65430,203,27.36099692666,15.37612149912,-47.52599345591,2,1,18 +2025-03-11T12:40:12.545272,479392812,65430,203,27.09241311932,15.12149782974,-47.034741833735,2,1,18 +2025-03-11T12:40:12.560897,479392812,65430,203,26.84738929508,14.85305170971,-46.55733204578,2,1,18 +2025-03-11T12:40:12.576522,479392812,65430,203,26.60236547084,14.598468805155,-46.10308379315,2,1,18 +2025-03-11T12:40:12.592147,479392812,65430,203,26.33849366012,14.35309543239,-45.6488454965,2,1,18 +2025-03-11T12:40:12.607772,479392812,65430,203,26.0746218494,14.0846167005,-45.171408584525,2,1,18 +2025-03-11T12:40:12.623397,479392812,65430,203,25.80603804206,13.825371959295,-44.694001971545,2,1,18 +2025-03-11T12:40:12.639022,479392812,65430,203,25.54687822796,13.55690138037,-44.198087108315,2,1,18 +2025-03-11T12:40:12.654647,479392812,65430,203,25.28300641724,13.311528007605,-43.725364079405,2,1,18 +2025-03-11T12:40:12.670272,479392812,65430,203,25.0144226099,13.038420050925,-43.229417114165,2,1,18 +2025-03-11T12:40:12.685897,479392812,65430,203,24.75997479242,12.75609440949,-42.74269577807,2,1,18 +2025-03-11T12:40:12.701522,479392812,65430,203,24.50081497832,12.48300275874,-42.242141191775,2,1,18 +2025-03-11T12:40:12.717147,479392812,65430,203,24.22280717774,12.223741711605,-41.76009983372,2,1,18 +2025-03-11T12:40:12.732772,479392812,65430,203,23.96364736364,11.95527113268,-41.268806153555,2,1,18 +2025-03-11T12:40:12.748397,479392812,65430,203,23.69035155968,11.66829180756,-40.786660336505,2,1,18 +2025-03-11T12:40:12.764022,479392812,65430,203,23.41705575572,11.38131248244,-40.29989333639,2,1,18 +2025-03-11T12:40:12.779647,479392812,65430,203,23.13904795514,11.11743036348,-39.81321225527,2,1,18 +2025-03-11T12:40:12.795272,479392812,65430,203,22.87517614442,10.83970948794,-39.298768798775,2,1,18 +2025-03-11T12:40:12.810897,479392812,65430,203,22.60659233708,10.580464746735,-38.784392721275,2,1,18 +2025-03-11T12:40:12.826522,479392812,65430,203,22.34272052636,10.311986014845,-38.283849893975,2,1,18 +2025-03-11T12:40:12.842147,479392812,65430,203,22.05528873254,10.038845446305,-37.78325462165,2,1,18 +2025-03-11T12:40:12.857772,479392812,65430,203,21.78199292858,9.770350408485,-37.31042533073,2,1,18 +2025-03-11T12:40:12.873397,479392812,65430,203,21.51340912124,9.49262137998,-36.809838642425,2,1,18 +2025-03-11T12:40:12.889022,479392812,65430,203,21.24011331728,9.210263126685,-36.299984266985,2,1,18 +2025-03-11T12:40:12.904647,479392812,65430,203,20.97152950994,8.92329195453,-35.803981681745,2,1,18 +2025-03-11T12:40:12.920272,479392812,65430,203,20.68409771612,8.654772457815,-35.308026132485,2,1,18 +2025-03-11T12:40:12.935897,479392812,65430,203,20.3966659223,8.372389745625,-34.79815141403,2,1,18 +2025-03-11T12:40:12.951522,479392812,65430,203,20.11865812172,8.090023339365,-34.279047891455,2,1,18 +2025-03-11T12:40:12.967147,479392812,65430,203,19.85007431438,7.816915382685,-33.75999501089,2,1,18 +2025-03-11T12:40:12.982772,479392812,65430,203,19.56264252056,7.52991159867,-33.26396530163,2,1,18 +2025-03-11T12:40:12.998397,479392812,65430,203,19.26107473688,7.24288335576,-32.749430517095,2,1,18 +2025-03-11T12:40:13.014022,479392812,65430,203,18.96893094644,6.960492490605,-32.230306651505,2,1,18 +2025-03-11T12:40:13.029647,479392812,65430,203,18.70505913572,6.682771615065,-31.701999645815,2,1,18 +2025-03-11T12:40:13.045272,479392812,65430,203,18.43647532838,6.40504258656,-31.187549408315,2,1,18 +2025-03-11T12:40:13.060897,479392812,65430,203,18.15375553118,6.11804695551,-30.659178198605,2,1,18 +2025-03-11T12:40:13.076522,479392812,65430,203,17.86161174074,5.84027716218,-30.14469405608,2,1,18 +2025-03-11T12:40:13.092147,479392812,65430,203,17.57889194354,5.54403938748,-29.639391681695,2,1,18 +2025-03-11T12:40:13.107772,479392812,65430,203,17.29146014972,5.247793459815,-29.12021897711,2,1,18 +2025-03-11T12:40:13.123397,479392812,65430,203,17.0040283559,4.9607896758,-28.582598620265,2,1,18 +2025-03-11T12:40:13.139022,479392812,65430,203,16.70717256884,4.66914851403,-28.03570379528,2,1,18 +2025-03-11T12:40:13.154647,479392812,65430,203,16.42445277164,4.38215288298,-27.521196134765,2,1,18 +2025-03-11T12:40:13.170272,479392812,65430,203,16.1558689643,4.09980278265,-26.99286380807,2,1,18 +2025-03-11T12:40:13.185897,479392812,65430,203,15.88257316034,3.817444529355,-26.46452470037,2,1,18 +2025-03-11T12:40:13.201522,479392812,65430,203,15.58100537666,3.511931999145,-25.949915755835,2,1,18 +2025-03-11T12:40:13.217147,479392812,65430,203,15.27943759298,3.21104054076,-25.430704168235,2,1,18 +2025-03-11T12:40:13.232772,479392812,65430,203,14.99200579916,2.905552469445,-24.89300965139,2,1,18 +2025-03-11T12:40:13.248397,479392812,65430,203,14.69986200872,2.62316160429,-24.369264602735,2,1,18 +2025-03-11T12:40:13.264022,479392812,65430,203,14.40300622166,2.336141514345,-23.817767134685,2,1,18 +2025-03-11T12:40:13.279647,479392812,65430,203,14.12028642446,2.04452481147,-23.29399856804,2,1,18 +2025-03-11T12:40:13.295272,479392812,65430,203,13.81871864078,1.75749656856,-22.760979051245,2,1,18 +2025-03-11T12:40:13.310897,479392812,65430,203,13.5407108402,1.456645875,-22.237180185605,2,1,18 +2025-03-11T12:40:13.326522,479392812,65430,203,13.25327904638,1.160399947335,-21.713386297955,2,1,18 +2025-03-11T12:40:13.342147,479392812,65430,203,12.97055924918,0.868783244459999,-21.16189063292,2,1,18 +2025-03-11T12:40:13.357772,479392812,65430,203,12.67370346212,0.567899939040001,-20.619579911,2,1,18 +2025-03-11T12:40:13.373397,479392812,65430,203,12.37213567844,0.27162955248,-20.09114449727,2,1,18 +2025-03-11T12:40:13.389022,479392812,65430,203,12.07056789476,-0.0246408340799995,-19.55346671741,2,1,18 +2025-03-11T12:40:13.404647,479392812,65430,203,11.7737121077,-0.316281995850001,-19.02967780775,2,1,18 +2025-03-11T12:40:13.420272,479392812,65430,203,11.47685632064,-0.598681013969999,-18.482820062765,2,1,18 +2025-03-11T12:40:13.435897,479392812,65430,203,11.18000053358,-0.904185391214999,-17.931248434715,2,1,18 +2025-03-11T12:40:13.451522,479392812,65430,203,10.89728073638,-1.200423165915,-17.38897659581,2,1,18 +2025-03-11T12:40:13.467147,479392812,65430,203,10.61456093918,-1.48279772514,-16.86986629223,2,1,18 +2025-03-11T12:40:13.482772,479392812,65430,203,10.31770515212,-1.78368103056,-16.322934387245,2,1,18 +2025-03-11T12:40:13.498397,479392812,65430,203,10.01613736844,-2.08919356077,-15.766734795125,2,1,18 +2025-03-11T12:40:13.514022,479392812,65430,203,9.70514559152,-2.37623810961,-15.229080533255,2,1,18 +2025-03-11T12:40:13.529647,479392812,65430,203,9.40828980446,-2.67712141503,-14.686769811335,2,1,18 +2025-03-11T12:40:13.545272,479392812,65430,203,9.10201002416,-2.991884241855,-14.1582534566,2,1,18 +2025-03-11T12:40:13.560897,479392812,65430,203,8.8051542371,-3.28814647545,-13.611340091615,2,1,18 +2025-03-11T12:40:13.576522,479392812,65430,203,8.4988744568,-3.584425014975,-13.06441316462,2,1,18 +2025-03-11T12:40:13.592147,479392812,65430,203,8.20201866974,-3.88068724857,-12.517499799635,2,1,18 +2025-03-11T12:40:13.607772,479392812,65430,203,7.91458687592,-4.17231210441,-11.975239719725,2,1,18 +2025-03-11T12:40:13.623397,479392812,65430,203,7.62244308548,-4.46856618504,-11.42371195268,2,1,18 +2025-03-11T12:40:13.639022,479392812,65430,203,7.3208753018,-4.769457643425,-10.87677326669,2,1,18 +2025-03-11T12:40:13.654647,479392812,65430,203,7.01930751812,-5.065728029985,-10.315989571505,2,1,18 +2025-03-11T12:40:13.670272,479392812,65430,203,6.72245173106,-5.37123240723,-9.773660309585,2,1,18 +2025-03-11T12:40:13.685897,479392812,65430,203,6.425595944,-5.676736784475,-9.23595223073,2,1,18 +2025-03-11T12:40:13.701522,479392812,65430,203,6.12874015694,-5.98224116172,-8.698244151875,2,1,18 +2025-03-11T12:40:13.717147,479392812,65430,203,5.81774838002,-6.292391069685,-8.142012457745,2,1,18 +2025-03-11T12:40:13.732772,479392812,65430,203,5.52560458958,-6.57478193484,-7.59978267683,2,1,18 +2025-03-11T12:40:13.748397,479392812,65430,203,5.22874880252,-6.871044168435,-7.06673286104,2,1,18 +2025-03-11T12:40:13.764022,479392812,65430,203,4.92246902222,-7.17656485161,-6.510526487915,2,1,18 +2025-03-11T12:40:13.779647,479392812,65430,203,4.6114772453,-7.468230472275,-5.954368953785,2,1,18 +2025-03-11T12:40:13.795272,479392812,65430,203,4.31933345486,-7.76910562473,-5.388959097545,2,1,18 +2025-03-11T12:40:13.810897,479392812,65430,203,4.03190166104,-8.074593696045,-4.86974931296,2,1,18 +2025-03-11T12:40:13.826522,479392812,65430,203,3.73504587398,-8.384719145115,-4.322780327975,2,1,18 +2025-03-11T12:40:13.842147,479392812,65430,203,3.42405409706,-8.708732268555,-3.76187183078,2,1,18 +2025-03-11T12:40:13.857772,479392812,65430,203,3.13191030662,-9.00036527736,-3.23346851906,2,1,18 +2025-03-11T12:40:13.873397,479392812,65430,203,2.83976651618,-9.301240429815,-2.67730102895,2,1,18 +2025-03-11T12:40:13.889022,479392812,65430,203,2.54291072912,-9.602123735235,-2.1257479409,2,1,18 +2025-03-11T12:40:13.904647,479392812,65430,203,2.22720695558,-9.893797508865,-1.58344717496,2,1,18 +2025-03-11T12:40:13.920272,479392812,65430,203,1.93506316514,-10.199293733145,-1.041124694045,2,1,18 +2025-03-11T12:40:13.935897,479392812,65430,203,1.63820737808,-10.49555596674,-0.498832512125,2,1,18 +2025-03-11T12:40:13.951522,479392812,65430,203,1.3366395944,-10.787205281475,0.06193264306,2,1,18 +2025-03-11T12:40:13.967147,479392812,65430,203,1.03978380734,-11.088088586895,0.608864548045,2,1,18 +2025-03-11T12:40:13.982772,479392812,65430,203,0.7240800338,-11.40286771965,1.151258013985,2,1,18 +2025-03-11T12:40:13.998321,479392816,65425,204,0.42722424674,-11.689887809595,1.702755482035,2,1,18 +2025-03-11T12:40:14.013946,479392816,65425,204,0.13036845968,-11.96766575589,2.24959468702,2,1,18 +2025-03-11T12:40:14.029571,479392816,65425,204,-0.17591132062,-12.291670726365,2.787390487885,2,1,18 +2025-03-11T12:40:14.045196,479392816,65425,204,-0.47276710768,-12.592554031785,3.329701209805,2,1,18 +2025-03-11T12:40:14.060821,479392816,65425,204,-0.76962289474,-12.893437337205,3.890496663985,2,1,18 +2025-03-11T12:40:14.076446,479392816,65425,204,-1.06176668518,-13.189691417835,4.418918515705,2,1,18 +2025-03-11T12:40:14.092071,479392816,65425,204,-1.349198479,-13.49517948915,4.961234215615,2,1,18 +2025-03-11T12:40:14.107696,479392816,65425,204,-1.64134226944,-13.79143356978,5.50351961653,2,1,18 +2025-03-11T12:40:14.123321,479392816,65425,204,-1.93348605988,-14.07844550676,6.045767937445,2,1,18 +2025-03-11T12:40:14.138946,479392816,65425,204,-2.2209178537,-14.365449290775,6.597251843485,2,1,18 +2025-03-11T12:40:14.154571,479392816,65425,204,-2.53190963062,-14.652493839615,7.144148471485,2,1,18 +2025-03-11T12:40:14.170196,479392816,65425,204,-2.84761340416,-14.96727297237,7.70040548662,2,1,18 +2025-03-11T12:40:14.185821,479392816,65425,204,-3.15860518108,-15.258938593035,8.233457105425,2,1,18 +2025-03-11T12:40:14.201446,479392816,65425,204,-3.44132497828,-15.573660655035,8.7665607382,2,1,18 +2025-03-11T12:40:14.217071,479392816,65425,204,-3.7287567721,-15.8699065827,9.313460541175,2,1,18 +2025-03-11T12:40:14.232696,479392816,65425,204,-4.02561255916,-16.16154774447,9.85111300003,2,1,18 +2025-03-11T12:40:14.248321,479392816,65425,204,-4.32246834622,-16.457809978065,10.379541632755,2,1,18 +2025-03-11T12:40:14.263946,479392816,65425,204,-4.60990014004,-16.749434833905,10.9171805296,2,1,18 +2025-03-11T12:40:14.279571,479392816,65425,204,-4.89733193386,-17.02719647427,11.473248538705,2,1,18 +2025-03-11T12:40:14.295196,479392816,65425,204,-5.1894757243,-17.3234505549,12.001670390425,2,1,18 +2025-03-11T12:40:14.310821,479392816,65425,204,-5.48633151136,-17.62433386032,12.516254013955,2,1,18 +2025-03-11T12:40:14.326446,479392816,65425,204,-5.78318729842,-17.911353950265,13.04464556668,2,1,18 +2025-03-11T12:40:14.342071,479392816,65425,204,-6.07533108886,-18.216850174545,13.56386213227,2,1,18 +2025-03-11T12:40:14.357696,479392816,65425,204,-6.36276288268,-18.51309610221,14.10614075218,2,1,18 +2025-03-11T12:40:14.373321,479392816,65425,204,-6.65490667312,-18.80010803919,14.657631439225,2,1,18 +2025-03-11T12:40:14.388946,479392816,65425,204,-6.94705046356,-19.100983191645,15.19069301401,2,1,18 +2025-03-11T12:40:14.404571,479392816,65425,204,-7.239194254,-19.415721559575,15.714567842665,2,1,18 +2025-03-11T12:40:14.420196,479392816,65425,204,-7.5454740343,-19.70275795545,16.229109408205,2,1,18 +2025-03-11T12:40:14.435821,479392816,65425,204,-7.83290582812,-19.97589852399,16.752810595855,2,1,18 +2025-03-11T12:40:14.451446,479392816,65425,204,-8.12504961856,-20.27215260462,17.28585363064,2,1,18 +2025-03-11T12:40:14.467071,479392816,65425,204,-8.41248141238,-20.568398532285,17.814268701355,2,1,18 +2025-03-11T12:40:14.482696,479392816,65425,204,-8.69520120958,-20.855394163335,18.324155178805,2,1,18 +2025-03-11T12:40:14.498321,479392816,65425,204,-8.97792100678,-21.142389794385,18.871011120775,2,1,18 +2025-03-11T12:40:14.513946,479392816,65425,204,-9.25121681074,-21.429369119505,19.40398995154,2,1,18 +2025-03-11T12:40:14.529571,479392816,65425,204,-9.53864860456,-21.71637290352,19.932367942255,2,1,18 +2025-03-11T12:40:14.545196,479392816,65425,204,-9.83550439162,-21.99877192164,20.45149858885,2,1,18 +2025-03-11T12:40:14.560821,479392816,65425,204,-10.11822418882,-22.281146480865,20.9613665263,2,1,18 +2025-03-11T12:40:14.576446,479392816,65425,204,-10.3962319894,-22.5958603899,21.49446337807,2,1,18 +2025-03-11T12:40:14.592071,479392816,65425,204,-10.68366378322,-22.87824310209,22.013580462655,2,1,18 +2025-03-11T12:40:14.607696,479392816,65425,204,-10.9616715838,-23.155988436525,22.5234230791,2,1,18 +2025-03-11T12:40:14.623321,479392816,65425,204,-11.23967938438,-23.438354842785,23.04714778474,2,1,18 +2025-03-11T12:40:14.638946,479392816,65425,204,-11.51768718496,-23.71610017722,23.566232767315,2,1,18 +2025-03-11T12:40:14.654571,479392816,65425,204,-11.80511897878,-23.993861817585,24.080710128835,2,1,18 +2025-03-11T12:40:14.670196,479392816,65425,204,-12.0925507726,-24.27162345795,24.604429856485,2,1,18 +2025-03-11T12:40:14.685821,479392816,65425,204,-12.37055857318,-24.549368792385,25.128136022125,2,1,18 +2025-03-11T12:40:14.701446,479392816,65425,204,-12.64856637376,-24.822493054995,25.642581281635,2,1,18 +2025-03-11T12:40:14.717071,479392816,65425,204,-12.92657417434,-25.10023838943,26.138560348885,2,1,18 +2025-03-11T12:40:14.732696,479392816,65425,204,-13.20929397154,-25.38723402048,26.62534091101,2,1,18 +2025-03-11T12:40:14.748321,479392816,65425,204,-13.47787777888,-25.65109983351,27.116629613185,2,1,18 +2025-03-11T12:40:14.763946,479392816,65425,204,-13.75588557946,-25.92422409612,27.640317238825,2,1,18 +2025-03-11T12:40:14.779571,479392816,65425,204,-14.03389338004,-26.211211574205,28.15019693527,2,1,18 +2025-03-11T12:40:14.795196,479392816,65425,204,-14.32132517386,-26.48897321457,28.64618956453,2,1,18 +2025-03-11T12:40:14.810821,479392816,65425,204,-14.60404497106,-26.76672670197,29.132933046655,2,1,18 +2025-03-11T12:40:14.826446,479392816,65425,204,-14.87734077502,-27.049084955265,29.64740860516,2,1,18 +2025-03-11T12:40:14.842071,479392816,65425,204,-15.13650058912,-27.33603982149,30.13415526226,2,1,18 +2025-03-11T12:40:14.857696,479392816,65425,204,-15.40508439646,-27.604526706345,30.6300836875,2,1,18 +2025-03-11T12:40:14.873321,479392816,65425,204,-15.6736682038,-27.868392519375,31.13523593887,2,1,18 +2025-03-11T12:40:14.888946,479392816,65425,204,-15.96109999762,-28.141533087915,31.63121002813,2,1,18 +2025-03-11T12:40:14.904571,479392816,65425,204,-16.22497180834,-28.40539074798,32.1224919493,2,1,18 +2025-03-11T12:40:14.920196,479392816,65425,204,-16.49355561568,-28.66925656101,32.61840183454,2,1,18 +2025-03-11T12:40:14.935821,479392816,65425,204,-16.76685141964,-28.933130527005,33.105076134655,2,1,18 +2025-03-11T12:40:14.951446,479392816,65425,204,-17.03072323036,-29.18774604342,33.59169979276,2,1,18 +2025-03-11T12:40:14.967071,479392816,65425,204,-17.28988304446,-29.456216622345,34.06912992373,2,1,18 +2025-03-11T12:40:14.982696,479392816,65425,204,-17.54433086194,-29.73854226378,34.555851259825,2,1,18 +2025-03-11T12:40:14.998321,479392816,65425,204,-17.81291466928,-30.025513435935,35.033369112805,2,1,18 +2025-03-11T12:40:15.013946,479392816,65425,204,-18.08621047324,-30.28938740193,35.506179863725,2,1,18 +2025-03-11T12:40:15.029571,479392816,65425,204,-18.34537028734,-30.539373693555,35.97891465163,2,1,18 +2025-03-11T12:40:15.045196,479392816,65425,204,-18.60924209806,-30.798610281795,36.4701780328,2,1,18 +2025-03-11T12:40:15.060821,479392816,65425,204,-18.86368991554,-31.07169377958,36.95224110583,2,1,18 +2025-03-11T12:40:15.076446,479392816,65425,204,-19.12756172626,-31.335551439645,37.411174745545,2,1,18 +2025-03-11T12:40:15.092071,479392816,65425,204,-19.38672154036,-31.580916659445,37.879269810385,2,1,18 +2025-03-11T12:40:15.107696,479392816,65425,204,-19.64116935784,-31.840136941755,38.34741371422,2,1,18 +2025-03-11T12:40:15.123321,479392816,65425,204,-19.89561717532,-32.090115080415,38.81089935499,2,1,18 +2025-03-11T12:40:15.138946,479392816,65425,204,-20.14535299618,-32.33084292246,39.265098768625,2,1,18 +2025-03-11T12:40:15.154571,479392816,65425,204,-20.39980081366,-32.585442132945,39.737845315525,2,1,18 +2025-03-11T12:40:15.170196,479392816,65425,204,-20.66367262438,-32.84005764936,40.210605424435,2,1,18 +2025-03-11T12:40:15.185821,479392816,65425,204,-20.91340844524,-33.11313299418,40.669555801135,2,1,18 +2025-03-11T12:40:15.201446,479392816,65425,204,-21.17728025596,-33.367748510595,41.11920999472,2,1,18 +2025-03-11T12:40:15.217071,479392816,65425,204,-21.43644007006,-33.59925051492,41.5687647073,2,1,18 +2025-03-11T12:40:15.232696,479392816,65425,204,-21.68617589092,-33.858462644265,42.004553548675,2,1,18 +2025-03-11T12:40:15.248321,479392816,65425,204,-21.93591171178,-34.08994834266,42.454094699245,2,1,18 +2025-03-11T12:40:15.263946,479392816,65425,204,-22.18564753264,-34.330676184705,42.90829411288,2,1,18 +2025-03-11T12:40:15.279571,479392816,65425,204,-22.42595936026,-34.594493079945,43.362572664505,2,1,18 +2025-03-11T12:40:15.295196,479392816,65425,204,-22.66627118788,-34.839825687885,43.821398239195,2,1,18 +2025-03-11T12:40:15.310821,479392816,65425,204,-22.91129501212,-35.07592430514,44.257087599565,2,1,18 +2025-03-11T12:40:15.326446,479392816,65425,204,-23.17045482622,-35.307426309465,44.697399946015,2,1,18 +2025-03-11T12:40:15.342071,479392816,65425,204,-23.39663066398,-35.557355530335,45.142360168495,2,1,18 +2025-03-11T12:40:15.357696,479392816,65425,204,-23.62751849836,-35.793429688695,45.58727155198,2,1,18 +2025-03-11T12:40:15.373321,479392816,65425,204,-23.86783032598,-36.038762296635,46.01837002828,2,1,18 +2025-03-11T12:40:15.388946,479392816,65425,204,-24.1081421536,-36.2702316891,46.463276433775,2,1,18 +2025-03-11T12:40:15.404571,479392816,65425,204,-24.3437419846,-36.506314000425,46.89433104907,2,1,18 +2025-03-11T12:40:15.420196,479392816,65425,204,-24.57462981898,-36.760872446085,47.32545304336,2,1,18 +2025-03-11T12:40:15.435821,479392816,65425,204,-24.7913816635,-36.992301073725,47.75184081157,2,1,18 +2025-03-11T12:40:15.451446,479392816,65425,204,-25.00813350802,-37.21910862954,48.17821003978,2,1,18 +2025-03-11T12:40:15.467071,479392816,65425,204,-25.2390213424,-37.4551827879,48.59077314181,2,1,18 +2025-03-11T12:40:15.482696,479392816,65425,204,-25.4746211734,-37.700507242875,49.012622470975,2,1,18 +2025-03-11T12:40:15.498321,479392816,65425,204,-25.7102210044,-37.92734741055,49.43439764014,2,1,18 +2025-03-11T12:40:15.513946,479392816,65425,204,-25.95524482864,-38.163446027805,49.837738719055,2,1,18 +2025-03-11T12:40:15.529571,479392816,65425,204,-26.16728467654,-38.39486650248,50.25487734013,2,1,18 +2025-03-11T12:40:15.545196,479392816,65425,204,-26.38874851768,-38.607818995785,50.653470630955,2,1,18 +2025-03-11T12:40:15.560821,479392816,65425,204,-26.62434834868,-38.830038091635,51.079848443185,2,1,18 +2025-03-11T12:40:15.576446,479392816,65425,204,-26.85994817968,-39.070741474785,51.48319450009,2,1,18 +2025-03-11T12:40:15.592071,479392816,65425,204,-27.08141202082,-39.297557183565,51.87722222785,2,1,18 +2025-03-11T12:40:15.607696,479392816,65425,204,-27.29816386534,-39.49663830843,52.280374300735,2,1,18 +2025-03-11T12:40:15.623321,479392816,65425,204,-27.52905169972,-39.700364964015,52.69742880583,2,1,18 +2025-03-11T12:40:15.638946,479392816,65425,204,-27.75051554086,-39.917938529145,53.09141945359,2,1,18 +2025-03-11T12:40:15.654571,479392816,65425,204,-27.94370740228,-40.135463176485,53.47612704919,2,1,18 +2025-03-11T12:40:15.670196,479392816,65425,204,-28.15103525356,-40.357633354545,53.860873527805,2,1,18 +2025-03-11T12:40:15.685821,479392816,65425,204,-28.3724990947,-40.5798279915,54.24101916637,2,1,18 +2025-03-11T12:40:15.701446,479392816,65425,204,-28.57511494936,-40.783505729295,54.611821154785,2,1,18 +2025-03-11T12:40:15.717071,479392816,65425,204,-28.78244280064,-40.97332840458,55.00568021953,2,1,18 +2025-03-11T12:40:15.732696,479392816,65425,204,-28.99919464516,-41.19551488857,55.39506144322,2,1,18 +2025-03-11T12:40:15.748321,479392816,65425,204,-29.20181049982,-41.399192626365,55.76124224857,2,1,18 +2025-03-11T12:40:15.763946,479392816,65425,204,-29.39971435786,-41.60748328302,56.13205599598,2,1,18 +2025-03-11T12:40:15.779571,479392816,65425,204,-29.61646620238,-41.815806551535,56.50289686741,2,1,18 +2025-03-11T12:40:15.795196,479392816,65425,204,-29.81437006042,-42.02409720819,56.878331797885,2,1,18 +2025-03-11T12:40:15.810821,479392816,65425,204,-30.03112190494,-42.223178333055,57.239893223185,2,1,18 +2025-03-11T12:40:15.826446,479392816,65425,204,-30.2337377596,-42.431477142675,57.59222901934,2,1,18 +2025-03-11T12:40:15.842071,479392816,65425,204,-30.4222176244,-42.63050934975,57.949128575545,2,1,18 +2025-03-11T12:40:15.857696,479392816,65425,204,-30.61540948582,-42.82954970979,58.30141372969,2,1,18 +2025-03-11T12:40:15.873321,479392816,65425,204,-30.81331334386,-43.019356079145,58.667532134035,2,1,18 +2025-03-11T12:40:15.888946,479392816,65425,204,-31.0112172019,-43.19992030485,59.038234641445,2,1,18 +2025-03-11T12:40:15.904571,479392816,65425,204,-31.20440906332,-43.394339593065,59.39974362172,2,1,18 +2025-03-11T12:40:15.920196,479392816,65425,204,-31.38346493488,-43.58411335056,59.74272898672,2,1,18 +2025-03-11T12:40:15.935821,479392816,65425,204,-31.56252080644,-43.76002389258,60.081037548655,2,1,18 +2025-03-11T12:40:15.951446,479392816,65425,204,-31.7651366611,-43.95908055855,60.419472715615,2,1,18 +2025-03-11T12:40:15.967071,479392816,65425,204,-31.93948053604,-44.16733045038,60.76252545961,2,1,18 +2025-03-11T12:40:15.982696,479392816,65425,204,-32.12796040084,-44.347878370155,61.110108489685,2,1,18 +2025-03-11T12:40:15.998321,479392816,65425,204,-32.32586425888,-44.53768473951,61.44849979564,2,1,18 +2025-03-11T12:40:16.013946,479392816,65425,204,-32.50492013044,-44.73207956883,61.78226133451,2,1,18 +2025-03-11T12:40:16.029571,479392816,65425,204,-32.69811199186,-44.908014569745,62.106726690265,2,1,18 +2025-03-11T12:40:16.045196,479392816,65425,204,-32.87716786342,-45.093167255415,62.421966416875,2,1,18 +2025-03-11T12:40:16.060821,479392816,65425,204,-33.04208774512,-45.264432266715,62.732508997405,2,1,18 +2025-03-11T12:40:16.076446,479392816,65425,204,-33.22114361668,-45.440342808735,63.056954010145,2,1,18 +2025-03-11T12:40:16.092071,479392816,65425,204,-33.40019948824,-45.61163227893,63.362895750625,2,1,18 +2025-03-11T12:40:16.107696,479392816,65425,204,-33.5792553598,-45.78754282095,63.67347721417,2,1,18 +2025-03-11T12:40:16.123321,479392816,65425,204,-33.73946324488,-45.97266289476,63.98868981676,2,1,18 +2025-03-11T12:40:16.138946,479392816,65425,204,-33.89967112996,-46.143919753095,64.30384679935,2,1,18 +2025-03-11T12:40:16.154571,479392816,65425,204,-34.06459101166,-46.31056369257,64.609749656815,2,1,18 +2025-03-11T12:40:16.170196,479392816,65425,204,-34.22479889674,-46.472578407255,64.90176364408,2,1,18 +2025-03-11T12:40:16.185821,479392816,65425,204,-34.38500678182,-46.611487762815,65.19830611441,2,1,18 +2025-03-11T12:40:16.201446,479392816,65425,204,-34.5452146669,-46.78274462115,65.50422073087,2,1,18 +2025-03-11T12:40:16.217071,479392816,65425,204,-34.7101345486,-46.949388560625,65.810123588335,2,1,18 +2025-03-11T12:40:16.232696,479392816,65425,204,-34.8750544303,-47.111411428275,66.111386722735,2,1,18 +2025-03-11T12:40:16.248321,479392816,65425,204,-35.02112632552,-47.26878061224,66.38949827779,2,1,18 +2025-03-11T12:40:16.263946,479392816,65425,204,-35.1813342106,-47.41693211145,66.66759309586,2,1,18 +2025-03-11T12:40:16.279571,479392816,65425,204,-35.33211810244,-47.56506730473,66.931810802725,2,1,18 +2025-03-11T12:40:16.295196,479392816,65425,204,-35.49232598752,-47.72246094759,67.22380624999,2,1,18 +2025-03-11T12:40:16.310821,479392816,65425,204,-35.64782187598,-47.870604293835,67.492651920925,2,1,18 +2025-03-11T12:40:16.326446,479392816,65425,204,-35.7938937712,-48.023352405975,67.77074493598,2,1,18 +2025-03-11T12:40:16.342071,479392816,65425,204,-35.9352536698,-48.152987006025,68.044117286965,2,1,18 +2025-03-11T12:40:16.357696,479392816,65425,204,-36.08132556502,-48.31035618999,68.29450174363,2,1,18 +2025-03-11T12:40:16.373321,479392816,65425,204,-36.22739746024,-48.467725373955,68.54950738336,2,1,18 +2025-03-11T12:40:16.388946,479392816,65425,204,-36.36404536222,-48.611215036515,68.81368620721,2,1,18 +2025-03-11T12:40:16.404571,479392816,65425,204,-36.50540526082,-48.750091780215,69.09171682126,2,1,18 +2025-03-11T12:40:16.420196,479392816,65425,204,-36.65618915266,-48.888984829845,69.346655081995,2,1,18 +2025-03-11T12:40:16.435821,479392816,65425,204,-36.8069730445,-49.018635735825,69.578450347405,2,1,18 +2025-03-11T12:40:16.451446,479392816,65425,204,-36.93419695324,-49.14824587698,69.824075256985,2,1,18 +2025-03-11T12:40:16.467071,479392816,65425,204,-37.0661328586,-49.28710631475,70.083607576765,2,1,18 +2025-03-11T12:40:16.482696,479392816,65425,204,-37.21691675044,-49.412136148905,70.315384302175,2,1,18 +2025-03-11T12:40:16.498321,479392816,65425,204,-37.35356465242,-49.546383667815,70.54717776457,2,1,18 +2025-03-11T12:40:16.513946,479392816,65425,204,-37.45251658144,-49.680565963005,70.78353816199,2,1,18 +2025-03-11T12:40:16.529571,479392816,65425,204,-37.57031649694,-49.79167551093,71.015211800365,2,1,18 +2025-03-11T12:40:16.545196,479392816,65425,204,-37.69282840906,-49.925898570945,71.237742553615,2,1,18 +2025-03-11T12:40:16.560821,479392816,65425,204,-37.82947631104,-50.050903946205,71.44177183762,2,1,18 +2025-03-11T12:40:16.576446,479392816,65425,204,-37.9614122164,-50.1574168812,71.678068462075,2,1,18 +2025-03-11T12:40:16.592071,479392816,65425,204,-38.06507614204,-50.273123042055,71.909740297435,2,1,18 +2025-03-11T12:40:16.607696,479392816,65425,204,-38.16874006768,-50.39807134656,72.122964480535,2,1,18 +2025-03-11T12:40:16.623321,479392816,65425,204,-38.2912519798,-50.513810119275,72.308451609265,2,1,18 +2025-03-11T12:40:16.638946,479392816,65425,204,-38.4090518953,-50.63416181085,72.50319286312,2,1,18 +2025-03-11T12:40:16.654571,479392816,65425,204,-38.51271582094,-50.749867971705,72.721001149285,2,1,18 +2025-03-11T12:40:16.670196,479392816,65425,204,-38.63993972968,-50.87023596921,72.91575596515,2,1,18 +2025-03-11T12:40:16.685821,479392816,65425,204,-38.74831565194,-50.999813498505,73.12438428619,2,1,18 +2025-03-11T12:40:16.701446,479392816,65425,204,-38.85197957758,-51.08779322841,73.332838966225,2,1,18 +2025-03-11T12:40:16.717071,479392816,65425,204,-38.9509315066,-51.161901589875,73.51812532993,2,1,18 +2025-03-11T12:40:16.732696,479392816,65425,204,-39.045171439,-51.24986501385,73.70346053263,2,1,18 +2025-03-11T12:40:16.748321,479392816,65425,204,-39.1394113714,-51.3516916533,73.893472538395,2,1,18 +2025-03-11T12:40:16.763946,479392816,65425,204,-39.2336513038,-51.448897220925,74.088087187225,2,1,18 +2025-03-11T12:40:16.779571,479392816,65425,204,-39.33260323282,-51.55073201334,74.2642424248,2,1,18 +2025-03-11T12:40:16.795196,479392816,65425,204,-39.42684316522,-51.657179724615,74.417303506045,2,1,18 +2025-03-11T12:40:16.810821,479392816,65425,204,-39.516371101,-51.763619282925,74.57497898935,2,1,18 +2025-03-11T12:40:16.826446,479392816,65425,204,-39.62474702326,-51.85622823762,74.741868342805,2,1,18 +2025-03-11T12:40:16.842071,479392816,65425,204,-39.70956296242,-51.94879642749,74.90410260817,2,1,18 +2025-03-11T12:40:16.857696,479392816,65425,204,-39.80380289482,-52.027517707815,75.066294815545,2,1,18 +2025-03-11T12:40:16.873321,479392816,65425,204,-39.88861883398,-52.09698053856,75.223815197845,2,1,18 +2025-03-11T12:40:16.888946,479392816,65425,204,-39.96872277652,-52.17567735999,75.376744696075,2,1,18 +2025-03-11T12:40:16.904571,479392816,65425,204,-40.05353871568,-52.26824554986,75.497388313855,2,1,18 +2025-03-11T12:40:16.920196,479392816,65425,204,-40.14306665146,-52.34695867722,75.650331374095,2,1,18 +2025-03-11T12:40:16.935821,479392816,65425,204,-40.223170594,-52.416413355,75.79860260926,2,1,18 +2025-03-11T12:40:16.951446,479392816,65425,204,-40.2938505433,-52.499714942325,75.937673536285,2,1,18 +2025-03-11T12:40:16.967071,479392816,65425,204,-40.36924248922,-52.583024682615,76.07213006125,2,1,18 +2025-03-11T12:40:16.982696,479392816,65425,204,-40.45405842838,-52.657108585185,76.21118425129,2,1,18 +2025-03-11T12:40:16.998321,479392816,65425,204,-40.52002638106,-52.72653880407,76.336329228115,2,1,18 +2025-03-11T12:40:17.013946,479392816,65425,204,-40.58128233712,-52.809824085465,76.452280677805,2,1,18 +2025-03-11T12:40:17.029571,479392816,65425,204,-40.65667428304,-52.87002846663,76.572780953575,2,1,18 +2025-03-11T12:40:17.045196,479392816,65425,204,-40.72264223572,-52.91635332639,76.702454413465,2,1,18 +2025-03-11T12:40:17.060821,479392816,65425,204,-40.77918619516,-52.99038831117,76.82760436828,2,1,18 +2025-03-11T12:40:17.076446,479392816,65425,204,-40.84515414784,-53.050576386405,76.92036398365,2,1,18 +2025-03-11T12:40:17.092071,479392816,65425,204,-40.89698611066,-53.10611893092,77.01770589907,2,1,18 +2025-03-11T12:40:17.107696,479392816,65425,204,-40.9535300701,-53.13394319745,77.142670453885,2,1,18 +2025-03-11T12:40:17.123321,479392816,65425,204,-41.01478602616,-53.18488097607,77.22614384212,2,1,18 +2025-03-11T12:40:17.138946,479392816,65425,204,-41.06190599236,-53.24965751127,77.30965250734,2,1,18 +2025-03-11T12:40:17.154571,479392816,65425,204,-41.10902595856,-53.31443404647,77.40240353869,2,1,18 +2025-03-11T12:40:17.170196,479392816,65425,204,-41.165569918,-53.365363672125,77.499733695115,2,1,18 +2025-03-11T12:40:17.185821,479392816,65425,204,-41.20797788758,-53.42088991071,77.587819682395,2,1,18 +2025-03-11T12:40:17.201446,479392816,65425,204,-41.2598098504,-53.467190311575,77.67126096862,2,1,18 +2025-03-11T12:40:17.217071,479392816,65425,204,-41.31164181322,-53.51349071244,77.75932343791,2,1,18 +2025-03-11T12:40:17.232696,479392816,65425,204,-41.33991379294,-53.54126606118,77.82417192685,2,1,18 +2025-03-11T12:40:17.248321,479392816,65425,204,-41.37289776928,-53.57367063471,77.89366691986,2,1,18 +2025-03-11T12:40:17.263946,479392816,65425,204,-41.4247297321,-53.6061078201,77.967810219955,2,1,18 +2025-03-11T12:40:17.279571,479392816,65425,204,-41.46713770168,-53.624665484085,78.04188433804,2,1,18 +2025-03-11T12:40:17.295196,479392816,65425,204,-41.50483367464,-53.66632035423,78.111423192055,2,1,18 +2025-03-11T12:40:17.310821,479392816,65425,204,-41.5425296476,-53.717217368025,78.167135576875,2,1,18 +2025-03-11T12:40:17.326446,479392816,65425,204,-41.55666563746,-53.740347186045,78.20421808441,2,1,18 +2025-03-11T12:40:17.342071,479392816,65425,204,-41.57080162732,-53.76809807589,78.26442504727,2,1,18 +2025-03-11T12:40:17.357696,479392816,65425,204,-41.59436161042,-53.805107415315,78.31544028601,2,1,18 +2025-03-11T12:40:17.373321,479392816,65425,204,-41.62263359014,-53.82826169223,78.357164319625,2,1,18 +2025-03-11T12:40:17.388946,479392816,65425,204,-41.65561756648,-53.837560906635,78.37573359892,2,1,18 +2025-03-11T12:40:17.404571,479392816,65425,204,-41.66504155972,-53.846819356215,78.41275370545,2,1,18 +2025-03-11T12:40:17.420196,479392816,65425,204,-41.6838895462,-53.8514730399,78.445147650925,2,1,18 +2025-03-11T12:40:17.435821,479392816,65425,204,-41.71216152592,-53.865385173165,78.472971055345,2,1,18 +2025-03-11T12:40:17.451446,479392816,65425,204,-41.73572150902,-53.888531297115,78.51006712489,2,1,18 +2025-03-11T12:40:17.467071,479392816,65425,204,-41.74985749888,-53.89779789966,78.556336378555,2,1,18 +2025-03-11T12:40:17.482696,479392816,65425,204,-41.74514550226,-53.907031890345,78.570230226745,2,1,18 +2025-03-11T12:40:17.498321,479392816,65425,204,-41.7545694955,-53.925532483575,78.588802681015,2,1,18 +2025-03-11T12:40:17.513946,479392816,65425,204,-41.76870548536,-53.939420157945,78.593499827095,2,1,18 +2025-03-11T12:40:17.529571,479392816,65425,204,-41.76870548536,-53.939420157945,78.58887864403,2,1,18 +2025-03-11T12:40:17.545196,479392816,65425,204,-41.75928149212,-53.94402492384,78.602747171215,2,1,18 +2025-03-11T12:40:17.560821,479392816,65425,204,-41.76870548536,-53.94404122977,78.60738191629,2,1,18 +2025-03-11T12:40:17.576446,479392816,65425,204,-41.76870548536,-53.939420157945,78.59812101016,2,1,18 +2025-03-11T12:40:17.592071,479392816,65425,204,-41.76399348874,-53.925548789505,78.59343742609,2,1,18 +2025-03-11T12:40:17.607696,479392816,65425,204,-41.7545694955,-53.93939569905,78.57499475182,2,1,18 +2025-03-11T12:40:17.623321,479392816,65425,204,-41.73572150902,-53.93936308719,78.561104078605,2,1,18 +2025-03-11T12:40:17.638946,479392816,65425,204,-41.72629751578,-53.92086249396,78.542531624335,2,1,18 +2025-03-11T12:40:17.654571,479392816,65425,204,-41.72629751578,-53.906999278485,78.505506539815,2,1,18 +2025-03-11T12:40:17.670196,479392816,65425,204,-41.71216152592,-53.883869460465,78.47766639841,2,1,18 +2025-03-11T12:40:17.685821,479392816,65425,204,-41.69331353944,-53.86073148948,78.445198292935,2,1,18 +2025-03-11T12:40:17.701446,479392816,65425,204,-41.6838895462,-53.846851968075,78.408159646405,2,1,18 +2025-03-11T12:40:17.717071,479392816,65425,204,-41.65561756648,-53.83293983481,78.380336241985,2,1,18 +2025-03-11T12:40:17.732696,479392816,65425,204,-41.63676958,-53.805180792,78.343228413445,2,1,18 +2025-03-11T12:40:17.748321,479392816,65425,204,-41.63205758338,-53.79130942356,78.29695418179,2,1,18 +2025-03-11T12:40:17.763946,479392816,65425,204,-41.6132095969,-53.7727925244,78.246019884055,2,1,18 +2025-03-11T12:40:17.779571,479392816,65425,204,-41.58022562056,-53.74963009452,78.19042552024,2,1,18 +2025-03-11T12:40:17.795196,479392816,65425,204,-41.55195364084,-53.707991530305,78.130142594365,2,1,18 +2025-03-11T12:40:17.810821,479392816,65425,204,-41.52839365774,-53.675603262705,78.079145895625,2,1,18 +2025-03-11T12:40:17.826446,479392816,65425,204,-41.48598568816,-53.652424526895,78.028159152865,2,1,18 +2025-03-11T12:40:17.842071,479392816,65425,204,-41.4482897152,-53.606148584925,77.97708649111,2,1,18 +2025-03-11T12:40:17.857696,479392816,65425,204,-41.41059374224,-53.59222014573,77.898416510965,2,1,18 +2025-03-11T12:40:17.873321,479392816,65425,204,-41.37289776928,-53.56442849106,77.824312093885,2,1,18 +2025-03-11T12:40:17.888946,479392816,65425,204,-41.32577780308,-53.50889409951,77.74546169173,2,1,18 +2025-03-11T12:40:17.904571,479392816,65425,204,-41.29750582336,-53.46263446347,77.666675493595,2,1,18 +2025-03-11T12:40:17.920196,479392816,65425,204,-41.2598098504,-53.411737449675,77.59709955958,2,1,18 +2025-03-11T12:40:17.935821,479392816,65425,204,-41.20326589096,-53.35156568037,77.51359587235,2,1,18 +2025-03-11T12:40:17.951446,479392816,65425,204,-41.14672193152,-53.300636054715,77.407023349795,2,1,18 +2025-03-11T12:40:17.967071,479392816,65425,204,-41.09017797208,-53.254327500885,77.30971173337,2,1,18 +2025-03-11T12:40:17.982696,479392816,65425,204,-41.03363401264,-53.19415573158,77.20772331388,2,1,18 +2025-03-11T12:40:17.998260,479392820,65421,205,-40.98651404644,-53.14786348368,77.09656171027,2,1,18 +2025-03-11T12:40:18.013885,479392820,65421,205,-40.92525809038,-53.083062489585,76.98068442058,2,1,18 +2025-03-11T12:40:18.029510,479392820,65421,205,-40.8592901377,-53.027495486175,76.87870097908,2,1,18 +2025-03-11T12:40:18.045135,479392820,65421,205,-40.79803418164,-52.97193663573,76.785966684715,2,1,18 +2025-03-11T12:40:18.060760,479392820,65421,205,-40.73677822558,-52.91175671346,76.67472911809,2,1,18 +2025-03-11T12:40:18.076385,479392820,65421,205,-40.6708102729,-52.851568638225,76.549621221265,2,1,18 +2025-03-11T12:40:18.092010,479392820,65421,205,-40.59541832698,-52.768258897935,76.43364942856,2,1,18 +2025-03-11T12:40:18.107635,479392820,65421,205,-40.54829836078,-52.694240219085,76.299270669625,2,1,18 +2025-03-11T12:40:18.123260,479392820,65421,205,-40.47761841148,-52.634043990885,76.17877717486,2,1,18 +2025-03-11T12:40:18.138885,479392820,65421,205,-40.39751446894,-52.564589313105,76.05361185502,2,1,18 +2025-03-11T12:40:18.154510,479392820,65421,205,-40.32212252302,-52.490521716465,75.900707677795,2,1,18 +2025-03-11T12:40:18.170135,479392820,65421,205,-40.24201858048,-52.41644596686,75.77090263489,2,1,18 +2025-03-11T12:40:18.185760,479392820,65421,205,-40.17133863118,-52.342386523185,75.613384055605,2,1,18 +2025-03-11T12:40:18.201385,479392820,65421,205,-40.10065868188,-52.254463864035,75.478915771645,2,1,18 +2025-03-11T12:40:18.217010,479392820,65421,205,-40.02997873258,-52.175783348535,75.344484567685,2,1,18 +2025-03-11T12:40:18.232635,479392820,65421,205,-39.94987479004,-52.09246545528,75.17767298026,2,1,18 +2025-03-11T12:40:18.248260,479392820,65421,205,-39.86505885088,-52.004518337235,75.02007843796,2,1,18 +2025-03-11T12:40:18.263885,479392820,65421,205,-39.76139492524,-51.91653860733,74.857835588575,2,1,18 +2025-03-11T12:40:18.279510,479392820,65421,205,-39.66244299622,-51.814703814915,74.70016508326,2,1,18 +2025-03-11T12:40:18.295135,479392820,65421,205,-39.59176304692,-51.72216008394,74.54719352704,2,1,18 +2025-03-11T12:40:18.310760,479392820,65421,205,-39.49752311452,-51.634196659965,74.3803430566,2,1,18 +2025-03-11T12:40:18.326385,479392820,65421,205,-39.40328318212,-51.541612164165,74.190368130835,2,1,18 +2025-03-11T12:40:18.342010,479392820,65421,205,-39.29019526324,-51.43513184103,74.00955282718,2,1,18 +2025-03-11T12:40:18.357635,479392820,65421,205,-39.19595533084,-51.33330520158,73.83340437061,2,1,18 +2025-03-11T12:40:18.373260,479392820,65421,205,-39.0922914052,-51.236083328025,73.66650325816,2,1,18 +2025-03-11T12:40:18.388885,479392820,65421,205,-38.99333947618,-51.129627463785,73.47646593139,2,1,18 +2025-03-11T12:40:18.404510,479392820,65421,205,-38.89909954378,-51.018558680685,73.295659211755,2,1,18 +2025-03-11T12:40:18.420135,479392820,65421,205,-38.7860116249,-50.907457285725,73.110204185035,2,1,18 +2025-03-11T12:40:18.435760,479392820,65421,205,-38.68234769926,-50.805614340345,72.92942098339,2,1,18 +2025-03-11T12:40:18.451385,479392820,65421,205,-38.57868377362,-50.722255682265,72.720984843355,2,1,18 +2025-03-11T12:40:18.467010,479392820,65421,205,-38.47030785136,-50.615783512095,72.521691588445,2,1,18 +2025-03-11T12:40:18.482635,479392820,65421,205,-38.35721993248,-50.50006104531,72.308490923335,2,1,18 +2025-03-11T12:40:18.498260,479392820,65421,205,-38.23470802036,-50.384322272595,72.095276696215,2,1,18 +2025-03-11T12:40:18.513885,479392820,65421,205,-38.11690810486,-50.259349509195,71.895895719295,2,1,18 +2025-03-11T12:40:18.529510,479392820,65421,205,-38.00382018598,-50.129763826935,71.673397068055,2,1,18 +2025-03-11T12:40:18.545135,479392820,65421,205,-37.88602027048,-50.023275350835,71.44174196968,2,1,18 +2025-03-11T12:40:18.560760,479392820,65421,205,-37.77764434822,-49.89369782154,71.210007733315,2,1,18 +2025-03-11T12:40:18.576385,479392820,65421,205,-37.64570844286,-49.759458455595,70.97359986886,2,1,18 +2025-03-11T12:40:18.592010,479392820,65421,205,-37.50434854426,-49.63444492737,70.73259433933,2,1,18 +2025-03-11T12:40:18.607635,479392820,65421,205,-37.3724126389,-49.48634234595,70.50999440407,2,1,18 +2025-03-11T12:40:18.623260,479392820,65421,205,-37.23576473692,-49.347473755215,70.268940035545,2,1,18 +2025-03-11T12:40:18.638885,479392820,65421,205,-37.1132528248,-49.22249283885,70.027961630035,2,1,18 +2025-03-11T12:40:18.654510,479392820,65421,205,-36.98131691944,-49.097495616555,69.78234847945,2,1,18 +2025-03-11T12:40:18.670135,479392820,65421,205,-36.85880500732,-48.95403041289,69.54129591394,2,1,18 +2025-03-11T12:40:18.685760,479392820,65421,205,-36.72686910196,-48.819791046945,69.29102450029,2,1,18 +2025-03-11T12:40:18.701385,479392820,65421,205,-36.59022119998,-48.685543528035,69.02688275644,2,1,18 +2025-03-11T12:40:18.717010,479392820,65421,205,-36.44886130138,-48.546666784335,68.77657924078,2,1,18 +2025-03-11T12:40:18.732635,479392820,65421,205,-36.30278940616,-48.39853974402,68.516989497985,2,1,18 +2025-03-11T12:40:18.748260,479392820,65421,205,-36.1472935177,-48.26425961325,68.262062996245,2,1,18 +2025-03-11T12:40:18.763885,479392820,65421,205,-36.0059336191,-48.120761797725,67.99787739139,2,1,18 +2025-03-11T12:40:18.779510,479392820,65421,205,-35.8645737205,-47.9587796949,67.71051171121,2,1,18 +2025-03-11T12:40:18.795135,479392820,65421,205,-35.71850182528,-47.810652654585,67.43705841922,2,1,18 +2025-03-11T12:40:18.810760,479392820,65421,205,-35.56300593682,-47.648646092865,67.16353594522,2,1,18 +2025-03-11T12:40:18.826385,479392820,65421,205,-35.40751004836,-47.50050274662,66.88082672509,2,1,18 +2025-03-11T12:40:18.842010,479392820,65421,205,-35.26615014976,-47.357004931095,66.58429283878,2,1,18 +2025-03-11T12:40:18.857635,479392820,65421,205,-35.12007825454,-47.213498962605,66.315479269855,2,1,18 +2025-03-11T12:40:18.873260,479392820,65421,205,-34.9692943627,-47.056121625675,66.03273975073,2,1,18 +2025-03-11T12:40:18.888885,479392820,65421,205,-34.81851047086,-46.88488107327,65.72683869628,2,1,18 +2025-03-11T12:40:18.904510,479392820,65421,205,-34.65359058916,-46.71361606197,65.439402031075,2,1,18 +2025-03-11T12:40:18.920135,479392820,65421,205,-34.4745347176,-46.560810879075,65.16588273205,2,1,18 +2025-03-11T12:40:18.935760,479392820,65421,205,-34.30490283928,-46.403400930285,64.87849490584,2,1,18 +2025-03-11T12:40:18.951385,479392820,65421,205,-34.13998295758,-46.23675699081,64.57721323144,2,1,18 +2025-03-11T12:40:18.967010,479392820,65421,205,-33.97506307588,-46.079355194985,64.262105087845,2,1,18 +2025-03-11T12:40:18.982635,479392820,65421,205,-33.80071920094,-45.908073877755,63.94692776224,2,1,18 +2025-03-11T12:40:18.998260,479392820,65421,205,-33.62166332938,-45.713679048435,63.627029772565,2,1,18 +2025-03-11T12:40:19.013885,479392820,65421,205,-33.44260745782,-45.53314743459,63.311808585955,2,1,18 +2025-03-11T12:40:19.029510,479392820,65421,205,-33.2729755795,-45.3572531985,62.99199831829,2,1,18 +2025-03-11T12:40:19.045135,479392820,65421,205,-33.12219168766,-45.19063371792,62.672252254645,2,1,18 +2025-03-11T12:40:19.060760,479392820,65421,205,-32.94784781272,-45.01935240069,62.35707492904,2,1,18 +2025-03-11T12:40:19.076385,479392820,65421,205,-32.77350393778,-44.834207867985,62.02797843424,2,1,18 +2025-03-11T12:40:19.092010,479392820,65421,205,-32.5897360696,-44.653668101175,61.72661401582,2,1,18 +2025-03-11T12:40:19.107635,479392820,65421,205,-32.40596820142,-44.48699154984,61.38833575288,2,1,18 +2025-03-11T12:40:19.123260,479392820,65421,205,-32.22220033324,-44.311072854855,61.03153567768,2,1,18 +2025-03-11T12:40:19.138885,479392820,65421,205,-32.03372046844,-44.13052493508,60.702437379865,2,1,18 +2025-03-11T12:40:19.154510,479392820,65421,205,-31.84524060364,-43.93611379983,60.36404109592,2,1,18 +2025-03-11T12:40:19.170135,479392820,65421,205,-31.68503271856,-43.74175158237,60.025685498005,2,1,18 +2025-03-11T12:40:19.185760,479392820,65421,205,-31.50126485038,-43.55196967191,59.678072168935,2,1,18 +2025-03-11T12:40:19.201385,479392820,65421,205,-31.3174969822,-43.366808833275,59.330477379865,2,1,18 +2025-03-11T12:40:19.217010,479392820,65421,205,-31.11488112754,-43.176994310955,58.97821574371,2,1,18 +2025-03-11T12:40:19.232635,479392820,65421,205,-30.91226527288,-42.98255871681,58.625935567555,2,1,18 +2025-03-11T12:40:19.248260,479392820,65421,205,-30.7284974047,-42.79277680635,58.28294342155,2,1,18 +2025-03-11T12:40:19.263885,479392820,65421,205,-30.53059354666,-42.59834936517,57.92142766027,2,1,18 +2025-03-11T12:40:19.279510,479392820,65421,205,-30.31855369876,-42.394655321445,57.550612109845,2,1,18 +2025-03-11T12:40:19.295135,479392820,65421,205,-30.13007383396,-42.181759898895,57.189035750575,2,1,18 +2025-03-11T12:40:19.310760,479392820,65421,205,-29.93216997592,-41.987332457715,56.82289880623,2,1,18 +2025-03-11T12:40:19.326385,479392820,65421,205,-29.73426611788,-41.792905016535,56.46138304495,2,1,18 +2025-03-11T12:40:19.342010,479392820,65421,205,-29.53636225984,-41.589235431705,56.095209020605,2,1,18 +2025-03-11T12:40:19.357635,479392820,65421,205,-29.31961041532,-41.37167001954,55.715088703045,2,1,18 +2025-03-11T12:40:19.373260,479392820,65421,205,-29.1028585708,-41.154104607375,55.334968385485,2,1,18 +2025-03-11T12:40:19.388885,479392820,65421,205,-28.88610672628,-40.941160267035,54.945624241795,2,1,18 +2025-03-11T12:40:19.404510,479392820,65421,205,-28.67406687838,-40.732845151485,54.570168968305,2,1,18 +2025-03-11T12:40:19.420135,479392820,65421,205,-28.46202703048,-40.515287892285,54.18081306562,2,1,18 +2025-03-11T12:40:19.435760,479392820,65421,205,-28.26412317244,-40.283891876505,53.79142188595,2,1,18 +2025-03-11T12:40:19.451385,479392820,65421,205,-28.06150731778,-40.07097199506,53.402098085275,2,1,18 +2025-03-11T12:40:19.467010,479392820,65421,205,-27.8306194834,-39.86262426765,53.008130955505,2,1,18 +2025-03-11T12:40:19.482635,479392820,65421,205,-27.6185796355,-39.658930223925,52.614209489755,2,1,18 +2025-03-11T12:40:19.498260,479392820,65421,205,-27.41125178422,-39.44138111769,52.22023918501,2,1,18 +2025-03-11T12:40:19.513885,479392820,65421,205,-27.18036394984,-39.23303339028,51.83551442137,2,1,18 +2025-03-11T12:40:19.529510,479392820,65421,205,-26.94476411884,-39.024677509905,51.4276769614,2,1,18 +2025-03-11T12:40:19.545135,479392820,65421,205,-26.71387628446,-38.797845495195,51.01515093937,2,1,18 +2025-03-11T12:40:19.560760,479392820,65421,205,-26.4877004467,-38.5617794898,50.584109886085,2,1,18 +2025-03-11T12:40:19.576385,479392820,65421,205,-26.2756605988,-38.330359015125,50.15772889888,2,1,18 +2025-03-11T12:40:19.592010,479392820,65421,205,-26.05890875428,-38.10355145931,49.735980853735,2,1,18 +2025-03-11T12:40:19.607635,479392820,65421,205,-25.8280209199,-37.881340516425,49.332715737835,2,1,18 +2025-03-11T12:40:19.623260,479392820,65421,205,-25.60184508214,-37.64527451103,48.93864414907,2,1,18 +2025-03-11T12:40:19.638885,479392820,65421,205,-25.37566924438,-37.399966361985,48.535293114175,2,1,18 +2025-03-11T12:40:19.654510,479392820,65421,205,-25.15420540324,-37.154666365905,48.09960057883,2,1,18 +2025-03-11T12:40:19.670135,479392820,65421,205,-24.91389357562,-36.92319697344,47.66855772253,2,1,18 +2025-03-11T12:40:19.685760,479392820,65421,205,-24.67829374462,-36.687114662115,47.228260741105,2,1,18 +2025-03-11T12:40:19.701385,479392820,65421,205,-24.45211790686,-36.44180651307,46.79718260782,2,1,18 +2025-03-11T12:40:19.717010,479392820,65421,205,-24.22123007248,-36.19649021106,46.37534005966,2,1,18 +2025-03-11T12:40:19.732635,479392820,65421,205,-23.99505423472,-35.96504527749,45.953559912505,2,1,18 +2025-03-11T12:40:19.748260,479392820,65421,205,-23.7547424071,-35.724333741375,45.522479976205,2,1,18 +2025-03-11T12:40:19.763885,479392820,65421,205,-23.51443057948,-35.48362220526,45.063672941515,2,1,18 +2025-03-11T12:40:19.779510,479392820,65421,205,-23.26940675524,-35.26138680348,44.64190275034,2,1,18 +2025-03-11T12:40:19.795135,479392820,65421,205,-23.01495893776,-35.02065080847,44.192317738765,2,1,18 +2025-03-11T12:40:19.810760,479392820,65421,205,-22.7652231169,-34.779922966425,43.74736069126,2,1,18 +2025-03-11T12:40:19.826385,479392820,65421,205,-22.52019929266,-34.53458220552,43.29314951863,2,1,18 +2025-03-11T12:40:19.842010,479392820,65421,205,-22.28459946166,-34.29387882237,42.85745518027,2,1,18 +2025-03-11T12:40:19.857635,479392820,65421,205,-22.04428763404,-34.04854621443,42.41711433784,2,1,18 +2025-03-11T12:40:19.873260,479392820,65421,205,-21.79455181318,-33.798576228735,41.944393111945,2,1,18 +2025-03-11T12:40:19.888885,479392820,65421,205,-21.54952798894,-33.557856539655,41.47633693012,2,1,18 +2025-03-11T12:40:19.904510,479392820,65421,205,-21.3045041647,-33.289410419625,41.017411874425,2,1,18 +2025-03-11T12:40:19.920135,479392820,65421,205,-21.06419233708,-33.034835668035,40.55392803667,2,1,18 +2025-03-11T12:40:19.935760,479392820,65421,205,-20.8097445196,-32.784857529375,40.104305945095,2,1,18 +2025-03-11T12:40:19.951385,479392820,65421,205,-20.5505847055,-32.539492309575,39.645453246385,2,1,18 +2025-03-11T12:40:19.967010,479392820,65421,205,-20.30084888464,-32.27103803658,39.177279043555,2,1,18 +2025-03-11T12:40:19.982635,479392820,65421,205,-20.04640106716,-32.007196682445,38.70911659972,2,1,18 +2025-03-11T12:40:19.998260,479392820,65421,205,-19.78252925644,-31.747960094205,38.240959133875,2,1,18 +2025-03-11T12:40:20.013885,479392820,65421,205,-19.51865744572,-31.48410243414,37.777404311095,2,1,18 +2025-03-11T12:40:20.029510,479392820,65421,205,-19.25949763162,-31.23873721434,37.309309246255,2,1,18 +2025-03-11T12:40:20.045135,479392820,65421,205,-19.00976181076,-30.979525084995,36.84579330649,2,1,18 +2025-03-11T12:40:20.060760,479392820,65421,205,-18.74589000004,-30.711046353105,36.368356394515,2,1,18 +2025-03-11T12:40:20.076385,479392820,65421,205,-18.4773061927,-30.44255946825,35.900155067665,2,1,18 +2025-03-11T12:40:20.092010,479392820,65421,205,-18.2181463786,-30.19719424845,35.413575270565,2,1,18 +2025-03-11T12:40:20.107635,479392820,65421,205,-17.9589865645,-29.928723669525,34.954629871855,2,1,18 +2025-03-11T12:40:20.123260,479392820,65421,205,-17.6998267504,-29.6602530906,34.458715008625,2,1,18 +2025-03-11T12:40:20.138885,479392820,65421,205,-17.4171069532,-29.4009838905,33.96280332037,2,1,18 +2025-03-11T12:40:20.154510,479392820,65421,205,-17.14381114924,-29.127867780855,33.48995548945,2,1,18 +2025-03-11T12:40:20.170135,479392820,65421,205,-16.88936333176,-28.86402642672,32.984823581095,2,1,18 +2025-03-11T12:40:20.185760,479392820,65421,205,-16.63491551428,-28.59556400076,32.493536681935,2,1,18 +2025-03-11T12:40:20.201385,479392820,65421,205,-16.36633170694,-28.33169818773,31.997626796695,2,1,18 +2025-03-11T12:40:20.217010,479392820,65421,205,-16.10717189284,-28.063227608805,31.51557548266,2,1,18 +2025-03-11T12:40:20.232635,479392820,65421,205,-15.8385880855,-27.79474072395,31.042752972745,2,1,18 +2025-03-11T12:40:20.248260,479392820,65421,205,-15.57000427816,-27.526253839095,30.546824547505,2,1,18 +2025-03-11T12:40:20.263885,479392820,65421,205,-15.31084446406,-27.25778326017,30.050909684275,2,1,18 +2025-03-11T12:40:20.279510,479392820,65421,205,-15.0375486601,-26.97080393505,29.55490031803,2,1,18 +2025-03-11T12:40:20.295135,479392820,65421,205,-14.74069287304,-26.683783845105,29.0403723145,2,1,18 +2025-03-11T12:40:20.310760,479392820,65421,205,-14.46268507246,-26.42452279797,28.53522504112,2,1,18 +2025-03-11T12:40:20.326385,479392820,65421,205,-14.19881326174,-26.142180850605,28.048490143015,2,1,18 +2025-03-11T12:40:20.342010,479392820,65421,205,-13.92551745778,-25.87830688461,27.53408874451,2,1,18 +2025-03-11T12:40:20.357635,479392820,65421,205,-13.63808566396,-25.60516631607,27.042735838315,2,1,18 +2025-03-11T12:40:20.373260,479392820,65421,205,-13.36478986,-25.31818699095,26.551347655135,2,1,18 +2025-03-11T12:40:20.388885,479392820,65421,205,-13.08678205942,-25.04506272834,26.027660029495,2,1,18 +2025-03-11T12:40:20.404510,479392820,65421,205,-12.82762224532,-24.75348679029,25.49930418481,2,1,18 +2025-03-11T12:40:20.420135,479392820,65421,205,-12.54961444474,-24.466499312205,24.998666854495,2,1,18 +2025-03-11T12:40:20.435760,479392820,65421,205,-12.26218265092,-24.184116600015,24.493413319105,2,1,18 +2025-03-11T12:40:20.451385,479392820,65421,205,-11.97946285372,-23.89249989714,23.983508301655,2,1,18 +2025-03-11T12:40:20.467010,479392820,65421,205,-11.68260706666,-23.614721950845,23.45515382893,2,1,18 +2025-03-11T12:40:20.482635,479392820,65421,205,-11.39046327622,-23.346194301165,22.949949132535,2,1,18 +2025-03-11T12:40:20.498260,479392820,65421,205,-11.11245547564,-23.045343607605,22.435392633025,2,1,18 +2025-03-11T12:40:20.513885,479392820,65421,205,-10.82502368182,-22.753718751765,21.920859651505,2,1,18 +2025-03-11T12:40:20.529510,479392820,65421,205,-10.54230388462,-22.48982847984,21.392581141795,2,1,18 +2025-03-11T12:40:20.545135,479392820,65421,205,-10.25958408742,-22.207453920615,20.85960728902,2,1,18 +2025-03-11T12:40:20.560760,479392820,65421,205,-9.96744029698,-21.920441983635,20.335843700365,2,1,18 +2025-03-11T12:40:20.576385,479392820,65421,205,-9.68000850316,-21.62419605597,19.80742862965,2,1,18 +2025-03-11T12:40:20.592010,479392820,65421,205,-9.39257670934,-21.337192271955,19.297535371195,2,1,18 +2025-03-11T12:40:20.607635,479392820,65421,205,-9.11456890876,-21.045583722045,18.783015951685,2,1,18 +2025-03-11T12:40:20.623260,479392820,65421,205,-8.82713711494,-20.75857993803,18.250016777905,2,1,18 +2025-03-11T12:40:20.638885,479392820,65421,205,-8.53028132788,-20.462317704435,17.726209328245,2,1,18 +2025-03-11T12:40:20.654510,479392820,65421,205,-8.24756153068,-20.175322073385,17.216322850795,2,1,18 +2025-03-11T12:40:20.670135,479392820,65421,205,-7.9695537301,-19.892955667125,16.674113412895,2,1,18 +2025-03-11T12:40:20.685760,479392820,65421,205,-7.67269794304,-19.59669343353,16.12720004791,2,1,18 +2025-03-11T12:40:20.701385,479392820,65421,205,-7.37113015936,-19.29118090332,15.58948518805,2,1,18 +2025-03-11T12:40:20.717010,479392820,65421,205,-7.09312235878,-19.004193425235,15.07498430854,2,1,18 +2025-03-11T12:40:20.732635,479392820,65421,205,-6.81982655482,-18.717214100115,14.560490210035,2,1,18 +2025-03-11T12:40:20.748260,479392820,65421,205,-6.52768276438,-18.420960019485,14.02744717525,2,1,18 +2025-03-11T12:40:20.763885,479392820,65421,205,-6.23082697732,-18.14318207319,13.50371388559,2,1,18 +2025-03-11T12:40:20.779510,479392820,65421,205,-5.93868318688,-17.851549064385,12.979931756935,2,1,18 +2025-03-11T12:40:20.795135,479392820,65421,205,-5.65596338968,-17.555311289685,12.44690228416,2,1,18 +2025-03-11T12:40:20.810760,479392820,65421,205,-5.34968360938,-17.25903275016,11.90459654023,2,1,18 +2025-03-11T12:40:20.826385,479392820,65421,205,-5.04340382908,-16.953512066985,11.357632533235,2,1,18 +2025-03-11T12:40:20.842010,479392820,65421,205,-4.77010802512,-16.648048454565,10.829200725535,2,1,18 +2025-03-11T12:40:20.857635,479392820,65421,205,-4.4826762313,-16.36104467055,10.286959185625,2,1,18 +2025-03-11T12:40:20.873260,479392820,65421,205,-4.18110844762,-16.06477428399,9.73541785657,2,1,18 +2025-03-11T12:40:20.888885,479392820,65421,205,-3.87954066394,-15.77774604108,9.183913607515,2,1,18 +2025-03-11T12:40:20.904510,479392820,65421,205,-3.58268487688,-15.48610487931,8.641639965595,2,1,18 +2025-03-11T12:40:20.920135,479392820,65421,205,-3.2811170932,-15.18983449275,8.103962185735,2,1,18 +2025-03-11T12:40:20.935760,479392820,65421,205,-2.99368529938,-14.893588565085,7.56630474889,2,1,18 +2025-03-11T12:40:20.951385,479392820,65421,205,-2.70625350556,-14.583479421945,7.01472814285,2,1,18 +2025-03-11T12:40:20.967010,479392820,65421,205,-2.40468572188,-14.29183010721,6.47706890299,2,1,18 +2025-03-11T12:40:20.982635,479392820,65421,205,-2.11254193144,-13.99557602658,5.925541135945,2,1,18 +2025-03-11T12:40:20.998260,479392820,65421,205,-1.7968381579,-13.699281181125,5.37860064694,2,1,18 +2025-03-11T12:40:21.013885,479392820,65421,205,-1.49527037422,-13.393768650915,4.854749336275,2,1,18 +2025-03-11T12:40:21.029510,479392820,65421,205,-1.19841458716,-13.102127489145,4.30785451129,2,1,18 +2025-03-11T12:40:21.045135,479392820,65421,205,-0.9015588001,-12.8151073992,3.760978226305,2,1,18 +2025-03-11T12:40:21.060760,479392820,65421,205,-0.61412700628,-12.509619327885,3.209420160265,2,1,18 +2025-03-11T12:40:21.076385,479392820,65421,205,-0.30784722598,-12.20409864471,2.66245615327,2,1,18 +2025-03-11T12:40:21.092010,479392820,65421,205,-0.0109914389200001,-11.90321533929,2.12938779748,2,1,18 +2025-03-11T12:40:21.107635,479392820,65421,205,0.28586434814,-11.606953105695,1.591716798625,2,1,18 +2025-03-11T12:40:21.123260,479392820,65421,205,0.57800813858,-11.30607795324,1.044791674645,2,1,18 +2025-03-11T12:40:21.138885,479392820,65421,205,0.8654399324,-11.009832025575,0.502513054735,2,1,18 +2025-03-11T12:40:21.154510,479392820,65421,205,1.17643170932,-10.713545333085,-0.0397994702000002,2,1,18 +2025-03-11T12:40:21.170135,479392820,65421,205,1.47328749638,-10.42652524314,-0.577433389055,2,1,18 +2025-03-11T12:40:21.185760,479392820,65421,205,1.77485528006,-10.11177056928,-1.124427695045,2,1,18 +2025-03-11T12:40:21.201385,479392820,65421,205,2.07642306374,-9.792394823595,-1.69454645636,2,1,18 +2025-03-11T12:40:21.217010,479392820,65421,205,2.37799084742,-9.486882293385,-2.246124865415,2,1,18 +2025-03-11T12:40:21.232635,479392820,65421,205,2.67013463786,-9.18600714093,-2.78842880633,2,1,18 +2025-03-11T12:40:21.248260,479392820,65421,205,2.97641441816,-8.89434967323,-3.326094827195,2,1,18 +2025-03-11T12:40:21.263885,479392820,65421,205,3.28740619508,-8.593441908915,-3.84994115987,2,1,18 +2025-03-11T12:40:21.279510,479392820,65421,205,3.58426198214,-8.292558603495,-4.387630698725,2,1,18 +2025-03-11T12:40:21.295135,479392820,65421,205,3.88582976582,-7.97318285781,-4.93926472778,2,1,18 +2025-03-11T12:40:21.310760,479392820,65421,205,4.17326155964,-7.67231585832,-5.48156188769,2,1,18 +2025-03-11T12:40:21.326385,479392820,65421,205,4.46540535008,-7.37606177769,-6.02846847167,2,1,18 +2025-03-11T12:40:21.342010,479392820,65421,205,4.76697313376,-7.07054924748,-6.57542569766,2,1,18 +2025-03-11T12:40:21.357635,479392820,65421,205,5.07325291406,-6.77889177978,-7.13619763385,2,1,18 +2025-03-11T12:40:21.373260,479392820,65421,205,5.3653967045,-6.478016627325,-7.696986307025,2,1,18 +2025-03-11T12:40:21.388885,479392820,65421,205,5.66696448818,-6.17712516894,-8.225440260755,2,1,18 +2025-03-11T12:40:21.404510,479392820,65421,205,5.96382027524,-5.87624186352,-8.767750982675,2,1,18 +2025-03-11T12:40:21.420135,479392820,65421,205,6.26538805892,-5.57072933331,-9.333192940925,2,1,18 +2025-03-11T12:40:21.435760,479392820,65421,205,6.54810785612,-5.269870486785,-9.889346869025,2,1,18 +2025-03-11T12:40:21.451385,479392820,65421,205,6.83553964994,-4.969003487295,-10.431644028935,2,1,18 +2025-03-11T12:40:21.467010,479392820,65421,205,7.132395437,-4.686604469175,-10.973880590855,2,1,18 +2025-03-11T12:40:21.482635,479392820,65421,205,7.45281120716,-4.37643825528,-11.5162622978,2,1,18 +2025-03-11T12:40:21.498260,479392820,65421,205,7.7685149807,-4.075522338,-12.05860014374,2,1,18 +2025-03-11T12:40:21.513885,479392820,65421,205,8.05594677452,-3.779276410335,-12.60087876365,2,1,18 +2025-03-11T12:40:21.529510,479392820,65421,205,8.3575145582,-3.4691428083,-13.14785452964,2,1,18 +2025-03-11T12:40:21.545135,479392820,65421,205,8.64965834864,-3.17288872767,-13.69476111362,2,1,18 +2025-03-11T12:40:21.560760,479392820,65421,205,8.95122613232,-2.871997269285,-14.227836250415,2,1,18 +2025-03-11T12:40:21.576385,479392820,65421,205,9.23394592952,-2.575759494585,-14.765486906255,2,1,18 +2025-03-11T12:40:21.592010,479392820,65421,205,9.54022570982,-2.28872309871,-15.33086148551,2,1,18 +2025-03-11T12:40:21.607635,479392820,65421,205,9.8417934935,-2.0016948558,-15.86850218537,2,1,18 +2025-03-11T12:40:21.623260,479392820,65421,205,10.14336127718,-1.70542446924,-16.383074049905,2,1,18 +2025-03-11T12:40:21.638885,479392820,65421,205,10.44021706424,-1.399920091995,-16.92078212876,2,1,18 +2025-03-11T12:40:21.654510,479392820,65421,205,10.71822486482,-1.099069398435,-17.46306572666,2,1,18 +2025-03-11T12:40:21.670135,479392820,65421,205,11.01508065188,-0.807428236664999,-18.00533936858,2,1,18 +2025-03-11T12:40:21.685760,479392820,65421,205,11.30722444232,-0.520416299685,-18.56145123869,2,1,18 +2025-03-11T12:40:21.701385,479392820,65421,205,11.59936823276,-0.214920075404999,-19.103773719605,2,1,18 +2025-03-11T12:40:21.717010,479392820,65421,205,11.8915120232,0.0767129333999996,-19.632177031325,2,1,18 +2025-03-11T12:40:21.732635,479392820,65421,205,12.18836781026,0.372975166995,-20.174469213245,2,1,18 +2025-03-11T12:40:21.748260,479392820,65421,205,12.49464759056,0.683116921995,-20.72145176024,2,1,18 +2025-03-11T12:40:21.763885,479392820,65421,205,12.81506336072,0.970177776765,-21.282225499445,2,1,18 +2025-03-11T12:40:21.779510,479392820,65421,205,13.10720715116,1.26181078557,-21.81524999423,2,1,18 +2025-03-11T12:40:21.795135,479392820,65421,205,13.38992694836,1.55804856027,-22.329794734745,2,1,18 +2025-03-11T12:40:21.810760,479392820,65421,205,13.68678273542,1.85893186569,-22.872105456665,2,1,18 +2025-03-11T12:40:21.826385,479392820,65421,205,13.97421452924,2.15055672153,-23.395880804315,2,1,18 +2025-03-11T12:40:21.842010,479392820,65421,205,14.26635831968,2.43756865851,-23.924265576035,2,1,18 +2025-03-11T12:40:21.857635,479392820,65421,205,14.53965412364,2.729169055455,-24.4572629468,2,1,18 +2025-03-11T12:40:21.873260,479392820,65421,205,14.83179791408,3.03004420791,-24.990324521585,2,1,18 +2025-03-11T12:40:21.888885,479392820,65421,205,15.1192297079,3.3124269201,-25.5186839723,2,1,18 +2025-03-11T12:40:21.904510,479392820,65421,205,15.40666150172,3.59480963229,-26.037801056885,2,1,18 +2025-03-11T12:40:21.920135,479392820,65421,205,15.69880529216,3.87257942562,-26.56152756554,2,1,18 +2025-03-11T12:40:21.935760,479392820,65421,205,15.98623708598,4.16420428146,-27.09454527932,2,1,18 +2025-03-11T12:40:21.951385,479392820,65421,205,16.2736688798,4.46507128095,-27.613736523905,2,1,18 +2025-03-11T12:40:21.967010,479392820,65421,205,16.57052466686,4.770575658195,-28.16068696889,2,1,18 +2025-03-11T12:40:21.982635,479392820,65421,205,16.84853246744,5.04832099263,-28.70287786679,2,1,18 +2025-03-11T12:40:21.998199,479392824,65417,206,17.13125226464,5.33531662368,-29.226627893435,2,1,18 +2025-03-11T12:40:22.013824,479392824,65417,206,17.42339605508,5.63157070431,-29.74118619596,2,1,18 +2025-03-11T12:40:22.029449,479392824,65417,206,17.70140385566,5.90469496692,-30.260252638535,2,1,18 +2025-03-11T12:40:22.045074,479392824,65417,206,17.98412365286,6.196311669795,-30.77477883905,2,1,18 +2025-03-11T12:40:22.060699,479392824,65417,206,18.28097943992,6.48333175974,-31.284685659515,2,1,18 +2025-03-11T12:40:22.076324,479392824,65417,206,18.5825472236,6.756496787175,-31.794543640985,2,1,18 +2025-03-11T12:40:22.091949,479392824,65417,206,18.86055502418,7.04348426526,-32.33215043582,2,1,18 +2025-03-11T12:40:22.107574,479392824,65417,206,19.13385082814,7.32122144673,-32.83274390513,2,1,18 +2025-03-11T12:40:22.123199,479392824,65417,206,19.41185862872,7.60358785299,-33.333362695445,2,1,18 +2025-03-11T12:40:22.138824,479392824,65417,206,19.6898664293,7.890575331075,-33.85248475802,2,1,18 +2025-03-11T12:40:22.154449,479392824,65417,206,19.96787422988,8.17756280916,-34.36698563753,2,1,18 +2025-03-11T12:40:22.170074,479392824,65417,206,20.24117003384,8.459921062455,-34.87684001297,2,1,18 +2025-03-11T12:40:22.185699,479392824,65417,206,20.5144658378,8.728416100275,-35.39588113454,2,1,18 +2025-03-11T12:40:22.201324,479392824,65417,206,20.797185635,9.00154851585,-35.91495435812,2,1,18 +2025-03-11T12:40:22.216949,479392824,65417,206,21.0799054322,9.2885441469,-36.42484083557,2,1,18 +2025-03-11T12:40:22.232574,479392824,65417,206,21.35791323278,9.566289481335,-36.90233517056,2,1,18 +2025-03-11T12:40:22.248199,479392824,65417,206,21.63592103336,9.839413743945,-37.40753806394,2,1,18 +2025-03-11T12:40:22.263824,479392824,65417,206,21.90921683732,10.107908781765,-37.89885208712,2,1,18 +2025-03-11T12:40:22.279449,479392824,65417,206,22.19193663452,10.385662269165,-38.394837935375,2,1,18 +2025-03-11T12:40:22.295074,479392824,65417,206,22.46523243848,10.654157306985,-38.90925787388,2,1,18 +2025-03-11T12:40:22.310699,479392824,65417,206,22.74795223568,10.941152938035,-39.414523168265,2,1,18 +2025-03-11T12:40:22.326324,479392824,65417,206,23.0118240464,11.209631669925,-39.89196008024,2,1,18 +2025-03-11T12:40:22.341949,479392824,65417,206,23.28040785374,11.473497482955,-40.374006416285,2,1,18 +2025-03-11T12:40:22.357574,479392824,65417,206,23.55841565432,11.746621745565,-40.879209309665,2,1,18 +2025-03-11T12:40:22.373199,479392824,65417,206,23.82228746504,12.01972154928,-41.370528310835,2,1,18 +2025-03-11T12:40:22.388824,479392824,65417,206,24.09087127238,12.29282950596,-41.86185409301,2,1,18 +2025-03-11T12:40:22.404449,479392824,65417,206,24.35003108648,12.561300084885,-42.362390139305,2,1,18 +2025-03-11T12:40:22.420074,479392824,65417,206,24.59976690734,12.825133286055,-42.85365171746,2,1,18 +2025-03-11T12:40:22.435699,479392824,65417,206,24.8730627113,13.08900725205,-43.349568383705,2,1,18 +2025-03-11T12:40:22.451324,479392824,65417,206,25.1322225254,13.348235687325,-43.826961434675,2,1,18 +2025-03-11T12:40:22.466949,479392824,65417,206,25.39609433612,13.61209334739,-44.28589507439,2,1,18 +2025-03-11T12:40:22.482574,479392824,65417,206,25.6741021367,13.89445975365,-44.758786766315,2,1,18 +2025-03-11T12:40:22.498199,479392824,65417,206,25.93797394742,14.16293848554,-45.24546604442,2,1,18 +2025-03-11T12:40:22.513824,479392824,65417,206,26.1924217649,14.417537696025,-45.73669732358,2,1,18 +2025-03-11T12:40:22.529449,479392824,65417,206,26.451581579,14.681387203125,-46.227972463745,2,1,18 +2025-03-11T12:40:22.545074,479392824,65417,206,26.72016538634,14.945253016155,-46.70077643366,2,1,18 +2025-03-11T12:40:22.560699,479392824,65417,206,26.97461320382,15.213715442115,-47.14585150217,2,1,18 +2025-03-11T12:40:22.576324,479392824,65417,206,27.22434902468,15.459064355985,-47.609311821935,2,1,18 +2025-03-11T12:40:22.591949,479392824,65417,206,27.49764482864,15.71369617833,-48.072843126725,2,1,18 +2025-03-11T12:40:22.607574,479392824,65417,206,27.73795665626,15.972892001745,-48.540966687545,2,1,18 +2025-03-11T12:40:22.623199,479392824,65417,206,28.00182846698,16.232128589985,-48.99988178726,2,1,18 +2025-03-11T12:40:22.638824,479392824,65417,206,28.25156428784,16.505203934805,-49.46807453009,2,1,18 +2025-03-11T12:40:22.654449,479392824,65417,206,28.51072410194,16.75519022643,-49.922324585735,2,1,18 +2025-03-11T12:40:22.670074,479392824,65417,206,28.7604599228,16.99129699665,-50.37650545937,2,1,18 +2025-03-11T12:40:22.685699,479392824,65417,206,29.01490774028,17.227411919835,-50.83993548014,2,1,18 +2025-03-11T12:40:22.701324,479392824,65417,206,29.26935555776,17.46352684302,-51.29412313478,2,1,18 +2025-03-11T12:40:22.716949,479392824,65417,206,29.514379382,17.718109747575,-51.73912902128,2,1,18 +2025-03-11T12:40:22.732574,479392824,65417,206,29.76411520286,17.96807973327,-52.174880782655,2,1,18 +2025-03-11T12:40:22.748199,479392824,65417,206,30.00442703048,18.21341234121,-52.62908517428,2,1,18 +2025-03-11T12:40:22.763824,479392824,65417,206,30.24002686148,18.46335786801,-53.069437775705,2,1,18 +2025-03-11T12:40:22.779449,479392824,65417,206,30.47091469586,18.69943202637,-53.518970342255,2,1,18 +2025-03-11T12:40:22.795074,479392824,65417,206,30.71122652348,18.930901418835,-53.96387674775,2,1,18 +2025-03-11T12:40:22.810699,479392824,65417,206,30.95625034772,19.180863251565,-54.40886409425,2,1,18 +2025-03-11T12:40:22.826324,479392824,65417,206,31.19185017872,19.43542985019,-54.84461405261,2,1,18 +2025-03-11T12:40:22.841949,479392824,65417,206,31.42745000972,19.67613323334,-55.266444841775,2,1,18 +2025-03-11T12:40:22.857574,479392824,65417,206,31.6583378441,19.9122073917,-55.715977408325,2,1,18 +2025-03-11T12:40:22.873199,479392824,65417,206,31.88922567848,20.13903940641,-56.15160934568,2,1,18 +2025-03-11T12:40:22.888824,479392824,65417,206,32.13424950272,20.37975909549,-56.57807487992,2,1,18 +2025-03-11T12:40:22.904449,479392824,65417,206,32.36984933372,20.62046247864,-56.99528448602,2,1,18 +2025-03-11T12:40:22.920074,479392824,65417,206,32.60544916472,20.847302646315,-57.41243847212,2,1,18 +2025-03-11T12:40:22.935699,479392824,65417,206,32.82691300586,21.083360498745,-57.82498801214,2,1,18 +2025-03-11T12:40:22.951324,479392824,65417,206,33.05780084024,21.31481358528,-58.242153757235,2,1,18 +2025-03-11T12:40:22.966949,479392824,65417,206,33.29811266786,21.546282977745,-58.65933306434,2,1,18 +2025-03-11T12:40:22.982574,479392824,65417,206,33.52428850562,21.768485767665,-59.08569731456,2,1,18 +2025-03-11T12:40:22.998199,479392824,65417,206,33.73632835352,21.995285170515,-59.493575029505,2,1,18 +2025-03-11T12:40:23.013824,479392824,65417,206,33.96250419128,22.235972247735,-59.901528707465,2,1,18 +2025-03-11T12:40:23.029449,479392824,65417,206,34.18396803242,22.45816688469,-60.30015907829,2,1,18 +2025-03-11T12:40:23.045074,479392824,65417,206,34.40071987694,22.68035336868,-60.721888583435,2,1,18 +2025-03-11T12:40:23.060699,479392824,65417,206,34.6268957147,22.879450799475,-61.129675401395,2,1,18 +2025-03-11T12:40:23.076324,479392824,65417,206,34.86720754232,23.10167804829,-61.53757526237,2,1,18 +2025-03-11T12:40:23.091949,479392824,65417,206,35.09338338008,23.33312298186,-61.931628311135,2,1,18 +2025-03-11T12:40:23.107574,479392824,65417,206,35.30542322798,23.536817025585,-62.32092859382,2,1,18 +2025-03-11T12:40:23.123199,479392824,65417,206,35.51746307588,23.745132141135,-62.70562623344,2,1,18 +2025-03-11T12:40:23.138824,479392824,65417,206,35.7342149204,23.95345540965,-63.090330654065,2,1,18 +2025-03-11T12:40:23.154449,479392824,65417,206,35.93211877844,24.180230353605,-63.46583974454,2,1,18 +2025-03-11T12:40:23.170074,479392824,65417,206,36.13002263648,24.383899938435,-63.841256135015,2,1,18 +2025-03-11T12:40:23.185699,479392824,65417,206,36.35148647762,24.59685243174,-64.22136469358,2,1,18 +2025-03-11T12:40:23.201324,479392824,65417,206,36.56823832214,24.81903891573,-64.596882368075,2,1,18 +2025-03-11T12:40:23.216949,479392824,65417,206,36.78499016666,25.02274111242,-64.986189431765,2,1,18 +2025-03-11T12:40:23.232574,479392824,65417,206,36.9828940247,25.212547481775,-65.35230783611,2,1,18 +2025-03-11T12:40:23.248199,479392824,65417,206,37.18079788274,25.43008028208,-65.72315866352,2,1,18 +2025-03-11T12:40:23.263824,479392824,65417,206,37.38812573402,25.64300831649,-66.098625696005,2,1,18 +2025-03-11T12:40:23.279449,479392824,65417,206,37.59074158868,25.846686054285,-66.48791241668,2,1,18 +2025-03-11T12:40:23.295074,479392824,65417,206,37.78864544672,26.022629208165,-66.84011165183,2,1,18 +2025-03-11T12:40:23.310699,479392824,65417,206,37.97712531152,26.21241927159,-67.196974128035,2,1,18 +2025-03-11T12:40:23.326324,479392824,65417,206,38.15618118308,26.40681410091,-67.53535684997,2,1,18 +2025-03-11T12:40:23.341949,479392824,65417,206,38.34466104788,26.605846307985,-67.88763522311,2,1,18 +2025-03-11T12:40:23.357574,479392824,65417,206,38.55198889916,26.80491112692,-68.244561903335,2,1,18 +2025-03-11T12:40:23.373199,479392824,65417,206,38.75931675044,26.994733802205,-68.60145150356,2,1,18 +2025-03-11T12:40:23.388824,479392824,65417,206,38.95250861186,27.184532018595,-68.944457211575,2,1,18 +2025-03-11T12:40:23.404449,479392824,65417,206,39.13627648004,27.37893500088,-69.29671026371,2,1,18 +2025-03-11T12:40:23.420074,479392824,65417,206,39.32004434822,27.564095839515,-69.658168601975,2,1,18 +2025-03-11T12:40:23.435699,479392824,65417,206,39.51794820626,27.749281137045,-69.97805663567,2,1,18 +2025-03-11T12:40:23.451324,479392824,65417,206,39.71114006768,27.957563640735,-70.302651771425,2,1,18 +2025-03-11T12:40:23.466949,479392824,65417,206,39.89019593924,28.13809525458,-70.64097887336,2,1,18 +2025-03-11T12:40:23.482574,479392824,65417,206,40.06453981418,28.31861871546,-70.96081446203,2,1,18 +2025-03-11T12:40:23.498199,479392824,65417,206,40.2341716925,28.499134023375,-71.30374918502,2,1,18 +2025-03-11T12:40:23.513824,479392824,65417,206,40.3990915742,28.6565358192,-71.64196324394,2,1,18 +2025-03-11T12:40:23.529449,479392824,65417,206,40.57814744576,28.837067433045,-71.95718443055,2,1,18 +2025-03-11T12:40:23.545074,479392824,65417,206,40.7524913207,29.017590893925,-72.27702001922,2,1,18 +2025-03-11T12:40:23.560699,479392824,65417,206,40.9174112024,29.19347697705,-72.601444688945,2,1,18 +2025-03-11T12:40:23.576324,479392824,65417,206,41.09175507734,29.37400043793,-72.91665909455,2,1,18 +2025-03-11T12:40:23.591949,479392824,65417,206,41.26609895228,29.54528175516,-73.21797287096,2,1,18 +2025-03-11T12:40:23.607574,479392824,65417,206,41.44986682046,29.702716162845,-73.51924458938,2,1,18 +2025-03-11T12:40:23.623199,479392824,65417,206,41.61007470554,29.860109805705,-73.82510358584,2,1,18 +2025-03-11T12:40:23.638824,479392824,65417,206,41.77499458724,30.02675374518,-74.140248809435,2,1,18 +2025-03-11T12:40:23.654449,479392824,65417,206,41.94462646556,30.188784765795,-74.43227635871,2,1,18 +2025-03-11T12:40:23.670074,479392824,65417,206,42.10012235402,30.35541239934,-74.72430210497,2,1,18 +2025-03-11T12:40:23.685699,479392824,65417,206,42.2603302391,30.52204818585,-75.0209558153,2,1,18 +2025-03-11T12:40:23.701324,479392824,65417,206,42.42053812418,30.674820756885,-75.29906917337,2,1,18 +2025-03-11T12:40:23.716949,479392824,65417,206,42.5666100194,30.818326725375,-75.577125108425,2,1,18 +2025-03-11T12:40:23.732574,479392824,65417,206,42.72210590786,30.980333287095,-75.83678403323,2,1,18 +2025-03-11T12:40:23.748199,479392824,65417,206,42.88231379294,31.128484786305,-76.128742400495,2,1,18 +2025-03-11T12:40:23.763824,479392824,65417,206,43.04723367464,31.28588658213,-76.4161234457,2,1,18 +2025-03-11T12:40:23.779449,479392824,65417,206,43.20744155972,31.43403808134,-76.708081812965,2,1,18 +2025-03-11T12:40:23.795074,479392824,65417,206,43.33466546846,31.57751143797,-76.990731807065,2,1,18 +2025-03-11T12:40:23.810699,479392824,65417,206,43.46660137382,31.72561401939,-77.250301206845,2,1,18 +2025-03-11T12:40:23.826324,479392824,65417,206,43.62209726228,31.87837843746,-77.505301868585,2,1,18 +2025-03-11T12:40:23.841949,479392824,65417,206,43.77759315074,32.02190071188,-77.760265450325,2,1,18 +2025-03-11T12:40:23.857574,479392824,65417,206,43.91895304934,32.156156383755,-78.01517160905,2,1,18 +2025-03-11T12:40:23.873199,479392824,65417,206,44.04617695808,32.308871884035,-78.27013158476,2,1,18 +2025-03-11T12:40:23.888824,479392824,65417,206,44.18753685668,32.438506484085,-78.53888275268,2,1,18 +2025-03-11T12:40:23.904449,479392824,65417,206,44.32889675528,32.586625371435,-78.77998098221,2,1,18 +2025-03-11T12:40:23.920074,479392824,65417,206,44.47025665388,32.725502115135,-79.02104213174,2,1,18 +2025-03-11T12:40:23.935699,479392824,65417,206,44.592768566,32.845861959675,-79.24351726499,2,1,18 +2025-03-11T12:40:23.951324,479392824,65417,206,44.72470447136,32.956995966495,-79.47521124638,2,1,18 +2025-03-11T12:40:23.966949,479392824,65417,206,44.85664037672,33.105098547915,-79.730159463095,2,1,18 +2025-03-11T12:40:23.982574,479392824,65417,206,44.98386428546,33.230087617245,-79.96190228348,2,1,18 +2025-03-11T12:40:23.998199,479392824,65417,206,45.1110881942,33.3412134711,-80.193589483865,2,1,18 +2025-03-11T12:40:24.013824,479392824,65417,206,45.2288881097,33.461565162675,-80.420679019175,2,1,18 +2025-03-11T12:40:24.029449,479392824,65417,206,45.35140002182,33.581925007215,-80.63853296936,2,1,18 +2025-03-11T12:40:24.045074,479392824,65417,206,45.46919993732,33.716139914265,-80.85643575854,2,1,18 +2025-03-11T12:40:24.060699,479392824,65417,206,45.59642384606,33.84575005542,-81.069712386665,2,1,18 +2025-03-11T12:40:24.076324,479392824,65417,206,45.71893575818,33.96610989996,-81.27832397072,2,1,18 +2025-03-11T12:40:24.091949,479392824,65417,206,45.82259968382,34.06795284534,-81.486834270755,2,1,18 +2025-03-11T12:40:24.107574,479392824,65417,206,45.92626360946,34.17903793437,-81.69538165079,2,1,18 +2025-03-11T12:40:24.123199,479392824,65417,206,46.03935152834,34.29938147298,-81.903979672835,2,1,18 +2025-03-11T12:40:24.138824,479392824,65417,206,46.15243944722,34.41048286794,-82.10329824875,2,1,18 +2025-03-11T12:40:24.154449,479392824,65417,206,46.25610337286,34.526189028795,-82.302621802655,2,1,18 +2025-03-11T12:40:24.170074,479392824,65417,206,46.36447929512,34.62804012714,-82.492654151435,2,1,18 +2025-03-11T12:40:24.185699,479392824,65417,206,46.47285521738,34.729891225485,-82.65958058489,2,1,18 +2025-03-11T12:40:24.201324,479392824,65417,206,46.57651914302,34.82711309904,-82.840345246535,2,1,18 +2025-03-11T12:40:24.216949,479392824,65417,206,46.67547107204,34.919705747805,-83.03494813637,2,1,18 +2025-03-11T12:40:24.232574,479392824,65417,206,46.77442300106,35.02154054022,-83.220345740075,2,1,18 +2025-03-11T12:40:24.248199,479392824,65417,206,46.87337493008,35.11875426081,-83.391861254585,2,1,18 +2025-03-11T12:40:24.263824,479392824,65417,206,46.96761486248,35.225201972085,-83.558785885025,2,1,18 +2025-03-11T12:40:24.279449,479392824,65417,206,47.0665667915,35.31779462085,-83.748767591795,2,1,18 +2025-03-11T12:40:24.295074,479392824,65417,206,47.1608067239,35.3826526857,-83.906282996105,2,1,18 +2025-03-11T12:40:24.310699,479392824,65417,206,47.24091066644,35.47059165078,-84.068491940465,2,1,18 +2025-03-11T12:40:24.326324,479392824,65417,206,47.32101460898,35.572393831335,-84.212271772565,2,1,18 +2025-03-11T12:40:24.341949,479392824,65417,206,47.41525454138,35.664978327135,-84.342171318485,2,1,18 +2025-03-11T12:40:24.357574,479392824,65417,206,47.49535848392,35.752917292215,-84.522864995105,2,1,18 +2025-03-11T12:40:24.373199,479392824,65417,206,47.57546242646,35.82699304182,-84.67115477027,2,1,18 +2025-03-11T12:40:24.388824,479392824,65417,206,47.66027836562,35.896455872565,-84.814811603375,2,1,18 +2025-03-11T12:40:24.404449,479392824,65417,206,47.74509430478,35.979781918785,-84.963145239545,2,1,18 +2025-03-11T12:40:24.420074,479392824,65417,206,47.81577425408,36.076946721585,-85.08378705431,2,1,18 +2025-03-11T12:40:24.435699,479392824,65417,206,47.87231821352,36.13711849089,-85.21350257219,2,1,18 +2025-03-11T12:40:24.451324,479392824,65417,206,47.93357416958,36.20654055681,-85.35712550027,2,1,18 +2025-03-11T12:40:24.466949,479392824,65417,206,48.01839010874,36.27138231573,-85.473036694985,2,1,18 +2025-03-11T12:40:24.482574,479392824,65417,206,48.09378205466,36.32696562507,-85.59813961382,2,1,18 +2025-03-11T12:40:24.498199,479392824,65417,206,48.1503260141,36.396379538025,-85.7278922117,2,1,18 +2025-03-11T12:40:24.513824,479392824,65417,206,48.20215797692,36.47040636984,-85.82530828712,2,1,18 +2025-03-11T12:40:24.529449,479392824,65417,206,48.2681259296,36.52597337325,-85.94577646088,2,1,18 +2025-03-11T12:40:24.545074,479392824,65417,206,48.32938188566,36.590774367345,-86.075517299765,2,1,18 +2025-03-11T12:40:24.560699,479392824,65417,206,48.3859258451,36.65094613665,-86.186748085385,2,1,18 +2025-03-11T12:40:24.576324,479392824,65417,206,48.46131779102,36.701908374165,-86.297968915025,2,1,18 +2025-03-11T12:40:24.591949,479392824,65417,206,48.51786175046,36.76208014347,-86.37685141919,2,1,18 +2025-03-11T12:40:24.607574,479392824,65417,206,48.55555772342,36.81759822909,-86.48803654079,2,1,18 +2025-03-11T12:40:24.623199,479392824,65417,206,48.6215256761,36.859302017025,-86.57147963003,2,1,18 +2025-03-11T12:40:24.638824,479392824,65417,206,48.67806963554,36.90098949903,-86.636424425,2,1,18 +2025-03-11T12:40:24.654449,479392824,65417,206,48.72990159836,36.956532043545,-86.719902791225,2,1,18 +2025-03-11T12:40:24.670074,479392824,65417,206,48.77230956794,37.01205828213,-86.8218523277,2,1,18 +2025-03-11T12:40:24.685699,479392824,65417,206,48.78173356118,37.053664234485,-86.88672931262,2,1,18 +2025-03-11T12:40:24.701324,479392824,65417,206,48.81942953414,37.090698032805,-86.956249626635,2,1,18 +2025-03-11T12:40:24.716949,479392824,65417,206,48.87126149696,37.132377361845,-87.03967237286,2,1,18 +2025-03-11T12:40:24.732574,479392824,65417,206,48.89953347668,37.16477378241,-87.109160584865,2,1,18 +2025-03-11T12:40:24.748199,479392824,65417,206,48.93722944964,37.18332329343,-87.164743189685,2,1,18 +2025-03-11T12:40:24.763824,479392824,65417,206,48.97963741922,37.21574417289,-87.225009378575,2,1,18 +2025-03-11T12:40:24.779449,479392824,65417,206,49.01733339218,37.24353582756,-87.28525024646,2,1,18 +2025-03-11T12:40:24.795074,479392824,65417,206,49.05031736852,37.262077185615,-87.34544725334,2,1,18 +2025-03-11T12:40:24.810699,479392824,65417,206,49.08330134486,37.28986068732,-87.38719660796,2,1,18 +2025-03-11T12:40:24.826324,479392824,65417,206,49.10214933134,37.30837758648,-87.438130905695,2,1,18 +2025-03-11T12:40:24.841949,479392824,65417,206,49.12099731782,37.35462091659,-87.503039992625,2,1,18 +2025-03-11T12:40:24.857574,479392824,65417,206,49.15398129416,37.373162274645,-87.526267534985,2,1,18 +2025-03-11T12:40:24.873199,479392824,65417,206,49.1869652705,37.387082560875,-87.53561298815,2,1,18 +2025-03-11T12:40:24.888824,479392824,65417,206,49.1869652705,37.40094577635,-87.5818804388,2,1,18 +2025-03-11T12:40:24.904449,479392824,65417,206,49.19638926374,37.41020422593,-87.605036996135,2,1,18 +2025-03-11T12:40:24.920074,479392824,65417,206,49.21523725022,37.433342196915,-87.614399186285,2,1,18 +2025-03-11T12:40:24.935699,479392824,65417,206,49.21994924684,37.437971421705,-87.60518214116,2,1,18 +2025-03-11T12:40:24.951324,479392824,65417,206,49.2340852367,37.433374808775,-87.623668676435,2,1,18 +2025-03-11T12:40:24.966949,479392824,65417,206,49.2340852367,37.44723802425,-87.642209028695,2,1,18 +2025-03-11T12:40:24.982574,479392824,65417,206,49.24822122656,37.474988914095,-87.66082534397,2,1,18 +2025-03-11T12:40:24.998199,479392824,65417,206,49.25293322318,37.479618138885,-87.670093031105,2,1,18 +2025-03-11T12:40:25.013824,479392824,65417,206,49.24822122656,37.474988914095,-87.674688893165,2,1,18 +2025-03-11T12:40:25.029449,479392824,65417,206,49.24822122656,37.465746770445,-87.68851536236,2,1,18 +2025-03-11T12:40:25.045074,479392824,65417,206,49.25293322318,37.46575492341,-87.69314332643,2,1,18 +2025-03-11T12:40:25.060699,479392824,65417,206,49.23879723332,37.46110939269,-87.69772562648,2,1,18 +2025-03-11T12:40:25.076324,479392824,65417,206,49.22937324008,37.44260879946,-87.66066843995,2,1,18 +2025-03-11T12:40:25.091949,479392824,65417,206,49.2340852367,37.424132665125,-87.642116328695,2,1,18 +2025-03-11T12:40:25.107574,479392824,65417,206,49.24350922994,37.424148971055,-87.62826634151,2,1,18 +2025-03-11T12:40:25.123199,479392824,65417,206,49.2340852367,37.442616952425,-87.6283269395,2,1,18 +2025-03-11T12:40:25.138824,479392824,65417,206,49.22466124346,37.42873743102,-87.6005306591,2,1,18 +2025-03-11T12:40:25.154449,479392824,65417,206,49.19167726712,37.419438216615,-87.54961309835,2,1,18 +2025-03-11T12:40:25.170074,479392824,65417,206,49.17754127726,37.396308398595,-87.48942467549,2,1,18 +2025-03-11T12:40:25.185699,479392824,65417,206,49.14926929754,37.35466983438,-87.46149003107,2,1,18 +2025-03-11T12:40:25.201324,479392824,65417,206,49.13513330768,37.33154001636,-87.424407523535,2,1,18 +2025-03-11T12:40:25.216949,479392824,65417,206,49.10686132796,37.308385739445,-87.37344112379,2,1,18 +2025-03-11T12:40:25.232574,479392824,65417,206,49.06445335838,37.28982807546,-87.32247292103,2,1,18 +2025-03-11T12:40:25.248199,479392824,65417,206,49.03146938204,37.27590778923,-87.29002155254,2,1,18 +2025-03-11T12:40:25.263824,479392824,65417,206,49.00790939894,37.238898449805,-87.22052158154,2,1,18 +2025-03-11T12:40:25.279449,479392824,65417,206,48.98906141246,37.20651833517,-87.15566811461,2,1,18 +2025-03-11T12:40:25.295074,479392824,65417,206,48.94665344288,37.178718527535,-87.090799282655,2,1,18 +2025-03-11T12:40:25.310699,479392824,65417,206,48.9042454733,37.1509187199,-87.03517281683,2,1,18 +2025-03-11T12:40:25.326324,479392824,65417,206,48.87597349358,37.08617479656,-86.965554824825,2,1,18 +2025-03-11T12:40:25.341949,479392824,65417,206,48.83827752062,37.03065671094,-86.882096801615,2,1,18 +2025-03-11T12:40:25.357574,479392824,65417,206,48.80058154766,36.98438076897,-86.80329704147,2,1,18 +2025-03-11T12:40:25.373199,479392824,65417,206,48.74403758822,36.942693286965,-86.715246331175,2,1,18 +2025-03-11T12:40:25.388824,479392824,65417,206,48.70162961864,36.89640919203,-86.64106097309,2,1,18 +2025-03-11T12:40:25.404449,479392824,65417,206,48.65922164906,36.83626188162,-86.566819995005,2,1,18 +2025-03-11T12:40:25.420074,479392824,65417,206,48.60738968624,36.79458255258,-86.46491251652,2,1,18 +2025-03-11T12:40:25.435699,479392824,65417,206,48.5508457268,36.752895070575,-86.37224062316,2,1,18 +2025-03-11T12:40:25.451324,479392824,65417,206,48.48487777412,36.706570210815,-86.28877899392,2,1,18 +2025-03-11T12:40:25.466949,479392824,65417,206,48.4330458113,36.655648738125,-86.1914556185,2,1,18 +2025-03-11T12:40:25.482574,479392824,65417,206,48.37650185186,36.60471911247,-86.09874664514,2,1,18 +2025-03-11T12:40:25.498199,479392824,65417,206,48.32466988904,36.53531335248,-85.987485560525,2,1,18 +2025-03-11T12:40:25.513824,479392824,65417,206,48.27754992284,36.456673601805,-85.848467078525,2,1,18 +2025-03-11T12:40:25.529449,479392824,65417,206,48.21629396678,36.39187260771,-85.72796860577,2,1,18 +2025-03-11T12:40:25.545074,479392824,65417,206,48.14561401748,36.345539594985,-85.607530731005,2,1,18 +2025-03-11T12:40:25.560699,479392824,65417,206,48.0796460648,36.28535151975,-85.487044017245,2,1,18 +2025-03-11T12:40:25.576324,479392824,65417,206,48.01367811212,36.197437013565,-85.366446063485,2,1,18 +2025-03-11T12:40:25.591949,479392824,65417,206,47.94299816282,36.127998641715,-85.222809573395,2,1,18 +2025-03-11T12:40:25.607574,479392824,65417,206,47.86289422028,36.06316503576,-85.079178061295,2,1,18 +2025-03-11T12:40:25.623199,479392824,65417,206,47.7969262676,35.9798716014,-84.958598647535,2,1,18 +2025-03-11T12:40:25.638824,479392824,65417,206,47.7262463183,35.9011910859,-84.833409809705,2,1,18 +2025-03-11T12:40:25.654449,479392824,65417,206,47.64143037914,35.813243967855,-84.6896788166,2,1,18 +2025-03-11T12:40:25.670074,479392824,65417,206,47.55190244336,35.734530840495,-84.541356939425,2,1,18 +2025-03-11T12:40:25.685699,479392824,65417,206,47.4670865042,35.660446937925,-84.383818017125,2,1,18 +2025-03-11T12:40:25.701324,479392824,65417,206,47.37755856842,35.56787059509,-84.22619815382,2,1,18 +2025-03-11T12:40:25.716949,479392824,65417,206,47.31630261236,35.47996424187,-84.08250106574,2,1,18 +2025-03-11T12:40:25.732574,479392824,65417,206,47.23619866982,35.396646348615,-83.91106829525,2,1,18 +2025-03-11T12:40:25.748199,479392824,65417,206,47.1372467408,35.299432628025,-83.74879514687,2,1,18 +2025-03-11T12:40:25.763824,479392824,65417,206,47.04771880502,35.19761414154,-83.581895837435,2,1,18 +2025-03-11T12:40:25.779449,479392824,65417,206,46.94405487938,35.100392267985,-83.39188880966,2,1,18 +2025-03-11T12:40:25.795074,479392824,65417,206,46.85923894022,34.99396086264,-83.2157353751,2,1,18 +2025-03-11T12:40:25.810699,479392824,65417,206,46.76971100444,34.89676344798,-83.05347578873,2,1,18 +2025-03-11T12:40:25.826324,479392824,65417,206,46.6660470788,34.818025861725,-82.85892173789,2,1,18 +2025-03-11T12:40:25.841949,479392824,65417,206,46.56238315316,34.716182916345,-82.668896170115,2,1,18 +2025-03-11T12:40:25.857574,479392824,65417,206,46.46343122414,34.609727052105,-82.478858843345,2,1,18 +2025-03-11T12:40:25.873199,479392824,65417,206,46.3597672985,34.517126250375,-82.284249172505,2,1,18 +2025-03-11T12:40:25.888824,479392824,65417,206,46.24667937962,34.415266999065,-82.12193714111,2,1,18 +2025-03-11T12:40:25.904449,479392824,65417,206,46.1241674675,34.294907154525,-81.931810289315,2,1,18 +2025-03-11T12:40:25.920074,479392824,65417,206,46.02050354186,34.165337778195,-81.718567566215,2,1,18 +2025-03-11T12:40:25.935699,479392824,65417,206,45.92155161284,34.058881913955,-81.519287873315,2,1,18 +2025-03-11T12:40:25.951324,479392824,65417,206,45.80846369396,33.96164373447,-81.3200249174,2,1,18 +2025-03-11T12:40:25.966949,479392824,65417,206,45.68595178184,33.85052603358,-81.09758686415,2,1,18 +2025-03-11T12:40:25.982574,479392824,65417,206,45.57286386296,33.716319279495,-80.87506967291,2,1,18 +2025-03-11T12:40:25.998123,479392828,65412,207,45.4409279576,33.605185272675,-80.65261805765,2,1,18 +2025-03-11T12:40:26.013748,479392828,65412,207,45.32784003872,33.48022066224,-80.416274397215,2,1,18 +2025-03-11T12:40:26.029373,479392828,65412,207,45.2053281266,33.3598608177,-80.203041630095,2,1,18 +2025-03-11T12:40:26.044998,479392828,65412,207,45.08281621448,33.234879901335,-79.97592677378,2,1,18 +2025-03-11T12:40:26.060623,479392828,65412,207,44.95559230574,33.11451190383,-79.744202493395,2,1,18 +2025-03-11T12:40:26.076248,479392828,65412,207,44.82365640038,33.00337789701,-79.521750878135,2,1,18 +2025-03-11T12:40:26.091873,479392828,65412,207,44.69643249164,32.85990454038,-79.28069153162,2,1,18 +2025-03-11T12:40:26.107498,479392828,65412,207,44.56449658628,32.71180195896,-79.0396068641,2,1,18 +2025-03-11T12:40:26.123123,479392828,65412,207,44.42313668768,32.57292521526,-78.784682165375,2,1,18 +2025-03-11T12:40:26.138748,479392828,65412,207,44.27706479246,32.44790353407,-78.54366985484,2,1,18 +2025-03-11T12:40:26.154373,479392828,65412,207,44.14041689048,32.32289815881,-78.284186374055,2,1,18 +2025-03-11T12:40:26.169998,479392828,65412,207,44.01319298174,32.184045874005,-78.020039652215,2,1,18 +2025-03-11T12:40:26.185623,479392828,65412,207,43.87183308314,32.026684843005,-77.778904342685,2,1,18 +2025-03-11T12:40:26.201248,479392828,65412,207,43.72576118792,31.892421018165,-77.50088548763,2,1,18 +2025-03-11T12:40:26.216873,479392828,65412,207,43.58911328594,31.75355242743,-77.23672520378,2,1,18 +2025-03-11T12:40:26.232498,479392828,65412,207,43.44304139072,31.59156217164,-76.995564573245,2,1,18 +2025-03-11T12:40:26.248123,479392828,65412,207,43.30168149212,31.42495899699,-76.735907451455,2,1,18 +2025-03-11T12:40:26.263748,479392828,65412,207,43.16032159352,31.27684010964,-76.4717033066,2,1,18 +2025-03-11T12:40:26.279373,479392828,65412,207,43.00482570506,31.12407569157,-76.175111997275,2,1,18 +2025-03-11T12:40:26.294998,479392828,65412,207,42.85404181322,30.962077282815,-75.89235393815,2,1,18 +2025-03-11T12:40:26.310623,479392828,65412,207,42.68912193152,30.81391763064,-75.60963115601,2,1,18 +2025-03-11T12:40:26.326248,479392828,65412,207,42.52420204982,30.675000122115,-75.31770308774,2,1,18 +2025-03-11T12:40:26.341873,479392828,65412,207,42.36399416474,30.52222755108,-75.03034736354,2,1,18 +2025-03-11T12:40:26.357498,479392828,65412,207,42.19907428304,30.35096253978,-74.733668332205,2,1,18 +2025-03-11T12:40:26.373123,479392828,65412,207,42.04357839458,30.175092762585,-74.450847872075,2,1,18 +2025-03-11T12:40:26.388748,479392828,65412,207,41.88808250612,30.02694941634,-74.15427510275,2,1,18 +2025-03-11T12:40:26.404373,479392828,65412,207,41.7420106109,29.8557170169,-73.8622443785,2,1,18 +2025-03-11T12:40:26.419998,479392828,65412,207,41.58180272582,29.675218014915,-73.560913865105,2,1,18 +2025-03-11T12:40:26.435623,479392828,65412,207,41.4121708475,29.50394485065,-73.24112213744,2,1,18 +2025-03-11T12:40:26.451248,479392828,65412,207,41.23311497594,29.32803430863,-72.92591949083,2,1,18 +2025-03-11T12:40:26.466873,479392828,65412,207,41.06348309762,29.166003288015,-72.606164843165,2,1,18 +2025-03-11T12:40:26.482498,479392828,65412,207,40.88913922268,28.99010089896,-72.29096897756,2,1,18 +2025-03-11T12:40:26.498123,479392828,65412,207,40.71950734436,28.83269095017,-71.961990503765,2,1,18 +2025-03-11T12:40:26.513748,479392828,65412,207,40.5404514728,28.670643623625,-71.64222229409,2,1,18 +2025-03-11T12:40:26.529373,479392828,65412,207,40.35668360462,28.480861713165,-71.32233606341,2,1,18 +2025-03-11T12:40:26.544998,479392828,65412,207,40.16820373982,28.286450577915,-70.99780332866,2,1,18 +2025-03-11T12:40:26.560623,479392828,65412,207,39.99385986488,28.115169260685,-70.673383636925,2,1,18 +2025-03-11T12:40:26.576248,479392828,65412,207,39.81480399332,27.92539550319,-70.34426182112,2,1,18 +2025-03-11T12:40:26.591873,479392828,65412,207,39.64046011838,27.73562989866,-70.02438915245,2,1,18 +2025-03-11T12:40:26.607498,479392828,65412,207,39.46611624344,27.54586429413,-69.67678938539,2,1,18 +2025-03-11T12:40:26.623123,479392828,65412,207,39.28234837526,27.360703455495,-69.32919459632,2,1,18 +2025-03-11T12:40:26.638748,479392828,65412,207,39.08444451722,27.16165494249,-68.972281478105,2,1,18 +2025-03-11T12:40:26.654373,479392828,65412,207,38.90067664904,26.99035731933,-68.6293634921,2,1,18 +2025-03-11T12:40:26.669998,479392828,65412,207,38.702772791,26.809793093625,-68.281766900015,2,1,18 +2025-03-11T12:40:26.685623,479392828,65412,207,38.4907329431,26.610720121725,-67.93869698798,2,1,18 +2025-03-11T12:40:26.701248,479392828,65412,207,38.3022530783,26.4209300583,-67.58645569484,2,1,18 +2025-03-11T12:40:26.716873,479392828,65412,207,38.12790920336,26.208059094645,-67.215657312455,2,1,18 +2025-03-11T12:40:26.732498,479392828,65412,207,37.93000534532,26.004389509815,-66.85872565424,2,1,18 +2025-03-11T12:40:26.748123,479392828,65412,207,37.72738949066,25.80071177202,-66.50178721502,2,1,18 +2025-03-11T12:40:26.763748,479392828,65412,207,37.52006163938,25.59702588126,-66.14946317786,2,1,18 +2025-03-11T12:40:26.779373,479392828,65412,207,37.31744578472,25.40721135894,-65.778716809445,2,1,18 +2025-03-11T12:40:26.794998,479392828,65412,207,37.11482993006,25.222017908445,-65.421852530225,2,1,18 +2025-03-11T12:40:26.810623,479392828,65412,207,36.90750207878,25.01371094586,-65.060267586935,2,1,18 +2025-03-11T12:40:26.826248,479392828,65412,207,36.70959822074,24.80079921738,-64.67557175033,2,1,18 +2025-03-11T12:40:26.841873,479392828,65412,207,36.5116943627,24.57864534525,-64.28621765066,2,1,18 +2025-03-11T12:40:26.857498,479392828,65412,207,36.30436651142,24.35647516719,-63.91533472124,2,1,18 +2025-03-11T12:40:26.873123,479392828,65412,207,36.10646265338,24.148184510535,-63.52603624157,2,1,18 +2025-03-11T12:40:26.888748,479392828,65412,207,35.88028681562,23.935223864265,-63.122814986675,2,1,18 +2025-03-11T12:40:26.904373,479392828,65412,207,35.65882297448,23.72227137096,-62.728842878915,2,1,18 +2025-03-11T12:40:26.919998,479392828,65412,207,35.45620711982,23.500109345865,-62.325618449045,2,1,18 +2025-03-11T12:40:26.935623,479392828,65412,207,35.23474327868,23.28715685256,-61.931646341285,2,1,18 +2025-03-11T12:40:26.951248,479392828,65412,207,35.01799143416,23.06497036857,-61.533022751465,2,1,18 +2025-03-11T12:40:26.966873,479392828,65412,207,34.79652759302,22.870502162565,-61.120640071445,2,1,18 +2025-03-11T12:40:26.982498,479392828,65412,207,34.5797757485,22.648315678575,-60.71739529856,2,1,18 +2025-03-11T12:40:26.998123,479392828,65412,207,34.36302390398,22.426129194585,-60.31877170874,2,1,18 +2025-03-11T12:40:27.013748,479392828,65412,207,34.14156006284,22.18545027033,-59.91544599485,2,1,18 +2025-03-11T12:40:27.029373,479392828,65412,207,33.92480821832,21.967884858165,-59.52608331116,2,1,18 +2025-03-11T12:40:27.044998,479392828,65412,207,33.7080563738,21.74107730235,-59.122819998275,2,1,18 +2025-03-11T12:40:27.060623,479392828,65412,207,33.48188053604,21.50039022513,-58.714866320315,2,1,18 +2025-03-11T12:40:27.076248,479392828,65412,207,33.2604166949,21.278195588175,-58.2885088511,2,1,18 +2025-03-11T12:40:27.091873,479392828,65412,207,33.03424085714,21.055992798255,-57.84365986862,2,1,18 +2025-03-11T12:40:27.107498,479392828,65412,207,32.80335302276,20.829160783545,-57.43113384659,2,1,18 +2025-03-11T12:40:27.123123,479392828,65412,207,32.55832919852,20.597683238115,-57.009326575415,2,1,18 +2025-03-11T12:40:27.138748,479392828,65412,207,32.3180173709,20.361592773825,-56.587507545245,2,1,18 +2025-03-11T12:40:27.154373,479392828,65412,207,32.0824175399,20.120889390675,-56.17491912221,2,1,18 +2025-03-11T12:40:27.169998,479392828,65412,207,31.85624170214,19.89406552893,-55.743915148925,2,1,18 +2025-03-11T12:40:27.185623,479392828,65412,207,31.62535386776,19.653370298745,-55.303606408505,2,1,18 +2025-03-11T12:40:27.201248,479392828,65412,207,31.39446603338,19.426538284035,-54.87721683728,2,1,18 +2025-03-11T12:40:27.216873,479392828,65412,207,31.14944220914,19.19968181043,-54.45080692304,2,1,18 +2025-03-11T12:40:27.232498,479392828,65412,207,30.89499439166,18.95894581542,-54.00584309453,2,1,18 +2025-03-11T12:40:27.248123,479392828,65412,207,30.65468256404,18.71361320748,-53.54701751984,2,1,18 +2025-03-11T12:40:27.263748,479392828,65412,207,30.42850672628,18.468305058435,-53.11131820349,2,1,18 +2025-03-11T12:40:27.279373,479392828,65412,207,30.18819489866,18.21835137867,-52.666337637995,2,1,18 +2025-03-11T12:40:27.294998,479392828,65412,207,29.9384590778,17.9545181775,-52.22128789049,2,1,18 +2025-03-11T12:40:27.310623,479392828,65412,207,29.69814725018,17.704564497735,-51.79017087419,2,1,18 +2025-03-11T12:40:27.326248,479392828,65412,207,29.45312342594,17.473086952305,-51.359121236885,2,1,18 +2025-03-11T12:40:27.341873,479392828,65412,207,29.19867560846,17.22772988547,-50.895654136115,2,1,18 +2025-03-11T12:40:27.357498,479392828,65412,207,28.94422779098,16.97775174681,-50.413683763085,2,1,18 +2025-03-11T12:40:27.373123,479392828,65412,207,28.70391596336,16.718555923395,-49.945560202265,2,1,18 +2025-03-11T12:40:27.388748,479392828,65412,207,28.43533215602,16.47779546949,-49.495954847675,2,1,18 +2025-03-11T12:40:27.404373,479392828,65412,207,28.18559633516,16.218583340145,-49.037060090975,2,1,18 +2025-03-11T12:40:27.419998,479392828,65412,207,27.94057251092,15.950137220115,-48.573513852215,2,1,18 +2025-03-11T12:40:27.435623,479392828,65412,207,27.69554868668,15.709417531035,-48.10545767039,2,1,18 +2025-03-11T12:40:27.451248,479392828,65412,207,27.43167687596,15.44555987097,-47.63266048148,2,1,18 +2025-03-11T12:40:27.466873,479392828,65412,207,27.16309306862,15.19093620159,-47.17375714076,2,1,18 +2025-03-11T12:40:27.482498,479392828,65412,207,26.90864525114,14.917852703805,-46.71017879999,2,1,18 +2025-03-11T12:40:27.498123,479392828,65412,207,26.6636214269,14.66326979925,-46.24668818123,2,1,18 +2025-03-11T12:40:27.513748,479392828,65412,207,26.41388560604,14.39943659808,-45.792396067595,2,1,18 +2025-03-11T12:40:27.529373,479392828,65412,207,26.15001379532,14.135578938015,-45.29649296336,2,1,18 +2025-03-11T12:40:27.544998,479392828,65412,207,25.87671799136,13.88094711567,-44.809855743245,2,1,18 +2025-03-11T12:40:27.560623,479392828,65412,207,25.61755817726,13.603234393095,-44.33700971534,2,1,18 +2025-03-11T12:40:27.576248,479392828,65412,207,25.33955037668,13.330110130485,-43.854912737285,2,1,18 +2025-03-11T12:40:27.591873,479392828,65412,207,25.08039056258,13.08012383886,-43.377556766315,2,1,18 +2025-03-11T12:40:27.607498,479392828,65412,207,24.8259427451,12.82090355655,-42.90017049635,2,1,18 +2025-03-11T12:40:27.623123,479392828,65412,207,24.55735893776,12.53855345622,-42.39494408498,2,1,18 +2025-03-11T12:40:27.638748,479392828,65412,207,24.31233511352,12.26086519254,-41.899012484765,2,1,18 +2025-03-11T12:40:27.654373,479392828,65412,207,24.0484633028,12.006249676125,-41.43087355892,2,1,18 +2025-03-11T12:40:27.669998,479392828,65412,207,23.77987949546,11.73776279127,-40.93494513368,2,1,18 +2025-03-11T12:40:27.685623,479392828,65412,207,23.49715969826,11.473872519345,-40.44363608849,2,1,18 +2025-03-11T12:40:27.701248,479392828,65412,207,23.2238638943,11.214619625175,-39.95235914531,2,1,18 +2025-03-11T12:40:27.716873,479392828,65412,207,22.94585609372,10.941495362565,-39.451777434995,2,1,18 +2025-03-11T12:40:27.732498,479392828,65412,207,22.66313629652,10.65912080334,-38.95577304674,2,1,18 +2025-03-11T12:40:27.748123,479392828,65412,207,22.3992644858,10.3813999278,-38.45519313944,2,1,18 +2025-03-11T12:40:27.763748,479392828,65412,207,22.12596868184,10.11290488998,-37.945394384,2,1,18 +2025-03-11T12:40:27.779373,479392828,65412,207,21.84796088126,9.835159555545,-37.44017295062,2,1,18 +2025-03-11T12:40:27.794998,479392828,65412,207,21.56524108406,9.55278499632,-36.9395473793,2,1,18 +2025-03-11T12:40:27.810623,479392828,65412,207,21.2919452801,9.279668886675,-36.443593633055,2,1,18 +2025-03-11T12:40:27.826248,479392828,65412,207,21.02336147276,9.01118200182,-35.93380165862,2,1,18 +2025-03-11T12:40:27.841873,479392828,65412,207,20.74064167556,8.72418637077,-35.44239991343,2,1,18 +2025-03-11T12:40:27.857498,479392828,65412,207,20.45320988174,8.455666874055,-34.93720199804,2,1,18 +2025-03-11T12:40:27.873123,479392828,65412,207,20.1610660913,8.1732760089,-34.413456949385,2,1,18 +2025-03-11T12:40:27.888748,479392828,65412,207,19.89719428058,7.89555513336,-33.89901349289,2,1,18 +2025-03-11T12:40:27.904373,479392828,65412,207,19.63332246986,7.60859211417,-33.3706694072,2,1,18 +2025-03-11T12:40:27.919998,479392828,65412,207,19.35531466928,7.30774142061,-32.85611290769,2,1,18 +2025-03-11T12:40:27.935623,479392828,65412,207,19.07259487208,7.025366861385,-32.350866153305,2,1,18 +2025-03-11T12:40:27.951248,479392828,65412,207,18.78045108164,6.75221813988,-31.831779367715,2,1,18 +2025-03-11T12:40:27.966873,479392828,65412,207,18.49301928782,6.47907757134,-31.298835813935,2,1,18 +2025-03-11T12:40:27.982498,479392828,65412,207,18.21972348386,6.19209824622,-30.78434171543,2,1,18 +2025-03-11T12:40:27.998123,479392828,65412,207,17.93700368666,5.900481543345,-30.269815514915,2,1,18 +2025-03-11T12:40:28.013748,479392828,65412,207,17.65899588608,5.608872993435,-29.7691596446,2,1,18 +2025-03-11T12:40:28.029373,479392828,65412,207,17.3809880855,5.317264443525,-29.250019042025,2,1,18 +2025-03-11T12:40:28.044998,479392828,65412,207,17.08884429506,5.03487357837,-28.703168078045,2,1,18 +2025-03-11T12:40:28.060623,479392828,65412,207,16.791988508,4.7432324166,-28.17475798532,2,1,18 +2025-03-11T12:40:28.076248,479392828,65412,207,16.49984471756,4.44697833597,-27.650957316665,2,1,18 +2025-03-11T12:40:28.091873,479392828,65412,207,16.21241292374,4.15535348013,-27.11331841982,2,1,18 +2025-03-11T12:40:28.107498,479392828,65412,207,15.92498112992,3.86372862429,-26.58030070604,2,1,18 +2025-03-11T12:40:28.123123,479392828,65412,207,15.63283733948,3.562853471835,-26.05186031432,2,1,18 +2025-03-11T12:40:28.138748,479392828,65412,207,15.34540554566,3.27584968782,-25.541967055865,2,1,18 +2025-03-11T12:40:28.154373,479392828,65412,207,15.06739774508,2.988862209735,-25.036708542485,2,1,18 +2025-03-11T12:40:28.169998,479392828,65412,207,14.77996595126,2.706479497545,-24.512970274835,2,1,18 +2025-03-11T12:40:28.185623,479392828,65412,207,14.49253415744,2.424096785355,-23.961504908795,2,1,18 +2025-03-11T12:40:28.201248,479392828,65412,207,14.19567837038,2.12783455176,-23.428455093005,2,1,18 +2025-03-11T12:40:28.216873,479392828,65412,207,13.90353457994,1.82233832748,-22.890753795155,2,1,18 +2025-03-11T12:40:28.232498,479392828,65412,207,13.60667879288,1.516833950235,-22.3530457163,2,1,18 +2025-03-11T12:40:28.248123,479392828,65412,207,13.3051110092,1.239047850975,-21.820063279505,2,1,18 +2025-03-11T12:40:28.263748,479392828,65412,207,13.01767921538,0.95204406696,-21.29168528879,2,1,18 +2025-03-11T12:40:28.279373,479392828,65412,207,12.73495941818,0.637322004960001,-20.749339289885,2,1,18 +2025-03-11T12:40:28.294998,479392828,65412,207,12.4333916345,0.345672690225,-20.20705886696,2,1,18 +2025-03-11T12:40:28.310623,479392828,65412,207,12.13653584744,0.0540315284549999,-19.678648774235,2,1,18 +2025-03-11T12:40:28.326248,479392828,65412,207,11.83025606714,-0.24224701107,-19.15944894563,2,1,18 +2025-03-11T12:40:28.341873,479392828,65412,207,11.5381122767,-0.524637876224999,-18.617219164715,2,1,18 +2025-03-11T12:40:28.357498,479392828,65412,207,11.23654449302,-0.825529334610001,-18.070280478725,2,1,18 +2025-03-11T12:40:28.373123,479392828,65412,207,10.94440070258,-1.12178341524,-17.53723744394,2,1,18 +2025-03-11T12:40:28.388748,479392828,65412,207,10.65225691214,-1.404174280395,-17.004250029155,2,1,18 +2025-03-11T12:40:28.404373,479392828,65412,207,10.36482511832,-1.70966235171,-16.45731314618,2,1,18 +2025-03-11T12:40:28.419998,479392828,65412,207,10.08210532112,-2.010521198235,-15.90115921808,2,1,18 +2025-03-11T12:40:28.435623,479392828,65412,207,9.78524953406,-2.30678343183,-15.34962467003,2,1,18 +2025-03-11T12:40:28.451248,479392828,65412,207,9.488393747,-2.621529952725,-14.811879511175,2,1,18 +2025-03-11T12:40:28.466873,479392828,65412,207,9.18682596332,-2.92242141111,-14.274183191315,2,1,18 +2025-03-11T12:40:28.482498,479392828,65412,207,8.88054618302,-3.209457806985,-13.71805097819,2,1,18 +2025-03-11T12:40:28.498123,479392828,65412,207,8.58840239258,-3.505711887615,-13.157280845015,2,1,18 +2025-03-11T12:40:28.513748,479392828,65412,207,8.2868346089,-3.792740130525,-12.62426132822,2,1,18 +2025-03-11T12:40:28.529373,479392828,65412,207,7.99469081846,-4.088994211155,-12.091218293435,2,1,18 +2025-03-11T12:40:28.544998,479392828,65412,207,7.69312303478,-4.39912781319,-11.553484893575,2,1,18 +2025-03-11T12:40:28.560623,479392828,65412,207,7.38684325448,-4.70002742454,-11.011160609645,2,1,18 +2025-03-11T12:40:28.576248,479392828,65412,207,7.08998746742,-4.996289658135,-10.46424724466,2,1,18 +2025-03-11T12:40:28.591873,479392828,65412,207,6.80726767022,-5.28790636101,-9.91737276269,2,1,18 +2025-03-11T12:40:28.607498,479392828,65412,207,6.50098788992,-5.59804811601,-9.37501139876,2,1,18 +2025-03-11T12:40:28.623123,479392828,65412,207,6.20413210286,-5.903552493255,-8.828060953775,2,1,18 +2025-03-11T12:40:28.638748,479392828,65412,207,5.91670030904,-6.19979842092,-8.29040351693,2,1,18 +2025-03-11T12:40:28.654373,479392828,65412,207,5.6009965355,-6.496093266375,-7.752705394055,2,1,18 +2025-03-11T12:40:28.669998,479392828,65412,207,5.2947167552,-6.796992877725,-7.201138743995,2,1,18 +2025-03-11T12:40:28.685623,479392828,65412,207,4.9884369749,-7.107134632725,-6.640292647805,2,1,18 +2025-03-11T12:40:28.701248,479392828,65412,207,4.70100518108,-7.408001632215,-6.0841319387,2,1,18 +2025-03-11T12:40:28.716873,479392828,65412,207,4.3994373974,-7.71813523425,-5.54639853884,2,1,18 +2025-03-11T12:40:28.732498,479392828,65412,207,4.0931576171,-8.032898061075,-5.008639817975,2,1,18 +2025-03-11T12:40:28.748123,479392828,65412,207,3.80101382666,-8.310667854405,-4.471049760125,2,1,18 +2025-03-11T12:40:28.763748,479392828,65412,207,3.50887003622,-8.606921935035,-3.914900810015,2,1,18 +2025-03-11T12:40:28.779373,479392828,65412,207,3.21201424916,-8.907805240455,-3.372590088095,2,1,18 +2025-03-11T12:40:28.794998,479392828,65412,207,2.90573446886,-9.217946995455,-2.83484990723,2,1,18 +2025-03-11T12:40:28.810623,479392828,65412,207,2.5853186987,-9.505007850225,-2.26945498496,2,1,18 +2025-03-11T12:40:28.826248,479392828,65412,207,2.28846291164,-9.80127008382,-1.731783986105,2,1,18 +2025-03-11T12:40:28.841873,479392828,65412,207,1.99160712458,-10.097532317415,-1.180249438055,2,1,18 +2025-03-11T12:40:28.857498,479392828,65412,207,1.69946333414,-10.40764961352,-0.624044867945,2,1,18 +2025-03-11T12:40:28.873123,479392828,65412,207,1.4073195437,-10.727009053275,-0.0724244009000001,2,1,18 +2025-03-11T12:40:28.888748,479392828,65412,207,1.11046375664,-11.027892358695,0.474507504085,2,1,18 +2025-03-11T12:40:28.904373,479392828,65412,207,0.80418397634,-11.32417089822,1.007570881885,2,1,18 +2025-03-11T12:40:28.919998,479392828,65412,207,0.49319219942,-11.62969973436,1.54067812069,2,1,18 +2025-03-11T12:40:28.935623,479392828,65412,207,0.2057604056,-11.9213245902,2.0829382006,2,1,18 +2025-03-11T12:40:28.951248,479392828,65412,207,-0.0863833848400001,-12.21757867083,2.625223601515,2,1,18 +2025-03-11T12:40:28.966873,479392828,65412,207,-0.37852717528,-12.509211679635,3.18597519469,2,1,18 +2025-03-11T12:40:28.982498,479392828,65412,207,-0.67538296234,-12.81471605688,3.732925639675,2,1,18 +2025-03-11T12:40:28.998123,479392828,65412,207,-0.9722387494,-13.120220434125,4.275254901595,2,1,18 +2025-03-11T12:40:29.013748,479392828,65412,207,-1.27380653308,-13.416490820685,4.83603859678,2,1,18 +2025-03-11T12:40:29.029373,479392828,65412,207,-1.57537431676,-13.703519063595,5.387542845835,2,1,18 +2025-03-11T12:40:29.044998,479392828,65412,207,-1.87223010382,-14.004402369015,5.92523238469,2,1,18 +2025-03-11T12:40:29.060623,479392828,65412,207,-2.16437389426,-14.319140736945,6.46297076254,2,1,18 +2025-03-11T12:40:29.076248,479392828,65412,207,-2.46122968132,-14.610781898715,7.009865587525,2,1,18 +2025-03-11T12:40:29.091873,479392828,65412,207,-2.75808546838,-14.88855984501,7.552083609445,2,1,18 +2025-03-11T12:40:29.107498,479392828,65412,207,-3.05494125544,-15.184822078605,8.0897546083,2,1,18 +2025-03-11T12:40:29.123123,479392828,65412,207,-3.34708504588,-15.49493937471,8.62747444615,2,1,18 +2025-03-11T12:40:29.138748,479392828,65412,207,-3.62509284646,-15.79579006827,9.165136860985,2,1,18 +2025-03-11T12:40:29.154373,479392828,65412,207,-3.90781264366,-16.08278569932,9.693508070695,2,1,18 +2025-03-11T12:40:29.169998,479392828,65412,207,-4.20466843072,-16.360563645615,10.23110490955,2,1,18 +2025-03-11T12:40:29.185623,479392828,65412,207,-4.5062362144,-16.65221296035,10.77800651554,2,1,18 +2025-03-11T12:40:29.201248,479392828,65412,207,-4.80309200146,-16.95309626577,11.32955960359,2,1,18 +2025-03-11T12:40:29.216873,479392828,65412,207,-5.09052379528,-17.258584337085,11.858011754305,2,1,18 +2025-03-11T12:40:29.232498,479392828,65412,207,-5.3779555891,-17.5455881211,12.372526195825,2,1,18 +2025-03-11T12:40:29.248123,479392828,65412,207,-5.66538738292,-17.82797083329,12.91012801267,2,1,18 +2025-03-11T12:40:29.263748,479392828,65412,207,-5.95281917674,-18.13807997643,13.447841069515,2,1,18 +2025-03-11T12:40:29.279373,479392828,65412,207,-6.24496296718,-18.438955128885,13.994766193495,2,1,18 +2025-03-11T12:40:29.294998,479392828,65412,207,-6.55124274748,-18.72599152476,14.537034857425,2,1,18 +2025-03-11T12:40:29.310623,479392828,65412,207,-6.85281053116,-19.02226191132,15.06084908809,2,1,18 +2025-03-11T12:40:29.326248,479392828,65412,207,-7.14024232498,-19.309265695335,15.579984712675,2,1,18 +2025-03-11T12:40:29.341873,479392828,65412,207,-7.43238611542,-19.614761919615,16.099201278265,2,1,18 +2025-03-11T12:40:29.357498,479392828,65412,207,-7.7339538991,-19.901790162525,16.63222079506,2,1,18 +2025-03-11T12:40:29.373123,479392828,65412,207,-8.02138569292,-20.17955180289,17.17442525497,2,1,18 +2025-03-11T12:40:29.388748,479392828,65412,207,-8.31352948336,-20.48504802717,17.70288418669,2,1,18 +2025-03-11T12:40:29.404373,479392828,65412,207,-8.59624928056,-20.78128580187,18.22205011027,2,1,18 +2025-03-11T12:40:29.419998,479392828,65412,207,-8.89781706424,-21.072935116605,18.745845800935,2,1,18 +2025-03-11T12:40:29.435623,479392828,65412,207,-9.1946728513,-21.364576278375,19.27425589366,2,1,18 +2025-03-11T12:40:29.451248,479392828,65412,207,-9.49152863836,-21.66083851197,19.80730570945,2,1,18 +2025-03-11T12:40:29.466873,479392828,65412,207,-9.77424843556,-21.94783414302,20.340298102225,2,1,18 +2025-03-11T12:40:29.482498,479392828,65412,207,-10.07110422262,-22.225612089315,20.85941020882,2,1,18 +2025-03-11T12:40:29.498123,479392828,65412,207,-10.35382401982,-22.494123433065,21.36922252627,2,1,18 +2025-03-11T12:40:29.513748,479392828,65412,207,-10.62711982378,-22.77648168636,21.892940450905,2,1,18 +2025-03-11T12:40:29.529373,479392828,65412,207,-10.90041562774,-23.068082083305,22.402831906345,2,1,18 +2025-03-11T12:40:29.544998,479392828,65412,207,-11.18784742156,-23.33660158002,22.92189337093,2,1,18 +2025-03-11T12:40:29.560623,479392828,65412,207,-11.47527921538,-23.62822643586,23.42718398632,2,1,18 +2025-03-11T12:40:29.576248,479392828,65412,207,-11.74386302272,-23.91981867984,23.94168984382,2,1,18 +2025-03-11T12:40:29.591873,479392828,65412,207,-12.01244683006,-24.20216878017,24.44691625519,2,1,18 +2025-03-11T12:40:29.607498,479392828,65412,207,-12.2810306374,-24.4845188805,24.947521483495,2,1,18 +2025-03-11T12:40:29.623123,479392828,65412,207,-12.5637504346,-24.776135583375,25.466668867075,2,1,18 +2025-03-11T12:40:29.638748,479392828,65412,207,-12.85118222842,-25.058518295565,25.971922402465,2,1,18 +2025-03-11T12:40:29.654373,479392828,65412,207,-13.11976603576,-25.31776303677,26.47243493077,2,1,18 +2025-03-11T12:40:29.669998,479392828,65412,207,-13.39777383634,-25.60012944303,26.991538453345,2,1,18 +2025-03-11T12:40:29.685623,479392828,65412,207,-13.68049363354,-25.891746145905,27.50606465386,2,1,18 +2025-03-11T12:40:29.701248,479392828,65412,207,-13.9537894375,-26.1556201119,28.03432960156,2,1,18 +2025-03-11T12:40:29.716873,479392828,65412,207,-14.23179723808,-26.43798651816,28.525706025745,2,1,18 +2025-03-11T12:40:29.732498,479392828,65412,207,-14.50980503866,-26.72035292442,29.02632481606,2,1,18 +2025-03-11T12:40:29.748123,479392828,65412,207,-14.79252483586,-26.993485339995,29.522292124315,2,1,18 +2025-03-11T12:40:29.763748,479392828,65412,207,-15.06582063982,-27.261980377815,30.00898496443,2,1,18 +2025-03-11T12:40:29.779373,479392828,65412,207,-15.3438284404,-27.5489678559,30.51424347781,2,1,18 +2025-03-11T12:40:29.794998,479392828,65412,207,-15.61241224774,-27.84056009988,31.01026460305,2,1,18 +2025-03-11T12:40:29.810623,479392828,65412,207,-15.88099605508,-28.10442591291,31.492310939095,2,1,18 +2025-03-11T12:40:29.826248,479392828,65412,207,-16.14015586918,-28.363654348185,31.98356753926,2,1,18 +2025-03-11T12:40:29.841873,479392828,65412,207,-16.41345167314,-28.622907242355,32.46560211631,2,1,18 +2025-03-11T12:40:29.857498,479392828,65412,207,-16.69145947372,-28.905273648615,32.947736174365,2,1,18 +2025-03-11T12:40:29.873123,479392828,65412,207,-16.95533128444,-29.17837345233,33.439055175535,2,1,18 +2025-03-11T12:40:29.888748,479392828,65412,207,-17.20977910192,-29.432972662815,33.930286454695,2,1,18 +2025-03-11T12:40:29.904373,479392828,65412,207,-17.45951492278,-29.696805863985,34.426169215915,2,1,18 +2025-03-11T12:40:29.919998,479392828,65412,207,-17.72809873012,-29.95605060519,34.894333462765,2,1,18 +2025-03-11T12:40:29.935623,479392828,65412,207,-18.00139453408,-30.21530349936,35.376368039815,2,1,18 +2025-03-11T12:40:29.951248,479392828,65412,207,-18.26055434818,-30.47915300646,35.86764317998,2,1,18 +2025-03-11T12:40:29.966873,479392828,65412,207,-18.5244261589,-30.733768522875,36.345024471955,2,1,18 +2025-03-11T12:40:29.982498,479392828,65412,207,-18.78829796962,-30.99762618294,36.817821660865,2,1,18 +2025-03-11T12:40:29.998062,479392832,65408,208,-19.04745778372,-31.275338905515,37.2999100549,2,1,18 +2025-03-11T12:40:30.013687,479392832,65408,208,-19.30661759782,-31.529946268965,37.76804219974,2,1,18 +2025-03-11T12:40:30.029312,479392832,65408,208,-19.5610654153,-31.789166551275,38.217701371315,2,1,18 +2025-03-11T12:40:30.044937,479392832,65408,208,-19.8202252294,-32.043773914725,38.695075882285,2,1,18 +2025-03-11T12:40:30.060562,479392832,65408,208,-20.0793850435,-32.298381278175,39.17707157632,2,1,18 +2025-03-11T12:40:30.076187,479392832,65408,208,-20.34796885084,-32.55762601938,39.649857006235,2,1,18 +2025-03-11T12:40:30.091812,479392832,65408,208,-20.59299267508,-32.802966780285,40.10868936193,2,1,18 +2025-03-11T12:40:30.107437,479392832,65408,208,-20.8333045027,-33.057541531875,40.572173199685,2,1,18 +2025-03-11T12:40:30.123062,479392832,65408,208,-21.07832832694,-33.30288229278,41.035626738445,2,1,18 +2025-03-11T12:40:30.138687,479392832,65408,208,-21.33748814104,-33.552868584405,41.485255611025,2,1,18 +2025-03-11T12:40:30.154312,479392832,65408,208,-21.60607194838,-33.798250110135,41.916394773355,2,1,18 +2025-03-11T12:40:30.169937,479392832,65408,208,-21.846383776,-34.062067005375,42.366052141915,2,1,18 +2025-03-11T12:40:30.185562,479392832,65408,208,-22.08669560362,-34.31202068514,42.82027507354,2,1,18 +2025-03-11T12:40:30.201187,479392832,65408,208,-22.3411434211,-34.548135608325,43.269841545115,2,1,18 +2025-03-11T12:40:30.216812,479392832,65408,208,-22.59559123858,-34.798113746985,43.724084819755,2,1,18 +2025-03-11T12:40:30.232437,479392832,65408,208,-22.8359030662,-35.04806742675,44.15982301912,2,1,18 +2025-03-11T12:40:30.248062,479392832,65408,208,-23.0715028972,-35.2887708099,44.60475972361,2,1,18 +2025-03-11T12:40:30.263687,479392832,65408,208,-23.32595071468,-35.524885733085,45.035841462925,2,1,18 +2025-03-11T12:40:30.279312,479392832,65408,208,-23.56155054568,-35.765589116235,45.462293435155,2,1,18 +2025-03-11T12:40:30.294937,479392832,65408,208,-23.78301438682,-36.010889112315,45.90722833663,2,1,18 +2025-03-11T12:40:30.310562,479392832,65408,208,-24.00447822796,-36.256189108395,46.34754205504,2,1,18 +2025-03-11T12:40:30.326187,479392832,65408,208,-24.25421404882,-36.483053734965,46.76009520109,2,1,18 +2025-03-11T12:40:30.341812,479392832,65408,208,-24.49452587644,-36.72376527108,47.186553954325,2,1,18 +2025-03-11T12:40:30.357437,479392832,65408,208,-24.72541371082,-36.964460501265,47.626862694745,2,1,18 +2025-03-11T12:40:30.373062,479392832,65408,208,-24.9563015452,-37.1959135878,48.04402843984,2,1,18 +2025-03-11T12:40:30.388687,479392832,65408,208,-25.1919013762,-37.4273748273,48.475064515135,2,1,18 +2025-03-11T12:40:30.404312,479392832,65408,208,-25.44163719706,-37.658860525695,48.933848031835,2,1,18 +2025-03-11T12:40:30.419937,479392832,65408,208,-25.67252503144,-37.876450396755,49.36944288919,2,1,18 +2025-03-11T12:40:30.435562,479392832,65408,208,-25.8987008692,-38.1032742585,49.791204496345,2,1,18 +2025-03-11T12:40:30.451187,479392832,65408,208,-26.12016471034,-38.325468895455,50.203698416365,2,1,18 +2025-03-11T12:40:30.466812,479392832,65408,208,-26.33691655486,-38.547655379445,50.59770082312,2,1,18 +2025-03-11T12:40:30.482437,479392832,65408,208,-26.56780438924,-38.783729537805,50.99177919289,2,1,18 +2025-03-11T12:40:30.498062,479392832,65408,208,-26.793980227,-39.0197955432,51.395093147785,2,1,18 +2025-03-11T12:40:30.513687,479392832,65408,208,-27.01544406814,-39.241990180155,51.80296588474,2,1,18 +2025-03-11T12:40:30.529312,479392832,65408,208,-27.22277191942,-39.464160358215,52.21081827868,2,1,18 +2025-03-11T12:40:30.544937,479392832,65408,208,-27.4536597538,-39.681750229275,52.63254958684,2,1,18 +2025-03-11T12:40:30.560562,479392832,65408,208,-27.6892595848,-39.8993482533,53.026560577615,2,1,18 +2025-03-11T12:40:30.576187,479392832,65408,208,-27.9012994327,-40.112284440675,53.4158979403,2,1,18 +2025-03-11T12:40:30.591812,479392832,65408,208,-28.11805127722,-40.325228781015,53.80524208399,2,1,18 +2025-03-11T12:40:30.607437,479392832,65408,208,-28.33480312174,-40.538173121355,54.217692143005,2,1,18 +2025-03-11T12:40:30.623062,479392832,65408,208,-28.54684296964,-40.746488236905,54.620874514885,2,1,18 +2025-03-11T12:40:30.638687,479392832,65408,208,-28.74003483106,-40.95014966877,54.996284124355,2,1,18 +2025-03-11T12:40:30.654312,479392832,65408,208,-28.95207467896,-41.16770692797,55.371776477845,2,1,18 +2025-03-11T12:40:30.669937,479392832,65408,208,-29.15940253024,-41.366771746905,55.74718789033,2,1,18 +2025-03-11T12:40:30.685562,479392832,65408,208,-29.3620183849,-41.565828412875,56.12259252181,2,1,18 +2025-03-11T12:40:30.701187,479392832,65408,208,-29.56934623618,-41.769514303635,56.49340129123,2,1,18 +2025-03-11T12:40:30.716812,479392832,65408,208,-29.76725009422,-41.982426032115,56.85499121251,2,1,18 +2025-03-11T12:40:30.732437,479392832,65408,208,-29.96515395226,-42.19071668877,57.22580495992,2,1,18 +2025-03-11T12:40:30.748062,479392832,65408,208,-30.18190579678,-42.389797813635,57.58736638522,2,1,18 +2025-03-11T12:40:30.763687,479392832,65408,208,-30.38923364806,-42.59810477622,57.935087779315,2,1,18 +2025-03-11T12:40:30.779312,479392832,65408,208,-30.58242550948,-42.78790299261,58.282714670395,2,1,18 +2025-03-11T12:40:30.794937,479392832,65408,208,-30.77090537428,-42.986935199685,58.653477775795,2,1,18 +2025-03-11T12:40:30.810562,479392832,65408,208,-30.9640972357,-43.1998387752,59.010439733005,2,1,18 +2025-03-11T12:40:30.826187,479392832,65408,208,-31.16200109374,-43.38502407273,59.381160780415,2,1,18 +2025-03-11T12:40:30.841812,479392832,65408,208,-31.3410569653,-43.584039973875,59.724183225415,2,1,18 +2025-03-11T12:40:30.857437,479392832,65408,208,-31.51068884362,-43.769176353615,60.057894122275,2,1,18 +2025-03-11T12:40:30.873062,479392832,65408,208,-31.69916870842,-43.94972427339,60.41471951848,2,1,18 +2025-03-11T12:40:30.888687,479392832,65408,208,-31.88764857322,-44.139514336815,60.762339628555,2,1,18 +2025-03-11T12:40:30.904312,479392832,65408,208,-32.08084043464,-44.32469148138,61.08684206431,2,1,18 +2025-03-11T12:40:30.919937,479392832,65408,208,-32.27403229606,-44.519110769595,61.411381580065,2,1,18 +2025-03-11T12:40:30.935562,479392832,65408,208,-32.46722415748,-44.699666842335,61.76359257421,2,1,18 +2025-03-11T12:40:30.951187,479392832,65408,208,-32.65570402228,-44.88021476211,62.09731205509,2,1,18 +2025-03-11T12:40:30.966812,479392832,65408,208,-32.83475989384,-45.05612530413,62.398651152505,2,1,18 +2025-03-11T12:40:30.982437,479392832,65408,208,-33.01852776202,-45.22742292729,62.71384204012,2,1,18 +2025-03-11T12:40:30.998062,479392832,65408,208,-33.2022956302,-45.403341622275,63.0336726508,2,1,18 +2025-03-11T12:40:31.013687,479392832,65408,208,-33.35779151866,-45.56996925582,63.35342549545,2,1,18 +2025-03-11T12:40:31.029312,479392832,65408,208,-33.51799940374,-45.73660504233,63.66856393804,2,1,18 +2025-03-11T12:40:31.044937,479392832,65408,208,-33.68763128206,-45.91249927842,63.98375302264,2,1,18 +2025-03-11T12:40:31.060562,479392832,65408,208,-33.861975157,-46.08378059565,64.298930348245,2,1,18 +2025-03-11T12:40:31.076187,479392832,65408,208,-34.03160703532,-46.24119054444,64.595560540585,2,1,18 +2025-03-11T12:40:31.091812,479392832,65408,208,-34.1918149204,-46.412447402775,64.90609634011,2,1,18 +2025-03-11T12:40:31.107437,479392832,65408,208,-34.35202280548,-46.579083189285,65.21199241657,2,1,18 +2025-03-11T12:40:31.123062,479392832,65408,208,-34.50280669732,-46.74108159804,65.513235207955,2,1,18 +2025-03-11T12:40:31.138687,479392832,65408,208,-34.67243857564,-46.89849154683,65.80524421723,2,1,18 +2025-03-11T12:40:31.154312,479392832,65408,208,-34.84207045396,-47.051280423795,66.087992320375,2,1,18 +2025-03-11T12:40:31.169937,479392832,65408,208,-34.99756634242,-47.222529129165,66.36617305744,2,1,18 +2025-03-11T12:40:31.185562,479392832,65408,208,-35.13892624102,-47.36602694469,66.66270694375,2,1,18 +2025-03-11T12:40:31.201187,479392832,65408,208,-35.28499813624,-47.52801720048,66.950079404935,2,1,18 +2025-03-11T12:40:31.216812,479392832,65408,208,-35.44991801794,-47.676176852655,67.22818100401,2,1,18 +2025-03-11T12:40:31.232437,479392832,65408,208,-35.59127791654,-47.815053596355,67.50621161806,2,1,18 +2025-03-11T12:40:31.248062,479392832,65408,208,-35.746773805,-47.967818014425,67.77969701206,2,1,18 +2025-03-11T12:40:31.263687,479392832,65408,208,-35.89755769684,-48.134437495005,68.043988878925,2,1,18 +2025-03-11T12:40:31.279312,479392832,65408,208,-36.0530535853,-48.28258084125,68.2943498176,2,1,18 +2025-03-11T12:40:31.294937,479392832,65408,208,-36.18498949066,-48.42144127902,68.56312450351,2,1,18 +2025-03-11T12:40:31.310562,479392832,65408,208,-36.31692539602,-48.564922788615,68.83191772942,2,1,18 +2025-03-11T12:40:31.326187,479392832,65408,208,-36.45828529462,-48.70842060414,69.077618602015,2,1,18 +2025-03-11T12:40:31.341812,479392832,65408,208,-36.60906918646,-48.84731365377,69.318693313555,2,1,18 +2025-03-11T12:40:31.357437,479392832,65408,208,-36.76456507492,-48.98159378454,69.57824099836,2,1,18 +2025-03-11T12:40:31.373062,479392832,65408,208,-36.90592497352,-49.115849456415,69.82852597402,2,1,18 +2025-03-11T12:40:31.388687,479392832,65408,208,-37.05199686874,-49.25473435308,70.07421508762,2,1,18 +2025-03-11T12:40:31.404312,479392832,65408,208,-37.18864477072,-49.38898187199,70.31062973308,2,1,18 +2025-03-11T12:40:31.419937,479392832,65408,208,-37.30644468622,-49.53243892269,70.542433151455,2,1,18 +2025-03-11T12:40:31.435562,479392832,65408,208,-37.42424460172,-49.671274901565,70.78346039596,2,1,18 +2025-03-11T12:40:31.451187,479392832,65408,208,-37.54204451722,-49.796247664965,71.024432020465,2,1,18 +2025-03-11T12:40:31.466812,479392832,65408,208,-37.67398042258,-49.907381671785,71.256126001855,2,1,18 +2025-03-11T12:40:31.482437,479392832,65408,208,-37.80120433132,-50.013886453815,71.47855229611,2,1,18 +2025-03-11T12:40:31.498062,479392832,65408,208,-37.90958025358,-50.13422183946,71.691764720215,2,1,18 +2025-03-11T12:40:31.513687,479392832,65408,208,-38.02266817246,-50.259186449895,71.905002465325,2,1,18 +2025-03-11T12:40:31.529312,479392832,65408,208,-38.14518008458,-50.388788438085,72.12289349551,2,1,18 +2025-03-11T12:40:31.544937,479392832,65408,208,-38.28182798656,-50.50917274152,72.326904239515,2,1,18 +2025-03-11T12:40:31.560562,479392832,65408,208,-38.40433989868,-50.606427226935,72.52618075744,2,1,18 +2025-03-11T12:40:31.576187,479392832,65408,208,-38.51271582094,-50.72676261258,72.72552963235,2,1,18 +2025-03-11T12:40:31.591812,479392832,65408,208,-38.62580373982,-50.83786400754,72.91098465907,2,1,18 +2025-03-11T12:40:31.607437,479392832,65408,208,-38.72946766546,-50.93046480927,73.10559432991,2,1,18 +2025-03-11T12:40:31.623062,479392832,65408,208,-38.8331315911,-51.027686682825,73.304843723815,2,1,18 +2025-03-11T12:40:31.638687,479392832,65408,208,-38.93208352012,-51.13876361889,73.48103604139,2,1,18 +2025-03-11T12:40:31.654312,479392832,65408,208,-39.02632345252,-51.24059025834,73.66642686409,2,1,18 +2025-03-11T12:40:31.669937,479392832,65408,208,-39.12527538154,-51.351667194405,73.842619181665,2,1,18 +2025-03-11T12:40:31.685562,479392832,65408,208,-39.22893930718,-51.45813121161,74.046526838635,2,1,18 +2025-03-11T12:40:31.701187,479392832,65408,208,-39.33731522944,-51.550740166305,74.245764473545,2,1,18 +2025-03-11T12:40:31.716812,479392832,65408,208,-39.4221311686,-51.6294451407,74.42642785117,2,1,18 +2025-03-11T12:40:31.732437,479392832,65408,208,-39.50223511114,-51.72662624943,74.584052692465,2,1,18 +2025-03-11T12:40:31.748062,479392832,65408,208,-39.5870510503,-51.82843658295,74.760187587025,2,1,18 +2025-03-11T12:40:31.763687,479392832,65408,208,-39.68600297932,-51.93489244719,74.91787663234,2,1,18 +2025-03-11T12:40:31.779312,479392832,65408,208,-39.78024291172,-52.032098014815,75.06627945052,2,1,18 +2025-03-11T12:40:31.794937,479392832,65408,208,-39.8697708475,-52.10619007035,75.22844633689,2,1,18 +2025-03-11T12:40:31.810562,479392832,65408,208,-39.95458678666,-52.18027397292,75.39522762532,2,1,18 +2025-03-11T12:40:31.826187,479392832,65408,208,-40.03940272582,-52.26360001914,75.55280362762,2,1,18 +2025-03-11T12:40:31.841812,479392832,65408,208,-40.11479467174,-52.342288687605,75.69186279565,2,1,18 +2025-03-11T12:40:31.857437,479392832,65408,208,-40.18547462104,-52.420969203105,75.830915182675,2,1,18 +2025-03-11T12:40:31.873062,479392832,65408,208,-40.2702905602,-52.49043203385,75.99305674804,2,1,18 +2025-03-11T12:40:31.888687,479392832,65408,208,-40.35510649936,-52.57375808007,76.127526835015,2,1,18 +2025-03-11T12:40:31.904312,479392832,65408,208,-40.42578644866,-52.647817523745,76.24807594978,2,1,18 +2025-03-11T12:40:31.919937,479392832,65408,208,-40.48704240472,-52.72186066149,76.38247505173,2,1,18 +2025-03-11T12:40:31.935562,479392832,65408,208,-40.5530103574,-52.782048736725,76.50296176549,2,1,18 +2025-03-11T12:40:31.951187,479392832,65408,208,-40.63782629656,-52.846890495645,76.60500941101,2,1,18 +2025-03-11T12:40:31.966812,479392832,65408,208,-40.69908225262,-52.92093363339,76.73940851296,2,1,18 +2025-03-11T12:40:31.982437,479392832,65408,208,-40.76033820868,-52.98111355566,76.850646079585,2,1,18 +2025-03-11T12:40:31.998062,479392832,65408,208,-40.82159416474,-53.036672406105,76.95262274008,2,1,18 +2025-03-11T12:40:32.013687,479392832,65408,208,-40.87813812418,-53.08760203176,77.059195262635,2,1,18 +2025-03-11T12:40:32.029312,479392832,65408,208,-40.9535300701,-53.1431853411,77.16581344921,2,1,18 +2025-03-11T12:40:32.044937,479392832,65408,208,-41.01949802278,-53.212615559985,77.272473693775,2,1,18 +2025-03-11T12:40:32.060562,479392832,65408,208,-41.08075397884,-53.27741655408,77.35600270201,2,1,18 +2025-03-11T12:40:32.076187,479392832,65408,208,-41.1184499518,-53.328313567875,77.462548100545,2,1,18 +2025-03-11T12:40:32.091812,479392832,65408,208,-41.15143392814,-53.379202428705,77.559844351945,2,1,18 +2025-03-11T12:40:32.107437,479392832,65408,208,-41.19855389434,-53.41163146113,77.64784442023,2,1,18 +2025-03-11T12:40:32.123062,479392832,65408,208,-41.24096186392,-53.45329448424,77.71739005525,2,1,18 +2025-03-11T12:40:32.138687,479392832,65408,208,-41.29279382674,-53.499594885105,77.791588975345,2,1,18 +2025-03-11T12:40:32.154312,479392832,65408,208,-41.33991379294,-53.53202391753,77.8703466775,2,1,18 +2025-03-11T12:40:32.169937,479392832,65408,208,-41.37289776928,-53.578291706535,77.935276107445,2,1,18 +2025-03-11T12:40:32.185562,479392832,65408,208,-41.41059374224,-53.61070443303,78.000156698395,2,1,18 +2025-03-11T12:40:32.201187,479392832,65408,208,-41.44357771858,-53.63386686291,78.069614611405,2,1,18 +2025-03-11T12:40:32.216812,479392832,65408,208,-41.4718496983,-53.6708843553,78.12987899728,2,1,18 +2025-03-11T12:40:32.232437,479392832,65408,208,-41.50012167802,-53.694038632215,78.18546658009,2,1,18 +2025-03-11T12:40:32.248062,479392832,65408,208,-41.53781765098,-53.73569350236,78.264247800235,2,1,18 +2025-03-11T12:40:32.263687,479392832,65408,208,-41.58022562056,-53.78659866912,78.306103416865,2,1,18 +2025-03-11T12:40:32.279312,479392832,65408,208,-41.6132095969,-53.81900324265,78.33400776229,2,1,18 +2025-03-11T12:40:32.294937,479392832,65408,208,-41.64148157662,-53.832915375915,78.357209983645,2,1,18 +2025-03-11T12:40:32.310562,479392832,65408,208,-41.65090556986,-53.842173825495,78.40809363937,2,1,18 +2025-03-11T12:40:32.326187,479392832,65408,208,-41.66975355634,-53.851448581005,78.449748490975,2,1,18 +2025-03-11T12:40:32.341812,479392832,65408,208,-41.6838895462,-53.87919947085,78.491470721575,2,1,18 +2025-03-11T12:40:32.357437,479392832,65408,208,-41.72158551916,-53.89774898187,78.5331897772,2,1,18 +2025-03-11T12:40:32.373062,479392832,65408,208,-41.74043350564,-53.89778159373,78.55170163348,2,1,18 +2025-03-11T12:40:32.388687,479392832,65408,208,-41.74514550226,-53.89316867487,78.58403815594,2,1,18 +2025-03-11T12:40:32.404312,479392832,65408,208,-41.74985749888,-53.91628218696,78.57951645388,2,1,18 +2025-03-11T12:40:32.419937,479392832,65408,208,-41.74985749888,-53.930145402435,78.593435623075,2,1,18 +2025-03-11T12:40:32.435562,479392832,65408,208,-41.76870548536,-53.94404122977,78.62586664855,2,1,18 +2025-03-11T12:40:32.451187,479392832,65408,208,-41.76870548536,-53.93479908612,78.61658720242,2,1,18 +2025-03-11T12:40:32.466812,479392832,65408,208,-41.76399348874,-53.944033076805,78.616617501415,2,1,18 +2025-03-11T12:40:32.482437,479392832,65408,208,-41.75928149212,-53.95326706749,78.630511349605,2,1,18 +2025-03-11T12:40:32.498062,479392832,65408,208,-41.75928149212,-53.939403852015,78.61659218041,2,1,18 +2025-03-11T12:40:32.513687,479392832,65408,208,-41.7781294786,-53.939436463875,78.6073769383,2,1,18 +2025-03-11T12:40:32.529312,479392832,65408,208,-41.76399348874,-53.934790933155,78.61195923835,2,1,18 +2025-03-11T12:40:32.544937,479392832,65408,208,-41.7545694955,-53.925532483575,78.607287413275,2,1,18 +2025-03-11T12:40:32.560562,479392832,65408,208,-41.75928149212,-53.90705634924,78.57949293589,2,1,18 +2025-03-11T12:40:32.576187,479392832,65408,208,-41.74043350564,-53.902402665555,78.547098990415,2,1,18 +2025-03-11T12:40:32.591812,479392832,65408,208,-41.72158551916,-53.902370053695,78.52396595107,2,1,18 +2025-03-11T12:40:32.607437,479392832,65408,208,-41.7074495293,-53.879240235675,78.50074699273,2,1,18 +2025-03-11T12:40:32.623062,479392832,65408,208,-41.6838895462,-53.856094111725,78.472893289315,2,1,18 +2025-03-11T12:40:32.638687,479392832,65408,208,-41.65561756648,-53.85142412211,78.454349331025,2,1,18 +2025-03-11T12:40:32.654312,479392832,65408,208,-41.64619357324,-53.828302457055,78.435758336755,2,1,18 +2025-03-11T12:40:32.669937,479392832,65408,208,-41.62734558676,-53.791301270595,78.380128695955,2,1,18 +2025-03-11T12:40:32.685562,479392832,65408,208,-41.60378560366,-53.76353407482,78.31528698802,2,1,18 +2025-03-11T12:40:32.701187,479392832,65408,208,-41.56137763408,-53.74035533901,78.25505787913,2,1,18 +2025-03-11T12:40:32.716812,479392832,65408,208,-41.52368166112,-53.72180582799,78.194854091245,2,1,18 +2025-03-11T12:40:32.732437,479392832,65408,208,-41.50483367464,-53.68480464153,78.14384563351,2,1,18 +2025-03-11T12:40:32.748062,479392832,65408,208,-41.46713770168,-53.64777084321,78.074325319495,2,1,18 +2025-03-11T12:40:32.763687,479392832,65408,208,-41.43415372534,-53.61536626968,77.995587960355,2,1,18 +2025-03-11T12:40:32.779312,479392832,65408,208,-41.39645775238,-53.57833247136,77.95379474473,2,1,18 +2025-03-11T12:40:32.794937,479392832,65408,208,-41.35876177942,-53.545919744865,77.90739888604,2,1,18 +2025-03-11T12:40:32.810562,479392832,65408,208,-41.32577780308,-53.49040981221,77.833190009965,2,1,18 +2025-03-11T12:40:32.826187,479392832,65408,208,-41.2833698335,-53.4487467891,77.74053845962,2,1,18 +2025-03-11T12:40:32.841812,479392832,65408,208,-41.23153787068,-53.40706746006,77.6432521642,2,1,18 +2025-03-11T12:40:32.857437,479392832,65408,208,-41.18441790448,-53.37925949946,77.55989181898,2,1,18 +2025-03-11T12:40:32.873062,479392832,65408,208,-41.1420099349,-53.323733260875,77.485669380895,2,1,18 +2025-03-11T12:40:32.888687,479392832,65408,208,-41.0948899687,-53.268198869325,77.38833424648,2,1,18 +2025-03-11T12:40:32.904312,479392832,65408,208,-41.05248199912,-53.21267263074,77.295627076135,2,1,18 +2025-03-11T12:40:32.919937,479392832,65408,208,-40.99593803968,-53.14787978961,77.184377750515,2,1,18 +2025-03-11T12:40:32.935562,479392832,65408,208,-40.93468208362,-53.09694201099,77.087040813085,2,1,18 +2025-03-11T12:40:32.951187,479392832,65408,208,-40.87813812418,-53.04139131351,76.975828567465,2,1,18 +2025-03-11T12:40:32.966812,479392832,65408,208,-40.81688216812,-52.985832463065,76.859988357775,2,1,18 +2025-03-11T12:40:32.982437,479392832,65408,208,-40.74620221882,-52.92101516304,76.762582238335,2,1,18 +2025-03-11T12:40:32.998062,479392832,65408,208,-40.68965825938,-52.851601250085,76.660556738845,2,1,18 +2025-03-11T12:40:33.013687,479392832,65408,208,-40.62840230332,-52.77755811234,76.53077881996,2,1,18 +2025-03-11T12:40:33.029312,479392832,65408,208,-40.56714634726,-52.712757118245,76.40565916414,2,1,18 +2025-03-11T12:40:33.044937,479392832,65408,208,-40.49175440134,-52.64331059343,76.262015893045,2,1,18 +2025-03-11T12:40:33.060562,479392832,65408,208,-40.41636245542,-52.56000085314,76.122938185015,2,1,18 +2025-03-11T12:40:33.076187,479392832,65408,208,-40.35510649936,-52.485957715395,75.988539083065,2,1,18 +2025-03-11T12:40:33.091812,479392832,65408,208,-40.2702905602,-52.421115956475,75.84490078996,2,1,18 +2025-03-11T12:40:33.107437,479392832,65408,208,-40.1996106109,-52.33781436915,75.705829862935,2,1,18 +2025-03-11T12:40:33.123062,479392832,65408,208,-40.12421866498,-52.26374677251,75.56216805184,2,1,18 +2025-03-11T12:40:33.138687,479392832,65408,208,-40.03940272582,-52.17117858264,75.418418518735,2,1,18 +2025-03-11T12:40:33.154312,479392832,65408,208,-39.96872277652,-52.08325592349,75.27008668558,2,1,18 +2025-03-11T12:40:33.169937,479392832,65408,208,-39.88861883398,-51.999938030235,75.121759830415,2,1,18 +2025-03-11T12:40:33.185562,479392832,65408,208,-39.80380289482,-51.925854127665,74.964220908115,2,1,18 +2025-03-11T12:40:33.201187,479392832,65408,208,-39.7048509658,-51.847124694375,74.783537187475,2,1,18 +2025-03-11T12:40:33.216812,479392832,65408,208,-39.6106110334,-51.74991912675,74.625892003165,2,1,18 +2025-03-11T12:40:33.232437,479392832,65408,208,-39.50694710776,-51.661939396845,74.468270336845,2,1,18 +2025-03-11T12:40:33.248062,479392832,65408,208,-39.40799517874,-51.555483532605,74.29209655927,2,1,18 +2025-03-11T12:40:33.263687,479392832,65408,208,-39.30904324972,-51.45364874019,74.11132013863,2,1,18 +2025-03-11T12:40:33.279312,479392832,65408,208,-39.21480331732,-51.35182210074,73.921308132865,2,1,18 +2025-03-11T12:40:33.294937,479392832,65408,208,-39.12056338492,-51.263858676765,73.75907884549,2,1,18 +2025-03-11T12:40:33.310562,479392832,65408,208,-39.03103544914,-51.157419118455,73.58753981299,2,1,18 +2025-03-11T12:40:33.326187,479392832,65408,208,-38.9273715235,-51.074060460375,73.388346039085,2,1,18 +2025-03-11T12:40:33.341812,479392832,65408,208,-38.82841959448,-50.976846739785,73.20296697538,2,1,18 +2025-03-11T12:40:33.357437,479392832,65408,208,-38.71061967898,-50.851873976385,73.008207181525,2,1,18 +2025-03-11T12:40:33.373062,479392832,65408,208,-38.6210917432,-50.726950130775,72.82273043983,2,1,18 +2025-03-11T12:40:33.388687,479392832,65408,208,-38.50800382432,-50.62046980764,72.61880922085,2,1,18 +2025-03-11T12:40:33.404312,479392832,65408,208,-38.38077991558,-50.509343953785,72.39174320353,2,1,18 +2025-03-11T12:40:33.419937,479392832,65408,208,-38.2676919967,-50.40286363065,72.183200801485,2,1,18 +2025-03-11T12:40:33.435562,479392832,65408,208,-38.15931607444,-50.28714931683,71.974628100445,2,1,18 +2025-03-11T12:40:33.451187,479392832,65408,208,-38.04151615894,-50.166797625255,71.766023297395,2,1,18 +2025-03-11T12:40:33.466812,479392832,65408,208,-37.9142922502,-50.051050699575,71.53431755701,2,1,18 +2025-03-11T12:40:33.482437,479392832,65408,208,-37.78706834146,-49.916819486595,71.30715883969,2,1,18 +2025-03-11T12:40:33.498062,479392832,65408,208,-37.65984443272,-49.79645148909,71.075434559305,2,1,18 +2025-03-11T12:40:33.513687,479392832,65408,208,-37.52319653074,-49.68068825748,70.857578806105,2,1,18 +2025-03-11T12:40:33.529312,479392832,65408,208,-37.40068461862,-49.55108626929,70.61196067753,2,1,18 +2025-03-11T12:40:33.544937,479392832,65408,208,-37.2781727065,-49.4029999938,70.38937430428,2,1,18 +2025-03-11T12:40:33.560562,479392832,65408,208,-37.160372791,-49.2780272304,70.157645045905,2,1,18 +2025-03-11T12:40:33.576187,479392832,65408,208,-37.0190128924,-49.1391504867,69.92120507944,2,1,18 +2025-03-11T12:40:33.591812,479392832,65408,208,-36.88707698704,-49.00029004893,69.666293942725,2,1,18 +2025-03-11T12:40:33.607437,479392832,65408,208,-36.74571708844,-48.87065544888,69.397542774805,2,1,18 +2025-03-11T12:40:33.623062,479392832,65408,208,-36.60435718984,-48.727157633355,69.137978353015,2,1,18 +2025-03-11T12:40:33.638687,479392832,65408,208,-36.4771332811,-48.574442133075,68.87839719424,2,1,18 +2025-03-11T12:40:33.654312,479392832,65408,208,-36.34990937236,-48.44483199192,68.628151101595,2,1,18 +2025-03-11T12:40:33.669937,479392832,65408,208,-36.20383747714,-48.31056816708,68.382480527995,2,1,18 +2025-03-11T12:40:33.685562,479392832,65408,208,-36.05776558192,-48.153198983115,68.127474888265,2,1,18 +2025-03-11T12:40:33.701187,479392832,65408,208,-35.90698169008,-48.00968486166,67.840169806075,2,1,18 +2025-03-11T12:40:33.716812,479392832,65408,208,-35.76562179148,-47.866187046135,67.56674183509,2,1,18 +2025-03-11T12:40:33.732437,479392832,65408,208,-35.59598991316,-47.708777097345,67.30708110727,2,1,18 +2025-03-11T12:40:33.748062,479392832,65408,208,-35.44991801794,-47.556028985205,67.028988092215,2,1,18 +2025-03-11T12:40:33.763687,479392832,65408,208,-35.29442212948,-47.394022423485,66.755465618215,2,1,18 +2025-03-11T12:40:33.779312,479392832,65408,208,-35.13892624102,-47.232015861765,66.481943144215,2,1,18 +2025-03-11T12:40:33.794937,479392832,65408,208,-34.9928543458,-47.088509893275,66.190023659965,2,1,18 +2025-03-11T12:40:33.810562,479392832,65408,208,-34.84678245058,-46.94038285296,65.90270681878,2,1,18 +2025-03-11T12:40:33.826187,479392832,65408,208,-34.70071055536,-46.792255812645,65.624632343725,2,1,18 +2025-03-11T12:40:33.841812,479392832,65408,208,-34.52636668042,-46.630216639065,65.332598013445,2,1,18 +2025-03-11T12:40:33.857437,479392832,65408,208,-34.3567348021,-46.46818561845,65.026706914975,2,1,18 +2025-03-11T12:40:33.873062,479392832,65408,208,-34.20595091026,-46.287702922395,64.72538996359,2,1,18 +2025-03-11T12:40:33.888687,479392832,65408,208,-34.03160703532,-46.12104267699,64.428715910245,2,1,18 +2025-03-11T12:40:33.904312,479392832,65408,208,-33.861975157,-45.9451484409,64.12739037484,2,1,18 +2025-03-11T12:40:33.919937,479392832,65408,208,-33.68291928544,-45.764616827055,63.816790371295,2,1,18 +2025-03-11T12:40:33.935562,479392832,65408,208,-33.51328740712,-45.58410151914,63.50620392976,2,1,18 +2025-03-11T12:40:33.951187,479392832,65408,208,-33.3436555288,-45.412828354875,63.18179101903,2,1,18 +2025-03-11T12:40:33.966812,479392832,65408,208,-33.17402365048,-45.24155519061,62.87586284056,2,1,18 +2025-03-11T12:40:33.982437,479392832,65408,208,-32.9902557823,-45.065636495625,62.53754749762,2,1,18 +2025-03-11T12:40:33.998001,479392836,65404,209,-32.79706392088,-44.894322566535,62.194615949605,2,1,18 +2025-03-11T12:40:34.013626,479392836,65404,209,-32.61800804932,-44.71379095269,61.870152396865,2,1,18 +2025-03-11T12:40:34.029251,479392836,65404,209,-32.43895217776,-44.53788041067,61.53184383493,2,1,18 +2025-03-11T12:40:34.044876,479392836,65404,209,-32.2598963062,-44.352727725,61.20736174219,2,1,18 +2025-03-11T12:40:34.060501,479392836,65404,209,-32.07612843802,-44.15370367089,60.87819606538,2,1,18 +2025-03-11T12:40:34.076126,479392836,65404,209,-31.89236056984,-43.97316390408,60.535240999375,2,1,18 +2025-03-11T12:40:34.091751,479392836,65404,209,-31.7180166949,-43.797261515025,60.18307566925,2,1,18 +2025-03-11T12:40:34.107376,479392836,65404,209,-31.53424882672,-43.61210067639,59.830859697115,2,1,18 +2025-03-11T12:40:34.123001,479392836,65404,209,-31.34576896192,-43.413068469315,59.487823690105,2,1,18 +2025-03-11T12:40:34.138626,479392836,65404,209,-31.1525771005,-43.204785965625,59.14474382209,2,1,18 +2025-03-11T12:40:34.154251,479392836,65404,209,-30.9640972357,-42.9965116149,58.797049552015,2,1,18 +2025-03-11T12:40:34.169876,479392836,65404,209,-30.7756173709,-42.815963695125,58.44022415581,2,1,18 +2025-03-11T12:40:34.185501,479392836,65404,209,-30.56828951962,-42.630762091665,58.083353095585,2,1,18 +2025-03-11T12:40:34.201126,479392836,65404,209,-30.36567366496,-42.42708435387,57.71255110717,2,1,18 +2025-03-11T12:40:34.216751,479392836,65404,209,-30.16776980692,-42.23265691269,57.346414162825,2,1,18 +2025-03-11T12:40:34.232376,479392836,65404,209,-29.96044195564,-42.024349950105,56.984829219535,2,1,18 +2025-03-11T12:40:34.248001,479392836,65404,209,-29.7625380976,-41.820680365275,56.623276378255,2,1,18 +2025-03-11T12:40:34.263626,479392836,65404,209,-29.56934623618,-41.612397861585,56.23398467959,2,1,18 +2025-03-11T12:40:34.279251,479392836,65404,209,-29.3620183849,-41.39484875535,55.849256740975,2,1,18 +2025-03-11T12:40:34.294876,479392836,65404,209,-29.16411452686,-41.195800242345,55.4738588905,2,1,18 +2025-03-11T12:40:34.310501,479392836,65404,209,-28.95207467896,-40.996727270445,55.093819513945,2,1,18 +2025-03-11T12:40:34.326126,479392836,65404,209,-28.73061083782,-40.77453263349,54.709052692315,2,1,18 +2025-03-11T12:40:34.341751,479392836,65404,209,-28.51857098992,-40.54773323064,54.33814444189,2,1,18 +2025-03-11T12:40:34.357376,479392836,65404,209,-28.31124313864,-40.33480519623,53.95805622634,2,1,18 +2025-03-11T12:40:34.373001,479392836,65404,209,-28.10862728398,-40.131127458435,53.550284773405,2,1,18 +2025-03-11T12:40:34.388626,479392836,65404,209,-27.89658743608,-39.913570199235,53.165550053785,2,1,18 +2025-03-11T12:40:34.404251,479392836,65404,209,-27.6892595848,-39.682157877525,52.776145312105,2,1,18 +2025-03-11T12:40:34.419876,479392836,65404,209,-27.46308374704,-39.46457615943,52.377526700275,2,1,18 +2025-03-11T12:40:34.435501,479392836,65404,209,-27.23219591266,-39.24698628837,51.96965894131,2,1,18 +2025-03-11T12:40:34.451126,479392836,65404,209,-27.02486806138,-39.029437182135,51.56182508737,2,1,18 +2025-03-11T12:40:34.466751,479392836,65404,209,-26.8175402101,-38.807267004075,51.158593876495,2,1,18 +2025-03-11T12:40:34.482376,479392836,65404,209,-26.58665237572,-38.59429820484,50.75074465753,2,1,18 +2025-03-11T12:40:34.498001,479392836,65404,209,-26.36518853458,-38.37672463971,50.33826927751,2,1,18 +2025-03-11T12:40:34.513626,479392836,65404,209,-26.14372469344,-38.145287859105,49.911874728295,2,1,18 +2025-03-11T12:40:34.529251,479392836,65404,209,-25.90341286582,-37.91381846664,49.49469542119,2,1,18 +2025-03-11T12:40:34.544876,479392836,65404,209,-25.67723702806,-37.686994604895,49.08679736323,2,1,18 +2025-03-11T12:40:34.560501,479392836,65404,209,-25.45577318692,-37.450936752465,48.678869006275,2,1,18 +2025-03-11T12:40:34.576126,479392836,65404,209,-25.2154613593,-37.21946736,48.26168969917,2,1,18 +2025-03-11T12:40:34.591751,479392836,65404,209,-24.97043753506,-36.98798981457,47.83526124493,2,1,18 +2025-03-11T12:40:34.607376,479392836,65404,209,-24.73483770406,-36.76577071872,47.41812579883,2,1,18 +2025-03-11T12:40:34.623001,479392836,65404,209,-24.51808585954,-36.529721019255,46.996340673685,2,1,18 +2025-03-11T12:40:34.638626,479392836,65404,209,-24.29191002178,-36.28441287021,46.569883723465,2,1,18 +2025-03-11T12:40:34.654251,479392836,65404,209,-24.05631019078,-36.03446734341,46.115667572845,2,1,18 +2025-03-11T12:40:34.669876,479392836,65404,209,-23.81599836316,-35.802997950945,45.68000353348,2,1,18 +2025-03-11T12:40:34.685501,479392836,65404,209,-23.57568653554,-35.557665343005,45.25814742331,2,1,18 +2025-03-11T12:40:34.701126,479392836,65404,209,-23.32595071468,-35.321558572785,44.813208915805,2,1,18 +2025-03-11T12:40:34.716751,479392836,65404,209,-23.08092689044,-35.080838883705,44.377501015435,2,1,18 +2025-03-11T12:40:34.732376,479392836,65404,209,-22.83119106958,-34.844732113485,43.93256250793,2,1,18 +2025-03-11T12:40:34.748001,479392836,65404,209,-22.59087924196,-34.608641649195,43.469152830175,2,1,18 +2025-03-11T12:40:34.763626,479392836,65404,209,-22.3411434211,-34.34942951985,43.019500439605,2,1,18 +2025-03-11T12:40:34.779251,479392836,65404,209,-22.09611959686,-34.09022554347,42.583718379235,2,1,18 +2025-03-11T12:40:34.794876,479392836,65404,209,-21.85580776924,-33.81716650458,42.12940274761,2,1,18 +2025-03-11T12:40:34.810501,479392836,65404,209,-21.60135995176,-33.57643050957,41.6844389191,2,1,18 +2025-03-11T12:40:34.826126,479392836,65404,209,-21.36104812414,-33.33109790163,41.24409807667,2,1,18 +2025-03-11T12:40:34.841751,479392836,65404,209,-21.10188831004,-33.09497482548,40.78528245796,2,1,18 +2025-03-11T12:40:34.857376,479392836,65404,209,-20.83801649932,-32.840359309065,40.30327998292,2,1,18 +2025-03-11T12:40:34.873001,479392836,65404,209,-20.58828067846,-32.57190503607,39.82586341396,2,1,18 +2025-03-11T12:40:34.888626,479392836,65404,209,-20.34796885084,-32.30808814083,39.38544841153,2,1,18 +2025-03-11T12:40:34.904251,479392836,65404,209,-20.10765702322,-32.06275553289,38.91738047071,2,1,18 +2025-03-11T12:40:34.919876,479392836,65404,209,-19.85320920574,-31.808156322405,38.43539155768,2,1,18 +2025-03-11T12:40:34.935501,479392836,65404,209,-19.5846253984,-31.55815372485,37.981127940025,2,1,18 +2025-03-11T12:40:34.951126,479392836,65404,209,-19.32075358768,-31.31740142391,37.508423451115,2,1,18 +2025-03-11T12:40:34.966751,479392836,65404,209,-19.0663057702,-31.0581811416,37.035658364215,2,1,18 +2025-03-11T12:40:34.982376,479392836,65404,209,-18.81656994934,-30.808211155905,36.567558321385,2,1,18 +2025-03-11T12:40:34.998001,479392836,65404,209,-18.56212213186,-30.52588551447,36.09932171755,2,1,18 +2025-03-11T12:40:35.013626,479392836,65404,209,-18.30296231776,-30.248172791895,35.626475689645,2,1,18 +2025-03-11T12:40:35.029251,479392836,65404,209,-18.03909050704,-29.98431513183,35.135193768475,2,1,18 +2025-03-11T12:40:35.044876,479392836,65404,209,-17.77993069294,-29.71122348108,34.639260365245,2,1,18 +2025-03-11T12:40:35.060501,479392836,65404,209,-17.51605888222,-29.456607964665,34.16187907327,2,1,18 +2025-03-11T12:40:35.076126,479392836,65404,209,-17.26161106474,-29.188145538705,33.684455723305,2,1,18 +2025-03-11T12:40:35.091751,479392836,65404,209,-16.9930272574,-28.915037582025,33.188508758065,2,1,18 +2025-03-11T12:40:35.107376,479392836,65404,209,-16.72444345006,-28.651171768995,32.692598872825,2,1,18 +2025-03-11T12:40:35.123001,479392836,65404,209,-16.44643564948,-28.37342643456,32.196619805575,2,1,18 +2025-03-11T12:40:35.138626,479392836,65404,209,-16.18256383876,-28.11418984632,31.705356424405,2,1,18 +2025-03-11T12:40:35.154251,479392836,65404,209,-15.90455603818,-27.85030772736,31.21405416022,2,1,18 +2025-03-11T12:40:35.169876,479392836,65404,209,-15.63126023422,-27.586433761365,30.718137493975,2,1,18 +2025-03-11T12:40:35.185501,479392836,65404,209,-15.35796443026,-27.317938723545,30.226823470795,2,1,18 +2025-03-11T12:40:35.201126,479392836,65404,209,-15.0846686263,-27.05406475755,29.71242207229,2,1,18 +2025-03-11T12:40:35.216751,479392836,65404,209,-14.81608481896,-26.77171465722,29.23492275931,2,1,18 +2025-03-11T12:40:35.232376,479392836,65404,209,-14.55221300824,-26.49399378168,28.729721668945,2,1,18 +2025-03-11T12:40:35.248001,479392836,65404,209,-14.27420520766,-26.22086951907,28.233761141695,2,1,18 +2025-03-11T12:40:35.263626,479392836,65404,209,-14.0009094037,-25.9431323376,27.751652404645,2,1,18 +2025-03-11T12:40:35.279251,479392836,65404,209,-13.7181896065,-25.669999922025,27.23720036413,2,1,18 +2025-03-11T12:40:35.294876,479392836,65404,209,-13.44018180592,-25.396875659415,26.727376287685,2,1,18 +2025-03-11T12:40:35.310501,479392836,65404,209,-13.17159799858,-25.10990448726,26.20826778712,2,1,18 +2025-03-11T12:40:35.326126,479392836,65404,209,-12.89830219462,-24.827546233965,25.703034594745,2,1,18 +2025-03-11T12:40:35.341751,479392836,65404,209,-12.62029439404,-24.54980089953,25.197813161365,2,1,18 +2025-03-11T12:40:35.357376,479392836,65404,209,-12.33757459684,-24.26280526848,24.669441951655,2,1,18 +2025-03-11T12:40:35.373001,479392836,65404,209,-12.05485479964,-23.971188565605,24.159536934205,2,1,18 +2025-03-11T12:40:35.388626,479392836,65404,209,-11.76742300582,-23.69342692524,23.64043838962,2,1,18 +2025-03-11T12:40:35.404251,479392836,65404,209,-11.48470320862,-23.420294509665,23.144471081365,2,1,18 +2025-03-11T12:40:35.419876,479392836,65404,209,-11.21140740466,-23.12869411272,22.653064358185,2,1,18 +2025-03-11T12:40:35.435501,479392836,65404,209,-10.91926361422,-22.837061103915,22.124661046465,2,1,18 +2025-03-11T12:40:35.451126,479392836,65404,209,-10.6318318204,-22.54081517625,21.60548834188,2,1,18 +2025-03-11T12:40:35.466751,479392836,65404,209,-10.3491120232,-22.2538195452,21.07711713217,2,1,18 +2025-03-11T12:40:35.482376,479392836,65404,209,-10.06168022938,-21.96219468936,20.54409941839,2,1,18 +2025-03-11T12:40:35.498001,479392836,65404,209,-9.78838442542,-21.689078579715,20.04352448908,2,1,18 +2025-03-11T12:40:35.513626,479392836,65404,209,-9.49152863836,-21.415921705245,19.542915654745,2,1,18 +2025-03-11T12:40:35.529251,479392836,65404,209,-9.20409684454,-21.11967577758,19.0052582179,2,1,18 +2025-03-11T12:40:35.544876,479392836,65404,209,-8.92137704734,-20.83268014653,18.472265825125,2,1,18 +2025-03-11T12:40:35.560501,479392836,65404,209,-8.63394525352,-20.53181314704,17.948453397475,2,1,18 +2025-03-11T12:40:35.576126,479392836,65404,209,-8.34180146308,-20.240180138235,17.420050085755,2,1,18 +2025-03-11T12:40:35.591751,479392836,65404,209,-8.06850565912,-19.95782188494,16.882468611925,2,1,18 +2025-03-11T12:40:35.607376,479392836,65404,209,-7.79049785854,-19.670834406855,16.367967732415,2,1,18 +2025-03-11T12:40:35.623001,479392836,65404,209,-7.48421807824,-19.379176939155,15.844165260745,2,1,18 +2025-03-11T12:40:35.638626,479392836,65404,209,-7.17793829794,-19.07365625598,15.301822436815,2,1,18 +2025-03-11T12:40:35.654251,479392836,65404,209,-6.89050650412,-18.777410328315,14.759543816905,2,1,18 +2025-03-11T12:40:35.669876,479392836,65404,209,-6.59836271368,-18.481156247685,14.22650078212,2,1,18 +2025-03-11T12:40:35.685501,479392836,65404,209,-6.31093091986,-18.19415246367,13.670395693015,2,1,18 +2025-03-11T12:40:35.701126,479392836,65404,209,-6.01878712942,-17.89789838304,13.13735265823,2,1,18 +2025-03-11T12:40:35.716751,479392836,65404,209,-5.70308335588,-17.60622460941,12.608915441485,2,1,18 +2025-03-11T12:40:35.732376,479392836,65404,209,-5.4015155722,-17.3191963665,12.07589592469,2,1,18 +2025-03-11T12:40:35.748001,479392836,65404,209,-5.12350777162,-17.013724601115,11.556699702115,2,1,18 +2025-03-11T12:40:35.763626,479392836,65404,209,-4.83136398118,-16.72209159231,11.02367520733,2,1,18 +2025-03-11T12:40:35.779251,479392836,65404,209,-4.54393218736,-16.425845664645,10.49063895355,2,1,18 +2025-03-11T12:40:35.794876,479392836,65404,209,-4.25178839692,-16.13421265584,9.939129726505,2,1,18 +2025-03-11T12:40:35.810501,479392836,65404,209,-3.95022061324,-15.84718441293,9.392246660515,2,1,18 +2025-03-11T12:40:35.826126,479392836,65404,209,-3.6580768228,-15.5509303323,8.84071889347,2,1,18 +2025-03-11T12:40:35.841751,479392836,65404,209,-3.36593303236,-15.25467625167,8.307675858685,2,1,18 +2025-03-11T12:40:35.857376,479392836,65404,209,-3.07378924192,-14.95842217104,7.78387519003,2,1,18 +2025-03-11T12:40:35.873001,479392836,65404,209,-2.77222145824,-14.657530712655,7.26466360243,2,1,18 +2025-03-11T12:40:35.888626,479392836,65404,209,-2.4800776678,-14.352034488375,6.70847757232,2,1,18 +2025-03-11T12:40:35.904251,479392836,65404,209,-2.1973578706,-14.055796713675,6.16158455035,2,1,18 +2025-03-11T12:40:35.919876,479392836,65404,209,-1.90521408016,-13.759542633045,5.6239203325,2,1,18 +2025-03-11T12:40:35.935501,479392836,65404,209,-1.6083582931,-13.46328039945,5.07238578445,2,1,18 +2025-03-11T12:40:35.951126,479392836,65404,209,-1.31150250604,-13.167018165855,4.53009360253,2,1,18 +2025-03-11T12:40:35.966751,479392836,65404,209,-1.00522272574,-12.86149748268,3.99699314473,2,1,18 +2025-03-11T12:40:35.982376,479392836,65404,209,-0.69894294544,-12.55135572768,3.4546317808,2,1,18 +2025-03-11T12:40:35.998001,479392836,65404,209,-0.39737516176,-12.25508534112,2.893848085615,2,1,18 +2025-03-11T12:40:36.013626,479392836,65404,209,-0.0863833848400001,-11.963419720455,2.337690551485,2,1,18 +2025-03-11T12:40:36.029251,479392836,65404,209,0.21518439884,-11.667149333895,1.800012771625,2,1,18 +2025-03-11T12:40:36.044876,479392836,65404,209,0.5120401859,-11.36164495665,1.26230469277,2,1,18 +2025-03-11T12:40:36.060501,479392836,65404,209,0.8183199662,-11.05150320165,0.70145859658,2,1,18 +2025-03-11T12:40:36.076126,479392836,65404,209,1.11517575326,-10.755240968055,0.16840878079,2,1,18 +2025-03-11T12:40:36.091751,479392836,65404,209,1.4073195437,-10.4543658156,-0.37851634319,2,1,18 +2025-03-11T12:40:36.107376,479392836,65404,209,1.69475133752,-10.14425667246,-0.9208505831,2,1,18 +2025-03-11T12:40:36.123001,479392836,65404,209,1.9963191212,-9.852607357725,-1.472373372155,2,1,18 +2025-03-11T12:40:36.138626,479392836,65404,209,2.29317490826,-9.56558726778,-2.02849202327,2,1,18 +2025-03-11T12:40:36.154251,479392836,65404,209,2.59474269194,-9.26931688122,-2.589275718455,2,1,18 +2025-03-11T12:40:36.169876,479392836,65404,209,2.90102247224,-8.96841726987,-3.131600002385,2,1,18 +2025-03-11T12:40:36.185501,479392836,65404,209,3.20259025592,-8.64442045236,-3.66476783918,2,1,18 +2025-03-11T12:40:36.201126,479392836,65404,209,3.49473404636,-8.343545299905,-4.188587047835,2,1,18 +2025-03-11T12:40:36.216751,479392836,65404,209,3.78216584018,-8.04729937224,-4.74472921694,2,1,18 +2025-03-11T12:40:36.232376,479392836,65404,209,4.07902162724,-7.75565821047,-5.319351140315,2,1,18 +2025-03-11T12:40:36.248001,479392836,65404,209,4.38530140754,-7.468621814595,-5.86624098731,2,1,18 +2025-03-11T12:40:36.263626,479392836,65404,209,4.6821571946,-7.16311743735,-6.43629734762,2,1,18 +2025-03-11T12:40:36.279251,479392836,65404,209,4.98372497828,-6.862225978965,-7.006341948935,2,1,18 +2025-03-11T12:40:36.294876,479392836,65404,209,5.2711567721,-6.55673790765,-7.548657648845,2,1,18 +2025-03-11T12:40:36.310501,479392836,65404,209,5.58214854902,-6.26969335881,-8.104796642975,2,1,18 +2025-03-11T12:40:36.326126,479392836,65404,209,5.88842832932,-5.973414819285,-8.656344753035,2,1,18 +2025-03-11T12:40:36.341751,479392836,65404,209,6.18057211976,-5.667918595005,-9.184803684755,2,1,18 +2025-03-11T12:40:36.357376,479392836,65404,209,6.47742790682,-5.36241421776,-9.727132946675,2,1,18 +2025-03-11T12:40:36.373001,479392836,65404,209,6.76957169726,-5.061539065305,-10.264815704525,2,1,18 +2025-03-11T12:40:36.388626,479392836,65404,209,7.07113948094,-4.746784391445,-10.811810010515,2,1,18 +2025-03-11T12:40:36.404251,479392836,65404,209,7.37741926124,-4.44126370827,-11.344910468315,2,1,18 +2025-03-11T12:40:36.419876,479392836,65404,209,7.67898704492,-4.15423546536,-11.88717235124,2,1,18 +2025-03-11T12:40:36.435501,479392836,65404,209,7.97584283198,-3.84411001629,-12.42952015316,2,1,18 +2025-03-11T12:40:36.451126,479392836,65404,209,8.2632746258,-3.53400087315,-12.96261202694,2,1,18 +2025-03-11T12:40:36.466751,479392836,65404,209,8.56484240948,-3.22848834294,-13.532675168255,2,1,18 +2025-03-11T12:40:36.482376,479392836,65404,209,8.87112218978,-2.941451947065,-14.074943832185,2,1,18 +2025-03-11T12:40:36.498001,479392836,65404,209,9.16797797684,-2.659052928945,-14.61255921104,2,1,18 +2025-03-11T12:40:36.513626,479392836,65404,209,9.46012176728,-2.353556704665,-15.136396959695,2,1,18 +2025-03-11T12:40:36.529251,479392836,65404,209,9.75226555772,-2.057302624035,-15.67868236061,2,1,18 +2025-03-11T12:40:36.544876,479392836,65404,209,10.04912134478,-1.77028253409,-16.234801011725,2,1,18 +2025-03-11T12:40:36.560501,479392836,65404,209,10.35540112508,-1.474003994565,-16.78172793872,2,1,18 +2025-03-11T12:40:36.576126,479392836,65404,209,10.65225691214,-1.173120689145,-17.319417477575,2,1,18 +2025-03-11T12:40:36.591751,479392836,65404,209,10.93497670934,-0.867640770795,-17.85248403035,2,1,18 +2025-03-11T12:40:36.607376,479392836,65404,209,11.22240850316,-0.58063698678,-18.39472557026,2,1,18 +2025-03-11T12:40:36.623001,479392836,65404,209,11.53340028008,-0.256623863339999,-18.937149335195,2,1,18 +2025-03-11T12:40:36.638626,479392836,65404,209,11.83496806376,0.0396465232200001,-19.474827115055,2,1,18 +2025-03-11T12:40:36.654251,479392836,65404,209,12.13653584744,0.322053694305001,-20.02631282411,2,1,18 +2025-03-11T12:40:36.669876,479392836,65404,209,12.44281562774,0.61833223383,-20.563997384975,2,1,18 +2025-03-11T12:40:36.685501,479392836,65404,209,12.73024742156,0.914578161495001,-21.097033638755,2,1,18 +2025-03-11T12:40:36.701126,479392836,65404,209,13.00825522214,1.196944567755,-21.62537952746,2,1,18 +2025-03-11T12:40:36.716751,479392836,65404,209,13.29568701596,1.488569423595,-22.163018424305,2,1,18 +2025-03-11T12:40:36.732376,479392836,65404,209,13.59254280302,1.780210585365,-22.696049700095,2,1,18 +2025-03-11T12:40:36.748001,479392836,65404,209,13.87997459684,2.08569865668,-23.23374421694,2,1,18 +2025-03-11T12:40:36.763626,479392836,65404,209,14.16740639066,2.37732351252,-23.762140747655,2,1,18 +2025-03-11T12:40:36.779251,479392836,65404,209,14.45012618786,2.65507699992,-24.2858536943,2,1,18 +2025-03-11T12:40:36.794876,479392836,65404,209,14.7422699783,2.946710008725,-24.818878189085,2,1,18 +2025-03-11T12:40:36.810501,479392836,65404,209,15.02970177212,3.238334864565,-25.351895902865,2,1,18 +2025-03-11T12:40:36.826126,479392836,65404,209,15.32184556256,3.52996787337,-25.898783946845,2,1,18 +2025-03-11T12:40:36.841751,479392836,65404,209,15.60456535976,3.82620564807,-26.427192236555,2,1,18 +2025-03-11T12:40:36.857376,479392836,65404,209,15.8967091502,4.1224597287,-26.946371722145,2,1,18 +2025-03-11T12:40:36.873001,479392836,65404,209,16.19356493726,4.40485874682,-27.460881185675,2,1,18 +2025-03-11T12:40:36.888626,479392836,65404,209,16.47157273784,4.68722515308,-27.993848257445,2,1,18 +2025-03-11T12:40:36.904251,479392836,65404,209,16.76371652828,4.97423709006,-28.52685421223,2,1,18 +2025-03-11T12:40:36.919876,479392836,65404,209,17.04172432886,5.26584563997,-29.045994814805,2,1,18 +2025-03-11T12:40:36.935501,479392836,65404,209,17.32444412606,5.56208341467,-29.565160738385,2,1,18 +2025-03-11T12:40:36.951126,479392836,65404,209,17.60716392326,5.835215830245,-30.074991595835,2,1,18 +2025-03-11T12:40:36.966751,479392836,65404,209,17.8993077137,6.12684883905,-30.594152541425,2,1,18 +2025-03-11T12:40:36.982376,479392836,65404,209,18.19145150414,6.41386077603,-31.10867376395,2,1,18 +2025-03-11T12:40:36.998001,479392836,65404,209,18.48359529458,6.687009497535,-31.632381732605,2,1,18 +2025-03-11T12:40:37.013626,479392836,65404,209,18.7710270884,6.969392209725,-32.156120000255,2,1,18 +2025-03-11T12:40:37.029251,479392836,65404,209,19.03961089574,7.25636338188,-32.670607317755,2,1,18 +2025-03-11T12:40:37.044876,479392836,65404,209,19.3129066997,7.520237347875,-33.161902800935,2,1,18 +2025-03-11T12:40:37.060501,479392836,65404,209,19.5956264969,7.8026119071,-33.681013104515,2,1,18 +2025-03-11T12:40:37.076126,479392836,65404,209,19.88777028734,8.085002772255,-34.19551578704,2,1,18 +2025-03-11T12:40:37.091751,479392836,65404,209,20.18933807102,8.36740994334,-34.71465321464,2,1,18 +2025-03-11T12:40:37.107376,479392836,65404,209,20.48148186146,8.659042952145,-35.2245717941,2,1,18 +2025-03-11T12:40:37.123001,479392836,65404,209,20.76420165866,8.92293322407,-35.729744388485,2,1,18 +2025-03-11T12:40:37.138626,479392836,65404,209,21.032785466,9.191420108925,-36.22105163066,2,1,18 +2025-03-11T12:40:37.154251,479392836,65404,209,21.2919452801,9.47837497515,-36.73552538615,2,1,18 +2025-03-11T12:40:37.169876,479392836,65404,209,21.56524108406,9.76535430027,-37.24539830159,2,1,18 +2025-03-11T12:40:37.185501,479392836,65404,209,21.83853688802,10.05233362539,-37.76451358316,2,1,18 +2025-03-11T12:40:37.201126,479392836,65404,209,22.1165446886,10.33470003165,-38.265132373475,2,1,18 +2025-03-11T12:40:37.216751,479392836,65404,209,22.38984049256,10.60319506947,-38.747204030525,2,1,18 +2025-03-11T12:40:37.232376,479392836,65404,209,22.66784829314,10.890182547555,-39.24784136084,2,1,18 +2025-03-11T12:40:37.248001,479392836,65404,209,22.94585609372,11.172548953815,-39.757702517285,2,1,18 +2025-03-11T12:40:37.263626,479392836,65404,209,23.21443990106,11.42255155137,-40.244314416395,2,1,18 +2025-03-11T12:40:37.279251,479392836,65404,209,23.47831171178,11.667924924135,-40.7309009945,2,1,18 +2025-03-11T12:40:37.294876,479392836,65404,209,23.7421835225,11.945645799675,-41.22223853567,2,1,18 +2025-03-11T12:40:37.310501,479392836,65404,209,23.99663133998,12.22797144111,-41.708959871765,2,1,18 +2025-03-11T12:40:37.326126,479392836,65404,209,24.25107915746,12.501054938895,-42.191022944795,2,1,18 +2025-03-11T12:40:37.341751,479392836,65404,209,24.52908695804,12.76031598603,-42.69154903511,2,1,18 +2025-03-11T12:40:37.357376,479392836,65404,209,24.79767076538,13.02418179906,-43.17821655422,2,1,18 +2025-03-11T12:40:37.373001,479392836,65404,209,25.06625457272,13.292668683915,-43.660281430265,2,1,18 +2025-03-11T12:40:37.388626,479392836,65404,209,25.33483838006,13.56115556877,-44.146967489375,2,1,18 +2025-03-11T12:40:37.404251,479392836,65404,209,25.59399819416,13.820384004045,-44.62898172341,2,1,18 +2025-03-11T12:40:37.419876,479392836,65404,209,25.84844601164,14.07498321453,-45.10172827031,2,1,18 +2025-03-11T12:40:37.435501,479392836,65404,209,26.10289382912,14.34344564049,-45.58377280334,2,1,18 +2025-03-11T12:40:37.451126,479392836,65404,209,26.36676563984,14.62116651603,-46.061246795315,2,1,18 +2025-03-11T12:40:37.466751,479392836,65404,209,26.63063745056,14.88040310427,-46.524783078095,2,1,18 +2025-03-11T12:40:37.482376,479392836,65404,209,26.88979726466,15.10728403677,-46.997425166,2,1,18 +2025-03-11T12:40:37.498001,479392836,65404,209,27.158381072,15.366528777975,-47.48407414511,2,1,18 +2025-03-11T12:40:37.513626,479392836,65404,209,27.40340489624,15.634974898005,-47.94762038387,2,1,18 +2025-03-11T12:40:37.529251,479392836,65404,209,27.6531407171,15.8849448837,-48.420341609765,2,1,18 +2025-03-11T12:40:37.544876,479392836,65404,209,27.90758853458,16.148786237835,-48.883882870535,2,1,18 +2025-03-11T12:40:37.560501,479392836,65404,209,28.15732435544,16.412619439005,-49.342796167235,2,1,18 +2025-03-11T12:40:37.576126,479392836,65404,209,28.42119616616,16.66723495542,-49.797071543885,2,1,18 +2025-03-11T12:40:37.591751,479392836,65404,209,28.67564398364,16.92645523773,-50.2282459832,2,1,18 +2025-03-11T12:40:37.607376,479392836,65404,209,28.93951579436,17.171828610495,-50.68248427985,2,1,18 +2025-03-11T12:40:37.623001,479392836,65404,209,29.18925161522,17.43104073984,-51.14137903655,2,1,18 +2025-03-11T12:40:37.638626,479392836,65404,209,29.43427543946,17.694865788045,-51.58642200305,2,1,18 +2025-03-11T12:40:37.654251,479392836,65404,209,29.68401126032,17.92635148644,-52.031341970555,2,1,18 +2025-03-11T12:40:37.669876,479392836,65404,209,29.91018709808,18.162417491835,-52.4808677561,2,1,18 +2025-03-11T12:40:37.685501,479392836,65404,209,30.1504989257,18.407750099775,-52.93969333079,2,1,18 +2025-03-11T12:40:37.701126,479392836,65404,209,30.40494674318,18.64386502296,-53.389259802365,2,1,18 +2025-03-11T12:40:37.716751,479392836,65404,209,30.6452585708,18.875334415425,-53.838787390925,2,1,18 +2025-03-11T12:40:37.732376,479392836,65404,209,30.89028239504,19.116054104505,-54.274495291295,2,1,18 +2025-03-11T12:40:37.748001,479392836,65404,209,31.12117022942,19.361370406515,-54.705580205585,2,1,18 +2025-03-11T12:40:37.763626,479392836,65404,209,31.37090605028,19.60209824856,-55.136673703895,2,1,18 +2025-03-11T12:40:37.779251,479392836,65404,209,31.60650588128,19.847422703535,-55.55852303306,2,1,18 +2025-03-11T12:40:37.794876,479392836,65404,209,31.84210571228,20.09274715851,-55.99423591142,2,1,18 +2025-03-11T12:40:37.810501,479392836,65404,209,32.0824175399,20.31959547915,-56.41601786159,2,1,18 +2025-03-11T12:40:37.826126,479392836,65404,209,32.30859337766,20.55104041272,-56.847040374875,2,1,18 +2025-03-11T12:40:37.841751,479392836,65404,209,32.54890520528,20.78713087701,-57.29196532037,2,1,18 +2025-03-11T12:40:37.857376,479392836,65404,209,32.78450503628,21.03707640381,-57.713833189535,2,1,18 +2025-03-11T12:40:37.873001,479392836,65404,209,33.02010486728,21.25929549966,-58.130968635635,2,1,18 +2025-03-11T12:40:37.888626,479392836,65404,209,33.24628070504,21.47225614593,-58.55267462279,2,1,18 +2025-03-11T12:40:37.904251,479392836,65404,209,33.46774454618,21.70831399836,-58.951360613615,2,1,18 +2025-03-11T12:40:37.919876,479392836,65404,209,33.69863238056,21.93514601307,-59.35926545258,2,1,18 +2025-03-11T12:40:37.935501,479392836,65404,209,33.9200962217,22.166582793675,-59.7717964526,2,1,18 +2025-03-11T12:40:37.951126,479392836,65404,209,34.12271207636,22.38874481877,-60.1842632486,2,1,18 +2025-03-11T12:40:37.966751,479392836,65404,209,34.33475192426,22.61554422162,-60.60600451274,2,1,18 +2025-03-11T12:40:37.982376,479392836,65404,209,34.57035175526,22.81927903017,-61.009202249645,2,1,18 +2025-03-11T12:40:37.997955,479392840,65401,210,34.79652759302,23.036860748265,-61.42168441067,2,1,18 +2025-03-11T12:40:38.013580,479392840,65401,210,35.0038554443,23.259030926325,-61.806430889285,2,1,18 +2025-03-11T12:40:38.029205,479392840,65401,210,35.22531928544,23.48122556328,-62.20506126011,2,1,18 +2025-03-11T12:40:38.044830,479392840,65401,210,35.44678312658,23.69879912841,-62.612915457065,2,1,18 +2025-03-11T12:40:38.060455,479392840,65401,210,35.65882297448,23.920977459435,-63.01153226588,2,1,18 +2025-03-11T12:40:38.076080,479392840,65401,210,35.86615082576,24.12928442202,-63.37311720917,2,1,18 +2025-03-11T12:40:38.091705,479392840,65401,210,36.0640546838,24.328332935025,-63.748515059645,2,1,18 +2025-03-11T12:40:38.107330,479392840,65401,210,36.2760945317,24.53202697875,-64.11933061007,2,1,18 +2025-03-11T12:40:38.122955,479392840,65401,210,36.49755837284,24.73111625658,-64.48551999944,2,1,18 +2025-03-11T12:40:38.138580,479392840,65401,210,36.70488622412,24.93480214734,-64.85632876886,2,1,18 +2025-03-11T12:40:38.154205,479392840,65401,210,36.91692607202,25.13387511924,-65.245610511545,2,1,18 +2025-03-11T12:40:38.169830,479392840,65401,210,37.1242539233,25.342182081825,-65.62105900403,2,1,18 +2025-03-11T12:40:38.185455,479392840,65401,210,37.31744578472,25.57356994464,-66.00582221963,2,1,18 +2025-03-11T12:40:38.201080,479392840,65401,210,37.52006163938,25.79111089791,-66.376679828045,2,1,18 +2025-03-11T12:40:38.216705,479392840,65401,210,37.72267749404,25.994788635705,-66.733618267265,2,1,18 +2025-03-11T12:40:38.232330,479392840,65401,210,37.91115735884,26.20306298643,-67.104418452665,2,1,18 +2025-03-11T12:40:38.247955,479392840,65401,210,38.10906121688,26.39749042761,-67.456691847815,2,1,18 +2025-03-11T12:40:38.263580,479392840,65401,210,38.30696507492,26.57343358149,-67.808891082965,2,1,18 +2025-03-11T12:40:38.279205,479392840,65401,210,38.5142929262,26.77711947225,-68.16583630319,2,1,18 +2025-03-11T12:40:38.294830,479392840,65401,210,38.702772791,26.96228846385,-68.513437873265,2,1,18 +2025-03-11T12:40:38.310455,479392840,65401,210,38.88654065918,27.16131251796,-68.8657094654,2,1,18 +2025-03-11T12:40:38.326080,479392840,65401,210,39.08915651384,27.36036918393,-69.208765815425,2,1,18 +2025-03-11T12:40:38.341705,479392840,65401,210,39.2682123854,27.5455218696,-69.54711145736,2,1,18 +2025-03-11T12:40:38.357330,479392840,65401,210,39.45198025358,27.73530378006,-69.890103603365,2,1,18 +2025-03-11T12:40:38.372955,479392840,65401,210,39.62632412852,27.91582724094,-70.237666290425,2,1,18 +2025-03-11T12:40:38.388580,479392840,65401,210,39.80066800346,28.09635070182,-70.575986611355,2,1,18 +2025-03-11T12:40:38.404205,479392840,65401,210,39.9750118784,28.272253090875,-70.905046026155,2,1,18 +2025-03-11T12:40:38.419830,479392840,65401,210,40.17291573644,28.457438388405,-71.238797609045,2,1,18 +2025-03-11T12:40:38.435455,479392840,65401,210,40.351971608,28.633348930425,-71.54937907259,2,1,18 +2025-03-11T12:40:38.451080,479392840,65401,210,40.52631548294,28.813872391305,-71.873835844325,2,1,18 +2025-03-11T12:40:38.466705,479392840,65401,210,40.71950734436,28.985186320395,-72.193661477015,2,1,18 +2025-03-11T12:40:38.482330,479392840,65401,210,40.8938512193,29.16108870945,-72.50885734262,2,1,18 +2025-03-11T12:40:38.497955,479392840,65401,210,41.05405910438,29.32772449596,-72.819374602145,2,1,18 +2025-03-11T12:40:38.513580,479392840,65401,210,41.23311497594,29.489771822505,-73.12065807956,2,1,18 +2025-03-11T12:40:38.529205,479392840,65401,210,41.40745885088,29.67491635521,-73.445133391295,2,1,18 +2025-03-11T12:40:38.544830,479392840,65401,210,41.56295473934,29.85540720423,-73.74183594062,2,1,18 +2025-03-11T12:40:38.560455,479392840,65401,210,41.72316262442,30.02204299074,-74.02924728482,2,1,18 +2025-03-11T12:40:38.576080,479392840,65401,210,41.88808250612,30.170202642915,-74.33045479922,2,1,18 +2025-03-11T12:40:38.591705,479392840,65401,210,42.05300238782,30.32760443874,-74.636320576685,2,1,18 +2025-03-11T12:40:38.607330,479392840,65401,210,42.20378627966,30.498844991145,-74.92835808194,2,1,18 +2025-03-11T12:40:38.622955,479392840,65401,210,42.36399416474,30.65161756218,-75.220334989205,2,1,18 +2025-03-11T12:40:38.638580,479392840,65401,210,42.53362604306,30.795164295495,-75.50304601235,2,1,18 +2025-03-11T12:40:38.654205,479392840,65401,210,42.6844099349,30.943299488775,-75.776506085345,2,1,18 +2025-03-11T12:40:38.669830,479392840,65401,210,42.83519382674,31.10529789753,-76.054642961405,2,1,18 +2025-03-11T12:40:38.685455,479392840,65401,210,42.9906897152,31.262683387425,-76.33276807847,2,1,18 +2025-03-11T12:40:38.701080,479392840,65401,210,43.1320496138,31.4154233466,-76.60161194639,2,1,18 +2025-03-11T12:40:38.716705,479392840,65401,210,43.25927352254,31.572759918705,-76.879696377425,2,1,18 +2025-03-11T12:40:38.732330,479392840,65401,210,43.414769411,31.70241897765,-77.14846788836,2,1,18 +2025-03-11T12:40:38.747955,479392840,65401,210,43.57026529946,31.822835892945,-77.42182350236,2,1,18 +2025-03-11T12:40:38.763580,479392840,65401,210,43.72576118792,31.966358167365,-77.690650633295,2,1,18 +2025-03-11T12:40:38.779205,479392840,65401,210,43.8624090899,32.1237110454,-77.954885077145,2,1,18 +2025-03-11T12:40:38.794830,479392840,65401,210,44.0037689885,32.276451004575,-78.20986539587,2,1,18 +2025-03-11T12:40:38.810455,479392840,65401,210,44.15455288034,32.406101910555,-78.464766576605,2,1,18 +2025-03-11T12:40:38.826080,479392840,65401,210,44.30062477556,32.540365735395,-78.71505833327,2,1,18 +2025-03-11T12:40:38.841705,479392840,65401,210,44.41371269444,32.67457248948,-78.95606025677,2,1,18 +2025-03-11T12:40:38.857330,479392840,65401,210,44.54093660318,32.81804584611,-79.19249842022,2,1,18 +2025-03-11T12:40:38.872955,479392840,65401,210,44.68229650178,32.94768044616,-79.419658940555,2,1,18 +2025-03-11T12:40:38.888580,479392840,65401,210,44.81894440376,33.068064749595,-79.637533233755,2,1,18 +2025-03-11T12:40:38.904205,479392840,65401,210,44.95559230574,33.183827981205,-79.87849490228,2,1,18 +2025-03-11T12:40:38.919830,479392840,65401,210,45.07339222124,33.31342181643,-80.10562151759,2,1,18 +2025-03-11T12:40:38.935455,479392840,65401,210,45.21004012322,33.44766933534,-80.33279379692,2,1,18 +2025-03-11T12:40:38.951080,479392840,65401,210,45.32784003872,33.577263170565,-80.56916277836,2,1,18 +2025-03-11T12:40:38.966705,479392840,65401,210,45.45506394746,33.702252239895,-80.78704204955,2,1,18 +2025-03-11T12:40:38.982330,479392840,65401,210,45.57286386296,33.817982859645,-81.00487067873,2,1,18 +2025-03-11T12:40:38.997955,479392840,65401,210,45.69066377846,33.93833455122,-81.218096664845,2,1,18 +2025-03-11T12:40:39.013580,479392840,65401,210,45.78961570748,34.05403255911,-81.426655803875,2,1,18 +2025-03-11T12:40:39.029205,479392840,65401,210,45.90741562298,34.17900532251,-81.62141559773,2,1,18 +2025-03-11T12:40:39.044830,479392840,65401,210,46.02050354186,34.285485645645,-81.82533681671,2,1,18 +2025-03-11T12:40:39.060455,479392840,65401,210,46.12887946412,34.391957815815,-82.020008888555,2,1,18 +2025-03-11T12:40:39.076080,479392840,65401,210,46.241967383,34.512301354425,-82.233228093665,2,1,18 +2025-03-11T12:40:39.091705,479392840,65401,210,46.34563130864,34.61876537163,-82.43251456757,2,1,18 +2025-03-11T12:40:39.107330,479392840,65401,210,46.43987124104,34.715970939255,-82.61788685027,2,1,18 +2025-03-11T12:40:39.122955,479392840,65401,210,46.54353516668,34.808571740985,-82.81249652111,2,1,18 +2025-03-11T12:40:39.138580,479392840,65401,210,46.63777509908,34.90577730861,-82.99786880381,2,1,18 +2025-03-11T12:40:39.154205,479392840,65401,210,46.75086301796,35.01687870357,-83.18332383053,2,1,18 +2025-03-11T12:40:39.169830,479392840,65401,210,46.83567895712,35.10944689344,-83.35017927896,2,1,18 +2025-03-11T12:40:39.185455,479392840,65401,210,46.92049489628,35.206636155135,-83.521674450455,2,1,18 +2025-03-11T12:40:39.201080,479392840,65401,210,47.01473482868,35.31308386641,-83.6747355317,2,1,18 +2025-03-11T12:40:39.216705,479392840,65401,210,47.11839875432,35.382579309015,-83.83228303802,2,1,18 +2025-03-11T12:40:39.232330,479392840,65401,210,47.2079266901,35.4474292209,-84.01289757665,2,1,18 +2025-03-11T12:40:39.247955,479392840,65401,210,47.29274262926,35.535376338945,-84.17049211895,2,1,18 +2025-03-11T12:40:39.263580,479392840,65401,210,47.39169455828,35.632590059535,-84.318901718135,2,1,18 +2025-03-11T12:40:39.279205,479392840,65401,210,47.47179850082,35.70666580914,-84.471812676365,2,1,18 +2025-03-11T12:40:39.294830,479392840,65401,210,47.55661443998,35.785370783535,-84.61550658947,2,1,18 +2025-03-11T12:40:39.310455,479392840,65401,210,47.64143037914,35.868696829755,-84.740734310315,2,1,18 +2025-03-11T12:40:39.326080,479392840,65401,210,47.71682232506,35.952006570045,-84.898296750605,2,1,18 +2025-03-11T12:40:39.341705,479392840,65401,210,47.78750227436,36.058413516495,-85.060566292955,2,1,18 +2025-03-11T12:40:39.357330,479392840,65401,210,47.85818222366,36.13247296017,-85.204221323045,2,1,18 +2025-03-11T12:40:39.372955,479392840,65401,210,47.92886217296,36.20191133202,-85.338615447005,2,1,18 +2025-03-11T12:40:39.388580,479392840,65401,210,48.0089661155,36.26212386615,-85.454501320715,2,1,18 +2025-03-11T12:40:39.404205,479392840,65401,210,48.08435806142,36.322328247315,-85.57038041342,2,1,18 +2025-03-11T12:40:39.419830,479392840,65401,210,48.15975000734,36.39177477213,-85.677054219995,2,1,18 +2025-03-11T12:40:39.435455,479392840,65401,210,48.21158197016,36.456559460295,-85.792917947675,2,1,18 +2025-03-11T12:40:39.451080,479392840,65401,210,48.27283792622,36.516739382565,-85.918019063495,2,1,18 +2025-03-11T12:40:39.466705,479392840,65401,210,48.32938188566,36.56766900822,-86.029212769115,2,1,18 +2025-03-11T12:40:39.482330,479392840,65401,210,48.3859258451,36.6232197057,-86.140425014735,2,1,18 +2025-03-11T12:40:39.497955,479392840,65401,210,48.44718180116,36.688020699795,-86.237817572165,2,1,18 +2025-03-11T12:40:39.513580,479392840,65401,210,48.49901376398,36.748184316135,-86.33979921065,2,1,18 +2025-03-11T12:40:39.529205,479392840,65401,210,48.55555772342,36.794492869965,-86.43248964401,2,1,18 +2025-03-11T12:40:39.544830,479392840,65401,210,48.59325369638,36.84538988376,-86.529792676415,2,1,18 +2025-03-11T12:40:39.560455,479392840,65401,210,48.6450856592,36.89631135645,-86.59476777038,2,1,18 +2025-03-11T12:40:39.576080,479392840,65401,210,48.6922056254,36.947224676175,-86.673599632535,2,1,18 +2025-03-11T12:40:39.591705,479392840,65401,210,48.73461359498,36.998129842935,-86.761667079815,2,1,18 +2025-03-11T12:40:39.607330,479392840,65401,210,48.79115755442,37.035196253115,-86.863562799305,2,1,18 +2025-03-11T12:40:39.622955,479392840,65401,210,48.833565524,37.06299606075,-86.933052814325,2,1,18 +2025-03-11T12:40:39.638580,479392840,65401,210,48.87597349358,37.100038012035,-87.002579909345,2,1,18 +2025-03-11T12:40:39.654205,479392840,65401,210,48.92309345978,37.146330259935,-87.067529682305,2,1,18 +2025-03-11T12:40:39.669830,479392840,65401,210,48.96078943274,37.183364058255,-87.13704999632,2,1,18 +2025-03-11T12:40:39.685455,479392840,65401,210,48.99377340908,37.225010775435,-87.1973397032,2,1,18 +2025-03-11T12:40:39.701080,479392840,65401,210,49.02675738542,37.26203642079,-87.25761087008,2,1,18 +2025-03-11T12:40:39.716705,479392840,65401,210,49.0456053719,37.28055331995,-87.29468161862,2,1,18 +2025-03-11T12:40:39.732330,479392840,65401,210,49.06445335838,37.312933434585,-87.345671536355,2,1,18 +2025-03-11T12:40:39.747955,479392840,65401,210,49.09743733472,37.34995907994,-87.415185069365,2,1,18 +2025-03-11T12:40:39.763580,479392840,65401,210,49.11157332458,37.37308889796,-87.4522675769,2,1,18 +2025-03-11T12:40:39.779205,479392840,65401,210,49.1398453043,37.396243174875,-87.48012806132,2,1,18 +2025-03-11T12:40:39.794830,479392840,65401,210,49.15869329078,37.405517930385,-87.512540546795,2,1,18 +2025-03-11T12:40:39.810455,479392840,65401,210,49.16811728402,37.41015530814,-87.549542113325,2,1,18 +2025-03-11T12:40:39.826080,479392840,65401,210,49.1869652705,37.4286722073,-87.586612861865,2,1,18 +2025-03-11T12:40:39.841705,479392840,65401,210,49.20110126036,37.437938809845,-87.619018566335,2,1,18 +2025-03-11T12:40:39.857330,479392840,65401,210,49.21994924684,37.46107678083,-87.62375957342,2,1,18 +2025-03-11T12:40:39.872955,479392840,65401,210,49.22466124346,37.470327077445,-87.633045800555,2,1,18 +2025-03-11T12:40:39.888580,479392840,65401,210,49.22466124346,37.470327077445,-87.63766698362,2,1,18 +2025-03-11T12:40:39.904205,479392840,65401,210,49.22466124346,37.461084933795,-87.651493452815,2,1,18 +2025-03-11T12:40:39.919830,479392840,65401,210,49.24822122656,37.47036784227,-87.6700491701,2,1,18 +2025-03-11T12:40:39.935455,479392840,65401,210,49.2576452198,37.47962629185,-87.67009981211,2,1,18 +2025-03-11T12:40:39.951080,479392840,65401,210,49.25293322318,37.48423921071,-87.65624802191,2,1,18 +2025-03-11T12:40:39.966705,479392840,65401,210,49.23879723332,37.47959367999,-87.67007268809,2,1,18 +2025-03-11T12:40:39.982330,479392840,65401,210,49.2340852367,37.488827670675,-87.670102987085,2,1,18 +2025-03-11T12:40:39.997955,479392840,65401,210,49.23879723332,37.47959367999,-87.646966772765,2,1,18 +2025-03-11T12:40:40.013580,479392840,65401,210,49.22937324008,37.46109308676,-87.62377313543,2,1,18 +2025-03-11T12:40:40.029205,479392840,65401,210,49.22937324008,37.447229871285,-87.591369233975,2,1,18 +2025-03-11T12:40:40.044830,479392840,65401,210,49.20581325698,37.433325890985,-87.56355261056,2,1,18 +2025-03-11T12:40:40.060455,479392840,65401,210,49.1869652705,37.414808991825,-87.549587777345,2,1,18 +2025-03-11T12:40:40.076080,479392840,65401,210,49.16811728402,37.39167102084,-87.51711967187,2,1,18 +2025-03-11T12:40:40.091705,479392840,65401,210,49.15869329078,37.368549355785,-87.48928631147,2,1,18 +2025-03-11T12:40:40.107330,479392840,65401,210,49.14926929754,37.37315412168,-87.44307945881,2,1,18 +2025-03-11T12:40:40.122955,479392840,65401,210,49.12570931444,37.354629069555,-87.406001929265,2,1,18 +2025-03-11T12:40:40.138580,479392840,65401,210,49.09743733472,37.33147479264,-87.36427789565,2,1,18 +2025-03-11T12:40:40.154205,479392840,65401,210,49.07387735162,37.294465453215,-87.3409897553,2,1,18 +2025-03-11T12:40:40.169830,479392840,65401,210,49.05031736852,37.271319329265,-87.28078777043,2,1,18 +2025-03-11T12:40:40.185455,479392840,65401,210,49.01262139556,37.234285530945,-87.211267456415,2,1,18 +2025-03-11T12:40:40.201080,479392840,65401,210,48.98906141246,37.183412976045,-87.169438963805,2,1,18 +2025-03-11T12:40:40.216705,479392840,65401,210,48.96078943274,37.15101655548,-87.10919311793,2,1,18 +2025-03-11T12:40:40.232330,479392840,65401,210,48.91366946654,37.11396645123,-87.04428042497,2,1,18 +2025-03-11T12:40:40.247955,479392840,65401,210,48.87597349358,37.081553724735,-86.984021017085,2,1,18 +2025-03-11T12:40:40.263580,479392840,65401,210,48.833565524,37.039890701625,-86.914475382065,2,1,18 +2025-03-11T12:40:40.279205,479392840,65401,210,48.80529354428,37.002873209235,-86.8264838978,2,1,18 +2025-03-11T12:40:40.294830,479392840,65401,210,48.76759757132,36.96121833909,-86.729217945395,2,1,18 +2025-03-11T12:40:40.310455,479392840,65401,210,48.72990159836,36.91494239712,-86.65041818525,2,1,18 +2025-03-11T12:40:40.326080,479392840,65401,210,48.69691762202,36.868674608115,-86.585488755305,2,1,18 +2025-03-11T12:40:40.341705,479392840,65401,210,48.63566166596,36.82235790132,-86.48354917481,2,1,18 +2025-03-11T12:40:40.357330,479392840,65401,210,48.5744057099,36.78066226635,-86.390870500445,2,1,18 +2025-03-11T12:40:40.372955,479392840,65401,210,48.51314975384,36.715861272255,-86.29809912608,2,1,18 +2025-03-11T12:40:40.388580,479392840,65401,210,48.46131779102,36.664939799565,-86.186912201465,2,1,18 +2025-03-11T12:40:40.404205,479392840,65401,210,48.40477383158,36.60476803026,-86.08954496504,2,1,18 +2025-03-11T12:40:40.419830,479392840,65401,210,48.34351787552,36.539967036165,-85.99215240761,2,1,18 +2025-03-11T12:40:40.435455,479392840,65401,210,48.28226191946,36.489029257545,-85.871709554855,2,1,18 +2025-03-11T12:40:40.451080,479392840,65401,210,48.21158197016,36.41496981387,-85.75116044009,2,1,18 +2025-03-11T12:40:40.466705,479392840,65401,210,48.16446200396,36.35943542232,-85.63071939035,2,1,18 +2025-03-11T12:40:40.482330,479392840,65401,210,48.09849405128,36.280763059785,-85.50091615046,2,1,18 +2025-03-11T12:40:40.497955,479392840,65401,210,48.02310210536,36.20207439132,-85.366478165495,2,1,18 +2025-03-11T12:40:40.513580,479392840,65401,210,47.96655814592,36.132660478365,-85.22286201842,2,1,18 +2025-03-11T12:40:40.529205,479392840,65401,210,47.89587819662,36.072464250165,-85.09774734059,2,1,18 +2025-03-11T12:40:40.544830,479392840,65401,210,47.82519824732,36.012268021965,-84.986496211955,2,1,18 +2025-03-11T12:40:40.560455,479392840,65401,210,47.74509430478,35.933571200535,-84.861293812115,2,1,18 +2025-03-11T12:40:40.576080,479392840,65401,210,47.66499036224,35.84101116363,-84.70368751082,2,1,18 +2025-03-11T12:40:40.591705,479392840,65401,210,47.58959841632,35.753080351515,-84.55534889666,2,1,18 +2025-03-11T12:40:40.607330,479392840,65401,210,47.50949447378,35.674383530085,-84.397798215365,2,1,18 +2025-03-11T12:40:40.622955,479392840,65401,210,47.41054254476,35.586411953145,-84.25866806231,2,1,18 +2025-03-11T12:40:40.638580,479392840,65401,210,47.31630261236,35.512311744645,-84.09187321187,2,1,18 +2025-03-11T12:40:40.654205,479392840,65401,210,47.21735068334,35.41971909588,-83.924997420425,2,1,18 +2025-03-11T12:40:40.669830,479392840,65401,210,47.13253474418,35.32715090601,-83.75352078893,2,1,18 +2025-03-11T12:40:40.685455,479392840,65401,210,47.04771880502,35.24382485979,-83.5867024205,2,1,18 +2025-03-11T12:40:40.701080,479392840,65401,210,46.97703885572,35.15590220064,-83.419885855085,2,1,18 +2025-03-11T12:40:40.716705,479392840,65401,210,46.89693491318,35.063342163735,-83.257658370725,2,1,18 +2025-03-11T12:40:40.732330,479392840,65401,210,46.79327098754,34.96612029018,-83.08613607521,2,1,18 +2025-03-11T12:40:40.747955,479392840,65401,210,46.68018306866,34.86426103887,-82.886854579295,2,1,18 +2025-03-11T12:40:40.763580,479392840,65401,210,46.5718071464,34.753167796875,-82.696785150515,2,1,18 +2025-03-11T12:40:40.779205,479392840,65401,210,46.47285521738,34.66057514811,-82.534530542135,2,1,18 +2025-03-11T12:40:40.794830,479392840,65401,210,46.37861528498,34.544885293185,-82.358326465565,2,1,18 +2025-03-11T12:40:40.810455,479392840,65401,210,46.2890873492,34.4245825194,-82.16362589774,2,1,18 +2025-03-11T12:40:40.826080,479392840,65401,210,46.18071142694,34.30886820558,-81.96429556283,2,1,18 +2025-03-11T12:40:40.841705,479392840,65401,210,46.06291151144,34.207000801305,-81.760386102845,2,1,18 +2025-03-11T12:40:40.857330,479392840,65401,210,45.9592475858,34.09129464045,-81.547198999745,2,1,18 +2025-03-11T12:40:40.872955,479392840,65401,210,45.83673567368,33.975555867735,-81.343227138755,2,1,18 +2025-03-11T12:40:40.888580,479392840,65401,210,45.70951176494,33.850566798405,-81.12996905063,2,1,18 +2025-03-11T12:40:40.904205,479392840,65401,210,45.58699985282,33.730206953865,-80.912115100445,2,1,18 +2025-03-11T12:40:40.919830,479392840,65401,210,45.46919993732,33.61909740594,-80.703547377395,2,1,18 +2025-03-11T12:40:40.935455,479392840,65401,210,45.36082401506,33.508004163945,-80.48112966716,2,1,18 +2025-03-11T12:40:40.951080,479392840,65401,210,45.23831210294,33.387644319405,-80.24941216778,2,1,18 +2025-03-11T12:40:40.966705,479392840,65401,210,45.11580019082,33.248800187565,-80.040726423725,2,1,18 +2025-03-11T12:40:40.982330,479392840,65401,210,44.99800027532,33.133069567815,-79.795170696155,2,1,18 +2025-03-11T12:40:40.997955,479392840,65401,210,44.86135237334,33.008064192555,-79.540308398435,2,1,18 +2025-03-11T12:40:41.013580,479392840,65401,210,44.7341284646,32.86921190775,-79.313131141115,2,1,18 +2025-03-11T12:40:41.029205,479392840,65401,210,44.592768566,32.744198379525,-79.08598916078,2,1,18 +2025-03-11T12:40:41.044830,479392840,65401,210,44.46083266064,32.623822229055,-78.849636916325,2,1,18 +2025-03-11T12:40:41.060455,479392840,65401,210,44.32889675528,32.484961791285,-78.58548341348,2,1,18 +2025-03-11T12:40:41.076080,479392840,65401,210,44.19696084992,32.336859209865,-78.339777562895,2,1,18 +2025-03-11T12:40:41.091705,479392840,65401,210,44.06973694118,32.18876478141,-78.09869967638,2,1,18 +2025-03-11T12:40:41.107330,479392840,65401,210,43.92837704258,32.04988803771,-77.84839616072,2,1,18 +2025-03-11T12:40:41.122955,479392840,65401,210,43.78230514736,31.89713992557,-77.58416669486,2,1,18 +2025-03-11T12:40:41.138580,479392840,65401,210,43.64565724538,31.75365026301,-77.31998787101,2,1,18 +2025-03-11T12:40:41.154205,479392840,65401,210,43.49016135692,31.62861227589,-77.02812898475,2,1,18 +2025-03-11T12:40:41.169830,479392840,65401,210,43.35822545156,31.47126755082,-76.75928013884,2,1,18 +2025-03-11T12:40:41.185455,479392840,65401,210,43.20744155972,31.309269142065,-76.48114326278,2,1,18 +2025-03-11T12:40:41.201080,479392840,65401,210,43.0613696645,31.156521029925,-76.212292613855,2,1,18 +2025-03-11T12:40:41.216705,479392840,65401,210,42.91058577266,31.008385836645,-75.95731727312,2,1,18 +2025-03-11T12:40:41.232330,479392840,65401,210,42.7315299011,30.85558065375,-75.67917679103,2,1,18 +2025-03-11T12:40:41.247955,479392840,65401,210,42.57132201602,30.69818701089,-75.40104489296,2,1,18 +2025-03-11T12:40:41.263580,479392840,65401,210,42.41582612756,30.540801520995,-75.09981386057,2,1,18 +2025-03-11T12:40:41.279205,479392840,65401,210,42.2603302391,30.388037102925,-74.78935900205,2,1,18 +2025-03-11T12:40:41.294830,479392840,65401,210,42.11425834388,30.23066791896,-74.4973838978,2,1,18 +2025-03-11T12:40:41.310455,479392840,65401,210,41.94462646556,30.04553153922,-74.20988483159,2,1,18 +2025-03-11T12:40:41.326080,479392840,65401,210,41.7891305771,29.8835249775,-73.9086352592,2,1,18 +2025-03-11T12:40:41.341705,479392840,65401,210,41.62892269202,29.73537347829,-73.61205570887,2,1,18 +2025-03-11T12:40:41.357330,479392840,65401,210,41.4592908137,29.582584601325,-73.29695932427,2,1,18 +2025-03-11T12:40:41.372955,479392840,65401,210,41.294370932,29.4066985182,-72.991019386805,2,1,18 +2025-03-11T12:40:41.388580,479392840,65401,210,41.12002705706,29.240038272795,-72.69434533346,2,1,18 +2025-03-11T12:40:41.404205,479392840,65401,210,40.94568318212,29.059514811915,-72.39299447705,2,1,18 +2025-03-11T12:40:41.419830,479392840,65401,210,40.77133930718,28.88361242286,-72.09166216064,2,1,18 +2025-03-11T12:40:41.435455,479392840,65401,210,40.59699543224,28.69384681833,-71.75330475971,2,1,18 +2025-03-11T12:40:41.451080,479392840,65401,210,40.42736355392,28.50871043859,-71.433457412045,2,1,18 +2025-03-11T12:40:41.466705,479392840,65401,210,40.25301967898,28.33742912136,-71.113658903375,2,1,18 +2025-03-11T12:40:41.482330,479392840,65401,210,40.06453981418,28.156881201585,-70.77531823943,2,1,18 +2025-03-11T12:40:41.497955,479392840,65401,210,39.880771946,27.967099291125,-70.42770491036,2,1,18 +2025-03-11T12:40:41.513580,479392840,65401,210,39.71114006768,27.781962911385,-70.10323637963,2,1,18 +2025-03-11T12:40:41.529205,479392840,65401,210,39.53208419612,27.59218915389,-69.77873574689,2,1,18 +2025-03-11T12:40:41.544830,479392840,65401,210,39.32946834146,27.406995703395,-69.435735016865,2,1,18 +2025-03-11T12:40:41.560455,479392840,65401,210,39.1268524868,27.226423324725,-69.078889277645,2,1,18 +2025-03-11T12:40:41.576080,479392840,65401,210,38.94308461862,27.036641414265,-68.731275948575,2,1,18 +2025-03-11T12:40:41.591705,479392840,65401,210,38.75460475382,26.860714566315,-68.388332641565,2,1,18 +2025-03-11T12:40:41.607330,479392840,65401,210,38.55670089578,26.65242390966,-68.03138244335,2,1,18 +2025-03-11T12:40:41.622955,479392840,65401,210,38.3729330276,26.448778783725,-67.66522876202,2,1,18 +2025-03-11T12:40:41.638580,479392840,65401,210,38.17974116618,26.258980567335,-67.312980687875,2,1,18 +2025-03-11T12:40:41.654205,479392840,65401,210,37.995973298,26.0553354414,-66.94220582348,2,1,18 +2025-03-11T12:40:41.669830,479392840,65401,210,37.79335744334,25.851657703605,-66.55754028587,2,1,18 +2025-03-11T12:40:41.685455,479392840,65401,210,37.57660559882,25.66181872239,-66.21450067283,2,1,18 +2025-03-11T12:40:41.701080,479392840,65401,210,37.3834137374,25.46277836235,-65.85759433562,2,1,18 +2025-03-11T12:40:41.716705,479392840,65401,210,37.18550987936,25.24986663387,-65.482140865145,2,1,18 +2025-03-11T12:40:41.732330,479392840,65401,210,36.9828940247,25.04156782425,-65.115941519795,2,1,18 +2025-03-11T12:40:41.747955,479392840,65401,210,36.77556617342,24.81939764619,-64.74043740731,2,1,18 +2025-03-11T12:40:41.763580,479392840,65401,210,36.55410233228,24.615687296535,-64.35574474568,2,1,18 +2025-03-11T12:40:41.779205,479392840,65401,210,36.346774481,24.40738033395,-63.961811520935,2,1,18 +2025-03-11T12:40:41.794830,479392840,65401,210,36.1347346331,24.1990652184,-63.58173506438,2,1,18 +2025-03-11T12:40:41.810455,479392840,65401,210,35.9462547683,23.990790867675,-63.197071329785,2,1,18 +2025-03-11T12:40:41.826080,479392840,65401,210,35.73892691702,23.777862833265,-62.80311956504,2,1,18 +2025-03-11T12:40:41.841705,479392840,65401,210,35.5221750725,23.564918492925,-62.409154238285,2,1,18 +2025-03-11T12:40:41.857330,479392840,65401,210,35.31484722122,23.370474745815,-62.029140182735,2,1,18 +2025-03-11T12:40:41.872955,479392840,65401,210,35.0980953767,23.1621514773,-61.639814579045,2,1,18 +2025-03-11T12:40:41.888580,479392840,65401,210,34.88134353218,22.93072284966,-61.250396275355,2,1,18 +2025-03-11T12:40:41.904205,479392840,65401,210,34.65987969104,22.70390714088,-60.837883815335,2,1,18 +2025-03-11T12:40:41.919830,479392840,65401,210,34.43370385328,22.486325422785,-60.411538105115,2,1,18 +2025-03-11T12:40:41.935455,479392840,65401,210,34.20752801552,22.25025941739,-60.003602967155,2,1,18 +2025-03-11T12:40:41.951080,479392840,65401,210,33.98135217776,22.02805662747,-59.60958699839,2,1,18 +2025-03-11T12:40:41.966705,479392840,65401,210,33.75988833662,21.805861990515,-59.201714261435,2,1,18 +2025-03-11T12:40:41.982330,479392840,65401,210,33.54784848872,21.58368365949,-58.789233903425,2,1,18 +2025-03-11T12:40:41.997879,479392844,65396,211,33.30282466448,21.356827185885,-58.37668753838,2,1,18 +2025-03-11T12:40:42.013504,479392844,65396,211,33.07664882672,21.10227689319,-57.95019350816,2,1,18 +2025-03-11T12:40:42.029129,479392844,65396,211,32.8363369991,20.870807500725,-57.523771834925,2,1,18 +2025-03-11T12:40:42.044754,479392844,65396,211,32.59131317486,20.64395102712,-57.097361920685,2,1,18 +2025-03-11T12:40:42.060379,479392844,65396,211,32.36984933372,20.40789317469,-56.666327648405,2,1,18 +2025-03-11T12:40:42.076004,479392844,65396,211,32.14367349596,20.181069312945,-56.23532367512,2,1,18 +2025-03-11T12:40:42.091629,479392844,65396,211,31.91278566158,19.954237298235,-55.81355528696,2,1,18 +2025-03-11T12:40:42.107254,479392844,65396,211,31.67247383396,19.70428361847,-55.377817087595,2,1,18 +2025-03-11T12:40:42.122879,479392844,65396,211,31.42745000972,19.458942857565,-54.92822709803,2,1,18 +2025-03-11T12:40:42.138504,479392844,65396,211,31.20598616858,19.21826393331,-54.492553102685,2,1,18 +2025-03-11T12:40:42.154129,479392844,65396,211,30.96567434096,18.98217346902,-54.061491706385,2,1,18 +2025-03-11T12:40:42.169754,479392844,65396,211,30.72065051672,18.72296949264,-53.62108846295,2,1,18 +2025-03-11T12:40:42.185379,479392844,65396,211,30.47562669248,18.48224980356,-53.180759379515,2,1,18 +2025-03-11T12:40:42.201004,479392844,65396,211,30.23060286824,18.255393329955,-52.74048591608,2,1,18 +2025-03-11T12:40:42.216629,479392844,65396,211,29.985579044,18.033157928175,-52.29560980958,2,1,18 +2025-03-11T12:40:42.232254,479392844,65396,211,29.73584322314,17.787809014305,-51.85525540514,2,1,18 +2025-03-11T12:40:42.247879,479392844,65396,211,29.4908193989,17.5239839661,-51.433318353965,2,1,18 +2025-03-11T12:40:42.263504,479392844,65396,211,29.25050757128,17.274030286335,-50.974474239275,2,1,18 +2025-03-11T12:40:42.279129,479392844,65396,211,28.99134775718,17.02404399471,-50.52022418363,2,1,18 +2025-03-11T12:40:42.294754,479392844,65396,211,28.74161193632,16.774074009015,-50.07060887306,2,1,18 +2025-03-11T12:40:42.310379,479392844,65396,211,28.50601210532,16.51026526674,-49.611715919375,2,1,18 +2025-03-11T12:40:42.326004,479392844,65396,211,28.25627628446,16.25567420922,-49.152839702675,2,1,18 +2025-03-11T12:40:42.341629,479392844,65396,211,28.01125246022,15.99647023284,-48.67546699472,2,1,18 +2025-03-11T12:40:42.357254,479392844,65396,211,27.76151663936,15.76036346262,-48.202801388825,2,1,18 +2025-03-11T12:40:42.372879,479392844,65396,211,27.49293283202,15.51498193689,-47.743935128105,2,1,18 +2025-03-11T12:40:42.388504,479392844,65396,211,27.23377301792,15.246511357965,-47.284989729395,2,1,18 +2025-03-11T12:40:42.404129,479392844,65396,211,26.97932520044,14.996533219305,-46.812261722495,2,1,18 +2025-03-11T12:40:42.419754,479392844,65396,211,26.71545338972,14.73267555924,-46.339464533585,2,1,18 +2025-03-11T12:40:42.435379,479392844,65396,211,26.44215758576,14.468801593245,-45.866653782665,2,1,18 +2025-03-11T12:40:42.451004,479392844,65396,211,26.19713376152,14.200355473215,-45.384622811645,2,1,18 +2025-03-11T12:40:42.466629,479392844,65396,211,25.93797394742,13.94112703794,-44.91185094374,2,1,18 +2025-03-11T12:40:42.482254,479392844,65396,211,25.66939014008,13.691124440385,-44.429860227695,2,1,18 +2025-03-11T12:40:42.497879,479392844,65396,211,25.40551832936,13.404161421195,-43.95234915572,2,1,18 +2025-03-11T12:40:42.513504,479392844,65396,211,25.14635851526,13.131069770445,-43.47490048475,2,1,18 +2025-03-11T12:40:42.529129,479392844,65396,211,24.87777470792,12.876446101065,-42.983648862575,2,1,18 +2025-03-11T12:40:42.544754,479392844,65396,211,24.60447890396,12.61257213507,-42.501595745525,2,1,18 +2025-03-11T12:40:42.560379,479392844,65396,211,24.3311831,12.339456025425,-42.01488436541,2,1,18 +2025-03-11T12:40:42.576004,479392844,65396,211,24.06731128928,12.07559836536,-41.537465993435,2,1,18 +2025-03-11T12:40:42.591629,479392844,65396,211,23.80343947856,11.80711963347,-41.055407898395,2,1,18 +2025-03-11T12:40:42.607254,479392844,65396,211,23.53956766784,11.52939875793,-40.55944917416,2,1,18 +2025-03-11T12:40:42.622879,479392844,65396,211,23.2709838605,11.25629080125,-40.058881025855,2,1,18 +2025-03-11T12:40:42.638504,479392844,65396,211,22.99297605992,10.997029754115,-39.54911256941,2,1,18 +2025-03-11T12:40:42.654129,479392844,65396,211,22.7291042492,10.719308878575,-39.04853266211,2,1,18 +2025-03-11T12:40:42.669754,479392844,65396,211,22.4699444351,10.45083829965,-38.54337543275,2,1,18 +2025-03-11T12:40:42.685379,479392844,65396,211,22.19664863114,10.17310111818,-38.04278196344,2,1,18 +2025-03-11T12:40:42.701004,479392844,65396,211,21.9045048407,9.890710253025,-37.546764013175,2,1,18 +2025-03-11T12:40:42.716629,479392844,65396,211,21.61707304688,9.61294861266,-37.04615020085,2,1,18 +2025-03-11T12:40:42.732254,479392844,65396,211,21.34848923954,9.335219584155,-36.53169996335,2,1,18 +2025-03-11T12:40:42.747879,479392844,65396,211,21.06576944234,9.048223953105,-36.026434668965,2,1,18 +2025-03-11T12:40:42.763504,479392844,65396,211,20.78304964514,8.77509153753,-35.525846177645,2,1,18 +2025-03-11T12:40:42.779129,479392844,65396,211,20.51917783442,8.501991733815,-35.02990599341,2,1,18 +2025-03-11T12:40:42.794754,479392844,65396,211,20.26001802032,8.22427901124,-34.538575233245,2,1,18 +2025-03-11T12:40:42.810379,479392844,65396,211,19.9725862265,7.94189629905,-34.014836965595,2,1,18 +2025-03-11T12:40:42.826004,479392844,65396,211,19.69457842592,7.664150964615,-33.49575198302,2,1,18 +2025-03-11T12:40:42.841629,479392844,65396,211,19.39772263886,7.37713087467,-32.99970871175,2,1,18 +2025-03-11T12:40:42.857254,479392844,65396,211,19.11029084504,7.090127090655,-32.480573087165,2,1,18 +2025-03-11T12:40:42.872879,479392844,65396,211,18.82285905122,6.798502234815,-31.95217655645,2,1,18 +2025-03-11T12:40:42.888504,479392844,65396,211,18.54485125064,6.52075690038,-31.42847039081,2,1,18 +2025-03-11T12:40:42.904129,479392844,65396,211,18.2762674433,6.2476489437,-30.91403869331,2,1,18 +2025-03-11T12:40:42.919754,479392844,65396,211,17.99825964272,5.988387896565,-30.3996490538,2,1,18 +2025-03-11T12:40:42.935379,479392844,65396,211,17.72025184214,5.69215827483,-29.87586872816,2,1,18 +2025-03-11T12:40:42.951004,479392844,65396,211,17.4281080517,5.3774199069,-29.35661508257,2,1,18 +2025-03-11T12:40:42.966629,479392844,65396,211,17.1453882545,5.085803204025,-28.83746769899,2,1,18 +2025-03-11T12:40:42.982254,479392844,65396,211,16.85795646068,4.79879942001,-28.299847342145,2,1,18 +2025-03-11T12:40:42.997879,479392844,65396,211,16.56110067362,4.521021473715,-27.77149286942,2,1,18 +2025-03-11T12:40:43.013504,479392844,65396,211,16.25953288994,4.23861430263,-27.24311307569,2,1,18 +2025-03-11T12:40:43.029129,479392844,65396,211,15.98152508936,3.94700575272,-26.71935129005,2,1,18 +2025-03-11T12:40:43.044754,479392844,65396,211,15.6846693023,3.65536459095,-26.200183563455,2,1,18 +2025-03-11T12:40:43.060379,479392844,65396,211,15.39252551186,3.372973725795,-25.6764385148,2,1,18 +2025-03-11T12:40:43.076004,479392844,65396,211,15.10980571466,3.08135702292,-25.134185215895,2,1,18 +2025-03-11T12:40:43.091629,479392844,65396,211,14.82237392084,2.785111095255,-24.591906595985,2,1,18 +2025-03-11T12:40:43.107254,479392844,65396,211,14.5302301304,2.498099158275,-24.06814300733,2,1,18 +2025-03-11T12:40:43.122879,479392844,65396,211,14.23808633996,2.201845077645,-23.544342338675,2,1,18 +2025-03-11T12:40:43.138504,479392844,65396,211,13.964790536,1.9102446807,-23.015966150975,2,1,18 +2025-03-11T12:40:43.154129,479392844,65396,211,13.6820707388,1.62324904965,-22.4829737582,2,1,18 +2025-03-11T12:40:43.169754,479392844,65396,211,13.38992694836,1.322373897195,-21.931427451155,2,1,18 +2025-03-11T12:40:43.185379,479392844,65396,211,13.0930711613,1.021490591775,-21.398359095365,2,1,18 +2025-03-11T12:40:43.201004,479392844,65396,211,12.80563936748,0.729865735934999,-20.865341381585,2,1,18 +2025-03-11T12:40:43.216629,479392844,65396,211,12.51349557704,0.42899058348,-20.336900989865,2,1,18 +2025-03-11T12:40:43.232254,479392844,65396,211,12.20721579674,0.132712043955001,-19.822322344325,2,1,18 +2025-03-11T12:40:43.247879,479392844,65396,211,11.91978400292,-0.168154955535,-19.307752282805,2,1,18 +2025-03-11T12:40:43.263504,479392844,65396,211,11.6323522091,-0.459779811374999,-18.747007470635,2,1,18 +2025-03-11T12:40:43.279129,479392844,65396,211,11.33549642204,-0.75604204497,-18.19085173952,2,1,18 +2025-03-11T12:40:43.294754,479392844,65396,211,11.03864063498,-1.04768320674,-17.643956914535,2,1,18 +2025-03-11T12:40:43.310379,479392844,65396,211,10.74178484792,-1.35780865581,-17.120093844875,2,1,18 +2025-03-11T12:40:43.326004,479392844,65396,211,10.44492906086,-1.65869196123,-16.587025489085,2,1,18 +2025-03-11T12:40:43.341629,479392844,65396,211,10.13393728394,-1.941115438245,-16.030905034955,2,1,18 +2025-03-11T12:40:43.357254,479392844,65396,211,9.83236950026,-2.23276475298,-15.47013987977,2,1,18 +2025-03-11T12:40:43.372879,479392844,65396,211,9.52608971996,-2.538285436155,-14.932418238905,2,1,18 +2025-03-11T12:40:43.388504,479392844,65396,211,9.2292339329,-2.85303195705,-14.40391544618,2,1,18 +2025-03-11T12:40:43.404129,479392844,65396,211,8.92766614922,-3.15854448726,-13.85695822019,2,1,18 +2025-03-11T12:40:43.419754,479392844,65396,211,8.62609836554,-3.450193801995,-13.32854134646,2,1,18 +2025-03-11T12:40:43.435379,479392844,65396,211,8.31981858524,-3.751093413345,-12.781595879465,2,1,18 +2025-03-11T12:40:43.451004,479392844,65396,211,8.01825080156,-4.04274272808,-12.23007309041,2,1,18 +2025-03-11T12:40:43.466629,479392844,65396,211,7.72610701112,-4.33899680871,-11.6739241403,2,1,18 +2025-03-11T12:40:43.482254,479392844,65396,211,7.4386752173,-4.63062166455,-11.13166406039,2,1,18 +2025-03-11T12:40:43.497879,479392844,65396,211,7.1559554201,-4.92685943925,-10.57552867229,2,1,18 +2025-03-11T12:40:43.513504,479392844,65396,211,6.86852362628,-5.22772643874,-10.03323151238,2,1,18 +2025-03-11T12:40:43.529129,479392844,65396,211,6.57166783922,-5.523988672335,-9.486318147395,2,1,18 +2025-03-11T12:40:43.544754,479392844,65396,211,6.27010005554,-5.82488013072,-8.930137095275,2,1,18 +2025-03-11T12:40:43.560379,479392844,65396,211,5.96382027524,-6.130400813895,-8.378551905215,2,1,18 +2025-03-11T12:40:43.576004,479392844,65396,211,5.6716764848,-6.445139181825,-7.831571161235,2,1,18 +2025-03-11T12:40:43.591629,479392844,65396,211,5.3653967045,-6.750659865,-7.289228337305,2,1,18 +2025-03-11T12:40:43.607254,479392844,65396,211,5.04026893772,-7.03310780091,-6.74232990629,2,1,18 +2025-03-11T12:40:43.622879,479392844,65396,211,4.7292771608,-7.32015234975,-6.20467564442,2,1,18 +2025-03-11T12:40:43.638504,479392844,65396,211,4.43713337036,-7.60716428673,-5.643942591245,2,1,18 +2025-03-11T12:40:43.654129,479392844,65396,211,4.14970157654,-7.91727342987,-5.092365985205,2,1,18 +2025-03-11T12:40:43.669754,479392844,65396,211,3.85284578948,-8.22739887894,-4.55463936635,2,1,18 +2025-03-11T12:40:43.685379,479392844,65396,211,3.5512780058,-8.528290337325,-4.030806595685,2,1,18 +2025-03-11T12:40:43.701004,479392844,65396,211,3.25442221874,-8.83379471457,-3.50234088296,2,1,18 +2025-03-11T12:40:43.716629,479392844,65396,211,2.94814243844,-9.148557541395,-2.94147624677,2,1,18 +2025-03-11T12:40:43.732254,479392844,65396,211,2.65128665138,-9.449440846815,-2.385301975655,2,1,18 +2025-03-11T12:40:43.747879,479392844,65396,211,2.35914286094,-9.736452783795,-1.81532655635,2,1,18 +2025-03-11T12:40:43.763504,479392844,65396,211,2.05757507726,-10.032723170355,-1.254542861165,2,1,18 +2025-03-11T12:40:43.779129,479392844,65396,211,1.7607192902,-10.3382275476,-0.71683478231,2,1,18 +2025-03-11T12:40:43.794754,479392844,65396,211,1.4544395099,-10.63912715895,-0.188374047575,2,1,18 +2025-03-11T12:40:43.810379,479392844,65396,211,1.15758372284,-10.935389392545,0.34929695128,2,1,18 +2025-03-11T12:40:43.826004,479392844,65396,211,0.8654399324,-11.240885616825,0.882377066065,2,1,18 +2025-03-11T12:40:43.841629,479392844,65396,211,0.58743213182,-11.54635738221,1.42930038703,2,1,18 +2025-03-11T12:40:43.857254,479392844,65396,211,0.29528834138,-11.84261146284,1.95772223875,2,1,18 +2025-03-11T12:40:43.872879,479392844,65396,211,-0.00156744568000011,-12.138873696435,2.513877969865,2,1,18 +2025-03-11T12:40:43.888504,479392844,65396,211,-0.30784722598,-12.439773307785,3.07006580299,2,1,18 +2025-03-11T12:40:43.904129,479392844,65396,211,-0.60470301304,-12.74527768503,3.607773881845,2,1,18 +2025-03-11T12:40:43.919754,479392844,65396,211,-0.9251187832,-13.0508228271,4.15013704879,2,1,18 +2025-03-11T12:40:43.935379,479392844,65396,211,-1.22668656688,-13.33785107001,4.701641297845,2,1,18 +2025-03-11T12:40:43.951004,479392844,65396,211,-1.52825435056,-13.63412145657,5.2531826269,2,1,18 +2025-03-11T12:40:43.966629,479392844,65396,211,-1.83924612748,-13.944271364535,5.79092958877,2,1,18 +2025-03-11T12:40:43.982254,479392844,65396,211,-2.13138991792,-14.240525445165,6.333214989685,2,1,18 +2025-03-11T12:40:43.997879,479392844,65396,211,-2.39997372526,-14.52749661732,6.88929295477,2,1,18 +2025-03-11T12:40:44.013504,479392844,65396,211,-2.68269352246,-14.82373439202,7.431564793675,2,1,18 +2025-03-11T12:40:44.029129,479392844,65396,211,-2.97954930952,-15.10613341014,7.96918017253,2,1,18 +2025-03-11T12:40:44.044754,479392844,65396,211,-3.27169309996,-15.39314534712,8.502186127315,2,1,18 +2025-03-11T12:40:44.060379,479392844,65396,211,-3.55441289716,-15.694004193645,9.002885858635,2,1,18 +2025-03-11T12:40:44.076004,479392844,65396,211,-3.85126868422,-16.00875071454,9.54987338362,2,1,18 +2025-03-11T12:40:44.091629,479392844,65396,211,-4.14812447128,-16.31887616361,10.1107059178,2,1,18 +2025-03-11T12:40:44.107254,479392844,65396,211,-4.44498025834,-16.61051732538,10.648358376655,2,1,18 +2025-03-11T12:40:44.122879,479392844,65396,211,-4.7418360454,-16.92064277445,11.199948544705,2,1,18 +2025-03-11T12:40:44.138504,479392844,65396,211,-5.0481158257,-17.216921313975,11.75611783783,2,1,18 +2025-03-11T12:40:44.154129,479392844,65396,211,-5.35910760262,-17.49934479099,12.298374742765,2,1,18 +2025-03-11T12:40:44.169754,479392844,65396,211,-5.64182739982,-17.78634042204,12.82212476941,2,1,18 +2025-03-11T12:40:44.185379,479392844,65396,211,-5.92454719702,-18.08257819674,13.35053305912,2,1,18 +2025-03-11T12:40:44.201004,479392844,65396,211,-6.21197899084,-18.38344519623,13.897451402095,2,1,18 +2025-03-11T12:40:44.216629,479392844,65396,211,-6.50412278128,-18.665836061385,14.435059999945,2,1,18 +2025-03-11T12:40:44.232254,479392844,65396,211,-6.80097856834,-18.94361400768,14.958793289605,2,1,18 +2025-03-11T12:40:44.247879,479392844,65396,211,-7.0978343554,-19.239876241275,15.4779795562,2,1,18 +2025-03-11T12:40:44.263504,479392844,65396,211,-7.38997814584,-19.545372465555,16.00643848792,2,1,18 +2025-03-11T12:40:44.279129,479392844,65396,211,-7.68212193628,-19.841626546185,16.54410270577,2,1,18 +2025-03-11T12:40:44.294754,479392844,65396,211,-7.95070574362,-20.123976646515,17.0678138494,2,1,18 +2025-03-11T12:40:44.310379,479392844,65396,211,-8.24756153068,-20.41099673646,17.59158421906,2,1,18 +2025-03-11T12:40:44.326004,479392844,65396,211,-8.54441731774,-20.69339575458,18.13382078098,2,1,18 +2025-03-11T12:40:44.341629,479392844,65396,211,-8.82713711494,-20.98963352928,18.66222907069,2,1,18 +2025-03-11T12:40:44.357254,479392844,65396,211,-9.10985691214,-21.27662916033,19.176736731205,2,1,18 +2025-03-11T12:40:44.372879,479392844,65396,211,-9.40200070258,-21.56364109731,19.70050031986,2,1,18 +2025-03-11T12:40:44.388504,479392844,65396,211,-9.6894324964,-21.850644881325,20.24274185977,2,1,18 +2025-03-11T12:40:44.404129,479392844,65396,211,-9.98628828346,-22.13766497127,20.771133412495,2,1,18 +2025-03-11T12:40:44.419754,479392844,65396,211,-10.27372007728,-22.42004768346,21.28100813095,2,1,18 +2025-03-11T12:40:44.435379,479392844,65396,211,-10.55643987448,-22.720906529985,21.795571411465,2,1,18 +2025-03-11T12:40:44.451004,479392844,65396,211,-10.83915967168,-23.007902161035,22.323942621175,2,1,18 +2025-03-11T12:40:44.466629,479392844,65396,211,-11.11245547564,-23.267155055205,22.83832547968,2,1,18 +2025-03-11T12:40:44.482254,479392844,65396,211,-11.40459926608,-23.544924848535,23.33894607301,2,1,18 +2025-03-11T12:40:44.497879,479392844,65396,211,-11.6920310599,-23.836549704375,23.839615505335,2,1,18 +2025-03-11T12:40:44.513504,479392844,65396,211,-11.97003886048,-24.13277932611,24.35877464791,2,1,18 +2025-03-11T12:40:44.529129,479392844,65396,211,-12.23862266782,-24.428992641915,24.87329904541,2,1,18 +2025-03-11T12:40:44.544754,479392844,65396,211,-12.52605446164,-24.69751213863,25.401602876125,2,1,18 +2025-03-11T12:40:44.560379,479392844,65396,211,-12.7993502656,-24.96600717645,25.9067804485,2,1,18 +2025-03-11T12:40:44.576004,479392844,65396,211,-13.0820700628,-25.248381735675,26.41664838595,2,1,18 +2025-03-11T12:40:44.591629,479392844,65396,211,-13.37421385324,-25.53077260083,26.931151068475,2,1,18 +2025-03-11T12:40:44.607254,479392844,65396,211,-13.66164564706,-25.80391316937,27.42250397467,2,1,18 +2025-03-11T12:40:44.622879,479392844,65396,211,-13.93494145102,-26.067787135365,27.93228419011,2,1,18 +2025-03-11T12:40:44.638504,479392844,65396,211,-14.20352525836,-26.35475830752,28.43752914148,2,1,18 +2025-03-11T12:40:44.654129,479392844,65396,211,-14.46739706908,-26.62323703941,28.91034487039,2,1,18 +2025-03-11T12:40:44.669754,479392844,65396,211,-14.73598087642,-26.900966067915,29.392446826435,2,1,18 +2025-03-11T12:40:44.685379,479392844,65396,211,-14.99985268714,-27.17406587163,29.902250559865,2,1,18 +2025-03-11T12:40:44.701004,479392844,65396,211,-15.26843649448,-27.44717382831,30.407439891235,2,1,18 +2025-03-11T12:40:44.716629,479392844,65396,211,-15.55115629168,-27.72492731571,30.90342573949,2,1,18 +2025-03-11T12:40:44.732254,479392844,65396,211,-15.82445209564,-28.007285569005,31.399416565735,2,1,18 +2025-03-11T12:40:44.747879,479392844,65396,211,-16.08832390636,-28.27114322907,31.899940853035,2,1,18 +2025-03-11T12:40:44.763504,479392844,65396,211,-16.3569077137,-28.539630113925,32.39124809521,2,1,18 +2025-03-11T12:40:44.779129,479392844,65396,211,-16.6160675278,-28.794237477375,32.891728521505,2,1,18 +2025-03-11T12:40:44.794754,479392844,65396,211,-16.87993933852,-29.07657942474,33.383084602675,2,1,18 +2025-03-11T12:40:44.810379,479392844,65396,211,-17.1579471391,-29.3404615437,33.842038585405,2,1,18 +2025-03-11T12:40:44.826004,479392844,65396,211,-17.4406669363,-29.60897288745,34.324123804465,2,1,18 +2025-03-11T12:40:44.841629,479392844,65396,211,-17.70925074364,-29.87283870048,34.81541250664,2,1,18 +2025-03-11T12:40:44.857254,479392844,65396,211,-17.96369856112,-30.136680054615,35.31592323193,2,1,18 +2025-03-11T12:40:44.872879,479392844,65396,211,-18.21343438198,-30.39589218396,35.797923903955,2,1,18 +2025-03-11T12:40:44.888504,479392844,65396,211,-18.4773061927,-30.6551287722,36.252217820605,2,1,18 +2025-03-11T12:40:44.904129,479392844,65396,211,-18.75531399328,-30.91901089116,36.738898901725,2,1,18 +2025-03-11T12:40:44.919754,479392844,65396,211,-19.019185804,-31.16900533575,37.193155738375,2,1,18 +2025-03-11T12:40:44.935379,479392844,65396,211,-19.26420962824,-31.442072527605,37.656720517135,2,1,18 +2025-03-11T12:40:44.951004,479392844,65396,211,-19.52336944234,-31.705922034705,38.13875329117,2,1,18 +2025-03-11T12:40:44.966629,479392844,65396,211,-19.77781725982,-31.965142317015,38.6207607442,2,1,18 +2025-03-11T12:40:44.982254,479392844,65396,211,-20.0322650773,-32.224362599325,39.088904648035,2,1,18 +2025-03-11T12:40:44.997879,479392844,65396,211,-20.28671289478,-32.474340737985,39.54776910574,2,1,18 +2025-03-11T12:40:45.013504,479392844,65396,211,-20.54587270888,-32.728948101435,40.002037701385,2,1,18 +2025-03-11T12:40:45.029129,479392844,65396,211,-20.80503252298,-32.983555464885,40.4470639309,2,1,18 +2025-03-11T12:40:45.044754,479392844,65396,211,-21.0453443506,-33.23350914465,40.910529228655,2,1,18 +2025-03-11T12:40:45.060379,479392844,65396,211,-21.29036817484,-33.48347097738,41.374001307415,2,1,18 +2025-03-11T12:40:45.076004,479392844,65396,211,-21.55423998556,-33.719602206495,41.837444890195,2,1,18 +2025-03-11T12:40:45.091629,479392844,65396,211,-21.7992638098,-33.969564039225,42.300916968955,2,1,18 +2025-03-11T12:40:45.107254,479392844,65396,211,-22.0348636408,-34.22413063785,42.75053047651,2,1,18 +2025-03-11T12:40:45.122879,479392844,65396,211,-22.27517546842,-34.483326461265,43.19092693894,2,1,18 +2025-03-11T12:40:45.138504,479392844,65396,211,-22.52491128928,-34.75178073426,43.63137404338,2,1,18 +2025-03-11T12:40:45.154129,479392844,65396,211,-22.77464711014,-34.983266432655,44.067051644755,2,1,18 +2025-03-11T12:40:45.169754,479392844,65396,211,-23.01495893776,-35.21473582512,44.51195805025,2,1,18 +2025-03-11T12:40:45.185379,479392844,65396,211,-23.259982762,-35.4554555142,44.952287133685,2,1,18 +2025-03-11T12:40:45.201004,479392844,65396,211,-23.50029458962,-35.70078812214,45.401870342245,2,1,18 +2025-03-11T12:40:45.216629,479392844,65396,211,-23.731182424,-35.941483352325,45.851421448795,2,1,18 +2025-03-11T12:40:45.232254,479392844,65396,211,-23.95264626514,-36.18216227658,46.28709544414,2,1,18 +2025-03-11T12:40:45.247879,479392844,65396,211,-24.18824609614,-36.42286565973,46.718168599435,2,1,18 +2025-03-11T12:40:45.263504,479392844,65396,211,-24.42384592714,-36.658947971055,47.144602031665,2,1,18 +2025-03-11T12:40:45.279129,479392844,65396,211,-24.66886975138,-36.899667660135,47.571067565905,2,1,18 +2025-03-11T12:40:45.294754,479392844,65396,211,-24.89975758576,-37.135741818495,47.99749421713,2,1,18 +2025-03-11T12:40:45.310379,479392844,65396,211,-25.12593342352,-37.367186752065,48.41465318122,2,1,18 +2025-03-11T12:40:45.326004,479392844,65396,211,-25.3568212579,-37.612503054075,48.841116912445,2,1,18 +2025-03-11T12:40:45.341629,479392844,65396,211,-25.58299709566,-37.843947987645,49.2628970596,2,1,18 +2025-03-11T12:40:45.357254,479392844,65396,211,-25.80917293342,-38.066150777565,49.68001894369,2,1,18 +2025-03-11T12:40:45.372879,479392844,65396,211,-26.03534877118,-38.29297463931,50.092538184715,2,1,18 +2025-03-11T12:40:45.388504,479392844,65396,211,-26.26623660556,-38.524427725845,50.49121919755,2,1,18 +2025-03-11T12:40:45.404129,479392844,65396,211,-26.5112604298,-38.75128419945,50.894523196465,2,1,18 +2025-03-11T12:40:45.419754,479392844,65396,211,-26.73743626756,-38.97348698937,51.302402714425,2,1,18 +2025-03-11T12:40:45.435379,479392844,65396,211,-26.9589001087,-39.18181841085,51.71946219751,2,1,18 +2025-03-11T12:40:45.451004,479392844,65396,211,-27.18507594646,-39.38553691347,52.12726755547,2,1,18 +2025-03-11T12:40:45.466629,479392844,65396,211,-27.40182779098,-39.603102325635,52.54435733755,2,1,18 +2025-03-11T12:40:45.482254,479392844,65396,211,-27.60915564226,-39.816030360045,52.9244455531,2,1,18 +2025-03-11T12:40:45.497879,479392844,65396,211,-27.82590748678,-40.04283791586,53.299981767595,2,1,18 +2025-03-11T12:40:45.513504,479392844,65396,211,-28.02381134482,-40.251128572515,53.689280247265,2,1,18 +2025-03-11T12:40:45.529129,479392844,65396,211,-28.23585119272,-40.468685831715,54.092499699145,2,1,18 +2025-03-11T12:40:45.544754,479392844,65396,211,-28.45260303724,-40.69549338753,54.46803591364,2,1,18 +2025-03-11T12:40:45.560379,479392844,65396,211,-28.66935488176,-40.894574512395,54.86656680346,2,1,18 +2025-03-11T12:40:45.576004,479392844,65396,211,-28.89553071952,-41.11215623049,55.251321866095,2,1,18 +2025-03-11T12:40:45.591629,479392844,65396,211,-29.10757056742,-41.31122920239,55.635982425715,2,1,18 +2025-03-11T12:40:45.607254,479392844,65396,211,-29.3148984187,-41.519536164975,56.02067328433,2,1,18 +2025-03-11T12:40:45.622879,479392844,65396,211,-29.51280227674,-41.73706896528,56.377660562545,2,1,18 +2025-03-11T12:40:45.638504,479392844,65396,211,-29.70128214154,-41.926859028705,56.74376540488,2,1,18 +2025-03-11T12:40:45.654129,479392844,65396,211,-29.9038979962,-42.116673551025,57.105269407165,2,1,18 +2025-03-11T12:40:45.669754,479392844,65396,211,-30.12064984072,-42.320375747715,57.47147055553,2,1,18 +2025-03-11T12:40:45.685379,479392844,65396,211,-30.32326569538,-42.53329562916,57.83768844088,2,1,18 +2025-03-11T12:40:45.701004,479392844,65396,211,-30.52116955342,-42.732344142165,58.19922274216,2,1,18 +2025-03-11T12:40:45.716629,479392844,65396,211,-30.7284974047,-42.945272176575,58.55158385932,2,1,18 +2025-03-11T12:40:45.732254,479392844,65396,211,-30.92168926612,-43.125828249315,58.8991736704,2,1,18 +2025-03-11T12:40:45.747879,479392844,65396,211,-31.11488112754,-43.32024753753,59.251440284545,2,1,18 +2025-03-11T12:40:45.763504,479392844,65396,211,-31.30807298896,-43.51928789757,59.599104255625,2,1,18 +2025-03-11T12:40:45.779129,479392844,65396,211,-31.49184085714,-43.704448736205,59.918971946305,2,1,18 +2025-03-11T12:40:45.794754,479392844,65396,211,-31.67560872532,-43.894230646665,60.266585275375,2,1,18 +2025-03-11T12:40:45.810379,479392844,65396,211,-31.84052860702,-44.083979945265,60.614171480425,2,1,18 +2025-03-11T12:40:45.826004,479392844,65396,211,-32.01016048534,-44.269116325005,60.96174592648,2,1,18 +2025-03-11T12:40:45.841629,479392844,65396,211,-32.21748833662,-44.44969685664,61.30473489751,2,1,18 +2025-03-11T12:40:45.857254,479392844,65396,211,-32.41068019804,-44.62101078573,61.638424079395,2,1,18 +2025-03-11T12:40:45.872879,479392844,65396,211,-32.59444806622,-44.787687337065,61.985944708465,2,1,18 +2025-03-11T12:40:45.888504,479392844,65396,211,-32.76879194116,-44.968210797945,62.315022663265,2,1,18 +2025-03-11T12:40:45.904129,479392844,65396,211,-32.9431358161,-45.17183961795,62.63032976887,2,1,18 +2025-03-11T12:40:45.919754,479392844,65396,211,-33.12219168766,-45.343129088145,62.94551387548,2,1,18 +2025-03-11T12:40:45.935379,479392844,65396,211,-33.28711156936,-45.50977302762,63.279143831335,2,1,18 +2025-03-11T12:40:45.951004,479392844,65396,211,-33.45674344768,-45.699530479185,63.599009719,2,1,18 +2025-03-11T12:40:45.966629,479392844,65396,211,-33.63579931924,-45.856956733905,63.909517022545,2,1,18 +2025-03-11T12:40:45.982254,479392844,65396,211,-33.81014319418,-46.03285912296,64.20622815589,2,1,18 +2025-03-11T12:40:45.997817,479392848,65392,212,-33.97035107926,-46.20873705312,64.50291894622,2,1,18 +2025-03-11T12:40:46.013442,479392848,65392,212,-34.12584696772,-46.366122543015,64.80414997861,2,1,18 +2025-03-11T12:40:46.029067,479392848,65392,212,-34.29547884604,-46.542016779105,65.114717880145,2,1,18 +2025-03-11T12:40:46.044692,479392848,65392,212,-34.46039872774,-46.69941857493,65.397477742285,2,1,18 +2025-03-11T12:40:46.060317,479392848,65392,212,-34.63003060606,-46.85682852372,65.675623202365,2,1,18 +2025-03-11T12:40:46.075942,479392848,65392,212,-34.79966248438,-47.02348061616,65.95842692551,2,1,18 +2025-03-11T12:40:46.091567,479392848,65392,212,-34.96458236608,-47.180882411985,66.25967151991,2,1,18 +2025-03-11T12:40:46.107192,479392848,65392,212,-35.12007825454,-47.315162542755,66.55156748617,2,1,18 +2025-03-11T12:40:46.122817,479392848,65392,212,-35.28028613962,-47.46793511379,66.82968084424,2,1,18 +2025-03-11T12:40:46.138442,479392848,65392,212,-35.42164603822,-47.63453828844,67.103201515225,2,1,18 +2025-03-11T12:40:46.154067,479392848,65392,212,-35.56771793344,-47.801149616055,67.39059251641,2,1,18 +2025-03-11T12:40:46.169692,479392848,65392,212,-35.73263781514,-47.953930340055,67.67333383855,2,1,18 +2025-03-11T12:40:46.185317,479392848,65392,212,-35.89284570022,-48.08821862379,67.955994219685,2,1,18 +2025-03-11T12:40:46.200942,479392848,65392,212,-36.04362959206,-48.21786952977,68.206274217355,2,1,18 +2025-03-11T12:40:46.216567,479392848,65392,212,-36.17556549742,-48.370593183015,68.46124097407,2,1,18 +2025-03-11T12:40:46.232192,479392848,65392,212,-36.3122133994,-48.5187039174,68.730059520985,2,1,18 +2025-03-11T12:40:46.247817,479392848,65392,212,-36.453573298,-48.6575806611,68.96649948745,2,1,18 +2025-03-11T12:40:46.263442,479392848,65392,212,-36.58550920336,-48.80568324252,69.212205338035,2,1,18 +2025-03-11T12:40:46.279067,479392848,65392,212,-36.72215710534,-48.94917290508,69.47176297882,2,1,18 +2025-03-11T12:40:46.294692,479392848,65392,212,-36.8540930107,-49.0787911992,69.74974295086,2,1,18 +2025-03-11T12:40:46.310317,479392848,65392,212,-37.00016490592,-49.19457073674,69.999960547525,2,1,18 +2025-03-11T12:40:46.325942,479392848,65392,212,-37.14623680114,-49.31959241793,70.23173049193,2,1,18 +2025-03-11T12:40:46.341567,479392848,65392,212,-37.26403671664,-49.44456518133,70.435732651915,2,1,18 +2025-03-11T12:40:46.357192,479392848,65392,212,-37.39126062538,-49.58803853796,70.681413181495,2,1,18 +2025-03-11T12:40:46.372817,479392848,65392,212,-37.52319653074,-49.722277903905,70.91782104595,2,1,18 +2025-03-11T12:40:46.388442,479392848,65392,212,-37.64570844286,-49.84725882027,71.154178268395,2,1,18 +2025-03-11T12:40:46.404067,479392848,65392,212,-37.79178033808,-49.967659429635,71.390550855865,2,1,18 +2025-03-11T12:40:46.419692,479392848,65392,212,-37.90958025358,-50.092632193035,71.599174198915,2,1,18 +2025-03-11T12:40:46.435317,479392848,65392,212,-38.01324417922,-50.20833835389,71.80774011895,2,1,18 +2025-03-11T12:40:46.450942,479392848,65392,212,-38.1263320981,-50.3286818925,72.01171695793,2,1,18 +2025-03-11T12:40:46.466567,479392848,65392,212,-38.22528402712,-50.43513775674,72.22948138309,2,1,18 +2025-03-11T12:40:46.482192,479392848,65392,212,-38.338371946,-50.55548129535,72.438079405135,2,1,18 +2025-03-11T12:40:46.497817,479392848,65392,212,-38.4561718615,-50.666590843275,72.64202594512,2,1,18 +2025-03-11T12:40:46.513442,479392848,65392,212,-38.57868377362,-50.77308747234,72.850581909175,2,1,18 +2025-03-11T12:40:46.529067,479392848,65392,212,-38.6917716925,-50.888809939125,73.045297842025,2,1,18 +2025-03-11T12:40:46.544692,479392848,65392,212,-38.80014761476,-51.00914532477,73.24002553387,2,1,18 +2025-03-11T12:40:46.560317,479392848,65392,212,-38.91794753026,-51.101770585395,73.425413181595,2,1,18 +2025-03-11T12:40:46.575942,479392848,65392,212,-39.01689945928,-51.20360537781,73.62005315143,2,1,18 +2025-03-11T12:40:46.591567,479392848,65392,212,-39.11113939168,-51.310053089085,73.819326063325,2,1,18 +2025-03-11T12:40:46.607192,479392848,65392,212,-39.20537932408,-51.411879728535,74.013959252155,2,1,18 +2025-03-11T12:40:46.622817,479392848,65392,212,-39.28548326662,-51.518302980915,74.185484722645,2,1,18 +2025-03-11T12:40:46.638442,479392848,65392,212,-39.37972319902,-51.620129620365,74.352390813085,2,1,18 +2025-03-11T12:40:46.654067,479392848,65392,212,-39.46453913818,-51.70807673841,74.509985355385,2,1,18 +2025-03-11T12:40:46.669692,479392848,65392,212,-39.55877907058,-51.78217694691,74.667537839695,2,1,18 +2025-03-11T12:40:46.685317,479392848,65392,212,-39.65301900298,-51.879382514535,74.843667756265,2,1,18 +2025-03-11T12:40:46.700942,479392848,65392,212,-39.74725893538,-51.990451297635,75.01523210977,2,1,18 +2025-03-11T12:40:46.716567,479392848,65392,212,-39.84149886778,-52.07841472161,75.158976664885,2,1,18 +2025-03-11T12:40:46.732192,479392848,65392,212,-39.93573880018,-52.15251493011,75.3026656,2,1,18 +2025-03-11T12:40:46.747817,479392848,65392,212,-40.0111307461,-52.231203598575,75.464830683355,2,1,18 +2025-03-11T12:40:46.763442,479392848,65392,212,-40.08652269202,-52.305271195215,75.613113677515,2,1,18 +2025-03-11T12:40:46.779067,479392848,65392,212,-40.1524906447,-52.3931857014,75.76605991273,2,1,18 +2025-03-11T12:40:46.794692,479392848,65392,212,-40.24201858048,-52.45341454146,75.91892881297,2,1,18 +2025-03-11T12:40:46.810317,479392848,65392,212,-40.32212252302,-52.52286921924,76.057957682005,2,1,18 +2025-03-11T12:40:46.825942,479392848,65392,212,-40.39751446894,-52.592315744055,76.178495037775,2,1,18 +2025-03-11T12:40:46.841567,479392848,65392,212,-40.47290641486,-52.675625484345,76.317572745805,2,1,18 +2025-03-11T12:40:46.857192,479392848,65392,212,-40.54829836078,-52.75431415281,76.447389547705,2,1,18 +2025-03-11T12:40:46.872817,479392848,65392,212,-40.6001303236,-52.819098840975,76.572495641515,2,1,18 +2025-03-11T12:40:46.888442,479392848,65392,212,-40.67552226952,-52.87930322214,76.692995917285,2,1,18 +2025-03-11T12:40:46.904067,479392848,65392,212,-40.74620221882,-52.925636234865,76.799570242855,2,1,18 +2025-03-11T12:40:46.919692,479392848,65392,212,-40.81688216812,-52.99969567854,76.89239225923,2,1,18 +2025-03-11T12:40:46.935317,479392848,65392,212,-40.87813812418,-53.073738816285,77.00830662892,2,1,18 +2025-03-11T12:40:46.950942,479392848,65392,212,-40.94410607686,-53.129305819695,77.124153619615,2,1,18 +2025-03-11T12:40:46.966567,479392848,65392,212,-41.00536203292,-53.189485741965,77.212285270915,2,1,18 +2025-03-11T12:40:46.982192,479392848,65392,212,-41.0477700025,-53.240390908725,77.300352718195,2,1,18 +2025-03-11T12:40:46.997817,479392848,65392,212,-41.09960196532,-53.28669130959,77.388415187485,2,1,18 +2025-03-11T12:40:47.013442,479392848,65392,212,-41.165569918,-53.342258313,77.47653507979,2,1,18 +2025-03-11T12:40:47.029067,479392848,65392,212,-41.20326589096,-53.37929211132,77.559918943,2,1,18 +2025-03-11T12:40:47.044692,479392848,65392,212,-41.23153787068,-53.439414962835,77.638760761135,2,1,18 +2025-03-11T12:40:47.060317,479392848,65392,212,-41.27865783688,-53.485707210735,77.712952900225,2,1,18 +2025-03-11T12:40:47.075942,479392848,65392,212,-41.3304897997,-53.527386539775,77.80561801258,2,1,18 +2025-03-11T12:40:47.091567,479392848,65392,212,-41.35876177942,-53.573646175815,77.88902539378,2,1,18 +2025-03-11T12:40:47.107192,479392848,65392,212,-41.3776097659,-53.5967841468,77.96308414684,2,1,18 +2025-03-11T12:40:47.122817,479392848,65392,212,-41.39645775238,-53.62454318961,78.014055524575,2,1,18 +2025-03-11T12:40:47.138442,479392848,65392,212,-41.43886572196,-53.661585140895,78.083582619595,2,1,18 +2025-03-11T12:40:47.154067,479392848,65392,212,-41.50012167802,-53.703280775865,78.134670646375,2,1,18 +2025-03-11T12:40:47.169692,479392848,65392,212,-41.52839365774,-53.731056124605,78.199519135315,2,1,18 +2025-03-11T12:40:47.185317,479392848,65392,212,-41.56137763408,-53.74959748266,78.245852593,2,1,18 +2025-03-11T12:40:47.200942,479392848,65392,212,-41.59436161042,-53.78200205619,78.310726402945,2,1,18 +2025-03-11T12:40:47.216567,479392848,65392,212,-41.61792159352,-53.81439032379,78.361723101685,2,1,18 +2025-03-11T12:40:47.232192,479392848,65392,212,-41.64619357324,-53.828302457055,78.4034100553,2,1,18 +2025-03-11T12:40:47.247817,479392848,65392,212,-41.65561756648,-53.846803050285,78.426603692635,2,1,18 +2025-03-11T12:40:47.263442,479392848,65392,212,-41.67446555296,-53.865319949445,78.45905325811,2,1,18 +2025-03-11T12:40:47.279067,479392848,65392,212,-41.67917754958,-53.879191317885,78.48222157444,2,1,18 +2025-03-11T12:40:47.294692,479392848,65392,212,-41.6838895462,-53.9069259018,78.49620314464,2,1,18 +2025-03-11T12:40:47.310317,479392848,65392,212,-41.70273753268,-53.911579585485,78.519354723985,2,1,18 +2025-03-11T12:40:47.325942,479392848,65392,212,-41.72629751578,-53.925483565785,78.5471713474,2,1,18 +2025-03-11T12:40:47.341567,479392848,65392,212,-41.74514550226,-53.934758321295,78.54723555142,2,1,18 +2025-03-11T12:40:47.357192,479392848,65392,212,-41.7545694955,-53.953258914525,78.57505037182,2,1,18 +2025-03-11T12:40:47.372817,479392848,65392,212,-41.75928149212,-53.957888139315,78.602802791215,2,1,18 +2025-03-11T12:40:47.388442,479392848,65392,212,-41.7545694955,-53.962501058175,78.598193367145,2,1,18 +2025-03-11T12:40:47.404067,479392848,65392,212,-41.7545694955,-53.944016770875,78.59349802408,2,1,18 +2025-03-11T12:40:47.419692,479392848,65392,212,-41.76399348874,-53.93941200498,78.607356595285,2,1,18 +2025-03-11T12:40:47.435317,479392848,65392,212,-41.76870548536,-53.93479908612,78.611966019355,2,1,18 +2025-03-11T12:40:47.450942,479392848,65392,212,-41.75928149212,-53.92554063654,78.58880946202,2,1,18 +2025-03-11T12:40:47.466567,479392848,65392,212,-41.74514550226,-53.92089510582,78.56566466368,2,1,18 +2025-03-11T12:40:47.482192,479392848,65392,212,-41.74043350564,-53.91626588103,78.584124074935,2,1,18 +2025-03-11T12:40:47.497817,479392848,65392,212,-41.7310095124,-53.92549171875,78.57028404373,2,1,18 +2025-03-11T12:40:47.513442,479392848,65392,212,-41.7310095124,-53.8977652878,78.528582156145,2,1,18 +2025-03-11T12:40:47.529067,479392848,65392,212,-41.71216152592,-53.883869460465,78.500772313735,2,1,18 +2025-03-11T12:40:47.544692,479392848,65392,212,-41.68860154282,-53.86534440834,78.468315967255,2,1,18 +2025-03-11T12:40:47.560317,479392848,65392,212,-41.66504155972,-53.846819356215,78.42199607158,2,1,18 +2025-03-11T12:40:47.575942,479392848,65392,212,-41.64619357324,-53.82368138523,78.37566441691,2,1,18 +2025-03-11T12:40:47.591567,479392848,65392,212,-41.62734558676,-53.809785557895,78.343233391435,2,1,18 +2025-03-11T12:40:47.607192,479392848,65392,212,-41.60378560366,-53.768155146645,78.31530552802,2,1,18 +2025-03-11T12:40:47.622817,479392848,65392,212,-41.57551362394,-53.75424301338,78.255133842145,2,1,18 +2025-03-11T12:40:47.638442,479392848,65392,212,-41.54724164422,-53.72646766464,78.19490653627,2,1,18 +2025-03-11T12:40:47.654067,479392848,65392,212,-41.52368166112,-53.68483725339,78.15311512366,2,1,18 +2025-03-11T12:40:47.669692,479392848,65392,212,-41.5189696645,-53.643239454,78.097487285875,2,1,18 +2025-03-11T12:40:47.685317,479392848,65392,212,-41.48127369154,-53.610826727505,78.02798551186,2,1,18 +2025-03-11T12:40:47.700942,479392848,65392,212,-41.41530573886,-53.57836508322,77.95382186875,2,1,18 +2025-03-11T12:40:47.716567,479392848,65392,212,-41.36818577266,-53.55055712262,77.884325072725,2,1,18 +2025-03-11T12:40:47.732192,479392848,65392,212,-41.3304897997,-53.52276546795,77.80559947258,2,1,18 +2025-03-11T12:40:47.747817,479392848,65392,212,-41.27865783688,-53.49032828256,77.722213806355,2,1,18 +2025-03-11T12:40:47.763442,479392848,65392,212,-41.23153787068,-53.448657106485,77.65266139033,2,1,18 +2025-03-11T12:40:47.779067,479392848,65392,212,-41.19384189772,-53.393139020865,77.55996100099,2,1,18 +2025-03-11T12:40:47.794692,479392848,65392,212,-41.15143392814,-53.332991710455,77.46261410758,2,1,18 +2025-03-11T12:40:47.810317,479392848,65392,212,-41.0948899687,-53.277441012975,77.36988659422,2,1,18 +2025-03-11T12:40:47.825942,479392848,65392,212,-41.03834600926,-53.22651138732,77.272556437795,2,1,18 +2025-03-11T12:40:47.841567,479392848,65392,212,-40.98651404644,-53.170968842805,77.175214522375,2,1,18 +2025-03-11T12:40:47.857192,479392848,65392,212,-40.93468208362,-53.110805226465,77.059369334695,2,1,18 +2025-03-11T12:40:47.872817,479392848,65392,212,-40.88756211742,-53.055270834915,76.957413017215,2,1,18 +2025-03-11T12:40:47.888442,479392848,65392,212,-40.8357301546,-52.99048614675,76.860034021795,2,1,18 +2025-03-11T12:40:47.904067,479392848,65392,212,-40.77447419854,-52.925685152655,76.734914365975,2,1,18 +2025-03-11T12:40:47.919692,479392848,65392,212,-40.71321824248,-52.85164201491,76.61437881322,2,1,18 +2025-03-11T12:40:47.935317,479392848,65392,212,-40.64253829318,-52.786824714885,76.50773032765,2,1,18 +2025-03-11T12:40:47.950942,479392848,65392,212,-40.5765703405,-52.722015567825,76.40570980615,2,1,18 +2025-03-11T12:40:47.966567,479392848,65392,212,-40.50117839458,-52.66181118666,76.27596716425,2,1,18 +2025-03-11T12:40:47.982192,479392848,65392,212,-40.4352104419,-52.592380967775,76.132337455165,2,1,18 +2025-03-11T12:40:47.997817,479392848,65392,212,-40.37395448584,-52.522958901855,76.00257807628,2,1,18 +2025-03-11T12:40:48.013442,479392848,65392,212,-40.29856253992,-52.44427023339,75.86351890825,2,1,18 +2025-03-11T12:40:48.029067,479392848,65392,212,-40.21845859738,-52.35633126831,75.71979469615,2,1,18 +2025-03-11T12:40:48.044692,479392848,65392,212,-40.1289306616,-52.27761814095,75.580715185105,2,1,18 +2025-03-11T12:40:48.060317,479392848,65392,212,-40.04882671906,-52.19892131952,75.44164923607,2,1,18 +2025-03-11T12:40:48.075942,479392848,65392,212,-39.95929878328,-52.11096604851,75.284047912765,2,1,18 +2025-03-11T12:40:48.091567,479392848,65392,212,-39.88390683736,-52.023035236395,75.117224566345,2,1,18 +2025-03-11T12:40:48.107192,479392848,65392,212,-39.80380289482,-51.94895948679,74.95045005892,2,1,18 +2025-03-11T12:40:48.122817,479392848,65392,212,-39.70956296242,-51.85637499099,74.815929329935,2,1,18 +2025-03-11T12:40:48.138442,479392848,65392,212,-39.6106110334,-51.773024485875,74.653711801555,2,1,18 +2025-03-11T12:40:48.154067,479392848,65392,212,-39.52108309762,-51.68969028669,74.482265469055,2,1,18 +2025-03-11T12:40:48.169692,479392848,65392,212,-39.44097915508,-51.58326703431,74.310739998565,2,1,18 +2025-03-11T12:40:48.185317,479392848,65392,212,-39.34202722606,-51.48605331372,74.148466850185,2,1,18 +2025-03-11T12:40:48.200942,479392848,65392,212,-39.24307529704,-51.37959744948,73.967671889545,2,1,18 +2025-03-11T12:40:48.216567,479392848,65392,212,-39.14883536464,-51.263907594555,73.78684662991,2,1,18 +2025-03-11T12:40:48.232192,479392848,65392,212,-39.05459543224,-51.162080955105,73.59221344108,2,1,18 +2025-03-11T12:40:48.247817,479392848,65392,212,-38.96035549984,-51.06487538748,73.411462341445,2,1,18 +2025-03-11T12:40:48.263442,479392848,65392,212,-38.84726758096,-50.958395064345,73.207541122465,2,1,18 +2025-03-11T12:40:48.279067,479392848,65392,212,-38.73417966208,-50.856535813035,73.003638443485,2,1,18 +2025-03-11T12:40:48.294692,479392848,65392,212,-38.63051573644,-50.745450724005,72.81357579571,2,1,18 +2025-03-11T12:40:48.310317,479392848,65392,212,-38.51742781756,-50.643591472695,72.614294299795,2,1,18 +2025-03-11T12:40:48.325942,479392848,65392,212,-38.4090518953,-50.527877158875,72.405721598755,2,1,18 +2025-03-11T12:40:48.341567,479392848,65392,212,-38.29596397642,-50.41215469209,72.192520933645,2,1,18 +2025-03-11T12:40:48.357192,479392848,65392,212,-38.1734520643,-50.3010369912,71.98394642959,2,1,18 +2025-03-11T12:40:48.372817,479392848,65392,212,-38.0556521488,-50.1945485151,71.780018429605,2,1,18 +2025-03-11T12:40:48.388442,479392848,65392,212,-37.92371624344,-50.069551292805,71.557511194345,2,1,18 +2025-03-11T12:40:48.404067,479392848,65392,212,-37.80120433132,-49.958433591915,71.325830774965,2,1,18 +2025-03-11T12:40:48.419692,479392848,65392,212,-37.6786924192,-49.8242105319,71.08943647252,2,1,18 +2025-03-11T12:40:48.435317,479392848,65392,212,-37.55618050708,-49.680745328235,70.86686863927,2,1,18 +2025-03-11T12:40:48.450942,479392848,65392,212,-37.44780458482,-49.546546727115,70.63049467984,2,1,18 +2025-03-11T12:40:48.466567,479392848,65392,212,-37.3252926727,-49.4308079544,70.40803808659,2,1,18 +2025-03-11T12:40:48.482192,479392848,65392,212,-37.18864477072,-49.30580257914,70.162418155,2,1,18 +2025-03-11T12:40:48.497817,479392848,65392,212,-37.05670886536,-49.18542642867,69.93068709361,2,1,18 +2025-03-11T12:40:48.513442,479392848,65392,212,-36.91534896676,-49.041928613145,69.675743854885,2,1,18 +2025-03-11T12:40:48.529067,479392848,65392,212,-36.78812505802,-48.90307632834,69.430081865305,2,1,18 +2025-03-11T12:40:48.544692,479392848,65392,212,-36.65147715604,-48.764207737605,69.17978513065,2,1,18 +2025-03-11T12:40:48.560317,479392848,65392,212,-36.51011725744,-48.61146777843,68.92018362886,2,1,18 +2025-03-11T12:40:48.575942,479392848,65392,212,-36.37818135208,-48.467986268835,68.66063276908,2,1,18 +2025-03-11T12:40:48.591567,479392848,65392,212,-36.23682145348,-48.32448845331,68.414931896485,2,1,18 +2025-03-11T12:40:48.607192,479392848,65392,212,-36.09546155488,-48.18561170961,68.155386014695,2,1,18 +2025-03-11T12:40:48.622817,479392848,65392,212,-35.94467766304,-48.042097588155,67.877323298635,2,1,18 +2025-03-11T12:40:48.638442,479392848,65392,212,-35.78446977796,-47.89856716077,67.608489386695,2,1,18 +2025-03-11T12:40:48.654067,479392848,65392,212,-35.62426189288,-47.745794589735,67.34423957782,2,1,18 +2025-03-11T12:40:48.669692,479392848,65392,212,-35.48290199428,-47.588433558735,67.06613480377,2,1,18 +2025-03-11T12:40:48.685317,479392848,65392,212,-35.33683009906,-47.435685446595,66.78342060565,2,1,18 +2025-03-11T12:40:48.700942,479392848,65392,212,-35.1813342106,-47.282921028525,66.50069284552,2,1,18 +2025-03-11T12:40:48.716567,479392848,65392,212,-35.039974312,-47.13018106935,66.227227794535,2,1,18 +2025-03-11T12:40:48.732192,479392848,65392,212,-34.87976642692,-46.96354528284,65.93519526727,2,1,18 +2025-03-11T12:40:48.747817,479392848,65392,212,-34.70542255198,-46.806127181085,65.638558293925,2,1,18 +2025-03-11T12:40:48.763442,479392848,65392,212,-34.5452146669,-46.657975681875,65.3281151944,2,1,18 +2025-03-11T12:40:48.779067,479392848,65392,212,-34.36615879534,-46.48668621168,65.008309904725,2,1,18 +2025-03-11T12:40:48.794692,479392848,65392,212,-34.20595091026,-46.315429353345,64.702395288265,2,1,18 +2025-03-11T12:40:48.810317,479392848,65392,212,-34.03631903194,-46.148777260905,64.433455114315,2,1,18 +2025-03-11T12:40:48.825942,479392848,65392,212,-33.87611114686,-45.982141474395,64.13218022092,2,1,18 +2025-03-11T12:40:48.841567,479392848,65392,212,-33.71119126516,-45.80625539127,63.82161910039,2,1,18 +2025-03-11T12:40:48.857192,479392848,65392,212,-33.5556953767,-45.64424882955,63.49264242961,2,1,18 +2025-03-11T12:40:48.872817,479392848,65392,212,-33.38606349838,-45.472975665285,63.16822951888,2,1,18 +2025-03-11T12:40:48.888442,479392848,65392,212,-33.21643162006,-45.306323572845,62.857698697345,2,1,18 +2025-03-11T12:40:48.904067,479392848,65392,212,-33.03266375188,-45.12116273421,62.537831006665,2,1,18 +2025-03-11T12:40:48.919692,479392848,65392,212,-32.84418388708,-44.92675159896,62.213298271915,2,1,18 +2025-03-11T12:40:48.935317,479392848,65392,212,-32.66512801552,-44.75084105694,61.898095625305,2,1,18 +2025-03-11T12:40:48.950942,479392848,65392,212,-32.48136014734,-44.565680218305,61.56436438543,2,1,18 +2025-03-11T12:40:48.966567,479392848,65392,212,-32.28816828592,-44.394366289215,61.221432837415,2,1,18 +2025-03-11T12:40:48.982192,479392848,65392,212,-32.10440041774,-44.223068666055,60.892378400605,2,1,18 +2025-03-11T12:40:48.997817,479392848,65392,212,-31.93476853942,-44.037932286315,60.558667503745,2,1,18 +2025-03-11T12:40:49.013442,479392848,65392,212,-31.76042466448,-43.848166681785,60.201825370555,2,1,18 +2025-03-11T12:40:49.029067,479392848,65392,212,-31.56252080644,-43.653739240605,59.868036707665,2,1,18 +2025-03-11T12:40:49.044692,479392848,65392,212,-31.34576896192,-43.45465811574,59.52958119769,2,1,18 +2025-03-11T12:40:49.060317,479392848,65392,212,-31.16671309036,-43.24177899912,59.16801840043,2,1,18 +2025-03-11T12:40:49.075942,479392848,65392,212,-31.00179320866,-43.05202970052,58.79270509699,2,1,18 +2025-03-11T12:40:49.091567,479392848,65392,212,-30.80860134724,-42.85298934048,58.458904675105,2,1,18 +2025-03-11T12:40:49.107192,479392848,65392,212,-30.62483347906,-42.649344214545,58.120478092165,2,1,18 +2025-03-11T12:40:49.122817,479392848,65392,212,-30.41279363116,-42.450271242645,57.763544630935,2,1,18 +2025-03-11T12:40:49.138442,479392848,65392,212,-30.21960176974,-42.260473026255,57.397433007595,2,1,18 +2025-03-11T12:40:49.154067,479392848,65392,212,-30.01227391846,-42.06140820732,57.017400412045,2,1,18 +2025-03-11T12:40:49.169692,479392848,65392,212,-29.80023407056,-41.857714163595,56.63734249549,2,1,18 +2025-03-11T12:40:49.185317,479392848,65392,212,-29.61175420576,-41.635576597395,56.271107873155,2,1,18 +2025-03-11T12:40:49.200942,479392848,65392,212,-29.41856234434,-41.445778381005,55.904996249815,2,1,18 +2025-03-11T12:40:49.216567,479392848,65392,212,-29.22537048292,-41.237495877315,55.520325734215,2,1,18 +2025-03-11T12:40:49.232192,479392848,65392,212,-29.01333063502,-41.02455968994,55.13098837153,2,1,18 +2025-03-11T12:40:49.247817,479392848,65392,212,-28.7965787905,-40.825478565075,54.764805763165,2,1,18 +2025-03-11T12:40:49.263442,479392848,65392,212,-28.58925093922,-40.59868731519,54.39852547681,2,1,18 +2025-03-11T12:40:49.279067,479392848,65392,212,-28.38192308794,-40.38575928078,54.00919489513,2,1,18 +2025-03-11T12:40:49.294692,479392848,65392,212,-28.17459523666,-40.20055767732,53.615354370385,2,1,18 +2025-03-11T12:40:49.310317,479392848,65392,212,-27.9484193989,-39.992218102875,53.207530472425,2,1,18 +2025-03-11T12:40:49.325942,479392848,65392,212,-27.73166755438,-39.760789475235,52.808869802605,2,1,18 +2025-03-11T12:40:49.341567,479392848,65392,212,-27.51962770648,-39.52012685691,52.41017883379,2,1,18 +2025-03-11T12:40:49.357192,479392848,65392,212,-27.2887398721,-39.297915914025,52.020777267085,2,1,18 +2025-03-11T12:40:49.372817,479392848,65392,212,-27.0531400411,-39.08031789,51.61752391018,2,1,18 +2025-03-11T12:40:49.388442,479392848,65392,212,-26.82696420334,-38.85811510008,51.214265575285,2,1,18 +2025-03-11T12:40:49.404067,479392848,65392,212,-26.61963635206,-38.63594492202,50.806413181345,2,1,18 +2025-03-11T12:40:49.419692,479392848,65392,212,-26.3934605143,-38.4137421321,50.407776029515,2,1,18 +2025-03-11T12:40:49.435317,479392848,65392,212,-26.17199667316,-38.182305351495,49.99062384643,2,1,18 +2025-03-11T12:40:49.450942,479392848,65392,212,-25.95995682526,-37.964748092295,49.56891966229,2,1,18 +2025-03-11T12:40:49.466567,479392848,65392,212,-25.7102210044,-37.7332623939,49.13786324398,2,1,18 +2025-03-11T12:40:49.482192,479392848,65392,212,-25.46990917678,-37.48792978596,48.73449186607,2,1,18 +2025-03-11T12:40:49.497817,479392848,65392,212,-25.2625813255,-37.25651746425,48.321981209065,2,1,18 +2025-03-11T12:40:49.513442,479392848,65392,212,-25.03640548774,-37.02507253068,47.904822244975,2,1,18 +2025-03-11T12:40:49.529067,479392848,65392,212,-24.79609366012,-36.802845281865,47.46919528561,2,1,18 +2025-03-11T12:40:49.544692,479392848,65392,212,-24.56520582574,-36.576013267155,47.033563348255,2,1,18 +2025-03-11T12:40:49.560317,479392848,65392,212,-24.32960599474,-36.335309884005,46.63021729135,2,1,18 +2025-03-11T12:40:49.575942,479392848,65392,212,-24.09871816036,-36.10385679747,46.20843036319,2,1,18 +2025-03-11T12:40:49.591567,479392848,65392,212,-23.85369433612,-35.86313710839,45.768101279755,2,1,18 +2025-03-11T12:40:49.607192,479392848,65392,212,-23.60395851526,-35.622409266345,45.327765415315,2,1,18 +2025-03-11T12:40:49.622817,479392848,65392,212,-23.36835868426,-35.37708481137,44.882810170825,2,1,18 +2025-03-11T12:40:49.638442,479392848,65392,212,-23.13747084988,-35.136389581185,44.414774332015,2,1,18 +2025-03-11T12:40:49.654067,479392848,65392,212,-22.89244702564,-34.90029096393,43.99294852084,2,1,18 +2025-03-11T12:40:49.669692,479392848,65392,212,-22.6474232014,-34.6503291312,43.55720354047,2,1,18 +2025-03-11T12:40:49.685317,479392848,65392,212,-22.41653536702,-34.41425497284,43.10767097392,2,1,18 +2025-03-11T12:40:49.700942,479392848,65392,212,-22.1762235394,-34.164301293075,42.653448042295,2,1,18 +2025-03-11T12:40:49.716567,479392848,65392,212,-21.9170637253,-33.91431500145,42.203819169715,2,1,18 +2025-03-11T12:40:49.732192,479392848,65392,212,-21.6579039112,-33.664328709825,41.72184201568,2,1,18 +2025-03-11T12:40:49.747817,479392848,65392,212,-21.41288008696,-33.405124733445,41.262954039985,2,1,18 +2025-03-11T12:40:49.763442,479392848,65392,212,-21.17728025596,-33.14131599117,40.817924635495,2,1,18 +2025-03-11T12:40:49.779067,479392848,65392,212,-20.93225643172,-32.877490942965,40.372881668995,2,1,18 +2025-03-11T12:40:49.794692,479392848,65392,212,-20.668384621,-32.6321175702,39.92326455541,2,1,18 +2025-03-11T12:40:49.810317,479392848,65392,212,-20.4092248069,-32.3867523504,39.469033039765,2,1,18 +2025-03-11T12:40:49.825942,479392848,65392,212,-20.1500649928,-32.1413871306,39.000937974925,2,1,18 +2025-03-11T12:40:49.841567,479392848,65392,212,-19.8909051787,-31.8775376235,38.532768750085,2,1,18 +2025-03-11T12:40:49.857192,479392848,65392,212,-19.62703336798,-31.62754317891,38.050784815045,2,1,18 +2025-03-11T12:40:49.872817,479392848,65392,212,-19.37729754712,-31.37295212139,37.56880268302,2,1,18 +2025-03-11T12:40:49.888442,479392848,65392,212,-19.13227372288,-31.099884929535,37.09599553813,2,1,18 +2025-03-11T12:40:49.904067,479392848,65392,212,-18.88724989864,-30.84530202498,36.63250491937,2,1,18 +2025-03-11T12:40:49.919692,479392848,65392,212,-18.61395409468,-30.58604913081,36.145849159255,2,1,18 +2025-03-11T12:40:49.935317,479392848,65392,212,-18.35008228396,-30.331433614395,35.673089050345,2,1,18 +2025-03-11T12:40:49.950942,479392848,65392,212,-18.09563446648,-30.07683440391,35.18647895425,2,1,18 +2025-03-11T12:40:49.966567,479392848,65392,212,-17.82705065914,-29.80372644723,34.70901672127,2,1,18 +2025-03-11T12:40:49.982192,479392848,65392,212,-17.55375485518,-29.521368193935,34.23613181035,2,1,18 +2025-03-11T12:40:49.997756,479392852,65388,213,-17.28517104784,-29.248260237255,33.74018484511,2,1,18 +2025-03-11T12:40:50.013381,479392852,65388,213,-17.02129923712,-28.979781505365,33.24888438394,2,1,18 +2025-03-11T12:40:50.029006,479392852,65388,213,-16.7574274264,-28.711302773475,32.7668262889,2,1,18 +2025-03-11T12:40:50.044631,479392852,65388,213,-16.48413162244,-28.44742880748,32.27553080572,2,1,18 +2025-03-11T12:40:50.060256,479392852,65388,213,-16.21083581848,-28.17893376966,31.788837965605,2,1,18 +2025-03-11T12:40:50.075881,479392852,65388,213,-15.94225201114,-27.90582581298,31.292891000365,2,1,18 +2025-03-11T12:40:50.091506,479392852,65388,213,-15.66895620718,-27.63733077516,30.783092244925,2,1,18 +2025-03-11T12:40:50.107131,479392852,65388,213,-15.38623640998,-27.35033514411,30.28706931667,2,1,18 +2025-03-11T12:40:50.122756,479392852,65388,213,-15.11294060602,-27.08184010629,29.79575529349,2,1,18 +2025-03-11T12:40:50.138381,479392852,65388,213,-14.84435679868,-26.831837508735,29.304522211315,2,1,18 +2025-03-11T12:40:50.154006,479392852,65388,213,-14.58048498796,-26.554116633195,28.803942304015,2,1,18 +2025-03-11T12:40:50.169631,479392852,65388,213,-14.307189184,-26.2717583799,28.303330294705,2,1,18 +2025-03-11T12:40:50.185256,479392852,65388,213,-14.02918138342,-25.99863411729,27.788885035195,2,1,18 +2025-03-11T12:40:50.200881,479392852,65388,213,-13.7417495896,-25.730114620575,27.27906593674,2,1,18 +2025-03-11T12:40:50.216506,479392852,65388,213,-13.4590297924,-25.452361133175,26.773837722355,2,1,18 +2025-03-11T12:40:50.232131,479392852,65388,213,-13.19044598506,-25.170011032845,26.27323249405,2,1,18 +2025-03-11T12:40:50.247756,479392852,65388,213,-12.92657417434,-24.88766908548,25.76339168062,2,1,18 +2025-03-11T12:40:50.263381,479392852,65388,213,-12.66270236362,-24.605327138115,25.248929684125,2,1,18 +2025-03-11T12:40:50.279006,479392852,65388,213,-12.37998256642,-24.32295257889,24.73444056361,2,1,18 +2025-03-11T12:40:50.294631,479392852,65388,213,-12.08312677936,-24.04055356077,24.233794649275,2,1,18 +2025-03-11T12:40:50.310256,479392852,65388,213,-11.80040698216,-23.75355792972,23.723908171825,2,1,18 +2025-03-11T12:40:50.325881,479392852,65388,213,-11.51768718496,-23.461941226845,23.19089723905,2,1,18 +2025-03-11T12:40:50.341506,479392852,65388,213,-11.244391381,-23.1888251172,22.694943492805,2,1,18 +2025-03-11T12:40:50.357131,479392852,65388,213,-10.96638358042,-22.901837639115,22.19430616249,2,1,18 +2025-03-11T12:40:50.372756,479392852,65388,213,-10.68366378322,-22.633326295365,21.670630295845,2,1,18 +2025-03-11T12:40:50.388381,479392852,65388,213,-10.39151999278,-22.355556502035,21.13766142106,2,1,18 +2025-03-11T12:40:50.404006,479392852,65388,213,-10.09466420572,-22.054673196615,20.609214248335,2,1,18 +2025-03-11T12:40:50.419631,479392852,65388,213,-9.81194440852,-21.77229863739,20.09472512782,2,1,18 +2025-03-11T12:40:50.435256,479392852,65388,213,-9.53393660794,-21.48069008748,19.57096334218,2,1,18 +2025-03-11T12:40:50.450881,479392852,65388,213,-9.24650481412,-21.17982308799,19.051772097595,2,1,18 +2025-03-11T12:40:50.466506,479392852,65388,213,-8.94022503382,-20.892786692115,18.518745799795,2,1,18 +2025-03-11T12:40:50.482131,479392852,65388,213,-8.65279324,-20.59654076445,17.99957309521,2,1,18 +2025-03-11T12:40:50.497756,479392852,65388,213,-8.37478543942,-20.309553286365,17.480451032635,2,1,18 +2025-03-11T12:40:50.513381,479392852,65388,213,-8.10148963546,-20.02719503307,16.961354291065,2,1,18 +2025-03-11T12:40:50.529006,479392852,65388,213,-7.81876983826,-19.744820473845,16.42838043829,2,1,18 +2025-03-11T12:40:50.544631,479392852,65388,213,-7.51720205458,-19.46241330276,15.895379461495,2,1,18 +2025-03-11T12:40:50.560256,479392852,65388,213,-7.23448225738,-19.17541767171,15.37162943485,2,1,18 +2025-03-11T12:40:50.575881,479392852,65388,213,-6.96589845004,-18.888446499555,14.83865738509,2,1,18 +2025-03-11T12:40:50.591506,479392852,65388,213,-6.68789064946,-18.59221687782,14.28714996106,2,1,18 +2025-03-11T12:40:50.607131,479392852,65388,213,-6.3910348624,-18.295954644225,13.767963694465,2,1,18 +2025-03-11T12:40:50.622756,479392852,65388,213,-6.10360306858,-17.995087644735,13.24877244988,2,1,18 +2025-03-11T12:40:50.638381,479392852,65388,213,-5.81145927814,-17.67572820498,12.71101553203,2,1,18 +2025-03-11T12:40:50.654006,479392852,65388,213,-5.50989149446,-17.37945781842,12.177958935235,2,1,18 +2025-03-11T12:40:50.669631,479392852,65388,213,-5.20361171416,-17.09704249437,11.64032999437,2,1,18 +2025-03-11T12:40:50.685256,479392852,65388,213,-4.9067559271,-16.79615918895,11.10726163858,2,1,18 +2025-03-11T12:40:50.700881,479392852,65388,213,-4.60990014004,-16.49527588353,10.56495091666,2,1,18 +2025-03-11T12:40:50.716506,479392852,65388,213,-4.31304435298,-16.20363472176,10.027298457805,2,1,18 +2025-03-11T12:40:50.732131,479392852,65388,213,-4.01618856592,-15.92123570364,9.48044071282,2,1,18 +2025-03-11T12:40:50.747756,479392852,65388,213,-3.71933277886,-15.624973470045,8.942769713965,2,1,18 +2025-03-11T12:40:50.763381,479392852,65388,213,-3.4224769918,-15.342574451925,8.409775518175,2,1,18 +2025-03-11T12:40:50.779006,479392852,65388,213,-3.12562120474,-15.041691146505,7.86284361319,2,1,18 +2025-03-11T12:40:50.794631,479392852,65388,213,-2.8334774143,-14.736194922225,7.32514231534,2,1,18 +2025-03-11T12:40:50.810256,479392852,65388,213,-2.54133362386,-14.421456554295,6.792025120555,2,1,18 +2025-03-11T12:40:50.825881,479392852,65388,213,-2.25861382666,-14.134460923245,6.25903272778,2,1,18 +2025-03-11T12:40:50.841506,479392852,65388,213,-1.96647003622,-13.85207005809,5.72142412993,2,1,18 +2025-03-11T12:40:50.857131,479392852,65388,213,-1.66490225254,-13.55579967153,5.17450398394,2,1,18 +2025-03-11T12:40:50.872756,479392852,65388,213,-1.35862247224,-13.24565791653,4.62290025388,2,1,18 +2025-03-11T12:40:50.888381,479392852,65388,213,-1.06176668518,-12.95401675476,4.076005428895,2,1,18 +2025-03-11T12:40:50.904006,479392852,65388,213,-0.76962289474,-12.653141602305,3.54294385411,2,1,18 +2025-03-11T12:40:50.919631,479392852,65388,213,-0.46805511106,-12.366113359395,2.982197238925,2,1,18 +2025-03-11T12:40:50.935256,479392852,65388,213,-0.18062331724,-12.065246359905,2.43527889595,2,1,18 +2025-03-11T12:40:50.950881,479392852,65388,213,0.12094446644,-11.750491686045,1.892905773025,2,1,18 +2025-03-11T12:40:50.966506,479392852,65388,213,0.43193624336,-11.43109963443,1.345879365025,2,1,18 +2025-03-11T12:40:50.982131,479392852,65388,213,0.73350402704,-11.139450319695,0.798977759035,2,1,18 +2025-03-11T12:40:50.997756,479392852,65388,213,1.03507181072,-10.843179933135,0.242815246915,2,1,18 +2025-03-11T12:40:51.013381,479392852,65388,213,1.33192759778,-10.54691769954,-0.308719301135,2,1,18 +2025-03-11T12:40:51.029006,479392852,65388,213,1.63349538146,-10.255268384805,-0.846378540995,2,1,18 +2025-03-11T12:40:51.044631,479392852,65388,213,1.93977516176,-9.94974770163,-1.39334254799,2,1,18 +2025-03-11T12:40:51.060256,479392852,65388,213,2.2319189522,-9.630388261875,-1.954205381165,2,1,18 +2025-03-11T12:40:51.075881,479392852,65388,213,2.51935074602,-9.32490019056,-2.496521081075,2,1,18 +2025-03-11T12:40:51.091506,479392852,65388,213,2.8209185297,-9.033250875825,-3.034180320935,2,1,18 +2025-03-11T12:40:51.107131,479392852,65388,213,3.13191030662,-8.736964183335,-3.571871662805,2,1,18 +2025-03-11T12:40:51.122756,479392852,65388,213,3.42405409706,-8.43608903088,-4.11417560372,2,1,18 +2025-03-11T12:40:51.138381,479392852,65388,213,3.72562188074,-8.153681859795,-4.656418946645,2,1,18 +2025-03-11T12:40:51.154006,479392852,65388,213,4.02718966442,-7.857411473235,-5.2079602757,2,1,18 +2025-03-11T12:40:51.169631,479392852,65388,213,4.33346944472,-7.55189079006,-5.764166648825,2,1,18 +2025-03-11T12:40:51.185256,479392852,65388,213,4.6350372284,-7.24637825985,-6.329608607075,2,1,18 +2025-03-11T12:40:51.200881,479392852,65388,213,4.92718101884,-6.945503107395,-6.885776097185,2,1,18 +2025-03-11T12:40:51.216506,479392852,65388,213,5.2240368059,-6.644619801975,-7.418844452975,2,1,18 +2025-03-11T12:40:51.232131,479392852,65388,213,5.52560458958,-6.329865128115,-7.965838758965,2,1,18 +2025-03-11T12:40:51.247756,479392852,65388,213,5.83188436988,-6.028965516765,-8.51278422596,2,1,18 +2025-03-11T12:40:51.263381,479392852,65388,213,6.13816415018,-5.74192912089,-9.059674072955,2,1,18 +2025-03-11T12:40:51.279006,479392852,65388,213,6.4491559271,-5.4456424284,-9.58350186563,2,1,18 +2025-03-11T12:40:51.294631,479392852,65388,213,6.74129971754,-5.135525132295,-10.12122170348,2,1,18 +2025-03-11T12:40:51.310256,479392852,65388,213,7.02873151136,-4.843900276455,-10.686587698715,2,1,18 +2025-03-11T12:40:51.325881,479392852,65388,213,7.31616330518,-4.533791133315,-11.23354312169,2,1,18 +2025-03-11T12:40:51.341506,479392852,65388,213,7.61301909224,-4.232907827895,-11.77585384361,2,1,18 +2025-03-11T12:40:51.357131,479392852,65388,213,7.90516288268,-3.94127481909,-12.327363070655,2,1,18 +2025-03-11T12:40:51.372756,479392852,65388,213,8.22086665622,-3.63111675816,-12.878980362725,2,1,18 +2025-03-11T12:40:51.388381,479392852,65388,213,8.51772244328,-3.325612380915,-13.40744607545,2,1,18 +2025-03-11T12:40:51.404006,479392852,65388,213,8.82400222358,-3.033954913215,-13.945112096315,2,1,18 +2025-03-11T12:40:51.419631,479392852,65388,213,9.10672202078,-2.728474994865,-14.482799832155,2,1,18 +2025-03-11T12:40:51.435256,479392852,65388,213,9.3941538146,-2.4322290672,-15.020457269,2,1,18 +2025-03-11T12:40:51.450881,479392852,65388,213,9.68629760504,-2.149838202045,-15.562687049915,2,1,18 +2025-03-11T12:40:51.466506,479392852,65388,213,9.97844139548,-1.853584121415,-16.118836000025,2,1,18 +2025-03-11T12:40:51.482131,479392852,65388,213,10.2894331724,-1.538813141625,-16.66122268496,2,1,18 +2025-03-11T12:40:51.497756,479392852,65388,213,10.58628895946,-1.24255090803,-17.20351486688,2,1,18 +2025-03-11T12:40:51.513381,479392852,65388,213,10.86900875666,-0.946313133329999,-17.75040788885,2,1,18 +2025-03-11T12:40:51.529006,479392852,65388,213,11.15644055048,-0.668551492965,-18.28336998263,2,1,18 +2025-03-11T12:40:51.544631,479392852,65388,213,11.46272033078,-0.37227295344,-18.811812177365,2,1,18 +2025-03-11T12:40:51.560256,479392852,65388,213,11.76900011108,-0.0852365575650005,-19.344838475165,2,1,18 +2025-03-11T12:40:51.575881,479392852,65388,213,12.06585589814,0.21102567603,-19.90099420628,2,1,18 +2025-03-11T12:40:51.591506,479392852,65388,213,12.35799968858,0.530385115785,-20.443372307195,2,1,18 +2025-03-11T12:40:51.607131,479392852,65388,213,12.65485547564,0.82664734938,-20.98104330605,2,1,18 +2025-03-11T12:40:51.622756,479392852,65388,213,12.95642325932,1.109054520465,-21.514044282845,2,1,18 +2025-03-11T12:40:51.638381,479392852,65388,213,13.25327904638,1.409937825885,-22.06097618783,2,1,18 +2025-03-11T12:40:51.654006,479392852,65388,213,13.54542283682,1.70157083469,-22.603243048745,2,1,18 +2025-03-11T12:40:51.669631,479392852,65388,213,13.83756662726,1.98858277167,-23.122385454335,2,1,18 +2025-03-11T12:40:51.685256,479392852,65388,213,14.12028642446,2.270957330895,-23.632253391785,2,1,18 +2025-03-11T12:40:51.700881,479392852,65388,213,14.42185420814,2.56260664563,-24.16529144858,2,1,18 +2025-03-11T12:40:51.716506,479392852,65388,213,14.69986200872,2.858836267365,-24.68907177422,2,1,18 +2025-03-11T12:40:51.732131,479392852,65388,213,14.98258180592,3.164316185715,-25.222138326995,2,1,18 +2025-03-11T12:40:51.747756,479392852,65388,213,15.27472559636,3.45594919452,-25.750541638715,2,1,18 +2025-03-11T12:40:51.763381,479392852,65388,213,15.55744539356,3.74294482557,-26.288155214555,2,1,18 +2025-03-11T12:40:51.779006,479392852,65388,213,15.85901317724,4.025351996655,-26.825777374415,2,1,18 +2025-03-11T12:40:51.794631,479392852,65388,213,16.14644497106,4.316976852495,-27.344931539,2,1,18 +2025-03-11T12:40:51.810256,479392852,65388,213,16.42916476826,4.61783569902,-27.877979551775,2,1,18 +2025-03-11T12:40:51.825881,479392852,65388,213,16.70717256884,4.914065320755,-28.411002243545,2,1,18 +2025-03-11T12:40:51.841506,479392852,65388,213,16.99460436266,5.187205889295,-28.925461065065,2,1,18 +2025-03-11T12:40:51.857131,479392852,65388,213,17.27261216324,5.469572295555,-29.439943404575,2,1,18 +2025-03-11T12:40:51.872756,479392852,65388,213,17.5694679503,5.74735024185,-29.972919060365,2,1,18 +2025-03-11T12:40:51.888381,479392852,65388,213,17.86161174074,6.038983250655,-30.482837639825,2,1,18 +2025-03-11T12:40:51.904006,479392852,65388,213,18.15375553118,6.325995187635,-31.001980045415,2,1,18 +2025-03-11T12:40:51.919631,479392852,65388,213,18.441187325,6.63148325895,-31.52118983,2,1,18 +2025-03-11T12:40:51.935256,479392852,65388,213,18.7239071222,6.90923674635,-32.044902776645,2,1,18 +2025-03-11T12:40:51.950881,479392852,65388,213,18.99720292616,7.18697392782,-32.55935979515,2,1,18 +2025-03-11T12:40:51.966506,479392852,65388,213,19.27521072674,7.46009819043,-33.069183871595,2,1,18 +2025-03-11T12:40:51.982131,479392852,65388,213,19.56735451718,7.742489055585,-33.579065371055,2,1,18 +2025-03-11T12:40:51.997756,479392852,65388,213,19.84536231776,8.03871867732,-34.075118598305,2,1,18 +2025-03-11T12:40:52.013381,479392852,65388,213,20.11865812172,8.321076930615,-34.57110942455,2,1,18 +2025-03-11T12:40:52.029006,479392852,65388,213,20.38724192906,8.594184887295,-35.08554112205,2,1,18 +2025-03-11T12:40:52.044631,479392852,65388,213,20.66053773302,8.87654314059,-35.60463786362,2,1,18 +2025-03-11T12:40:52.060256,479392852,65388,213,20.9385455336,9.14042525955,-36.12828840926,2,1,18 +2025-03-11T12:40:52.075881,479392852,65388,213,21.23068932404,9.41819505288,-36.633530185655,2,1,18 +2025-03-11T12:40:52.091506,479392852,65388,213,21.51340912124,9.70519068393,-37.12955311391,2,1,18 +2025-03-11T12:40:52.107131,479392852,65388,213,21.77256893534,9.973661262855,-37.620846794075,2,1,18 +2025-03-11T12:40:52.122756,479392852,65388,213,22.05057673592,10.256027669115,-38.126086767455,2,1,18 +2025-03-11T12:40:52.138381,479392852,65388,213,22.31444854664,10.52912747283,-38.626648134755,2,1,18 +2025-03-11T12:40:52.154006,479392852,65388,213,22.5877443506,10.802243582475,-39.122601881,2,1,18 +2025-03-11T12:40:52.169631,479392852,65388,213,22.8704641478,11.079997069875,-39.627830095385,2,1,18 +2025-03-11T12:40:52.185256,479392852,65388,213,23.13904795514,11.353105026555,-40.133019426755,2,1,18 +2025-03-11T12:40:52.200881,479392852,65388,213,23.41705575572,11.63085036099,-40.62437731094,2,1,18 +2025-03-11T12:40:52.216506,479392852,65388,213,23.68092756644,11.894708021055,-41.10641686598,2,1,18 +2025-03-11T12:40:52.232131,479392852,65388,213,23.9542233704,12.1493398434,-41.60691763529,2,1,18 +2025-03-11T12:40:52.247756,479392852,65388,213,24.21809518112,12.40857643164,-42.102802199525,2,1,18 +2025-03-11T12:40:52.263381,479392852,65388,213,24.48196699184,12.681676235355,-42.58950001763,2,1,18 +2025-03-11T12:40:52.279006,479392852,65388,213,24.75055079918,12.945542048385,-43.071546353675,2,1,18 +2025-03-11T12:40:52.294631,479392852,65388,213,25.02384660314,13.214037086205,-43.562860376855,2,1,18 +2025-03-11T12:40:52.310256,479392852,65388,213,25.2971424071,13.473289980375,-44.03103140471,2,1,18 +2025-03-11T12:40:52.325881,479392852,65388,213,25.54687822796,13.75098639702,-44.513106236735,2,1,18 +2025-03-11T12:40:52.341506,479392852,65388,213,25.81075003868,14.024086200735,-44.995182871775,2,1,18 +2025-03-11T12:40:52.357131,479392852,65388,213,26.0746218494,14.2694595735,-45.48176944988,2,1,18 +2025-03-11T12:40:52.372756,479392852,65388,213,26.35262964998,14.54258383611,-45.95000287874,2,1,18 +2025-03-11T12:40:52.388381,479392852,65388,213,26.60236547084,14.80641703728,-46.41815854157,2,1,18 +2025-03-11T12:40:52.404006,479392852,65388,213,26.84267729846,15.065612860695,-46.890903285455,2,1,18 +2025-03-11T12:40:52.419631,479392852,65388,213,27.10654910918,15.33871266441,-47.36835873743,2,1,18 +2025-03-11T12:40:52.435256,479392852,65388,213,27.36570892328,15.579456812385,-47.850298811465,2,1,18 +2025-03-11T12:40:52.450881,479392852,65388,213,27.62486873738,15.834064175835,-48.32305213937,2,1,18 +2025-03-11T12:40:52.466506,479392852,65388,213,27.87931655486,16.084042314495,-48.781916597075,2,1,18 +2025-03-11T12:40:52.482131,479392852,65388,213,28.11962838248,16.32475385061,-49.231481265635,2,1,18 +2025-03-11T12:40:52.497756,479392852,65388,213,28.37407619996,16.579353061095,-49.68112189721,2,1,18 +2025-03-11T12:40:52.513381,479392852,65388,213,28.63794801068,16.838589649335,-50.13541581386,2,1,18 +2025-03-11T12:40:52.529006,479392852,65388,213,28.88297183492,17.09317255389,-50.58966406649,2,1,18 +2025-03-11T12:40:52.544631,479392852,65388,213,29.1374196524,17.3339085489,-51.04387026113,2,1,18 +2025-03-11T12:40:52.560256,479392852,65388,213,29.38715547326,17.58849960642,-51.48426174557,2,1,18 +2025-03-11T12:40:52.575881,479392852,65388,213,29.62746730088,17.84307435801,-51.929260851065,2,1,18 +2025-03-11T12:40:52.591506,479392852,65388,213,29.87249112512,18.088415118915,-52.37885084063,2,1,18 +2025-03-11T12:40:52.607131,479392852,65388,213,30.1269389426,18.319908970275,-52.8422623214,2,1,18 +2025-03-11T12:40:52.622756,479392852,65388,213,30.37196276684,18.560628659355,-53.291833770965,2,1,18 +2025-03-11T12:40:52.638381,479392852,65388,213,30.61227459446,18.81058233912,-53.713708421135,2,1,18 +2025-03-11T12:40:52.654006,479392852,65388,213,30.83845043222,19.046648344515,-54.140128291355,2,1,18 +2025-03-11T12:40:52.669631,479392852,65388,213,31.07876225984,19.291980952455,-54.580469133785,2,1,18 +2025-03-11T12:40:52.685256,479392852,65388,213,31.3284980807,19.537329866325,-55.020823538225,2,1,18 +2025-03-11T12:40:52.700881,479392852,65388,213,31.56880990832,19.791904617915,-55.451959094525,2,1,18 +2025-03-11T12:40:52.716506,479392852,65388,213,31.80912173594,20.04185829768,-55.883076110825,2,1,18 +2025-03-11T12:40:52.732131,479392852,65388,213,32.0352975737,20.27330323125,-56.318719807175,2,1,18 +2025-03-11T12:40:52.747756,479392852,65388,213,32.25676141484,20.48163465273,-56.75426402252,2,1,18 +2025-03-11T12:40:52.763381,479392852,65388,213,32.4829372526,20.7130795863,-57.185286535805,2,1,18 +2025-03-11T12:40:52.779006,479392852,65388,213,32.70440109374,20.944516366905,-57.59319635276,2,1,18 +2025-03-11T12:40:52.794631,479392852,65388,213,32.93528892812,21.171348381615,-58.010343557855,2,1,18 +2025-03-11T12:40:52.810256,479392852,65388,213,33.17088875912,21.39818854929,-58.42287636089,2,1,18 +2025-03-11T12:40:52.825881,479392852,65388,213,33.4017765935,21.629641635825,-58.82617855679,2,1,18 +2025-03-11T12:40:52.841506,479392852,65388,213,33.62324043464,21.856457344605,-59.23869101681,2,1,18 +2025-03-11T12:40:52.857131,479392852,65388,213,33.8494162724,22.069417990875,-59.64653345477,2,1,18 +2025-03-11T12:40:52.872756,479392852,65388,213,34.08030410678,22.30087107741,-60.08680511519,2,1,18 +2025-03-11T12:40:52.888381,479392852,65388,213,34.30176794792,22.541550001665,-60.494752012145,2,1,18 +2025-03-11T12:40:52.904006,479392852,65388,213,34.50438380258,22.76371202676,-60.88411289282,2,1,18 +2025-03-11T12:40:52.919631,479392852,65388,213,34.72584764372,22.97204344824,-61.273445277515,2,1,18 +2025-03-11T12:40:52.935256,479392852,65388,213,34.94259948824,23.17574564493,-61.671994707335,2,1,18 +2025-03-11T12:40:52.950881,479392852,65388,213,35.17348732262,23.388714444165,-62.075222743235,2,1,18 +2025-03-11T12:40:52.966506,479392852,65388,213,35.404375157,23.624788602525,-62.4831646622,2,1,18 +2025-03-11T12:40:52.982131,479392852,65388,213,35.6164150049,23.851588005375,-62.872557644885,2,1,18 +2025-03-11T12:40:52.997756,479392852,65388,213,35.81903085956,24.059886814995,-63.257241722495,2,1,18 +2025-03-11T12:40:53.013381,479392852,65388,213,36.0404947007,24.26359716465,-63.641934384125,2,1,18 +2025-03-11T12:40:53.029006,479392852,65388,213,36.24311055536,24.476517046095,-64.008152269475,2,1,18 +2025-03-11T12:40:53.044631,479392852,65388,213,36.44572641002,24.68019478389,-64.392817807085,2,1,18 +2025-03-11T12:40:53.060256,479392852,65388,213,36.66719025116,24.883905133545,-64.786752834845,2,1,18 +2025-03-11T12:40:53.075881,479392852,65388,213,36.89336608892,25.10148685164,-65.16226553135,2,1,18 +2025-03-11T12:40:53.091506,479392852,65388,213,37.08655795034,25.31901149898,-65.53773076082,2,1,18 +2025-03-11T12:40:53.107131,479392852,65388,213,37.289173805,25.513447093125,-65.908495669235,2,1,18 +2025-03-11T12:40:53.122756,479392852,65388,213,37.5012136529,25.712520065025,-66.27929267966,2,1,18 +2025-03-11T12:40:53.138381,479392852,65388,213,37.69911751094,25.91156857803,-66.65006934707,2,1,18 +2025-03-11T12:40:53.154006,479392852,65388,213,37.9017333656,26.110625244,-67.002368063225,2,1,18 +2025-03-11T12:40:53.169631,479392852,65388,213,38.0902132304,26.309657451075,-67.36850998556,2,1,18 +2025-03-11T12:40:53.185256,479392852,65388,213,38.29282908506,26.517956260695,-67.74395169704,2,1,18 +2025-03-11T12:40:53.200881,479392852,65388,213,38.48602094648,26.716996620735,-68.096236851185,2,1,18 +2025-03-11T12:40:53.216506,479392852,65388,213,38.67450081128,26.89754454051,-68.44381988126,2,1,18 +2025-03-11T12:40:53.232131,479392852,65388,213,38.84884468622,27.07806800139,-68.77289783606,2,1,18 +2025-03-11T12:40:53.247756,479392852,65388,213,39.04203654764,27.28635050508,-69.115977704075,2,1,18 +2025-03-11T12:40:53.263381,479392852,65388,213,39.23522840906,27.490011936945,-69.46828139822,2,1,18 +2025-03-11T12:40:53.279006,479392852,65388,213,39.409572284,27.665914326,-69.77885608076,2,1,18 +2025-03-11T12:40:53.294631,479392852,65388,213,39.59334015218,27.83721194916,-70.112531700635,2,1,18 +2025-03-11T12:40:53.310256,479392852,65388,213,39.78182001698,28.027002012585,-70.437045895385,2,1,18 +2025-03-11T12:40:53.325881,479392852,65388,213,39.96558788516,28.216783923045,-70.793901590585,2,1,18 +2025-03-11T12:40:53.341506,479392852,65388,213,40.13521976348,28.401920302785,-71.14147603664,2,1,18 +2025-03-11T12:40:53.357131,479392852,65388,213,40.30956363842,28.55009626089,-71.456560662245,2,1,18 +2025-03-11T12:40:53.372756,479392852,65388,213,40.48861950998,28.730627874735,-71.75791829966,2,1,18 +2025-03-11T12:40:53.388381,479392852,65388,213,40.66767538154,28.89267520128,-72.0823076924,2,1,18 +2025-03-11T12:40:53.404006,479392852,65388,213,40.85144324972,29.068593896265,-72.38365357082,2,1,18 +2025-03-11T12:40:53.419631,479392852,65388,213,41.0352111179,29.258375806725,-72.71278216763,2,1,18 +2025-03-11T12:40:53.435256,479392852,65388,213,41.20484299622,29.443512186465,-73.051114247555,2,1,18 +2025-03-11T12:40:53.450881,479392852,65388,213,41.36976287792,29.61939826959,-73.370917734215,2,1,18 +2025-03-11T12:40:53.466506,479392852,65388,213,41.54881874948,29.772203452485,-73.676785314695,2,1,18 +2025-03-11T12:40:53.482131,479392852,65388,213,41.7184506278,29.929613401275,-73.991900239295,2,1,18 +2025-03-11T12:40:53.497756,479392852,65388,213,41.87865851288,30.105491331435,-74.288591029625,2,1,18 +2025-03-11T12:40:53.513381,479392852,65388,213,42.03886639796,30.281369261595,-74.566797087695,2,1,18 +2025-03-11T12:40:53.529006,479392852,65388,213,42.1896502898,30.4341255267,-74.854139249885,2,1,18 +2025-03-11T12:40:53.544631,479392852,65388,213,42.32629819178,30.591478404735,-75.14147960906,2,1,18 +2025-03-11T12:40:53.560256,479392852,65388,213,42.48179408024,30.75810603828,-75.419641806125,2,1,18 +2025-03-11T12:40:53.575881,479392852,65388,213,42.64200196532,30.910878609315,-75.71161871339,2,1,18 +2025-03-11T12:40:53.591506,479392852,65388,213,42.8022098504,31.06365118035,-75.99897443759,2,1,18 +2025-03-11T12:40:53.607131,479392852,65388,213,42.9671297321,31.2071897607,-76.2724363136,2,1,18 +2025-03-11T12:40:53.622756,479392852,65388,213,43.12733761718,31.36458340356,-76.5598105778,2,1,18 +2025-03-11T12:40:53.638381,479392852,65388,213,43.28283350564,31.512726749805,-76.82403506567,2,1,18 +2025-03-11T12:40:53.654006,479392852,65388,213,43.42890540086,31.665474861945,-77.08826453153,2,1,18 +2025-03-11T12:40:53.669631,479392852,65388,213,43.57497729608,31.81360190226,-77.338611908195,2,1,18 +2025-03-11T12:40:53.685256,479392852,65388,213,43.7210491913,31.943244655275,-77.584263941795,2,1,18 +2025-03-11T12:40:53.700881,479392852,65388,213,43.85298509666,32.08672616487,-77.82995125238,2,1,18 +2025-03-11T12:40:53.716506,479392852,65388,213,43.99905699188,32.225611061535,-78.08488273211,2,1,18 +2025-03-11T12:40:53.732131,479392852,65388,213,44.13570489386,32.35523750862,-78.32127883757,2,1,18 +2025-03-11T12:40:53.747756,479392852,65388,213,44.2629288026,32.484847649775,-78.571524930215,2,1,18 +2025-03-11T12:40:53.763381,479392852,65388,213,44.4042887012,32.632966537125,-78.821865525875,2,1,18 +2025-03-11T12:40:53.779006,479392852,65388,213,44.54093660318,32.78107727151,-79.07219934053,2,1,18 +2025-03-11T12:40:53.794631,479392852,65388,213,44.65873651868,32.910671106735,-79.30856832197,2,1,18 +2025-03-11T12:40:53.810256,479392852,65388,213,44.77653643418,33.044886013785,-79.54495584341,2,1,18 +2025-03-11T12:40:53.825881,479392852,65388,213,44.92732032602,33.17915799159,-79.77676964882,2,1,18 +2025-03-11T12:40:53.841506,479392852,65388,213,45.063968228,33.30416336685,-80.00390484815,2,1,18 +2025-03-11T12:40:53.857131,479392852,65388,213,45.1817681435,33.433757202075,-80.235652646525,2,1,18 +2025-03-11T12:40:53.872756,479392852,65388,213,45.30899205224,33.55412519958,-80.45813456078,2,1,18 +2025-03-11T12:40:53.888381,479392852,65388,213,45.43150396436,33.669863972295,-80.657485238705,2,1,18 +2025-03-11T12:40:53.904006,479392852,65388,213,45.54459188324,33.799449654555,-80.852256791555,2,1,18 +2025-03-11T12:40:53.919631,479392852,65388,213,45.6529678055,33.92902718385,-81.079369844855,2,1,18 +2025-03-11T12:40:53.935256,479392852,65388,213,45.76134372776,34.030878282195,-81.30175047509,2,1,18 +2025-03-11T12:40:53.950881,479392852,65388,213,45.87914364326,34.13274568647,-81.514902301205,2,1,18 +2025-03-11T12:40:53.966506,479392852,65388,213,46.006367552,34.234629396675,-81.72806768933,2,1,18 +2025-03-11T12:40:53.982131,479392852,65388,213,46.11474347426,34.33648049502,-81.941205953435,2,1,18 +2025-03-11T12:40:53.997695,479392856,65384,214,46.2184073999,34.442944512225,-82.154355976535,2,1,18 +2025-03-11T12:40:54.013320,479392856,65384,214,46.33149531878,34.544803763535,-82.339773923255,2,1,18 +2025-03-11T12:40:54.028945,479392856,65384,214,46.43515924442,34.674373139865,-82.516047181835,2,1,18 +2025-03-11T12:40:54.044570,479392856,65384,214,46.53882317006,34.79007930072,-82.68764363735,2,1,18 +2025-03-11T12:40:54.060195,479392856,65384,214,46.63306310246,34.878042724695,-82.868357656985,2,1,18 +2025-03-11T12:40:54.075820,479392856,65384,214,46.74143902472,34.97065167939,-83.058352925765,2,1,18 +2025-03-11T12:40:54.091445,479392856,65384,214,46.84039095374,35.05862325633,-83.239073726405,2,1,18 +2025-03-11T12:40:54.107070,479392856,65384,214,46.92049489628,35.151183293235,-83.410543576895,2,1,18 +2025-03-11T12:40:54.122695,479392856,65384,214,47.01473482868,35.253009932685,-83.5820708504,2,1,18 +2025-03-11T12:40:54.138320,479392856,65384,214,47.12311075094,35.350239959205,-83.748978743855,2,1,18 +2025-03-11T12:40:54.153945,479392856,65384,214,47.20321469348,35.438178924285,-83.91580887128,2,1,18 +2025-03-11T12:40:54.169570,479392856,65384,214,47.2786066394,35.521488664575,-84.077992494635,2,1,18 +2025-03-11T12:40:54.185195,479392856,65384,214,47.36813457518,35.60482286376,-84.23557527794,2,1,18 +2025-03-11T12:40:54.200820,479392856,65384,214,47.45766251096,35.688157062945,-84.38853687818,2,1,18 +2025-03-11T12:40:54.216445,479392856,65384,214,47.54247845012,35.780725252815,-84.541528777415,2,1,18 +2025-03-11T12:40:54.232070,479392856,65384,214,47.62258239266,35.868664217895,-84.685252989515,2,1,18 +2025-03-11T12:40:54.247695,479392856,65384,214,47.69797433858,35.94735288636,-84.833554523675,2,1,18 +2025-03-11T12:40:54.263320,479392856,65384,214,47.79221427098,36.01221095121,-84.963342829595,2,1,18 +2025-03-11T12:40:54.278945,479392856,65384,214,47.88174220676,36.07243979127,-85.11159054677,2,1,18 +2025-03-11T12:40:54.294570,479392856,65384,214,47.94299816282,36.15110400084,-85.232144639525,2,1,18 +2025-03-11T12:40:54.310195,479392856,65384,214,48.00425411888,36.22052606676,-85.33417692002,2,1,18 +2025-03-11T12:40:54.325820,479392856,65384,214,48.06551007494,36.294569204505,-85.45933365584,2,1,18 +2025-03-11T12:40:54.341445,479392856,65384,214,48.13147802762,36.36399942339,-85.58909981573,2,1,18 +2025-03-11T12:40:54.357070,479392856,65384,214,48.21158197016,36.42421195752,-85.718849238635,2,1,18 +2025-03-11T12:40:54.372695,479392856,65384,214,48.28226191946,36.50289247302,-85.834795710335,2,1,18 +2025-03-11T12:40:54.388320,479392856,65384,214,48.3388058789,36.563064242325,-85.95064767902,2,1,18 +2025-03-11T12:40:54.403945,479392856,65384,214,48.39063784172,36.613985715015,-86.061834603635,2,1,18 +2025-03-11T12:40:54.419570,479392856,65384,214,48.4330458113,36.664890881775,-86.16376560011,2,1,18 +2025-03-11T12:40:54.435195,479392856,65384,214,48.49430176736,36.725070804045,-86.26113961754,2,1,18 +2025-03-11T12:40:54.450820,479392856,65384,214,48.56498171666,36.77140381677,-86.363092760045,2,1,18 +2025-03-11T12:40:54.466445,479392856,65384,214,48.60738968624,36.82230898353,-86.460402573455,2,1,18 +2025-03-11T12:40:54.482070,479392856,65384,214,48.64037366258,36.87319784436,-86.539214092595,2,1,18 +2025-03-11T12:40:54.497695,479392856,65384,214,48.68278163216,36.919481939295,-86.599535901485,2,1,18 +2025-03-11T12:40:54.513320,479392856,65384,214,48.7393255916,36.965790493125,-86.68760515178,2,1,18 +2025-03-11T12:40:54.528945,479392856,65384,214,48.77702156456,37.00744536327,-86.775628738055,2,1,18 +2025-03-11T12:40:54.544570,479392856,65384,214,48.82414153076,37.049116539345,-86.86366588634,2,1,18 +2025-03-11T12:40:54.560195,479392856,65384,214,48.87126149696,37.104650930895,-86.924031556235,2,1,18 +2025-03-11T12:40:54.575820,479392856,65384,214,48.91838146316,37.141701035145,-86.99356543226,2,1,18 +2025-03-11T12:40:54.591445,479392856,65384,214,48.94665344288,37.17409745571,-87.06767482733,2,1,18 +2025-03-11T12:40:54.607070,479392856,65384,214,48.9749254226,37.188009588975,-87.137088879335,2,1,18 +2025-03-11T12:40:54.622695,479392856,65384,214,49.00319740232,37.22964815319,-87.17888707295,2,1,18 +2025-03-11T12:40:54.638320,479392856,65384,214,49.03618137866,37.26205272672,-87.234518516765,2,1,18 +2025-03-11T12:40:54.653945,479392856,65384,214,49.06445335838,37.294449147285,-87.290143179575,2,1,18 +2025-03-11T12:40:54.669570,479392856,65384,214,49.08330134486,37.331450333745,-87.327288088115,2,1,18 +2025-03-11T12:40:54.685195,479392856,65384,214,49.10686132796,37.363838601345,-87.37366360379,2,1,18 +2025-03-11T12:40:54.700820,479392856,65384,214,49.13042131106,37.386984725295,-87.410759673335,2,1,18 +2025-03-11T12:40:54.716445,479392856,65384,214,49.14926929754,37.396259480805,-87.447793341875,2,1,18 +2025-03-11T12:40:54.732070,479392856,65384,214,49.1634052874,37.414768227,-87.5125844078,2,1,18 +2025-03-11T12:40:54.747695,479392856,65384,214,49.17754127726,37.414792685895,-87.540331849205,2,1,18 +2025-03-11T12:40:54.763320,479392856,65384,214,49.19638926374,37.424067441405,-87.558880785485,2,1,18 +2025-03-11T12:40:54.778945,479392856,65384,214,49.20581325698,37.43794696281,-87.577434699755,2,1,18 +2025-03-11T12:40:54.794570,479392856,65384,214,49.21523725022,37.46568969969,-87.586801867895,2,1,18 +2025-03-11T12:40:54.810195,479392856,65384,214,49.23879723332,37.46110939269,-87.600680782115,2,1,18 +2025-03-11T12:40:54.825820,479392856,65384,214,49.25293322318,37.44727063611,-87.614509054325,2,1,18 +2025-03-11T12:40:54.841445,479392856,65384,214,49.26235721642,37.461150157515,-87.6191994194,2,1,18 +2025-03-11T12:40:54.857070,479392856,65384,214,49.2576452198,37.475005220025,-87.628490624525,2,1,18 +2025-03-11T12:40:54.872695,479392856,65384,214,49.25293322318,37.461133851585,-87.633049406585,2,1,18 +2025-03-11T12:40:54.888320,479392856,65384,214,49.24822122656,37.45188355497,-87.61452081332,2,1,18 +2025-03-11T12:40:54.903945,479392856,65384,214,49.23879723332,37.447246177215,-87.60524634518,2,1,18 +2025-03-11T12:40:54.919570,479392856,65384,214,49.24350922994,37.451875402005,-87.586786933925,2,1,18 +2025-03-11T12:40:54.935195,479392856,65384,214,49.23879723332,37.447246177215,-87.56827688066,2,1,18 +2025-03-11T12:40:54.950820,479392856,65384,214,49.23879723332,37.44262510539,-87.56825834066,2,1,18 +2025-03-11T12:40:54.966445,479392856,65384,214,49.2340852367,37.424132665125,-87.549692667395,2,1,18 +2025-03-11T12:40:54.982070,479392856,65384,214,49.21994924684,37.39638177528,-87.52183398599,2,1,18 +2025-03-11T12:40:54.997695,479392856,65384,214,49.1869652705,37.387082560875,-87.49864352363,2,1,18 +2025-03-11T12:40:55.013320,479392856,65384,214,49.15869329078,37.377791499435,-87.47083865921,2,1,18 +2025-03-11T12:40:55.028945,479392856,65384,214,49.13513330768,37.354645375485,-87.424500223535,2,1,18 +2025-03-11T12:40:55.044570,479392856,65384,214,49.1162853212,37.32226526085,-87.35502557354,2,1,18 +2025-03-11T12:40:55.060195,479392856,65384,214,49.09743733472,37.29450621804,-87.29943301274,2,1,18 +2025-03-11T12:40:55.075820,479392856,65384,214,49.06445335838,37.27134378816,-87.262323381185,2,1,18 +2025-03-11T12:40:55.091445,479392856,65384,214,49.0456053719,37.238963673525,-87.234439378775,2,1,18 +2025-03-11T12:40:55.107070,479392856,65384,214,49.02675738542,37.20658355889,-87.169585911845,2,1,18 +2025-03-11T12:40:55.122695,479392856,65384,214,49.01733339218,37.174219750185,-87.10936718999,2,1,18 +2025-03-11T12:40:55.138320,479392856,65384,214,48.97963741922,37.14180702369,-87.05372896517,2,1,18 +2025-03-11T12:40:55.153945,479392856,65384,214,48.93251745302,37.109377991265,-86.984213629145,2,1,18 +2025-03-11T12:40:55.169570,479392856,65384,214,48.89482148006,37.05848097747,-86.928501244325,2,1,18 +2025-03-11T12:40:55.185195,479392856,65384,214,48.87126149696,37.02609270987,-86.85439863026,2,1,18 +2025-03-11T12:40:55.200820,479392856,65384,214,48.83827752062,37.007551351815,-86.76647452499,2,1,18 +2025-03-11T12:40:55.216445,479392856,65384,214,48.78173356118,36.96586386981,-86.69228736389,2,1,18 +2025-03-11T12:40:55.232070,479392856,65384,214,48.73461359498,36.905708406435,-86.6180396048,2,1,18 +2025-03-11T12:40:55.247695,479392856,65384,214,48.68278163216,36.86865014922,-86.53001421551,2,1,18 +2025-03-11T12:40:55.263320,479392856,65384,214,48.64037366258,36.81774498246,-86.44194676823,2,1,18 +2025-03-11T12:40:55.278945,479392856,65384,214,48.58854169976,36.762202437945,-86.33536248668,2,1,18 +2025-03-11T12:40:55.294570,479392856,65384,214,48.53670973694,36.70665989343,-86.23802057126,2,1,18 +2025-03-11T12:40:55.310195,479392856,65384,214,48.4801657775,36.65110919595,-86.1452930579,2,1,18 +2025-03-11T12:40:55.325820,479392856,65384,214,48.42362181806,36.60480064212,-86.03411789228,2,1,18 +2025-03-11T12:40:55.341445,479392856,65384,214,48.37178985524,36.549258097605,-85.92753361073,2,1,18 +2025-03-11T12:40:55.357070,479392856,65384,214,48.29639790932,36.484432644615,-85.830120710285,2,1,18 +2025-03-11T12:40:55.372695,479392856,65384,214,48.23514195326,36.41963165052,-85.723485786725,2,1,18 +2025-03-11T12:40:55.388320,479392856,65384,214,48.1738859972,36.345588512775,-85.60295023397,2,1,18 +2025-03-11T12:40:55.403945,479392856,65384,214,48.126766031,36.27619090575,-85.4732111981,2,1,18 +2025-03-11T12:40:55.419570,479392856,65384,214,48.0560860817,36.2067525339,-85.352680623335,2,1,18 +2025-03-11T12:40:55.435195,479392856,65384,214,47.98069413578,36.14192708091,-85.213677075305,2,1,18 +2025-03-11T12:40:55.450820,479392856,65384,214,47.91943817972,36.077126086815,-85.08393623642,2,1,18 +2025-03-11T12:40:55.466445,479392856,65384,214,47.8440462338,36.021542777475,-84.97269686678,2,1,18 +2025-03-11T12:40:55.482070,479392856,65384,214,47.76394229126,35.93822488422,-84.842854743875,2,1,18 +2025-03-11T12:40:55.497695,479392856,65384,214,47.67441435548,35.85951175686,-84.68529050057,2,1,18 +2025-03-11T12:40:55.513320,479392856,65384,214,47.59431041294,35.78081493543,-84.54160336847,2,1,18 +2025-03-11T12:40:55.528945,479392856,65384,214,47.52834246026,35.702142572895,-84.379451847125,2,1,18 +2025-03-11T12:40:55.544570,479392856,65384,214,47.44823851772,35.614203607815,-84.23110645196,2,1,18 +2025-03-11T12:40:55.560195,479392856,65384,214,47.35399858532,35.540103399315,-84.07355396765,2,1,18 +2025-03-11T12:40:55.575820,479392856,65384,214,47.26918264616,35.46139842492,-83.920617688415,2,1,18 +2025-03-11T12:40:55.591445,479392856,65384,214,47.17965471038,35.368822082085,-83.76299782511,2,1,18 +2025-03-11T12:40:55.607070,479392856,65384,214,47.08070278136,35.26698728967,-83.60070613673,2,1,18 +2025-03-11T12:40:55.622695,479392856,65384,214,46.98646284896,35.169781722045,-83.41533385403,2,1,18 +2025-03-11T12:40:55.638320,479392856,65384,214,46.90635890642,35.072600613315,-83.229981914345,2,1,18 +2025-03-11T12:40:55.653945,479392856,65384,214,46.80269498078,34.970757667935,-83.05844107883,2,1,18 +2025-03-11T12:40:55.669570,479392856,65384,214,46.70374305176,34.86892287552,-82.882285841255,2,1,18 +2025-03-11T12:40:55.685195,479392856,65384,214,46.60479112274,34.75322486763,-82.701453800615,2,1,18 +2025-03-11T12:40:55.700820,479392856,65384,214,46.5011271971,34.646760850425,-82.51140969284,2,1,18 +2025-03-11T12:40:55.716445,479392856,65384,214,46.39275127484,34.558772967555,-82.32143296406,2,1,18 +2025-03-11T12:40:55.732070,479392856,65384,214,46.30793533568,34.456962634035,-82.13605570337,2,1,18 +2025-03-11T12:40:55.747695,479392856,65384,214,46.19955941342,34.359732607515,-81.941420711525,2,1,18 +2025-03-11T12:40:55.763320,479392856,65384,214,46.08647149454,34.239389068905,-81.73282268948,2,1,18 +2025-03-11T12:40:55.778945,479392856,65384,214,45.96395958242,34.12365029619,-81.51960846236,2,1,18 +2025-03-11T12:40:55.794570,479392856,65384,214,45.85087166354,34.01254890123,-81.329532252575,2,1,18 +2025-03-11T12:40:55.810195,479392856,65384,214,45.74249574128,33.87835030011,-81.111643025405,2,1,18 +2025-03-11T12:40:55.825820,479392856,65384,214,45.61998382916,33.75799045557,-80.898410258285,2,1,18 +2025-03-11T12:40:55.841445,479392856,65384,214,45.5116079069,33.64227614175,-80.68521637418,2,1,18 +2025-03-11T12:40:55.857070,479392856,65384,214,45.39851998802,33.53117474679,-80.47203424907,2,1,18 +2025-03-11T12:40:55.872695,479392856,65384,214,45.26187208604,33.410790443355,-80.258781138935,2,1,18 +2025-03-11T12:40:55.888320,479392856,65384,214,45.12993618068,33.30427750836,-80.03172688061,2,1,18 +2025-03-11T12:40:55.903945,479392856,65384,214,45.00742426856,33.17467552017,-79.79997230123,2,1,18 +2025-03-11T12:40:55.919570,479392856,65384,214,44.88020035982,33.03120216354,-79.586640053105,2,1,18 +2025-03-11T12:40:55.935195,479392856,65384,214,44.74826445446,32.896962797595,-79.336368639455,2,1,18 +2025-03-11T12:40:55.950820,479392856,65384,214,44.6163285491,32.7719655753,-79.076891939675,2,1,18 +2025-03-11T12:40:55.966445,479392856,65384,214,44.49381663698,32.656226802585,-78.835950614165,2,1,18 +2025-03-11T12:40:55.982070,479392856,65384,214,44.357168735,32.5266003555,-78.571827410315,2,1,18 +2025-03-11T12:40:55.997695,479392856,65384,214,44.22052083302,32.369247477465,-78.344562430985,2,1,18 +2025-03-11T12:40:56.013320,479392856,65384,214,44.08387293104,32.225757814905,-78.10348952246,2,1,18 +2025-03-11T12:40:56.028945,479392856,65384,214,43.94251303244,32.08225999938,-77.839303917605,2,1,18 +2025-03-11T12:40:56.044570,479392856,65384,214,43.81057712708,31.920294202485,-77.561194165565,2,1,18 +2025-03-11T12:40:56.060195,479392856,65384,214,43.66921722848,31.781417458785,-77.28778473458,2,1,18 +2025-03-11T12:40:56.075820,479392856,65384,214,43.52314533326,31.65177470577,-77.055996250175,2,1,18 +2025-03-11T12:40:56.091445,479392856,65384,214,43.38178543466,31.52214010572,-76.78262389919,2,1,18 +2025-03-11T12:40:56.107070,479392856,65384,214,43.23100154282,31.35552062514,-76.527574398455,2,1,18 +2025-03-11T12:40:56.122695,479392856,65384,214,43.07550565436,31.21199835072,-76.24950490139,2,1,18 +2025-03-11T12:40:56.138320,479392856,65384,214,42.9200097659,31.054612860825,-75.962137418195,2,1,18 +2025-03-11T12:40:56.153945,479392856,65384,214,42.76922587406,30.87413016477,-75.67930519907,2,1,18 +2025-03-11T12:40:56.169570,479392856,65384,214,42.61844198222,30.71675282784,-75.39194449688,2,1,18 +2025-03-11T12:40:56.185195,479392856,65384,214,42.45823409714,30.55935918498,-75.11381259881,2,1,18 +2025-03-11T12:40:56.200820,479392856,65384,214,42.29802621206,30.406586613945,-74.821835691545,2,1,18 +2025-03-11T12:40:56.216445,479392856,65384,214,42.12839433374,30.239934521505,-74.515926053075,2,1,18 +2025-03-11T12:40:56.232070,479392856,65384,214,41.9540504588,30.087137491575,-74.22854998586,2,1,18 +2025-03-11T12:40:56.247695,479392856,65384,214,41.79384257372,29.91588063324,-73.936498918595,2,1,18 +2025-03-11T12:40:56.263320,479392856,65384,214,41.63834668526,29.749252999695,-73.635230806205,2,1,18 +2025-03-11T12:40:56.278945,479392856,65384,214,41.47813880018,29.582617213185,-73.34319827894,2,1,18 +2025-03-11T12:40:56.294570,479392856,65384,214,41.3179309151,29.4021182112,-73.02800421635,2,1,18 +2025-03-11T12:40:56.310195,479392856,65384,214,41.14358704016,29.235457965795,-72.703603064615,2,1,18 +2025-03-11T12:40:56.325820,479392856,65384,214,40.94568318212,29.068756955565,-72.397652740115,2,1,18 +2025-03-11T12:40:56.341445,479392856,65384,214,40.78547529704,28.902121169055,-72.06865074833,2,1,18 +2025-03-11T12:40:56.357070,479392856,65384,214,40.6111314221,28.740081995475,-71.744268136595,2,1,18 +2025-03-11T12:40:56.372695,479392856,65384,214,40.43678754716,28.55493746277,-71.41979282486,2,1,18 +2025-03-11T12:40:56.388320,479392856,65384,214,40.26244367222,28.369792930065,-71.095317513125,2,1,18 +2025-03-11T12:40:56.403945,479392856,65384,214,40.0928117939,28.1985197658,-70.752419870135,2,1,18 +2025-03-11T12:40:56.419570,479392856,65384,214,39.9043319291,28.008729702375,-70.43252685845,2,1,18 +2025-03-11T12:40:56.435195,479392856,65384,214,39.7158520643,27.8281817826,-70.09880737757,2,1,18 +2025-03-11T12:40:56.450820,479392856,65384,214,39.54622018598,27.647666474685,-69.76511502071,2,1,18 +2025-03-11T12:40:56.466445,479392856,65384,214,39.37658830766,27.44866687947,-69.417484954655,2,1,18 +2025-03-11T12:40:56.482070,479392856,65384,214,39.18810844286,27.268118959695,-69.083765473775,2,1,18 +2025-03-11T12:40:56.497695,479392856,65384,214,38.99020458482,27.07831259034,-68.740752984755,2,1,18 +2025-03-11T12:40:56.513320,479392856,65384,214,38.80172472002,26.870038239615,-68.39305871468,2,1,18 +2025-03-11T12:40:56.528945,479392856,65384,214,38.60382086198,26.67098972661,-68.05000914566,2,1,18 +2025-03-11T12:40:56.544570,479392856,65384,214,38.41062900056,26.48119151022,-67.71162462071,2,1,18 +2025-03-11T12:40:56.560195,479392856,65384,214,38.22214913576,26.300643590445,-67.354799224505,2,1,18 +2025-03-11T12:40:56.575820,479392856,65384,214,38.03366927096,26.096990311545,-66.984017579105,2,1,18 +2025-03-11T12:40:56.591445,479392856,65384,214,37.82634141968,25.88868334896,-66.613190269685,2,1,18 +2025-03-11T12:40:56.607070,479392856,65384,214,37.62843756164,25.67577162048,-66.24697916534,2,1,18 +2025-03-11T12:40:56.622695,479392856,65384,214,37.4305337036,25.4813441793,-65.880842220995,2,1,18 +2025-03-11T12:40:56.638320,479392856,65384,214,37.23262984556,25.300779953595,-65.510139713585,2,1,18 +2025-03-11T12:40:56.653945,479392856,65384,214,37.01587800104,25.115562044205,-65.13477035909,2,1,18 +2025-03-11T12:40:56.669570,479392856,65384,214,36.81326214638,24.91188430641,-64.75934718761,2,1,18 +2025-03-11T12:40:56.685195,479392856,65384,214,36.61535828834,24.70821472158,-64.374688431005,2,1,18 +2025-03-11T12:40:56.700820,479392856,65384,214,36.4174544303,24.499924064925,-64.00849586666,2,1,18 +2025-03-11T12:40:56.716445,479392856,65384,214,36.20070258578,24.28235865276,-63.63761791523,2,1,18 +2025-03-11T12:40:56.732070,479392856,65384,214,35.98395074126,24.064793240595,-63.24825523154,2,1,18 +2025-03-11T12:40:56.747695,479392856,65384,214,35.76248690012,23.84259860364,-62.858867226845,2,1,18 +2025-03-11T12:40:56.763320,479392856,65384,214,35.5457350556,23.615791047825,-62.47408864622,2,1,18 +2025-03-11T12:40:56.778945,479392856,65384,214,35.32898321108,23.39822563566,-62.0754835964,2,1,18 +2025-03-11T12:40:56.794570,479392856,65384,214,35.11223136656,23.189902367145,-61.66767326045,2,1,18 +2025-03-11T12:40:56.810195,479392856,65384,214,34.91432750852,22.967748495015,-61.273697977715,2,1,18 +2025-03-11T12:40:56.825820,479392856,65384,214,34.69286366738,22.74555385806,-60.86582524076,2,1,18 +2025-03-11T12:40:56.841445,479392856,65384,214,34.46668782962,22.527972139965,-60.46720662893,2,1,18 +2025-03-11T12:40:56.857070,479392856,65384,214,34.23579999524,22.29651905343,-60.04541970077,2,1,18 +2025-03-11T12:40:56.872695,479392856,65384,214,34.01904815072,22.07433256944,-59.632932561755,2,1,18 +2025-03-11T12:40:56.888320,479392856,65384,214,33.8022963062,21.856767157275,-59.238948695,2,1,18 +2025-03-11T12:40:56.903945,479392856,65384,214,33.57140847182,21.639177286215,-58.840323302165,2,1,18 +2025-03-11T12:40:56.919570,479392856,65384,214,33.3546566273,21.407748658575,-58.42779908315,2,1,18 +2025-03-11T12:40:56.935195,479392856,65384,214,33.12376879292,21.180916643865,-57.992167145795,2,1,18 +2025-03-11T12:40:56.950820,479392856,65384,214,32.88816896192,20.949455404365,-57.57037343663,2,1,18 +2025-03-11T12:40:56.966445,479392856,65384,214,32.66670512078,20.694913264635,-57.13926500435,2,1,18 +2025-03-11T12:40:56.982070,479392856,65384,214,32.43110528978,20.44958880966,-56.717415675185,2,1,18 +2025-03-11T12:40:56.997695,479392856,65384,214,32.2002174554,20.227377866775,-56.314150559285,2,1,18 +2025-03-11T12:40:57.013320,479392856,65384,214,31.97404161764,20.00055400503,-55.89238895213,2,1,18 +2025-03-11T12:40:57.028945,479392856,65384,214,31.74315378326,19.778343062145,-55.46139673784,2,1,18 +2025-03-11T12:40:57.044570,479392856,65384,214,31.50284195564,19.523768310555,-55.025639998475,2,1,18 +2025-03-11T12:40:57.060195,479392856,65384,214,31.26253012802,19.278435702615,-54.58992033911,2,1,18 +2025-03-11T12:40:57.075820,479392856,65384,214,31.0222183004,19.0377241665,-54.14035567055,2,1,18 +2025-03-11T12:40:57.091445,479392856,65384,214,30.77248247954,18.806238468105,-53.70005688611,2,1,18 +2025-03-11T12:40:57.107070,479392856,65384,214,30.53217065192,18.570148003815,-53.255131940615,2,1,18 +2025-03-11T12:40:57.122695,479392856,65384,214,30.28714682768,18.320186171085,-52.828629326375,2,1,18 +2025-03-11T12:40:57.138320,479392856,65384,214,30.04683500006,18.074853563145,-52.406773216205,2,1,18 +2025-03-11T12:40:57.153945,479392856,65384,214,29.80652317244,17.829520955205,-51.938705275385,2,1,18 +2025-03-11T12:40:57.169570,479392856,65384,214,29.5614993482,17.57493805065,-51.484457022755,2,1,18 +2025-03-11T12:40:57.185195,479392856,65384,214,29.29762753748,17.329564677885,-51.039461092235,2,1,18 +2025-03-11T12:40:57.200820,479392856,65384,214,29.04789171662,17.065731476715,-50.57592661247,2,1,18 +2025-03-11T12:40:57.216445,479392856,65384,214,28.81229188562,16.82040702174,-50.107865452655,2,1,18 +2025-03-11T12:40:57.232070,479392856,65384,214,28.55784406814,16.57042888308,-49.635137445755,2,1,18 +2025-03-11T12:40:57.247695,479392856,65384,214,28.29868425404,16.320442591455,-49.18088739011,2,1,18 +2025-03-11T12:40:57.263320,479392856,65384,214,28.03952443994,16.075077371655,-48.73127705753,2,1,18 +2025-03-11T12:40:57.278945,479392856,65384,214,27.79921261232,15.811260476415,-48.26313495671,2,1,18 +2025-03-11T12:40:57.294570,479392856,65384,214,27.54005279822,15.547410969315,-47.78572336574,2,1,18 +2025-03-11T12:40:57.310195,479392856,65384,214,27.28089298412,15.292803605865,-47.303727671705,2,1,18 +2025-03-11T12:40:57.325820,479392856,65384,214,27.03115716326,15.028970404695,-46.826329642745,2,1,18 +2025-03-11T12:40:57.341445,479392856,65384,214,26.77670934578,14.76512905056,-46.372030748105,2,1,18 +2025-03-11T12:40:57.357070,479392856,65384,214,26.52697352492,14.496674777565,-45.913098911405,2,1,18 +2025-03-11T12:40:57.372695,479392856,65384,214,26.27723770406,14.25594693552,-45.435793582445,2,1,18 +2025-03-11T12:40:57.388320,479392856,65384,214,25.99922990348,14.00130696021,-44.958391947455,2,1,18 +2025-03-11T12:40:57.403945,479392856,65384,214,25.73535809276,13.737449300145,-44.48097357548,2,1,18 +2025-03-11T12:40:57.419570,479392856,65384,214,25.47619827866,13.46897872122,-43.98505871225,2,1,18 +2025-03-11T12:40:57.435195,479392856,65384,214,25.2029024747,13.205104755225,-43.49376322907,2,1,18 +2025-03-11T12:40:57.450820,479392856,65384,214,24.93431866736,12.931996798545,-43.039406911415,2,1,18 +2025-03-11T12:40:57.466445,479392856,65384,214,24.67987084988,12.663534372585,-42.557362378385,2,1,18 +2025-03-11T12:40:57.482070,479392856,65384,214,24.41599903916,12.404297784345,-42.06147781415,2,1,18 +2025-03-11T12:40:57.497695,479392856,65384,214,24.17568721154,12.13585981728,-41.579453624135,2,1,18 +2025-03-11T12:40:57.513320,479392856,65384,214,23.9071034042,11.87199400425,-41.092786105025,2,1,18 +2025-03-11T12:40:57.528945,479392856,65384,214,23.63380760024,11.61274111008,-40.619993894105,2,1,18 +2025-03-11T12:40:57.544570,479392856,65384,214,23.36051179628,11.348867144085,-40.119456044795,2,1,18 +2025-03-11T12:40:57.560195,479392856,65384,214,23.07308000246,11.066484431895,-39.60958132634,2,1,18 +2025-03-11T12:40:57.575820,479392856,65384,214,22.78564820864,10.77023850423,-39.127378086275,2,1,18 +2025-03-11T12:40:57.591445,479392856,65384,214,22.51235240468,10.50174346641,-38.645306429225,2,1,18 +2025-03-11T12:40:57.607070,479392856,65384,214,22.23905660072,10.23324842859,-38.144750039915,2,1,18 +2025-03-11T12:40:57.622695,479392856,65384,214,21.96576079676,9.94626910347,-37.644119490605,2,1,18 +2025-03-11T12:40:57.638320,479392856,65384,214,21.68775299618,9.677765912685,-37.13431395416,2,1,18 +2025-03-11T12:40:57.653945,479392856,65384,214,21.42859318208,9.38156890281,-36.605939569475,2,1,18 +2025-03-11T12:40:57.669570,479392856,65384,214,21.15529737812,9.108452793165,-36.114607006295,2,1,18 +2025-03-11T12:40:57.685195,479392856,65384,214,20.8914255674,8.830731917625,-35.595542366735,2,1,18 +2025-03-11T12:40:57.700820,479392856,65384,214,20.61341776682,8.548365511365,-35.081060027225,2,1,18 +2025-03-11T12:40:57.716445,479392856,65384,214,20.325985973,8.265982799175,-34.575806491835,2,1,18 +2025-03-11T12:40:57.732070,479392856,65384,214,20.03384218256,7.99283407767,-34.06134088931,2,1,18 +2025-03-11T12:40:57.747695,479392856,65384,214,19.74641038874,7.715072437305,-33.560727076985,2,1,18 +2025-03-11T12:40:57.763320,479392856,65384,214,19.47311458478,7.437335255835,-33.02778532622,2,1,18 +2025-03-11T12:40:57.778945,479392856,65384,214,19.17625879772,7.15955730954,-32.508673219625,2,1,18 +2025-03-11T12:40:57.794570,479392856,65384,214,18.89825099714,6.872569831455,-31.98955115705,2,1,18 +2025-03-11T12:40:57.810195,479392856,65384,214,18.62024319656,6.59482449702,-31.46584499141,2,1,18 +2025-03-11T12:40:57.825820,479392856,65384,214,18.34223539598,6.31245809076,-30.937499102705,2,1,18 +2025-03-11T12:40:57.841445,479392856,65384,214,18.05009160554,6.020825081955,-30.436822889375,2,1,18 +2025-03-11T12:40:57.857070,479392856,65384,214,17.76265981172,5.73382129794,-29.940793180115,2,1,18 +2025-03-11T12:40:57.872695,479392856,65384,214,17.48465201114,5.446833819855,-29.407807568345,2,1,18 +2025-03-11T12:40:57.888320,479392856,65384,214,17.20664421056,5.182951700895,-28.893399388835,2,1,18 +2025-03-11T12:40:57.903945,479392856,65384,214,16.91450042012,4.89131869209,-28.38810199244,2,1,18 +2025-03-11T12:40:57.919570,479392856,65384,214,16.63649261954,4.585846926705,-27.8642845868,2,1,18 +2025-03-11T12:40:57.935195,479392856,65384,214,16.3443488291,4.289592846075,-27.34510510121,2,1,18 +2025-03-11T12:40:57.950820,479392856,65384,214,16.04278104542,3.98870138769,-26.82589351361,2,1,18 +2025-03-11T12:40:57.966445,479392856,65384,214,15.77419723808,3.720214502835,-26.29299562385,2,1,18 +2025-03-11T12:40:57.982070,479392856,65384,214,15.48205344764,3.42858149403,-25.759971129065,2,1,18 +2025-03-11T12:40:57.997634,479392860,65380,215,15.18519766058,3.132319260435,-25.236163679405,2,1,18 +2025-03-11T12:40:58.013259,479392860,65380,215,14.89305387014,2.836065179805,-24.69387827849,2,1,18 +2025-03-11T12:40:58.028884,479392860,65380,215,14.6009100797,2.57215860195,-24.15634384064,2,1,18 +2025-03-11T12:40:58.044509,479392860,65380,215,14.30405429264,2.28975958383,-23.600243729525,2,1,18 +2025-03-11T12:40:58.060134,479392860,65380,215,14.02133449544,1.988900737305,-23.08568044901,2,1,18 +2025-03-11T12:40:58.075759,479392860,65380,215,13.73390270162,1.697275881465,-22.557283918295,2,1,18 +2025-03-11T12:40:58.091384,479392860,65380,215,13.43704691456,1.387150432395,-22.033420848635,2,1,18 +2025-03-11T12:40:58.107009,479392860,65380,215,13.1401911275,1.086267126975,-21.48648894365,2,1,18 +2025-03-11T12:40:58.122634,479392860,65380,215,12.84804733706,0.794634118169999,-20.93960089967,2,1,18 +2025-03-11T12:40:58.138259,479392860,65380,215,12.56532753986,0.493775271645001,-20.397310520765,2,1,18 +2025-03-11T12:40:58.153884,479392860,65380,215,12.2684717528,0.2067551817,-19.85967660191,2,1,18 +2025-03-11T12:40:58.169509,479392860,65380,215,11.97632796236,-0.0894988989299996,-19.33125475019,2,1,18 +2025-03-11T12:40:58.185134,479392860,65380,215,11.67004818206,-0.376535294805,-18.784364903195,2,1,18 +2025-03-11T12:40:58.200759,479392860,65380,215,11.38261638824,-0.67278122247,-18.24670746635,2,1,18 +2025-03-11T12:40:58.216384,479392860,65380,215,11.08576060118,-0.97366452789,-17.690533195235,2,1,18 +2025-03-11T12:40:58.232009,479392860,65380,215,10.78890481412,-1.26530568966,-17.14363837025,2,1,18 +2025-03-11T12:40:58.247634,479392860,65380,215,10.49676102368,-1.575422985765,-16.6059185324,2,1,18 +2025-03-11T12:40:58.263259,479392860,65380,215,10.19990523662,-1.867064147535,-16.077508439675,2,1,18 +2025-03-11T12:40:58.278884,479392860,65380,215,9.90304944956,-2.186431740255,-15.54898710695,2,1,18 +2025-03-11T12:40:58.294509,479392860,65380,215,9.60148166588,-2.482702126815,-15.02055169322,2,1,18 +2025-03-11T12:40:58.310134,479392860,65380,215,9.31404987206,-2.77894805448,-14.48751543944,2,1,18 +2025-03-11T12:40:58.325759,479392860,65380,215,9.017194085,-3.084452431725,-13.931322628325,2,1,18 +2025-03-11T12:40:58.341384,479392860,65380,215,8.72033829794,-3.38071466532,-13.379788080275,2,1,18 +2025-03-11T12:40:58.357009,479392860,65380,215,8.42348251088,-3.67235582709,-12.828272072225,2,1,18 +2025-03-11T12:40:58.372634,479392860,65380,215,8.1219147272,-3.96862621365,-12.281351926235,2,1,18 +2025-03-11T12:40:58.388259,479392860,65380,215,7.82034694352,-4.26489660021,-11.73905296331,2,1,18 +2025-03-11T12:40:58.403884,479392860,65380,215,7.51877915984,-4.565788058595,-11.187493094255,2,1,18 +2025-03-11T12:40:58.419509,479392860,65380,215,7.21249937954,-4.85282445447,-10.64060324726,2,1,18 +2025-03-11T12:40:58.435134,479392860,65380,215,6.90621959924,-5.158345137645,-10.093639240265,2,1,18 +2025-03-11T12:40:58.450759,479392860,65380,215,6.60465181556,-5.44075230873,-9.556017080405,2,1,18 +2025-03-11T12:40:58.466384,479392860,65380,215,6.3077960285,-5.746256685975,-9.004445452355,2,1,18 +2025-03-11T12:40:58.482009,479392860,65380,215,6.00622824482,-6.04714814436,-8.466749132495,2,1,18 +2025-03-11T12:40:58.497634,479392860,65380,215,5.71408445438,-6.35264436864,-7.91518428545,2,1,18 +2025-03-11T12:40:58.513259,479392860,65380,215,5.42194066394,-6.644277377445,-7.36829624147,2,1,18 +2025-03-11T12:40:58.528884,479392860,65380,215,5.13450887012,-6.94976544876,-6.82598054156,2,1,18 +2025-03-11T12:40:58.544509,479392860,65380,215,4.84236507968,-7.259882744865,-6.27901833758,2,1,18 +2025-03-11T12:40:58.560134,479392860,65380,215,4.53137330276,-7.565411581005,-5.73204754958,2,1,18 +2025-03-11T12:40:58.575759,479392860,65380,215,4.21566952922,-7.875569641935,-5.175809074445,2,1,18 +2025-03-11T12:40:58.591384,479392860,65380,215,3.91881374216,-8.167210803705,-4.64739898172,2,1,18 +2025-03-11T12:40:58.607009,479392860,65380,215,3.62666995172,-8.46808595616,-4.10047385774,2,1,18 +2025-03-11T12:40:58.622634,479392860,65380,215,3.34395015452,-8.76432373086,-3.558202018835,2,1,18 +2025-03-11T12:40:58.638259,479392860,65380,215,3.03767037422,-9.05598119856,-3.01129363184,2,1,18 +2025-03-11T12:40:58.653884,479392860,65380,215,2.73610259054,-9.36149372877,-2.459715222785,2,1,18 +2025-03-11T12:40:58.669509,479392860,65380,215,2.43453480686,-9.671627330805,-1.91736063986,2,1,18 +2025-03-11T12:40:58.685134,479392860,65380,215,2.12354302994,-9.97253509512,-1.384271941055,2,1,18 +2025-03-11T12:40:58.700759,479392860,65380,215,1.8313992395,-10.264168103925,-0.837383897075,2,1,18 +2025-03-11T12:40:58.716384,479392860,65380,215,1.53454345244,-10.56043033752,-0.276606982895,2,1,18 +2025-03-11T12:40:58.732009,479392860,65380,215,1.23297566876,-10.861321795905,0.279574069225,2,1,18 +2025-03-11T12:40:58.747634,479392860,65380,215,0.95496786818,-11.171414633115,0.83575829632,2,1,18 +2025-03-11T12:40:58.763259,479392860,65380,215,0.65811208112,-11.472297938535,1.38731138437,2,1,18 +2025-03-11T12:40:58.778884,479392860,65380,215,0.34240830758,-11.791698143115,1.90199629192,2,1,18 +2025-03-11T12:40:58.794509,479392860,65380,215,0.0314165306599999,-12.069500548305,2.453477022985,2,1,18 +2025-03-11T12:40:58.810134,479392860,65380,215,-0.2654392564,-12.35652063825,3.00035330797,2,1,18 +2025-03-11T12:40:58.825759,479392860,65380,215,-0.55758304684,-12.67125900618,3.53809168582,2,1,18 +2025-03-11T12:40:58.841384,479392860,65380,215,-0.84972683728,-12.96751308681,4.0849982698,2,1,18 +2025-03-11T12:40:58.857009,479392860,65380,215,-1.14658262434,-13.24991210493,4.641098380915,2,1,18 +2025-03-11T12:40:58.872634,479392860,65380,215,-1.4434384114,-13.55079541035,5.20651501816,2,1,18 +2025-03-11T12:40:58.888259,479392860,65380,215,-1.74500619508,-13.87479222786,5.748925221085,2,1,18 +2025-03-11T12:40:58.903884,479392860,65380,215,-2.04186198214,-14.17567553328,6.27737239381,2,1,18 +2025-03-11T12:40:58.919509,479392860,65380,215,-2.33400577258,-14.47192961391,6.81503661166,2,1,18 +2025-03-11T12:40:58.935134,479392860,65380,215,-2.63557355626,-14.763578928645,7.357317034585,2,1,18 +2025-03-11T12:40:58.950759,479392860,65380,215,-2.92300535008,-15.05058271266,7.881073842235,2,1,18 +2025-03-11T12:40:58.966384,479392860,65380,215,-3.2104371439,-15.346828640325,8.42797364521,2,1,18 +2025-03-11T12:40:58.982009,479392860,65380,215,-3.50729293096,-15.64309087392,8.974887010195,2,1,18 +2025-03-11T12:40:58.997634,479392860,65380,215,-3.80886071464,-15.93011911683,9.50790652699,2,1,18 +2025-03-11T12:40:59.013259,479392860,65380,215,-4.11042849832,-16.23563164704,10.031757837655,2,1,18 +2025-03-11T12:40:59.028884,479392860,65380,215,-4.40257228876,-16.53188572767,10.569422055505,2,1,18 +2025-03-11T12:40:59.044509,479392860,65380,215,-4.69942807582,-16.818905817615,11.10705597436,2,1,18 +2025-03-11T12:40:59.060134,479392860,65380,215,-4.99157186626,-17.12902311372,11.64477581221,2,1,18 +2025-03-11T12:40:59.075759,479392860,65380,215,-5.27429166346,-17.42526088842,12.17318410192,2,1,18 +2025-03-11T12:40:59.091384,479392860,65380,215,-5.55701146066,-17.726119734945,12.715474480825,2,1,18 +2025-03-11T12:40:59.107009,479392860,65380,215,-5.85386724772,-18.017760896715,13.25312693968,2,1,18 +2025-03-11T12:40:59.122634,479392860,65380,215,-6.1554350314,-18.29092592415,13.77222728728,2,1,18 +2025-03-11T12:40:59.138259,479392860,65380,215,-6.44757882184,-18.591801076605,14.305288862065,2,1,18 +2025-03-11T12:40:59.153884,479392860,65380,215,-6.73972261228,-18.88343408541,14.842934539915,2,1,18 +2025-03-11T12:40:59.169509,479392860,65380,215,-7.03186640272,-19.193551381515,15.38527556083,2,1,18 +2025-03-11T12:40:59.185134,479392860,65380,215,-7.32401019316,-19.489805462145,15.909076229485,2,1,18 +2025-03-11T12:40:59.200759,479392860,65380,215,-7.63028997346,-19.76759971437,16.41895953196,2,1,18 +2025-03-11T12:40:59.216384,479392860,65380,215,-7.91772176728,-20.054603498385,16.956579888805,2,1,18 +2025-03-11T12:40:59.232009,479392860,65380,215,-8.20044156448,-20.341599129435,17.503435830775,2,1,18 +2025-03-11T12:40:59.247634,479392860,65380,215,-8.49729735154,-20.633240291205,18.04108828963,2,1,18 +2025-03-11T12:40:59.263259,479392860,65380,215,-8.78472914536,-20.934107290695,18.56490071728,2,1,18 +2025-03-11T12:40:59.278884,479392860,65380,215,-9.06744894256,-21.221102921745,19.107135476185,2,1,18 +2025-03-11T12:40:59.294509,479392860,65380,215,-9.35488073638,-21.512727777585,19.61704727464,2,1,18 +2025-03-11T12:40:59.310134,479392860,65380,215,-9.64702452682,-21.790497570915,20.13615260023,2,1,18 +2025-03-11T12:40:59.325759,479392860,65380,215,-9.92974432402,-22.086735345615,20.669182073005,2,1,18 +2025-03-11T12:40:59.341384,479392860,65380,215,-10.2077521246,-22.369101751875,21.183664412515,2,1,18 +2025-03-11T12:40:59.357009,479392860,65380,215,-10.49989591504,-22.656113688855,21.68894326891,2,1,18 +2025-03-11T12:40:59.372634,479392860,65380,215,-10.78261571224,-22.933867176255,22.212656215555,2,1,18 +2025-03-11T12:40:59.388259,479392860,65380,215,-11.0559115162,-23.23470971685,22.74569066632,2,1,18 +2025-03-11T12:40:59.403884,479392860,65380,215,-11.3386313134,-23.53094749155,23.260235406835,2,1,18 +2025-03-11T12:40:59.419509,479392860,65380,215,-11.6213511106,-23.8179431226,23.77474306735,2,1,18 +2025-03-11T12:40:59.435134,479392860,65380,215,-11.89935891118,-24.095688457035,24.29844923299,2,1,18 +2025-03-11T12:40:59.450759,479392860,65380,215,-12.17265471514,-24.364183494855,24.80824798843,2,1,18 +2025-03-11T12:40:59.466384,479392860,65380,215,-12.46479850558,-24.632711144535,25.30883150176,2,1,18 +2025-03-11T12:40:59.482009,479392860,65380,215,-12.74751830278,-24.90584356011,25.80017762695,2,1,18 +2025-03-11T12:40:59.497634,479392860,65380,215,-13.0113901135,-25.197427651125,26.31005552038,2,1,18 +2025-03-11T12:40:59.513259,479392860,65380,215,-13.28468591746,-25.465922688945,26.824475458885,2,1,18 +2025-03-11T12:40:59.528884,479392860,65380,215,-13.56269371804,-25.74366802338,27.338939258395,2,1,18 +2025-03-11T12:40:59.544509,479392860,65380,215,-13.84541351524,-26.026042582605,27.83494364665,2,1,18 +2025-03-11T12:40:59.560134,479392860,65380,215,-14.13284530906,-26.31304636662,28.34945808817,2,1,18 +2025-03-11T12:40:59.575759,479392860,65380,215,-14.40614111302,-26.567678188965,28.845337674415,2,1,18 +2025-03-11T12:40:59.591384,479392860,65380,215,-14.67001292374,-26.85002013633,29.34131493865,2,1,18 +2025-03-11T12:40:59.607009,479392860,65380,215,-14.9433087277,-27.1462416051,29.846603751025,2,1,18 +2025-03-11T12:40:59.622634,479392860,65380,215,-15.21189253504,-27.433212777255,30.34722751933,2,1,18 +2025-03-11T12:40:59.638259,479392860,65380,215,-15.485188339,-27.692465671425,30.833883279445,2,1,18 +2025-03-11T12:40:59.653884,479392860,65380,215,-15.75377214634,-27.96095255628,31.311326972425,2,1,18 +2025-03-11T12:40:59.669509,479392860,65380,215,-16.01764395706,-28.23867343182,31.79804333053,2,1,18 +2025-03-11T12:40:59.685134,479392860,65380,215,-16.29565175764,-28.49331340713,32.307793246975,2,1,18 +2025-03-11T12:40:59.700759,479392860,65380,215,-16.57837155484,-28.75258260723,32.82218966749,2,1,18 +2025-03-11T12:40:59.716384,479392860,65380,215,-16.84695536218,-29.01644842026,33.294993637405,2,1,18 +2025-03-11T12:40:59.732009,479392860,65380,215,-17.11553916952,-29.28955637694,33.781698236515,2,1,18 +2025-03-11T12:40:59.747634,479392860,65380,215,-17.38412297686,-29.567285405445,34.268421375625,2,1,18 +2025-03-11T12:40:59.763259,479392860,65380,215,-17.64328279096,-29.812650625245,34.74113762353,2,1,18 +2025-03-11T12:40:59.778884,479392860,65380,215,-17.90244260506,-30.076500132345,35.22779158063,2,1,18 +2025-03-11T12:40:59.794509,479392860,65380,215,-18.15217842592,-30.349575477165,35.719090238785,2,1,18 +2025-03-11T12:40:59.810134,479392860,65380,215,-18.42076223326,-30.61806236202,36.20115511483,2,1,18 +2025-03-11T12:40:59.825759,479392860,65380,215,-18.6893460406,-30.877307103225,36.67856172781,2,1,18 +2025-03-11T12:40:59.841384,479392860,65380,215,-18.94379385808,-31.136527385535,37.146705631645,2,1,18 +2025-03-11T12:40:59.857009,479392860,65380,215,-19.19824167556,-31.395747667845,37.61484953548,2,1,18 +2025-03-11T12:40:59.872634,479392860,65380,215,-19.45740148966,-31.659597174945,38.087639943385,2,1,18 +2025-03-11T12:40:59.888259,479392860,65380,215,-19.73069729362,-31.92347114094,38.551208328175,2,1,18 +2025-03-11T12:40:59.903884,479392860,65380,215,-19.98043311448,-32.17806219846,39.019326911005,2,1,18 +2025-03-11T12:40:59.919509,479392860,65380,215,-20.2443049252,-32.42805664305,39.48744729685,2,1,18 +2025-03-11T12:40:59.935134,479392860,65380,215,-20.50817673592,-32.69653537494,39.9417782935,2,1,18 +2025-03-11T12:40:59.950759,479392860,65380,215,-20.7626245534,-32.9465135136,40.39602156814,2,1,18 +2025-03-11T12:40:59.966384,479392860,65380,215,-20.9982243844,-33.191837968575,40.85946154489,2,1,18 +2025-03-11T12:40:59.982009,479392860,65380,215,-21.23853621202,-33.437170576515,41.32752948571,2,1,18 +2025-03-11T12:40:59.997634,479392860,65380,215,-21.4929840295,-33.68252764335,41.76326948809,2,1,18 +2025-03-11T12:41:00.013259,479392860,65380,215,-21.74743184698,-33.92326363836,42.21747568273,2,1,18 +2025-03-11T12:41:00.028884,479392860,65380,215,-22.00187966446,-34.159378561545,42.6809057035,2,1,18 +2025-03-11T12:41:00.044509,479392860,65380,215,-22.2469034887,-34.418582537925,43.12593013,2,1,18 +2025-03-11T12:41:00.060134,479392860,65380,215,-22.49192731294,-34.67316544248,43.56169365037,2,1,18 +2025-03-11T12:41:00.075759,479392860,65380,215,-22.73695113718,-34.909264059735,44.00662537687,2,1,18 +2025-03-11T12:41:00.091384,479392860,65380,215,-22.98197496142,-35.17308910794,44.447047160305,2,1,18 +2025-03-11T12:41:00.107009,479392860,65380,215,-23.2128627958,-35.413784338125,44.896598266855,2,1,18 +2025-03-11T12:41:00.122634,479392860,65380,215,-23.44375063018,-35.659100640135,45.355410279535,2,1,18 +2025-03-11T12:41:00.138259,479392860,65380,215,-23.68877445442,-35.89519925739,45.8049631891,2,1,18 +2025-03-11T12:41:00.153884,479392860,65380,215,-23.92908628204,-36.14053186533,46.22681929927,2,1,18 +2025-03-11T12:41:00.169509,479392860,65380,215,-24.16939810966,-36.35813804232,46.65780653557,2,1,18 +2025-03-11T12:41:00.185134,479392860,65380,215,-24.40028594404,-36.58497005703,47.074953740665,2,1,18 +2025-03-11T12:41:00.200759,479392860,65380,215,-24.64059777166,-36.82106052132,47.48290922164,2,1,18 +2025-03-11T12:41:00.216384,479392860,65380,215,-24.88090959928,-37.05715098561,47.92321298407,2,1,18 +2025-03-11T12:41:00.232009,479392860,65380,215,-25.1212214269,-37.2932414499,48.3635167465,2,1,18 +2025-03-11T12:41:00.247634,479392860,65380,215,-25.34739726466,-37.529307455295,48.78993661672,2,1,18 +2025-03-11T12:41:00.263259,479392860,65380,215,-25.56414910918,-37.742251795635,49.211629041865,2,1,18 +2025-03-11T12:41:00.278884,479392860,65380,215,-25.79032494694,-37.96907565738,49.619527099825,2,1,18 +2025-03-11T12:41:00.294509,479392860,65380,215,-26.01178878808,-38.21437565346,50.022871353715,2,1,18 +2025-03-11T12:41:00.310134,479392860,65380,215,-26.24738861908,-38.441215821135,50.440025339815,2,1,18 +2025-03-11T12:41:00.325759,479392860,65380,215,-26.4641404636,-38.672644448775,50.83406482657,2,1,18 +2025-03-11T12:41:00.341384,479392860,65380,215,-26.69031630136,-38.89946831052,51.246584067595,2,1,18 +2025-03-11T12:41:00.357009,479392860,65380,215,-26.90235614926,-39.121646641545,51.64520087641,2,1,18 +2025-03-11T12:41:00.372634,479392860,65380,215,-27.13324398364,-39.339236512605,52.04844745231,2,1,18 +2025-03-11T12:41:00.388259,479392860,65380,215,-27.3594198214,-39.561439302525,52.460948153335,2,1,18 +2025-03-11T12:41:00.403884,479392860,65380,215,-27.5714596693,-39.769754418075,52.85026697602,2,1,18 +2025-03-11T12:41:00.419509,479392860,65380,215,-27.77407552396,-39.987295371345,53.26271523202,2,1,18 +2025-03-11T12:41:00.435134,479392860,65380,215,-27.98611537186,-40.195610486895,53.68438233616,2,1,18 +2025-03-11T12:41:00.450759,479392860,65380,215,-28.21229120962,-40.408571133165,54.06449767573,2,1,18 +2025-03-11T12:41:00.466384,479392860,65380,215,-28.4196190609,-40.61687809575,54.41684025289,2,1,18 +2025-03-11T12:41:00.482009,479392860,65380,215,-28.63637090542,-40.843685651565,54.79699765045,2,1,18 +2025-03-11T12:41:00.497634,479392860,65380,215,-28.85312274994,-41.06125106373,55.181739151075,2,1,18 +2025-03-11T12:41:00.513259,479392860,65380,215,-29.05102660798,-41.29264707951,55.561887964615,2,1,18 +2025-03-11T12:41:00.528884,479392860,65380,215,-29.25364246264,-41.49170374548,55.928050229965,2,1,18 +2025-03-11T12:41:00.544509,479392860,65380,215,-29.46097031392,-41.681526420765,56.30342456245,2,1,18 +2025-03-11T12:41:00.560134,479392860,65380,215,-29.67301016182,-41.880599392665,56.67884275594,2,1,18 +2025-03-11T12:41:00.575759,479392860,65380,215,-29.87091401986,-42.084268977495,57.054259146415,2,1,18 +2025-03-11T12:41:00.591384,479392860,65380,215,-30.0688178779,-42.29255963415,57.42969407689,2,1,18 +2025-03-11T12:41:00.607009,479392860,65380,215,-30.27143373256,-42.49161630012,57.791235159175,2,1,18 +2025-03-11T12:41:00.622634,479392860,65380,215,-30.47876158384,-42.69530219088,58.16666511166,2,1,18 +2025-03-11T12:41:00.638259,479392860,65380,215,-30.67195344526,-42.898963622745,58.51434762274,2,1,18 +2025-03-11T12:41:00.653884,479392860,65380,215,-30.87928129654,-43.09802844168,58.852789570705,2,1,18 +2025-03-11T12:41:00.669509,479392860,65380,215,-31.07247315796,-43.28782665807,59.21428001098,2,1,18 +2025-03-11T12:41:00.685134,479392860,65380,215,-31.25152902952,-43.47297934374,59.561868019045,2,1,18 +2025-03-11T12:41:00.700759,479392860,65380,215,-31.44472089094,-43.67201970378,59.91415317319,2,1,18 +2025-03-11T12:41:00.716384,479392860,65380,215,-31.6237767625,-43.871035604925,60.252554435125,2,1,18 +2025-03-11T12:41:00.732009,479392860,65380,215,-31.8122566273,-44.046962452875,60.6001189252,2,1,18 +2025-03-11T12:41:00.747634,479392860,65380,215,-32.00544848872,-44.227518525615,60.93846637015,2,1,18 +2025-03-11T12:41:00.763259,479392860,65380,215,-32.1892163569,-44.4034372206,61.281402896155,2,1,18 +2025-03-11T12:41:00.778884,479392860,65380,215,-32.36827222846,-44.593210978095,61.61976707809,2,1,18 +2025-03-11T12:41:00.794509,479392860,65380,215,-32.56146408988,-44.77838812266,61.953511879975,2,1,18 +2025-03-11T12:41:00.810134,479392860,65380,215,-32.74994395468,-44.968178186085,62.28264725779,2,1,18 +2025-03-11T12:41:00.825759,479392860,65380,215,-32.92428782962,-45.130217359665,62.579302771135,2,1,18 +2025-03-11T12:41:00.841384,479392860,65380,215,-33.08920771132,-45.30610344279,62.89448507473,2,1,18 +2025-03-11T12:41:00.857009,479392860,65380,215,-33.26355158626,-45.48662690367,63.209699480335,2,1,18 +2025-03-11T12:41:00.872634,479392860,65380,215,-33.44731945444,-45.65792452683,63.53413273408,2,1,18 +2025-03-11T12:41:00.888259,479392860,65380,215,-33.62166332938,-45.824584772235,63.87239743501,2,1,18 +2025-03-11T12:41:00.903884,479392860,65380,215,-33.7912952077,-45.9958579365,64.17832561348,2,1,18 +2025-03-11T12:41:00.919509,479392860,65380,215,-33.95150309278,-46.167114794835,64.470376680745,2,1,18 +2025-03-11T12:41:00.935134,479392860,65380,215,-34.12584696772,-46.33377504024,64.780914283285,2,1,18 +2025-03-11T12:41:00.950759,479392860,65380,215,-34.2860548528,-46.495789754925,65.07292827055,2,1,18 +2025-03-11T12:41:00.966384,479392860,65380,215,-34.4509747345,-46.657812622575,65.378812588015,2,1,18 +2025-03-11T12:41:00.982009,479392860,65380,215,-34.60647062296,-46.82444025612,65.689323066535,2,1,18 +2025-03-11T12:41:00.997634,479392860,65380,215,-34.76667850804,-46.97259175533,65.958175518475,2,1,18 +2025-03-11T12:41:01.013259,479392860,65380,215,-34.92688639312,-47.11150111089,66.25933917187,2,1,18 +2025-03-11T12:41:01.028884,479392860,65380,215,-35.09180627482,-47.27352397854,66.55135994014,2,1,18 +2025-03-11T12:41:01.044509,479392860,65380,215,-35.2520141599,-47.435538693225,66.843373927405,2,1,18 +2025-03-11T12:41:01.060134,479392860,65380,215,-35.39808605512,-47.597528949015,67.116882839395,2,1,18 +2025-03-11T12:41:01.075759,479392860,65380,215,-35.54886994696,-47.745664142295,67.39958527852,2,1,18 +2025-03-11T12:41:01.091384,479392860,65380,215,-35.69494184218,-47.898412254435,67.66381474438,2,1,18 +2025-03-11T12:41:01.107009,479392860,65380,215,-35.84572573402,-48.046547447715,67.918790085115,2,1,18 +2025-03-11T12:41:01.122634,479392860,65380,215,-35.99650962586,-48.203924784645,68.187666055045,2,1,18 +2025-03-11T12:41:01.138259,479392860,65380,215,-36.13315752784,-48.347414447205,68.470329611155,2,1,18 +2025-03-11T12:41:01.153884,479392860,65380,215,-36.27451742644,-48.486291190905,68.729875492945,2,1,18 +2025-03-11T12:41:01.169509,479392860,65380,215,-36.4300133149,-48.648297752625,68.984913234685,2,1,18 +2025-03-11T12:41:01.185134,479392860,65380,215,-36.57608521012,-48.801045864765,69.230657968285,2,1,18 +2025-03-11T12:41:01.200759,479392860,65380,215,-36.689173129,-48.91676833155,69.471585731785,2,1,18 +2025-03-11T12:41:01.216384,479392860,65380,215,-36.8305330276,-49.041781859775,69.72645481051,2,1,18 +2025-03-11T12:41:01.232009,479392860,65380,215,-36.97660492282,-49.176045684615,69.985988933305,2,1,18 +2025-03-11T12:41:01.247634,479392860,65380,215,-37.11796482142,-49.324164571965,70.22246597977,2,1,18 +2025-03-11T12:41:01.263259,479392860,65380,215,-37.24518873016,-49.449153641295,70.44958761709,2,1,18 +2025-03-11T12:41:01.278884,479392860,65380,215,-37.37712463552,-49.57415086359,70.676716035415,2,1,18 +2025-03-11T12:41:01.294509,479392860,65380,215,-37.5137725375,-49.694535167025,70.90845387781,2,1,18 +2025-03-11T12:41:01.310134,479392860,65380,215,-37.64099644624,-49.82414530818,71.13559405513,2,1,18 +2025-03-11T12:41:01.325759,479392860,65380,215,-37.76350835836,-49.949126224545,71.36733009451,2,1,18 +2025-03-11T12:41:01.341384,479392860,65380,215,-37.88130827386,-50.074098987945,71.58519580369,2,1,18 +2025-03-11T12:41:01.357009,479392860,65380,215,-38.00382018598,-50.18059561701,71.812236500005,2,1,18 +2025-03-11T12:41:01.372634,479392860,65380,215,-38.11219610824,-50.300931002655,72.03469129024,2,1,18 +2025-03-11T12:41:01.388259,479392860,65380,215,-38.2205720305,-50.425887460125,72.23405870515,2,1,18 +2025-03-11T12:41:01.403884,479392860,65380,215,-38.32894795276,-50.54622284577,72.438028763125,2,1,18 +2025-03-11T12:41:01.419509,479392860,65380,215,-38.44203587164,-50.65732424073,72.632726155975,2,1,18 +2025-03-11T12:41:01.435134,479392860,65380,215,-38.55983578714,-50.768433788655,72.832051512895,2,1,18 +2025-03-11T12:41:01.450759,479392860,65380,215,-38.66349971278,-50.87489780586,73.026716803735,2,1,18 +2025-03-11T12:41:01.466384,479392860,65380,215,-38.76716363842,-50.981361823065,73.23524564377,2,1,18 +2025-03-11T12:41:01.482009,479392860,65380,215,-38.87082756406,-51.09706798392,73.425326831545,2,1,18 +2025-03-11T12:41:01.497634,479392860,65380,215,-38.98862747956,-51.19431431637,73.615354202335,2,1,18 +2025-03-11T12:41:01.513259,479392860,65380,215,-39.08286741196,-51.28689881217,73.809950311165,2,1,18 +2025-03-11T12:41:01.528884,479392860,65380,215,-39.19124333422,-51.41185526964,73.99545417688,2,1,18 +2025-03-11T12:41:01.544509,479392860,65380,215,-39.28548326662,-51.50443976544,74.18080791958,2,1,18 +2025-03-11T12:41:01.560134,479392860,65380,215,-39.37972319902,-51.58778211759,74.34763985002,2,1,18 +2025-03-11T12:41:01.575759,479392860,65380,215,-39.48809912128,-51.671148928635,74.50062857428,2,1,18 +2025-03-11T12:41:01.591384,479392860,65380,215,-39.57291506044,-51.77758033398,74.672160825775,2,1,18 +2025-03-11T12:41:01.607009,479392860,65380,215,-39.66715499284,-51.865543757955,74.83439011315,2,1,18 +2025-03-11T12:41:01.622634,479392860,65380,215,-39.75668292862,-51.944256885315,74.982711990325,2,1,18 +2025-03-11T12:41:01.638259,479392860,65380,215,-39.83207487454,-52.027566625605,75.15413797981,2,1,18 +2025-03-11T12:41:01.653884,479392860,65380,215,-39.90746682046,-52.11549743772,75.3117189601,2,1,18 +2025-03-11T12:41:01.669509,479392860,65380,215,-39.99699475624,-52.21269485238,75.47397854647,2,1,18 +2025-03-11T12:41:01.685134,479392860,65380,215,-40.06296270892,-52.291367214915,75.61302415249,2,1,18 +2025-03-11T12:41:01.700759,479392860,65380,215,-40.14777864808,-52.356208973835,75.76128362866,2,1,18 +2025-03-11T12:41:01.716384,479392860,65380,215,-40.22788259062,-52.43952686709,75.92347403302,2,1,18 +2025-03-11T12:41:01.732009,479392860,65380,215,-40.30327453654,-52.518215535555,76.04404846879,2,1,18 +2025-03-11T12:41:01.747634,479392860,65380,215,-40.3880904757,-52.592299438125,76.1738602927,2,1,18 +2025-03-11T12:41:01.763259,479392860,65380,215,-40.458770425,-52.643253522675,76.294316707465,2,1,18 +2025-03-11T12:41:01.778884,479392860,65380,215,-40.53416237092,-52.717321119315,76.4194937863,2,1,18 +2025-03-11T12:41:01.794509,479392860,65380,215,-40.59070633036,-52.78673503227,76.563109933375,2,1,18 +2025-03-11T12:41:01.810134,479392860,65380,215,-40.65667428304,-52.86078632298,76.692894633265,2,1,18 +2025-03-11T12:41:01.825759,479392860,65380,215,-40.72735423234,-52.934845766655,76.818064931095,2,1,18 +2025-03-11T12:41:01.841384,479392860,65380,215,-40.78389819178,-52.990396464135,76.92465599365,2,1,18 +2025-03-11T12:41:01.857009,479392860,65380,215,-40.84515414784,-53.041334242755,77.017371748015,2,1,18 +2025-03-11T12:41:01.872634,479392860,65380,215,-40.91112210052,-53.09228017434,77.119336649515,2,1,18 +2025-03-11T12:41:01.888259,479392860,65380,215,-40.97237805658,-53.147839024785,77.23055567614,2,1,18 +2025-03-11T12:41:01.903884,479392860,65380,215,-41.0242100194,-53.208002641125,77.304810216235,2,1,18 +2025-03-11T12:41:01.919509,479392860,65380,215,-41.0713299856,-53.272779176325,77.36521296613,2,1,18 +2025-03-11T12:41:01.935134,479392860,65380,215,-41.10902595856,-53.32367619012,77.44865244934,2,1,18 +2025-03-11T12:41:01.950759,479392860,65380,215,-41.15143392814,-53.369960285055,77.53670135662,2,1,18 +2025-03-11T12:41:01.966384,479392860,65380,215,-41.20797788758,-53.407026695235,77.62935470998,2,1,18 +2025-03-11T12:41:01.982009,479392860,65380,215,-41.25038585716,-53.43482650287,77.721950640325,2,1,18 +2025-03-11T12:41:01.997558,479392864,65375,216,-41.29279382674,-53.48573166963,77.800775721475,2,1,18 +2025-03-11T12:41:02.013183,479392864,65375,216,-41.33520179632,-53.532015764565,77.879582262625,2,1,18 +2025-03-11T12:41:02.028808,479392864,65375,216,-41.37289776928,-53.56442849106,77.93059930438,2,1,18 +2025-03-11T12:41:02.044433,479392864,65375,216,-41.41530573886,-53.58760722687,78.00931314553,2,1,18 +2025-03-11T12:41:02.060058,479392864,65375,216,-41.46242570506,-53.638520546595,78.08352382462,2,1,18 +2025-03-11T12:41:02.075683,479392864,65375,216,-41.4954096814,-53.680167263775,78.13457116537,2,1,18 +2025-03-11T12:41:02.091308,479392864,65375,216,-41.52839365774,-53.712571837305,78.19482379225,2,1,18 +2025-03-11T12:41:02.106933,479392864,65375,216,-41.5425296476,-53.7495648708,78.250446652045,2,1,18 +2025-03-11T12:41:02.122558,479392864,65375,216,-41.57080162732,-53.781961291365,78.296828948725,2,1,18 +2025-03-11T12:41:02.138183,479392864,65375,216,-41.59907360704,-53.800494496455,78.333913259275,2,1,18 +2025-03-11T12:41:02.153808,479392864,65375,216,-41.62734558676,-53.81440662972,78.37560021289,2,1,18 +2025-03-11T12:41:02.169433,479392864,65375,216,-41.64619357324,-53.837544600705,78.4034471353,2,1,18 +2025-03-11T12:41:02.185058,479392864,65375,216,-41.65090556986,-53.851415969145,78.43585781776,2,1,18 +2025-03-11T12:41:02.200683,479392864,65375,216,-41.66975355634,-53.86531179648,78.48215239243,2,1,18 +2025-03-11T12:41:02.216308,479392864,65375,216,-41.6838895462,-53.883820542675,78.50535281077,2,1,18 +2025-03-11T12:41:02.231933,479392864,65375,216,-41.70273753268,-53.893095298185,78.54238647931,2,1,18 +2025-03-11T12:41:02.247558,479392864,65375,216,-41.71687352254,-53.897740828905,78.54704654539,2,1,18 +2025-03-11T12:41:02.263183,479392864,65375,216,-41.72629751578,-53.90237820666,78.5470786474,2,1,18 +2025-03-11T12:41:02.278808,479392864,65375,216,-41.73572150902,-53.92087879989,78.561029918605,2,1,18 +2025-03-11T12:41:02.294433,479392864,65375,216,-41.74985749888,-53.92552433061,78.584174716945,2,1,18 +2025-03-11T12:41:02.310058,479392864,65375,216,-41.7545694955,-53.925532483575,78.60266623021,2,1,18 +2025-03-11T12:41:02.325683,479392864,65375,216,-41.74985749888,-53.930145402435,78.602677989205,2,1,18 +2025-03-11T12:41:02.341308,479392864,65375,216,-41.74514550226,-53.934758321295,78.59344738207,2,1,18 +2025-03-11T12:41:02.356933,479392864,65375,216,-41.74514550226,-53.93013724947,78.61191357433,2,1,18 +2025-03-11T12:41:02.372558,479392864,65375,216,-41.76399348874,-53.925548789505,78.61192215835,2,1,18 +2025-03-11T12:41:02.388183,479392864,65375,216,-41.76399348874,-53.916306645855,78.588779163025,2,1,18 +2025-03-11T12:41:02.403808,479392864,65375,216,-41.74514550226,-53.916274033995,78.579509672875,2,1,18 +2025-03-11T12:41:02.419433,479392864,65375,216,-41.72629751578,-53.91162035031,78.551736910465,2,1,18 +2025-03-11T12:41:02.435058,479392864,65375,216,-41.71687352254,-53.90236190073,78.496232071675,2,1,18 +2025-03-11T12:41:02.450683,479392864,65375,216,-41.69802553606,-53.879223929745,78.48224869846,2,1,18 +2025-03-11T12:41:02.466308,479392864,65375,216,-41.6838895462,-53.846851968075,78.44050792786,2,1,18 +2025-03-11T12:41:02.481933,479392864,65375,216,-41.66975355634,-53.832964293705,78.40808368339,2,1,18 +2025-03-11T12:41:02.497558,479392864,65375,216,-41.6603295631,-53.832947987775,78.366479473795,2,1,18 +2025-03-11T12:41:02.513183,479392864,65375,216,-41.63676958,-53.805180792,78.315501315055,2,1,18 +2025-03-11T12:41:02.528808,479392864,65375,216,-41.60849760028,-53.772784371435,78.27374020144,2,1,18 +2025-03-11T12:41:02.544433,479392864,65375,216,-41.58022562056,-53.74963009452,78.232016167825,2,1,18 +2025-03-11T12:41:02.560058,479392864,65375,216,-41.5660896307,-53.712637061025,78.18563567416,2,1,18 +2025-03-11T12:41:02.575683,479392864,65375,216,-41.5425296476,-53.689490937075,78.130054872355,2,1,18 +2025-03-11T12:41:02.591308,479392864,65375,216,-41.50483367464,-53.652457138755,78.06977692447,2,1,18 +2025-03-11T12:41:02.606933,479392864,65375,216,-41.46713770168,-53.615423340435,78.00487779352,2,1,18 +2025-03-11T12:41:02.622558,479392864,65375,216,-41.43886572196,-53.58302691987,77.93076839845,2,1,18 +2025-03-11T12:41:02.638183,479392864,65375,216,-41.401169749,-53.54599312155,77.861248084435,2,1,18 +2025-03-11T12:41:02.653808,479392864,65375,216,-41.35876177942,-53.518193313915,77.782515703285,2,1,18 +2025-03-11T12:41:02.669433,479392864,65375,216,-41.31164181322,-53.46727999419,77.72216857339,2,1,18 +2025-03-11T12:41:02.685058,479392864,65375,216,-41.27865783688,-53.421012205185,77.65261796038,2,1,18 +2025-03-11T12:41:02.700683,479392864,65375,216,-41.24096186392,-53.393220550515,77.564649994105,2,1,18 +2025-03-11T12:41:02.716308,479392864,65375,216,-41.1891299011,-53.342299077825,77.485811350945,2,1,18 +2025-03-11T12:41:02.731933,479392864,65375,216,-41.1420099349,-53.28214361445,77.42542714105,2,1,18 +2025-03-11T12:41:02.747558,479392864,65375,216,-41.08075397884,-53.22196369218,77.332674306685,2,1,18 +2025-03-11T12:41:02.763183,479392864,65375,216,-41.01478602616,-53.15715454512,77.22603260212,2,1,18 +2025-03-11T12:41:02.778808,479392864,65375,216,-40.94410607686,-53.09695831692,77.11016029042,2,1,18 +2025-03-11T12:41:02.794433,479392864,65375,216,-40.8828501208,-53.03677839465,76.998922723795,2,1,18 +2025-03-11T12:41:02.810058,479392864,65375,216,-40.83101815798,-52.97661477831,76.883077536115,2,1,18 +2025-03-11T12:41:02.825683,479392864,65375,216,-40.77918619516,-52.921072233795,76.7718720715,2,1,18 +2025-03-11T12:41:02.841308,479392864,65375,216,-40.72735423234,-52.85628754563,76.669871893015,2,1,18 +2025-03-11T12:41:02.856933,479392864,65375,216,-40.67552226952,-52.79612392929,76.54016315614,2,1,18 +2025-03-11T12:41:02.872558,479392864,65375,216,-40.60484232022,-52.74516984474,76.419706741375,2,1,18 +2025-03-11T12:41:02.888183,479392864,65375,216,-40.54358636416,-52.67574777882,76.285326179425,2,1,18 +2025-03-11T12:41:02.903808,479392864,65375,216,-40.47290641486,-52.601688335145,76.160155881595,2,1,18 +2025-03-11T12:41:02.919433,479392864,65375,216,-40.38337847908,-52.532217351435,76.03035581668,2,1,18 +2025-03-11T12:41:02.935058,479392864,65375,216,-40.30327453654,-52.453520530005,75.891289867645,2,1,18 +2025-03-11T12:41:02.950683,479392864,65375,216,-40.23259458724,-52.365597870855,75.747579217555,2,1,18 +2025-03-11T12:41:02.966308,479392864,65375,216,-40.1524906447,-52.277658905775,75.60847618852,2,1,18 +2025-03-11T12:41:02.981933,479392864,65375,216,-40.06296270892,-52.21280899389,75.46483111441,2,1,18 +2025-03-11T12:41:02.997558,479392864,65375,216,-39.97814676976,-52.12948294767,75.31649747824,2,1,18 +2025-03-11T12:41:03.013183,479392864,65375,216,-39.8933308306,-52.041535829625,75.154281752875,2,1,18 +2025-03-11T12:41:03.028808,479392864,65375,216,-39.81793888468,-51.967468232985,75.01061994178,2,1,18 +2025-03-11T12:41:03.044433,479392864,65375,216,-39.74725893538,-51.870303430185,74.84838747943,2,1,18 +2025-03-11T12:41:03.060058,479392864,65375,216,-39.65301900298,-51.759234647085,74.67220194286,2,1,18 +2025-03-11T12:41:03.075683,479392864,65375,216,-39.57291506044,-51.67591675383,74.514632721565,2,1,18 +2025-03-11T12:41:03.091308,479392864,65375,216,-39.47867512804,-51.58333225803,74.347763711125,2,1,18 +2025-03-11T12:41:03.106933,479392864,65375,216,-39.38914719226,-51.49537698702,74.176298838625,2,1,18 +2025-03-11T12:41:03.122558,479392864,65375,216,-39.29961925648,-51.39817957236,73.995554519995,2,1,18 +2025-03-11T12:41:03.138183,479392864,65375,216,-39.20066732746,-51.31020799542,73.79172780403,2,1,18 +2025-03-11T12:41:03.153808,479392864,65375,216,-39.09700340182,-51.203743978215,73.62478961158,2,1,18 +2025-03-11T12:41:03.169433,479392864,65375,216,-39.00276346942,-51.09729626694,73.45786498114,2,1,18 +2025-03-11T12:41:03.185058,479392864,65375,216,-38.89438754716,-50.976960881295,73.253894923165,2,1,18 +2025-03-11T12:41:03.200683,479392864,65375,216,-38.78129962828,-50.85199627086,73.04527836112,2,1,18 +2025-03-11T12:41:03.216308,479392864,65375,216,-38.65878771616,-50.75012071362,72.845983303195,2,1,18 +2025-03-11T12:41:03.231933,479392864,65375,216,-38.5504117939,-50.648269615275,72.655950954415,2,1,18 +2025-03-11T12:41:03.247558,479392864,65375,216,-38.44674786826,-50.537184526245,72.46588830664,2,1,18 +2025-03-11T12:41:03.263183,479392864,65375,216,-38.33365994938,-50.42146205946,72.26193000766,2,1,18 +2025-03-11T12:41:03.278808,479392864,65375,216,-38.21586003388,-50.31497358336,72.030274909285,2,1,18 +2025-03-11T12:41:03.294433,479392864,65375,216,-38.08392412852,-50.20383957654,71.807823294025,2,1,18 +2025-03-11T12:41:03.310058,479392864,65375,216,-37.9614122164,-50.09272187565,71.594627606905,2,1,18 +2025-03-11T12:41:03.325683,479392864,65375,216,-37.85774829076,-49.958531427495,71.38598752687,2,1,18 +2025-03-11T12:41:03.341308,479392864,65375,216,-37.73052438202,-49.824300214515,71.17731354181,2,1,18 +2025-03-11T12:41:03.356933,479392864,65375,216,-37.59387648004,-49.690052695605,70.945520079415,2,1,18 +2025-03-11T12:41:03.372558,479392864,65375,216,-37.47136456792,-49.57431392289,70.72768466923,2,1,18 +2025-03-11T12:41:03.388183,479392864,65375,216,-37.36298864566,-49.43087317812,70.495894812865,2,1,18 +2025-03-11T12:41:03.403808,479392864,65375,216,-37.23576473692,-49.30588410879,70.25490962635,2,1,18 +2025-03-11T12:41:03.419433,479392864,65375,216,-37.10854082818,-49.194758254935,70.013980059835,2,1,18 +2025-03-11T12:41:03.435058,479392864,65375,216,-36.97660492282,-49.055897817165,69.75906892312,2,1,18 +2025-03-11T12:41:03.450683,479392864,65375,216,-36.8540930107,-48.917053685325,69.50879253148,2,1,18 +2025-03-11T12:41:03.466308,479392864,65375,216,-36.71744510872,-48.773564022765,69.249234890695,2,1,18 +2025-03-11T12:41:03.481933,479392864,65375,216,-36.56666121688,-48.63004990131,68.98503572383,2,1,18 +2025-03-11T12:41:03.497558,479392864,65375,216,-36.41587732504,-48.505020067155,68.73477426616,2,1,18 +2025-03-11T12:41:03.513183,479392864,65375,216,-36.26038143658,-48.35687672091,68.465928595225,2,1,18 +2025-03-11T12:41:03.528808,479392864,65375,216,-36.1001735515,-48.2087252217,68.19245496022,2,1,18 +2025-03-11T12:41:03.544433,479392864,65375,216,-35.9588136529,-48.06060633435,67.919008449235,2,1,18 +2025-03-11T12:41:03.560058,479392864,65375,216,-35.82216575092,-47.912495599965,67.654811085385,2,1,18 +2025-03-11T12:41:03.575683,479392864,65375,216,-35.68080585232,-47.773618856265,67.386022837465,2,1,18 +2025-03-11T12:41:03.591308,479392864,65375,216,-35.52530996386,-47.611612294545,67.130985095725,2,1,18 +2025-03-11T12:41:03.606933,479392864,65375,216,-35.37452607202,-47.46809817309,66.862164745795,2,1,18 +2025-03-11T12:41:03.622558,479392864,65375,216,-35.21903018356,-47.310712683195,66.588660811795,2,1,18 +2025-03-11T12:41:03.638183,479392864,65375,216,-35.07295828834,-47.139480283755,66.296630087545,2,1,18 +2025-03-11T12:41:03.653808,479392864,65375,216,-34.91746239988,-46.99133693751,66.00005731822,2,1,18 +2025-03-11T12:41:03.669433,479392864,65375,216,-34.7808144979,-46.84784727495,65.703530212915,2,1,18 +2025-03-11T12:41:03.685058,479392864,65375,216,-34.62060661282,-46.68121148844,65.41149768565,2,1,18 +2025-03-11T12:41:03.700683,479392864,65375,216,-34.46039872774,-46.528438917405,65.12414196145,2,1,18 +2025-03-11T12:41:03.716308,479392864,65375,216,-34.30019084266,-46.343318843595,64.832035274185,2,1,18 +2025-03-11T12:41:03.731933,479392864,65375,216,-34.1211349711,-46.1720293734,64.516851167575,2,1,18 +2025-03-11T12:41:03.747558,479392864,65375,216,-33.9562150894,-46.005385433925,64.187842394785,2,1,18 +2025-03-11T12:41:03.763183,479392864,65375,216,-33.7912952077,-45.834120422625,63.89116336345,2,1,18 +2025-03-11T12:41:03.778808,479392864,65375,216,-33.61695133276,-45.672081249045,63.58988666704,2,1,18 +2025-03-11T12:41:03.794433,479392864,65375,216,-33.44731945444,-45.486944869305,63.26541813631,2,1,18 +2025-03-11T12:41:03.810058,479392864,65375,216,-33.26355158626,-45.30178403067,62.92706571337,2,1,18 +2025-03-11T12:41:03.825683,479392864,65375,216,-33.08920771132,-45.13050271344,62.611888387765,2,1,18 +2025-03-11T12:41:03.841308,479392864,65375,216,-32.91486383638,-44.95922139621,62.29671106216,2,1,18 +2025-03-11T12:41:03.856933,479392864,65375,216,-32.73580796482,-44.78331085419,61.967644866355,2,1,18 +2025-03-11T12:41:03.872558,479392864,65375,216,-32.55675209326,-44.59815816852,61.643162773615,2,1,18 +2025-03-11T12:41:03.888183,479392864,65375,216,-32.38240821832,-44.422255779465,61.304860992685,2,1,18 +2025-03-11T12:41:03.903808,479392864,65375,216,-32.20335234676,-44.237103093795,60.95727298462,2,1,18 +2025-03-11T12:41:03.919433,479392864,65375,216,-32.01487248196,-44.070418389495,60.62360912374,2,1,18 +2025-03-11T12:41:03.935058,479392864,65375,216,-31.83110461378,-43.880636479035,60.29448052693,2,1,18 +2025-03-11T12:41:03.950683,479392864,65375,216,-31.6473367456,-43.690854568575,59.960730747055,2,1,18 +2025-03-11T12:41:03.966308,479392864,65375,216,-31.4588568808,-43.487201289675,59.608433833915,2,1,18 +2025-03-11T12:41:03.981933,479392864,65375,216,-31.26566501938,-43.278918785985,59.260732782835,2,1,18 +2025-03-11T12:41:03.997558,479392864,65375,216,-31.06776116134,-43.075249201155,58.908422307685,2,1,18 +2025-03-11T12:41:04.013183,479392864,65375,216,-30.8698573033,-42.8854428318,58.556167452535,2,1,18 +2025-03-11T12:41:04.028808,479392864,65375,216,-30.66252945202,-42.70024122834,58.19929639231,2,1,18 +2025-03-11T12:41:04.044433,479392864,65375,216,-30.45048960412,-42.515031471915,57.856282100275,2,1,18 +2025-03-11T12:41:04.060058,479392864,65375,216,-30.25258574608,-42.30674081526,57.4808471698,2,1,18 +2025-03-11T12:41:04.075683,479392864,65375,216,-30.05939388466,-42.09845831157,57.110040203395,2,1,18 +2025-03-11T12:41:04.091308,479392864,65375,216,-29.86149002662,-41.890167654915,56.729984089855,2,1,18 +2025-03-11T12:41:04.106933,479392864,65375,216,-29.67301016182,-41.695756519665,56.37310307365,2,1,18 +2025-03-11T12:41:04.122558,479392864,65375,216,-29.47039430716,-41.49207878187,55.99767990217,2,1,18 +2025-03-11T12:41:04.138183,479392864,65375,216,-29.2442184694,-41.28836027925,55.62684400873,2,1,18 +2025-03-11T12:41:04.153808,479392864,65375,216,-29.03689061812,-41.08467438849,55.251414056245,2,1,18 +2025-03-11T12:41:04.169433,479392864,65375,216,-28.83427476346,-40.871754507045,54.8713326217,2,1,18 +2025-03-11T12:41:04.185058,479392864,65375,216,-28.6316589088,-40.654213553775,54.472747914895,2,1,18 +2025-03-11T12:41:04.200683,479392864,65375,216,-28.40548307104,-40.450495051155,54.06956374,2,1,18 +2025-03-11T12:41:04.216308,479392864,65375,216,-28.19344322314,-40.223695648305,53.680170757315,2,1,18 +2025-03-11T12:41:04.231933,479392864,65375,216,-27.98611537186,-40.001525470245,53.2954242787,2,1,18 +2025-03-11T12:41:04.247558,479392864,65375,216,-27.77878752058,-39.807081723135,52.90616785702,2,1,18 +2025-03-11T12:41:04.263183,479392864,65375,216,-27.55732367944,-39.589508158005,52.51217720926,2,1,18 +2025-03-11T12:41:04.278808,479392864,65375,216,-27.34057183492,-39.376563817665,52.108969516375,2,1,18 +2025-03-11T12:41:04.294433,479392864,65375,216,-27.13795598026,-39.149780720745,51.724211278765,2,1,18 +2025-03-11T12:41:04.310058,479392864,65375,216,-26.92591613236,-38.89987595877,51.348589145275,2,1,18 +2025-03-11T12:41:04.325683,479392864,65375,216,-26.69502829798,-38.677665015885,50.936081663245,2,1,18 +2025-03-11T12:41:04.341308,479392864,65375,216,-26.46885246022,-38.473946513265,50.500549206895,2,1,18 +2025-03-11T12:41:04.356933,479392864,65375,216,-26.23325262922,-38.25634848924,50.092674666925,2,1,18 +2025-03-11T12:41:04.372558,479392864,65375,216,-26.01178878808,-38.01104849316,49.6939515961,2,1,18 +2025-03-11T12:41:04.388183,479392864,65375,216,-25.7809009537,-37.7749743348,49.267524944875,2,1,18 +2025-03-11T12:41:04.403808,479392864,65375,216,-25.5453011227,-37.5435130953,48.84573123571,2,1,18 +2025-03-11T12:41:04.419433,479392864,65375,216,-25.32383728156,-37.321318458345,48.419373766495,2,1,18 +2025-03-11T12:41:04.435058,479392864,65375,216,-25.09294944718,-37.09910751546,47.98376036914,2,1,18 +2025-03-11T12:41:04.450683,479392864,65375,216,-24.8620616128,-36.858412285275,47.557315177915,2,1,18 +2025-03-11T12:41:04.466308,479392864,65375,216,-24.63117377842,-36.63620134239,47.13094414669,2,1,18 +2025-03-11T12:41:04.481933,479392864,65375,216,-24.38614995418,-36.40472379696,46.699894509385,2,1,18 +2025-03-11T12:41:04.497558,479392864,65375,216,-24.15055012318,-36.14553612651,46.273368377155,2,1,18 +2025-03-11T12:41:04.513183,479392864,65375,216,-23.91023829556,-35.895582446745,45.823766628595,2,1,18 +2025-03-11T12:41:04.528808,479392864,65375,216,-23.67935046118,-35.650266144735,45.383439348175,2,1,18 +2025-03-11T12:41:04.544433,479392864,65375,216,-23.44375063018,-35.428047048885,44.95244035288,2,1,18 +2025-03-11T12:41:04.560058,479392864,65375,216,-23.19872680594,-35.18270628798,44.50747154638,2,1,18 +2025-03-11T12:41:04.575683,479392864,65375,216,-22.94899098508,-34.93735737411,44.06711714194,2,1,18 +2025-03-11T12:41:04.591308,479392864,65375,216,-22.6945431676,-34.6966213791,43.626774496495,2,1,18 +2025-03-11T12:41:04.606933,479392864,65375,216,-22.44480734674,-34.45127246523,43.186420092055,2,1,18 +2025-03-11T12:41:04.622558,479392864,65375,216,-22.1997835225,-34.196689560675,42.73679302249,2,1,18 +2025-03-11T12:41:04.638183,479392864,65375,216,-21.95947169488,-33.942114809085,42.2779303678,2,1,18 +2025-03-11T12:41:04.653808,479392864,65375,216,-21.72387186388,-33.70603249776,41.819148654115,2,1,18 +2025-03-11T12:41:04.669433,479392864,65375,216,-21.47884803964,-33.469933880505,41.36959574455,2,1,18 +2025-03-11T12:41:04.685058,479392864,65375,216,-21.2338242154,-33.229214191425,40.92464547805,2,1,18 +2025-03-11T12:41:04.700683,479392864,65375,216,-20.98880039116,-32.95614699957,40.47956543155,2,1,18 +2025-03-11T12:41:04.716308,479392864,65375,216,-20.74848856354,-32.68308796068,40.025249799925,2,1,18 +2025-03-11T12:41:04.731933,479392864,65375,216,-20.48932874944,-32.433101669055,39.55251501202,2,1,18 +2025-03-11T12:41:04.747558,479392864,65375,216,-20.23016893534,-32.196978592905,39.08445702718,2,1,18 +2025-03-11T12:41:04.763183,479392864,65375,216,-19.95687313138,-31.946967842385,38.625565445455,2,1,18 +2025-03-11T12:41:04.778808,479392864,65375,216,-19.69300132066,-31.67386803867,38.15735235961,2,1,18 +2025-03-11T12:41:04.794433,479392864,65375,216,-19.42912950994,-31.42387359408,37.66612605844,2,1,18 +2025-03-11T12:41:04.810058,479392864,65375,216,-19.17468169246,-31.15541116812,37.20256625767,2,1,18 +2025-03-11T12:41:04.825683,479392864,65375,216,-18.91552187836,-30.896182732845,36.729794389765,2,1,18 +2025-03-11T12:41:04.841308,479392864,65375,216,-18.66107406088,-30.64158352236,36.247805476735,2,1,18 +2025-03-11T12:41:04.856933,479392864,65375,216,-18.41605023664,-30.377758474155,35.793520144105,2,1,18 +2025-03-11T12:41:04.872558,479392864,65375,216,-18.15689042254,-30.113908967055,35.32997210233,2,1,18 +2025-03-11T12:41:04.888183,479392864,65375,216,-17.8883066152,-29.8454220822,34.838664860155,2,1,18 +2025-03-11T12:41:04.903808,479392864,65375,216,-17.6291468011,-29.5815725751,34.33814735386,2,1,18 +2025-03-11T12:41:04.919433,479392864,65375,216,-17.35585099714,-29.308456465455,33.84681479068,2,1,18 +2025-03-11T12:41:04.935058,479392864,65375,216,-17.08255519318,-29.04458249946,33.34627694137,2,1,18 +2025-03-11T12:41:04.950683,479392864,65375,216,-16.83281937232,-28.776128226465,32.854996823215,2,1,18 +2025-03-11T12:41:04.966308,479392864,65375,216,-16.56423556498,-28.512262413435,32.3821928533,2,1,18 +2025-03-11T12:41:04.981933,479392864,65375,216,-16.2862277644,-28.257622438125,31.91403358444,2,1,18 +2025-03-11T12:41:04.997558,479392864,65375,216,-16.03177994692,-27.989160012165,31.42274668528,2,1,18 +2025-03-11T12:41:05.013183,479392864,65375,216,-15.74906014972,-27.72526974024,30.93143764009,2,1,18 +2025-03-11T12:41:05.028808,479392864,65375,216,-15.46634035252,-27.44751625284,30.435451791835,2,1,18 +2025-03-11T12:41:05.044433,479392864,65375,216,-15.2024685418,-27.174416449125,29.9395116076,2,1,18 +2025-03-11T12:41:05.060058,479392864,65375,216,-14.93859673108,-26.896695573585,29.443552883365,2,1,18 +2025-03-11T12:41:05.075683,479392864,65375,216,-14.64645294064,-26.609683636605,28.933652843905,2,1,18 +2025-03-11T12:41:05.091308,479392864,65375,216,-14.38258112992,-26.322720617415,28.43765703967,2,1,18 +2025-03-11T12:41:05.106933,479392864,65375,216,-14.11399732258,-26.058854804385,27.92326242217,2,1,18 +2025-03-11T12:41:05.122558,479392864,65375,216,-13.85483750848,-25.776521009985,27.422670755875,2,1,18 +2025-03-11T12:41:05.138183,479392864,65375,216,-13.5768297079,-25.484912460075,26.93125725169,2,1,18 +2025-03-11T12:41:05.153808,479392864,65375,216,-13.28939791408,-25.211771891535,26.430661979365,2,1,18 +2025-03-11T12:41:05.169433,479392864,65375,216,-13.01610211012,-24.93865578189,25.920844683925,2,1,18 +2025-03-11T12:41:05.185058,479392864,65375,216,-12.74280630616,-24.656297528595,25.39712675929,2,1,18 +2025-03-11T12:41:05.200683,479392864,65375,216,-12.46479850558,-24.37855219416,24.86417822752,2,1,18 +2025-03-11T12:41:05.216308,479392864,65375,216,-12.17265471514,-24.10078240083,24.34507290193,2,1,18 +2025-03-11T12:41:05.231933,479392864,65375,216,-11.9040709078,-23.813811228675,23.835206767495,2,1,18 +2025-03-11T12:41:05.247558,479392864,65375,216,-11.60250312412,-23.53140405759,23.32069052296,2,1,18 +2025-03-11T12:41:05.263183,479392864,65375,216,-11.32920732016,-23.25366687612,22.815475870585,2,1,18 +2025-03-11T12:41:05.278808,479392864,65375,216,-11.06062351282,-22.95283248849,22.300932933085,2,1,18 +2025-03-11T12:41:05.294433,479392864,65375,216,-10.79203970548,-22.647377029035,21.786371455585,2,1,18 +2025-03-11T12:41:05.310058,479392864,65375,216,-10.4904719218,-22.3926962889,21.267345267985,2,1,18 +2025-03-11T12:41:05.325683,479392864,65375,216,-10.19832813136,-22.13341078287,20.739071736265,2,1,18 +2025-03-11T12:41:05.341308,479392864,65375,216,-9.91089633754,-21.855649142505,20.21997319168,2,1,18 +2025-03-11T12:41:05.356933,479392864,65375,216,-9.61404055048,-21.55014476526,19.69612866202,2,1,18 +2025-03-11T12:41:05.372558,479392864,65375,216,-9.32189676004,-21.240027469155,19.1676511903,2,1,18 +2025-03-11T12:41:05.388183,479392864,65375,216,-9.0297529696,-20.94839446035,18.63000551245,2,1,18 +2025-03-11T12:41:05.403808,479392864,65375,216,-8.7470331724,-20.656777757475,18.124721678065,2,1,18 +2025-03-11T12:41:05.419433,479392864,65375,216,-8.4643133752,-20.360539982775,17.596313388355,2,1,18 +2025-03-11T12:41:05.435058,479392864,65375,216,-8.181593578,-20.082786495375,17.06335807558,2,1,18 +2025-03-11T12:41:05.450683,479392864,65375,216,-7.89416178418,-19.77729842406,16.525663558735,2,1,18 +2025-03-11T12:41:05.466308,479392864,65375,216,-7.61144198698,-19.485681721185,15.997273809025,2,1,18 +2025-03-11T12:41:05.481933,479392864,65375,216,-7.31458619992,-19.20790377489,15.4689193363,2,1,18 +2025-03-11T12:41:05.497558,479392864,65375,216,-7.01773041286,-18.92550475677,14.949788689705,2,1,18 +2025-03-11T12:41:05.513183,479392864,65375,216,-6.73501061566,-18.633888053895,14.42602012306,2,1,18 +2025-03-11T12:41:05.528808,479392864,65375,216,-6.44286682522,-18.33301290144,13.88833736521,2,1,18 +2025-03-11T12:41:05.544433,479392864,65375,216,-6.14129904154,-18.041363586705,13.355299308415,2,1,18 +2025-03-11T12:41:05.560058,479392864,65375,216,-5.83973125786,-17.754335343795,12.82227979162,2,1,18 +2025-03-11T12:41:05.575683,479392864,65375,216,-5.55701146066,-17.458097569095,12.29387150191,2,1,18 +2025-03-11T12:41:05.591308,479392864,65375,216,-5.27429166346,-17.15723872257,11.74695993994,2,1,18 +2025-03-11T12:41:05.606933,479392864,65375,216,-4.98214787302,-16.847121426465,11.20924010209,2,1,18 +2025-03-11T12:41:05.622558,479392864,65375,216,-4.68058008934,-16.55547211173,10.676202045295,2,1,18 +2025-03-11T12:41:05.638183,479392864,65375,216,-4.38372430228,-16.268452021785,10.12008339418,2,1,18 +2025-03-11T12:41:05.653808,479392864,65375,216,-4.0821565186,-15.981423778875,9.57320032819,2,1,18 +2025-03-11T12:41:05.669433,479392864,65375,216,-3.78530073154,-15.689782617105,9.035547869335,2,1,18 +2025-03-11T12:41:05.685058,479392864,65375,216,-3.50258093434,-15.393544842405,8.52100312882,2,1,18 +2025-03-11T12:41:05.700683,479392864,65375,216,-3.21514914052,-15.09729891474,7.96948214278,2,1,18 +2025-03-11T12:41:05.716308,479392864,65375,216,-2.92300535008,-14.81028697776,7.436476187995,2,1,18 +2025-03-11T12:41:05.731933,479392864,65375,216,-2.63557355626,-14.50017783462,6.894141948085,2,1,18 +2025-03-11T12:41:05.747558,479392864,65375,216,-2.32929377596,-14.19003607962,6.34715940109,2,1,18 +2025-03-11T12:41:05.763183,479392864,65375,216,-2.0324379889,-13.8891527742,5.80484867917,2,1,18 +2025-03-11T12:41:05.778808,479392864,65375,216,-1.73558220184,-13.58826946878,5.26253795725,2,1,18 +2025-03-11T12:41:05.794433,479392864,65375,216,-1.43401441816,-13.296620154045,4.711015168195,2,1,18 +2025-03-11T12:41:05.810058,479392864,65375,216,-1.14187062772,-12.99574500159,4.17795359341,2,1,18 +2025-03-11T12:41:05.825683,479392864,65375,216,-0.84972683728,-12.70873306461,3.635705272495,2,1,18 +2025-03-11T12:41:05.841308,479392864,65375,216,-0.55287105022,-12.412470831015,3.09803427364,2,1,18 +2025-03-11T12:41:05.856933,479392864,65375,216,-0.25130326654,-12.11157937263,2.56033795378,2,1,18 +2025-03-11T12:41:05.872558,479392864,65375,216,0.05026451714,-11.801445770595,2.017983370855,2,1,18 +2025-03-11T12:41:05.888183,479392864,65375,216,0.35654429744,-11.50516723107,1.457192894665,2,1,18 +2025-03-11T12:41:05.903808,479392864,65375,216,0.65811208112,-11.204275772685,0.88714829335,2,1,18 +2025-03-11T12:41:05.919433,479392864,65375,216,0.95025587156,-10.91264276388,0.344881432435,2,1,18 +2025-03-11T12:41:05.935058,479392864,65375,216,1.25182365524,-10.611751305495,-0.18819370436,2,1,18 +2025-03-11T12:41:05.950683,479392864,65375,216,1.55339143892,-10.315480918935,-0.72587148422,2,1,18 +2025-03-11T12:41:05.966308,479392864,65375,216,1.85024722598,-10.00997654169,-1.27744311227,2,1,18 +2025-03-11T12:41:05.981933,479392864,65375,216,2.14710301304,-9.704472164445,-1.81977237419,2,1,18 +2025-03-11T12:41:05.997497,479392868,65371,217,2.4439588001,-9.412831002675,-2.35280364998,2,1,18 +2025-03-11T12:41:06.013122,479392868,65371,217,2.76908656688,-9.11651985129,-2.90437888406,2,1,18 +2025-03-11T12:41:06.028747,479392868,65371,217,3.06594235394,-8.81563654587,-3.469795521305,2,1,18 +2025-03-11T12:41:06.044372,479392868,65371,217,3.35808614438,-8.514761393415,-4.007478279155,2,1,18 +2025-03-11T12:41:06.059997,479392868,65371,217,3.65965392806,-8.21386993503,-4.545174599015,2,1,18 +2025-03-11T12:41:06.075622,479392868,65371,217,3.95650971512,-7.91298662961,-5.096727687065,2,1,18 +2025-03-11T12:41:06.091247,479392868,65371,217,4.2580774988,-7.593610883925,-5.64836171612,2,1,18 +2025-03-11T12:41:06.106872,479392868,65371,217,4.55964528248,-7.29271942554,-6.17681566985,2,1,18 +2025-03-11T12:41:06.122497,479392868,65371,217,4.8706370594,-6.99643273305,-6.71450701172,2,1,18 +2025-03-11T12:41:06.138122,479392868,65371,217,5.16278084984,-6.704799724245,-7.256773872635,2,1,18 +2025-03-11T12:41:06.153747,479392868,65371,217,5.46906063014,-6.39927904107,-7.799116696565,2,1,18 +2025-03-11T12:41:06.169372,479392868,65371,217,5.7659164172,-6.089153592,-8.359949230745,2,1,18 +2025-03-11T12:41:06.184997,479392868,65371,217,6.05806020764,-5.797520583195,-8.89297372553,2,1,18 +2025-03-11T12:41:06.200622,479392868,65371,217,6.3549159947,-5.496637277775,-9.43528444745,2,1,18 +2025-03-11T12:41:06.216247,479392868,65371,217,6.661195775,-5.1911165946,-9.982248454445,2,1,18 +2025-03-11T12:41:06.231872,479392868,65371,217,6.9674755553,-4.8809748396,-10.543094550635,2,1,18 +2025-03-11T12:41:06.247497,479392868,65371,217,7.24548335588,-4.584745217865,-11.0899807916,2,1,18 +2025-03-11T12:41:06.263122,479392868,65371,217,7.55176313618,-4.28846667834,-11.627665352465,2,1,18 +2025-03-11T12:41:06.278747,479392868,65371,217,7.84390692662,-4.006075813185,-12.16989513338,2,1,18 +2025-03-11T12:41:06.294372,479392868,65371,217,8.14076271368,-3.714434651415,-12.707547592235,2,1,18 +2025-03-11T12:41:06.309997,479392868,65371,217,8.44704249398,-3.413535040065,-13.259114242295,2,1,18 +2025-03-11T12:41:06.325622,479392868,65371,217,8.75332227428,-3.103393285065,-13.819960338485,2,1,18 +2025-03-11T12:41:06.341247,479392868,65371,217,9.0643140512,-2.797864448925,-14.35306757729,2,1,18 +2025-03-11T12:41:06.356872,479392868,65371,217,9.35645784164,-2.50623144012,-14.88147088901,2,1,18 +2025-03-11T12:41:06.372497,479392868,65371,217,9.6533136287,-2.209969206525,-15.409899521735,2,1,18 +2025-03-11T12:41:06.388122,479392868,65371,217,9.94074542252,-1.918344350685,-15.952159601645,2,1,18 +2025-03-11T12:41:06.403747,479392868,65371,217,10.22817721634,-1.617477351195,-16.51756267688,2,1,18 +2025-03-11T12:41:06.419372,479392868,65371,217,10.5250330034,-1.307351902125,-17.064531661865,2,1,18 +2025-03-11T12:41:06.434997,479392868,65371,217,10.81717679384,-1.011097821495,-17.61605942891,2,1,18 +2025-03-11T12:41:06.450622,479392868,65371,217,11.12345657414,-0.72406142562,-18.15832809284,2,1,18 +2025-03-11T12:41:06.466247,479392868,65371,217,11.41560036458,-0.432428416815,-18.69597377069,2,1,18 +2025-03-11T12:41:06.481872,479392868,65371,217,11.70774415502,-0.136174336184999,-19.23363798854,2,1,18 +2025-03-11T12:41:06.497497,479392868,65371,217,12.00459994208,0.164708969235001,-19.77594871046,2,1,18 +2025-03-11T12:41:06.513122,479392868,65371,217,12.29674373252,0.451720906215,-20.308954665245,2,1,18 +2025-03-11T12:41:06.528747,479392868,65371,217,12.58417552634,0.747966833880001,-20.8188850037,2,1,18 +2025-03-11T12:41:06.544372,479392868,65371,217,12.86689532354,1.05344675223,-21.34733037341,2,1,18 +2025-03-11T12:41:06.559997,479392868,65371,217,13.1637511106,1.349708985825,-21.894243738395,2,1,18 +2025-03-11T12:41:06.575622,479392868,65371,217,13.4464709078,1.659809976,-22.422707648105,2,1,18 +2025-03-11T12:41:06.591247,479392868,65371,217,13.73861469824,1.951442984805,-22.960353325955,2,1,18 +2025-03-11T12:41:06.606872,479392868,65371,217,14.03075848868,2.23383384996,-23.516446656065,2,1,18 +2025-03-11T12:41:06.622497,479392868,65371,217,14.3181902825,2.5254587058,-24.058706735975,2,1,18 +2025-03-11T12:41:06.638122,479392868,65371,217,14.6244700628,2.8171161735,-24.591751573775,2,1,18 +2025-03-11T12:41:06.653747,479392868,65371,217,14.91190185662,3.113362101165,-25.11092427836,2,1,18 +2025-03-11T12:41:06.669372,479392868,65371,217,15.20875764368,3.405003262935,-25.630092004955,2,1,18 +2025-03-11T12:41:06.684997,479392868,65371,217,15.49147744088,3.691998893985,-26.158463214665,2,1,18 +2025-03-11T12:41:06.700622,479392868,65371,217,15.7789092347,3.974381606175,-26.68682266538,2,1,18 +2025-03-11T12:41:06.716247,479392868,65371,217,16.07576502176,4.266022767945,-27.224475124235,2,1,18 +2025-03-11T12:41:06.731872,479392868,65371,217,16.3679088122,4.5484136331,-27.752841355955,2,1,18 +2025-03-11T12:41:06.747497,479392868,65371,217,16.66005260264,4.821562354605,-28.281170507675,2,1,18 +2025-03-11T12:41:06.763122,479392868,65371,217,16.94748439646,5.122429354095,-28.80960411839,2,1,18 +2025-03-11T12:41:06.778747,479392868,65371,217,17.22549219704,5.43714326313,-29.30573150564,2,1,18 +2025-03-11T12:41:06.794372,479392868,65371,217,17.51763598748,5.719534128285,-29.83409773736,2,1,18 +2025-03-11T12:41:06.809997,479392868,65371,217,17.79564378806,5.99727946272,-30.371667452195,2,1,18 +2025-03-11T12:41:06.825622,479392868,65371,217,18.08307558188,6.27042003126,-30.876883907585,2,1,18 +2025-03-11T12:41:06.841247,479392868,65371,217,18.36579537908,6.53893137501,-31.3913174081,2,1,18 +2025-03-11T12:41:06.856872,479392868,65371,217,18.64380317966,6.835160996745,-31.90585536761,2,1,18 +2025-03-11T12:41:06.872497,479392868,65371,217,18.92652297686,7.131398771445,-32.42502129119,2,1,18 +2025-03-11T12:41:06.888122,479392868,65371,217,19.2186667673,7.409168564775,-32.948747799845,2,1,18 +2025-03-11T12:41:06.903747,479392868,65371,217,19.49667456788,7.691534971035,-33.444745407095,2,1,18 +2025-03-11T12:41:06.919372,479392868,65371,217,19.76525837522,7.973885071365,-33.95459300153,2,1,18 +2025-03-11T12:41:06.934997,479392868,65371,217,20.03384218256,8.256235171695,-34.46906177903,2,1,18 +2025-03-11T12:41:06.950622,479392868,65371,217,20.31656197976,8.52936758727,-34.97889263648,2,1,18 +2025-03-11T12:41:06.966247,479392868,65371,217,20.6087057702,8.821000596075,-35.474947666745,2,1,18 +2025-03-11T12:41:06.981872,479392868,65371,217,20.87728957754,9.09872962458,-35.989397904245,2,1,18 +2025-03-11T12:41:06.997497,479392868,65371,217,21.15529737812,9.376474959015,-36.485376971495,2,1,18 +2025-03-11T12:41:07.013122,479392868,65371,217,21.43801717532,9.654228446415,-37.004468735075,2,1,18 +2025-03-11T12:41:07.028747,479392868,65371,217,21.70660098266,9.93195747492,-37.518918972575,2,1,18 +2025-03-11T12:41:07.044372,479392868,65371,217,21.97989678662,10.214315728215,-38.010288615755,2,1,18 +2025-03-11T12:41:07.059997,479392868,65371,217,22.25319259058,10.48743183786,-38.49699999587,2,1,18 +2025-03-11T12:41:07.075622,479392868,65371,217,22.52648839454,10.75592687568,-39.00679875131,2,1,18 +2025-03-11T12:41:07.091247,479392868,65371,217,22.7997841985,11.0429062008,-39.52591403288,2,1,18 +2025-03-11T12:41:07.106872,479392868,65371,217,23.09192798894,11.306812778655,-40.021857823145,2,1,18 +2025-03-11T12:41:07.122497,479392868,65371,217,23.3652237929,11.5799288883,-40.513190386325,2,1,18 +2025-03-11T12:41:07.138122,479392868,65371,217,23.624383607,11.839157323575,-41.00444698649,2,1,18 +2025-03-11T12:41:07.153747,479392868,65371,217,23.89296741434,12.10764420843,-41.495754228665,2,1,18 +2025-03-11T12:41:07.169372,479392868,65371,217,24.15212722844,12.37149371553,-41.96854463657,2,1,18 +2025-03-11T12:41:07.184997,479392868,65371,217,24.41599903916,12.616867088295,-42.473615946935,2,1,18 +2025-03-11T12:41:07.200622,479392868,65371,217,24.69400683974,12.889991350905,-42.951091741925,2,1,18 +2025-03-11T12:41:07.216247,479392868,65371,217,24.95316665384,13.15846192983,-43.42390068983,2,1,18 +2025-03-11T12:41:07.231872,479392868,65371,217,25.21703846456,13.422319589895,-43.901319061805,2,1,18 +2025-03-11T12:41:07.247497,479392868,65371,217,25.47148628204,13.68616094403,-44.392587420965,2,1,18 +2025-03-11T12:41:07.263122,479392868,65371,217,25.73064609614,13.95001045113,-44.869999011935,2,1,18 +2025-03-11T12:41:07.278747,479392868,65371,217,26.0039419001,14.21850548895,-45.34744948592,2,1,18 +2025-03-11T12:41:07.294372,479392868,65371,217,26.26781371082,14.491605292665,-45.82952612096,2,1,18 +2025-03-11T12:41:07.309997,479392868,65371,217,26.51283753506,14.750809269045,-46.306898828915,2,1,18 +2025-03-11T12:41:07.325622,479392868,65371,217,26.76728535254,15.010029551355,-46.761179183555,2,1,18 +2025-03-11T12:41:07.341247,479392868,65371,217,27.03586915988,15.264653220735,-47.238567256535,2,1,18 +2025-03-11T12:41:07.356872,479392868,65371,217,27.2997409706,15.523889808975,-47.72520945464,2,1,18 +2025-03-11T12:41:07.372497,479392868,65371,217,27.54947679146,15.778480866495,-48.18408567134,2,1,18 +2025-03-11T12:41:07.388122,479392868,65371,217,27.79921261232,16.02845085219,-48.638322164975,2,1,18 +2025-03-11T12:41:07.403747,479392868,65371,217,28.06779641966,16.27383237792,-49.097188425695,2,1,18 +2025-03-11T12:41:07.419372,479392868,65371,217,28.32224423714,16.52381051658,-49.579158798725,2,1,18 +2025-03-11T12:41:07.434997,479392868,65371,217,28.56726806138,16.787635564785,-50.03806531442,2,1,18 +2025-03-11T12:41:07.450622,479392868,65371,217,28.81700388224,17.051468765955,-50.49697861112,2,1,18 +2025-03-11T12:41:07.466247,479392868,65371,217,29.0667397031,17.30143875165,-50.941972738625,2,1,18 +2025-03-11T12:41:07.481872,479392868,65371,217,29.31176352734,17.565263799855,-51.40087925432,2,1,18 +2025-03-11T12:41:07.497497,479392868,65371,217,29.5614993482,17.801370570075,-51.845817761825,2,1,18 +2025-03-11T12:41:07.513122,479392868,65371,217,29.81594716568,18.042106565085,-52.281539224205,2,1,18 +2025-03-11T12:41:07.528747,479392868,65371,217,30.0562589933,18.296681316675,-52.721917146635,2,1,18 +2025-03-11T12:41:07.544372,479392868,65371,217,30.29657082092,18.53739285279,-53.171481815195,2,1,18 +2025-03-11T12:41:07.559997,479392868,65371,217,30.54159464516,18.773491470045,-53.625655907825,2,1,18 +2025-03-11T12:41:07.575622,479392868,65371,217,30.78190647278,19.009581934335,-54.06133848719,2,1,18 +2025-03-11T12:41:07.591247,479392868,65371,217,31.0222183004,19.25029347045,-54.497039606555,2,1,18 +2025-03-11T12:41:07.606872,479392868,65371,217,31.26253012802,19.49562607839,-54.946622815115,2,1,18 +2025-03-11T12:41:07.622497,479392868,65371,217,31.52168994212,19.736370226365,-55.37310869237,2,1,18 +2025-03-11T12:41:07.638122,479392868,65371,217,31.76671376636,19.95398455632,-55.80872389274,2,1,18 +2025-03-11T12:41:07.653747,479392868,65371,217,31.99288960412,20.190050561715,-56.239764946025,2,1,18 +2025-03-11T12:41:07.669372,479392868,65371,217,32.21906544188,20.43535871076,-56.666221896245,2,1,18 +2025-03-11T12:41:07.684997,479392868,65371,217,32.45466527288,20.66681995026,-57.111121520735,2,1,18 +2025-03-11T12:41:07.700622,479392868,65371,217,32.67612911402,20.90287780269,-57.542155793015,2,1,18 +2025-03-11T12:41:07.716247,479392868,65371,217,32.91172894502,21.12509689854,-57.93618532379,2,1,18 +2025-03-11T12:41:07.731872,479392868,65371,217,33.1426167794,21.338065697775,-58.33017099356,2,1,18 +2025-03-11T12:41:07.747497,479392868,65371,217,33.36408062054,21.574123550205,-58.73347816745,2,1,18 +2025-03-11T12:41:07.763122,479392868,65371,217,33.58554446168,21.819423546285,-59.16454951973,2,1,18 +2025-03-11T12:41:07.778747,479392868,65371,217,33.82114429268,22.050884785785,-59.58172204583,2,1,18 +2025-03-11T12:41:07.794372,479392868,65371,217,34.0378961372,22.273071269775,-59.994209184845,2,1,18 +2025-03-11T12:41:07.809997,479392868,65371,217,34.25935997834,22.490644834905,-60.397442198735,2,1,18 +2025-03-11T12:41:07.825622,479392868,65371,217,34.47611182286,22.712831318895,-60.79144460549,2,1,18 +2025-03-11T12:41:07.841247,479392868,65371,217,34.68815167076,22.939630721745,-61.190079954305,2,1,18 +2025-03-11T12:41:07.856872,479392868,65371,217,34.9096155119,23.147962143225,-61.59789707126,2,1,18 +2025-03-11T12:41:07.872497,479392868,65371,217,35.15463933614,23.37481861683,-61.99657988711,2,1,18 +2025-03-11T12:41:07.888122,479392868,65371,217,35.36667918404,23.57389158873,-62.376619263665,2,1,18 +2025-03-11T12:41:07.903747,479392868,65371,217,35.57871903194,23.78220670428,-62.76593808635,2,1,18 +2025-03-11T12:41:07.919372,479392868,65371,217,35.79075887984,23.99052181983,-63.16912045823,2,1,18 +2025-03-11T12:41:07.934997,479392868,65371,217,36.00279872774,24.212700150855,-63.57235845011,2,1,18 +2025-03-11T12:41:07.950622,479392868,65371,217,36.2054145824,24.430241104125,-63.94783724159,2,1,18 +2025-03-11T12:41:07.966247,479392868,65371,217,36.41274243368,24.643169138535,-64.32792545714,2,1,18 +2025-03-11T12:41:07.981872,479392868,65371,217,36.6294942782,24.86997669435,-64.712704037765,2,1,18 +2025-03-11T12:41:07.997497,479392868,65371,217,36.8415341261,25.064428594425,-65.08348250819,2,1,18 +2025-03-11T12:41:08.013122,479392868,65371,217,37.04886197738,25.268114485185,-65.440427728415,2,1,18 +2025-03-11T12:41:08.028747,479392868,65371,217,37.2420538388,25.47177591705,-65.81121615482,2,1,18 +2025-03-11T12:41:08.044372,479392868,65371,217,37.44938169008,25.67546180781,-66.195888473435,2,1,18 +2025-03-11T12:41:08.059997,479392868,65371,217,37.65199754474,25.879139545605,-66.562069278785,2,1,18 +2025-03-11T12:41:08.075622,479392868,65371,217,37.84990140278,26.06894591496,-66.942051232325,2,1,18 +2025-03-11T12:41:08.091247,479392868,65371,217,38.05722925406,26.28187394937,-67.294412349485,2,1,18 +2025-03-11T12:41:08.106872,479392868,65371,217,38.24570911886,26.47628508462,-67.64205099956,2,1,18 +2025-03-11T12:41:08.122497,479392868,65371,217,38.43418898366,26.67069621987,-67.9943108327,2,1,18 +2025-03-11T12:41:08.138122,479392868,65371,217,38.61795685184,26.87896241763,-68.3512406879,2,1,18 +2025-03-11T12:41:08.153747,479392868,65371,217,38.80643671664,27.05488926558,-68.698805177975,2,1,18 +2025-03-11T12:41:08.169372,479392868,65371,217,38.99962857806,27.24468748197,-69.055674435185,2,1,18 +2025-03-11T12:41:08.184997,479392868,65371,217,39.1975324361,27.43911492315,-69.398705464205,2,1,18 +2025-03-11T12:41:08.200622,479392868,65371,217,39.3860123009,27.62428391475,-69.73706466815,2,1,18 +2025-03-11T12:41:08.216247,479392868,65371,217,39.55564417922,27.80942029449,-70.07077556501,2,1,18 +2025-03-11T12:41:08.231872,479392868,65371,217,39.72527605754,27.99455667423,-70.39524409574,2,1,18 +2025-03-11T12:41:08.247497,479392868,65371,217,39.90904392572,28.20282287199,-70.73368921868,2,1,18 +2025-03-11T12:41:08.263122,479392868,65371,217,40.0928117939,28.378741566975,-71.076625744685,2,1,18 +2025-03-11T12:41:08.278747,479392868,65371,217,40.27657966208,28.55466026196,-71.396456355365,2,1,18 +2025-03-11T12:41:08.294372,479392868,65371,217,40.46034753026,28.730578956945,-71.71166578298,2,1,18 +2025-03-11T12:41:08.309997,479392868,65371,217,40.6346914052,28.906481346,-72.045346380845,2,1,18 +2025-03-11T12:41:08.325622,479392868,65371,217,40.80903528014,29.06852051958,-72.346623077255,2,1,18 +2025-03-11T12:41:08.341247,479392868,65371,217,40.98337915508,29.23980183681,-72.66180040286,2,1,18 +2025-03-11T12:41:08.356872,479392868,65371,217,41.1530110334,29.42493821655,-72.97702656746,2,1,18 +2025-03-11T12:41:08.372497,479392868,65371,217,41.3179309151,29.5869610842,-73.282910884925,2,1,18 +2025-03-11T12:41:08.388122,479392868,65371,217,41.48756279342,29.758234248465,-73.579596697265,2,1,18 +2025-03-11T12:41:08.403747,479392868,65371,217,41.65719467174,29.92026526908,-73.885487795735,2,1,18 +2025-03-11T12:41:08.419372,479392868,65371,217,41.8362505433,30.0776915238,-74.19599509928,2,1,18 +2025-03-11T12:41:08.434997,479392868,65371,217,42.00588242162,30.23510147259,-74.488004108555,2,1,18 +2025-03-11T12:41:08.450622,479392868,65371,217,42.1660903067,30.39249511545,-74.784620738885,2,1,18 +2025-03-11T12:41:08.466247,479392868,65371,217,42.32629819178,30.554509830135,-75.08587709228,2,1,18 +2025-03-11T12:41:08.481872,479392868,65371,217,42.48650607686,30.71652454482,-75.359406347285,2,1,18 +2025-03-11T12:41:08.497497,479392868,65371,217,42.6372899687,30.8646597381,-75.628245237215,2,1,18 +2025-03-11T12:41:08.513122,479392868,65371,217,42.78336186392,31.012786778415,-75.892456163075,2,1,18 +2025-03-11T12:41:08.528747,479392868,65371,217,42.93414575576,31.170164115345,-76.20292278059,2,1,18 +2025-03-11T12:41:08.544372,479392868,65371,217,43.09435364084,31.327557758205,-76.50878177705,2,1,18 +2025-03-11T12:41:08.559997,479392868,65371,217,43.24513753268,31.48955616696,-76.773055103915,2,1,18 +2025-03-11T12:41:08.575622,479392868,65371,217,43.38649743128,31.651538269785,-77.03731486877,2,1,18 +2025-03-11T12:41:08.591247,479392868,65371,217,43.53728132312,31.79505239124,-77.292271669505,2,1,18 +2025-03-11T12:41:08.606872,479392868,65371,217,43.67864122172,31.938550206765,-77.54721490823,2,1,18 +2025-03-11T12:41:08.622497,479392868,65371,217,43.8152891237,32.0774187975,-77.82061755821,2,1,18 +2025-03-11T12:41:08.638122,479392868,65371,217,43.94722502906,32.20703709162,-78.066249248795,2,1,18 +2025-03-11T12:41:08.653747,479392868,65371,217,44.09329692428,32.35054306011,-78.30733571933,2,1,18 +2025-03-11T12:41:08.669372,479392868,65371,217,44.22994482626,32.49403272267,-78.557650993985,2,1,18 +2025-03-11T12:41:08.684997,479392868,65371,217,44.36188073162,32.63289316044,-78.789456215375,2,1,18 +2025-03-11T12:41:08.700622,479392868,65371,217,44.50324063022,32.76252776049,-79.0443438341,2,1,18 +2025-03-11T12:41:08.716247,479392868,65371,217,44.62575254234,32.89212974868,-79.299204328805,2,1,18 +2025-03-11T12:41:08.731872,479392868,65371,217,44.76240044432,33.01713512394,-79.554066626525,2,1,18 +2025-03-11T12:41:08.747497,479392868,65371,217,44.8990483463,33.15138264285,-79.78586008892,2,1,18 +2025-03-11T12:41:08.763122,479392868,65371,217,45.03098425166,33.276379865145,-80.00836732418,2,1,18 +2025-03-11T12:41:08.778747,479392868,65371,217,45.15349616378,33.39211863786,-80.235445100495,2,1,18 +2025-03-11T12:41:08.794372,479392868,65371,217,45.28543206914,33.517115860155,-80.457952335755,2,1,18 +2025-03-11T12:41:08.809997,479392868,65371,217,45.40323198464,33.63746755173,-80.68966305413,2,1,18 +2025-03-11T12:41:08.825622,479392868,65371,217,45.50689591028,33.75779478441,-80.916732246425,2,1,18 +2025-03-11T12:41:08.841247,479392868,65371,217,45.63411981902,33.868920638265,-81.134555897615,2,1,18 +2025-03-11T12:41:08.856872,479392868,65371,217,45.7472077379,33.98464310505,-81.338514196595,2,1,18 +2025-03-11T12:41:08.872497,479392868,65371,217,45.86971965002,34.091139734115,-81.55631252678,2,1,18 +2025-03-11T12:41:08.888122,479392868,65371,217,45.97338357566,34.211466966795,-81.75103343762,2,1,18 +2025-03-11T12:41:08.903747,479392868,65371,217,46.07233550468,34.34102819016,-81.955027013585,2,1,18 +2025-03-11T12:41:08.919372,479392868,65371,217,46.1948474168,34.45214589105,-82.15435915151,2,1,18 +2025-03-11T12:41:08.934997,479392868,65371,217,46.30322333906,34.56786020487,-82.33520475416,2,1,18 +2025-03-11T12:41:08.950622,479392868,65371,217,46.4068872647,34.6789452939,-82.525267401935,2,1,18 +2025-03-11T12:41:08.966247,479392868,65371,217,46.51055119034,34.776167167455,-82.719895612775,2,1,18 +2025-03-11T12:41:08.981872,479392868,65371,217,46.6189271126,34.873397193975,-82.900667055425,2,1,18 +2025-03-11T12:41:08.997497,479392868,65371,217,46.713167045,34.975223833425,-83.09067906119,2,1,18 +2025-03-11T12:41:09.013122,479392868,65371,217,46.80269498078,35.063179104435,-83.26214393369,2,1,18 +2025-03-11T12:41:09.028747,479392868,65371,217,46.90635890642,35.15115883434,-83.424386783075,2,1,18 +2025-03-11T12:41:09.044372,479392868,65371,217,47.00059883882,35.257606545615,-83.59593259658,2,1,18 +2025-03-11T12:41:09.059997,479392868,65371,217,47.0901267746,35.3594250321,-83.77669545521,2,1,18 +2025-03-11T12:41:09.075622,479392868,65371,217,47.17965471038,35.43813815946,-83.934259698515,2,1,18 +2025-03-11T12:41:09.091247,479392868,65371,217,47.26918264616,35.512230214995,-84.096426584885,2,1,18 +2025-03-11T12:41:09.106872,479392868,65371,217,47.35871058194,35.59556441418,-84.240145818995,2,1,18 +2025-03-11T12:41:09.122497,479392868,65371,217,47.43881452448,35.68350337926,-84.38849121416,2,1,18 +2025-03-11T12:41:09.138122,479392868,65371,217,47.52363046364,35.771450497305,-84.54608575646,2,1,18 +2025-03-11T12:41:09.153747,479392868,65371,217,47.61787039604,35.854792849455,-84.699054137705,2,1,18 +2025-03-11T12:41:09.169372,479392868,65371,217,47.68383834872,35.938086283815,-84.847360649855,2,1,18 +2025-03-11T12:41:09.184997,479392868,65371,217,47.74509430478,36.025992637035,-84.981815371805,2,1,18 +2025-03-11T12:41:09.200622,479392868,65371,217,47.8204862507,36.090818090025,-85.10695537064,2,1,18 +2025-03-11T12:41:09.216247,479392868,65371,217,47.91001418648,36.141804786435,-85.23206009249,2,1,18 +2025-03-11T12:41:09.231872,479392868,65371,217,47.9854061324,36.215872383075,-85.38034308665,2,1,18 +2025-03-11T12:41:09.247497,479392868,65371,217,48.04666208846,36.294536592645,-85.500897179405,2,1,18 +2025-03-11T12:41:09.263122,479392868,65371,217,48.12205403438,36.36398311746,-85.60757098598,2,1,18 +2025-03-11T12:41:09.278747,479392868,65371,217,48.1974459803,36.42880857045,-85.74657453401,2,1,18 +2025-03-11T12:41:09.294372,479392868,65371,217,48.25398993974,36.48435926793,-85.862407962695,2,1,18 +2025-03-11T12:41:09.309997,479392868,65371,217,48.31995789242,36.544547343165,-85.95978876113,2,1,18 +2025-03-11T12:41:09.325622,479392868,65371,217,48.39063784172,36.595501427715,-86.05713926057,2,1,18 +2025-03-11T12:41:09.341247,479392868,65371,217,48.43775780792,36.651035819265,-86.15909557805,2,1,18 +2025-03-11T12:41:09.356872,479392868,65371,217,48.48487777412,36.725054498115,-86.274989604725,2,1,18 +2025-03-11T12:41:09.372497,479392868,65371,217,48.54613373018,36.785234420385,-86.363121256025,2,1,18 +2025-03-11T12:41:09.388122,479392868,65371,217,48.58854169976,36.836139587145,-86.45580988637,2,1,18 +2025-03-11T12:41:09.403747,479392868,65371,217,48.63094966934,36.877802610255,-86.55308261978,2,1,18 +2025-03-11T12:41:09.419372,479392868,65371,217,48.67335763892,36.93332884884,-86.64116860706,2,1,18 +2025-03-11T12:41:09.434997,479392868,65371,217,48.72518960174,36.97500817788,-86.724591353285,2,1,18 +2025-03-11T12:41:09.450622,479392868,65371,217,48.76759757132,37.012050129165,-86.8079819975,2,1,18 +2025-03-11T12:41:09.466247,479392868,65371,217,48.80529354428,37.049083927485,-86.89136586071,2,1,18 +2025-03-11T12:41:09.481872,479392868,65371,217,48.85241351048,37.095376175385,-86.970179182865,2,1,18 +2025-03-11T12:41:09.497497,479392868,65371,217,48.90895746992,37.12782151374,-87.03046571477,2,1,18 +2025-03-11T12:41:09.513122,479392868,65371,217,48.94194144626,37.15098394362,-87.09992362778,2,1,18 +2025-03-11T12:41:09.528747,479392868,65371,217,48.97021342598,37.18800143601,-87.15556683059,2,1,18 +2025-03-11T12:41:09.544372,479392868,65371,217,49.00319740232,37.22964815319,-87.220477720535,2,1,18 +2025-03-11T12:41:09.559997,479392868,65371,217,49.03618137866,37.266673798545,-87.29461243661,2,1,18 +2025-03-11T12:41:09.575622,479392868,65371,217,49.069165355,37.31294158755,-87.34567831736,2,1,18 +2025-03-11T12:41:09.591247,479392868,65371,217,49.10686132796,37.317627883095,-87.387341752985,2,1,18 +2025-03-11T12:41:09.606872,479392868,65371,217,49.12570931444,37.317660494955,-87.424338341525,2,1,18 +2025-03-11T12:41:09.622497,479392868,65371,217,49.13513330768,37.35002430366,-87.470693514185,2,1,18 +2025-03-11T12:41:09.638122,479392868,65371,217,49.14926929754,37.377775193505,-87.51703692785,2,1,18 +2025-03-11T12:41:09.653747,479392868,65371,217,49.17282928064,37.39630024563,-87.554114457395,2,1,18 +2025-03-11T12:41:09.669372,479392868,65371,217,49.17754127726,37.424034829545,-87.59120194292,2,1,18 +2025-03-11T12:41:09.684997,479392868,65371,217,49.20581325698,37.442568034635,-87.595937972015,2,1,18 +2025-03-11T12:41:09.700622,479392868,65371,217,49.2105252536,37.45181833125,-87.609845382215,2,1,18 +2025-03-11T12:41:09.716247,479392868,65371,217,49.21523725022,37.45644755604,-87.62835543548,2,1,18 +2025-03-11T12:41:09.731872,479392868,65371,217,49.21994924684,37.45183463718,-87.64220722568,2,1,18 +2025-03-11T12:41:09.747497,479392868,65371,217,49.22466124346,37.442600646495,-87.660661658945,2,1,18 +2025-03-11T12:41:09.763122,479392868,65371,217,49.23879723332,37.456488320865,-87.656116438895,2,1,18 +2025-03-11T12:41:09.778747,479392868,65371,217,49.25293322318,37.470375995235,-87.651571218845,2,1,18 +2025-03-11T12:41:09.794372,479392868,65371,217,49.24822122656,37.484231057745,-87.674725973165,2,1,18 +2025-03-11T12:41:09.809997,479392868,65371,217,49.24822122656,37.48885212957,-87.65163859784,2,1,18 +2025-03-11T12:41:09.825622,479392868,65371,217,49.26235721642,37.48425551664,-87.651640400855,2,1,18 +2025-03-11T12:41:09.841247,479392868,65371,217,49.26706921304,37.47040045413,-87.646970378795,2,1,18 +2025-03-11T12:41:09.856872,479392868,65371,217,49.24350922994,37.45649647383,-87.62839612151,2,1,18 +2025-03-11T12:41:09.872497,479392868,65371,217,49.2340852367,37.4564801679,-87.60065546111,2,1,18 +2025-03-11T12:41:09.888122,479392868,65371,217,49.22466124346,37.41949528737,-87.58200884684,2,1,18 +2025-03-11T12:41:09.903747,479392868,65371,217,49.20110126036,37.410212378895,-87.56807431262,2,1,18 +2025-03-11T12:41:09.919372,479392868,65371,217,49.1869652705,37.405566848175,-87.52644478202,2,1,18 +2025-03-11T12:41:09.934997,479392868,65371,217,49.18225327388,37.382453336085,-87.470891104235,2,1,18 +2025-03-11T12:41:09.950622,479392868,65371,217,49.16811728402,37.368565661715,-87.4338456767,2,1,18 +2025-03-11T12:41:09.966247,479392868,65371,217,49.1398453043,37.359274600275,-87.40604081228,2,1,18 +2025-03-11T12:41:09.981872,479392868,65371,217,49.11157332458,37.322257107885,-87.373503524795,2,1,18 +2025-03-11T12:41:09.997436,479392872,65367,218,49.07858934824,37.289852534355,-87.33635681324,2,1,18 +2025-03-11T12:41:10.013061,479392872,65367,218,49.069165355,37.280594084775,-87.294715523645,2,1,18 +2025-03-11T12:41:10.028686,479392872,65367,218,49.05031736852,37.24821397014,-87.21599850752,2,1,18 +2025-03-11T12:41:10.044311,479392872,65367,218,49.0220453888,37.215817549575,-87.164995027775,2,1,18 +2025-03-11T12:41:10.059936,479392872,65367,218,48.99377340908,37.178800057185,-87.12321537416,2,1,18 +2025-03-11T12:41:10.075561,479392872,65367,218,48.9513654395,37.1417581059,-87.067551828335,2,1,18 +2025-03-11T12:41:10.091186,479392872,65367,218,48.92309345978,37.109361685335,-86.993442433265,2,1,18 +2025-03-11T12:41:10.106811,479392872,65367,218,48.88539748682,37.06770681519,-86.91466121312,2,1,18 +2025-03-11T12:41:10.122436,479392872,65367,218,48.82885352738,37.03064040501,-86.84049259202,2,1,18 +2025-03-11T12:41:10.138061,479392872,65367,218,48.78173356118,36.99359030076,-86.770958715995,2,1,18 +2025-03-11T12:41:10.153686,479392872,65367,218,48.7393255916,36.947306205825,-86.692152174845,2,1,18 +2025-03-11T12:41:10.169311,479392872,65367,218,48.70162961864,36.90565133568,-86.617992137765,2,1,18 +2025-03-11T12:41:10.184936,479392872,65367,218,48.6450856592,36.85934278185,-86.52068052134,2,1,18 +2025-03-11T12:41:10.200561,479392872,65367,218,48.58854169976,36.79454994072,-86.404810012655,2,1,18 +2025-03-11T12:41:10.216186,479392872,65367,218,48.53199774032,36.73899924324,-86.312082499295,2,1,18 +2025-03-11T12:41:10.231811,479392872,65367,218,48.4801657775,36.692698842375,-86.21939884694,2,1,18 +2025-03-11T12:41:10.247436,479392872,65367,218,48.41890982144,36.65562427923,-86.12211752951,2,1,18 +2025-03-11T12:41:10.263061,479392872,65367,218,48.362365862,36.595452509925,-86.024750293085,2,1,18 +2025-03-11T12:41:10.278686,479392872,65367,218,48.30582190256,36.52603859697,-85.904240061335,2,1,18 +2025-03-11T12:41:10.294311,479392872,65367,218,48.24927794312,36.46124575584,-85.77912718652,2,1,18 +2025-03-11T12:41:10.309936,479392872,65367,218,48.18802198706,36.39182368992,-85.67247372296,2,1,18 +2025-03-11T12:41:10.325561,479392872,65367,218,48.126766031,36.308538408525,-85.561143456335,2,1,18 +2025-03-11T12:41:10.341186,479392872,65367,218,48.07493406818,36.239132648535,-85.445261188655,2,1,18 +2025-03-11T12:41:10.356811,479392872,65367,218,47.99954212226,36.174307195545,-85.315500006755,2,1,18 +2025-03-11T12:41:10.372436,479392872,65367,218,47.92886217296,36.104868823695,-85.181105882795,2,1,18 +2025-03-11T12:41:10.388061,479392872,65367,218,47.85347022704,36.030801227055,-85.04668643783,2,1,18 +2025-03-11T12:41:10.403686,479392872,65367,218,47.7733662845,35.95672547745,-84.90301784573,2,1,18 +2025-03-11T12:41:10.419311,479392872,65367,218,47.69326234196,35.891891871495,-84.7501439675,2,1,18 +2025-03-11T12:41:10.434936,479392872,65367,218,47.6084464028,35.808565825275,-84.61105269746,2,1,18 +2025-03-11T12:41:10.450561,479392872,65367,218,47.52363046364,35.72061870723,-84.448836972095,2,1,18 +2025-03-11T12:41:10.466186,479392872,65367,218,47.45766251096,35.62808312922,-84.29587219688,2,1,18 +2025-03-11T12:41:10.481811,479392872,65367,218,47.3728465718,35.53551493935,-84.1752285791,2,1,18 +2025-03-11T12:41:10.497436,479392872,65367,218,47.29274262926,35.452197046095,-84.01303817474,2,1,18 +2025-03-11T12:41:10.513061,479392872,65367,218,47.20321469348,35.373483918735,-83.836989199175,2,1,18 +2025-03-11T12:41:10.528686,479392872,65367,218,47.09955076784,35.28550418883,-83.67474634979,2,1,18 +2025-03-11T12:41:10.544311,479392872,65367,218,47.00531083544,35.18367754938,-83.50784025935,2,1,18 +2025-03-11T12:41:10.559936,479392872,65367,218,46.92049489628,35.09110935951,-83.345605993985,2,1,18 +2025-03-11T12:41:10.575561,479392872,65367,218,46.8309669605,35.0031540885,-83.18800467068,2,1,18 +2025-03-11T12:41:10.591186,479392872,65367,218,46.7367270281,34.915190664525,-83.007290651045,2,1,18 +2025-03-11T12:41:10.606811,479392872,65367,218,46.63306310246,34.804105575495,-82.812606820205,2,1,18 +2025-03-11T12:41:10.622436,479392872,65367,218,46.52939917682,34.68839941464,-82.63176799856,2,1,18 +2025-03-11T12:41:10.638061,479392872,65367,218,46.4304472478,34.577322478575,-82.446333314855,2,1,18 +2025-03-11T12:41:10.653686,479392872,65367,218,46.33149531878,34.470866614335,-82.237811255825,2,1,18 +2025-03-11T12:41:10.669311,479392872,65367,218,46.22311939652,34.373636587815,-82.047797447045,2,1,18 +2025-03-11T12:41:10.684936,479392872,65367,218,46.11474347426,34.276406561295,-81.84392008907,2,1,18 +2025-03-11T12:41:10.700561,479392872,65367,218,45.99694355876,34.151433797895,-81.66302384441,2,1,18 +2025-03-11T12:41:10.716186,479392872,65367,218,45.86971965002,34.02182365674,-81.431262484025,2,1,18 +2025-03-11T12:41:10.731811,479392872,65367,218,45.75663173114,33.906101189955,-81.21344063585,2,1,18 +2025-03-11T12:41:10.747436,479392872,65367,218,45.63883181564,33.79499164203,-81.009494095865,2,1,18 +2025-03-11T12:41:10.763061,479392872,65367,218,45.52574389676,33.679269175245,-80.796293430755,2,1,18 +2025-03-11T12:41:10.778686,479392872,65367,218,45.4173679745,33.56817593325,-80.57387572052,2,1,18 +2025-03-11T12:41:10.794311,479392872,65367,218,45.29014406576,33.44318686392,-80.36523881546,2,1,18 +2025-03-11T12:41:10.809936,479392872,65367,218,45.16763215364,33.308963803905,-80.13346569608,2,1,18 +2025-03-11T12:41:10.825561,479392872,65367,218,45.04512024152,33.18398288754,-79.897108473635,2,1,18 +2025-03-11T12:41:10.841186,479392872,65367,218,44.91789633278,33.063614890035,-79.670005376315,2,1,18 +2025-03-11T12:41:10.856811,479392872,65367,218,44.7812484308,32.938609514775,-79.43824899392,2,1,18 +2025-03-11T12:41:10.872436,479392872,65367,218,44.65873651868,32.80438645476,-79.192612325345,2,1,18 +2025-03-11T12:41:10.888061,479392872,65367,218,44.53151260994,32.67939738543,-78.96086950496,2,1,18 +2025-03-11T12:41:10.903686,479392872,65367,218,44.40900069782,32.54979539724,-78.73835729171,2,1,18 +2025-03-11T12:41:10.919311,479392872,65367,218,44.2629288026,32.40628942875,-78.469543722785,2,1,18 +2025-03-11T12:41:10.934936,479392872,65367,218,44.121568904,32.2396862541,-78.209886600995,2,1,18 +2025-03-11T12:41:10.950561,479392872,65367,218,43.97549700878,32.09618028561,-77.9503153982,2,1,18 +2025-03-11T12:41:10.966186,479392872,65367,218,43.84827310004,31.948085857155,-77.69537396249,2,1,18 +2025-03-11T12:41:10.981811,479392872,65367,218,43.72576118792,31.82310494079,-77.43591082472,2,1,18 +2025-03-11T12:41:10.997436,479392872,65367,218,43.57026529946,31.67958266637,-77.148598961525,2,1,18 +2025-03-11T12:41:11.013061,479392872,65367,218,43.42419340424,31.53607669788,-76.893648941795,2,1,18 +2025-03-11T12:41:11.028686,479392872,65367,218,43.26869751578,31.37407013616,-76.629368833925,2,1,18 +2025-03-11T12:41:11.044311,479392872,65367,218,43.1084896307,31.221297565125,-76.36511902505,2,1,18 +2025-03-11T12:41:11.059936,479392872,65367,218,42.943569749,31.068516841125,-76.096241252105,2,1,18 +2025-03-11T12:41:11.075561,479392872,65367,218,42.78336186392,30.91574427009,-75.827370260165,2,1,18 +2025-03-11T12:41:11.091186,479392872,65367,218,42.62786597546,30.76297985202,-75.535400133905,2,1,18 +2025-03-11T12:41:11.106811,479392872,65367,218,42.47708208362,30.61484465874,-75.238834145585,2,1,18 +2025-03-11T12:41:11.122436,479392872,65367,218,42.33572218502,30.45748362774,-74.960729371535,2,1,18 +2025-03-11T12:41:11.138061,479392872,65367,218,42.18493829318,30.30934843446,-74.664163383215,2,1,18 +2025-03-11T12:41:11.153686,479392872,65367,218,42.0247304081,30.1519547916,-74.367546752885,2,1,18 +2025-03-11T12:41:11.169311,479392872,65367,218,41.8598105264,29.994552995775,-74.066302158485,2,1,18 +2025-03-11T12:41:11.184936,479392872,65367,218,41.6948906447,29.823287984475,-73.75113839489,2,1,18 +2025-03-11T12:41:11.200561,479392872,65367,218,41.52525876638,29.647393748385,-73.431328127225,2,1,18 +2025-03-11T12:41:11.216186,479392872,65367,218,41.36033888468,29.485370880735,-73.130064992825,2,1,18 +2025-03-11T12:41:11.231811,479392872,65367,218,41.2001309996,29.327977237875,-72.84731191169,2,1,18 +2025-03-11T12:41:11.247436,479392872,65367,218,41.02578712466,29.147453776995,-72.52747632302,2,1,18 +2025-03-11T12:41:11.263061,479392872,65367,218,40.84201925648,28.96229293836,-72.18912390008,2,1,18 +2025-03-11T12:41:11.278686,479392872,65367,218,40.65353939168,28.790987162235,-71.86468386533,2,1,18 +2025-03-11T12:41:11.294311,479392872,65367,218,40.48861950998,28.610480007285,-71.5541042048,2,1,18 +2025-03-11T12:41:11.309936,479392872,65367,218,40.31427563504,28.42533547458,-71.257355991455,2,1,18 +2025-03-11T12:41:11.325561,479392872,65367,218,40.13521976348,28.24942493256,-70.93753216178,2,1,18 +2025-03-11T12:41:11.341186,479392872,65367,218,39.9514518953,28.0781273094,-70.603856541905,2,1,18 +2025-03-11T12:41:11.356811,479392872,65367,218,39.77239602374,27.89297462373,-70.260889716905,2,1,18 +2025-03-11T12:41:11.372436,479392872,65367,218,39.58391615894,27.693942416655,-69.917853709895,2,1,18 +2025-03-11T12:41:11.388061,479392872,65367,218,39.3860123009,27.499514975475,-69.57020149781,2,1,18 +2025-03-11T12:41:11.403686,479392872,65367,218,39.20695642934,27.314362289805,-69.21799230668,2,1,18 +2025-03-11T12:41:11.419311,479392872,65367,218,39.03732455102,27.13384698189,-68.870436400625,2,1,18 +2025-03-11T12:41:11.434936,479392872,65367,218,38.84884468622,26.93943584664,-68.52279775055,2,1,18 +2025-03-11T12:41:11.450561,479392872,65367,218,38.6556528248,26.74963763025,-68.1844132256,2,1,18 +2025-03-11T12:41:11.466186,479392872,65367,218,38.45303697014,26.555202036105,-67.84599659864,2,1,18 +2025-03-11T12:41:11.481811,479392872,65367,218,38.25042111548,26.346903226485,-67.493660802485,2,1,18 +2025-03-11T12:41:11.497436,479392872,65367,218,38.05251725744,26.14785471348,-67.11826295201,2,1,18 +2025-03-11T12:41:11.513061,479392872,65367,218,37.84990140278,25.95804019116,-66.74289540053,2,1,18 +2025-03-11T12:41:11.528686,479392872,65367,218,37.66142153798,25.75438691226,-66.37211375513,2,1,18 +2025-03-11T12:41:11.544311,479392872,65367,218,37.45880568332,25.550709174465,-66.00593294978,2,1,18 +2025-03-11T12:41:11.559936,479392872,65367,218,37.2656138219,25.342426670775,-65.64898953257,2,1,18 +2025-03-11T12:41:11.575561,479392872,65367,218,37.0771339571,25.13415232005,-65.29667407943,2,1,18 +2025-03-11T12:41:11.591186,479392872,65367,218,36.8886540923,24.935120112975,-64.9166686079,2,1,18 +2025-03-11T12:41:11.606811,479392872,65367,218,36.67190224778,24.731417916285,-64.522740361145,2,1,18 +2025-03-11T12:41:11.622436,479392872,65367,218,36.45515040326,24.51385250412,-64.12875649439,2,1,18 +2025-03-11T12:41:11.638061,479392872,65367,218,36.24311055536,24.310158460395,-63.74407739477,2,1,18 +2025-03-11T12:41:11.653686,479392872,65367,218,36.02635871084,24.106456263705,-63.368633880275,2,1,18 +2025-03-11T12:41:11.669311,479392872,65367,218,35.82374285618,23.898157454085,-62.9793286196,2,1,18 +2025-03-11T12:41:11.684936,479392872,65367,218,35.60699101166,23.694455257395,-62.59002155591,2,1,18 +2025-03-11T12:41:11.700561,479392872,65367,218,35.39023916714,23.490753060705,-62.214578041415,2,1,18 +2025-03-11T12:41:11.716186,479392872,65367,218,35.17819931924,23.254711514205,-61.811284429535,2,1,18 +2025-03-11T12:41:11.731811,479392872,65367,218,34.95202348148,23.014024436985,-61.412573117705,2,1,18 +2025-03-11T12:41:11.747436,479392872,65367,218,34.72584764372,22.79644271889,-61.00933332281,2,1,18 +2025-03-11T12:41:11.763061,479392872,65367,218,34.51380779582,22.592748675165,-60.60616949093,2,1,18 +2025-03-11T12:41:11.778686,479392872,65367,218,34.30176794792,22.365949272315,-60.207534142115,2,1,18 +2025-03-11T12:41:11.794311,479392872,65367,218,34.08030410678,22.139133563535,-59.79040049903,2,1,18 +2025-03-11T12:41:11.809936,479392872,65367,218,33.84470427578,21.916914467685,-59.377886235995,2,1,18 +2025-03-11T12:41:11.825561,479392872,65367,218,33.61852843802,21.69933274959,-58.96540407497,2,1,18 +2025-03-11T12:41:11.841186,479392872,65367,218,33.38292860702,21.45862936644,-58.562058018065,2,1,18 +2025-03-11T12:41:11.856811,479392872,65367,218,33.1661767625,21.222579666975,-58.135651709855,2,1,18 +2025-03-11T12:41:11.872436,479392872,65367,218,32.94000092474,20.991134733405,-57.718492745765,2,1,18 +2025-03-11T12:41:11.888061,479392872,65367,218,32.71382508698,20.74582658436,-57.29665697861,2,1,18 +2025-03-11T12:41:11.903686,479392872,65367,218,32.46880126274,20.518970110755,-56.865625881305,2,1,18 +2025-03-11T12:41:11.919311,479392872,65367,218,32.2237774385,20.2828714935,-56.429936520935,2,1,18 +2025-03-11T12:41:11.934936,479392872,65367,218,31.99760160074,20.046805488105,-56.00813783378,2,1,18 +2025-03-11T12:41:11.950561,479392872,65367,218,31.78084975622,19.81999793229,-55.595632154765,2,1,18 +2025-03-11T12:41:11.966186,479392872,65367,218,31.55938591508,19.588561151685,-55.16923760555,2,1,18 +2025-03-11T12:41:11.981811,479392872,65367,218,31.31907408746,19.34784961557,-54.724294120055,2,1,18 +2025-03-11T12:41:11.997436,479392872,65367,218,31.07876225984,19.116380223105,-54.293251263755,2,1,18 +2025-03-11T12:41:12.013061,479392872,65367,218,30.8337384356,18.875660534025,-53.86216454645,2,1,18 +2025-03-11T12:41:12.028686,479392872,65367,218,30.58871461136,18.63031977312,-53.431059289145,2,1,18 +2025-03-11T12:41:12.044311,479392872,65367,218,30.35311478036,18.38037424632,-52.986085504655,2,1,18 +2025-03-11T12:41:12.059936,479392872,65367,218,30.11280295274,18.15352592568,-52.54119763916,2,1,18 +2025-03-11T12:41:12.075561,479392872,65367,218,29.85835513526,17.90354778702,-52.07771199839,2,1,18 +2025-03-11T12:41:12.091186,479392872,65367,218,29.59919532116,17.63969827992,-51.61878513968,2,1,18 +2025-03-11T12:41:12.106811,479392872,65367,218,29.35417149692,17.38973644719,-51.18304015931,2,1,18 +2025-03-11T12:41:12.122436,479392872,65367,218,29.12328366254,17.149041217005,-50.719625503565,2,1,18 +2025-03-11T12:41:12.138061,479392872,65367,218,28.85941185182,16.899046772415,-50.26074748385,2,1,18 +2025-03-11T12:41:12.153686,479392872,65367,218,28.61438802758,16.64446386786,-49.811120414285,2,1,18 +2025-03-11T12:41:12.169311,479392872,65367,218,28.37407619996,16.38988911627,-49.35687894266,2,1,18 +2025-03-11T12:41:12.184936,479392872,65367,218,28.11491638586,16.13528175282,-48.89798916395,2,1,18 +2025-03-11T12:41:12.200561,479392872,65367,218,27.85104457514,15.880666236405,-48.4437137873,2,1,18 +2025-03-11T12:41:12.216186,479392872,65367,218,27.58717276442,15.639913935465,-47.984872847585,2,1,18 +2025-03-11T12:41:12.231811,479392872,65367,218,27.33272494694,15.39455686863,-47.530648112945,2,1,18 +2025-03-11T12:41:12.247436,479392872,65367,218,27.08298912608,15.13072366746,-47.044007717855,2,1,18 +2025-03-11T12:41:12.263061,479392872,65367,218,26.83796530184,14.87151969108,-46.55739264377,2,1,18 +2025-03-11T12:41:12.278686,479392872,65367,218,26.57880548774,14.603049112155,-46.075341329735,2,1,18 +2025-03-11T12:41:12.294311,479392872,65367,218,26.3102216804,14.348425442775,-45.607195622885,2,1,18 +2025-03-11T12:41:12.309936,479392872,65367,218,26.0510618663,14.0891970075,-45.13442375498,2,1,18 +2025-03-11T12:41:12.325561,479392872,65367,218,25.78719005558,13.816097203785,-44.64310475381,2,1,18 +2025-03-11T12:41:12.341186,479392872,65367,218,25.52803024148,13.543005553035,-44.161034899775,2,1,18 +2025-03-11T12:41:12.356811,479392872,65367,218,25.25944643414,13.28376081183,-43.692870652925,2,1,18 +2025-03-11T12:41:12.372436,479392872,65367,218,24.98615063018,13.00602363036,-43.19689836668,2,1,18 +2025-03-11T12:41:12.388061,479392872,65367,218,24.72227881946,12.723681682995,-42.71478465164,2,1,18 +2025-03-11T12:41:12.403686,479392872,65367,218,24.45369501212,12.47367908544,-42.22817275253,2,1,18 +2025-03-11T12:41:12.419311,479392872,65367,218,24.19924719464,12.219079874955,-41.75542620563,2,1,18 +2025-03-11T12:41:12.434936,479392872,65367,218,23.94479937716,11.950617448995,-41.287245221795,2,1,18 +2025-03-11T12:41:12.450561,479392872,65367,218,23.6715035732,11.686743483,-40.795949738615,2,1,18 +2025-03-11T12:41:12.466186,479392872,65367,218,23.39349577262,11.41361922039,-40.299989211365,2,1,18 +2025-03-11T12:41:12.481811,479392872,65367,218,23.13433595852,11.14976971329,-39.79947170507,2,1,18 +2025-03-11T12:41:12.497436,479392872,65367,218,22.86104015456,10.86279038817,-39.303462338825,2,1,18 +2025-03-11T12:41:12.513061,479392872,65367,218,22.59245634722,10.57119814419,-38.798198847455,2,1,18 +2025-03-11T12:41:12.528686,479392872,65367,218,22.32387253988,10.29809018751,-38.293009516085,2,1,18 +2025-03-11T12:41:12.544311,479392872,65367,218,22.0694247224,10.034248833375,-37.78787760773,2,1,18 +2025-03-11T12:41:12.559936,479392872,65367,218,21.80084091506,9.76576194852,-37.28270681636,2,1,18 +2025-03-11T12:41:12.575561,479392872,65367,218,21.50869712462,9.474128939715,-36.78203060303,2,1,18 +2025-03-11T12:41:12.591186,479392872,65367,218,21.22597732742,9.20099652414,-36.276820928645,2,1,18 +2025-03-11T12:41:12.606811,479392872,65367,218,20.94796952684,8.914009046055,-35.7669412322,2,1,18 +2025-03-11T12:41:12.622436,479392872,65367,218,20.66524972964,8.64087663048,-35.252489191685,2,1,18 +2025-03-11T12:41:12.638061,479392872,65367,218,20.38724192906,8.35851022422,-34.747249218305,2,1,18 +2025-03-11T12:41:12.653686,479392872,65367,218,20.10923412848,8.07614381796,-34.23738806186,2,1,18 +2025-03-11T12:41:12.669311,479392872,65367,218,19.84065032114,7.789172645805,-33.736764293555,2,1,18 +2025-03-11T12:41:12.684936,479392872,65367,218,19.56735451718,7.52529867981,-33.226984078115,2,1,18 +2025-03-11T12:41:12.700561,479392872,65367,218,19.29877070984,7.238327507655,-32.703254394485,2,1,18 +2025-03-11T12:41:12.716186,479392872,65367,218,19.01133891602,6.937460508165,-32.188684332965,2,1,18 +2025-03-11T12:41:12.731811,479392872,65367,218,18.71448312896,6.64119827457,-31.6787404325,2,1,18 +2025-03-11T12:41:12.747436,479392872,65367,218,18.42233933852,6.349565265765,-31.164200669975,2,1,18 +2025-03-11T12:41:12.763061,479392872,65367,218,18.13961954132,6.08567499384,-30.645164526395,2,1,18 +2025-03-11T12:41:12.778686,479392872,65367,218,17.86161174074,5.798687515755,-30.11680009769,2,1,18 +2025-03-11T12:41:12.794311,479392872,65367,218,17.5694679503,5.502433435125,-29.602241795165,2,1,18 +2025-03-11T12:41:12.809936,479392872,65367,218,17.28203615648,5.20618750746,-29.07382672445,2,1,18 +2025-03-11T12:41:12.825561,479392872,65367,218,16.98518036942,4.91454634569,-28.554658997855,2,1,18 +2025-03-11T12:41:12.841186,479392872,65367,218,16.70717256884,4.627558867605,-28.021673386085,2,1,18 +2025-03-11T12:41:12.856811,479392872,65367,218,16.42445277164,4.34518430838,-27.484078350245,2,1,18 +2025-03-11T12:41:12.872436,479392872,65367,218,16.10403700148,4.06736559726,-26.955689972495,2,1,18 +2025-03-11T12:41:12.888061,479392872,65367,218,15.81189321104,3.77111151663,-26.43188930384,2,1,18 +2025-03-11T12:41:12.903686,479392872,65367,218,15.5433094037,3.484140344475,-25.912780803275,2,1,18 +2025-03-11T12:41:12.919311,479392872,65367,218,15.2605896065,3.20176578525,-25.38904931663,2,1,18 +2025-03-11T12:41:12.934936,479392872,65367,218,14.9778698093,2.919391226025,-24.865317829985,2,1,18 +2025-03-11T12:41:12.950561,479392872,65367,218,14.68572601886,2.632379289045,-24.34155424133,2,1,18 +2025-03-11T12:41:12.966186,479392872,65367,218,14.3888702318,2.331495983625,-23.80848588554,2,1,18 +2025-03-11T12:41:12.981811,479392872,65367,218,14.09672644136,2.02137868752,-23.27076604769,2,1,18 +2025-03-11T12:41:12.997436,479392872,65367,218,13.7998706543,1.72973752575,-22.7377347719,2,1,18 +2025-03-11T12:41:13.013061,479392872,65367,218,13.52186285372,1.442750047665,-22.195506794,2,1,18 +2025-03-11T12:41:13.028686,479392872,65367,218,13.24385505314,1.15576256958,-21.6532788161,2,1,18 +2025-03-11T12:41:13.044311,479392872,65367,218,12.94699926608,0.868742479634999,-21.12950844644,2,1,18 +2025-03-11T12:41:13.059936,479392872,65367,218,12.64071948578,0.586327155585001,-20.601121871705,2,1,18 +2025-03-11T12:41:13.075561,479392872,65367,218,12.34857569534,0.280830931305,-20.044935841595,2,1,18 +2025-03-11T12:41:13.091186,479392872,65367,218,12.06114390152,-0.0292782118349999,-19.521086333945,2,1,18 +2025-03-11T12:41:13.106811,479392872,65367,218,11.75957611784,-0.32092752657,-18.98804827715,2,1,18 +2025-03-11T12:41:13.122436,479392872,65367,218,11.47214432402,-0.617173454234999,-18.44576965724,2,1,18 +2025-03-11T12:41:13.138061,479392872,65367,218,11.17057654034,-0.922685984445,-17.912675980445,2,1,18 +2025-03-11T12:41:13.153686,479392872,65367,218,10.8784327499,-1.21431899325,-17.3611667534,2,1,18 +2025-03-11T12:41:13.169311,479392872,65367,218,10.5721529696,-1.510597532775,-16.81886100947,2,1,18 +2025-03-11T12:41:13.184936,479392872,65367,218,10.27529718254,-1.820722981845,-16.281134390615,2,1,18 +2025-03-11T12:41:13.200561,479392872,65367,218,9.97372939886,-2.135477655705,-15.752624816885,2,1,18 +2025-03-11T12:41:13.216186,479392872,65367,218,9.68629760504,-2.42248143972,-15.238110375365,2,1,18 +2025-03-11T12:41:13.231811,479392872,65367,218,9.38944181798,-2.70488045784,-14.69125263038,2,1,18 +2025-03-11T12:41:13.247436,479392872,65367,218,9.10201002416,-3.010368529155,-14.125831015145,2,1,18 +2025-03-11T12:41:13.263061,479392872,65367,218,8.8051542371,-3.292767547275,-13.56973090403,2,1,18 +2025-03-11T12:41:13.278686,479392872,65367,218,8.50829845004,-3.57978763722,-13.013612252915,2,1,18 +2025-03-11T12:41:13.294311,479392872,65367,218,8.21144266298,-3.876049870815,-12.471320070995,2,1,18 +2025-03-11T12:41:13.309936,479392872,65367,218,7.90516288268,-4.19081269764,-11.924318984,2,1,18 +2025-03-11T12:41:13.325561,479392872,65367,218,7.59888310238,-4.50095445264,-11.37271525394,2,1,18 +2025-03-11T12:41:13.341186,479392872,65367,218,7.30202731532,-4.80183775806,-10.835025715085,2,1,18 +2025-03-11T12:41:13.356811,479392872,65367,218,7.00988352488,-5.10733398234,-10.315809149495,2,1,18 +2025-03-11T12:41:13.372436,479392872,65367,218,6.7083157412,-5.4036043689,-9.76426782044,2,1,18 +2025-03-11T12:41:13.388061,479392872,65367,218,6.40674795752,-5.69987475546,-9.212726491385,2,1,18 +2025-03-11T12:41:13.403686,479392872,65367,218,6.11460416708,-6.000749907915,-8.6796649166,2,1,18 +2025-03-11T12:41:13.419311,479392872,65367,218,5.80832438678,-6.30627059109,-8.12807972654,2,1,18 +2025-03-11T12:41:13.434936,479392872,65367,218,5.49733260986,-6.60255728358,-7.56266128628,2,1,18 +2025-03-11T12:41:13.450561,479392872,65367,218,5.19576482618,-6.894206598315,-7.00651731416,2,1,18 +2025-03-11T12:41:13.466186,479392872,65367,218,4.88948504588,-7.195106209665,-6.44570829797,2,1,18 +2025-03-11T12:41:13.481811,479392872,65367,218,4.59734125544,-7.500602433945,-5.921870549315,2,1,18 +2025-03-11T12:41:13.497436,479392872,65367,218,4.30990946162,-7.82457479256,-5.397965421665,2,1,18 +2025-03-11T12:41:13.513061,479392872,65367,218,4.01305367456,-8.120837026155,-4.864915605875,2,1,18 +2025-03-11T12:41:13.528686,479392872,65367,218,3.72090988412,-8.39398574766,-4.318101721895,2,1,18 +2025-03-11T12:41:13.544311,479392872,65367,218,3.42405409706,-8.699490124905,-3.74342417852,2,1,18 +2025-03-11T12:41:13.559936,479392872,65367,218,3.13662230324,-9.00497819622,-3.178002563285,2,1,18 +2025-03-11T12:41:13.575561,479392872,65367,218,2.83034252294,-9.29663566392,-2.64957890855,2,1,18 +2025-03-11T12:41:13.591186,479392872,65367,218,2.5146387494,-9.5790672939,-2.09807285648,2,1,18 +2025-03-11T12:41:13.606811,479392872,65367,218,2.21307096572,-9.90306411141,-1.55104147049,2,1,18 +2025-03-11T12:41:13.622436,479392872,65367,218,1.92092717528,-10.19931819204,-0.99489252038,2,1,18 +2025-03-11T12:41:13.638061,479392872,65367,218,1.63820737808,-10.48631382309,-0.45727894454,2,1,18 +2025-03-11T12:41:13.653686,479392872,65367,218,1.3366395944,-10.7918263533,0.0804359153199998,2,1,18 +2025-03-11T12:41:13.669311,479392872,65367,218,1.02564781748,-11.08811304579,0.631990806385,2,1,18 +2025-03-11T12:41:13.684936,479392872,65367,218,0.71465604056,-11.398262953755,1.19284368358,2,1,18 +2025-03-11T12:41:13.700561,479392872,65367,218,0.41308825688,-11.70839655579,1.744440632635,2,1,18 +2025-03-11T12:41:13.716186,479392872,65367,218,0.11623246982,-12.004658789385,2.28211163149,2,1,18 +2025-03-11T12:41:13.731811,479392872,65367,218,-0.18533531386,-12.30555024777,2.824429134415,2,1,18 +2025-03-11T12:41:13.747436,479392872,65367,218,-0.47276710768,-12.61565939091,3.36214219126,2,1,18 +2025-03-11T12:41:13.763061,479392872,65367,218,-0.76962289474,-12.92578483998,3.909111176245,2,1,18 +2025-03-11T12:41:13.778686,479392872,65367,218,-1.06176668518,-13.21279677696,4.446738314095,2,1,18 +2025-03-11T12:41:13.794311,479392872,65367,218,-1.35862247224,-13.48595365143,4.98431661295,2,1,18 +2025-03-11T12:41:13.809936,479392872,65367,218,-1.6554782593,-13.78683695685,5.540490884065,2,1,18 +2025-03-11T12:41:13.825561,479392872,65367,218,-1.9617580396,-14.092357640025,6.10593962332,2,1,18 +2025-03-11T12:41:13.841186,479392872,65367,218,-2.2680378199,-14.402499395025,6.62981625499,2,1,18 +2025-03-11T12:41:13.856811,479392872,65367,218,-2.56489360696,-14.684898413145,7.167431633845,2,1,18 +2025-03-11T12:41:13.872436,479392872,65367,218,-2.8570373974,-14.981152493775,7.71895940089,2,1,18 +2025-03-11T12:41:13.888061,479392872,65367,218,-3.1397571946,-15.27276919665,8.2473491506,2,1,18 +2025-03-11T12:41:13.903686,479392872,65367,218,-3.43190098504,-15.55978113363,8.79421865458,2,1,18 +2025-03-11T12:41:13.919311,479392872,65367,218,-3.73346876872,-15.869914735665,9.336573237505,2,1,18 +2025-03-11T12:41:13.934936,479392872,65367,218,-4.02561255916,-16.175410959945,9.86965335229,2,1,18 +2025-03-11T12:41:13.950561,479392872,65367,218,-4.32718034284,-16.471681346505,10.411952315215,2,1,18 +2025-03-11T12:41:13.966186,479392872,65367,218,-4.6240361299,-16.754080364625,10.94956769407,2,1,18 +2025-03-11T12:41:13.981811,479392872,65367,218,-4.91617992034,-17.03647122978,11.49641865805,2,1,18 +2025-03-11T12:41:13.997375,479392876,65363,219,-5.21774770402,-17.328120544515,12.02483553178,2,1,18 +2025-03-11T12:41:14.013000,479392876,65363,219,-5.52873948094,-17.62902830883,12.567166596715,2,1,18 +2025-03-11T12:41:14.028625,479392876,65363,219,-5.83030726462,-17.929919767215,13.10024173351,2,1,18 +2025-03-11T12:41:14.044250,479392876,65363,219,-6.11773905844,-18.221544623055,13.647122996485,2,1,18 +2025-03-11T12:41:14.059875,479392876,65363,219,-6.38632286578,-18.522379010685,14.17552948318,2,1,18 +2025-03-11T12:41:14.075500,479392876,65363,219,-6.67846665622,-18.83249630679,14.708628137965,2,1,18 +2025-03-11T12:41:14.091125,479392876,65363,219,-6.9800344399,-19.12876669335,15.23244236863,2,1,18 +2025-03-11T12:41:14.106750,479392876,65363,219,-7.25333024386,-19.401882802995,15.7515020302,2,1,18 +2025-03-11T12:41:14.122375,479392876,65363,219,-7.54076203768,-19.684265515185,16.279861480915,2,1,18 +2025-03-11T12:41:14.138000,479392876,65363,219,-7.84704181798,-19.985165126535,16.794458666455,2,1,18 +2025-03-11T12:41:14.153625,479392876,65363,219,-8.12504961856,-20.286015820095,17.309015165965,2,1,18 +2025-03-11T12:41:14.169250,479392876,65363,219,-8.40305741914,-20.577624370005,17.8466405008,2,1,18 +2025-03-11T12:41:14.184875,479392876,65363,219,-8.68106521972,-20.869232919915,18.384265835635,2,1,18 +2025-03-11T12:41:14.200500,479392876,65363,219,-8.97320901016,-21.14238164142,18.912594987355,2,1,18 +2025-03-11T12:41:14.216125,479392876,65363,219,-9.27006479722,-21.45250709049,19.436458057015,2,1,18 +2025-03-11T12:41:14.231750,479392876,65363,219,-9.55749659104,-21.748753018155,19.97411549386,2,1,18 +2025-03-11T12:41:14.247375,479392876,65363,219,-9.83550439162,-22.031119424415,20.51632493176,2,1,18 +2025-03-11T12:41:14.263000,479392876,65363,219,-10.12764818206,-22.31351028957,21.02620643122,2,1,18 +2025-03-11T12:41:14.278625,479392876,65363,219,-10.4197919725,-22.595901154725,21.51760319842,2,1,18 +2025-03-11T12:41:14.294250,479392876,65363,219,-10.7025117697,-22.882896785775,22.04597440813,2,1,18 +2025-03-11T12:41:14.309875,479392876,65363,219,-10.98051957028,-23.156021048385,22.56041966764,2,1,18 +2025-03-11T12:41:14.325500,479392876,65363,219,-11.2679513641,-23.43378268875,23.07489702916,2,1,18 +2025-03-11T12:41:14.341125,479392876,65363,219,-11.54595916468,-23.72539123866,23.594037631735,2,1,18 +2025-03-11T12:41:14.356750,479392876,65363,219,-11.82867896188,-24.01238686971,24.11778765838,2,1,18 +2025-03-11T12:41:14.372375,479392876,65363,219,-12.13024674556,-24.294794040795,24.62768271985,2,1,18 +2025-03-11T12:41:14.388000,479392876,65363,219,-12.41296654276,-24.57716860002,25.1375506573,2,1,18 +2025-03-11T12:41:14.403625,479392876,65363,219,-12.6815503501,-24.868760844,25.64281414867,2,1,18 +2025-03-11T12:41:14.419250,479392876,65363,219,-12.95955815068,-25.13264296296,26.12949522979,2,1,18 +2025-03-11T12:41:14.434875,479392876,65363,219,-13.23756595126,-25.40576722557,26.648561672365,2,1,18 +2025-03-11T12:41:14.450500,479392876,65363,219,-13.51086175522,-25.669641191565,27.167584253935,2,1,18 +2025-03-11T12:41:14.466125,479392876,65363,219,-13.77473356594,-25.95198313893,27.66356151817,2,1,18 +2025-03-11T12:41:14.481750,479392876,65363,219,-14.0480293699,-26.23896246405,28.150328518285,2,1,18 +2025-03-11T12:41:14.497375,479392876,65363,219,-14.34488515696,-26.51211933852,28.655558535685,2,1,18 +2025-03-11T12:41:14.513000,479392876,65363,219,-14.62289295754,-26.771380385655,29.160705809065,2,1,18 +2025-03-11T12:41:14.528625,479392876,65363,219,-14.90090075812,-27.05836786374,29.647479590185,2,1,18 +2025-03-11T12:41:14.544250,479392876,65363,219,-15.16006057222,-27.34070165814,30.152692439545,2,1,18 +2025-03-11T12:41:14.559875,479392876,65363,219,-15.4380683728,-27.609204848925,30.64401324373,2,1,18 +2025-03-11T12:41:14.575500,479392876,65363,219,-15.71607617338,-27.873086967885,31.153800240175,2,1,18 +2025-03-11T12:41:14.591125,479392876,65363,219,-15.98937197734,-28.14620307753,31.65899635255,2,1,18 +2025-03-11T12:41:14.606750,479392876,65363,219,-16.25795578468,-28.423932106035,32.150340674725,2,1,18 +2025-03-11T12:41:14.622375,479392876,65363,219,-16.5218275954,-28.6877897661,32.623137863635,2,1,18 +2025-03-11T12:41:14.638000,479392876,65363,219,-16.79041140274,-28.96089772278,33.100600096615,2,1,18 +2025-03-11T12:41:14.653625,479392876,65363,219,-17.05899521008,-29.238626751285,33.61042915105,2,1,18 +2025-03-11T12:41:14.669250,479392876,65363,219,-17.31815502418,-29.49785518656,34.101685751215,2,1,18 +2025-03-11T12:41:14.684875,479392876,65363,219,-17.5820268349,-29.761712846625,34.574482940125,2,1,18 +2025-03-11T12:41:14.700500,479392876,65363,219,-17.841186649,-30.03018342555,35.05653425416,2,1,18 +2025-03-11T12:41:14.716125,479392876,65363,219,-18.10505845972,-30.284798941965,35.54777909533,2,1,18 +2025-03-11T12:41:14.731750,479392876,65363,219,-18.3595062772,-30.53939815245,36.015904459165,2,1,18 +2025-03-11T12:41:14.747375,479392876,65363,219,-18.60924209806,-30.817094569095,36.48873692506,2,1,18 +2025-03-11T12:41:14.763000,479392876,65363,219,-18.87311390878,-31.076331157335,36.956894390905,2,1,18 +2025-03-11T12:41:14.778625,479392876,65363,219,-19.13227372288,-31.340180664435,37.41120006655,2,1,18 +2025-03-11T12:41:14.794250,479392876,65363,219,-19.40085753022,-31.604046477465,37.874761670335,2,1,18 +2025-03-11T12:41:14.809875,479392876,65363,219,-19.66001734432,-31.858653840915,38.361378547435,2,1,18 +2025-03-11T12:41:14.825500,479392876,65363,219,-19.9144651618,-32.1132530514,38.82950391127,2,1,18 +2025-03-11T12:41:14.841125,479392876,65363,219,-20.1736249759,-32.3771025585,39.29767313611,2,1,18 +2025-03-11T12:41:14.856750,479392876,65363,219,-20.42807279338,-32.61783855351,39.76112169688,2,1,18 +2025-03-11T12:41:14.872375,479392876,65363,219,-20.67780861424,-32.867808539205,40.224600556645,2,1,18 +2025-03-11T12:41:14.888000,479392876,65363,219,-20.9275444351,-33.1177785249,40.7158065148,2,1,18 +2025-03-11T12:41:14.903625,479392876,65363,219,-21.1867042492,-33.381628032,41.19321810577,2,1,18 +2025-03-11T12:41:14.919250,479392876,65363,219,-21.43644007006,-33.640840161345,41.656734045535,2,1,18 +2025-03-11T12:41:14.934875,479392876,65363,219,-21.68617589092,-33.89081014704,42.106349356105,2,1,18 +2025-03-11T12:41:14.950500,479392876,65363,219,-21.9406237084,-34.13154614205,42.54669200155,2,1,18 +2025-03-11T12:41:14.966125,479392876,65363,219,-22.19507152588,-34.38152428071,43.005556459255,2,1,18 +2025-03-11T12:41:14.981750,479392876,65363,219,-22.41653536702,-34.622203204965,43.455094003795,2,1,18 +2025-03-11T12:41:14.997375,479392876,65363,219,-22.65213519802,-34.862906588115,43.88616715909,2,1,18 +2025-03-11T12:41:15.013000,479392876,65363,219,-22.9065830155,-35.10826365495,44.335770710665,2,1,18 +2025-03-11T12:41:15.028625,479392876,65363,219,-23.14689484312,-35.367459478365,44.757682440835,2,1,18 +2025-03-11T12:41:15.044250,479392876,65363,219,-23.3777826775,-35.622017924025,45.20266798432,2,1,18 +2025-03-11T12:41:15.059875,479392876,65363,219,-23.6369424916,-35.858141000175,45.66148360303,2,1,18 +2025-03-11T12:41:15.075500,479392876,65363,219,-23.89139030908,-36.09425592336,46.10642889154,2,1,18 +2025-03-11T12:41:15.091125,479392876,65363,219,-24.11756614684,-36.330321928755,46.53284876176,2,1,18 +2025-03-11T12:41:15.106750,479392876,65363,219,-24.35787797446,-36.57103346487,46.9454439658,2,1,18 +2025-03-11T12:41:15.122375,479392876,65363,219,-24.58876580884,-36.793244407755,47.381057363155,2,1,18 +2025-03-11T12:41:15.138000,479392876,65363,219,-24.80551765336,-37.033915179045,47.816724577495,2,1,18 +2025-03-11T12:41:15.153625,479392876,65363,219,-25.04111748436,-37.274618562195,48.224691817465,2,1,18 +2025-03-11T12:41:15.169250,479392876,65363,219,-25.27200531874,-37.492208433255,48.64180194256,2,1,18 +2025-03-11T12:41:15.184875,479392876,65363,219,-25.50289315312,-37.719040447965,49.068191513785,2,1,18 +2025-03-11T12:41:15.200500,479392876,65363,219,-25.73849298412,-37.941259543815,49.48994814295,2,1,18 +2025-03-11T12:41:15.216125,479392876,65363,219,-25.95524482864,-38.172688171455,49.920957094225,2,1,18 +2025-03-11T12:41:15.231750,479392876,65363,219,-26.16728467654,-38.38562435883,50.31953682304,2,1,18 +2025-03-11T12:41:15.247375,479392876,65363,219,-26.39817251092,-38.60321422989,50.718162215875,2,1,18 +2025-03-11T12:41:15.263000,479392876,65363,219,-26.62434834868,-38.83465916346,51.126078813835,2,1,18 +2025-03-11T12:41:15.278625,479392876,65363,219,-26.8411001932,-39.0660877911,51.524739483655,2,1,18 +2025-03-11T12:41:15.294250,479392876,65363,219,-27.07198802758,-39.279056590335,51.94183106875,2,1,18 +2025-03-11T12:41:15.309875,479392876,65363,219,-27.3122998552,-39.505904910975,52.3266435544,2,1,18 +2025-03-11T12:41:15.325500,479392876,65363,219,-27.5243397031,-39.728083242,52.716017997085,2,1,18 +2025-03-11T12:41:15.341125,479392876,65363,219,-27.73166755438,-39.93176913276,53.123796231025,2,1,18 +2025-03-11T12:41:15.356750,479392876,65363,219,-27.9248594158,-40.135430564625,53.52231175582,2,1,18 +2025-03-11T12:41:15.372375,479392876,65363,219,-28.14161126032,-40.376101335915,53.89328240725,2,1,18 +2025-03-11T12:41:15.388000,479392876,65363,219,-28.36307510146,-40.60753811652,54.282707491945,2,1,18 +2025-03-11T12:41:15.403625,479392876,65363,219,-28.57982694598,-40.82048245686,54.66743045257,2,1,18 +2025-03-11T12:41:15.419250,479392876,65363,219,-28.78715479726,-41.02416834762,55.06596632038,2,1,18 +2025-03-11T12:41:15.434875,479392876,65363,219,-28.99919464516,-41.22324131952,55.45062688,2,1,18 +2025-03-11T12:41:15.450500,479392876,65363,219,-29.20652249644,-41.422306138455,55.816795926355,2,1,18 +2025-03-11T12:41:15.466125,479392876,65363,219,-29.41385034772,-41.63985524469,56.178417949645,2,1,18 +2025-03-11T12:41:15.481750,479392876,65363,219,-29.62589019562,-41.852791432065,56.54927058007,2,1,18 +2025-03-11T12:41:15.497375,479392876,65363,219,-29.8332180469,-42.04261410735,56.924644912555,2,1,18 +2025-03-11T12:41:15.513000,479392876,65363,219,-30.03112190494,-42.241662620355,57.30928512916,2,1,18 +2025-03-11T12:41:15.528625,479392876,65363,219,-30.22902576298,-42.436090061535,57.656937341245,2,1,18 +2025-03-11T12:41:15.544250,479392876,65363,219,-30.43164161764,-42.635146727505,58.013857240465,2,1,18 +2025-03-11T12:41:15.559875,479392876,65363,219,-30.62954547568,-42.81571095321,58.37993856481,2,1,18 +2025-03-11T12:41:15.575500,479392876,65363,219,-30.82744933372,-43.024001609865,58.736888763025,2,1,18 +2025-03-11T12:41:15.591125,479392876,65363,219,-31.01592919852,-43.218412745115,59.09376977923,2,1,18 +2025-03-11T12:41:15.606750,479392876,65363,219,-31.21854505318,-43.42209048291,59.427602303125,2,1,18 +2025-03-11T12:41:15.622375,479392876,65363,219,-31.42587290446,-43.60729208637,59.761367448025,2,1,18 +2025-03-11T12:41:15.638000,479392876,65363,219,-31.60492877602,-43.79244477204,60.113576639155,2,1,18 +2025-03-11T12:41:15.653625,479392876,65363,219,-31.77927265096,-43.986831448395,60.44733139702,2,1,18 +2025-03-11T12:41:15.669250,479392876,65363,219,-31.95832852252,-44.171984134065,60.79029822202,2,1,18 +2025-03-11T12:41:15.684875,479392876,65363,219,-32.14680838732,-44.35253205384,61.11477533677,2,1,18 +2025-03-11T12:41:15.700500,479392876,65363,219,-32.32586425888,-44.533063667685,61.453102438705,2,1,18 +2025-03-11T12:41:15.716125,479392876,65363,219,-32.51434412368,-44.736716946585,61.79153580265,2,1,18 +2025-03-11T12:41:15.731750,479392876,65363,219,-32.7075359851,-44.92189409115,62.125280604535,2,1,18 +2025-03-11T12:41:15.747375,479392876,65363,219,-32.8960158499,-45.093199867275,62.45434182235,2,1,18 +2025-03-11T12:41:15.763000,479392876,65363,219,-33.07978371808,-45.25987641861,62.78337771916,2,1,18 +2025-03-11T12:41:15.778625,479392876,65363,219,-33.25883958964,-45.431165888805,63.08007709351,2,1,18 +2025-03-11T12:41:15.794250,479392876,65363,219,-33.41904747472,-45.607043818965,63.40449498223,2,1,18 +2025-03-11T12:41:15.809875,479392876,65363,219,-33.59339134966,-45.778325136195,63.7242934909,2,1,18 +2025-03-11T12:41:15.825500,479392876,65363,219,-33.77715921784,-45.940380615705,64.03482611545,2,1,18 +2025-03-11T12:41:15.841125,479392876,65363,219,-33.92323111306,-46.111613015145,64.331478022765,2,1,18 +2025-03-11T12:41:15.856750,479392876,65363,219,-34.07872700152,-46.27824064869,64.62812495209,2,1,18 +2025-03-11T12:41:15.872375,479392876,65363,219,-34.24364688322,-46.444884588165,64.961754907945,2,1,18 +2025-03-11T12:41:15.888000,479392876,65363,219,-34.41327876154,-46.602294536955,65.29073338174,2,1,18 +2025-03-11T12:41:15.903625,479392876,65363,219,-34.58762263648,-46.75971263871,65.58274917202,2,1,18 +2025-03-11T12:41:15.919250,479392876,65363,219,-34.73840652832,-46.91708997564,65.87935224034,2,1,18 +2025-03-11T12:41:15.934875,479392876,65363,219,-34.8986144134,-47.08372576215,66.171384767605,2,1,18 +2025-03-11T12:41:15.950500,479392876,65363,219,-35.0635342951,-47.241127557975,66.463386995875,2,1,18 +2025-03-11T12:41:15.966125,479392876,65363,219,-35.2048941937,-47.398488588975,66.759976502185,2,1,18 +2025-03-11T12:41:15.981750,479392876,65363,219,-35.33683009906,-47.555833314045,67.05193126342,2,1,18 +2025-03-11T12:41:15.997375,479392876,65363,219,-35.48290199428,-47.717823569835,67.339303724605,2,1,18 +2025-03-11T12:41:16.013000,479392876,65363,219,-35.6525338726,-47.875233518625,67.598964452425,2,1,18 +2025-03-11T12:41:16.028625,479392876,65363,219,-35.80331776444,-48.01874764008,67.867784802355,2,1,18 +2025-03-11T12:41:16.044250,479392876,65363,219,-35.9588136529,-48.1622699145,68.122748384095,2,1,18 +2025-03-11T12:41:16.059875,479392876,65363,219,-36.10488554812,-48.310396954815,68.405444042215,2,1,18 +2025-03-11T12:41:16.075500,479392876,65363,219,-36.25095744334,-48.444660779655,68.65573579888,2,1,18 +2025-03-11T12:41:16.091125,479392876,65363,219,-36.38760534532,-48.59277151404,68.906069613535,2,1,18 +2025-03-11T12:41:16.106750,479392876,65363,219,-36.52896524392,-48.745511473215,69.184155847585,2,1,18 +2025-03-11T12:41:16.122375,479392876,65363,219,-36.6656131459,-48.8936222076,69.43448966224,2,1,18 +2025-03-11T12:41:16.138000,479392876,65363,219,-36.78812505802,-49.02322419579,69.670865424685,2,1,18 +2025-03-11T12:41:16.153625,479392876,65363,219,-36.92006096338,-49.15284248991,69.911875932205,2,1,18 +2025-03-11T12:41:16.169250,479392876,65363,219,-37.06142086198,-49.287098161785,70.1575397248,2,1,18 +2025-03-11T12:41:16.184875,479392876,65363,219,-37.20278076058,-49.416732761835,70.403184977395,2,1,18 +2025-03-11T12:41:16.200500,479392876,65363,219,-37.32058067608,-49.550947668885,70.6441936819,2,1,18 +2025-03-11T12:41:16.216125,479392876,65363,219,-37.45251658144,-49.680565963005,70.862098274095,2,1,18 +2025-03-11T12:41:16.231750,479392876,65363,219,-37.58916448342,-49.796329194615,71.09381757649,2,1,18 +2025-03-11T12:41:16.247375,479392876,65363,219,-37.71638839216,-49.921318263945,71.33018157994,2,1,18 +2025-03-11T12:41:16.263000,479392876,65363,219,-37.82947631104,-50.04628287438,71.538798141985,2,1,18 +2025-03-11T12:41:16.278625,479392876,65363,219,-37.94256422992,-50.17586855664,71.761296793225,2,1,18 +2025-03-11T12:41:16.294250,479392876,65363,219,-38.06507614204,-50.28698625753,71.974492480345,2,1,18 +2025-03-11T12:41:16.309875,479392876,65363,219,-38.18287605754,-50.41195902093,72.183115823395,2,1,18 +2025-03-11T12:41:16.325500,479392876,65363,219,-38.31009996628,-50.52770594661,72.37785209926,2,1,18 +2025-03-11T12:41:16.341125,479392876,65363,219,-38.4090518953,-50.648025026325,72.58642977829,2,1,18 +2025-03-11T12:41:16.356750,479392876,65363,219,-38.52213981418,-50.76374749311,72.813493992595,2,1,18 +2025-03-11T12:41:16.372375,479392876,65363,219,-38.62580373982,-50.860969366665,73.00350102037,2,1,18 +2025-03-11T12:41:16.388000,479392876,65363,219,-38.74360365532,-50.967457842765,73.1750807389,2,1,18 +2025-03-11T12:41:16.403625,479392876,65363,219,-38.85197957758,-51.06930894111,73.39284018607,2,1,18 +2025-03-11T12:41:16.419250,479392876,65363,219,-38.96035549984,-51.161917895805,73.596699004045,2,1,18 +2025-03-11T12:41:16.434875,479392876,65363,219,-39.0687314221,-51.259147922325,73.78209162976,2,1,18 +2025-03-11T12:41:16.450500,479392876,65363,219,-39.15825935788,-51.35172426516,73.94433267613,2,1,18 +2025-03-11T12:41:16.466125,479392876,65363,219,-39.25249929028,-51.46279304826,74.12976057883,2,1,18 +2025-03-11T12:41:16.481750,479392876,65363,219,-39.35616321592,-51.56463599364,74.32440732967,2,1,18 +2025-03-11T12:41:16.497375,479392876,65363,219,-39.46453913818,-51.66186602016,74.48669404006,2,1,18 +2025-03-11T12:41:16.513000,479392876,65363,219,-39.54935507734,-51.749813138205,74.63504621623,2,1,18 +2025-03-11T12:41:16.528625,479392876,65363,219,-39.64359500974,-51.842397634005,74.80191522667,2,1,18 +2025-03-11T12:41:16.544250,479392876,65363,219,-39.74254693876,-51.939611354595,74.98267310731,2,1,18 +2025-03-11T12:41:16.559875,479392876,65363,219,-39.81322688806,-52.027534013745,75.15411085579,2,1,18 +2025-03-11T12:41:16.575500,479392876,65363,219,-39.8933308306,-52.10160976335,75.29777944789,2,1,18 +2025-03-11T12:41:16.591125,479392876,65363,219,-39.987570763,-52.189573187325,75.44614518607,2,1,18 +2025-03-11T12:41:16.606750,479392876,65363,219,-40.06767470554,-52.27289108058,75.612956773495,2,1,18 +2025-03-11T12:41:16.622375,479392876,65363,219,-40.14306665146,-52.34695867722,75.75661858459,2,1,18 +2025-03-11T12:41:16.638000,479392876,65363,219,-40.22788259062,-52.425663651615,75.900312497695,2,1,18 +2025-03-11T12:41:16.653625,479392876,65363,219,-40.30798653316,-52.49049725757,76.0300804606,2,1,18 +2025-03-11T12:41:16.669250,479392876,65363,219,-40.38337847908,-52.559943782385,76.15061781637,2,1,18 +2025-03-11T12:41:16.684875,479392876,65363,219,-40.46348242162,-52.62477738834,76.280385779275,2,1,18 +2025-03-11T12:41:16.700500,479392876,65363,219,-40.53416237092,-52.69421576019,76.40091635404,2,1,18 +2025-03-11T12:41:16.716125,479392876,65363,219,-40.59541832698,-52.777501041585,76.539973719055,2,1,18 +2025-03-11T12:41:16.731750,479392876,65363,219,-40.6472502898,-52.856148945225,76.6605142498,2,1,18 +2025-03-11T12:41:16.747375,479392876,65363,219,-40.7179302391,-52.916345173425,76.781007744565,2,1,18 +2025-03-11T12:41:16.763000,479392876,65363,219,-40.78389819178,-52.971912176835,76.910718284455,2,1,18 +2025-03-11T12:41:16.778625,479392876,65363,219,-40.84515414784,-53.03671317093,77.02197439108,2,1,18 +2025-03-11T12:41:16.794250,479392876,65363,219,-40.90169810728,-53.09226386841,77.110080721375,2,1,18 +2025-03-11T12:41:16.809875,479392876,65363,219,-40.95824206672,-53.152435637715,77.2074479578,2,1,18 +2025-03-11T12:41:16.825500,479392876,65363,219,-41.0006500363,-53.212582948125,77.31403721734,2,1,18 +2025-03-11T12:41:16.841125,479392876,65363,219,-41.0477700025,-53.2542541242,77.402074365625,2,1,18 +2025-03-11T12:41:16.856750,479392876,65363,219,-41.10431396194,-53.305183749855,77.485540972855,2,1,18 +2025-03-11T12:41:16.872375,479392876,65363,219,-41.16085792138,-53.37459766281,77.57370292315,2,1,18 +2025-03-11T12:41:16.888000,479392876,65363,219,-41.20326589096,-53.42550282957,77.6525280043,2,1,18 +2025-03-11T12:41:16.903625,479392876,65363,219,-41.25509785378,-53.453318943135,77.735895130525,2,1,18 +2025-03-11T12:41:16.919250,479392876,65363,219,-41.30221781998,-53.49499011921,77.82393227881,2,1,18 +2025-03-11T12:41:16.934875,479392876,65363,219,-41.34933778618,-53.53204022346,77.911950887095,2,1,18 +2025-03-11T12:41:16.950500,479392876,65363,219,-41.39174575576,-53.57370324657,77.981496522115,2,1,18 +2025-03-11T12:41:16.966125,479392876,65363,219,-41.43415372534,-53.610745197855,78.051023617135,2,1,18 +2025-03-11T12:41:16.981750,479392876,65363,219,-41.46242570506,-53.647762690245,78.09280327075,2,1,18 +2025-03-11T12:41:16.997375,479392876,65363,219,-41.49069768478,-53.694022326285,78.15772591969,2,1,18 +2025-03-11T12:41:17.013000,479392876,65363,219,-41.50954567126,-53.721781369095,78.217939663555,2,1,18 +2025-03-11T12:41:17.028625,479392876,65363,219,-41.53781765098,-53.740314574185,78.273508706365,2,1,18 +2025-03-11T12:41:17.044250,479392876,65363,219,-41.57080162732,-53.763477004065,78.333724253245,2,1,18 +2025-03-11T12:41:17.059875,479392876,65363,219,-41.59907360704,-53.78663128098,78.380069469925,2,1,18 +2025-03-11T12:41:17.075500,479392876,65363,219,-41.62263359014,-53.80977740493,78.4264079056,2,1,18 +2025-03-11T12:41:17.091125,479392876,65363,219,-41.64619357324,-53.828302457055,78.44962188595,2,1,18 +2025-03-11T12:41:17.106750,479392876,65363,219,-41.66504155972,-53.86068257169,78.500611803685,2,1,18 +2025-03-11T12:41:17.122375,479392876,65363,219,-41.6838895462,-53.8884416145,78.54234081529,2,1,18 +2025-03-11T12:41:17.138000,479392876,65363,219,-41.70273753268,-53.911579585485,78.565566554635,2,1,18 +2025-03-11T12:41:17.153625,479392876,65363,219,-41.7074495293,-53.906966666625,78.588660710965,2,1,18 +2025-03-11T12:41:17.169250,479392876,65363,219,-41.72158551916,-53.90699112552,78.61640815237,2,1,18 +2025-03-11T12:41:17.184875,479392876,65363,219,-41.74043350564,-53.91626588103,78.63495708865,2,1,18 +2025-03-11T12:41:17.200500,479392876,65363,219,-41.75928149212,-53.939403852015,78.66280401106,2,1,18 +2025-03-11T12:41:17.216125,479392876,65363,219,-41.76870548536,-53.94404122977,78.6720784792,2,1,18 +2025-03-11T12:41:17.231750,479392876,65363,219,-41.77341748198,-53.94867045456,78.662861434075,2,1,18 +2025-03-11T12:41:17.247375,479392876,65363,219,-41.77341748198,-53.944049382735,78.662842894075,2,1,18 +2025-03-11T12:41:17.263000,479392876,65363,219,-41.77341748198,-53.93018616726,78.672029640205,2,1,18 +2025-03-11T12:41:17.278625,479392876,65363,219,-41.77341748198,-53.92094402361,78.681234926335,2,1,18 +2025-03-11T12:41:17.294250,479392876,65363,219,-41.76399348874,-53.93016986133,78.662773712065,2,1,18 +2025-03-11T12:41:17.309875,479392876,65363,219,-41.74985749888,-53.920903258785,78.64423155679,2,1,18 +2025-03-11T12:41:17.325500,479392876,65363,219,-41.73572150902,-53.91163665624,78.63031058458,2,1,18 +2025-03-11T12:41:17.341125,479392876,65363,219,-41.72629751578,-53.91162035031,78.59332755805,2,1,18 +2025-03-11T12:41:17.356750,479392876,65363,219,-41.71687352254,-53.91160404438,78.579450446845,2,1,18 +2025-03-11T12:41:17.372375,479392876,65363,219,-41.71216152592,-53.893111604115,78.56088477358,2,1,18 +2025-03-11T12:41:17.388000,479392876,65363,219,-41.69331353944,-53.856110417655,78.52373986504,2,1,18 +2025-03-11T12:41:17.403625,479392876,65363,219,-41.66504155972,-53.82371399709,78.500463483685,2,1,18 +2025-03-11T12:41:17.419250,479392876,65363,219,-41.65561756648,-53.819076619335,78.463461917155,2,1,18 +2025-03-11T12:41:17.434875,479392876,65363,219,-41.63205758338,-53.79130942356,78.421726124545,2,1,18 +2025-03-11T12:41:17.450500,479392876,65363,219,-41.61792159352,-53.77742174919,78.37543833088,2,1,18 +2025-03-11T12:41:17.466125,479392876,65363,219,-41.59907360704,-53.75890485003,78.34760994847,2,1,18 +2025-03-11T12:41:17.481750,479392876,65363,219,-41.57080162732,-53.726508429465,78.278121736465,2,1,18 +2025-03-11T12:41:17.497375,479392876,65363,219,-41.53781765098,-53.703345999585,78.21328500652,2,1,18 +2025-03-11T12:41:17.513000,479392876,65363,219,-41.50483367464,-53.652457138755,78.148337036575,2,1,18 +2025-03-11T12:41:17.528625,479392876,65363,219,-41.46713770168,-53.615423340435,78.09730145482,2,1,18 +2025-03-11T12:41:17.544250,479392876,65363,219,-41.4247297321,-53.601486748275,78.032488242865,2,1,18 +2025-03-11T12:41:17.559875,479392876,65363,219,-41.38703375914,-53.56907402178,77.97222883498,2,1,18 +2025-03-11T12:41:17.575500,479392876,65363,219,-41.3540497828,-53.5274273046,77.90269676197,2,1,18 +2025-03-11T12:41:17.591125,479392876,65363,219,-41.3069298166,-53.4811350567,77.814641073685,2,1,18 +2025-03-11T12:41:17.606750,479392876,65363,219,-41.26452184702,-53.434850961765,77.735834532535,2,1,18 +2025-03-11T12:41:17.622375,479392876,65363,219,-41.23153787068,-53.37934102911,77.647762107265,2,1,18 +2025-03-11T12:41:17.638000,479392876,65363,219,-41.17499391124,-53.33303247528,77.54120812471,2,1,18 +2025-03-11T12:41:17.653625,479392876,65363,219,-41.12316194842,-53.30059528989,77.430095360095,2,1,18 +2025-03-11T12:41:17.669250,479392876,65363,219,-41.08075397884,-53.25893226678,77.33744380975,2,1,18 +2025-03-11T12:41:17.684875,479392876,65363,219,-41.03363401264,-53.198776803405,77.23546895227,2,1,18 +2025-03-11T12:41:17.700500,479392876,65363,219,-40.97237805658,-53.13397580931,77.13807639484,2,1,18 +2025-03-11T12:41:17.716125,479392876,65363,219,-40.91112210052,-53.096901246165,77.036173894345,2,1,18 +2025-03-11T12:41:17.731750,479392876,65363,219,-40.87342612756,-53.041383160545,76.915746406615,2,1,18 +2025-03-11T12:41:17.747375,479392876,65363,219,-40.81688216812,-52.967348175765,76.813702367125,2,1,18 +2025-03-11T12:41:17.763000,479392876,65363,219,-40.7414902222,-52.902522722775,76.693183551355,2,1,18 +2025-03-11T12:41:17.778625,479392876,65363,219,-40.68023426614,-52.833100656855,76.58190890473,2,1,18 +2025-03-11T12:41:17.794250,479392876,65363,219,-40.6236903067,-52.7452024566,76.46132451298,2,1,18 +2025-03-11T12:41:17.809875,479392876,65363,219,-40.54829836078,-52.666513788135,76.336128894145,2,1,18 +2025-03-11T12:41:17.825500,479392876,65363,219,-40.47290641486,-52.592446191495,76.21095181531,2,1,18 +2025-03-11T12:41:17.841125,479392876,65363,219,-40.40693846218,-52.527637044435,76.095067744615,2,1,18 +2025-03-11T12:41:17.856750,479392876,65363,219,-40.33625851288,-52.47206188806,75.95610805759,2,1,18 +2025-03-11T12:41:17.872375,479392876,65363,219,-40.25615457034,-52.38412292298,75.817005028555,2,1,18 +2025-03-11T12:41:17.888000,479392876,65363,219,-40.17133863118,-52.30079687676,75.67329257545,2,1,18 +2025-03-11T12:41:17.903625,479392876,65363,219,-40.09594668526,-52.222108208295,75.51574867516,2,1,18 +2025-03-11T12:41:17.919250,479392876,65363,219,-40.02526673596,-52.14804876462,75.367472462005,2,1,18 +2025-03-11T12:41:17.934875,479392876,65363,219,-39.94516279342,-52.06010979954,75.20988470071,2,1,18 +2025-03-11T12:41:17.950500,479392876,65363,219,-39.86034685426,-51.96754160967,75.04302925228,2,1,18 +2025-03-11T12:41:17.966125,479392876,65363,219,-39.76139492524,-51.87957003273,74.885414366965,2,1,18 +2025-03-11T12:41:17.981750,479392876,65363,219,-39.67657898608,-51.791622914685,74.718577458535,2,1,18 +2025-03-11T12:41:17.997299,479392880,65358,220,-39.5870510503,-51.703667643675,74.57021850136,2,1,18 +2025-03-11T12:41:18.012924,479392880,65358,220,-39.4928111179,-51.611083147875,74.40334949092,2,1,18 +2025-03-11T12:41:18.028549,479392880,65358,220,-39.39385918888,-51.504627283635,74.21331216415,2,1,18 +2025-03-11T12:41:18.044174,479392880,65358,220,-39.29490725986,-51.41203463487,74.027951640445,2,1,18 +2025-03-11T12:41:18.059799,479392880,65358,220,-39.20066732746,-51.324071210895,73.84723762081,2,1,18 +2025-03-11T12:41:18.075424,479392880,65358,220,-39.09700340182,-51.212986121865,73.657174973035,2,1,18 +2025-03-11T12:41:18.091049,479392880,65358,220,-38.98862747956,-51.097271808045,73.47170818732,2,1,18 +2025-03-11T12:41:18.106674,479392880,65358,220,-38.88967555054,-50.990815943805,73.28167086055,2,1,18 +2025-03-11T12:41:18.122299,479392880,65358,220,-38.77187563504,-50.87970639588,73.086966686695,2,1,18 +2025-03-11T12:41:18.137924,479392880,65358,220,-38.66349971278,-50.768613153885,72.90151844098,2,1,18 +2025-03-11T12:41:18.153549,479392880,65358,220,-38.5504117939,-50.68061711805,72.693050198935,2,1,18 +2025-03-11T12:41:18.169174,479392880,65358,220,-38.43732387502,-50.58800001039,72.48456341689,2,1,18 +2025-03-11T12:41:18.184799,479392880,65358,220,-38.34308394262,-50.472310155465,72.28063224193,2,1,18 +2025-03-11T12:41:18.200424,479392880,65358,220,-38.23470802036,-50.35197476982,72.085904550085,2,1,18 +2025-03-11T12:41:18.216049,479392880,65358,220,-38.11690810486,-50.222380934595,71.858777934775,2,1,18 +2025-03-11T12:41:18.231674,479392880,65358,220,-37.99910818936,-50.09278709937,71.640893685595,2,1,18 +2025-03-11T12:41:18.247299,479392880,65358,220,-37.867172284,-49.98165309255,71.436926802595,2,1,18 +2025-03-11T12:41:18.262924,479392880,65358,220,-37.75408436512,-49.85206741029,71.214428151355,2,1,18 +2025-03-11T12:41:18.278549,479392880,65358,220,-37.63628444962,-49.731715718715,70.987338616045,2,1,18 +2025-03-11T12:41:18.294174,479392880,65358,220,-37.51848453412,-49.61136402714,70.741764348475,2,1,18 +2025-03-11T12:41:18.309799,479392880,65358,220,-37.39126062538,-49.47713281416,70.52846918035,2,1,18 +2025-03-11T12:41:18.325424,479392880,65358,220,-37.24990072678,-49.342877142285,70.30591130308,2,1,18 +2025-03-11T12:41:18.341049,479392880,65358,220,-37.12267681804,-49.208645929305,70.055646670435,2,1,18 +2025-03-11T12:41:18.356674,479392880,65358,220,-37.00016490592,-49.07442286929,69.7915252696,2,1,18 +2025-03-11T12:41:18.372299,479392880,65358,220,-36.87294099718,-48.94019165631,69.53663945389,2,1,18 +2025-03-11T12:41:18.387924,479392880,65358,220,-36.72215710534,-48.80129860668,69.300185925415,2,1,18 +2025-03-11T12:41:18.403549,479392880,65358,220,-36.58079720674,-48.67166400663,69.04529830669,2,1,18 +2025-03-11T12:41:18.419174,479392880,65358,220,-36.4300133149,-48.518907741525,68.78568324289,2,1,18 +2025-03-11T12:41:18.434799,479392880,65358,220,-36.2886534163,-48.375409926,68.530740004165,2,1,18 +2025-03-11T12:41:18.450424,479392880,65358,220,-36.15671751094,-48.24579163188,68.26662358132,2,1,18 +2025-03-11T12:41:18.466049,479392880,65358,220,-36.01064561572,-48.088422447915,67.99313320933,2,1,18 +2025-03-11T12:41:18.481674,479392880,65358,220,-35.86928571712,-47.93568248874,67.72428934141,2,1,18 +2025-03-11T12:41:18.497299,479392880,65358,220,-35.71850182528,-47.80603158276,67.450903428415,2,1,18 +2025-03-11T12:41:18.512924,479392880,65358,220,-35.56771793344,-47.671759604955,67.200604890745,2,1,18 +2025-03-11T12:41:18.528549,479392880,65358,220,-35.4169340416,-47.514382268025,66.931728920815,2,1,18 +2025-03-11T12:41:18.544174,479392880,65358,220,-35.25672615652,-47.34312540969,66.644299036615,2,1,18 +2025-03-11T12:41:18.559799,479392880,65358,220,-35.11536625792,-47.18576437869,66.3615730795,2,1,18 +2025-03-11T12:41:18.575424,479392880,65358,220,-34.95515837284,-47.051476094955,66.0742915153,2,1,18 +2025-03-11T12:41:18.591049,479392880,65358,220,-34.78552649452,-46.875581858865,65.782208346025,2,1,18 +2025-03-11T12:41:18.606674,479392880,65358,220,-34.63003060606,-46.71819636897,65.4855984967,2,1,18 +2025-03-11T12:41:18.622299,479392880,65358,220,-34.48395871084,-46.55620611318,65.18436248632,2,1,18 +2025-03-11T12:41:18.637924,479392880,65358,220,-34.31903882914,-46.38494110188,64.89230463805,2,1,18 +2025-03-11T12:41:18.653549,479392880,65358,220,-34.14940695082,-46.21828900944,64.59563736571,2,1,18 +2025-03-11T12:41:18.669174,479392880,65358,220,-33.9797750725,-46.056257988825,64.28050390111,2,1,18 +2025-03-11T12:41:18.684799,479392880,65358,220,-33.81956718742,-45.88500113049,63.96534691852,2,1,18 +2025-03-11T12:41:18.700424,479392880,65358,220,-33.64051131586,-45.713711660295,63.65940517804,2,1,18 +2025-03-11T12:41:18.716049,479392880,65358,220,-33.47559143416,-45.53782557717,63.35808642364,2,1,18 +2025-03-11T12:41:18.731674,479392880,65358,220,-33.31538354908,-45.366568718835,63.01520234266,2,1,18 +2025-03-11T12:41:18.747299,479392880,65358,220,-33.1316156809,-45.1814078802,62.69533465198,2,1,18 +2025-03-11T12:41:18.762924,479392880,65358,220,-32.94784781272,-44.99162596974,62.38469078743,2,1,18 +2025-03-11T12:41:18.778549,479392880,65358,220,-32.76879194116,-44.820336499545,62.074127863885,2,1,18 +2025-03-11T12:41:18.794174,479392880,65358,220,-32.59916006284,-44.635200119805,61.74503815009,2,1,18 +2025-03-11T12:41:18.809799,479392880,65358,220,-32.42010419128,-44.440805290485,61.397413062025,2,1,18 +2025-03-11T12:41:18.825424,479392880,65358,220,-32.24576031634,-44.27414504508,61.068390727225,2,1,18 +2025-03-11T12:41:18.841049,479392880,65358,220,-32.06670444478,-44.09823450306,60.73008216529,2,1,18 +2025-03-11T12:41:18.856674,479392880,65358,220,-31.8829365766,-43.9084525926,60.396332385415,2,1,18 +2025-03-11T12:41:18.872299,479392880,65358,220,-31.69916870842,-43.714049610315,60.048700516345,2,1,18 +2025-03-11T12:41:18.887924,479392880,65358,220,-31.505976847,-43.51038817845,59.701018005265,2,1,18 +2025-03-11T12:41:18.903549,479392880,65358,220,-31.31278498558,-43.325211033885,59.362652020315,2,1,18 +2025-03-11T12:41:18.919174,479392880,65358,220,-31.11488112754,-43.13540466453,59.019639531295,2,1,18 +2025-03-11T12:41:18.934799,479392880,65358,220,-30.90755327626,-42.936339845595,58.648849301875,2,1,18 +2025-03-11T12:41:18.950424,479392880,65358,220,-30.69551342836,-42.76037223282,58.28738735758,2,1,18 +2025-03-11T12:41:18.966049,479392880,65358,220,-30.49760957032,-42.56594479164,57.930492779365,2,1,18 +2025-03-11T12:41:18.981674,479392880,65358,220,-30.29970571228,-42.36227520681,57.559697571955,2,1,18 +2025-03-11T12:41:18.997299,479392880,65358,220,-30.11122584748,-42.163242999735,57.198176832685,2,1,18 +2025-03-11T12:41:19.012924,479392880,65358,220,-29.92274598268,-41.94572650536,56.84120311648,2,1,18 +2025-03-11T12:41:19.028549,479392880,65358,220,-29.73426611788,-41.737452154635,56.47040293108,2,1,18 +2025-03-11T12:41:19.044174,479392880,65358,220,-29.52222626998,-41.53375811091,56.07648146533,2,1,18 +2025-03-11T12:41:19.059799,479392880,65358,220,-29.3148984187,-41.33007222015,55.71491506204,2,1,18 +2025-03-11T12:41:19.075424,479392880,65358,220,-29.10757056742,-41.12638632939,55.339485109555,2,1,18 +2025-03-11T12:41:19.091049,479392880,65358,220,-28.90024271614,-40.908837223155,54.93627243868,2,1,18 +2025-03-11T12:41:19.106674,479392880,65358,220,-28.69762686148,-40.69591734171,54.565433370265,2,1,18 +2025-03-11T12:41:19.122299,479392880,65358,220,-28.49501100682,-40.492239603915,54.18538901572,2,1,18 +2025-03-11T12:41:19.137924,479392880,65358,220,-28.26883516906,-40.279278957645,53.78678894389,2,1,18 +2025-03-11T12:41:19.153549,479392880,65358,220,-28.05208332454,-40.057092473655,53.392786537135,2,1,18 +2025-03-11T12:41:19.169174,479392880,65358,220,-27.84004347664,-39.85339842993,53.00348625445,2,1,18 +2025-03-11T12:41:19.184799,479392880,65358,220,-27.62800362874,-39.640462242555,52.60028534257,2,1,18 +2025-03-11T12:41:19.200424,479392880,65358,220,-27.4065397876,-39.422888677425,52.201673511745,2,1,18 +2025-03-11T12:41:19.216049,479392880,65358,220,-27.18978794308,-39.19608112161,51.803031381925,2,1,18 +2025-03-11T12:41:19.231674,479392880,65358,220,-26.95418811208,-38.96461988211,51.404343588085,2,1,18 +2025-03-11T12:41:19.247299,479392880,65358,220,-26.7233002777,-38.742408939225,51.001078472185,2,1,18 +2025-03-11T12:41:19.262924,479392880,65358,220,-26.50654843318,-38.529464598885,50.593249596235,2,1,18 +2025-03-11T12:41:19.278549,479392880,65358,220,-26.28508459204,-38.302648890105,50.18535831928,2,1,18 +2025-03-11T12:41:19.294174,479392880,65358,220,-26.06833274752,-38.089704549765,49.782150626395,2,1,18 +2025-03-11T12:41:19.309799,479392880,65358,220,-25.851580903,-37.86289699395,49.374266130445,2,1,18 +2025-03-11T12:41:19.325424,479392880,65358,220,-25.62540506524,-37.626830988555,48.966330992485,2,1,18 +2025-03-11T12:41:19.341049,479392880,65358,220,-25.38980523424,-37.386127605405,48.53525783719,2,1,18 +2025-03-11T12:41:19.356674,479392880,65358,220,-25.14006941338,-37.14539976336,48.10416433888,2,1,18 +2025-03-11T12:41:19.372299,479392880,65358,220,-24.91389357562,-36.909333757965,47.67774446866,2,1,18 +2025-03-11T12:41:19.387924,479392880,65358,220,-24.68771773786,-36.668646680745,47.25130605844,2,1,18 +2025-03-11T12:41:19.403549,479392880,65358,220,-24.44740591024,-36.41869300098,46.834052591335,2,1,18 +2025-03-11T12:41:19.419174,479392880,65358,220,-24.21651807586,-36.196482058095,46.421545109305,2,1,18 +2025-03-11T12:41:19.434799,479392880,65358,220,-23.97149425162,-35.974246656315,45.995153735065,2,1,18 +2025-03-11T12:41:19.450424,479392880,65358,220,-23.71704643414,-35.74737387678,45.559487892685,2,1,18 +2025-03-11T12:41:19.466049,479392880,65358,220,-23.48615859976,-35.51129971842,45.091470593875,2,1,18 +2025-03-11T12:41:19.481674,479392880,65358,220,-23.25527076538,-35.261362344585,44.64650359039,2,1,18 +2025-03-11T12:41:19.497299,479392880,65358,220,-23.01967093438,-35.020658961435,44.196945702835,2,1,18 +2025-03-11T12:41:19.512924,479392880,65358,220,-22.76993511352,-34.77068897574,43.76119394146,2,1,18 +2025-03-11T12:41:19.528549,479392880,65358,220,-22.52019929266,-34.520718990045,43.31157863089,2,1,18 +2025-03-11T12:41:19.544174,479392880,65358,220,-22.28459946166,-34.26615239142,42.8665863064,2,1,18 +2025-03-11T12:41:19.559799,479392880,65358,220,-22.03957563742,-34.01619055869,42.41235659377,2,1,18 +2025-03-11T12:41:19.575424,479392880,65358,220,-21.7992638098,-33.784721166225,41.967450188275,2,1,18 +2025-03-11T12:41:19.591049,479392880,65358,220,-21.54481599232,-33.525500883915,41.513169833635,2,1,18 +2025-03-11T12:41:19.606674,479392880,65358,220,-21.29979216808,-33.266296907535,41.05428185794,2,1,18 +2025-03-11T12:41:19.622299,479392880,65358,220,-21.04063235398,-33.030173831385,40.60470860536,2,1,18 +2025-03-11T12:41:19.637924,479392880,65358,220,-20.77676054326,-32.780179386795,40.118103487255,2,1,18 +2025-03-11T12:41:19.653549,479392880,65358,220,-20.51760072916,-32.525572023345,39.640728976285,2,1,18 +2025-03-11T12:41:19.669174,479392880,65358,220,-20.26315291168,-32.27097281286,39.19108834471,2,1,18 +2025-03-11T12:41:19.684799,479392880,65358,220,-20.02284108406,-32.011776989445,38.736828333085,2,1,18 +2025-03-11T12:41:19.700424,479392880,65358,220,-19.77781725982,-31.752573013065,38.26869799126,2,1,18 +2025-03-11T12:41:19.716049,479392880,65358,220,-19.52336944234,-31.484110587105,37.809759373555,2,1,18 +2025-03-11T12:41:19.731674,479392880,65358,220,-19.25949763162,-31.22025292704,37.336962184645,2,1,18 +2025-03-11T12:41:19.747299,479392880,65358,220,-18.99091382428,-30.96562925766,36.86419529473,2,1,18 +2025-03-11T12:41:19.762924,479392880,65358,220,-18.71761802032,-30.710997435315,36.39142162381,2,1,18 +2025-03-11T12:41:19.778549,479392880,65358,220,-18.46788219946,-30.456406377795,35.92330304098,2,1,18 +2025-03-11T12:41:19.794174,479392880,65358,220,-18.20401038874,-30.206411933205,35.436697922875,2,1,18 +2025-03-11T12:41:19.809799,479392880,65358,220,-17.94485057464,-29.92869921063,34.93612479658,2,1,18 +2025-03-11T12:41:19.825424,479392880,65358,220,-17.69040275716,-29.646373569195,34.47250937581,2,1,18 +2025-03-11T12:41:19.841049,479392880,65358,220,-17.43595493968,-29.387153286885,33.995123105845,2,1,18 +2025-03-11T12:41:19.856674,479392880,65358,220,-17.17679512558,-29.123303779785,33.526953881005,2,1,18 +2025-03-11T12:41:19.872299,479392880,65358,220,-16.91763531148,-28.85483320086,33.03566020084,2,1,18 +2025-03-11T12:41:19.887924,479392880,65358,220,-16.64433950752,-28.590959234865,32.548985900725,2,1,18 +2025-03-11T12:41:19.903549,479392880,65358,220,-16.37575570018,-28.31323020636,32.05764157855,2,1,18 +2025-03-11T12:41:19.919174,479392880,65358,220,-16.10245989622,-28.030871953065,31.55702956924,2,1,18 +2025-03-11T12:41:19.934799,479392880,65358,220,-15.83387608888,-27.75314292456,31.056442880935,2,1,18 +2025-03-11T12:41:19.950424,479392880,65358,220,-15.55115629168,-27.480010508985,30.55123320655,2,1,18 +2025-03-11T12:41:19.966049,479392880,65358,220,-15.27786048772,-27.220757614815,30.055335080305,2,1,18 +2025-03-11T12:41:19.981674,479392880,65358,220,-14.99985268714,-26.938391208555,29.56395865612,2,1,18 +2025-03-11T12:41:19.997299,479392880,65358,220,-14.7312688798,-26.6699043237,29.054166681685,2,1,18 +2025-03-11T12:41:20.012924,479392880,65358,220,-14.46268507246,-26.401417438845,28.56285943951,2,1,18 +2025-03-11T12:41:20.028549,479392880,65358,220,-14.19881326174,-26.12831763513,28.06229807221,2,1,18 +2025-03-11T12:41:20.044174,479392880,65358,220,-13.9302294544,-25.85520967845,27.561729923905,2,1,18 +2025-03-11T12:41:20.059799,479392880,65358,220,-13.64279766058,-25.577448038085,27.07035847771,2,1,18 +2025-03-11T12:41:20.075424,479392880,65358,220,-13.35536586676,-25.285823182245,26.578931411515,2,1,18 +2025-03-11T12:41:20.091049,479392880,65358,220,-13.08678205942,-25.003473081915,26.05984145095,2,1,18 +2025-03-11T12:41:20.106674,479392880,65358,220,-12.79463826898,-24.73032436041,25.53151229923,2,1,18 +2025-03-11T12:41:20.122299,479392880,65358,220,-12.53076645826,-24.45260348487,25.0216900258,2,1,18 +2025-03-11T12:41:20.137924,479392880,65358,220,-12.26689464754,-24.18412475298,24.516526015435,2,1,18 +2025-03-11T12:41:20.153549,479392880,65358,220,-11.96532686386,-23.89709651007,24.01123359703,2,1,18 +2025-03-11T12:41:20.169174,479392880,65358,220,-11.6684710768,-23.619318563775,23.492121490435,2,1,18 +2025-03-11T12:41:20.184799,479392880,65358,220,-11.39517527284,-23.32771816683,22.972987668865,2,1,18 +2025-03-11T12:41:20.200424,479392880,65358,220,-11.12187946888,-23.045359913535,22.472375659555,2,1,18 +2025-03-11T12:41:20.216049,479392880,65358,220,-10.82973567844,-22.776832263855,21.934822681705,2,1,18 +2025-03-11T12:41:20.231674,479392880,65358,220,-10.537591888,-22.489820326875,21.40181672692,2,1,18 +2025-03-11T12:41:20.247299,479392880,65358,220,-10.24073610094,-22.198179165105,20.891891366455,2,1,18 +2025-03-11T12:41:20.262924,479392880,65358,220,-9.96744029698,-21.901957696335,20.381981371015,2,1,18 +2025-03-11T12:41:20.278549,479392880,65358,220,-9.70828048288,-21.601139614635,19.858209629395,2,1,18 +2025-03-11T12:41:20.294174,479392880,65358,220,-9.4302726823,-21.3049099929,19.325186937625,2,1,18 +2025-03-11T12:41:20.309799,479392880,65358,220,-9.13341689524,-21.027132046605,18.801453647965,2,1,18 +2025-03-11T12:41:20.325424,479392880,65358,220,-8.8412731048,-20.7354990378,18.282292702375,2,1,18 +2025-03-11T12:41:20.341049,479392880,65358,220,-8.53970532112,-20.45771293854,17.753931448645,2,1,18 +2025-03-11T12:41:20.356674,479392880,65358,220,-8.25698552392,-20.15223302019,17.21162252974,2,1,18 +2025-03-11T12:41:20.372299,479392880,65358,220,-7.97897772334,-19.85138232663,16.6878236641,2,1,18 +2025-03-11T12:41:20.387924,479392880,65358,220,-7.6868339329,-19.5736125333,16.164097155445,2,1,18 +2025-03-11T12:41:20.403549,479392880,65358,220,-7.39940213908,-19.286608749285,15.649582713925,2,1,18 +2025-03-11T12:41:20.419174,479392880,65358,220,-7.10254635202,-18.994967587515,15.107309072005,2,1,18 +2025-03-11T12:41:20.434799,479392880,65358,220,-6.79626657172,-18.721794407115,14.57895957727,2,1,18 +2025-03-11T12:41:20.450424,479392880,65358,220,-6.50412278128,-18.444024613785,14.04136951942,2,1,18 +2025-03-11T12:41:20.466049,479392880,65358,220,-6.20726699422,-18.14776238019,13.4990773375,2,1,18 +2025-03-11T12:41:20.481674,479392880,65358,220,-5.90098721392,-17.83762062519,12.95671597357,2,1,18 +2025-03-11T12:41:20.497299,479392880,65358,220,-5.60413142686,-17.54597946342,12.43292706391,2,1,18 +2025-03-11T12:41:20.512924,479392880,65358,220,-5.3072756398,-17.249717229825,11.904498431185,2,1,18 +2025-03-11T12:41:20.528549,479392880,65358,220,-5.0245558426,-16.95810052695,11.36224513228,2,1,18 +2025-03-11T12:41:20.544174,479392880,65358,220,-4.7418360454,-16.66186275225,10.819973293375,2,1,18 +2025-03-11T12:41:20.559799,479392880,65358,220,-4.4591162482,-16.36562497755,10.27770145447,2,1,18 +2025-03-11T12:41:20.575424,479392880,65358,220,-4.1528364679,-16.069346438025,9.73539571054,2,1,18 +2025-03-11T12:41:20.591049,479392880,65358,220,-3.85126868422,-15.763833907815,9.18843848455,2,1,18 +2025-03-11T12:41:20.606674,479392880,65358,220,-3.55912489378,-15.467579827185,8.646153083635,2,1,18 +2025-03-11T12:41:20.622299,479392880,65358,220,-3.26226910672,-15.18055973724,8.103897981715,2,1,18 +2025-03-11T12:41:20.637924,479392880,65358,220,-2.97954930952,-14.89356410619,7.575526772005,2,1,18 +2025-03-11T12:41:20.653549,479392880,65358,220,-2.69682951232,-14.59732633149,7.04249729923,2,1,18 +2025-03-11T12:41:20.669174,479392880,65358,220,-2.4093977185,-14.2779750447,6.49088361319,2,1,18 +2025-03-11T12:41:20.684799,479392880,65358,220,-2.10782993482,-13.958599299015,5.96235549946,2,1,18 +2025-03-11T12:41:20.700424,479392880,65358,220,-1.80155015452,-13.66232075949,5.42929212166,2,1,18 +2025-03-11T12:41:20.716049,479392880,65358,220,-1.49527037422,-13.37990543544,4.873178448535,2,1,18 +2025-03-11T12:41:20.731674,479392880,65358,220,-1.1842785973,-13.088239814775,4.32164209747,2,1,18 +2025-03-11T12:41:20.747299,479392880,65358,220,-0.89213480686,-12.782743590495,3.77469843349,2,1,18 +2025-03-11T12:41:20.762924,479392880,65358,220,-0.60470301304,-12.48649766283,3.246283362775,2,1,18 +2025-03-11T12:41:20.778549,479392880,65358,220,-0.30784722598,-12.19485650106,2.704009720855,2,1,18 +2025-03-11T12:41:20.794174,479392880,65358,220,-0.0109914389200001,-11.898594267465,2.152475172805,2,1,18 +2025-03-11T12:41:20.809799,479392880,65358,220,0.28586434814,-11.58384774657,1.60548764782,2,1,18 +2025-03-11T12:41:20.825424,479392880,65358,220,0.59214412844,-11.29219027887,1.067821626955,2,1,18 +2025-03-11T12:41:20.841049,479392880,65358,220,0.87957592226,-10.995944351205,0.544027739305,2,1,18 +2025-03-11T12:41:20.856674,479392880,65358,220,1.18585570256,-10.695044739855,0.0109458215049996,2,1,18 +2025-03-11T12:41:20.872299,479392880,65358,220,1.477999493,-10.38492744375,-0.5591222978,2,1,18 +2025-03-11T12:41:20.887924,479392880,65358,220,1.77485528006,-10.06555985103,-1.13847664424,2,1,18 +2025-03-11T12:41:20.903549,479392880,65358,220,2.09527105022,-9.773877924435,-1.67616300812,2,1,18 +2025-03-11T12:41:20.919174,479392880,65358,220,2.3968388339,-9.468365394225,-2.209256684915,2,1,18 +2025-03-11T12:41:20.934799,479392880,65358,220,2.68427062772,-9.17211946656,-2.751535304825,2,1,18 +2025-03-11T12:41:20.950424,479392880,65358,220,2.97641441816,-8.86662324228,-3.30310015187,2,1,18 +2025-03-11T12:41:20.966049,479392880,65358,220,3.27798220184,-8.57035285572,-3.863883847055,2,1,18 +2025-03-11T12:41:20.981674,479392880,65358,220,3.57012599228,-8.27409877509,-4.40616924797,2,1,18 +2025-03-11T12:41:20.997299,479392880,65358,220,3.8575577861,-7.9732317756,-4.95770877401,2,1,18 +2025-03-11T12:41:21.012924,479392880,65358,220,4.15441357316,-7.686211685655,-5.476857960605,2,1,18 +2025-03-11T12:41:21.028549,479392880,65358,220,4.45126936022,-7.39919159571,-5.991385964135,2,1,18 +2025-03-11T12:41:21.044174,479392880,65358,220,4.75754914052,-7.093670912535,-6.51986523887,2,1,18 +2025-03-11T12:41:21.059799,479392880,65358,220,5.0591169242,-6.778916238675,-7.062238361795,2,1,18 +2025-03-11T12:41:21.075424,479392880,65358,220,5.3653967045,-6.46415341185,-7.60923944879,2,1,18 +2025-03-11T12:41:21.091049,479392880,65358,220,5.65282849832,-6.18177069966,-8.16994718096,2,1,18 +2025-03-11T12:41:21.106674,479392880,65358,220,5.94497228876,-5.88551661903,-8.71685376494,2,1,18 +2025-03-11T12:41:21.122299,479392880,65358,220,6.25596406568,-5.593850998365,-9.26376893294,2,1,18 +2025-03-11T12:41:21.137924,479392880,65358,220,6.55753184936,-5.28371739633,-9.81074469893,2,1,18 +2025-03-11T12:41:21.153549,479392880,65358,220,6.85909963304,-4.97820486612,-10.37618665718,2,1,18 +2025-03-11T12:41:21.169174,479392880,65358,220,7.1559554201,-4.66807941705,-10.932398008295,2,1,18 +2025-03-11T12:41:21.184799,479392880,65358,220,7.44338721392,-4.36721241756,-11.474695168205,2,1,18 +2025-03-11T12:41:21.200424,479392880,65358,220,7.73553100436,-4.08020048058,-12.00770112299,2,1,18 +2025-03-11T12:41:21.216049,479392880,65358,220,8.04181078466,-3.783921941055,-12.55924923305,2,1,18 +2025-03-11T12:41:21.231674,479392880,65358,220,8.34337856834,-3.48303048267,-13.101566735975,2,1,18 +2025-03-11T12:41:21.247299,479392880,65358,220,8.64494635202,-3.18676009611,-13.65310806503,2,1,18 +2025-03-11T12:41:21.262924,479392880,65358,220,8.94180213908,-2.89511893434,-14.18613934082,2,1,18 +2025-03-11T12:41:21.278549,479392880,65358,220,9.24808191938,-2.59421932299,-14.72846362475,2,1,18 +2025-03-11T12:41:21.294174,479392880,65358,220,9.55436169968,-2.297940783465,-15.284632917875,2,1,18 +2025-03-11T12:41:21.309799,479392880,65358,220,9.84650549012,-1.98782348736,-15.80848920653,2,1,18 +2025-03-11T12:41:21.325424,479392880,65358,220,10.14336127718,-1.673076966465,-16.35085554845,2,1,18 +2025-03-11T12:41:21.341049,479392880,65358,220,10.43550506762,-1.386065029485,-16.902346235495,2,1,18 +2025-03-11T12:41:21.356674,479392880,65358,220,10.73236085468,-1.094423867715,-17.43075632822,2,1,18 +2025-03-11T12:41:21.372299,479392880,65358,220,11.03392863836,-0.798153481155,-17.97767647421,2,1,18 +2025-03-11T12:41:21.387924,479392880,65358,220,11.33078442542,-0.49264910391,-18.506142186935,2,1,18 +2025-03-11T12:41:21.403549,479392880,65358,220,11.61350422262,-0.205653472859999,-19.02064984745,2,1,18 +2025-03-11T12:41:21.419174,479392880,65358,220,11.91036000968,0.081366617085,-19.5721473155,2,1,18 +2025-03-11T12:41:21.434799,479392880,65358,220,12.20721579674,0.36838670703,-20.128265966615,2,1,18 +2025-03-11T12:41:21.450424,479392880,65358,220,12.48993559394,0.669245553555,-20.66131397939,2,1,18 +2025-03-11T12:41:21.466049,479392880,65358,220,12.77736738776,0.970112553045001,-21.18512640704,2,1,18 +2025-03-11T12:41:21.481674,479392880,65358,220,13.08364716806,1.261770020745,-21.722792427905,2,1,18 +2025-03-11T12:41:21.497299,479392880,65358,220,13.38050295512,1.553411182515,-22.2419601545,2,1,18 +2025-03-11T12:41:21.512924,479392880,65358,220,13.6820707388,1.86354478455,-22.78893592049,2,1,18 +2025-03-11T12:41:21.528549,479392880,65358,220,13.97892652586,2.16442808997,-23.335867825475,2,1,18 +2025-03-11T12:41:21.544174,479392880,65358,220,14.27578231292,2.432963892615,-23.85494285207,2,1,18 +2025-03-11T12:41:21.559799,479392880,65358,220,14.56321410674,2.71996767663,-24.38794202585,2,1,18 +2025-03-11T12:41:21.575424,479392880,65358,220,14.85535789718,3.02546390091,-24.9256433237,2,1,18 +2025-03-11T12:41:21.591049,479392880,65358,220,15.14750168762,3.326339053365,-25.440220166225,2,1,18 +2025-03-11T12:41:21.606674,479392880,65358,220,15.43022148482,3.613334684415,-25.95472782674,2,1,18 +2025-03-11T12:41:21.622299,479392880,65358,220,15.7082292854,3.904943234325,-26.50621671077,2,1,18 +2025-03-11T12:41:21.637924,479392880,65358,220,15.99566107922,4.196568090165,-27.05771915681,2,1,18 +2025-03-11T12:41:21.653549,479392880,65358,220,16.2972288629,4.483596333075,-27.572253941345,2,1,18 +2025-03-11T12:41:21.669174,479392880,65358,220,16.5799486601,4.7659708923,-28.063637146535,2,1,18 +2025-03-11T12:41:21.684799,479392880,65358,220,16.85795646068,5.06682158586,-28.578193646045,2,1,18 +2025-03-11T12:41:21.700424,479392880,65358,220,17.15010025112,5.36307566649,-29.106615497765,2,1,18 +2025-03-11T12:41:21.716049,479392880,65358,220,17.4281080517,5.631578857275,-29.639526949535,2,1,18 +2025-03-11T12:41:21.731674,479392880,65358,220,17.7108278489,5.92319556015,-30.158674333115,2,1,18 +2025-03-11T12:41:21.747299,479392880,65358,220,17.9935476461,6.205570119375,-30.668542270565,2,1,18 +2025-03-11T12:41:21.762924,479392880,65358,220,18.28569143654,6.48796098453,-31.18304495309,2,1,18 +2025-03-11T12:41:21.778549,479392880,65358,220,18.57312323036,6.77958584037,-31.702199117675,2,1,18 +2025-03-11T12:41:21.794174,479392880,65358,220,18.8652670208,7.06659777735,-32.23520507246,2,1,18 +2025-03-11T12:41:21.809799,479392880,65358,220,19.147986818,7.348972336575,-32.75431537604,2,1,18 +2025-03-11T12:41:21.825424,479392880,65358,220,19.42128262196,7.617467374395,-33.25487176535,2,1,18 +2025-03-11T12:41:21.841049,479392880,65358,220,19.69929042254,7.899833780655,-33.773975287925,2,1,18 +2025-03-11T12:41:21.856674,479392880,65358,220,19.97729822312,8.182200186915,-34.288457627435,2,1,18 +2025-03-11T12:41:21.872299,479392880,65358,220,20.2553060237,8.469187665,-34.79833732388,2,1,18 +2025-03-11T12:41:21.887924,479392880,65358,220,20.54273781752,8.756191449015,-35.298988216205,2,1,18 +2025-03-11T12:41:21.903549,479392880,65358,220,20.8207456181,9.020073567975,-35.804154029585,2,1,18 +2025-03-11T12:41:21.919174,479392880,65358,220,21.09404142206,9.30243182127,-36.323250771155,2,1,18 +2025-03-11T12:41:21.934799,479392880,65358,220,21.37204922264,9.598661443005,-36.82392518147,2,1,18 +2025-03-11T12:41:21.950424,479392880,65358,220,21.6453450266,9.876398624475,-37.319897467715,2,1,18 +2025-03-11T12:41:21.966049,479392880,65358,220,21.92335282718,10.140280743435,-37.825063281095,2,1,18 +2025-03-11T12:41:21.981674,479392880,65358,220,22.20136062776,10.394920718745,-38.330192014475,2,1,18 +2025-03-11T12:41:21.997238,479392884,65354,221,22.48408042496,10.681916349795,-38.830836125795,2,1,18 +2025-03-11T12:41:22.012863,479392884,65354,221,22.75737622892,10.959653531265,-39.33605077817,2,1,18 +2025-03-11T12:41:22.028488,479392884,65354,221,23.0353840295,11.232777793875,-39.83201130542,2,1,18 +2025-03-11T12:41:22.044113,479392884,65354,221,23.2945438436,11.49200622915,-40.31864672252,2,1,18 +2025-03-11T12:41:22.059738,479392884,65354,221,23.54899166108,11.76971079876,-40.786864786355,2,1,18 +2025-03-11T12:41:22.075363,479392884,65354,221,23.8128634718,12.061294889775,-41.28287913059,2,1,18 +2025-03-11T12:41:22.090988,479392884,65354,221,24.08144727914,12.325160702805,-41.774167832765,2,1,18 +2025-03-11T12:41:22.106613,479392884,65354,221,24.3547430831,12.565929309675,-42.274612982075,2,1,18 +2025-03-11T12:41:22.122238,479392884,65354,221,24.62803888706,12.82980327567,-42.756666099125,2,1,18 +2025-03-11T12:41:22.137863,479392884,65354,221,24.89191069778,13.102903079385,-43.247985100295,2,1,18 +2025-03-11T12:41:22.153488,479392884,65354,221,25.1557825085,13.362139667625,-43.720763749205,2,1,18 +2025-03-11T12:41:22.169113,479392884,65354,221,25.42436631584,13.63062655248,-44.20282862525,2,1,18 +2025-03-11T12:41:22.184738,479392884,65354,221,25.69295012318,13.90373450916,-44.68953322436,2,1,18 +2025-03-11T12:41:22.200363,479392884,65354,221,25.94268594404,14.17680985398,-45.16696833332,2,1,18 +2025-03-11T12:41:22.215988,479392884,65354,221,26.21126975138,14.454538882485,-45.639827923235,2,1,18 +2025-03-11T12:41:22.231613,479392884,65354,221,26.46571756886,14.69065380567,-46.121742676265,2,1,18 +2025-03-11T12:41:22.247238,479392884,65354,221,26.72487738296,14.940640097295,-46.599098647235,2,1,18 +2025-03-11T12:41:22.262863,479392884,65354,221,26.98403719706,15.19986853257,-47.067249332075,2,1,18 +2025-03-11T12:41:22.278488,479392884,65354,221,27.23848501454,15.45908881488,-47.53539323591,2,1,18 +2025-03-11T12:41:22.294113,479392884,65354,221,27.49293283202,15.71830909719,-48.01740068894,2,1,18 +2025-03-11T12:41:22.309738,479392884,65354,221,27.76151663936,15.97293276657,-48.490167578855,2,1,18 +2025-03-11T12:41:22.325363,479392884,65354,221,28.02067645346,16.222919058195,-48.939796451435,2,1,18 +2025-03-11T12:41:22.340988,479392884,65354,221,28.27512427094,16.47751826868,-49.38943708301,2,1,18 +2025-03-11T12:41:22.356613,479392884,65354,221,28.52014809518,16.73672224506,-49.8621886079,2,1,18 +2025-03-11T12:41:22.372238,479392884,65354,221,28.76517191942,17.00516836509,-50.302628931335,2,1,18 +2025-03-11T12:41:22.387863,479392884,65354,221,29.00077175042,17.250492820065,-50.75220535889,2,1,18 +2025-03-11T12:41:22.403488,479392884,65354,221,29.24579557466,17.491212509145,-51.21564035765,2,1,18 +2025-03-11T12:41:22.419113,479392884,65354,221,29.50966738538,17.750449097385,-51.68841900656,2,1,18 +2025-03-11T12:41:22.434738,479392884,65354,221,29.75940320624,18.014282298555,-52.124226387935,2,1,18 +2025-03-11T12:41:22.450363,479392884,65354,221,30.00442703048,18.25962305946,-52.541468096045,2,1,18 +2025-03-11T12:41:22.465988,479392884,65354,221,30.24945085472,18.49110060489,-52.995623648675,2,1,18 +2025-03-11T12:41:22.481613,479392884,65354,221,30.48505068572,18.74104613169,-53.44521861623,2,1,18 +2025-03-11T12:41:22.497238,479392884,65354,221,30.73478650658,18.98639504556,-53.90405775293,2,1,18 +2025-03-11T12:41:22.512863,479392884,65354,221,30.96567434096,19.208605988445,-54.32580760109,2,1,18 +2025-03-11T12:41:22.528488,479392884,65354,221,31.20127417196,19.45393044342,-54.756899296385,2,1,18 +2025-03-11T12:41:22.544113,479392884,65354,221,31.4462979962,19.690029060675,-55.183346290625,2,1,18 +2025-03-11T12:41:22.559738,479392884,65354,221,31.69132182044,19.91688553428,-55.62361975406,2,1,18 +2025-03-11T12:41:22.575363,479392884,65354,221,31.92692165144,20.152967845605,-56.054674369355,2,1,18 +2025-03-11T12:41:22.590988,479392884,65354,221,32.1530974892,20.393654922825,-56.49497632877,2,1,18 +2025-03-11T12:41:22.606613,479392884,65354,221,32.38398532358,20.620486937535,-56.921365899995,2,1,18 +2025-03-11T12:41:22.622238,479392884,65354,221,32.61958515458,20.842706033385,-57.347743712225,2,1,18 +2025-03-11T12:41:22.637863,479392884,65354,221,32.8598969822,21.07417542585,-57.769544202395,2,1,18 +2025-03-11T12:41:22.653488,479392884,65354,221,33.07664882672,21.310225125315,-58.17284459528,2,1,18 +2025-03-11T12:41:22.669113,479392884,65354,221,33.28868867462,21.555508815465,-58.59466001942,2,1,18 +2025-03-11T12:41:22.684738,479392884,65354,221,33.51015251576,21.782324524245,-58.99793011331,2,1,18 +2025-03-11T12:41:22.700363,479392884,65354,221,33.74104035014,21.999914395305,-59.415040238405,2,1,18 +2025-03-11T12:41:22.715988,479392884,65354,221,33.96250419128,22.23135117591,-59.82295005536,2,1,18 +2025-03-11T12:41:22.731613,479392884,65354,221,34.18868002904,22.46279610948,-60.226245470255,2,1,18 +2025-03-11T12:41:22.747238,479392884,65354,221,34.39600788032,22.680345215715,-60.62945814113,2,1,18 +2025-03-11T12:41:22.762863,479392884,65354,221,34.63160771132,22.88870109609,-61.04653796723,2,1,18 +2025-03-11T12:41:22.778488,479392884,65354,221,34.85778354908,23.09241959871,-61.431237409865,2,1,18 +2025-03-11T12:41:22.794113,479392884,65354,221,35.08395938684,23.310001316805,-61.839098387825,2,1,18 +2025-03-11T12:41:22.809738,479392884,65354,221,35.29599923474,23.52293750418,-62.22843575051,2,1,18 +2025-03-11T12:41:22.825363,479392884,65354,221,35.50803908264,23.74049476338,-62.61317047013,2,1,18 +2025-03-11T12:41:22.840988,479392884,65354,221,35.72007893054,23.962673094405,-62.993302546685,2,1,18 +2025-03-11T12:41:22.856613,479392884,65354,221,35.93683077506,24.184859578395,-63.382683770375,2,1,18 +2025-03-11T12:41:22.872238,479392884,65354,221,36.15358261958,24.39318284691,-63.767388191,2,1,18 +2025-03-11T12:41:22.887863,479392884,65354,221,36.35148647762,24.59685243174,-64.161289313735,2,1,18 +2025-03-11T12:41:22.903488,479392884,65354,221,36.55410233228,24.809772313185,-64.54137074828,2,1,18 +2025-03-11T12:41:22.919113,479392884,65354,221,36.75200619032,25.01806296984,-64.91218449569,2,1,18 +2025-03-11T12:41:22.934738,479392884,65354,221,36.96404603822,25.21713594174,-65.28760268918,2,1,18 +2025-03-11T12:41:22.950363,479392884,65354,221,37.17608588612,25.42545105729,-65.658436779605,2,1,18 +2025-03-11T12:41:22.965988,479392884,65354,221,37.3834137374,25.64762123535,-66.03394089209,2,1,18 +2025-03-11T12:41:22.981613,479392884,65354,221,37.58602959206,25.832814685845,-66.39080517131,2,1,18 +2025-03-11T12:41:22.997238,479392884,65354,221,37.78864544672,26.031871351815,-66.752346253595,2,1,18 +2025-03-11T12:41:23.012863,479392884,65354,221,37.98183730814,26.221669568205,-67.12307906,2,1,18 +2025-03-11T12:41:23.028488,479392884,65354,221,38.1844531628,26.411484090525,-67.484583062285,2,1,18 +2025-03-11T12:41:23.044113,479392884,65354,221,38.37764502422,26.601282306915,-67.841452319495,2,1,18 +2025-03-11T12:41:23.059738,479392884,65354,221,38.57083688564,26.80494373878,-68.189134830575,2,1,18 +2025-03-11T12:41:23.075363,479392884,65354,221,38.76402874706,27.00398409882,-68.54141998472,2,1,18 +2025-03-11T12:41:23.090988,479392884,65354,221,38.9619326051,27.1799272527,-68.879755670675,2,1,18 +2025-03-11T12:41:23.106613,479392884,65354,221,39.14570047328,27.374330234985,-69.20428162442,2,1,18 +2025-03-11T12:41:23.122238,479392884,65354,221,39.32475634484,27.56410399248,-69.54726698942,2,1,18 +2025-03-11T12:41:23.137863,479392884,65354,221,39.51794820626,27.758523280695,-69.8949124205,2,1,18 +2025-03-11T12:41:23.153488,479392884,65354,221,39.7158520643,27.9575717937,-70.23796198952,2,1,18 +2025-03-11T12:41:23.169113,479392884,65354,221,39.89019593924,28.133474182755,-70.56702140432,2,1,18 +2025-03-11T12:41:23.184738,479392884,65354,221,40.0692518108,28.3140057966,-70.896106140125,2,1,18 +2025-03-11T12:41:23.200363,479392884,65354,221,40.2341716925,28.5037550952,-71.23907116211,2,1,18 +2025-03-11T12:41:23.215988,479392884,65354,221,40.40851556744,28.67503641243,-71.55886967078,2,1,18 +2025-03-11T12:41:23.231613,479392884,65354,221,40.58285944238,28.841696657835,-71.864786090255,2,1,18 +2025-03-11T12:41:23.247238,479392884,65354,221,40.77133930718,29.008381362135,-72.17534403581,2,1,18 +2025-03-11T12:41:23.262863,479392884,65354,221,40.95510717536,29.179678985295,-72.490534923425,2,1,18 +2025-03-11T12:41:23.278488,479392884,65354,221,41.12473905368,29.35095214956,-72.805705468025,2,1,18 +2025-03-11T12:41:23.294113,479392884,65354,221,41.29908292862,29.52223346679,-73.1116404275,2,1,18 +2025-03-11T12:41:23.309738,479392884,65354,221,41.46400281032,29.69349847809,-73.436046557225,2,1,18 +2025-03-11T12:41:23.325363,479392884,65354,221,41.63834668526,29.87402193897,-73.75126096283,2,1,18 +2025-03-11T12:41:23.340988,479392884,65354,221,41.7891305771,30.036020347725,-74.052503754215,2,1,18 +2025-03-11T12:41:23.356613,479392884,65354,221,41.94462646556,30.198026909445,-74.35837450967,2,1,18 +2025-03-11T12:41:23.372238,479392884,65354,221,42.11425834388,30.36005793006,-74.650402058945,2,1,18 +2025-03-11T12:41:23.387863,479392884,65354,221,42.26975423234,30.51282234813,-74.93775100214,2,1,18 +2025-03-11T12:41:23.403488,479392884,65354,221,42.43938611066,30.674853368745,-75.229778551415,2,1,18 +2025-03-11T12:41:23.419113,479392884,65354,221,42.59959399574,30.823004867955,-75.51249455255,2,1,18 +2025-03-11T12:41:23.434738,479392884,65354,221,42.74095389434,30.971123755305,-75.79980461273,2,1,18 +2025-03-11T12:41:23.450363,479392884,65354,221,42.88702578956,31.123871867445,-76.077897627785,2,1,18 +2025-03-11T12:41:23.465988,479392884,65354,221,43.0378096814,31.281249204375,-76.35139478078,2,1,18 +2025-03-11T12:41:23.481613,479392884,65354,221,43.18859357324,31.43400546948,-76.624873393775,2,1,18 +2025-03-11T12:41:23.497238,479392884,65354,221,43.34880145832,31.596020184165,-76.87991791652,2,1,18 +2025-03-11T12:41:23.512863,479392884,65354,221,43.49958535016,31.734913233795,-77.14871972645,2,1,18 +2025-03-11T12:41:23.528488,479392884,65354,221,43.63623325214,31.87378182453,-77.40363764417,2,1,18 +2025-03-11T12:41:23.544113,479392884,65354,221,43.7917291406,32.012683027125,-77.64934031978,2,1,18 +2025-03-11T12:41:23.559738,479392884,65354,221,43.93780103582,32.156188995615,-77.92277507177,2,1,18 +2025-03-11T12:41:23.575363,479392884,65354,221,44.0744489378,32.290436514525,-78.18691681562,2,1,18 +2025-03-11T12:41:23.590988,479392884,65354,221,44.22523282964,32.44319277963,-78.44653187942,2,1,18 +2025-03-11T12:41:23.606613,479392884,65354,221,44.357168735,32.577432145575,-78.682939743875,2,1,18 +2025-03-11T12:41:23.622238,479392884,65354,221,44.50795262684,32.72094626703,-78.92865417848,2,1,18 +2025-03-11T12:41:23.637863,479392884,65354,221,44.63517653558,32.859798551835,-79.18355853419,2,1,18 +2025-03-11T12:41:23.653488,479392884,65354,221,44.75297645108,32.975529171585,-79.4106295295,2,1,18 +2025-03-11T12:41:23.669113,479392884,65354,221,44.88020035982,33.09589716909,-79.623869077625,2,1,18 +2025-03-11T12:41:23.684738,479392884,65354,221,44.9932882787,33.22548285135,-79.874094827255,2,1,18 +2025-03-11T12:41:23.700363,479392884,65354,221,45.10637619758,33.359689605435,-80.096612018495,2,1,18 +2025-03-11T12:41:23.715988,479392884,65354,221,45.23360010632,33.475436531115,-80.31907539275,2,1,18 +2025-03-11T12:41:23.731613,479392884,65354,221,45.35611201844,33.60041744748,-80.541569066,2,1,18 +2025-03-11T12:41:23.747238,479392884,65354,221,45.45977594408,33.725365751985,-80.759414432165,2,1,18 +2025-03-11T12:41:23.762863,479392884,65354,221,45.57757585958,33.850338515385,-80.99114369054,2,1,18 +2025-03-11T12:41:23.778488,479392884,65354,221,45.70951176494,33.970714665855,-81.2136323858,2,1,18 +2025-03-11T12:41:23.794113,479392884,65354,221,45.8414476703,34.0679854572,-81.394437733475,2,1,18 +2025-03-11T12:41:23.809738,479392884,65354,221,45.9592475858,34.179095005125,-81.621490188785,2,1,18 +2025-03-11T12:41:23.825363,479392884,65354,221,46.06762350806,34.285567175295,-81.830025809825,2,1,18 +2025-03-11T12:41:23.840988,479392884,65354,221,46.1712874337,34.396652264325,-82.02933082373,2,1,18 +2025-03-11T12:41:23.856613,479392884,65354,221,46.2655273661,34.526205334725,-82.228696435625,2,1,18 +2025-03-11T12:41:23.872238,479392884,65354,221,46.3597672985,34.637274117825,-82.423366704455,2,1,18 +2025-03-11T12:41:23.887863,479392884,65354,221,46.47285521738,34.72527015366,-82.61335021424,2,1,18 +2025-03-11T12:41:23.903488,479392884,65354,221,46.56238315316,34.83170971197,-82.79413161287,2,1,18 +2025-03-11T12:41:23.919113,479392884,65354,221,46.66133508218,34.933544504385,-82.979529216575,2,1,18 +2025-03-11T12:41:23.934738,479392884,65354,221,46.77442300106,35.044645899345,-83.1511206941,2,1,18 +2025-03-11T12:41:23.950363,479392884,65354,221,46.87337493008,35.141859619935,-83.32263620861,2,1,18 +2025-03-11T12:41:23.965988,479392884,65354,221,46.96290286586,35.248299178245,-83.49417524111,2,1,18 +2025-03-11T12:41:23.981613,479392884,65354,221,47.06185479488,35.345512898835,-83.679554304815,2,1,18 +2025-03-11T12:41:23.997238,479392884,65354,221,47.15138273066,35.424226026195,-83.84636091425,2,1,18 +2025-03-11T12:41:24.012863,479392884,65354,221,47.2314866732,35.50754391945,-84.003930135545,2,1,18 +2025-03-11T12:41:24.028488,479392884,65354,221,47.32101460898,35.58625704681,-84.147630829655,2,1,18 +2025-03-11T12:41:24.044113,479392884,65354,221,47.41525454138,35.65111511166,-84.3005250509,2,1,18 +2025-03-11T12:41:24.059738,479392884,65354,221,47.50007048054,35.74368330153,-84.4581381332,2,1,18 +2025-03-11T12:41:24.075363,479392884,65354,221,47.58017442308,35.82238012296,-84.61106763143,2,1,18 +2025-03-11T12:41:24.090988,479392884,65354,221,47.65085437238,35.887197422985,-84.74544321539,2,1,18 +2025-03-11T12:41:24.106613,479392884,65354,221,47.71682232506,35.970490857345,-84.88450736141,2,1,18 +2025-03-11T12:41:24.122238,479392884,65354,221,47.80163826422,36.05843797539,-85.028238354515,2,1,18 +2025-03-11T12:41:24.137863,479392884,65354,221,47.8676062169,36.127868194275,-85.139519782145,2,1,18 +2025-03-11T12:41:24.153488,479392884,65354,221,47.95713415268,36.19271810616,-85.264680123995,2,1,18 +2025-03-11T12:41:24.169113,479392884,65354,221,48.04195009184,36.26680200873,-85.39911313097,2,1,18 +2025-03-11T12:41:24.184738,479392884,65354,221,48.1032060479,36.331603002825,-85.519611603725,2,1,18 +2025-03-11T12:41:24.200363,479392884,65354,221,48.15975000734,36.387153700305,-85.63544503241,2,1,18 +2025-03-11T12:41:24.215988,479392884,65354,221,48.22571796002,36.45658391919,-85.75596882617,2,1,18 +2025-03-11T12:41:24.231613,479392884,65354,221,48.29639790932,36.521401219215,-85.87185967787,2,1,18 +2025-03-11T12:41:24.247238,479392884,65354,221,48.34822987214,36.57694376373,-85.973822776355,2,1,18 +2025-03-11T12:41:24.262863,479392884,65354,221,48.4094858282,36.6556079733,-86.07589213685,2,1,18 +2025-03-11T12:41:24.278488,479392884,65354,221,48.4801657775,36.70656205785,-86.196348551615,2,1,18 +2025-03-11T12:41:24.294113,479392884,65354,221,48.5272857437,36.748233233925,-86.29362806603,2,1,18 +2025-03-11T12:41:24.309738,479392884,65354,221,48.5744057099,36.803767625475,-86.38634201738,2,1,18 +2025-03-11T12:41:24.325363,479392884,65354,221,48.61210168286,36.859285711095,-86.47904240672,2,1,18 +2025-03-11T12:41:24.340988,479392884,65354,221,48.65922164906,36.90095688717,-86.56245837194,2,1,18 +2025-03-11T12:41:24.356613,479392884,65354,221,48.70634161526,36.93800699142,-86.66434052942,2,1,18 +2025-03-11T12:41:24.372238,479392884,65354,221,48.7628855747,36.979694473425,-86.752391239715,2,1,18 +2025-03-11T12:41:24.387863,479392884,65354,221,48.80529354428,37.021357496535,-86.831179240865,2,1,18 +2025-03-11T12:41:24.403488,479392884,65354,221,48.84770151386,37.06764159147,-86.919228148145,2,1,18 +2025-03-11T12:41:24.419113,479392884,65354,221,48.8806854902,37.12777259595,-86.979592015025,2,1,18 +2025-03-11T12:41:24.434738,479392884,65354,221,48.91838146316,37.169427466095,-87.03988850291,2,1,18 +2025-03-11T12:41:24.450363,479392884,65354,221,48.9513654395,37.1972109678,-87.086259040595,2,1,18 +2025-03-11T12:41:24.465988,479392884,65354,221,48.97963741922,37.229607388365,-87.14650488647,2,1,18 +2025-03-11T12:41:24.481613,479392884,65354,221,49.00319740232,37.261995655965,-87.211365134405,2,1,18 +2025-03-11T12:41:24.497238,479392884,65354,221,49.02675738542,37.28052070809,-87.253063847015,2,1,18 +2025-03-11T12:41:24.512863,479392884,65354,221,49.05031736852,37.30366683204,-87.30864464882,2,1,18 +2025-03-11T12:41:24.528488,479392884,65354,221,49.08330134486,37.32682926192,-87.34113309731,2,1,18 +2025-03-11T12:41:24.544113,479392884,65354,221,49.10686132796,37.33149109857,-87.368912640725,2,1,18 +2025-03-11T12:41:24.559738,479392884,65354,221,49.11157332458,37.349983538835,-87.41520541238,2,1,18 +2025-03-11T12:41:24.575363,479392884,65354,221,49.13513330768,37.36850859096,-87.443040575795,2,1,18 +2025-03-11T12:41:24.590988,479392884,65354,221,49.16811728402,37.387049949015,-87.484752850415,2,1,18 +2025-03-11T12:41:24.606613,479392884,65354,221,49.20110126036,37.40559130707,-87.535707491165,2,1,18 +2025-03-11T12:41:24.622238,479392884,65354,221,49.21994924684,37.410244990755,-87.56810143664,2,1,18 +2025-03-11T12:41:24.637863,479392884,65354,221,49.2340852367,37.42875373695,-87.60054422111,2,1,18 +2025-03-11T12:41:24.653488,479392884,65354,221,49.23879723332,37.447246177215,-87.60524634518,2,1,18 +2025-03-11T12:41:24.669113,479392884,65354,221,49.23879723332,37.447246177215,-87.59600397905,2,1,18 +2025-03-11T12:41:24.684738,479392884,65354,221,49.24822122656,37.46112569862,-87.61455789332,2,1,18 +2025-03-11T12:41:24.700363,479392884,65354,221,49.24822122656,37.47960998592,-87.61463205332,2,1,18 +2025-03-11T12:41:24.715988,479392884,65354,221,49.24350922994,37.48422290478,-87.614643812315,2,1,18 +2025-03-11T12:41:24.731613,479392884,65354,221,49.24822122656,37.484231057745,-87.600787044125,2,1,18 +2025-03-11T12:41:24.747238,479392884,65354,221,49.2340852367,37.4564801679,-87.58217072885,2,1,18 +2025-03-11T12:41:24.762863,479392884,65354,221,49.22937324008,37.45185094311,-87.57752422478,2,1,18 +2025-03-11T12:41:24.778488,479392884,65354,221,49.24350922994,37.451875402005,-87.577544567795,2,1,18 +2025-03-11T12:41:24.794113,479392884,65354,221,49.25293322318,37.43802849246,-87.559017777545,2,1,18 +2025-03-11T12:41:24.809738,479392884,65354,221,49.24350922994,37.424148971055,-87.521979131015,2,1,18 +2025-03-11T12:41:24.825363,479392884,65354,221,49.22466124346,37.41025314372,-87.494169288605,2,1,18 +2025-03-11T12:41:24.840988,479392884,65354,221,49.20581325698,37.405599460035,-87.48950244152,2,1,18 +2025-03-11T12:41:24.856613,479392884,65354,221,49.1869652705,37.387082560875,-87.466295242175,2,1,18 +2025-03-11T12:41:24.872238,479392884,65354,221,49.17754127726,37.36396089582,-87.42459833258,2,1,18 +2025-03-11T12:41:24.887863,479392884,65354,221,49.15398129416,37.34081477187,-87.37363871384,2,1,18 +2025-03-11T12:41:24.903488,479392884,65354,221,49.12099731782,37.303789126515,-87.327231096155,2,1,18 +2025-03-11T12:41:24.919113,479392884,65354,221,49.09743733472,37.280643002565,-87.29937739274,2,1,18 +2025-03-11T12:41:24.934738,479392884,65354,221,49.05974136176,37.27595670702,-87.26233514018,2,1,18 +2025-03-11T12:41:24.950363,479392884,65354,221,49.03146938204,37.252802430105,-87.19750519124,2,1,18 +2025-03-11T12:41:24.965988,479392884,65354,221,49.01733339218,37.23429368391,-87.151198857575,2,1,18 +2025-03-11T12:41:24.981613,479392884,65354,221,48.98434941584,37.188025894905,-87.08626942763,2,1,18 +2025-03-11T12:41:24.997238,479392884,65354,221,48.94194144626,37.146362871795,-87.030587341805,2,1,18 +2025-03-11T12:41:25.012863,479392884,65354,221,48.9042454733,37.10470800165,-86.96104848779,2,1,18 +2025-03-11T12:41:25.028488,479392884,65354,221,48.86183750372,37.058423906715,-86.886863129705,2,1,18 +2025-03-11T12:41:25.044113,479392884,65354,221,48.833565524,36.9983010552,-86.80802131157,2,1,18 +2025-03-11T12:41:25.059738,479392884,65354,221,48.79586955104,36.965888328705,-86.738519537555,2,1,18 +2025-03-11T12:41:25.075363,479392884,65354,221,48.75346158146,36.93808852107,-86.6736507056,2,1,18 +2025-03-11T12:41:25.090988,479392884,65354,221,48.70162961864,36.882545976555,-86.580929973245,2,1,18 +2025-03-11T12:41:25.106613,479392884,65354,221,48.65450965244,36.817769441355,-86.50204249109,2,1,18 +2025-03-11T12:41:25.122238,479392884,65354,221,48.597965693,36.75759767205,-86.40929643773,2,1,18 +2025-03-11T12:41:25.137863,479392884,65354,221,48.54142173356,36.72053126187,-86.312021901305,2,1,18 +2025-03-11T12:41:25.153488,479392884,65354,221,48.49901376398,36.674247166935,-86.2008670787,2,1,18 +2025-03-11T12:41:25.169113,479392884,65354,221,48.4566057944,36.61872092835,-86.080432809965,2,1,18 +2025-03-11T12:41:25.184738,479392884,65354,221,48.39534983834,36.56778314973,-85.983095872535,2,1,18 +2025-03-11T12:41:25.200363,479392884,65354,221,48.32938188566,36.507595074495,-85.86723034184,2,1,18 +2025-03-11T12:41:25.215988,479392884,65354,221,48.26341393298,36.43816485561,-85.751327731145,2,1,18 +2025-03-11T12:41:25.231613,479392884,65354,221,48.1974459803,36.3825978522,-85.63548074045,2,1,18 +2025-03-11T12:41:25.247238,479392884,65354,221,48.14561401748,36.32243423586,-85.51039318664,2,1,18 +2025-03-11T12:41:25.262863,479392884,65354,221,48.08907005804,36.253020322905,-85.38988295489,2,1,18 +2025-03-11T12:41:25.278488,479392884,65354,221,48.01367811212,36.18357379809,-85.26934559912,2,1,18 +2025-03-11T12:41:25.294113,479392884,65354,221,47.94299816282,36.11413542624,-85.14419384129,2,1,18 +2025-03-11T12:41:25.309738,479392884,65354,221,47.86289422028,36.030817532985,-85.00973053532,2,1,18 +2025-03-11T12:41:25.325363,479392884,65354,221,47.79221427098,35.95675808931,-84.88456023749,2,1,18 +2025-03-11T12:41:25.340988,479392884,65354,221,47.71682232506,35.88269049267,-84.759383158655,2,1,18 +2025-03-11T12:41:25.356613,479392884,65354,221,47.63671838252,35.80399367124,-84.59259011123,2,1,18 +2025-03-11T12:41:25.372238,479392884,65354,221,47.55661443998,35.720675777985,-84.439642073,2,1,18 +2025-03-11T12:41:25.387863,479392884,65354,221,47.48122249406,35.637366037695,-84.3098067311,2,1,18 +2025-03-11T12:41:25.403488,479392884,65354,221,47.3964065549,35.554039991475,-84.1522307288,2,1,18 +2025-03-11T12:41:25.419113,479392884,65354,221,47.30687861912,35.466084720465,-83.99000822243,2,1,18 +2025-03-11T12:41:25.434738,479392884,65354,221,47.22206267996,35.38737974607,-83.827829577065,2,1,18 +2025-03-11T12:41:25.450363,479392884,65354,221,47.11839875432,35.31326323164,-83.633294066225,2,1,18 +2025-03-11T12:41:25.465988,479392884,65354,221,47.03358281516,35.22069504177,-83.47105980086,2,1,18 +2025-03-11T12:41:25.481613,479392884,65354,221,46.94405487938,35.12349762711,-83.322663763685,2,1,18 +2025-03-11T12:41:25.497238,479392884,65354,221,46.8545269436,35.021679140625,-83.160385637315,2,1,18 +2025-03-11T12:41:25.512863,479392884,65354,221,46.74615102134,34.92907018593,-82.979632734665,2,1,18 +2025-03-11T12:41:25.528488,479392884,65354,221,46.6424870957,34.831848312375,-82.78962570689,2,1,18 +2025-03-11T12:41:25.544113,479392884,65354,221,46.54353516668,34.72077137631,-82.59956984012,2,1,18 +2025-03-11T12:41:25.559738,479392884,65354,221,46.44458323766,34.609694440245,-82.42799870561,2,1,18 +2025-03-11T12:41:25.575363,479392884,65354,221,46.34563130864,34.503238576005,-82.23796137884,2,1,18 +2025-03-11T12:41:25.590988,479392884,65354,221,46.23725538638,34.406008549485,-82.043326386995,2,1,18 +2025-03-11T12:41:25.606613,479392884,65354,221,46.1241674675,34.304149298175,-81.85328725721,2,1,18 +2025-03-11T12:41:25.622238,479392884,65354,221,46.01579154524,34.197677128005,-81.640130453105,2,1,18 +2025-03-11T12:41:25.637863,479392884,65354,221,45.9121276196,34.08197096715,-81.417700983875,2,1,18 +2025-03-11T12:41:25.653488,479392884,65354,221,45.80375169734,33.970877725155,-81.218389188965,2,1,18 +2025-03-11T12:41:25.669113,479392884,65354,221,45.7000877717,33.86441370795,-81.00986034893,2,1,18 +2025-03-11T12:41:25.684738,479392884,65354,221,45.57757585958,33.74405386341,-80.80586994794,2,1,18 +2025-03-11T12:41:25.700363,479392884,65354,221,45.46919993732,33.605234190465,-80.56947744851,2,1,18 +2025-03-11T12:41:25.715988,479392884,65354,221,45.35611201844,33.47102743638,-80.32847552501,2,1,18 +2025-03-11T12:41:25.731613,479392884,65354,221,45.23831210294,33.34605467298,-80.11060981583,2,1,18 +2025-03-11T12:41:25.747238,479392884,65354,221,45.10637619758,33.20719423521,-79.87880459444,2,1,18 +2025-03-11T12:41:25.762863,479392884,65354,221,44.96501629898,33.082180706985,-79.65628379717,2,1,18 +2025-03-11T12:41:25.778488,479392884,65354,221,44.81423240714,32.943287657355,-79.42445145176,2,1,18 +2025-03-11T12:41:25.794113,479392884,65354,221,44.68229650178,32.832153650535,-79.17427273811,2,1,18 +2025-03-11T12:41:25.809738,479392884,65354,221,44.55978458966,32.69793059052,-78.92401488647,2,1,18 +2025-03-11T12:41:25.825363,479392884,65354,221,44.4278486843,32.55907015275,-78.687588482015,2,1,18 +2025-03-11T12:41:25.840988,479392884,65354,221,44.30062477556,32.42483893977,-78.43732384937,2,1,18 +2025-03-11T12:41:25.856613,479392884,65354,221,44.1686888702,32.285978502,-78.191655078785,2,1,18 +2025-03-11T12:41:25.872238,479392884,65354,221,44.01790497836,32.14708545237,-77.950580367245,2,1,18 +2025-03-11T12:41:25.887863,479392884,65354,221,43.86712108652,32.00819240274,-77.691020923445,2,1,18 +2025-03-11T12:41:25.903488,479392884,65354,221,43.7210491913,31.8739285779,-77.43148680065,2,1,18 +2025-03-11T12:41:25.919113,479392884,65354,221,43.60796127242,31.74434289564,-77.17201868489,2,1,18 +2025-03-11T12:41:25.934738,479392884,65354,221,43.45717738058,31.591586630535,-76.90316125496,2,1,18 +2025-03-11T12:41:25.950363,479392884,65354,221,43.2969694955,31.434192987675,-76.63427172302,2,1,18 +2025-03-11T12:41:25.965988,479392884,65354,221,43.15089760028,31.290687019185,-76.356215787965,2,1,18 +2025-03-11T12:41:25.981613,479392884,65354,221,43.00482570506,31.147181050695,-76.092023402105,2,1,18 +2025-03-11T12:41:25.997177,479392888,65350,222,42.85875380984,30.98981186673,-75.818533030115,2,1,18 +2025-03-11T12:41:26.012802,479392888,65350,222,42.707969918,30.837055601625,-75.52656968486,2,1,18 +2025-03-11T12:41:26.028427,479392888,65350,222,42.55247402954,30.69815439903,-75.2346551786,2,1,18 +2025-03-11T12:41:26.044052,479392888,65350,222,42.38284215122,30.54074445024,-74.97499445078,2,1,18 +2025-03-11T12:41:26.059677,479392888,65350,222,42.22734626276,30.36949574487,-74.68295016452,2,1,18 +2025-03-11T12:41:26.075302,479392888,65350,222,42.07656237092,30.198255192465,-74.390912659265,2,1,18 +2025-03-11T12:41:26.090927,479392888,65350,222,41.91635448584,30.02699833413,-74.08961922587,2,1,18 +2025-03-11T12:41:26.106552,479392888,65350,222,41.73729861428,29.85108779211,-73.779037762325,2,1,18 +2025-03-11T12:41:26.122177,479392888,65350,222,41.58651472244,29.679847239705,-73.473136707875,2,1,18 +2025-03-11T12:41:26.137802,479392888,65350,222,41.41688284412,29.522437290915,-73.176506515535,2,1,18 +2025-03-11T12:41:26.153427,479392888,65350,222,41.23311497594,29.34651859593,-72.84281235566,2,1,18 +2025-03-11T12:41:26.169052,479392888,65350,222,41.04463511114,29.175212819805,-72.51837232091,2,1,18 +2025-03-11T12:41:26.184677,479392888,65350,222,40.87971522944,28.994705664855,-72.20779266038,2,1,18 +2025-03-11T12:41:26.200302,479392888,65350,222,40.70065935788,28.81417405101,-71.887950290705,2,1,18 +2025-03-11T12:41:26.215927,479392888,65350,222,40.53102747956,28.62903767127,-71.56810294304,2,1,18 +2025-03-11T12:41:26.231552,479392888,65350,222,40.36139560124,28.44390129153,-71.24363441231,2,1,18 +2025-03-11T12:41:26.247177,479392888,65350,222,40.20118771616,28.27726550502,-70.923874786655,2,1,18 +2025-03-11T12:41:26.262802,479392888,65350,222,40.02684384122,28.092120972315,-70.594778291855,2,1,18 +2025-03-11T12:41:26.278427,479392888,65350,222,39.84778796966,27.916210430295,-70.25646972992,2,1,18 +2025-03-11T12:41:26.294052,479392888,65350,222,39.65459610824,27.726412213905,-69.91808520497,2,1,18 +2025-03-11T12:41:26.309677,479392888,65350,222,39.4566922502,27.5458479882,-69.58435216208,2,1,18 +2025-03-11T12:41:26.325302,479392888,65350,222,39.25878839216,27.35142054702,-69.24132113306,2,1,18 +2025-03-11T12:41:26.340927,479392888,65350,222,39.07030852736,27.170872627245,-68.90760165218,2,1,18 +2025-03-11T12:41:26.356552,479392888,65350,222,38.88182866256,26.976461491995,-68.578447734365,2,1,18 +2025-03-11T12:41:26.372177,479392888,65350,222,38.69806079438,26.777437437885,-68.230797325295,2,1,18 +2025-03-11T12:41:26.387802,479392888,65350,222,38.50958092958,26.58764737446,-67.850828933765,2,1,18 +2025-03-11T12:41:26.403427,479392888,65350,222,38.33523705464,26.393260698105,-67.49858944364,2,1,18 +2025-03-11T12:41:26.419052,479392888,65350,222,38.1373331966,26.208075400575,-67.15559549462,2,1,18 +2025-03-11T12:41:26.434677,479392888,65350,222,37.93471734194,26.027503021905,-66.784886206205,2,1,18 +2025-03-11T12:41:26.450302,479392888,65350,222,37.73210148728,25.828446355935,-66.42334512392,2,1,18 +2025-03-11T12:41:26.465927,479392888,65350,222,37.52948563262,25.620147546315,-66.061766961635,2,1,18 +2025-03-11T12:41:26.481552,479392888,65350,222,37.32215778134,25.416461655555,-65.681715826085,2,1,18 +2025-03-11T12:41:26.497177,479392888,65350,222,37.12896591992,25.20355808004,-65.31089031968,2,1,18 +2025-03-11T12:41:26.512802,479392888,65350,222,36.93106206188,24.995267423385,-64.944697755335,2,1,18 +2025-03-11T12:41:26.528427,479392888,65350,222,36.7237342106,24.7869604608,-64.57849162898,2,1,18 +2025-03-11T12:41:26.544052,479392888,65350,222,36.52111835594,24.57866165118,-64.2030499175,2,1,18 +2025-03-11T12:41:26.559677,479392888,65350,222,36.29494251818,24.370322076735,-63.809089568735,2,1,18 +2025-03-11T12:41:26.575302,479392888,65350,222,36.08290267028,24.143522673885,-63.39196948766,2,1,18 +2025-03-11T12:41:26.590927,479392888,65350,222,35.87086282238,23.92134434286,-62.98873149578,2,1,18 +2025-03-11T12:41:26.606552,479392888,65350,222,35.64939898124,23.71301292138,-62.608641477215,2,1,18 +2025-03-11T12:41:26.622177,479392888,65350,222,35.43735913334,23.51393994948,-62.205496185335,2,1,18 +2025-03-11T12:41:26.637802,479392888,65350,222,35.23003128206,23.287148699595,-61.788382885265,2,1,18 +2025-03-11T12:41:26.653427,479392888,65350,222,35.01799143416,23.07421251222,-61.40828788871,2,1,18 +2025-03-11T12:41:26.669052,479392888,65350,222,34.81066358288,22.856663405985,-61.01893876703,2,1,18 +2025-03-11T12:41:26.684677,479392888,65350,222,34.57506375188,22.634444310135,-60.615666870125,2,1,18 +2025-03-11T12:41:26.700302,479392888,65350,222,34.35359991074,22.41224967318,-60.2170364993,2,1,18 +2025-03-11T12:41:26.715927,479392888,65350,222,34.13684806622,22.194684261015,-59.813810266415,2,1,18 +2025-03-11T12:41:26.731552,479392888,65350,222,33.9200962217,21.990982064325,-59.4013972874,2,1,18 +2025-03-11T12:41:26.747177,479392888,65350,222,33.68920838732,21.764150049615,-58.98887126537,2,1,18 +2025-03-11T12:41:26.762802,479392888,65350,222,33.46303254956,21.532705116045,-58.594818216605,2,1,18 +2025-03-11T12:41:26.778427,479392888,65350,222,33.24628070504,21.31513970388,-58.18234961759,2,1,18 +2025-03-11T12:41:26.794052,479392888,65350,222,33.02010486728,21.07445262666,-57.75591120737,2,1,18 +2025-03-11T12:41:26.809677,479392888,65350,222,32.77508104304,20.83373293758,-57.33868803926,2,1,18 +2025-03-11T12:41:26.825302,479392888,65350,222,32.5300572188,20.597634320325,-56.916862228085,2,1,18 +2025-03-11T12:41:26.840927,479392888,65350,222,32.2944573878,20.366173080825,-56.46734142053,2,1,18 +2025-03-11T12:41:26.856552,479392888,65350,222,32.06828155004,20.13010707543,-56.05016391644,2,1,18 +2025-03-11T12:41:26.872177,479392888,65350,222,31.83739371566,19.89403291707,-55.63760081441,2,1,18 +2025-03-11T12:41:26.887802,479392888,65350,222,31.58294589818,19.65329692206,-55.206500535095,2,1,18 +2025-03-11T12:41:26.903427,479392888,65350,222,31.33792207394,19.41257723298,-54.78465618392,2,1,18 +2025-03-11T12:41:26.919052,479392888,65350,222,31.10703423956,19.18574521827,-54.358266612695,2,1,18 +2025-03-11T12:41:26.934677,479392888,65350,222,30.87614640518,18.93118677261,-53.91328106921,2,1,18 +2025-03-11T12:41:26.950302,479392888,65350,222,30.64054657418,18.685862317635,-53.454462275525,2,1,18 +2025-03-11T12:41:26.965927,479392888,65350,222,30.39081075332,18.44513447559,-52.995641678825,2,1,18 +2025-03-11T12:41:26.981552,479392888,65350,222,30.1504989257,18.2090440113,-52.536853184135,2,1,18 +2025-03-11T12:41:26.997177,479392888,65350,222,29.91961109132,17.959106637465,-52.10112854678,2,1,18 +2025-03-11T12:41:27.012802,479392888,65350,222,29.66987527046,17.695273436295,-51.6791847146,2,1,18 +2025-03-11T12:41:27.028427,479392888,65350,222,29.4201394496,17.45454559425,-51.22960648403,2,1,18 +2025-03-11T12:41:27.044052,479392888,65350,222,29.17511562536,17.209204833345,-50.761531762205,2,1,18 +2025-03-11T12:41:27.059677,479392888,65350,222,28.9253798045,16.963855919475,-50.30731380857,2,1,18 +2025-03-11T12:41:27.075302,479392888,65350,222,28.67093198702,16.70001456534,-49.85301491393,2,1,18 +2025-03-11T12:41:27.090927,479392888,65350,222,28.41648416954,16.436173211205,-49.375610103965,2,1,18 +2025-03-11T12:41:27.106552,479392888,65350,222,28.16674834868,16.190824297335,-48.90290741807,2,1,18 +2025-03-11T12:41:27.122177,479392888,65350,222,27.91701252782,15.936233239815,-48.47175829976,2,1,18 +2025-03-11T12:41:27.137802,479392888,65350,222,27.66727670696,15.681642182295,-48.008260899995,2,1,18 +2025-03-11T12:41:27.153427,479392888,65350,222,27.41282888948,15.44552725911,-47.53096733003,2,1,18 +2025-03-11T12:41:27.169052,479392888,65350,222,27.16309306862,15.177072986115,-47.0627931272,2,1,18 +2025-03-11T12:41:27.184677,479392888,65350,222,26.91335724776,14.91786085677,-46.599277187435,2,1,18 +2025-03-11T12:41:27.200302,479392888,65350,222,26.65419743366,14.658632421495,-46.140368868725,2,1,18 +2025-03-11T12:41:27.215927,479392888,65350,222,26.37618963308,14.40861351801,-45.65836459067,2,1,18 +2025-03-11T12:41:27.231552,479392888,65350,222,26.11702981898,14.12627972361,-45.15315174131,2,1,18 +2025-03-11T12:41:27.247177,479392888,65350,222,25.86729399812,13.867067594265,-44.680393435415,2,1,18 +2025-03-11T12:41:27.262802,479392888,65350,222,25.61755817726,13.630960824045,-44.20772782952,2,1,18 +2025-03-11T12:41:27.278427,479392888,65350,222,25.33955037668,13.367078705085,-43.734910297595,2,1,18 +2025-03-11T12:41:27.294052,479392888,65350,222,25.06625457272,13.098583667265,-43.24821745748,2,1,18 +2025-03-11T12:41:27.309677,479392888,65350,222,24.81651875186,12.816266178795,-42.77074526852,2,1,18 +2025-03-11T12:41:27.325302,479392888,65350,222,24.56207093438,12.54318268101,-42.27019746323,2,1,18 +2025-03-11T12:41:27.340927,479392888,65350,222,24.28877513042,12.288550858665,-41.783560243115,2,1,18 +2025-03-11T12:41:27.356552,479392888,65350,222,24.01547932646,12.029297964495,-41.30614684913,2,1,18 +2025-03-11T12:41:27.372177,479392888,65350,222,23.73747152588,11.77003691736,-40.81948430801,2,1,18 +2025-03-11T12:41:27.387802,479392888,65350,222,23.46417572192,11.496920807715,-40.30966701257,2,1,18 +2025-03-11T12:41:27.403427,479392888,65350,222,23.19559191458,11.214570707385,-39.799819418135,2,1,18 +2025-03-11T12:41:27.419052,479392888,65350,222,22.91287211738,10.946059363635,-39.30387064988,2,1,18 +2025-03-11T12:41:27.434677,479392888,65350,222,22.63957631342,10.68218539764,-38.8125751667,2,1,18 +2025-03-11T12:41:27.450302,479392888,65350,222,22.38041649932,10.404472675065,-38.330486772665,2,1,18 +2025-03-11T12:41:27.465927,479392888,65350,222,22.11183269198,10.11750150291,-37.82986300436,2,1,18 +2025-03-11T12:41:27.481552,479392888,65350,222,21.82440089816,9.830497718895,-37.31534856284,2,1,18 +2025-03-11T12:41:27.497177,479392888,65350,222,21.54168110096,9.534259944195,-36.819288554585,2,1,18 +2025-03-11T12:41:27.512802,479392888,65350,222,21.26367330038,9.24727246611,-36.323272407335,2,1,18 +2025-03-11T12:41:27.528427,479392888,65350,222,20.99037749642,8.992640643765,-35.81815045496,2,1,18 +2025-03-11T12:41:27.544052,479392888,65350,222,20.71236969584,8.71489530933,-35.31292902158,2,1,18 +2025-03-11T12:41:27.559677,479392888,65350,222,20.43907389188,8.432537056035,-34.807695829205,2,1,18 +2025-03-11T12:41:27.575302,479392888,65350,222,20.15635409468,8.15940464046,-34.27475905643,2,1,18 +2025-03-11T12:41:27.590927,479392888,65350,222,19.8783462941,7.8770382342,-33.76027671692,2,1,18 +2025-03-11T12:41:27.606552,479392888,65350,222,19.60033849352,7.599292899765,-33.250434100475,2,1,18 +2025-03-11T12:41:27.622177,479392888,65350,222,19.32233069294,7.33078970898,-32.74062856403,2,1,18 +2025-03-11T12:41:27.637802,479392888,65350,222,19.02076290926,7.03451932242,-32.23067788256,2,1,18 +2025-03-11T12:41:27.653427,479392888,65350,222,18.73333111544,6.747515538405,-31.720784624105,2,1,18 +2025-03-11T12:41:27.669052,479392888,65350,222,18.44589932162,6.455890682565,-31.20163045952,2,1,18 +2025-03-11T12:41:27.684677,479392888,65350,222,18.17731551428,6.173540582235,-30.673298132825,2,1,18 +2025-03-11T12:41:27.700302,479392888,65350,222,17.89459571708,5.86343959206,-30.154076589245,2,1,18 +2025-03-11T12:41:27.715927,479392888,65350,222,17.62129991312,5.590323482415,-29.644259293805,2,1,18 +2025-03-11T12:41:27.731552,479392888,65350,222,17.33858011592,5.303327851365,-29.125130450225,2,1,18 +2025-03-11T12:41:27.747177,479392888,65350,222,17.0511483221,5.0070819237,-28.610578928705,2,1,18 +2025-03-11T12:41:27.762802,479392888,65350,222,16.78256451476,4.729352895195,-28.068401592815,2,1,18 +2025-03-11T12:41:27.778427,479392888,65350,222,16.48099673108,4.442324652285,-27.521518526825,2,1,18 +2025-03-11T12:41:27.794052,479392888,65350,222,16.17471695078,4.14604611276,-26.997697515155,2,1,18 +2025-03-11T12:41:27.809677,479392888,65350,222,15.8967091502,3.859058634675,-26.46933308645,2,1,18 +2025-03-11T12:41:27.825302,479392888,65350,222,15.61870134962,3.567450084765,-25.95481366694,2,1,18 +2025-03-11T12:41:27.840927,479392888,65350,222,15.3312695558,3.294309516225,-25.44035484542,2,1,18 +2025-03-11T12:41:27.856552,479392888,65350,222,15.03912576536,3.02116079472,-24.907404510635,2,1,18 +2025-03-11T12:41:27.872177,479392888,65350,222,14.75169397154,2.724914867055,-24.383610622985,2,1,18 +2025-03-11T12:41:27.887802,479392888,65350,222,14.4595501811,2.4240397146,-23.855170231265,2,1,18 +2025-03-11T12:41:27.903427,479392888,65350,222,14.15798239742,2.123148256215,-23.317473911405,2,1,18 +2025-03-11T12:41:27.919052,479392888,65350,222,13.86583860698,1.82227310376,-22.789033519685,2,1,18 +2025-03-11T12:41:27.934677,479392888,65350,222,13.5642708233,1.549108076325,-22.251448439825,2,1,18 +2025-03-11T12:41:27.950302,479392888,65350,222,13.2815510261,1.252870301625,-21.723040150115,2,1,18 +2025-03-11T12:41:27.965927,479392888,65350,222,13.00354322552,0.95664067989,-21.19463864141,2,1,18 +2025-03-11T12:41:27.981552,479392888,65350,222,12.69726344522,0.660362140365001,-20.64309053135,2,1,18 +2025-03-11T12:41:27.997177,479392888,65350,222,12.39569566154,0.35022853833,-20.109978314555,2,1,18 +2025-03-11T12:41:28.012802,479392888,65350,222,12.09883987448,0.0678295202100001,-19.5723629357,2,1,18 +2025-03-11T12:41:28.028427,479392888,65350,222,11.80669608404,-0.214561344944999,-19.039375520915,2,1,18 +2025-03-11T12:41:28.044052,479392888,65350,222,11.50984029698,-0.510823578539999,-18.4832197898,2,1,18 +2025-03-11T12:41:28.059677,479392888,65350,222,11.21769650654,-0.825561946470001,-17.94548141195,2,1,18 +2025-03-11T12:41:28.075302,479392888,65350,222,10.91141672624,-1.140324773295,-17.40310150802,2,1,18 +2025-03-11T12:41:28.090927,479392888,65350,222,10.62869692904,-1.43194147617,-16.860848209115,2,1,18 +2025-03-11T12:41:28.106552,479392888,65350,222,10.34597713184,-1.723558179045,-16.30935254408,2,1,18 +2025-03-11T12:41:28.122177,479392888,65350,222,10.06325733464,-2.02441702557,-15.785546897435,2,1,18 +2025-03-11T12:41:28.137802,479392888,65350,222,9.7475535611,-2.3160907992,-15.243246131495,2,1,18 +2025-03-11T12:41:28.153427,479392888,65350,222,9.44598577742,-2.59387689846,-14.696400145505,2,1,18 +2025-03-11T12:41:28.169052,479392888,65350,222,9.17268997346,-2.89934051088,-14.16334715474,2,1,18 +2025-03-11T12:41:28.184677,479392888,65350,222,8.8758341864,-3.20946595995,-13.62099935282,2,1,18 +2025-03-11T12:41:28.200302,479392888,65350,222,8.57897839934,-3.51034926537,-13.074067447835,2,1,18 +2025-03-11T12:41:28.215927,479392888,65350,222,8.26798662242,-3.80663595786,-12.527133739835,2,1,18 +2025-03-11T12:41:28.231552,479392888,65350,222,7.96641883874,-4.11214848807,-12.007903612235,2,1,18 +2025-03-11T12:41:28.247177,479392888,65350,222,7.6742750483,-4.426886856,-11.479407600515,2,1,18 +2025-03-11T12:41:28.262802,479392888,65350,222,7.38684325448,-4.71851171184,-10.91404160528,2,1,18 +2025-03-11T12:41:28.278427,479392888,65350,222,7.08056347418,-5.01941132319,-10.35323258909,2,1,18 +2025-03-11T12:41:28.294052,479392888,65350,222,6.78370768712,-5.306431413135,-9.81097748717,2,1,18 +2025-03-11T12:41:28.309677,479392888,65350,222,6.49156389668,-5.60730656559,-9.268673546255,2,1,18 +2025-03-11T12:41:28.325302,479392888,65350,222,6.18528411638,-5.912827248765,-8.72170953926,2,1,18 +2025-03-11T12:41:28.340927,479392888,65350,222,5.88842832932,-6.21833162601,-8.174759094275,2,1,18 +2025-03-11T12:41:28.356552,479392888,65350,222,5.58686054564,-6.51460201257,-7.627838948285,2,1,18 +2025-03-11T12:41:28.372177,479392888,65350,222,5.2711567721,-6.81551792985,-7.076258736215,2,1,18 +2025-03-11T12:41:28.387802,479392888,65350,222,4.97430098504,-7.10715909162,-6.533985094295,2,1,18 +2025-03-11T12:41:28.403427,479392888,65350,222,4.67744519798,-7.40804239704,-5.982432006245,2,1,18 +2025-03-11T12:41:28.419052,479392888,65350,222,4.38058941092,-7.704304630635,-5.430897458195,2,1,18 +2025-03-11T12:41:28.434677,479392888,65350,222,4.069597634,-8.00521239495,-4.883945210195,2,1,18 +2025-03-11T12:41:28.450302,479392888,65350,222,3.77274184694,-8.310716772195,-4.34623713134,2,1,18 +2025-03-11T12:41:28.465927,479392888,65350,222,3.4805980565,-8.602349781,-3.803970270425,2,1,18 +2025-03-11T12:41:28.481552,479392888,65350,222,3.18845426606,-8.893982789805,-3.257082226445,2,1,18 +2025-03-11T12:41:28.497177,479392888,65350,222,2.88217448576,-9.20874561663,-2.71932350558,2,1,18 +2025-03-11T12:41:28.512802,479392888,65350,222,2.5853186987,-9.5003867784,-2.17704986366,2,1,18 +2025-03-11T12:41:28.528427,479392888,65350,222,2.27432692178,-9.810536686365,-1.616196986465,2,1,18 +2025-03-11T12:41:28.544052,479392888,65350,222,1.96804714148,-10.11605736954,-1.05999061334,2,1,18 +2025-03-11T12:41:28.559677,479392888,65350,222,1.68061534766,-10.40768222538,-0.503866984235001,2,1,18 +2025-03-11T12:41:28.575302,479392888,65350,222,1.37904756398,-10.690089396465,0.0337551756250001,2,1,18 +2025-03-11T12:41:28.590927,479392888,65350,222,1.07276778368,-10.990989007815,0.58070064262,2,1,18 +2025-03-11T12:41:28.606552,479392888,65350,222,0.78533598986,-11.29647707913,1.118395159465,2,1,18 +2025-03-11T12:41:28.622177,479392888,65350,222,0.49319219942,-11.597352231585,1.66069910038,2,1,18 +2025-03-11T12:41:28.637802,479392888,65350,222,0.1822004225,-11.8982599959,2.21689371451,2,1,18 +2025-03-11T12:41:28.653427,479392888,65350,222,-0.11936736118,-12.20377252611,2.7638509405,2,1,18 +2025-03-11T12:41:28.669052,479392888,65350,222,-0.41622314824,-12.518519047005,3.31545964855,2,1,18 +2025-03-11T12:41:28.684677,479392888,65350,222,-0.7130789353,-12.819402352425,3.8670127366,2,1,18 +2025-03-11T12:41:28.700302,479392888,65350,222,-1.0193587156,-13.111059820125,4.4000575744,2,1,18 +2025-03-11T12:41:28.715927,479392888,65350,222,-1.31150250604,-13.40269282893,4.94694561838,2,1,18 +2025-03-11T12:41:28.731552,479392888,65350,222,-1.59893429986,-13.69431768477,5.49844806442,2,1,18 +2025-03-11T12:41:28.747177,479392888,65350,222,-1.89579008692,-14.00444313384,6.04079586634,2,1,18 +2025-03-11T12:41:28.762802,479392888,65350,222,-2.1973578706,-14.30995566405,6.56926836007,2,1,18 +2025-03-11T12:41:28.778427,479392888,65350,222,-2.48950166104,-14.60620974468,7.111553760985,2,1,18 +2025-03-11T12:41:28.794052,479392888,65350,222,-2.7863574481,-14.89785090645,7.644585036775,2,1,18 +2025-03-11T12:41:28.809677,479392888,65350,222,-3.08792523178,-15.189500221185,8.182244276635,2,1,18 +2025-03-11T12:41:28.825302,479392888,65350,222,-3.37064502898,-15.49035906771,8.71529228941,2,1,18 +2025-03-11T12:41:28.840927,479392888,65350,222,-3.66278881942,-15.78661314834,9.257577690325,2,1,18 +2025-03-11T12:41:28.856552,479392888,65350,222,-3.96906859972,-16.082891687865,9.80450461732,2,1,18 +2025-03-11T12:41:28.872177,479392888,65350,222,-4.26592438678,-16.38839606511,10.33759151311,2,1,18 +2025-03-11T12:41:28.887802,479392888,65350,222,-4.5533561806,-16.684641992775,10.866006583825,2,1,18 +2025-03-11T12:41:28.903427,479392888,65350,222,-4.85021196766,-16.976283154545,11.41290140881,2,1,18 +2025-03-11T12:41:28.919052,479392888,65350,222,-5.13293176486,-17.25865771377,11.964359993845,2,1,18 +2025-03-11T12:41:28.934677,479392888,65350,222,-5.4250755553,-17.550290722575,12.483520939435,2,1,18 +2025-03-11T12:41:28.950302,479392888,65350,222,-5.73606733222,-17.828093127765,12.99803220598,2,1,18 +2025-03-11T12:41:28.965927,479392888,65350,222,-6.02821112266,-18.115105064745,13.53565934383,2,1,18 +2025-03-11T12:41:28.981552,479392888,65350,222,-6.31093091986,-18.429827126745,14.087247708865,2,1,18 +2025-03-11T12:41:28.997177,479392888,65350,222,-6.6030747103,-18.716839063725,14.61101129752,2,1,18 +2025-03-11T12:41:29.012802,479392888,65350,222,-6.89050650412,-19.026948206865,15.12561843904,2,1,18 +2025-03-11T12:41:29.028427,479392888,65350,222,-7.17793829794,-19.32319413453,15.66789705895,2,1,18 +2025-03-11T12:41:29.044052,479392888,65350,222,-7.474794085,-19.6148352963,16.196307151675,2,1,18 +2025-03-11T12:41:29.059677,479392888,65350,222,-7.77164987206,-19.93420288902,16.729449667465,2,1,18 +2025-03-11T12:41:29.075302,479392888,65350,222,-8.05908166588,-20.20734345756,17.253150855115,2,1,18 +2025-03-11T12:41:29.090927,479392888,65350,222,-8.34180146308,-20.49433908861,17.76765851563,2,1,18 +2025-03-11T12:41:29.106552,479392888,65350,222,-8.64336924676,-20.76288304422,18.300603872425,2,1,18 +2025-03-11T12:41:29.122177,479392888,65350,222,-8.94022503382,-21.049903134165,18.82899542515,2,1,18 +2025-03-11T12:41:29.137802,479392888,65350,222,-9.22765682764,-21.341527990005,19.38049787119,2,1,18 +2025-03-11T12:41:29.153427,479392888,65350,222,-9.49152863836,-21.63311208102,19.922724046075,2,1,18 +2025-03-11T12:41:29.169052,479392888,65350,222,-9.77424843556,-21.906244496595,20.423312537395,2,1,18 +2025-03-11T12:41:29.184677,479392888,65350,222,-10.05696823276,-22.193240127645,20.92857783178,2,1,18 +2025-03-11T12:41:29.200302,479392888,65350,222,-10.33497603334,-22.48022760573,21.456942260485,2,1,18 +2025-03-11T12:41:29.215927,479392888,65350,222,-10.6318318204,-22.767247695675,21.980712630145,2,1,18 +2025-03-11T12:41:29.231552,479392888,65350,222,-10.93339960408,-23.072760225885,22.499942757745,2,1,18 +2025-03-11T12:41:29.247177,479392888,65350,222,-11.21140740466,-23.35974770397,23.00058008806,2,1,18 +2025-03-11T12:41:29.262802,479392888,65350,222,-11.479991212,-23.65133994795,23.510464762495,2,1,18 +2025-03-11T12:41:29.278427,479392888,65350,222,-11.75799901258,-23.93370635421,24.02032591894,2,1,18 +2025-03-11T12:41:29.294052,479392888,65350,222,-12.0454308064,-24.20684692275,24.53478474046,2,1,18 +2025-03-11T12:41:29.309677,479392888,65350,222,-12.33757459684,-24.48461671608,25.058511249115,2,1,18 +2025-03-11T12:41:29.325302,479392888,65350,222,-12.62029439404,-24.785475562605,25.577695712695,2,1,18 +2025-03-11T12:41:29.340927,479392888,65350,222,-12.89830219462,-25.06322089704,26.08753832914,2,1,18 +2025-03-11T12:41:29.356552,479392888,65350,222,-13.18102199182,-25.327111168965,26.61581683885,2,1,18 +2025-03-11T12:41:29.372177,479392888,65350,222,-13.45431779578,-25.604848350435,27.10716794203,2,1,18 +2025-03-11T12:41:29.387802,479392888,65350,222,-13.7181896065,-25.8871902978,27.593902840135,2,1,18 +2025-03-11T12:41:29.403427,479392888,65350,222,-13.99619740708,-26.164935632235,28.07601835819,2,1,18 +2025-03-11T12:41:29.419052,479392888,65350,222,-14.26949321104,-26.442672813705,28.59509655976,2,1,18 +2025-03-11T12:41:29.434677,479392888,65350,222,-14.54750101162,-26.706554932665,29.104883556205,2,1,18 +2025-03-11T12:41:29.450302,479392888,65350,222,-14.83493280544,-26.988937644855,29.610137091595,2,1,18 +2025-03-11T12:41:29.465927,479392888,65350,222,-15.10351661278,-27.262045601535,30.1107052399,2,1,18 +2025-03-11T12:41:29.481552,479392888,65350,222,-15.37681241674,-27.530540639355,30.615882812275,2,1,18 +2025-03-11T12:41:29.497177,479392888,65350,222,-15.64539622408,-27.80826966786,31.102605951385,2,1,18 +2025-03-11T12:41:29.512802,479392888,65350,222,-15.89984404156,-28.072111021995,31.584631944415,2,1,18 +2025-03-11T12:41:29.528427,479392888,65350,222,-16.17313984552,-28.33598498799,32.066685061465,2,1,18 +2025-03-11T12:41:29.544052,479392888,65350,222,-16.46057163934,-28.622988772005,32.562714770725,2,1,18 +2025-03-11T12:41:29.559677,479392888,65350,222,-16.71973145344,-28.896080422755,33.058648173955,2,1,18 +2025-03-11T12:41:29.575302,479392888,65350,222,-16.97889126754,-29.16455100168,33.54994185412,2,1,18 +2025-03-11T12:41:29.590927,479392888,65350,222,-17.24276307826,-29.428408661745,34.045844958355,2,1,18 +2025-03-11T12:41:29.606552,479392888,65350,222,-17.5113468856,-29.692274474775,34.53713366053,2,1,18 +2025-03-11T12:41:29.622177,479392888,65350,222,-17.77993069294,-29.965382431455,34.99611116125,2,1,18 +2025-03-11T12:41:29.637802,479392888,65350,222,-18.04380250366,-30.224619019695,35.45964744403,2,1,18 +2025-03-11T12:41:29.653427,479392888,65350,222,-18.312386311,-30.488484832725,35.93707259701,2,1,18 +2025-03-11T12:41:29.669052,479392888,65350,222,-18.58097011834,-30.73848743028,36.428305679185,2,1,18 +2025-03-11T12:41:29.684677,479392888,65350,222,-18.84484192906,-30.983860803045,36.92413462342,2,1,18 +2025-03-11T12:41:29.700302,479392888,65350,222,-19.0898657533,-31.2384437076,37.419973523635,2,1,18 +2025-03-11T12:41:29.715927,479392888,65350,222,-19.35373756402,-31.511543511315,37.88818660948,2,1,18 +2025-03-11T12:41:29.731552,479392888,65350,222,-19.61760937474,-31.770780099555,38.337859343065,2,1,18 +2025-03-11T12:41:29.747177,479392888,65350,222,-19.86263319898,-32.02536300411,38.792107595695,2,1,18 +2025-03-11T12:41:29.762802,479392888,65350,222,-20.10765702322,-32.28456698049,39.246374388325,2,1,18 +2025-03-11T12:41:29.778427,479392888,65350,222,-20.37624083056,-32.53919064987,39.71914127824,2,1,18 +2025-03-11T12:41:29.794052,479392888,65350,222,-20.6212646548,-32.7891524826,40.182613357,2,1,18 +2025-03-11T12:41:29.809677,479392888,65350,222,-20.86157648242,-33.048348306015,40.655358100885,2,1,18 +2025-03-11T12:41:29.825302,479392888,65350,222,-21.12073629652,-33.302955669465,41.123490245725,2,1,18 +2025-03-11T12:41:29.840927,479392888,65350,222,-21.37047211738,-33.566788870635,41.582403542425,2,1,18 +2025-03-11T12:41:29.856552,479392888,65350,222,-21.60607194838,-33.82135546926,42.027395866915,2,1,18 +2025-03-11T12:41:29.872177,479392888,65350,222,-21.85580776924,-34.062083311305,42.467731731355,2,1,18 +2025-03-11T12:41:29.887802,479392888,65350,222,-22.11025558672,-34.30744037814,42.89885055067,2,1,18 +2025-03-11T12:41:29.903427,479392888,65350,222,-22.36941540082,-34.548184526115,43.34844234325,2,1,18 +2025-03-11T12:41:29.919052,479392888,65350,222,-22.61443922506,-34.798146358845,43.807293238945,2,1,18 +2025-03-11T12:41:29.934677,479392888,65350,222,-22.84061506282,-35.048075579715,44.25687464449,2,1,18 +2025-03-11T12:41:29.950302,479392888,65350,222,-23.0715028972,-35.2887708099,44.68794101878,2,1,18 +2025-03-11T12:41:29.965927,479392888,65350,222,-23.32123871806,-35.54336186742,45.14681723548,2,1,18 +2025-03-11T12:41:29.981552,479392888,65350,222,-23.57097453892,-35.774847565815,45.60560075218,2,1,18 +2025-03-11T12:41:29.997116,479392892,65346,223,-23.80657436992,-36.00168773349,46.02275473828,2,1,18 +2025-03-11T12:41:30.012741,479392892,65346,223,-24.0610221874,-36.219318369375,46.44914113453,2,1,18 +2025-03-11T12:41:30.028366,479392892,65346,223,-24.27777403192,-36.441504853365,46.870870639675,2,1,18 +2025-03-11T12:41:30.043991,479392892,65346,223,-24.51337386292,-36.691450380165,47.3112232411,2,1,18 +2025-03-11T12:41:30.059616,479392892,65346,223,-24.7678216804,-36.94604959065,47.742379140415,2,1,18 +2025-03-11T12:41:30.075241,479392892,65346,223,-24.99399751816,-37.18673666787,48.159575184505,2,1,18 +2025-03-11T12:41:30.090866,479392892,65346,223,-25.22017335592,-37.422802673265,48.576752688595,2,1,18 +2025-03-11T12:41:30.106491,479392892,65346,223,-25.46048518354,-37.658893137555,48.9939505357,2,1,18 +2025-03-11T12:41:30.122116,479392892,65346,223,-25.6866610213,-37.890338071125,49.42035186592,2,1,18 +2025-03-11T12:41:30.137741,479392892,65346,223,-25.91283685906,-38.11716193287,49.842113473075,2,1,18 +2025-03-11T12:41:30.153366,479392892,65346,223,-26.1343007002,-38.32549335435,50.25917295616,2,1,18 +2025-03-11T12:41:30.168991,479392892,65346,223,-26.36518853458,-38.55232536906,50.648593062865,2,1,18 +2025-03-11T12:41:30.184616,479392892,65346,223,-26.59136437234,-38.77452815898,51.04260903163,2,1,18 +2025-03-11T12:41:30.200241,479392892,65346,223,-26.80811621686,-38.992093571145,51.44121408145,2,1,18 +2025-03-11T12:41:30.215866,479392892,65346,223,-27.03429205462,-39.22815957654,51.863012768605,2,1,18 +2025-03-11T12:41:30.231491,479392892,65346,223,-27.24633190252,-39.450337907565,52.266250760485,2,1,18 +2025-03-11T12:41:30.247116,479392892,65346,223,-27.46308374704,-39.67714546338,52.64178697498,2,1,18 +2025-03-11T12:41:30.262741,479392892,65346,223,-27.67512359494,-39.890081650755,53.021881971535,2,1,18 +2025-03-11T12:41:30.278366,479392892,65346,223,-27.88716344284,-40.11225998178,53.425119963415,2,1,18 +2025-03-11T12:41:30.293991,479392892,65346,223,-28.10391528736,-40.31596217847,53.81904821017,2,1,18 +2025-03-11T12:41:30.309616,479392892,65346,223,-28.33480312174,-40.519688834055,54.22223916607,2,1,18 +2025-03-11T12:41:30.325241,479392892,65346,223,-28.55626696288,-40.74188347101,54.611627170765,2,1,18 +2025-03-11T12:41:30.340866,479392892,65346,223,-28.76359481416,-40.968674720895,54.98714982325,2,1,18 +2025-03-11T12:41:30.356491,479392892,65346,223,-28.9614986722,-41.181586449375,55.353360927595,2,1,18 +2025-03-11T12:41:30.372116,479392892,65346,223,-29.16411452686,-41.36677989987,55.74257348827,2,1,18 +2025-03-11T12:41:30.387741,479392892,65346,223,-29.38086637138,-41.56123995291,56.145707021155,2,1,18 +2025-03-11T12:41:30.403366,479392892,65346,223,-29.57877022942,-41.760288465915,56.525726054695,2,1,18 +2025-03-11T12:41:30.418991,479392892,65346,223,-29.77667408746,-41.973200194395,56.88269479291,2,1,18 +2025-03-11T12:41:30.434616,479392892,65346,223,-29.97928994212,-42.190741147665,57.262794767455,2,1,18 +2025-03-11T12:41:30.450241,479392892,65346,223,-30.17248180354,-42.399023651355,57.638222916925,2,1,18 +2025-03-11T12:41:30.465866,479392892,65346,223,-30.3750976582,-42.5934592455,57.97201836082,2,1,18 +2025-03-11T12:41:30.481491,479392892,65346,223,-30.58242550948,-42.783281920785,58.32428677798,2,1,18 +2025-03-11T12:41:30.497116,479392892,65346,223,-30.78032936752,-42.977709361965,58.69504490539,2,1,18 +2025-03-11T12:41:30.512741,479392892,65346,223,-30.97823322556,-43.181378946795,59.051976563605,2,1,18 +2025-03-11T12:41:30.528366,479392892,65346,223,-31.17142508698,-43.38504037866,59.408901440815,2,1,18 +2025-03-11T12:41:30.543991,479392892,65346,223,-31.35990495178,-43.584072585735,59.751937447825,2,1,18 +2025-03-11T12:41:30.559616,479392892,65346,223,-31.5530968132,-43.773870802125,60.09494315584,2,1,18 +2025-03-11T12:41:30.575241,479392892,65346,223,-31.75100067124,-43.95443502783,60.442539747925,2,1,18 +2025-03-11T12:41:30.590866,479392892,65346,223,-31.92063254956,-44.144192479395,60.776269184785,2,1,18 +2025-03-11T12:41:30.606491,479392892,65346,223,-32.09026442788,-44.329328859135,61.109980081645,2,1,18 +2025-03-11T12:41:30.622116,479392892,65346,223,-32.27874429268,-44.50987677891,61.452941928655,2,1,18 +2025-03-11T12:41:30.637741,479392892,65346,223,-32.4719361541,-44.681190708,61.77738874441,2,1,18 +2025-03-11T12:41:30.653366,479392892,65346,223,-32.67926400538,-44.84790802416,62.106458546245,2,1,18 +2025-03-11T12:41:30.668991,479392892,65346,223,-32.85831987694,-45.01457642253,62.42624529592,2,1,18 +2025-03-11T12:41:30.684616,479392892,65346,223,-33.0138157654,-45.190446199725,62.741414037505,2,1,18 +2025-03-11T12:41:30.700241,479392892,65346,223,-33.1787356471,-45.370953354675,63.061236064165,2,1,18 +2025-03-11T12:41:30.715866,479392892,65346,223,-33.35779151866,-45.565348183995,63.39037641997,2,1,18 +2025-03-11T12:41:30.731491,479392892,65346,223,-33.52271140036,-45.736613195295,63.7009190005,2,1,18 +2025-03-11T12:41:30.747116,479392892,65346,223,-33.71119126516,-45.90791897142,63.99763193686,2,1,18 +2025-03-11T12:41:30.762741,479392892,65346,223,-33.89024713672,-46.069966297965,64.3220213296,2,1,18 +2025-03-11T12:41:30.778366,479392892,65346,223,-34.05516701842,-46.23661023744,64.623303004,2,1,18 +2025-03-11T12:41:30.793991,479392892,65346,223,-34.22008690012,-46.403254176915,64.9245846784,2,1,18 +2025-03-11T12:41:30.809616,479392892,65346,223,-34.38500678182,-46.56989811639,65.21662398667,2,1,18 +2025-03-11T12:41:30.825241,479392892,65346,223,-34.55463866014,-46.73655020883,65.517912442075,2,1,18 +2025-03-11T12:41:30.840866,479392892,65346,223,-34.71484654522,-46.88470170804,65.823734358535,2,1,18 +2025-03-11T12:41:30.856491,479392892,65346,223,-34.86091844044,-47.060555179305,66.115783622785,2,1,18 +2025-03-11T12:41:30.872116,479392892,65346,223,-35.00227833904,-47.20405299483,66.3984539599,2,1,18 +2025-03-11T12:41:30.887741,479392892,65346,223,-35.14835023426,-47.361422178795,66.685807881085,2,1,18 +2025-03-11T12:41:30.903366,479392892,65346,223,-35.30855811934,-47.518815821655,66.963939779155,2,1,18 +2025-03-11T12:41:30.918991,479392892,65346,223,-35.4640540078,-47.671580239725,67.24204635622,2,1,18 +2025-03-11T12:41:30.934616,479392892,65346,223,-35.61012590302,-47.815086208215,67.52472347434,2,1,18 +2025-03-11T12:41:30.950241,479392892,65346,223,-35.76562179148,-47.97247169811,67.793606225275,2,1,18 +2025-03-11T12:41:30.965866,479392892,65346,223,-35.90698169008,-48.11134844181,68.05777329013,2,1,18 +2025-03-11T12:41:30.981491,479392892,65346,223,-36.04834158868,-48.25022518551,68.31731917192,2,1,18 +2025-03-11T12:41:30.997116,479392892,65346,223,-36.20854947376,-48.39837668472,68.590792806925,2,1,18 +2025-03-11T12:41:31.012741,479392892,65346,223,-36.35462136898,-48.537261581385,68.84110310359,2,1,18 +2025-03-11T12:41:31.028366,479392892,65346,223,-36.48655727434,-48.68074309098,69.114517512565,2,1,18 +2025-03-11T12:41:31.043991,479392892,65346,223,-36.6184931797,-48.81960352875,69.364807466215,2,1,18 +2025-03-11T12:41:31.059616,479392892,65346,223,-36.76927707154,-48.96773872203,69.60129807469,2,1,18 +2025-03-11T12:41:31.075241,479392892,65346,223,-36.91063697014,-49.111236537555,69.828514215025,2,1,18 +2025-03-11T12:41:31.090866,479392892,65346,223,-37.05199686874,-49.25473435308,70.06497272149,2,1,18 +2025-03-11T12:41:31.106491,479392892,65346,223,-37.18864477072,-49.38898187199,70.315250916145,2,1,18 +2025-03-11T12:41:31.122116,479392892,65346,223,-37.32058067608,-49.50935802246,70.56084552673,2,1,18 +2025-03-11T12:41:31.137741,479392892,65346,223,-37.44780458482,-49.629726019965,70.80643335631,2,1,18 +2025-03-11T12:41:31.153366,479392892,65346,223,-37.5608925037,-49.76393277405,71.02895054755,2,1,18 +2025-03-11T12:41:31.168991,479392892,65346,223,-37.68340441582,-49.87505047494,71.2513886008,2,1,18 +2025-03-11T12:41:31.184616,479392892,65346,223,-37.80120433132,-49.98153895104,71.446074234655,2,1,18 +2025-03-11T12:41:31.200241,479392892,65346,223,-37.9378522333,-50.1250286136,71.654798861725,2,1,18 +2025-03-11T12:41:31.215866,479392892,65346,223,-38.06036414542,-50.250009529965,71.86342898578,2,1,18 +2025-03-11T12:41:31.231491,479392892,65346,223,-38.17816406092,-50.374982293365,72.076673511895,2,1,18 +2025-03-11T12:41:31.247116,479392892,65346,223,-38.2912519798,-50.495325831975,72.299135083135,2,1,18 +2025-03-11T12:41:31.262741,479392892,65346,223,-38.39962790206,-50.592555858495,72.526118356435,2,1,18 +2025-03-11T12:41:31.278366,479392892,65346,223,-38.49857983108,-50.69439065091,72.72075832627,2,1,18 +2025-03-11T12:41:31.293991,479392892,65346,223,-38.60224375672,-50.800854668115,72.93390834937,2,1,18 +2025-03-11T12:41:31.309616,479392892,65346,223,-38.7153316756,-50.9165771349,73.12862428222,2,1,18 +2025-03-11T12:41:31.325241,479392892,65346,223,-38.82841959448,-51.01843638621,73.32328459507,2,1,18 +2025-03-11T12:41:31.340866,479392892,65346,223,-38.9273715235,-51.12489225045,73.48559482345,2,1,18 +2025-03-11T12:41:31.356491,479392892,65346,223,-39.0216114559,-51.240582105375,73.65255653389,2,1,18 +2025-03-11T12:41:31.372116,479392892,65346,223,-39.13469937478,-51.342441356685,73.842595663675,2,1,18 +2025-03-11T12:41:31.387741,479392892,65346,223,-39.22893930718,-51.444267996135,74.046471218635,2,1,18 +2025-03-11T12:41:31.403366,479392892,65346,223,-39.32317923958,-51.536852491935,74.22720377827,2,1,18 +2025-03-11T12:41:31.418991,479392892,65346,223,-39.41270717536,-51.62942883477,74.394066007705,2,1,18 +2025-03-11T12:41:31.434616,479392892,65346,223,-39.51165910438,-51.72664255536,74.565581522215,2,1,18 +2025-03-11T12:41:31.450241,479392892,65346,223,-39.60589903678,-51.82846919481,74.75559352798,2,1,18 +2025-03-11T12:41:31.465866,479392892,65346,223,-39.70013896918,-51.916432618785,74.917822815355,2,1,18 +2025-03-11T12:41:31.481491,479392892,65346,223,-39.78966690496,-51.995145746145,75.070765875595,2,1,18 +2025-03-11T12:41:31.497116,479392892,65346,223,-39.8697708475,-52.083084711225,75.21911127076,2,1,18 +2025-03-11T12:41:31.512741,479392892,65346,223,-39.95458678666,-52.166410757445,75.362823723865,2,1,18 +2025-03-11T12:41:31.528366,479392892,65346,223,-40.04411472244,-52.25898710028,75.51120122104,2,1,18 +2025-03-11T12:41:31.543991,479392892,65346,223,-40.1289306616,-52.3423131465,75.66877722334,2,1,18 +2025-03-11T12:41:31.559616,479392892,65346,223,-40.1996106109,-52.425614733825,75.817090516495,2,1,18 +2025-03-11T12:41:31.575241,479392892,65346,223,-40.27971455344,-52.49969048343,75.951516742465,2,1,18 +2025-03-11T12:41:31.590866,479392892,65346,223,-40.35981849598,-52.573766233035,76.095185334565,2,1,18 +2025-03-11T12:41:31.606491,479392892,65346,223,-40.42107445204,-52.643188298955,76.21570234732,2,1,18 +2025-03-11T12:41:31.622116,479392892,65346,223,-40.50117839458,-52.71726404856,76.33164384103,2,1,18 +2025-03-11T12:41:31.637741,479392892,65346,223,-40.5765703405,-52.78208950155,76.456783839865,2,1,18 +2025-03-11T12:41:31.653366,479392892,65346,223,-40.64253829318,-52.85614079226,76.586568539755,2,1,18 +2025-03-11T12:41:31.668991,479392892,65346,223,-40.70379424924,-52.93480500183,76.69788026638,2,1,18 +2025-03-11T12:41:31.684616,479392892,65346,223,-40.7650502053,-52.98574278045,76.809080753005,2,1,18 +2025-03-11T12:41:31.700241,479392892,65346,223,-40.84044215122,-53.03208394614,76.929525408775,2,1,18 +2025-03-11T12:41:31.715866,479392892,65346,223,-40.89227411404,-53.087626490655,77.03148850726,2,1,18 +2025-03-11T12:41:31.731491,479392892,65346,223,-40.9535300701,-53.138564269275,77.11958307856,2,1,18 +2025-03-11T12:41:31.747116,479392892,65346,223,-41.01478602616,-53.189502047895,77.19843528373,2,1,18 +2025-03-11T12:41:31.762741,479392892,65346,223,-41.06661798898,-53.24504459241,77.31426193141,2,1,18 +2025-03-11T12:41:31.778366,479392892,65346,223,-41.12787394504,-53.309845586505,77.41165448884,2,1,18 +2025-03-11T12:41:31.793991,479392892,65346,223,-41.17970590786,-53.351524915545,77.504319601195,2,1,18 +2025-03-11T12:41:31.809616,479392892,65346,223,-41.2126898842,-53.383929489075,77.592299326465,2,1,18 +2025-03-11T12:41:31.825241,479392892,65346,223,-41.26923384364,-53.43485911473,77.67114475063,2,1,18 +2025-03-11T12:41:31.840866,479392892,65346,223,-41.32106580646,-53.481159515595,77.754586036855,2,1,18 +2025-03-11T12:41:31.856491,479392892,65346,223,-41.34933778618,-53.53204022346,77.819527225795,2,1,18 +2025-03-11T12:41:31.872116,479392892,65346,223,-41.38703375914,-53.56907402178,77.893668722875,2,1,18 +2025-03-11T12:41:31.887741,479392892,65346,223,-41.4247297321,-53.61534996375,77.977089666085,2,1,18 +2025-03-11T12:41:31.903366,479392892,65346,223,-41.45771370844,-53.652375609105,78.02349728377,2,1,18 +2025-03-11T12:41:31.918991,479392892,65346,223,-41.4954096814,-53.680167263775,78.074495785525,2,1,18 +2025-03-11T12:41:31.934616,479392892,65346,223,-41.52368166112,-53.69407939704,78.1346674714,2,1,18 +2025-03-11T12:41:31.950241,479392892,65346,223,-41.54724164422,-53.72646766464,78.208770085465,2,1,18 +2025-03-11T12:41:31.965866,479392892,65346,223,-41.58493761718,-53.75425931931,78.27825331948,2,1,18 +2025-03-11T12:41:31.981491,479392892,65346,223,-41.6132095969,-53.7912768117,78.329275339225,2,1,18 +2025-03-11T12:41:31.997116,479392892,65346,223,-41.61792159352,-53.819011395615,78.38484755701,2,1,18 +2025-03-11T12:41:32.012741,479392892,65346,223,-41.63205758338,-53.832899069985,78.40802943535,2,1,18 +2025-03-11T12:41:32.028366,479392892,65346,223,-41.66975355634,-53.832964293705,78.431189598715,2,1,18 +2025-03-11T12:41:32.043991,479392892,65346,223,-41.68860154282,-53.851481192865,78.468260347255,2,1,18 +2025-03-11T12:41:32.059616,479392892,65346,223,-41.7074495293,-53.87461916385,78.50072845273,2,1,18 +2025-03-11T12:41:32.075241,479392892,65346,223,-41.73572150902,-53.90239451259,78.533228660215,2,1,18 +2025-03-11T12:41:32.090866,479392892,65346,223,-41.74985749888,-53.91628218696,78.54254698936,2,1,18 +2025-03-11T12:41:32.106491,479392892,65346,223,-41.74985749888,-53.930145402435,78.56108734162,2,1,18 +2025-03-11T12:41:32.122116,479392892,65346,223,-41.74985749888,-53.920903258785,78.57953499388,2,1,18 +2025-03-11T12:41:32.137741,479392892,65346,223,-41.7545694955,-53.9301535554,78.60268477021,2,1,18 +2025-03-11T12:41:32.153366,479392892,65346,223,-41.76399348874,-53.944033076805,78.598132769155,2,1,18 +2025-03-11T12:41:32.168991,479392892,65346,223,-41.76399348874,-53.953275220455,78.59354866609,2,1,18 +2025-03-11T12:41:32.184616,479392892,65346,223,-41.76399348874,-53.953275220455,78.598169849155,2,1,18 +2025-03-11T12:41:32.200241,479392892,65346,223,-41.7545694955,-53.95787998635,78.579690094885,2,1,18 +2025-03-11T12:41:32.215866,479392892,65346,223,-41.76399348874,-53.94865414863,78.5658030277,2,1,18 +2025-03-11T12:41:32.231491,479392892,65346,223,-41.76399348874,-53.934790933155,78.551883858505,2,1,18 +2025-03-11T12:41:32.247116,479392892,65346,223,-41.7545694955,-53.925532483575,78.54721203343,2,1,18 +2025-03-11T12:41:32.262741,479392892,65346,223,-41.73572150902,-53.92087879989,78.52868163715,2,1,18 +2025-03-11T12:41:32.278366,479392892,65346,223,-41.71687352254,-53.92084618803,78.50092741474,2,1,18 +2025-03-11T12:41:32.293991,479392892,65346,223,-41.7074495293,-53.897724522975,78.486957603535,2,1,18 +2025-03-11T12:41:32.309616,479392892,65346,223,-41.70273753268,-53.86998993906,78.472976033335,2,1,18 +2025-03-11T12:41:32.325241,479392892,65346,223,-41.6838895462,-53.8514730399,78.44976883399,2,1,18 +2025-03-11T12:41:32.340866,479392892,65346,223,-41.66975355634,-53.842206437355,78.41736312952,2,1,18 +2025-03-11T12:41:32.356491,479392892,65346,223,-41.63676958,-53.819044007475,78.371011131835,2,1,18 +2025-03-11T12:41:32.372116,479392892,65346,223,-41.6132095969,-53.786655739875,78.320014433095,2,1,18 +2025-03-11T12:41:32.387741,479392892,65346,223,-41.58493761718,-53.749638247485,78.264371230285,2,1,18 +2025-03-11T12:41:32.403366,479392892,65346,223,-41.56137763408,-53.735734267185,78.222691057675,2,1,18 +2025-03-11T12:41:32.418991,479392892,65346,223,-41.53781765098,-53.703345999585,78.171694358935,2,1,18 +2025-03-11T12:41:32.434616,479392892,65346,223,-41.48598568816,-53.68477202967,78.10684904497,2,1,18 +2025-03-11T12:41:32.450241,479392892,65346,223,-41.46713770168,-53.65701298686,78.046635301105,2,1,18 +2025-03-11T12:41:32.465866,479392892,65346,223,-41.43415372534,-53.610745197855,77.97246350503,2,1,18 +2025-03-11T12:41:32.481491,479392892,65346,223,-41.38703375914,-53.555210806305,77.893613102875,2,1,18 +2025-03-11T12:41:32.497116,479392892,65346,223,-41.34933778618,-53.51355593616,77.837937798055,2,1,18 +2025-03-11T12:41:32.512741,479392892,65346,223,-41.31164181322,-53.48576428149,77.77769693017,2,1,18 +2025-03-11T12:41:32.528366,479392892,65346,223,-41.27394584026,-53.444109411345,77.69429452696,2,1,18 +2025-03-11T12:41:32.543991,479392892,65346,223,-41.24096186392,-53.39784162234,77.58777444943,2,1,18 +2025-03-11T12:41:32.559616,479392892,65346,223,-41.20797788758,-53.351573833335,77.504360287225,2,1,18 +2025-03-11T12:41:32.575241,479392892,65346,223,-41.165569918,-53.309910810225,77.425572286075,2,1,18 +2025-03-11T12:41:32.590866,479392892,65346,223,-41.11373795518,-53.249747193885,77.33283301372,2,1,18 +2025-03-11T12:41:32.606491,479392892,65346,223,-41.03834600926,-53.184921740895,77.24004129634,2,1,18 +2025-03-11T12:41:32.622116,479392892,65346,223,-40.98180204982,-53.12474997159,77.142674059915,2,1,18 +2025-03-11T12:41:32.637741,479392892,65346,223,-40.93468208362,-53.083078795515,77.02690981324,2,1,18 +2025-03-11T12:41:32.653366,479392892,65346,223,-40.88756211742,-53.027544403965,76.929574678825,2,1,18 +2025-03-11T12:41:32.668991,479392892,65346,223,-40.82159416474,-52.962735256905,76.827554157325,2,1,18 +2025-03-11T12:41:32.684616,479392892,65346,223,-40.76976220192,-52.902571640565,76.71633015271,2,1,18 +2025-03-11T12:41:32.700241,479392892,65346,223,-40.70850624586,-52.83777064647,76.60045286302,2,1,18 +2025-03-11T12:41:32.715866,479392892,65346,223,-40.64253829318,-52.768340427585,76.48917143539,2,1,18 +2025-03-11T12:41:32.731491,479392892,65346,223,-40.56714634726,-52.70813604642,76.354807610425,2,1,18 +2025-03-11T12:41:32.747116,479392892,65346,223,-40.50117839458,-52.64332689936,76.215817624405,2,1,18 +2025-03-11T12:41:32.762741,479392892,65346,223,-40.41636245542,-52.564621924965,76.09985080969,2,1,18 +2025-03-11T12:41:32.778366,479392892,65346,223,-40.33154651626,-52.490538022395,75.974660168845,2,1,18 +2025-03-11T12:41:32.793991,479392892,65346,223,-40.25615457034,-52.40260721028,75.835563920815,2,1,18 +2025-03-11T12:41:32.809616,479392892,65346,223,-40.17133863118,-52.32852330771,75.69188854771,2,1,18 +2025-03-11T12:41:32.825241,479392892,65346,223,-40.10065868188,-52.25908493586,75.53900969149,2,1,18 +2025-03-11T12:41:32.840866,479392892,65346,223,-40.02997873258,-52.18964656401,75.372267286075,2,1,18 +2025-03-11T12:41:32.856491,479392892,65346,223,-39.94987479004,-52.097086527105,75.219282167845,2,1,18 +2025-03-11T12:41:32.872116,479392892,65346,223,-39.87448284412,-52.013776786815,75.070962093685,2,1,18 +2025-03-11T12:41:32.887741,479392892,65346,223,-39.78024291172,-51.92581336284,74.913353989375,2,1,18 +2025-03-11T12:41:32.903366,479392892,65346,223,-39.69542697256,-51.828624101145,74.76034355014,2,1,18 +2025-03-11T12:41:32.918991,479392892,65346,223,-39.62474702326,-51.73608037017,74.58888726166,2,1,18 +2025-03-11T12:41:32.934616,479392892,65346,223,-39.516371101,-51.643471415475,74.4358614574,2,1,18 +2025-03-11T12:41:32.950241,479392892,65346,223,-39.40799517874,-51.56010460443,74.26438800088,2,1,18 +2025-03-11T12:41:32.965866,479392892,65346,223,-39.31846724296,-51.48139147707,74.07447547612,2,1,18 +2025-03-11T12:41:32.981491,479392892,65346,223,-39.22422731056,-51.365701622145,73.87054430116,2,1,18 +2025-03-11T12:41:32.997116,479392892,65346,223,-39.12527538154,-51.25462468608,73.69897316665,2,1,18 +2025-03-11T12:41:33.012741,479392892,65346,223,-39.0216114559,-51.157402812525,73.52282968807,2,1,18 +2025-03-11T12:41:33.028366,479392892,65346,223,-38.92265952688,-51.05556802011,73.328189718235,2,1,18 +2025-03-11T12:41:33.043991,479392892,65346,223,-38.82370759786,-50.953733227695,73.128928565335,2,1,18 +2025-03-11T12:41:33.059616,479392892,65346,223,-38.71061967898,-50.84725290456,72.94811326168,2,1,18 +2025-03-11T12:41:33.075241,479392892,65346,223,-38.60224375672,-50.736159662565,72.725695551445,2,1,18 +2025-03-11T12:41:33.090866,479392892,65346,223,-38.49857983108,-50.615832429885,72.52635345754,2,1,18 +2025-03-11T12:41:33.106491,479392892,65346,223,-38.39020390882,-50.50473918789,72.331662845695,2,1,18 +2025-03-11T12:41:33.122116,479392892,65346,223,-38.26298000008,-50.37975011856,72.11840475757,2,1,18 +2025-03-11T12:41:33.137741,479392892,65346,223,-38.12162010148,-50.25011551851,71.891244237235,2,1,18 +2025-03-11T12:41:33.153366,479392892,65346,223,-38.0085321826,-50.134393051725,71.67342238906,2,1,18 +2025-03-11T12:41:33.168991,479392892,65346,223,-37.8907322671,-50.009420288325,71.450935496815,2,1,18 +2025-03-11T12:41:33.184616,479392892,65346,223,-37.78235634484,-49.875221687205,71.23766745271,2,1,18 +2025-03-11T12:41:33.200241,479392892,65346,223,-37.66455642934,-49.750248923805,71.015180560465,2,1,18 +2025-03-11T12:41:33.215866,479392892,65346,223,-37.53262052398,-49.639114916985,70.78810776214,2,1,18 +2025-03-11T12:41:33.231491,479392892,65346,223,-37.40068461862,-49.518738766515,70.551755517685,2,1,18 +2025-03-11T12:41:33.247116,479392892,65346,223,-37.26874871326,-49.38449940057,70.31534765323,2,1,18 +2025-03-11T12:41:33.262741,479392892,65346,223,-37.13210081128,-49.25949402531,70.074348904705,2,1,18 +2025-03-11T12:41:33.278366,479392892,65346,223,-36.99074091268,-49.12061728161,69.83790893824,2,1,18 +2025-03-11T12:41:33.293991,479392892,65346,223,-36.88236499042,-48.99566082414,69.606193241875,2,1,18 +2025-03-11T12:41:33.309616,479392892,65346,223,-36.75042908506,-48.86604253002,69.337455635965,2,1,18 +2025-03-11T12:41:33.325241,479392892,65346,223,-36.60435718984,-48.708673346055,69.073207630105,2,1,18 +2025-03-11T12:41:33.340866,479392892,65346,223,-36.47242128448,-48.56519183646,68.813656770325,2,1,18 +2025-03-11T12:41:33.356491,479392892,65346,223,-36.33106138588,-48.42631509276,68.563353254665,2,1,18 +2025-03-11T12:41:33.372116,479392892,65346,223,-36.18970148728,-48.28743834906,68.285322640615,2,1,18 +2025-03-11T12:41:33.387741,479392892,65346,223,-36.04362959206,-48.157795596045,68.02580705782,2,1,18 +2025-03-11T12:41:33.403366,479392892,65346,223,-35.8881337036,-47.995789034325,67.76152694995,2,1,18 +2025-03-11T12:41:33.418991,479392892,65346,223,-35.75619779824,-47.83382323743,67.5111442963,2,1,18 +2025-03-11T12:41:33.434616,479392892,65346,223,-35.6054139064,-47.690309115975,67.23308158024,2,1,18 +2025-03-11T12:41:33.450241,479392892,65346,223,-35.45934201118,-47.556045291135,66.955062725185,2,1,18 +2025-03-11T12:41:33.465866,479392892,65346,223,-35.31798211258,-47.407926403785,66.67237384807,2,1,18 +2025-03-11T12:41:33.481491,479392892,65346,223,-35.14363823764,-47.245887230205,66.38958188392,2,1,18 +2025-03-11T12:41:33.497116,479392892,65346,223,-34.97400635932,-47.08385620959,66.116039066905,2,1,18 +2025-03-11T12:41:33.512741,479392892,65346,223,-34.8279344641,-46.9218659538,65.81018187346,2,1,18 +2025-03-11T12:41:33.528366,479392892,65346,223,-34.67243857564,-46.75985939208,65.522795850265,2,1,18 +2025-03-11T12:41:33.543991,479392892,65346,223,-34.4980947007,-46.60706236215,65.221556233855,2,1,18 +2025-03-11T12:41:33.559616,479392892,65346,223,-34.32375082576,-46.449644260395,64.929540443575,2,1,18 +2025-03-11T12:41:33.575241,479392892,65346,223,-34.17296693392,-46.27840370799,64.623639389125,2,1,18 +2025-03-11T12:41:33.590866,479392892,65346,223,-34.0033350556,-46.107130543725,64.32233239372,2,1,18 +2025-03-11T12:41:33.606491,479392892,65346,223,-33.8384151739,-45.92200231695,64.01173419319,2,1,18 +2025-03-11T12:41:33.622116,479392892,65346,223,-33.66407129896,-45.736857784245,63.70112243065,2,1,18 +2025-03-11T12:41:33.637741,479392892,65346,223,-33.49443942064,-45.56558461998,63.38595188605,2,1,18 +2025-03-11T12:41:33.653366,479392892,65346,223,-33.33894353218,-45.40357805826,63.080081130595,2,1,18 +2025-03-11T12:41:33.668991,479392892,65346,223,-33.15988766062,-45.232288588065,62.76951820705,2,1,18 +2025-03-11T12:41:33.684616,479392892,65346,223,-32.97140779582,-45.047119596465,62.4450225523,2,1,18 +2025-03-11T12:41:33.700241,479392892,65346,223,-32.79235192426,-44.871209054445,62.1020928073,2,1,18 +2025-03-11T12:41:33.715866,479392892,65346,223,-32.6132960527,-44.676814225125,61.77757363456,2,1,18 +2025-03-11T12:41:33.731491,479392892,65346,223,-32.43424018114,-44.491661539455,61.448470358755,2,1,18 +2025-03-11T12:41:33.747116,479392892,65346,223,-32.25518430958,-44.315750997435,61.096298247625,2,1,18 +2025-03-11T12:41:33.762741,479392892,65346,223,-32.06670444478,-44.139824149485,60.74873375755,2,1,18 +2025-03-11T12:41:33.778366,479392892,65346,223,-31.89707256646,-43.95930884157,60.40579903456,2,1,18 +2025-03-11T12:41:33.793991,479392892,65346,223,-31.7180166949,-43.7741561559,60.067453392625,2,1,18 +2025-03-11T12:41:33.809616,479392892,65346,223,-31.52482483348,-43.579736867685,59.729050327675,2,1,18 +2025-03-11T12:41:33.825241,479392892,65346,223,-31.33634496868,-43.38070466061,59.395256686795,2,1,18 +2025-03-11T12:41:33.840866,479392892,65346,223,-31.13372911402,-43.19089013829,59.07072214903,2,1,18 +2025-03-11T12:41:33.856491,479392892,65346,223,-30.95467324246,-42.991874237145,58.69997260564,2,1,18 +2025-03-11T12:41:33.872116,479392892,65346,223,-30.74734539118,-42.797430490035,58.324579733155,2,1,18 +2025-03-11T12:41:33.887741,479392892,65346,223,-30.54472953652,-42.60299489589,57.967678373935,2,1,18 +2025-03-11T12:41:33.903366,479392892,65346,223,-30.3515376751,-42.408575607675,57.62465412592,2,1,18 +2025-03-11T12:41:33.918991,479392892,65346,223,-30.14892182044,-42.200276798055,57.235348865245,2,1,18 +2025-03-11T12:41:33.934616,479392892,65346,223,-29.9510179624,-42.00122828505,56.85070864864,2,1,18 +2025-03-11T12:41:33.950241,479392892,65346,223,-29.74369011112,-41.792921322465,56.493744888415,2,1,18 +2025-03-11T12:41:33.965866,479392892,65346,223,-29.53636225984,-41.57537221623,56.11825931593,2,1,18 +2025-03-11T12:41:33.981491,479392892,65346,223,-29.33374640518,-41.390178765735,55.738289121385,2,1,18 +2025-03-11T12:41:33.997039,479392896,65341,224,-29.1264185539,-41.195735018625,55.376759798095,2,1,18 +2025-03-11T12:41:34.012664,479392896,65341,224,-28.92380269924,-40.98281513718,55.019784278875,2,1,18 +2025-03-11T12:41:34.028289,479392896,65341,224,-28.70705085472,-40.75138650954,54.630365975185,2,1,18 +2025-03-11T12:41:34.043914,479392896,65341,224,-28.50443500006,-40.529224484445,54.24100509451,2,1,18 +2025-03-11T12:41:34.059539,479392896,65341,224,-28.29239515216,-40.311667225245,53.860891557955,2,1,18 +2025-03-11T12:41:34.075164,479392896,65341,224,-28.08506730088,-40.107981334485,53.47621923934,2,1,18 +2025-03-11T12:41:34.090789,479392896,65341,224,-27.88245144622,-39.899682524865,53.086913978665,2,1,18 +2025-03-11T12:41:34.106414,479392896,65341,224,-27.66098760508,-39.700593247035,52.711482223165,2,1,18 +2025-03-11T12:41:34.122039,479392896,65341,224,-27.42067577746,-39.48760814187,52.31286180832,2,1,18 +2025-03-11T12:41:34.137664,479392896,65341,224,-27.20392393294,-39.242316298755,51.89566078624,2,1,18 +2025-03-11T12:41:34.153289,479392896,65341,224,-26.99659608166,-39.00628290522,51.492373955365,2,1,18 +2025-03-11T12:41:34.168914,479392896,65341,224,-26.78926823038,-38.797975942635,51.09844073062,2,1,18 +2025-03-11T12:41:34.184539,479392896,65341,224,-26.56780438924,-38.580402377505,50.6859653506,2,1,18 +2025-03-11T12:41:34.200164,479392896,65341,224,-26.33220455824,-38.36280435348,50.2688484445,2,1,18 +2025-03-11T12:41:34.215789,479392896,65341,224,-26.1107407171,-38.140609716525,49.85635452448,2,1,18 +2025-03-11T12:41:34.231414,479392896,65341,224,-25.88927687596,-37.904551864095,49.44380498446,2,1,18 +2025-03-11T12:41:34.247039,479392896,65341,224,-25.64896504834,-37.66384032798,49.017346231225,2,1,18 +2025-03-11T12:41:34.262664,479392896,65341,224,-25.40865322072,-37.432370935515,48.59092455799,2,1,18 +2025-03-11T12:41:34.278289,479392896,65341,224,-25.19661337282,-37.21019260449,48.173823016915,2,1,18 +2025-03-11T12:41:34.293914,479392896,65341,224,-24.97514953168,-36.987997967535,47.761329096895,2,1,18 +2025-03-11T12:41:34.309539,479392896,65341,224,-24.73012570744,-36.74265720663,47.353329754915,2,1,18 +2025-03-11T12:41:34.325164,479392896,65341,224,-24.49452587644,-36.51119596713,46.926914862685,2,1,18 +2025-03-11T12:41:34.340789,479392896,65341,224,-24.25892604544,-36.27049258398,46.472735792065,2,1,18 +2025-03-11T12:41:34.356414,479392896,65341,224,-24.01861421782,-36.01591783239,46.041600235765,2,1,18 +2025-03-11T12:41:34.372039,479392896,65341,224,-23.79243838006,-35.77523075517,45.61054064248,2,1,18 +2025-03-11T12:41:34.387664,479392896,65341,224,-23.55212655244,-35.534519219055,45.165597156985,2,1,18 +2025-03-11T12:41:34.403289,479392896,65341,224,-23.31652672144,-35.303057979555,44.720697532495,2,1,18 +2025-03-11T12:41:34.418914,479392896,65341,224,-23.06679090058,-35.07157228116,44.280398748055,2,1,18 +2025-03-11T12:41:34.434539,479392896,65341,224,-22.82647907296,-34.812376457745,43.849244651755,2,1,18 +2025-03-11T12:41:34.450164,479392896,65341,224,-22.5767432521,-34.567027543875,43.390405515055,2,1,18 +2025-03-11T12:41:34.465789,479392896,65341,224,-22.32229543462,-34.326291548865,42.945441686545,2,1,18 +2025-03-11T12:41:34.481414,479392896,65341,224,-22.08669560362,-34.08096709389,42.509728808185,2,1,18 +2025-03-11T12:41:34.497039,479392896,65341,224,-21.83695978276,-33.830997108195,42.050871131485,2,1,18 +2025-03-11T12:41:34.512664,479392896,65341,224,-21.58251196528,-33.581018969535,41.58276430765,2,1,18 +2025-03-11T12:41:34.528289,479392896,65341,224,-21.34220013766,-33.354170648895,41.156361174415,2,1,18 +2025-03-11T12:41:34.543914,479392896,65341,224,-21.11131230328,-33.09499113141,40.697493541735,2,1,18 +2025-03-11T12:41:34.559539,479392896,65341,224,-20.85215248918,-32.835762696135,40.238585223025,2,1,18 +2025-03-11T12:41:34.575164,479392896,65341,224,-20.5977046717,-32.58116348565,39.756596309995,2,1,18 +2025-03-11T12:41:34.590789,479392896,65341,224,-20.34325685422,-32.32194320334,39.283831223095,2,1,18 +2025-03-11T12:41:34.606414,479392896,65341,224,-20.09352103336,-32.062731073995,38.83880001559,2,1,18 +2025-03-11T12:41:34.622039,479392896,65341,224,-19.83907321588,-31.812752935335,38.38455674095,2,1,18 +2025-03-11T12:41:34.637664,479392896,65341,224,-19.57991340178,-31.57200878736,37.92572258224,2,1,18 +2025-03-11T12:41:34.653289,479392896,65341,224,-19.32075358768,-31.30815928026,37.44831099127,2,1,18 +2025-03-11T12:41:34.668914,479392896,65341,224,-19.0663057702,-31.035075782475,36.970869101305,2,1,18 +2025-03-11T12:41:34.684539,479392896,65341,224,-18.81185795272,-30.766613356515,36.479582202145,2,1,18 +2025-03-11T12:41:34.700164,479392896,65341,224,-18.53385015214,-30.49811016573,35.992882581025,2,1,18 +2025-03-11T12:41:34.715789,479392896,65341,224,-18.2652663448,-30.2342443527,35.524699794175,2,1,18 +2025-03-11T12:41:34.731414,479392896,65341,224,-18.00139453408,-29.97500776446,35.061163511395,2,1,18 +2025-03-11T12:41:34.747039,479392896,65341,224,-17.73281072674,-29.70189980778,34.583701278415,2,1,18 +2025-03-11T12:41:34.762664,479392896,65341,224,-17.47365091264,-29.45653458798,34.09250029825,2,1,18 +2025-03-11T12:41:34.778289,479392896,65341,224,-17.21920309516,-29.19731430567,33.624356394415,2,1,18 +2025-03-11T12:41:34.793914,479392896,65341,224,-16.95533128444,-28.94731986108,33.13775127631,2,1,18 +2025-03-11T12:41:34.809539,479392896,65341,224,-16.69145947372,-28.67884112919,32.641829632075,2,1,18 +2025-03-11T12:41:34.825164,479392896,65341,224,-16.41816366976,-28.39186180407,32.14582026583,2,1,18 +2025-03-11T12:41:34.840789,479392896,65341,224,-16.14957986242,-28.104890631915,31.65906004672,2,1,18 +2025-03-11T12:41:34.856414,479392896,65341,224,-15.87157206184,-27.822524225655,31.1723048056,2,1,18 +2025-03-11T12:41:34.872039,479392896,65341,224,-15.6029882545,-27.5540373408,30.662512831165,2,1,18 +2025-03-11T12:41:34.887664,479392896,65341,224,-15.3202684573,-27.280904925225,30.152681973715,2,1,18 +2025-03-11T12:41:34.903289,479392896,65341,224,-15.04697265334,-27.012409887405,29.6659891336,2,1,18 +2025-03-11T12:41:34.918914,479392896,65341,224,-14.78310084262,-26.734689011865,29.17465159243,2,1,18 +2025-03-11T12:41:34.934539,479392896,65341,224,-14.51451703528,-26.461581055185,28.655598711865,2,1,18 +2025-03-11T12:41:34.950164,479392896,65341,224,-14.2365092347,-26.1745935771,28.131855466225,2,1,18 +2025-03-11T12:41:34.965789,479392896,65341,224,-13.96321343074,-25.89685639563,27.649746729175,2,1,18 +2025-03-11T12:41:34.981414,479392896,65341,224,-13.68520563016,-25.63297427667,27.163065648055,2,1,18 +2025-03-11T12:41:34.997039,479392896,65341,224,-13.4119098262,-25.3367528079,26.653155652615,2,1,18 +2025-03-11T12:41:35.012664,479392896,65341,224,-13.12447803238,-25.068233311185,26.13409418803,2,1,18 +2025-03-11T12:41:35.028289,479392896,65341,224,-12.84175823518,-24.79510089561,25.619642147515,2,1,18 +2025-03-11T12:41:35.043914,479392896,65341,224,-12.57788642446,-24.531243235545,25.119117860215,2,1,18 +2025-03-11T12:41:35.059539,479392896,65341,224,-12.3045906205,-24.2581271259,24.618542930905,2,1,18 +2025-03-11T12:41:35.075164,479392896,65341,224,-12.0218708233,-23.9803736385,24.108693533455,2,1,18 +2025-03-11T12:41:35.090789,479392896,65341,224,-11.7391510261,-23.6841358638,23.589527609875,2,1,18 +2025-03-11T12:41:35.106414,479392896,65341,224,-11.46114322552,-23.387906242065,23.074989650365,2,1,18 +2025-03-11T12:41:35.122039,479392896,65341,224,-11.16899943508,-23.100894305085,22.54198369558,2,1,18 +2025-03-11T12:41:35.137664,479392896,65341,224,-10.87214364802,-22.809253143315,22.022815968985,2,1,18 +2025-03-11T12:41:35.153289,479392896,65341,224,-10.57999985758,-22.52686227816,21.503692103395,2,1,18 +2025-03-11T12:41:35.168914,479392896,65341,224,-10.29728006038,-22.23986664711,20.97069971062,2,1,18 +2025-03-11T12:41:35.184539,479392896,65341,224,-10.0192722598,-21.95750024085,20.451596188045,2,1,18 +2025-03-11T12:41:35.200164,479392896,65341,224,-9.7365524626,-21.6889888971,19.95564741979,2,1,18 +2025-03-11T12:41:35.215789,479392896,65341,224,-9.45854466202,-21.392759275365,19.42262472802,2,1,18 +2025-03-11T12:41:35.231414,479392896,65341,224,-9.1711128682,-21.101134419525,18.894228197305,2,1,18 +2025-03-11T12:41:35.247039,479392896,65341,224,-8.888393071,-20.8187598603,18.365875527595,2,1,18 +2025-03-11T12:41:35.262664,479392896,65341,224,-8.6056732738,-20.5225220856,17.84208842095,2,1,18 +2025-03-11T12:41:35.278289,479392896,65341,224,-8.31352948336,-20.240131220445,17.290616273905,2,1,18 +2025-03-11T12:41:35.293914,479392896,65341,224,-8.02138569292,-19.953119283465,16.77609505138,2,1,18 +2025-03-11T12:41:35.309539,479392896,65341,224,-7.73866589572,-19.67074472424,16.29395421232,2,1,18 +2025-03-11T12:41:35.325164,479392896,65341,224,-7.44652210528,-19.369869571785,15.7655138206,2,1,18 +2025-03-11T12:41:35.340789,479392896,65341,224,-7.14966631822,-19.078228410015,15.21399781255,2,1,18 +2025-03-11T12:41:35.356414,479392896,65341,224,-6.85752252778,-18.78659540121,14.680973317765,2,1,18 +2025-03-11T12:41:35.372039,479392896,65341,224,-6.5795147272,-18.499607923125,14.147987705995,2,1,18 +2025-03-11T12:41:35.387664,479392896,65341,224,-6.28265894014,-18.19410354588,13.624143176335,2,1,18 +2025-03-11T12:41:35.403289,479392896,65341,224,-5.9905151497,-17.911712680725,13.10039812768,2,1,18 +2025-03-11T12:41:35.418914,479392896,65341,224,-5.69837135926,-17.615458600095,12.567355092895,2,1,18 +2025-03-11T12:41:35.434539,479392896,65341,224,-5.39680357558,-17.30532499806,12.020379326905,2,1,18 +2025-03-11T12:41:35.450164,479392896,65341,224,-5.0952357919,-17.022917826975,11.46889361785,2,1,18 +2025-03-11T12:41:35.465789,479392896,65341,224,-4.79838000484,-16.722034521555,10.940446445125,2,1,18 +2025-03-11T12:41:35.481414,479392896,65341,224,-4.51566020764,-16.416554603205,10.40737989235,2,1,18 +2025-03-11T12:41:35.497039,479392896,65341,224,-4.23294041044,-16.120316828505,9.86972923651,2,1,18 +2025-03-11T12:41:35.512664,479392896,65341,224,-3.94079662,-15.8286838197,9.32284119253,2,1,18 +2025-03-11T12:41:35.528289,479392896,65341,224,-3.63922883632,-15.537034504965,8.77593958654,2,1,18 +2025-03-11T12:41:35.543914,479392896,65341,224,-3.34708504588,-15.250022567985,8.23831244869,2,1,18 +2025-03-11T12:41:35.559539,479392896,65341,224,-3.05022925882,-14.939897118915,7.719070562095,2,1,18 +2025-03-11T12:41:35.575164,479392896,65341,224,-2.74394947852,-14.638997507565,7.167503912035,2,1,18 +2025-03-11T12:41:35.590789,479392896,65341,224,-2.44709369146,-14.347356345795,6.62985145318,2,1,18 +2025-03-11T12:41:35.606414,479392896,65341,224,-2.15966189764,-14.064973633605,6.092249636335,2,1,18 +2025-03-11T12:41:35.622039,479392896,65341,224,-1.85809411396,-13.768703247045,5.55919303954,2,1,18 +2025-03-11T12:41:35.637664,479392896,65341,224,-1.56595032352,-13.46782809459,5.016889098625,2,1,18 +2025-03-11T12:41:35.653289,479392896,65341,224,-1.2549585466,-13.1715414021,4.460713024495,2,1,18 +2025-03-11T12:41:35.668914,479392896,65341,224,-0.95810275954,-12.87065809668,3.90453875338,2,1,18 +2025-03-11T12:41:35.684539,479392896,65341,224,-0.67538296234,-12.560557106505,3.371453660605,2,1,18 +2025-03-11T12:41:35.700164,479392896,65341,224,-0.38795116852,-12.259690107015,2.83377768376,2,1,18 +2025-03-11T12:41:35.715789,479392896,65341,224,-0.0863833848400001,-11.954177576805,2.27757809164,2,1,18 +2025-03-11T12:41:35.731414,479392896,65341,224,0.22460839208,-11.676375171615,1.71223381138,2,1,18 +2025-03-11T12:41:35.747039,479392896,65341,224,0.54031216562,-11.384701397985,1.16069067931,2,1,18 +2025-03-11T12:41:35.762664,479392896,65341,224,0.83245595606,-11.08382624553,0.61376555533,2,1,18 +2025-03-11T12:41:35.778289,479392896,65341,224,1.1245997465,-10.773708949425,0.0760457174799998,2,1,18 +2025-03-11T12:41:35.793914,479392896,65341,224,1.42616753018,-10.449712131915,-0.475606851575,2,1,18 +2025-03-11T12:41:35.809539,479392896,65341,224,1.72302331724,-10.13496561102,-1.02259437656,2,1,18 +2025-03-11T12:41:35.825164,479392896,65341,224,2.02459110092,-9.834074152635,-1.555669513355,2,1,18 +2025-03-11T12:41:35.840789,479392896,65341,224,2.31673489136,-9.54244114383,-2.09793637427,2,1,18 +2025-03-11T12:41:35.856414,479392896,65341,224,2.62301467166,-9.23229938883,-2.644918921265,2,1,18 +2025-03-11T12:41:35.872039,479392896,65341,224,2.9151584621,-8.931424236375,-3.201086411375,2,1,18 +2025-03-11T12:41:35.887664,479392896,65341,224,3.21672624578,-8.644395993465,-3.73410592817,2,1,18 +2025-03-11T12:41:35.903289,479392896,65341,224,3.50887003622,-8.348141912835,-4.267148962955,2,1,18 +2025-03-11T12:41:35.918914,479392896,65341,224,3.80101382666,-8.03802461673,-4.81873235,2,1,18 +2025-03-11T12:41:35.934539,479392896,65341,224,4.10258161034,-7.74175423017,-5.36565249599,2,1,18 +2025-03-11T12:41:35.950164,479392896,65341,224,4.40886139064,-7.436233546995,-5.940343601375,2,1,18 +2025-03-11T12:41:35.965789,479392896,65341,224,4.7057171777,-7.126108097925,-6.47807022023,2,1,18 +2025-03-11T12:41:35.981414,479392896,65341,224,5.00728496138,-6.829837711365,-7.011126817025,2,1,18 +2025-03-11T12:41:35.997039,479392896,65341,224,5.29942875182,-6.524341487085,-7.558070481005,2,1,18 +2025-03-11T12:41:36.012664,479392896,65341,224,5.61042052874,-6.237296938245,-8.104967109005,2,1,18 +2025-03-11T12:41:36.028289,479392896,65341,224,5.92141230566,-5.95487346123,-8.63798164781,2,1,18 +2025-03-11T12:41:36.043914,479392896,65341,224,6.21826809272,-5.640126940335,-9.18034798973,2,1,18 +2025-03-11T12:41:36.059539,479392896,65341,224,6.51041188316,-5.33925178788,-9.73651547984,2,1,18 +2025-03-11T12:41:36.075164,479392896,65341,224,6.81197966684,-5.03373925767,-10.288093888895,2,1,18 +2025-03-11T12:41:36.090789,479392896,65341,224,7.1088354539,-4.71437166495,-10.82585758775,2,1,18 +2025-03-11T12:41:36.106414,479392896,65341,224,7.40097924434,-4.41811758432,-11.377385354795,2,1,18 +2025-03-11T12:41:36.122039,479392896,65341,224,7.70254702802,-4.13108934141,-11.91964723772,2,1,18 +2025-03-11T12:41:36.137664,479392896,65341,224,7.99940281508,-3.85793246694,-12.457225536575,2,1,18 +2025-03-11T12:41:36.153289,479392896,65341,224,8.30097059876,-3.55241993673,-12.994940396435,2,1,18 +2025-03-11T12:41:36.168914,479392896,65341,224,8.60253838244,-3.24690740652,-13.54651880549,2,1,18 +2025-03-11T12:41:36.184539,479392896,65341,224,8.8993941695,-2.95526624475,-14.111898362735,2,1,18 +2025-03-11T12:41:36.200164,479392896,65341,224,9.20096195318,-2.654374786365,-14.668079414855,2,1,18 +2025-03-11T12:41:36.215789,479392896,65341,224,9.50724173348,-2.344233031365,-15.20581959572,2,1,18 +2025-03-11T12:41:36.231414,479392896,65341,224,9.80409752054,-2.05721294142,-15.743453514575,2,1,18 +2025-03-11T12:41:36.247039,479392896,65341,224,10.09624131098,-1.774822076265,-16.29492566162,2,1,18 +2025-03-11T12:41:36.262664,479392896,65341,224,10.39309709804,-1.473938770845,-16.823372834345,2,1,18 +2025-03-11T12:41:36.278289,479392896,65341,224,10.6899528851,-1.1684343936,-17.3610809132,2,1,18 +2025-03-11T12:41:36.293914,479392896,65341,224,10.98209667554,-0.858317097495,-17.894179567985,2,1,18 +2025-03-11T12:41:36.309539,479392896,65341,224,11.27424046598,-0.56668408869,-18.41796169664,2,1,18 +2025-03-11T12:41:36.325164,479392896,65341,224,11.55224826656,-0.288938754255,-18.96015259454,2,1,18 +2025-03-11T12:41:36.340789,479392896,65341,224,11.844392057,0.0073153263750001,-19.49781681239,2,1,18 +2025-03-11T12:41:36.356414,479392896,65341,224,12.1506718373,0.312836009550001,-20.03091727019,2,1,18 +2025-03-11T12:41:36.372039,479392896,65341,224,12.45223962098,0.595243180635,-20.57778179618,2,1,18 +2025-03-11T12:41:36.387664,479392896,65341,224,12.7396714148,0.900731251950001,-21.124718679155,2,1,18 +2025-03-11T12:41:36.403289,479392896,65341,224,13.03181520524,1.201606404405,-21.653159070875,2,1,18 +2025-03-11T12:41:36.418914,479392896,65341,224,13.3051110092,1.49320680135,-22.17691407551,2,1,18 +2025-03-11T12:41:36.434539,479392896,65341,224,13.5878308064,1.7802024324,-22.71452765135,2,1,18 +2025-03-11T12:41:36.450164,479392896,65341,224,13.87997459684,2.08569865668,-23.2522289492,2,1,18 +2025-03-11T12:41:36.465789,479392896,65341,224,14.16740639066,2.391186727995,-23.771438733785,2,1,18 +2025-03-11T12:41:36.481414,479392896,65341,224,14.46426217772,2.673585746115,-24.30905411264,2,1,18 +2025-03-11T12:41:36.497039,479392896,65341,224,14.76111796478,2.955984764235,-24.84204830843,2,1,18 +2025-03-11T12:41:36.512664,479392896,65341,224,15.05797375184,3.25224699783,-25.36585575809,2,1,18 +2025-03-11T12:41:36.528289,479392896,65341,224,15.35011754228,3.553122150285,-25.88505378368,2,1,18 +2025-03-11T12:41:36.543914,479392896,65341,224,15.6375493361,3.835504862475,-26.422655600525,2,1,18 +2025-03-11T12:41:36.559539,479392896,65341,224,15.91555713668,4.127113412385,-26.9417962031,2,1,18 +2025-03-11T12:41:36.575164,479392896,65341,224,16.19827693388,4.42797225891,-27.46098066668,2,1,18 +2025-03-11T12:41:36.590789,479392896,65341,224,16.49513272094,4.714992348855,-27.998614585535,2,1,18 +2025-03-11T12:41:36.606414,479392896,65341,224,16.80612449786,4.99741582587,-28.527007941275,2,1,18 +2025-03-11T12:41:36.622039,479392896,65341,224,17.0982682883,5.28442776285,-29.0415291638,2,1,18 +2025-03-11T12:41:36.637664,479392896,65341,224,17.37156409226,5.566786016145,-29.574489454565,2,1,18 +2025-03-11T12:41:36.653289,479392896,65341,224,17.64957189284,5.85377349423,-30.10285388327,2,1,18 +2025-03-11T12:41:36.668914,479392896,65341,224,17.93700368666,6.13615620642,-30.621970967855,2,1,18 +2025-03-11T12:41:36.684539,479392896,65341,224,18.21972348386,6.41390969382,-31.1456839145,2,1,18 +2025-03-11T12:41:36.700164,479392896,65341,224,18.4883072912,6.7055019378,-31.660189772,2,1,18 +2025-03-11T12:41:36.715789,479392896,65341,224,18.76631509178,6.992489415885,-32.179311834575,2,1,18 +2025-03-11T12:41:36.731414,479392896,65341,224,19.06317087884,7.274888434005,-32.684578931975,2,1,18 +2025-03-11T12:41:36.747039,479392896,65341,224,19.35531466928,7.53879501186,-33.203628637565,2,1,18 +2025-03-11T12:41:36.762664,479392896,65341,224,19.64745845972,7.821185877015,-33.71813132009,2,1,18 +2025-03-11T12:41:36.778289,479392896,65341,224,19.93017825692,8.117423651715,-34.22805487754,2,1,18 +2025-03-11T12:41:36.793914,479392896,65341,224,20.20347406088,8.40902404866,-34.72870396685,2,1,18 +2025-03-11T12:41:36.809539,479392896,65341,224,20.47676986484,8.691382301955,-35.233937159225,2,1,18 +2025-03-11T12:41:36.825164,479392896,65341,224,20.7500656688,8.95525626795,-35.74833855773,2,1,18 +2025-03-11T12:41:36.840789,479392896,65341,224,21.02807346938,9.205275171435,-36.26269111724,2,1,18 +2025-03-11T12:41:36.856414,479392896,65341,224,21.30608126996,9.48302050587,-36.763291367555,2,1,18 +2025-03-11T12:41:36.872039,479392896,65341,224,21.58880106716,9.765395065095,-37.273159305005,2,1,18 +2025-03-11T12:41:36.887664,479392896,65341,224,21.87152086436,10.061632839795,-37.773840496325,2,1,18 +2025-03-11T12:41:36.903289,479392896,65341,224,22.14481666832,10.32550680579,-38.2789995287,2,1,18 +2025-03-11T12:41:36.918914,479392896,65341,224,22.41811247228,10.607865059085,-38.774990354945,2,1,18 +2025-03-11T12:41:36.934539,479392896,65341,224,22.68669627962,10.87635194394,-39.270918780185,2,1,18 +2025-03-11T12:41:36.950164,479392896,65341,224,22.96941607682,11.140242215865,-39.771470191505,2,1,18 +2025-03-11T12:41:36.965789,479392896,65341,224,23.21443990106,11.417930479545,-40.281265340915,2,1,18 +2025-03-11T12:41:36.981414,479392896,65341,224,23.47831171178,11.704893498735,-40.781882328215,2,1,18 +2025-03-11T12:41:36.997039,479392896,65341,224,23.77045550222,11.982663292065,-41.23166990783,2,1,18 +2025-03-11T12:41:37.012664,479392896,65341,224,24.05317529942,12.241932492165,-41.718339229955,2,1,18 +2025-03-11T12:41:37.028289,479392896,65341,224,24.31233511352,12.51040307109,-42.21887527625,2,1,18 +2025-03-11T12:41:37.043914,479392896,65341,224,24.57620692424,12.783502874805,-42.71019427742,2,1,18 +2025-03-11T12:41:37.059539,479392896,65341,224,24.84479073158,13.07047404696,-43.201575679595,2,1,18 +2025-03-11T12:41:37.075164,479392896,65341,224,25.12751052878,13.32974324706,-43.66976026946,2,1,18 +2025-03-11T12:41:37.090789,479392896,65341,224,25.38195834626,13.593584601195,-44.17027099475,2,1,18 +2025-03-11T12:41:37.106414,479392896,65341,224,25.63169416712,13.85279673054,-44.65689284984,2,1,18 +2025-03-11T12:41:37.122039,479392896,65341,224,25.89556597784,14.107412246955,-45.125031775685,2,1,18 +2025-03-11T12:41:37.137664,479392896,65341,224,26.1453017987,14.362003304475,-45.58852917545,2,1,18 +2025-03-11T12:41:37.153289,479392896,65341,224,26.39503761956,14.62121543382,-46.05666629828,2,1,18 +2025-03-11T12:41:37.168914,479392896,65341,224,26.65890943028,14.88969416571,-46.534103210255,2,1,18 +2025-03-11T12:41:37.184539,479392896,65341,224,26.91806924438,15.158164744635,-47.002290975095,2,1,18 +2025-03-11T12:41:37.200164,479392896,65341,224,27.16780506524,15.39889258668,-47.470353937925,2,1,18 +2025-03-11T12:41:37.215789,479392896,65341,224,27.43167687596,15.662750246745,-47.93852994377,2,1,18 +2025-03-11T12:41:37.231414,479392896,65341,224,27.69083669006,15.926599753845,-48.402077985545,2,1,18 +2025-03-11T12:41:37.247039,479392896,65341,224,27.94528450754,16.18119896433,-48.856339800185,2,1,18 +2025-03-11T12:41:37.262664,479392896,65341,224,28.19973232502,16.44041924664,-49.329104887085,2,1,18 +2025-03-11T12:41:37.278289,479392896,65341,224,28.44946814588,16.69501030416,-49.79260228685,2,1,18 +2025-03-11T12:41:37.293914,479392896,65341,224,28.7133399566,16.931141533275,-50.2468035035,2,1,18 +2025-03-11T12:41:37.309539,479392896,65341,224,28.9489397876,17.171844916425,-50.71022494025,2,1,18 +2025-03-11T12:41:37.325164,479392896,65341,224,29.20338760508,17.42644412691,-51.17372912102,2,1,18 +2025-03-11T12:41:37.340789,479392896,65341,224,29.46254741918,17.676430418535,-51.60487326134,2,1,18 +2025-03-11T12:41:37.356414,479392896,65341,224,29.7028592468,17.91714195465,-52.059059112965,2,1,18 +2025-03-11T12:41:37.372039,479392896,65341,224,29.94788307104,18.171724859205,-52.504064999465,2,1,18 +2025-03-11T12:41:37.387664,479392896,65341,224,30.19290689528,18.421686691935,-52.9444311629,2,1,18 +2025-03-11T12:41:37.403289,479392896,65341,224,30.44264271614,18.667035605805,-53.389406750405,2,1,18 +2025-03-11T12:41:37.418914,479392896,65341,224,30.68295454376,18.91698928557,-53.84362968203,2,1,18 +2025-03-11T12:41:37.434539,479392896,65341,224,30.91384237814,19.16230558758,-54.288578145515,2,1,18 +2025-03-11T12:41:37.450164,479392896,65341,224,31.14473021252,19.37989545864,-54.733415369,2,1,18 +2025-03-11T12:41:37.465789,479392896,65341,224,31.39917803,19.616010381825,-55.16911829138,2,1,18 +2025-03-11T12:41:37.481414,479392896,65341,224,31.64420185424,19.847487927255,-55.59554674562,2,1,18 +2025-03-11T12:41:37.497039,479392896,65341,224,31.87980168524,20.088191310405,-56.04972581624,2,1,18 +2025-03-11T12:41:37.512664,479392896,65341,224,32.09655352976,20.32424100987,-56.45764739219,2,1,18 +2025-03-11T12:41:37.528289,479392896,65341,224,32.33215336076,20.569565464845,-56.86563317216,2,1,18 +2025-03-11T12:41:37.543914,479392896,65341,224,32.56775319176,20.810268847995,-57.287463961325,2,1,18 +2025-03-11T12:41:37.559539,479392896,65341,224,32.7892170329,21.0417056286,-57.69537377828,2,1,18 +2025-03-11T12:41:37.575164,479392896,65341,224,33.01539287066,21.259287346695,-58.126340671565,2,1,18 +2025-03-11T12:41:37.590789,479392896,65341,224,33.2368567118,21.49996627095,-58.53428756852,2,1,18 +2025-03-11T12:41:37.606414,479392896,65341,224,33.46303254956,21.74065334817,-58.96072597874,2,1,18 +2025-03-11T12:41:37.622039,479392896,65341,224,33.68920838732,21.967477209915,-59.373245219765,2,1,18 +2025-03-11T12:41:37.637664,479392896,65341,224,33.91538422508,22.18505892801,-59.799590929985,2,1,18 +2025-03-11T12:41:37.653289,479392896,65341,224,34.1321360696,22.407245412,-60.216699252065,2,1,18 +2025-03-11T12:41:37.668914,479392896,65341,224,34.34888791412,22.61094760869,-60.61986986495,2,1,18 +2025-03-11T12:41:37.684539,479392896,65341,224,34.5797757485,22.8377796234,-61.018532337785,2,1,18 +2025-03-11T12:41:37.700164,479392896,65341,224,34.80595158626,23.07846670062,-61.41262246655,2,1,18 +2025-03-11T12:41:37.715789,479392896,65341,224,35.01799143416,23.29602395982,-61.801978369235,2,1,18 +2025-03-11T12:41:37.731414,479392896,65341,224,35.23003128206,23.499718003545,-62.19127865192,2,1,18 +2025-03-11T12:41:37.747039,479392896,65341,224,35.4514951232,23.71267049685,-62.580629576615,2,1,18 +2025-03-11T12:41:37.762664,479392896,65341,224,35.67295896434,23.916380846505,-62.956079872115,2,1,18 +2025-03-11T12:41:37.778289,479392896,65341,224,35.88971080886,24.13394625867,-63.35006373887,2,1,18 +2025-03-11T12:41:37.793914,479392896,65341,224,36.10646265338,24.351511670835,-63.744047605625,2,1,18 +2025-03-11T12:41:37.809539,479392896,65341,224,36.3232144979,24.5505927957,-64.13795731238,2,1,18 +2025-03-11T12:41:37.825164,479392896,65341,224,36.53054234918,24.758899758285,-64.522648170995,2,1,18 +2025-03-11T12:41:37.840789,479392896,65341,224,36.72844620722,24.97643255859,-64.9073625476,2,1,18 +2025-03-11T12:41:37.856414,479392896,65341,224,36.9357740585,25.18011844935,-65.27817131702,2,1,18 +2025-03-11T12:41:37.872039,479392896,65341,224,37.13838991316,25.393038330795,-65.64438920237,2,1,18 +2025-03-11T12:41:37.887664,479392896,65341,224,37.33158177458,25.58745761901,-66.005898182645,2,1,18 +2025-03-11T12:41:37.903289,479392896,65341,224,37.52948563262,25.80036934749,-66.38135165312,2,1,18 +2025-03-11T12:41:37.918914,479392896,65341,224,37.72738949066,25.999417860495,-66.73364358827,2,1,18 +2025-03-11T12:41:37.934539,479392896,65341,224,37.9252933487,26.18922422985,-67.07665607729,2,1,18 +2025-03-11T12:41:37.950164,479392896,65341,224,38.13262119998,26.379046905135,-67.42892449445,2,1,18 +2025-03-11T12:41:37.965789,479392896,65341,224,38.33994905126,26.573490652245,-67.79969618387,2,1,18 +2025-03-11T12:41:37.981414,479392896,65341,224,38.53314091268,26.781773155935,-68.15663960108,2,1,18 +2025-03-11T12:41:37.996978,479392900,65337,225,38.71219678424,26.966925841605,-68.49960642608,2,1,18 +2025-03-11T12:41:38.012603,479392900,65337,225,38.90538864566,27.147481914345,-68.842575054095,2,1,18 +2025-03-11T12:41:38.028228,479392900,65337,225,39.09858050708,27.337280130735,-69.171717212915,2,1,18 +2025-03-11T12:41:38.043853,479392900,65337,225,39.28234837526,27.53168311302,-69.52397026505,2,1,18 +2025-03-11T12:41:38.059478,479392900,65337,225,39.46611624344,27.726086095305,-69.876223317185,2,1,18 +2025-03-11T12:41:38.075103,479392900,65337,225,39.64988411162,27.906625862115,-70.20993601706,2,1,18 +2025-03-11T12:41:38.090728,479392900,65337,225,39.8572119629,28.082585321925,-70.54366408196,2,1,18 +2025-03-11T12:41:38.106353,479392900,65337,225,40.0456918277,28.27237538535,-70.87742064284,2,1,18 +2025-03-11T12:41:38.121978,479392900,65337,225,40.21532370602,28.44826962144,-71.2110944597,2,1,18 +2025-03-11T12:41:38.137603,479392900,65337,225,40.3755315911,28.6241475516,-71.53551234842,2,1,18 +2025-03-11T12:41:38.153228,479392900,65337,225,40.55458746266,28.804679165445,-71.85073353503,2,1,18 +2025-03-11T12:41:38.168853,479392900,65337,225,40.73364333422,28.971347563815,-72.17514146777,2,1,18 +2025-03-11T12:41:38.184478,479392900,65337,225,40.90798720916,29.16573424017,-72.47654794418,2,1,18 +2025-03-11T12:41:38.200103,479392900,65337,225,41.0823310841,29.3370155574,-72.773240537525,2,1,18 +2025-03-11T12:41:38.215728,479392900,65337,225,41.25196296242,29.499046578015,-73.097616368255,2,1,18 +2025-03-11T12:41:38.231353,479392900,65337,225,41.42630683736,29.64722253612,-73.43118572612,2,1,18 +2025-03-11T12:41:38.246978,479392900,65337,225,41.59122671906,29.81848754742,-73.727864757455,2,1,18 +2025-03-11T12:41:38.262603,479392900,65337,225,41.74672260752,29.98973625279,-74.03377259291,2,1,18 +2025-03-11T12:41:38.278228,479392900,65337,225,41.9069304926,30.142508823825,-74.334991866305,2,1,18 +2025-03-11T12:41:38.293853,479392900,65337,225,42.0718503743,30.3091527633,-74.617788808445,2,1,18 +2025-03-11T12:41:38.309478,479392900,65337,225,42.24619424924,30.48043408053,-74.91448140179,2,1,18 +2025-03-11T12:41:38.325103,479392900,65337,225,42.41111413094,30.65169909183,-75.20653925006,2,1,18 +2025-03-11T12:41:38.340728,479392900,65337,225,42.57603401264,30.81372195948,-75.484696469135,2,1,18 +2025-03-11T12:41:38.356353,479392900,65337,225,42.72210590786,30.95722792797,-75.767373587255,2,1,18 +2025-03-11T12:41:38.371978,479392900,65337,225,42.86346580646,31.109967887145,-76.054702187435,2,1,18 +2025-03-11T12:41:38.387603,479392900,65337,225,43.0142496983,31.26272415225,-76.32818080043,2,1,18 +2025-03-11T12:41:38.403228,479392900,65337,225,43.16503359014,31.406238273705,-76.60624351649,2,1,18 +2025-03-11T12:41:38.418853,479392900,65337,225,43.31110548536,31.549744242195,-76.875057085415,2,1,18 +2025-03-11T12:41:38.434478,479392900,65337,225,43.47602536706,31.702524966195,-77.16241959062,2,1,18 +2025-03-11T12:41:38.450103,479392900,65337,225,43.62209726228,31.846030934685,-77.421990793415,2,1,18 +2025-03-11T12:41:38.465728,479392900,65337,225,43.75874516426,31.989520597245,-77.676927251135,2,1,18 +2025-03-11T12:41:38.481353,479392900,65337,225,43.89539306624,32.13763133163,-77.91801869966,2,1,18 +2025-03-11T12:41:38.496978,479392900,65337,225,44.04146496146,32.28113730012,-78.177589902455,2,1,18 +2025-03-11T12:41:38.512603,479392900,65337,225,44.1922488533,32.433893565225,-78.418720233995,2,1,18 +2025-03-11T12:41:38.528228,479392900,65337,225,44.32418475866,32.563511859345,-78.650488375385,2,1,18 +2025-03-11T12:41:38.543853,479392900,65337,225,44.45612066402,32.693130153465,-78.909983615165,2,1,18 +2025-03-11T12:41:38.559478,479392900,65337,225,44.57863257614,32.80886892618,-79.16478848987,2,1,18 +2025-03-11T12:41:38.575103,479392900,65337,225,44.69643249164,32.938462761405,-79.378051555985,2,1,18 +2025-03-11T12:41:38.590728,479392900,65337,225,44.83308039362,33.07733135214,-79.60986355838,2,1,18 +2025-03-11T12:41:38.606353,479392900,65337,225,44.96501629898,33.202328574435,-79.86009789203,2,1,18 +2025-03-11T12:41:38.621978,479392900,65337,225,45.09224020772,33.327317643765,-80.08721952935,2,1,18 +2025-03-11T12:41:38.637603,479392900,65337,225,45.21475211984,33.46154070378,-80.3097502826,2,1,18 +2025-03-11T12:41:38.653228,479392900,65337,225,45.35140002182,33.60503036634,-80.541580824995,2,1,18 +2025-03-11T12:41:38.668853,479392900,65337,225,45.46919993732,33.71151884244,-80.7824782895,2,1,18 +2025-03-11T12:41:38.684478,479392900,65337,225,45.5822878562,33.8041359501,-81.00482862074,2,1,18 +2025-03-11T12:41:38.700103,479392900,65337,225,45.69537577508,33.93372163236,-81.204221356655,2,1,18 +2025-03-11T12:41:38.715728,479392900,65337,225,45.79903970072,34.05404886504,-81.40356345056,2,1,18 +2025-03-11T12:41:38.731353,479392900,65337,225,45.92155161284,34.151303350455,-81.61670351768,2,1,18 +2025-03-11T12:41:38.746978,479392900,65337,225,46.03935152834,34.257791826555,-81.811389151535,2,1,18 +2025-03-11T12:41:38.762603,479392900,65337,225,46.1477274506,34.373506140375,-82.019961852575,2,1,18 +2025-03-11T12:41:38.778228,479392900,65337,225,46.25139137624,34.493833373055,-82.21930394648,2,1,18 +2025-03-11T12:41:38.793853,479392900,65337,225,46.3597672985,34.60492661505,-82.395509826065,2,1,18 +2025-03-11T12:41:38.809478,479392900,65337,225,46.4540072309,34.69751111085,-82.59472711796,2,1,18 +2025-03-11T12:41:38.825103,479392900,65337,225,46.55767115654,34.794732984405,-82.784734145735,2,1,18 +2025-03-11T12:41:38.840728,479392900,65337,225,46.65662308556,34.87808348952,-82.956194040245,2,1,18 +2025-03-11T12:41:38.856353,479392900,65337,225,46.76971100444,34.975321669005,-83.1369722639,2,1,18 +2025-03-11T12:41:38.871978,479392900,65337,225,46.86395093684,35.086390452105,-83.308536617405,2,1,18 +2025-03-11T12:41:38.887603,479392900,65337,225,46.95347887262,35.192830010415,-83.470833283775,2,1,18 +2025-03-11T12:41:38.903228,479392900,65337,225,47.04771880502,35.29003557804,-83.646963200345,2,1,18 +2025-03-11T12:41:38.918853,479392900,65337,225,47.1372467408,35.382611920875,-83.827688978975,2,1,18 +2025-03-11T12:41:38.934478,479392900,65337,225,47.2314866732,35.447469985725,-83.98982556635,2,1,18 +2025-03-11T12:41:38.950103,479392900,65337,225,47.3021666225,35.5215294294,-84.147344145635,2,1,18 +2025-03-11T12:41:38.965728,479392900,65337,225,47.38227056504,35.61871053813,-84.31421135306,2,1,18 +2025-03-11T12:41:38.981353,479392900,65337,225,47.47651049744,35.725158249405,-84.476514800435,2,1,18 +2025-03-11T12:41:38.996978,479392900,65337,225,47.5613264366,35.799242151975,-84.606326624345,2,1,18 +2025-03-11T12:41:39.012603,479392900,65337,225,47.64143037914,35.877938973405,-84.73615020725,2,1,18 +2025-03-11T12:41:39.028228,479392900,65337,225,47.73567031154,35.95666025373,-84.879857682365,2,1,18 +2025-03-11T12:41:39.043853,479392900,65337,225,47.80163826422,36.035332616265,-85.009660922255,2,1,18 +2025-03-11T12:41:39.059478,479392900,65337,225,47.87703021014,36.109400212905,-85.139459184155,2,1,18 +2025-03-11T12:41:39.075103,479392900,65337,225,47.94771015944,36.19270180023,-85.273908928115,2,1,18 +2025-03-11T12:41:39.090728,479392900,65337,225,48.02310210536,36.25752725322,-85.412912476145,2,1,18 +2025-03-11T12:41:39.106353,479392900,65337,225,48.07493406818,36.322311941385,-85.54263975302,2,1,18 +2025-03-11T12:41:39.121978,479392900,65337,225,48.13619002424,36.391734007305,-85.65853558271,2,1,18 +2025-03-11T12:41:39.137603,479392900,65337,225,48.1974459803,36.4565350014,-85.79289760466,2,1,18 +2025-03-11T12:41:39.153228,479392900,65337,225,48.26341393298,36.52134414846,-85.899539309225,2,1,18 +2025-03-11T12:41:39.168853,479392900,65337,225,48.33409388228,36.586161448485,-85.98308187947,2,1,18 +2025-03-11T12:41:39.184478,479392900,65337,225,48.40006183496,36.632486308245,-86.11275533936,2,1,18 +2025-03-11T12:41:39.200103,479392900,65337,225,48.45189379778,36.67878670911,-86.214681357845,2,1,18 +2025-03-11T12:41:39.215728,479392900,65337,225,48.49430176736,36.72969187587,-86.30736998819,2,1,18 +2025-03-11T12:41:39.231353,479392900,65337,225,48.56026972004,36.78525887928,-86.40011106356,2,1,18 +2025-03-11T12:41:39.246978,479392900,65337,225,48.61681367948,36.83156743311,-86.49280149692,2,1,18 +2025-03-11T12:41:39.262603,479392900,65337,225,48.66393364568,36.882480752835,-86.580875725205,2,1,18 +2025-03-11T12:41:39.278228,479392900,65337,225,48.70162961864,36.928756694805,-86.664296668415,2,1,18 +2025-03-11T12:41:39.293853,479392900,65337,225,48.75346158146,36.98429923932,-86.74777503464,2,1,18 +2025-03-11T12:41:39.309478,479392900,65337,225,48.80058154766,37.025970415395,-86.83119099986,2,1,18 +2025-03-11T12:41:39.325103,479392900,65337,225,48.83827752062,37.063004213715,-86.882226581615,2,1,18 +2025-03-11T12:41:39.340728,479392900,65337,225,48.87126149696,37.113893074545,-86.95641691769,2,1,18 +2025-03-11T12:41:39.356353,479392900,65337,225,48.91366946654,37.14169288218,-87.049012848035,2,1,18 +2025-03-11T12:41:39.371978,479392900,65337,225,48.96078943274,37.16950084278,-87.113888460995,2,1,18 +2025-03-11T12:41:39.387603,479392900,65337,225,49.00319740232,37.215784937715,-87.16958908682,2,1,18 +2025-03-11T12:41:39.403228,479392900,65337,225,49.03618137866,37.257431654895,-87.234499976765,2,1,18 +2025-03-11T12:41:39.418853,479392900,65337,225,49.06445335838,37.28058593181,-87.280845193445,2,1,18 +2025-03-11T12:41:39.434478,479392900,65337,225,49.08330134486,37.30834497462,-87.31333183892,2,1,18 +2025-03-11T12:41:39.450103,479392900,65337,225,49.11157332458,37.322257107885,-87.35039760947,2,1,18 +2025-03-11T12:41:39.465728,479392900,65337,225,49.1398453043,37.340790312975,-87.392103103085,2,1,18 +2025-03-11T12:41:39.481353,479392900,65337,225,49.1634052874,37.373178580575,-87.443099801825,2,1,18 +2025-03-11T12:41:39.496978,479392900,65337,225,49.17754127726,37.39168732677,-87.47092140323,2,1,18 +2025-03-11T12:41:39.512603,479392900,65337,225,49.19638926374,37.39171993863,-87.50791799177,2,1,18 +2025-03-11T12:41:39.528228,479392900,65337,225,49.20110126036,37.41483345072,-87.563471669555,2,1,18 +2025-03-11T12:41:39.543853,479392900,65337,225,49.22466124346,37.43797957467,-87.6005677391,2,1,18 +2025-03-11T12:41:39.559478,479392900,65337,225,49.24822122656,37.44264141132,-87.637589648645,2,1,18 +2025-03-11T12:41:39.575103,479392900,65337,225,49.25293322318,37.44727063611,-87.64685733578,2,1,18 +2025-03-11T12:41:39.590728,479392900,65337,225,49.2576452198,37.44265771725,-87.65146675985,2,1,18 +2025-03-11T12:41:39.606353,479392900,65337,225,49.2576452198,37.4518998609,-87.637640290655,2,1,18 +2025-03-11T12:41:39.621978,479392900,65337,225,49.25293322318,37.45651277976,-87.651515598845,2,1,18 +2025-03-11T12:41:39.637603,479392900,65337,225,49.2576452198,37.447278789075,-87.656106482915,2,1,18 +2025-03-11T12:41:39.653228,479392900,65337,225,49.27178120966,37.442682176145,-87.642244736735,2,1,18 +2025-03-11T12:41:39.668853,479392900,65337,225,49.26235721642,37.43804479839,-87.63759145166,2,1,18 +2025-03-11T12:41:39.684478,479392900,65337,225,49.23879723332,37.447246177215,-87.63297344357,2,1,18 +2025-03-11T12:41:39.700103,479392900,65337,225,49.2340852367,37.44723802425,-87.60986074724,2,1,18 +2025-03-11T12:41:39.715728,479392900,65337,225,49.22937324008,37.42412451216,-87.591276533975,2,1,18 +2025-03-11T12:41:39.731353,479392900,65337,225,49.22466124346,37.433358502845,-87.57282210071,2,1,18 +2025-03-11T12:41:39.746978,479392900,65337,225,49.22466124346,37.43797957467,-87.549734725385,2,1,18 +2025-03-11T12:41:39.762603,479392900,65337,225,49.20110126036,37.42407559437,-87.517296918905,2,1,18 +2025-03-11T12:41:39.778228,479392900,65337,225,49.1869652705,37.3917036327,-87.4894196975,2,1,18 +2025-03-11T12:41:39.793853,479392900,65337,225,49.1869652705,37.36397720175,-87.45233899298,2,1,18 +2025-03-11T12:41:39.809478,479392900,65337,225,49.15869329078,37.340822924835,-87.41523614243,2,1,18 +2025-03-11T12:41:39.825103,479392900,65337,225,49.13513330768,37.32229787271,-87.38277979595,2,1,18 +2025-03-11T12:41:39.840728,479392900,65337,225,49.11157332458,37.29915174876,-87.345683726405,2,1,18 +2025-03-11T12:41:39.856353,479392900,65337,225,49.0927253381,37.266771634125,-87.299314991735,2,1,18 +2025-03-11T12:41:39.871978,479392900,65337,225,49.06445335838,37.24361735721,-87.22986385973,2,1,18 +2025-03-11T12:41:39.887603,479392900,65337,225,49.03146938204,37.215833855505,-87.17887213898,2,1,18 +2025-03-11T12:41:39.903228,479392900,65337,225,49.00790939894,37.18806665973,-87.11865161411,2,1,18 +2025-03-11T12:41:39.918853,479392900,65337,225,48.97963741922,37.16029131099,-87.058424308235,2,1,18 +2025-03-11T12:41:39.934478,479392900,65337,225,48.94665344288,37.104781378335,-86.988836615225,2,1,18 +2025-03-11T12:41:39.950103,479392900,65337,225,48.9042454733,37.0769815707,-86.928588966335,2,1,18 +2025-03-11T12:41:39.965728,479392900,65337,225,48.86183750372,37.039939619415,-86.87292542051,2,1,18 +2025-03-11T12:41:39.981353,479392900,65337,225,48.83827752062,36.99368813634,-86.808009552575,2,1,18 +2025-03-11T12:41:39.996978,479392900,65337,225,48.79586955104,36.95202511323,-86.719979185295,2,1,18 +2025-03-11T12:41:40.012603,479392900,65337,225,48.7393255916,36.91495870305,-86.62270464887,2,1,18 +2025-03-11T12:41:40.028228,479392900,65337,225,48.6922056254,36.864045383325,-86.53925160365,2,1,18 +2025-03-11T12:41:40.043853,479392900,65337,225,48.6450856592,36.80388991995,-86.441897929235,2,1,18 +2025-03-11T12:41:40.059478,479392900,65337,225,48.59325369638,36.75296844726,-86.353816919945,2,1,18 +2025-03-11T12:41:40.075103,479392900,65337,225,48.5508457268,36.697442208675,-86.265730932665,2,1,18 +2025-03-11T12:41:40.090728,479392900,65337,225,48.49901376398,36.628036448685,-86.16371221418,2,1,18 +2025-03-11T12:41:40.106353,479392900,65337,225,48.4330458113,36.563227301625,-86.047828143485,2,1,18 +2025-03-11T12:41:40.121978,479392900,65337,225,48.36707785862,36.52152351369,-85.936657955855,2,1,18 +2025-03-11T12:41:40.137603,479392900,65337,225,48.30110990594,36.461335438455,-85.825413608225,2,1,18 +2025-03-11T12:41:40.153228,479392900,65337,225,48.23514195326,36.387284147745,-85.704871274465,2,1,18 +2025-03-11T12:41:40.168853,479392900,65337,225,48.16917400058,36.33633821616,-85.60752755603,2,1,18 +2025-03-11T12:41:40.184478,479392900,65337,225,48.11263004114,36.294650734155,-85.49637093041,2,1,18 +2025-03-11T12:41:40.200103,479392900,65337,225,48.05137408508,36.225228668235,-85.38047510072,2,1,18 +2025-03-11T12:41:40.215728,479392900,65337,225,47.97598213916,36.14653999977,-85.24141593269,2,1,18 +2025-03-11T12:41:40.231353,479392900,65337,225,47.90530218986,36.063238412445,-85.0977238226,2,1,18 +2025-03-11T12:41:40.246978,479392900,65337,225,47.82519824732,35.993783734665,-84.949452587435,2,1,18 +2025-03-11T12:41:40.262603,479392900,65337,225,47.74038230816,35.91507876027,-84.82424340659,2,1,18 +2025-03-11T12:41:40.278228,479392900,65337,225,47.655566369,35.836373785875,-84.68517067655,2,1,18 +2025-03-11T12:41:40.293853,479392900,65337,225,47.57075042984,35.762289883305,-84.52763175425,2,1,18 +2025-03-11T12:41:40.309478,479392900,65337,225,47.48593449068,35.67434276526,-84.36079484582,2,1,18 +2025-03-11T12:41:40.325103,479392900,65337,225,47.41054254476,35.586411953145,-84.1939714994,2,1,18 +2025-03-11T12:41:40.340728,479392900,65337,225,47.33986259546,35.507731437645,-84.02257083092,2,1,18 +2025-03-11T12:41:40.356353,479392900,65337,225,47.25975865292,35.419792472565,-83.87884661882,2,1,18 +2025-03-11T12:41:40.371978,479392900,65337,225,47.16551872052,35.31334476129,-83.72116435451,2,1,18 +2025-03-11T12:41:40.387603,479392900,65337,225,47.07127878812,35.216139193665,-83.558897987135,2,1,18 +2025-03-11T12:41:40.403228,479392900,65337,225,46.96290286586,35.137393454445,-83.41054898594,2,1,18 +2025-03-11T12:41:40.418853,479392900,65337,225,46.86395093684,35.03555866203,-83.234393748365,2,1,18 +2025-03-11T12:41:40.434478,479392900,65337,225,46.76499900782,34.942966013265,-83.053654407725,2,1,18 +2025-03-11T12:41:40.450103,479392900,65337,225,46.67075907542,34.850381517465,-82.87292184809,2,1,18 +2025-03-11T12:41:40.465728,479392900,65337,225,46.58123113964,34.743941959155,-82.678276900265,2,1,18 +2025-03-11T12:41:40.481353,479392900,65337,225,46.46814322076,34.632840564195,-82.492821873545,2,1,18 +2025-03-11T12:41:40.496978,479392900,65337,225,46.35034330526,34.54021530357,-82.312055408885,2,1,18 +2025-03-11T12:41:40.512603,479392900,65337,225,46.24667937962,34.42913021454,-82.108129211915,2,1,18 +2025-03-11T12:41:40.528228,479392900,65337,225,46.15715144384,34.318069584405,-81.899602174895,2,1,18 +2025-03-11T12:41:40.543853,479392900,65337,225,46.04877552158,34.202355270585,-81.700271839985,2,1,18 +2025-03-11T12:41:40.559478,479392900,65337,225,45.94982359256,34.077415119045,-81.500917987085,2,1,18 +2025-03-11T12:41:40.575103,479392900,65337,225,45.8414476703,33.961700805225,-81.31545120137,2,1,18 +2025-03-11T12:41:40.590728,479392900,65337,225,45.7236477548,33.845970185475,-81.09762257219,2,1,18 +2025-03-11T12:41:40.606353,479392900,65337,225,45.61998382916,33.734885096445,-80.89369637522,2,1,18 +2025-03-11T12:41:40.621978,479392900,65337,225,45.50218391366,33.609912333045,-80.68507303217,2,1,18 +2025-03-11T12:41:40.637603,479392900,65337,225,45.37496000492,33.484923263715,-80.46719376098,2,1,18 +2025-03-11T12:41:40.653228,479392900,65337,225,45.24302409956,33.364547113245,-80.24470506572,2,1,18 +2025-03-11T12:41:40.668853,479392900,65337,225,45.1110881942,33.23954989095,-80.02219783046,2,1,18 +2025-03-11T12:41:40.684478,479392900,65337,225,44.98857628208,33.11919004641,-79.785859148015,2,1,18 +2025-03-11T12:41:40.700103,479392900,65337,225,44.86606436996,32.99883020187,-79.544899282505,2,1,18 +2025-03-11T12:41:40.715728,479392900,65337,225,44.73884046122,32.86459898889,-79.299255832925,2,1,18 +2025-03-11T12:41:40.731353,479392900,65337,225,44.60219255924,32.725730398155,-79.06744383053,2,1,18 +2025-03-11T12:41:40.746978,479392900,65337,225,44.46083266064,32.60071686993,-78.821817117935,2,1,18 +2025-03-11T12:41:40.762603,479392900,65337,225,44.32418475866,32.471090422845,-78.58079982941,2,1,18 +2025-03-11T12:41:40.778228,479392900,65337,225,44.20167284654,32.332246291005,-78.32128107164,2,1,18 +2025-03-11T12:41:40.793853,479392900,65337,225,44.0508889547,32.1794900259,-78.07090837397,2,1,18 +2025-03-11T12:41:40.809478,479392900,65337,225,43.90481705948,32.040605129235,-77.811355711175,2,1,18 +2025-03-11T12:41:40.825103,479392900,65337,225,43.7681691575,31.897115466675,-77.556419253455,2,1,18 +2025-03-11T12:41:40.840728,479392900,65337,225,43.64094524876,31.74902103822,-77.28761426855,2,1,18 +2025-03-11T12:41:40.856353,479392900,65337,225,43.49487335354,31.600893997905,-77.02340334269,2,1,18 +2025-03-11T12:41:40.871978,479392900,65337,225,43.33937746508,31.466613867135,-76.754613291755,2,1,18 +2025-03-11T12:41:40.887603,479392900,65337,225,43.18859357324,31.309236530205,-76.476494955695,2,1,18 +2025-03-11T12:41:40.903228,479392900,65337,225,43.04723367464,31.14725442738,-76.207614007775,2,1,18 +2025-03-11T12:41:40.918853,479392900,65337,225,42.88702578956,30.98986078452,-75.910997377445,2,1,18 +2025-03-11T12:41:40.934478,479392900,65337,225,42.72681790448,30.83246714166,-75.623623113245,2,1,18 +2025-03-11T12:41:40.950103,479392900,65337,225,42.57132201602,30.67970272359,-75.34551653618,2,1,18 +2025-03-11T12:41:40.965728,479392900,65337,225,42.41582612756,30.52693830552,-75.058167592985,2,1,18 +2025-03-11T12:41:40.981353,479392900,65337,225,42.25090624586,30.369536509695,-74.76154418165,2,1,18 +2025-03-11T12:41:40.996978,479392900,65337,225,42.09069836078,30.202900723185,-74.469511654385,2,1,18 +2025-03-11T12:41:41.012603,479392900,65337,225,41.9304904757,30.036264936675,-74.172857944055,2,1,18 +2025-03-11T12:41:41.028228,479392900,65337,225,41.765570594,29.874242069025,-73.871594809655,2,1,18 +2025-03-11T12:41:41.043853,479392900,65337,225,41.59593871568,29.70296890476,-73.565666631185,2,1,18 +2025-03-11T12:41:41.059478,479392900,65337,225,41.42159484074,29.54092973118,-73.245905202515,2,1,18 +2025-03-11T12:41:41.075103,479392900,65337,225,41.25667495904,29.36966471988,-72.935362621985,2,1,18 +2025-03-11T12:41:41.090728,479392900,65337,225,41.0823310841,29.203004474475,-72.62944620251,2,1,18 +2025-03-11T12:41:41.106353,479392900,65337,225,40.91269920578,29.036352382035,-72.328157747105,2,1,18 +2025-03-11T12:41:41.121978,479392900,65337,225,40.74777932408,28.865087370735,-72.017615166575,2,1,18 +2025-03-11T12:41:41.137603,479392900,65337,225,40.57343544914,28.67994283803,-71.69313985484,2,1,18 +2025-03-11T12:41:41.153228,479392900,65337,225,40.3755315911,28.490136468675,-71.38709683034,2,1,18 +2025-03-11T12:41:41.168853,479392900,65337,225,40.19176372292,28.29573348639,-71.0487073274,2,1,18 +2025-03-11T12:41:41.184478,479392900,65337,225,40.02684384122,28.12446847509,-70.71968001461,2,1,18 +2025-03-11T12:41:41.200103,479392900,65337,225,39.8572119629,27.95781638265,-70.39528564388,2,1,18 +2025-03-11T12:41:41.215728,479392900,65337,225,39.6922920812,27.76806708405,-70.06618417109,2,1,18 +2025-03-11T12:41:41.231353,479392900,65337,225,39.49438822316,27.58288178652,-69.71394785594,2,1,18 +2025-03-11T12:41:41.246978,479392900,65337,225,39.2917723685,27.40230940785,-69.352480933655,2,1,18 +2025-03-11T12:41:41.262603,479392900,65337,225,39.11271649694,27.221777794005,-69.01415383172,2,1,18 +2025-03-11T12:41:41.278228,479392900,65337,225,38.938372622,27.032012189475,-68.680417613855,2,1,18 +2025-03-11T12:41:41.293853,479392900,65337,225,38.7498927572,26.8329799824,-68.33276042378,2,1,18 +2025-03-11T12:41:41.309478,479392900,65337,225,38.56612488902,26.64319807194,-67.96666236245,2,1,18 +2025-03-11T12:41:41.325103,479392900,65337,225,38.35408504112,26.448746171865,-67.61898980735,2,1,18 +2025-03-11T12:41:41.340728,479392900,65337,225,38.15146918646,26.25431057772,-67.27133081426,2,1,18 +2025-03-11T12:41:41.356353,479392900,65337,225,37.95827732504,26.050649145855,-66.909784753985,2,1,18 +2025-03-11T12:41:41.371978,479392900,65337,225,37.760373467,25.8423584892,-66.55283455577,2,1,18 +2025-03-11T12:41:41.387603,479392900,65337,225,37.55775761234,25.647922895055,-66.18669083042,2,1,18 +2025-03-11T12:41:41.403228,479392900,65337,225,37.35514175768,25.45348730091,-65.815925922005,2,1,18 +2025-03-11T12:41:41.418853,479392900,65337,225,37.15723789964,25.24057557243,-65.426608902335,2,1,18 +2025-03-11T12:41:41.434478,479392900,65337,225,36.96875803484,25.04616443718,-65.06048552,2,1,18 +2025-03-11T12:41:41.450103,479392900,65337,225,36.76143018356,24.856341761895,-64.69897473671,2,1,18 +2025-03-11T12:41:41.465728,479392900,65337,225,36.54939033566,24.64340557452,-64.32350092322,2,1,18 +2025-03-11T12:41:41.481353,479392900,65337,225,36.33263849114,24.43970337783,-63.938815042595,2,1,18 +2025-03-11T12:41:41.496978,479392900,65337,225,36.11588664662,24.231380109315,-63.549489438905,2,1,18 +2025-03-11T12:41:41.512603,479392900,65337,225,35.8991348021,24.0045725535,-63.141604942955,2,1,18 +2025-03-11T12:41:41.528228,479392900,65337,225,35.70123094406,23.77317653772,-62.75683494635,2,1,18 +2025-03-11T12:41:41.543853,479392900,65337,225,35.48447909954,23.55099005373,-62.372074905725,2,1,18 +2025-03-11T12:41:41.559478,479392900,65337,225,35.27243925164,23.33343279453,-61.968855453845,2,1,18 +2025-03-11T12:41:41.575103,479392900,65337,225,35.06511140036,23.12050476012,-61.5749036891,2,1,18 +2025-03-11T12:41:41.590728,479392900,65337,225,34.85778354908,22.921439941185,-61.181007544355,2,1,18 +2025-03-11T12:41:41.606353,479392900,65337,225,34.63631970794,22.70848744788,-60.787035436595,2,1,18 +2025-03-11T12:41:41.621978,479392900,65337,225,34.40543187356,22.477034361345,-60.374490874565,2,1,18 +2025-03-11T12:41:41.637603,479392900,65337,225,34.19339202566,22.259477102145,-59.980513788815,2,1,18 +2025-03-11T12:41:41.653228,479392900,65337,225,33.96250419128,22.023402943785,-59.59105660211,2,1,18 +2025-03-11T12:41:41.668853,479392900,65337,225,33.74104035014,21.78272401953,-59.183109705155,2,1,18 +2025-03-11T12:41:41.684478,479392900,65337,225,33.50072852252,21.56511784254,-58.76598601805,2,1,18 +2025-03-11T12:41:41.700103,479392900,65337,225,33.26984068814,21.33828582783,-58.35345999602,2,1,18 +2025-03-11T12:41:41.715728,479392900,65337,225,33.04366485038,21.102219822435,-57.93628249193,2,1,18 +2025-03-11T12:41:41.731353,479392900,65337,225,32.80335302276,20.866129358145,-57.509842278695,2,1,18 +2025-03-11T12:41:41.746978,479392900,65337,225,32.59131317486,20.64395102712,-57.069634822295,2,1,18 +2025-03-11T12:41:41.762603,479392900,65337,225,32.36984933372,20.412514246515,-56.657103822275,2,1,18 +2025-03-11T12:41:41.778228,479392900,65337,225,32.13896149934,20.18106115998,-56.22145334492,2,1,18 +2025-03-11T12:41:41.793853,479392900,65337,225,31.8939376751,19.935720399075,-55.790348087615,2,1,18 +2025-03-11T12:41:41.809478,479392900,65337,225,31.6583378441,19.704259159575,-55.354690829255,2,1,18 +2025-03-11T12:41:41.825103,479392900,65337,225,31.42745000972,19.468185001215,-54.93750654416,2,1,18 +2025-03-11T12:41:41.840728,479392900,65337,225,31.20127417196,19.227497923995,-54.497204584745,2,1,18 +2025-03-11T12:41:41.856353,479392900,65337,225,30.96096234434,18.991407459705,-54.056900822315,2,1,18 +2025-03-11T12:41:41.871978,479392900,65337,225,30.7159385201,18.741445626975,-53.61653465888,2,1,18 +2025-03-11T12:41:41.887603,479392900,65337,225,30.46620269924,18.505338856755,-53.180838517505,2,1,18 +2025-03-11T12:41:41.903228,479392900,65337,225,30.22589087162,18.25538517699,-52.73585795201,2,1,18 +2025-03-11T12:41:41.918853,479392900,65337,225,29.98086704738,18.000802272435,-52.28160969938,2,1,18 +2025-03-11T12:41:41.934478,479392900,65337,225,29.73113122652,17.75083228674,-51.83199438881,2,1,18 +2025-03-11T12:41:41.950103,479392900,65337,225,29.48610740228,17.51935474131,-51.37783883618,2,1,18 +2025-03-11T12:41:41.965728,479392900,65337,225,29.23637158142,17.27400582744,-50.92824206561,2,1,18 +2025-03-11T12:41:41.981353,479392900,65337,225,28.9960597538,17.014810004025,-50.47860323705,2,1,18 +2025-03-11T12:41:41.996917,479392904,65333,226,28.76517191942,16.76487263019,-50.01053031824,2,1,18 +2025-03-11T12:41:42.012542,479392904,65333,226,28.51072410194,16.528757707005,-49.54710029747,2,1,18 +2025-03-11T12:41:42.028167,479392904,65333,226,28.2421402946,16.2695129658,-49.083557233685,2,1,18 +2025-03-11T12:41:42.043792,479392904,65333,226,27.99711647036,16.01955113307,-48.629327521055,2,1,18 +2025-03-11T12:41:42.059417,479392904,65333,226,27.75209264612,15.76034715669,-48.156575996165,2,1,18 +2025-03-11T12:41:42.075042,479392904,65333,226,27.48350883878,15.491860271835,-47.68375348625,2,1,18 +2025-03-11T12:41:42.090667,479392904,65333,226,27.21492503144,15.246478746105,-47.2156448594,2,1,18 +2025-03-11T12:41:42.106292,479392904,65333,226,26.95105322072,14.978000014215,-46.76131386275,2,1,18 +2025-03-11T12:41:42.121917,479392904,65333,226,26.69189340662,14.714150507115,-46.279281088715,2,1,18 +2025-03-11T12:41:42.137542,479392904,65333,226,26.44215758576,14.450317305945,-45.79726187669,2,1,18 +2025-03-11T12:41:42.153167,479392904,65333,226,26.18770976828,14.191097023635,-45.34298152205,2,1,18 +2025-03-11T12:41:42.168792,479392904,65333,226,25.93797394742,13.93188489429,-44.851738483895,2,1,18 +2025-03-11T12:41:42.184417,479392904,65333,226,25.67881413332,13.672656459015,-44.365103066795,2,1,18 +2025-03-11T12:41:42.200042,479392904,65333,226,25.41023032598,13.390306358685,-43.859876655425,2,1,18 +2025-03-11T12:41:42.215667,479392904,65333,226,25.14164651864,13.126440545655,-43.382451502445,2,1,18 +2025-03-11T12:41:42.231292,479392904,65333,226,24.8730627113,12.86719580445,-42.895802523335,2,1,18 +2025-03-11T12:41:42.246917,479392904,65333,226,24.6139028972,12.607967369175,-42.418409472365,2,1,18 +2025-03-11T12:41:42.262542,479392904,65333,226,24.34531908986,12.325617268845,-41.95477370858,2,1,18 +2025-03-11T12:41:42.278167,479392904,65333,226,24.0720232859,12.075606518325,-41.4635338454,2,1,18 +2025-03-11T12:41:42.293792,479392904,65333,226,23.79401548532,11.820966543015,-40.981511027345,2,1,18 +2025-03-11T12:41:42.309417,479392904,65333,226,23.5301436746,11.534003523825,-40.47627285698,2,1,18 +2025-03-11T12:41:42.325042,479392904,65333,226,23.26627186388,11.256282648285,-39.961829400485,2,1,18 +2025-03-11T12:41:42.340667,479392904,65333,226,22.99297605992,10.978545466815,-39.479720663435,2,1,18 +2025-03-11T12:41:42.356292,479392904,65333,226,22.73381624582,10.70083274424,-38.97914753714,2,1,18 +2025-03-11T12:41:42.371917,479392904,65333,226,22.46523243848,10.432345859385,-38.4832191119,2,1,18 +2025-03-11T12:41:42.387542,479392904,65333,226,22.18251264128,10.154592371985,-37.987233263645,2,1,18 +2025-03-11T12:41:42.403167,479392904,65333,226,21.9045048407,9.872225965725,-37.491235656395,2,1,18 +2025-03-11T12:41:42.418792,479392904,65333,226,21.63120903674,9.603730927905,-36.99530045015,2,1,18 +2025-03-11T12:41:42.434417,479392904,65333,226,21.35791323278,9.325993746435,-36.490085797775,2,1,18 +2025-03-11T12:41:42.450042,479392904,65333,226,21.07519343558,9.038998115385,-35.970956954195,2,1,18 +2025-03-11T12:41:42.465667,479392904,65333,226,20.79247363838,8.76586569981,-35.470368462875,2,1,18 +2025-03-11T12:41:42.481292,479392904,65333,226,20.51917783442,8.50661280564,-34.960606787435,2,1,18 +2025-03-11T12:41:42.496917,479392904,65333,226,20.24588203046,8.22887562417,-34.45539213506,2,1,18 +2025-03-11T12:41:42.512542,479392904,65333,226,19.9725862265,7.94189629905,-33.94551921962,2,1,18 +2025-03-11T12:41:42.528167,479392904,65333,226,19.69457842592,7.664150964615,-33.44029778624,2,1,18 +2025-03-11T12:41:42.543792,479392904,65333,226,19.41185862872,7.367913189915,-32.91188949653,2,1,18 +2025-03-11T12:41:42.559417,479392904,65333,226,19.1244268349,7.0809094059,-32.39737505501,2,1,18 +2025-03-11T12:41:42.575042,479392904,65333,226,18.8181470546,6.8077362255,-31.87364674334,2,1,18 +2025-03-11T12:41:42.590667,479392904,65333,226,18.54013925402,6.539233034715,-31.363841206895,2,1,18 +2025-03-11T12:41:42.606292,479392904,65333,226,18.2762674433,6.2291646564,-30.8492679704,2,1,18 +2025-03-11T12:41:42.621917,479392904,65333,226,17.9935476461,5.92368473805,-30.325443783755,2,1,18 +2025-03-11T12:41:42.637542,479392904,65333,226,17.71553984552,5.636697259965,-29.810942904245,2,1,18 +2025-03-11T12:41:42.653167,479392904,65333,226,17.44224404156,5.37282329397,-29.28729913961,2,1,18 +2025-03-11T12:41:42.668792,479392904,65333,226,17.1453882545,5.0996664195,-28.777447939145,2,1,18 +2025-03-11T12:41:42.684417,479392904,65333,226,16.8626684573,4.8034286448,-28.249039649435,2,1,18 +2025-03-11T12:41:42.700042,479392904,65333,226,16.57523666348,4.52104593261,-27.72992256485,2,1,18 +2025-03-11T12:41:42.715667,479392904,65333,226,16.28309287304,4.238655067455,-27.196935150065,2,1,18 +2025-03-11T12:41:42.731292,479392904,65333,226,15.98152508936,3.933142537245,-26.68232620553,2,1,18 +2025-03-11T12:41:42.746917,479392904,65333,226,15.67995730568,3.636872150685,-26.1538907918,2,1,18 +2025-03-11T12:41:42.762542,479392904,65333,226,15.38781351524,3.35448128553,-25.61628219395,2,1,18 +2025-03-11T12:41:42.778167,479392904,65333,226,15.10509371804,3.06748565448,-25.092532167305,2,1,18 +2025-03-11T12:41:42.793792,479392904,65333,226,14.82237392084,2.775868951605,-24.56876360066,2,1,18 +2025-03-11T12:41:42.809417,479392904,65333,226,14.54907811688,2.47502641101,-24.008002051505,2,1,18 +2025-03-11T12:41:42.825042,479392904,65333,226,14.25693432644,2.17877233038,-23.451853101395,2,1,18 +2025-03-11T12:41:42.840667,479392904,65333,226,13.964790536,1.8732761061,-22.91877298661,2,1,18 +2025-03-11T12:41:42.856292,479392904,65333,226,13.66793474894,1.586256016155,-22.399623800015,2,1,18 +2025-03-11T12:41:42.871917,479392904,65333,226,13.36165496864,1.303840692105,-21.875858408345,2,1,18 +2025-03-11T12:41:42.887542,479392904,65333,226,13.06008718496,1.007570305545,-21.34280181155,2,1,18 +2025-03-11T12:41:42.903167,479392904,65333,226,12.77736738776,0.69746931537,-20.809716718775,2,1,18 +2025-03-11T12:41:42.918792,479392904,65333,226,12.48993559394,0.419707675005,-20.276754624995,2,1,18 +2025-03-11T12:41:42.934417,479392904,65333,226,12.19307980688,0.123445441410001,-19.73908362614,2,1,18 +2025-03-11T12:41:42.950042,479392904,65333,226,11.91036000968,-0.172792333289999,-19.2014329703,2,1,18 +2025-03-11T12:41:42.965667,479392904,65333,226,11.608792226,-0.473683791675,-18.6822213827,2,1,18 +2025-03-11T12:41:42.981292,479392904,65333,226,11.30722444232,-0.779196321885,-18.15374888897,2,1,18 +2025-03-11T12:41:42.996917,479392904,65333,226,11.00094466202,-1.070853789585,-17.61146168504,2,1,18 +2025-03-11T12:41:43.012542,479392904,65333,226,10.70408887496,-1.380979238655,-17.055250333925,2,1,18 +2025-03-11T12:41:43.028167,479392904,65333,226,10.40252109128,-1.67262855339,-16.508348727935,2,1,18 +2025-03-11T12:41:43.043792,479392904,65333,226,10.10566530422,-1.959648643335,-15.97071480908,2,1,18 +2025-03-11T12:41:43.059417,479392904,65333,226,9.8182335104,-2.269757786475,-15.4376229353,2,1,18 +2025-03-11T12:41:43.075042,479392904,65333,226,9.52608971996,-2.575254010755,-14.89067927132,2,1,18 +2025-03-11T12:41:43.090667,479392904,65333,226,9.2292339329,-2.8622741007,-14.33918180327,2,1,18 +2025-03-11T12:41:43.106292,479392904,65333,226,8.92766614922,-3.153923415435,-13.787659014215,2,1,18 +2025-03-11T12:41:43.121917,479392904,65333,226,8.62609836554,-3.450193801995,-13.249981234355,2,1,18 +2025-03-11T12:41:43.137542,479392904,65333,226,8.31981858524,-3.751093413345,-12.698414584295,2,1,18 +2025-03-11T12:41:43.153167,479392904,65333,226,8.04181078466,-4.042701963255,-12.15154688333,2,1,18 +2025-03-11T12:41:43.168792,479392904,65333,226,7.7449549976,-4.343585268675,-11.604614978345,2,1,18 +2025-03-11T12:41:43.184417,479392904,65333,226,7.44338721392,-4.64447672706,-11.076161024615,2,1,18 +2025-03-11T12:41:43.200042,479392904,65333,226,7.13710743362,-4.94537633841,-10.51997319149,2,1,18 +2025-03-11T12:41:43.215667,479392904,65333,226,6.84496364318,-5.246251490865,-9.96380570138,2,1,18 +2025-03-11T12:41:43.231292,479392904,65333,226,6.55281985274,-5.542505571495,-9.440005032725,2,1,18 +2025-03-11T12:41:43.246917,479392904,65333,226,6.25125206906,-5.848018101705,-8.8976689898,2,1,18 +2025-03-11T12:41:43.262542,479392904,65333,226,5.94968428538,-6.153530631915,-8.34146939768,2,1,18 +2025-03-11T12:41:43.278167,479392904,65333,226,5.6481165017,-6.4544220903,-7.80377307782,2,1,18 +2025-03-11T12:41:43.293792,479392904,65333,226,5.36068470788,-6.73680480249,-7.247686528715,2,1,18 +2025-03-11T12:41:43.309417,479392904,65333,226,5.0591169242,-7.03307518905,-6.700766382725,2,1,18 +2025-03-11T12:41:43.325042,479392904,65333,226,4.76697313376,-7.33857141333,-6.14920153568,2,1,18 +2025-03-11T12:41:43.340667,479392904,65333,226,4.45598135684,-7.65334239312,-5.60219366768,2,1,18 +2025-03-11T12:41:43.356292,479392904,65333,226,4.15912556978,-7.940362483065,-5.05069619963,2,1,18 +2025-03-11T12:41:43.371917,479392904,65333,226,3.87169377596,-8.22736626708,-4.51769702585,2,1,18 +2025-03-11T12:41:43.387542,479392904,65333,226,3.5748379889,-8.542112787975,-3.970709500865,2,1,18 +2025-03-11T12:41:43.403167,479392904,65333,226,3.26384621198,-8.847641624115,-3.423738712865,2,1,18 +2025-03-11T12:41:43.418792,479392904,65333,226,2.95756643168,-9.14392016364,-2.87681178587,2,1,18 +2025-03-11T12:41:43.434417,479392904,65333,226,2.66071064462,-9.44480346906,-2.339122247015,2,1,18 +2025-03-11T12:41:43.450042,479392904,65333,226,2.36385485756,-9.741065702655,-1.787587698965,2,1,18 +2025-03-11T12:41:43.465667,479392904,65333,226,2.04815108402,-10.032739476285,-1.254529299155,2,1,18 +2025-03-11T12:41:43.481292,479392904,65333,226,1.75129529696,-10.31975956623,-0.712274197235,2,1,18 +2025-03-11T12:41:43.496917,479392904,65333,226,1.4544395099,-10.62064287165,-0.169963475315,2,1,18 +2025-03-11T12:41:43.512542,479392904,65333,226,1.15287172622,-10.921534330035,0.38159639374,2,1,18 +2025-03-11T12:41:43.528167,479392904,65333,226,0.8654399324,-11.240885616825,0.93321007978,2,1,18 +2025-03-11T12:41:43.543792,479392904,65333,226,0.57329614196,-11.55100291293,1.47092991763,2,1,18 +2025-03-11T12:41:43.559417,479392904,65333,226,0.26701636166,-11.847281452455,2.02247802769,2,1,18 +2025-03-11T12:41:43.575042,479392904,65333,226,-0.03926341864,-12.14355999198,2.578647320815,2,1,18 +2025-03-11T12:41:43.590667,479392904,65333,226,-0.3361192057,-12.45368544105,3.11637393967,2,1,18 +2025-03-11T12:41:43.606292,479392904,65333,226,-0.65182297924,-12.759222430155,3.65873032561,2,1,18 +2025-03-11T12:41:43.621917,479392904,65333,226,-0.93454277644,-13.06008127668,4.19639952145,2,1,18 +2025-03-11T12:41:43.637542,479392904,65333,226,-1.23611056012,-13.35635166324,4.74331966744,2,1,18 +2025-03-11T12:41:43.653167,479392904,65333,226,-1.5376783438,-13.6526220498,5.304103362625,2,1,18 +2025-03-11T12:41:43.668792,479392904,65333,226,-1.82982213424,-13.93963398678,5.850972866605,2,1,18 +2025-03-11T12:41:43.684417,479392904,65333,226,-2.1266779213,-14.245138364025,6.374817396265,2,1,18 +2025-03-11T12:41:43.700042,479392904,65333,226,-2.42353370836,-14.55064274127,6.92176784125,2,1,18 +2025-03-11T12:41:43.715667,479392904,65333,226,-2.72510149204,-14.83767098418,7.464029724175,2,1,18 +2025-03-11T12:41:43.731292,479392904,65333,226,-3.00782128924,-15.129287687055,8.001661840015,2,1,18 +2025-03-11T12:41:43.746917,479392904,65333,226,-3.29996507968,-15.434783911335,8.54398432093,2,1,18 +2025-03-11T12:41:43.762542,479392904,65333,226,-3.5873968735,-15.735650910825,9.08628148084,2,1,18 +2025-03-11T12:41:43.778167,479392904,65333,226,-3.87482866732,-16.02265469484,9.642386569945,2,1,18 +2025-03-11T12:41:43.793792,479392904,65333,226,-4.16226046114,-16.34200598163,10.18013670679,2,1,18 +2025-03-11T12:41:43.809417,479392904,65333,226,-4.46854024144,-16.64290559298,10.71321862459,2,1,18 +2025-03-11T12:41:43.825042,479392904,65333,226,-4.77482002174,-16.929941988855,11.241623739325,2,1,18 +2025-03-11T12:41:43.840667,479392904,65333,226,-5.06225181556,-17.221566844695,11.783883819235,2,1,18 +2025-03-11T12:41:43.856292,479392904,65333,226,-5.35910760262,-17.522450150115,12.32157335809,2,1,18 +2025-03-11T12:41:43.871917,479392904,65333,226,-5.64653939644,-17.804832862305,12.849932808805,2,1,18 +2025-03-11T12:41:43.887542,479392904,65333,226,-5.9433951835,-18.0826108086,13.39677201379,2,1,18 +2025-03-11T12:41:43.903167,479392904,65333,226,-6.24025097056,-18.37425197037,13.925182106515,2,1,18 +2025-03-11T12:41:43.918792,479392904,65333,226,-6.532394761,-18.670506051,14.43974040904,2,1,18 +2025-03-11T12:41:43.934417,479392904,65333,226,-6.81982655482,-18.975994122315,14.97281374282,2,1,18 +2025-03-11T12:41:43.950042,479392904,65333,226,-7.11668234188,-19.27225635591,15.50586355861,2,1,18 +2025-03-11T12:41:43.965667,479392904,65333,226,-7.39940213908,-19.55925198696,16.01575003606,2,1,18 +2025-03-11T12:41:43.981292,479392904,65333,226,-7.69154592952,-19.850884995765,16.55339571391,2,1,18 +2025-03-11T12:41:43.996917,479392904,65333,226,-7.97897772334,-20.151751995255,17.081829324625,2,1,18 +2025-03-11T12:41:44.012542,479392904,65333,226,-8.26169752054,-20.42488441083,17.610144914335,2,1,18 +2025-03-11T12:41:44.028167,479392904,65333,226,-8.55384131098,-20.70265420416,18.129250239925,2,1,18 +2025-03-11T12:41:44.043792,479392904,65333,226,-8.84598510142,-20.994287212965,18.666895917775,2,1,18 +2025-03-11T12:41:44.059417,479392904,65333,226,-9.13341689524,-21.267427781505,19.19521828849,2,1,18 +2025-03-11T12:41:44.075042,479392904,65333,226,-9.41613669244,-21.55904448438,19.718986855135,2,1,18 +2025-03-11T12:41:44.090667,479392904,65333,226,-9.70828048288,-21.859919636835,20.24280606379,2,1,18 +2025-03-11T12:41:44.106292,479392904,65333,226,-9.98157628684,-22.15152003378,20.766561068425,2,1,18 +2025-03-11T12:41:44.121917,479392904,65333,226,-10.25958408742,-22.44312858369,21.285701671,2,1,18 +2025-03-11T12:41:44.137542,479392904,65333,226,-10.55643987448,-22.739390817285,21.80950912066,2,1,18 +2025-03-11T12:41:44.153167,479392904,65333,226,-10.82973567844,-23.035612286055,22.333282665295,2,1,18 +2025-03-11T12:41:44.168792,479392904,65333,226,-11.11245547564,-23.313365773455,22.83851087968,2,1,18 +2025-03-11T12:41:44.184417,479392904,65333,226,-11.41402325932,-23.600394016365,23.343803298085,2,1,18 +2025-03-11T12:41:44.200042,479392904,65333,226,-11.69674305652,-23.88276857559,23.872155967795,2,1,18 +2025-03-11T12:41:44.215667,479392904,65333,226,-11.9747508571,-24.14665069455,24.4004276965,2,1,18 +2025-03-11T12:41:44.231292,479392904,65333,226,-12.2574706543,-24.438267397425,24.905711530885,2,1,18 +2025-03-11T12:41:44.246917,479392904,65333,226,-12.53547845488,-24.71601273186,25.410932964265,2,1,18 +2025-03-11T12:41:44.262542,479392904,65333,226,-12.80877425884,-24.98450776968,25.920731719705,2,1,18 +2025-03-11T12:41:44.278167,479392904,65333,226,-13.09149405604,-25.266882328905,26.449084389415,2,1,18 +2025-03-11T12:41:44.293792,479392904,65333,226,-13.37421385324,-25.54925688813,26.958952326865,2,1,18 +2025-03-11T12:41:44.309417,479392904,65333,226,-13.64279766058,-25.81312270116,27.445619845975,2,1,18 +2025-03-11T12:41:44.325042,479392904,65333,226,-13.92080546116,-26.100110179245,27.94625717629,2,1,18 +2025-03-11T12:41:44.340667,479392904,65333,226,-14.20352525836,-26.387105810295,28.451522470675,2,1,18 +2025-03-11T12:41:44.356292,479392904,65333,226,-14.48153305894,-26.660230072905,28.96134654712,2,1,18 +2025-03-11T12:41:44.371917,479392904,65333,226,-14.74540486966,-26.928708804795,29.457268191355,2,1,18 +2025-03-11T12:41:44.387542,479392904,65333,226,-15.00456468376,-27.211042599195,29.95785985765,2,1,18 +2025-03-11T12:41:44.403167,479392904,65333,226,-15.28257248434,-27.484166861805,30.46306275103,2,1,18 +2025-03-11T12:41:44.418792,479392904,65333,226,-15.55115629168,-27.76189589031,30.95902825627,2,1,18 +2025-03-11T12:41:44.434417,479392904,65333,226,-15.81974009902,-28.030382775165,31.450335498445,2,1,18 +2025-03-11T12:41:44.450042,479392904,65333,226,-16.10245989622,-28.289651975265,31.950868369765,2,1,18 +2025-03-11T12:41:44.465667,479392904,65333,226,-16.36633170694,-28.55350963533,32.41904437561,2,1,18 +2025-03-11T12:41:44.481292,479392904,65333,226,-16.63020351766,-28.826609439045,32.905742193715,2,1,18 +2025-03-11T12:41:44.496917,479392904,65333,226,-16.89407532838,-29.08122495546,33.387744668755,2,1,18 +2025-03-11T12:41:44.512542,479392904,65333,226,-17.16737113234,-29.34047784963,33.89288516113,2,1,18 +2025-03-11T12:41:44.528167,479392904,65333,226,-17.4406669363,-29.5997307438,34.39340447044,2,1,18 +2025-03-11T12:41:44.543792,479392904,65333,226,-17.70925074364,-29.87283870048,34.87086670342,2,1,18 +2025-03-11T12:41:44.559417,479392904,65333,226,-17.96369856112,-30.145922198265,35.366793325645,2,1,18 +2025-03-11T12:41:44.575042,479392904,65333,226,-18.22285837522,-30.40515063354,35.834944010485,2,1,18 +2025-03-11T12:41:44.590667,479392904,65333,226,-18.4773061927,-30.659749844025,36.31231174045,2,1,18 +2025-03-11T12:41:44.606292,479392904,65333,226,-18.7364660068,-30.9374625666,36.78053658529,2,1,18 +2025-03-11T12:41:44.621917,479392904,65333,226,-19.00504981414,-31.196707307805,37.253322015205,2,1,18 +2025-03-11T12:41:44.637542,479392904,65333,226,-19.27363362148,-31.451330977185,37.730710088185,2,1,18 +2025-03-11T12:41:44.653167,479392904,65333,226,-19.53279343558,-31.71980155611,38.217382585285,2,1,18 +2025-03-11T12:41:44.668792,479392904,65333,226,-19.78252925644,-31.98363475728,38.685538248115,2,1,18 +2025-03-11T12:41:44.684417,479392904,65333,226,-20.0322650773,-32.242846886625,39.13056945562,2,1,18 +2025-03-11T12:41:44.700042,479392904,65333,226,-20.28671289478,-32.49744609711,39.589452453325,2,1,18 +2025-03-11T12:41:44.715667,479392904,65333,226,-20.53644871564,-32.75203715463,40.04370748696,2,1,18 +2025-03-11T12:41:44.731292,479392904,65333,226,-20.80503252298,-33.01590296766,40.48416317542,2,1,18 +2025-03-11T12:41:44.746917,479392904,65333,226,-21.06419233708,-33.247404971985,40.97068735252,2,1,18 +2025-03-11T12:41:44.762542,479392904,65333,226,-21.31392815794,-33.492753885855,41.42952648922,2,1,18 +2025-03-11T12:41:44.778167,479392904,65333,226,-21.56837597542,-33.74735309634,41.879167120795,2,1,18 +2025-03-11T12:41:44.793792,479392904,65333,226,-21.80868780304,-34.01116999158,42.33344567242,2,1,18 +2025-03-11T12:41:44.809417,479392904,65333,226,-22.03957563742,-34.25648629359,42.77377295284,2,1,18 +2025-03-11T12:41:44.825042,479392904,65333,226,-22.28931145828,-34.49259306381,43.21409027728,2,1,18 +2025-03-11T12:41:44.840667,479392904,65333,226,-22.53433528252,-34.737933824715,43.654437900715,2,1,18 +2025-03-11T12:41:44.856292,479392904,65333,226,-22.77464711014,-34.98788750448,44.094797283145,2,1,18 +2025-03-11T12:41:44.871917,479392904,65333,226,-23.01967093438,-35.22860719356,44.548989915775,2,1,18 +2025-03-11T12:41:44.887542,479392904,65333,226,-23.259982762,-35.469318729675,44.998554584335,2,1,18 +2025-03-11T12:41:44.903167,479392904,65333,226,-23.50500658624,-35.719280562405,45.4481631139,2,1,18 +2025-03-11T12:41:44.918792,479392904,65333,226,-23.74531841386,-35.96923424217,45.8792801302,2,1,18 +2025-03-11T12:41:44.934417,479392904,65333,226,-23.9903422381,-36.2007117876,46.3241933167,2,1,18 +2025-03-11T12:41:44.950042,479392904,65333,226,-24.23536606234,-36.43218933303,46.75986413707,2,1,18 +2025-03-11T12:41:44.965667,479392904,65333,226,-24.47096589334,-36.67289271618,47.200179658495,2,1,18 +2025-03-11T12:41:44.981292,479392904,65333,226,-24.70185372772,-36.922830090015,47.60817719746,2,1,18 +2025-03-11T12:41:44.996917,479392904,65333,226,-24.93745355872,-37.15891240134,48.011504714365,2,1,18 +2025-03-11T12:41:45.012542,479392904,65333,226,-25.16362939648,-37.385736263085,48.437887504585,2,1,18 +2025-03-11T12:41:45.028167,479392904,65333,226,-25.38509323762,-37.612551971865,48.8642635138,2,1,18 +2025-03-11T12:41:45.043792,479392904,65333,226,-25.61126907538,-37.83013368996,49.267503308695,2,1,18 +2025-03-11T12:41:45.059417,479392904,65333,226,-25.85629289962,-38.04312694809,49.675372870675,2,1,18 +2025-03-11T12:41:45.075042,479392904,65333,226,-26.07304474414,-38.28379771938,50.09717653582,2,1,18 +2025-03-11T12:41:45.090667,479392904,65333,226,-26.29450858528,-38.50137128451,50.523515465035,2,1,18 +2025-03-11T12:41:45.106292,479392904,65333,226,-26.50654843318,-38.732791759185,50.92216935385,2,1,18 +2025-03-11T12:41:45.121917,479392904,65333,226,-26.73272427094,-38.964236692755,51.33008595181,2,1,18 +2025-03-11T12:41:45.137542,479392904,65333,226,-26.9589001087,-39.18181841085,51.73794692977,2,1,18 +2025-03-11T12:41:45.153167,479392904,65333,226,-27.18036394984,-39.404013047805,52.136577300595,2,1,18 +2025-03-11T12:41:45.168792,479392904,65333,226,-27.40182779098,-39.621586612935,52.539810314485,2,1,18 +2025-03-11T12:41:45.184417,479392904,65333,226,-27.6185796355,-39.84839416875,52.9523159935,2,1,18 +2025-03-11T12:41:45.200042,479392904,65333,226,-27.8306194834,-40.0567092843,53.33701363312,2,1,18 +2025-03-11T12:41:45.215667,479392904,65333,226,-28.04737132792,-40.26965362464,53.73560014294,2,1,18 +2025-03-11T12:41:45.231292,479392904,65333,226,-28.26883516906,-40.46874290247,54.13875899683,2,1,18 +2025-03-11T12:41:45.246917,479392904,65333,226,-28.47145102372,-40.67704171209,54.51420070831,2,1,18 +2025-03-11T12:41:45.262542,479392904,65333,226,-28.68820286824,-40.913091411555,54.889774002805,2,1,18 +2025-03-11T12:41:45.278167,479392904,65333,226,-28.90024271614,-41.121406527105,55.26985045936,2,1,18 +2025-03-11T12:41:45.293792,479392904,65333,226,-29.11699456066,-41.315866580145,55.63139334466,2,1,18 +2025-03-11T12:41:45.309417,479392904,65333,226,-29.32432241194,-41.51493139908,56.01142594021,2,1,18 +2025-03-11T12:41:45.325042,479392904,65333,226,-29.5269382666,-41.746335567825,56.39620271782,2,1,18 +2025-03-11T12:41:45.340667,479392904,65333,226,-29.72955412126,-41.945392233795,56.776228532365,2,1,18 +2025-03-11T12:41:45.356292,479392904,65333,226,-29.9274579793,-42.13519860315,57.13310457058,2,1,18 +2025-03-11T12:41:45.371917,479392904,65333,226,-30.1159378441,-42.33885188205,57.471537934525,2,1,18 +2025-03-11T12:41:45.387542,479392904,65333,226,-30.31855369876,-42.55639283532,57.837774359875,2,1,18 +2025-03-11T12:41:45.403167,479392904,65333,226,-30.52588155004,-42.74159443878,58.208508969295,2,1,18 +2025-03-11T12:41:45.418792,479392904,65333,226,-30.71436141484,-42.94524771768,58.57466943163,2,1,18 +2025-03-11T12:41:45.434417,479392904,65333,226,-30.91226527288,-43.13967515886,58.93618519291,2,1,18 +2025-03-11T12:41:45.450042,479392904,65333,226,-31.09603314106,-43.32021492567,59.269897892785,2,1,18 +2025-03-11T12:41:45.465667,479392904,65333,226,-31.28451300586,-43.510004989095,59.622139185925,2,1,18 +2025-03-11T12:41:45.481292,479392904,65333,226,-31.47299287066,-43.713658267995,59.965193732935,2,1,18 +2025-03-11T12:41:45.496917,479392904,65333,226,-31.67560872532,-43.90809386214,60.312852726025,2,1,18 +2025-03-11T12:41:45.512542,479392904,65333,226,-31.86408859012,-44.09326285374,60.665075479165,2,1,18 +2025-03-11T12:41:45.528167,479392904,65333,226,-32.05256845492,-44.273810773515,61.008037326175,2,1,18 +2025-03-11T12:41:45.543792,479392904,65333,226,-32.24576031634,-44.463608989905,61.318694752735,2,1,18 +2025-03-11T12:41:45.559417,479392904,65333,226,-32.43424018114,-44.64415690968,61.652414233615,2,1,18 +2025-03-11T12:41:45.575042,479392904,65333,226,-32.60387205946,-44.833914361245,61.995386036605,2,1,18 +2025-03-11T12:41:45.590667,479392904,65333,226,-32.78292793102,-45.02368811874,62.329129035475,2,1,18 +2025-03-11T12:41:45.606292,479392904,65333,226,-32.95727180596,-45.208832651445,62.61663488269,2,1,18 +2025-03-11T12:41:45.621917,479392904,65333,226,-33.1316156809,-45.3662507532,62.92713540523,2,1,18 +2025-03-11T12:41:45.637542,479392904,65333,226,-33.30595955584,-45.532910998605,63.25615774003,2,1,18 +2025-03-11T12:41:45.653167,479392904,65333,226,-33.46616744092,-45.70416785694,63.58979945488,2,1,18 +2025-03-11T12:41:45.668792,479392904,65333,226,-33.63108732262,-45.870811796415,63.90032349541,2,1,18 +2025-03-11T12:41:45.684417,479392904,65333,226,-33.80543119756,-46.03747204182,64.215482281015,2,1,18 +2025-03-11T12:41:45.700042,479392904,65333,226,-33.97035107926,-46.20873705312,64.526024861545,2,1,18 +2025-03-11T12:41:45.715667,479392904,65333,226,-34.13527096096,-46.384623136245,64.855070714335,2,1,18 +2025-03-11T12:41:45.731292,479392904,65333,226,-34.30490283928,-46.54665415686,65.13785589748,2,1,18 +2025-03-11T12:41:45.746917,479392904,65333,226,-34.47924671422,-46.694830114965,65.434455790825,2,1,18 +2025-03-11T12:41:45.762542,479392904,65333,226,-34.63474260268,-46.85221560486,65.717202090955,2,1,18 +2025-03-11T12:41:45.778167,479392904,65333,226,-34.78552649452,-47.01883508544,66.004599873145,2,1,18 +2025-03-11T12:41:45.793792,479392904,65333,226,-34.95044637622,-47.18085795309,66.30124182448,2,1,18 +2025-03-11T12:41:45.809417,479392904,65333,226,-35.11536625792,-47.347501892565,66.597902315815,2,1,18 +2025-03-11T12:41:45.825042,479392904,65333,226,-35.275574143,-47.495653391775,66.875997133885,2,1,18 +2025-03-11T12:41:45.840667,479392904,65333,226,-35.42635803484,-47.64840965688,67.14023338075,2,1,18 +2025-03-11T12:41:45.856292,479392904,65333,226,-35.57714192668,-47.80578699381,67.404488167615,2,1,18 +2025-03-11T12:41:45.871917,479392904,65333,226,-35.71378982866,-47.96776094367,67.6641199684,2,1,18 +2025-03-11T12:41:45.887542,479392904,65333,226,-35.85986172388,-48.097403696685,67.92825673426,2,1,18 +2025-03-11T12:41:45.903167,479392904,65333,226,-36.01064561572,-48.227054602665,68.192400281125,2,1,18 +2025-03-11T12:41:45.918792,479392904,65333,226,-36.15200551432,-48.37979456184,68.452001782915,2,1,18 +2025-03-11T12:41:45.934417,479392904,65333,226,-36.29807740954,-48.537163745805,68.71162860571,2,1,18 +2025-03-11T12:41:45.950042,479392904,65333,226,-36.45828529462,-48.685315245015,68.99896578991,2,1,18 +2025-03-11T12:41:45.965667,479392904,65333,226,-36.5949331966,-48.819562763925,69.2446228015,2,1,18 +2025-03-11T12:41:45.981292,479392904,65333,226,-36.73158109858,-48.953810282835,69.48103744696,2,1,18 +2025-03-11T12:41:45.996856,479392908,65329,227,-36.87294099718,-49.083444882885,69.735925065685,2,1,18 +2025-03-11T12:41:46.012481,479392908,65329,227,-36.9954529093,-49.20842579925,69.986145837325,2,1,18 +2025-03-11T12:41:46.028106,479392908,65329,227,-37.12267681804,-49.35189915588,70.21796281771,2,1,18 +2025-03-11T12:41:46.043731,479392908,65329,227,-37.26874871326,-49.48616298072,70.468254574375,2,1,18 +2025-03-11T12:41:46.059356,479392908,65329,227,-37.39126062538,-49.611143897085,70.699990613755,2,1,18 +2025-03-11T12:41:46.074981,479392908,65329,227,-37.52319653074,-49.73614111938,70.92711903208,2,1,18 +2025-03-11T12:41:46.090606,479392908,65329,227,-37.64570844286,-49.86574310757,71.154252428395,2,1,18 +2025-03-11T12:41:46.106231,479392908,65329,227,-37.76350835836,-49.99071587097,71.390602869835,2,1,18 +2025-03-11T12:41:46.121856,479392908,65329,227,-37.88602027048,-50.12031785916,71.622357449215,2,1,18 +2025-03-11T12:41:46.137481,479392908,65329,227,-38.0085321826,-50.23143556005,71.8401743194,2,1,18 +2025-03-11T12:41:46.153106,479392908,65329,227,-38.13575609134,-50.35642462938,72.053432407525,2,1,18 +2025-03-11T12:41:46.168731,479392908,65329,227,-38.25355600684,-50.467534177305,72.25737894751,2,1,18 +2025-03-11T12:41:46.184356,479392908,65329,227,-38.3619319291,-50.58786956295,72.461349005485,2,1,18 +2025-03-11T12:41:46.199981,479392908,65329,227,-38.46559585474,-50.694333580155,72.65139311326,2,1,18 +2025-03-11T12:41:46.215606,479392908,65329,227,-38.58339577024,-50.800822056255,72.855321113245,2,1,18 +2025-03-11T12:41:46.231231,479392908,65329,227,-38.68234769926,-50.92114113597,73.073141158405,2,1,18 +2025-03-11T12:41:46.246856,479392908,65329,227,-38.7860116249,-51.036847296825,73.258601163115,2,1,18 +2025-03-11T12:41:46.262481,479392908,65329,227,-38.88967555054,-51.129448098555,73.453210833955,2,1,18 +2025-03-11T12:41:46.278106,479392908,65329,227,-38.99333947618,-51.22666997211,73.647839044795,2,1,18 +2025-03-11T12:41:46.293731,479392908,65329,227,-39.10171539844,-51.33314214228,73.81478401825,2,1,18 +2025-03-11T12:41:46.309356,479392908,65329,227,-39.20066732746,-51.425734791045,74.01400809115,2,1,18 +2025-03-11T12:41:46.324981,479392908,65329,227,-39.29490725986,-51.536803574145,74.19943599385,2,1,18 +2025-03-11T12:41:46.340606,479392908,65329,227,-39.40328318212,-51.634033600665,74.37096507037,2,1,18 +2025-03-11T12:41:46.356231,479392908,65329,227,-39.50223511114,-51.71738410578,74.54242496488,2,1,18 +2025-03-11T12:41:46.371856,479392908,65329,227,-39.58233905368,-51.809944142685,74.690788900045,2,1,18 +2025-03-11T12:41:46.387481,479392908,65329,227,-39.67186698946,-51.907141557345,74.85766966948,2,1,18 +2025-03-11T12:41:46.403106,479392908,65329,227,-39.76610692186,-51.999726053145,75.029159862985,2,1,18 +2025-03-11T12:41:46.418731,479392908,65329,227,-39.8462108644,-52.087665018225,75.17750525815,2,1,18 +2025-03-11T12:41:46.434356,479392908,65329,227,-39.93573880018,-52.18024136106,75.325882755325,2,1,18 +2025-03-11T12:41:46.449981,479392908,65329,227,-40.02055473934,-52.249704191805,75.47878195456,2,1,18 +2025-03-11T12:41:46.465606,479392908,65329,227,-40.09594668526,-52.30990857297,75.640872877915,2,1,18 +2025-03-11T12:41:46.481231,479392908,65329,227,-40.1760506278,-52.37936325075,75.793765296145,2,1,18 +2025-03-11T12:41:46.496856,479392908,65329,227,-40.26557856358,-52.462697449935,75.93286334719,2,1,18 +2025-03-11T12:41:46.512481,479392908,65329,227,-40.33154651626,-52.545990884295,76.067306310145,2,1,18 +2025-03-11T12:41:46.528106,479392908,65329,227,-40.40222646556,-52.62005032797,76.183234241845,2,1,18 +2025-03-11T12:41:46.543731,479392908,65329,227,-40.47290641486,-52.69873084347,76.299180713545,2,1,18 +2025-03-11T12:41:46.559356,479392908,65329,227,-40.54358636416,-52.76816921532,76.43819602057,2,1,18 +2025-03-11T12:41:46.574981,479392908,65329,227,-40.60484232022,-52.832970209415,76.56331567639,2,1,18 +2025-03-11T12:41:46.590606,479392908,65329,227,-40.67552226952,-52.893166437615,76.683809171155,2,1,18 +2025-03-11T12:41:46.606231,479392908,65329,227,-40.75562621206,-52.96724218722,76.7951294818,2,1,18 +2025-03-11T12:41:46.621856,479392908,65329,227,-40.80745817488,-53.02740580356,76.897111120285,2,1,18 +2025-03-11T12:41:46.637481,479392908,65329,227,-40.8592901377,-53.0875694199,77.0083351249,2,1,18 +2025-03-11T12:41:46.653106,479392908,65329,227,-40.92054609376,-53.143128270345,77.101069419265,2,1,18 +2025-03-11T12:41:46.668731,479392908,65329,227,-40.99122604306,-53.19870342672,77.207680824835,2,1,18 +2025-03-11T12:41:46.684356,479392908,65329,227,-41.05248199912,-53.24039906169,77.314223048395,2,1,18 +2025-03-11T12:41:46.699981,479392908,65329,227,-41.0948899687,-53.295925300275,77.420793767935,2,1,18 +2025-03-11T12:41:46.715606,479392908,65329,227,-41.14672193152,-53.346846772965,77.508874777225,2,1,18 +2025-03-11T12:41:46.731231,479392908,65329,227,-41.1891299011,-53.397751939725,77.60156340757,2,1,18 +2025-03-11T12:41:46.746856,479392908,65329,227,-41.23153787068,-53.457899250135,77.68042556872,2,1,18 +2025-03-11T12:41:46.762481,479392908,65329,227,-41.26923384364,-53.50879626393,77.76386505193,2,1,18 +2025-03-11T12:41:46.778106,479392908,65329,227,-41.31164181322,-53.54121714339,77.847237156145,2,1,18 +2025-03-11T12:41:46.793731,479392908,65329,227,-41.35876177942,-53.58750939129,77.91680811217,2,1,18 +2025-03-11T12:41:46.809356,479392908,65329,227,-41.39645775238,-53.619922117785,77.98168870312,2,1,18 +2025-03-11T12:41:46.824981,479392908,65329,227,-41.42944172872,-53.643084547665,78.04190425,2,1,18 +2025-03-11T12:41:46.840606,479392908,65329,227,-41.45300171182,-53.68009388709,78.088298305675,2,1,18 +2025-03-11T12:41:46.856231,479392908,65329,227,-41.50012167802,-53.69865970404,78.13927328944,2,1,18 +2025-03-11T12:41:46.871856,479392908,65329,227,-41.53310565436,-53.726443205745,78.19026501019,2,1,18 +2025-03-11T12:41:46.887481,479392908,65329,227,-41.56137763408,-53.754218554485,78.245871133,2,1,18 +2025-03-11T12:41:46.903106,479392908,65329,227,-41.58022562056,-53.77735652547,78.3014451538,2,1,18 +2025-03-11T12:41:46.918731,479392908,65329,227,-41.60378560366,-53.814365864895,78.35246039254,2,1,18 +2025-03-11T12:41:46.934356,479392908,65329,227,-41.63205758338,-53.82827799816,78.384904980025,2,1,18 +2025-03-11T12:41:46.949981,479392908,65329,227,-41.64148157662,-53.83753644774,78.41730390349,2,1,18 +2025-03-11T12:41:46.965606,479392908,65329,227,-41.66504155972,-53.86068257169,78.435915240775,2,1,18 +2025-03-11T12:41:46.981231,479392908,65329,227,-41.67917754958,-53.888433461535,78.468395105245,2,1,18 +2025-03-11T12:41:46.996856,479392908,65329,227,-41.6838895462,-53.911546973625,78.510085233835,2,1,18 +2025-03-11T12:41:47.012481,479392908,65329,227,-41.71687352254,-53.91160404438,78.52861743313,2,1,18 +2025-03-11T12:41:47.028106,479392908,65329,227,-41.73572150902,-53.925499871715,78.551806092475,2,1,18 +2025-03-11T12:41:47.043731,479392908,65329,227,-41.74043350564,-53.939371240155,78.56111085961,2,1,18 +2025-03-11T12:41:47.059356,479392908,65329,227,-41.74043350564,-53.948613383805,78.584253854935,2,1,18 +2025-03-11T12:41:47.074981,479392908,65329,227,-41.74043350564,-53.957855527455,78.59815448413,2,1,18 +2025-03-11T12:41:47.090606,479392908,65329,227,-41.74514550226,-53.94862153677,78.6027453682,2,1,18 +2025-03-11T12:41:47.106231,479392908,65329,227,-41.74985749888,-53.948629689735,78.593509783075,2,1,18 +2025-03-11T12:41:47.121856,479392908,65329,227,-41.76399348874,-53.953275220455,78.58430629996,2,1,18 +2025-03-11T12:41:47.137481,479392908,65329,227,-41.7545694955,-53.962501058175,78.57508745182,2,1,18 +2025-03-11T12:41:47.153106,479392908,65329,227,-41.7545694955,-53.95787998635,78.57506891182,2,1,18 +2025-03-11T12:41:47.168731,479392908,65329,227,-41.74985749888,-53.93476647426,78.57034824775,2,1,18 +2025-03-11T12:41:47.184356,479392908,65329,227,-41.74514550226,-53.934758321295,78.561099100615,2,1,18 +2025-03-11T12:41:47.199981,479392908,65329,227,-41.74043350564,-53.92550802468,78.53332814122,2,1,18 +2025-03-11T12:41:47.215606,479392908,65329,227,-41.7310095124,-53.902386359625,78.519358330015,2,1,18 +2025-03-11T12:41:47.231231,479392908,65329,227,-41.70273753268,-53.874611010885,78.48685812253,2,1,18 +2025-03-11T12:41:47.246856,479392908,65329,227,-41.6838895462,-53.86071518355,78.47753301238,2,1,18 +2025-03-11T12:41:47.262481,479392908,65329,227,-41.6603295631,-53.8560533469,78.449753468965,2,1,18 +2025-03-11T12:41:47.278106,479392908,65329,227,-41.64148157662,-53.851399663215,78.394253608165,2,1,18 +2025-03-11T12:41:47.293731,479392908,65329,227,-41.60378560366,-53.823608008545,78.33401274028,2,1,18 +2025-03-11T12:41:47.309356,479392908,65329,227,-41.5896496138,-53.80509926235,78.296948772745,2,1,18 +2025-03-11T12:41:47.324981,479392908,65329,227,-41.5660896307,-53.768089922925,78.24131235094,2,1,18 +2025-03-11T12:41:47.340606,479392908,65329,227,-41.53310565436,-53.726443205745,78.185643827125,2,1,18 +2025-03-11T12:41:47.356231,479392908,65329,227,-41.50954567126,-53.69867600997,78.153150400645,2,1,18 +2025-03-11T12:41:47.371856,479392908,65329,227,-41.4718496983,-53.675505427125,78.106791621955,2,1,18 +2025-03-11T12:41:47.387481,479392908,65329,227,-41.44357771858,-53.629245791085,78.041868973015,2,1,18 +2025-03-11T12:41:47.403106,479392908,65329,227,-41.41059374224,-53.596841217555,77.95851043081,2,1,18 +2025-03-11T12:41:47.418731,479392908,65329,227,-41.38232176252,-53.550581581515,77.89358778187,2,1,18 +2025-03-11T12:41:47.434356,479392908,65329,227,-41.3304897997,-53.495039037,77.819351781775,2,1,18 +2025-03-11T12:41:47.449981,479392908,65329,227,-41.27394584026,-53.462593698645,77.745201700675,2,1,18 +2025-03-11T12:41:47.465606,479392908,65329,227,-41.2362498673,-53.4209388285,77.66642048053,2,1,18 +2025-03-11T12:41:47.481231,479392908,65329,227,-41.19855389434,-53.370041814705,77.596844546515,2,1,18 +2025-03-11T12:41:47.496856,479392908,65329,227,-41.15614592476,-53.31451557612,77.5133797423,2,1,18 +2025-03-11T12:41:47.512481,479392908,65329,227,-41.10431396194,-53.258973031605,77.420659009945,2,1,18 +2025-03-11T12:41:47.528106,479392908,65329,227,-41.05248199912,-53.20343048709,77.323317094525,2,1,18 +2025-03-11T12:41:47.543731,479392908,65329,227,-40.99593803968,-53.13863764596,77.21668895197,2,1,18 +2025-03-11T12:41:47.559356,479392908,65329,227,-40.929970087,-53.106176001675,77.11479821047,2,1,18 +2025-03-11T12:41:47.574981,479392908,65329,227,-40.86871413094,-53.05061715123,77.01744273304,2,1,18 +2025-03-11T12:41:47.590606,479392908,65329,227,-40.80274617826,-52.981186932345,76.89691893928,2,1,18 +2025-03-11T12:41:47.606231,479392908,65329,227,-40.75091421544,-52.930265459655,76.776489648535,2,1,18 +2025-03-11T12:41:47.621856,479392908,65329,227,-40.70379424924,-52.88859428358,76.66996776799,2,1,18 +2025-03-11T12:41:47.637481,479392908,65329,227,-40.64253829318,-52.823793289485,76.56333284443,2,1,18 +2025-03-11T12:41:47.653106,479392908,65329,227,-40.57185834388,-52.735870630335,76.442728109665,2,1,18 +2025-03-11T12:41:47.668731,479392908,65329,227,-40.51531438444,-52.65721457373,76.30831724872,2,1,18 +2025-03-11T12:41:47.684356,479392908,65329,227,-40.45405842838,-52.59703465146,76.16473140064,2,1,18 +2025-03-11T12:41:47.699981,479392908,65329,227,-40.38337847908,-52.51835413596,76.01181546442,2,1,18 +2025-03-11T12:41:47.715606,479392908,65329,227,-40.29856253992,-52.439649161565,75.88198510051,2,1,18 +2025-03-11T12:41:47.731231,479392908,65329,227,-40.21845859738,-52.36557341196,75.74755887454,2,1,18 +2025-03-11T12:41:47.746856,479392908,65329,227,-40.13364265822,-52.28224736574,75.585361689175,2,1,18 +2025-03-11T12:41:47.762481,479392908,65329,227,-40.04882671906,-52.212784534995,75.44170485607,2,1,18 +2025-03-11T12:41:47.778106,479392908,65329,227,-39.97343477314,-52.138716938355,75.316527777235,2,1,18 +2025-03-11T12:41:47.793731,479392908,65329,227,-39.88861883398,-52.036906604835,75.163498798,2,1,18 +2025-03-11T12:41:47.809356,479392908,65329,227,-39.7990908982,-51.948951333825,74.9920339255,2,1,18 +2025-03-11T12:41:47.824981,479392908,65329,227,-39.71427495904,-51.847141000305,74.81589903094,2,1,18 +2025-03-11T12:41:47.840606,479392908,65329,227,-39.62003502664,-51.72220900173,74.644279057435,2,1,18 +2025-03-11T12:41:47.856231,479392908,65329,227,-39.516371101,-51.624987128175,74.47275676192,2,1,18 +2025-03-11T12:41:47.871856,479392908,65329,227,-39.4221311686,-51.54626584785,74.292079822285,2,1,18 +2025-03-11T12:41:47.887481,479392908,65329,227,-39.33260323282,-51.46755272049,74.120652029785,2,1,18 +2025-03-11T12:41:47.903106,479392908,65329,227,-39.2336513038,-51.374960071725,73.94453387221,2,1,18 +2025-03-11T12:41:47.918731,479392908,65329,227,-39.12998737816,-51.26849605452,73.76835331363,2,1,18 +2025-03-11T12:41:47.934356,479392908,65329,227,-39.03574744576,-51.16666941507,73.596826040125,2,1,18 +2025-03-11T12:41:47.949981,479392908,65329,227,-38.9273715235,-51.046334029425,73.415961897475,2,1,18 +2025-03-11T12:41:47.965606,479392908,65329,227,-38.82370759786,-50.935248940395,73.20741451744,2,1,18 +2025-03-11T12:41:47.981231,479392908,65329,227,-38.70590768236,-50.83338153612,73.00812624052,2,1,18 +2025-03-11T12:41:47.996856,479392908,65329,227,-38.60224375672,-50.73153859074,72.818100672745,2,1,18 +2025-03-11T12:41:48.012481,479392908,65329,227,-38.48915583784,-50.62043719578,72.623403279895,2,1,18 +2025-03-11T12:41:48.028106,479392908,65329,227,-38.3854919122,-50.523215322225,72.41491151986,2,1,18 +2025-03-11T12:41:48.043731,479392908,65329,227,-38.2676919967,-50.393621487,72.19702727068,2,1,18 +2025-03-11T12:41:48.059356,479392908,65329,227,-38.15460407782,-50.24555151744,71.988318008635,2,1,18 +2025-03-11T12:41:48.074981,479392908,65329,227,-38.04622815556,-50.12059505997,71.779708227595,2,1,18 +2025-03-11T12:41:48.090606,479392908,65329,227,-37.93314023668,-50.014114736835,71.57116582555,2,1,18 +2025-03-11T12:41:48.106231,479392908,65329,227,-37.81062832456,-49.902997035945,71.3487277723,2,1,18 +2025-03-11T12:41:48.121856,479392908,65329,227,-37.68811641244,-49.791879335055,71.121668535985,2,1,18 +2025-03-11T12:41:48.137481,479392908,65329,227,-37.57031649694,-49.67152764348,70.876094268415,2,1,18 +2025-03-11T12:41:48.153106,479392908,65329,227,-37.44780458482,-49.54192565529,70.653582055165,2,1,18 +2025-03-11T12:41:48.168731,479392908,65329,227,-37.33000466932,-49.40771074824,70.42181571679,2,1,18 +2025-03-11T12:41:48.184356,479392908,65329,227,-37.19806876396,-49.273471382295,70.176165486205,2,1,18 +2025-03-11T12:41:48.199981,479392908,65329,227,-37.05199686874,-49.13458648563,69.921234006475,2,1,18 +2025-03-11T12:41:48.215606,479392908,65329,227,-36.90592497352,-49.004943732615,69.68020315594,2,1,18 +2025-03-11T12:41:48.231231,479392908,65329,227,-36.76456507492,-48.866066988915,69.434520823345,2,1,18 +2025-03-11T12:41:48.246856,479392908,65329,227,-36.63262916956,-48.72258547932,69.193454695825,2,1,18 +2025-03-11T12:41:48.262481,479392908,65329,227,-36.49126927096,-48.588329807445,68.92930617097,2,1,18 +2025-03-11T12:41:48.278106,479392908,65329,227,-36.34990937236,-48.46331627922,68.665194726115,2,1,18 +2025-03-11T12:41:48.293731,479392908,65329,227,-36.20854947376,-48.310576320045,68.387108492065,2,1,18 +2025-03-11T12:41:48.309356,479392908,65329,227,-36.06247757854,-48.139343920605,68.122804866205,2,1,18 +2025-03-11T12:41:48.324981,479392908,65329,227,-35.92111767994,-48.000467176905,67.854016618285,2,1,18 +2025-03-11T12:41:48.340606,479392908,65329,227,-35.79860576782,-47.870865188715,67.58991375745,2,1,18 +2025-03-11T12:41:48.356231,479392908,65329,227,-35.64782187598,-47.72735106726,67.325714590585,2,1,18 +2025-03-11T12:41:48.371856,479392908,65329,227,-35.49703798414,-47.58845801763,67.06153396372,2,1,18 +2025-03-11T12:41:48.387481,479392908,65329,227,-35.33683009906,-47.435685446595,66.79266297178,2,1,18 +2025-03-11T12:41:48.403106,479392908,65329,227,-35.17662221398,-47.27367073191,66.509891350645,2,1,18 +2025-03-11T12:41:48.418731,479392908,65329,227,-35.02112632552,-47.116285242015,66.24100859971,2,1,18 +2025-03-11T12:41:48.434356,479392908,65329,227,-34.86091844044,-46.94502838368,65.93509398325,2,1,18 +2025-03-11T12:41:48.449981,479392908,65329,227,-34.70542255198,-46.80150610926,65.62467620473,2,1,18 +2025-03-11T12:41:48.465606,479392908,65329,227,-34.54992666352,-46.653362763015,65.337345801535,2,1,18 +2025-03-11T12:41:48.481231,479392908,65329,227,-34.39914277168,-46.47288006696,65.04527121628,2,1,18 +2025-03-11T12:41:48.496856,479392908,65329,227,-34.2389348866,-46.30624428045,64.73937513982,2,1,18 +2025-03-11T12:41:48.512481,479392908,65329,227,-34.05987901504,-46.13957588208,64.44269430547,2,1,18 +2025-03-11T12:41:48.528106,479392908,65329,227,-33.8855351401,-45.94981027755,64.13206400293,2,1,18 +2025-03-11T12:41:48.543731,479392908,65329,227,-33.7206152584,-45.783166338075,63.816918779335,2,1,18 +2025-03-11T12:41:48.559356,479392908,65329,227,-33.56511936994,-45.62578084818,63.50182419775,2,1,18 +2025-03-11T12:41:48.574981,479392908,65329,227,-33.38606349838,-45.44987030616,63.182000368075,2,1,18 +2025-03-11T12:41:48.590606,479392908,65329,227,-33.21643162006,-45.27397607007,62.848326551215,2,1,18 +2025-03-11T12:41:48.606231,479392908,65329,227,-33.02795175526,-45.084186006645,62.5191911734,2,1,18 +2025-03-11T12:41:48.621856,479392908,65329,227,-32.8488958837,-44.917517608275,62.208646789855,2,1,18 +2025-03-11T12:41:48.637481,479392908,65329,227,-32.67926400538,-44.732381228535,61.893420625255,2,1,18 +2025-03-11T12:41:48.653106,479392908,65329,227,-32.50492013044,-44.54723669583,61.564324130455,2,1,18 +2025-03-11T12:41:48.668731,479392908,65329,227,-32.31644026564,-44.366688776055,61.221362283445,2,1,18 +2025-03-11T12:41:48.684356,479392908,65329,227,-32.1185364076,-44.18612455035,60.88300805749,2,1,18 +2025-03-11T12:41:48.699981,479392908,65329,227,-31.92063254956,-43.996318180995,60.535374385405,2,1,18 +2025-03-11T12:41:48.715606,479392908,65329,227,-31.74628867462,-43.80193150464,60.187756078345,2,1,18 +2025-03-11T12:41:48.731231,479392908,65329,227,-31.56252080644,-43.61214959418,59.840142749275,2,1,18 +2025-03-11T12:41:48.746856,479392908,65329,227,-31.3646169484,-43.440827512125,59.497204420255,2,1,18 +2025-03-11T12:41:48.762481,479392908,65329,227,-31.17142508698,-43.25565036756,59.14497488611,2,1,18 +2025-03-11T12:41:48.778106,479392908,65329,227,-30.96880923232,-43.03810941429,58.80646555915,2,1,18 +2025-03-11T12:41:48.793731,479392908,65329,227,-30.77090537428,-42.83443982946,58.46339745013,2,1,18 +2025-03-11T12:41:48.809356,479392908,65329,227,-30.58242550948,-42.64002869421,58.115758800055,2,1,18 +2025-03-11T12:41:48.824981,479392908,65329,227,-30.38452165144,-42.43635910938,57.76806950797,2,1,18 +2025-03-11T12:41:48.840606,479392908,65329,227,-30.20075378326,-42.241956127095,57.388089357445,2,1,18 +2025-03-11T12:41:48.856231,479392908,65329,227,-30.00284992522,-42.029044398615,57.01263588697,2,1,18 +2025-03-11T12:41:48.871856,479392908,65329,227,-29.7860980807,-41.82996327375,56.65107446167,2,1,18 +2025-03-11T12:41:48.887481,479392908,65329,227,-29.59290621928,-41.63092291371,56.28492575833,2,1,18 +2025-03-11T12:41:48.903106,479392908,65329,227,-29.39029036462,-41.42262410409,55.91872641298,2,1,18 +2025-03-11T12:41:48.918731,479392908,65329,227,-29.18767450996,-41.218946366295,55.520197326175,2,1,18 +2025-03-11T12:41:48.934356,479392908,65329,227,-28.97563466206,-41.01525232257,55.135518226555,2,1,18 +2025-03-11T12:41:48.949981,479392908,65329,227,-28.76830681078,-40.806945359985,54.75082736794,2,1,18 +2025-03-11T12:41:48.965606,479392908,65329,227,-28.55626696288,-40.61249345991,54.352321799125,2,1,18 +2025-03-11T12:41:48.981231,479392908,65329,227,-28.33480312174,-40.381056679305,53.96289671443,2,1,18 +2025-03-11T12:41:48.996856,479392908,65329,227,-28.12747527046,-40.16350757307,53.59203232501,2,1,18 +2025-03-11T12:41:49.012481,479392908,65329,227,-27.91543542256,-39.96443460117,53.20737176539,2,1,18 +2025-03-11T12:41:49.028106,479392908,65329,227,-27.69868357804,-39.746869189005,52.80876671557,2,1,18 +2025-03-11T12:41:49.043731,479392908,65329,227,-27.4772197369,-39.52467455205,52.41475752781,2,1,18 +2025-03-11T12:41:49.059356,479392908,65329,227,-27.26989188562,-39.297883302165,52.011507776935,2,1,18 +2025-03-11T12:41:49.074981,479392908,65329,227,-27.04842804448,-39.07568866521,51.61287740611,2,1,18 +2025-03-11T12:41:49.090606,479392908,65329,227,-26.83638819658,-38.853510334185,51.214260597295,2,1,18 +2025-03-11T12:41:49.106231,479392908,65329,227,-26.60078836558,-38.631291238335,50.815609883455,2,1,18 +2025-03-11T12:41:49.121856,479392908,65329,227,-26.37932452444,-38.40909660138,50.4077371465,2,1,18 +2025-03-11T12:41:49.137481,479392908,65329,227,-26.17199667316,-38.182305351495,49.986002663365,2,1,18 +2025-03-11T12:41:49.153106,479392908,65329,227,-25.95524482864,-37.95549779568,49.578118167415,2,1,18 +2025-03-11T12:41:49.168731,479392908,65329,227,-25.72435699426,-37.733286852795,49.174853051515,2,1,18 +2025-03-11T12:41:49.184356,479392908,65329,227,-25.4746211734,-37.506422226225,48.76692108853,2,1,18 +2025-03-11T12:41:49.199981,479392908,65329,227,-25.24373333902,-37.270348067865,48.349736803435,2,1,18 +2025-03-11T12:41:49.215606,479392908,65329,227,-25.00813350802,-37.029644684715,47.923284831205,2,1,18 +2025-03-11T12:41:49.231231,479392908,65329,227,-24.79609366012,-36.784360994565,47.510711773195,2,1,18 +2025-03-11T12:41:49.246856,479392908,65329,227,-24.56049382912,-36.552899755065,47.09816043016,2,1,18 +2025-03-11T12:41:49.262481,479392908,65329,227,-24.31075800826,-36.316792984845,46.65784310572,2,1,18 +2025-03-11T12:41:49.278106,479392908,65329,227,-24.07515817726,-36.08995281717,46.22220438736,2,1,18 +2025-03-11T12:41:49.293731,479392908,65329,227,-23.8254223564,-35.858467118775,45.795769152115,2,1,18 +2025-03-11T12:41:49.309356,479392908,65329,227,-23.5898225254,-35.608521591975,45.36465891682,2,1,18 +2025-03-11T12:41:49.324981,479392908,65329,227,-23.3542226944,-35.349333921525,44.933511601525,2,1,18 +2025-03-11T12:41:49.340606,479392908,65329,227,-23.1186228634,-35.108630538375,44.48395371397,2,1,18 +2025-03-11T12:41:49.356231,479392908,65329,227,-22.8830230324,-34.867927155225,44.03901700948,2,1,18 +2025-03-11T12:41:49.371856,479392908,65329,227,-22.63328721154,-34.631820385005,43.60794205117,2,1,18 +2025-03-11T12:41:49.387481,479392908,65329,227,-22.38355139068,-34.386471471135,43.153724097535,2,1,18 +2025-03-11T12:41:49.403106,479392908,65329,227,-22.14795155968,-34.14114701616,42.699526486915,2,1,18 +2025-03-11T12:41:49.418731,479392908,65329,227,-21.89821573882,-33.88655595864,42.25451381941,2,1,18 +2025-03-11T12:41:49.434356,479392908,65329,227,-21.64847991796,-33.63196490112,41.800258785775,2,1,18 +2025-03-11T12:41:49.449981,479392908,65329,227,-21.40345609372,-33.386624140215,41.336805247015,2,1,18 +2025-03-11T12:41:49.465606,479392908,65329,227,-21.1631442661,-33.1459126041,40.88261939539,2,1,18 +2025-03-11T12:41:49.481231,479392908,65329,227,-20.91340844524,-32.89132154658,40.43298554482,2,1,18 +2025-03-11T12:41:49.496856,479392908,65329,227,-20.66367262438,-32.62748834541,39.969451065055,2,1,18 +2025-03-11T12:41:49.512481,479392908,65329,227,-20.39508881704,-32.386727891505,39.5152245274,2,1,18 +2025-03-11T12:41:49.528106,479392908,65329,227,-20.15477698942,-32.13677421174,39.03789568045,2,1,18 +2025-03-11T12:41:49.543731,479392908,65329,227,-19.8909051787,-31.86829547985,38.56507995154,2,1,18 +2025-03-11T12:41:49.559356,479392908,65329,227,-19.62703336798,-31.61830103526,38.087717199565,2,1,18 +2025-03-11T12:41:49.574981,479392908,65329,227,-19.3725855505,-31.3683228966,37.605746826535,2,1,18 +2025-03-11T12:41:49.590606,479392908,65329,227,-19.11813773302,-31.10910261429,37.132981739635,2,1,18 +2025-03-11T12:41:49.606231,479392908,65329,227,-18.85897791892,-30.840632035365,36.66941515786,2,1,18 +2025-03-11T12:41:49.621856,479392908,65329,227,-18.5951061082,-30.572153303475,36.182735879755,2,1,18 +2025-03-11T12:41:49.637481,479392908,65329,227,-18.33123429748,-30.303674571585,35.700677784715,2,1,18 +2025-03-11T12:41:49.653106,479392908,65329,227,-18.07207448338,-30.04444613631,35.223284733745,2,1,18 +2025-03-11T12:41:49.668731,479392908,65329,227,-17.80349067604,-29.785201395105,34.773605219155,2,1,18 +2025-03-11T12:41:49.684356,479392908,65329,227,-17.52548287546,-29.50745606067,34.2914897011,2,1,18 +2025-03-11T12:41:49.699981,479392908,65329,227,-17.27103505798,-29.234372562885,33.80942662807,2,1,18 +2025-03-11T12:41:49.715606,479392908,65329,227,-17.02601123374,-28.97054751468,33.32741419705,2,1,18 +2025-03-11T12:41:49.731231,479392908,65329,227,-16.75271542978,-28.71129462051,32.831516070805,2,1,18 +2025-03-11T12:41:49.746856,479392908,65329,227,-16.46999563258,-28.43354113311,32.349393771745,2,1,18 +2025-03-11T12:41:49.762481,479392908,65329,227,-16.20141182524,-28.16967532008,31.83962033731,2,1,18 +2025-03-11T12:41:49.778106,479392908,65329,227,-15.9328280179,-27.90580950705,31.33446808594,2,1,18 +2025-03-11T12:41:49.793731,479392908,65329,227,-15.6736682038,-27.628096784475,30.84775850884,2,1,18 +2025-03-11T12:41:49.809356,479392908,65329,227,-15.40508439646,-27.35036775597,30.3517930036,2,1,18 +2025-03-11T12:41:49.824981,479392908,65329,227,-15.1317885925,-27.077251646325,29.86970280655,2,1,18 +2025-03-11T12:41:49.840606,479392908,65329,227,-14.85378079192,-26.80874845554,29.3737608193,2,1,18 +2025-03-11T12:41:49.856231,479392908,65329,227,-14.57577299134,-26.52638204928,28.87776321205,2,1,18 +2025-03-11T12:41:49.871856,479392908,65329,227,-14.30247718738,-26.25788701146,28.381828005805,2,1,18 +2025-03-11T12:41:49.887481,479392908,65329,227,-14.02918138342,-25.975528758165,27.87659481343,2,1,18 +2025-03-11T12:41:49.903106,479392908,65329,227,-13.75117358284,-25.68854128008,27.37133630005,2,1,18 +2025-03-11T12:41:49.918731,479392908,65329,227,-13.47316578226,-25.401553801995,26.870698969735,2,1,18 +2025-03-11T12:41:49.934356,479392908,65329,227,-13.19044598506,-25.114558170945,26.34694894309,2,1,18 +2025-03-11T12:41:49.949981,479392908,65329,227,-12.92657417434,-24.836837295405,25.82788430353,2,1,18 +2025-03-11T12:41:49.965606,479392908,65329,227,-12.64856637376,-24.563713032795,25.318060227085,2,1,18 +2025-03-11T12:41:49.981231,479392908,65329,227,-12.35642258332,-24.29056431129,24.808215807625,2,1,18 +2025-03-11T12:41:49.996795,479392912,65325,228,-12.0689907895,-24.01742374275,24.284514619975,2,1,18 +2025-03-11T12:41:50.012420,479392912,65325,228,-11.79098298892,-23.73505733649,23.77465346353,2,1,18 +2025-03-11T12:41:50.028045,479392912,65325,228,-11.52239918158,-23.47119152346,23.255637662965,2,1,18 +2025-03-11T12:41:50.043670,479392912,65325,228,-11.23496738776,-23.17956666762,22.741104681445,2,1,18 +2025-03-11T12:41:50.059295,479392912,65325,228,-10.94282359732,-22.878691515165,22.212664289725,2,1,18 +2025-03-11T12:41:50.074920,479392912,65325,228,-10.65067980688,-22.591679578185,21.702764250265,2,1,18 +2025-03-11T12:41:50.090545,479392912,65325,228,-10.36324801306,-22.318539009645,21.18368424568,2,1,18 +2025-03-11T12:41:50.106170,479392912,65325,228,-10.0899522091,-22.040801828175,20.65536367798,2,1,18 +2025-03-11T12:41:50.121795,479392912,65325,228,-9.81665640514,-21.76768571853,20.131682833345,2,1,18 +2025-03-11T12:41:50.137420,479392912,65325,228,-9.53864860456,-21.48531931227,19.63106404303,2,1,18 +2025-03-11T12:41:50.153045,479392912,65325,228,-9.25121681074,-21.19369445643,19.11653106151,2,1,18 +2025-03-11T12:41:50.168670,479392912,65325,228,-8.94964902706,-20.892802998045,18.57883474165,2,1,18 +2025-03-11T12:41:50.184295,479392912,65325,228,-8.67164122648,-20.60581551996,18.050470312945,2,1,18 +2025-03-11T12:41:50.199920,479392912,65325,228,-8.38892142928,-20.30957774526,17.531304389365,2,1,18 +2025-03-11T12:41:50.215545,479392912,65325,228,-8.10148963546,-20.02719503307,16.989081389455,2,1,18 +2025-03-11T12:41:50.231170,479392912,65325,228,-7.8046338484,-19.730932799475,16.456031573665,2,1,18 +2025-03-11T12:41:50.246795,479392912,65325,228,-7.51249005796,-19.43005764702,15.927591181945,2,1,18 +2025-03-11T12:41:50.262420,479392912,65325,228,-7.22034626752,-19.13380356639,15.399169330225,2,1,18 +2025-03-11T12:41:50.278045,479392912,65325,228,-6.9329144737,-18.84217871055,14.893878714835,2,1,18 +2025-03-11T12:41:50.293670,479392912,65325,228,-6.6501946765,-18.54594093585,14.37009160819,2,1,18 +2025-03-11T12:41:50.309295,479392912,65325,228,-6.37218687592,-18.24509024229,13.823186827225,2,1,18 +2025-03-11T12:41:50.324920,479392912,65325,228,-6.0847550821,-17.9442232428,13.29475321651,2,1,18 +2025-03-11T12:41:50.340545,479392912,65325,228,-5.78318729842,-17.661816071715,12.752509873585,2,1,18 +2025-03-11T12:41:50.356170,479392912,65325,228,-5.48161951474,-17.37016675698,12.21022945066,2,1,18 +2025-03-11T12:41:50.371795,479392912,65325,228,-5.1894757243,-17.07391267635,11.68180759894,2,1,18 +2025-03-11T12:41:50.387420,479392912,65325,228,-4.90204393048,-16.768424605035,11.13949189903,2,1,18 +2025-03-11T12:41:50.403045,479392912,65325,228,-4.60518814342,-16.486025586915,10.583391787915,2,1,18 +2025-03-11T12:41:50.418670,479392912,65325,228,-4.30362035974,-16.18513412853,10.054937834185,2,1,18 +2025-03-11T12:41:50.434295,479392912,65325,228,-4.00205257606,-15.902726957445,9.51269449126,2,1,18 +2025-03-11T12:41:50.449920,479392912,65325,228,-3.70048479238,-15.61107764271,8.96579288527,2,1,18 +2025-03-11T12:41:50.465545,479392912,65325,228,-3.39420501208,-15.305556959535,8.42345006134,2,1,18 +2025-03-11T12:41:50.481170,479392912,65325,228,-3.11148521488,-15.00469811301,7.89502323163,2,1,18 +2025-03-11T12:41:50.496795,479392912,65325,228,-2.81934142444,-14.703822960555,7.36658283991,2,1,18 +2025-03-11T12:41:50.512420,479392912,65325,228,-2.54133362386,-14.402972266995,6.819678058945,2,1,18 +2025-03-11T12:41:50.528045,479392912,65325,228,-2.25390183004,-14.111347411155,6.27279679597,2,1,18 +2025-03-11T12:41:50.543670,479392912,65325,228,-1.9617580396,-13.824335474175,5.73516965812,2,1,18 +2025-03-11T12:41:50.559295,479392912,65325,228,-1.64605426606,-13.504935269595,5.188136469115,2,1,18 +2025-03-11T12:41:50.574920,479392912,65325,228,-1.33977448576,-13.204035658245,4.655054551315,2,1,18 +2025-03-11T12:41:50.590545,479392912,65325,228,-1.03820670208,-12.91238634351,4.117395311455,2,1,18 +2025-03-11T12:41:50.606170,479392912,65325,228,-0.7366389184,-12.620737028775,3.570493705465,2,1,18 +2025-03-11T12:41:50.621795,479392912,65325,228,-0.43978313134,-12.32447479518,3.02358034048,2,1,18 +2025-03-11T12:41:50.637420,479392912,65325,228,-0.15235133752,-12.01436565204,2.458140185245,2,1,18 +2025-03-11T12:41:50.653045,479392912,65325,228,0.1350804563,-11.718119724375,1.91124038227,2,1,18 +2025-03-11T12:41:50.668670,479392912,65325,228,0.43664823998,-11.41722826599,1.368922879345,2,1,18 +2025-03-11T12:41:50.684295,479392912,65325,228,0.7476400169,-11.107078358025,0.831175917475,2,1,18 +2025-03-11T12:41:50.699920,479392912,65325,228,1.04449580396,-10.806195052605,0.29348637862,2,1,18 +2025-03-11T12:41:50.715545,479392912,65325,228,1.34135159102,-10.49144853171,-0.244258780235,2,1,18 +2025-03-11T12:41:50.731170,479392912,65325,228,1.65705536456,-10.195153686255,-0.79119926924,2,1,18 +2025-03-11T12:41:50.746795,479392912,65325,228,1.94448715838,-9.88966561494,-1.33351496915,2,1,18 +2025-03-11T12:41:50.762420,479392912,65325,228,2.2319189522,-9.593419687275,-1.871172405995,2,1,18 +2025-03-11T12:41:50.778045,479392912,65325,228,2.5381987325,-9.2878990041,-2.441242328315,2,1,18 +2025-03-11T12:41:50.793670,479392912,65325,228,2.8444785128,-9.0147258237,-2.98807655531,2,1,18 +2025-03-11T12:41:50.809295,479392912,65325,228,3.13191030662,-8.71385882421,-3.53037371522,2,1,18 +2025-03-11T12:41:50.824920,479392912,65325,228,3.42876609368,-8.41297551879,-4.077305620205,2,1,18 +2025-03-11T12:41:50.840545,479392912,65325,228,3.73504587398,-8.11207590744,-4.628872270265,2,1,18 +2025-03-11T12:41:50.856170,479392912,65325,228,4.04132565428,-7.825039511565,-5.18500448339,2,1,18 +2025-03-11T12:41:50.871795,479392912,65325,228,4.33818144134,-7.524156206145,-5.72731520531,2,1,18 +2025-03-11T12:41:50.887420,479392912,65325,228,4.63032523178,-7.209417838215,-6.27429594929,2,1,18 +2025-03-11T12:41:50.903045,479392912,65325,228,4.93660501208,-6.90389715504,-6.82588113935,2,1,18 +2025-03-11T12:41:50.918670,479392912,65325,228,5.24288479238,-6.60299754369,-7.36820542328,2,1,18 +2025-03-11T12:41:50.934295,479392912,65325,228,5.53974057944,-6.31135638192,-7.905857882135,2,1,18 +2025-03-11T12:41:50.949920,479392912,65325,228,5.84130836312,-6.00584385171,-8.46667865732,2,1,18 +2025-03-11T12:41:50.965545,479392912,65325,228,6.13345215356,-5.71883191473,-9.018169344365,2,1,18 +2025-03-11T12:41:50.981170,479392912,65325,228,6.42088394738,-5.404101699765,-9.569764490405,2,1,18 +2025-03-11T12:41:50.996795,479392912,65325,228,6.7083157412,-5.084750412975,-10.10751462725,2,1,18 +2025-03-11T12:41:51.012420,479392912,65325,228,7.00988352488,-4.80234324189,-10.65437915324,2,1,18 +2025-03-11T12:41:51.028045,479392912,65325,228,7.32558729842,-4.515290540085,-11.192040196115,2,1,18 +2025-03-11T12:41:51.043670,479392912,65325,228,7.63186707872,-4.20052771326,-11.72979891698,2,1,18 +2025-03-11T12:41:51.059295,479392912,65325,228,7.9334348624,-3.91349947035,-12.24895488458,2,1,18 +2025-03-11T12:41:51.074920,479392912,65325,228,8.23029064946,-3.635721524055,-12.786551723435,2,1,18 +2025-03-11T12:41:51.090545,479392912,65325,228,8.53657042976,-3.33020084088,-13.33351573043,2,1,18 +2025-03-11T12:41:51.106170,479392912,65325,228,8.8287142202,-2.99697818565,-13.894434183605,2,1,18 +2025-03-11T12:41:51.121795,479392912,65325,228,9.13028200388,-2.686844583615,-14.45527349879,2,1,18 +2025-03-11T12:41:51.137420,479392912,65325,228,9.42713779094,-2.404445565495,-14.974404145385,2,1,18 +2025-03-11T12:41:51.153045,479392912,65325,228,9.72870557462,-2.117417322585,-15.512044845245,2,1,18 +2025-03-11T12:41:51.168670,479392912,65325,228,10.02084936506,-1.82578431378,-16.06355407229,2,1,18 +2025-03-11T12:41:51.184295,479392912,65325,228,10.30356916226,-1.52030439543,-16.61048417426,2,1,18 +2025-03-11T12:41:51.199920,479392912,65325,228,10.5957129527,-1.21480817115,-17.14818547211,2,1,18 +2025-03-11T12:41:51.215545,479392912,65325,228,10.88314474652,-0.92318331531,-17.676582002825,2,1,18 +2025-03-11T12:41:51.231170,479392912,65325,228,11.18942452682,-0.63152584761,-18.218869206755,2,1,18 +2025-03-11T12:41:51.246795,479392912,65325,228,11.48628031388,-0.330642542190001,-18.761179928675,2,1,18 +2025-03-11T12:41:51.262420,479392912,65325,228,11.78784809756,-0.0297510838050004,-19.317360980795,2,1,18 +2025-03-11T12:41:51.278045,479392912,65325,228,12.08941588124,0.266519302755,-19.855038760655,2,1,18 +2025-03-11T12:41:51.293670,479392912,65325,228,12.37213567844,0.562757077455,-20.383447050365,2,1,18 +2025-03-11T12:41:51.309295,479392912,65325,228,12.65485547564,0.858994852155,-20.92571888927,2,1,18 +2025-03-11T12:41:51.324920,479392912,65325,228,12.93757527284,1.145990483205,-21.44484773285,2,1,18 +2025-03-11T12:41:51.340545,479392912,65325,228,13.2344310599,1.4237684295,-21.97782338864,2,1,18 +2025-03-11T12:41:51.356170,479392912,65325,228,13.5407108402,1.710804825375,-22.524713235635,2,1,18 +2025-03-11T12:41:51.371795,479392912,65325,228,13.82814263402,2.002429681215,-23.048488583285,2,1,18 +2025-03-11T12:41:51.387420,479392912,65325,228,14.12028642446,2.29406269002,-23.58151307807,2,1,18 +2025-03-11T12:41:51.403045,479392912,65325,228,14.42185420814,2.58109093293,-24.1099114118,2,1,18 +2025-03-11T12:41:51.418670,479392912,65325,228,14.70457400534,2.88657085128,-24.63835678151,2,1,18 +2025-03-11T12:41:51.434295,479392912,65325,228,14.98258180592,3.17817940119,-25.166739750215,2,1,18 +2025-03-11T12:41:51.449920,479392912,65325,228,15.27001359974,3.46056211338,-25.708962750125,2,1,18 +2025-03-11T12:41:51.465545,479392912,65325,228,15.5668693868,3.75220327515,-26.241994025915,2,1,18 +2025-03-11T12:41:51.481170,479392912,65325,228,15.86372517386,4.048465508745,-26.765801475575,2,1,18 +2025-03-11T12:41:51.496795,479392912,65325,228,16.16058096092,4.34472774234,-27.308093657495,2,1,18 +2025-03-11T12:41:51.512420,479392912,65325,228,16.45272475136,4.636360751145,-27.836496969215,2,1,18 +2025-03-11T12:41:51.528045,479392912,65325,228,16.73544454856,4.92797745402,-28.346401986665,2,1,18 +2025-03-11T12:41:51.543670,479392912,65325,228,17.0040283559,5.2010854107,-28.860833684165,2,1,18 +2025-03-11T12:41:51.559295,479392912,65325,228,17.29146014972,5.50195241019,-29.384646111815,2,1,18 +2025-03-11T12:41:51.574920,479392912,65325,228,17.57889194354,5.807440481505,-29.908477079465,2,1,18 +2025-03-11T12:41:51.590545,479392912,65325,228,17.86632373736,6.08520212187,-30.413712074855,2,1,18 +2025-03-11T12:41:51.606170,479392912,65325,228,18.15375553118,6.362963762235,-30.937431802505,2,1,18 +2025-03-11T12:41:51.621795,479392912,65325,228,18.45061131824,6.64074170853,-31.451922726035,2,1,18 +2025-03-11T12:41:51.637420,479392912,65325,228,18.74275510868,6.92775364551,-31.97568631469,2,1,18 +2025-03-11T12:41:51.653045,479392912,65325,228,19.02076290926,7.214741123595,-32.4901871942,2,1,18 +2025-03-11T12:41:51.668670,479392912,65325,228,19.29877070984,7.497107529855,-32.99542716758,2,1,18 +2025-03-11T12:41:51.684295,479392912,65325,228,19.58620250366,7.770248098395,-33.51912835523,2,1,18 +2025-03-11T12:41:51.699920,479392912,65325,228,19.87363429748,8.05725188241,-34.056748712075,2,1,18 +2025-03-11T12:41:51.715545,479392912,65325,228,20.1375061082,8.3442149016,-34.56198688244,2,1,18 +2025-03-11T12:41:51.731170,479392912,65325,228,20.40608991554,8.631186073755,-35.071853016875,2,1,18 +2025-03-11T12:41:51.746795,479392912,65325,228,20.66996172626,8.89504373382,-35.57699848724,2,1,18 +2025-03-11T12:41:51.762420,479392912,65325,228,20.95268152346,9.177418293045,-36.08686642469,2,1,18 +2025-03-11T12:41:51.778045,479392912,65325,228,21.22597732742,9.46901868999,-36.587515514,2,1,18 +2025-03-11T12:41:51.793670,479392912,65325,228,21.503985128,9.73290080895,-37.08343896125,2,1,18 +2025-03-11T12:41:51.809295,479392912,65325,228,21.7867049252,10.01065429635,-37.579424809505,2,1,18 +2025-03-11T12:41:51.824920,479392912,65325,228,22.05057673592,10.27913302824,-38.08458881987,2,1,18 +2025-03-11T12:41:51.840545,479392912,65325,228,22.32387253988,10.55687020971,-38.571318739985,2,1,18 +2025-03-11T12:41:51.856170,479392912,65325,228,22.59245634722,10.816114950915,-39.06258890216,2,1,18 +2025-03-11T12:41:51.871795,479392912,65325,228,22.86575215118,11.08923106056,-39.549300282275,2,1,18 +2025-03-11T12:41:51.887420,479392912,65325,228,23.14847194838,11.380847763435,-40.06382648279,2,1,18 +2025-03-11T12:41:51.903045,479392912,65325,228,23.4123437591,11.6447054235,-40.559729587025,2,1,18 +2025-03-11T12:41:51.918670,479392912,65325,228,23.68563956306,11.908579389495,-41.05564625327,2,1,18 +2025-03-11T12:41:51.934295,479392912,65325,228,23.94951137378,12.177058121385,-41.55618908057,2,1,18 +2025-03-11T12:41:51.949920,479392912,65325,228,24.22280717774,12.454795302855,-42.04754018375,2,1,18 +2025-03-11T12:41:51.965545,479392912,65325,228,24.49139098508,12.727903259535,-42.53424478286,2,1,18 +2025-03-11T12:41:51.981170,479392912,65325,228,24.75055079918,13.010237053935,-43.02097289996,2,1,18 +2025-03-11T12:41:51.996795,479392912,65325,228,25.02384660314,13.26486887628,-43.498367753945,2,1,18 +2025-03-11T12:41:52.012420,479392912,65325,228,25.28300641724,13.51947623973,-43.966499898785,2,1,18 +2025-03-11T12:41:52.028045,479392912,65325,228,25.54216623134,13.77408360318,-44.443874409755,2,1,18 +2025-03-11T12:41:52.043670,479392912,65325,228,25.81075003868,14.04719155986,-44.921336642735,2,1,18 +2025-03-11T12:41:52.059295,479392912,65325,228,26.08404584264,14.311065525855,-45.41725330898,2,1,18 +2025-03-11T12:41:52.074920,479392912,65325,228,26.34791765336,14.570302114095,-45.894653140955,2,1,18 +2025-03-11T12:41:52.090545,479392912,65325,228,26.59765347422,14.82027209979,-46.34888963459,2,1,18 +2025-03-11T12:41:52.106170,479392912,65325,228,26.84267729846,15.07947607617,-46.83088352561,2,1,18 +2025-03-11T12:41:52.121795,479392912,65325,228,27.1112611058,15.3433418892,-47.322172227785,2,1,18 +2025-03-11T12:41:52.137420,479392912,65325,228,27.36570892328,15.607183243335,-47.79033467162,2,1,18 +2025-03-11T12:41:52.153045,479392912,65325,228,27.61544474414,15.86639537268,-48.253850611385,2,1,18 +2025-03-11T12:41:52.168670,479392912,65325,228,27.86989256162,16.10713136769,-48.72192035522,2,1,18 +2025-03-11T12:41:52.184295,479392912,65325,228,28.12905237572,16.347875515665,-49.185375696995,2,1,18 +2025-03-11T12:41:52.199920,479392912,65325,228,28.38821218982,16.602482879115,-49.64888665877,2,1,18 +2025-03-11T12:41:52.215545,479392912,65325,228,28.63323601406,16.85706578367,-50.080028996075,2,1,18 +2025-03-11T12:41:52.231170,479392912,65325,228,28.88768383154,17.12552820963,-50.52972524765,2,1,18 +2025-03-11T12:41:52.246795,479392912,65325,228,29.14213164902,17.37550634829,-50.99321088842,2,1,18 +2025-03-11T12:41:52.262420,479392912,65325,228,29.38244347664,17.61159681258,-51.428893467785,2,1,18 +2025-03-11T12:41:52.278045,479392912,65325,228,29.6321792975,17.85694572645,-51.896974970615,2,1,18 +2025-03-11T12:41:52.293670,479392912,65325,228,29.87249112512,18.09303619074,-52.365005831435,2,1,18 +2025-03-11T12:41:52.309295,479392912,65325,228,30.1269389426,18.3430143294,-52.800764373815,2,1,18 +2025-03-11T12:41:52.324920,479392912,65325,228,30.37196276684,18.597597233955,-53.23190671112,2,1,18 +2025-03-11T12:41:52.340545,479392912,65325,228,30.60285060122,18.84753460779,-53.676873714605,2,1,18 +2025-03-11T12:41:52.356170,479392912,65325,228,30.8337384356,19.08360876615,-54.12178509809,2,1,18 +2025-03-11T12:41:52.371795,479392912,65325,228,31.08347425646,19.324336608195,-54.557499779465,2,1,18 +2025-03-11T12:41:52.387420,479392912,65325,228,31.33321007732,19.59279088119,-54.98408333471,2,1,18 +2025-03-11T12:41:52.403045,479392912,65325,228,31.5640979117,19.833486111375,-55.415149709,2,1,18 +2025-03-11T12:41:52.418670,479392912,65325,228,31.79498574608,20.05569705426,-55.83689955716,2,1,18 +2025-03-11T12:41:52.434295,479392912,65325,228,32.02587358046,20.268665853495,-56.28633942371,2,1,18 +2025-03-11T12:41:52.449920,479392912,65325,228,32.25204941822,20.51397400254,-56.735902289255,2,1,18 +2025-03-11T12:41:52.465545,479392912,65325,228,32.48764924922,20.750056313865,-57.162335721485,2,1,18 +2025-03-11T12:41:52.481170,479392912,65325,228,32.73738507008,20.98154201226,-57.556422675275,2,1,18 +2025-03-11T12:41:52.496795,479392912,65325,228,32.97298490108,21.21300325176,-57.973595201375,2,1,18 +2025-03-11T12:41:52.512420,479392912,65325,228,33.19916073884,21.449069257155,-58.40463625466,2,1,18 +2025-03-11T12:41:52.528045,479392912,65325,228,33.43004857322,21.68052234369,-58.812559633625,2,1,18 +2025-03-11T12:41:52.543670,479392912,65325,228,33.6609364076,21.9073543584,-59.22046447259,2,1,18 +2025-03-11T12:41:52.559295,479392912,65325,228,33.8729762555,22.11566947395,-59.646752759795,2,1,18 +2025-03-11T12:41:52.574920,479392912,65325,228,34.08030410678,22.342460723835,-60.05000251067,2,1,18 +2025-03-11T12:41:52.590545,479392912,65325,228,34.30176794792,22.56465536079,-60.42552696617,2,1,18 +2025-03-11T12:41:52.606170,479392912,65325,228,34.51380779582,22.786833691815,-60.824143774985,2,1,18 +2025-03-11T12:41:52.621795,479392912,65325,228,34.73527163696,22.995165113295,-61.245824441135,2,1,18 +2025-03-11T12:41:52.637420,479392912,65325,228,34.96144747472,23.22198897504,-61.64910131603,2,1,18 +2025-03-11T12:41:52.653045,479392912,65325,228,35.17348732262,23.444167306065,-62.019991026455,2,1,18 +2025-03-11T12:41:52.668670,479392912,65325,228,35.39023916714,23.66173271823,-62.427838442405,2,1,18 +2025-03-11T12:41:52.684295,479392912,65325,228,35.6164150049,23.86545122085,-62.8310226173,2,1,18 +2025-03-11T12:41:52.699920,479392912,65325,228,35.84259084266,24.06916972347,-63.206479693805,2,1,18 +2025-03-11T12:41:52.715545,479392912,65325,228,36.05934268718,24.28211406381,-63.5819602883,2,1,18 +2025-03-11T12:41:52.731170,479392912,65325,228,36.26667053846,24.490421026395,-63.96202996385,2,1,18 +2025-03-11T12:41:52.746795,479392912,65325,228,36.47399838974,24.71721227628,-64.35141616553,2,1,18 +2025-03-11T12:41:52.762420,479392912,65325,228,36.68132624102,24.934761382515,-64.745386470275,2,1,18 +2025-03-11T12:41:52.778045,479392912,65325,228,36.88394209568,25.133818048485,-65.120791101755,2,1,18 +2025-03-11T12:41:52.793670,479392912,65325,228,37.1006939402,25.33289917335,-65.491594893185,2,1,18 +2025-03-11T12:41:52.809295,479392912,65325,228,37.30330979486,25.53195583932,-65.848514792405,2,1,18 +2025-03-11T12:41:52.824920,479392912,65325,228,37.5012136529,25.749488639625,-66.21474443675,2,1,18 +2025-03-11T12:41:52.840545,479392912,65325,228,37.69911751094,25.95777929628,-66.58555818416,2,1,18 +2025-03-11T12:41:52.856170,479392912,65325,228,37.89702136898,26.15220673746,-66.95631631157,2,1,18 +2025-03-11T12:41:52.871795,479392912,65325,228,38.08550123378,26.33737572906,-67.331644980035,2,1,18 +2025-03-11T12:41:52.887420,479392912,65325,228,38.28340509182,26.554908529365,-67.684011075185,2,1,18 +2025-03-11T12:41:52.903045,479392912,65325,228,38.46717296,26.74931151165,-68.031642944255,2,1,18 +2025-03-11T12:41:52.918670,479392912,65325,228,38.65094082818,26.934472350285,-68.37461655026,2,1,18 +2025-03-11T12:41:52.934295,479392912,65325,228,38.8441326896,27.1288916385,-68.73150434747,2,1,18 +2025-03-11T12:41:52.949920,479392912,65325,228,39.04674854426,27.314085088995,-69.083747443625,2,1,18 +2025-03-11T12:41:52.965545,479392912,65325,228,39.2446524023,27.50389145835,-69.426759932645,2,1,18 +2025-03-11T12:41:52.981170,479392912,65325,228,39.42842027048,27.69367336881,-69.75126734639,2,1,18 +2025-03-11T12:41:52.996795,479392912,65325,228,39.61690013528,27.874221288585,-70.0942291934,2,1,18 +2025-03-11T12:41:53.012420,479392912,65325,228,39.80066800346,28.05013998357,-70.43254453634,2,1,18 +2025-03-11T12:41:53.028045,479392912,65325,228,39.9750118784,28.235284516275,-70.76164103114,2,1,18 +2025-03-11T12:41:53.043670,479392912,65325,228,40.1634917432,28.4065902924,-71.090702248955,2,1,18 +2025-03-11T12:41:53.059295,479392912,65325,228,40.33783561814,28.591734825105,-71.419798743755,2,1,18 +2025-03-11T12:41:53.074920,479392912,65325,228,40.51217949308,28.763016142335,-71.75346080162,2,1,18 +2025-03-11T12:41:53.090545,479392912,65325,228,40.68652336802,28.93891853139,-72.05479311803,2,1,18 +2025-03-11T12:41:53.106170,479392912,65325,228,40.87500323282,29.110224307515,-72.36999078665,2,1,18 +2025-03-11T12:41:53.121795,479392912,65325,228,41.058771101,29.2861430025,-72.6805790312,2,1,18 +2025-03-11T12:41:53.137420,479392912,65325,228,41.2236909827,29.4574080138,-72.995742794795,2,1,18 +2025-03-11T12:41:53.153045,479392912,65325,228,41.39332286102,29.63330224989,-73.30631069633,2,1,18 +2025-03-11T12:41:53.168670,479392912,65325,228,41.54881874948,29.79530881161,-73.621423817915,2,1,18 +2025-03-11T12:41:53.184295,479392912,65325,228,41.71373863118,29.93884739196,-73.922612792315,2,1,18 +2025-03-11T12:41:53.199920,479392912,65325,228,41.87865851288,30.105491331435,-74.214652100585,2,1,18 +2025-03-11T12:41:53.215545,479392912,65325,228,42.03886639796,30.28599033342,-74.51598261398,2,1,18 +2025-03-11T12:41:53.231170,479392912,65325,228,42.20378627966,30.45725534472,-74.803419279185,2,1,18 +2025-03-11T12:41:53.246795,479392912,65325,228,42.3545701715,30.610011609825,-75.072276709115,2,1,18 +2025-03-11T12:41:53.262420,479392912,65325,228,42.51006605996,30.76739709972,-75.35964419231,2,1,18 +2025-03-11T12:41:53.278045,479392912,65325,228,42.66556194842,30.92940366144,-75.656272581635,2,1,18 +2025-03-11T12:41:53.293670,479392912,65325,228,42.81634584026,31.082159926545,-75.943614743825,2,1,18 +2025-03-11T12:41:53.309295,479392912,65325,228,42.97655372534,31.230311425755,-76.203224829635,2,1,18 +2025-03-11T12:41:53.324920,479392912,65325,228,43.13676161042,31.369220781315,-76.472040201575,2,1,18 +2025-03-11T12:41:53.340545,479392912,65325,228,43.30168149212,31.503517218015,-76.75008618065,2,1,18 +2025-03-11T12:41:53.356170,479392912,65325,228,43.4383293941,31.66087009605,-77.0143206245,2,1,18 +2025-03-11T12:41:53.371795,479392912,65325,228,43.57026529946,31.79973053382,-77.28309531041,2,1,18 +2025-03-11T12:41:53.387420,479392912,65325,228,43.7210491913,31.952486798925,-77.55195274034,2,1,18 +2025-03-11T12:41:53.403045,479392912,65325,228,43.85298509666,32.08672616487,-77.80222415399,2,1,18 +2025-03-11T12:41:53.418670,479392912,65325,228,43.98963299864,32.21173154013,-78.04784408558,2,1,18 +2025-03-11T12:41:53.434295,479392912,65325,228,44.13570489386,32.369100724095,-78.32133445757,2,1,18 +2025-03-11T12:41:53.449920,479392912,65325,228,44.27235279584,32.512590386655,-78.55778618303,2,1,18 +2025-03-11T12:41:53.465545,479392912,65325,228,44.41371269444,32.651467130355,-78.80808969869,2,1,18 +2025-03-11T12:41:53.481170,479392912,65325,228,44.5456485998,32.781085424475,-79.05834257234,2,1,18 +2025-03-11T12:41:53.496795,479392912,65325,228,44.67758450516,32.910703718595,-79.29011071373,2,1,18 +2025-03-11T12:41:53.512420,479392912,65325,228,44.80952041052,33.040322012715,-79.535742404315,2,1,18 +2025-03-11T12:41:53.528045,479392912,65325,228,44.92732032602,33.16067370429,-79.781316671885,2,1,18 +2025-03-11T12:41:53.543670,479392912,65325,228,45.05454423476,33.28566277362,-80.017680675335,2,1,18 +2025-03-11T12:41:53.559295,479392912,65325,228,45.18648014012,33.41528106774,-80.249448816725,2,1,18 +2025-03-11T12:41:53.574920,479392912,65325,228,45.299568059,33.53562460635,-80.471910387965,2,1,18 +2025-03-11T12:41:53.590545,479392912,65325,228,45.40794398126,33.65133892017,-80.680483089005,2,1,18 +2025-03-11T12:41:53.606170,479392912,65325,228,45.53045589338,33.776319836535,-80.893734396125,2,1,18 +2025-03-11T12:41:53.621795,479392912,65325,228,45.6529678055,33.9013007529,-81.106985703245,2,1,18 +2025-03-11T12:41:53.637420,479392912,65325,228,45.77547971762,34.017039525615,-81.320199930365,2,1,18 +2025-03-11T12:41:53.653045,479392912,65325,228,45.88385563988,34.123511695785,-81.519493185275,2,1,18 +2025-03-11T12:41:53.668670,479392912,65325,228,45.99694355876,34.23923416257,-81.732693850385,2,1,18 +2025-03-11T12:41:53.684295,479392912,65325,228,46.11003147764,34.35033555753,-81.927391243235,2,1,18 +2025-03-11T12:41:53.699920,479392912,65325,228,46.22311939652,34.47992123979,-82.12678397915,2,1,18 +2025-03-11T12:41:53.715545,479392912,65325,228,46.32207132554,34.58637710403,-82.330684855115,2,1,18 +2025-03-11T12:41:53.731170,479392912,65325,228,46.42573525118,34.68822004941,-82.497604507565,2,1,18 +2025-03-11T12:41:53.746795,479392912,65325,228,46.53411117344,34.79469221958,-82.696897762475,2,1,18 +2025-03-11T12:41:53.762420,479392912,65325,228,46.63306310246,34.90114808382,-82.886935089245,2,1,18 +2025-03-11T12:41:53.778045,479392912,65325,228,46.73201503148,34.993740732585,-83.049189697625,2,1,18 +2025-03-11T12:41:53.793670,479392912,65325,228,46.84039095374,35.07710754363,-83.220663154145,2,1,18 +2025-03-11T12:41:53.809295,479392912,65325,228,46.93934288276,35.17432126422,-83.401421034785,2,1,18 +2025-03-11T12:41:53.824920,479392912,65325,228,47.02415882192,35.28537374139,-83.568350643215,2,1,18 +2025-03-11T12:41:53.840545,479392912,65325,228,47.1136867577,35.387192227875,-83.739871135715,2,1,18 +2025-03-11T12:41:53.856170,479392912,65325,228,47.19850269686,35.461276130445,-83.906652424145,2,1,18 +2025-03-11T12:41:53.871795,479392912,65325,228,47.2786066394,35.539972951875,-84.09193020383,2,1,18 +2025-03-11T12:41:53.887420,479392912,65325,228,47.35871058194,35.62329084513,-84.249499425125,2,1,18 +2025-03-11T12:41:53.903045,479392912,65325,228,47.45766251096,35.706641350245,-84.41633813657,2,1,18 +2025-03-11T12:41:53.918670,479392912,65325,228,47.55190244336,35.799225846045,-84.58320714701,2,1,18 +2025-03-11T12:41:53.934295,479392912,65325,228,47.62258239266,35.87328528972,-84.71761981097,2,1,18 +2025-03-11T12:41:53.949920,479392912,65325,228,47.69797433858,35.942731814535,-84.852020715935,2,1,18 +2025-03-11T12:41:53.965545,479392912,65325,228,47.77807828112,36.03529185144,-84.995763468035,2,1,18 +2025-03-11T12:41:53.981170,479392912,65325,228,47.8440462338,36.113964213975,-85.13018789099,2,1,18 +2025-03-11T12:41:53.996719,479392916,65320,229,47.90059019324,36.20186241423,-85.26001464887,2,1,18 +2025-03-11T12:41:54.012344,479392916,65320,229,47.9854061324,36.2759463168,-85.394447655845,2,1,18 +2025-03-11T12:41:54.027969,479392916,65320,229,48.07022207156,36.33154593207,-85.533427685885,2,1,18 +2025-03-11T12:41:54.043594,479392916,65320,229,48.14090202086,36.377878944795,-85.658486743715,2,1,18 +2025-03-11T12:41:54.059219,479392916,65320,229,48.21629396678,36.43808332596,-85.760502287225,2,1,18 +2025-03-11T12:41:54.074844,479392916,65320,229,48.2916859127,36.507529850775,-85.85793372767,2,1,18 +2025-03-11T12:41:54.090469,479392916,65320,229,48.34822987214,36.563080548255,-85.964524790225,2,1,18 +2025-03-11T12:41:54.106094,479392916,65320,229,48.40006183496,36.614002020945,-86.071090531775,2,1,18 +2025-03-11T12:41:54.121719,479392916,65320,229,48.4566057944,36.6649316466,-86.182284237395,2,1,18 +2025-03-11T12:41:54.137344,479392916,65320,229,48.49901376398,36.72507895701,-86.27500994774,2,1,18 +2025-03-11T12:41:54.152969,479392916,65320,229,48.56026972004,36.78525887928,-86.37238396517,2,1,18 +2025-03-11T12:41:54.168594,479392916,65320,229,48.597965693,36.836155893075,-86.47430818064,2,1,18 +2025-03-11T12:41:54.184219,479392916,65320,229,48.65922164906,36.887093671695,-86.55316038581,2,1,18 +2025-03-11T12:41:54.199844,479392916,65320,229,48.7157656085,36.947265441,-86.632042889975,2,1,18 +2025-03-11T12:41:54.215469,479392916,65320,229,48.75346158146,36.98429923932,-86.715426753185,2,1,18 +2025-03-11T12:41:54.231094,479392916,65320,229,48.78173356118,37.025937803535,-86.789573228255,2,1,18 +2025-03-11T12:41:54.246719,479392916,65320,229,48.82885352738,37.07685112326,-86.873026273475,2,1,18 +2025-03-11T12:41:54.262344,479392916,65320,229,48.86654950034,37.109263849755,-86.947149230555,2,1,18 +2025-03-11T12:41:54.277969,479392916,65320,229,48.92309345978,37.14170918811,-87.021299311655,2,1,18 +2025-03-11T12:41:54.293594,479392916,65320,229,48.95607743612,37.178734833465,-87.072328112405,2,1,18 +2025-03-11T12:41:54.309219,479392916,65320,229,48.98434941584,37.224994469505,-87.12338721215,2,1,18 +2025-03-11T12:41:54.324844,479392916,65320,229,49.03146938204,37.271286717405,-87.16985225285,2,1,18 +2025-03-11T12:41:54.340469,479392916,65320,229,49.06445335838,37.285207003635,-87.234651902795,2,1,18 +2025-03-11T12:41:54.356094,479392916,65320,229,49.07858934824,37.299094678005,-87.304045611785,2,1,18 +2025-03-11T12:41:54.371719,479392916,65320,229,49.09743733472,37.31299050534,-87.359582552585,2,1,18 +2025-03-11T12:41:54.387344,479392916,65320,229,49.11157332458,37.34536246701,-87.39670214012,2,1,18 +2025-03-11T12:41:54.402969,479392916,65320,229,49.13042131106,37.37312150982,-87.43380996866,2,1,18 +2025-03-11T12:41:54.418594,479392916,65320,229,49.17754127726,37.38244518312,-87.466263140165,2,1,18 +2025-03-11T12:41:54.434219,479392916,65320,229,49.20110126036,37.38710701977,-87.489421500515,2,1,18 +2025-03-11T12:41:54.449844,479392916,65320,229,49.21523725022,37.41023683779,-87.521882824985,2,1,18 +2025-03-11T12:41:54.465469,479392916,65320,229,49.22466124346,37.42873743102,-87.558940011515,2,1,18 +2025-03-11T12:41:54.481094,479392916,65320,229,49.22937324008,37.45185094311,-87.572903041715,2,1,18 +2025-03-11T12:41:54.496719,479392916,65320,229,49.24822122656,37.456504626795,-87.59605462106,2,1,18 +2025-03-11T12:41:54.512344,479392916,65320,229,49.2576452198,37.465763076375,-87.609968812265,2,1,18 +2025-03-11T12:41:54.527969,479392916,65320,229,49.26235721642,37.461150157515,-87.614578236335,2,1,18 +2025-03-11T12:41:54.543594,479392916,65320,229,49.26235721642,37.45652908569,-87.642286794725,2,1,18 +2025-03-11T12:41:54.559219,479392916,65320,229,49.26706921304,37.47040045413,-87.65159156186,2,1,18 +2025-03-11T12:41:54.574844,479392916,65320,229,49.27649320628,37.465795688235,-87.637723034675,2,1,18 +2025-03-11T12:41:54.590469,479392916,65320,229,49.27178120966,37.461166463445,-87.62845534754,2,1,18 +2025-03-11T12:41:54.606094,479392916,65320,229,49.2576452198,37.465763076375,-87.63307472759,2,1,18 +2025-03-11T12:41:54.621719,479392916,65320,229,49.24822122656,37.465746770445,-87.61457643332,2,1,18 +2025-03-11T12:41:54.637344,479392916,65320,229,49.25293322318,37.45651277976,-87.596061402065,2,1,18 +2025-03-11T12:41:54.652969,479392916,65320,229,49.24822122656,37.447262483145,-87.563669259605,2,1,18 +2025-03-11T12:41:54.668594,479392916,65320,229,49.22466124346,37.42873743102,-87.549697645385,2,1,18 +2025-03-11T12:41:54.684219,479392916,65320,229,49.21523725022,37.414857909615,-87.521901364985,2,1,18 +2025-03-11T12:41:54.699844,479392916,65320,229,49.21523725022,37.39175255049,-87.48946038353,2,1,18 +2025-03-11T12:41:54.715469,479392916,65320,229,49.1869652705,37.368598273575,-87.466221082175,2,1,18 +2025-03-11T12:41:54.731094,479392916,65320,229,49.14926929754,37.350048762555,-87.438365575745,2,1,18 +2025-03-11T12:41:54.746719,479392916,65320,229,49.12570931444,37.345386925905,-87.4013436662,2,1,18 +2025-03-11T12:41:54.762344,479392916,65320,229,49.09743733472,37.31299050534,-87.35496136952,2,1,18 +2025-03-11T12:41:54.777969,479392916,65320,229,49.05974136176,37.280577778845,-87.276217229375,2,1,18 +2025-03-11T12:41:54.793594,479392916,65320,229,49.04089337528,37.24819766421,-87.21598494551,2,1,18 +2025-03-11T12:41:54.809219,479392916,65320,229,49.01733339218,37.21580939661,-87.16498824677,2,1,18 +2025-03-11T12:41:54.824844,479392916,65320,229,48.97963741922,37.18801774194,-87.11861092808,2,1,18 +2025-03-11T12:41:54.840469,479392916,65320,229,48.94665344288,37.15561316841,-87.0583583012,2,1,18 +2025-03-11T12:41:54.856094,479392916,65320,229,48.91366946654,37.13245073853,-87.012006303515,2,1,18 +2025-03-11T12:41:54.871719,479392916,65320,229,48.89482148006,37.090828480245,-86.93325220739,2,1,18 +2025-03-11T12:41:54.887344,479392916,65320,229,48.86654950034,37.03994777238,-86.87755338458,2,1,18 +2025-03-11T12:41:54.902969,479392916,65320,229,48.82885352738,37.007535045885,-86.798809244435,2,1,18 +2025-03-11T12:41:54.918594,479392916,65320,229,48.78173356118,36.96586386981,-86.696908546955,2,1,18 +2025-03-11T12:41:54.934219,479392916,65320,229,48.72047760512,36.93341037849,-86.627372867915,2,1,18 +2025-03-11T12:41:54.949844,479392916,65320,229,48.68278163216,36.891755508345,-86.5578340139,2,1,18 +2025-03-11T12:41:54.965469,479392916,65320,229,48.63094966934,36.850076179305,-86.455926535415,2,1,18 +2025-03-11T12:41:54.981094,479392916,65320,229,48.56969371328,36.799138400685,-86.377074330245,2,1,18 +2025-03-11T12:41:54.996719,479392916,65320,229,48.5272857437,36.729748946625,-86.270447990705,2,1,18 +2025-03-11T12:41:55.012344,479392916,65320,229,48.47074178426,36.683440392795,-86.17313637428,2,1,18 +2025-03-11T12:41:55.027969,479392916,65320,229,48.4094858282,36.623260470525,-86.08500472298,2,1,18 +2025-03-11T12:41:55.043594,479392916,65320,229,48.34351787552,36.558451323465,-85.987605384545,2,1,18 +2025-03-11T12:41:55.059219,479392916,65320,229,48.28697391608,36.49827955416,-85.88099578199,2,1,18 +2025-03-11T12:41:55.074844,479392916,65320,229,48.23042995664,36.43348671303,-85.75126172411,2,1,18 +2025-03-11T12:41:55.090469,479392916,65320,229,48.16917400058,36.368685718935,-85.63538443442,2,1,18 +2025-03-11T12:41:55.106094,479392916,65320,229,48.10791804452,36.308505796665,-85.52876805086,2,1,18 +2025-03-11T12:41:55.121719,479392916,65320,229,48.04195009184,36.23907557778,-85.394380707905,2,1,18 +2025-03-11T12:41:55.137344,479392916,65320,229,47.97127014254,36.16963720593,-85.250744217815,2,1,18 +2025-03-11T12:41:55.152969,479392916,65320,229,47.90530218986,36.100206987045,-85.130220424055,2,1,18 +2025-03-11T12:41:55.168594,479392916,65320,229,47.8204862507,36.016880940825,-85.009613886275,2,1,18 +2025-03-11T12:41:55.184219,479392916,65320,229,47.72153432168,35.938151507535,-84.856657264025,2,1,18 +2025-03-11T12:41:55.199844,479392916,65320,229,47.65085437238,35.859470992035,-84.70836251087,2,1,18 +2025-03-11T12:41:55.215469,479392916,65320,229,47.57546242646,35.785403395395,-84.55083715058,2,1,18 +2025-03-11T12:41:55.231094,479392916,65320,229,47.50007048054,35.71595687058,-84.39333033029,2,1,18 +2025-03-11T12:41:55.246719,479392916,65320,229,47.41525454138,35.628009752535,-84.240356971055,2,1,18 +2025-03-11T12:41:55.262344,479392916,65320,229,47.33986259546,35.544700012245,-84.092036896895,2,1,18 +2025-03-11T12:41:55.277969,479392916,65320,229,47.26918264616,35.447535209445,-83.93442561761,2,1,18 +2025-03-11T12:41:55.293594,479392916,65320,229,47.17965471038,35.34571672296,-83.76290512511,2,1,18 +2025-03-11T12:41:55.309219,479392916,65320,229,47.07127878812,35.253107768265,-83.60063695472,2,1,18 +2025-03-11T12:41:55.324844,479392916,65320,229,47.00059883882,35.155942965465,-83.43840449237,2,1,18 +2025-03-11T12:41:55.340469,479392916,65320,229,46.90635890642,35.054116326015,-83.257634852735,2,1,18 +2025-03-11T12:41:55.356094,479392916,65320,229,46.79798298416,34.97074951497,-83.086161396215,2,1,18 +2025-03-11T12:41:55.371719,479392916,65320,229,46.70845504838,34.859688884835,-82.905361457585,2,1,18 +2025-03-11T12:41:55.387344,479392916,65320,229,46.6189271126,34.7486282547,-82.71994033589,2,1,18 +2025-03-11T12:41:55.402969,479392916,65320,229,46.51526318696,34.651406381145,-82.55303922344,2,1,18 +2025-03-11T12:41:55.418594,479392916,65320,229,46.40217526808,34.549547129835,-82.363000093655,2,1,18 +2025-03-11T12:41:55.434219,479392916,65320,229,46.29851134244,34.45232525628,-82.159129516685,2,1,18 +2025-03-11T12:41:55.449844,479392916,65320,229,46.19013542018,34.34585308611,-81.94597271258,2,1,18 +2025-03-11T12:41:55.465469,479392916,65320,229,46.07233550468,34.234743538185,-81.742026172595,2,1,18 +2025-03-11T12:41:55.481094,479392916,65320,229,45.96395958242,34.119029224365,-81.533453471555,2,1,18 +2025-03-11T12:41:55.496719,479392916,65320,229,45.8414476703,34.007911523475,-81.33412133363,2,1,18 +2025-03-11T12:41:55.512344,479392916,65320,229,45.72835975142,33.896810128515,-81.12093920852,2,1,18 +2025-03-11T12:41:55.527969,479392916,65320,229,45.61055983592,33.76721629329,-80.90305495934,2,1,18 +2025-03-11T12:41:55.543594,479392916,65320,229,45.50689591028,33.63764691696,-80.68056987011,2,1,18 +2025-03-11T12:41:55.559219,479392916,65320,229,45.38438399816,33.512666000595,-80.453455013795,2,1,18 +2025-03-11T12:41:55.574844,479392916,65320,229,45.2524480928,33.3876687783,-80.2355689616,2,1,18 +2025-03-11T12:41:55.590469,479392916,65320,229,45.12993618068,33.25806679011,-80.017677931415,2,1,18 +2025-03-11T12:41:55.606094,479392916,65320,229,45.00742426856,33.14694908922,-79.795239878165,2,1,18 +2025-03-11T12:41:55.621719,479392916,65320,229,44.88491235644,33.01734710103,-79.55886411572,2,1,18 +2025-03-11T12:41:55.637344,479392916,65320,229,44.75297645108,32.89697095056,-79.32713305433,2,1,18 +2025-03-11T12:41:55.652969,479392916,65320,229,44.62575254234,32.767360809405,-79.095371693945,2,1,18 +2025-03-11T12:41:55.668594,479392916,65320,229,44.49381663698,32.64236358711,-78.854379726425,2,1,18 +2025-03-11T12:41:55.684219,479392916,65320,229,44.36659272824,32.49889023048,-78.59483564765,2,1,18 +2025-03-11T12:41:55.699844,479392916,65320,229,44.22523282964,32.355392414955,-78.33527122586,2,1,18 +2025-03-11T12:41:55.715469,479392916,65320,229,44.07916093442,32.21650751829,-78.08958211226,2,1,18 +2025-03-11T12:41:55.731094,479392916,65320,229,43.93780103582,32.07763077459,-77.843899779665,2,1,18 +2025-03-11T12:41:55.746719,479392916,65320,229,43.80115313384,31.938762183855,-77.598224228075,2,1,18 +2025-03-11T12:41:55.762344,479392916,65320,229,43.6739292251,31.804530970875,-77.334096046235,2,1,18 +2025-03-11T12:41:55.777969,479392916,65320,229,43.52314533326,31.656395777595,-77.065257156305,2,1,18 +2025-03-11T12:41:55.793594,479392916,65320,229,43.36293744818,31.50362320656,-76.787143798235,2,1,18 +2025-03-11T12:41:55.809219,479392916,65320,229,43.21686555296,31.36011723807,-76.52757259544,2,1,18 +2025-03-11T12:41:55.824844,479392916,65320,229,43.06608166112,31.21198204479,-76.25873370551,2,1,18 +2025-03-11T12:41:55.840469,479392916,65320,229,42.91529776928,31.06384685151,-75.976031266385,2,1,18 +2025-03-11T12:41:55.856094,479392916,65320,229,42.76922587406,30.89261445207,-75.6886217252,2,1,18 +2025-03-11T12:41:55.871719,479392916,65320,229,42.61844198222,30.73523711514,-75.41050338914,2,1,18 +2025-03-11T12:41:55.887344,479392916,65320,229,42.46294609376,30.59171484072,-75.123191525945,2,1,18 +2025-03-11T12:41:55.902969,479392916,65320,229,42.31216220192,30.42509536014,-74.835793743755,2,1,18 +2025-03-11T12:41:55.918594,479392916,65320,229,42.14724232022,30.258451420665,-74.52989088629,2,1,18 +2025-03-11T12:41:55.934219,479392916,65320,229,41.9776104419,30.091799328225,-74.228602430885,2,1,18 +2025-03-11T12:41:55.949844,479392916,65320,229,41.8126905602,29.929776460575,-73.93196047955,2,1,18 +2025-03-11T12:41:55.965469,479392916,65320,229,41.6477706785,29.749269305625,-73.63986555128,2,1,18 +2025-03-11T12:41:55.981094,479392916,65320,229,41.4828507968,29.578004294325,-73.32932297075,2,1,18 +2025-03-11T12:41:55.996719,479392916,65320,229,41.31321891848,29.41597327371,-73.009568323085,2,1,18 +2025-03-11T12:41:56.012344,479392916,65320,229,41.14829903678,29.249329334235,-72.680559550295,2,1,18 +2025-03-11T12:41:56.027969,479392916,65320,229,40.97395516184,29.068805873355,-72.36534514469,2,1,18 +2025-03-11T12:41:56.043594,479392916,65320,229,40.80432328352,28.902153780915,-72.05943550622,2,1,18 +2025-03-11T12:41:56.059219,479392916,65320,229,40.63940340182,28.73550984144,-71.744290282625,2,1,18 +2025-03-11T12:41:56.074844,479392916,65320,229,40.46505952688,28.54574423691,-71.424417613955,2,1,18 +2025-03-11T12:41:56.090469,479392916,65320,229,40.2812916587,28.37444661375,-71.095363177145,2,1,18 +2025-03-11T12:41:56.106094,479392916,65320,229,40.10223578714,28.193914999905,-70.743172526015,2,1,18 +2025-03-11T12:41:56.121719,479392916,65320,229,39.92317991558,28.00414124241,-70.42329307634,2,1,18 +2025-03-11T12:41:56.137344,479392916,65320,229,39.73470005078,27.842077609935,-70.08964775546,2,1,18 +2025-03-11T12:41:56.152969,479392916,65320,229,39.53679619274,27.666134456055,-69.74669088644,2,1,18 +2025-03-11T12:41:56.168594,479392916,65320,229,39.35302832456,27.47173147377,-69.412922566565,2,1,18 +2025-03-11T12:41:56.184219,479392916,65320,229,39.16454845976,27.281941410345,-69.06530245649,2,1,18 +2025-03-11T12:41:56.199844,479392916,65320,229,38.97606859496,27.078288131445,-68.73149027561,2,1,18 +2025-03-11T12:41:56.215469,479392916,65320,229,38.79230072678,26.88388514916,-68.388479589605,2,1,18 +2025-03-11T12:41:56.231094,479392916,65320,229,38.60382086198,26.68947401391,-68.036219756465,2,1,18 +2025-03-11T12:41:56.246719,479392916,65320,229,38.4200529938,26.504313175275,-67.688624967395,2,1,18 +2025-03-11T12:41:56.262344,479392916,65320,229,38.22686113238,26.31913603071,-67.32715306712,2,1,18 +2025-03-11T12:41:56.277969,479392916,65320,229,38.0195332811,26.11545013995,-66.970207846895,2,1,18 +2025-03-11T12:41:56.293594,479392916,65320,229,37.81691742644,25.930256689455,-66.59948001848,2,1,18 +2025-03-11T12:41:56.309219,479392916,65320,229,37.61430157178,25.721957879835,-66.224038307,2,1,18 +2025-03-11T12:41:56.324844,479392916,65320,229,37.41168571712,25.50903799839,-65.84857805552,2,1,18 +2025-03-11T12:41:56.340469,479392916,65320,229,37.20435786584,25.30535210763,-65.500875201425,2,1,18 +2025-03-11T12:41:56.356094,479392916,65320,229,36.99231801794,25.101658063905,-65.130059651,2,1,18 +2025-03-11T12:41:56.371719,479392916,65320,229,36.78970216328,24.884117110635,-64.749959676455,2,1,18 +2025-03-11T12:41:56.387344,479392916,65320,229,36.59179830524,24.671205382155,-64.388369755175,2,1,18 +2025-03-11T12:41:56.402969,479392916,65320,229,36.37975845734,24.47675348208,-64.012970101685,2,1,18 +2025-03-11T12:41:56.418594,479392916,65320,229,36.18656659592,24.273092050215,-63.619075759955,2,1,18 +2025-03-11T12:41:56.434219,479392916,65320,229,35.97452674802,24.05091371919,-63.243564866465,2,1,18 +2025-03-11T12:41:56.449844,479392916,65320,229,35.76719889674,23.82874354113,-62.881924303175,2,1,18 +2025-03-11T12:41:56.465469,479392916,65320,229,35.56458304208,23.615823659685,-62.47411577024,2,1,18 +2025-03-11T12:41:56.481094,479392916,65320,229,35.35254319418,23.41212961596,-62.075573121425,2,1,18 +2025-03-11T12:41:56.496719,479392916,65320,229,35.13579134966,23.20842741927,-61.68164487467,2,1,18 +2025-03-11T12:41:56.512344,479392916,65320,229,34.91432750852,22.995474925965,-61.27843040078,2,1,18 +2025-03-11T12:41:56.527969,479392916,65320,229,34.69286366738,22.77328028901,-60.89366357915,2,1,18 +2025-03-11T12:41:56.543594,479392916,65320,229,34.47611182286,22.537230589545,-60.481120820135,2,1,18 +2025-03-11T12:41:56.559219,479392916,65320,229,34.25464798172,22.310414880765,-60.04550244479,2,1,18 +2025-03-11T12:41:56.574844,479392916,65320,229,34.03318414058,22.08822024381,-59.646872073965,2,1,18 +2025-03-11T12:41:56.590469,479392916,65320,229,33.80700830282,21.86601745389,-59.248234922135,2,1,18 +2025-03-11T12:41:56.606094,479392916,65320,229,33.5666964752,21.643790205075,-58.84033506116,2,1,18 +2025-03-11T12:41:56.621719,479392916,65320,229,33.3310966442,21.403086821925,-58.418504271995,2,1,18 +2025-03-11T12:41:56.637344,479392916,65320,229,33.10020880982,21.16239159174,-58.005922629965,2,1,18 +2025-03-11T12:41:56.652969,479392916,65320,229,32.86460897882,20.93093035224,-57.5841289208,2,1,18 +2025-03-11T12:41:56.668594,479392916,65320,229,32.61958515458,20.685589591335,-57.162266029625,2,1,18 +2025-03-11T12:41:56.684219,479392916,65320,229,32.38398532358,20.454128351835,-56.745093503525,2,1,18 +2025-03-11T12:41:56.699844,479392916,65320,229,32.17194547568,20.208844661685,-56.32789926245,2,1,18 +2025-03-11T12:41:56.715469,479392916,65320,229,31.95519363116,19.98203710587,-55.90153003424,2,1,18 +2025-03-11T12:41:56.731094,479392916,65320,229,31.71959380016,19.75981801002,-55.46590985588,2,1,18 +2025-03-11T12:41:56.746719,479392916,65320,229,31.48870596578,19.53298599531,-55.02565673546,2,1,18 +2025-03-11T12:41:56.762344,479392916,65320,229,31.2578181314,19.292290765125,-54.6038327273,2,1,18 +2025-03-11T12:41:56.777969,479392916,65320,229,31.00337031392,19.04693369829,-54.15885035879,2,1,18 +2025-03-11T12:41:56.793594,479392916,65320,229,30.74421049982,18.82005276579,-53.704693003145,2,1,18 +2025-03-11T12:41:56.809219,479392916,65320,229,30.51332266544,18.579357535605,-53.26900544579,2,1,18 +2025-03-11T12:41:56.824844,479392916,65320,229,30.27301083782,18.32940385584,-52.805540148035,2,1,18 +2025-03-11T12:41:56.840469,479392916,65320,229,30.04683500006,18.074853563145,-52.351319019425,2,1,18 +2025-03-11T12:41:56.856094,479392916,65320,229,29.8206591623,17.82030327045,-51.906340256945,2,1,18 +2025-03-11T12:41:56.871719,479392916,65320,229,29.56621134482,17.56108298814,-51.45668108537,2,1,18 +2025-03-11T12:41:56.887344,479392916,65320,229,29.30705153072,17.329580983815,-51.002505189725,2,1,18 +2025-03-11T12:41:56.902969,479392916,65320,229,29.04317972,17.08420761105,-50.557509259205,2,1,18 +2025-03-11T12:41:56.918594,479392916,65320,229,28.807579889,16.83426208425,-50.10791429165,2,1,18 +2025-03-11T12:41:56.934219,479392916,65320,229,28.55784406814,16.57967102673,-49.66752280721,2,1,18 +2025-03-11T12:41:56.949844,479392916,65320,229,28.28454826418,16.33890241986,-49.227153037745,2,1,18 +2025-03-11T12:41:56.965469,479392916,65320,229,28.01596445684,16.09352089413,-48.7451808617,2,1,18 +2025-03-11T12:41:56.981094,479392916,65320,229,27.76151663936,15.838921683645,-48.267813131735,2,1,18 +2025-03-11T12:41:56.996719,479392916,65320,229,27.50235682526,15.57969324837,-47.80428362996,2,1,18 +2025-03-11T12:41:57.012344,479392916,65320,229,27.25733300102,15.32973141564,-47.33156918507,2,1,18 +2025-03-11T12:41:57.027969,479392916,65320,229,27.01230917678,15.06128529561,-46.854159397115,2,1,18 +2025-03-11T12:41:57.043594,479392916,65320,229,26.75314936268,14.77895150121,-46.39977956147,2,1,18 +2025-03-11T12:41:57.059219,479392916,65320,229,26.4987015452,14.515110147075,-45.9362383007,2,1,18 +2025-03-11T12:41:57.074844,479392916,65320,229,26.2395417311,14.2558817118,-45.454224066665,2,1,18 +2025-03-11T12:41:57.090469,479392916,65320,229,25.98509391362,14.001282501315,-44.962992787505,2,1,18 +2025-03-11T12:41:57.106094,479392916,65320,229,25.72593409952,13.737432994215,-44.49944474573,2,1,18 +2025-03-11T12:41:57.121719,479392916,65320,229,25.47148628204,13.478212711905,-44.02667965883,2,1,18 +2025-03-11T12:41:57.137344,479392916,65320,229,25.2029024747,13.20972582705,-43.535372416655,2,1,18 +2025-03-11T12:41:57.152969,479392916,65320,229,24.9201826775,12.955077698775,-43.044100451465,2,1,18 +2025-03-11T12:41:57.168594,479392916,65320,229,24.67044685664,12.691244497605,-42.566702422505,2,1,18 +2025-03-11T12:41:57.184219,479392916,65320,229,24.42071103578,12.418169152785,-42.080024947415,2,1,18 +2025-03-11T12:41:57.199844,479392916,65320,229,24.13327924196,12.135786440595,-41.584013778155,2,1,18 +2025-03-11T12:41:57.215469,479392916,65320,229,23.859983438,11.867291402775,-41.09732093804,2,1,18 +2025-03-11T12:41:57.231094,479392916,65320,229,23.6008236239,11.59882082385,-40.61064844094,2,1,18 +2025-03-11T12:41:57.246719,479392916,65320,229,23.32752781994,11.316462570555,-40.114657614695,2,1,18 +2025-03-11T12:41:57.262344,479392916,65320,229,23.04952001936,11.03871723612,-39.618678547445,2,1,18 +2025-03-11T12:41:57.277969,479392916,65320,229,22.7762242154,10.7887064856,-39.13205986733,2,1,18 +2025-03-11T12:41:57.293594,479392916,65320,229,22.50292841144,10.524832519605,-38.626900834955,2,1,18 +2025-03-11T12:41:57.309219,479392916,65320,229,22.2343446041,10.23786134745,-38.121655883585,2,1,18 +2025-03-11T12:41:57.324844,479392916,65320,229,21.97047279338,9.96014047191,-37.630318342415,2,1,18 +2025-03-11T12:41:57.340469,479392916,65320,229,21.68775299618,9.677765912685,-37.111208038835,2,1,18 +2025-03-11T12:41:57.356094,479392916,65320,229,21.40503319898,9.418496712585,-36.610675167515,2,1,18 +2025-03-11T12:41:57.371719,479392916,65320,229,21.12231340178,9.14536429701,-36.110086676195,2,1,18 +2025-03-11T12:41:57.387344,479392916,65320,229,20.85372959444,8.849150981205,-35.595562278695,2,1,18 +2025-03-11T12:41:57.402969,479392916,65320,229,20.58043379048,8.562171656085,-35.08106818019,2,1,18 +2025-03-11T12:41:57.418594,479392916,65320,229,20.29300199666,8.27516787207,-34.561932555605,2,1,18 +2025-03-11T12:41:57.434219,479392916,65320,229,20.01499419608,8.00204360946,-34.06135084529,2,1,18 +2025-03-11T12:41:57.449844,479392916,65320,229,19.74169839212,7.71506428434,-33.56072029598,2,1,18 +2025-03-11T12:41:57.465469,479392916,65320,229,19.45897859492,7.41882650964,-33.046175555465,2,1,18 +2025-03-11T12:41:57.481094,479392916,65320,229,19.1951067842,7.15034777775,-32.53176917897,2,1,18 +2025-03-11T12:41:57.496719,479392916,65320,229,18.89825099714,6.881811975105,-31.98958823705,2,1,18 +2025-03-11T12:41:57.512344,479392916,65320,229,18.6296671898,6.5855986593,-31.451957924225,2,1,18 +2025-03-11T12:41:57.527969,479392916,65320,229,18.3469473926,6.29860302825,-30.94669262984,2,1,18 +2025-03-11T12:41:57.543594,479392916,65320,229,18.05009160554,6.01620401013,-30.446046715505,2,1,18 +2025-03-11T12:41:57.559219,479392916,65320,229,17.75323581848,5.73380499201,-29.913052519715,2,1,18 +2025-03-11T12:41:57.574844,479392916,65320,229,17.47051602128,5.442188289135,-29.393905136135,2,1,18 +2025-03-11T12:41:57.590469,479392916,65320,229,17.17837223084,5.15979742398,-28.86091772135,2,1,18 +2025-03-11T12:41:57.606094,479392916,65320,229,16.89094043702,4.872793639965,-28.34640327983,2,1,18 +2025-03-11T12:41:57.621719,479392916,65320,229,16.60822063982,4.576555865265,-27.80875262399,2,1,18 +2025-03-11T12:41:57.637344,479392916,65320,229,16.33021283924,4.28032624353,-27.298835847545,2,1,18 +2025-03-11T12:41:57.652969,479392916,65320,229,16.05691703528,3.997967990235,-26.779739105975,2,1,18 +2025-03-11T12:41:57.668594,479392916,65320,229,15.76477324484,3.720198196905,-26.269876146515,2,1,18 +2025-03-11T12:41:57.684219,479392916,65320,229,15.46791745778,3.456283466085,-25.746198476855,2,1,18 +2025-03-11T12:41:57.699844,479392916,65320,229,15.17577366734,3.16465045728,-25.208552799005,2,1,18 +2025-03-11T12:41:57.715469,479392916,65320,229,14.89776586676,2.859178691895,-24.666250661105,2,1,18 +2025-03-11T12:41:57.731094,479392916,65320,229,14.6244700628,2.562957223125,-24.128613567275,2,1,18 +2025-03-11T12:41:57.746719,479392916,65320,229,14.33703826898,2.26671129546,-23.61868322882,2,1,18 +2025-03-11T12:41:57.762344,479392916,65320,229,14.0354704853,1.975061980725,-23.076402805895,2,1,18 +2025-03-11T12:41:57.777969,479392916,65320,229,13.73390270162,1.669549450515,-22.547930312165,2,1,18 +2025-03-11T12:41:57.793594,479392916,65320,229,13.44175891118,1.364053226235,-22.019471380445,2,1,18 +2025-03-11T12:41:57.809219,479392916,65320,229,13.14490312412,1.07703313629,-21.477216278525,2,1,18 +2025-03-11T12:41:57.824844,479392916,65320,229,12.84804733706,0.77614983087,-20.934905556605,2,1,18 +2025-03-11T12:41:57.840469,479392916,65320,229,12.54647955338,0.484500516135,-20.40186749981,2,1,18 +2025-03-11T12:41:57.856094,479392916,65320,229,12.26375975618,0.197504885085,-19.859632740905,2,1,18 +2025-03-11T12:41:57.871719,479392916,65320,229,11.95747997588,-0.0756682953150003,-19.3405256123,2,1,18 +2025-03-11T12:41:57.887344,479392916,65320,229,11.6559121922,-0.36731761005,-18.79362400631,2,1,18 +2025-03-11T12:41:57.902969,479392916,65320,229,11.3496324119,-0.672838293225,-18.25128118238,2,1,18 +2025-03-11T12:41:57.918594,479392916,65320,229,11.05748862146,-0.982955589329999,-17.71356134453,2,1,18 +2025-03-11T12:41:57.934219,479392916,65320,229,10.77476882426,-1.26995122038,-17.162084219495,2,1,18 +2025-03-11T12:41:57.949844,479392916,65320,229,10.4779130372,-1.575455597625,-16.62437614064,2,1,18 +2025-03-11T12:41:57.965469,479392916,65320,229,10.1716332569,-1.876355208975,-16.095915405905,2,1,18 +2025-03-11T12:41:57.981094,479392916,65320,229,9.88420146308,-2.17260113664,-15.55825796906,2,1,18 +2025-03-11T12:41:57.996658,479392920,65316,230,9.59676966926,-2.46422599248,-15.01599788915,2,1,18 +2025-03-11T12:41:58.012283,479392920,65316,230,9.2999138822,-2.760488226075,-14.48294807336,2,1,18 +2025-03-11T12:41:58.027908,479392920,65316,230,9.01248208838,-3.052113081915,-13.954551542645,2,1,18 +2025-03-11T12:41:58.043533,479392920,65316,230,8.7109143047,-3.348383468475,-13.407631396655,2,1,18 +2025-03-11T12:41:58.059158,479392920,65316,230,8.4046345244,-3.658525223475,-12.86989121579,2,1,18 +2025-03-11T12:41:58.074783,479392920,65316,230,8.11249073396,-3.95015823228,-12.32300317181,2,1,18 +2025-03-11T12:41:58.090408,479392920,65316,230,7.81092295028,-4.251049690665,-11.762200936625,2,1,18 +2025-03-11T12:41:58.106033,479392920,65316,230,7.51406716322,-4.561175139735,-11.210610768575,2,1,18 +2025-03-11T12:41:58.121658,479392920,65316,230,7.2030753863,-4.86208290405,-10.65903733751,2,1,18 +2025-03-11T12:41:58.137283,479392920,65316,230,6.91564359248,-5.167570975365,-10.09823690534,2,1,18 +2025-03-11T12:41:58.152908,479392920,65316,230,6.61878780542,-5.477696424435,-9.551267920355,2,1,18 +2025-03-11T12:41:58.168533,479392920,65316,230,6.31250802512,-5.78321710761,-9.03203101175,2,1,18 +2025-03-11T12:41:58.184158,479392920,65316,230,6.02978822792,-6.09793916961,-8.480442646715,2,1,18 +2025-03-11T12:41:58.199783,479392920,65316,230,5.73764443748,-6.380330034765,-7.90124340128,2,1,18 +2025-03-11T12:41:58.215408,479392920,65316,230,5.44550064704,-6.676584115395,-7.377442732625,2,1,18 +2025-03-11T12:41:58.231033,479392920,65316,230,5.14864485998,-6.968225277165,-6.835169090705,2,1,18 +2025-03-11T12:41:58.246658,479392920,65316,230,4.8470770763,-7.26911673555,-6.28360922165,2,1,18 +2025-03-11T12:41:58.262283,479392920,65316,230,4.53137330276,-7.583895868305,-5.755079304905,2,1,18 +2025-03-11T12:41:58.277908,479392920,65316,230,4.22509352246,-7.88017440783,-5.20815237791,2,1,18 +2025-03-11T12:41:58.293533,479392920,65316,230,3.91881374216,-8.167210803705,-4.652020164785,2,1,18 +2025-03-11T12:41:58.309158,479392920,65316,230,3.62666995172,-8.46808595616,-4.10047385774,2,1,18 +2025-03-11T12:41:58.324783,479392920,65316,230,3.34395015452,-8.768944802685,-3.558183478835,2,1,18 +2025-03-11T12:41:58.340408,479392920,65316,230,3.0329583776,-9.06061042335,-3.00664712777,2,1,18 +2025-03-11T12:41:58.356033,479392920,65316,230,2.73139059392,-9.36612295356,-2.455068718715,2,1,18 +2025-03-11T12:41:58.371658,479392920,65316,230,2.42511081362,-9.671643636735,-1.884998796395,2,1,18 +2025-03-11T12:41:58.387283,479392920,65316,230,2.1376790198,-9.9678895644,-1.333477810355,2,1,18 +2025-03-11T12:41:58.402908,479392920,65316,230,1.83611123612,-10.268781022785,-0.805023856625001,2,1,18 +2025-03-11T12:41:58.418533,479392920,65316,230,1.52983145582,-10.56505956231,-0.271960478825001,2,1,18 +2025-03-11T12:41:58.434158,479392920,65316,230,1.23768766538,-10.87055578659,0.293467917415,2,1,18 +2025-03-11T12:41:58.449783,479392920,65316,230,0.95025587156,-11.17142278608,0.835765077325,2,1,18 +2025-03-11T12:41:58.465408,479392920,65316,230,0.6534000845,-11.4723060915,1.36421225005,2,1,18 +2025-03-11T12:41:58.481033,479392920,65316,230,0.36125629406,-11.77780231578,1.89267118177,2,1,18 +2025-03-11T12:41:58.496658,479392920,65316,230,0.06911250362,-12.069435324585,2.434938042685,2,1,18 +2025-03-11T12:41:58.512283,479392920,65316,230,-0.2418792733,-12.356479873425,2.991077036815,2,1,18 +2025-03-11T12:41:58.527908,479392920,65316,230,-0.55287105022,-12.66662978139,3.538066364815,2,1,18 +2025-03-11T12:41:58.543533,479392920,65316,230,-0.86386282714,-12.976779689355,4.08967687588,2,1,18 +2025-03-11T12:41:58.559158,479392920,65316,230,-1.17956660068,-13.277695606635,4.636635904885,2,1,18 +2025-03-11T12:41:58.574783,479392920,65316,230,-1.4669983945,-13.5739415343,5.188156890925,2,1,18 +2025-03-11T12:41:58.590408,479392920,65316,230,-1.75443018832,-13.87480853379,5.7350752339,2,1,18 +2025-03-11T12:41:58.606033,479392920,65316,230,-2.06070996862,-14.17570814514,6.272778334765,2,1,18 +2025-03-11T12:41:58.621658,479392920,65316,230,-2.35285375906,-14.46272008212,6.791920740355,2,1,18 +2025-03-11T12:41:58.637283,479392920,65316,230,-2.6449975495,-14.772837378225,7.320398212075,2,1,18 +2025-03-11T12:41:58.652908,479392920,65316,230,-2.93714133994,-15.087575746155,7.885863688315,2,1,18 +2025-03-11T12:41:58.668533,479392920,65316,230,-3.22457313376,-15.369958458345,8.43270787129,2,1,18 +2025-03-11T12:41:58.684158,479392920,65316,230,-3.5167169242,-15.666212538975,8.956508539945,2,1,18 +2025-03-11T12:41:58.699783,479392920,65316,230,-3.81357271126,-15.96247477257,9.498800721865,2,1,18 +2025-03-11T12:41:58.715408,479392920,65316,230,-4.11042849832,-16.249494862515,10.059540556045,2,1,18 +2025-03-11T12:41:58.731033,479392920,65316,230,-4.40728428538,-16.541136024285,10.60643538103,2,1,18 +2025-03-11T12:41:58.746658,479392920,65316,230,-4.69000408258,-16.85123701446,11.130278107675,2,1,18 +2025-03-11T12:41:58.762283,479392920,65316,230,-4.98214787302,-17.152112166915,11.649476133265,2,1,18 +2025-03-11T12:41:58.777908,479392920,65316,230,-5.29313964994,-17.45301993123,12.177943649005,2,1,18 +2025-03-11T12:41:58.793533,479392920,65316,230,-5.58528344038,-17.74003186821,12.72019196992,2,1,18 +2025-03-11T12:41:58.809158,479392920,65316,230,-5.88685122406,-18.031681182945,13.280957125105,2,1,18 +2025-03-11T12:41:58.824783,479392920,65316,230,-6.1789950145,-18.3140720481,13.81394453989,2,1,18 +2025-03-11T12:41:58.840408,479392920,65316,230,-6.4617148117,-18.577962320025,14.346844232665,2,1,18 +2025-03-11T12:41:58.856033,479392920,65316,230,-6.73501061566,-18.883425932445,14.8706548573,2,1,18 +2025-03-11T12:41:58.871658,479392920,65316,230,-7.03186640272,-19.19817245334,15.41302119922,2,1,18 +2025-03-11T12:41:58.887283,479392920,65316,230,-7.32872218978,-19.48057147146,15.922909479685,2,1,18 +2025-03-11T12:41:58.902908,479392920,65316,230,-7.62086598022,-19.753720192965,16.432753899145,2,1,18 +2025-03-11T12:41:58.918533,479392920,65316,230,-7.90829777404,-20.04996612063,16.975032519055,2,1,18 +2025-03-11T12:41:58.934158,479392920,65316,230,-8.20044156448,-20.350841273085,17.51733645997,2,1,18 +2025-03-11T12:41:58.949783,479392920,65316,230,-8.4878733583,-20.642466128925,18.045732990685,2,1,18 +2025-03-11T12:41:58.965408,479392920,65316,230,-8.77530515212,-20.92022776929,18.56483153527,2,1,18 +2025-03-11T12:41:58.981033,479392920,65316,230,-9.06273694594,-21.20261048148,19.083948619855,2,1,18 +2025-03-11T12:41:58.996658,479392920,65316,230,-9.359592733,-21.5034937869,19.60315342645,2,1,18 +2025-03-11T12:41:59.012283,479392920,65316,230,-9.6423125302,-21.795110489775,20.12230081003,2,1,18 +2025-03-11T12:41:59.027908,479392920,65316,230,-9.92032033078,-22.08209796786,20.659907604865,2,1,18 +2025-03-11T12:41:59.043533,479392920,65316,230,-10.19361613474,-22.36907729298,21.1836440695,2,1,18 +2025-03-11T12:41:59.059158,479392920,65316,230,-10.48104792856,-22.656081076995,21.702779694085,2,1,18 +2025-03-11T12:41:59.074783,479392920,65316,230,-10.76847972238,-22.94308486101,22.217294135605,2,1,18 +2025-03-11T12:41:59.090408,479392920,65316,230,-11.0559115162,-23.2254675732,22.73641122019,2,1,18 +2025-03-11T12:41:59.106033,479392920,65316,230,-11.34334331002,-23.52633457269,23.264844830905,2,1,18 +2025-03-11T12:41:59.121658,479392920,65316,230,-11.62606310722,-23.799466988265,23.774675688355,2,1,18 +2025-03-11T12:41:59.137283,479392920,65316,230,-11.91349490104,-24.072607556805,24.28451332681,2,1,18 +2025-03-11T12:41:59.152908,479392920,65316,230,-12.19621469824,-24.350361044205,24.79436272426,2,1,18 +2025-03-11T12:41:59.168533,479392920,65316,230,-12.48364649206,-24.632743756395,25.30885862578,2,1,18 +2025-03-11T12:41:59.184158,479392920,65316,230,-12.76636628926,-24.92436045927,25.814142460165,2,1,18 +2025-03-11T12:41:59.199783,479392920,65316,230,-13.04437408984,-25.19748472188,26.32396653661,2,1,18 +2025-03-11T12:41:59.215408,479392920,65316,230,-13.31295789718,-25.47059267856,26.82915586798,2,1,18 +2025-03-11T12:41:59.231033,479392920,65316,230,-13.5768297079,-25.75755569775,27.334394038345,2,1,18 +2025-03-11T12:41:59.246658,479392920,65316,230,-13.84541351524,-26.01217936713,27.839509209715,2,1,18 +2025-03-11T12:41:59.262283,479392920,65316,230,-14.12342131582,-26.289924701565,28.34935182616,2,1,18 +2025-03-11T12:41:59.277908,479392920,65316,230,-14.41556510626,-26.567694494895,28.85921478562,2,1,18 +2025-03-11T12:41:59.293533,479392920,65316,230,-14.68886091022,-26.83156846089,29.355131451865,2,1,18 +2025-03-11T12:41:59.309158,479392920,65316,230,-14.95744471756,-27.118539633045,29.851134037105,2,1,18 +2025-03-11T12:41:59.324783,479392920,65316,230,-15.2260285249,-27.419374020675,30.356434608475,2,1,18 +2025-03-11T12:41:59.340408,479392920,65316,230,-15.49932432886,-27.678626914845,30.85233273472,2,1,18 +2025-03-11T12:41:59.356033,479392920,65316,230,-15.78204412606,-27.956380402245,31.339076216845,2,1,18 +2025-03-11T12:41:59.371658,479392920,65316,230,-16.06947591988,-28.229520970785,31.835050306105,2,1,18 +2025-03-11T12:41:59.387283,479392920,65316,230,-16.32863573398,-28.48874940606,32.3355492724,2,1,18 +2025-03-11T12:41:59.402908,479392920,65316,230,-16.58308355146,-28.76645397567,32.8083885193,2,1,18 +2025-03-11T12:41:59.418533,479392920,65316,230,-16.84695536218,-29.030311635735,33.276564525145,2,1,18 +2025-03-11T12:41:59.434158,479392920,65316,230,-17.10611517628,-29.28954007101,33.753957576115,2,1,18 +2025-03-11T12:41:59.449783,479392920,65316,230,-17.36527499038,-29.558010649935,34.240630073215,2,1,18 +2025-03-11T12:41:59.465408,479392920,65316,230,-17.6291468011,-29.82186831,34.73653317745,2,1,18 +2025-03-11T12:41:59.481033,479392920,65316,230,-17.90715460168,-30.081129357135,35.227816901635,2,1,18 +2025-03-11T12:41:59.496658,479392920,65316,230,-18.17573840902,-30.335753026515,35.705204974615,2,1,18 +2025-03-11T12:41:59.512283,479392920,65316,230,-18.4301862265,-30.594973308825,36.187212427645,2,1,18 +2025-03-11T12:41:59.527908,479392920,65316,230,-18.69405803722,-30.85883096889,36.65538843349,2,1,18 +2025-03-11T12:41:59.543533,479392920,65316,230,-18.96735384118,-31.11808386306,37.13742301054,2,1,18 +2025-03-11T12:41:59.559158,479392920,65316,230,-19.22651365528,-31.377312298335,37.619437244575,2,1,18 +2025-03-11T12:41:59.574783,479392920,65316,230,-19.48096147276,-31.63191150882,38.08756260841,2,1,18 +2025-03-11T12:41:59.590408,479392920,65316,230,-19.73540929024,-31.90037393478,38.574228324505,2,1,18 +2025-03-11T12:41:59.606033,479392920,65316,230,-19.9851451111,-32.16420713595,39.0470051704,2,1,18 +2025-03-11T12:41:59.621658,479392920,65316,230,-20.25372891844,-32.42807294898,39.51518795725,2,1,18 +2025-03-11T12:41:59.637283,479392920,65316,230,-20.50817673592,-32.67805108764,39.974052414955,2,1,18 +2025-03-11T12:41:59.652908,479392920,65316,230,-20.7626245534,-32.9465135136,40.428369849595,2,1,18 +2025-03-11T12:41:59.668533,479392920,65316,230,-21.00764837764,-33.191854274505,40.88720220529,2,1,18 +2025-03-11T12:41:59.684158,479392920,65316,230,-21.25267220188,-33.441816107235,41.33218955179,2,1,18 +2025-03-11T12:41:59.699783,479392920,65316,230,-21.50712001936,-33.673309958595,41.781737483365,2,1,18 +2025-03-11T12:41:59.715408,479392920,65316,230,-21.75685584022,-33.94176423159,42.236048137,2,1,18 +2025-03-11T12:41:59.731033,479392920,65316,230,-22.00187966446,-34.187104992495,42.69025930963,2,1,18 +2025-03-11T12:41:59.746658,479392920,65316,230,-22.24219149208,-34.423195456785,43.135184255125,2,1,18 +2025-03-11T12:41:59.762283,479392920,65316,230,-22.49192731294,-34.67316544248,43.58017838263,2,1,18 +2025-03-11T12:41:59.777908,479392920,65316,230,-22.73223914056,-34.91849805042,44.025140408125,2,1,18 +2025-03-11T12:41:59.793533,479392920,65316,230,-22.9772629648,-35.154596667675,44.45620858543,2,1,18 +2025-03-11T12:41:59.809158,479392920,65316,230,-23.23171078228,-35.404574806335,44.91045186007,2,1,18 +2025-03-11T12:41:59.824783,479392920,65316,230,-23.4720226099,-35.6545284861,45.36005360863,2,1,18 +2025-03-11T12:41:59.840408,479392920,65316,230,-23.71233443752,-35.89986109404,45.80039445106,2,1,18 +2025-03-11T12:41:59.856033,479392920,65316,230,-23.93851027528,-36.145169243085,46.24533613354,2,1,18 +2025-03-11T12:41:59.871658,479392920,65316,230,-24.16939810966,-36.37662232962,46.65788069557,2,1,18 +2025-03-11T12:41:59.887283,479392920,65316,230,-24.40028594404,-36.60345434433,47.093512632925,2,1,18 +2025-03-11T12:41:59.902908,479392920,65316,230,-24.62174978518,-36.83027005311,47.50140390988,2,1,18 +2025-03-11T12:41:59.918533,479392920,65316,230,-24.85734961618,-37.06173129261,47.913955252915,2,1,18 +2025-03-11T12:41:59.934158,479392920,65316,230,-25.0976614438,-37.2978217569,48.34963783228,2,1,18 +2025-03-11T12:41:59.949783,479392920,65316,230,-25.33797327142,-37.547775436665,48.78999721471,2,1,18 +2025-03-11T12:41:59.965408,479392920,65316,230,-25.5688611058,-37.78847066685,49.207200039805,2,1,18 +2025-03-11T12:41:59.981033,479392920,65316,230,-25.79503694356,-38.02915774407,49.615153717765,2,1,18 +2025-03-11T12:41:59.996658,479392920,65316,230,-26.0165007847,-38.2467313092,50.018386731655,2,1,18 +2025-03-11T12:42:00.012283,479392920,65316,230,-26.2521006157,-38.46895040505,50.426279811625,2,1,18 +2025-03-11T12:42:00.027908,479392920,65316,230,-26.49712443994,-38.705049022305,50.834242073605,2,1,18 +2025-03-11T12:42:00.043533,479392920,65316,230,-26.69502829798,-38.91333967896,51.232782919405,2,1,18 +2025-03-11T12:42:00.059158,479392920,65316,230,-26.90235614926,-39.130888785195,51.61751085802,2,1,18 +2025-03-11T12:42:00.074783,479392920,65316,230,-27.1238199904,-39.3438412785,52.016104148845,2,1,18 +2025-03-11T12:42:00.090408,479392920,65316,230,-27.34528383154,-39.55217269998,52.419300082735,2,1,18 +2025-03-11T12:42:00.106033,479392920,65316,230,-27.56674767268,-39.76974626511,52.83639664582,2,1,18 +2025-03-11T12:42:00.121658,479392920,65316,230,-27.79763550706,-39.99657827982,53.244301484785,2,1,18 +2025-03-11T12:42:00.137283,479392920,65316,230,-28.01438735158,-40.223385835635,53.642943614605,2,1,18 +2025-03-11T12:42:00.152908,479392920,65316,230,-28.2311391961,-40.436330175975,54.00918184297,2,1,18 +2025-03-11T12:42:00.168533,479392920,65316,230,-28.45260303724,-40.653903741105,54.40317249073,2,1,18 +2025-03-11T12:42:00.184158,479392920,65316,230,-28.65993088852,-40.86221070369,54.787863349345,2,1,18 +2025-03-11T12:42:00.199783,479392920,65316,230,-28.8672587398,-41.061275522625,55.186380677155,2,1,18 +2025-03-11T12:42:00.215408,479392920,65316,230,-29.06516259784,-41.264945107455,55.566418250695,2,1,18 +2025-03-11T12:42:00.231033,479392920,65316,230,-29.25364246264,-41.468598386355,55.93257871303,2,1,18 +2025-03-11T12:42:00.246658,479392920,65316,230,-29.46568231054,-41.667671358255,56.29875454039,2,1,18 +2025-03-11T12:42:00.262283,479392920,65316,230,-29.67301016182,-41.87597832084,56.646475934485,2,1,18 +2025-03-11T12:42:00.277908,479392920,65316,230,-29.86620202324,-42.079639752705,57.031127910085,2,1,18 +2025-03-11T12:42:00.293533,479392920,65316,230,-30.05468188804,-42.283293031605,57.429636653875,2,1,18 +2025-03-11T12:42:00.309158,479392920,65316,230,-30.25258574608,-42.48234154461,57.77730740596,2,1,18 +2025-03-11T12:42:00.324783,479392920,65316,230,-30.46462559398,-42.69065666016,58.129656764125,2,1,18 +2025-03-11T12:42:00.340408,479392920,65316,230,-30.68608943512,-42.885124866165,58.49120643043,2,1,18 +2025-03-11T12:42:00.356033,479392920,65316,230,-30.88399329316,-43.070310163695,58.866548660905,2,1,18 +2025-03-11T12:42:00.371658,479392920,65316,230,-31.07718515458,-43.26472945191,59.20957290892,2,1,18 +2025-03-11T12:42:00.387283,479392920,65316,230,-31.27508901262,-43.45915689309,59.55260393794,2,1,18 +2025-03-11T12:42:00.402908,479392920,65316,230,-31.4588568808,-43.64893880355,59.90021726701,2,1,18 +2025-03-11T12:42:00.418533,479392920,65316,230,-31.64262474898,-43.843341785835,60.24784913608,2,1,18 +2025-03-11T12:42:00.434158,479392920,65316,230,-31.83110461378,-44.03313184926,60.59084806309,2,1,18 +2025-03-11T12:42:00.449783,479392920,65316,230,-32.01016048534,-44.222905606755,60.93383342809,2,1,18 +2025-03-11T12:42:00.465408,479392920,65316,230,-32.18450436028,-44.403429067635,61.27215374902,2,1,18 +2025-03-11T12:42:00.481033,479392920,65316,230,-32.37298422508,-44.579355915585,61.601233506835,2,1,18 +2025-03-11T12:42:00.496658,479392920,65316,230,-32.55675209326,-44.76451675422,61.939585929775,2,1,18 +2025-03-11T12:42:00.512283,479392920,65316,230,-32.72638397158,-44.954274205785,62.264073000505,2,1,18 +2025-03-11T12:42:00.527908,479392920,65316,230,-32.90543984314,-45.13480581963,62.579294187115,2,1,18 +2025-03-11T12:42:00.543533,479392920,65316,230,-33.07978371808,-45.301466065035,62.899074155785,2,1,18 +2025-03-11T12:42:00.559158,479392920,65316,230,-33.2494155964,-45.4727392293,63.214244700385,2,1,18 +2025-03-11T12:42:00.574783,479392920,65316,230,-33.42375947134,-45.64402054653,63.53866439212,2,1,18 +2025-03-11T12:42:00.590408,479392920,65316,230,-33.59339134966,-45.815293710795,63.85383493672,2,1,18 +2025-03-11T12:42:00.606033,479392920,65316,230,-33.77244722122,-45.981962109165,64.173621686395,2,1,18 +2025-03-11T12:42:00.621658,479392920,65316,230,-33.94679109616,-46.13938021092,64.484122208935,2,1,18 +2025-03-11T12:42:00.637283,479392920,65316,230,-34.12584696772,-46.329153968415,64.780895743285,2,1,18 +2025-03-11T12:42:00.652908,479392920,65316,230,-34.30019084266,-46.500435285645,65.08683070276,2,1,18 +2025-03-11T12:42:00.668533,479392920,65316,230,-34.46039872774,-46.676313215805,65.378900310025,2,1,18 +2025-03-11T12:42:00.684158,479392920,65316,230,-34.62531860944,-46.829093939805,65.66626281523,2,1,18 +2025-03-11T12:42:00.699783,479392920,65316,230,-34.77610250128,-46.967986989435,65.95354935742,2,1,18 +2025-03-11T12:42:00.715408,479392920,65316,230,-34.9221743965,-47.120735101575,66.23626355554,2,1,18 +2025-03-11T12:42:00.731033,479392920,65316,230,-35.0870942782,-47.301242256525,66.51911611768,2,1,18 +2025-03-11T12:42:00.746658,479392920,65316,230,-35.25672615652,-47.45403113349,66.801864220825,2,1,18 +2025-03-11T12:42:00.762283,479392920,65316,230,-35.41222204498,-47.611416623385,67.075368154825,2,1,18 +2025-03-11T12:42:00.777908,479392920,65316,230,-35.56300593682,-47.759551816665,67.325722312495,2,1,18 +2025-03-11T12:42:00.793533,479392920,65316,230,-35.70436583542,-47.92153391949,67.603845626545,2,1,18 +2025-03-11T12:42:00.809158,479392920,65316,230,-35.84572573402,-48.06965280684,67.872670954465,2,1,18 +2025-03-11T12:42:00.824783,479392920,65316,230,-36.00122162248,-48.199311865785,68.15992719766,2,1,18 +2025-03-11T12:42:00.840408,479392920,65316,230,-36.14258152108,-48.347430753135,68.433373708645,2,1,18 +2025-03-11T12:42:00.856033,479392920,65316,230,-36.2886534163,-48.500178865275,68.679118442245,2,1,18 +2025-03-11T12:42:00.871658,479392920,65316,230,-36.42530131828,-48.652910671485,68.943334346095,2,1,18 +2025-03-11T12:42:00.887283,479392920,65316,230,-36.56666121688,-48.791787415185,69.20750141095,2,1,18 +2025-03-11T12:42:00.902908,479392920,65316,230,-36.70802111548,-48.930664158885,69.443941377415,2,1,18 +2025-03-11T12:42:00.918533,479392920,65316,230,-36.83524502422,-49.05103215639,69.68490802393,2,1,18 +2025-03-11T12:42:00.934158,479392920,65316,230,-36.9718929262,-49.17603753165,69.935149138585,2,1,18 +2025-03-11T12:42:00.949783,479392920,65316,230,-37.10854082818,-49.31952719421,70.180843230175,2,1,18 +2025-03-11T12:42:00.965408,479392920,65316,230,-37.22634074368,-49.44449995761,70.44029958694,2,1,18 +2025-03-11T12:42:00.981033,479392920,65316,230,-37.36298864566,-49.574126404695,70.6766956924,2,1,18 +2025-03-11T12:42:00.996658,479392920,65316,230,-37.50434854426,-49.703761004745,70.922340944995,2,1,18 +2025-03-11T12:42:01.012283,479392920,65316,230,-37.62686045638,-49.82874192111,71.144834618245,2,1,18 +2025-03-11T12:42:01.027908,479392920,65316,230,-37.7493723685,-49.94910176565,71.3534462023,2,1,18 +2025-03-11T12:42:01.043533,479392920,65316,230,-37.867172284,-50.078695600875,71.57133045148,2,1,18 +2025-03-11T12:42:01.059158,479392920,65316,230,-37.97554820626,-50.185167771045,71.793729621715,2,1,18 +2025-03-11T12:42:01.074783,479392920,65316,230,-38.08863612514,-50.287027022355,72.006874666825,2,1,18 +2025-03-11T12:42:01.090408,479392920,65316,230,-38.2205720305,-50.398161029175,72.20622036676,2,1,18 +2025-03-11T12:42:01.106033,479392920,65316,230,-38.338371946,-50.5277548644,72.42410461594,2,1,18 +2025-03-11T12:42:01.121658,479392920,65316,230,-38.45145986488,-50.652719474835,72.62809999492,2,1,18 +2025-03-11T12:42:01.137283,479392920,65316,230,-38.55983578714,-50.74532842953,72.831958812895,2,1,18 +2025-03-11T12:42:01.152908,479392920,65316,230,-38.66349971278,-50.870276734035,73.0313194468,2,1,18 +2025-03-11T12:42:01.168533,479392920,65316,230,-38.7624516418,-50.97211152645,73.244444148895,2,1,18 +2025-03-11T12:42:01.184158,479392920,65316,230,-38.86611556744,-51.078575543655,73.4437306228,2,1,18 +2025-03-11T12:42:01.199783,479392920,65316,230,-38.9744914897,-51.175805570175,73.629123248515,2,1,18 +2025-03-11T12:42:01.215408,479392920,65316,230,-39.07815541534,-51.27302744373,73.80988791016,2,1,18 +2025-03-11T12:42:01.231033,479392920,65316,230,-39.1865313376,-51.374878542075,73.99992025894,2,1,18 +2025-03-11T12:42:01.246658,479392920,65316,230,-39.29961925648,-51.476737793385,74.17609583953,2,1,18 +2025-03-11T12:42:01.262283,479392920,65316,230,-39.3985711855,-51.583193657625,74.34764843404,2,1,18 +2025-03-11T12:42:01.277908,479392920,65316,230,-39.48338712466,-51.685003991145,74.51454096247,2,1,18 +2025-03-11T12:42:01.293533,479392920,65316,230,-39.55877907058,-51.76369265961,74.676706045825,2,1,18 +2025-03-11T12:42:01.309158,479392920,65316,230,-39.63888301312,-51.865494840165,74.86207652551,2,1,18 +2025-03-11T12:42:01.324783,479392920,65316,230,-39.7284109489,-51.962692254825,75.010472562685,2,1,18 +2025-03-11T12:42:01.340408,479392920,65316,230,-39.83207487454,-52.04142984108,75.14495123368,2,1,18 +2025-03-11T12:42:01.356033,479392920,65316,230,-39.93102680356,-52.12015927437,75.29790785593,2,1,18 +2025-03-11T12:42:01.371658,479392920,65316,230,-40.00170675286,-52.203460861695,75.45084233215,2,1,18 +2025-03-11T12:42:01.387283,479392920,65316,230,-40.06767470554,-52.27289108058,75.585229675105,2,1,18 +2025-03-11T12:42:01.402908,479392920,65316,230,-40.13835465484,-52.346950524255,75.728884705195,2,1,18 +2025-03-11T12:42:01.418533,479392920,65316,230,-40.21374660076,-52.430260264545,75.89106832855,2,1,18 +2025-03-11T12:42:01.434158,479392920,65316,230,-40.29856253992,-52.51820738259,76.02093577246,2,1,18 +2025-03-11T12:42:01.449783,479392920,65316,230,-40.37866648246,-52.57841991672,76.150685195365,2,1,18 +2025-03-11T12:42:01.465408,479392920,65316,230,-40.45405842838,-52.65248751336,76.28510464033,2,1,18 +2025-03-11T12:42:01.481033,479392920,65316,230,-40.51531438444,-52.73115172293,76.424143465345,2,1,18 +2025-03-11T12:42:01.496658,479392920,65316,230,-40.58599433374,-52.80983223843,76.540089937045,2,1,18 +2025-03-11T12:42:01.512283,479392920,65316,230,-40.64253829318,-52.870004007735,76.65594190573,2,1,18 +2025-03-11T12:42:01.527908,479392920,65316,230,-40.70850624586,-52.93019208297,76.771807436425,2,1,18 +2025-03-11T12:42:01.543533,479392920,65316,230,-40.7650502053,-52.999605995925,76.89693885124,2,1,18 +2025-03-11T12:42:01.559158,479392920,65316,230,-40.83101815798,-53.055172999335,77.00816465887,2,1,18 +2025-03-11T12:42:01.574783,479392920,65316,230,-40.89698611066,-53.110740002745,77.105526917305,2,1,18 +2025-03-11T12:42:01.590408,479392920,65316,230,-40.96766605996,-53.170936230945,77.20753567981,2,1,18 +2025-03-11T12:42:01.606033,479392920,65316,230,-41.01007402954,-53.21722032588,77.318690502415,2,1,18 +2025-03-11T12:42:01.621658,479392920,65316,230,-41.06190599236,-53.272762870395,77.41141123477,2,1,18 +2025-03-11T12:42:01.637283,479392920,65316,230,-41.12787394504,-53.32370880198,77.527239685465,2,1,18 +2025-03-11T12:42:01.652908,479392920,65316,230,-41.18441790448,-53.383880571285,77.610743372695,2,1,18 +2025-03-11T12:42:01.668533,479392920,65316,230,-41.23153787068,-53.430172819185,77.694177877915,2,1,18 +2025-03-11T12:42:01.684158,479392920,65316,230,-41.26923384364,-53.467206617505,77.77294055806,2,1,18 +2025-03-11T12:42:01.699783,479392920,65316,230,-41.32106580646,-53.51350701837,77.84251829509,2,1,18 +2025-03-11T12:42:01.715408,479392920,65316,230,-41.36347377604,-53.56441218513,77.90285864398,2,1,18 +2025-03-11T12:42:01.731033,479392920,65316,230,-41.40588174562,-53.59683306459,77.986230748195,2,1,18 +2025-03-11T12:42:01.746658,479392920,65316,230,-41.42944172872,-53.606115973065,78.037134746935,2,1,18 +2025-03-11T12:42:01.762283,479392920,65316,230,-41.46713770168,-53.643149771385,78.102033877885,2,1,18 +2025-03-11T12:42:01.777908,479392920,65316,230,-41.50954567126,-53.675570650845,78.171542432905,2,1,18 +2025-03-11T12:42:01.793533,479392920,65316,230,-41.53310565436,-53.68485355932,78.213204065515,2,1,18 +2025-03-11T12:42:01.809158,479392920,65316,230,-41.5425296476,-53.726459511675,78.250353952045,2,1,18 +2025-03-11T12:42:01.824783,479392920,65316,230,-41.55666563746,-53.758831473345,78.310579454905,2,1,18 +2025-03-11T12:42:01.840408,479392920,65316,230,-41.59907360704,-53.782010209155,78.36618738073,2,1,18 +2025-03-11T12:42:01.856033,479392920,65316,230,-41.63676958,-53.8236650793,78.426483868615,2,1,18 +2025-03-11T12:42:01.871658,479392920,65316,230,-41.65561756648,-53.846803050285,78.45895197409,2,1,18 +2025-03-11T12:42:01.887283,479392920,65316,230,-41.6603295631,-53.8560533469,78.46361701816,2,1,18 +2025-03-11T12:42:01.902908,479392920,65316,230,-41.67446555296,-53.86994102127,78.50528362876,2,1,18 +2025-03-11T12:42:01.918533,479392920,65316,230,-41.67917754958,-53.888433461535,78.51922811896,2,1,18 +2025-03-11T12:42:01.934158,479392920,65316,230,-41.6838895462,-53.9069259018,78.53317260916,2,1,18 +2025-03-11T12:42:01.949783,479392920,65316,230,-41.7074495293,-53.9208298821,78.560989232575,2,1,18 +2025-03-11T12:42:01.965408,479392920,65316,230,-41.7310095124,-53.939354934225,78.593445579055,2,1,18 +2025-03-11T12:42:01.981033,479392920,65316,230,-41.7310095124,-53.957839221525,78.61662565438,2,1,18 +2025-03-11T12:42:01.996597,479392924,65312,231,-41.73572150902,-53.95784737449,78.63973835071,2,1,18 +2025-03-11T12:42:02.012222,479392924,65312,231,-41.74514550226,-53.95786368042,78.644373095785,2,1,18 +2025-03-11T12:42:02.027847,479392924,65312,231,-41.76399348874,-53.94865414863,78.63974195674,2,1,18 +2025-03-11T12:42:02.043472,479392924,65312,231,-41.75928149212,-53.95326706749,78.62589016654,2,1,18 +2025-03-11T12:42:02.059097,479392924,65312,231,-41.74514550226,-53.95786368042,78.625888363525,2,1,18 +2025-03-11T12:42:02.074722,479392924,65312,231,-41.74514550226,-53.94862153677,78.635093649655,2,1,18 +2025-03-11T12:42:02.090347,479392924,65312,231,-41.74514550226,-53.93937939312,78.6027082882,2,1,18 +2025-03-11T12:42:02.105972,479392924,65312,231,-41.73572150902,-53.93012094354,78.59341528006,2,1,18 +2025-03-11T12:42:02.121597,479392924,65312,231,-41.71687352254,-53.916225116205,78.579468986845,2,1,18 +2025-03-11T12:42:02.137222,479392924,65312,231,-41.7074495293,-53.9023455948,78.560915072575,2,1,18 +2025-03-11T12:42:02.152847,479392924,65312,231,-41.69331353944,-53.89770006408,78.5423914573,2,1,18 +2025-03-11T12:42:02.168472,479392924,65312,231,-41.67446555296,-53.88842530857,78.51460015489,2,1,18 +2025-03-11T12:42:02.184097,479392924,65312,231,-41.64619357324,-53.874513175305,78.47753438434,2,1,18 +2025-03-11T12:42:02.199722,479392924,65312,231,-41.62734558676,-53.84213306067,78.4404080158,2,1,18 +2025-03-11T12:42:02.215347,479392924,65312,231,-41.59907360704,-53.81435771193,78.380180709925,2,1,18 +2025-03-11T12:42:02.230972,479392924,65312,231,-41.58493761718,-53.78198575026,78.33381875626,2,1,18 +2025-03-11T12:42:02.246597,479392924,65312,231,-41.55666563746,-53.749589329695,78.28743645958,2,1,18 +2025-03-11T12:42:02.262222,479392924,65312,231,-41.52368166112,-53.735669043465,78.23650035883,2,1,18 +2025-03-11T12:42:02.277847,479392924,65312,231,-41.50483367464,-53.70328892883,78.19013162416,2,1,18 +2025-03-11T12:42:02.293472,479392924,65312,231,-41.46713770168,-53.670876202335,78.129872216275,2,1,18 +2025-03-11T12:42:02.309097,479392924,65312,231,-41.43415372534,-53.638471628805,78.07424077246,2,1,18 +2025-03-11T12:42:02.324722,479392924,65312,231,-41.41059374224,-53.587599073905,78.027791096785,2,1,18 +2025-03-11T12:42:02.340347,479392924,65312,231,-41.37289776928,-53.550565275585,77.935164867445,2,1,18 +2025-03-11T12:42:02.355972,479392924,65312,231,-41.33520179632,-53.513531477265,77.833296271975,2,1,18 +2025-03-11T12:42:02.371597,479392924,65312,231,-41.29279382674,-53.47648952598,77.763769176955,2,1,18 +2025-03-11T12:42:02.387222,479392924,65312,231,-41.25509785378,-53.43945572766,77.680385313745,2,1,18 +2025-03-11T12:42:02.402847,479392924,65312,231,-41.21740188082,-53.397800857515,77.615467642795,2,1,18 +2025-03-11T12:42:02.418472,479392924,65312,231,-41.17028191462,-53.34688753779,77.513529865315,2,1,18 +2025-03-11T12:42:02.434097,479392924,65312,231,-41.11373795518,-53.286715768485,77.402299079695,2,1,18 +2025-03-11T12:42:02.449722,479392924,65312,231,-41.05248199912,-53.22191477439,77.31877007146,2,1,18 +2025-03-11T12:42:02.465347,479392924,65312,231,-41.00536203292,-53.15713823919,77.212155490915,2,1,18 +2025-03-11T12:42:02.480972,479392924,65312,231,-40.94410607686,-53.10620046057,77.11019737042,2,1,18 +2025-03-11T12:42:02.496597,479392924,65312,231,-40.89227411404,-53.059900059705,77.012892535,2,1,18 +2025-03-11T12:42:02.512222,479392924,65312,231,-40.8357301546,-52.99048614675,76.924730584705,2,1,18 +2025-03-11T12:42:02.527847,479392924,65312,231,-40.76976220192,-52.921055927865,76.813449157075,2,1,18 +2025-03-11T12:42:02.543472,479392924,65312,231,-40.70850624586,-52.879360292895,76.69304338432,2,1,18 +2025-03-11T12:42:02.559097,479392924,65312,231,-40.64253829318,-52.80993007401,76.558656041365,2,1,18 +2025-03-11T12:42:02.574722,479392924,65312,231,-40.58128233712,-52.735886936265,76.442741671675,2,1,18 +2025-03-11T12:42:02.590347,479392924,65312,231,-40.52002638106,-52.67108594217,76.31300083279,2,1,18 +2025-03-11T12:42:02.605972,479392924,65312,231,-40.44463443514,-52.601639417355,76.178599927825,2,1,18 +2025-03-11T12:42:02.621597,479392924,65312,231,-40.3645304926,-52.522942595925,76.04877634492,2,1,18 +2025-03-11T12:42:02.637222,479392924,65312,231,-40.28442655006,-52.435003630845,75.91429449895,2,1,18 +2025-03-11T12:42:02.652847,479392924,65312,231,-40.20432260752,-52.365548953065,75.77064444685,2,1,18 +2025-03-11T12:42:02.668472,479392924,65312,231,-40.1289306616,-52.2868602846,75.626964095755,2,1,18 +2025-03-11T12:42:02.684097,479392924,65312,231,-40.06767470554,-52.222059290505,75.511086806065,2,1,18 +2025-03-11T12:42:02.699722,479392924,65312,231,-39.98285876638,-52.13411217246,75.353492263765,2,1,18 +2025-03-11T12:42:02.715347,479392924,65312,231,-39.8933308306,-52.041535829625,75.19587240046,2,1,18 +2025-03-11T12:42:02.730972,479392924,65312,231,-39.81322688806,-51.953596864545,75.0336634561,2,1,18 +2025-03-11T12:42:02.746597,479392924,65312,231,-39.7284109489,-51.87489189015,74.86686362767,2,1,18 +2025-03-11T12:42:02.762222,479392924,65312,231,-39.6341710165,-51.786928466175,74.686149608035,2,1,18 +2025-03-11T12:42:02.777847,479392924,65312,231,-39.54464308072,-51.698973195165,74.5193059186,2,1,18 +2025-03-11T12:42:02.793472,479392924,65312,231,-39.45982714156,-51.60178393347,74.35243193017,2,1,18 +2025-03-11T12:42:02.809097,479392924,65312,231,-39.35616321592,-51.513804203565,74.171704348525,2,1,18 +2025-03-11T12:42:02.824722,479392924,65312,231,-39.26192328352,-51.41659863594,74.004816798085,2,1,18 +2025-03-11T12:42:02.840347,479392924,65312,231,-39.1629713545,-51.314763843525,73.833282743575,2,1,18 +2025-03-11T12:42:02.855972,479392924,65312,231,-39.06401942548,-51.20368690746,73.63860569374,2,1,18 +2025-03-11T12:42:02.871597,479392924,65312,231,-38.95564350322,-51.101835809115,73.443952161895,2,1,18 +2025-03-11T12:42:02.887222,479392924,65312,231,-38.8566915742,-50.99075887305,73.24927511206,2,1,18 +2025-03-11T12:42:02.902847,479392924,65312,231,-38.7624516418,-50.875069018125,73.07307103549,2,1,18 +2025-03-11T12:42:02.918472,479392924,65312,231,-38.64936372292,-50.763967623165,72.901479557965,2,1,18 +2025-03-11T12:42:02.934097,479392924,65312,231,-38.53627580404,-50.63900301273,72.678999446725,2,1,18 +2025-03-11T12:42:02.949722,479392924,65312,231,-38.41376389192,-50.54636959914,72.45201437041,2,1,18 +2025-03-11T12:42:02.965347,479392924,65312,231,-38.30538796966,-50.44913957262,72.229652280175,2,1,18 +2025-03-11T12:42:02.980972,479392924,65312,231,-38.18758805416,-50.33340895287,72.011823650995,2,1,18 +2025-03-11T12:42:02.996597,479392924,65312,231,-38.07450013528,-50.208444342435,71.798585905885,2,1,18 +2025-03-11T12:42:03.012222,479392924,65312,231,-37.95670021978,-50.09733479451,71.60388173203,2,1,18 +2025-03-11T12:42:03.027847,479392924,65312,231,-37.83418830766,-49.981596021795,71.39990987104,2,1,18 +2025-03-11T12:42:03.043472,479392924,65312,231,-37.7022524023,-49.851977727675,71.17738409578,2,1,18 +2025-03-11T12:42:03.059097,479392924,65312,231,-37.5844524868,-49.717762820625,70.96872367273,2,1,18 +2025-03-11T12:42:03.074722,479392924,65312,231,-37.47136456792,-49.58355606654,70.723100566165,2,1,18 +2025-03-11T12:42:03.090347,479392924,65312,231,-37.35827664904,-49.46321252793,70.482154262665,2,1,18 +2025-03-11T12:42:03.105972,479392924,65312,231,-37.2310527403,-49.34746560225,70.23196379002,2,1,18 +2025-03-11T12:42:03.121597,479392924,65312,231,-37.0896928417,-49.203967786725,69.995505283555,2,1,18 +2025-03-11T12:42:03.137222,479392924,65312,231,-36.95304493972,-49.04661490869,69.7451343889,2,1,18 +2025-03-11T12:42:03.152847,479392924,65312,231,-36.81639703774,-48.90312524613,69.485576748115,2,1,18 +2025-03-11T12:42:03.168472,479392924,65312,231,-36.689173129,-48.773515104975,69.239951838535,2,1,18 +2025-03-11T12:42:03.184097,479392924,65312,231,-36.55723722364,-48.643896810855,68.99432014795,2,1,18 +2025-03-11T12:42:03.199722,479392924,65312,231,-36.41116532842,-48.518875129665,68.73944428822,2,1,18 +2025-03-11T12:42:03.215347,479392924,65312,231,-36.26980542982,-48.361514098665,68.475203063365,2,1,18 +2025-03-11T12:42:03.230972,479392924,65312,231,-36.10959754474,-48.213362599455,68.22021416062,2,1,18 +2025-03-11T12:42:03.246597,479392924,65312,231,-35.95410165628,-48.09294568416,67.960722095815,2,1,18 +2025-03-11T12:42:03.262222,479392924,65312,231,-35.8174537543,-47.935592806125,67.68262410277,2,1,18 +2025-03-11T12:42:03.277847,479392924,65312,231,-35.6760938557,-47.787473918775,67.409177591785,2,1,18 +2025-03-11T12:42:03.293472,479392924,65312,231,-35.52059796724,-47.63008842888,67.144916023915,2,1,18 +2025-03-11T12:42:03.309097,479392924,65312,231,-35.35096608892,-47.468057408265,66.8713732069,2,1,18 +2025-03-11T12:42:03.324722,479392924,65312,231,-35.19075820384,-47.329148052705,66.579451919635,2,1,18 +2025-03-11T12:42:03.340347,479392924,65312,231,-35.04468630862,-47.17177886874,66.29209799845,2,1,18 +2025-03-11T12:42:03.355972,479392924,65312,231,-34.89390241678,-47.000538316335,66.000060493195,2,1,18 +2025-03-11T12:42:03.371597,479392924,65312,231,-34.7336945317,-46.829281458,65.712630608995,2,1,18 +2025-03-11T12:42:03.387222,479392924,65312,231,-34.56877465,-46.6580164467,65.41595157766,2,1,18 +2025-03-11T12:42:03.402847,479392924,65312,231,-34.40856676492,-46.50062280384,65.114713764265,2,1,18 +2025-03-11T12:42:03.418472,479392924,65312,231,-34.25778287308,-46.347866538735,64.81350805288,2,1,18 +2025-03-11T12:42:03.434097,479392924,65312,231,-34.08815099476,-46.171972302645,64.51680370054,2,1,18 +2025-03-11T12:42:03.449722,479392924,65312,231,-33.91380711982,-45.99606991359,64.21547138413,2,1,18 +2025-03-11T12:42:03.465347,479392924,65312,231,-33.75359923474,-45.82943412708,63.90957530767,2,1,18 +2025-03-11T12:42:03.480972,479392924,65312,231,-33.5792553598,-45.6489106662,63.59898208513,2,1,18 +2025-03-11T12:42:03.496597,479392924,65312,231,-33.390775495,-45.486847033725,63.288442679575,2,1,18 +2025-03-11T12:42:03.512222,479392924,65312,231,-33.21643162006,-45.315565716495,62.96402298784,2,1,18 +2025-03-11T12:42:03.527847,479392924,65312,231,-33.05151173836,-45.13043748972,62.61645532279,2,1,18 +2025-03-11T12:42:03.543472,479392924,65312,231,-32.86774387018,-44.963760938385,62.29666179211,2,1,18 +2025-03-11T12:42:03.559097,479392924,65312,231,-32.68868799862,-44.778608252715,61.995285614695,2,1,18 +2025-03-11T12:42:03.574722,479392924,65312,231,-32.50963212706,-44.584213423395,61.65690289276,2,1,18 +2025-03-11T12:42:03.590347,479392924,65312,231,-32.3305762555,-44.40368180955,61.32319697389,2,1,18 +2025-03-11T12:42:03.605972,479392924,65312,231,-32.15152038394,-44.223150195705,60.975627505825,2,1,18 +2025-03-11T12:42:03.621597,479392924,65312,231,-31.977176509,-44.033384591175,60.64189128796,2,1,18 +2025-03-11T12:42:03.637222,479392924,65312,231,-31.77927265096,-43.85282036547,60.303537062005,2,1,18 +2025-03-11T12:42:03.652847,479392924,65312,231,-31.59079278616,-43.672272445695,59.969817581125,2,1,18 +2025-03-11T12:42:03.668472,479392924,65312,231,-31.40231292136,-43.487103454095,59.62221601105,2,1,18 +2025-03-11T12:42:03.684097,479392924,65312,231,-31.21854505318,-43.29270047181,59.25609940972,2,1,18 +2025-03-11T12:42:03.699722,479392924,65312,231,-31.03006518838,-43.084426121085,58.89454159045,2,1,18 +2025-03-11T12:42:03.715347,479392924,65312,231,-30.83216133034,-42.871514392605,58.5421940353,2,1,18 +2025-03-11T12:42:03.730972,479392924,65312,231,-30.63896946892,-42.672474032565,58.208393613415,2,1,18 +2025-03-11T12:42:03.746597,479392924,65312,231,-30.45048960412,-42.48268396914,57.846909954145,2,1,18 +2025-03-11T12:42:03.762222,479392924,65312,231,-30.2572977427,-42.3021278964,57.490077776935,2,1,18 +2025-03-11T12:42:03.777847,479392924,65312,231,-30.0452578948,-42.11229706815,57.11007548038,2,1,18 +2025-03-11T12:42:03.793472,479392924,65312,231,-29.84264204014,-41.90399825853,56.739254951965,2,1,18 +2025-03-11T12:42:03.809097,479392924,65312,231,-29.6447381821,-41.695707601875,56.368441204555,2,1,18 +2025-03-11T12:42:03.824722,479392924,65312,231,-29.43741033082,-41.482779567465,55.997595355135,2,1,18 +2025-03-11T12:42:03.840347,479392924,65312,231,-29.23008247954,-41.279093676705,55.62216540265,2,1,18 +2025-03-11T12:42:03.855972,479392924,65312,231,-29.01804263164,-41.080020704805,55.232883659965,2,1,18 +2025-03-11T12:42:03.871597,479392924,65312,231,-28.80600278374,-40.871705589255,54.84356483728,2,1,18 +2025-03-11T12:42:03.887222,479392924,65312,231,-28.60338692908,-40.663406779635,54.45888075967,2,1,18 +2025-03-11T12:42:03.902847,479392924,65312,231,-28.40077107442,-40.445865826365,54.08340196819,2,1,18 +2025-03-11T12:42:03.918472,479392924,65312,231,-28.18873122652,-40.228308567165,53.7079096147,2,1,18 +2025-03-11T12:42:03.934097,479392924,65312,231,-27.971979382,-40.0292274423,53.30013635875,2,1,18 +2025-03-11T12:42:03.949722,479392924,65312,231,-27.76936352734,-39.797823273555,52.901496031945,2,1,18 +2025-03-11T12:42:03.965347,479392924,65312,231,-27.56674767268,-39.58490339211,52.49368749901,2,1,18 +2025-03-11T12:42:03.980972,479392924,65312,231,-27.34999582816,-39.36271690812,52.090442726125,2,1,18 +2025-03-11T12:42:03.996597,479392924,65312,231,-27.1238199904,-39.1405141182,51.6779420251,2,1,18 +2025-03-11T12:42:04.012222,479392924,65312,231,-26.89764415264,-38.922932400105,51.27932341327,2,1,18 +2025-03-11T12:42:04.027847,479392924,65312,231,-26.6761803115,-38.705358834975,50.889953948575,2,1,18 +2025-03-11T12:42:04.043472,479392924,65312,231,-26.45000447374,-38.473913901405,50.49590089981,2,1,18 +2025-03-11T12:42:04.059097,479392924,65312,231,-26.21440464274,-38.25631587738,50.08802635984,2,1,18 +2025-03-11T12:42:04.074722,479392924,65312,231,-25.98822880498,-38.04335523111,49.68942628801,2,1,18 +2025-03-11T12:42:04.090347,479392924,65312,231,-25.75262897398,-37.80265184796,49.276837864975,2,1,18 +2025-03-11T12:42:04.105972,479392924,65312,231,-25.52645313622,-37.54348048344,48.84570411169,2,1,18 +2025-03-11T12:42:04.121597,479392924,65312,231,-25.30498929508,-37.31666477466,48.428570468605,2,1,18 +2025-03-11T12:42:04.137222,479392924,65312,231,-25.0741014607,-37.085211688125,47.979056442055,2,1,18 +2025-03-11T12:42:04.152847,479392924,65312,231,-24.85263761956,-36.85377490752,47.55266189284,2,1,18 +2025-03-11T12:42:04.168472,479392924,65312,231,-24.63117377842,-36.603853839615,47.14005673282,2,1,18 +2025-03-11T12:42:04.184097,479392924,65312,231,-24.38614995418,-36.381618437835,46.718286541645,2,1,18 +2025-03-11T12:42:04.199722,479392924,65312,231,-24.14112612994,-36.14551982058,46.27797599821,2,1,18 +2025-03-11T12:42:04.215347,479392924,65312,231,-23.90552629894,-35.91405858108,45.84231873985,2,1,18 +2025-03-11T12:42:04.230972,479392924,65312,231,-23.67463846456,-35.66874227907,45.425097374755,2,1,18 +2025-03-11T12:42:04.246597,479392924,65312,231,-23.4484626268,-35.42805520185,44.97555304921,2,1,18 +2025-03-11T12:42:04.262222,479392924,65312,231,-23.19872680594,-35.17346414433,44.521298015575,2,1,18 +2025-03-11T12:42:04.277847,479392924,65312,231,-22.93485499522,-34.937332915215,44.08096034812,2,1,18 +2025-03-11T12:42:04.293472,479392924,65312,231,-22.68040717774,-34.696596920205,43.640617702675,2,1,18 +2025-03-11T12:42:04.309097,479392924,65312,231,-22.44951934336,-34.45590169002,43.19568777919,2,1,18 +2025-03-11T12:42:04.324722,479392924,65312,231,-22.1997835225,-34.205931704325,42.750693651685,2,1,18 +2025-03-11T12:42:04.340347,479392924,65312,231,-21.95004770164,-33.951340646805,42.291817434985,2,1,18 +2025-03-11T12:42:04.355972,479392924,65312,231,-21.70031188078,-33.724476020235,41.84691600748,2,1,18 +2025-03-11T12:42:04.371597,479392924,65312,231,-21.45528805654,-33.47913525933,41.388083651785,2,1,18 +2025-03-11T12:42:04.387222,479392924,65312,231,-21.20084023906,-33.196809617895,40.92908941408,2,1,18 +2025-03-11T12:42:04.402847,479392924,65312,231,-20.9511044182,-32.942218560375,40.456349648185,2,1,18 +2025-03-11T12:42:04.418472,479392924,65312,231,-20.70136859734,-32.70149071833,39.98366550229,2,1,18 +2025-03-11T12:42:04.434097,479392924,65312,231,-20.44220878324,-32.423777995755,39.53392538971,2,1,18 +2025-03-11T12:42:04.449722,479392924,65312,231,-20.197184959,-32.164574019375,39.07041623095,2,1,18 +2025-03-11T12:42:04.465347,479392924,65312,231,-19.94744913814,-31.919225105505,38.597713545055,2,1,18 +2025-03-11T12:42:04.480972,479392924,65312,231,-19.66944133756,-31.683069417495,38.129628436195,2,1,18 +2025-03-11T12:42:04.496597,479392924,65312,231,-19.40085753022,-31.428445748115,37.661482729345,2,1,18 +2025-03-11T12:42:04.512222,479392924,65312,231,-19.1605457026,-31.183113140175,37.193414788525,2,1,18 +2025-03-11T12:42:04.527847,479392924,65312,231,-18.91552187836,-30.914667020145,36.71600500057,2,1,18 +2025-03-11T12:42:04.543472,479392924,65312,231,-18.65165006764,-30.64156721643,36.247791914725,2,1,18 +2025-03-11T12:42:04.559097,479392924,65312,231,-18.38777825692,-30.396193843665,35.77969006888,2,1,18 +2025-03-11T12:42:04.574722,479392924,65312,231,-18.1474664293,-30.1277558766,35.2930446958,2,1,18 +2025-03-11T12:42:04.590347,479392924,65312,231,-17.89773060844,-29.859301603605,34.79714339458,2,1,18 +2025-03-11T12:42:04.605972,479392924,65312,231,-17.63385879772,-29.57695965624,34.310408496475,2,1,18 +2025-03-11T12:42:04.621597,479392924,65312,231,-17.36527499038,-29.30385169956,33.851430995755,2,1,18 +2025-03-11T12:42:04.637222,479392924,65312,231,-17.09197918642,-29.04459880539,33.360154052575,2,1,18 +2025-03-11T12:42:04.652847,479392924,65312,231,-16.81868338246,-28.789966983045,32.868895649395,2,1,18 +2025-03-11T12:42:04.668472,479392924,65312,231,-16.5453875785,-28.502987657925,32.39137101541,2,1,18 +2025-03-11T12:42:04.684097,479392924,65312,231,-16.27209177454,-28.22062940463,31.90000137223,2,1,18 +2025-03-11T12:42:04.699722,479392924,65312,231,-16.01293196044,-27.94753775388,31.417931518195,2,1,18 +2025-03-11T12:42:04.715347,479392924,65312,231,-15.73963615648,-27.66980057241,30.93120159808,2,1,18 +2025-03-11T12:42:04.730972,479392924,65312,231,-15.4616283559,-27.410539525275,30.4260543247,2,1,18 +2025-03-11T12:42:04.746597,479392924,65312,231,-15.18362055532,-27.16052062179,29.934807680515,2,1,18 +2025-03-11T12:42:04.762222,479392924,65312,231,-14.91032475136,-26.887404512145,29.43885393427,2,1,18 +2025-03-11T12:42:04.777847,479392924,65312,231,-14.64174094402,-26.595812268165,28.928969259835,2,1,18 +2025-03-11T12:42:04.793472,479392924,65312,231,-14.36844514006,-26.32269615852,28.42377314746,2,1,18 +2025-03-11T12:42:04.809097,479392924,65312,231,-14.0951493361,-26.04495897705,27.918558495085,2,1,18 +2025-03-11T12:42:04.824722,479392924,65312,231,-13.82656552876,-25.776472092195,27.413387703715,2,1,18 +2025-03-11T12:42:04.840347,479392924,65312,231,-13.54384573156,-25.498718604795,26.912780672395,2,1,18 +2025-03-11T12:42:04.855972,479392924,65312,231,-13.26583793098,-25.225594342185,26.407577779015,2,1,18 +2025-03-11T12:42:04.871597,479392924,65312,231,-12.99725412364,-24.94786531368,25.893127541515,2,1,18 +2025-03-11T12:42:04.887222,479392924,65312,231,-12.71453432644,-24.665490754455,25.378638421,2,1,18 +2025-03-11T12:42:04.902847,479392924,65312,231,-12.43181452924,-24.38311619523,24.87801284968,2,1,18 +2025-03-11T12:42:04.918472,479392924,65312,231,-12.14438273542,-24.096112411215,24.35425604203,2,1,18 +2025-03-11T12:42:04.934097,479392924,65312,231,-11.86166293822,-23.81373785199,23.84438810458,2,1,18 +2025-03-11T12:42:04.949722,479392924,65312,231,-11.59307913088,-23.54062989531,23.34844113934,2,1,18 +2025-03-11T12:42:04.965347,479392924,65312,231,-11.32449532354,-23.262900866805,22.829369718775,2,1,18 +2025-03-11T12:42:04.980972,479392924,65312,231,-11.04177552634,-22.975905235755,22.296377326,2,1,18 +2025-03-11T12:42:04.996597,479392924,65312,231,-10.75905572914,-22.670425317405,21.76793195629,2,1,18 +2025-03-11T12:42:05.012222,479392924,65312,231,-10.47162393532,-22.37417938974,21.25338043477,2,1,18 +2025-03-11T12:42:05.027847,479392924,65312,231,-10.17948014488,-22.101030668235,20.72505128305,2,1,18 +2025-03-11T12:42:05.043472,479392924,65312,231,-9.89204835106,-21.83251117152,20.215232184595,2,1,18 +2025-03-11T12:42:05.059097,479392924,65312,231,-9.60461655724,-21.545507387505,19.682233010815,2,1,18 +2025-03-11T12:42:05.074722,479392924,65312,231,-9.32189676004,-21.24464854098,19.13994263191,2,1,18 +2025-03-11T12:42:05.090347,479392924,65312,231,-9.0297529696,-20.962257675825,18.62081876632,2,1,18 +2025-03-11T12:42:05.105972,479392924,65312,231,-8.7470331724,-20.656777757475,18.106236945805,2,1,18 +2025-03-11T12:42:05.121597,479392924,65312,231,-8.4643133752,-20.379024270075,17.577902816095,2,1,18 +2025-03-11T12:42:05.137222,479392924,65312,231,-8.19101757124,-20.08742387313,17.04490544533,2,1,18 +2025-03-11T12:42:05.152847,479392924,65312,231,-7.88473779094,-19.791145333605,16.52108443366,2,1,18 +2025-03-11T12:42:05.168472,479392924,65312,231,-7.58317000726,-19.504117090695,16.00192846606,2,1,18 +2025-03-11T12:42:05.184097,479392924,65312,231,-7.2863142202,-19.230960216225,15.4782137164,2,1,18 +2025-03-11T12:42:05.199722,479392924,65312,231,-6.99888242638,-18.92547214491,14.949761565685,2,1,18 +2025-03-11T12:42:05.215347,479392924,65312,231,-6.71145063256,-18.63384728907,14.42136503497,2,1,18 +2025-03-11T12:42:05.230972,479392924,65312,231,-6.41930684212,-18.33759320844,13.888322000185,2,1,18 +2025-03-11T12:42:05.246597,479392924,65312,231,-6.12716305168,-18.036718055985,13.359881608465,2,1,18 +2025-03-11T12:42:05.262222,479392924,65312,231,-5.8491552511,-17.754351649725,12.826914536695,2,1,18 +2025-03-11T12:42:05.277847,479392924,65312,231,-5.55229946404,-17.462710487955,12.29850444397,2,1,18 +2025-03-11T12:42:05.293472,479392924,65312,231,-5.2601556736,-17.17107747915,11.76085876612,2,1,18 +2025-03-11T12:42:05.309097,479392924,65312,231,-4.95858788992,-16.88404923624,11.19549096787,2,1,18 +2025-03-11T12:42:05.324722,479392924,65312,231,-4.66173210286,-16.587787002645,10.648577602885,2,1,18 +2025-03-11T12:42:05.340347,479392924,65312,231,-4.3648763158,-16.2822826254,10.115490707095,2,1,18 +2025-03-11T12:42:05.355972,479392924,65312,231,-4.06802052874,-15.97215717633,9.591627637435,2,1,18 +2025-03-11T12:42:05.371597,479392924,65312,231,-3.7758767383,-15.671282023875,9.05856606265,2,1,18 +2025-03-11T12:42:05.387222,479392924,65312,231,-3.48373294786,-15.375027943245,8.516280661735,2,1,18 +2025-03-11T12:42:05.402847,479392924,65312,231,-3.19158915742,-15.08339493444,7.97401380082,2,1,18 +2025-03-11T12:42:05.418472,479392924,65312,231,-2.89002137374,-14.79636669153,7.42713073483,2,1,18 +2025-03-11T12:42:05.434097,479392924,65312,231,-2.59316558668,-14.49548338611,6.880198829845,2,1,18 +2025-03-11T12:42:05.449722,479392924,65312,231,-2.291597803,-14.185349784075,6.333223063855,2,1,18 +2025-03-11T12:42:05.465347,479392924,65312,231,-2.00416600918,-13.884482784585,5.79554708701,2,1,18 +2025-03-11T12:42:05.480972,479392924,65312,231,-1.70731022212,-13.583599479165,5.267099914285,2,1,18 +2025-03-11T12:42:05.496597,479392924,65312,231,-1.41045443506,-13.28733724557,4.73867128156,2,1,18 +2025-03-11T12:42:05.512222,479392924,65312,231,-1.09946265814,-12.99105055308,4.20097993969,2,1,18 +2025-03-11T12:42:05.527847,479392924,65312,231,-0.8073188677,-12.6855543288,3.67252100797,2,1,18 +2025-03-11T12:42:05.543472,479392924,65312,231,-0.51046308064,-12.38467102338,3.107104370725,2,1,18 +2025-03-11T12:42:05.559097,479392924,65312,231,-0.2183192902,-12.0791747991,2.550918340615,2,1,18 +2025-03-11T12:42:05.574722,479392924,65312,231,0.0785364968599999,-11.78753363733,1.999402332565,2,1,18 +2025-03-11T12:42:05.590347,479392924,65312,231,0.38952827378,-11.49124694484,1.470953356825,2,1,18 +2025-03-11T12:42:05.605972,479392924,65312,231,0.68167206422,-11.18575072056,0.933252058975,2,1,18 +2025-03-11T12:42:05.621597,479392924,65312,231,0.99266384114,-10.903327243545,0.38175278791,2,1,18 +2025-03-11T12:42:05.637222,479392924,65312,231,1.2895196282,-10.5978228663,-0.183682389335,2,1,18 +2025-03-11T12:42:05.652847,479392924,65312,231,1.58637541526,-10.292318489055,-0.716769285125,2,1,18 +2025-03-11T12:42:05.668472,479392924,65312,231,1.89265519556,-10.000661021355,-1.25443530599,2,1,18 +2025-03-11T12:42:05.684097,479392924,65312,231,2.20364697248,-9.704374328865,-1.796747830925,2,1,18 +2025-03-11T12:42:05.699722,479392924,65312,231,2.50050275954,-9.39886995162,-2.34369827591,2,1,18 +2025-03-11T12:42:05.715347,479392924,65312,231,2.78322255674,-9.088768961445,-2.895268100945,2,1,18 +2025-03-11T12:42:05.730972,479392924,65312,231,3.0800783438,-8.787885656025,-3.437578822865,2,1,18 +2025-03-11T12:42:05.746597,479392924,65312,231,3.3863581241,-8.4916071165,-3.99374811599,2,1,18 +2025-03-11T12:42:05.762222,479392924,65312,231,3.6690779213,-8.190748269975,-4.517553762635,2,1,18 +2025-03-11T12:42:05.777847,479392924,65312,231,3.9753577016,-7.899090802275,-5.059840966565,2,1,18 +2025-03-11T12:42:05.793472,479392924,65312,231,4.2816374819,-7.5935701191,-5.62528970582,2,1,18 +2025-03-11T12:42:05.809097,479392924,65312,231,4.58320526558,-7.28805758889,-6.17224693181,2,1,18 +2025-03-11T12:42:05.824722,479392924,65312,231,4.88948504588,-6.991779049365,-6.70531030961,2,1,18 +2025-03-11T12:42:05.840347,479392924,65312,231,5.18162883632,-6.686282825085,-7.26149633972,2,1,18 +2025-03-11T12:42:05.855972,479392924,65312,231,5.48319662,-6.371528151225,-7.803869462645,2,1,18 +2025-03-11T12:42:05.871597,479392924,65312,231,5.77062841382,-6.08452436721,-8.318383904165,2,1,18 +2025-03-11T12:42:05.887222,479392924,65312,231,6.06277220426,-5.774407071105,-8.85148255895,2,1,18 +2025-03-11T12:42:05.902847,479392924,65312,231,6.3549159947,-5.478152990475,-9.393767959865,2,1,18 +2025-03-11T12:42:05.918472,479392924,65312,231,6.65177178176,-5.19113290053,-9.936023061785,2,1,18 +2025-03-11T12:42:05.934097,479392924,65312,231,6.95333956544,-4.90410465762,-10.492148493905,2,1,18 +2025-03-11T12:42:05.949722,479392924,65312,231,7.2501953525,-4.6032213522,-11.03908039889,2,1,18 +2025-03-11T12:42:05.965347,479392924,65312,231,7.54705113956,-4.30233804678,-11.59063348694,2,1,18 +2025-03-11T12:42:05.980972,479392924,65312,231,7.83919493,-4.019947181625,-12.132863267855,2,1,18 +2025-03-11T12:42:05.996536,479392928,65308,232,8.14076271368,-3.705192507765,-12.68447875691,2,1,18 +2025-03-11T12:42:06.012161,479392928,65308,232,8.43761850074,-3.39044598687,-13.2176027327,2,1,18 +2025-03-11T12:42:06.027786,479392928,65308,232,8.73918628442,-3.09417560031,-13.759901695625,2,1,18 +2025-03-11T12:42:06.043411,479392928,65308,232,9.03604207148,-2.81177658219,-14.292895891415,2,1,18 +2025-03-11T12:42:06.059036,479392928,65308,232,9.33760985516,-2.520127267455,-14.830555131275,2,1,18 +2025-03-11T12:42:06.074661,479392928,65308,232,9.63917763884,-2.196130449945,-15.377586517265,2,1,18 +2025-03-11T12:42:06.090286,479392928,65308,232,9.9360334259,-1.895247144525,-15.91527605612,2,1,18 +2025-03-11T12:42:06.105911,479392928,65308,232,10.21404122648,-1.59901752279,-16.452919930955,2,1,18 +2025-03-11T12:42:06.121536,479392928,65308,232,10.50618501692,-1.298142370335,-16.990602688805,2,1,18 +2025-03-11T12:42:06.137161,479392928,65308,232,10.8077528006,-1.01573519925,-17.55133076399,2,1,18 +2025-03-11T12:42:06.152786,479392928,65308,232,11.10932058428,-0.733328028164999,-18.11668002224,2,1,18 +2025-03-11T12:42:06.168411,479392928,65308,232,11.41560036458,-0.441670560465,-18.635861310845,2,1,18 +2025-03-11T12:42:06.184036,479392928,65308,232,11.71245615164,-0.136166183219999,-19.16432702357,2,1,18 +2025-03-11T12:42:06.199661,479392928,65308,232,12.0093119387,0.164717122200001,-19.692774196295,2,1,18 +2025-03-11T12:42:06.215286,479392928,65308,232,12.30616772576,0.460979355795,-20.23968756128,2,1,18 +2025-03-11T12:42:06.230911,479392928,65308,232,12.58417552634,0.771072193005,-20.79125060531,2,1,18 +2025-03-11T12:42:06.246536,479392928,65308,232,12.87631931678,1.067326273635,-21.31967245703,2,1,18 +2025-03-11T12:42:06.262161,479392928,65308,232,13.16846310722,1.34971713879,-21.834175139555,2,1,18 +2025-03-11T12:42:06.277786,479392928,65308,232,13.47945488414,1.64600383128,-22.36724529836,2,1,18 +2025-03-11T12:42:06.293411,479392928,65308,232,13.76688667796,1.93762868712,-22.914126561335,2,1,18 +2025-03-11T12:42:06.309036,479392928,65308,232,14.05431847178,2.24773783026,-23.447218435115,2,1,18 +2025-03-11T12:42:06.324661,479392928,65308,232,14.34646226222,2.54399191089,-23.97101910377,2,1,18 +2025-03-11T12:42:06.340286,479392928,65308,232,14.64331804928,2.83563307266,-24.51329274569,2,1,18 +2025-03-11T12:42:06.355911,479392928,65308,232,14.92603784648,3.13187084736,-25.055564584595,2,1,18 +2025-03-11T12:42:06.371536,479392928,65308,232,15.22760563016,3.41889909027,-25.593205284455,2,1,18 +2025-03-11T12:42:06.387161,479392928,65308,232,15.5197494206,3.710532099075,-26.103123863915,2,1,18 +2025-03-11T12:42:06.402786,479392928,65308,232,15.79304522456,3.997511424195,-26.631481511615,2,1,18 +2025-03-11T12:42:06.418411,479392928,65308,232,16.085189015,4.27990228935,-27.159847743335,2,1,18 +2025-03-11T12:42:06.434036,479392928,65308,232,16.37262080882,4.57152714519,-27.69748664018,2,1,18 +2025-03-11T12:42:06.449661,479392928,65308,232,16.66005260264,4.858530929205,-28.216622264765,2,1,18 +2025-03-11T12:42:06.465286,479392928,65308,232,16.94748439646,5.150155785045,-28.73577642935,2,1,18 +2025-03-11T12:42:06.480911,479392928,65308,232,17.22549219704,5.432522191305,-29.264122318055,2,1,18 +2025-03-11T12:42:06.496536,479392928,65308,232,17.51292399086,5.714904903495,-29.787860585705,2,1,18 +2025-03-11T12:42:06.512161,479392928,65308,232,17.79564378806,5.99727946272,-30.288486157025,2,1,18 +2025-03-11T12:42:06.527786,479392928,65308,232,18.0877875785,6.298154615175,-30.81230536568,2,1,18 +2025-03-11T12:42:06.543411,479392928,65308,232,18.3705073757,6.575908102575,-31.326775946195,2,1,18 +2025-03-11T12:42:06.559036,479392928,65308,232,18.66265116614,6.85829896773,-31.845899811785,2,1,18 +2025-03-11T12:42:06.574661,479392928,65308,232,18.95008295996,7.14992382357,-32.34656924411,2,1,18 +2025-03-11T12:42:06.590286,479392928,65308,232,19.22337876392,7.44614529234,-32.870342788745,2,1,18 +2025-03-11T12:42:06.605911,479392928,65308,232,19.51081055774,7.723906932705,-33.384820150265,2,1,18 +2025-03-11T12:42:06.621536,479392928,65308,232,19.79824235156,7.997047501245,-33.917763704045,2,1,18 +2025-03-11T12:42:06.637161,479392928,65308,232,20.07625015214,8.27479283568,-34.43684868662,2,1,18 +2025-03-11T12:42:06.652786,479392928,65308,232,20.35425795272,8.543296026465,-34.928169490805,2,1,18 +2025-03-11T12:42:06.668411,479392928,65308,232,20.62755375668,8.82565427976,-35.438023866245,2,1,18 +2025-03-11T12:42:06.684036,479392928,65308,232,20.8914255674,9.107996227125,-35.95248586274,2,1,18 +2025-03-11T12:42:06.699661,479392928,65308,232,21.16472137136,9.39035448042,-36.448476688985,2,1,18 +2025-03-11T12:42:06.715286,479392928,65308,232,21.43801717532,9.663470590065,-36.95367280136,2,1,18 +2025-03-11T12:42:06.730911,479392928,65308,232,21.7160249759,9.927352709025,-37.454217431675,2,1,18 +2025-03-11T12:42:06.746536,479392928,65308,232,21.99403277648,10.18661375616,-37.93625878973,2,1,18 +2025-03-11T12:42:06.762161,479392928,65308,232,22.26261658382,10.473584928315,-38.43226137497,2,1,18 +2025-03-11T12:42:06.777786,479392928,65308,232,22.53591238778,10.76518532526,-38.94215283041,2,1,18 +2025-03-11T12:42:06.793411,479392928,65308,232,22.8233441816,11.042946965625,-39.470493741125,2,1,18 +2025-03-11T12:42:06.809036,479392928,65308,232,23.10135198218,11.297586940935,-39.957137742245,2,1,18 +2025-03-11T12:42:06.824661,479392928,65308,232,23.37935978276,11.579953347195,-40.4392718003,2,1,18 +2025-03-11T12:42:06.840286,479392928,65308,232,23.64323159348,11.848432079085,-40.925951078405,2,1,18 +2025-03-11T12:42:06.855911,479392928,65308,232,23.9071034042,12.11228973915,-41.41261181651,2,1,18 +2025-03-11T12:42:06.871536,479392928,65308,232,24.18039920816,12.376163705145,-41.89466493356,2,1,18 +2025-03-11T12:42:06.887161,479392928,65308,232,24.45369501212,12.64003767114,-42.404445149,2,1,18 +2025-03-11T12:42:06.902786,479392928,65308,232,24.71756682284,12.903895331205,-42.9049694363,2,1,18 +2025-03-11T12:42:06.918411,479392928,65308,232,24.97201464032,13.181599900815,-43.382429866265,2,1,18 +2025-03-11T12:42:06.934036,479392928,65308,232,25.24059844766,13.45932892932,-43.86453182231,2,1,18 +2025-03-11T12:42:06.949661,479392928,65308,232,25.50447025838,13.723186589385,-44.35581374348,2,1,18 +2025-03-11T12:42:06.965286,479392928,65308,232,25.7683420691,13.9962863931,-44.84713274465,2,1,18 +2025-03-11T12:42:06.980911,479392928,65308,232,26.0275018832,14.264756972025,-45.338426424815,2,1,18 +2025-03-11T12:42:06.996536,479392928,65308,232,26.27252570744,14.505476661105,-45.792619057445,2,1,18 +2025-03-11T12:42:07.012161,479392928,65308,232,26.53639751816,14.76933432117,-46.26079506329,2,1,18 +2025-03-11T12:42:07.027786,479392928,65308,232,26.79555733226,15.047047043745,-46.724398725065,2,1,18 +2025-03-11T12:42:07.043411,479392928,65308,232,27.05000514974,15.315509469705,-47.1925797089,2,1,18 +2025-03-11T12:42:07.059036,479392928,65308,232,27.29031697736,15.570084221295,-47.656063546655,2,1,18 +2025-03-11T12:42:07.074661,479392928,65308,232,27.54947679146,15.815449441095,-48.11953742843,2,1,18 +2025-03-11T12:42:07.090286,479392928,65308,232,27.80863660556,16.051572517245,-48.573731864075,2,1,18 +2025-03-11T12:42:07.105911,479392928,65308,232,28.07250841628,16.310809105485,-49.037268146855,2,1,18 +2025-03-11T12:42:07.121536,479392928,65308,232,28.34109222362,16.565432774865,-49.51003503677,2,1,18 +2025-03-11T12:42:07.137161,479392928,65308,232,28.59082804448,16.81540276056,-49.9781350796,2,1,18 +2025-03-11T12:42:07.152786,479392928,65308,232,28.8311398721,17.065356440325,-50.432358011225,2,1,18 +2025-03-11T12:42:07.168411,479392928,65308,232,29.08558768958,17.31071350716,-50.886582745865,2,1,18 +2025-03-11T12:42:07.184036,479392928,65308,232,29.33532351044,17.560683492855,-51.3408192395,2,1,18 +2025-03-11T12:42:07.199661,479392928,65308,232,29.58034733468,17.801403181935,-51.808875421325,2,1,18 +2025-03-11T12:42:07.215286,479392928,65308,232,29.8206591623,18.055977933525,-52.249253343755,2,1,18 +2025-03-11T12:42:07.230911,479392928,65308,232,30.06568298654,18.296697622605,-52.68034006106,2,1,18 +2025-03-11T12:42:07.246536,479392928,65308,232,30.2918588243,18.537384699825,-53.139126752735,2,1,18 +2025-03-11T12:42:07.262161,479392928,65308,232,30.53217065192,18.782717307765,-53.58408877823,2,1,18 +2025-03-11T12:42:07.277786,479392928,65308,232,30.7866184694,19.014211159125,-54.01977316061,2,1,18 +2025-03-11T12:42:07.293411,479392928,65308,232,31.0222183004,19.273398829575,-54.44629929284,2,1,18 +2025-03-11T12:42:07.309036,479392928,65308,232,31.26724212464,19.532602805955,-54.877460170145,2,1,18 +2025-03-11T12:42:07.324661,479392928,65308,232,31.52168994212,19.75947558549,-55.322368378655,2,1,18 +2025-03-11T12:42:07.340286,479392928,65308,232,31.75728977312,20.00017896864,-55.75344153395,2,1,18 +2025-03-11T12:42:07.355911,479392928,65308,232,31.98346561088,20.24086604586,-56.1891223103,2,1,18 +2025-03-11T12:42:07.371536,479392928,65308,232,32.20964144864,20.476932051255,-56.61554218052,2,1,18 +2025-03-11T12:42:07.387161,479392928,65308,232,32.44524127964,20.708393290755,-57.037335889685,2,1,18 +2025-03-11T12:42:07.402786,479392928,65308,232,32.69026510388,20.930628692535,-57.445242531665,2,1,18 +2025-03-11T12:42:07.418411,479392928,65308,232,32.92115293826,21.148218563595,-57.87159502289,2,1,18 +2025-03-11T12:42:07.434036,479392928,65308,232,33.13319278616,21.37039689462,-58.31180247929,2,1,18 +2025-03-11T12:42:07.449661,479392928,65308,232,33.34523263406,21.611059512945,-58.719735814235,2,1,18 +2025-03-11T12:42:07.465286,479392928,65308,232,33.58083246506,21.842520752445,-59.13228715727,2,1,18 +2025-03-11T12:42:07.480911,479392928,65308,232,33.81643229606,22.064739848295,-59.544801420305,2,1,18 +2025-03-11T12:42:07.496536,479392928,65308,232,34.0378961372,22.2961766289,-59.975817152585,2,1,18 +2025-03-11T12:42:07.512161,479392928,65308,232,34.26407197496,22.523000490645,-60.37909402748,2,1,18 +2025-03-11T12:42:07.527786,479392928,65308,232,34.49024781272,22.74982435239,-60.763886170115,2,1,18 +2025-03-11T12:42:07.543411,479392928,65308,232,34.71171165386,22.95815577387,-61.15321855481,2,1,18 +2025-03-11T12:42:07.559036,479392928,65308,232,34.92375150176,23.152607673945,-61.54710294056,2,1,18 +2025-03-11T12:42:07.574661,479392928,65308,232,35.13579134966,23.37478600497,-61.945719749375,2,1,18 +2025-03-11T12:42:07.590286,479392928,65308,232,35.35254319418,23.592351417135,-62.34894598226,2,1,18 +2025-03-11T12:42:07.605911,479392928,65308,232,35.58343102856,23.81456236002,-62.729105182835,2,1,18 +2025-03-11T12:42:07.621536,479392928,65308,232,35.79075887984,24.032111466255,-63.109211938385,2,1,18 +2025-03-11T12:42:07.637161,479392928,65308,232,35.98866273788,24.235781051085,-63.51235542725,2,1,18 +2025-03-11T12:42:07.652786,479392928,65308,232,36.19599058916,24.44408801367,-63.897046285865,2,1,18 +2025-03-11T12:42:07.668411,479392928,65308,232,36.4174544303,24.6616615788,-64.281794567495,2,1,18 +2025-03-11T12:42:07.684036,479392928,65308,232,36.64363026806,24.86538008142,-64.657251644,2,1,18 +2025-03-11T12:42:07.699661,479392928,65308,232,36.85095811934,25.06906597218,-65.03730277955,2,1,18 +2025-03-11T12:42:07.715286,479392928,65308,232,37.03943798414,25.29120353838,-65.412779768015,2,1,18 +2025-03-11T12:42:07.730911,479392928,65308,232,37.2420538388,25.494881276175,-65.788202939495,2,1,18 +2025-03-11T12:42:07.746536,479392928,65308,232,37.45880568332,25.70320454469,-66.159043810925,2,1,18 +2025-03-11T12:42:07.762161,479392928,65308,232,37.6661335346,25.911511507275,-66.52524993728,2,1,18 +2025-03-11T12:42:07.777786,479392928,65308,232,37.8546133994,26.09205942705,-66.86821178429,2,1,18 +2025-03-11T12:42:07.793411,479392928,65308,232,38.03366927096,26.272591040895,-67.21116006929,2,1,18 +2025-03-11T12:42:07.809036,479392928,65308,232,38.22214913576,26.48086539162,-67.57271788856,2,1,18 +2025-03-11T12:42:07.824661,479392928,65308,232,38.42476499042,26.675300985765,-67.92037688165,2,1,18 +2025-03-11T12:42:07.840286,479392928,65308,232,38.62266884846,26.87434949877,-68.28191118293,2,1,18 +2025-03-11T12:42:07.855911,479392928,65308,232,38.8205727065,27.0595347963,-68.629526315015,2,1,18 +2025-03-11T12:42:07.871536,479392928,65308,232,39.00434057468,27.25855885041,-68.97255554102,2,1,18 +2025-03-11T12:42:07.887161,479392928,65308,232,39.17868444962,27.452945526765,-69.32017384808,2,1,18 +2025-03-11T12:42:07.902786,479392928,65308,232,39.35774032118,27.64271928426,-69.68164394534,2,1,18 +2025-03-11T12:42:07.918411,479392928,65308,232,39.54150818936,27.82325905107,-70.01997782828,2,1,18 +2025-03-11T12:42:07.934036,479392928,65308,232,39.72998805416,28.013049114495,-70.36297675529,2,1,18 +2025-03-11T12:42:07.949661,479392928,65308,232,39.91846791896,28.198218106095,-70.701335959235,2,1,18 +2025-03-11T12:42:07.965286,479392928,65308,232,40.09752379052,28.374128648115,-71.035023338105,2,1,18 +2025-03-11T12:42:07.980911,479392928,65308,232,40.27657966208,28.55466026196,-71.341002158585,2,1,18 +2025-03-11T12:42:07.996536,479392928,65308,232,40.44149954378,28.71668312961,-71.660750025245,2,1,18 +2025-03-11T12:42:08.012161,479392928,65308,232,40.62997940858,28.90185212121,-71.98062449693,2,1,18 +2025-03-11T12:42:08.027786,479392928,65308,232,40.80903528014,29.08700480688,-72.291243040475,2,1,18 +2025-03-11T12:42:08.043411,479392928,65308,232,40.97866715846,29.249035827495,-72.606376505075,2,1,18 +2025-03-11T12:42:08.059036,479392928,65308,232,41.14829903678,29.424930063585,-72.92618677274,2,1,18 +2025-03-11T12:42:08.074661,479392928,65308,232,41.3179309151,29.582340012375,-73.24130169734,2,1,18 +2025-03-11T12:42:08.090286,479392928,65308,232,41.49698678666,29.758250554395,-73.53801961169,2,1,18 +2025-03-11T12:42:08.105911,479392928,65308,232,41.6713306616,29.920289727975,-73.862402223425,2,1,18 +2025-03-11T12:42:08.121536,479392928,65308,232,41.84567453654,30.100813188855,-74.154510713705,2,1,18 +2025-03-11T12:42:08.137161,479392928,65308,232,42.01059441824,30.26745712833,-74.43268647278,2,1,18 +2025-03-11T12:42:08.152786,479392928,65308,232,42.15666631346,30.42020524047,-74.729264220095,2,1,18 +2025-03-11T12:42:08.168411,479392928,65308,232,42.32158619516,30.568364892645,-75.021229368365,2,1,18 +2025-03-11T12:42:08.184036,479392928,65308,232,42.48179408024,30.72113746368,-75.29472154337,2,1,18 +2025-03-11T12:42:08.199661,479392928,65308,232,42.6372899687,30.87390188175,-75.572828120435,2,1,18 +2025-03-11T12:42:08.215286,479392928,65308,232,42.78807386054,31.045142434155,-75.841759710365,2,1,18 +2025-03-11T12:42:08.230911,479392928,65308,232,42.92472176252,31.216358527665,-76.133776872605,2,1,18 +2025-03-11T12:42:08.246536,479392928,65308,232,43.07550565436,31.364493720945,-76.42572167786,2,1,18 +2025-03-11T12:42:08.262161,479392928,65308,232,43.2262895462,31.51724998605,-76.72230620618,2,1,18 +2025-03-11T12:42:08.277786,479392928,65308,232,43.3912094279,31.65154642275,-76.98648863606,2,1,18 +2025-03-11T12:42:08.293411,479392928,65308,232,43.5325693265,31.795044238275,-77.22756832559,2,1,18 +2025-03-11T12:42:08.309036,479392928,65308,232,43.67864122172,31.947792350415,-77.505661340645,2,1,18 +2025-03-11T12:42:08.324661,479392928,65308,232,43.81057712708,32.086652788185,-77.75133011123,2,1,18 +2025-03-11T12:42:08.340286,479392928,65308,232,43.94251303244,32.207028938655,-78.00154590488,2,1,18 +2025-03-11T12:42:08.355911,479392928,65308,232,44.0744489378,32.345889376425,-78.274941773855,2,1,18 +2025-03-11T12:42:08.371536,479392928,65308,232,44.20638484316,32.512476245145,-78.5392065167,2,1,18 +2025-03-11T12:42:08.387161,479392928,65308,232,44.35245673838,32.64211899816,-78.77561618417,2,1,18 +2025-03-11T12:42:08.402786,479392928,65308,232,44.48439264374,32.767116220455,-79.021229334755,2,1,18 +2025-03-11T12:42:08.418411,479392928,65308,232,44.62575254234,32.89212974868,-79.25761368122,2,1,18 +2025-03-11T12:42:08.434036,479392928,65308,232,44.76240044432,33.012514052115,-79.49397270668,2,1,18 +2025-03-11T12:42:08.449661,479392928,65308,232,44.88962435306,33.137503121445,-79.73957907626,2,1,18 +2025-03-11T12:42:08.465286,479392928,65308,232,45.01213626518,33.257862965985,-79.98053894177,2,1,18 +2025-03-11T12:42:08.480911,479392928,65308,232,45.1346481773,33.392086026,-80.216933244215,2,1,18 +2025-03-11T12:42:08.496536,479392928,65308,232,45.26658408266,33.51246217647,-80.439421939475,2,1,18 +2025-03-11T12:42:08.512161,479392928,65308,232,45.38438399816,33.642056011695,-80.638821456395,2,1,18 +2025-03-11T12:42:08.527786,479392928,65308,232,45.51631990352,33.762432162165,-80.84744660246,2,1,18 +2025-03-11T12:42:08.543411,479392928,65308,232,45.63883181564,33.87817093488,-81.056039646515,2,1,18 +2025-03-11T12:42:08.559036,479392928,65308,232,45.76134372776,33.99853077942,-81.28313596283,2,1,18 +2025-03-11T12:42:08.574661,479392928,65308,232,45.86971965002,34.11424509324,-81.51019339613,2,1,18 +2025-03-11T12:42:08.590286,479392928,65308,232,45.9828075689,34.2438307755,-81.709586132045,2,1,18 +2025-03-11T12:42:08.605911,479392928,65308,232,46.09118349116,34.35030294567,-81.899637020825,2,1,18 +2025-03-11T12:42:08.621536,479392928,65308,232,46.19955941342,34.452154044015,-82.1035329188,2,1,18 +2025-03-11T12:42:08.637161,479392928,65308,232,46.29851134244,34.567852051905,-82.288986142505,2,1,18 +2025-03-11T12:42:08.652786,479392928,65308,232,46.4068872647,34.6604610066,-82.45587549596,2,1,18 +2025-03-11T12:42:08.668411,479392928,65308,232,46.49641520048,34.74841627761,-82.64582510072,2,1,18 +2025-03-11T12:42:08.684036,479392928,65308,232,46.5953671295,34.85487214185,-82.831241244425,2,1,18 +2025-03-11T12:42:08.699661,479392928,65308,232,46.69903105514,34.95671508723,-83.0212668122,2,1,18 +2025-03-11T12:42:08.715286,479392928,65308,232,46.79327098754,35.053920654855,-83.202017911835,2,1,18 +2025-03-11T12:42:08.730911,479392928,65308,232,46.89693491318,35.155763600235,-83.387422296545,2,1,18 +2025-03-11T12:42:08.746536,479392928,65308,232,46.98646284896,35.23909779942,-83.56348981211,2,1,18 +2025-03-11T12:42:08.762161,479392928,65308,232,47.08541477798,35.322448304535,-83.72570734049,2,1,18 +2025-03-11T12:42:08.777786,479392928,65308,232,47.17965471038,35.41965387216,-83.8833525248,2,1,18 +2025-03-11T12:42:08.793411,479392928,65308,232,47.25975865292,35.50759283724,-84.022455553835,2,1,18 +2025-03-11T12:42:08.809036,479392928,65308,232,47.3492865887,35.581684892775,-84.18924362327,2,1,18 +2025-03-11T12:42:08.824661,479392928,65308,232,47.43410252786,35.66963201082,-84.351459348635,2,1,18 +2025-03-11T12:42:08.840286,479392928,65308,232,47.53305445688,35.762224659585,-84.513713957015,2,1,18 +2025-03-11T12:42:08.855911,479392928,65308,232,47.60373440618,35.85476839056,-84.65282196404,2,1,18 +2025-03-11T12:42:08.871536,479392928,65308,232,47.67441435548,35.928827834235,-84.782613444935,2,1,18 +2025-03-11T12:42:08.887161,479392928,65308,232,47.75923029464,36.012153880455,-84.921704714975,2,1,18 +2025-03-11T12:42:08.902786,479392928,65308,232,47.82991024394,36.081592252305,-85.065341205065,2,1,18 +2025-03-11T12:42:08.918411,479392928,65308,232,47.8911662,36.151014318225,-85.199721767015,2,1,18 +2025-03-11T12:42:08.934036,479392928,65308,232,47.97127014254,36.20660578053,-85.324831466855,2,1,18 +2025-03-11T12:42:08.949661,479392928,65308,232,48.05137408508,36.280681530135,-85.45463650976,2,1,18 +2025-03-11T12:42:08.965286,479392928,65308,232,48.11263004114,36.37320895518,-85.57986740558,2,1,18 +2025-03-11T12:42:08.980911,479392928,65308,232,48.18330999044,36.438026255205,-85.69575825728,2,1,18 +2025-03-11T12:42:08.996536,479392928,65308,232,48.23985394988,36.49819802451,-85.78850431064,2,1,18 +2025-03-11T12:42:09.012161,479392928,65308,232,48.2916859127,36.562982712675,-85.899746855255,2,1,18 +2025-03-11T12:42:09.027786,479392928,65308,232,48.35765386538,36.618549716085,-86.00635147982,2,1,18 +2025-03-11T12:42:09.043411,479392928,65308,232,48.41419782482,36.66023719809,-86.10826573931,2,1,18 +2025-03-11T12:42:09.059036,479392928,65308,232,48.47074178426,36.70654575192,-86.2101985388,2,1,18 +2025-03-11T12:42:09.074661,479392928,65308,232,48.5272857437,36.775959664875,-86.32146640442,2,1,18 +2025-03-11T12:42:09.090286,479392928,65308,232,48.57911770652,36.83150220939,-86.42805068597,2,1,18 +2025-03-11T12:42:09.105911,479392928,65308,232,48.63094966934,36.868560466605,-86.539181990585,2,1,18 +2025-03-11T12:42:09.121536,479392928,65308,232,48.67335763892,36.900981346065,-86.63179646093,2,1,18 +2025-03-11T12:42:09.137161,479392928,65308,232,48.7157656085,36.95650758465,-86.70139771595,2,1,18 +2025-03-11T12:42:09.152786,479392928,65308,232,48.75817357808,37.00741275141,-86.76173806484,2,1,18 +2025-03-11T12:42:09.168411,479392928,65308,232,48.80058154766,37.05831791817,-86.854426695185,2,1,18 +2025-03-11T12:42:09.184036,479392928,65308,232,48.83827752062,37.09535171649,-86.937810558395,2,1,18 +2025-03-11T12:42:09.199661,479392928,65308,232,48.88539748682,37.14164396439,-86.98889678216,2,1,18 +2025-03-11T12:42:09.215286,479392928,65308,232,48.93722944964,37.16483900613,-87.044518269995,2,1,18 +2025-03-11T12:42:09.230911,479392928,65308,232,48.98434941584,37.178783751255,-87.109338262955,2,1,18 +2025-03-11T12:42:09.246536,479392928,65308,232,49.01733339218,37.21580939661,-87.15574588064,2,1,18 +2025-03-11T12:42:09.262161,479392928,65308,232,49.03146938204,37.24818135828,-87.2159713835,2,1,18 +2025-03-11T12:42:09.277786,479392928,65308,232,49.0456053719,37.26206903265,-87.280743909425,2,1,18 +2025-03-11T12:42:09.293411,479392928,65308,232,49.07858934824,37.299094678005,-87.31790916098,2,1,18 +2025-03-11T12:42:09.309036,479392928,65308,232,49.11157332458,37.32687817971,-87.35041614947,2,1,18 +2025-03-11T12:42:09.324661,479392928,65308,232,49.1398453043,37.35465352845,-87.37829517389,2,1,18 +2025-03-11T12:42:09.340286,479392928,65308,232,49.14455730092,37.37776704054,-87.424606485545,2,1,18 +2025-03-11T12:42:09.355911,479392928,65308,232,49.17754127726,37.40092947042,-87.4617161171,2,1,18 +2025-03-11T12:42:09.371536,479392928,65308,232,49.19638926374,37.424067441405,-87.494184222575,2,1,18 +2025-03-11T12:42:09.387161,479392928,65308,232,49.20110126036,37.43331773802,-87.52195518197,2,1,18 +2025-03-11T12:42:09.402786,479392928,65308,232,49.19638926374,37.44717280053,-87.53586757016,2,1,18 +2025-03-11T12:42:09.418411,479392928,65308,232,49.20581325698,37.46567339376,-87.540576475235,2,1,18 +2025-03-11T12:42:09.434036,479392928,65308,232,49.22937324008,37.47957737406,-87.57763546478,2,1,18 +2025-03-11T12:42:09.449661,479392928,65308,232,49.25293322318,37.479618138885,-87.60077528513,2,1,18 +2025-03-11T12:42:09.465286,479392928,65308,232,49.25293322318,37.488860282535,-87.60081236513,2,1,18 +2025-03-11T12:42:09.480911,479392928,65308,232,49.24350922994,37.488843976605,-87.60079880312,2,1,18 +2025-03-11T12:42:09.496536,479392928,65308,232,49.2576452198,37.4888684355,-87.6054403292,2,1,18 +2025-03-11T12:42:09.512161,479392928,65308,232,49.26235721642,37.48425551664,-87.614670936335,2,1,18 +2025-03-11T12:42:09.527786,479392928,65308,232,49.2576452198,37.4703841482,-87.609987352265,2,1,18 +2025-03-11T12:42:09.543411,479392928,65308,232,49.24350922994,37.46573861748,-87.59146373699,2,1,18 +2025-03-11T12:42:09.559036,479392928,65308,232,49.23879723332,37.456488320865,-87.582177509855,2,1,18 +2025-03-11T12:42:09.574661,479392928,65308,232,49.24350922994,37.45649647383,-87.55445719247,2,1,18 +2025-03-11T12:42:09.590286,479392928,65308,232,49.22937324008,37.45185094311,-87.526691211065,2,1,18 +2025-03-11T12:42:09.605911,479392928,65308,232,49.20581325698,37.43794696281,-87.531222869105,2,1,18 +2025-03-11T12:42:09.621536,479392928,65308,232,49.20110126036,37.40559130707,-87.517222758905,2,1,18 +2025-03-11T12:42:09.637161,479392928,65308,232,49.18225327388,37.391695479735,-87.489412916495,2,1,18 +2025-03-11T12:42:09.652786,479392928,65308,232,49.14926929754,37.39163840898,-87.44315361881,2,1,18 +2025-03-11T12:42:09.668411,479392928,65308,232,49.12570931444,37.382355500505,-87.406113169265,2,1,18 +2025-03-11T12:42:09.684036,479392928,65308,232,49.10214933134,37.35458830473,-87.364377376655,2,1,18 +2025-03-11T12:42:09.699661,479392928,65308,232,49.069165355,37.317562659375,-87.30872739284,2,1,18 +2025-03-11T12:42:09.715286,479392928,65308,232,49.05031736852,37.271319329265,-87.257681855105,2,1,18 +2025-03-11T12:42:09.730911,479392928,65308,232,49.0456053719,37.24358474535,-87.22059436958,2,1,18 +2025-03-11T12:42:09.746536,479392928,65308,232,49.01733339218,37.220430468435,-87.1742491529,2,1,18 +2025-03-11T12:42:09.762161,479392928,65308,232,48.97963741922,37.18801774194,-87.104747378885,2,1,18 +2025-03-11T12:42:09.777786,479392928,65308,232,48.93251745302,37.13248335039,-87.030518159795,2,1,18 +2025-03-11T12:42:09.793411,479392928,65308,232,48.88539748682,37.081570030665,-86.947065114575,2,1,18 +2025-03-11T12:42:09.809036,479392928,65308,232,48.85241351048,37.04454438531,-86.859066849305,2,1,18 +2025-03-11T12:42:09.824661,479392928,65308,232,48.82414153076,37.00752689292,-86.794181280365,2,1,18 +2025-03-11T12:42:09.840286,479392928,65308,232,48.78173356118,36.96586386981,-86.743120377605,2,1,18 +2025-03-11T12:42:09.855911,479392928,65308,232,48.73461359498,36.924192693735,-86.659704412385,2,1,18 +2025-03-11T12:42:09.871536,479392928,65308,232,48.68278163216,36.882513364695,-86.5577969339,2,1,18 +2025-03-11T12:42:09.887161,479392928,65308,232,48.63094966934,36.840834035655,-86.465131821545,2,1,18 +2025-03-11T12:42:09.902786,479392928,65308,232,48.58854169976,36.789928868895,-86.386306740395,2,1,18 +2025-03-11T12:42:09.918411,479392928,65308,232,48.53199774032,36.743620315065,-86.28899512397,2,1,18 +2025-03-11T12:42:09.934036,479392928,65308,232,48.4801657775,36.6788356269,-86.18237376242,2,1,18 +2025-03-11T12:42:09.949661,479392928,65308,232,48.41890982144,36.623276776455,-86.080397101925,2,1,18 +2025-03-11T12:42:09.965286,479392928,65308,232,48.36707785862,36.57697637559,-85.992334632635,2,1,18 +2025-03-11T12:42:09.980911,479392928,65308,232,48.3152458958,36.512191687425,-85.89033445415,2,1,18 +2025-03-11T12:42:09.996459,479392932,65303,233,48.25870193636,36.438156702645,-85.76056331627,2,1,18 +2025-03-11T12:42:10.012084,479392932,65303,233,48.20215797692,36.36874278969,-85.626189535325,2,1,18 +2025-03-11T12:42:10.027709,479392932,65303,233,48.14090202086,36.30856286742,-85.501088419505,2,1,18 +2025-03-11T12:42:10.043334,479392932,65303,233,48.07022207156,36.23912449557,-85.394421393935,2,1,18 +2025-03-11T12:42:10.058959,479392932,65303,233,47.99011812902,36.183533033265,-85.269311694095,2,1,18 +2025-03-11T12:42:10.074584,479392932,65303,233,47.92415017634,36.118723886205,-85.14418525727,2,1,18 +2025-03-11T12:42:10.090209,479392932,65303,233,47.84875823042,36.035414145915,-85.01434991537,2,1,18 +2025-03-11T12:42:10.105834,479392932,65303,233,47.77807828112,35.95211255859,-84.856794256085,2,1,18 +2025-03-11T12:42:10.121459,479392932,65303,233,47.68855034534,35.887262646705,-84.703906815845,2,1,18 +2025-03-11T12:42:10.137084,479392932,65303,233,47.61315839942,35.80857397824,-84.555605281685,2,1,18 +2025-03-11T12:42:10.152709,479392932,65303,233,47.54719044674,35.71603840023,-84.43036760486,2,1,18 +2025-03-11T12:42:10.168334,479392932,65303,233,47.47179850082,35.63272865994,-84.27280516457,2,1,18 +2025-03-11T12:42:10.183959,479392932,65303,233,47.37755856842,35.563249523265,-84.119892403325,2,1,18 +2025-03-11T12:42:10.199584,479392932,65303,233,47.2786066394,35.4706568745,-83.96225897801,2,1,18 +2025-03-11T12:42:10.215209,479392932,65303,233,47.18907870362,35.387322675315,-83.804676194705,2,1,18 +2025-03-11T12:42:10.230834,479392932,65303,233,47.09955076784,35.299367404305,-83.6470748714,2,1,18 +2025-03-11T12:42:10.246459,479392932,65303,233,47.00059883882,35.18829046824,-83.46626137076,2,1,18 +2025-03-11T12:42:10.262084,479392932,65303,233,46.90635890642,35.09570597244,-83.29014999419,2,1,18 +2025-03-11T12:42:10.277709,479392932,65303,233,46.82154296726,35.007758854395,-83.118691902695,2,1,18 +2025-03-11T12:42:10.293334,479392932,65303,233,46.72730303486,34.915174358595,-82.961065258385,2,1,18 +2025-03-11T12:42:10.308959,479392932,65303,233,46.61421511598,34.80869403546,-82.766386405535,2,1,18 +2025-03-11T12:42:10.324584,479392932,65303,233,46.51997518358,34.70686739601,-82.55788966751,2,1,18 +2025-03-11T12:42:10.340209,479392932,65303,233,46.42573525118,34.600419684735,-82.36323793868,2,1,18 +2025-03-11T12:42:10.355834,479392932,65303,233,46.30322333906,34.480059840195,-82.15924753769,2,1,18 +2025-03-11T12:42:10.371459,479392932,65303,233,46.20427141004,34.36898290413,-81.96919167092,2,1,18 +2025-03-11T12:42:10.387084,479392932,65303,233,46.10531948102,34.26252703989,-81.783775527215,2,1,18 +2025-03-11T12:42:10.402709,479392932,65303,233,46.00165555538,34.156063022685,-81.589110236375,2,1,18 +2025-03-11T12:42:10.418334,479392932,65303,233,45.87914364326,34.054187465445,-81.385193995385,2,1,18 +2025-03-11T12:42:10.433959,479392932,65303,233,45.76605572438,33.93846499866,-81.18585687947,2,1,18 +2025-03-11T12:42:10.449584,479392932,65303,233,45.66239179874,33.82737990963,-80.99117304863,2,1,18 +2025-03-11T12:42:10.465209,479392932,65303,233,45.54459188324,33.697786074405,-80.76404643332,2,1,18 +2025-03-11T12:42:10.480834,479392932,65303,233,45.42207997112,33.568184086215,-80.53229185394,2,1,18 +2025-03-11T12:42:10.496459,479392932,65303,233,45.29014406576,33.447807935745,-80.30980315868,2,1,18 +2025-03-11T12:42:10.512084,479392932,65303,233,45.16292015702,33.313576722765,-80.068780892165,2,1,18 +2025-03-11T12:42:10.527709,479392932,65303,233,45.02627225504,33.20243456298,-79.8463224959,2,1,18 +2025-03-11T12:42:10.543334,479392932,65303,233,44.90376034292,33.077453646615,-79.619207639585,2,1,18 +2025-03-11T12:42:10.558959,479392932,65303,233,44.78596042742,32.92937552409,-79.36890094895,2,1,18 +2025-03-11T12:42:10.574584,479392932,65303,233,44.6634485153,32.795152464075,-79.132506646505,2,1,18 +2025-03-11T12:42:10.590209,479392932,65303,233,44.53151260994,32.67939738543,-78.88693057592,2,1,18 +2025-03-11T12:42:10.605834,479392932,65303,233,44.3807287181,32.5405043358,-78.641234681315,2,1,18 +2025-03-11T12:42:10.621459,479392932,65303,233,44.24408081612,32.401635745065,-78.395559129725,2,1,18 +2025-03-11T12:42:10.637084,479392932,65303,233,44.11214491076,32.262775307295,-78.14064799301,2,1,18 +2025-03-11T12:42:10.652709,479392932,65303,233,43.9802090054,32.114672725875,-77.885699776295,2,1,18 +2025-03-11T12:42:10.668334,479392932,65303,233,43.83413711018,31.961924613735,-77.621470310435,2,1,18 +2025-03-11T12:42:10.683959,479392932,65303,233,43.68335321834,31.813789420455,-77.361873786635,2,1,18 +2025-03-11T12:42:10.699584,479392932,65303,233,43.53728132312,31.67490452379,-77.097699940775,2,1,18 +2025-03-11T12:42:10.715209,479392932,65303,233,43.3912094279,31.54064069895,-76.83816581798,2,1,18 +2025-03-11T12:42:10.730834,479392932,65303,233,43.24042553606,31.397126577495,-76.56010310192,2,1,18 +2025-03-11T12:42:10.746459,479392932,65303,233,43.0849296476,31.2397410876,-76.29584153405,2,1,18 +2025-03-11T12:42:10.762084,479392932,65303,233,42.943569749,31.087001128425,-76.02699766613,2,1,18 +2025-03-11T12:42:10.777709,479392932,65303,233,42.78336186392,30.938849629215,-75.744281664995,2,1,18 +2025-03-11T12:42:10.793334,479392932,65303,233,42.62786597546,30.795327354795,-75.4569698018,2,1,18 +2025-03-11T12:42:10.808959,479392932,65303,233,42.472370087,30.642562936725,-75.160378492475,2,1,18 +2025-03-11T12:42:10.824584,479392932,65303,233,42.31687419854,30.46669315953,-74.86369448315,2,1,18 +2025-03-11T12:42:10.840209,479392932,65303,233,42.17551429994,30.304711056705,-74.580949986035,2,1,18 +2025-03-11T12:42:10.855834,479392932,65303,233,42.01530641486,30.138075270195,-74.2981598249,2,1,18 +2025-03-11T12:42:10.871459,479392932,65303,233,41.85038653316,29.98067347437,-73.992294047435,2,1,18 +2025-03-11T12:42:10.887084,479392932,65303,233,41.68075465484,29.81402138193,-73.686384408965,2,1,18 +2025-03-11T12:42:10.902709,479392932,65303,233,41.52054676976,29.642764523595,-73.380469792505,2,1,18 +2025-03-11T12:42:10.918334,479392932,65303,233,41.35562688806,29.46687844047,-73.07452985504,2,1,18 +2025-03-11T12:42:10.933959,479392932,65303,233,41.17185901988,29.30482296096,-72.768618413555,2,1,18 +2025-03-11T12:42:10.949584,479392932,65303,233,41.00222714156,29.133549796695,-72.45806905202,2,1,18 +2025-03-11T12:42:10.965209,479392932,65303,233,40.83259526324,28.96227663243,-72.156762056615,2,1,18 +2025-03-11T12:42:10.980834,479392932,65303,233,40.67238737816,28.77715655862,-71.82768590483,2,1,18 +2025-03-11T12:42:10.996459,479392932,65303,233,40.49804350322,28.58739095409,-71.493949686965,2,1,18 +2025-03-11T12:42:11.012084,479392932,65303,233,40.30956363842,28.416085177965,-71.169509652215,2,1,18 +2025-03-11T12:42:11.027709,479392932,65303,233,40.116371777,28.226286961575,-70.849609859525,2,1,18 +2025-03-11T12:42:11.043334,479392932,65303,233,39.9278919122,28.059602257275,-70.515945998645,2,1,18 +2025-03-11T12:42:11.058959,479392932,65303,233,39.74412404402,27.869820346815,-70.186817401835,2,1,18 +2025-03-11T12:42:11.074584,479392932,65303,233,39.56506817246,27.684667661145,-69.8484717599,2,1,18 +2025-03-11T12:42:11.090209,479392932,65303,233,39.38130030428,27.49950682251,-69.505498153895,2,1,18 +2025-03-11T12:42:11.105834,479392932,65303,233,39.18810844286,27.30970860612,-69.14400771362,2,1,18 +2025-03-11T12:42:11.121459,479392932,65303,233,38.99491658144,27.11991038973,-68.810244371735,2,1,18 +2025-03-11T12:42:11.137084,479392932,65303,233,38.81586070988,26.91627341676,-68.4718245698,2,1,18 +2025-03-11T12:42:11.152709,479392932,65303,233,38.64151683494,26.721886740405,-68.147312178065,2,1,18 +2025-03-11T12:42:11.168334,479392932,65303,233,38.4436129769,26.51359608375,-67.794983162915,2,1,18 +2025-03-11T12:42:11.183959,479392932,65303,233,38.24570911886,26.33765292987,-67.442783927765,2,1,18 +2025-03-11T12:42:11.199584,479392932,65303,233,38.05251725744,26.13861256983,-67.067392858295,2,1,18 +2025-03-11T12:42:11.215209,479392932,65303,233,37.86403739264,25.95344357823,-66.71054892209,2,1,18 +2025-03-11T12:42:11.230834,479392932,65303,233,37.6661335346,25.763637208875,-66.344430517745,2,1,18 +2025-03-11T12:42:11.246459,479392932,65303,233,37.47294167318,25.55997577701,-65.969020908275,2,1,18 +2025-03-11T12:42:11.262084,479392932,65303,233,37.28446180838,25.34708035446,-65.588959816745,2,1,18 +2025-03-11T12:42:11.277709,479392932,65303,233,37.06770996386,25.13413601412,-65.208858039185,2,1,18 +2025-03-11T12:42:11.293334,479392932,65303,233,36.85567011596,24.921199826745,-64.84724777489,2,1,18 +2025-03-11T12:42:11.308959,479392932,65303,233,36.6530542613,24.71752208895,-64.46258223728,2,1,18 +2025-03-11T12:42:11.324584,479392932,65303,233,36.43630241678,24.52306203591,-64.077933436655,2,1,18 +2025-03-11T12:42:11.340209,479392932,65303,233,36.22426256888,24.310125848535,-63.6978384401,2,1,18 +2025-03-11T12:42:11.355834,479392932,65303,233,36.02635871084,24.10183519188,-63.322403509625,2,1,18 +2025-03-11T12:42:11.371459,479392932,65303,233,35.81431886294,23.879656860855,-62.937650250005,2,1,18 +2025-03-11T12:42:11.387084,479392932,65303,233,35.58814302518,23.657454070935,-62.52514954898,2,1,18 +2025-03-11T12:42:11.402709,479392932,65303,233,35.36196718742,23.43987235284,-62.12653093715,2,1,18 +2025-03-11T12:42:11.418334,479392932,65303,233,35.14992733952,23.217694021815,-61.737156494465,2,1,18 +2025-03-11T12:42:11.433959,479392932,65303,233,34.933175495,23.00012860965,-61.36165735997,2,1,18 +2025-03-11T12:42:11.449584,479392932,65303,233,34.697575664,22.7779095138,-60.958385463065,2,1,18 +2025-03-11T12:42:11.465209,479392932,65303,233,34.4855358161,22.55111011095,-60.536644198925,2,1,18 +2025-03-11T12:42:11.480834,479392932,65303,233,34.26407197496,22.338157617645,-60.105702626645,2,1,18 +2025-03-11T12:42:11.496459,479392932,65303,233,34.05203212706,22.120600358445,-59.71634672396,2,1,18 +2025-03-11T12:42:11.512084,479392932,65303,233,33.83528028254,21.907656018105,-59.313139031075,2,1,18 +2025-03-11T12:42:11.527709,479392932,65303,233,33.61852843802,21.666985246815,-58.90982009819,2,1,18 +2025-03-11T12:42:11.543334,479392932,65303,233,33.39706459688,21.430927394385,-58.511134107365,2,1,18 +2025-03-11T12:42:11.558959,479392932,65303,233,33.15675276926,21.19945800192,-58.075470068,2,1,18 +2025-03-11T12:42:11.574584,479392932,65303,233,32.92115293826,20.96799676242,-57.63981280964,2,1,18 +2025-03-11T12:42:11.590209,479392932,65303,233,32.69968909712,20.727317838165,-57.22724472962,2,1,18 +2025-03-11T12:42:11.605834,479392932,65303,233,32.45466527288,20.495840292735,-56.814679824575,2,1,18 +2025-03-11T12:42:11.621459,479392932,65303,233,32.21435344526,20.26437090027,-56.392879334405,2,1,18 +2025-03-11T12:42:11.637084,479392932,65303,233,31.9881776075,20.028304894875,-55.957217098055,2,1,18 +2025-03-11T12:42:11.652709,479392932,65303,233,31.74786577988,19.80607764606,-55.53083250482,2,1,18 +2025-03-11T12:42:11.668334,479392932,65303,233,31.52168994212,19.55614842519,-55.090493465405,2,1,18 +2025-03-11T12:42:11.683959,479392932,65303,233,31.29551410436,19.30621920432,-54.65015442599,2,1,18 +2025-03-11T12:42:11.699584,479392932,65303,233,31.05991427336,19.079379036645,-54.21451570763,2,1,18 +2025-03-11T12:42:11.715209,479392932,65303,233,30.8101784525,18.8386511946,-53.769558660125,2,1,18 +2025-03-11T12:42:11.730834,479392932,65303,233,30.56044263164,18.597923352555,-53.329222795685,2,1,18 +2025-03-11T12:42:11.746459,479392932,65303,233,30.32484280064,18.35259889758,-52.884267551195,2,1,18 +2025-03-11T12:42:11.762084,479392932,65303,233,30.07510697978,18.10724998371,-52.44853432982,2,1,18 +2025-03-11T12:42:11.777709,479392932,65303,233,29.83950714878,17.85730445691,-52.01280291146,2,1,18 +2025-03-11T12:42:11.793334,479392932,65303,233,29.5850593313,17.602705246425,-51.57702582908,2,1,18 +2025-03-11T12:42:11.808959,479392932,65303,233,29.34474750368,17.357372638485,-51.11820025439,2,1,18 +2025-03-11T12:42:11.824584,479392932,65303,233,29.09501168282,17.10740265279,-50.65934257769,2,1,18 +2025-03-11T12:42:11.840209,479392932,65303,233,28.83585186872,16.86203743299,-50.19124751285,2,1,18 +2025-03-11T12:42:11.855834,479392932,65303,233,28.58140405124,16.616680366155,-49.74626514434,2,1,18 +2025-03-11T12:42:11.871459,479392932,65303,233,28.33166823038,16.362089308635,-49.282767744575,2,1,18 +2025-03-11T12:42:11.887084,479392932,65303,233,28.08664440614,16.112127475905,-48.83315921501,2,1,18 +2025-03-11T12:42:11.902709,479392932,65303,233,27.82277259542,15.85751195949,-48.36964147223,2,1,18 +2025-03-11T12:42:11.918334,479392932,65303,233,27.56832477794,15.60753382083,-47.8876710992,2,1,18 +2025-03-11T12:42:11.933959,479392932,65303,233,27.32801295032,15.339095853765,-47.396404543055,2,1,18 +2025-03-11T12:42:11.949584,479392932,65303,233,27.0641411396,15.089101409175,-46.92828415721,2,1,18 +2025-03-11T12:42:11.965209,479392932,65303,233,26.8049813255,14.8298729739,-46.473997021565,2,1,18 +2025-03-11T12:42:11.980834,479392932,65303,233,26.5458215114,14.561402394975,-45.99194570753,2,1,18 +2025-03-11T12:42:11.996459,479392932,65303,233,26.27723770406,14.297536581945,-45.51452055455,2,1,18 +2025-03-11T12:42:12.012084,479392932,65303,233,26.02278988658,14.06142165876,-45.06033289991,2,1,18 +2025-03-11T12:42:12.027709,479392932,65303,233,25.77776606234,13.78373339508,-44.60599194728,2,1,18 +2025-03-11T12:42:12.043334,479392932,65303,233,25.52803024148,13.515279122085,-44.133196561385,2,1,18 +2025-03-11T12:42:12.058959,479392932,65303,233,25.25944643414,13.24679223723,-43.646510502275,2,1,18 +2025-03-11T12:42:12.074584,479392932,65303,233,24.98143863356,12.98291011827,-43.141344688895,2,1,18 +2025-03-11T12:42:12.090209,479392932,65303,233,24.71756682284,12.719052458205,-42.650062767725,2,1,18 +2025-03-11T12:42:12.105834,479392932,65303,233,24.45369501212,12.450573726315,-42.16338348962,2,1,18 +2025-03-11T12:42:12.121459,479392932,65303,233,24.19924719464,12.172869156705,-41.676680693525,2,1,18 +2025-03-11T12:42:12.137084,479392932,65303,233,23.92123939406,11.89512382227,-41.18532280934,2,1,18 +2025-03-11T12:42:12.152709,479392932,65303,233,23.63851959686,11.64509676582,-40.698690567215,2,1,18 +2025-03-11T12:42:12.168334,479392932,65303,233,23.37464778614,11.390481249405,-40.207445726045,2,1,18 +2025-03-11T12:42:12.183959,479392932,65303,233,23.1060639788,11.12199436455,-39.702274934675,2,1,18 +2025-03-11T12:42:12.199584,479392932,65303,233,22.83276817484,10.848878254905,-39.220184737625,2,1,18 +2025-03-11T12:42:12.215209,479392932,65303,233,22.55947237088,10.571141073435,-38.738076000575,2,1,18 +2025-03-11T12:42:12.230834,479392932,65303,233,22.29560056016,10.28879912607,-38.246719919405,2,1,18 +2025-03-11T12:42:12.246459,479392932,65303,233,22.02701675282,10.00644902574,-37.732251141905,2,1,18 +2025-03-11T12:42:12.262084,479392932,65303,233,21.75372094886,9.71946970062,-37.222378226465,2,1,18 +2025-03-11T12:42:12.277709,479392932,65303,233,21.46628915504,9.450950203905,-36.726422677205,2,1,18 +2025-03-11T12:42:12.293334,479392932,65303,233,21.18356935784,9.16857564468,-36.23966065508,2,1,18 +2025-03-11T12:42:12.308959,479392932,65303,233,20.91027355388,8.886217391385,-35.725185096575,2,1,18 +2025-03-11T12:42:12.324584,479392932,65303,233,20.64640174316,8.599254372195,-35.206083377015,2,1,18 +2025-03-11T12:42:12.340209,479392932,65303,233,20.3731059392,8.321517190725,-34.69162635851,2,1,18 +2025-03-11T12:42:12.355834,479392932,65303,233,20.08096214876,8.052989541045,-34.177179295985,2,1,18 +2025-03-11T12:42:12.371459,479392932,65303,233,19.78881835832,7.76135653224,-33.65339716733,2,1,18 +2025-03-11T12:42:12.387084,479392932,65303,233,19.51552255436,7.488240422595,-33.15282223802,2,1,18 +2025-03-11T12:42:12.402709,479392932,65303,233,19.24693874702,7.21051139409,-32.652235549715,2,1,18 +2025-03-11T12:42:12.418334,479392932,65303,233,18.97835493968,6.93740343741,-32.119319119955,2,1,18 +2025-03-11T12:42:12.433959,479392932,65303,233,18.69563514248,6.65040780636,-31.609432642505,2,1,18 +2025-03-11T12:42:12.449584,479392932,65303,233,18.41291534528,6.368033247135,-31.099564705055,2,1,18 +2025-03-11T12:42:12.465209,479392932,65303,233,18.13019554808,6.07641654426,-30.571174955345,2,1,18 +2025-03-11T12:42:12.480834,479392932,65303,233,17.84747575088,5.784799841385,-30.05664875483,2,1,18 +2025-03-11T12:42:12.496459,479392932,65303,233,17.55061996382,5.50702189509,-29.53291546517,2,1,18 +2025-03-11T12:42:12.512084,479392932,65303,233,17.25376417676,5.22462287697,-28.99992126938,2,1,18 +2025-03-11T12:42:12.527709,479392932,65303,233,16.96162038632,4.92836879634,-28.46225705153,2,1,18 +2025-03-11T12:42:12.543334,479392932,65303,233,16.66476459926,4.64596977822,-27.943126404935,2,1,18 +2025-03-11T12:42:12.558959,479392932,65303,233,16.37262080882,4.363578913065,-27.442487271605,2,1,18 +2025-03-11T12:42:12.574584,479392932,65303,233,16.085189015,4.071954057225,-26.90484837476,2,1,18 +2025-03-11T12:42:12.590209,479392932,65303,233,15.8024692178,3.78033735435,-26.371837441985,2,1,18 +2025-03-11T12:42:12.605834,479392932,65303,233,15.52446141722,3.493349876265,-25.838851830215,2,1,18 +2025-03-11T12:42:12.621459,479392932,65303,233,15.24174162002,3.20173317339,-25.319704446635,2,1,18 +2025-03-11T12:42:12.637084,479392932,65303,233,14.94959782958,2.91472123641,-24.809804407175,2,1,18 +2025-03-11T12:42:12.652709,479392932,65303,233,14.66687803238,2.623104533535,-24.262929925205,2,1,18 +2025-03-11T12:42:12.668334,479392932,65303,233,14.37944623856,2.33610074952,-23.72530956836,2,1,18 +2025-03-11T12:42:12.683959,479392932,65303,233,14.0825904515,2.04445958775,-23.187657109505,2,1,18 +2025-03-11T12:42:12.699584,479392932,65303,233,13.78573466444,1.74357628233,-22.65920993678,2,1,18 +2025-03-11T12:42:12.715209,479392932,65303,233,13.50301486724,1.43809636398,-22.126143384005,2,1,18 +2025-03-11T12:42:12.730834,479392932,65303,233,13.21558307342,1.14647150814,-21.59774685329,2,1,18 +2025-03-11T12:42:12.746459,479392932,65303,233,12.92343928298,0.85021742751,-21.055461452375,2,1,18 +2025-03-11T12:42:12.762084,479392932,65303,233,12.62658349592,0.544713050265001,-20.513132190455,2,1,18 +2025-03-11T12:42:12.777709,479392932,65303,233,12.32972770886,0.262314032144999,-19.980137994665,2,1,18 +2025-03-11T12:42:12.793334,479392932,65303,233,12.03758391842,-0.0385611203099998,-19.451697602945,2,1,18 +2025-03-11T12:42:12.808959,479392932,65303,233,11.74072813136,-0.325581210255001,-18.90482131796,2,1,18 +2025-03-11T12:42:12.824584,479392932,65303,233,11.43916034768,-0.621851596815,-18.371764721165,2,1,18 +2025-03-11T12:42:12.840209,479392932,65303,233,11.15172855386,-0.913476452654999,-17.83412582432,2,1,18 +2025-03-11T12:42:12.855834,479392932,65303,233,10.86429676004,-1.21896452397,-17.277946575215,2,1,18 +2025-03-11T12:42:12.871459,479392932,65303,233,10.55801697974,-1.515243063495,-16.73101964822,2,1,18 +2025-03-11T12:42:12.887084,479392932,65303,233,10.26116119268,-1.80226315344,-16.1887645463,2,1,18 +2025-03-11T12:42:12.902709,479392932,65303,233,9.96901740224,-2.09851723407,-15.655721511515,2,1,18 +2025-03-11T12:42:12.918334,479392932,65303,233,9.66744961856,-2.39478762063,-15.118043731655,2,1,18 +2025-03-11T12:42:12.933959,479392932,65303,233,9.37530582812,-2.71876813221,-14.571025907675,2,1,18 +2025-03-11T12:42:12.949584,479392932,65303,233,9.0878740343,-3.015014059875,-14.037989653895,2,1,18 +2025-03-11T12:42:12.965209,479392932,65303,233,8.77688225738,-3.30667968054,-13.49569566896,2,1,18 +2025-03-11T12:42:12.980834,479392932,65303,233,8.48473846694,-3.616796976645,-12.962597014175,2,1,18 +2025-03-11T12:42:12.996459,479392932,65303,233,8.1925946765,-3.922293200925,-12.424895716325,2,1,18 +2025-03-11T12:42:13.012084,479392932,65303,233,7.89573888944,-4.232418649995,-11.882547914405,2,1,18 +2025-03-11T12:42:13.027709,479392932,65303,233,7.59417110576,-4.52406796473,-11.33102512535,2,1,18 +2025-03-11T12:42:13.043334,479392932,65303,233,7.27846733222,-4.81574173836,-10.77948199328,2,1,18 +2025-03-11T12:42:13.058959,479392932,65303,233,6.97218755192,-5.11664134971,-10.23715770935,2,1,18 +2025-03-11T12:42:13.074584,479392932,65303,233,6.66590777162,-5.41754096106,-9.69483342542,2,1,18 +2025-03-11T12:42:13.090209,479392932,65303,233,6.36433998794,-5.718432419445,-9.1386523733,2,1,18 +2025-03-11T12:42:13.105834,479392932,65303,233,6.07690819412,-6.019299418935,-8.57787048113,2,1,18 +2025-03-11T12:42:13.121459,479392932,65303,233,5.78476440368,-6.324795643215,-8.017063267955,2,1,18 +2025-03-11T12:42:13.137084,479392932,65303,233,5.49262061324,-6.63491293932,-7.479343430105,2,1,18 +2025-03-11T12:42:13.152709,479392932,65303,233,5.2004768228,-6.935788091775,-6.950903038385,2,1,18 +2025-03-11T12:42:13.168334,479392932,65303,233,4.8941970425,-7.22282448765,-6.408634374455,2,1,18 +2025-03-11T12:42:13.183959,479392932,65303,233,4.5879172622,-7.528345170825,-5.857049184395,2,1,18 +2025-03-11T12:42:13.199584,479392932,65303,233,4.2816374819,-7.829244782175,-5.314724900465,2,1,18 +2025-03-11T12:42:13.215209,479392932,65303,233,3.98478169484,-8.130128087595,-4.76779299548,2,1,18 +2025-03-11T12:42:13.230834,479392932,65303,233,3.68792590778,-8.412527105715,-4.21631406743,2,1,18 +2025-03-11T12:42:13.246459,479392932,65303,233,3.40520611058,-8.71338595224,-3.683266054655,2,1,18 +2025-03-11T12:42:13.262084,479392932,65303,233,3.1036383269,-9.014277410625,-3.136327368665,2,1,18 +2025-03-11T12:42:13.277709,479392932,65303,233,2.78322255674,-9.319822552695,-2.59396420172,2,1,18 +2025-03-11T12:42:13.293334,479392932,65303,233,2.46280678658,-9.616125551115,-2.06550166397,2,1,18 +2025-03-11T12:42:13.308959,479392932,65303,233,2.18008698938,-9.921605469465,-1.504708012805,2,1,18 +2025-03-11T12:42:13.324584,479392932,65303,233,1.88323120232,-10.222488774885,-0.93004900943,2,1,18 +2025-03-11T12:42:13.340209,479392932,65303,233,1.58637541526,-10.514129936655,-0.373911818315,2,1,18 +2025-03-11T12:42:13.355834,479392932,65303,233,1.29894362144,-10.833481223445,0.159217135465,2,1,18 +2025-03-11T12:42:13.371459,479392932,65303,233,1.00208783438,-11.12974345704,0.683024585125,2,1,18 +2025-03-11T12:42:13.387084,479392932,65303,233,0.69580805408,-11.416779852915,1.216050882925,2,1,18 +2025-03-11T12:42:13.402709,479392932,65303,233,0.40366426364,-11.713033933545,1.762957466905,2,1,18 +2025-03-11T12:42:13.418334,479392932,65303,233,0.10680847658,-12.004675095315,2.32833702415,2,1,18 +2025-03-11T12:42:13.433959,479392932,65303,233,-0.20418330034,-12.319446075105,2.86610252602,2,1,18 +2025-03-11T12:42:13.449584,479392932,65303,233,-0.51046308064,-12.62496675828,3.403824166885,2,1,18 +2025-03-11T12:42:13.465209,479392932,65303,233,-0.80260687108,-12.916599767085,3.950712210865,2,1,18 +2025-03-11T12:42:13.480834,479392932,65303,233,-1.09475066152,-13.20823277589,4.497600254845,2,1,18 +2025-03-11T12:42:13.496459,479392932,65303,233,-1.38689445196,-13.509107928345,5.044525378825,2,1,18 +2025-03-11T12:42:13.512084,479392932,65303,233,-1.6790382424,-13.81922522445,5.59610876587,2,1,18 +2025-03-11T12:42:13.527709,479392932,65303,233,-1.9853180227,-14.1201248358,6.1384330498,2,1,18 +2025-03-11T12:42:13.543334,479392932,65303,233,-2.29630979962,-14.411790456465,6.67610585167,2,1,18 +2025-03-11T12:42:13.558959,479392932,65303,233,-2.57902959682,-14.71264930299,7.227638596705,2,1,18 +2025-03-11T12:42:13.574584,479392932,65303,233,-2.86646139064,-15.018137374305,7.77457547968,2,1,18 +2025-03-11T12:42:13.590209,479392932,65303,233,-3.1633171777,-15.30515746425,8.30758821547,2,1,18 +2025-03-11T12:42:13.605834,479392932,65303,233,-3.47430895462,-15.606065228565,8.83605573121,2,1,18 +2025-03-11T12:42:13.621459,479392932,65303,233,-3.76645274506,-15.91618252467,9.36453320293,2,1,18 +2025-03-11T12:42:13.637084,479392932,65303,233,-4.06802052874,-16.20321076758,9.91141626892,2,1,18 +2025-03-11T12:42:13.652709,479392932,65303,233,-4.36958831242,-16.49023901049,10.453678151845,2,1,18 +2025-03-11T12:42:13.668334,479392932,65303,233,-4.65702010624,-16.78186386633,11.005180597885,2,1,18 +2025-03-11T12:42:13.683959,479392932,65303,233,-4.9538758933,-17.0735050281,11.55207542287,2,1,18 +2025-03-11T12:42:13.699584,479392932,65303,233,-5.24130768712,-17.369750955765,12.08511167665,2,1,18 +2025-03-11T12:42:13.715209,479392932,65303,233,-5.53816347418,-17.66601318936,12.604297943245,2,1,18 +2025-03-11T12:42:13.730834,479392932,65303,233,-5.83501926124,-17.95765435113,13.1419504021,2,1,18 +2025-03-11T12:42:13.746459,479392932,65303,233,-6.11773905844,-18.25389212583,13.66111632568,2,1,18 +2025-03-11T12:42:13.762084,479392932,65303,233,-6.4145948455,-18.55477543125,14.19418468147,2,1,18 +2025-03-11T12:42:13.777709,479392932,65303,233,-6.71145063256,-18.85565873667,14.72725303726,2,1,18 +2025-03-11T12:42:13.793334,479392932,65303,233,-6.99417042976,-19.138033295895,15.260226890035,2,1,18 +2025-03-11T12:42:13.808959,479392932,65303,233,-7.27217823034,-19.42502077398,15.783970135675,2,1,18 +2025-03-11T12:42:13.824584,479392932,65303,233,-7.5690340174,-19.702798720275,16.316945791465,2,1,18 +2025-03-11T12:42:13.840209,479392932,65303,233,-7.86588980446,-19.994439882045,16.840734701125,2,1,18 +2025-03-11T12:42:13.855834,479392932,65303,233,-8.15332159828,-20.286064737885,17.373752414905,2,1,18 +2025-03-11T12:42:13.871459,479392932,65303,233,-8.4407533921,-20.5730685219,17.888266856425,2,1,18 +2025-03-11T12:42:13.887084,479392932,65303,233,-8.71876119268,-20.88316135911,18.412102802065,2,1,18 +2025-03-11T12:42:13.902709,479392932,65303,233,-9.00148098988,-21.17939913381,18.93588990871,2,1,18 +2025-03-11T12:42:13.918334,479392932,65303,233,-9.27006479722,-21.457128162315,19.473446061535,2,1,18 +2025-03-11T12:42:13.933959,479392932,65303,233,-9.55278459442,-21.73950272154,19.97869281592,2,1,18 +2025-03-11T12:42:13.949584,479392932,65303,233,-9.84492838486,-22.01727251487,20.493176958445,2,1,18 +2025-03-11T12:42:13.965209,479392932,65303,233,-10.11822418882,-22.299630768165,21.01689488308,2,1,18 +2025-03-11T12:42:13.980834,479392932,65303,233,-10.41036797926,-22.59126377697,21.568404110125,2,1,18 +2025-03-11T12:42:13.996398,479392936,65299,234,-10.70722376632,-22.88290493874,22.092193019785,2,1,18 +2025-03-11T12:42:14.012023,479392936,65299,234,-10.98994356352,-23.156037354315,22.61588742643,2,1,18 +2025-03-11T12:42:14.027648,479392936,65299,234,-11.26323936748,-23.433774535785,23.134965628,2,1,18 +2025-03-11T12:42:14.043273,479392936,65299,234,-11.54595916468,-23.72539123866,23.64487064545,2,1,18 +2025-03-11T12:42:14.058898,479392936,65299,234,-11.8333909585,-24.003152879025,24.154726823905,2,1,18 +2025-03-11T12:42:14.074523,479392936,65299,234,-12.13024674556,-24.285551897145,24.678478653565,2,1,18 +2025-03-11T12:42:14.090148,479392936,65299,234,-12.40825454614,-24.57253937523,25.192979533075,2,1,18 +2025-03-11T12:42:14.105773,479392936,65299,234,-12.69097434334,-24.85953500628,25.693623644395,2,1,18 +2025-03-11T12:42:14.121398,479392936,65299,234,-12.97840613716,-25.13267557482,26.19421891672,2,1,18 +2025-03-11T12:42:14.137023,479392936,65299,234,-13.25170194112,-25.41041275629,26.708675935225,2,1,18 +2025-03-11T12:42:14.152648,479392936,65299,234,-13.52499774508,-25.68814993776,27.18616348921,2,1,18 +2025-03-11T12:42:14.168273,479392936,65299,234,-13.79829354904,-25.96588711923,27.67751459239,2,1,18 +2025-03-11T12:42:14.183898,479392936,65299,234,-14.071589353,-26.25286644435,28.19662987396,2,1,18 +2025-03-11T12:42:14.199523,479392936,65299,234,-14.33546116372,-26.535208391715,28.711091870455,2,1,18 +2025-03-11T12:42:14.215148,479392936,65299,234,-14.60875696768,-26.80832450136,29.211666799765,2,1,18 +2025-03-11T12:42:14.230773,479392936,65299,234,-14.90090075812,-27.08609429469,29.712287393095,2,1,18 +2025-03-11T12:42:14.246398,479392936,65299,234,-15.1789085587,-27.354597485475,30.20360819728,2,1,18 +2025-03-11T12:42:14.262023,479392936,65299,234,-15.45691635928,-27.61385853261,30.70875547066,2,1,18 +2025-03-11T12:42:14.277648,479392936,65299,234,-15.72550016662,-27.882345417465,31.200062712835,2,1,18 +2025-03-11T12:42:14.293273,479392936,65299,234,-15.99408397396,-28.15083230232,31.69136995501,2,1,18 +2025-03-11T12:42:14.308898,479392936,65299,234,-16.2626677813,-28.428561330825,32.17809309412,2,1,18 +2025-03-11T12:42:14.324523,479392936,65299,234,-16.51711559878,-28.715508044085,32.66021178715,2,1,18 +2025-03-11T12:42:14.340148,479392936,65299,234,-16.79041140274,-28.97013986643,33.146849007265,2,1,18 +2025-03-11T12:42:14.355773,479392936,65299,234,-17.04957121684,-29.23398937353,33.642745330495,2,1,18 +2025-03-11T12:42:14.371398,479392936,65299,234,-17.30873103094,-29.50708102428,34.138678733725,2,1,18 +2025-03-11T12:42:14.387023,479392936,65299,234,-17.58673883152,-29.78020528689,34.63001807791,2,1,18 +2025-03-11T12:42:14.402648,479392936,65299,234,-17.85532263886,-30.04407109992,35.112064413955,2,1,18 +2025-03-11T12:42:14.418273,479392936,65299,234,-18.11919444958,-30.298686616335,35.594066888995,2,1,18 +2025-03-11T12:42:14.433898,479392936,65299,234,-18.38777825692,-30.562552429365,36.05762849278,2,1,18 +2025-03-11T12:42:14.449523,479392936,65299,234,-18.65636206426,-30.826418242395,36.53505364576,2,1,18 +2025-03-11T12:42:14.465148,479392936,65299,234,-18.91080988174,-31.08101745288,37.012421375725,2,1,18 +2025-03-11T12:42:14.480773,479392936,65299,234,-19.16525769922,-31.34947987884,37.466738810365,2,1,18 +2025-03-11T12:42:14.496398,479392936,65299,234,-19.42441751332,-31.608708314115,37.944131861335,2,1,18 +2025-03-11T12:42:14.512023,479392936,65299,234,-19.67415333418,-31.881783658935,38.421566970295,2,1,18 +2025-03-11T12:42:14.527648,479392936,65299,234,-19.92388915504,-32.15023793193,38.898983539255,2,1,18 +2025-03-11T12:42:14.543273,479392936,65299,234,-20.16420098266,-32.39557053987,39.357809113945,2,1,18 +2025-03-11T12:42:14.558898,479392936,65299,234,-20.41393680352,-32.65016159739,39.80282178145,2,1,18 +2025-03-11T12:42:14.574523,479392936,65299,234,-20.67309661762,-32.91401110449,40.27099100629,2,1,18 +2025-03-11T12:42:14.590148,479392936,65299,234,-20.91812044186,-33.15473079357,40.729804821985,2,1,18 +2025-03-11T12:42:14.605773,479392936,65299,234,-21.17256825934,-33.409330004055,41.193309002755,2,1,18 +2025-03-11T12:42:14.621398,479392936,65299,234,-21.43644007006,-33.668566592295,41.656845285535,2,1,18 +2025-03-11T12:42:14.637023,479392936,65299,234,-21.6814638943,-33.918528425025,42.111074998165,2,1,18 +2025-03-11T12:42:14.652648,479392936,65299,234,-21.9406237084,-34.159272573,42.57453033994,2,1,18 +2025-03-11T12:42:14.668273,479392936,65299,234,-22.1997835225,-34.400016720975,43.01487976639,2,1,18 +2025-03-11T12:42:14.683898,479392936,65299,234,-22.44480734674,-34.65459962553,43.464506835955,2,1,18 +2025-03-11T12:42:14.699523,479392936,65299,234,-22.68511917436,-34.89993223347,43.914090044515,2,1,18 +2025-03-11T12:42:14.715148,479392936,65299,234,-22.93485499522,-35.131417931865,44.34976764589,2,1,18 +2025-03-11T12:42:14.730773,479392936,65299,234,-23.18459081608,-35.38138791756,44.785519407265,2,1,18 +2025-03-11T12:42:14.746398,479392936,65299,234,-23.42961464032,-35.63134975029,45.221264387635,2,1,18 +2025-03-11T12:42:14.762023,479392936,65299,234,-23.66521447132,-35.858189917965,45.656903105995,2,1,18 +2025-03-11T12:42:14.777648,479392936,65299,234,-23.91023829556,-36.09428853522,46.09721364943,2,1,18 +2025-03-11T12:42:14.793273,479392936,65299,234,-24.14583812656,-36.339612990195,46.54216889392,2,1,18 +2025-03-11T12:42:14.808898,479392936,65299,234,-24.37201396432,-36.580300067415,46.97784967027,2,1,18 +2025-03-11T12:42:14.824523,479392936,65299,234,-24.6029017987,-36.816374225775,47.39965513843,2,1,18 +2025-03-11T12:42:14.840148,479392936,65299,234,-24.83378963308,-37.052448384135,47.835324155785,2,1,18 +2025-03-11T12:42:14.855773,479392936,65299,234,-25.0741014607,-37.2839177766,48.266367012085,2,1,18 +2025-03-11T12:42:14.871398,479392936,65299,234,-25.3097012917,-37.5153790161,48.683539538185,2,1,18 +2025-03-11T12:42:14.887023,479392936,65299,234,-25.53116513284,-37.74219472488,49.10067318127,2,1,18 +2025-03-11T12:42:14.902648,479392936,65299,234,-25.74791697736,-37.96438120887,49.50853913722,2,1,18 +2025-03-11T12:42:14.918273,479392936,65299,234,-25.9693808185,-38.19119691765,49.934915146435,2,1,18 +2025-03-11T12:42:14.933898,479392936,65299,234,-26.1814206664,-38.413375248675,50.35201668751,2,1,18 +2025-03-11T12:42:14.949523,479392936,65299,234,-26.40288450754,-38.64481202928,50.759926504465,2,1,18 +2025-03-11T12:42:14.965148,479392936,65299,234,-26.63848433854,-38.87627326878,51.16323548137,2,1,18 +2025-03-11T12:42:14.980773,479392936,65299,234,-26.8646601763,-39.08923391505,51.594183834655,2,1,18 +2025-03-11T12:42:14.996398,479392936,65299,234,-27.08141202082,-39.30217825539,52.002012710605,2,1,18 +2025-03-11T12:42:15.012023,479392936,65299,234,-27.29816386534,-39.528985811205,52.40527602349,2,1,18 +2025-03-11T12:42:15.027648,479392936,65299,234,-27.51962770648,-39.737317232685,52.79922959125,2,1,18 +2025-03-11T12:42:15.043273,479392936,65299,234,-27.72695555776,-39.94562419527,53.165435717605,2,1,18 +2025-03-11T12:42:15.058898,479392936,65299,234,-27.93899540566,-40.17242359812,53.550207517225,2,1,18 +2025-03-11T12:42:15.074523,479392936,65299,234,-28.1604592468,-40.385376091425,53.93031607579,2,1,18 +2025-03-11T12:42:15.090148,479392936,65299,234,-28.36778709808,-40.598304125835,54.31964665747,2,1,18 +2025-03-11T12:42:15.105773,479392936,65299,234,-28.5845389426,-40.802006322525,54.704332538095,2,1,18 +2025-03-11T12:42:15.121398,479392936,65299,234,-28.81071478036,-41.00110375332,55.084392257665,2,1,18 +2025-03-11T12:42:15.137023,479392936,65299,234,-29.02275462826,-41.22790315617,55.47378524035,2,1,18 +2025-03-11T12:42:15.152648,479392936,65299,234,-29.2206584863,-41.445435956475,55.86312080002,2,1,18 +2025-03-11T12:42:15.168273,479392936,65299,234,-29.42327434096,-41.644492622445,56.243146614565,2,1,18 +2025-03-11T12:42:15.183898,479392936,65299,234,-29.621178199,-41.838920063625,56.604662375845,2,1,18 +2025-03-11T12:42:15.199523,479392936,65299,234,-29.82850605028,-42.03798488256,56.966210239135,2,1,18 +2025-03-11T12:42:15.215148,479392936,65299,234,-30.02640990832,-42.23241232374,57.327726000415,2,1,18 +2025-03-11T12:42:15.230773,479392936,65299,234,-30.21488977312,-42.43606560264,57.689265279685,2,1,18 +2025-03-11T12:42:15.246398,479392936,65299,234,-30.41750562778,-42.648985484085,58.05086198197,2,1,18 +2025-03-11T12:42:15.262023,479392936,65299,234,-30.62483347906,-42.83880815937,58.41237276526,2,1,18 +2025-03-11T12:42:15.277648,479392936,65299,234,-30.8227373371,-43.028614528725,58.778491169605,2,1,18 +2025-03-11T12:42:15.293273,479392936,65299,234,-31.00179320866,-43.21838828622,59.121476534605,2,1,18 +2025-03-11T12:42:15.308898,479392936,65299,234,-31.20440906332,-43.41744495219,59.47377525076,2,1,18 +2025-03-11T12:42:15.324523,479392936,65299,234,-31.40231292136,-43.607251321545,59.82603010591,2,1,18 +2025-03-11T12:42:15.340148,479392936,65299,234,-31.58136879292,-43.792404007215,60.173618113975,2,1,18 +2025-03-11T12:42:15.355773,479392936,65299,234,-31.77456065434,-43.982202223605,60.52586618812,2,1,18 +2025-03-11T12:42:15.371398,479392936,65299,234,-31.95832852252,-44.16736306224,60.868839794125,2,1,18 +2025-03-11T12:42:15.387023,479392936,65299,234,-32.14680838732,-44.366395269315,61.193391068875,2,1,18 +2025-03-11T12:42:15.402648,479392936,65299,234,-32.32586425888,-44.560790098635,61.51328905855,2,1,18 +2025-03-11T12:42:15.418273,479392936,65299,234,-32.50020813382,-44.732071415865,61.846951116415,2,1,18 +2025-03-11T12:42:15.433898,479392936,65299,234,-32.67455200876,-44.921837020395,62.18068733428,2,1,18 +2025-03-11T12:42:15.449523,479392936,65299,234,-32.85831987694,-45.10699785903,62.49131265883,2,1,18 +2025-03-11T12:42:15.465148,479392936,65299,234,-33.02795175526,-45.287513166945,62.80652028343,2,1,18 +2025-03-11T12:42:15.480773,479392936,65299,234,-33.20700762682,-45.454181565315,63.117064666975,2,1,18 +2025-03-11T12:42:15.496398,479392936,65299,234,-33.390775495,-45.6301002603,63.436895277655,2,1,18 +2025-03-11T12:42:15.512023,479392936,65299,234,-33.56511936994,-45.79213943388,63.765899072455,2,1,18 +2025-03-11T12:42:15.527648,479392936,65299,234,-33.7441752415,-45.95880783225,64.09492818826,2,1,18 +2025-03-11T12:42:15.543273,479392936,65299,234,-33.91380711982,-46.130080996515,64.396235183665,2,1,18 +2025-03-11T12:42:15.558898,479392936,65299,234,-34.08343899814,-46.296733088955,64.7067660052,2,1,18 +2025-03-11T12:42:15.574523,479392936,65299,234,-34.24835887984,-46.449513812955,65.012613242665,2,1,18 +2025-03-11T12:42:15.590148,479392936,65299,234,-34.41799075816,-46.61154483357,65.300019608875,2,1,18 +2025-03-11T12:42:15.605773,479392936,65299,234,-34.57819864324,-46.782801691905,65.587449493075,2,1,18 +2025-03-11T12:42:15.621398,479392936,65299,234,-34.72898253508,-46.95404224431,65.884108181395,2,1,18 +2025-03-11T12:42:15.637023,479392936,65299,234,-34.87976642692,-47.106798509415,66.17607152665,2,1,18 +2025-03-11T12:42:15.652648,479392936,65299,234,-35.03526231538,-47.268805071135,66.45883636678,2,1,18 +2025-03-11T12:42:15.668273,479392936,65299,234,-35.18604620722,-47.43080347989,66.7554579751,2,1,18 +2025-03-11T12:42:15.683898,479392936,65299,234,-35.35567808554,-47.583592356855,67.02434252905,2,1,18 +2025-03-11T12:42:15.699523,479392936,65299,234,-35.50646197738,-47.72710647831,67.288541695915,2,1,18 +2025-03-11T12:42:15.715148,479392936,65299,234,-35.64310987936,-47.87983828452,67.571242332025,2,1,18 +2025-03-11T12:42:15.730773,479392936,65299,234,-35.7938937712,-48.0464577651,67.84477656502,2,1,18 +2025-03-11T12:42:15.746398,479392936,65299,234,-35.9588136529,-48.185375273625,68.113598717965,2,1,18 +2025-03-11T12:42:15.762023,479392936,65299,234,-36.11430954136,-48.32427647622,68.368543759705,2,1,18 +2025-03-11T12:42:15.777648,479392936,65299,234,-36.26038143658,-48.463161372885,68.641959971695,2,1,18 +2025-03-11T12:42:15.793273,479392936,65299,234,-36.39231734194,-48.602021810655,68.91535584067,2,1,18 +2025-03-11T12:42:15.808898,479392936,65299,234,-36.53838923716,-48.754769922795,69.165721757335,2,1,18 +2025-03-11T12:42:15.824523,479392936,65299,234,-36.67974913576,-48.893646666495,69.416025272995,2,1,18 +2025-03-11T12:42:15.840148,479392936,65299,234,-36.79283705464,-49.01861127693,69.68009603182,2,1,18 +2025-03-11T12:42:15.855773,479392936,65299,234,-36.92477296,-49.162092786525,69.916540976275,2,1,18 +2025-03-11T12:42:15.871398,479392936,65299,234,-37.05199686874,-49.29170292768,70.13905997053,2,1,18 +2025-03-11T12:42:15.887023,479392936,65299,234,-37.17922077748,-49.42593414066,70.380082237045,2,1,18 +2025-03-11T12:42:15.902648,479392936,65299,234,-37.30644468622,-49.564786425465,70.625744226625,2,1,18 +2025-03-11T12:42:15.918273,479392936,65299,234,-37.4430925882,-49.680549657075,70.85746352902,2,1,18 +2025-03-11T12:42:15.933898,479392936,65299,234,-37.57502849356,-49.810167951195,71.047641022825,2,1,18 +2025-03-11T12:42:15.949523,479392936,65299,234,-37.71167639554,-49.93055225463,71.265515316025,2,1,18 +2025-03-11T12:42:15.965148,479392936,65299,234,-37.82947631104,-50.050903946205,71.501847217465,2,1,18 +2025-03-11T12:42:15.980773,479392936,65299,234,-37.95670021978,-50.17127194371,71.738192680915,2,1,18 +2025-03-11T12:42:15.996398,479392936,65299,234,-38.06978813866,-50.286994410495,71.942150979895,2,1,18 +2025-03-11T12:42:16.012023,479392936,65299,234,-38.18287605754,-50.41195902093,72.164631091135,2,1,18 +2025-03-11T12:42:16.027648,479392936,65299,234,-38.31009996628,-50.53694809026,72.373267996195,2,1,18 +2025-03-11T12:42:16.043273,479392936,65299,234,-38.42318788516,-50.63880734157,72.58179185824,2,1,18 +2025-03-11T12:42:16.058898,479392936,65299,234,-38.53156380742,-50.740658439915,72.78106657315,2,1,18 +2025-03-11T12:42:16.074523,479392936,65299,234,-38.63051573644,-50.847114304155,72.98958863218,2,1,18 +2025-03-11T12:42:16.090148,479392936,65299,234,-38.73417966208,-50.95357832136,73.18425392302,2,1,18 +2025-03-11T12:42:16.105773,479392936,65299,234,-38.84255558434,-51.064671563355,73.36508098567,2,1,18 +2025-03-11T12:42:16.121398,479392936,65299,234,-38.94621950998,-51.17113558056,73.564367459575,2,1,18 +2025-03-11T12:42:16.137023,479392936,65299,234,-39.05930742886,-51.27299483187,73.749785406295,2,1,18 +2025-03-11T12:42:16.152648,479392936,65299,234,-39.17239534774,-51.370233011355,73.93980599608,2,1,18 +2025-03-11T12:42:16.168273,479392936,65299,234,-39.26663528014,-51.45819643533,74.129762381845,2,1,18 +2025-03-11T12:42:16.183898,479392936,65299,234,-39.37029920578,-51.564660452535,74.31056412349,2,1,18 +2025-03-11T12:42:16.199523,479392936,65299,234,-39.45040314832,-51.652599417615,74.47277306785,2,1,18 +2025-03-11T12:42:16.215148,479392936,65299,234,-39.53050709086,-51.740538382695,74.621118463015,2,1,18 +2025-03-11T12:42:16.230773,479392936,65299,234,-39.62474702326,-51.823880734845,74.797192759585,2,1,18 +2025-03-11T12:42:16.246398,479392936,65299,234,-39.72369895228,-51.90723123996,74.96403147103,2,1,18 +2025-03-11T12:42:16.262023,479392936,65299,234,-39.7990908982,-52.00902526755,75.13091043745,2,1,18 +2025-03-11T12:42:16.277648,479392936,65299,234,-39.88390683736,-52.096972385595,75.28850497975,2,1,18 +2025-03-11T12:42:16.293273,479392936,65299,234,-39.95929878328,-52.17566105406,75.42756414778,2,1,18 +2025-03-11T12:42:16.308898,479392936,65299,234,-40.03940272582,-52.26360001914,75.58053072601,2,1,18 +2025-03-11T12:42:16.324523,479392936,65299,234,-40.14777864808,-52.34234575836,75.738122093335,2,1,18 +2025-03-11T12:42:16.340148,479392936,65299,234,-40.22788259062,-52.43028472344,75.900331037695,2,1,18 +2025-03-11T12:42:16.355773,479392936,65299,234,-40.31269852978,-52.50436862601,76.039385227735,2,1,18 +2025-03-11T12:42:16.371398,479392936,65299,234,-40.38337847908,-52.57380699786,76.16915816863,2,1,18 +2025-03-11T12:42:16.387023,479392936,65299,234,-40.45405842838,-52.638624297885,76.29429138646,2,1,18 +2025-03-11T12:42:16.402648,479392936,65299,234,-40.52002638106,-52.721917732245,76.40562843409,2,1,18 +2025-03-11T12:42:16.418273,479392936,65299,234,-40.58128233712,-52.782097654515,76.507623634585,2,1,18 +2025-03-11T12:42:16.433898,479392936,65299,234,-40.63782629656,-52.837648351995,76.6326994294,2,1,18 +2025-03-11T12:42:16.449523,479392936,65299,234,-40.68965825938,-52.89319089651,76.743904894015,2,1,18 +2025-03-11T12:42:16.465148,479392936,65299,234,-40.75091421544,-52.97185510608,76.859837803705,2,1,18 +2025-03-11T12:42:16.480773,479392936,65299,234,-40.82159416474,-53.045914549755,76.975765735405,2,1,18 +2025-03-11T12:42:16.496398,479392936,65299,234,-40.88756211742,-53.11534476864,77.077804796905,2,1,18 +2025-03-11T12:42:16.512023,479392936,65299,234,-40.94410607686,-53.17089546612,77.189017042525,2,1,18 +2025-03-11T12:42:16.527648,479392936,65299,234,-41.0006500363,-53.2079618763,77.318639860405,2,1,18 +2025-03-11T12:42:16.543273,479392936,65299,234,-41.05248199912,-53.26812549264,77.3928944005,2,1,18 +2025-03-11T12:42:16.558898,479392936,65299,234,-41.10902595856,-53.31443404647,77.47634246773,2,1,18 +2025-03-11T12:42:16.574523,479392936,65299,234,-41.165569918,-53.35150045665,77.57823818722,2,1,18 +2025-03-11T12:42:16.590148,479392936,65299,234,-41.19855389434,-53.41163146113,77.66632915249,2,1,18 +2025-03-11T12:42:16.605773,479392936,65299,234,-41.2362498673,-53.462528474925,77.754389818765,2,1,18 +2025-03-11T12:42:16.621398,479392936,65299,234,-41.27865783688,-53.504191498035,77.823935453785,2,1,18 +2025-03-11T12:42:16.637023,479392936,65299,234,-41.31164181322,-53.55970143069,77.893523146795,2,1,18 +2025-03-11T12:42:16.652648,479392936,65299,234,-41.36347377604,-53.59213861608,77.96766644689,2,1,18 +2025-03-11T12:42:16.668273,479392936,65299,234,-41.41530573886,-53.62457580147,78.03718856392,2,1,18 +2025-03-11T12:42:16.683898,479392936,65299,234,-41.44357771858,-53.66159329386,78.097452949795,2,1,18 +2025-03-11T12:42:16.699523,479392936,65299,234,-41.4718496983,-53.693989714425,78.134592880345,2,1,18 +2025-03-11T12:42:16.715148,479392936,65299,234,-41.50483367464,-53.72177321613,78.185584601095,2,1,18 +2025-03-11T12:42:16.730773,479392936,65299,234,-41.54724164422,-53.74495195194,78.25043489305,2,1,18 +2025-03-11T12:42:16.746398,479392936,65299,234,-41.56137763408,-53.763460698135,78.29212004365,2,1,18 +2025-03-11T12:42:16.762023,479392936,65299,234,-41.57080162732,-53.79582450684,78.343096399375,2,1,18 +2025-03-11T12:42:16.777648,479392936,65299,234,-41.60378560366,-53.823608008545,78.403330486255,2,1,18 +2025-03-11T12:42:16.793273,479392936,65299,234,-41.62263359014,-53.82826169223,78.440345614795,2,1,18 +2025-03-11T12:42:16.808898,479392936,65299,234,-41.65561756648,-53.85142412211,78.48669761248,2,1,18 +2025-03-11T12:42:16.824523,479392936,65299,234,-41.67917754958,-53.869949174235,78.51915395896,2,1,18 +2025-03-11T12:42:16.840148,479392936,65299,234,-41.69331353944,-53.883836848605,78.537714654235,2,1,18 +2025-03-11T12:42:16.855773,479392936,65299,234,-41.70273753268,-53.893095298185,78.556250028505,2,1,18 +2025-03-11T12:42:16.871398,479392936,65299,234,-41.71216152592,-53.893111604115,78.574748322775,2,1,18 +2025-03-11T12:42:16.887023,479392936,65299,234,-41.73572150902,-53.90239451259,78.59330404006,2,1,18 +2025-03-11T12:42:16.902648,479392936,65299,234,-41.74043350564,-53.91626588103,78.61647235639,2,1,18 +2025-03-11T12:42:16.918273,479392936,65299,234,-41.74043350564,-53.90702373738,78.621056459455,2,1,18 +2025-03-11T12:42:16.933898,479392936,65299,234,-41.74043350564,-53.911644809205,78.630317365585,2,1,18 +2025-03-11T12:42:16.949523,479392936,65299,234,-41.74514550226,-53.925516177645,78.62113740046,2,1,18 +2025-03-11T12:42:16.965148,479392936,65299,234,-41.74514550226,-53.93937939312,78.616571837395,2,1,18 +2025-03-11T12:42:16.980773,479392936,65299,234,-41.7545694955,-53.944016770875,78.625846305535,2,1,18 +2025-03-11T12:42:16.996398,479392936,65299,234,-41.76399348874,-53.93941200498,78.62122014448,2,1,18 +2025-03-11T12:42:17.012023,479392936,65299,234,-41.76399348874,-53.907064502205,78.62109036448,2,1,18 +2025-03-11T12:42:17.027648,479392936,65299,234,-41.7545694955,-53.897806052625,78.607176173275,2,1,18 +2025-03-11T12:42:17.043273,479392936,65299,234,-41.73572150902,-53.89315236894,78.588645776995,2,1,18 +2025-03-11T12:42:17.058898,479392936,65299,234,-41.71216152592,-53.87000624499,78.56079207358,2,1,18 +2025-03-11T12:42:17.074523,479392936,65299,234,-41.70273753268,-53.865368867235,78.53303287318,2,1,18 +2025-03-11T12:42:17.090148,479392936,65299,234,-41.6838895462,-53.8514730399,78.50522303077,2,1,18 +2025-03-11T12:42:17.105773,479392936,65299,234,-41.66504155972,-53.84219828439,78.482052911425,2,1,18 +2025-03-11T12:42:17.121398,479392936,65299,234,-41.64148157662,-53.832915375915,78.43577009575,2,1,18 +2025-03-11T12:42:17.137023,479392936,65299,234,-41.62263359014,-53.814398476755,78.37097224882,2,1,18 +2025-03-11T12:42:17.152648,479392936,65299,234,-41.60378560366,-53.786639433945,78.329243237215,2,1,18 +2025-03-11T12:42:17.168273,479392936,65299,234,-41.5896496138,-53.7588885441,78.287521006615,2,1,18 +2025-03-11T12:42:17.183898,479392936,65299,234,-41.56137763408,-53.744976410835,78.245834053,2,1,18 +2025-03-11T12:42:17.199523,479392936,65299,234,-41.52368166112,-53.698700468865,78.18089784205,2,1,18 +2025-03-11T12:42:17.215148,479392936,65299,234,-41.49069768478,-53.66167482351,78.12062667517,2,1,18 +2025-03-11T12:42:17.230773,479392936,65299,234,-41.45771370844,-53.63851239363,78.065032311355,2,1,18 +2025-03-11T12:42:17.246398,479392936,65299,234,-41.4247297321,-53.6061078201,77.995537318345,2,1,18 +2025-03-11T12:42:17.262023,479392936,65299,234,-41.3776097659,-53.5598155722,77.930587545385,2,1,18 +2025-03-11T12:42:17.277648,479392936,65299,234,-41.33520179632,-53.52739469274,77.842594258105,2,1,18 +2025-03-11T12:42:17.293273,479392936,65299,234,-41.29279382674,-53.49497381328,77.754600970825,2,1,18 +2025-03-11T12:42:17.308898,479392936,65299,234,-41.25509785378,-53.444076799485,77.68502503681,2,1,18 +2025-03-11T12:42:17.324523,479392936,65299,234,-41.2126898842,-53.39779270455,77.610839678725,2,1,18 +2025-03-11T12:42:17.340148,479392936,65299,234,-41.15143392814,-53.36533921323,77.53668281662,2,1,18 +2025-03-11T12:42:17.355773,479392936,65299,234,-41.09960196532,-53.319038812365,77.462483896525,2,1,18 +2025-03-11T12:42:17.371398,479392936,65299,234,-41.0477700025,-53.258875196025,77.374365807235,2,1,18 +2025-03-11T12:42:17.387023,479392936,65299,234,-40.99593803968,-53.207953723335,77.267800065685,2,1,18 +2025-03-11T12:42:17.402648,479392936,65299,234,-40.94410607686,-53.15241117882,77.15659460107,2,1,18 +2025-03-11T12:42:17.418273,479392936,65299,234,-40.88756211742,-53.092239409515,77.04536381545,2,1,18 +2025-03-11T12:42:17.433898,479392936,65299,234,-40.8357301546,-53.032075793175,76.943382176965,2,1,18 +2025-03-11T12:42:17.449523,479392936,65299,234,-40.78389819178,-52.95804896136,76.82286018622,2,1,18 +2025-03-11T12:42:17.465148,479392936,65299,234,-40.72264223572,-52.88862689544,76.702343173465,2,1,18 +2025-03-11T12:42:17.480773,479392936,65299,234,-40.66609827628,-52.82383405431,76.58647266478,2,1,18 +2025-03-11T12:42:17.496398,479392936,65299,234,-40.59070633036,-52.745145385845,76.45665586288,2,1,18 +2025-03-11T12:42:17.512023,479392936,65299,234,-40.52473837768,-52.66647302331,76.331473806055,2,1,18 +2025-03-11T12:42:17.527648,479392936,65299,234,-40.46348242162,-52.61553524469,76.215652136365,2,1,18 +2025-03-11T12:42:17.543273,479392936,65299,234,-40.38337847908,-52.54608056691,76.09510799959,2,1,18 +2025-03-11T12:42:17.558898,479392936,65299,234,-40.29856253992,-52.458133448865,75.95599818955,2,1,18 +2025-03-11T12:42:17.574523,479392936,65299,234,-40.23259458724,-52.402566445455,75.793939368205,2,1,18 +2025-03-11T12:42:17.590148,479392936,65299,234,-40.15720264132,-52.30539348969,75.636321307915,2,1,18 +2025-03-11T12:42:17.605773,479392936,65299,234,-40.07709869878,-52.203591309135,75.511026208075,2,1,18 +2025-03-11T12:42:17.621398,479392936,65299,234,-40.0111307461,-52.13416109025,75.372017682055,2,1,18 +2025-03-11T12:42:17.637023,479392936,65299,234,-39.92160281032,-52.06469010654,75.20524815262,2,1,18 +2025-03-11T12:42:17.652648,479392936,65299,234,-39.84149886778,-51.97675114146,75.056902757455,2,1,18 +2025-03-11T12:42:17.668273,479392936,65299,234,-39.76139492524,-51.893433248205,74.90857590229,2,1,18 +2025-03-11T12:42:17.683898,479392936,65299,234,-39.66715499284,-51.810090896055,74.76947107024,2,1,18 +2025-03-11T12:42:17.699523,479392936,65299,234,-39.57291506044,-51.72212747208,74.588757050605,2,1,18 +2025-03-11T12:42:17.715148,479392936,65299,234,-39.47396313142,-51.620292679665,74.407980629965,2,1,18 +2025-03-11T12:42:17.730773,479392936,65299,234,-39.37029920578,-51.52307080611,74.22721596832,2,1,18 +2025-03-11T12:42:17.746398,479392936,65299,234,-39.27605927338,-51.425865238485,74.046464868685,2,1,18 +2025-03-11T12:42:17.762023,479392936,65299,234,-39.19124333422,-51.32867597679,73.870348514125,2,1,18 +2025-03-11T12:42:17.777648,479392936,65299,234,-39.08286741196,-51.217582734795,73.689521451475,2,1,18 +2025-03-11T12:42:17.793273,479392936,65299,234,-38.99333947618,-51.101901032835,73.49483942365,2,1,18 +2025-03-11T12:42:17.808898,479392936,65299,234,-38.88967555054,-51.009300231105,73.295608569745,2,1,18 +2025-03-11T12:42:17.824523,479392936,65299,234,-38.7624516418,-50.902795449075,73.105530556945,2,1,18 +2025-03-11T12:42:17.840148,479392936,65299,234,-38.64936372292,-50.79631512594,72.938578802485,2,1,18 +2025-03-11T12:42:17.855773,479392936,65299,234,-38.55983578714,-50.68063342398,72.757760323855,2,1,18 +2025-03-11T12:42:17.871398,479392936,65299,234,-38.44674786826,-50.56953202902,72.544578198745,2,1,18 +2025-03-11T12:42:17.887023,479392936,65299,234,-38.32423595614,-50.43993004083,72.32668716856,2,1,18 +2025-03-11T12:42:17.902648,479392936,65299,234,-38.20643604064,-50.32419942108,72.104237356315,2,1,18 +2025-03-11T12:42:17.918273,479392936,65299,234,-38.07450013528,-50.208444342435,71.87714601799,2,1,18 +2025-03-11T12:42:17.933898,479392936,65299,234,-37.95670021978,-50.101955866335,71.65935446881,2,1,18 +2025-03-11T12:42:17.949523,479392936,65299,234,-37.85303629414,-49.98624970548,71.450788548775,2,1,18 +2025-03-11T12:42:17.965148,479392936,65299,234,-37.73994837526,-49.86590616687,71.2329481606,2,1,18 +2025-03-11T12:42:17.980773,479392936,65299,234,-37.61272446652,-49.745538169365,71.00584506328,2,1,18 +2025-03-11T12:42:17.996337,479392940,65295,235,-37.4902125544,-49.61131510935,70.769450760835,2,1,18 +2025-03-11T12:42:18.011962,479392940,65295,235,-37.36298864566,-49.47708389637,70.53767086045,2,1,18 +2025-03-11T12:42:18.027587,479392940,65295,235,-37.23576473692,-49.35209482704,70.305928040065,2,1,18 +2025-03-11T12:42:18.043212,479392940,65295,235,-37.10854082818,-49.22710575771,70.06494285355,2,1,18 +2025-03-11T12:42:18.058837,479392940,65295,235,-36.9718929262,-49.10210038245,69.81932292196,2,1,18 +2025-03-11T12:42:18.074462,479392940,65295,235,-36.83524502422,-48.95861071989,69.5828711965,2,1,18 +2025-03-11T12:42:18.090087,479392940,65295,235,-36.68446113238,-48.81971767026,69.337175301895,2,1,18 +2025-03-11T12:42:18.105712,479392940,65295,235,-36.53838923716,-48.680832773595,69.08686500523,2,1,18 +2025-03-11T12:42:18.121337,479392940,65295,235,-36.38760534532,-48.52807650849,68.8180075753,2,1,18 +2025-03-11T12:42:18.136962,479392940,65295,235,-36.25566943996,-48.39845821437,68.54926996939,2,1,18 +2025-03-11T12:42:18.152587,479392940,65295,235,-36.11902153798,-48.26421069546,68.26664349328,2,1,18 +2025-03-11T12:42:18.168212,479392940,65295,235,-35.97766163938,-48.11609180811,68.01630289762,2,1,18 +2025-03-11T12:42:18.183837,479392940,65295,235,-35.82687774754,-47.96795661483,67.75670637382,2,1,18 +2025-03-11T12:42:18.199462,479392940,65295,235,-35.68080585232,-47.801345287215,67.497042471025,2,1,18 +2025-03-11T12:42:18.215087,479392940,65295,235,-35.52530996386,-47.66244408462,67.223612697025,2,1,18 +2025-03-11T12:42:18.230712,479392940,65295,235,-35.38395006526,-47.51432519727,66.954787369105,2,1,18 +2025-03-11T12:42:18.246337,479392940,65295,235,-35.24730216328,-47.347730175585,66.6581675638,2,1,18 +2025-03-11T12:42:18.261962,479392940,65295,235,-35.0870942782,-47.1857154609,66.35229002734,2,1,18 +2025-03-11T12:42:18.277587,479392940,65295,235,-34.92688639312,-47.02832181804,66.051052213945,2,1,18 +2025-03-11T12:42:18.293212,479392940,65295,235,-34.77139050466,-46.85707311267,65.77287147688,2,1,18 +2025-03-11T12:42:18.308837,479392940,65295,235,-34.59704662972,-46.71351822639,65.4809113066,2,1,18 +2025-03-11T12:42:18.324462,479392940,65295,235,-34.44155074126,-46.55151166467,65.18890410034,2,1,18 +2025-03-11T12:42:18.340087,479392940,65295,235,-34.30490283928,-46.375674499335,64.892247215035,2,1,18 +2025-03-11T12:42:18.355712,479392940,65295,235,-34.15883094406,-46.21830531537,64.58640856159,2,1,18 +2025-03-11T12:42:18.371337,479392940,65295,235,-33.9797750725,-46.04239477335,64.285069464175,2,1,18 +2025-03-11T12:42:18.386962,479392940,65295,235,-33.80071920094,-45.86648423133,63.979109183695,2,1,18 +2025-03-11T12:42:18.402587,479392940,65295,235,-33.62166332938,-45.695194761135,63.673167443215,2,1,18 +2025-03-11T12:42:18.418212,479392940,65295,235,-33.45203145106,-45.52392159687,63.36261808168,2,1,18 +2025-03-11T12:42:18.433837,479392940,65295,235,-33.2729755795,-45.3572531985,63.042831332005,2,1,18 +2025-03-11T12:42:18.449462,479392940,65295,235,-33.1080556978,-45.172124971725,62.71836958228,2,1,18 +2025-03-11T12:42:18.465087,479392940,65295,235,-32.93371182286,-45.000843654495,62.384707524415,2,1,18 +2025-03-11T12:42:18.480712,479392940,65295,235,-32.74994395468,-44.829546031335,62.05103190454,2,1,18 +2025-03-11T12:42:18.496337,479392940,65295,235,-32.5661760865,-44.639764120875,61.726524490795,2,1,18 +2025-03-11T12:42:18.511962,479392940,65295,235,-32.39654420818,-44.436143453835,61.397360617,2,1,18 +2025-03-11T12:42:18.527587,479392940,65295,235,-32.21748833662,-44.250990768165,61.068257341195,2,1,18 +2025-03-11T12:42:18.543212,479392940,65295,235,-32.0242964752,-44.079676839075,60.72532579318,2,1,18 +2025-03-11T12:42:18.558837,479392940,65295,235,-31.84052860702,-43.90375814409,60.373146901045,2,1,18 +2025-03-11T12:42:18.574462,479392940,65295,235,-31.65676073884,-43.71397623363,60.03939712117,2,1,18 +2025-03-11T12:42:18.590087,479392940,65295,235,-31.47770486728,-43.51958140431,59.691772033105,2,1,18 +2025-03-11T12:42:18.605712,479392940,65295,235,-31.28451300586,-43.325162116095,59.344126602025,2,1,18 +2025-03-11T12:42:18.621337,479392940,65295,235,-31.08660914782,-43.14459789039,58.991908826875,2,1,18 +2025-03-11T12:42:18.636962,479392940,65295,235,-30.8934172864,-42.94555753035,58.671971954185,2,1,18 +2025-03-11T12:42:18.652587,479392940,65295,235,-30.69551342836,-42.74188794552,58.3242826621,2,1,18 +2025-03-11T12:42:18.668212,479392940,65295,235,-30.50232156694,-42.53360544183,57.962718061825,2,1,18 +2025-03-11T12:42:18.683837,479392940,65295,235,-30.3044177089,-42.3484201443,57.591997014415,2,1,18 +2025-03-11T12:42:18.699462,479392940,65295,235,-30.09708985762,-42.158597469015,57.21662268193,2,1,18 +2025-03-11T12:42:18.715087,479392940,65295,235,-29.89447400296,-41.95491973122,56.855063059645,2,1,18 +2025-03-11T12:42:18.730712,479392940,65295,235,-29.69657014492,-41.75125014639,56.49813140143,2,1,18 +2025-03-11T12:42:18.746337,479392940,65295,235,-29.48924229364,-41.55680639928,56.131980895075,2,1,18 +2025-03-11T12:42:18.761962,479392940,65295,235,-29.28662643898,-41.325402230535,55.75182530053,2,1,18 +2025-03-11T12:42:18.777587,479392940,65295,235,-29.0792985877,-41.11709526795,55.348649709655,2,1,18 +2025-03-11T12:42:18.793212,479392940,65295,235,-28.86254674318,-40.918014143085,54.968603552095,2,1,18 +2025-03-11T12:42:18.808837,479392940,65295,235,-28.65993088852,-40.700473189815,54.583882394485,2,1,18 +2025-03-11T12:42:18.824462,479392940,65295,235,-28.45731503386,-40.482932236545,54.208403603005,2,1,18 +2025-03-11T12:42:18.840087,479392940,65295,235,-28.23585119272,-40.283842958715,53.814487115245,2,1,18 +2025-03-11T12:42:18.855712,479392940,65295,235,-28.02381134482,-40.066285699515,53.420510029495,2,1,18 +2025-03-11T12:42:18.871337,479392940,65295,235,-27.81648349354,-39.844115521455,53.02652118475,2,1,18 +2025-03-11T12:42:18.886962,479392940,65295,235,-27.59030765578,-39.62653380336,52.63714493905,2,1,18 +2025-03-11T12:42:18.902587,479392940,65295,235,-27.36413181802,-39.408952085265,52.243147510285,2,1,18 +2025-03-11T12:42:18.918212,479392940,65295,235,-27.13795598026,-39.19137036717,51.826044166195,2,1,18 +2025-03-11T12:42:18.933837,479392940,65295,235,-26.91649213912,-38.95531251474,51.422736992305,2,1,18 +2025-03-11T12:42:18.949462,479392940,65295,235,-26.69502829798,-38.72849680596,51.019466898415,2,1,18 +2025-03-11T12:42:18.965087,479392940,65295,235,-26.46885246022,-38.501672944215,50.60694765739,2,1,18 +2025-03-11T12:42:18.980712,479392940,65295,235,-26.2521006157,-38.279486460225,50.194460518375,2,1,18 +2025-03-11T12:42:18.996337,479392940,65295,235,-26.02592477794,-38.05266259848,49.80042600961,2,1,18 +2025-03-11T12:42:19.011962,479392940,65295,235,-25.8044609368,-37.821225817875,49.364789094265,2,1,18 +2025-03-11T12:42:19.027587,479392940,65295,235,-25.5924210889,-37.594426415025,48.95691137932,2,1,18 +2025-03-11T12:42:19.043212,479392940,65295,235,-25.3568212579,-37.372207319175,48.54901829935,2,1,18 +2025-03-11T12:42:19.058837,479392940,65295,235,-25.12593342352,-37.14999637629,48.131889634255,2,1,18 +2025-03-11T12:42:19.074462,479392940,65295,235,-24.89033359252,-36.90005084949,47.714642948155,2,1,18 +2025-03-11T12:42:19.090087,479392940,65295,235,-24.6500217649,-36.659339313375,47.27894182879,2,1,18 +2025-03-11T12:42:19.105712,479392940,65295,235,-24.43326992038,-36.41404747026,46.83401370832,2,1,18 +2025-03-11T12:42:19.121337,479392940,65295,235,-24.19295809276,-36.182578077795,46.407592035085,2,1,18 +2025-03-11T12:42:19.136962,479392940,65295,235,-23.95264626514,-35.946487613505,45.976530638785,2,1,18 +2025-03-11T12:42:19.152587,479392940,65295,235,-23.7076224409,-35.71038899625,45.540841278415,2,1,18 +2025-03-11T12:42:19.168212,479392940,65295,235,-23.46259861666,-35.474290378995,45.09128836885,2,1,18 +2025-03-11T12:42:19.183837,479392940,65295,235,-23.21757479242,-35.224328546265,44.64630102235,2,1,18 +2025-03-11T12:42:19.199462,479392940,65295,235,-22.98197496142,-34.97900409129,44.20134577786,2,1,18 +2025-03-11T12:42:19.215087,479392940,65295,235,-22.74637513042,-34.742921779965,43.7656699795,2,1,18 +2025-03-11T12:42:19.230712,479392940,65295,235,-22.51548729604,-34.50222654978,43.320740056015,2,1,18 +2025-03-11T12:42:19.246337,479392940,65295,235,-22.2704634718,-34.266127932525,42.88042951258,2,1,18 +2025-03-11T12:42:19.261962,479392940,65295,235,-22.01601565432,-34.016149793865,42.449292153265,2,1,18 +2025-03-11T12:42:19.277587,479392940,65295,235,-21.76627983346,-33.761558736345,42.00427948576,2,1,18 +2025-03-11T12:42:19.293212,479392940,65295,235,-21.53539199908,-33.507000290685,41.540809210015,2,1,18 +2025-03-11T12:42:19.308837,479392940,65295,235,-21.3045041647,-33.2663050605,41.072773371205,2,1,18 +2025-03-11T12:42:19.324462,479392940,65295,235,-21.04063235398,-33.020931687735,40.609292708425,2,1,18 +2025-03-11T12:42:19.340087,479392940,65295,235,-20.78147253988,-32.757082180635,40.141123483585,2,1,18 +2025-03-11T12:42:19.355712,479392940,65295,235,-20.53173671902,-32.48862790764,39.68681282995,2,1,18 +2025-03-11T12:42:19.371337,479392940,65295,235,-20.26315291168,-32.23400423826,39.22790948923,2,1,18 +2025-03-11T12:42:19.386962,479392940,65295,235,-19.99456910434,-31.984001640705,38.76902468851,2,1,18 +2025-03-11T12:42:19.402587,479392940,65295,235,-19.73540929024,-31.747878564555,38.296345520605,2,1,18 +2025-03-11T12:42:19.418212,479392940,65295,235,-19.47624947614,-31.493271201105,37.80510746044,2,1,18 +2025-03-11T12:42:19.433837,479392940,65295,235,-19.21708966204,-31.23404276583,37.341577958665,2,1,18 +2025-03-11T12:42:19.449462,479392940,65295,235,-18.95792984794,-30.974814330555,36.854942541565,2,1,18 +2025-03-11T12:42:19.465087,479392940,65295,235,-18.7129060237,-30.697126066875,36.37749567361,2,1,18 +2025-03-11T12:42:19.480712,479392940,65295,235,-18.46788219946,-30.419437803195,35.91391235485,2,1,18 +2025-03-11T12:42:19.496337,479392940,65295,235,-18.19929839212,-30.146329846515,35.441071304935,2,1,18 +2025-03-11T12:42:19.511962,479392940,65295,235,-17.94013857802,-29.90558569854,34.96837359703,2,1,18 +2025-03-11T12:42:19.527587,479392940,65295,235,-17.68569076054,-29.650986488055,34.486384684,2,1,18 +2025-03-11T12:42:19.543212,479392940,65295,235,-17.42653094644,-29.37327376548,33.985811557705,2,1,18 +2025-03-11T12:42:19.558837,479392940,65295,235,-17.14852314586,-29.10939164652,33.48526692739,2,1,18 +2025-03-11T12:42:19.574462,479392940,65295,235,-16.8752273419,-28.83165446505,32.998537007275,2,1,18 +2025-03-11T12:42:19.590087,479392940,65295,235,-16.59721954132,-28.56777234609,32.52571947535,2,1,18 +2025-03-11T12:42:19.605712,479392940,65295,235,-16.33805972722,-28.299301767165,32.043668161315,2,1,18 +2025-03-11T12:42:19.621337,479392940,65295,235,-16.07889991312,-28.02158904459,31.556958584215,2,1,18 +2025-03-11T12:42:19.636962,479392940,65295,235,-15.80560410916,-27.748472934945,31.06100483797,2,1,18 +2025-03-11T12:42:19.652587,479392940,65295,235,-15.54173229844,-27.470752059405,30.56042493067,2,1,18 +2025-03-11T12:42:19.668212,479392940,65295,235,-15.26372449786,-27.22073315592,30.059935920355,2,1,18 +2025-03-11T12:42:19.683837,479392940,65295,235,-14.98100470066,-26.947600740345,29.577832161295,2,1,18 +2025-03-11T12:42:19.699462,479392940,65295,235,-14.70299690008,-26.66061326226,29.063331281785,2,1,18 +2025-03-11T12:42:19.715087,479392940,65295,235,-14.42970109612,-26.387497152615,28.55813516941,2,1,18 +2025-03-11T12:42:19.730712,479392940,65295,235,-14.16111728878,-26.10976812411,28.066790847235,2,1,18 +2025-03-11T12:42:19.746337,479392940,65295,235,-13.8831094882,-25.841264933325,27.57547004305,2,1,18 +2025-03-11T12:42:19.761962,479392940,65295,235,-13.60510168762,-25.56351959889,27.06100624354,2,1,18 +2025-03-11T12:42:19.777587,479392940,65295,235,-13.3176698938,-25.27189474305,26.551094445085,2,1,18 +2025-03-11T12:42:19.793212,479392940,65295,235,-13.04908608646,-24.984923570895,26.055091859845,2,1,18 +2025-03-11T12:42:19.808837,479392940,65295,235,-12.76165429264,-24.69791978688,25.549819784455,2,1,18 +2025-03-11T12:42:19.824462,479392940,65295,235,-12.4695105022,-24.434013209025,25.04463362806,2,1,18 +2025-03-11T12:42:19.840087,479392940,65295,235,-12.19621469824,-24.156276027555,24.54404015875,2,1,18 +2025-03-11T12:42:19.855712,479392940,65295,235,-11.92291889428,-23.86467563061,24.038769886375,2,1,18 +2025-03-11T12:42:19.871337,479392940,65295,235,-11.64962309032,-23.56845416184,23.519617524805,2,1,18 +2025-03-11T12:42:19.886962,479392940,65295,235,-11.39046327622,-23.28612036744,23.00978349238,2,1,18 +2025-03-11T12:42:19.902587,479392940,65295,235,-11.11716747226,-23.013004257795,22.495345013875,2,1,18 +2025-03-11T12:42:19.918212,479392940,65295,235,-10.82973567844,-22.721379401955,21.943842567835,2,1,18 +2025-03-11T12:42:19.933837,479392940,65295,235,-10.54230388462,-22.43437561794,21.42470694325,2,1,18 +2025-03-11T12:42:19.949462,479392940,65295,235,-10.24544809756,-22.15197659982,20.91019747972,2,1,18 +2025-03-11T12:42:19.965087,479392940,65295,235,-9.95330430712,-21.88344895014,20.39112923413,2,1,18 +2025-03-11T12:42:19.980712,479392940,65295,235,-9.66116051668,-21.57795272586,19.87191266854,2,1,18 +2025-03-11T12:42:19.996337,479392940,65295,235,-9.36430472962,-21.28631156409,19.34812375888,2,1,18 +2025-03-11T12:42:20.011962,479392940,65295,235,-9.0768729358,-21.01317099555,18.83366493736,2,1,18 +2025-03-11T12:42:20.027587,479392940,65295,235,-8.78944114198,-20.72154613971,18.30064722358,2,1,18 +2025-03-11T12:42:20.043212,479392940,65295,235,-8.5114333414,-20.42069544615,17.762984808745,2,1,18 +2025-03-11T12:42:20.058837,479392940,65295,235,-8.23813753744,-20.12447397738,17.22996889798,2,1,18 +2025-03-11T12:42:20.074462,479392940,65295,235,-7.94128175038,-19.837453887435,16.70619852832,2,1,18 +2025-03-11T12:42:20.090087,479392940,65295,235,-7.64442596332,-19.55967594114,16.177844055595,2,1,18 +2025-03-11T12:42:20.105712,479392940,65295,235,-7.36641816274,-19.25882524758,15.64942400689,2,1,18 +2025-03-11T12:42:20.121337,479392940,65295,235,-7.08369836554,-18.976450688355,15.11182897105,2,1,18 +2025-03-11T12:42:20.136962,479392940,65295,235,-6.80097856834,-18.698697200955,14.57425247521,2,1,18 +2025-03-11T12:42:20.152587,479392940,65295,235,-6.51825877114,-18.39783835443,14.0458256455,2,1,18 +2025-03-11T12:42:20.168212,479392940,65295,235,-6.2261149807,-18.078478914675,13.503447544585,2,1,18 +2025-03-11T12:42:20.183837,479392940,65295,235,-5.92925919364,-17.79145882473,12.970434808795,2,1,18 +2025-03-11T12:42:20.199462,479392940,65295,235,-5.6371154032,-17.50444688775,12.442050037075,2,1,18 +2025-03-11T12:42:20.215087,479392940,65295,235,-5.34025961614,-17.22204786963,11.918298207415,2,1,18 +2025-03-11T12:42:20.230712,479392940,65295,235,-5.04340382908,-16.92116456421,11.38060866856,2,1,18 +2025-03-11T12:42:20.246337,479392940,65295,235,-4.74654804202,-16.615660186965,10.852142955835,2,1,18 +2025-03-11T12:42:20.261962,479392940,65295,235,-4.45440425158,-16.319406106335,10.323721104115,2,1,18 +2025-03-11T12:42:20.277587,479392940,65295,235,-4.14341247466,-16.02774048567,9.776805936115,2,1,18 +2025-03-11T12:42:20.293212,479392940,65295,235,-3.84184469098,-15.73147009911,9.229885790125,2,1,18 +2025-03-11T12:42:20.308837,479392940,65295,235,-3.54970090054,-15.42597387483,8.692184492275,2,1,18 +2025-03-11T12:42:20.324462,479392940,65295,235,-3.26698110334,-15.134357171955,8.145310010305,2,1,18 +2025-03-11T12:42:20.340087,479392940,65295,235,-2.96541331966,-14.83346571357,7.607613690445,2,1,18 +2025-03-11T12:42:20.355712,479392940,65295,235,-2.66384553598,-14.54643747066,7.079215356715,2,1,18 +2025-03-11T12:42:20.371337,479392940,65295,235,-2.37170174554,-14.245562318205,6.5369114158,2,1,18 +2025-03-11T12:42:20.386962,479392940,65295,235,-2.08426995172,-13.94931639054,5.99463279589,2,1,18 +2025-03-11T12:42:20.402587,479392940,65295,235,-1.78270216804,-13.648424932155,5.4476941099,2,1,18 +2025-03-11T12:42:20.418212,479392940,65295,235,-1.49998237084,-13.361429301105,4.90083816793,2,1,18 +2025-03-11T12:42:20.433837,479392940,65295,235,-1.19841458716,-13.055916770895,4.349259758875,2,1,18 +2025-03-11T12:42:20.449462,479392940,65295,235,-0.89213480686,-12.755017159545,3.797693108815,2,1,18 +2025-03-11T12:42:20.465087,479392940,65295,235,-0.60941500966,-12.458779384845,3.250800086845,2,1,18 +2025-03-11T12:42:20.480712,479392940,65295,235,-0.32198321584,-12.17177560083,2.745528011455,2,1,18 +2025-03-11T12:42:20.496337,479392940,65295,235,-0.0157034355400002,-11.86163384583,2.193924281395,2,1,18 +2025-03-11T12:42:20.511962,479392940,65295,235,0.29057634476,-11.556113162655,1.623854359075,2,1,18 +2025-03-11T12:42:20.527587,479392940,65295,235,0.59214412844,-11.259842776095,1.07231303002,2,1,18 +2025-03-11T12:42:20.543212,479392940,65295,235,0.89371191212,-10.945088102235,0.5160763579,2,1,18 +2025-03-11T12:42:20.558837,479392940,65295,235,1.19056769918,-10.653446940465,-0.0123337348249999,2,1,18 +2025-03-11T12:42:20.574462,479392940,65295,235,1.477999493,-10.361822084625,-0.554593814735,2,1,18 +2025-03-11T12:42:20.590087,479392940,65295,235,1.77956727668,-10.07941491354,-1.11532188992,2,1,18 +2025-03-11T12:42:20.605712,479392940,65295,235,2.07171106712,-9.78316083291,-1.648364924705,2,1,18 +2025-03-11T12:42:20.621337,479392940,65295,235,2.3732788508,-9.4776483027,-2.19994333376,2,1,18 +2025-03-11T12:42:20.636962,479392940,65295,235,2.69840661758,-9.153610720365,-2.756250990905,2,1,18 +2025-03-11T12:42:20.652587,479392940,65295,235,2.99997440126,-8.84347711833,-3.293984390765,2,1,18 +2025-03-11T12:42:20.668212,479392940,65295,235,3.28740619508,-8.55185226249,-3.836244470675,2,1,18 +2025-03-11T12:42:20.683837,479392940,65295,235,3.57954998552,-8.260219253685,-4.383132514655,2,1,18 +2025-03-11T12:42:20.699462,479392940,65295,235,3.88582976582,-7.950077498685,-4.93935742778,2,1,18 +2025-03-11T12:42:20.715087,479392940,65295,235,4.19210954612,-7.63531467186,-5.49097969784,2,1,18 +2025-03-11T12:42:20.730712,479392940,65295,235,4.48425333656,-7.34830273488,-6.02860683569,2,1,18 +2025-03-11T12:42:20.746337,479392940,65295,235,4.78110912362,-7.05666157311,-6.56163811148,2,1,18 +2025-03-11T12:42:20.761962,479392940,65295,235,5.0826769073,-6.7511490429,-7.1178377036,2,1,18 +2025-03-11T12:42:20.777587,479392940,65295,235,5.37953269436,-6.464128952955,-7.673956354715,2,1,18 +2025-03-11T12:42:20.793212,479392940,65295,235,5.68581247466,-6.16785041343,-8.225504464775,2,1,18 +2025-03-11T12:42:20.808837,479392940,65295,235,5.99680425158,-5.866942649115,-8.772456712775,2,1,18 +2025-03-11T12:42:20.824462,479392940,65295,235,6.27952404878,-5.56608380259,-9.29626235942,2,1,18 +2025-03-11T12:42:20.840087,479392940,65295,235,6.57166783922,-5.255966506485,-9.810876281945,2,1,18 +2025-03-11T12:42:20.855712,479392940,65295,235,6.86852362628,-4.955083201065,-10.371671736125,2,1,18 +2025-03-11T12:42:20.871337,479392940,65295,235,7.1795154032,-4.649554364925,-10.946369622515,2,1,18 +2025-03-11T12:42:20.886962,479392940,65295,235,7.48108318688,-4.353283978365,-11.48866858544,2,1,18 +2025-03-11T12:42:20.902587,479392940,65295,235,7.78265097056,-4.05239251998,-12.021743722235,2,1,18 +2025-03-11T12:42:20.918212,479392940,65295,235,8.074794761,-3.7468962957,-12.559445020085,2,1,18 +2025-03-11T12:42:20.933837,479392940,65295,235,8.37636254468,-3.44138376549,-13.106402246075,2,1,18 +2025-03-11T12:42:20.949462,479392940,65295,235,8.66850633512,-3.140508613035,-13.64870618699,2,1,18 +2025-03-11T12:42:20.965087,479392940,65295,235,8.96536212218,-2.839625307615,-14.204880458105,2,1,18 +2025-03-11T12:42:20.980712,479392940,65295,235,9.26692990586,-2.561839208355,-14.751726444095,2,1,18 +2025-03-11T12:42:20.996337,479392940,65295,235,9.57320968616,-2.26556066883,-15.294032188025,2,1,18 +2025-03-11T12:42:21.011962,479392940,65295,235,9.87006547322,-1.969298435235,-15.82246082075,2,1,18 +2025-03-11T12:42:21.027587,479392940,65295,235,10.15278527042,-1.65919744506,-16.36940946272,2,1,18 +2025-03-11T12:42:21.043212,479392940,65295,235,10.44021706424,-1.36757258922,-16.91166954263,2,1,18 +2025-03-11T12:42:21.058837,479392940,65295,235,10.73236085468,-1.066697436765,-17.435488751285,2,1,18 +2025-03-11T12:42:21.074462,479392940,65295,235,11.03392863836,-0.77504812203,-17.973147991145,2,1,18 +2025-03-11T12:42:21.090087,479392940,65295,235,11.34020841866,-0.49263279798,-18.524640481205,2,1,18 +2025-03-11T12:42:21.105712,479392940,65295,235,11.64648819896,-0.19173318663,-19.076207131265,2,1,18 +2025-03-11T12:42:21.121337,479392940,65295,235,11.92449599954,0.0952542914549994,-19.62305629223,2,1,18 +2025-03-11T12:42:21.136962,479392940,65295,235,12.20721579674,0.400734209805,-20.15150166194,2,1,18 +2025-03-11T12:42:21.152587,479392940,65295,235,12.5040715838,0.701617515225,-20.679948834665,2,1,18 +2025-03-11T12:42:21.168212,479392940,65295,235,12.79621537424,1.007113739505,-21.23151368171,2,1,18 +2025-03-11T12:42:21.183837,479392940,65295,235,13.0930711613,1.298754901275,-21.75530259137,2,1,18 +2025-03-11T12:42:21.199462,479392940,65295,235,13.39463894498,1.585783144185,-22.29294329123,2,1,18 +2025-03-11T12:42:21.215087,479392940,65295,235,13.69149473204,1.858940018655,-22.84438513928,2,1,18 +2025-03-11T12:42:21.230712,479392940,65295,235,13.9883505191,2.150581180425,-23.36817404894,2,1,18 +2025-03-11T12:42:21.246337,479392940,65295,235,14.2710703163,2.456061098775,-23.90586178478,2,1,18 +2025-03-11T12:42:21.261962,479392940,65295,235,14.54907811688,2.738427505035,-24.42958649042,2,1,18 +2025-03-11T12:42:21.277587,479392940,65295,235,14.85064590056,3.025455747945,-24.95798482415,2,1,18 +2025-03-11T12:42:21.293212,479392940,65295,235,15.15221368424,3.321726134505,-25.47717787175,2,1,18 +2025-03-11T12:42:21.308837,479392940,65295,235,15.43964547806,3.594866703045,-26.0008790594,2,1,18 +2025-03-11T12:42:21.324462,479392940,65295,235,15.7317892685,3.88649971185,-26.51079763886,2,1,18 +2025-03-11T12:42:21.340087,479392940,65295,235,16.02393305894,4.18275379248,-27.03921949058,2,1,18 +2025-03-11T12:42:21.355712,479392940,65295,235,16.30665285614,4.47899156718,-27.563006597225,2,1,18 +2025-03-11T12:42:21.371337,479392940,65295,235,16.57523666348,4.77982595481,-28.086791900855,2,1,18 +2025-03-11T12:42:21.386962,479392940,65295,235,16.8626684573,5.07145081065,-28.61518843157,2,1,18 +2025-03-11T12:42:21.402587,479392940,65295,235,17.15010025112,5.35383352284,-29.12968433309,2,1,18 +2025-03-11T12:42:21.418212,479392940,65295,235,17.44224404156,5.63160331617,-29.662653207875,2,1,18 +2025-03-11T12:42:21.433837,479392940,65295,235,17.7108278489,5.909332344675,-30.2002093607,2,1,18 +2025-03-11T12:42:21.449462,479392940,65295,235,17.9935476461,6.196327975725,-30.742444119605,2,1,18 +2025-03-11T12:42:21.465087,479392940,65295,235,18.28569143654,6.49720312818,-31.247778596,2,1,18 +2025-03-11T12:42:21.480712,479392940,65295,235,18.5825472236,6.802707505425,-31.77162312566,2,1,18 +2025-03-11T12:42:21.496337,479392940,65295,235,18.85113103094,7.08043653393,-32.290694546225,2,1,18 +2025-03-11T12:42:21.511962,479392940,65295,235,19.13385082814,7.344326805855,-32.80510950674,2,1,18 +2025-03-11T12:42:21.527587,479392940,65295,235,19.42599461858,7.631338742835,-33.32425191233,2,1,18 +2025-03-11T12:42:21.543212,479392940,65295,235,19.71813840902,7.918350679815,-33.820288402595,2,1,18 +2025-03-11T12:42:21.558837,479392940,65295,235,19.9961462096,8.19609601425,-34.33937338517,2,1,18 +2025-03-11T12:42:21.574462,479392940,65295,235,20.28357800342,8.473857654615,-34.849229563625,2,1,18 +2025-03-11T12:42:21.590087,479392940,65295,235,20.57100979724,8.756240366805,-35.36834664821,2,1,18 +2025-03-11T12:42:21.605712,479392940,65295,235,20.84901759782,9.047848916715,-35.887487250785,2,1,18 +2025-03-11T12:42:21.621337,479392940,65295,235,21.10817741192,9.31631949564,-36.383402114015,2,1,18 +2025-03-11T12:42:21.636962,479392940,65295,235,21.38147321588,9.60329882076,-36.87016911413,2,1,18 +2025-03-11T12:42:21.652587,479392940,65295,235,21.65948101646,9.890286298845,-37.370806444445,2,1,18 +2025-03-11T12:42:21.668212,479392940,65295,235,21.92335282718,10.149522887085,-37.87593337481,2,1,18 +2025-03-11T12:42:21.683837,479392940,65295,235,22.19664863114,10.427260068555,-38.37652684412,2,1,18 +2025-03-11T12:42:21.699462,479392940,65295,235,22.47936842834,10.705013555955,-38.87713387544,2,1,18 +2025-03-11T12:42:21.715087,479392940,65295,235,22.73852824244,10.97348413488,-39.37304873867,2,1,18 +2025-03-11T12:42:21.730712,479392940,65295,235,23.01653604302,11.24660839749,-39.85976689979,2,1,18 +2025-03-11T12:42:21.746337,479392940,65295,235,23.27569585712,11.51045790459,-40.369526772215,2,1,18 +2025-03-11T12:42:21.761962,479392940,65295,235,23.54427966446,11.788186933095,-40.87935582665,2,1,18 +2025-03-11T12:42:21.777587,479392940,65295,235,23.82699946166,12.075182564145,-41.375378754905,2,1,18 +2025-03-11T12:42:21.793212,479392940,65295,235,24.095583269,12.339048377175,-41.852803907885,2,1,18 +2025-03-11T12:42:21.808837,479392940,65295,235,24.35003108648,12.598268659485,-42.33019017785,2,1,18 +2025-03-11T12:42:21.824462,479392940,65295,235,24.60919090058,12.85749709476,-42.812204411885,2,1,18 +2025-03-11T12:42:21.840087,479392940,65295,235,24.88719870116,13.13062135737,-43.289680206875,2,1,18 +2025-03-11T12:42:21.855712,479392940,65295,235,25.14635851526,13.389849792645,-43.77169444091,2,1,18 +2025-03-11T12:42:21.871337,479392940,65295,235,25.41023032598,13.658328524535,-44.249131352885,2,1,18 +2025-03-11T12:42:21.886962,479392940,65295,235,25.67881413332,13.931436481215,-44.74969950119,2,1,18 +2025-03-11T12:42:21.902587,479392940,65295,235,25.9568219339,14.186076456525,-45.23634350231,2,1,18 +2025-03-11T12:42:21.918212,479392940,65295,235,26.20655775476,14.45453072952,-45.71376007127,2,1,18 +2025-03-11T12:42:21.933837,479392940,65295,235,26.451581579,14.709113634075,-46.181871873095,2,1,18 +2025-03-11T12:42:21.949462,479392940,65295,235,26.71545338972,14.97297129414,-46.654669062005,2,1,18 +2025-03-11T12:42:21.965087,479392940,65295,235,26.98874919368,15.25070847561,-47.12291424986,2,1,18 +2025-03-11T12:42:21.980712,479392940,65295,235,27.24319701116,15.50992875792,-47.58643697063,2,1,18 +2025-03-11T12:42:21.996276,479392944,65291,236,27.49764482864,15.764527968405,-48.0499411514,2,1,18 +2025-03-11T12:42:22.011901,479392944,65291,236,27.75209264612,16.00988503524,-48.518029435235,2,1,18 +2025-03-11T12:42:22.027526,479392944,65291,236,28.0065404636,16.2598631739,-48.97689389294,2,1,18 +2025-03-11T12:42:22.043151,479392944,65291,236,28.26098828108,16.514462384385,-49.43115570758,2,1,18 +2025-03-11T12:42:22.058776,479392944,65291,236,28.52014809518,16.75520653236,-49.88998986629,2,1,18 +2025-03-11T12:42:22.074401,479392944,65291,236,28.7604599228,17.014402355775,-50.34887106098,2,1,18 +2025-03-11T12:42:22.090026,479392944,65291,236,29.01019574366,17.27361448512,-50.81700818381,2,1,18 +2025-03-11T12:42:22.105651,479392944,65291,236,29.25993156452,17.51896339899,-51.252741405185,2,1,18 +2025-03-11T12:42:22.121276,479392944,65291,236,29.51909137862,17.768949690615,-51.6977490947,2,1,18 +2025-03-11T12:42:22.136901,479392944,65291,236,29.76411520286,18.000427236045,-52.17038937959,2,1,18 +2025-03-11T12:42:22.152526,479392944,65291,236,29.99500303724,18.25036460988,-52.606114016945,2,1,18 +2025-03-11T12:42:22.168151,479392944,65291,236,30.24945085472,18.49110060489,-53.03721429626,2,1,18 +2025-03-11T12:42:22.183776,479392944,65291,236,30.47562669248,18.74102982576,-53.477553335675,2,1,18 +2025-03-11T12:42:22.199401,479392944,65291,236,30.70651452686,18.990967199595,-53.91327797303,2,1,18 +2025-03-11T12:42:22.215026,479392944,65291,236,30.95625034772,19.22245289799,-54.37206148973,2,1,18 +2025-03-11T12:42:22.230651,479392944,65291,236,31.19656217534,19.44930121863,-54.807706989095,2,1,18 +2025-03-11T12:42:22.246276,479392944,65291,236,31.43687400296,19.690012754745,-55.2249233762,2,1,18 +2025-03-11T12:42:22.261901,479392944,65291,236,31.67718583058,19.93072429086,-55.642139763305,2,1,18 +2025-03-11T12:42:22.277526,479392944,65291,236,31.92692165144,20.16683106108,-56.07783590468,2,1,18 +2025-03-11T12:42:22.293151,479392944,65291,236,32.1530974892,20.41676028195,-56.508932577965,2,1,18 +2025-03-11T12:42:22.308776,479392944,65291,236,32.39340931682,20.63436645894,-56.930677448135,2,1,18 +2025-03-11T12:42:22.324401,479392944,65291,236,32.61958515458,20.87505353616,-57.375600590615,2,1,18 +2025-03-11T12:42:22.340026,479392944,65291,236,32.85047298896,21.12961198182,-57.806722584905,2,1,18 +2025-03-11T12:42:22.355651,479392944,65291,236,33.07664882672,21.36105691539,-58.22850273206,2,1,18 +2025-03-11T12:42:22.371276,479392944,65291,236,33.28868867462,21.573993102765,-58.645567193135,2,1,18 +2025-03-11T12:42:22.386901,479392944,65291,236,33.51486451238,21.786953749035,-59.044167264965,2,1,18 +2025-03-11T12:42:22.402526,479392944,65291,236,33.75517634,22.013802069675,-59.44284329981,2,1,18 +2025-03-11T12:42:22.418151,479392944,65291,236,33.98606417438,22.231391940735,-59.832226326515,2,1,18 +2025-03-11T12:42:22.433776,479392944,65291,236,34.19810402228,22.44432812811,-60.272396702915,2,1,18 +2025-03-11T12:42:22.449401,479392944,65291,236,34.42427986004,22.661909846205,-60.689500047005,2,1,18 +2025-03-11T12:42:22.465026,479392944,65291,236,34.64103170456,22.89795954567,-61.097421622955,2,1,18 +2025-03-11T12:42:22.480651,479392944,65291,236,34.85307155246,23.120137876695,-61.5052807979,2,1,18 +2025-03-11T12:42:22.496276,479392944,65291,236,35.06039940374,23.34692912658,-61.88542463345,2,1,18 +2025-03-11T12:42:22.511901,479392944,65291,236,35.2865752415,23.55988977285,-62.27478233915,2,1,18 +2025-03-11T12:42:22.527526,479392944,65291,236,35.51746307588,23.772858572085,-62.65952564279,2,1,18 +2025-03-11T12:42:22.543151,479392944,65291,236,35.73892691702,23.98581106539,-63.03501301829,2,1,18 +2025-03-11T12:42:22.558776,479392944,65291,236,35.94154277168,24.20335201866,-63.43821890816,2,1,18 +2025-03-11T12:42:22.574401,479392944,65291,236,36.1582946162,24.420917430825,-63.82758159185,2,1,18 +2025-03-11T12:42:22.590026,479392944,65291,236,36.37504646072,24.61999855569,-64.193764200215,2,1,18 +2025-03-11T12:42:22.605651,479392944,65291,236,36.59179830524,24.819079680555,-64.564567991645,2,1,18 +2025-03-11T12:42:22.621276,479392944,65291,236,36.7944141599,25.031999562,-64.949270609255,2,1,18 +2025-03-11T12:42:22.636901,479392944,65291,236,36.99231801794,25.23566914683,-65.3154446336,2,1,18 +2025-03-11T12:42:22.652526,479392944,65291,236,37.1949338726,25.448589028275,-65.68166251895,2,1,18 +2025-03-11T12:42:22.668151,479392944,65291,236,37.40226172388,25.64765384721,-66.057073931435,2,1,18 +2025-03-11T12:42:22.683776,479392944,65291,236,37.60958957516,25.84209759432,-66.437087986985,2,1,18 +2025-03-11T12:42:22.699401,479392944,65291,236,37.8074934332,26.04576717915,-66.789398462135,2,1,18 +2025-03-11T12:42:22.715026,479392944,65291,236,37.995973298,26.235557242575,-67.14626093834,2,1,18 +2025-03-11T12:42:22.730651,479392944,65291,236,38.19858915266,26.425371764895,-67.507764940625,2,1,18 +2025-03-11T12:42:22.746276,479392944,65291,236,38.3964930107,26.619799206075,-67.869280701905,2,1,18 +2025-03-11T12:42:22.761901,479392944,65291,236,38.58026087888,26.828065403835,-68.216968190975,2,1,18 +2025-03-11T12:42:22.777526,479392944,65291,236,38.76402874706,27.027089457945,-68.546133867785,2,1,18 +2025-03-11T12:42:22.793151,479392944,65291,236,38.94308461862,27.22610535909,-68.898398678915,2,1,18 +2025-03-11T12:42:22.808776,479392944,65291,236,39.1268524868,27.4066451259,-69.25059611105,2,1,18 +2025-03-11T12:42:22.824401,479392944,65291,236,39.32004434822,27.58720119864,-69.602807105195,2,1,18 +2025-03-11T12:42:22.840026,479392944,65291,236,39.50852421302,27.767749118415,-69.9596325014,2,1,18 +2025-03-11T12:42:22.855651,479392944,65291,236,39.68286808796,27.957514722945,-70.27026280394,2,1,18 +2025-03-11T12:42:22.871276,479392944,65291,236,39.87605994938,28.156555082985,-70.594820859695,2,1,18 +2025-03-11T12:42:22.886901,479392944,65291,236,40.0456918277,28.341691462725,-70.937774122685,2,1,18 +2025-03-11T12:42:22.902526,479392944,65291,236,40.22474769926,28.526844148395,-71.27611976462,2,1,18 +2025-03-11T12:42:22.918151,479392944,65291,236,40.3990915742,28.688883321975,-71.60512355942,2,1,18 +2025-03-11T12:42:22.933776,479392944,65291,236,40.56872345252,28.864777558065,-71.924933827085,2,1,18 +2025-03-11T12:42:22.949401,479392944,65291,236,40.74306732746,29.036058875295,-72.22162642043,2,1,18 +2025-03-11T12:42:22.965026,479392944,65291,236,40.91269920578,29.19808989591,-72.53675988503,2,1,18 +2025-03-11T12:42:22.980651,479392944,65291,236,41.09646707396,29.38787180637,-72.83816138345,2,1,18 +2025-03-11T12:42:22.996276,479392944,65291,236,41.28494693876,29.559177582495,-73.139495502875,2,1,18 +2025-03-11T12:42:23.011901,479392944,65291,236,41.46400281032,29.72122490904,-73.445400163355,2,1,18 +2025-03-11T12:42:23.027526,479392944,65291,236,41.61949869878,29.897094686235,-73.746705355745,2,1,18 +2025-03-11T12:42:23.043151,479392944,65291,236,41.7891305771,30.05912570685,-74.04797527115,2,1,18 +2025-03-11T12:42:23.058776,479392944,65291,236,41.94462646556,30.207269053095,-74.34916922354,2,1,18 +2025-03-11T12:42:23.074401,479392944,65291,236,42.10483435064,30.35079948048,-74.63648786774,2,1,18 +2025-03-11T12:42:23.090026,479392944,65291,236,42.27917822558,30.517459725885,-74.923919554955,2,1,18 +2025-03-11T12:42:23.105651,479392944,65291,236,42.42996211742,30.67021599099,-75.21588290021,2,1,18 +2025-03-11T12:42:23.121276,479392944,65291,236,42.58545800588,30.83222255271,-75.512511289535,2,1,18 +2025-03-11T12:42:23.136901,479392944,65291,236,42.74566589096,31.003479411045,-75.81380472293,2,1,18 +2025-03-11T12:42:23.152526,479392944,65291,236,42.90587377604,31.14700983843,-76.10112336713,2,1,18 +2025-03-11T12:42:23.168151,479392944,65291,236,43.04723367464,31.299749797605,-76.365346051985,2,1,18 +2025-03-11T12:42:23.183776,479392944,65291,236,43.20744155972,31.45252236864,-76.62035349473,2,1,18 +2025-03-11T12:42:23.199401,479392944,65291,236,43.34880145832,31.605262327815,-76.884576179585,2,1,18 +2025-03-11T12:42:23.215026,479392944,65291,236,43.49487335354,31.76263151178,-77.15344536851,2,1,18 +2025-03-11T12:42:23.230651,479392944,65291,236,43.64094524876,31.90613748027,-77.413016571305,2,1,18 +2025-03-11T12:42:23.246276,479392944,65291,236,43.78701714398,32.06812773606,-77.69114666636,2,1,18 +2025-03-11T12:42:23.261901,479392944,65291,236,43.91895304934,32.211609245655,-77.955318709205,2,1,18 +2025-03-11T12:42:23.277526,479392944,65291,236,44.06031294794,32.34586491753,-78.205603684865,2,1,18 +2025-03-11T12:42:23.293151,479392944,65291,236,44.1922488533,32.47548321165,-78.45123537545,2,1,18 +2025-03-11T12:42:23.308776,479392944,65291,236,44.32889675528,32.595867515085,-78.692215583975,2,1,18 +2025-03-11T12:42:23.324401,479392944,65291,236,44.47025665388,32.734744258785,-78.93789791657,2,1,18 +2025-03-11T12:42:23.340026,479392944,65291,236,44.59748056262,32.87359654359,-79.188181089215,2,1,18 +2025-03-11T12:42:23.355651,479392944,65291,236,44.72470447136,32.98934346927,-79.452235111055,2,1,18 +2025-03-11T12:42:23.371276,479392944,65291,236,44.84721638348,33.11894545746,-79.69785323963,2,1,18 +2025-03-11T12:42:23.386901,479392944,65291,236,44.97444029222,33.25317667044,-79.91576959082,2,1,18 +2025-03-11T12:42:23.402526,479392944,65291,236,45.1110881942,33.36893990205,-80.138246527085,2,1,18 +2025-03-11T12:42:23.418151,479392944,65291,236,45.2524480928,33.493953430275,-80.351524958225,2,1,18 +2025-03-11T12:42:23.433776,479392944,65291,236,45.37496000492,33.632797562115,-80.574074251475,2,1,18 +2025-03-11T12:42:23.449401,479392944,65291,236,45.47391193394,33.76235878548,-80.78731019357,2,1,18 +2025-03-11T12:42:23.465026,479392944,65291,236,45.59642384606,33.859613270895,-80.995829077625,2,1,18 +2025-03-11T12:42:23.480651,479392944,65291,236,45.7236477548,33.984602340225,-81.19984479962,2,1,18 +2025-03-11T12:42:23.496276,479392944,65291,236,45.8414476703,34.100332959975,-81.413052245735,2,1,18 +2025-03-11T12:42:23.511901,479392944,65291,236,45.94982359256,34.206805130145,-81.621587866775,2,1,18 +2025-03-11T12:42:23.527526,479392944,65291,236,46.06291151144,34.31328545328,-81.84861500108,2,1,18 +2025-03-11T12:42:23.543151,479392944,65291,236,46.18542342356,34.43364529782,-82.066468951265,2,1,18 +2025-03-11T12:42:23.558776,479392944,65291,236,46.2890873492,34.549351458675,-82.261171322105,2,1,18 +2025-03-11T12:42:23.574401,479392944,65291,236,46.37861528498,34.65116994516,-82.432691814605,2,1,18 +2025-03-11T12:42:23.590026,479392944,65291,236,46.48227921062,34.739149675065,-82.618040579315,2,1,18 +2025-03-11T12:42:23.605651,479392944,65291,236,46.5953671295,34.8271457109,-82.79878172297,2,1,18 +2025-03-11T12:42:23.621276,479392944,65291,236,46.69431905852,34.94284371879,-82.97961376361,2,1,18 +2025-03-11T12:42:23.636901,479392944,65291,236,46.77913499768,35.04465405231,-83.169612207365,2,1,18 +2025-03-11T12:42:23.652526,479392944,65291,236,46.86866293346,35.137230395145,-83.34571680293,2,1,18 +2025-03-11T12:42:23.668151,479392944,65291,236,46.97703885572,35.234460421665,-83.512624696385,2,1,18 +2025-03-11T12:42:23.683776,479392944,65291,236,47.07599078474,35.322431998605,-83.67948194783,2,1,18 +2025-03-11T12:42:23.699401,479392944,65291,236,47.16551872052,35.410387269615,-83.837083271135,2,1,18 +2025-03-11T12:42:23.715026,479392944,65291,236,47.2550466563,35.50296361245,-83.99470313444,2,1,18 +2025-03-11T12:42:23.730651,479392944,65291,236,47.3492865887,35.5863059646,-84.16153506488,2,1,18 +2025-03-11T12:42:23.746276,479392944,65291,236,47.43410252786,35.66963201082,-84.314489884115,2,1,18 +2025-03-11T12:42:23.761901,479392944,65291,236,47.50007048054,35.766788660655,-84.453609650135,2,1,18 +2025-03-11T12:42:23.777526,479392944,65291,236,47.57546242646,35.83623518547,-84.592631738165,2,1,18 +2025-03-11T12:42:23.793151,479392944,65291,236,47.66499036224,35.910327241005,-84.754798624535,2,1,18 +2025-03-11T12:42:23.808776,479392944,65291,236,47.74509430478,35.989024062435,-84.91234930583,2,1,18 +2025-03-11T12:42:23.824401,479392944,65291,236,47.82519824732,36.06309981204,-85.051396714865,2,1,18 +2025-03-11T12:42:23.840026,479392944,65291,236,47.88645420338,36.13252187796,-85.19039845988,2,1,18 +2025-03-11T12:42:23.855651,479392944,65291,236,47.9618461493,36.19734733095,-85.31091727565,2,1,18 +2025-03-11T12:42:23.871276,479392944,65291,236,48.03723809522,36.27141492759,-85.426851988355,2,1,18 +2025-03-11T12:42:23.886901,479392944,65291,236,48.09849405128,36.345458065335,-85.55662990724,2,1,18 +2025-03-11T12:42:23.902526,479392944,65291,236,48.1738859972,36.410283518325,-85.681769906075,2,1,18 +2025-03-11T12:42:23.918151,479392944,65291,236,48.2445659465,36.470479746525,-85.779157485515,2,1,18 +2025-03-11T12:42:23.933776,479392944,65291,236,48.29639790932,36.530643362865,-85.895002673195,2,1,18 +2025-03-11T12:42:23.949401,479392944,65291,236,48.35294186876,36.59081513217,-85.99236990962,2,1,18 +2025-03-11T12:42:23.965026,479392944,65291,236,48.40477383158,36.646357676685,-86.1081965573,2,1,18 +2025-03-11T12:42:23.980651,479392944,65291,236,48.46131779102,36.68804515869,-86.223974365985,2,1,18 +2025-03-11T12:42:23.996276,479392944,65291,236,48.51314975384,36.752829846855,-86.31673217834,2,1,18 +2025-03-11T12:42:24.011901,479392944,65291,236,48.5744057099,36.813009769125,-86.409485012705,2,1,18 +2025-03-11T12:42:24.027526,479392944,65291,236,48.6215256761,36.859302017025,-86.492919517925,2,1,18 +2025-03-11T12:42:24.043151,479392944,65291,236,48.65922164906,36.90095688717,-86.57170073807,2,1,18 +2025-03-11T12:42:24.058776,479392944,65291,236,48.71105361188,36.94263621621,-86.65974466736,2,1,18 +2025-03-11T12:42:24.074401,479392944,65291,236,48.75346158146,36.99354138297,-86.7662968469,2,1,18 +2025-03-11T12:42:24.090026,479392944,65291,236,48.80058154766,37.04907577452,-86.84052606599,2,1,18 +2025-03-11T12:42:24.105651,479392944,65291,236,48.84770151386,37.090746950595,-86.92394203121,2,1,18 +2025-03-11T12:42:24.121276,479392944,65291,236,48.89482148006,37.127797054845,-86.97961235804,2,1,18 +2025-03-11T12:42:24.136901,479392944,65291,236,48.93251745302,37.15096763769,-87.05369823512,2,1,18 +2025-03-11T12:42:24.152526,479392944,65291,236,48.96078943274,37.18798513008,-87.123204987125,2,1,18 +2025-03-11T12:42:24.168151,479392944,65291,236,48.97963741922,37.21574417289,-87.18341873099,2,1,18 +2025-03-11T12:42:24.183776,479392944,65291,236,49.01733339218,37.24353582756,-87.23903841581,2,1,18 +2025-03-11T12:42:24.199401,479392944,65291,236,49.05502936514,37.27132748223,-87.26693100224,2,1,18 +2025-03-11T12:42:24.215026,479392944,65291,236,49.07858934824,37.30371574983,-87.294821785655,2,1,18 +2025-03-11T12:42:24.230651,479392944,65291,236,49.09743733472,37.33147479264,-87.35503552952,2,1,18 +2025-03-11T12:42:24.246276,479392944,65291,236,49.13042131106,37.36387936617,-87.40604579027,2,1,18 +2025-03-11T12:42:24.261901,479392944,65291,236,49.15869329078,37.40089685856,-87.43396189469,2,1,18 +2025-03-11T12:42:24.277526,479392944,65291,236,49.17754127726,37.414792685895,-87.4617717371,2,1,18 +2025-03-11T12:42:24.293151,479392944,65291,236,49.19638926374,37.42868851323,-87.48033921338,2,1,18 +2025-03-11T12:42:24.308776,479392944,65291,236,49.21523725022,37.44720541239,-87.50816759579,2,1,18 +2025-03-11T12:42:24.324401,479392944,65291,236,49.22466124346,37.470327077445,-87.52675859006,2,1,18 +2025-03-11T12:42:24.340026,479392944,65291,236,49.23879723332,37.47959367999,-87.545300745335,2,1,18 +2025-03-11T12:42:24.355651,479392944,65291,236,49.24350922994,37.47498076113,-87.57301608473,2,1,18 +2025-03-11T12:42:24.371276,479392944,65291,236,49.25293322318,37.48423921071,-87.586930275935,2,1,18 +2025-03-11T12:42:24.386901,479392944,65291,236,49.2576452198,37.484247363675,-87.6054217892,2,1,18 +2025-03-11T12:42:24.402526,479392944,65291,236,49.26235721642,37.48425551664,-87.60080738714,2,1,18 +2025-03-11T12:42:24.418151,479392944,65291,236,49.2576452198,37.484247363675,-87.59617942307,2,1,18 +2025-03-11T12:42:24.433776,479392944,65291,236,49.25293322318,37.46575492341,-87.596098482065,2,1,18 +2025-03-11T12:42:24.449401,479392944,65291,236,49.23879723332,37.465730464515,-87.60532050518,2,1,18 +2025-03-11T12:42:24.465026,479392944,65291,236,49.22466124346,37.44722171832,-87.595983636035,2,1,18 +2025-03-11T12:42:24.480651,479392944,65291,236,49.2105252536,37.437955115775,-87.591305029955,2,1,18 +2025-03-11T12:42:24.496276,479392944,65291,236,49.20581325698,37.442568034635,-87.57283205669,2,1,18 +2025-03-11T12:42:24.511901,479392944,65291,236,49.20581325698,37.43794696281,-87.549707601365,2,1,18 +2025-03-11T12:42:24.527526,479392944,65291,236,49.20581325698,37.424083747335,-87.521924882975,2,1,18 +2025-03-11T12:42:24.543151,479392944,65291,236,49.20581325698,37.41022053186,-87.50800571378,2,1,18 +2025-03-11T12:42:24.558776,479392944,65291,236,49.19167726712,37.39633285749,-87.470960286245,2,1,18 +2025-03-11T12:42:24.574401,479392944,65291,236,49.15869329078,37.377791499435,-87.43386919469,2,1,18 +2025-03-11T12:42:24.590026,479392944,65291,236,49.1398453043,37.368516743925,-87.39683552615,2,1,18 +2025-03-11T12:42:24.605651,479392944,65291,236,49.1162853212,37.3315074045,-87.341199104345,2,1,18 +2025-03-11T12:42:24.621276,479392944,65291,236,49.10214933134,37.29913544283,-87.29483715068,2,1,18 +2025-03-11T12:42:24.636901,479392944,65291,236,49.05974136176,37.289819922495,-87.248527210985,2,1,18 +2025-03-11T12:42:24.652526,479392944,65291,236,49.03146938204,37.25742350193,-87.202144914305,2,1,18 +2025-03-11T12:42:24.668151,479392944,65291,236,49.01262139556,37.215801243645,-87.155739099635,2,1,18 +2025-03-11T12:42:24.683776,479392944,65291,236,48.9984854057,37.183429281975,-87.104755962905,2,1,18 +2025-03-11T12:42:24.699401,479392944,65291,236,48.9749254226,37.160283158025,-87.0491751611,2,1,18 +2025-03-11T12:42:24.715026,479392944,65291,236,48.93251745302,37.118620134915,-86.97962952608,2,1,18 +2025-03-11T12:42:24.730651,479392944,65291,236,48.89010948344,37.07233603998,-86.91006535106,2,1,18 +2025-03-11T12:42:24.746276,479392944,65291,236,48.833565524,37.021406414325,-86.831219926895,2,1,18 +2025-03-11T12:42:24.761901,479392944,65291,236,48.7864455578,36.984356310075,-86.76168605087,2,1,18 +2025-03-11T12:42:24.777526,479392944,65291,236,48.75817357808,36.95195988951,-86.682955472735,2,1,18 +2025-03-11T12:42:24.793151,479392944,65291,236,48.7157656085,36.90105472275,-86.59950920852,2,1,18 +2025-03-11T12:42:24.808776,479392944,65291,236,48.65922164906,36.850125097095,-86.511421418225,2,1,18 +2025-03-11T12:42:24.824401,479392944,65291,236,48.60267768962,36.80843761509,-86.427991890995,2,1,18 +2025-03-11T12:42:24.840026,479392944,65291,236,48.54142173356,36.74825769282,-86.330617873565,2,1,18 +2025-03-11T12:42:24.855651,479392944,65291,236,48.48487777412,36.70194913899,-86.22406389101,2,1,18 +2025-03-11T12:42:24.871276,479392944,65291,236,48.43775780792,36.651035819265,-86.12212611353,2,1,18 +2025-03-11T12:42:24.886901,479392944,65291,236,48.40006183496,36.595517733645,-86.006319808865,2,1,18 +2025-03-11T12:42:24.902526,479392944,65291,236,48.3388058789,36.544579955025,-85.89511932224,2,1,18 +2025-03-11T12:42:24.918151,479392944,65291,236,48.28226191946,36.470544970245,-85.760727001295,2,1,18 +2025-03-11T12:42:24.933776,479392944,65291,236,48.22571796002,36.405752129115,-85.649477675675,2,1,18 +2025-03-11T12:42:24.949401,479392944,65291,236,48.15503801072,36.345555900915,-85.533605363975,2,1,18 +2025-03-11T12:42:24.965026,479392944,65291,236,48.08435806142,36.28073860089,-85.41309332921,2,1,18 +2025-03-11T12:42:24.980651,479392944,65291,236,48.02781410198,36.220566831585,-85.278756628265,2,1,18 +2025-03-11T12:42:24.996276,479392944,65291,236,47.94299816282,36.127998641715,-85.148870644355,2,1,18 +2025-03-11T12:42:25.011901,479392944,65291,236,47.85347022704,36.040043370705,-85.01899641944,2,1,18 +2025-03-11T12:42:25.027526,479392944,65291,236,47.76394229126,35.94746702787,-84.90296720372,2,1,18 +2025-03-11T12:42:25.043151,479392944,65291,236,47.68855034534,35.887262646705,-84.768603378755,2,1,18 +2025-03-11T12:42:25.058776,479392944,65291,236,47.61787039604,35.827066418505,-84.61114041947,2,1,18 +2025-03-11T12:42:25.074401,479392944,65291,236,47.53305445688,35.734498228635,-84.4627697033,2,1,18 +2025-03-11T12:42:25.090026,479392944,65291,236,47.45295051434,35.637317119905,-84.28203894668,2,1,18 +2025-03-11T12:42:25.105651,479392944,65291,236,47.3728465718,35.55399922665,-84.124469725385,2,1,18 +2025-03-11T12:42:25.121276,479392944,65291,236,47.2786066394,35.466035802675,-83.97148280414,2,1,18 +2025-03-11T12:42:25.136901,479392944,65291,236,47.19850269686,35.378096837595,-83.83700095817,2,1,18 +2025-03-11T12:42:25.152526,479392944,65291,236,47.12311075094,35.276302810005,-83.683985540945,2,1,18 +2025-03-11T12:42:25.168151,479392944,65291,236,47.02887081854,35.18833938603,-83.51251388744,2,1,18 +2025-03-11T12:42:25.183776,479392944,65291,236,46.93463088614,35.10499703388,-83.345681957,2,1,18 +2025-03-11T12:42:25.199401,479392944,65291,236,46.8545269436,35.00781592515,-83.169572383445,2,1,18 +2025-03-11T12:42:25.215026,479392944,65291,236,46.75557501458,34.905981132735,-82.99341714587,2,1,18 +2025-03-11T12:42:25.230651,479392944,65291,236,46.64719909232,34.808751106215,-82.817266886285,2,1,18 +2025-03-11T12:42:25.246276,479392944,65291,236,46.53882317006,34.70690000787,-82.617992171375,2,1,18 +2025-03-11T12:42:25.261901,479392944,65291,236,46.44458323766,34.609694440245,-82.432619888675,2,1,18 +2025-03-11T12:42:25.277526,479392944,65291,236,46.34091931202,34.507851494865,-82.2425943209,2,1,18 +2025-03-11T12:42:25.293151,479392944,65291,236,46.23725538638,34.396766405835,-82.043289306995,2,1,18 +2025-03-11T12:42:25.308776,479392944,65291,236,46.13830345736,34.28568946977,-81.834748707965,2,1,18 +2025-03-11T12:42:25.324401,479392944,65291,236,46.03463953172,34.179225452565,-81.6169775018,2,1,18 +2025-03-11T12:42:25.340026,479392944,65291,236,45.9121276196,34.0542445362,-81.39448382855,2,1,18 +2025-03-11T12:42:25.355651,479392944,65291,236,45.7943277041,33.933892844625,-81.181257842435,2,1,18 +2025-03-11T12:42:25.371276,479392944,65291,236,45.68123978522,33.82741252149,-80.977336623455,2,1,18 +2025-03-11T12:42:25.386901,479392944,65291,236,45.56815186634,33.711690054705,-80.77799950754,2,1,18 +2025-03-11T12:42:25.402526,479392944,65291,236,45.43621596098,33.591313904235,-80.56475317841,2,1,18 +2025-03-11T12:42:25.418151,479392944,65291,236,45.30899205224,33.47094590673,-80.32840771496,2,1,18 +2025-03-11T12:42:25.433776,479392944,65291,236,45.20061612998,33.33674730561,-80.11051848779,2,1,18 +2025-03-11T12:42:25.449401,479392944,65291,236,45.063968228,33.207120858525,-79.878743565395,2,1,18 +2025-03-11T12:42:25.465026,479392944,65291,236,44.94145631588,33.086761013985,-79.656268432145,2,1,18 +2025-03-11T12:42:25.480651,479392944,65291,236,44.81894440376,32.96178009762,-79.424532392765,2,1,18 +2025-03-11T12:42:25.496276,479392944,65291,236,44.70114448826,32.832186262395,-79.20202696052,2,1,18 +2025-03-11T12:42:25.511901,479392944,65291,236,44.56449658628,32.697938743485,-78.96561231506,2,1,18 +2025-03-11T12:42:25.527526,479392944,65291,236,44.41842469106,32.56829599047,-78.715339098395,2,1,18 +2025-03-11T12:42:25.543151,479392944,65291,236,44.27706479246,32.43866139042,-78.465072662735,2,1,18 +2025-03-11T12:42:25.558776,479392944,65291,236,44.14041689048,32.299792799685,-78.22401829421,2,1,18 +2025-03-11T12:42:25.574401,479392944,65291,236,44.01790497836,32.151706524195,-77.950598907245,2,1,18 +2025-03-11T12:42:25.590026,479392944,65291,236,43.88125707638,31.998974717985,-77.677140637265,2,1,18 +2025-03-11T12:42:25.605651,479392944,65291,236,43.71633719468,31.86929935311,-77.431461479645,2,1,18 +2025-03-11T12:42:25.621276,479392944,65291,236,43.57026529946,31.72579338462,-77.17189027685,2,1,18 +2025-03-11T12:42:25.636901,479392944,65291,236,43.43361739748,31.57306157841,-76.912295556065,2,1,18 +2025-03-11T12:42:25.652526,479392944,65291,236,43.28283350564,31.42492638513,-76.643456666135,2,1,18 +2025-03-11T12:42:25.668151,479392944,65291,236,43.14147360704,31.26756535413,-76.356109525955,2,1,18 +2025-03-11T12:42:25.683776,479392944,65291,236,42.98597771858,31.11480093606,-76.06876058276,2,1,18 +2025-03-11T12:42:25.699401,479392944,65291,236,42.83048183012,30.966657589815,-75.790672545695,2,1,18 +2025-03-11T12:42:25.715026,479392944,65291,236,42.67498594166,30.813893171745,-75.517187151695,2,1,18 +2025-03-11T12:42:25.730651,479392944,65291,236,42.5194900532,30.65650768185,-75.2298196685,2,1,18 +2025-03-11T12:42:25.746276,479392944,65291,236,42.36870616136,30.49913034492,-74.93321660018,2,1,18 +2025-03-11T12:42:25.761901,479392944,65291,236,42.20849827628,30.346357773885,-74.659724425175,2,1,18 +2025-03-11T12:42:25.777526,479392944,65291,236,42.05771438444,30.198222580605,-74.36777961992,2,1,18 +2025-03-11T12:42:25.793151,479392944,65291,236,41.91635448584,30.02699833413,-74.066513310545,2,1,18 +2025-03-11T12:42:25.808776,479392944,65291,236,41.74672260752,29.86034624169,-73.75598248901,2,1,18 +2025-03-11T12:42:25.824401,479392944,65291,236,41.56766673596,29.698298915145,-73.426971913205,2,1,18 +2025-03-11T12:42:25.840026,479392944,65291,236,41.39332286102,29.517775454265,-73.13024223986,2,1,18 +2025-03-11T12:42:25.855651,479392944,65291,236,41.21897898608,29.33263092156,-72.81963047732,2,1,18 +2025-03-11T12:42:25.871276,479392944,65291,236,41.02578712466,29.165938064295,-72.513686933825,2,1,18 +2025-03-11T12:42:25.886901,479392944,65291,236,40.86086724296,28.99005198117,-72.19850463023,2,1,18 +2025-03-11T12:42:25.902526,479392944,65291,236,40.69594736126,28.81878696987,-71.874098500505,2,1,18 +2025-03-11T12:42:25.918151,479392944,65291,236,40.53102747956,28.633658743095,-71.54963675078,2,1,18 +2025-03-11T12:42:25.933776,479392944,65291,236,40.351971608,28.4623692729,-71.23445264417,2,1,18 +2025-03-11T12:42:25.949401,479392944,65291,236,40.17762773306,28.29108795567,-70.910032952435,2,1,18 +2025-03-11T12:42:25.965026,479392944,65291,236,39.98914786826,28.10591896407,-70.58091611462,2,1,18 +2025-03-11T12:42:25.980651,479392944,65291,236,39.80066800346,27.91150782882,-70.242519830675,2,1,18 +2025-03-11T12:42:25.996200,479392948,65286,237,39.6216121319,27.721734071325,-69.908776831805,2,1,18 +2025-03-11T12:42:26.011825,479392948,65286,237,39.44255626034,27.54120245748,-69.565828546805,2,1,18 +2025-03-11T12:42:26.027450,479392948,65286,237,39.25878839216,27.356041618845,-69.227476123865,2,1,18 +2025-03-11T12:42:26.043075,479392948,65286,237,39.06559653074,27.17086447428,-68.879867772785,2,1,18 +2025-03-11T12:42:26.058700,479392948,65286,237,38.8676926727,26.9764370331,-68.527594377635,2,1,18 +2025-03-11T12:42:26.074325,479392948,65286,237,38.66978881466,26.78200959192,-68.17994216555,2,1,18 +2025-03-11T12:42:26.089950,479392948,65286,237,38.46246096338,26.582944772985,-67.832257851455,2,1,18 +2025-03-11T12:42:26.105575,479392948,65286,237,38.27398109858,26.39315470956,-67.470774192185,2,1,18 +2025-03-11T12:42:26.121200,479392948,65286,237,38.08550123378,26.19874357431,-67.109271992915,2,1,18 +2025-03-11T12:42:26.136825,479392948,65286,237,37.89230937236,26.004324286095,-66.75700537877,2,1,18 +2025-03-11T12:42:26.152450,479392948,65286,237,37.7132535008,25.809929456775,-66.400137924575,2,1,18 +2025-03-11T12:42:26.168075,479392948,65286,237,37.524773636,25.597034034225,-66.04318274837,2,1,18 +2025-03-11T12:42:26.183700,479392948,65286,237,37.3127337881,25.388718918675,-65.681591024075,2,1,18 +2025-03-11T12:42:26.199325,479392948,65286,237,37.09126994696,25.189629640845,-65.30153808551,2,1,18 +2025-03-11T12:42:26.214950,479392948,65286,237,36.87923009906,24.981314525295,-64.92608281202,2,1,18 +2025-03-11T12:42:26.230575,479392948,65286,237,36.68603823764,24.782274165255,-64.54144937642,2,1,18 +2025-03-11T12:42:26.246200,479392948,65286,237,36.49284637622,24.57861273339,-64.142933851625,2,1,18 +2025-03-11T12:42:26.261825,479392948,65286,237,36.28080652832,24.38878190514,-63.75368918894,2,1,18 +2025-03-11T12:42:26.277450,479392948,65286,237,36.07347867704,24.171232798905,-63.378203616455,2,1,18 +2025-03-11T12:42:26.293075,479392948,65286,237,35.8520148359,23.953659233775,-63.00731888402,2,1,18 +2025-03-11T12:42:26.308700,479392948,65286,237,35.63526299138,23.73609382161,-62.6087138342,2,1,18 +2025-03-11T12:42:26.324325,479392948,65286,237,35.42322314348,23.50929441876,-62.210078485385,2,1,18 +2025-03-11T12:42:26.339950,479392948,65286,237,35.21118329558,23.28249501591,-61.8206855027,2,1,18 +2025-03-11T12:42:26.355575,479392948,65286,237,35.0038554443,23.055703766025,-61.435920484085,2,1,18 +2025-03-11T12:42:26.371200,479392948,65286,237,34.78239160316,22.856614488195,-61.03738281326,2,1,18 +2025-03-11T12:42:26.386825,479392948,65286,237,34.5562157654,22.6390327701,-60.615658286105,2,1,18 +2025-03-11T12:42:26.402450,479392948,65286,237,34.34888791412,22.40762044839,-60.198526446035,2,1,18 +2025-03-11T12:42:26.418075,479392948,65286,237,34.12742407298,22.194667955085,-59.786069606015,2,1,18 +2025-03-11T12:42:26.433700,479392948,65286,237,33.8965362386,21.9724570122,-59.38742567318,2,1,18 +2025-03-11T12:42:26.449325,479392948,65286,237,33.6609364076,21.745616844525,-58.984135236275,2,1,18 +2025-03-11T12:42:26.464950,479392948,65286,237,33.43476056984,21.532656198255,-58.58091398138,2,1,18 +2025-03-11T12:42:26.480575,479392948,65286,237,33.21800872532,21.301227570615,-58.186874494625,2,1,18 +2025-03-11T12:42:26.496200,479392948,65286,237,32.98712089094,21.055911268605,-57.765031946465,2,1,18 +2025-03-11T12:42:26.511825,479392948,65286,237,32.75623305656,20.82445818207,-57.334002652175,2,1,18 +2025-03-11T12:42:26.527450,479392948,65286,237,32.52534522218,20.60686831101,-56.89840779482,2,1,18 +2025-03-11T12:42:26.543075,479392948,65286,237,32.30388138104,20.37081045858,-56.471994705605,2,1,18 +2025-03-11T12:42:26.558700,479392948,65286,237,32.06356955342,20.13471999429,-56.040933309305,2,1,18 +2025-03-11T12:42:26.574325,479392948,65286,237,31.83268171904,19.903266907755,-55.609904015015,2,1,18 +2025-03-11T12:42:26.589950,479392948,65286,237,31.59708188804,19.66718459643,-55.18809176585,2,1,18 +2025-03-11T12:42:26.605575,479392948,65286,237,31.35677006042,19.417230916665,-54.76621711568,2,1,18 +2025-03-11T12:42:26.621200,479392948,65286,237,31.10703423956,19.181124146445,-54.321278608175,2,1,18 +2025-03-11T12:42:26.636825,479392948,65286,237,30.8572984187,18.935775232575,-53.87630302067,2,1,18 +2025-03-11T12:42:26.652450,479392948,65286,237,30.61227459446,18.69043447167,-53.435955397235,2,1,18 +2025-03-11T12:42:26.668075,479392948,65286,237,30.37196276684,18.44510186373,-52.995614554805,2,1,18 +2025-03-11T12:42:26.683700,479392948,65286,237,30.14578692908,18.199793714685,-52.55529405539,2,1,18 +2025-03-11T12:42:26.699325,479392948,65286,237,29.90547510146,17.96832432222,-52.11500883296,2,1,18 +2025-03-11T12:42:26.714950,479392948,65286,237,29.6557392806,17.732217552,-51.660827959325,2,1,18 +2025-03-11T12:42:26.730575,479392948,65286,237,29.42485144622,17.473038034515,-51.201960326645,2,1,18 +2025-03-11T12:42:26.746200,479392948,65286,237,29.1845396186,17.2323264984,-50.780122756475,2,1,18 +2025-03-11T12:42:26.761825,479392948,65286,237,28.9253798045,16.982340206775,-50.330493883895,2,1,18 +2025-03-11T12:42:26.777450,479392948,65286,237,28.67564398364,16.718507005605,-49.862338221065,2,1,18 +2025-03-11T12:42:26.793075,479392948,65286,237,28.41648416954,16.463899642155,-49.38034252703,2,1,18 +2025-03-11T12:42:26.808700,479392948,65286,237,28.1714603453,16.20007459395,-48.89833009601,2,1,18 +2025-03-11T12:42:26.824325,479392948,65286,237,27.9123005312,15.9454672305,-48.425576768105,2,1,18 +2025-03-11T12:42:26.839950,479392948,65286,237,27.66256471034,15.69087617298,-47.97132173447,2,1,18 +2025-03-11T12:42:26.855575,479392948,65286,237,27.40340489624,15.43626880953,-47.51243195576,2,1,18 +2025-03-11T12:42:26.871200,479392948,65286,237,27.13010909228,15.200121274485,-47.03973244484,2,1,18 +2025-03-11T12:42:26.886825,479392948,65286,237,26.87094927818,14.936271767385,-46.58080558613,2,1,18 +2025-03-11T12:42:26.902450,479392948,65286,237,26.6165014607,14.667809341425,-46.10800341923,2,1,18 +2025-03-11T12:42:26.918075,479392948,65286,237,26.36676563984,14.40859721208,-45.64910866253,2,1,18 +2025-03-11T12:42:26.933700,479392948,65286,237,26.10289382912,14.14011848019,-45.18553529975,2,1,18 +2025-03-11T12:42:26.949325,479392948,65286,237,25.8390220184,13.8716397483,-44.717340753905,2,1,18 +2025-03-11T12:42:26.964950,479392948,65286,237,25.58457420092,13.61241946599,-44.226090934745,2,1,18 +2025-03-11T12:42:26.980575,479392948,65286,237,25.30656640034,13.33929520338,-43.73475159056,2,1,18 +2025-03-11T12:42:26.996200,479392948,65286,237,25.04269458962,13.07081647149,-43.266557044715,2,1,18 +2025-03-11T12:42:27.011825,479392948,65286,237,24.78824677214,12.81159618918,-42.77992840862,2,1,18 +2025-03-11T12:42:27.027450,479392948,65286,237,24.52908695804,12.552367753905,-42.260944710065,2,1,18 +2025-03-11T12:42:27.043075,479392948,65286,237,24.26992714394,12.288518246805,-41.76042720377,2,1,18 +2025-03-11T12:42:27.058700,479392948,65286,237,24.0013433366,12.00154707465,-41.28290935079,2,1,18 +2025-03-11T12:42:27.074325,479392948,65286,237,23.73275952926,11.733060189795,-40.79622329168,2,1,18 +2025-03-11T12:42:27.089950,479392948,65286,237,23.4594637253,11.4691862238,-40.300306625435,2,1,18 +2025-03-11T12:42:27.105575,479392948,65286,237,23.19087991796,11.20532041077,-39.79977555713,2,1,18 +2025-03-11T12:42:27.121200,479392948,65286,237,22.92229611062,10.93221245409,-39.289965042695,2,1,18 +2025-03-11T12:42:27.136825,479392948,65286,237,22.64900030666,10.64523312897,-38.807819225645,2,1,18 +2025-03-11T12:42:27.152450,479392948,65286,237,22.38041649932,10.37212517229,-38.321114626535,2,1,18 +2025-03-11T12:42:27.168075,479392948,65286,237,22.09769670212,10.108234900365,-37.83442676441,2,1,18 +2025-03-11T12:42:27.183700,479392948,65286,237,21.81497690492,9.839723556615,-37.338477996155,2,1,18 +2025-03-11T12:42:27.199325,479392948,65286,237,21.53225710772,9.561970069215,-36.83324978177,2,1,18 +2025-03-11T12:42:27.214950,479392948,65286,237,21.25896130376,9.27036967227,-36.309494777135,2,1,18 +2025-03-11T12:42:27.230575,479392948,65286,237,20.97624150656,9.00185832852,-35.790440093555,2,1,18 +2025-03-11T12:42:27.246200,479392948,65286,237,20.69352170936,8.728725912945,-35.2944727853,2,1,18 +2025-03-11T12:42:27.261825,479392948,65286,237,20.42493790202,8.427891525315,-34.77068748167,2,1,18 +2025-03-11T12:42:27.277450,479392948,65286,237,20.1375061082,8.145508813125,-34.24694921402,2,1,18 +2025-03-11T12:42:27.293075,479392948,65286,237,19.85949830762,7.872384550515,-33.72326158838,2,1,18 +2025-03-11T12:42:27.308700,479392948,65286,237,19.56735451718,7.58075154171,-33.217964191985,2,1,18 +2025-03-11T12:42:27.324325,479392948,65286,237,19.28463471998,7.307619126135,-32.717375700665,2,1,18 +2025-03-11T12:42:27.339950,479392948,65286,237,19.01605091264,7.025269025805,-32.221391655425,2,1,18 +2025-03-11T12:42:27.355575,479392948,65286,237,18.74275510868,6.73366862886,-31.70687901692,2,1,18 +2025-03-11T12:42:27.371200,479392948,65286,237,18.47888329796,6.460568825145,-31.17859055123,2,1,18 +2025-03-11T12:42:27.386825,479392948,65286,237,18.18673950752,6.182799031815,-30.65948522564,2,1,18 +2025-03-11T12:42:27.402450,479392948,65286,237,17.89459571708,5.89116602301,-30.14956664618,2,1,18 +2025-03-11T12:42:27.418075,479392948,65286,237,17.62129991312,5.581081338765,-29.644222213805,2,1,18 +2025-03-11T12:42:27.433700,479392948,65286,237,17.33858011592,5.29870677954,-29.125111910225,2,1,18 +2025-03-11T12:42:27.449325,479392948,65286,237,17.04643632548,5.025558058035,-28.596782758505,2,1,18 +2025-03-11T12:42:27.464950,479392948,65286,237,16.75429253504,4.74316719288,-28.07303770985,2,1,18 +2025-03-11T12:42:27.480575,479392948,65286,237,16.47157273784,4.442308346355,-27.55385324627,2,1,18 +2025-03-11T12:42:27.496200,479392948,65286,237,16.1794289474,4.146054265725,-27.020810211485,2,1,18 +2025-03-11T12:42:27.511825,479392948,65286,237,15.88257316034,3.85903417578,-26.49241865876,2,1,18 +2025-03-11T12:42:27.527450,479392948,65286,237,15.5904293699,3.56278009515,-25.977860356235,2,1,18 +2025-03-11T12:42:27.543075,479392948,65286,237,15.3077095727,3.271163392275,-25.46333415572,2,1,18 +2025-03-11T12:42:27.558700,479392948,65286,237,15.03441376874,2.974941923505,-24.921075878825,2,1,18 +2025-03-11T12:42:27.574325,479392948,65286,237,14.7422699783,2.687929986525,-24.37882755791,2,1,18 +2025-03-11T12:42:27.589950,479392948,65286,237,14.45012618786,2.41478126502,-23.845877223125,2,1,18 +2025-03-11T12:42:27.605575,479392948,65286,237,14.1532704008,2.146245462375,-23.32680219653,2,1,18 +2025-03-11T12:42:27.621200,479392948,65286,237,13.8705506036,1.850007687675,-22.812257456015,2,1,18 +2025-03-11T12:42:27.636825,479392948,65286,237,13.59254280302,1.53529377864,-22.288402970375,2,1,18 +2025-03-11T12:42:27.652450,479392948,65286,237,13.2815510261,1.23900708615,-21.750711628505,2,1,18 +2025-03-11T12:42:27.668075,479392948,65286,237,12.9752712458,0.947349618450001,-21.189939692315,2,1,18 +2025-03-11T12:42:27.683700,479392948,65286,237,12.67370346212,0.651079231890001,-20.64764072939,2,1,18 +2025-03-11T12:42:27.699325,479392948,65286,237,12.39098366492,0.359462529015,-20.11925097968,2,1,18 +2025-03-11T12:42:27.714950,479392948,65286,237,12.08470388462,0.0631839894899997,-19.57694523575,2,1,18 +2025-03-11T12:42:27.730575,479392948,65286,237,11.79256009418,-0.24231223479,-19.034622754835,2,1,18 +2025-03-11T12:42:27.746200,479392948,65286,237,11.5145522936,-0.533920784699999,-18.501618603065,2,1,18 +2025-03-11T12:42:27.761825,479392948,65286,237,11.21298450992,-0.82094902761,-17.9778414524,2,1,18 +2025-03-11T12:42:27.777450,479392948,65286,237,10.9255527161,-1.1218160271,-17.421680743295,2,1,18 +2025-03-11T12:42:27.793075,479392948,65286,237,10.63340892566,-1.431933323205,-16.874718539315,2,1,18 +2025-03-11T12:42:27.808700,479392948,65286,237,10.3365531386,-1.7466798441,-16.350836929655,2,1,18 +2025-03-11T12:42:27.824325,479392948,65286,237,10.03498535492,-2.038329158835,-15.80855650673,2,1,18 +2025-03-11T12:42:27.839950,479392948,65286,237,9.72870557462,-2.32536555471,-15.27553020893,2,1,18 +2025-03-11T12:42:27.855575,479392948,65286,237,9.42713779094,-2.62163594127,-14.72861006294,2,1,18 +2025-03-11T12:42:27.871200,479392948,65286,237,9.14441799374,-2.922494787795,-14.17245613484,2,1,18 +2025-03-11T12:42:27.886825,479392948,65286,237,8.84285021006,-3.218765174355,-13.630157171915,2,1,18 +2025-03-11T12:42:27.902450,479392948,65286,237,8.53657042976,-3.519664785705,-13.087832887985,2,1,18 +2025-03-11T12:42:27.918075,479392948,65286,237,8.24913863594,-3.820531785195,-12.517808629685,2,1,18 +2025-03-11T12:42:27.933700,479392948,65286,237,7.94757085226,-4.10293895628,-11.97556528676,2,1,18 +2025-03-11T12:42:27.949325,479392948,65286,237,7.66013905844,-4.39456381212,-11.44254757298,2,1,18 +2025-03-11T12:42:27.964950,479392948,65286,237,7.36328327138,-4.68620497389,-10.90951629719,2,1,18 +2025-03-11T12:42:27.980575,479392948,65286,237,7.06642748432,-4.991709351135,-10.362565852205,2,1,18 +2025-03-11T12:42:27.996200,479392948,65286,237,6.77428369388,-5.306447719065,-9.82020629129,2,1,18 +2025-03-11T12:42:28.011825,479392948,65286,237,6.4727159102,-5.602718105625,-9.2732861453,2,1,18 +2025-03-11T12:42:28.027450,479392948,65286,237,6.17114812652,-5.88512527671,-8.71717925318,2,1,18 +2025-03-11T12:42:28.043075,479392948,65286,237,5.86958034284,-6.18139566327,-8.16101674106,2,1,18 +2025-03-11T12:42:28.058700,479392948,65286,237,5.55858856592,-6.49616664306,-7.61400887306,2,1,18 +2025-03-11T12:42:28.074325,479392948,65286,237,5.25230878562,-6.792445182585,-7.085566678325,2,1,18 +2025-03-11T12:42:28.089950,479392948,65286,237,4.96016499518,-7.09332033504,-6.538641554345,2,1,18 +2025-03-11T12:42:28.105575,479392948,65286,237,4.66330920812,-7.398824712285,-5.977827560165,2,1,18 +2025-03-11T12:42:28.121200,479392948,65286,237,4.36174142444,-7.695095098845,-5.43552859724,2,1,18 +2025-03-11T12:42:28.136825,479392948,65286,237,4.06488563738,-8.005220547915,-4.88393842919,2,1,18 +2025-03-11T12:42:28.152450,479392948,65286,237,3.76802985032,-8.31072492516,-4.318503251945,2,1,18 +2025-03-11T12:42:28.168075,479392948,65286,237,3.46646206664,-8.60699531172,-3.78544665515,2,1,18 +2025-03-11T12:42:28.183700,479392948,65286,237,3.16018228634,-8.894031707595,-3.247799174285,2,1,18 +2025-03-11T12:42:28.199325,479392948,65286,237,2.86332649928,-9.204157156665,-2.696209006235,2,1,18 +2025-03-11T12:42:28.214950,479392948,65286,237,2.57118270884,-9.50503230912,-2.149283882255,2,1,18 +2025-03-11T12:42:28.230575,479392948,65286,237,2.2790389184,-9.8105285334,-1.593097852145,2,1,18 +2025-03-11T12:42:28.246200,479392948,65286,237,1.97747113472,-10.129904279085,-1.046085006155,2,1,18 +2025-03-11T12:42:28.261825,479392948,65286,237,1.6664793578,-10.435433115225,-0.50373540122,2,1,18 +2025-03-11T12:42:28.277450,479392948,65286,237,1.36491157412,-10.731703501785,0.0293211955750001,2,1,18 +2025-03-11T12:42:28.293075,479392948,65286,237,1.06805578706,-11.023344663555,0.553110105235,2,1,18 +2025-03-11T12:42:28.308700,479392948,65286,237,0.78062399324,-11.314969519395,1.113854917405,2,1,18 +2025-03-11T12:42:28.324325,479392948,65286,237,0.47434421294,-11.615869130745,1.6608003844,2,1,18 +2025-03-11T12:42:28.339950,479392948,65286,237,0.17277642926,-11.91676058913,2.20773907039,2,1,18 +2025-03-11T12:42:28.355575,479392948,65286,237,-0.1240793578,-12.213022822725,2.75927361844,2,1,18 +2025-03-11T12:42:28.371200,479392948,65286,237,-0.42093514486,-12.51852719997,3.29236051423,2,1,18 +2025-03-11T12:42:28.386825,479392948,65286,237,-0.71779093192,-12.81941050539,3.839292419215,2,1,18 +2025-03-11T12:42:28.402450,479392948,65286,237,-1.02407071222,-13.124931188565,4.39549879234,2,1,18 +2025-03-11T12:42:28.418075,479392948,65286,237,-1.30679050942,-13.43503217874,4.93320506818,2,1,18 +2025-03-11T12:42:28.433700,479392948,65286,237,-1.59893429986,-13.74052840302,5.475527549095,2,1,18 +2025-03-11T12:42:28.449325,479392948,65286,237,-1.90521408016,-14.03218587072,6.01319356996,2,1,18 +2025-03-11T12:42:28.464950,479392948,65286,237,-2.20678186384,-14.314593041805,6.564679279015,2,1,18 +2025-03-11T12:42:28.480575,479392948,65286,237,-2.51306164414,-14.59238729403,7.13001677827,2,1,18 +2025-03-11T12:42:28.496200,479392948,65286,237,-2.82405342106,-14.89791613017,7.66774520014,2,1,18 +2025-03-11T12:42:28.511825,479392948,65286,237,-3.10677321826,-15.20339604852,8.21467530211,2,1,18 +2025-03-11T12:42:28.527450,479392948,65286,237,-3.3989170087,-15.485786913675,8.75228389996,2,1,18 +2025-03-11T12:42:28.543075,479392948,65286,237,-3.68634880252,-15.795896056815,9.29461813987,2,1,18 +2025-03-11T12:42:28.558700,479392948,65286,237,-3.9879165862,-16.0967875152,9.83231445973,2,1,18 +2025-03-11T12:42:28.574325,479392948,65286,237,-4.2706363834,-16.388404218075,10.356083026375,2,1,18 +2025-03-11T12:42:28.589950,479392948,65286,237,-4.57220416708,-16.68929567646,10.893779346235,2,1,18 +2025-03-11T12:42:28.605575,479392948,65286,237,-4.8596359609,-16.99016267595,11.43145532308,2,1,18 +2025-03-11T12:42:28.621200,479392948,65286,237,-5.17062773782,-17.291070440265,11.97840757108,2,1,18 +2025-03-11T12:42:28.636825,479392948,65286,237,-5.4721955215,-17.5642354677,12.51599265094,2,1,18 +2025-03-11T12:42:28.652450,479392948,65286,237,-5.76433931194,-17.85124740468,13.0258926904,2,1,18 +2025-03-11T12:42:28.668075,479392948,65286,237,-6.05177110576,-18.156735475995,13.55896602418,2,1,18 +2025-03-11T12:42:28.683700,479392948,65286,237,-6.33920289958,-18.45298140366,14.087381094895,2,1,18 +2025-03-11T12:42:28.699325,479392948,65286,237,-6.61721070016,-18.749211025395,14.629646152795,2,1,18 +2025-03-11T12:42:28.714950,479392948,65286,237,-6.91406648722,-19.02698897169,15.16724299165,2,1,18 +2025-03-11T12:42:28.730575,479392948,65286,237,-7.21092227428,-19.323251205285,15.695671624375,2,1,18 +2025-03-11T12:42:28.746200,479392948,65286,237,-7.50306606472,-19.610263142265,16.214814029965,2,1,18 +2025-03-11T12:42:28.761825,479392948,65286,237,-7.7810738653,-19.906492764,16.747836721735,2,1,18 +2025-03-11T12:42:28.777450,479392948,65286,237,-8.0637936625,-20.198109466875,17.28084765451,2,1,18 +2025-03-11T12:42:28.793075,479392948,65286,237,-8.3465134597,-20.48972616975,17.804616221155,2,1,18 +2025-03-11T12:42:28.808700,479392948,65286,237,-8.63865725014,-20.781359178555,18.323777166745,2,1,18 +2025-03-11T12:42:28.824325,479392948,65286,237,-8.9355130372,-21.0683792685,18.85216871947,2,1,18 +2025-03-11T12:42:28.839950,479392948,65286,237,-9.23708082088,-21.36464965506,19.375982950135,2,1,18 +2025-03-11T12:42:28.855575,479392948,65286,237,-9.51980061808,-21.665508501585,19.885925047585,2,1,18 +2025-03-11T12:42:28.871200,479392948,65286,237,-9.79780841866,-21.947874907845,20.40502857016,2,1,18 +2025-03-11T12:42:28.886825,479392948,65286,237,-10.08524021248,-22.24412083551,20.924201274745,2,1,18 +2025-03-11T12:42:28.902450,479392948,65286,237,-10.3726720063,-22.5265035477,21.45256072546,2,1,18 +2025-03-11T12:42:28.918075,479392948,65286,237,-10.6553918035,-22.799635963275,21.9901186813,2,1,18 +2025-03-11T12:42:28.933700,479392948,65286,237,-10.94282359732,-23.08663974729,22.50463312282,2,1,18 +2025-03-11T12:42:28.949325,479392948,65286,237,-11.2208313979,-23.36900615355,23.01911546233,2,1,18 +2025-03-11T12:42:28.964950,479392948,65286,237,-11.479991212,-23.655961019775,23.538210400885,2,1,18 +2025-03-11T12:42:28.980575,479392948,65286,237,-11.7627110092,-23.952198794475,24.0527551414,2,1,18 +2025-03-11T12:42:28.996200,479392948,65286,237,-12.05956679626,-24.22997674077,24.56724606493,2,1,18 +2025-03-11T12:42:29.011825,479392948,65286,237,-12.33757459684,-24.50310100338,25.086312507505,2,1,18 +2025-03-11T12:42:29.027450,479392948,65286,237,-12.61558239742,-24.790088481465,25.591571020885,2,1,18 +2025-03-11T12:42:29.043075,479392948,65286,237,-12.893590198,-25.063212744075,26.0921527312,2,1,18 +2025-03-11T12:42:29.058700,479392948,65286,237,-13.1763099952,-25.322481944175,26.59268560252,2,1,18 +2025-03-11T12:42:29.074325,479392948,65286,237,-13.45431779578,-25.60022727861,27.0979070359,2,1,18 +2025-03-11T12:42:29.089950,479392948,65286,237,-13.71347760988,-25.887182144835,27.60313842526,2,1,18 +2025-03-11T12:42:29.105575,479392948,65286,237,-13.99148541046,-26.16492747927,28.11760222477,2,1,18 +2025-03-11T12:42:29.121200,479392948,65286,237,-14.26949321104,-26.433430670055,28.627407761215,2,1,18 +2025-03-11T12:42:29.136825,479392948,65286,237,-14.54750101162,-26.71117600449,29.1187656454,2,1,18 +2025-03-11T12:42:29.152450,479392948,65286,237,-14.82079681558,-26.975049970485,29.614682311645,2,1,18 +2025-03-11T12:42:29.168075,479392948,65286,237,-15.09409261954,-27.25740822378,30.12915787015,2,1,18 +2025-03-11T12:42:29.183700,479392948,65286,237,-15.37681241674,-27.530540639355,30.634367544535,2,1,18 +2025-03-11T12:42:29.199325,479392948,65286,237,-15.64068422746,-27.789777227595,31.10252501038,2,1,18 +2025-03-11T12:42:29.214950,479392948,65286,237,-15.91398003142,-28.05365119359,31.589199310495,2,1,18 +2025-03-11T12:42:29.230575,479392948,65286,237,-16.191987832,-28.33601759985,32.094439283875,2,1,18 +2025-03-11T12:42:29.246200,479392948,65286,237,-16.46528363596,-28.609133709495,32.58115066399,2,1,18 +2025-03-11T12:42:29.261825,479392948,65286,237,-16.7338674433,-28.8683784507,33.072420826165,2,1,18 +2025-03-11T12:42:29.277450,479392948,65286,237,-16.98831526078,-29.15532516396,33.56840306839,2,1,18 +2025-03-11T12:42:29.293075,479392948,65286,237,-17.24747507488,-29.423795742885,34.050454382425,2,1,18 +2025-03-11T12:42:29.308700,479392948,65286,237,-17.52548287546,-29.68305679002,34.537116923545,2,1,18 +2025-03-11T12:42:29.324325,479392948,65286,237,-17.7940666828,-29.96540689035,35.023858602655,2,1,18 +2025-03-11T12:42:29.339950,479392948,65286,237,-18.0532264969,-30.24774068475,35.501344353625,2,1,18 +2025-03-11T12:42:29.355575,479392948,65286,237,-18.312386311,-30.506969120025,35.99260095379,2,1,18 +2025-03-11T12:42:29.371200,479392948,65286,237,-18.58568211496,-30.775464157845,36.46543024471,2,1,18 +2025-03-11T12:42:29.386825,479392948,65286,237,-18.84012993244,-31.02082122468,36.93813971161,2,1,18 +2025-03-11T12:42:29.402450,479392948,65286,237,-19.09928974654,-31.28467073178,37.401687753385,2,1,18 +2025-03-11T12:42:29.418075,479392948,65286,237,-19.3725855505,-31.539302554125,37.87908260737,2,1,18 +2025-03-11T12:42:29.433700,479392948,65286,237,-19.62703336798,-31.80314390826,38.347245051205,2,1,18 +2025-03-11T12:42:29.449325,479392948,65286,237,-19.88619318208,-32.062372343535,38.82001691911,2,1,18 +2025-03-11T12:42:29.464950,479392948,65286,237,-20.14064099956,-32.30772941037,39.288105202945,2,1,18 +2025-03-11T12:42:29.480575,479392948,65286,237,-20.37624083056,-32.571538152645,39.751619339695,2,1,18 +2025-03-11T12:42:29.496200,479392948,65286,237,-20.6448246379,-32.807677534725,40.21506970348,2,1,18 +2025-03-11T12:42:29.511825,479392948,65286,237,-20.89927245538,-33.057655673385,40.673934161185,2,1,18 +2025-03-11T12:42:29.527450,479392948,65286,237,-21.14900827624,-33.31686780273,41.142071284015,2,1,18 +2025-03-11T12:42:29.543075,479392948,65286,237,-21.3987440971,-33.566837788425,41.591686594585,2,1,18 +2025-03-11T12:42:29.558700,479392948,65286,237,-21.64847991796,-33.80756563047,42.032022459025,2,1,18 +2025-03-11T12:42:29.574325,479392948,65286,237,-21.8935037422,-34.052906391375,42.467748899395,2,1,18 +2025-03-11T12:42:29.589950,479392948,65286,237,-22.13852756644,-34.302868224105,42.91735742896,2,1,18 +2025-03-11T12:42:29.605575,479392948,65286,237,-22.38355139068,-34.54820898501,43.366947418525,2,1,18 +2025-03-11T12:42:29.621200,479392948,65286,237,-22.61915122168,-34.802775583635,43.811939743015,2,1,18 +2025-03-11T12:42:29.636825,479392948,65286,237,-22.8594630493,-35.057350335225,44.252317665445,2,1,18 +2025-03-11T12:42:29.652450,479392948,65286,237,-23.10448687354,-35.28420680883,44.70183349501,2,1,18 +2025-03-11T12:42:29.668075,479392948,65286,237,-23.34008670454,-35.52491019198,45.1467701995,2,1,18 +2025-03-11T12:42:29.683700,479392948,65286,237,-23.57568653554,-35.76561357513,45.587085720925,2,1,18 +2025-03-11T12:42:29.699325,479392948,65286,237,-23.82071035978,-36.010954336035,46.03667571049,2,1,18 +2025-03-11T12:42:29.714950,479392948,65286,237,-24.06573418402,-36.25629509694,46.467780967795,2,1,18 +2025-03-11T12:42:29.730575,479392948,65286,237,-24.2966220184,-36.496990327125,46.880362609825,2,1,18 +2025-03-11T12:42:29.746200,479392948,65286,237,-24.54635783926,-36.71923388187,47.292897215875,2,1,18 +2025-03-11T12:42:29.761825,479392948,65286,237,-24.78195767026,-36.94145297772,47.728517394235,2,1,18 +2025-03-11T12:42:29.777450,479392948,65286,237,-25.00813350802,-37.18214005494,48.15957698752,2,1,18 +2025-03-11T12:42:29.793075,479392948,65286,237,-25.26729332212,-37.413642059265,48.58140460171,2,1,18 +2025-03-11T12:42:29.808700,479392948,65286,237,-25.4981811565,-37.63585300215,49.007775632935,2,1,18 +2025-03-11T12:42:29.824325,479392948,65286,237,-25.7102210044,-37.862652405,49.41565334788,2,1,18 +2025-03-11T12:42:29.839950,479392948,65286,237,-25.93639684216,-38.10333948222,49.818985842775,2,1,18 +2025-03-11T12:42:29.855575,479392948,65286,237,-26.1578606833,-38.32091304735,50.240703588925,2,1,18 +2025-03-11T12:42:29.871200,479392948,65286,237,-26.37932452444,-38.543107684305,50.64857632588,2,1,18 +2025-03-11T12:42:29.886825,479392948,65286,237,-26.6055003622,-38.76993154605,51.06571674997,2,1,18 +2025-03-11T12:42:29.902450,479392948,65286,237,-26.82225220672,-39.00136017369,51.468998602855,2,1,18 +2025-03-11T12:42:29.918075,479392948,65286,237,-27.03900405124,-39.218925585855,51.87222483574,2,1,18 +2025-03-11T12:42:29.933700,479392948,65286,237,-27.25104389914,-39.454967132355,52.27551844762,2,1,18 +2025-03-11T12:42:29.949325,479392948,65286,237,-27.48193173352,-39.663314859765,52.683349126585,2,1,18 +2025-03-11T12:42:29.964950,479392948,65286,237,-27.70810757128,-39.88089657786,53.081967738415,2,1,18 +2025-03-11T12:42:29.980575,479392948,65286,237,-27.91543542256,-40.089203540445,53.489764512355,2,1,18 +2025-03-11T12:42:29.996139,479392952,65282,238,-28.12276327384,-40.31599479033,53.869908347905,2,1,18 +2025-03-11T12:42:30.011764,479392952,65282,238,-28.31595513526,-40.528898365845,54.23149148818,2,1,18 +2025-03-11T12:42:30.027389,479392952,65282,238,-28.52799498316,-40.727971337745,54.611530864735,2,1,18 +2025-03-11T12:42:30.043014,479392952,65282,238,-28.74003483106,-40.93166538147,55.005452330485,2,1,18 +2025-03-11T12:42:30.058639,479392952,65282,238,-28.95207467896,-41.144601568845,55.38554732704,2,1,18 +2025-03-11T12:42:30.074264,479392952,65282,238,-29.15940253024,-41.37139281873,55.76569116259,2,1,18 +2025-03-11T12:42:30.089889,479392952,65282,238,-29.37144237814,-41.575086862455,56.136506713015,2,1,18 +2025-03-11T12:42:30.105514,479392952,65282,238,-29.57877022942,-41.769530609565,56.507278402435,2,1,18 +2025-03-11T12:42:30.121139,479392952,65282,238,-29.79081007732,-41.98246679694,56.88737339899,2,1,18 +2025-03-11T12:42:30.136764,479392952,65282,238,-29.98871393536,-42.18613638177,57.262789789465,2,1,18 +2025-03-11T12:42:30.152389,479392952,65282,238,-30.19604178664,-42.38058012888,57.615076746625,2,1,18 +2025-03-11T12:42:30.168014,479392952,65282,238,-30.41279363116,-42.570419110095,57.97197990886,2,1,18 +2025-03-11T12:42:30.183639,479392952,65282,238,-30.6106974892,-42.774088694925,58.33353275014,2,1,18 +2025-03-11T12:42:30.199264,479392952,65282,238,-30.799177354,-42.973120902,58.69505348941,2,1,18 +2025-03-11T12:42:30.214889,479392952,65282,238,-30.97823322556,-43.162894659495,59.0657659528,2,1,18 +2025-03-11T12:42:30.230514,479392952,65282,238,-31.16671309036,-43.35268472292,59.422628429005,2,1,18 +2025-03-11T12:42:30.246139,479392952,65282,238,-31.35990495178,-43.537861867485,59.78410032928,2,1,18 +2025-03-11T12:42:30.261764,479392952,65282,238,-31.55780880982,-43.741531452315,60.10868370604,2,1,18 +2025-03-11T12:42:30.277389,479392952,65282,238,-31.73686468138,-43.945168425285,60.43323995878,2,1,18 +2025-03-11T12:42:30.293014,479392952,65282,238,-31.92063254956,-44.13032926392,60.79007711398,2,1,18 +2025-03-11T12:42:30.308639,479392952,65282,238,-32.10911241436,-44.310877183695,61.12379659486,2,1,18 +2025-03-11T12:42:30.324264,479392952,65282,238,-32.30230427578,-44.48681218461,61.466746682875,2,1,18 +2025-03-11T12:42:30.339889,479392952,65282,238,-32.48607214396,-44.67659409507,61.814360011945,2,1,18 +2025-03-11T12:42:30.355514,479392952,65282,238,-32.66512801552,-44.857125708915,62.14344474775,2,1,18 +2025-03-11T12:42:30.371139,479392952,65282,238,-32.8488958837,-45.046907619375,62.449467429235,2,1,18 +2025-03-11T12:42:30.386764,479392952,65282,238,-33.02795175526,-45.21819708957,62.76003035278,2,1,18 +2025-03-11T12:42:30.402389,479392952,65282,238,-33.21171962344,-45.38025256908,63.09829007572,2,1,18 +2025-03-11T12:42:30.418014,479392952,65282,238,-33.37192750852,-45.551509427415,63.418068241375,2,1,18 +2025-03-11T12:42:30.433639,479392952,65282,238,-33.54155938684,-45.727403663505,63.733257325975,2,1,18 +2025-03-11T12:42:30.449264,479392952,65282,238,-33.71119126516,-45.89867682777,64.039185504445,2,1,18 +2025-03-11T12:42:30.464889,479392952,65282,238,-33.89495913334,-46.06997445093,64.34513402593,2,1,18 +2025-03-11T12:42:30.480514,479392952,65282,238,-34.06930300828,-46.236634696335,64.63718689621,2,1,18 +2025-03-11T12:42:30.496139,479392952,65282,238,-34.22479889674,-46.41250447353,64.952355637795,2,1,18 +2025-03-11T12:42:30.511764,479392952,65282,238,-34.37558278858,-46.57912395411,65.267480518375,2,1,18 +2025-03-11T12:42:30.527389,479392952,65282,238,-34.53107867704,-46.74113051583,65.568730090765,2,1,18 +2025-03-11T12:42:30.543014,479392952,65282,238,-34.70542255198,-46.898548617585,65.85612469798,2,1,18 +2025-03-11T12:42:30.558639,479392952,65282,238,-34.87976642692,-47.042103503865,66.13884250213,2,1,18 +2025-03-11T12:42:30.574264,479392952,65282,238,-35.039974312,-47.1948760749,66.421577043265,2,1,18 +2025-03-11T12:42:30.589889,479392952,65282,238,-35.1813342106,-47.366100321375,66.68587388812,2,1,18 +2025-03-11T12:42:30.605514,479392952,65282,238,-35.32740610582,-47.528090577165,66.97786753237,2,1,18 +2025-03-11T12:42:30.621139,479392952,65282,238,-35.48290199428,-47.67623392341,67.28830385089,2,1,18 +2025-03-11T12:42:30.636764,479392952,65282,238,-35.62426189288,-47.838216026235,67.580290714135,2,1,18 +2025-03-11T12:42:30.652389,479392952,65282,238,-35.76562179148,-47.995577057235,67.83528957286,2,1,18 +2025-03-11T12:42:30.668014,479392952,65282,238,-35.92111767994,-48.13447825983,68.076371065405,2,1,18 +2025-03-11T12:42:30.683639,479392952,65282,238,-36.06718957516,-48.25949994102,68.34511047433,2,1,18 +2025-03-11T12:42:30.699264,479392952,65282,238,-36.19912548052,-48.41684466609,68.59547458798,2,1,18 +2025-03-11T12:42:30.714889,479392952,65282,238,-36.3357733825,-48.56033432865,68.855032228765,2,1,18 +2025-03-11T12:42:30.730514,479392952,65282,238,-36.4771332811,-48.708453216,69.123857556685,2,1,18 +2025-03-11T12:42:30.746139,479392952,65282,238,-36.62791717294,-48.83810412198,69.374137554355,2,1,18 +2025-03-11T12:42:30.761764,479392952,65282,238,-36.76456507492,-48.97235164089,69.619794565945,2,1,18 +2025-03-11T12:42:30.777389,479392952,65282,238,-36.89178898366,-49.10658285387,69.86081683246,2,1,18 +2025-03-11T12:42:30.793014,479392952,65282,238,-37.02843688564,-49.236209300955,70.101834120985,2,1,18 +2025-03-11T12:42:30.808639,479392952,65282,238,-37.16508478762,-49.35659360439,70.338193146445,2,1,18 +2025-03-11T12:42:30.824264,479392952,65282,238,-37.3017326896,-49.486220051475,70.56996806884,2,1,18 +2025-03-11T12:42:30.839889,479392952,65282,238,-37.43838059158,-49.61584649856,70.829470089625,2,1,18 +2025-03-11T12:42:30.855514,479392952,65282,238,-37.57031649694,-49.73622264903,71.061201151015,2,1,18 +2025-03-11T12:42:30.871139,479392952,65282,238,-37.68811641244,-49.87043755608,71.288346306325,2,1,18 +2025-03-11T12:42:30.886764,479392952,65282,238,-37.79178033808,-49.99076478876,71.501551949425,2,1,18 +2025-03-11T12:42:30.902389,479392952,65282,238,-37.90015626034,-50.12496338988,71.71481999353,2,1,18 +2025-03-11T12:42:30.918014,479392952,65282,238,-38.01795617584,-50.245315081455,71.928045979645,2,1,18 +2025-03-11T12:42:30.933639,479392952,65282,238,-38.1498920812,-50.347206944625,72.13659696571,2,1,18 +2025-03-11T12:42:30.949264,479392952,65282,238,-38.27711598994,-50.462953870305,72.349817973835,2,1,18 +2025-03-11T12:42:30.964889,479392952,65282,238,-38.39020390882,-50.583297408915,72.563037178945,2,1,18 +2025-03-11T12:42:30.980514,479392952,65282,238,-38.49857983108,-50.699011722735,72.76698869692,2,1,18 +2025-03-11T12:42:30.996139,479392952,65282,238,-38.61166774996,-50.81473418952,72.966325812835,2,1,18 +2025-03-11T12:42:31.011764,479392952,65282,238,-38.7153316756,-50.92581927855,73.15638846061,2,1,18 +2025-03-11T12:42:31.027389,479392952,65282,238,-38.82370759786,-51.04153359237,73.32799169713,2,1,18 +2025-03-11T12:42:31.043014,479392952,65282,238,-38.9273715235,-51.14337653775,73.536501997165,2,1,18 +2025-03-11T12:42:31.058639,479392952,65282,238,-39.03103544914,-51.23597733948,73.731111668005,2,1,18 +2025-03-11T12:42:31.074264,479392952,65282,238,-39.14412336802,-51.34707873444,73.907324328595,2,1,18 +2025-03-11T12:42:31.089889,479392952,65282,238,-39.24778729366,-51.444300607995,74.092710173305,2,1,18 +2025-03-11T12:42:31.105514,479392952,65282,238,-39.33731522944,-51.53687695083,74.273435951935,2,1,18 +2025-03-11T12:42:31.121139,479392952,65282,238,-39.42684316522,-51.62483222184,74.454143190565,2,1,18 +2025-03-11T12:42:31.136764,479392952,65282,238,-39.51165910438,-51.72664255536,74.62565690206,2,1,18 +2025-03-11T12:42:31.152389,479392952,65282,238,-39.61532303002,-51.823864428915,74.797179197575,2,1,18 +2025-03-11T12:42:31.168014,479392952,65282,238,-39.71427495904,-51.91645707768,74.96405498902,2,1,18 +2025-03-11T12:42:31.183639,479392952,65282,238,-39.7990908982,-51.985919908425,75.14006010358,2,1,18 +2025-03-11T12:42:31.199264,479392952,65282,238,-39.87919484074,-52.083101017155,75.31154849407,2,1,18 +2025-03-11T12:42:31.214889,479392952,65282,238,-39.95929878328,-52.161797838585,75.44599326004,2,1,18 +2025-03-11T12:42:31.230514,479392952,65282,238,-40.0346907292,-52.2312443634,75.580394165005,2,1,18 +2025-03-11T12:42:31.246139,479392952,65282,238,-40.11479467174,-52.30069904118,75.714801850975,2,1,18 +2025-03-11T12:42:31.261764,479392952,65282,238,-40.20903460414,-52.379420321505,75.86775169222,2,1,18 +2025-03-11T12:42:31.277389,479392952,65282,238,-40.2938505433,-52.462746367725,76.002221779195,2,1,18 +2025-03-11T12:42:31.293014,479392952,65282,238,-40.38337847908,-52.53683842326,76.127419201045,2,1,18 +2025-03-11T12:42:31.308639,479392952,65282,238,-40.44934643176,-52.61088971397,76.261825084,2,1,18 +2025-03-11T12:42:31.324264,479392952,65282,238,-40.51531438444,-52.680319932855,76.386970060825,2,1,18 +2025-03-11T12:42:31.339889,479392952,65282,238,-40.59070633036,-52.745145385845,76.50286769353,2,1,18 +2025-03-11T12:42:31.355514,479392952,65282,238,-40.64253829318,-52.823793289485,76.641892956535,2,1,18 +2025-03-11T12:42:31.371139,479392952,65282,238,-40.694370256,-52.90706226495,76.757830844215,2,1,18 +2025-03-11T12:42:31.386764,479392952,65282,238,-40.75562621206,-52.96724218722,76.87831077697,2,1,18 +2025-03-11T12:42:31.402389,479392952,65282,238,-40.82630616136,-53.032059487245,76.989580445605,2,1,18 +2025-03-11T12:42:31.418014,479392952,65282,238,-40.89698611066,-53.08763464362,77.105434217305,2,1,18 +2025-03-11T12:42:31.433639,479392952,65282,238,-40.96295406334,-53.13395950338,77.20275939574,2,1,18 +2025-03-11T12:42:31.449264,479392952,65282,238,-41.0242100194,-53.180276210175,77.29083542704,2,1,18 +2025-03-11T12:42:31.464889,479392952,65282,238,-41.06661798898,-53.23580244876,77.411269695775,2,1,18 +2025-03-11T12:42:31.480514,479392952,65282,238,-41.0948899687,-53.286683156625,77.503937983105,2,1,18 +2025-03-11T12:42:31.496139,479392952,65282,238,-41.12787394504,-53.33295094563,77.57810977918,2,1,18 +2025-03-11T12:42:31.511764,479392952,65282,238,-41.18441790448,-53.39774378676,77.657010823345,2,1,18 +2025-03-11T12:42:31.527389,479392952,65282,238,-41.23153787068,-53.448657106485,77.731221502435,2,1,18 +2025-03-11T12:42:31.543014,479392952,65282,238,-41.2833698335,-53.49495750735,77.819283971725,2,1,18 +2025-03-11T12:42:31.558639,479392952,65282,238,-41.3304897997,-53.5320076116,77.911923763075,2,1,18 +2025-03-11T12:42:31.574264,479392952,65282,238,-41.37289776928,-53.56442849106,77.98605350116,2,1,18 +2025-03-11T12:42:31.589889,479392952,65282,238,-41.40588174562,-53.60607520824,78.02785847578,2,1,18 +2025-03-11T12:42:31.605514,479392952,65282,238,-41.4482897152,-53.64773823135,78.083540561605,2,1,18 +2025-03-11T12:42:31.621139,479392952,65282,238,-41.49069768478,-53.684780182635,78.14844647356,2,1,18 +2025-03-11T12:42:31.636764,479392952,65282,238,-41.52368166112,-53.707942612515,78.204040837375,2,1,18 +2025-03-11T12:42:31.652389,479392952,65282,238,-41.55666563746,-53.731105042395,78.264256384255,2,1,18 +2025-03-11T12:42:31.668014,479392952,65282,238,-41.5896496138,-53.754267472275,78.315229565005,2,1,18 +2025-03-11T12:42:31.683639,479392952,65282,238,-41.61792159352,-53.78666389284,78.361611861685,2,1,18 +2025-03-11T12:42:31.699264,479392952,65282,238,-41.63676958,-53.828286151125,78.408017676355,2,1,18 +2025-03-11T12:42:31.714889,479392952,65282,238,-41.6603295631,-53.851432275075,78.45435611203,2,1,18 +2025-03-11T12:42:31.730514,479392952,65282,238,-41.6838895462,-53.874578399025,78.491452181575,2,1,18 +2025-03-11T12:42:31.746139,479392952,65282,238,-41.70273753268,-53.87923208271,78.53308849318,2,1,18 +2025-03-11T12:42:31.761764,479392952,65282,238,-41.72629751578,-53.89313606301,78.56552629966,2,1,18 +2025-03-11T12:42:31.777389,479392952,65282,238,-41.7310095124,-53.8977652878,78.57017280373,2,1,18 +2025-03-11T12:42:31.793014,479392952,65282,238,-41.7310095124,-53.90700743145,78.584073432925,2,1,18 +2025-03-11T12:42:31.808639,479392952,65282,238,-41.74043350564,-53.94399231198,78.60734123026,2,1,18 +2025-03-11T12:42:31.824264,479392952,65282,238,-41.7545694955,-53.934774627225,78.63967277473,2,1,18 +2025-03-11T12:42:31.839889,479392952,65282,238,-41.7545694955,-53.9301535554,78.653517783925,2,1,18 +2025-03-11T12:42:31.855514,479392952,65282,238,-41.75928149212,-53.93478278019,78.658164287995,2,1,18 +2025-03-11T12:42:31.871139,479392952,65282,238,-41.76399348874,-53.944033076805,78.64896578287,2,1,18 +2025-03-11T12:42:31.886764,479392952,65282,238,-41.77341748198,-53.925565095435,78.64890518488,2,1,18 +2025-03-11T12:42:31.902389,479392952,65282,238,-41.76870548536,-53.920935870645,78.639637497745,2,1,18 +2025-03-11T12:42:31.918014,479392952,65282,238,-41.77341748198,-53.93018616726,78.616575443425,2,1,18 +2025-03-11T12:42:31.933639,479392952,65282,238,-41.76870548536,-53.920935870645,78.60728921629,2,1,18 +2025-03-11T12:42:31.949264,479392952,65282,238,-41.76399348874,-53.897822358555,78.597947369155,2,1,18 +2025-03-11T12:42:31.964889,479392952,65282,238,-41.7545694955,-53.888563908975,78.58403317795,2,1,18 +2025-03-11T12:42:31.980514,479392952,65282,238,-41.74514550226,-53.879305459395,78.560876620615,2,1,18 +2025-03-11T12:42:31.996139,479392952,65282,238,-41.73572150902,-53.860804866165,78.551546532475,2,1,18 +2025-03-11T12:42:32.011764,479392952,65282,238,-41.72629751578,-53.83768320111,78.52833435514,2,1,18 +2025-03-11T12:42:32.027389,479392952,65282,238,-41.69802553606,-53.823771067845,78.49126858459,2,1,18 +2025-03-11T12:42:32.043014,479392952,65282,238,-41.67446555296,-53.809867087545,78.45883077811,2,1,18 +2025-03-11T12:42:32.058639,479392952,65282,238,-41.64148157662,-53.786704657665,78.41709996349,2,1,18 +2025-03-11T12:42:32.074264,479392952,65282,238,-41.60849760028,-53.763542227785,78.384611515,2,1,18 +2025-03-11T12:42:32.089889,479392952,65282,238,-41.58493761718,-53.740396103835,78.329030713195,2,1,18 +2025-03-11T12:42:32.105514,479392952,65282,238,-41.57080162732,-53.69416092669,78.259507224205,2,1,18 +2025-03-11T12:42:32.121139,479392952,65282,238,-41.53310565436,-53.661748200195,78.222353731645,2,1,18 +2025-03-11T12:42:32.136764,479392952,65282,238,-41.4954096814,-53.652440832825,78.157565840695,2,1,18 +2025-03-11T12:42:32.152389,479392952,65282,238,-41.46713770168,-53.633907627735,78.129723896275,2,1,18 +2025-03-11T12:42:32.168014,479392952,65282,238,-41.43886572196,-53.59226906352,78.05095623814,2,1,18 +2025-03-11T12:42:32.183639,479392952,65282,238,-41.39174575576,-53.55521895927,77.972179995985,2,1,18 +2025-03-11T12:42:32.199264,479392952,65282,238,-41.35876177942,-53.518193313915,77.893424096845,2,1,18 +2025-03-11T12:42:32.214889,479392952,65282,238,-41.32106580646,-53.48578058742,77.828543505895,2,1,18 +2025-03-11T12:42:32.230514,479392952,65282,238,-41.26923384364,-53.45334340203,77.740536656605,2,1,18 +2025-03-11T12:42:32.246139,479392952,65282,238,-41.22682587406,-53.40243823527,77.670953941585,2,1,18 +2025-03-11T12:42:32.261764,479392952,65282,238,-41.1891299011,-53.337678006,77.587458838375,2,1,18 +2025-03-11T12:42:32.277389,479392952,65282,238,-41.14672193152,-53.272909623765,77.499335771095,2,1,18 +2025-03-11T12:42:32.293014,479392952,65282,238,-41.0948899687,-53.21736707925,77.40661503874,2,1,18 +2025-03-11T12:42:32.308639,479392952,65282,238,-41.03834600926,-53.17105852542,77.30468223925,2,1,18 +2025-03-11T12:42:32.324264,479392952,65282,238,-40.98651404644,-53.115515980905,77.193476774635,2,1,18 +2025-03-11T12:42:32.339889,479392952,65282,238,-40.93468208362,-53.064594508215,77.086911033085,2,1,18 +2025-03-11T12:42:32.355514,479392952,65282,238,-40.8828501208,-53.01829410735,76.989606197665,2,1,18 +2025-03-11T12:42:32.371139,479392952,65282,238,-40.82159416474,-52.944250969605,76.873691827975,2,1,18 +2025-03-11T12:42:32.386764,479392952,65282,238,-40.76033820868,-52.874828903685,76.767038364415,2,1,18 +2025-03-11T12:42:32.402389,479392952,65282,238,-40.70850624586,-52.82852850282,76.669733528995,2,1,18 +2025-03-11T12:42:32.418014,479392952,65282,238,-40.6472502898,-52.763727508725,76.54923505624,2,1,18 +2025-03-11T12:42:32.433639,479392952,65282,238,-40.57185834388,-52.689659912085,76.424057977405,2,1,18 +2025-03-11T12:42:32.449264,479392952,65282,238,-40.50117839458,-52.62484261206,76.289682393445,2,1,18 +2025-03-11T12:42:32.464889,479392952,65282,238,-40.42107445204,-52.550766862455,76.173740899735,2,1,18 +2025-03-11T12:42:32.480514,479392952,65282,238,-40.35981849598,-52.481344796535,76.04398152085,2,1,18 +2025-03-11T12:42:32.496139,479392952,65282,238,-40.28913854668,-52.430390711985,75.90966155689,2,1,18 +2025-03-11T12:42:32.511764,479392952,65282,238,-40.21374660076,-52.35170204352,75.756738839665,2,1,18 +2025-03-11T12:42:32.527389,479392952,65282,238,-40.13835465484,-52.254529087755,75.60374196244,2,1,18 +2025-03-11T12:42:32.543014,479392952,65282,238,-40.04882671906,-52.166573816745,75.455383005265,2,1,18 +2025-03-11T12:42:32.558639,479392952,65282,238,-39.9640107799,-52.083247770525,75.297807002965,2,1,18 +2025-03-11T12:42:32.574264,479392952,65282,238,-39.87919484074,-51.990679580655,75.149436286795,2,1,18 +2025-03-11T12:42:32.589889,479392952,65282,238,-39.7755309151,-51.8934577071,74.982535174345,2,1,18 +2025-03-11T12:42:32.605514,479392952,65282,238,-39.68600297932,-51.81474457974,74.829592114105,2,1,18 +2025-03-11T12:42:32.621139,479392952,65282,238,-39.59176304692,-51.726781155765,74.67660519286,2,1,18 +2025-03-11T12:42:32.636764,479392952,65282,238,-39.51165910438,-51.64346326251,74.5144147885,2,1,18 +2025-03-11T12:42:32.652389,479392952,65282,238,-39.42684316522,-51.555516144465,74.342956697005,2,1,18 +2025-03-11T12:42:32.668014,479392952,65282,238,-39.32317923958,-51.444431055435,74.157515232295,2,1,18 +2025-03-11T12:42:32.683639,479392952,65282,238,-39.22893930718,-51.333362272335,73.97670851266,2,1,18 +2025-03-11T12:42:32.699264,479392952,65282,238,-39.12527538154,-51.24538254243,73.777496198755,2,1,18 +2025-03-11T12:42:32.714889,479392952,65282,238,-39.0216114559,-51.138918525225,73.582830907915,2,1,18 +2025-03-11T12:42:32.730514,479392952,65282,238,-38.92265952688,-51.041704804635,73.39745184421,2,1,18 +2025-03-11T12:42:32.746139,479392952,65282,238,-38.81428360462,-50.935232634465,73.212022138495,2,1,18 +2025-03-11T12:42:32.761764,479392952,65282,238,-38.70119568574,-50.824131239505,73.008082379515,2,1,18 +2025-03-11T12:42:32.777389,479392952,65282,238,-38.58810776686,-50.71765091637,72.785676428275,2,1,18 +2025-03-11T12:42:32.793014,479392952,65282,238,-38.47501984798,-50.60654952141,72.590979035425,2,1,18 +2025-03-11T12:42:32.808639,479392952,65282,238,-38.3619319291,-50.49544812645,72.396281642575,2,1,18 +2025-03-11T12:42:32.824264,479392952,65282,238,-38.2441320136,-50.375096434875,72.187676839525,2,1,18 +2025-03-11T12:42:32.839889,479392952,65282,238,-38.1498920812,-50.2501644363,71.974466218435,2,1,18 +2025-03-11T12:42:32.855514,479392952,65282,238,-38.0320921657,-50.139054888375,71.76127731232,2,1,18 +2025-03-11T12:42:32.871139,479392952,65282,238,-37.91900424682,-50.027953493415,71.552716370275,2,1,18 +2025-03-11T12:42:32.886764,479392952,65282,238,-37.78706834146,-49.90295627112,71.311724402755,2,1,18 +2025-03-11T12:42:32.902389,479392952,65282,238,-37.65042043948,-49.77795089586,71.08921038649,2,1,18 +2025-03-11T12:42:32.918014,479392952,65282,238,-37.52319653074,-49.648340754705,70.8713125753,2,1,18 +2025-03-11T12:42:32.933639,479392952,65282,238,-37.39126062538,-49.509480316935,70.625643804715,2,1,18 +2025-03-11T12:42:32.949264,479392952,65282,238,-37.2781727065,-49.379894634675,70.384660421215,2,1,18 +2025-03-11T12:42:32.964889,479392952,65282,238,-37.15566079438,-49.250292646485,70.14828465877,2,1,18 +2025-03-11T12:42:32.980514,479392952,65282,238,-37.02372488902,-49.11605328054,69.930361526575,2,1,18 +2025-03-11T12:42:32.996139,479392952,65282,238,-36.88707698704,-48.986426833455,69.67085950579,2,1,18 +2025-03-11T12:42:33.011764,479392952,65282,238,-36.75514108168,-48.856808539335,69.41136426601,2,1,18 +2025-03-11T12:42:33.027389,479392952,65282,238,-36.60906918646,-48.713302570845,69.161035429345,2,1,18 +2025-03-11T12:42:33.043014,479392952,65282,238,-36.46770928786,-48.574425827145,68.901489547555,2,1,18 +2025-03-11T12:42:33.058639,479392952,65282,238,-36.33106138588,-48.421694020935,68.637273643705,2,1,18 +2025-03-11T12:42:33.074264,479392952,65282,238,-36.19912548052,-48.25972822404,68.386890990055,2,1,18 +2025-03-11T12:42:33.089889,479392952,65282,238,-36.04834158868,-48.11159303076,68.136536832385,2,1,18 +2025-03-11T12:42:33.105514,479392952,65282,238,-35.9116936867,-47.972724440025,67.863134182405,2,1,18 +2025-03-11T12:42:33.121139,479392952,65282,238,-35.75148580162,-47.824572940815,67.5896605474,2,1,18 +2025-03-11T12:42:33.136764,479392952,65282,238,-35.59598991316,-47.65794530727,67.32536189953,2,1,18 +2025-03-11T12:42:33.152389,479392952,65282,238,-35.43107003146,-47.509785655095,67.04263911739,2,1,18 +2025-03-11T12:42:33.168014,479392952,65282,238,-35.275574143,-47.347779093375,66.755253094195,2,1,18 +2025-03-11T12:42:33.183639,479392952,65282,238,-35.12007825454,-47.195014675305,66.472525334065,2,1,18 +2025-03-11T12:42:33.199264,479392952,65282,238,-34.97400635932,-47.05612977864,66.180624389815,2,1,18 +2025-03-11T12:42:33.214889,479392952,65282,238,-34.81851047086,-46.89412321692,65.888617183555,2,1,18 +2025-03-11T12:42:33.230514,479392952,65282,238,-34.6630145824,-46.736737727025,65.59200733423,2,1,18 +2025-03-11T12:42:33.246139,479392952,65282,238,-34.51223069056,-46.57473931827,65.290764542845,2,1,18 +2025-03-11T12:42:33.261764,479392952,65282,238,-34.35202280548,-46.403482459935,64.99871347558,2,1,18 +2025-03-11T12:42:33.277389,479392952,65282,238,-34.1918149204,-46.227604529775,64.688159136055,2,1,18 +2025-03-11T12:42:33.293014,479392952,65282,238,-34.02218304208,-46.05633136551,64.38685214065,2,1,18 +2025-03-11T12:42:33.308639,479392952,65282,238,-33.84783916714,-45.889671120105,64.099420453435,2,1,18 +2025-03-11T12:42:33.324264,479392952,65282,238,-33.67820728882,-45.732261171315,63.77968434577,2,1,18 +2025-03-11T12:42:33.339889,479392952,65282,238,-33.49915141726,-45.574834916595,63.4460711269,2,1,18 +2025-03-11T12:42:33.355514,479392952,65282,238,-33.33423153556,-45.39894883347,63.121646457175,2,1,18 +2025-03-11T12:42:33.371139,479392952,65282,238,-33.16459965724,-45.21381245373,62.81104147564,2,1,18 +2025-03-11T12:42:33.386764,479392952,65282,238,-32.98083178906,-45.028651615095,62.495794968025,2,1,18 +2025-03-11T12:42:33.402389,479392952,65282,238,-32.8017759175,-44.852741073075,62.180592321415,2,1,18 +2025-03-11T12:42:33.418014,479392952,65282,238,-32.62272004594,-44.67220945923,61.856128768675,2,1,18 +2025-03-11T12:42:33.433639,479392952,65282,238,-32.43424018114,-44.500903683105,61.513204001665,2,1,18 +2025-03-11T12:42:33.449264,479392952,65282,238,-32.24104831972,-44.31572653854,61.17021683365,2,1,18 +2025-03-11T12:42:33.464889,479392952,65282,238,-32.0714164414,-44.1305901588,60.831884753725,2,1,18 +2025-03-11T12:42:33.480514,479392952,65282,238,-31.89236056984,-43.940816401305,60.49352057179,2,1,18 +2025-03-11T12:42:33.496139,479392952,65282,238,-31.70388070504,-43.755647409705,60.15978255091,2,1,18 +2025-03-11T12:42:33.511764,479392952,65282,238,-31.505976847,-43.5565988967,59.812111798825,2,1,18 +2025-03-11T12:42:33.527389,479392952,65282,238,-31.30336099234,-43.35754223073,59.47829781493,2,1,18 +2025-03-11T12:42:33.543014,479392952,65282,238,-31.11488112754,-43.18161538278,59.12611214179,2,1,18 +2025-03-11T12:42:33.558639,479392952,65282,238,-30.92640126274,-42.98720424753,58.77385230865,2,1,18 +2025-03-11T12:42:33.574264,479392952,65282,238,-30.72378540808,-42.78814758156,58.412311226365,2,1,18 +2025-03-11T12:42:33.589889,479392952,65282,238,-30.52588155004,-42.58447799673,58.060000751215,2,1,18 +2025-03-11T12:42:33.605514,479392952,65282,238,-30.33268968862,-42.399300852165,57.68928648481,2,1,18 +2025-03-11T12:42:33.621139,479392952,65282,238,-30.14892182044,-42.191034654405,57.34159899574,2,1,18 +2025-03-11T12:42:33.636764,479392952,65282,238,-29.96044195564,-41.99200244733,56.9893206226,2,1,18 +2025-03-11T12:42:33.652389,479392952,65282,238,-29.75311410436,-41.78831655657,56.623133036245,2,1,18 +2025-03-11T12:42:33.668014,479392952,65282,238,-29.54578625308,-41.59387280946,56.252361346825,2,1,18 +2025-03-11T12:42:33.683639,479392952,65282,238,-29.35259439166,-41.37634816212,55.88151730042,2,1,18 +2025-03-11T12:42:33.699264,479392952,65282,238,-29.14055454376,-41.15879090292,55.50602494693,2,1,18 +2025-03-11T12:42:33.714889,479392952,65282,238,-28.93322669248,-40.95510501216,55.102867896055,2,1,18 +2025-03-11T12:42:33.730514,479392952,65282,238,-28.70705085472,-40.75138650954,54.72741081955,2,1,18 +2025-03-11T12:42:33.746139,479392952,65282,238,-28.5138589933,-40.529240790375,54.356548233145,2,1,18 +2025-03-11T12:42:33.761764,479392952,65282,238,-28.32066713188,-40.31633721486,53.95799562835,2,1,18 +2025-03-11T12:42:33.777389,479392952,65282,238,-28.09449129412,-40.10337656859,53.545532007325,2,1,18 +2025-03-11T12:42:33.793014,479392952,65282,238,-27.86360345974,-39.899649913005,53.151583417555,2,1,18 +2025-03-11T12:42:33.808639,479392952,65282,238,-27.6421396186,-39.6866974197,52.766853675925,2,1,18 +2025-03-11T12:42:33.824264,479392952,65282,238,-27.42067577746,-39.45988171092,52.382068314295,2,1,18 +2025-03-11T12:42:33.839889,479392952,65282,238,-27.1944999397,-39.233057849175,51.974170256335,2,1,18 +2025-03-11T12:42:33.855514,479392952,65282,238,-26.97303609856,-39.02010535587,51.561713416315,2,1,18 +2025-03-11T12:42:33.871139,479392952,65282,238,-26.76099625066,-38.81179024032,51.14466749524,2,1,18 +2025-03-11T12:42:33.886764,479392952,65282,238,-26.53010841628,-38.589579297435,50.727538830145,2,1,18 +2025-03-11T12:42:33.902389,479392952,65282,238,-26.30393257852,-38.348892220215,50.328827518315,2,1,18 +2025-03-11T12:42:33.918014,479392952,65282,238,-26.08246873738,-38.112834367785,49.92089916136,2,1,18 +2025-03-11T12:42:33.933639,479392952,65282,238,-25.86571689286,-37.88602681197,49.49452993315,2,1,18 +2025-03-11T12:42:33.949264,479392952,65282,238,-25.63482905848,-37.645331581785,49.07270592499,2,1,18 +2025-03-11T12:42:33.964889,479392952,65282,238,-25.42278921058,-37.418532178935,48.65096466085,2,1,18 +2025-03-11T12:42:33.980514,479392952,65282,238,-25.17776538634,-37.177812489855,48.229120309675,2,1,18 +2025-03-11T12:42:33.996078,479392956,65278,239,-24.9327415621,-36.927850657125,47.802617695435,2,1,18 +2025-03-11T12:42:34.011703,479392956,65278,239,-24.70656572434,-36.714890010855,47.394775257475,2,1,18 +2025-03-11T12:42:34.027328,479392956,65278,239,-24.48981387982,-36.46959816774,46.9637106862,2,1,18 +2025-03-11T12:42:34.042953,479392956,65278,239,-24.25421404882,-36.24737907189,46.541954057035,2,1,18 +2025-03-11T12:42:34.058578,479392956,65278,239,-24.02332621444,-36.01130491353,46.101663856615,2,1,18 +2025-03-11T12:42:34.074203,479392956,65278,239,-23.76887839696,-35.77981106217,45.665979474235,2,1,18 +2025-03-11T12:42:34.089828,479392956,65278,239,-23.53799056258,-35.54373690381,45.22106809075,2,1,18 +2025-03-11T12:42:34.105453,479392956,65278,239,-23.3071027282,-35.30766274545,44.79926262259,2,1,18 +2025-03-11T12:42:34.121078,479392956,65278,239,-23.06207890396,-35.06694305637,44.35431235609,2,1,18 +2025-03-11T12:42:34.136703,479392956,65278,239,-22.81705507972,-34.821602295465,43.895480000395,2,1,18 +2025-03-11T12:42:34.152328,479392956,65278,239,-22.58145524872,-34.553172481365,43.45505323897,2,1,18 +2025-03-11T12:42:34.167953,479392956,65278,239,-22.3411434211,-34.298597729775,43.01467531654,2,1,18 +2025-03-11T12:42:34.183578,479392956,65278,239,-22.09611959686,-34.057878040695,42.55124031778,2,1,18 +2025-03-11T12:42:34.199203,479392956,65278,239,-21.84167177938,-33.81252097386,42.08777321701,2,1,18 +2025-03-11T12:42:34.214828,479392956,65278,239,-21.60607194838,-33.57181759071,41.647457695585,2,1,18 +2025-03-11T12:42:34.230453,479392956,65278,239,-21.3516241309,-33.32183945205,41.202456787075,2,1,18 +2025-03-11T12:42:34.246078,479392956,65278,239,-21.09717631342,-33.08110345704,40.76211414163,2,1,18 +2025-03-11T12:42:34.261703,479392956,65278,239,-20.83801649932,-32.83573823724,40.30326144292,2,1,18 +2025-03-11T12:42:34.277328,479392956,65278,239,-20.58356868184,-32.571896883105,39.844341365215,2,1,18 +2025-03-11T12:42:34.292953,479392956,65278,239,-20.33383286098,-32.31268475376,39.37158305932,2,1,18 +2025-03-11T12:42:34.308578,479392956,65278,239,-20.0793850435,-32.048843399625,38.89879943242,2,1,18 +2025-03-11T12:42:34.324203,479392956,65278,239,-19.81551323278,-31.79422788321,38.43528168964,2,1,18 +2025-03-11T12:42:34.339828,479392956,65278,239,-19.56577741192,-31.544257897515,37.971802829875,2,1,18 +2025-03-11T12:42:34.355453,479392956,65278,239,-19.30661759782,-31.28502946224,37.48978859584,2,1,18 +2025-03-11T12:42:34.371078,479392956,65278,239,-19.05216978034,-31.00732489263,37.00770698281,2,1,18 +2025-03-11T12:42:34.386703,479392956,65278,239,-18.79300996624,-30.74347538553,36.53029539184,2,1,18 +2025-03-11T12:42:34.402328,479392956,65278,239,-18.5244261589,-30.484230644325,36.057509961925,2,1,18 +2025-03-11T12:42:34.417953,479392956,65278,239,-18.26055434818,-30.224994056085,35.593973679145,2,1,18 +2025-03-11T12:42:34.433578,479392956,65278,239,-17.98725854422,-29.965741161915,35.102696735965,2,1,18 +2025-03-11T12:42:34.449203,479392956,65278,239,-17.71396274026,-29.71110933957,34.620680698915,2,1,18 +2025-03-11T12:42:34.464828,479392956,65278,239,-17.45951492278,-29.447267985435,34.12479115669,2,1,18 +2025-03-11T12:42:34.480453,479392956,65278,239,-17.2050671053,-29.169563415825,33.647330726725,2,1,18 +2025-03-11T12:42:34.496078,479392956,65278,239,-16.93648329796,-28.896455459145,33.169868493745,2,1,18 +2025-03-11T12:42:34.511703,479392956,65278,239,-16.67261148724,-28.618734583605,32.68315213564,2,1,18 +2025-03-11T12:42:34.527328,479392956,65278,239,-16.41345167314,-28.354885076505,32.19649817854,2,1,18 +2025-03-11T12:42:34.542953,479392956,65278,239,-16.15429185904,-28.08641449758,31.70982568144,2,1,18 +2025-03-11T12:42:34.558578,479392956,65278,239,-15.8857080517,-27.82254868455,31.22315816233,2,1,18 +2025-03-11T12:42:34.574203,479392956,65278,239,-15.61712424436,-27.544819656045,30.722571474025,2,1,18 +2025-03-11T12:42:34.589828,479392956,65278,239,-15.33911644378,-27.26707432161,30.21272885758,2,1,18 +2025-03-11T12:42:34.605453,479392956,65278,239,-15.0611086432,-26.993950059,29.721389513395,2,1,18 +2025-03-11T12:42:34.621078,479392956,65278,239,-14.77367684938,-26.71156734681,29.22075716107,2,1,18 +2025-03-11T12:42:34.636703,479392956,65278,239,-14.4956690488,-26.42920094055,28.720138370755,2,1,18 +2025-03-11T12:42:34.652328,479392956,65278,239,-14.2365092347,-26.1561092898,28.21958378446,2,1,18 +2025-03-11T12:42:34.667953,479392956,65278,239,-13.9537894375,-25.910703305175,27.71910653314,2,1,18 +2025-03-11T12:42:34.683578,479392956,65278,239,-13.6710696403,-25.632949817775,27.20925713569,2,1,18 +2025-03-11T12:42:34.699203,479392956,65278,239,-13.3883498431,-25.355196330375,26.70865010437,2,1,18 +2025-03-11T12:42:34.714828,479392956,65278,239,-13.10091804928,-25.06819254636,26.19413566285,2,1,18 +2025-03-11T12:42:34.730453,479392956,65278,239,-12.8229102487,-24.771962924625,25.684218886405,2,1,18 +2025-03-11T12:42:34.746078,479392956,65278,239,-12.54490244812,-24.480354374715,25.160457100765,2,1,18 +2025-03-11T12:42:34.761703,479392956,65278,239,-12.26689464754,-24.188745824805,24.636695315125,2,1,18 +2025-03-11T12:42:34.777328,479392956,65278,239,-11.9983108402,-23.9110167963,24.131487443755,2,1,18 +2025-03-11T12:42:34.792953,479392956,65278,239,-11.72501503624,-23.65176390213,23.61710458525,2,1,18 +2025-03-11T12:42:34.808578,479392956,65278,239,-11.44700723566,-23.36939749587,23.098001062675,2,1,18 +2025-03-11T12:42:34.824203,479392956,65278,239,-11.15486344522,-23.08238555889,22.588101023215,2,1,18 +2025-03-11T12:42:34.839828,479392956,65278,239,-10.87685564464,-22.80001915263,22.073618683705,2,1,18 +2025-03-11T12:42:34.855453,479392956,65278,239,-10.5847118542,-22.517628287475,21.56835836731,2,1,18 +2025-03-11T12:42:34.871078,479392956,65278,239,-10.29728006038,-22.23986664711,21.049259822725,2,1,18 +2025-03-11T12:42:34.886703,479392956,65278,239,-10.00984826656,-21.952862863095,20.53012419814,2,1,18 +2025-03-11T12:42:34.902328,479392956,65278,239,-9.71770447612,-21.656608782465,19.997081163355,2,1,18 +2025-03-11T12:42:34.917953,479392956,65278,239,-9.45854466202,-21.36041177259,19.482570327865,2,1,18 +2025-03-11T12:42:34.933578,479392956,65278,239,-9.18053686144,-21.05956107903,18.968013828355,2,1,18 +2025-03-11T12:42:34.949203,479392956,65278,239,-8.87425708114,-20.77714575498,18.44886961975,2,1,18 +2025-03-11T12:42:34.964828,479392956,65278,239,-8.59153728394,-20.504013339405,17.92055403004,2,1,18 +2025-03-11T12:42:34.980453,479392956,65278,239,-8.2993934935,-20.226243546075,17.396827521385,2,1,18 +2025-03-11T12:42:34.996078,479392956,65278,239,-8.0166736963,-19.9346268432,16.87305895474,2,1,18 +2025-03-11T12:42:35.011703,479392956,65278,239,-7.71981790924,-19.63374353778,16.344611782015,2,1,18 +2025-03-11T12:42:35.027328,479392956,65278,239,-7.4276741188,-19.3467316008,15.806984644165,2,1,18 +2025-03-11T12:42:35.042953,479392956,65278,239,-7.1449543216,-19.0504938261,15.278576354455,2,1,18 +2025-03-11T12:42:35.058578,479392956,65278,239,-6.8622345244,-18.7542560514,14.74554688168,2,1,18 +2025-03-11T12:42:35.074203,479392956,65278,239,-6.57009073396,-18.471865186245,14.212559466895,2,1,18 +2025-03-11T12:42:35.089828,479392956,65278,239,-6.27794694352,-18.17099003379,13.665634342915,2,1,18 +2025-03-11T12:42:35.105453,479392956,65278,239,-5.97637915984,-17.879340719055,13.11411155386,2,1,18 +2025-03-11T12:42:35.121078,479392956,65278,239,-5.67952337278,-17.578457413635,12.567179648875,2,1,18 +2025-03-11T12:42:35.136703,479392956,65278,239,-5.39209157896,-17.28221148597,12.052628127355,2,1,18 +2025-03-11T12:42:35.152328,479392956,65278,239,-5.0952357919,-16.985949252375,11.519578311565,2,1,18 +2025-03-11T12:42:35.167953,479392956,65278,239,-4.7889560116,-16.70815500015,10.986589093765,2,1,18 +2025-03-11T12:42:35.183578,479392956,65278,239,-4.49210022454,-16.411892766555,10.45816046104,2,1,18 +2025-03-11T12:42:35.199203,479392956,65278,239,-4.19524443748,-16.10638838931,9.929694748315,2,1,18 +2025-03-11T12:42:35.214828,479392956,65278,239,-3.91252464028,-15.80090847096,9.382764646345,2,1,18 +2025-03-11T12:42:35.230453,479392956,65278,239,-3.62980484308,-15.500049624435,8.82198953518,2,1,18 +2025-03-11T12:42:35.246078,479392956,65278,239,-3.33294905602,-15.22227167814,8.29825624552,2,1,18 +2025-03-11T12:42:35.261703,479392956,65278,239,-3.02666927572,-14.93061421044,7.760590224655,2,1,18 +2025-03-11T12:42:35.277328,479392956,65278,239,-2.71096550218,-14.62969829316,7.209010012585,2,1,18 +2025-03-11T12:42:35.292953,479392956,65278,239,-2.42824570498,-14.338081590285,6.67599907981,2,1,18 +2025-03-11T12:42:35.308578,479392956,65278,239,-2.14552590778,-14.041843815585,6.133727240905,2,1,18 +2025-03-11T12:42:35.324203,479392956,65278,239,-1.85338211734,-13.74096866313,5.596044483055,2,1,18 +2025-03-11T12:42:35.339828,479392956,65278,239,-1.55181433366,-13.41697184562,5.044391914,2,1,18 +2025-03-11T12:42:35.355453,479392956,65278,239,-1.2549585466,-13.1345728275,4.497534169015,2,1,18 +2025-03-11T12:42:35.371078,479392956,65278,239,-0.96752675278,-12.83370582801,3.9691005583,2,1,18 +2025-03-11T12:42:35.386703,479392956,65278,239,-0.66124697248,-12.537427288485,3.42679481437,2,1,18 +2025-03-11T12:42:35.402328,479392956,65278,239,-0.3596791888,-12.231914758275,2.86135285612,2,1,18 +2025-03-11T12:42:35.417953,479392956,65278,239,-0.06282340174,-11.921789309205,2.3190050542,2,1,18 +2025-03-11T12:42:35.433578,479392956,65278,239,0.23874438194,-11.625518922645,1.767463725145,2,1,18 +2025-03-11T12:42:35.449203,479392956,65278,239,0.53088817238,-11.320022698365,1.2158988781,2,1,18 +2025-03-11T12:42:35.464828,479392956,65278,239,0.83245595606,-11.00988909633,0.67816547824,2,1,18 +2025-03-11T12:42:35.480453,479392956,65278,239,1.13402373974,-10.71361870977,0.135866515315,2,1,18 +2025-03-11T12:42:35.496078,479392956,65278,239,1.44030352004,-10.41271909842,-0.424942500875,2,1,18 +2025-03-11T12:42:35.511703,479392956,65278,239,1.74187130372,-10.12569085551,-0.97644674993,2,1,18 +2025-03-11T12:42:35.527328,479392956,65278,239,2.02930309754,-9.83406599967,-1.50946446371,2,1,18 +2025-03-11T12:42:35.542953,479392956,65278,239,2.31673489136,-9.519335784705,-2.04257487749,2,1,18 +2025-03-11T12:42:35.558578,479392956,65278,239,2.62772666828,-9.232291235865,-2.59871387162,2,1,18 +2025-03-11T12:42:35.574203,479392956,65278,239,2.91987045872,-8.94065822706,-3.150223098665,2,1,18 +2025-03-11T12:42:35.589828,479392956,65278,239,3.21201424916,-8.63516200278,-3.70178794571,2,1,18 +2025-03-11T12:42:35.605453,479392956,65278,239,3.52300602608,-8.33887531029,-4.25796401984,2,1,18 +2025-03-11T12:42:35.621078,479392956,65278,239,3.82928580638,-8.042596770765,-4.8095121299,2,1,18 +2025-03-11T12:42:35.636703,479392956,65278,239,4.12614159344,-7.741713465345,-5.35182285182,2,1,18 +2025-03-11T12:42:35.652328,479392956,65278,239,4.4229973805,-7.431588016275,-5.89417065374,2,1,18 +2025-03-11T12:42:35.667953,479392956,65278,239,4.72456516418,-7.12145441424,-6.436525236665,2,1,18 +2025-03-11T12:42:35.683578,479392956,65278,239,5.03084494448,-6.815933731065,-6.97424687753,2,1,18 +2025-03-11T12:42:35.699203,479392956,65278,239,5.33241272816,-6.52428441633,-7.52114848352,2,1,18 +2025-03-11T12:42:35.714828,479392956,65278,239,5.62926851522,-6.23264325456,-8.058800942375,2,1,18 +2025-03-11T12:42:35.730453,479392956,65278,239,5.9308362989,-5.90864643705,-8.605832328365,2,1,18 +2025-03-11T12:42:35.746078,479392956,65278,239,6.23240408258,-5.60313390684,-9.162031920485,2,1,18 +2025-03-11T12:42:35.761703,479392956,65278,239,6.5198358764,-5.3299933383,-9.70883902346,2,1,18 +2025-03-11T12:42:35.777328,479392956,65278,239,6.80726767022,-5.033747410635,-10.255738826435,2,1,18 +2025-03-11T12:42:35.792953,479392956,65278,239,7.10412345728,-4.732864105215,-10.80267073142,2,1,18 +2025-03-11T12:42:35.808578,479392956,65278,239,7.4151152342,-4.4319563409,-11.345001796355,2,1,18 +2025-03-11T12:42:35.824203,479392956,65278,239,7.73081900774,-4.13104042362,-11.905824374555,2,1,18 +2025-03-11T12:42:35.839828,479392956,65278,239,8.0276747948,-3.82091497455,-12.44355099341,2,1,18 +2025-03-11T12:42:35.855453,479392956,65278,239,8.310394592,-3.5154350562,-12.985859912315,2,1,18 +2025-03-11T12:42:35.871078,479392956,65278,239,8.59782638582,-3.228431272185,-13.528101452225,2,1,18 +2025-03-11T12:42:35.886703,479392956,65278,239,8.88054618302,-2.92757242566,-14.065770648065,2,1,18 +2025-03-11T12:42:35.902328,479392956,65278,239,9.17268997346,-2.635939416855,-14.631143424305,2,1,18 +2025-03-11T12:42:35.917953,479392956,65278,239,9.47896975376,-2.33041873368,-15.16886506517,2,1,18 +2025-03-11T12:42:35.933578,479392956,65278,239,9.78053753744,-2.02490620347,-15.6973375589,2,1,18 +2025-03-11T12:42:35.949203,479392956,65278,239,10.0773933245,-1.728643969875,-16.235008557755,2,1,18 +2025-03-11T12:42:35.964828,479392956,65278,239,10.38838510142,-1.42773620556,-16.78658198882,2,1,18 +2025-03-11T12:42:35.980453,479392956,65278,239,10.68052889186,-1.136103196755,-17.32422766667,2,1,18 +2025-03-11T12:42:35.996078,479392956,65278,239,10.98680867216,-0.835203585405,-17.861930767535,2,1,18 +2025-03-11T12:42:36.011703,479392956,65278,239,11.27424046598,-0.543578729565,-18.404190847445,2,1,18 +2025-03-11T12:42:36.027328,479392956,65278,239,11.57109625304,-0.256558639619999,-18.95106713243,2,1,18 +2025-03-11T12:42:36.042953,479392956,65278,239,11.85381605024,0.0304369914299993,-19.4979230744,2,1,18 +2025-03-11T12:42:36.058578,479392956,65278,239,12.14595984068,0.335933215710001,-20.02638200612,2,1,18 +2025-03-11T12:42:36.074203,479392956,65278,239,12.43810363112,0.64142943999,-20.568704487035,2,1,18 +2025-03-11T12:42:36.089828,479392956,65278,239,12.74438341142,0.942329051340001,-21.09716522177,2,1,18 +2025-03-11T12:42:36.105453,479392956,65278,239,13.03181520524,1.22471176353,-21.63014585555,2,1,18 +2025-03-11T12:42:36.121078,479392956,65278,239,13.31924699906,1.502473403895,-22.158486766265,2,1,18 +2025-03-11T12:42:36.136703,479392956,65278,239,13.6113907895,1.798727484525,-22.696150984115,2,1,18 +2025-03-11T12:42:36.152328,479392956,65278,239,13.90824657656,2.10423186177,-23.21537433071,2,1,18 +2025-03-11T12:42:36.167953,479392956,65278,239,14.200390367,2.414349157875,-23.748472985495,2,1,18 +2025-03-11T12:42:36.183578,479392956,65278,239,14.48782216082,2.71059508554,-24.299993971535,2,1,18 +2025-03-11T12:42:36.199203,479392956,65278,239,14.77525395464,2.988356725905,-24.842198431445,2,1,18 +2025-03-11T12:42:36.214828,479392956,65278,239,15.0721097417,3.2661346722,-25.365931721105,2,1,18 +2025-03-11T12:42:36.230453,479392956,65278,239,15.36425353214,3.557767681005,-25.885092666695,2,1,18 +2025-03-11T12:42:36.246078,479392956,65278,239,15.62812534286,3.863214987495,-26.39964736319,2,1,18 +2025-03-11T12:42:36.261703,479392956,65278,239,15.90142114682,4.14557324079,-26.91874410476,2,1,18 +2025-03-11T12:42:36.277328,479392956,65278,239,16.20770092712,4.432609636665,-27.456391585625,2,1,18 +2025-03-11T12:42:36.292953,479392956,65278,239,16.5092687108,4.7242589514,-27.984808459355,2,1,18 +2025-03-11T12:42:36.308578,479392956,65278,239,16.79670050462,5.002020591765,-28.499285820875,2,1,18 +2025-03-11T12:42:36.324203,479392956,65278,239,17.08884429506,5.29365360057,-29.018446766465,2,1,18 +2025-03-11T12:42:36.339828,479392956,65278,239,17.39041207874,5.59916613078,-29.55154044326,2,1,18 +2025-03-11T12:42:36.355453,479392956,65278,239,17.67784387256,5.886169914795,-30.06605488478,2,1,18 +2025-03-11T12:42:36.371078,479392956,65278,239,17.969987663,6.16856077995,-30.571315201175,2,1,18 +2025-03-11T12:42:36.386703,479392956,65278,239,18.24799546358,6.446306114385,-31.09040018375,2,1,18 +2025-03-11T12:42:36.402328,479392956,65278,239,18.5118672743,6.74713234905,-31.61879988944,2,1,18 +2025-03-11T12:42:36.417953,479392956,65278,239,18.7945870715,7.0341279801,-32.124065183825,2,1,18 +2025-03-11T12:42:36.433578,479392956,65278,239,19.07259487208,7.311873314535,-32.638528983335,2,1,18 +2025-03-11T12:42:36.449203,479392956,65278,239,19.34589067604,7.589610496005,-33.14374363571,2,1,18 +2025-03-11T12:42:36.464828,479392956,65278,239,19.62389847662,7.862734758615,-33.653567712155,2,1,18 +2025-03-11T12:42:36.480453,479392956,65278,239,19.91604226706,8.149746695595,-34.172710117745,2,1,18 +2025-03-11T12:42:36.496078,479392956,65278,239,20.1846260744,8.43671786775,-34.696439801375,2,1,18 +2025-03-11T12:42:36.511703,479392956,65278,239,20.46263387498,8.723705345835,-35.201698314755,2,1,18 +2025-03-11T12:42:36.527328,479392956,65278,239,20.7500656688,8.9829826989,-35.697616784015,2,1,18 +2025-03-11T12:42:36.542953,479392956,65278,239,21.02807346938,9.251485889685,-36.21666468659,2,1,18 +2025-03-11T12:42:36.558578,479392956,65278,239,21.30608126996,9.52923122412,-36.717264936905,2,1,18 +2025-03-11T12:42:36.574203,479392956,65278,239,21.57937707392,9.79772626194,-37.227063692345,2,1,18 +2025-03-11T12:42:36.589828,479392956,65278,239,21.86680886774,10.084730045955,-37.7369569508,2,1,18 +2025-03-11T12:42:36.605453,479392956,65278,239,22.13539267508,10.357838002635,-38.228282732975,2,1,18 +2025-03-11T12:42:36.621078,479392956,65278,239,22.41811247228,10.617107202735,-38.728815604295,2,1,18 +2025-03-11T12:42:36.636703,479392956,65278,239,22.69140827624,10.89946545603,-39.210942881345,2,1,18 +2025-03-11T12:42:36.652328,479392956,65278,239,22.95528008696,11.172565259745,-39.702261882515,2,1,18 +2025-03-11T12:42:36.667953,479392956,65278,239,23.23328788754,11.436447378705,-40.22129124509,2,1,18 +2025-03-11T12:42:36.683578,479392956,65278,239,23.5065836915,11.7003213447,-40.74031382666,2,1,18 +2025-03-11T12:42:36.699203,479392956,65278,239,23.77045550222,11.991905435715,-41.227085804765,2,1,18 +2025-03-11T12:42:36.714828,479392956,65278,239,24.03903930956,12.26963446422,-41.69994539468,2,1,18 +2025-03-11T12:42:36.730453,479392956,65278,239,24.30291112028,12.524249980635,-42.186569052785,2,1,18 +2025-03-11T12:42:36.746078,479392956,65278,239,24.56207093438,12.78347841591,-42.691689202145,2,1,18 +2025-03-11T12:42:36.761703,479392956,65278,239,24.81651875186,13.056561913695,-43.18761582437,2,1,18 +2025-03-11T12:42:36.777328,479392956,65278,239,25.08039056258,13.325040645585,-43.65118918715,2,1,18 +2025-03-11T12:42:36.792953,479392956,65278,239,25.36311035978,13.593551989335,-44.14251677234,2,1,18 +2025-03-11T12:42:36.808578,479392956,65278,239,25.64583015698,13.852821189435,-44.6245649114,2,1,18 +2025-03-11T12:42:36.824203,479392956,65278,239,25.90027797446,14.112041471745,-45.0973299983,2,1,18 +2025-03-11T12:42:36.839828,479392956,65278,239,26.15943778856,14.366648835195,-45.570083326205,2,1,18 +2025-03-11T12:42:36.855453,479392956,65278,239,26.42330959928,14.635127567085,-46.04752023818,2,1,18 +2025-03-11T12:42:36.871078,479392956,65278,239,26.68246941338,14.898977074185,-46.520310646085,2,1,18 +2025-03-11T12:42:36.886703,479392956,65278,239,26.9463412241,15.167455806075,-46.98850519193,2,1,18 +2025-03-11T12:42:36.902328,479392956,65278,239,27.20078904158,15.44053930386,-47.4520835327,2,1,18 +2025-03-11T12:42:36.917953,479392956,65278,239,27.45523685906,15.69975958617,-47.938712168795,2,1,18 +2025-03-11T12:42:36.933578,479392956,65278,239,27.71439667316,15.949745877795,-48.397583407505,2,1,18 +2025-03-11T12:42:36.949203,479392956,65278,239,27.96413249402,16.195094791665,-48.856422544205,2,1,18 +2025-03-11T12:42:36.964828,479392956,65278,239,28.19973232502,16.44966139029,-49.319899600955,2,1,18 +2025-03-11T12:42:36.980453,479392956,65278,239,28.44946814588,16.71349459146,-49.77419171459,2,1,18 +2025-03-11T12:42:36.996078,479392956,65278,239,28.69449197012,16.968077496015,-50.22843996722,2,1,18 +2025-03-11T12:42:37.011703,479392956,65278,239,28.9489397876,17.2226767065,-50.69194414799,2,1,18 +2025-03-11T12:42:37.027328,479392956,65278,239,29.20338760508,17.468033773335,-51.160032431825,2,1,18 +2025-03-11T12:42:37.042953,479392956,65278,239,29.45312342594,17.713382687205,-51.591144470135,2,1,18 +2025-03-11T12:42:37.058578,479392956,65278,239,29.69814725018,17.95872344811,-52.036113276635,2,1,18 +2025-03-11T12:42:37.074203,479392956,65278,239,29.94317107442,18.194822065365,-52.4856661862,2,1,18 +2025-03-11T12:42:37.089828,479392956,65278,239,30.19290689528,18.430928835585,-52.921362327575,2,1,18 +2025-03-11T12:42:37.105453,479392956,65278,239,30.42850672628,18.67625329056,-53.37093875513,2,1,18 +2025-03-11T12:42:37.121078,479392956,65278,239,30.67353055052,18.89848869234,-53.838920776955,2,1,18 +2025-03-11T12:42:37.136703,479392956,65278,239,30.91855437476,19.13920838142,-54.31621932491,2,1,18 +2025-03-11T12:42:37.152328,479392956,65278,239,31.15886620238,19.38454098936,-54.76580253347,2,1,18 +2025-03-11T12:42:37.167953,479392956,65278,239,31.40860202324,19.62988990323,-55.210778120975,2,1,18 +2025-03-11T12:42:37.183578,479392956,65278,239,31.63006586438,19.879810971135,-55.641868013255,2,1,18 +2025-03-11T12:42:37.199203,479392956,65278,239,31.85152970552,20.134353110865,-56.05911289634,2,1,18 +2025-03-11T12:42:37.214828,479392956,65278,239,32.08712953652,20.375056494015,-56.48556486857,2,1,18 +2025-03-11T12:42:37.230453,479392956,65278,239,32.32744136414,20.592662671005,-56.911930921805,2,1,18 +2025-03-11T12:42:37.246078,479392956,65278,239,32.56304119514,20.824123910505,-57.32448226484,2,1,18 +2025-03-11T12:42:37.261703,479392956,65278,239,32.80335302276,21.060214374795,-57.741680111945,2,1,18 +2025-03-11T12:42:37.277328,479392956,65278,239,33.03895285376,21.28705454247,-58.17269764724,2,1,18 +2025-03-11T12:42:37.292953,479392956,65278,239,33.2604166949,21.509249179425,-58.589812750325,2,1,18 +2025-03-11T12:42:37.308578,479392956,65278,239,33.50072852252,21.736097500065,-58.993109968235,2,1,18 +2025-03-11T12:42:37.324203,479392956,65278,239,33.7316163569,21.953687371125,-59.41022009333,2,1,18 +2025-03-11T12:42:37.339828,479392956,65278,239,33.93423221156,22.180470468045,-59.84119016159,2,1,18 +2025-03-11T12:42:37.355453,479392956,65278,239,34.15098405608,22.411899095685,-60.25833556367,2,1,18 +2025-03-11T12:42:37.371078,479392956,65278,239,34.37715989384,22.62023867013,-60.64767472937,2,1,18 +2025-03-11T12:42:37.386703,479392956,65278,239,34.59862373498,22.83781223526,-61.009317095675,2,1,18 +2025-03-11T12:42:37.402328,479392956,65278,239,34.80595158626,23.083087772445,-61.408019823485,2,1,18 +2025-03-11T12:42:37.417953,479392956,65278,239,35.02270343078,23.29141104096,-61.80196661024,2,1,18 +2025-03-11T12:42:37.433578,479392956,65278,239,35.25359126516,23.50900091202,-62.20521318614,2,1,18 +2025-03-11T12:42:37.449203,479392956,65278,239,35.48447909954,23.73583292673,-62.603875658975,2,1,18 +2025-03-11T12:42:37.464828,479392956,65278,239,35.68238295758,23.953365727035,-62.983968852515,2,1,18 +2025-03-11T12:42:37.480453,479392956,65278,239,35.89442280548,24.170922986235,-63.387188304395,2,1,18 +2025-03-11T12:42:37.496078,479392956,65278,239,36.11117465,24.37924625475,-63.776513908085,2,1,18 +2025-03-11T12:42:37.511703,479392956,65278,239,36.31850250128,24.587553217335,-64.147341217505,2,1,18 +2025-03-11T12:42:37.527328,479392956,65278,239,36.53054234918,24.77276297376,-64.513461424865,2,1,18 +2025-03-11T12:42:37.542953,479392956,65278,239,36.73315820384,24.98106178338,-64.89352431941,2,1,18 +2025-03-11T12:42:37.558578,479392956,65278,239,36.94048605512,25.198610889615,-65.27363107496,2,1,18 +2025-03-11T12:42:37.574203,479392956,65278,239,37.14310190978,25.40228862741,-65.65829661257,2,1,18 +2025-03-11T12:42:37.589828,479392956,65278,239,37.35042976106,25.59673237452,-66.033689485055,2,1,18 +2025-03-11T12:42:37.605453,479392956,65278,239,37.55775761234,25.80041826528,-66.395255888345,2,1,18 +2025-03-11T12:42:37.621078,479392956,65278,239,37.76979746024,25.99949123718,-66.76605289877,2,1,18 +2025-03-11T12:42:37.636703,479392956,65278,239,37.96298932166,26.19853159722,-67.118338052915,2,1,18 +2025-03-11T12:42:37.652328,479392956,65278,239,38.14204519322,26.39292642654,-67.47520550711,2,1,18 +2025-03-11T12:42:37.667953,479392956,65278,239,38.33052505802,26.58733756179,-67.81822297412,2,1,18 +2025-03-11T12:42:37.683578,479392956,65278,239,38.52842891606,26.786386074795,-68.165893726205,2,1,18 +2025-03-11T12:42:37.699203,479392956,65278,239,38.7263327741,26.9854345878,-68.52280684442,2,1,18 +2025-03-11T12:42:37.714828,479392956,65278,239,38.91952463552,27.15674851689,-68.884223124695,2,1,18 +2025-03-11T12:42:37.730453,479392956,65278,239,39.09386851046,27.341893049595,-69.23642553482,2,1,18 +2025-03-11T12:42:37.746078,479392956,65278,239,39.27292438202,27.53166680709,-69.5424414353,2,1,18 +2025-03-11T12:42:37.761703,479392956,65278,239,39.46611624344,27.716843951655,-69.89004978638,2,1,18 +2025-03-11T12:42:37.777328,479392956,65278,239,39.65930810486,27.90202109622,-70.242279320525,2,1,18 +2025-03-11T12:42:37.792953,479392956,65278,239,39.83836397642,28.09641592554,-70.57141967633,2,1,18 +2025-03-11T12:42:37.808578,479392956,65278,239,40.02684384122,28.276963845315,-70.88665442495,2,1,18 +2025-03-11T12:42:37.824203,479392956,65278,239,40.2106117094,28.448261468475,-71.211087678695,2,1,18 +2025-03-11T12:42:37.839828,479392956,65278,239,40.39437957758,28.628801235285,-71.540179195505,2,1,18 +2025-03-11T12:42:37.855453,479392956,65278,239,40.55929945928,28.818550533885,-71.86465948523,2,1,18 +2025-03-11T12:42:37.871078,479392956,65278,239,40.73364333422,28.989831851115,-72.17521562777,2,1,18 +2025-03-11T12:42:37.886703,479392956,65278,239,40.89856321592,29.151854718765,-72.490342311365,2,1,18 +2025-03-11T12:42:37.902328,479392956,65278,239,41.06819509424,29.34161217033,-72.814829382095,2,1,18 +2025-03-11T12:42:37.917953,479392956,65278,239,41.24253896918,29.51289348756,-73.13924907383,2,1,18 +2025-03-11T12:42:37.933578,479392956,65278,239,41.42159484074,29.674940814105,-73.42666900205,2,1,18 +2025-03-11T12:42:37.949203,479392956,65278,239,41.58180272582,29.85543981609,-73.72337833238,2,1,18 +2025-03-11T12:42:37.964828,479392956,65278,239,41.75143460414,30.017470836705,-74.04775416311,2,1,18 +2025-03-11T12:42:37.980453,479392956,65278,239,41.91635448584,30.179493704355,-74.35825966364,2,1,18 +2025-03-11T12:42:37.996017,479392960,65274,240,42.08127436754,30.350758715655,-74.664181061105,2,1,18 +2025-03-11T12:42:38.011642,479392960,65274,240,42.24619424924,30.50816051148,-74.96080447244,2,1,18 +2025-03-11T12:42:38.027267,479392960,65274,240,42.40640213432,30.65631201069,-75.243520473575,2,1,18 +2025-03-11T12:42:38.042892,479392960,65274,240,42.5666100194,30.8229477972,-75.52631063471,2,1,18 +2025-03-11T12:42:38.058517,479392960,65274,240,42.72210590786,30.97571221527,-75.813659577905,2,1,18 +2025-03-11T12:42:38.074142,479392960,65274,240,42.8728897997,31.128468480375,-76.101001740095,2,1,18 +2025-03-11T12:42:38.089767,479392960,65274,240,43.03309768478,31.276619979585,-76.369854192035,2,1,18 +2025-03-11T12:42:38.105392,479392960,65274,240,43.17916958,31.41550487625,-76.6201644887,2,1,18 +2025-03-11T12:42:38.121017,479392960,65274,240,43.31581748198,31.545131323335,-76.87504532642,2,1,18 +2025-03-11T12:42:38.136642,479392960,65274,240,43.4618893772,31.688637291825,-77.153101261475,2,1,18 +2025-03-11T12:42:38.152267,479392960,65274,240,43.61738526566,31.83678063807,-77.41270456628,2,1,18 +2025-03-11T12:42:38.167892,479392960,65274,240,43.76345716088,31.96180231926,-77.68606515827,2,1,18 +2025-03-11T12:42:38.183517,479392960,65274,240,43.89539306624,32.10990490068,-77.95487692418,2,1,18 +2025-03-11T12:42:38.199142,479392960,65274,240,44.04146496146,32.267274084645,-78.20988256391,2,1,18 +2025-03-11T12:42:38.214767,479392960,65274,240,44.18753685668,32.41540112496,-78.469472306705,2,1,18 +2025-03-11T12:42:38.230392,479392960,65274,240,44.32418475866,32.563511859345,-78.705942572165,2,1,18 +2025-03-11T12:42:38.246017,479392960,65274,240,44.44198467416,32.697726766395,-78.92846654441,2,1,18 +2025-03-11T12:42:38.261642,479392960,65274,240,44.5692085829,32.8180947639,-79.16481200786,2,1,18 +2025-03-11T12:42:38.277267,479392960,65274,240,44.70114448826,32.94771305802,-79.428928430705,2,1,18 +2025-03-11T12:42:38.292892,479392960,65274,240,44.828368397,33.086565342825,-79.656105688025,2,1,18 +2025-03-11T12:42:38.308517,479392960,65274,240,44.96030430236,33.206941493295,-79.87397320022,2,1,18 +2025-03-11T12:42:38.324142,479392960,65274,240,45.10166420096,33.33195502152,-80.10573636362,2,1,18 +2025-03-11T12:42:38.339767,479392960,65274,240,45.22417611308,33.45231486606,-80.351317412195,2,1,18 +2025-03-11T12:42:38.355392,479392960,65274,240,45.3466880252,33.568053638775,-80.564531639315,2,1,18 +2025-03-11T12:42:38.371017,479392960,65274,240,45.4644879407,33.70688961765,-80.78707415156,2,1,18 +2025-03-11T12:42:38.386642,479392960,65274,240,45.59171184944,33.854984046105,-81.00504612275,2,1,18 +2025-03-11T12:42:38.402267,479392960,65274,240,45.70951176494,33.970714665855,-81.22287475193,2,1,18 +2025-03-11T12:42:38.417892,479392960,65274,240,45.83202367706,34.081832366745,-81.440691622115,2,1,18 +2025-03-11T12:42:38.433517,479392960,65274,240,45.94039959932,34.18368346509,-81.639966337025,2,1,18 +2025-03-11T12:42:38.449142,479392960,65274,240,46.04877552158,34.29015563526,-81.830017225805,2,1,18 +2025-03-11T12:42:38.464767,479392960,65274,240,46.15243944722,34.40124072429,-82.02007987358,2,1,18 +2025-03-11T12:42:38.480392,479392960,65274,240,46.25610337286,34.507704741495,-82.219366347485,2,1,18 +2025-03-11T12:42:38.496017,479392960,65274,240,46.3597672985,34.609547686875,-82.423255464455,2,1,18 +2025-03-11T12:42:38.511642,479392960,65274,240,46.45871922752,34.72986676659,-82.613348411225,2,1,18 +2025-03-11T12:42:38.527267,479392960,65274,240,46.5482471633,34.840927396725,-82.78952716679,2,1,18 +2025-03-11T12:42:38.542892,479392960,65274,240,46.65662308556,34.93353635142,-82.97028006944,2,1,18 +2025-03-11T12:42:38.558517,479392960,65274,240,46.7602870112,35.030758224975,-83.15566591415,2,1,18 +2025-03-11T12:42:38.574142,479392960,65274,240,46.86395093684,35.123359026705,-83.34103321886,2,1,18 +2025-03-11T12:42:38.589767,479392960,65274,240,46.95819086924,35.22056459433,-83.512541952365,2,1,18 +2025-03-11T12:42:38.605392,479392960,65274,240,47.06185479488,35.31316539606,-83.679424524815,2,1,18 +2025-03-11T12:42:38.621017,479392960,65274,240,47.15138273066,35.396499595245,-83.83700730812,2,1,18 +2025-03-11T12:42:38.636642,479392960,65274,240,47.22206267996,35.47055903892,-84.003768253535,2,1,18 +2025-03-11T12:42:38.652267,479392960,65274,240,47.3021666225,35.558498004,-84.165977197895,2,1,18 +2025-03-11T12:42:38.667892,479392960,65274,240,47.3964065549,35.6325982125,-84.323529682205,2,1,18 +2025-03-11T12:42:38.683517,479392960,65274,240,47.48593449068,35.706690268035,-84.457969470185,2,1,18 +2025-03-11T12:42:38.699142,479392960,65274,240,47.56603843322,35.794629233115,-84.610936048415,2,1,18 +2025-03-11T12:42:38.714767,479392960,65274,240,47.66027836562,35.887213728915,-84.77318387579,2,1,18 +2025-03-11T12:42:38.730392,479392960,65274,240,47.7498063014,35.97979007175,-84.9169401899,2,1,18 +2025-03-11T12:42:38.746017,479392960,65274,240,47.81577425408,36.06308350611,-85.042140786725,2,1,18 +2025-03-11T12:42:38.761642,479392960,65274,240,47.88174220676,36.12789265317,-85.162646040485,2,1,18 +2025-03-11T12:42:38.777267,479392960,65274,240,47.94771015944,36.20194394388,-85.283188374245,2,1,18 +2025-03-11T12:42:38.792892,479392960,65274,240,48.02781410198,36.266777549835,-85.417577520215,2,1,18 +2025-03-11T12:42:38.808517,479392960,65274,240,48.11263004114,36.331619308755,-85.56121581332,2,1,18 +2025-03-11T12:42:38.824142,479392960,65274,240,48.16917400058,36.387170006235,-85.667806875875,2,1,18 +2025-03-11T12:42:38.839767,479392960,65274,240,48.2210059634,36.456575766225,-85.774446777425,2,1,18 +2025-03-11T12:42:38.855392,479392960,65274,240,48.30110990594,36.53065151583,-85.86728235581,2,1,18 +2025-03-11T12:42:38.871017,479392960,65274,240,48.35765386538,36.58620221331,-85.98773696756,2,1,18 +2025-03-11T12:42:38.886642,479392960,65274,240,48.40477383158,36.64173660486,-86.08969328504,2,1,18 +2025-03-11T12:42:38.902267,479392960,65274,240,48.44718180116,36.706504987095,-86.182437535385,2,1,18 +2025-03-11T12:42:38.917892,479392960,65274,240,48.50843775722,36.766684909365,-86.27519036975,2,1,18 +2025-03-11T12:42:38.933517,479392960,65274,240,48.56498171666,36.81761453502,-86.34941461085,2,1,18 +2025-03-11T12:42:38.949142,479392960,65274,240,48.60738968624,36.863898629955,-86.460569433455,2,1,18 +2025-03-11T12:42:38.964767,479392960,65274,240,48.6450856592,36.910174571925,-86.54861155973,2,1,18 +2025-03-11T12:42:38.980392,479392960,65274,240,48.6922056254,36.951845748,-86.627406341885,2,1,18 +2025-03-11T12:42:38.996017,479392960,65274,240,48.74874958484,36.993533230005,-86.701593502985,2,1,18 +2025-03-11T12:42:39.011642,479392960,65274,240,48.7864455578,37.030567028325,-86.784977366195,2,1,18 +2025-03-11T12:42:39.027267,479392960,65274,240,48.83827752062,37.063004213715,-86.863741849355,2,1,18 +2025-03-11T12:42:39.042892,479392960,65274,240,48.87597349358,37.08617479656,-86.937827726435,2,1,18 +2025-03-11T12:42:39.058517,479392960,65274,240,48.91838146316,37.141701035145,-87.03053489678,2,1,18 +2025-03-11T12:42:39.074142,479392960,65274,240,48.96078943274,37.16950084278,-87.123130827125,2,1,18 +2025-03-11T12:42:39.089767,479392960,65274,240,48.9749254226,37.2111149481,-87.16028749466,2,1,18 +2025-03-11T12:42:39.105392,479392960,65274,240,49.01262139556,37.23890660277,-87.192801264155,2,1,18 +2025-03-11T12:42:39.121017,479392960,65274,240,49.05031736852,37.262077185615,-87.24378122591,2,1,18 +2025-03-11T12:42:39.136642,479392960,65274,240,49.08801334148,37.30373205576,-87.276350615405,2,1,18 +2025-03-11T12:42:39.152267,479392960,65274,240,49.10686132796,37.336112170395,-87.33658289927,2,1,18 +2025-03-11T12:42:39.167892,479392960,65274,240,49.13042131106,37.359258294345,-87.38754251801,2,1,18 +2025-03-11T12:42:39.183517,479392960,65274,240,49.14455730092,37.373145968715,-87.415345579415,2,1,18 +2025-03-11T12:42:39.199142,479392960,65274,240,49.15869329078,37.39165471491,-87.45240954695,2,1,18 +2025-03-11T12:42:39.214767,479392960,65274,240,49.17282928064,37.410163461105,-87.47560996529,2,1,18 +2025-03-11T12:42:39.230392,479392960,65274,240,49.19638926374,37.42868851323,-87.521929860965,2,1,18 +2025-03-11T12:42:39.246017,479392960,65274,240,49.21523725022,37.424100053265,-87.54504436031,2,1,18 +2025-03-11T12:42:39.261642,479392960,65274,240,49.21994924684,37.44259249353,-87.55898885051,2,1,18 +2025-03-11T12:42:39.277267,479392960,65274,240,49.21994924684,37.46107678083,-87.57754774277,2,1,18 +2025-03-11T12:42:39.292892,479392960,65274,240,49.22466124346,37.470327077445,-87.59145515297,2,1,18 +2025-03-11T12:42:39.308517,479392960,65274,240,49.2340852367,37.4749644552,-87.596108438045,2,1,18 +2025-03-11T12:42:39.324142,479392960,65274,240,49.24822122656,37.47036784227,-87.600731424125,2,1,18 +2025-03-11T12:42:39.339767,479392960,65274,240,49.26235721642,37.47501337299,-87.596149124075,2,1,18 +2025-03-11T12:42:39.355392,479392960,65274,240,49.25293322318,37.46575492341,-87.60996203126,2,1,18 +2025-03-11T12:42:39.371017,479392960,65274,240,49.24350922994,37.461117545655,-87.60992992925,2,1,18 +2025-03-11T12:42:39.386642,479392960,65274,240,49.24350922994,37.45649647383,-87.59142665699,2,1,18 +2025-03-11T12:42:39.402267,479392960,65274,240,49.23879723332,37.46110939269,-87.591438415985,2,1,18 +2025-03-11T12:42:39.417892,479392960,65274,240,49.2340852367,37.4564801679,-87.58217072885,2,1,18 +2025-03-11T12:42:39.433517,479392960,65274,240,49.21994924684,37.45183463718,-87.554404747445,2,1,18 +2025-03-11T12:42:39.449142,479392960,65274,240,49.2105252536,37.437955115775,-87.535850833175,2,1,18 +2025-03-11T12:42:39.464767,479392960,65274,240,49.2105252536,37.419470828475,-87.52191312398,2,1,18 +2025-03-11T12:42:39.480392,479392960,65274,240,49.17754127726,37.39168732677,-87.466300220165,2,1,18 +2025-03-11T12:42:39.496017,479392960,65274,240,49.14926929754,37.38239626533,-87.42463180655,2,1,18 +2025-03-11T12:42:39.511642,479392960,65274,240,49.13513330768,37.35926644731,-87.38292811595,2,1,18 +2025-03-11T12:42:39.527267,479392960,65274,240,49.10686132796,37.336112170395,-87.3458252654,2,1,18 +2025-03-11T12:42:39.542892,479392960,65274,240,49.0927253381,37.312982352375,-87.308742757865,2,1,18 +2025-03-11T12:42:39.558517,479392960,65274,240,49.06445335838,37.285207003635,-87.26700018425,2,1,18 +2025-03-11T12:42:39.574142,479392960,65274,240,49.04089337528,37.25743980786,-87.20677965938,2,1,18 +2025-03-11T12:42:39.589767,479392960,65274,240,49.01262139556,37.225043387295,-87.146533813505,2,1,18 +2025-03-11T12:42:39.605392,479392960,65274,240,48.9749254226,37.188009588975,-87.09549823175,2,1,18 +2025-03-11T12:42:39.621017,479392960,65274,240,48.94194144626,37.155605015445,-87.021382055675,2,1,18 +2025-03-11T12:42:39.636642,479392960,65274,240,48.90895746992,37.123200441915,-86.95650824573,2,1,18 +2025-03-11T12:42:39.652267,479392960,65274,240,48.8806854902,37.076940805875,-86.89158559679,2,1,18 +2025-03-11T12:42:39.667892,479392960,65274,240,48.83827752062,37.035277782765,-86.817418778705,2,1,18 +2025-03-11T12:42:39.683517,479392960,65274,240,48.80529354428,36.993631065585,-86.747886705695,2,1,18 +2025-03-11T12:42:39.699142,479392960,65274,240,48.76759757132,36.956597267265,-86.68760875781,2,1,18 +2025-03-11T12:42:39.714767,479392960,65274,240,48.72047760512,36.910305019365,-86.61341661872,2,1,18 +2025-03-11T12:42:39.730392,479392960,65274,240,48.64979765582,36.859350934815,-86.529929668475,2,1,18 +2025-03-11T12:42:39.746017,479392960,65274,240,48.60267768962,36.81767975874,-86.428028970995,2,1,18 +2025-03-11T12:42:39.761642,479392960,65274,240,48.56498171666,36.77140381677,-86.316880929395,2,1,18 +2025-03-11T12:42:39.777267,479392960,65274,240,48.5272857437,36.711264659325,-86.196434901665,2,1,18 +2025-03-11T12:42:39.792892,479392960,65274,240,48.47074178426,36.65109289002,-86.103688848305,2,1,18 +2025-03-11T12:42:39.808517,479392960,65274,240,48.3859258451,36.600114346575,-85.99707563972,2,1,18 +2025-03-11T12:42:39.824142,479392960,65274,240,48.33409388228,36.530708586585,-85.8996781043,2,1,18 +2025-03-11T12:42:39.839767,479392960,65274,240,48.28697391608,36.465932051385,-85.78844234069,2,1,18 +2025-03-11T12:42:39.855392,479392960,65274,240,48.23042995664,36.39651813843,-85.663310925875,2,1,18 +2025-03-11T12:42:39.871017,479392960,65274,240,48.17859799382,36.32711237844,-85.556671024325,2,1,18 +2025-03-11T12:42:39.886642,479392960,65274,240,48.1032060479,36.2530447818,-85.436115128555,2,1,18 +2025-03-11T12:42:39.902267,479392960,65274,240,48.02781410198,36.183598256985,-85.297093040525,2,1,18 +2025-03-11T12:42:39.917892,479392960,65274,240,47.9618461493,36.1141680381,-85.1719480637,2,1,18 +2025-03-11T12:42:39.933517,479392960,65274,240,47.87231821352,36.05393919804,-85.03756389572,2,1,18 +2025-03-11T12:42:39.949142,479392960,65274,240,47.80635026084,35.99837219463,-84.90785335583,2,1,18 +2025-03-11T12:42:39.964767,479392960,65274,240,47.73567031154,35.924312750955,-84.759577142675,2,1,18 +2025-03-11T12:42:39.980392,479392960,65274,240,47.655566369,35.85023700135,-84.615908550575,2,1,18 +2025-03-11T12:42:39.996017,479392960,65274,240,47.5613264366,35.762273577375,-84.449058080135,2,1,18 +2025-03-11T12:42:40.011642,479392960,65274,240,47.48122249406,35.66971354047,-84.3099365111,2,1,18 +2025-03-11T12:42:40.027267,479392960,65274,240,47.41525454138,35.581799034285,-84.184717374275,2,1,18 +2025-03-11T12:42:40.042892,479392960,65274,240,47.3257266056,35.503085906925,-84.01791076484,2,1,18 +2025-03-11T12:42:40.058517,479392960,65274,240,47.24091066644,35.42438093253,-83.846489753345,2,1,18 +2025-03-11T12:42:40.074142,479392960,65274,240,47.15609472728,35.34105488631,-83.69353493411,2,1,18 +2025-03-11T12:42:40.089767,479392960,65274,240,47.0665667915,35.257720687125,-83.526709784675,2,1,18 +2025-03-11T12:42:40.105392,479392960,65274,240,46.96290286586,35.14201452627,-83.359734512225,2,1,18 +2025-03-11T12:42:40.121017,479392960,65274,240,46.8545269436,35.02630021245,-83.188131275705,2,1,18 +2025-03-11T12:42:40.136642,479392960,65274,240,46.75557501458,34.92908649186,-83.007373395065,2,1,18 +2025-03-11T12:42:40.152267,479392960,65274,240,46.6660470788,34.8318890772,-82.8312502595,2,1,18 +2025-03-11T12:42:40.167892,479392960,65274,240,46.57651914302,34.74393380619,-82.659785387,2,1,18 +2025-03-11T12:42:40.183517,479392960,65274,240,46.477567214,34.63747794195,-82.483611609425,2,1,18 +2025-03-11T12:42:40.199142,479392960,65274,240,46.36447929512,34.530997618815,-82.28431157351,2,1,18 +2025-03-11T12:42:40.214767,479392960,65274,240,46.25139137624,34.44300158298,-82.085085697595,2,1,18 +2025-03-11T12:42:40.230392,479392960,65274,240,46.13359146074,34.32727096323,-81.876499434545,2,1,18 +2025-03-11T12:42:40.246017,479392960,65274,240,46.01579154524,34.206919271655,-81.667894631495,2,1,18 +2025-03-11T12:42:40.261642,479392960,65274,240,45.90741562298,34.08658388601,-81.45468220739,2,1,18 +2025-03-11T12:42:40.277267,479392960,65274,240,45.79903970072,33.97086957219,-81.241488323285,2,1,18 +2025-03-11T12:42:40.292892,479392960,65274,240,45.69537577508,33.85978448316,-81.046804492445,2,1,18 +2025-03-11T12:42:40.308517,479392960,65274,240,45.5822878562,33.744062016375,-80.82898264427,2,1,18 +2025-03-11T12:42:40.324142,479392960,65274,240,45.47391193394,33.62372663073,-80.60190667097,2,1,18 +2025-03-11T12:42:40.339767,479392960,65274,240,45.35140002182,33.489503570715,-80.374754734655,2,1,18 +2025-03-11T12:42:40.355392,479392960,65274,240,45.22417611308,33.35989342956,-80.156856923465,2,1,18 +2025-03-11T12:42:40.371017,479392960,65274,240,45.10166420096,33.244154656845,-79.934400330215,2,1,18 +2025-03-11T12:42:40.386642,479392960,65274,240,44.9697282956,33.1283995782,-79.70730899189,2,1,18 +2025-03-11T12:42:40.402267,479392960,65274,240,44.82365640038,32.99413575336,-79.457017235225,2,1,18 +2025-03-11T12:42:40.417892,479392960,65274,240,44.69172049502,32.859896387415,-79.21136700464,2,1,18 +2025-03-11T12:42:40.433517,479392960,65274,240,44.55978458966,32.70717273417,-78.965642614055,2,1,18 +2025-03-11T12:42:40.449142,479392960,65274,240,44.43256068092,32.586804736665,-78.7431606998,2,1,18 +2025-03-11T12:42:40.464767,479392960,65274,240,44.30533677218,32.46643673916,-78.49757287022,2,1,18 +2025-03-11T12:42:40.480392,479392960,65274,240,44.1686888702,32.327568148425,-78.2426549525,2,1,18 +2025-03-11T12:42:40.496017,479392960,65274,240,44.03204096822,32.18869955769,-77.98773703478,2,1,18 +2025-03-11T12:42:40.511642,479392960,65274,240,43.90010506286,32.035975904445,-77.723527911935,2,1,18 +2025-03-11T12:42:40.527267,479392960,65274,240,43.75403316764,31.883227792305,-77.468540812205,2,1,18 +2025-03-11T12:42:40.542892,479392960,65274,240,43.60796127242,31.748963967465,-77.204385506345,2,1,18 +2025-03-11T12:42:40.558517,479392960,65274,240,43.47131337044,31.605474304905,-76.930964316365,2,1,18 +2025-03-11T12:42:40.574142,479392960,65274,240,43.32995347184,31.457355417555,-76.671381354575,2,1,18 +2025-03-11T12:42:40.589767,479392960,65274,240,43.17916958,31.3138412961,-76.402561004645,2,1,18 +2025-03-11T12:42:40.605392,479392960,65274,240,43.02367369154,31.17031902168,-76.119870324515,2,1,18 +2025-03-11T12:42:40.621017,479392960,65274,240,42.86346580646,31.00368323517,-75.841701346445,2,1,18 +2025-03-11T12:42:40.636642,479392960,65274,240,42.72210590786,30.83708006052,-75.545074760135,2,1,18 +2025-03-11T12:42:40.652267,479392960,65274,240,42.58545800588,30.688969326135,-75.280877396285,2,1,18 +2025-03-11T12:42:40.667892,479392960,65274,240,42.42053812418,30.526946458485,-75.00272017721,2,1,18 +2025-03-11T12:42:40.683517,479392960,65274,240,42.25090624586,30.35567329422,-74.701413181805,2,1,18 +2025-03-11T12:42:40.699142,479392960,65274,240,42.09069836078,30.19827965136,-74.40941773454,2,1,18 +2025-03-11T12:42:40.714767,479392960,65274,240,41.93991446894,30.04090231443,-74.108193483155,2,1,18 +2025-03-11T12:42:40.730392,479392960,65274,240,41.77028259062,29.869629150165,-73.80688648775,2,1,18 +2025-03-11T12:42:40.746017,479392960,65274,240,41.60536270892,29.698364138865,-73.49634390722,2,1,18 +2025-03-11T12:42:40.761642,479392960,65274,240,41.44044282722,29.527099127565,-73.20428605895,2,1,18 +2025-03-11T12:42:40.777267,479392960,65274,240,41.26138695566,29.369672872845,-72.89839993847,2,1,18 +2025-03-11T12:42:40.792892,479392960,65274,240,41.09646707396,29.20302893337,-72.58787589794,2,1,18 +2025-03-11T12:42:40.808517,479392960,65274,240,40.93625918888,29.01790885956,-72.26342092922,2,1,18 +2025-03-11T12:42:40.824142,479392960,65274,240,40.7524913207,28.832748020925,-71.93431087241,2,1,18 +2025-03-11T12:42:40.839767,479392960,65274,240,40.57814744576,28.661466703695,-71.609891180675,2,1,18 +2025-03-11T12:42:40.855392,479392960,65274,240,40.38966758096,28.476297712095,-71.294637892055,2,1,18 +2025-03-11T12:42:40.871017,479392960,65274,240,40.22003570264,28.300403476005,-70.970206441325,2,1,18 +2025-03-11T12:42:40.886642,479392960,65274,240,40.0456918277,28.119880015125,-70.641128486525,2,1,18 +2025-03-11T12:42:40.902267,479392960,65274,240,39.86192395952,27.939340248315,-70.30741578665,2,1,18 +2025-03-11T12:42:40.917892,479392960,65274,240,39.67815609134,27.758800481505,-69.964460720645,2,1,18 +2025-03-11T12:42:40.933517,479392960,65274,240,39.48496422992,27.559760121465,-69.63066029876,2,1,18 +2025-03-11T12:42:40.949142,479392960,65274,240,39.31062035498,27.369994516935,-69.30154526396,2,1,18 +2025-03-11T12:42:40.964767,479392960,65274,240,39.11742849356,27.198680587845,-68.95399253288,2,1,18 +2025-03-11T12:42:40.980392,479392960,65274,240,38.92423663214,27.02274558693,-68.611042444865,2,1,18 +2025-03-11T12:42:40.996017,479392960,65274,240,38.74046876396,26.83296367647,-68.281913848055,2,1,18 +2025-03-11T12:42:41.011642,479392960,65274,240,38.55198889916,26.624689325745,-67.91573484572,2,1,18 +2025-03-11T12:42:41.027267,479392960,65274,240,38.36822103098,26.416423127985,-67.554183807455,2,1,18 +2025-03-11T12:42:41.042892,479392960,65274,240,38.17974116618,26.20814877726,-67.19724717125,2,1,18 +2025-03-11T12:42:41.058517,479392960,65274,240,37.97712531152,26.022955326765,-66.845004075095,2,1,18 +2025-03-11T12:42:41.074142,479392960,65274,240,37.77450945686,25.823898660795,-66.478841809745,2,1,18 +2025-03-11T12:42:41.089767,479392960,65274,240,37.56718160558,25.610970626385,-66.107995960325,2,1,18 +2025-03-11T12:42:41.105392,479392960,65274,240,37.36456575092,25.42577717589,-65.732646948845,2,1,18 +2025-03-11T12:42:41.121017,479392960,65274,240,37.16666189288,25.21286544741,-65.34795111224,2,1,18 +2025-03-11T12:42:41.136642,479392960,65274,240,36.96404603822,25.00456663779,-64.967888217695,2,1,18 +2025-03-11T12:42:41.152267,479392960,65274,240,36.75671818694,24.81012289068,-64.587874162145,2,1,18 +2025-03-11T12:42:41.167892,479392960,65274,240,36.5352543458,24.597170397375,-64.221629152775,2,1,18 +2025-03-11T12:42:41.183517,479392960,65274,240,36.31850250128,24.384226057035,-63.841527375215,2,1,18 +2025-03-11T12:42:41.199142,479392960,65274,240,36.11588664662,24.16206403194,-63.4706512268,2,1,18 +2025-03-11T12:42:41.214767,479392960,65274,240,35.91798278858,23.95839444711,-63.09985601939,2,1,18 +2025-03-11T12:42:41.230392,479392960,65274,240,35.70594294068,23.745458259735,-62.701276290575,2,1,18 +2025-03-11T12:42:41.246017,479392960,65274,240,35.47976710292,23.541739757115,-62.284228566485,2,1,18 +2025-03-11T12:42:41.261642,479392960,65274,240,35.2630152584,23.328795416775,-61.885642056665,2,1,18 +2025-03-11T12:42:41.277267,479392960,65274,240,35.04155141726,23.10660077982,-61.49625405197,2,1,18 +2025-03-11T12:42:41.292892,479392960,65274,240,34.82951156936,22.884422448795,-61.09301606009,2,1,18 +2025-03-11T12:42:41.308517,479392960,65274,240,34.60804772822,22.67146995549,-60.685180403135,2,1,18 +2025-03-11T12:42:41.324142,479392960,65274,240,34.38658388708,22.45389639036,-60.28656857231,2,1,18 +2025-03-11T12:42:41.339767,479392960,65274,240,34.15098405608,22.245540509985,-59.901837027665,2,1,18 +2025-03-11T12:42:41.355392,479392960,65274,240,33.92480821832,22.00947450459,-59.48928070664,2,1,18 +2025-03-11T12:42:41.371017,479392960,65274,240,33.71276837042,21.77343295809,-59.081365911695,2,1,18 +2025-03-11T12:42:41.386642,479392960,65274,240,33.49130452928,21.551238321135,-58.65500844248,2,1,18 +2025-03-11T12:42:41.402267,479392960,65274,240,33.26512869152,21.329035531215,-58.214780643065,2,1,18 +2025-03-11T12:42:41.417892,479392960,65274,240,33.03895285376,21.10221166947,-57.816124951235,2,1,18 +2025-03-11T12:42:41.433517,479392960,65274,240,32.80335302276,20.86150828632,-57.408157711265,2,1,18 +2025-03-11T12:42:41.449142,479392960,65274,240,32.58188918162,20.620829362065,-56.98172608205,2,1,18 +2025-03-11T12:42:41.464767,479392960,65274,240,32.35571334386,20.380142284845,-56.559908854895,2,1,18 +2025-03-11T12:42:41.480392,479392960,65274,240,32.11068951962,20.13480152394,-56.142667146785,2,1,18 +2025-03-11T12:42:41.496017,479392960,65274,240,31.8939376751,19.907993968125,-55.72091910164,2,1,18 +2025-03-11T12:42:41.511642,479392960,65274,240,31.6818978272,19.671952421625,-55.28065602524,2,1,18 +2025-03-11T12:42:41.527267,479392960,65274,240,31.44158599958,19.426619813685,-54.84955754894,2,1,18 +2025-03-11T12:42:41.542892,479392960,65274,240,31.1871381821,19.185883818675,-54.42307845269,2,1,18 +2025-03-11T12:42:41.558517,479392960,65274,240,30.93740236124,18.940534904805,-53.987345231315,2,1,18 +2025-03-11T12:42:41.574142,479392960,65274,240,30.70180253024,18.70445259348,-53.53780588376,2,1,18 +2025-03-11T12:42:41.589767,479392960,65274,240,30.46149070262,18.472983201015,-53.102141844395,2,1,18 +2025-03-11T12:42:41.605392,479392960,65274,240,30.22589087162,18.241521961515,-52.65262103684,2,1,18 +2025-03-11T12:42:41.621017,479392960,65274,240,29.97615505076,18.014657334945,-52.207719609335,2,1,18 +2025-03-11T12:42:41.636642,479392960,65274,240,29.74055521976,17.76009073632,-51.762727284845,2,1,18 +2025-03-11T12:42:41.652267,479392960,65274,240,29.4908193989,17.49625753515,-51.303813988145,2,1,18 +2025-03-11T12:42:41.667892,479392960,65274,240,29.23637158142,17.24627939649,-50.8634342627,2,1,18 +2025-03-11T12:42:41.683517,479392960,65274,240,28.98663576056,17.01017262627,-50.400011022935,2,1,18 +2025-03-11T12:42:41.699142,479392960,65274,240,28.7368999397,16.760202640575,-49.95501689543,2,1,18 +2025-03-11T12:42:41.714767,479392960,65274,240,28.5013001087,16.519499257425,-49.496216641745,2,1,18 +2025-03-11T12:42:41.730392,479392960,65274,240,28.24685229122,16.23717361599,-49.02798003791,2,1,18 +2025-03-11T12:42:41.746017,479392960,65274,240,27.9829804805,15.97793702775,-48.569064938195,2,1,18 +2025-03-11T12:42:41.761642,479392960,65274,240,27.73795665626,15.723354123195,-48.1101955025,2,1,18 +2025-03-11T12:42:41.777267,479392960,65274,240,27.4882208354,15.44565770655,-47.637363036605,2,1,18 +2025-03-11T12:42:41.792892,479392960,65274,240,27.23377301792,15.191058496065,-47.155374123575,2,1,18 +2025-03-11T12:42:41.808517,479392960,65274,240,26.95576521734,14.936418520755,-46.69183603778,2,1,18 +2025-03-11T12:42:41.824142,479392960,65274,240,26.69189340662,14.69104514799,-46.232976558065,2,1,18 +2025-03-11T12:42:41.839767,479392960,65274,240,26.4280215959,14.43180855975,-45.760197909155,2,1,18 +2025-03-11T12:42:41.855392,479392960,65274,240,26.17357377842,14.158725061965,-45.268892469995,2,1,18 +2025-03-11T12:42:41.871017,479392960,65274,240,25.92383795756,13.885649717145,-44.7960785441,2,1,18 +2025-03-11T12:42:41.886642,479392960,65274,240,25.64583015698,13.640251885485,-44.314092806045,2,1,18 +2025-03-11T12:42:41.902267,479392960,65274,240,25.38195834626,13.38563636907,-43.841332697135,2,1,18 +2025-03-11T12:42:41.917892,479392960,65274,240,25.12279853216,13.12178686197,-43.354678740035,2,1,18 +2025-03-11T12:42:41.933517,479392960,65274,240,24.85892672144,12.86255027373,-42.854172992735,2,1,18 +2025-03-11T12:42:41.949142,479392960,65274,240,24.5903429141,12.58944231705,-42.367468393625,2,1,18 +2025-03-11T12:42:41.964767,479392960,65274,240,24.3311831,12.320971738125,-41.871553530395,2,1,18 +2025-03-11T12:42:41.980392,479392960,65274,240,24.07673528252,12.043267168515,-41.370987185105,2,1,18 +2025-03-11T12:42:41.995956,479392964,65270,241,23.79401548532,11.765513681115,-40.888864886045,2,1,18 +2025-03-11T12:42:42.011581,479392964,65270,241,23.52071968136,11.497018643295,-40.397550862865,2,1,18 +2025-03-11T12:42:42.027206,479392964,65270,241,23.25684787064,11.23316098323,-39.915511307825,2,1,18 +2025-03-11T12:42:42.042831,479392964,65270,241,22.99768805654,10.955448260655,-39.43342291379,2,1,18 +2025-03-11T12:42:42.058456,479392964,65270,241,22.71968025596,10.67770292622,-38.93744384654,2,1,18 +2025-03-11T12:42:42.074081,479392964,65270,241,22.43696045876,10.39994943882,-38.432215632155,2,1,18 +2025-03-11T12:42:42.089706,479392964,65270,241,22.1636646548,10.126833329175,-37.931640702845,2,1,18 +2025-03-11T12:42:42.105331,479392964,65270,241,21.89508084746,9.853725372495,-37.44031492067,2,1,18 +2025-03-11T12:42:42.120956,479392964,65270,241,21.6217850435,9.5898514065,-36.935155888295,2,1,18 +2025-03-11T12:42:42.136581,479392964,65270,241,21.34377724292,9.330590359365,-36.42538743185,2,1,18 +2025-03-11T12:42:42.152206,479392964,65270,241,21.06105744572,9.043594728315,-35.90625858827,2,1,18 +2025-03-11T12:42:42.167831,479392964,65270,241,20.78776164176,8.747373259545,-35.40559095896,2,1,18 +2025-03-11T12:42:42.183456,479392964,65270,241,20.5144658378,8.469636078075,-34.89575512352,2,1,18 +2025-03-11T12:42:42.199081,479392964,65270,241,20.23645803722,8.19189074364,-34.39053369014,2,1,18 +2025-03-11T12:42:42.214706,479392964,65270,241,19.95845023664,7.914145409205,-33.880691073695,2,1,18 +2025-03-11T12:42:42.230331,479392964,65270,241,19.68515443268,7.63178715591,-33.36621551519,2,1,18 +2025-03-11T12:42:42.245956,479392964,65270,241,19.40243463548,7.340170453035,-32.870174046935,2,1,18 +2025-03-11T12:42:42.261581,479392964,65270,241,19.1244268349,7.067046190425,-32.364971153555,2,1,18 +2025-03-11T12:42:42.277206,479392964,65270,241,18.8417070377,6.7846716312,-31.84123966691,2,1,18 +2025-03-11T12:42:42.292831,479392964,65270,241,18.55427524388,6.51153106266,-31.31753847926,2,1,18 +2025-03-11T12:42:42.308456,479392964,65270,241,18.24799546358,6.242978954085,-30.80307107372,2,1,18 +2025-03-11T12:42:42.324081,479392964,65270,241,17.95585167314,5.955967017105,-30.288549851195,2,1,18 +2025-03-11T12:42:42.339706,479392964,65270,241,17.69197986242,5.669003997915,-29.750963399375,2,1,18 +2025-03-11T12:42:42.355331,479392964,65270,241,17.40926006522,5.37738729504,-29.2179524666,2,1,18 +2025-03-11T12:42:42.370956,479392964,65270,241,17.12654026802,5.08114952034,-28.712650092215,2,1,18 +2025-03-11T12:42:42.386581,479392964,65270,241,16.84382047082,4.78491174564,-28.211968900895,2,1,18 +2025-03-11T12:42:42.402206,479392964,65270,241,16.55167668038,4.49789980866,-27.702068861435,2,1,18 +2025-03-11T12:42:42.417831,479392964,65270,241,16.26424488656,4.220138168295,-27.169106767655,2,1,18 +2025-03-11T12:42:42.433456,479392964,65270,241,15.97210109612,3.923884087665,-26.622200183675,2,1,18 +2025-03-11T12:42:42.449081,479392964,65270,241,15.67524530906,3.62762185407,-26.08452918482,2,1,18 +2025-03-11T12:42:42.464706,479392964,65270,241,15.38310151862,3.33136777344,-25.56534969923,2,1,18 +2025-03-11T12:42:42.480331,479392964,65270,241,15.10509371804,3.03975922353,-25.046209096655,2,1,18 +2025-03-11T12:42:42.495956,479392964,65270,241,14.80823793098,2.761981277235,-24.494748708605,2,1,18 +2025-03-11T12:42:42.511581,479392964,65270,241,14.52080613716,2.461114277745,-23.961693914825,2,1,18 +2025-03-11T12:42:42.527206,479392964,65270,241,14.23337434334,2.160247278255,-23.44250267024,2,1,18 +2025-03-11T12:42:42.542831,479392964,65270,241,13.94594254952,1.868622422415,-22.923348505655,2,1,18 +2025-03-11T12:42:42.558456,479392964,65270,241,13.64437476584,1.57697310768,-22.385689265795,2,1,18 +2025-03-11T12:42:42.574081,479392964,65270,241,13.34751897878,1.262226586785,-21.84794410694,2,1,18 +2025-03-11T12:42:42.589706,479392964,65270,241,13.05066319172,0.970585425015001,-21.29642809889,2,1,18 +2025-03-11T12:42:42.605331,479392964,65270,241,12.74909540804,0.692799325755001,-20.772688028225,2,1,18 +2025-03-11T12:42:42.620956,479392964,65270,241,12.45223962098,0.419642451285,-20.22586736324,2,1,18 +2025-03-11T12:42:42.636581,479392964,65270,241,12.16480782716,0.109533308145001,-19.6742907572,2,1,18 +2025-03-11T12:42:42.652206,479392964,65270,241,11.88680002658,-0.19593845724,-19.15047335156,2,1,18 +2025-03-11T12:42:42.667831,479392964,65270,241,11.58994423952,-0.492200690834999,-18.622044718835,2,1,18 +2025-03-11T12:42:42.683456,479392964,65270,241,11.28837645584,-0.779228933745,-18.07978283591,2,1,18 +2025-03-11T12:42:42.699081,479392964,65270,241,10.98680867216,-1.07087824848,-17.537502412985,2,1,18 +2025-03-11T12:42:42.714706,479392964,65270,241,10.70408887496,-1.371737095005,-16.98596966795,2,1,18 +2025-03-11T12:42:42.730331,479392964,65270,241,10.41194508452,-1.67261224746,-16.43904454397,2,1,18 +2025-03-11T12:42:42.745956,479392964,65270,241,10.11037730084,-1.96888263402,-15.91060913024,2,1,18 +2025-03-11T12:42:42.761581,479392964,65270,241,9.80409752054,-2.274403317195,-15.372887489375,2,1,18 +2025-03-11T12:42:42.777206,479392964,65270,241,9.52608971996,-2.57987508258,-14.821342985345,2,1,18 +2025-03-11T12:42:42.792831,479392964,65270,241,9.2292339329,-2.866895172525,-14.260603151165,2,1,18 +2025-03-11T12:42:42.808456,479392964,65270,241,8.92766614922,-3.181649846385,-13.71823002824,2,1,18 +2025-03-11T12:42:42.824081,479392964,65270,241,8.63081036216,-3.48715422363,-13.180521949385,2,1,18 +2025-03-11T12:42:42.839706,479392964,65270,241,8.33866657172,-3.76492401696,-12.62906834234,2,1,18 +2025-03-11T12:42:42.855331,479392964,65270,241,8.04652278128,-4.05193595394,-12.068335289165,2,1,18 +2025-03-11T12:42:42.870956,479392964,65270,241,7.74966699422,-4.357440331185,-11.526006027245,2,1,18 +2025-03-11T12:42:42.886581,479392964,65270,241,7.45281120716,-4.66294470843,-10.98829794839,2,1,18 +2025-03-11T12:42:42.902206,479392964,65270,241,7.15124342348,-4.96845723864,-10.455204271595,2,1,18 +2025-03-11T12:42:42.917831,479392964,65270,241,6.84496364318,-5.273977921815,-9.931346179925,2,1,18 +2025-03-11T12:42:42.933456,479392964,65270,241,6.53868386288,-5.574877533165,-9.389021895995,2,1,18 +2025-03-11T12:42:42.949081,479392964,65270,241,6.2371160792,-5.8665268479,-8.86522620533,2,1,18 +2025-03-11T12:42:42.964706,479392964,65270,241,5.94968428538,-6.162772775565,-8.327568768485,2,1,18 +2025-03-11T12:42:42.980331,479392964,65270,241,5.63869250846,-6.449817324405,-7.78529332355,2,1,18 +2025-03-11T12:42:42.995956,479392964,65270,241,5.3418367214,-6.746079558,-7.22451640937,2,1,18 +2025-03-11T12:42:43.011581,479392964,65270,241,5.04969293096,-7.06081792593,-6.68677803152,2,1,18 +2025-03-11T12:42:43.027206,479392964,65270,241,4.74812514728,-7.370951527965,-6.144423448595,2,1,18 +2025-03-11T12:42:43.042831,479392964,65270,241,4.4465573636,-7.676464058175,-5.59284503954,2,1,18 +2025-03-11T12:42:43.058456,479392964,65270,241,4.15441357316,-7.97733921063,-5.0274351833,2,1,18 +2025-03-11T12:42:43.074081,479392964,65270,241,3.8575577861,-8.264359300575,-4.480558898315,2,1,18 +2025-03-11T12:42:43.089706,479392964,65270,241,3.56541399566,-8.56523445303,-3.942876140465,2,1,18 +2025-03-11T12:42:43.105331,479392964,65270,241,3.25442221874,-8.86152114552,-3.40056361553,2,1,18 +2025-03-11T12:42:43.120956,479392964,65270,241,2.94814243844,-9.157799685045,-2.8582578716,2,1,18 +2025-03-11T12:42:43.136581,479392964,65270,241,2.64657465476,-9.472554358905,-2.315884748675,2,1,18 +2025-03-11T12:42:43.152206,479392964,65270,241,2.3497188677,-9.773437664325,-1.745846928365,2,1,18 +2025-03-11T12:42:43.167831,479392964,65270,241,2.05757507726,-10.078933888605,-1.18503971519,2,1,18 +2025-03-11T12:42:43.183456,479392964,65270,241,1.77014328344,-10.370558744445,-0.638158452215,2,1,18 +2025-03-11T12:42:43.199081,479392964,65270,241,1.47328749638,-10.68530526534,-0.105034476425,2,1,18 +2025-03-11T12:42:43.214706,479392964,65270,241,1.18114370594,-10.986180417795,0.451133013685,2,1,18 +2025-03-11T12:42:43.230331,479392964,65270,241,0.87957592226,-11.26858758888,0.98413399048,2,1,18 +2025-03-11T12:42:43.245956,479392964,65270,241,0.5591601521,-11.551027371825,1.52178327436,2,1,18 +2025-03-11T12:42:43.261581,479392964,65270,241,0.24816837518,-11.856556207965,2.08723879462,2,1,18 +2025-03-11T12:42:43.277206,479392964,65270,241,-0.0486874118800001,-12.166681657035,2.62034423041,2,1,18 +2025-03-11T12:42:43.292831,479392964,65270,241,-0.34083120232,-12.472177881315,3.15804552826,2,1,18 +2025-03-11T12:42:43.308456,479392964,65270,241,-0.64711098262,-12.78694070814,3.70966779832,2,1,18 +2025-03-11T12:42:43.324081,479392964,65270,241,-0.94396676968,-13.08782401356,4.256599703305,2,1,18 +2025-03-11T12:42:43.339706,479392964,65270,241,-1.23611056012,-13.379457022365,4.78038183196,2,1,18 +2025-03-11T12:42:43.355331,479392964,65270,241,-1.53296634718,-13.661856040485,5.33186076001,2,1,18 +2025-03-11T12:42:43.370956,479392964,65270,241,-1.82982213424,-13.95811827408,5.888016491125,2,1,18 +2025-03-11T12:42:43.386581,479392964,65270,241,-2.1266779213,-14.24975943585,6.44415368224,2,1,18 +2025-03-11T12:42:43.402206,479392964,65270,241,-2.42824570498,-14.54602982241,6.986452645165,2,1,18 +2025-03-11T12:42:43.417831,479392964,65270,241,-2.72038949542,-14.837662831215,7.524098323015,2,1,18 +2025-03-11T12:42:43.433456,479392964,65270,241,-3.0219572791,-15.14779643325,8.071074089005,2,1,18 +2025-03-11T12:42:43.449081,479392964,65270,241,-3.33766105264,-15.462575566005,8.604225188815,2,1,18 +2025-03-11T12:42:43.464706,479392964,65270,241,-3.62980484308,-15.74496643116,9.151076152795,2,1,18 +2025-03-11T12:42:43.480331,479392964,65270,241,-3.91252464028,-16.04120420586,9.679484442505,2,1,18 +2025-03-11T12:42:43.495956,479392964,65270,241,-4.20466843072,-16.351321501965,10.22182546342,2,1,18 +2025-03-11T12:42:43.511581,479392964,65270,241,-4.51094821102,-16.661463256965,10.76418682735,2,1,18 +2025-03-11T12:42:43.527206,479392964,65270,241,-4.80309200146,-16.95309626577,11.29259013907,2,1,18 +2025-03-11T12:42:43.542831,479392964,65270,241,-5.09994778852,-17.23549528389,11.82558433486,2,1,18 +2025-03-11T12:42:43.558456,479392964,65270,241,-5.39209157896,-17.53174936452,12.36324855271,2,1,18 +2025-03-11T12:42:43.574081,479392964,65270,241,-5.67009937954,-17.837221129905,12.900929507545,2,1,18 +2025-03-11T12:42:43.589706,479392964,65270,241,-5.94810718012,-18.128829679815,13.424691293185,2,1,18 +2025-03-11T12:42:43.605331,479392964,65270,241,-6.23553897394,-18.411212392005,13.957671926965,2,1,18 +2025-03-11T12:42:43.620956,479392964,65270,241,-6.53710675762,-18.69361956309,14.495294086825,2,1,18 +2025-03-11T12:42:43.636581,479392964,65270,241,-6.84809853454,-18.985285183755,15.032966888695,2,1,18 +2025-03-11T12:42:43.652206,479392964,65270,241,-7.1213943385,-19.281506652525,15.579846348655,2,1,18 +2025-03-11T12:42:43.667831,479392964,65270,241,-7.4041141357,-19.577744427225,16.108254638365,2,1,18 +2025-03-11T12:42:43.683456,479392964,65270,241,-7.70096992276,-19.87400666082,16.641304454155,2,1,18 +2025-03-11T12:42:43.699081,479392964,65270,241,-7.99782570982,-20.16564782259,17.155850997685,2,1,18 +2025-03-11T12:42:43.714706,479392964,65270,241,-8.28996950026,-20.466522975045,17.67967020634,2,1,18 +2025-03-11T12:42:43.730331,479392964,65270,241,-8.57268929746,-20.75813967792,18.175711674595,2,1,18 +2025-03-11T12:42:43.745956,479392964,65270,241,-8.86012109128,-21.03128024646,18.70403404531,2,1,18 +2025-03-11T12:42:43.761581,479392964,65270,241,-9.16640087158,-21.33217985781,19.22787359698,2,1,18 +2025-03-11T12:42:43.777206,479392964,65270,241,-9.45854466202,-21.60994965114,19.7562212887,2,1,18 +2025-03-11T12:42:43.792831,479392964,65270,241,-9.7365524626,-21.8923160574,20.275324811275,2,1,18 +2025-03-11T12:42:43.808456,479392964,65270,241,-10.01456026318,-22.179303535485,20.808310423045,2,1,18 +2025-03-11T12:42:43.824081,479392964,65270,241,-10.28314407052,-22.470895779465,21.332058646675,2,1,18 +2025-03-11T12:42:43.839706,479392964,65270,241,-10.5611518711,-22.7671254012,21.86046015538,2,1,18 +2025-03-11T12:42:43.855331,479392964,65270,241,-10.8438716683,-23.0448788886,22.38879428509,2,1,18 +2025-03-11T12:42:43.870956,479392964,65270,241,-11.1265914655,-23.327253447825,22.89866222254,2,1,18 +2025-03-11T12:42:43.886581,479392964,65270,241,-11.4093112627,-23.6188701507,23.422430789185,2,1,18 +2025-03-11T12:42:43.902206,479392964,65270,241,-11.68731906328,-23.887373341485,23.936857508695,2,1,18 +2025-03-11T12:42:43.917831,479392964,65270,241,-11.9747508571,-24.1558928382,24.451297790215,2,1,18 +2025-03-11T12:42:43.933456,479392964,65270,241,-12.2574706543,-24.44288846925,24.979668999925,2,1,18 +2025-03-11T12:42:43.949081,479392964,65270,241,-12.5401904515,-24.725263028475,25.498779303505,2,1,18 +2025-03-11T12:42:43.964706,479392964,65270,241,-12.84175823518,-24.98918591226,25.99473665578,2,1,18 +2025-03-11T12:42:43.980331,479392964,65270,241,-13.11976603576,-25.29003660582,26.50005078916,2,1,18 +2025-03-11T12:42:43.995956,479392964,65270,241,-13.40248583296,-25.572411165045,27.00991872661,2,1,18 +2025-03-11T12:42:44.011581,479392964,65270,241,-13.68049363354,-25.854777571305,27.50591633386,2,1,18 +2025-03-11T12:42:44.027206,479392964,65270,241,-13.94436544426,-26.12787737502,28.020341250355,2,1,18 +2025-03-11T12:42:44.042831,479392964,65270,241,-14.21766124822,-26.40561455649,28.52555590273,2,1,18 +2025-03-11T12:42:44.058456,479392964,65270,241,-14.50980503866,-26.688005421645,29.01695266993,2,1,18 +2025-03-11T12:42:44.074081,479392964,65270,241,-14.79723683248,-26.951903846535,29.51288967919,2,1,18 +2025-03-11T12:42:44.089706,479392964,65270,241,-15.05168464996,-27.21574520067,30.00415803835,2,1,18 +2025-03-11T12:42:44.105331,479392964,65270,241,-15.31084446406,-27.50732113872,30.504786784645,2,1,18 +2025-03-11T12:42:44.120956,479392964,65270,241,-15.5794282714,-27.794292310875,31.000789369885,2,1,18 +2025-03-11T12:42:44.136581,479392964,65270,241,-15.85743607198,-28.048932286185,31.487433371005,2,1,18 +2025-03-11T12:42:44.152206,479392964,65270,241,-16.1213078827,-28.317411018075,31.978733832175,2,1,18 +2025-03-11T12:42:44.167831,479392964,65270,241,-16.38517969342,-28.57202653449,32.47459985641,2,1,18 +2025-03-11T12:42:44.183456,479392964,65270,241,-16.65376350076,-28.84513449117,32.965925638585,2,1,18 +2025-03-11T12:42:44.199081,479392964,65270,241,-16.93177130134,-29.113637681955,33.452625259705,2,1,18 +2025-03-11T12:42:44.214706,479392964,65270,241,-17.20977910192,-29.386761944565,33.930101054695,2,1,18 +2025-03-11T12:42:44.230331,479392964,65270,241,-17.47365091264,-29.65061960463,34.42600415893,2,1,18 +2025-03-11T12:42:44.245956,479392964,65270,241,-17.72809873012,-29.92832417424,34.894222222765,2,1,18 +2025-03-11T12:42:44.261581,479392964,65270,241,-17.98725854422,-30.18293153769,35.380839099865,2,1,18 +2025-03-11T12:42:44.277206,479392964,65270,241,-18.23699436508,-30.43752259521,35.876684781085,2,1,18 +2025-03-11T12:42:44.292831,479392964,65270,241,-18.49615417918,-30.71061424596,36.34026990286,2,1,18 +2025-03-11T12:42:44.308456,479392964,65270,241,-18.75060199666,-30.974455600095,36.799189980565,2,1,18 +2025-03-11T12:42:44.324081,479392964,65270,241,-19.01447380738,-31.23831326016,37.271987169475,2,1,18 +2025-03-11T12:42:44.339706,479392964,65270,241,-19.26892162486,-31.47904925517,37.744678096375,2,1,18 +2025-03-11T12:42:44.355331,479392964,65270,241,-19.52336944234,-31.742890609305,38.21284054021,2,1,18 +2025-03-11T12:42:44.370956,479392964,65270,241,-19.79195324968,-31.997514278685,38.69947097932,2,1,18 +2025-03-11T12:42:44.386581,479392964,65270,241,-20.04640106716,-32.256734560995,39.167614883155,2,1,18 +2025-03-11T12:42:44.402206,479392964,65270,241,-20.30556088126,-32.50672085262,39.608001389605,2,1,18 +2025-03-11T12:42:44.417831,479392964,65270,241,-20.56943269198,-32.752094225385,40.05761850319,2,1,18 +2025-03-11T12:42:44.433456,479392964,65270,241,-20.82388050946,-33.011314507695,40.535004773155,2,1,18 +2025-03-11T12:42:44.449081,479392964,65270,241,-21.0689043337,-33.28438169955,40.998569551915,2,1,18 +2025-03-11T12:42:44.464706,479392964,65270,241,-21.31392815794,-33.53434353228,41.47590517987,2,1,18 +2025-03-11T12:42:44.480331,479392964,65270,241,-21.56837597542,-33.770458455465,41.92085046838,2,1,18 +2025-03-11T12:42:44.495956,479392964,65270,241,-21.7992638098,-34.025016901125,42.34273009654,2,1,18 +2025-03-11T12:42:44.511581,479392964,65270,241,-22.04428763404,-34.274978733855,42.79695980917,2,1,18 +2025-03-11T12:42:44.527206,479392964,65270,241,-22.28931145828,-34.515698422935,43.255773624865,2,1,18 +2025-03-11T12:42:44.542831,479392964,65270,241,-22.52491128928,-34.76102287791,43.71459241855,2,1,18 +2025-03-11T12:42:44.558456,479392964,65270,241,-22.77935910676,-34.99251672927,44.15951916706,2,1,18 +2025-03-11T12:42:44.574081,479392964,65270,241,-23.03851892086,-35.242503020895,44.586042124315,2,1,18 +2025-03-11T12:42:44.589706,479392964,65270,241,-23.26940675524,-35.49244039473,45.026387944735,2,1,18 +2025-03-11T12:42:44.605331,479392964,65270,241,-23.50500658624,-35.728522706055,45.462063743095,2,1,18 +2025-03-11T12:42:44.620956,479392964,65270,241,-23.74060641724,-35.959983945555,45.906963367585,2,1,18 +2025-03-11T12:42:44.636581,479392964,65270,241,-23.98563024148,-36.200703634635,46.342671267955,2,1,18 +2025-03-11T12:42:44.652206,479392964,65270,241,-24.23536606234,-36.44143147668,46.78762831546,2,1,18 +2025-03-11T12:42:44.667831,479392964,65270,241,-24.47567788996,-36.67752194097,47.204826162565,2,1,18 +2025-03-11T12:42:44.683456,479392964,65270,241,-24.71127772096,-36.922846395945,47.631296674795,2,1,18 +2025-03-11T12:42:44.699081,479392964,65270,241,-24.93745355872,-37.163533473165,48.076219817275,2,1,18 +2025-03-11T12:42:44.714706,479392964,65270,241,-25.16362939648,-37.404220550385,48.484173495235,2,1,18 +2025-03-11T12:42:44.730331,479392964,65270,241,-25.38980523424,-37.626423340305,48.901295379325,2,1,18 +2025-03-11T12:42:44.745956,479392964,65270,241,-25.62540506524,-37.85326350798,49.327691731555,2,1,18 +2025-03-11T12:42:44.761581,479392964,65270,241,-25.86100489624,-38.098587962955,49.74954106072,2,1,18 +2025-03-11T12:42:44.777206,479392964,65270,241,-26.09660472724,-38.311564915155,50.162018243755,2,1,18 +2025-03-11T12:42:44.792831,479392964,65270,241,-26.322780565,-38.524525561425,50.55599713252,2,1,18 +2025-03-11T12:42:44.808456,479392964,65270,241,-26.54424440614,-38.751341270205,50.973130775605,2,1,18 +2025-03-11T12:42:44.824081,479392964,65270,241,-26.76570824728,-38.978156978985,51.38102205256,2,1,18 +2025-03-11T12:42:44.839706,479392964,65270,241,-26.97774809518,-39.18185102271,51.79342825057,2,1,18 +2025-03-11T12:42:44.855331,479392964,65270,241,-27.1944999397,-39.4040375067,52.178188291195,2,1,18 +2025-03-11T12:42:44.870956,479392964,65270,241,-27.42067577746,-39.61699815297,52.57216717996,2,1,18 +2025-03-11T12:42:44.886581,479392964,65270,241,-27.63742762198,-39.834563565135,52.97077222978,2,1,18 +2025-03-11T12:42:44.902206,479392964,65270,241,-27.85889146312,-40.061379273915,53.369421140605,2,1,18 +2025-03-11T12:42:44.917831,479392964,65270,241,-28.08035530426,-40.278952839045,53.763411788365,2,1,18 +2025-03-11T12:42:44.933456,479392964,65270,241,-28.28768315554,-40.49650194528,54.14813972698,2,1,18 +2025-03-11T12:42:44.949081,479392964,65270,241,-28.48087501696,-40.718647664445,54.509759947255,2,1,18 +2025-03-11T12:42:44.964706,479392964,65270,241,-28.69291486486,-40.92234170817,54.885196680745,2,1,18 +2025-03-11T12:42:44.980331,479392964,65270,241,-28.90966670938,-41.11680176121,55.28833021363,2,1,18 +2025-03-11T12:42:44.995956,479392964,65270,241,-29.12170655728,-41.311253661285,55.69145696551,2,1,18 +2025-03-11T12:42:45.011581,479392964,65270,241,-29.32903440856,-41.53804491117,56.07160080106,2,1,18 +2025-03-11T12:42:45.027206,479392964,65270,241,-29.51751427336,-41.746319261895,56.4239162542,2,1,18 +2025-03-11T12:42:45.042831,479392964,65270,241,-29.73426611788,-41.94540038676,56.7854776795,2,1,18 +2025-03-11T12:42:45.058456,479392964,65270,241,-29.93688197254,-42.149078124555,57.165522034045,2,1,18 +2025-03-11T12:42:45.074081,479392964,65270,241,-30.1394978272,-42.348134790525,57.53630548246,2,1,18 +2025-03-11T12:42:45.089706,479392964,65270,241,-30.34211368186,-42.556433600145,57.89326246168,2,1,18 +2025-03-11T12:42:45.105331,479392964,65270,241,-30.5400175399,-42.7462399695,58.259380866025,2,1,18 +2025-03-11T12:42:45.120956,479392964,65270,241,-30.7284974047,-42.945272176575,58.62552278836,2,1,18 +2025-03-11T12:42:45.136581,479392964,65270,241,-30.91226527288,-43.125811943385,58.99158376969,2,1,18 +2025-03-11T12:42:45.152206,479392964,65270,241,-31.1054571343,-43.315610159775,59.32996829464,2,1,18 +2025-03-11T12:42:45.167831,479392964,65270,241,-31.30807298896,-43.51928789757,59.67766436773,2,1,18 +2025-03-11T12:42:45.183456,479392964,65270,241,-31.50126485038,-43.722949329435,60.01610451268,2,1,18 +2025-03-11T12:42:45.199081,479392964,65270,241,-31.6944567118,-43.908126474,60.35447049763,2,1,18 +2025-03-11T12:42:45.214706,479392964,65270,241,-31.86880058674,-44.102513150355,60.678982889365,2,1,18 +2025-03-11T12:42:45.230331,479392964,65270,241,-32.05728045154,-44.278439998305,61.00806264718,2,1,18 +2025-03-11T12:42:45.245956,479392964,65270,241,-32.24104831972,-44.458979765115,61.34639653012,2,1,18 +2025-03-11T12:42:45.261581,479392964,65270,241,-32.4248161879,-44.639519531925,61.689351596125,2,1,18 +2025-03-11T12:42:45.277206,479392964,65270,241,-32.62272004594,-44.815462685805,62.02768728208,2,1,18 +2025-03-11T12:42:45.292831,479392964,65270,241,-32.79706392088,-45.005228290335,62.342938767685,2,1,18 +2025-03-11T12:42:45.308456,479392964,65270,241,-32.97140779582,-45.19961496669,62.653587610225,2,1,18 +2025-03-11T12:42:45.324081,479392964,65270,241,-33.15988766062,-45.370920742815,62.978027644975,2,1,18 +2025-03-11T12:42:45.339706,479392964,65270,241,-33.33423153556,-45.52833884457,63.307012899775,2,1,18 +2025-03-11T12:42:45.355331,479392964,65270,241,-33.49915141726,-45.704224927695,63.617574020305,2,1,18 +2025-03-11T12:42:45.370956,479392964,65270,241,-33.6734952922,-45.875506244925,63.92350897978,2,1,18 +2025-03-11T12:42:45.386581,479392964,65270,241,-33.84783916714,-46.03292434668,64.24325186845,2,1,18 +2025-03-11T12:42:45.402206,479392964,65270,241,-34.01275904884,-46.19494721433,64.539893819785,2,1,18 +2025-03-11T12:42:45.417831,479392964,65270,241,-34.16354294068,-46.38005098221,64.84122931117,2,1,18 +2025-03-11T12:42:45.433456,479392964,65270,241,-34.32846282238,-46.546694921685,65.147132168635,2,1,18 +2025-03-11T12:42:45.449081,479392964,65270,241,-34.48867070746,-46.704088564545,65.44836998203,2,1,18 +2025-03-11T12:42:45.464706,479392964,65270,241,-34.6394545993,-46.870708045125,65.76349486261,2,1,18 +2025-03-11T12:42:45.480331,479392964,65270,241,-34.80908647762,-47.037360137565,66.064783318015,2,1,18 +2025-03-11T12:42:45.495956,479392964,65270,241,-34.96458236608,-47.190124555635,66.34288989508,2,1,18 +2025-03-11T12:42:45.511581,479392964,65270,241,-35.12950224778,-47.33828420781,66.620991494155,2,1,18 +2025-03-11T12:42:45.527206,479392964,65270,241,-35.29442212948,-47.504928147285,66.90840961936,2,1,18 +2025-03-11T12:42:45.542831,479392964,65270,241,-35.44991801794,-47.666934709005,67.18193209336,2,1,18 +2025-03-11T12:42:45.558456,479392964,65270,241,-35.59127791654,-47.81967466818,67.464639510475,2,1,18 +2025-03-11T12:42:45.574081,479392964,65270,241,-35.75148580162,-47.96782616739,67.733491962415,2,1,18 +2025-03-11T12:42:45.589706,479392964,65270,241,-35.89755769684,-48.115953207705,67.99308170521,2,1,18 +2025-03-11T12:42:45.605331,479392964,65270,241,-36.03891759544,-48.273314238705,68.266565296195,2,1,18 +2025-03-11T12:42:45.620956,479392964,65270,241,-36.17556549742,-48.42142497309,68.53538384311,2,1,18 +2025-03-11T12:42:45.636581,479392964,65270,241,-36.33106138588,-48.57418939116,68.79038450485,2,1,18 +2025-03-11T12:42:45.652206,479392964,65270,241,-36.48184527772,-48.699219225315,69.045267145585,2,1,18 +2025-03-11T12:42:45.667831,479392964,65270,241,-36.60906918646,-48.824208294645,69.2862523321,2,1,18 +2025-03-11T12:42:45.683456,479392964,65270,241,-36.74100509182,-48.95844766059,69.541144928815,2,1,18 +2025-03-11T12:42:45.699081,479392964,65270,241,-36.87294099718,-49.09730809836,69.77757133327,2,1,18 +2025-03-11T12:42:45.714706,479392964,65270,241,-37.00958889916,-49.236176689095,70.01400451873,2,1,18 +2025-03-11T12:42:45.730331,479392964,65270,241,-37.15094879776,-49.37043236097,70.25504712826,2,1,18 +2025-03-11T12:42:45.745956,479392964,65270,241,-37.28759669974,-49.49543773623,70.51915179211,2,1,18 +2025-03-11T12:42:45.761581,479392964,65270,241,-37.4195326051,-49.611192814875,70.74162194737,2,1,18 +2025-03-11T12:42:45.777206,479392964,65270,241,-37.52790852736,-49.73152820052,70.96869792067,2,1,18 +2025-03-11T12:42:45.792831,479392964,65270,241,-37.64570844286,-49.86574310757,71.209706625175,2,1,18 +2025-03-11T12:42:45.808456,479392964,65270,241,-37.76822035498,-49.990724023935,71.43682148149,2,1,18 +2025-03-11T12:42:45.824081,479392964,65270,241,-37.8907322671,-50.111083868475,71.65005424861,2,1,18 +2025-03-11T12:42:45.839706,479392964,65270,241,-37.99910818936,-50.22217711047,71.86785077578,2,1,18 +2025-03-11T12:42:45.855331,479392964,65270,241,-38.11690810486,-50.333286658395,72.081039681895,2,1,18 +2025-03-11T12:42:45.870956,479392964,65270,241,-38.22999602374,-50.462872340655,72.29891715007,2,1,18 +2025-03-11T12:42:45.886581,479392964,65270,241,-38.338371946,-50.587828798125,72.502905748045,2,1,18 +2025-03-11T12:42:45.902206,479392964,65270,241,-38.4561718615,-50.703559417875,72.720734377225,2,1,18 +2025-03-11T12:42:45.917831,479392964,65270,241,-38.56925978038,-50.81003974101,72.92927677927,2,1,18 +2025-03-11T12:42:45.933456,479392964,65270,241,-38.68234769926,-50.916520064145,73.128576815185,2,1,18 +2025-03-11T12:42:45.949081,479392964,65270,241,-38.80014761476,-51.032250683895,73.31405716291,2,1,18 +2025-03-11T12:42:45.964706,479392964,65270,241,-38.90852353702,-51.14334392589,73.48564185943,2,1,18 +2025-03-11T12:42:45.980331,479392964,65270,241,-39.00276346942,-51.249791637165,73.661808856,2,1,18 +2025-03-11T12:42:45.995880,479392968,65265,242,-39.10171539844,-51.35162642958,73.847206459705,2,1,18 +2025-03-11T12:42:46.011505,479392968,65265,242,-39.20066732746,-51.43959800652,74.03254844341,2,1,18 +2025-03-11T12:42:46.027130,479392968,65265,242,-39.29019526324,-51.51831113388,74.20397623591,2,1,18 +2025-03-11T12:42:46.042755,479392968,65265,242,-39.3985711855,-51.610920088575,74.38472913856,2,1,18 +2025-03-11T12:42:46.058380,479392968,65265,242,-39.4928111179,-51.71736779985,74.547032585935,2,1,18 +2025-03-11T12:42:46.074005,479392968,65265,242,-39.5870510503,-51.80995229565,74.713901596375,2,1,18 +2025-03-11T12:42:46.089630,479392968,65265,242,-39.6812909827,-51.90253679145,74.890012972945,2,1,18 +2025-03-11T12:42:46.105255,479392968,65265,242,-39.78495490834,-51.98589544953,75.066100831525,2,1,18 +2025-03-11T12:42:46.120880,479392968,65265,242,-39.86505885088,-52.069213342785,75.228291235885,2,1,18 +2025-03-11T12:42:46.136505,479392968,65265,242,-39.95458678666,-52.157168613795,75.372029009995,2,1,18 +2025-03-11T12:42:46.152130,479392968,65265,242,-40.02997873258,-52.240478354085,75.51572790109,2,1,18 +2025-03-11T12:42:46.167755,479392968,65265,242,-40.09123468864,-52.30527934818,75.654711106105,2,1,18 +2025-03-11T12:42:46.183380,479392968,65265,242,-40.17133863118,-52.379355097785,75.798379698205,2,1,18 +2025-03-11T12:42:46.199005,479392968,65265,242,-40.26086656696,-52.458068225145,75.942080392315,2,1,18 +2025-03-11T12:42:46.214630,479392968,65265,242,-40.33625851288,-52.54599903726,76.062691908085,2,1,18 +2025-03-11T12:42:46.230255,479392968,65265,242,-40.4116504588,-52.624687705725,76.19712989305,2,1,18 +2025-03-11T12:42:46.245880,479392968,65265,242,-40.46819441824,-52.70334376233,76.33616193706,2,1,18 +2025-03-11T12:42:46.261505,479392968,65265,242,-40.53416237092,-52.763531837565,76.44740628469,2,1,18 +2025-03-11T12:42:46.277130,479392968,65265,242,-40.60484232022,-52.82834913759,76.58178186865,2,1,18 +2025-03-11T12:42:46.292755,479392968,65265,242,-40.67552226952,-52.90702965309,76.71621307261,2,1,18 +2025-03-11T12:42:46.308380,479392968,65265,242,-40.74620221882,-52.971846953115,76.845967473505,2,1,18 +2025-03-11T12:42:46.324005,479392968,65265,242,-40.79803418164,-53.022768425805,76.95715439812,2,1,18 +2025-03-11T12:42:46.339630,479392968,65265,242,-40.84986614446,-53.082932042145,77.059136036605,2,1,18 +2025-03-11T12:42:46.355255,479392968,65265,242,-40.9064101039,-53.138482739625,77.142621183835,2,1,18 +2025-03-11T12:42:46.370880,479392968,65265,242,-40.96766605996,-53.20328373372,77.230771375135,2,1,18 +2025-03-11T12:42:46.386505,479392968,65265,242,-41.02892201602,-53.24497936869,77.34193478176,2,1,18 +2025-03-11T12:42:46.402130,479392968,65265,242,-41.0948899687,-53.286683156625,77.439241420195,2,1,18 +2025-03-11T12:42:46.417755,479392968,65265,242,-41.1420099349,-53.342217548175,77.53657655461,2,1,18 +2025-03-11T12:42:46.433380,479392968,65265,242,-41.18441790448,-53.37925949946,77.62458838189,2,1,18 +2025-03-11T12:42:46.449005,479392968,65265,242,-41.22211387744,-53.420914369605,77.703369602035,2,1,18 +2025-03-11T12:42:46.464630,479392968,65265,242,-41.2598098504,-53.46256923975,77.78215082218,2,1,18 +2025-03-11T12:42:46.480255,479392968,65265,242,-41.29750582336,-53.51808732537,77.837881747,2,1,18 +2025-03-11T12:42:46.495880,479392968,65265,242,-41.33991379294,-53.573613563955,77.930588917345,2,1,18 +2025-03-11T12:42:46.511505,479392968,65265,242,-41.38232176252,-53.606034443415,78.009339838495,2,1,18 +2025-03-11T12:42:46.527130,479392968,65265,242,-41.40588174562,-53.629180567365,78.088026555625,2,1,18 +2025-03-11T12:42:46.542755,479392968,65265,242,-41.45771370844,-53.66623882458,78.14370366346,2,1,18 +2025-03-11T12:42:46.558380,479392968,65265,242,-41.49069768478,-53.69864339811,78.2224410226,2,1,18 +2025-03-11T12:42:46.574005,479392968,65265,242,-41.53310565436,-53.73106427757,78.26422247923,2,1,18 +2025-03-11T12:42:46.589630,479392968,65265,242,-41.57080162732,-53.76809807589,78.315258060985,2,1,18 +2025-03-11T12:42:46.605255,479392968,65265,242,-41.5896496138,-53.791236046875,78.35696853259,2,1,18 +2025-03-11T12:42:46.620880,479392968,65265,242,-41.59907360704,-53.818978783755,78.389441616055,2,1,18 +2025-03-11T12:42:46.636505,479392968,65265,242,-41.62734558676,-53.846754132495,78.426563006605,2,1,18 +2025-03-11T12:42:46.652130,479392968,65265,242,-41.65090556986,-53.879142400095,78.46369615615,2,1,18 +2025-03-11T12:42:46.667755,479392968,65265,242,-41.66975355634,-53.89303822743,78.50999073082,2,1,18 +2025-03-11T12:42:46.683380,479392968,65265,242,-41.6838895462,-53.89768375815,78.537756712225,2,1,18 +2025-03-11T12:42:46.699005,479392968,65265,242,-41.69331353944,-53.902321135905,78.556273546495,2,1,18 +2025-03-11T12:42:46.714630,479392968,65265,242,-41.69802553606,-53.925434647995,78.588721308955,2,1,18 +2025-03-11T12:42:46.730255,479392968,65265,242,-41.70273753268,-53.920821729135,78.61643664835,2,1,18 +2025-03-11T12:42:46.745880,479392968,65265,242,-41.71216152592,-53.920838035065,78.639556125685,2,1,18 +2025-03-11T12:42:46.761505,479392968,65265,242,-41.72629751578,-53.943967853085,78.644290351765,2,1,18 +2025-03-11T12:42:46.777130,479392968,65265,242,-41.74043350564,-53.939371240155,78.648913337845,2,1,18 +2025-03-11T12:42:46.792755,479392968,65265,242,-41.73572150902,-53.93936308719,78.63966419071,2,1,18 +2025-03-11T12:42:46.808380,479392968,65265,242,-41.74514550226,-53.944000464945,78.653559841915,2,1,18 +2025-03-11T12:42:46.824005,479392968,65265,242,-41.74985749888,-53.939387546085,78.64430571679,2,1,18 +2025-03-11T12:42:46.839630,479392968,65265,242,-41.74514550226,-53.93937939312,78.64892011885,2,1,18 +2025-03-11T12:42:46.855255,479392968,65265,242,-41.7545694955,-53.934774627225,78.64891514086,2,1,18 +2025-03-11T12:42:46.870880,479392968,65265,242,-41.7545694955,-53.92091141175,78.62113242247,2,1,18 +2025-03-11T12:42:46.886505,479392968,65265,242,-41.73572150902,-53.92087879989,78.58413583393,2,1,18 +2025-03-11T12:42:46.902130,479392968,65265,242,-41.7310095124,-53.911628503275,78.5609860576,2,1,18 +2025-03-11T12:42:46.917755,479392968,65265,242,-41.72158551916,-53.89774898187,78.5331897772,2,1,18 +2025-03-11T12:42:46.933380,479392968,65265,242,-41.69331353944,-53.883836848605,78.509987555845,2,1,18 +2025-03-11T12:42:46.949005,479392968,65265,242,-41.6603295631,-53.86529549055,78.477517647355,2,1,18 +2025-03-11T12:42:46.964630,479392968,65265,242,-41.64148157662,-53.842157519565,78.45429190801,2,1,18 +2025-03-11T12:42:46.980255,479392968,65265,242,-41.61792159352,-53.81439032379,78.42179848153,2,1,18 +2025-03-11T12:42:46.995880,479392968,65265,242,-41.59436161042,-53.81897063079,78.38019246892,2,1,18 +2025-03-11T12:42:47.011505,479392968,65265,242,-41.58022562056,-53.79584081277,78.333867595255,2,1,18 +2025-03-11T12:42:47.027130,479392968,65265,242,-41.55666563746,-53.768073616995,78.27826825345,2,1,18 +2025-03-11T12:42:47.042755,479392968,65265,242,-41.53781765098,-53.72645135871,78.21337770652,2,1,18 +2025-03-11T12:42:47.058380,479392968,65265,242,-41.50954567126,-53.68019172267,78.162318606775,2,1,18 +2025-03-11T12:42:47.074005,479392968,65265,242,-41.47656169492,-53.652408220965,78.09746333683,2,1,18 +2025-03-11T12:42:47.089630,479392968,65265,242,-41.4482897152,-53.624632872225,78.05109958015,2,1,18 +2025-03-11T12:42:47.105255,479392968,65265,242,-41.39645775238,-53.58757461501,77.986180106185,2,1,18 +2025-03-11T12:42:47.120880,479392968,65265,242,-41.35876177942,-53.545919744865,77.912020069105,2,1,18 +2025-03-11T12:42:47.136505,479392968,65265,242,-41.32577780308,-53.49040981221,77.842432376095,2,1,18 +2025-03-11T12:42:47.152130,479392968,65265,242,-41.2833698335,-53.444125717275,77.75900465188,2,1,18 +2025-03-11T12:42:47.167755,479392968,65265,242,-41.25509785378,-53.39324500941,77.680199913745,2,1,18 +2025-03-11T12:42:47.183380,479392968,65265,242,-41.22211387744,-53.36084043588,77.59684137154,2,1,18 +2025-03-11T12:42:47.199005,479392968,65265,242,-41.17499391124,-53.300684972505,77.508730063255,2,1,18 +2025-03-11T12:42:47.214630,479392968,65265,242,-41.13729793828,-53.245166886885,77.434514406175,2,1,18 +2025-03-11T12:42:47.230255,479392968,65265,242,-41.07604198222,-53.194229108265,77.35104101794,2,1,18 +2025-03-11T12:42:47.245880,479392968,65265,242,-41.00536203292,-53.143275023715,77.24444815237,2,1,18 +2025-03-11T12:42:47.261505,479392968,65265,242,-40.93939408024,-53.078465876655,77.119321715545,2,1,18 +2025-03-11T12:42:47.277130,479392968,65265,242,-40.87342612756,-53.032141016895,77.01275417098,2,1,18 +2025-03-11T12:42:47.292755,479392968,65265,242,-40.81688216812,-52.976590319415,76.90154192536,2,1,18 +2025-03-11T12:42:47.308380,479392968,65265,242,-40.74620221882,-52.916394091215,76.790290796725,2,1,18 +2025-03-11T12:42:47.324005,479392968,65265,242,-40.66609827628,-52.856181557085,76.68826847221,2,1,18 +2025-03-11T12:42:47.339630,479392968,65265,242,-40.61897831008,-52.800647165535,76.563206239405,2,1,18 +2025-03-11T12:42:47.355255,479392968,65265,242,-40.57185834388,-52.72200741486,76.424187757405,2,1,18 +2025-03-11T12:42:47.370880,479392968,65265,242,-40.52002638106,-52.64335951122,76.299026043595,2,1,18 +2025-03-11T12:42:47.386505,479392968,65265,242,-40.45405842838,-52.57855036416,76.1831419729,2,1,18 +2025-03-11T12:42:47.402130,479392968,65265,242,-40.37395448584,-52.50909568638,76.05797665306,2,1,18 +2025-03-11T12:42:47.417755,479392968,65265,242,-40.30327453654,-52.43965731453,75.928203712165,2,1,18 +2025-03-11T12:42:47.433380,479392968,65265,242,-40.21374660076,-52.36094418717,75.793745384185,2,1,18 +2025-03-11T12:42:47.449005,479392968,65265,242,-40.1289306616,-52.272997069125,75.645393208015,2,1,18 +2025-03-11T12:42:47.464630,479392968,65265,242,-40.05353871568,-52.189687328835,75.48320958466,2,1,18 +2025-03-11T12:42:47.480255,479392968,65265,242,-39.95929878328,-52.11096604851,75.321017377285,2,1,18 +2025-03-11T12:42:47.495880,479392968,65265,242,-39.87448284412,-52.02764000229,75.144956642725,2,1,18 +2025-03-11T12:42:47.511505,479392968,65265,242,-39.78024291172,-51.94429765014,74.99198826148,2,1,18 +2025-03-11T12:42:47.527130,479392968,65265,242,-39.68600297932,-51.85171315434,74.820498067975,2,1,18 +2025-03-11T12:42:47.542755,479392968,65265,242,-39.60589903678,-51.76377418926,74.649046757485,2,1,18 +2025-03-11T12:42:47.558380,479392968,65265,242,-39.516371101,-51.6850610619,74.468376598855,2,1,18 +2025-03-11T12:42:47.574005,479392968,65265,242,-39.42684316522,-51.583242575415,74.30147728942,2,1,18 +2025-03-11T12:42:47.589630,479392968,65265,242,-39.33260323282,-51.481415935965,74.120707649785,2,1,18 +2025-03-11T12:42:47.605255,479392968,65265,242,-39.22893930718,-51.388815134235,73.972309809595,2,1,18 +2025-03-11T12:42:47.620880,479392968,65265,242,-39.12527538154,-51.296214332505,73.796184871015,2,1,18 +2025-03-11T12:42:47.636505,479392968,65265,242,-39.02632345252,-51.18513739644,73.615371370375,2,1,18 +2025-03-11T12:42:47.652130,479392968,65265,242,-38.91794753026,-51.07866522627,73.425320481595,2,1,18 +2025-03-11T12:42:47.667755,479392968,65265,242,-38.81428360462,-50.96758013724,73.249121383015,2,1,18 +2025-03-11T12:42:47.683380,479392968,65265,242,-38.7153316756,-50.847261057525,73.068270802375,2,1,18 +2025-03-11T12:42:47.699005,479392968,65265,242,-38.61166774996,-50.75928132762,72.85981612234,2,1,18 +2025-03-11T12:42:47.714630,479392968,65265,242,-38.5032918277,-50.657430229275,72.637435492105,2,1,18 +2025-03-11T12:42:47.730255,479392968,65265,242,-38.39491590544,-50.53709484363,72.428844251065,2,1,18 +2025-03-11T12:42:47.745880,479392968,65265,242,-38.28653998318,-50.42138052981,72.220271550025,2,1,18 +2025-03-11T12:42:47.761505,479392968,65265,242,-38.16874006768,-50.29640776641,72.002405840845,2,1,18 +2025-03-11T12:42:47.777130,479392968,65265,242,-38.0320921657,-50.185265606625,71.77994744458,2,1,18 +2025-03-11T12:42:47.792755,479392968,65265,242,-37.90958025358,-50.06952683391,71.55749085133,2,1,18 +2025-03-11T12:42:47.808380,479392968,65265,242,-37.80120433132,-49.95381252009,71.34891815029,2,1,18 +2025-03-11T12:42:47.824005,479392968,65265,242,-37.68340441582,-49.82883975669,71.126431258045,2,1,18 +2025-03-11T12:42:47.839630,479392968,65265,242,-37.56560450032,-49.70386699329,70.880838450475,2,1,18 +2025-03-11T12:42:47.855255,479392968,65265,242,-37.42424460172,-49.58347453689,70.64447264401,2,1,18 +2025-03-11T12:42:47.870880,479392968,65265,242,-37.29230869636,-49.44461409912,70.42190978875,2,1,18 +2025-03-11T12:42:47.886505,479392968,65265,242,-37.160372791,-49.32423794865,70.194799910425,2,1,18 +2025-03-11T12:42:47.902130,479392968,65265,242,-37.02843688564,-49.18537751088,69.93988877371,2,1,18 +2025-03-11T12:42:47.917755,479392968,65265,242,-36.88707698704,-49.04650076718,69.703448807245,2,1,18 +2025-03-11T12:42:47.933380,479392968,65265,242,-36.75514108168,-48.903019257585,69.471625045855,2,1,18 +2025-03-11T12:42:47.949005,479392968,65265,242,-36.62320517632,-48.773400963465,69.20750862301,2,1,18 +2025-03-11T12:42:47.964630,479392968,65265,242,-36.49598126758,-48.629927606835,68.94334336117,2,1,18 +2025-03-11T12:42:47.980255,479392968,65265,242,-36.34990937236,-48.477179494695,68.68835626144,2,1,18 +2025-03-11T12:42:47.995880,479392968,65265,242,-36.20854947376,-48.347544894645,68.43808982578,2,1,18 +2025-03-11T12:42:48.011505,479392968,65265,242,-36.0766135684,-48.20406338505,68.173917782935,2,1,18 +2025-03-11T12:42:48.027130,479392968,65265,242,-35.9352536698,-48.069807713175,67.90976925808,2,1,18 +2025-03-11T12:42:48.042755,479392968,65265,242,-35.7703337881,-47.907784845525,67.62699085594,2,1,18 +2025-03-11T12:42:48.058380,479392968,65265,242,-35.61483789964,-47.75039935563,67.367350471135,2,1,18 +2025-03-11T12:42:48.074005,479392968,65265,242,-35.46876600442,-47.602272315315,67.08003362995,2,1,18 +2025-03-11T12:42:48.089630,479392968,65265,242,-35.31798211258,-47.44027390656,66.806517936955,2,1,18 +2025-03-11T12:42:48.105255,479392968,65265,242,-35.17662221398,-47.278291803735,66.5422581721,2,1,18 +2025-03-11T12:42:48.120880,479392968,65265,242,-35.02112632552,-47.125527385665,66.25953041197,2,1,18 +2025-03-11T12:42:48.136505,479392968,65265,242,-34.86563043706,-46.96814189577,65.953678196515,2,1,18 +2025-03-11T12:42:48.152130,479392968,65265,242,-34.71484654522,-46.80152241519,65.643174499,2,1,18 +2025-03-11T12:42:48.167755,479392968,65265,242,-34.5452146669,-46.63487032275,65.33726486053,2,1,18 +2025-03-11T12:42:48.183380,479392968,65265,242,-34.38971877844,-46.47286376103,65.03601528814,2,1,18 +2025-03-11T12:42:48.199005,479392968,65265,242,-34.2153749035,-46.315445659275,64.73475713173,2,1,18 +2025-03-11T12:42:48.214630,479392968,65265,242,-34.0268950387,-46.139518811325,64.433404472305,2,1,18 +2025-03-11T12:42:48.230255,479392968,65265,242,-33.85726316038,-45.96824564706,64.1320974769,2,1,18 +2025-03-11T12:42:48.245880,479392968,65265,242,-33.70647926854,-45.80162616648,63.812351413255,2,1,18 +2025-03-11T12:42:48.261505,479392968,65265,242,-33.54627138346,-45.621127164495,63.4925361676,2,1,18 +2025-03-11T12:42:48.277130,479392968,65265,242,-33.38135150176,-45.412893578595,63.18184526707,2,1,18 +2025-03-11T12:42:48.292755,479392968,65265,242,-33.19287163696,-45.24158780247,62.871268781515,2,1,18 +2025-03-11T12:42:48.308380,479392968,65265,242,-33.01852776202,-45.074927557065,62.569973545105,2,1,18 +2025-03-11T12:42:48.324005,479392968,65265,242,-32.8253359006,-44.903613627975,62.25476909548,2,1,18 +2025-03-11T12:42:48.339630,479392968,65265,242,-32.64628002904,-44.718460942305,61.92104463661,2,1,18 +2025-03-11T12:42:48.355255,479392968,65265,242,-32.47664815072,-44.561050993515,61.573581430555,2,1,18 +2025-03-11T12:42:48.370880,479392968,65265,242,-32.30230427578,-44.38514860446,61.244522015755,2,1,18 +2025-03-11T12:42:48.386505,479392968,65265,242,-32.10911241436,-44.19535038807,60.90151630774,2,1,18 +2025-03-11T12:42:48.402130,479392968,65265,242,-31.91120855632,-44.00092294689,60.563106461785,2,1,18 +2025-03-11T12:42:48.417755,479392968,65265,242,-31.73215268476,-43.80652811757,60.210860190655,2,1,18 +2025-03-11T12:42:48.433380,479392968,65265,242,-31.53424882672,-43.616721748215,59.86322651857,2,1,18 +2025-03-11T12:42:48.449005,479392968,65265,242,-31.35048095854,-43.436181981405,59.511029086435,2,1,18 +2025-03-11T12:42:48.464630,479392968,65265,242,-31.15728909712,-43.24176269319,59.181868387615,2,1,18 +2025-03-11T12:42:48.480255,479392968,65265,242,-30.95467324246,-43.047327099045,58.83883057759,2,1,18 +2025-03-11T12:42:48.495880,479392968,65265,242,-30.76148138104,-42.85290781083,58.47270041425,2,1,18 +2025-03-11T12:42:48.511505,479392968,65265,242,-30.56828951962,-42.658488522615,58.11581261704,2,1,18 +2025-03-11T12:42:48.527130,479392968,65265,242,-30.37980965482,-42.464077387365,57.75431041777,2,1,18 +2025-03-11T12:42:48.542755,479392968,65265,242,-30.20075378326,-42.260440414395,57.388163517445,2,1,18 +2025-03-11T12:42:48.558380,479392968,65265,242,-30.00284992522,-42.06139190139,57.01276566697,2,1,18 +2025-03-11T12:42:48.574005,479392968,65265,242,-29.79081007732,-41.866940001315,56.651229562675,2,1,18 +2025-03-11T12:42:48.589630,479392968,65265,242,-29.5740582328,-41.6586167328,56.28500987431,2,1,18 +2025-03-11T12:42:48.605255,479392968,65265,242,-29.38086637138,-41.445713157285,55.91880555097,2,1,18 +2025-03-11T12:42:48.620880,479392968,65265,242,-29.18767450996,-41.24205172542,55.538774758435,2,1,18 +2025-03-11T12:42:48.636505,479392968,65265,242,-28.98034665868,-41.03836583466,55.16334480595,2,1,18 +2025-03-11T12:42:48.652130,479392968,65265,242,-28.76830681078,-40.816187503635,54.7693491802,2,1,18 +2025-03-11T12:42:48.667755,479392968,65265,242,-28.56569095612,-40.60326762219,54.36616183033,2,1,18 +2025-03-11T12:42:48.683380,479392968,65265,242,-28.36307510146,-40.390347740745,53.976838029655,2,1,18 +2025-03-11T12:42:48.699005,479392968,65265,242,-28.14161126032,-40.16815310379,53.610555940285,2,1,18 +2025-03-11T12:42:48.714630,479392968,65265,242,-27.90601142932,-39.941312936115,53.22575023564,2,1,18 +2025-03-11T12:42:48.730255,479392968,65265,242,-27.6892595848,-39.7329896676,52.82718226582,2,1,18 +2025-03-11T12:42:48.745880,479392968,65265,242,-27.48664373014,-39.520069786155,52.43323728208,2,1,18 +2025-03-11T12:42:48.761505,479392968,65265,242,-27.26046789238,-39.30248806806,52.029997487185,2,1,18 +2025-03-11T12:42:48.777130,479392968,65265,242,-27.03900405124,-39.080293431105,51.63136711636,2,1,18 +2025-03-11T12:42:48.792755,479392968,65265,242,-26.82225220672,-38.85348587529,51.228103803475,2,1,18 +2025-03-11T12:42:48.808380,479392968,65265,242,-26.6055003622,-38.6312993913,50.80637429833,2,1,18 +2025-03-11T12:42:48.824005,479392968,65265,242,-26.37932452444,-38.41833874503,50.403153043435,2,1,18 +2025-03-11T12:42:48.839630,479392968,65265,242,-26.15314868668,-38.18689381146,49.99985762854,2,1,18 +2025-03-11T12:42:48.855255,479392968,65265,242,-25.9222608523,-37.94157750945,49.57801508038,2,1,18 +2025-03-11T12:42:48.870880,479392968,65265,242,-25.70550900778,-37.71939102546,49.165527941365,2,1,18 +2025-03-11T12:42:48.886505,479392968,65265,242,-25.47933317002,-37.483325020065,48.76221398647,2,1,18 +2025-03-11T12:42:48.902130,479392968,65265,242,-25.24844533564,-37.247250861705,48.34040851831,2,1,18 +2025-03-11T12:42:48.917755,479392968,65265,242,-25.02226949788,-37.034290215435,47.92332371422,2,1,18 +2025-03-11T12:42:48.933380,479392968,65265,242,-24.78666966688,-36.79820790411,47.492269098925,2,1,18 +2025-03-11T12:42:48.949005,479392968,65265,242,-24.53693384602,-36.566722205715,47.05659149755,2,1,18 +2025-03-11T12:42:48.964630,479392968,65265,242,-24.30604601164,-36.32602697553,46.639388672455,2,1,18 +2025-03-11T12:42:48.980255,479392968,65265,242,-24.07987017388,-36.080718826485,46.194446989975,2,1,18 +2025-03-11T12:42:48.995880,479392968,65265,242,-23.84427034288,-35.849257586985,45.768032097745,2,1,18 +2025-03-11T12:42:49.011505,479392968,65265,242,-23.6133825085,-35.603941284975,45.33232600039,2,1,18 +2025-03-11T12:42:49.027130,479392968,65265,242,-23.35893469102,-35.344721002665,44.891909194945,2,1,18 +2025-03-11T12:42:49.042755,479392968,65265,242,-23.1186228634,-35.108630538375,44.45622661558,2,1,18 +2025-03-11T12:42:49.058380,479392968,65265,242,-22.87359903916,-34.86328977747,44.01125780908,2,1,18 +2025-03-11T12:42:49.074005,479392968,65265,242,-22.62857521492,-34.636433303865,43.570984345645,2,1,18 +2025-03-11T12:42:49.089630,479392968,65265,242,-22.37883939406,-34.391084389995,43.11676639201,2,1,18 +2025-03-11T12:42:49.105255,479392968,65265,242,-22.11496758334,-34.11798458628,42.648553306165,2,1,18 +2025-03-11T12:42:49.120880,479392968,65265,242,-21.86523176248,-33.858772456935,42.208143281725,2,1,18 +2025-03-11T12:42:49.136505,479392968,65265,242,-21.62491993486,-33.613439848995,41.7539388901,2,1,18 +2025-03-11T12:42:49.152130,479392968,65265,242,-21.38932010386,-33.36811539402,41.31822601174,2,1,18 +2025-03-11T12:42:49.167755,479392968,65265,242,-21.14429627962,-33.132016776765,40.859430736045,2,1,18 +2025-03-11T12:42:49.183380,479392968,65265,242,-20.91340844524,-32.88207940293,40.40522136643,2,1,18 +2025-03-11T12:42:49.199005,479392968,65265,242,-20.65424863114,-32.60898775218,39.941636244655,2,1,18 +2025-03-11T12:42:49.214630,479392968,65265,242,-20.39508881704,-32.340517173255,39.473448479815,2,1,18 +2025-03-11T12:42:49.230255,479392968,65265,242,-20.13592900294,-32.085909809805,39.01917988417,2,1,18 +2025-03-11T12:42:49.245880,479392968,65265,242,-19.87676918884,-31.84516566183,38.555724542395,2,1,18 +2025-03-11T12:42:49.261505,479392968,65265,242,-19.61760937474,-31.59980044203,38.087629477555,2,1,18 +2025-03-11T12:42:49.277130,479392968,65265,242,-19.35373756402,-31.33132171014,37.61019256558,2,1,18 +2025-03-11T12:42:49.292755,479392968,65265,242,-19.09457774992,-31.06747220304,37.13278097461,2,1,18 +2025-03-11T12:42:49.308380,479392968,65265,242,-18.8307059392,-30.812856686625,36.64153613344,2,1,18 +2025-03-11T12:42:49.324005,479392968,65265,242,-18.55741013524,-30.54898272063,36.164104199455,2,1,18 +2025-03-11T12:42:49.339630,479392968,65265,242,-18.30296231776,-30.28976243832,35.691339112555,2,1,18 +2025-03-11T12:42:49.355255,479392968,65265,242,-18.04380250366,-30.021291859395,35.20004543239,2,1,18 +2025-03-11T12:42:49.370880,479392968,65265,242,-17.78464268956,-29.757442352295,34.72263384142,2,1,18 +2025-03-11T12:42:49.386505,479392968,65265,242,-17.53019487208,-29.49360099816,34.24985021452,2,1,18 +2025-03-11T12:42:49.402130,479392968,65265,242,-17.24747507488,-29.23433179806,33.744696160135,2,1,18 +2025-03-11T12:42:49.417755,479392968,65265,242,-16.98831526078,-28.965861219135,33.25340247997,2,1,18 +2025-03-11T12:42:49.433380,479392968,65265,242,-16.72444345006,-28.69276141542,32.78981057719,2,1,18 +2025-03-11T12:42:49.449005,479392968,65265,242,-16.4511476461,-28.4242663776,32.29849655401,2,1,18 +2025-03-11T12:42:49.464630,479392968,65265,242,-16.18727583538,-28.160408717535,31.802593449775,2,1,18 +2025-03-11T12:42:49.480255,479392968,65265,242,-15.92340402466,-27.89655105747,31.31593271167,2,1,18 +2025-03-11T12:42:49.495880,479392968,65265,242,-15.65482021732,-27.63268524444,30.80153809417,2,1,18 +2025-03-11T12:42:49.511505,479392968,65265,242,-15.38623640998,-27.354956215935,30.310193771995,2,1,18 +2025-03-11T12:42:49.527130,479392968,65265,242,-15.11294060602,-27.07259796264,29.82344531188,2,1,18 +2025-03-11T12:42:49.542755,479392968,65265,242,-14.84435679868,-26.79949000596,29.31825598051,2,1,18 +2025-03-11T12:42:49.558380,479392968,65265,242,-14.55692500486,-26.530970509245,28.80381569899,2,1,18 +2025-03-11T12:42:49.574005,479392968,65265,242,-14.2836292009,-26.253233327775,28.29397986355,2,1,18 +2025-03-11T12:42:49.589630,479392968,65265,242,-14.0244693868,-25.96627846155,27.793369657255,2,1,18 +2025-03-11T12:42:49.605255,479392968,65265,242,-13.75117358284,-25.683920208255,27.302000014075,2,1,18 +2025-03-11T12:42:49.620880,479392968,65265,242,-13.4590297924,-25.4200136304,26.80605622381,2,1,18 +2025-03-11T12:42:49.636505,479392968,65265,242,-13.19044598506,-25.14690567372,26.31010925857,2,1,18 +2025-03-11T12:42:49.652130,479392968,65265,242,-12.90301419124,-24.87376510518,25.79565043705,2,1,18 +2025-03-11T12:42:49.667755,479392968,65265,242,-12.62971838728,-24.60527006736,25.27660931548,2,1,18 +2025-03-11T12:42:49.683380,479392968,65265,242,-12.36113457994,-24.31367782338,24.757482274915,2,1,18 +2025-03-11T12:42:49.699005,479392968,65265,242,-12.08312677936,-24.01282712982,24.2567893246,2,1,18 +2025-03-11T12:42:49.714630,479392968,65265,242,-11.79569498554,-23.725823345805,23.75151724921,2,1,18 +2025-03-11T12:42:49.730255,479392968,65265,242,-11.5271111782,-23.43885217365,23.23702993171,2,1,18 +2025-03-11T12:42:49.745880,479392968,65265,242,-11.23496738776,-23.17032452397,22.71796168612,2,1,18 +2025-03-11T12:42:49.761505,479392968,65265,242,-10.94282359732,-22.88331258699,22.19881928053,2,1,18 +2025-03-11T12:42:49.777130,479392968,65265,242,-10.66010380012,-22.60555909959,21.67972751695,2,1,18 +2025-03-11T12:42:49.792755,479392968,65265,242,-10.38209599954,-22.32319269333,21.15600281131,2,1,18 +2025-03-11T12:42:49.808380,479392968,65265,242,-10.09466420572,-22.026946765665,20.636830106725,2,1,18 +2025-03-11T12:42:49.824005,479392968,65265,242,-9.8072324119,-21.72145869435,20.11762032214,2,1,18 +2025-03-11T12:42:49.839630,479392968,65265,242,-9.51508862146,-21.420583541895,19.59842229655,2,1,18 +2025-03-11T12:42:49.855255,479392968,65265,242,-9.2182328344,-21.138184523775,19.06542810076,2,1,18 +2025-03-11T12:42:49.870880,479392968,65265,242,-8.94022503382,-20.86968133299,18.537137832055,2,1,18 +2025-03-11T12:42:49.886505,479392968,65265,242,-8.65750523662,-20.58268570194,18.02263017154,2,1,18 +2025-03-11T12:42:49.902130,479392968,65265,242,-8.37478543942,-20.27720578359,17.498805984895,2,1,18 +2025-03-11T12:42:49.917755,479392968,65265,242,-8.08264164898,-19.98095170296,16.96576295011,2,1,18 +2025-03-11T12:42:49.933380,479392968,65265,242,-7.79049785854,-19.689318694155,16.43735963839,2,1,18 +2025-03-11T12:42:49.949005,479392968,65265,242,-7.4983540681,-19.41616997265,15.895166937475,2,1,18 +2025-03-11T12:42:49.964630,479392968,65265,242,-7.21092227428,-19.138408332285,15.362204843695,2,1,18 +2025-03-11T12:42:49.980255,479392968,65265,242,-6.91406648722,-18.84214609869,14.819912661775,2,1,18 +2025-03-11T12:42:49.995819,479392972,65261,243,-6.6266346934,-18.545900171025,14.29149759106,2,1,18 +2025-03-11T12:42:50.011444,479392972,65261,243,-6.32506690972,-18.26349299994,13.758496614265,2,1,18 +2025-03-11T12:42:50.027069,479392972,65261,243,-6.04234711252,-17.962634153415,13.22544860149,2,1,18 +2025-03-11T12:42:50.042694,479392972,65261,243,-5.75962731532,-17.657154235065,12.692382048715,2,1,18 +2025-03-11T12:42:50.058319,479392972,65261,243,-5.4721955215,-17.37015045105,12.150140508805,2,1,18 +2025-03-11T12:42:50.073944,479392972,65261,243,-5.17062773782,-17.087743279965,11.640245447335,2,1,18 +2025-03-11T12:42:50.089569,479392972,65261,243,-4.883195944,-16.80073949595,11.12110982275,2,1,18 +2025-03-11T12:42:50.105194,479392972,65261,243,-4.5769161637,-16.504460956425,10.57880407882,2,1,18 +2025-03-11T12:42:50.120819,479392972,65261,243,-4.28006037664,-16.212819794655,10.0365304369,2,1,18 +2025-03-11T12:42:50.136444,479392972,65261,243,-3.97849259296,-15.907307264445,9.49881557704,2,1,18 +2025-03-11T12:42:50.152069,479392972,65261,243,-3.6816368059,-15.6018028872,8.961107498185,2,1,18 +2025-03-11T12:42:50.167694,479392972,65261,243,-3.37064502898,-15.300895122885,8.395670517925,2,1,18 +2025-03-11T12:42:50.183319,479392972,65261,243,-3.06436524868,-14.99537443971,7.834842961735,2,1,18 +2025-03-11T12:42:50.198944,479392972,65261,243,-2.77222145824,-14.694499287255,7.324887302275,2,1,18 +2025-03-11T12:42:50.214569,479392972,65261,243,-2.48950166104,-14.416745799855,6.80117435563,2,1,18 +2025-03-11T12:42:50.230194,479392972,65261,243,-2.19264587398,-14.12972570991,6.24043452145,2,1,18 +2025-03-11T12:42:50.245819,479392972,65261,243,-1.90521408016,-13.82885871042,5.68889499541,2,1,18 +2025-03-11T12:42:50.261444,479392972,65261,243,-1.61307028972,-13.537225701615,5.14200695143,2,1,18 +2025-03-11T12:42:50.277069,479392972,65261,243,-1.32092649928,-13.240971620985,4.608963916645,2,1,18 +2025-03-11T12:42:50.292694,479392972,65261,243,-1.02878270884,-12.93085432488,4.080486444925,2,1,18 +2025-03-11T12:42:50.308319,479392972,65261,243,-0.7366389184,-12.63460024425,3.53820104401,2,1,18 +2025-03-11T12:42:50.323944,479392972,65261,243,-0.43507113472,-12.32908771404,2.97275908576,2,1,18 +2025-03-11T12:42:50.339569,479392972,65261,243,-0.14292734428,-12.03283363341,2.430473684845,2,1,18 +2025-03-11T12:42:50.355194,479392972,65261,243,0.1586404394,-11.7273211032,1.88813764192,2,1,18 +2025-03-11T12:42:50.370819,479392972,65261,243,0.47434421294,-11.43564732957,1.33659450985,2,1,18 +2025-03-11T12:42:50.386444,479392972,65261,243,0.78533598986,-11.143981708905,0.78967934185,2,1,18 +2025-03-11T12:42:50.402069,479392972,65261,243,1.07276778368,-10.82000935029,0.22880474968,2,1,18 +2025-03-11T12:42:50.417694,479392972,65261,243,1.36491157412,-10.519134197835,-0.3181203743,2,1,18 +2025-03-11T12:42:50.433319,479392972,65261,243,1.66176736118,-10.22287196424,-0.874276105415,2,1,18 +2025-03-11T12:42:50.448944,479392972,65261,243,1.96333514486,-9.921980505855,-1.39810887608,2,1,18 +2025-03-11T12:42:50.464569,479392972,65261,243,2.2554789353,-9.644210712525,-1.931077750865,2,1,18 +2025-03-11T12:42:50.480194,479392972,65261,243,2.55233472236,-9.34794847893,-2.491854665045,2,1,18 +2025-03-11T12:42:50.495819,479392972,65261,243,2.85390250604,-9.04243594872,-3.05267544023,2,1,18 +2025-03-11T12:42:50.511444,479392972,65261,243,3.15547028972,-8.72768127486,-3.59966974622,2,1,18 +2025-03-11T12:42:50.527069,479392972,65261,243,3.44761408016,-8.42218505058,-4.12812867794,2,1,18 +2025-03-11T12:42:50.542694,479392972,65261,243,3.7397578706,-8.130552041775,-4.68425908805,2,1,18 +2025-03-11T12:42:50.558319,479392972,65261,243,4.05546164414,-7.820393980845,-5.22663401399,2,1,18 +2025-03-11T12:42:50.573944,479392972,65261,243,4.36645342106,-7.514865144705,-5.778225985055,2,1,18 +2025-03-11T12:42:50.589569,479392972,65261,243,4.6585972115,-7.209368920425,-6.334412015165,2,1,18 +2025-03-11T12:42:50.605194,479392972,65261,243,4.95074100194,-6.89925162432,-6.86751066995,2,1,18 +2025-03-11T12:42:50.620819,479392972,65261,243,5.25230878562,-6.60298123776,-7.419051999005,2,1,18 +2025-03-11T12:42:50.636444,479392972,65261,243,5.53974057944,-6.315977453745,-7.970535905045,2,1,18 +2025-03-11T12:42:50.652069,479392972,65261,243,5.84602035974,-6.02894105787,-8.50818338591,2,1,18 +2025-03-11T12:42:50.667694,479392972,65261,243,6.14758814342,-5.709565312185,-9.03671149964,2,1,18 +2025-03-11T12:42:50.683319,479392972,65261,243,6.44444393048,-5.417924150415,-9.592848690755,2,1,18 +2025-03-11T12:42:50.698944,479392972,65261,243,6.75072371078,-5.126266682715,-10.153620626945,2,1,18 +2025-03-11T12:42:50.714569,479392972,65261,243,7.04757949784,-4.834625520945,-10.714379001125,2,1,18 +2025-03-11T12:42:50.730194,479392972,65261,243,7.34914728152,-4.52449191891,-11.25673358405,2,1,18 +2025-03-11T12:42:50.745819,479392972,65261,243,7.65542706182,-4.218971235735,-11.78059167572,2,1,18 +2025-03-11T12:42:50.761444,479392972,65261,243,7.93814685902,-3.92735453286,-12.30898142543,2,1,18 +2025-03-11T12:42:50.777069,479392972,65261,243,8.23500264608,-3.62647122744,-12.855913330415,2,1,18 +2025-03-11T12:42:50.792694,479392972,65261,243,8.51772244328,-3.32099130909,-13.39822224932,2,1,18 +2025-03-11T12:42:50.808319,479392972,65261,243,8.81457823034,-3.01086586002,-13.945191234305,2,1,18 +2025-03-11T12:42:50.823944,479392972,65261,243,9.1114340174,-2.7099825546,-14.487501956225,2,1,18 +2025-03-11T12:42:50.839569,479392972,65261,243,9.41300180108,-2.418333239865,-15.015918829955,2,1,18 +2025-03-11T12:42:50.855194,479392972,65261,243,9.71456958476,-2.122062853305,-15.57670252514,2,1,18 +2025-03-11T12:42:50.870819,479392972,65261,243,10.01142537182,-1.811937404235,-16.123671510125,2,1,18 +2025-03-11T12:42:50.886444,479392972,65261,243,10.29885716564,-1.51569147657,-16.65208658084,2,1,18 +2025-03-11T12:42:50.902069,479392972,65261,243,10.5957129527,-1.21480817115,-17.21288203502,2,1,18 +2025-03-11T12:42:50.917694,479392972,65261,243,10.87372075328,-0.92319962124,-17.77361328518,2,1,18 +2025-03-11T12:42:50.933319,479392972,65261,243,11.18000053358,-0.636163225364999,-18.29739721685,2,1,18 +2025-03-11T12:42:50.948944,479392972,65261,243,11.4909923105,-0.339876532875,-18.811982643395,2,1,18 +2025-03-11T12:42:50.964569,479392972,65261,243,11.79256009418,-0.0482272181400001,-19.35426306632,2,1,18 +2025-03-11T12:42:50.980194,479392972,65261,243,12.09883987448,0.24343024956,-19.882686721055,2,1,18 +2025-03-11T12:42:50.995819,479392972,65261,243,12.3862716683,0.535055105400001,-20.406462068705,2,1,18 +2025-03-11T12:42:51.011444,479392972,65261,243,12.6925514486,0.81747042945,-20.93484864344,2,1,18 +2025-03-11T12:42:51.027069,479392972,65261,243,12.98469523904,1.118345581905,-21.47253140129,2,1,18 +2025-03-11T12:42:51.042694,479392972,65261,243,13.2815510261,1.409986743675,-22.02404740934,2,1,18 +2025-03-11T12:42:51.058319,479392972,65261,243,13.57840681316,1.69700683362,-22.55706014513,2,1,18 +2025-03-11T12:42:51.073944,479392972,65261,243,13.85641461374,2.00709967083,-23.0901384569,2,1,18 +2025-03-11T12:42:51.089569,479392972,65261,243,14.13442241432,2.30795036439,-23.627800871735,2,1,18 +2025-03-11T12:42:51.105194,479392972,65261,243,14.42185420814,2.604196292055,-24.15621594245,2,1,18 +2025-03-11T12:42:51.120819,479392972,65261,243,14.70457400534,2.900434066755,-24.689245415225,2,1,18 +2025-03-11T12:42:51.136444,479392972,65261,243,14.99200579916,3.192058922595,-25.203778396745,2,1,18 +2025-03-11T12:42:51.152069,479392972,65261,243,15.26530160312,3.46517503224,-25.74594397364,2,1,18 +2025-03-11T12:42:51.167694,479392972,65261,243,15.54802140032,3.756791735115,-26.288197272545,2,1,18 +2025-03-11T12:42:51.183319,479392972,65261,243,15.85430118062,4.05307027464,-26.821260650345,2,1,18 +2025-03-11T12:42:51.198944,479392972,65261,243,16.16058096092,4.349348814165,-27.34046047895,2,1,18 +2025-03-11T12:42:51.214569,479392972,65261,243,16.44801275474,4.650215813655,-27.85503054047,2,1,18 +2025-03-11T12:42:51.230194,479392972,65261,243,16.73544454856,4.92797745402,-28.383371451185,2,1,18 +2025-03-11T12:42:51.245819,479392972,65261,243,17.027588339,5.210368319175,-28.902495316775,2,1,18 +2025-03-11T12:42:51.261444,479392972,65261,243,17.31973212944,5.49275918433,-29.43548273156,2,1,18 +2025-03-11T12:42:51.277069,479392972,65261,243,17.5930279334,5.802843868575,-29.97317544539,2,1,18 +2025-03-11T12:42:51.292694,479392972,65261,243,17.86632373736,6.07595997822,-30.487613923895,2,1,18 +2025-03-11T12:42:51.308319,479392972,65261,243,18.14904353456,6.367576681095,-31.00214012441,2,1,18 +2025-03-11T12:42:51.323944,479392972,65261,243,18.43647532838,6.64533832146,-31.502753936735,2,1,18 +2025-03-11T12:42:51.339569,479392972,65261,243,18.71448312896,6.913841512245,-32.03104420544,2,1,18 +2025-03-11T12:42:51.355194,479392972,65261,243,19.0066269194,7.210095592875,-32.55022369103,2,1,18 +2025-03-11T12:42:51.370819,479392972,65261,243,19.2893467166,7.487849080275,-33.06007308848,2,1,18 +2025-03-11T12:42:51.386444,479392972,65261,243,19.58620250366,7.761005954745,-33.579166655075,2,1,18 +2025-03-11T12:42:51.402069,479392972,65261,243,19.8783462941,8.05263896355,-34.07522168534,2,1,18 +2025-03-11T12:42:51.417694,479392972,65261,243,20.15635409468,8.339626441635,-34.575859015655,2,1,18 +2025-03-11T12:42:51.433319,479392972,65261,243,20.42964989864,8.61274255128,-35.0718127619,2,1,18 +2025-03-11T12:42:51.448944,479392972,65261,243,20.69823370598,8.89509265161,-35.59552390553,2,1,18 +2025-03-11T12:42:51.464569,479392972,65261,243,20.97624150656,9.16821691422,-36.114590348105,2,1,18 +2025-03-11T12:42:51.480194,479392972,65261,243,21.24953731052,9.441333023865,-36.61054409435,2,1,18 +2025-03-11T12:42:51.495819,479392972,65261,243,21.53225710772,9.728328654915,-37.097324656475,2,1,18 +2025-03-11T12:42:51.511444,479392972,65261,243,21.80084091506,9.992194467945,-37.602476907845,2,1,18 +2025-03-11T12:42:51.527069,479392972,65261,243,22.0694247224,10.2606813528,-38.107647699215,2,1,18 +2025-03-11T12:42:51.542694,479392972,65261,243,22.33800852974,10.53378930948,-38.603594664455,2,1,18 +2025-03-11T12:42:51.558319,479392972,65261,243,22.60659233708,10.81613940981,-39.10419989276,2,1,18 +2025-03-11T12:42:51.573944,479392972,65261,243,22.86575215118,11.103094276035,-39.623294831315,2,1,18 +2025-03-11T12:42:51.589569,479392972,65261,243,23.13433595852,11.37158116089,-40.11460207349,2,1,18 +2025-03-11T12:42:51.605194,479392972,65261,243,23.40291976586,11.649310189395,-40.61056757873,2,1,18 +2025-03-11T12:42:51.620819,479392972,65261,243,23.67621556982,11.92242629904,-41.10190014191,2,1,18 +2025-03-11T12:42:51.636444,479392972,65261,243,23.94008738054,12.195526102755,-41.57473441082,2,1,18 +2025-03-11T12:42:51.652069,479392972,65261,243,24.2133831845,12.44091578145,-42.05671336787,2,1,18 +2025-03-11T12:42:51.667694,479392972,65261,243,24.50081497832,12.69557206269,-42.529507381805,2,1,18 +2025-03-11T12:42:51.683319,479392972,65261,243,24.78353477552,12.977946621915,-43.011648220865,2,1,18 +2025-03-11T12:42:51.698944,479392972,65261,243,25.04269458962,13.25565934449,-43.507600164095,2,1,18 +2025-03-11T12:42:51.714569,479392972,65261,243,25.2971424071,13.5148796268,-43.998849983255,2,1,18 +2025-03-11T12:42:51.730194,479392972,65261,243,25.56101421782,13.78335835869,-44.480908078295,2,1,18 +2025-03-11T12:42:51.745819,479392972,65261,243,25.82959802516,14.05646631537,-44.96299149434,2,1,18 +2025-03-11T12:42:51.761444,479392972,65261,243,26.08404584264,14.31568659768,-45.449620130435,2,1,18 +2025-03-11T12:42:51.777069,479392972,65261,243,26.34320565674,14.57029396113,-45.92237345834,2,1,18 +2025-03-11T12:42:51.792694,479392972,65261,243,26.60707746746,14.82028840572,-46.37663029499,2,1,18 +2025-03-11T12:42:51.808319,479392972,65261,243,26.86623728156,15.079516840995,-46.86326571209,2,1,18 +2025-03-11T12:42:51.823944,479392972,65261,243,27.13010909228,15.338753429235,-47.34528672713,2,1,18 +2025-03-11T12:42:51.839569,479392972,65261,243,27.38926890638,15.60722400816,-47.818095675035,2,1,18 +2025-03-11T12:42:51.855194,479392972,65261,243,27.64371672386,15.85720214682,-48.26771776661,2,1,18 +2025-03-11T12:42:51.870819,479392972,65261,243,27.87931655486,16.11638981727,-48.745076912555,2,1,18 +2025-03-11T12:42:51.886444,479392972,65261,243,28.13376437234,16.37561009958,-49.208599633325,2,1,18 +2025-03-11T12:42:51.902069,479392972,65261,243,28.39292418644,16.62097531938,-49.658209965905,2,1,18 +2025-03-11T12:42:51.917694,479392972,65261,243,28.65208400054,16.87558268283,-50.126342110745,2,1,18 +2025-03-11T12:42:51.933319,479392972,65261,243,28.91595581126,17.12557712742,-50.58522013046,2,1,18 +2025-03-11T12:42:51.948944,479392972,65261,243,29.16569163212,17.37092604129,-51.0255745349,2,1,18 +2025-03-11T12:42:51.964569,479392972,65261,243,29.40600345974,17.620879721055,-51.48441864959,2,1,18 +2025-03-11T12:42:51.980194,479392972,65261,243,29.64631528736,17.86159125717,-51.938604501215,2,1,18 +2025-03-11T12:42:51.995819,479392972,65261,243,29.88662711498,18.11616600876,-52.36511887445,2,1,18 +2025-03-11T12:42:52.011444,479392972,65261,243,30.1269389426,18.37074076035,-52.810117979945,2,1,18 +2025-03-11T12:42:52.027069,479392972,65261,243,30.37667476346,18.611468602395,-53.27355975971,2,1,18 +2025-03-11T12:42:52.042694,479392972,65261,243,30.6216985877,18.84756721965,-53.70000675395,2,1,18 +2025-03-11T12:42:52.058319,479392972,65261,243,30.8572984187,19.0882706028,-54.13570109231,2,1,18 +2025-03-11T12:42:52.073944,479392972,65261,243,31.08347425646,19.324336608195,-54.575984511725,2,1,18 +2025-03-11T12:42:52.089569,479392972,65261,243,31.32378608408,19.569669216135,-55.016325354155,2,1,18 +2025-03-11T12:42:52.105194,479392972,65261,243,31.56880990832,19.80576783339,-55.452014714525,2,1,18 +2025-03-11T12:42:52.120819,479392972,65261,243,31.79027374946,20.05106782947,-55.873843700675,2,1,18 +2025-03-11T12:42:52.136444,479392972,65261,243,32.02587358046,20.277907997145,-56.29561886984,2,1,18 +2025-03-11T12:42:52.152069,479392972,65261,243,32.26618540808,20.50013524596,-56.731245829205,2,1,18 +2025-03-11T12:42:52.167694,479392972,65261,243,32.50178523908,20.726975413635,-57.166884547565,2,1,18 +2025-03-11T12:42:52.183319,479392972,65261,243,32.72324908022,20.953791122415,-57.59326055678,2,1,18 +2025-03-11T12:42:52.198944,479392972,65261,243,32.94000092474,21.203704037355,-58.005858935795,2,1,18 +2025-03-11T12:42:52.214569,479392972,65261,243,33.17088875912,21.439778195715,-58.41380085476,2,1,18 +2025-03-11T12:42:52.230194,479392972,65261,243,33.43004857322,21.657416984565,-58.840194032015,2,1,18 +2025-03-11T12:42:52.245819,479392972,65261,243,33.65151241436,21.87036947787,-59.24802968897,2,1,18 +2025-03-11T12:42:52.261444,479392972,65261,243,33.88240024874,22.092580420755,-59.655915987935,2,1,18 +2025-03-11T12:42:52.277069,479392972,65261,243,34.1085760865,22.3194042825,-60.073056412025,2,1,18 +2025-03-11T12:42:52.292694,479392972,65261,243,34.3441759175,22.5323812347,-60.48553359506,2,1,18 +2025-03-11T12:42:52.308319,479392972,65261,243,34.56092776202,22.759188790515,-60.89341809101,2,1,18 +2025-03-11T12:42:52.323944,479392972,65261,243,34.77296760992,22.98136712154,-61.282792533695,2,1,18 +2025-03-11T12:42:52.339569,479392972,65261,243,34.97558346458,23.203529146635,-61.6813957805,2,1,18 +2025-03-11T12:42:52.355194,479392972,65261,243,35.17819931924,23.411827956255,-62.07532222424,2,1,18 +2025-03-11T12:42:52.370819,479392972,65261,243,35.39966316038,23.61553830591,-62.469257252,2,1,18 +2025-03-11T12:42:52.386444,479392972,65261,243,35.61170300828,23.837716636935,-62.840146962425,2,1,18 +2025-03-11T12:42:52.402069,479392972,65261,243,35.81903085956,24.04602359952,-63.23408018717,2,1,18 +2025-03-11T12:42:52.417694,479392972,65261,243,36.04520669732,24.272847461265,-63.618872329805,2,1,18 +2025-03-11T12:42:52.433319,479392972,65261,243,36.27138253508,24.495050251185,-63.999024749375,2,1,18 +2025-03-11T12:42:52.448944,479392972,65261,243,36.47871038636,24.70335721377,-64.38371560799,2,1,18 +2025-03-11T12:42:52.464569,479392972,65261,243,36.67190224778,24.897776501985,-64.745224588265,2,1,18 +2025-03-11T12:42:52.480194,479392972,65261,243,36.87451810244,25.096833167955,-65.12525040281,2,1,18 +2025-03-11T12:42:52.495819,479392972,65261,243,37.0771339571,25.30051090575,-65.505294757355,2,1,18 +2025-03-11T12:42:52.511444,479392972,65261,243,37.30330979486,25.527334767495,-65.876223350795,2,1,18 +2025-03-11T12:42:52.527069,479392972,65261,243,37.51063764614,25.749504945555,-66.247106280215,2,1,18 +2025-03-11T12:42:52.542694,479392972,65261,243,37.7132535008,25.95318268335,-66.622529451695,2,1,18 +2025-03-11T12:42:52.558319,479392972,65261,243,37.90644536222,26.147601971565,-66.979417248905,2,1,18 +2025-03-11T12:42:52.573944,479392972,65261,243,38.09492522702,26.332770963165,-67.340882368175,2,1,18 +2025-03-11T12:42:52.589569,479392972,65261,243,38.28340509182,26.52256102659,-67.702366027445,2,1,18 +2025-03-11T12:42:52.605194,479392972,65261,243,38.48602094648,26.72161769256,-68.068528292795,2,1,18 +2025-03-11T12:42:52.620819,479392972,65261,243,38.68392480452,26.920666205565,-68.430062594075,2,1,18 +2025-03-11T12:42:52.636444,479392972,65261,243,38.86298067608,27.11968210671,-68.773085039075,2,1,18 +2025-03-11T12:42:52.652069,479392972,65261,243,39.05146054088,27.318714313785,-69.106878679955,2,1,18 +2025-03-11T12:42:52.667694,479392972,65261,243,39.2446524023,27.50389145835,-69.44986584797,2,1,18 +2025-03-11T12:42:52.683319,479392972,65261,243,39.43784426372,27.689068602915,-69.80671656518,2,1,18 +2025-03-11T12:42:52.698944,479392972,65261,243,39.63103612514,27.85576146018,-70.140387207065,2,1,18 +2025-03-11T12:42:52.714569,479392972,65261,243,39.81480399332,28.031680155165,-70.460217817745,2,1,18 +2025-03-11T12:42:52.730194,479392972,65261,243,39.9985718615,28.2168409938,-70.780085508425,2,1,18 +2025-03-11T12:42:52.745819,479392972,65261,243,40.1634917432,28.39734814875,-71.109149901215,2,1,18 +2025-03-11T12:42:52.761444,479392972,65261,243,40.35668360462,28.58714636514,-71.419807327775,2,1,18 +2025-03-11T12:42:52.777069,479392972,65261,243,40.53102747956,28.772290897845,-71.74428263951,2,1,18 +2025-03-11T12:42:52.792694,479392972,65261,243,40.69123536464,28.929684540705,-72.073247551295,2,1,18 +2025-03-11T12:42:52.808319,479392972,65261,243,40.85144324972,29.11018354269,-72.38382043082,2,1,18 +2025-03-11T12:42:52.823944,479392972,65261,243,41.03992311452,29.290731462465,-72.68981281331,2,1,18 +2025-03-11T12:42:52.839569,479392972,65261,243,41.21897898608,29.466642004485,-73.01425782605,2,1,18 +2025-03-11T12:42:52.855194,479392972,65261,243,41.38389886778,29.64252808761,-73.32481894658,2,1,18 +2025-03-11T12:42:52.870819,479392972,65261,243,41.54881874948,29.80455095526,-73.63532444711,2,1,18 +2025-03-11T12:42:52.886444,479392972,65261,243,41.7184506278,29.975824119525,-73.93201025945,2,1,18 +2025-03-11T12:42:52.902069,479392972,65261,243,41.89279450274,30.147105436755,-74.2148393036,2,1,18 +2025-03-11T12:42:52.917694,479392972,65261,243,42.05300238782,30.29987800779,-74.516058576995,2,1,18 +2025-03-11T12:42:52.933319,479392972,65261,243,42.20378627966,30.461876416545,-74.80805900225,2,1,18 +2025-03-11T12:42:52.948944,479392972,65261,243,42.36399416474,30.619270059405,-75.09543326645,2,1,18 +2025-03-11T12:42:52.964569,479392972,65261,243,42.51477805658,30.78126846816,-75.38281250864,2,1,18 +2025-03-11T12:42:52.980194,479392972,65261,243,42.66556194842,30.924782589615,-75.67011759083,2,1,18 +2025-03-11T12:42:52.995819,479392972,65261,243,42.81634584026,31.08678099837,-75.95749683302,2,1,18 +2025-03-11T12:42:53.011444,479392972,65261,243,42.9671297321,31.2441583353,-76.221751619885,2,1,18 +2025-03-11T12:42:53.027069,479392972,65261,243,43.10377763408,31.383026926035,-76.495154269865,2,1,18 +2025-03-11T12:42:53.042694,479392972,65261,243,43.25456152592,31.531162119315,-76.77785670899,2,1,18 +2025-03-11T12:42:53.058319,479392972,65261,243,43.414769411,31.68393469035,-77.060591250125,2,1,18 +2025-03-11T12:42:53.073944,479392972,65261,243,43.56084130622,31.832061730665,-77.32018099292,2,1,18 +2025-03-11T12:42:53.089569,479392972,65261,243,43.71633719468,31.975584005085,-77.570523391595,2,1,18 +2025-03-11T12:42:53.105194,479392972,65261,243,43.84827310004,32.11906551468,-77.811589519115,2,1,18 +2025-03-11T12:42:53.120819,479392972,65261,243,43.97078501216,32.24866750287,-78.071071196885,2,1,18 +2025-03-11T12:42:53.136444,479392972,65261,243,44.10743291414,32.40139930908,-78.335287100735,2,1,18 +2025-03-11T12:42:53.152069,479392972,65261,243,44.25821680598,32.54953450236,-78.585641258405,2,1,18 +2025-03-11T12:42:53.167694,479392972,65261,243,44.39957670458,32.66068481511,-78.817348801805,2,1,18 +2025-03-11T12:42:53.183319,479392972,65261,243,44.53622460656,32.78569019037,-79.05834755033,2,1,18 +2025-03-11T12:42:53.198944,479392972,65261,243,44.6634485153,32.924542475175,-79.290145990715,2,1,18 +2025-03-11T12:42:53.214569,479392972,65261,243,44.79067242404,33.058773688155,-79.5219258911,2,1,18 +2025-03-11T12:42:53.230194,479392972,65261,243,44.91789633278,33.18838382931,-79.762929617615,2,1,18 +2025-03-11T12:42:53.245819,479392972,65261,243,45.04983223814,33.313381051605,-79.99005803594,2,1,18 +2025-03-11T12:42:53.261444,479392972,65261,243,45.18648014012,33.429144283215,-80.23564088753,2,1,18 +2025-03-11T12:42:53.277069,479392972,65261,243,45.31370404886,33.54027013707,-80.467328087915,2,1,18 +2025-03-11T12:42:53.292694,479392972,65261,243,45.42679196774,33.66985581933,-80.68520555609,2,1,18 +2025-03-11T12:42:53.308319,479392972,65261,243,45.54930387986,33.813321022995,-80.89853102321,2,1,18 +2025-03-11T12:42:53.323944,479392972,65261,243,45.67181579198,33.93830193936,-81.1025399642,2,1,18 +2025-03-11T12:42:53.339569,479392972,65261,243,45.78019171424,34.030910894055,-81.31101996524,2,1,18 +2025-03-11T12:42:53.355194,479392972,65261,243,45.89327963312,34.142012289015,-81.528823273415,2,1,18 +2025-03-11T12:42:53.370819,479392972,65261,243,46.02050354186,34.267001358345,-81.746702544605,2,1,18 +2025-03-11T12:42:53.386444,479392972,65261,243,46.1241674675,34.3642232319,-81.94595193851,2,1,18 +2025-03-11T12:42:53.402069,479392972,65261,243,46.22783139314,34.46606617728,-82.12211395709,2,1,18 +2025-03-11T12:42:53.417694,479392972,65261,243,46.33149531878,34.572530194485,-82.312158064865,2,1,18 +2025-03-11T12:42:53.433319,479392972,65261,243,46.42102325456,34.66510653732,-82.520610941885,2,1,18 +2025-03-11T12:42:53.448944,479392972,65261,243,46.51997518358,34.766941329735,-82.701387362525,2,1,18 +2025-03-11T12:42:53.464569,479392972,65261,243,46.62363910922,34.87340534694,-82.886810287235,2,1,18 +2025-03-11T12:42:53.480194,479392972,65261,243,46.72730303486,34.979869364145,-83.072233211945,2,1,18 +2025-03-11T12:42:53.495819,479392972,65261,243,46.82625496388,35.08170415656,-83.23914608339,2,1,18 +2025-03-11T12:42:53.511444,479392972,65261,243,46.91578289966,35.17890157122,-83.41064803589,2,1,18 +2025-03-11T12:42:53.527069,479392972,65261,243,47.02887081854,35.27151867888,-83.582165353415,2,1,18 +2025-03-11T12:42:53.542694,479392972,65261,243,47.12782274756,35.35024811217,-83.74898552486,2,1,18 +2025-03-11T12:42:53.558319,479392972,65261,243,47.21735068334,35.442824455005,-83.92046893736,2,1,18 +2025-03-11T12:42:53.573944,479392972,65261,243,47.30687861912,35.540021869665,-84.08272852373,2,1,18 +2025-03-11T12:42:53.589569,479392972,65261,243,47.38698256166,35.627960834745,-84.231073918895,2,1,18 +2025-03-11T12:42:53.605194,479392972,65261,243,47.4670865042,35.715899799825,-84.393282863255,2,1,18 +2025-03-11T12:42:53.620819,479392972,65261,243,47.5377664535,35.776096028025,-84.546124639475,2,1,18 +2025-03-11T12:42:53.636444,479392972,65261,243,47.60373440618,35.859389462385,-84.675946419365,2,1,18 +2025-03-11T12:42:53.652069,479392972,65261,243,47.68383834872,35.938086283815,-84.83349710066,2,1,18 +2025-03-11T12:42:53.667694,479392972,65261,243,47.76865428788,36.012170186385,-84.96330892457,2,1,18 +2025-03-11T12:42:53.683319,479392972,65261,243,47.84875823042,36.09548807964,-85.074666315215,2,1,18 +2025-03-11T12:42:53.698944,479392972,65261,243,47.92886217296,36.17418490107,-85.22297463038,2,1,18 +2025-03-11T12:42:53.714569,479392972,65261,243,48.01839010874,36.26214017208,-85.352848855295,2,1,18 +2025-03-11T12:42:53.730194,479392972,65261,243,48.09849405128,36.31311056256,-85.487182381265,2,1,18 +2025-03-11T12:42:53.745819,479392972,65261,243,48.14090202086,36.377878944795,-85.60765373,2,1,18 +2025-03-11T12:42:53.761444,479392972,65261,243,48.18802198706,36.44727655182,-85.71890803361,2,1,18 +2025-03-11T12:42:53.777069,479392972,65261,243,48.2445659465,36.507448321125,-85.816275270035,2,1,18 +2025-03-11T12:42:53.792694,479392972,65261,243,48.31053389918,36.56763639636,-85.936761983795,2,1,18 +2025-03-11T12:42:53.808319,479392972,65261,243,48.36707785862,36.62318709384,-86.057216595545,2,1,18 +2025-03-11T12:42:53.823944,479392972,65261,243,48.42833381468,36.669503800635,-86.163777359105,2,1,18 +2025-03-11T12:42:53.839569,479392972,65261,243,48.47545378088,36.72965926401,-86.265752216585,2,1,18 +2025-03-11T12:42:53.855194,479392972,65261,243,48.51786175046,36.794427646245,-86.344632917735,2,1,18 +2025-03-11T12:42:53.870819,479392972,65261,243,48.58382970314,36.84537357783,-86.42349190391,2,1,18 +2025-03-11T12:42:53.886444,479392972,65261,243,48.64037366258,36.89168213166,-86.520803520335,2,1,18 +2025-03-11T12:42:53.902069,479392972,65261,243,48.69691762202,36.93799068549,-86.622736319825,2,1,18 +2025-03-11T12:42:53.917694,479392972,65261,243,48.73461359498,36.979645555635,-86.7107599061,2,1,18 +2025-03-11T12:42:53.933319,479392972,65261,243,48.77702156456,37.02592965057,-86.81729354564,2,1,18 +2025-03-11T12:42:53.948944,479392972,65261,243,48.82885352738,37.06760897961,-86.919201024125,2,1,18 +2025-03-11T12:42:53.964569,479392972,65261,243,48.87126149696,37.10002985907,-86.997951945275,2,1,18 +2025-03-11T12:42:53.980194,479392972,65261,243,48.90895746992,37.13706365739,-87.05822989316,2,1,18 +2025-03-11T12:42:53.995758,479392976,65257,244,48.93722944964,37.16483900613,-87.099972466775,2,1,18 +2025-03-11T12:42:54.011383,479392976,65257,244,48.96078943274,37.19722727373,-87.16483271471,2,1,18 +2025-03-11T12:42:54.027008,479392976,65257,244,48.9984854057,37.229640000225,-87.22971330566,2,1,18 +2025-03-11T12:42:54.042633,479392976,65257,244,49.03618137866,37.266673798545,-87.299233619675,2,1,18 +2025-03-11T12:42:54.058258,479392976,65257,244,49.05974136176,37.28519885067,-87.350174698415,2,1,18 +2025-03-11T12:42:54.073883,479392976,65257,244,49.08330134486,37.30834497462,-87.38727076796,2,1,18 +2025-03-11T12:42:54.089508,479392976,65257,244,49.12570931444,37.34076585408,-87.42905222459,2,1,18 +2025-03-11T12:42:54.105133,479392976,65257,244,49.15398129416,37.354677987345,-87.49384509353,2,1,18 +2025-03-11T12:42:54.120758,479392976,65257,244,49.17282928064,37.373194886505,-87.517052292875,2,1,18 +2025-03-11T12:42:54.136383,479392976,65257,244,49.19167726712,37.38709071384,-87.535619769155,2,1,18 +2025-03-11T12:42:54.152008,479392976,65257,244,49.21523725022,37.405615765965,-87.54497020031,2,1,18 +2025-03-11T12:42:54.167633,479392976,65257,244,49.21994924684,37.42410820623,-87.57739942277,2,1,18 +2025-03-11T12:42:54.183258,479392976,65257,244,49.22466124346,37.424116359195,-87.6005121191,2,1,18 +2025-03-11T12:42:54.198883,479392976,65257,244,49.22937324008,37.437987727635,-87.6144380693,2,1,18 +2025-03-11T12:42:54.214508,479392976,65257,244,49.22466124346,37.442600646495,-87.62831337749,2,1,18 +2025-03-11T12:42:54.230133,479392976,65257,244,49.22937324008,37.447229871285,-87.637581064625,2,1,18 +2025-03-11T12:42:54.245758,479392976,65257,244,49.23879723332,37.456488320865,-87.619146974375,2,1,18 +2025-03-11T12:42:54.261383,479392976,65257,244,49.24350922994,37.44725433018,-87.623737858445,2,1,18 +2025-03-11T12:42:54.277008,479392976,65257,244,49.24822122656,37.46112569862,-87.619179076385,2,1,18 +2025-03-11T12:42:54.292633,479392976,65257,244,49.24822122656,37.465746770445,-87.61457643332,2,1,18 +2025-03-11T12:42:54.308258,479392976,65257,244,49.24350922994,37.45649647383,-87.614532572315,2,1,18 +2025-03-11T12:42:54.323883,479392976,65257,244,49.2340852367,37.44723802425,-87.60061838111,2,1,18 +2025-03-11T12:42:54.339508,479392976,65257,244,49.22937324008,37.43336665581,-87.609798346235,2,1,18 +2025-03-11T12:42:54.355133,479392976,65257,244,49.22937324008,37.42412451216,-87.591276533975,2,1,18 +2025-03-11T12:42:54.370758,479392976,65257,244,49.2105252536,37.400986541175,-87.57729316076,2,1,18 +2025-03-11T12:42:54.386383,479392976,65257,244,49.20110126036,37.38710701977,-87.563360429555,2,1,18 +2025-03-11T12:42:54.402008,479392976,65257,244,49.19167726712,37.37784857019,-87.52171913996,2,1,18 +2025-03-11T12:42:54.417633,479392976,65257,244,49.17754127726,37.36396089582,-87.466188980165,2,1,18 +2025-03-11T12:42:54.433258,479392976,65257,244,49.14926929754,37.340806618905,-87.410601397355,2,1,18 +2025-03-11T12:42:54.448883,479392976,65257,244,49.1162853212,37.317644189025,-87.35500703354,2,1,18 +2025-03-11T12:42:54.464508,479392976,65257,244,49.0927253381,37.2991191369,-87.317929503995,2,1,18 +2025-03-11T12:42:54.480133,479392976,65257,244,49.07387735162,37.26211795044,-87.262299863195,2,1,18 +2025-03-11T12:42:54.495758,479392976,65257,244,49.04089337528,37.234334448735,-87.21592932551,2,1,18 +2025-03-11T12:42:54.511383,479392976,65257,244,49.01262139556,37.225043387295,-87.174260911895,2,1,18 +2025-03-11T12:42:54.527008,479392976,65257,244,48.97963741922,37.22498631654,-87.12800161421,2,1,18 +2025-03-11T12:42:54.542633,479392976,65257,244,48.94194144626,37.17871037457,-87.058444220195,2,1,18 +2025-03-11T12:42:54.558258,479392976,65257,244,48.91838146316,37.123216747845,-87.007354821455,2,1,18 +2025-03-11T12:42:54.573883,479392976,65257,244,48.89482148006,37.072344192945,-86.947041596585,2,1,18 +2025-03-11T12:42:54.589508,479392976,65257,244,48.8571255071,37.035310394625,-86.86827891644,2,1,18 +2025-03-11T12:42:54.605133,479392976,65257,244,48.80058154766,36.989001840795,-86.76634611695,2,1,18 +2025-03-11T12:42:54.620758,479392976,65257,244,48.75817357808,36.956580961335,-86.673731646605,2,1,18 +2025-03-11T12:42:54.636383,479392976,65257,244,48.72047760512,36.92416823484,-86.59498750646,2,1,18 +2025-03-11T12:42:54.652008,479392976,65257,244,48.68749362878,36.87327937401,-86.52541835345,2,1,18 +2025-03-11T12:42:54.667633,479392976,65257,244,48.63566166596,36.817736829495,-86.441939987225,2,1,18 +2025-03-11T12:42:54.683258,479392976,65257,244,48.57911770652,36.780670419315,-86.349286633865,2,1,18 +2025-03-11T12:42:54.698883,479392976,65257,244,48.5272857437,36.7251278748,-86.251944718445,2,1,18 +2025-03-11T12:42:54.714508,479392976,65257,244,48.47545378088,36.660343186635,-86.145323356895,2,1,18 +2025-03-11T12:42:54.730133,479392976,65257,244,48.42362181806,36.600179570295,-86.029478169215,2,1,18 +2025-03-11T12:42:54.745758,479392976,65257,244,48.35294186876,36.51687798297,-85.941240255905,2,1,18 +2025-03-11T12:42:54.761383,479392976,65257,244,48.29639790932,36.45208514184,-85.820748564155,2,1,18 +2025-03-11T12:42:54.777008,479392976,65257,244,48.23042995664,36.401139210255,-85.691056564265,2,1,18 +2025-03-11T12:42:54.792633,479392976,65257,244,48.15975000734,36.34556405388,-85.565960426435,2,1,18 +2025-03-11T12:42:54.808258,479392976,65257,244,48.09849405128,36.29462627526,-85.450138756745,2,1,18 +2025-03-11T12:42:54.823883,479392976,65257,244,48.0325260986,36.2298171282,-85.301906404595,2,1,18 +2025-03-11T12:42:54.839508,479392976,65257,244,47.9618461493,36.1511366127,-85.18133874983,2,1,18 +2025-03-11T12:42:54.855133,479392976,65257,244,47.88645420338,36.07706901606,-85.065404037125,2,1,18 +2025-03-11T12:42:54.870758,479392976,65257,244,47.8204862507,35.9937755817,-84.9402034403,2,1,18 +2025-03-11T12:42:54.886383,479392976,65257,244,47.74038230816,35.919699832095,-84.791913665135,2,1,18 +2025-03-11T12:42:54.902008,479392976,65257,244,47.64614237576,35.85022069542,-84.652864453085,2,1,18 +2025-03-11T12:42:54.917633,479392976,65257,244,47.56603843322,35.75303958669,-84.499860794855,2,1,18 +2025-03-11T12:42:54.933258,479392976,65257,244,47.4906464873,35.665108774575,-84.35614336376,2,1,18 +2025-03-11T12:42:54.948883,479392976,65257,244,47.41054254476,35.58179088132,-84.20319532553,2,1,18 +2025-03-11T12:42:54.964508,479392976,65257,244,47.3257266056,35.493843763275,-84.0363584171,2,1,18 +2025-03-11T12:42:54.980133,479392976,65257,244,47.24562266306,35.40128372637,-83.878752115805,2,1,18 +2025-03-11T12:42:54.995758,479392976,65257,244,47.15609472728,35.317949527185,-83.7211693325,2,1,18 +2025-03-11T12:42:55.011383,479392976,65257,244,47.04771880502,35.239203787965,-83.54971441598,2,1,18 +2025-03-11T12:42:55.027008,479392976,65257,244,46.95819086924,35.142006373305,-83.38745482961,2,1,18 +2025-03-11T12:42:55.042633,479392976,65257,244,46.86395093684,35.058664021155,-83.216001716105,2,1,18 +2025-03-11T12:42:55.058258,479392976,65257,244,46.76971100444,34.956837381705,-83.02598971034,2,1,18 +2025-03-11T12:42:55.073883,479392976,65257,244,46.6660470788,34.836510149025,-82.84051116563,2,1,18 +2025-03-11T12:42:55.089508,479392976,65257,244,46.5718071464,34.734683509575,-82.668983892125,2,1,18 +2025-03-11T12:42:55.105133,479392976,65257,244,46.477567214,34.632856870125,-82.492835435555,2,1,18 +2025-03-11T12:42:55.120758,479392976,65257,244,46.36447929512,34.530997618815,-82.29355393964,2,1,18 +2025-03-11T12:42:55.136383,479392976,65257,244,46.2655273661,34.4291628264,-82.10353515287,2,1,18 +2025-03-11T12:42:55.152008,479392976,65257,244,46.1712874337,34.3180940433,-81.90886488404,2,1,18 +2025-03-11T12:42:55.167633,479392976,65257,244,46.06762350806,34.211630026095,-81.718820776265,2,1,18 +2025-03-11T12:42:55.183258,479392976,65257,244,45.94982359256,34.10052047817,-81.537980151605,2,1,18 +2025-03-11T12:42:55.198883,479392976,65257,244,45.83202367706,33.970926642945,-81.329338268555,2,1,18 +2025-03-11T12:42:55.214508,479392976,65257,244,45.70479976832,33.85055864544,-81.12534108656,2,1,18 +2025-03-11T12:42:55.230133,479392976,65257,244,45.59171184944,33.744078322305,-80.926041050645,2,1,18 +2025-03-11T12:42:55.245758,479392976,65257,244,45.4880479238,33.642235376925,-80.712909567545,2,1,18 +2025-03-11T12:42:55.261383,479392976,65257,244,45.37967200154,33.52189999128,-80.504318326505,2,1,18 +2025-03-11T12:42:55.277008,479392976,65257,244,45.24773609618,33.396902768985,-80.272568725115,2,1,18 +2025-03-11T12:42:55.292633,479392976,65257,244,45.12522418406,33.267300780795,-80.02695059654,2,1,18 +2025-03-11T12:42:55.308258,479392976,65257,244,44.9932882787,33.1423035585,-79.790579812085,2,1,18 +2025-03-11T12:42:55.323883,479392976,65257,244,44.86606436996,33.003451273695,-79.5587813717,2,1,18 +2025-03-11T12:42:55.339508,479392976,65257,244,44.74826445446,32.869236366645,-79.327015033325,2,1,18 +2025-03-11T12:42:55.355133,479392976,65257,244,44.62575254234,32.74425545028,-79.07217307862,2,1,18 +2025-03-11T12:42:55.370758,479392976,65257,244,44.48910464036,32.605386859545,-78.840361076225,2,1,18 +2025-03-11T12:42:55.386383,479392976,65257,244,44.34774474176,32.475752259495,-78.60395818976,2,1,18 +2025-03-11T12:42:55.402008,479392976,65257,244,44.22052083302,32.33689997469,-78.353675017115,2,1,18 +2025-03-11T12:42:55.417633,479392976,65257,244,44.07916093442,32.193402159165,-78.09873177839,2,1,18 +2025-03-11T12:42:55.433258,479392976,65257,244,43.93780103582,32.045283271815,-77.853012365795,2,1,18 +2025-03-11T12:42:55.448883,479392976,65257,244,43.80586513046,31.915664977695,-77.58889594295,2,1,18 +2025-03-11T12:42:55.464508,479392976,65257,244,43.65979323524,31.762916865555,-77.320045294025,2,1,18 +2025-03-11T12:42:55.480133,479392976,65257,244,43.52314533326,31.60556398752,-77.05118966711,2,1,18 +2025-03-11T12:42:55.495758,479392976,65257,244,43.3676494448,31.475904928575,-76.81476643763,2,1,18 +2025-03-11T12:42:55.511383,479392976,65257,244,43.20744155972,31.336995573015,-76.53670869956,2,1,18 +2025-03-11T12:42:55.527008,479392976,65257,244,43.06608166112,31.18425561384,-76.254001282445,2,1,18 +2025-03-11T12:42:55.542633,479392976,65257,244,42.9200097659,31.026886429875,-75.962026178195,2,1,18 +2025-03-11T12:42:55.558258,479392976,65257,244,42.77393787068,30.86951724591,-75.679293440075,2,1,18 +2025-03-11T12:42:55.573883,479392976,65257,244,42.60901798898,30.702873306435,-75.396496497935,2,1,18 +2025-03-11T12:42:55.589508,479392976,65257,244,42.4488101039,30.55934287905,-75.1137990368,2,1,18 +2025-03-11T12:42:55.605133,479392976,65257,244,42.28860221882,30.42043352349,-74.831120115665,2,1,18 +2025-03-11T12:42:55.620758,479392976,65257,244,42.12839433374,30.25379773698,-74.543708771465,2,1,18 +2025-03-11T12:42:55.636383,479392976,65257,244,41.96818644866,30.073298734995,-74.237757075005,2,1,18 +2025-03-11T12:42:55.652008,479392976,65257,244,41.80326656696,29.89741265187,-73.92257477141,2,1,18 +2025-03-11T12:42:55.667633,479392976,65257,244,41.63363468864,29.726139487605,-73.6351313252,2,1,18 +2025-03-11T12:42:55.683258,479392976,65257,244,41.47342680356,29.56412477292,-73.324632605675,2,1,18 +2025-03-11T12:42:55.698883,479392976,65257,244,41.30850692186,29.39285976162,-73.023332391275,2,1,18 +2025-03-11T12:42:55.714508,479392976,65257,244,41.13416304692,29.22157844439,-72.731260980995,2,1,18 +2025-03-11T12:42:55.730133,479392976,65257,244,40.9645311686,29.05492635195,-72.4022454272,2,1,18 +2025-03-11T12:42:55.745758,479392976,65257,244,40.80432328352,28.88829056544,-72.07786461848,2,1,18 +2025-03-11T12:42:55.761383,479392976,65257,244,40.62055541534,28.712371870455,-71.762655190865,2,1,18 +2025-03-11T12:42:55.777008,479392976,65257,244,40.43678754716,28.52721103182,-71.42892395099,2,1,18 +2025-03-11T12:42:55.792633,479392976,65257,244,40.2577316756,28.36054263345,-71.11375838438,2,1,18 +2025-03-11T12:42:55.808258,479392976,65257,244,40.08338780066,28.184640244395,-70.789320152645,2,1,18 +2025-03-11T12:42:55.823883,479392976,65257,244,39.89490793586,28.01333446827,-70.46950130096,2,1,18 +2025-03-11T12:42:55.839508,479392976,65257,244,39.7158520643,27.805076423475,-70.140305325155,2,1,18 +2025-03-11T12:42:55.855133,479392976,65257,244,39.5273721995,27.610665288225,-69.81115140734,2,1,18 +2025-03-11T12:42:55.870758,479392976,65257,244,39.32946834146,27.43934320617,-69.46821307832,2,1,18 +2025-03-11T12:42:55.886383,479392976,65257,244,39.14570047328,27.24956129571,-69.10211501699,2,1,18 +2025-03-11T12:42:55.902008,479392976,65257,244,38.96664460172,27.06440861004,-68.745284642795,2,1,18 +2025-03-11T12:42:55.917633,479392976,65257,244,38.78287673354,26.86538455593,-68.406876599855,2,1,18 +2025-03-11T12:42:55.933258,479392976,65257,244,38.5849728755,26.666336042925,-68.05920584777,2,1,18 +2025-03-11T12:42:55.948883,479392976,65257,244,38.39178101408,26.48115889836,-67.70235513056,2,1,18 +2025-03-11T12:42:55.964508,479392976,65257,244,38.1844531628,26.291336223075,-67.3500867134,2,1,18 +2025-03-11T12:42:55.980133,479392976,65257,244,37.97712531152,26.08302926049,-66.97001703785,2,1,18 +2025-03-11T12:42:55.995758,479392976,65257,244,37.77922145348,25.865496460185,-66.613029759635,2,1,18 +2025-03-11T12:42:56.011383,479392976,65257,244,37.58602959206,25.657213956495,-66.246843976295,2,1,18 +2025-03-11T12:42:56.027008,479392976,65257,244,37.39283773064,25.467415740105,-65.880732352955,2,1,18 +2025-03-11T12:42:56.042633,479392976,65257,244,37.18079788274,25.259100624555,-65.514519445595,2,1,18 +2025-03-11T12:42:56.058258,479392976,65257,244,36.9828940247,25.06005211155,-65.13912159512,2,1,18 +2025-03-11T12:42:56.073883,479392976,65257,244,36.7944141599,24.870262048125,-64.76839556972,2,1,18 +2025-03-11T12:42:56.089508,479392976,65257,244,36.6059342951,24.675850912875,-64.383787455125,2,1,18 +2025-03-11T12:42:56.105133,479392976,65257,244,36.38918245058,24.453664428885,-63.994406231435,2,1,18 +2025-03-11T12:42:56.120758,479392976,65257,244,36.17243060606,24.222235801245,-63.60960911081,2,1,18 +2025-03-11T12:42:56.136383,479392976,65257,244,35.96039075816,24.013920685695,-63.23415383732,2,1,18 +2025-03-11T12:42:56.152008,479392976,65257,244,35.74363891364,23.81483956083,-62.849486496695,2,1,18 +2025-03-11T12:42:56.167633,479392976,65257,244,35.53631106236,23.597290454595,-62.46475855808,2,1,18 +2025-03-11T12:42:56.183258,479392976,65257,244,35.32898321108,23.375120276535,-62.080012079465,2,1,18 +2025-03-11T12:42:56.198883,479392976,65257,244,35.1216553598,23.1575711703,-61.690662957785,2,1,18 +2025-03-11T12:42:56.214508,479392976,65257,244,34.9096155119,22.9584981984,-61.296760032035,2,1,18 +2025-03-11T12:42:56.230133,479392976,65257,244,34.68815167076,22.745545705095,-60.88892437508,2,1,18 +2025-03-11T12:42:56.245758,479392976,65257,244,34.461975833,22.51872184335,-60.48102631712,2,1,18 +2025-03-11T12:42:56.261383,479392976,65257,244,34.23108799862,22.30113197229,-60.063916192025,2,1,18 +2025-03-11T12:42:56.277008,479392976,65257,244,33.99548816762,22.07891287644,-59.66064429512,2,1,18 +2025-03-11T12:42:56.292633,479392976,65257,244,33.75988833662,21.852072708765,-59.238869125955,2,1,18 +2025-03-11T12:42:56.308258,479392976,65257,244,33.52428850562,21.61599039744,-58.82629924292,2,1,18 +2025-03-11T12:42:56.323883,479392976,65257,244,33.30282466448,21.375311473185,-58.4137311629,2,1,18 +2025-03-11T12:42:56.339508,479392976,65257,244,33.08607281996,21.143882845545,-57.99658576082,2,1,18 +2025-03-11T12:42:56.355133,479392976,65257,244,32.8598969822,20.903195768325,-57.574768533665,2,1,18 +2025-03-11T12:42:56.370758,479392976,65257,244,32.62900914782,20.68098482544,-57.162261051635,2,1,18 +2025-03-11T12:42:56.386383,479392976,65257,244,32.40283331006,20.44953989187,-56.735859721415,2,1,18 +2025-03-11T12:42:56.402008,479392976,65257,244,32.1766574723,20.2180949583,-56.31407957426,2,1,18 +2025-03-11T12:42:56.417633,479392976,65257,244,31.93634564468,19.98200449401,-55.878396994895,2,1,18 +2025-03-11T12:42:56.433258,479392976,65257,244,31.70074581368,19.73205896721,-55.451907942665,2,1,18 +2025-03-11T12:42:56.448883,479392976,65257,244,31.47456997592,19.477508674515,-55.03003509551,2,1,18 +2025-03-11T12:42:56.464508,479392976,65257,244,31.23897014492,19.23218421954,-54.589701034085,2,1,18 +2025-03-11T12:42:56.480133,479392976,65257,244,30.97981033082,18.99606114339,-54.1539913307,2,1,18 +2025-03-11T12:42:56.495758,479392976,65257,244,30.73007450996,18.75995437317,-53.71367400626,2,1,18 +2025-03-11T12:42:56.511383,479392976,65257,244,30.48976268234,18.519242837055,-53.250245788505,2,1,18 +2025-03-11T12:42:56.527008,479392976,65257,244,30.24945085472,18.27853130094,-52.81454466914,2,1,18 +2025-03-11T12:42:56.542633,479392976,65257,244,30.01856302034,18.05169928623,-52.37429154872,2,1,18 +2025-03-11T12:42:56.558258,479392976,65257,244,29.79238718258,17.797148993535,-51.933933969305,2,1,18 +2025-03-11T12:42:56.573883,479392976,65257,244,29.5379393651,17.56103407035,-51.49360986386,2,1,18 +2025-03-11T12:42:56.589508,479392976,65257,244,29.278779551,17.31566885055,-51.02551479902,2,1,18 +2025-03-11T12:42:56.605133,479392976,65257,244,29.01490774028,17.06567440596,-50.57125796237,2,1,18 +2025-03-11T12:42:56.620758,479392976,65257,244,28.77459591266,16.81109965437,-50.09391057542,2,1,18 +2025-03-11T12:42:56.636383,479392976,65257,244,28.53428408504,16.551903830955,-49.61654464847,2,1,18 +2025-03-11T12:42:56.652008,479392976,65257,244,28.27512427094,16.29267539568,-49.15763632976,2,1,18 +2025-03-11T12:42:56.667633,479392976,65257,244,28.02067645346,16.038076185195,-48.680268599795,2,1,18 +2025-03-11T12:42:56.683258,479392976,65257,244,27.76622863598,15.778855902885,-48.216745879025,2,1,18 +2025-03-11T12:42:56.698883,479392976,65257,244,27.5117808185,15.53349883605,-47.744036412125,2,1,18 +2025-03-11T12:42:56.714508,479392976,65257,244,27.26675699426,15.28353700332,-47.280564333365,2,1,18 +2025-03-11T12:42:56.730133,479392976,65257,244,27.01230917678,15.028937792835,-46.826302518725,2,1,18 +2025-03-11T12:42:56.745758,479392976,65257,244,26.75314936268,14.783572573035,-46.367449820015,2,1,18 +2025-03-11T12:42:56.761383,479392976,65257,244,26.48927755196,14.51971491297,-45.88078908191,2,1,18 +2025-03-11T12:42:56.777008,479392976,65257,244,26.24425372772,14.24202664929,-45.38023629863,2,1,18 +2025-03-11T12:42:56.792633,479392976,65257,244,25.980381917,13.96430577375,-44.902762306655,2,1,18 +2025-03-11T12:42:56.808258,479392976,65257,244,25.71651010628,13.700448113685,-44.43458630081,2,1,18 +2025-03-11T12:42:56.823883,479392976,65257,244,25.44321430232,13.42733200404,-43.966359652955,2,1,18 +2025-03-11T12:42:56.839508,479392976,65257,244,25.16520650174,13.177313100555,-43.488976557965,2,1,18 +2025-03-11T12:42:56.855133,479392976,65257,244,24.90133469102,12.92269758414,-43.00235289986,2,1,18 +2025-03-11T12:42:56.870758,479392976,65257,244,24.64217487692,12.64960593339,-42.52490422889,2,1,18 +2025-03-11T12:42:56.886383,479392976,65257,244,24.3783030662,12.3626429142,-42.028908424655,2,1,18 +2025-03-11T12:42:56.902008,479392976,65257,244,24.12385524872,12.089559416415,-41.537602985495,2,1,18 +2025-03-11T12:42:56.917633,479392976,65257,244,23.84584744814,11.816435153805,-41.041642458245,2,1,18 +2025-03-11T12:42:56.933258,479392976,65257,244,23.5772636408,11.552569340775,-40.564217305265,2,1,18 +2025-03-11T12:42:56.948883,479392976,65257,244,23.3181038267,11.279477690025,-40.0729050851,2,1,18 +2025-03-11T12:42:56.964508,479392976,65257,244,23.04952001936,11.006369733345,-39.572336936795,2,1,18 +2025-03-11T12:42:56.980133,479392976,65257,244,22.76208822554,10.742471308455,-39.094884659795,2,1,18 +2025-03-11T12:42:56.995758,479392976,65257,244,22.47936842834,10.464717821055,-38.58965644541,2,1,18 +2025-03-11T12:42:57.011383,479392976,65257,244,22.19193663452,10.19619832434,-38.089079713085,2,1,18 +2025-03-11T12:42:57.027008,479392976,65257,244,21.92335282718,9.918469295835,-37.57925065865,2,1,18 +2025-03-11T12:42:57.042633,479392976,65257,244,21.65948101646,9.65461163577,-37.07872637135,2,1,18 +2025-03-11T12:42:57.058258,479392976,65257,244,21.3861852125,9.381495526125,-36.573530258975,2,1,18 +2025-03-11T12:42:57.073883,479392976,65257,244,21.12231340178,9.113016794235,-36.05912388248,2,1,18 +2025-03-11T12:42:57.089508,479392976,65257,244,20.85372959444,8.81680347843,-35.53535711885,2,1,18 +2025-03-11T12:42:57.105133,479392976,65257,244,20.56629780062,8.529799694415,-35.016221494265,2,1,18 +2025-03-11T12:42:57.120758,479392976,65257,244,20.2788660068,8.2427959104,-34.529434151135,2,1,18 +2025-03-11T12:42:57.136383,479392976,65257,244,20.00085820622,7.974292719615,-34.024249797755,2,1,18 +2025-03-11T12:42:57.152008,479392976,65257,244,19.72285040564,7.691926313355,-33.500525092115,2,1,18 +2025-03-11T12:42:57.167633,479392976,65257,244,19.44484260506,7.40493883527,-32.98140302954,2,1,18 +2025-03-11T12:42:57.183258,479392976,65257,244,19.16212280786,7.11794320422,-32.476137735155,2,1,18 +2025-03-11T12:42:57.198883,479392976,65257,244,18.88411500728,6.82633465431,-31.95699713258,2,1,18 +2025-03-11T12:42:57.214508,479392976,65257,244,18.60139521008,6.53933902326,-31.44711065513,2,1,18 +2025-03-11T12:42:57.230133,479392976,65257,244,18.30925141964,6.256948158105,-30.90950205728,2,1,18 +2025-03-11T12:42:57.245758,479392976,65257,244,18.02653162244,5.97457359888,-30.385770570635,2,1,18 +2025-03-11T12:42:57.261383,479392976,65257,244,17.74852382186,5.696828264445,-29.880549137255,2,1,18 +2025-03-11T12:42:57.277008,479392976,65257,244,17.4516680348,5.4282924618,-29.36147411066,2,1,18 +2025-03-11T12:42:57.292633,479392976,65257,244,17.1689482376,5.136675758925,-28.83308436095,2,1,18 +2025-03-11T12:42:57.308258,479392976,65257,244,16.89094043702,4.845067209015,-28.295459026115,2,1,18 +2025-03-11T12:42:57.323883,479392976,65257,244,16.60822063982,4.55345050614,-27.7809328256,2,1,18 +2025-03-11T12:42:57.339508,479392976,65257,244,16.320788846,4.27106779395,-27.24795219182,2,1,18 +2025-03-11T12:42:57.355133,479392976,65257,244,16.0380690488,3.988693234725,-26.71959952211,2,1,18 +2025-03-11T12:42:57.370758,479392976,65257,244,15.73650126512,3.683180704515,-26.214232943705,2,1,18 +2025-03-11T12:42:57.386383,479392976,65257,244,15.4490694713,3.391555848675,-25.699699962185,2,1,18 +2025-03-11T12:42:57.402008,479392976,65257,244,15.14750168762,3.09066439029,-25.17586719152,2,1,18 +2025-03-11T12:42:57.417633,479392976,65257,244,14.8600698938,2.794418462625,-24.63358857161,2,1,18 +2025-03-11T12:42:57.433258,479392976,65257,244,14.58677408984,2.516681281155,-24.09602563778,2,1,18 +2025-03-11T12:42:57.448883,479392976,65257,244,14.28991830278,2.215797975735,-23.55371491586,2,1,18 +2025-03-11T12:42:57.464508,479392976,65257,244,13.99306251572,1.924156813965,-23.01144127394,2,1,18 +2025-03-11T12:42:57.480133,479392976,65257,244,13.69620672866,1.64637886767,-22.47846561815,2,1,18 +2025-03-11T12:42:57.495758,479392976,65257,244,13.40406293822,1.35012478704,-21.95004376643,2,1,18 +2025-03-11T12:42:57.511383,479392976,65257,244,13.10720715116,1.053862553445,-21.412372767575,2,1,18 +2025-03-11T12:42:57.527008,479392976,65257,244,12.82919935058,0.753011859885,-20.879331535805,2,1,18 +2025-03-11T12:42:57.542633,479392976,65257,244,12.54176755676,0.461387004045,-20.36017737122,2,1,18 +2025-03-11T12:42:57.558258,479392976,65257,244,12.24962376632,0.169753995240001,-19.82253169337,2,1,18 +2025-03-11T12:42:57.573883,479392976,65257,244,11.95276797926,-0.12188716653,-19.275636868385,2,1,18 +2025-03-11T12:42:57.589508,479392976,65257,244,11.67004818206,-0.413503869405,-18.75186830174,2,1,18 +2025-03-11T12:42:57.605133,479392976,65257,244,11.373192395,-0.6912818157,-18.22813501208,2,1,18 +2025-03-11T12:42:57.620758,479392976,65257,244,11.0669126147,-0.996802498874999,-17.69503455428,2,1,18 +2025-03-11T12:42:57.636383,479392976,65257,244,10.77948082088,-1.32077485749,-17.148023511305,2,1,18 +2025-03-11T12:42:57.652008,479392976,65257,244,10.46848904396,-1.621682621805,-16.58720771411,2,1,18 +2025-03-11T12:42:57.667633,479392976,65257,244,10.16692126028,-1.92257408019,-16.02178429586,2,1,18 +2025-03-11T12:42:57.683258,479392976,65257,244,9.87006547322,-2.209594170135,-15.48877156007,2,1,18 +2025-03-11T12:42:57.698883,479392976,65257,244,9.57792168278,-2.496606107115,-14.965007971415,2,1,18 +2025-03-11T12:42:57.714508,479392976,65257,244,9.27164190248,-2.78364250299,-14.40887575829,2,1,18 +2025-03-11T12:42:57.730133,479392976,65257,244,8.98421010866,-3.09375164613,-13.84805678612,2,1,18 +2025-03-11T12:42:57.745758,479392976,65257,244,8.6873543216,-3.390013879725,-13.32424933646,2,1,18 +2025-03-11T12:42:57.761383,479392976,65257,244,8.39049853454,-3.68627611332,-12.79119952067,2,1,18 +2025-03-11T12:42:57.777008,479392976,65257,244,8.10306674072,-3.98714311281,-12.235038811565,2,1,18 +2025-03-11T12:42:57.792633,479392976,65257,244,7.8156349469,-4.283389040475,-11.683517825525,2,1,18 +2025-03-11T12:42:57.808258,479392976,65257,244,7.51406716322,-4.58428049886,-11.15044268873,2,1,18 +2025-03-11T12:42:57.823883,479392976,65257,244,7.19836338968,-4.880575344315,-10.62660811505,2,1,18 +2025-03-11T12:42:57.839508,479392976,65257,244,6.896795606,-5.1814668027,-10.075048245995,2,1,18 +2025-03-11T12:42:57.855133,479392976,65257,244,6.5905158257,-5.496229629525,-9.528047159,2,1,18 +2025-03-11T12:42:57.870758,479392976,65257,244,6.28894804202,-5.792500016085,-8.967263463815,2,1,18 +2025-03-11T12:42:57.886383,479392976,65257,244,5.98738025834,-6.079528258995,-8.40651684863,2,1,18 +2025-03-11T12:42:57.902008,479392976,65257,244,5.68581247466,-6.375798645555,-7.8780814349,2,1,18 +2025-03-11T12:42:57.917633,479392976,65257,244,5.39366868422,-6.67667379801,-7.335777493985,2,1,18 +2025-03-11T12:42:57.933258,479392976,65257,244,5.1062368904,-6.98678294115,-6.78882207101,2,1,18 +2025-03-11T12:42:57.948883,479392976,65257,244,4.80466910672,-7.306158686835,-6.246430408085,2,1,18 +2025-03-11T12:42:57.964508,479392976,65257,244,4.50310132304,-7.60705014522,-5.681006989835,2,1,18 +2025-03-11T12:42:57.980133,479392976,65257,244,4.22038152584,-7.90328791992,-5.134113967865,2,1,18 +2025-03-11T12:42:57.995697,479392980,65253,245,3.93294973202,-8.190291703935,-4.57800887876,2,1,18 +2025-03-11T12:42:58.011322,479392980,65253,245,3.6219579551,-8.5004416119,-4.044883099955,2,1,18 +2025-03-11T12:42:58.026947,479392980,65253,245,3.3156781748,-8.805962295075,-3.511782642155,2,1,18 +2025-03-11T12:42:58.042572,479392980,65253,245,3.01882238774,-9.097603456845,-2.960266634105,2,1,18 +2025-03-11T12:42:58.058197,479392980,65253,245,2.70783061082,-9.403132292985,-2.413295846105,2,1,18 +2025-03-11T12:42:58.073822,479392980,65253,245,2.41568682038,-9.70400744544,-1.86174953906,2,1,18 +2025-03-11T12:42:58.089447,479392980,65253,245,2.1141190367,-10.004898903825,-1.30556848694,2,1,18 +2025-03-11T12:42:58.105072,479392980,65253,245,1.82197524626,-10.30577405628,-0.75864336296,2,1,18 +2025-03-11T12:42:58.120697,479392980,65253,245,1.52040746258,-10.59280229919,-0.20251793084,2,1,18 +2025-03-11T12:42:58.136322,479392980,65253,245,1.2188396789,-10.88907268575,0.35364458128,2,1,18 +2025-03-11T12:42:58.151947,479392980,65253,245,0.92198389184,-11.18995599117,0.8959553032,2,1,18 +2025-03-11T12:42:58.167572,479392980,65253,245,0.62512810478,-11.48159715294,1.442850128185,2,1,18 +2025-03-11T12:42:58.183197,479392980,65253,245,0.32827231772,-11.787101530185,1.985179390105,2,1,18 +2025-03-11T12:42:58.198822,479392980,65253,245,0.0314165306599999,-12.097226979255,2.509042459765,2,1,18 +2025-03-11T12:42:58.214447,479392980,65253,245,-0.2654392564,-12.388868141025,3.04669491862,2,1,18 +2025-03-11T12:42:58.230072,479392980,65253,245,-0.57643103332,-12.68977590534,3.570541251295,2,1,18 +2025-03-11T12:42:58.245697,479392980,65253,245,-0.877998817,-12.990667363725,4.11285875422,2,1,18 +2025-03-11T12:42:58.261322,479392980,65253,245,-1.1607186142,-13.286905138425,4.66899414232,2,1,18 +2025-03-11T12:42:58.276947,479392980,65253,245,-1.4669983945,-13.5924258216,5.22057933238,2,1,18 +2025-03-11T12:42:58.292572,479392980,65253,245,-1.76856617818,-13.89793835181,5.772157741435,2,1,18 +2025-03-11T12:42:58.308197,479392980,65253,245,-2.06070996862,-14.180329216965,6.30514515622,2,1,18 +2025-03-11T12:42:58.323822,479392980,65253,245,-2.3622777523,-14.48122067535,6.82435674382,2,1,18 +2025-03-11T12:42:58.339447,479392980,65253,245,-2.66384553598,-14.782112133735,7.38978016207,2,1,18 +2025-03-11T12:42:58.355072,479392980,65253,245,-2.96070132304,-15.06913222368,7.95051999625,2,1,18 +2025-03-11T12:42:58.370697,479392980,65253,245,-3.26226910672,-15.37464475389,8.47899248998,2,1,18 +2025-03-11T12:42:58.386322,479392980,65253,245,-3.55441289716,-15.675519906345,9.002811698635,2,1,18 +2025-03-11T12:42:58.401947,479392980,65253,245,-3.84184469098,-15.98100797766,9.52202148322,2,1,18 +2025-03-11T12:42:58.417572,479392980,65253,245,-4.1292764848,-16.28187497715,10.078182192325,2,1,18 +2025-03-11T12:42:58.433197,479392980,65253,245,-4.42142027524,-16.56888691413,10.61118814711,2,1,18 +2025-03-11T12:42:58.448822,479392980,65253,245,-4.71356406568,-16.86514099476,11.13960999883,2,1,18 +2025-03-11T12:42:58.464447,479392980,65253,245,-5.01041985274,-17.161403228355,11.68190218075,2,1,18 +2025-03-11T12:42:58.480072,479392980,65253,245,-5.3072756398,-17.443802246475,12.228759925735,2,1,18 +2025-03-11T12:42:58.495697,479392980,65253,245,-5.59941943024,-17.730814183455,12.75252351439,2,1,18 +2025-03-11T12:42:58.511322,479392980,65253,245,-5.8962752173,-18.04556070435,13.299511039375,2,1,18 +2025-03-11T12:42:58.526947,479392980,65253,245,-6.19784300098,-18.337210019085,13.837170279235,2,1,18 +2025-03-11T12:42:58.542572,479392980,65253,245,-6.4852747948,-18.6242138031,14.370169453015,2,1,18 +2025-03-11T12:42:58.558197,479392980,65253,245,-6.78213058186,-18.920476036695,14.90784045187,2,1,18 +2025-03-11T12:42:58.573822,479392980,65253,245,-7.06956237568,-19.212100892535,15.436236982585,2,1,18 +2025-03-11T12:42:58.589447,479392980,65253,245,-7.3569941695,-19.503725748375,15.94614878104,2,1,18 +2025-03-11T12:42:58.605072,479392980,65253,245,-7.65384995656,-19.79074583832,16.437570869245,2,1,18 +2025-03-11T12:42:58.620697,479392980,65253,245,-7.93656975376,-20.082362541195,16.947475886695,2,1,18 +2025-03-11T12:42:58.636322,479392980,65253,245,-8.22400154758,-20.373987397035,17.46663005128,2,1,18 +2025-03-11T12:42:58.651947,479392980,65253,245,-8.5114333414,-20.6702333247,18.00890867119,2,1,18 +2025-03-11T12:42:58.667572,479392980,65253,245,-8.7941531386,-20.952607883925,18.532640157835,2,1,18 +2025-03-11T12:42:58.683197,479392980,65253,245,-9.08158493242,-21.234990596115,19.065620791615,2,1,18 +2025-03-11T12:42:58.698822,479392980,65253,245,-9.36901672624,-21.517373308305,19.60322260846,2,1,18 +2025-03-11T12:42:58.714447,479392980,65253,245,-9.65644852006,-21.81361923597,20.140880045305,2,1,18 +2025-03-11T12:42:58.730072,479392980,65253,245,-9.93445632064,-22.100606714055,20.67848684014,2,1,18 +2025-03-11T12:42:58.745697,479392980,65253,245,-10.22188811446,-22.38761049807,21.197622464725,2,1,18 +2025-03-11T12:42:58.761322,479392980,65253,245,-10.5140319049,-22.6838645787,21.69369603499,2,1,18 +2025-03-11T12:42:58.776947,479392980,65253,245,-10.80146369872,-22.952384075415,22.19889395038,2,1,18 +2025-03-11T12:42:58.792572,479392980,65253,245,-11.0794714993,-23.2393715535,22.72263719602,2,1,18 +2025-03-11T12:42:58.808197,479392980,65253,245,-11.35276730326,-23.51710873497,23.22323066533,2,1,18 +2025-03-11T12:42:58.823822,479392980,65253,245,-11.64019909708,-23.804112518985,23.733123923785,2,1,18 +2025-03-11T12:42:58.839447,479392980,65253,245,-11.94176688076,-24.091140761895,24.261522257515,2,1,18 +2025-03-11T12:42:58.855072,479392980,65253,245,-12.22448667796,-24.36427317747,24.771353114965,2,1,18 +2025-03-11T12:42:58.870697,479392980,65253,245,-12.4930704853,-24.6466232778,25.285821892465,2,1,18 +2025-03-11T12:42:58.886322,479392980,65253,245,-12.78050227912,-24.933627061815,25.800336333985,2,1,18 +2025-03-11T12:42:58.901947,479392980,65253,245,-13.06322207632,-25.229864836515,26.301017525305,2,1,18 +2025-03-11T12:42:58.917572,479392980,65253,245,-13.3412298769,-25.493746955475,26.79231978949,2,1,18 +2025-03-11T12:42:58.933197,479392980,65253,245,-13.60981368424,-25.76223384033,27.30673294699,2,1,18 +2025-03-11T12:42:58.948822,479392980,65253,245,-13.87839749158,-26.04458394066,27.807338175295,2,1,18 +2025-03-11T12:42:58.964447,479392980,65253,245,-14.15169329554,-26.33156326578,28.30334754154,2,1,18 +2025-03-11T12:42:58.980072,479392980,65253,245,-14.43912508936,-26.600082762495,28.822409006125,2,1,18 +2025-03-11T12:42:58.995697,479392980,65253,245,-14.7077088967,-26.86856964735,29.327579797495,2,1,18 +2025-03-11T12:42:59.011322,479392980,65253,245,-14.97158070742,-27.150911594715,29.828178244795,2,1,18 +2025-03-11T12:42:59.026947,479392980,65253,245,-15.24487651138,-27.43326984801,30.338032620235,2,1,18 +2025-03-11T12:42:59.042572,479392980,65253,245,-15.51346031872,-27.701756732865,30.833961045475,2,1,18 +2025-03-11T12:42:59.058197,479392980,65253,245,-15.78204412606,-27.96100147407,31.32523120765,2,1,18 +2025-03-11T12:42:59.073822,479392980,65253,245,-16.06476392326,-28.23875496147,31.821217055905,2,1,18 +2025-03-11T12:42:59.089447,479392980,65253,245,-16.32392373736,-28.53033089952,32.317224619135,2,1,18 +2025-03-11T12:42:59.105072,479392980,65253,245,-16.58308355146,-28.789559334795,32.803860036235,2,1,18 +2025-03-11T12:42:59.120697,479392980,65253,245,-16.85637935542,-29.048812228965,33.285894613285,2,1,18 +2025-03-11T12:42:59.136322,479392980,65253,245,-17.12967515938,-29.29420190766,33.76325238727,2,1,18 +2025-03-11T12:42:59.151947,479392980,65253,245,-17.39825896672,-29.56730986434,34.25919935251,2,1,18 +2025-03-11T12:42:59.167572,479392980,65253,245,-17.66213077744,-29.84503073988,34.75053689368,2,1,18 +2025-03-11T12:42:59.183197,479392980,65253,245,-17.92129059154,-30.11812239063,35.22798556465,2,1,18 +2025-03-11T12:42:59.198822,479392980,65253,245,-18.18516240226,-30.372737907045,35.70074567356,2,1,18 +2025-03-11T12:42:59.214447,479392980,65253,245,-18.44432221636,-30.645829557795,36.173573161465,2,1,18 +2025-03-11T12:42:59.230072,479392980,65253,245,-18.69877003384,-30.905049840105,36.646338248365,2,1,18 +2025-03-11T12:42:59.245697,479392980,65253,245,-18.95321785132,-31.164270122415,37.109860969135,2,1,18 +2025-03-11T12:42:59.261322,479392980,65253,245,-19.22651365528,-31.414280872935,37.582616100055,2,1,18 +2025-03-11T12:42:59.276947,479392980,65253,245,-19.490385466,-31.66889638935,38.05999739203,2,1,18 +2025-03-11T12:42:59.292572,479392980,65253,245,-19.74483328348,-31.923495599835,38.528122755865,2,1,18 +2025-03-11T12:42:59.308197,479392980,65253,245,-19.99456910434,-32.187328801005,38.99165723563,2,1,18 +2025-03-11T12:42:59.323822,479392980,65253,245,-20.25372891844,-32.45579937993,39.4690873666,2,1,18 +2025-03-11T12:42:59.339447,479392980,65253,245,-20.52231272578,-32.715044121135,39.92800924732,2,1,18 +2025-03-11T12:42:59.355072,479392980,65253,245,-20.76733655002,-32.965005953865,40.386860143015,2,1,18 +2025-03-11T12:42:59.370697,479392980,65253,245,-21.01707237088,-33.21497593956,40.85033900278,2,1,18 +2025-03-11T12:42:59.386322,479392980,65253,245,-21.27152018836,-33.45571193457,41.31378756355,2,1,18 +2025-03-11T12:42:59.401947,479392980,65253,245,-21.52125600922,-33.696439776615,41.77260816025,2,1,18 +2025-03-11T12:42:59.417572,479392980,65253,245,-21.75685584022,-33.946385303415,42.21758194474,2,1,18 +2025-03-11T12:42:59.433197,479392980,65253,245,-21.99245567122,-34.20095190204,42.667195452295,2,1,18 +2025-03-11T12:42:59.448822,479392980,65253,245,-22.25161548532,-34.45555926549,43.13070641407,2,1,18 +2025-03-11T12:42:59.464447,479392980,65253,245,-22.49192731294,-34.70089187343,43.58028962263,2,1,18 +2025-03-11T12:42:59.480072,479392980,65253,245,-22.73695113718,-34.946232634335,44.02525842913,2,1,18 +2025-03-11T12:42:59.495697,479392980,65253,245,-22.9772629648,-35.200807385925,44.451772802365,2,1,18 +2025-03-11T12:42:59.511322,479392980,65253,245,-23.22228678904,-35.43690600318,44.887462162735,2,1,18 +2025-03-11T12:42:59.526947,479392980,65253,245,-23.46259861666,-35.659133251995,45.336952671295,2,1,18 +2025-03-11T12:42:59.542572,479392980,65253,245,-23.70291044428,-35.90908693176,45.758827321465,2,1,18 +2025-03-11T12:42:59.558197,479392980,65253,245,-23.9432222719,-36.1544195397,46.180683431635,2,1,18 +2025-03-11T12:42:59.573822,479392980,65253,245,-24.18824609614,-36.390518156955,46.616372792005,2,1,18 +2025-03-11T12:42:59.589447,479392980,65253,245,-24.41913393052,-36.61272909984,47.065849738555,2,1,18 +2025-03-11T12:42:59.605072,479392980,65253,245,-24.63117377842,-36.83952850269,47.49221218576,2,1,18 +2025-03-11T12:42:59.620697,479392980,65253,245,-24.8620616128,-37.0848448047,47.918675916985,2,1,18 +2025-03-11T12:42:59.636322,479392980,65253,245,-25.10237344042,-37.33017741264,48.359016759415,2,1,18 +2025-03-11T12:42:59.651947,479392980,65253,245,-25.3332612748,-37.552388355525,48.780766607575,2,1,18 +2025-03-11T12:42:59.667572,479392980,65253,245,-25.5688611058,-37.783849595025,49.19331795061,2,1,18 +2025-03-11T12:42:59.683197,479392980,65253,245,-25.8044609368,-38.015310834525,49.596626927515,2,1,18 +2025-03-11T12:42:59.698822,479392980,65253,245,-26.03534877118,-38.260627136535,50.01384829261,2,1,18 +2025-03-11T12:42:59.714447,479392980,65253,245,-26.24738861908,-38.496668683035,50.431005453685,2,1,18 +2025-03-11T12:42:59.730072,479392980,65253,245,-26.4641404636,-38.691128736075,50.829517803505,2,1,18 +2025-03-11T12:42:59.745697,479392980,65253,245,-26.6997402946,-38.9087267601,51.24201352654,2,1,18 +2025-03-11T12:42:59.761322,479392980,65253,245,-26.92120413574,-39.149405684355,51.640718057365,2,1,18 +2025-03-11T12:42:59.776947,479392980,65253,245,-27.14266797688,-39.36235817766,52.053174897385,2,1,18 +2025-03-11T12:42:59.792572,479392980,65253,245,-27.34999582816,-39.589149427545,52.44718228213,2,1,18 +2025-03-11T12:42:59.808197,479392980,65253,245,-27.56674767268,-39.80671483971,52.83654496582,2,1,18 +2025-03-11T12:42:59.823822,479392980,65253,245,-27.78821151382,-40.01504626119,53.235119716645,2,1,18 +2025-03-11T12:42:59.839447,479392980,65253,245,-27.9955393651,-40.2279742956,53.61058674913,2,1,18 +2025-03-11T12:42:59.855072,479392980,65253,245,-28.20286721638,-40.454765545485,53.995351767745,2,1,18 +2025-03-11T12:42:59.870697,479392980,65253,245,-28.41019506766,-40.667693579895,54.393924715555,2,1,18 +2025-03-11T12:42:59.886322,479392980,65253,245,-28.6316589088,-40.87140392955,54.778617377185,2,1,18 +2025-03-11T12:42:59.901947,479392980,65253,245,-28.86254674318,-41.08899380061,55.163379220825,2,1,18 +2025-03-11T12:42:59.917572,479392980,65253,245,-29.07458659108,-41.292687844335,55.548058320445,2,1,18 +2025-03-11T12:42:59.933197,479392980,65253,245,-29.27249044912,-41.496357429165,55.90498997866,2,1,18 +2025-03-11T12:42:59.948822,479392980,65253,245,-29.48453029702,-41.695430401065,56.28040817215,2,1,18 +2025-03-11T12:42:59.964447,479392980,65253,245,-29.68243415506,-41.899099985895,56.66044574569,2,1,18 +2025-03-11T12:42:59.980072,479392980,65253,245,-29.8803380131,-42.12587492985,57.04057601923,2,1,18 +2025-03-11T12:42:59.995697,479392980,65253,245,-30.08295386776,-42.329552667645,57.40675682458,2,1,18 +2025-03-11T12:43:00.011322,479392980,65253,245,-30.28556972242,-42.519367189965,57.759018460735,2,1,18 +2025-03-11T12:43:00.026947,479392980,65253,245,-30.47404958722,-42.70915725339,58.120502120005,2,1,18 +2025-03-11T12:43:00.042572,479392980,65253,245,-30.67195344526,-42.91282683822,58.482054961285,2,1,18 +2025-03-11T12:43:00.058197,479392980,65253,245,-30.86043331006,-43.093374757995,58.82963799136,2,1,18 +2025-03-11T12:43:00.073822,479392980,65253,245,-31.06304916472,-43.28781035214,59.181918167515,2,1,18 +2025-03-11T12:43:00.089447,479392980,65253,245,-31.2468170329,-43.4775922626,59.53415267965,2,1,18 +2025-03-11T12:43:00.105072,479392980,65253,245,-31.4352968977,-43.658140182375,59.872493343595,2,1,18 +2025-03-11T12:43:00.120697,479392980,65253,245,-31.62848875912,-43.866422686065,60.220194394675,2,1,18 +2025-03-11T12:43:00.136322,479392980,65253,245,-31.8358166104,-44.065487505,60.55863634264,2,1,18 +2025-03-11T12:43:00.151947,479392980,65253,245,-32.01958447858,-44.22754298451,60.89689606558,2,1,18 +2025-03-11T12:43:00.167572,479392980,65253,245,-32.18450436028,-44.41729228311,61.25372463676,2,1,18 +2025-03-11T12:43:00.183197,479392980,65253,245,-32.3776962217,-44.593227284025,61.58281117558,2,1,18 +2025-03-11T12:43:00.198822,479392980,65253,245,-32.57088808312,-44.773783356765,61.907295071335,2,1,18 +2025-03-11T12:43:00.214447,479392980,65253,245,-32.73580796482,-44.954290511715,62.227117097995,2,1,18 +2025-03-11T12:43:00.230072,479392980,65253,245,-32.90543984314,-45.139426891455,62.54696444566,2,1,18 +2025-03-11T12:43:00.245697,479392980,65253,245,-33.08920771132,-45.32458773009,62.880695685535,2,1,18 +2025-03-11T12:43:00.261322,479392980,65253,245,-33.26355158626,-45.49586904732,63.200494194205,2,1,18 +2025-03-11T12:43:00.276947,479392980,65253,245,-33.43318346458,-45.67176328341,63.506440912675,2,1,18 +2025-03-11T12:43:00.292572,479392980,65253,245,-33.60752733952,-45.838423528815,63.826220881345,2,1,18 +2025-03-11T12:43:00.308197,479392980,65253,245,-33.78658321108,-46.014334070835,64.141423527955,2,1,18 +2025-03-11T12:43:00.323822,479392980,65253,245,-33.96092708602,-46.17175217259,64.45654523356,2,1,18 +2025-03-11T12:43:00.339447,479392980,65253,245,-34.13527096096,-46.347654561645,64.73939281771,2,1,18 +2025-03-11T12:43:00.355072,479392980,65253,245,-34.29547884604,-46.50042713268,65.022127358845,2,1,18 +2025-03-11T12:43:00.370697,479392980,65253,245,-34.4509747345,-46.657812622575,65.3279795743,2,1,18 +2025-03-11T12:43:00.386322,479392980,65253,245,-34.60647062296,-46.82444025612,65.65697478508,2,1,18 +2025-03-11T12:43:00.401947,479392980,65253,245,-34.76667850804,-46.98183389898,65.93510668315,2,1,18 +2025-03-11T12:43:00.417572,479392980,65253,245,-34.94102238298,-47.130009857085,66.20860066117,2,1,18 +2025-03-11T12:43:00.433197,479392980,65253,245,-35.0870942782,-47.28737904105,66.495954582355,2,1,18 +2025-03-11T12:43:00.448822,479392980,65253,245,-35.23316617342,-47.444748225015,66.77406613741,2,1,18 +2025-03-11T12:43:00.464447,479392980,65253,245,-35.38395006526,-47.602125561945,67.047563290405,2,1,18 +2025-03-11T12:43:00.480072,479392980,65253,245,-35.5347339571,-47.777987186175,67.325755786465,2,1,18 +2025-03-11T12:43:00.495697,479392980,65253,245,-35.69022984556,-47.92613053242,67.599222640465,2,1,18 +2025-03-11T12:43:00.511322,479392980,65253,245,-35.85514972726,-48.06042696912,67.86802625341,2,1,18 +2025-03-11T12:43:00.526947,479392980,65253,245,-36.01064561572,-48.208570315365,68.12300837515,2,1,18 +2025-03-11T12:43:00.542572,479392980,65253,245,-36.1472935177,-48.352059977925,68.382566015935,2,1,18 +2025-03-11T12:43:00.558197,479392980,65253,245,-36.27922942306,-48.49554148752,68.651359241845,2,1,18 +2025-03-11T12:43:00.573822,479392980,65253,245,-36.41116532842,-48.64364406894,68.91554982469,2,1,18 +2025-03-11T12:43:00.589447,479392980,65253,245,-36.55723722364,-48.77790789378,69.17970513055,2,1,18 +2025-03-11T12:43:00.605072,479392980,65253,245,-36.70330911886,-48.92141386227,69.430033967215,2,1,18 +2025-03-11T12:43:00.620697,479392980,65253,245,-36.8305330276,-49.0464029316,69.675640336795,2,1,18 +2025-03-11T12:43:00.636322,479392980,65253,245,-36.95775693634,-49.194497360055,69.92596058944,2,1,18 +2025-03-11T12:43:00.651947,479392980,65253,245,-37.09911683494,-49.33799517558,70.162419095905,2,1,18 +2025-03-11T12:43:00.667572,479392980,65253,245,-37.24990072678,-49.472267153385,70.412717633575,2,1,18 +2025-03-11T12:43:00.683197,479392980,65253,245,-37.36298864566,-49.601852835645,70.64907983401,2,1,18 +2025-03-11T12:43:00.698822,479392980,65253,245,-37.4902125544,-49.726841904975,70.862337922135,2,1,18 +2025-03-11T12:43:00.714447,479392980,65253,245,-37.6080124699,-49.842572524725,71.098651283575,2,1,18 +2025-03-11T12:43:00.730072,479392980,65253,245,-37.72110038878,-49.962916063335,71.33497640401,2,1,18 +2025-03-11T12:43:00.745697,479392980,65253,245,-37.84832429752,-50.09252620449,71.56211658133,2,1,18 +2025-03-11T12:43:00.761322,479392980,65253,245,-37.97083620964,-50.189780689905,71.770635465385,2,1,18 +2025-03-11T12:43:00.776947,479392980,65253,245,-38.09806011838,-50.30090654376,72.00232266577,2,1,18 +2025-03-11T12:43:00.792572,479392980,65253,245,-38.22528402712,-50.41665346944,72.215543673895,2,1,18 +2025-03-11T12:43:00.808197,479392980,65253,245,-38.34779593924,-50.550876529455,72.428832061015,2,1,18 +2025-03-11T12:43:00.823822,479392980,65253,245,-38.46559585474,-50.67122822103,72.628194497935,2,1,18 +2025-03-11T12:43:00.839447,479392980,65253,245,-38.56454778376,-50.773063013445,72.818213284705,2,1,18 +2025-03-11T12:43:00.855072,479392980,65253,245,-38.65407571954,-50.888744715405,72.999031763335,2,1,18 +2025-03-11T12:43:00.870697,479392980,65253,245,-38.7624516418,-50.9998379574,73.179858825985,2,1,18 +2025-03-11T12:43:00.886322,479392980,65253,245,-38.87082756406,-51.101689055745,73.38375472396,2,1,18 +2025-03-11T12:43:00.901947,479392980,65253,245,-38.97920348632,-51.22202444139,73.596967148065,2,1,18 +2025-03-11T12:43:00.917572,479392980,65253,245,-39.07815541534,-51.314617090155,73.78232767177,2,1,18 +2025-03-11T12:43:00.933197,479392980,65253,245,-39.18181934098,-51.41183896371,73.972334699545,2,1,18 +2025-03-11T12:43:00.948822,479392980,65253,245,-39.28548326662,-51.499818693615,74.14381991506,2,1,18 +2025-03-11T12:43:00.964447,479392980,65253,245,-39.38443519564,-51.59241134238,74.310695706505,2,1,18 +2025-03-11T12:43:00.980072,479392980,65253,245,-39.48809912128,-51.689633215935,74.496081551215,2,1,18 +2025-03-11T12:43:00.995697,479392980,65253,245,-39.58233905368,-51.782217711735,74.66757174472,2,1,18 +2025-03-11T12:43:01.011322,479392980,65253,245,-39.67186698946,-51.879415126395,74.82983133109,2,1,18 +2025-03-11T12:43:01.026947,479392980,65253,245,-39.74725893538,-51.96734593851,74.98741231138,2,1,18 +2025-03-11T12:43:01.042572,479392980,65253,245,-39.82736287792,-52.07376919089,75.154316598805,2,1,18 +2025-03-11T12:43:01.058197,479392980,65253,245,-39.91217881708,-52.16633738076,75.30730849804,2,1,18 +2025-03-11T12:43:01.073822,479392980,65253,245,-39.99228275962,-52.240413130365,75.464840639335,2,1,18 +2025-03-11T12:43:01.089447,479392980,65253,245,-40.07238670216,-52.319109951795,75.60390658837,2,1,18 +2025-03-11T12:43:01.105072,479392980,65253,245,-40.1524906447,-52.3931857014,75.752196363535,2,1,18 +2025-03-11T12:43:01.120697,479392980,65253,245,-40.24201858048,-52.448793469635,75.90966790684,2,1,18 +2025-03-11T12:43:01.136322,479392980,65253,245,-40.32683451964,-52.522877372205,76.04872209688,2,1,18 +2025-03-11T12:43:01.151947,479392980,65253,245,-40.39751446894,-52.60617895953,76.15544474245,2,1,18 +2025-03-11T12:43:01.167572,479392980,65253,245,-40.46819441824,-52.68485947503,76.276012397215,2,1,18 +2025-03-11T12:43:01.183197,479392980,65253,245,-40.53416237092,-52.763531837565,76.405815637105,2,1,18 +2025-03-11T12:43:01.198822,479392980,65253,245,-40.59541832698,-52.83757497531,76.53559355599,2,1,18 +2025-03-11T12:43:01.214447,479392980,65253,245,-40.66609827628,-52.88852905986,76.65142878769,2,1,18 +2025-03-11T12:43:01.230072,479392980,65253,245,-40.72735423234,-52.94870898213,76.771908720445,2,1,18 +2025-03-11T12:43:01.245697,479392980,65253,245,-40.78389819178,-52.999638607785,76.878481243,2,1,18 +2025-03-11T12:43:01.261322,479392980,65253,245,-40.84044215122,-53.055189305265,76.97120875636,2,1,18 +2025-03-11T12:43:01.276947,479392980,65253,245,-40.90169810728,-53.115369227535,77.07782513992,2,1,18 +2025-03-11T12:43:01.292572,479392980,65253,245,-40.96295406334,-53.17092807798,77.15669588509,2,1,18 +2025-03-11T12:43:01.308197,479392980,65253,245,-41.0242100194,-53.2218658566,77.267896371715,2,1,18 +2025-03-11T12:43:01.323822,479392980,65253,245,-41.0948899687,-53.2820620848,77.36990513422,2,1,18 +2025-03-11T12:43:01.339447,479392980,65253,245,-41.1420099349,-53.332975404525,77.457979362505,2,1,18 +2025-03-11T12:43:01.355072,479392980,65253,245,-41.18441790448,-53.383880571285,77.55066799285,2,1,18 +2025-03-11T12:43:01.370697,479392980,65253,245,-41.22211387744,-53.43477758508,77.64334984219,2,1,18 +2025-03-11T12:43:01.386322,479392980,65253,245,-41.24567386054,-53.46716585268,77.717452456255,2,1,18 +2025-03-11T12:43:01.401947,479392980,65253,245,-41.29279382674,-53.51345810058,77.791644595345,2,1,18 +2025-03-11T12:43:01.417572,479392980,65253,245,-41.34462578956,-53.559758501445,77.851979966245,2,1,18 +2025-03-11T12:43:01.433197,479392980,65253,245,-41.401169749,-53.596824911625,77.93076977041,2,1,18 +2025-03-11T12:43:01.448822,479392980,65253,245,-41.44357771858,-53.638487934735,78.00955777156,2,1,18 +2025-03-11T12:43:01.464447,479392980,65253,245,-41.46713770168,-53.680118345985,78.06983391643,2,1,18 +2025-03-11T12:43:01.480072,479392980,65253,245,-41.4954096814,-53.698651551075,78.12540295924,2,1,18 +2025-03-11T12:43:01.495697,479392980,65253,245,-41.52368166112,-53.726426899815,78.18100908205,2,1,18 +2025-03-11T12:43:01.511322,479392980,65253,245,-41.55195364084,-53.763444392205,78.24589465099,2,1,18 +2025-03-11T12:43:01.526947,479392980,65253,245,-41.57551362394,-53.795832659805,78.2876489836,2,1,18 +2025-03-11T12:43:01.542572,479392980,65253,245,-41.59907360704,-53.809736640105,78.33857152234,2,1,18 +2025-03-11T12:43:01.558197,479392980,65253,245,-41.62263359014,-53.83750383588,78.38030731495,2,1,18 +2025-03-11T12:43:01.573822,479392980,65253,245,-41.64619357324,-53.856028888005,78.426627210625,2,1,18 +2025-03-11T12:43:01.589447,479392980,65253,245,-41.66975355634,-53.86531179648,78.449804110975,2,1,18 +2025-03-11T12:43:01.605072,479392980,65253,245,-41.68860154282,-53.888449767465,78.47302985032,2,1,18 +2025-03-11T12:43:01.620697,479392980,65253,245,-41.70273753268,-53.911579585485,78.49624880866,2,1,18 +2025-03-11T12:43:01.636322,479392980,65253,245,-41.71687352254,-53.91160404438,78.533238616195,2,1,18 +2025-03-11T12:43:01.651947,479392980,65253,245,-41.72629751578,-53.92086249396,78.56563753966,2,1,18 +2025-03-11T12:43:01.667572,479392980,65253,245,-41.73572150902,-53.93012094354,78.588794096995,2,1,18 +2025-03-11T12:43:01.683197,479392980,65253,245,-41.74514550226,-53.93013724947,78.588807659005,2,1,18 +2025-03-11T12:43:01.698822,479392980,65253,245,-41.74985749888,-53.93476647426,78.58883298001,2,1,18 +2025-03-11T12:43:01.714447,479392980,65253,245,-41.74514550226,-53.953242608595,78.59352154207,2,1,18 +2025-03-11T12:43:01.730072,479392980,65253,245,-41.7545694955,-53.96712213,78.607454273275,2,1,18 +2025-03-11T12:43:01.745697,479392980,65253,245,-41.75928149212,-53.96250921114,78.58895778202,2,1,18 +2025-03-11T12:43:01.761322,479392980,65253,245,-41.75928149212,-53.948645995665,78.57041742976,2,1,18 +2025-03-11T12:43:01.776947,479392980,65253,245,-41.75928149212,-53.93478278019,78.556498260565,2,1,18 +2025-03-11T12:43:01.792572,479392980,65253,245,-41.7545694955,-53.925532483575,78.54721203343,2,1,18 +2025-03-11T12:43:01.808197,479392980,65253,245,-41.74043350564,-53.930129096505,78.528725498155,2,1,18 +2025-03-11T12:43:01.823822,479392980,65253,245,-41.7310095124,-53.920870646925,78.52405367308,2,1,18 +2025-03-11T12:43:01.839447,479392980,65253,245,-41.71687352254,-53.90236190073,78.50085325474,2,1,18 +2025-03-11T12:43:01.855072,479392980,65253,245,-41.71216152592,-53.874627316815,78.473008135345,2,1,18 +2025-03-11T12:43:01.870697,479392980,65253,245,-41.70273753268,-53.856126723585,78.43132976575,2,1,18 +2025-03-11T12:43:01.886322,479392980,65253,245,-41.6838895462,-53.828367680775,78.41270666947,2,1,18 +2025-03-11T12:43:01.901947,479392980,65253,245,-41.65090556986,-53.823689538195,78.384913564045,2,1,18 +2025-03-11T12:43:01.917572,479392980,65253,245,-41.62263359014,-53.81901954858,78.347884873495,2,1,18 +2025-03-11T12:43:01.933197,479392980,65253,245,-41.60378560366,-53.786639433945,78.292273772695,2,1,18 +2025-03-11T12:43:01.948822,479392980,65253,245,-41.58493761718,-53.75425931931,78.255147404155,2,1,18 +2025-03-11T12:43:01.964447,479392980,65253,245,-41.54724164422,-53.72646766464,78.208770085465,2,1,18 +2025-03-11T12:43:01.980072,479392980,65253,245,-41.50954567126,-53.703297081795,78.14854775758,2,1,18 +2025-03-11T12:43:01.995620,479392984,65248,246,-41.47656169492,-53.67551358009,78.07907130457,2,1,18 +2025-03-11T12:43:02.011245,479392984,65248,246,-41.44357771858,-53.63386686291,78.00953923156,2,1,18 +2025-03-11T12:43:02.026870,479392984,65248,246,-41.41530573886,-53.57836508322,77.94457950262,2,1,18 +2025-03-11T12:43:02.042495,479392984,65248,246,-41.38232176252,-53.541339437865,77.87506596961,2,1,18 +2025-03-11T12:43:02.058120,479392984,65248,246,-41.34462578956,-53.51816885502,77.814843641725,2,1,18 +2025-03-11T12:43:02.073745,479392984,65248,246,-41.3069298166,-53.4811350567,77.731459778515,2,1,18 +2025-03-11T12:43:02.089370,479392984,65248,246,-41.2598098504,-53.44408495245,77.657304719425,2,1,18 +2025-03-11T12:43:02.104995,479392984,65248,246,-41.20326589096,-53.393155326795,77.564595746065,2,1,18 +2025-03-11T12:43:02.120620,479392984,65248,246,-41.16085792138,-53.351492303685,77.467323012655,2,1,18 +2025-03-11T12:43:02.136245,479392984,65248,246,-41.1184499518,-53.300587136925,77.388497931505,2,1,18 +2025-03-11T12:43:02.151870,479392984,65248,246,-41.0713299856,-53.245052745375,77.286541614025,2,1,18 +2025-03-11T12:43:02.167495,479392984,65248,246,-41.00536203292,-53.18486467014,77.184539632525,2,1,18 +2025-03-11T12:43:02.183120,479392984,65248,246,-40.93939408024,-53.143160882205,77.07799062796,2,1,18 +2025-03-11T12:43:02.198745,479392984,65248,246,-40.8828501208,-53.07374696925,76.980586311535,2,1,18 +2025-03-11T12:43:02.214370,479392984,65248,246,-40.82630616136,-53.022817343595,76.87401378898,2,1,18 +2025-03-11T12:43:02.229995,479392984,65248,246,-40.77918619516,-52.958040808395,76.76277802537,2,1,18 +2025-03-11T12:43:02.245620,479392984,65248,246,-40.7179302391,-52.879376598825,76.642223932615,2,1,18 +2025-03-11T12:43:02.261245,479392984,65248,246,-40.64253829318,-52.81917221766,76.52634483991,2,1,18 +2025-03-11T12:43:02.276870,479392984,65248,246,-40.58128233712,-52.754371223565,76.40122518409,2,1,18 +2025-03-11T12:43:02.292495,479392984,65248,246,-40.52473837768,-52.68495731061,76.26223022008,2,1,18 +2025-03-11T12:43:02.308120,479392984,65248,246,-40.45405842838,-52.61551893876,76.132457279185,2,1,18 +2025-03-11T12:43:02.323745,479392984,65248,246,-40.37395448584,-52.54606426098,76.007291959345,2,1,18 +2025-03-11T12:43:02.339370,479392984,65248,246,-40.2938505433,-52.4581252959,75.882052479505,2,1,18 +2025-03-11T12:43:02.354995,479392984,65248,246,-40.21845859738,-52.379436627435,75.733750945345,2,1,18 +2025-03-11T12:43:02.370620,479392984,65248,246,-40.13364265822,-52.296110581215,75.59003849224,2,1,18 +2025-03-11T12:43:02.386245,479392984,65248,246,-40.05353871568,-52.217413759785,75.43710899401,2,1,18 +2025-03-11T12:43:02.401870,479392984,65248,246,-39.98285876638,-52.12487002881,75.279516254725,2,1,18 +2025-03-11T12:43:02.417495,479392984,65248,246,-39.90746682046,-52.04156028852,75.131196180565,2,1,18 +2025-03-11T12:43:02.433120,479392984,65248,246,-39.80380289482,-51.953580558615,74.98743806344,2,1,18 +2025-03-11T12:43:02.448745,479392984,65248,246,-39.71898695566,-51.861012368745,74.82058261501,2,1,18 +2025-03-11T12:43:02.464370,479392984,65248,246,-39.6341710165,-51.78230739435,74.658403969645,2,1,18 +2025-03-11T12:43:02.479995,479392984,65248,246,-39.5399310841,-51.68972289855,74.482292593075,2,1,18 +2025-03-11T12:43:02.495620,479392984,65248,246,-39.45511514494,-51.59715470868,74.29233122932,2,1,18 +2025-03-11T12:43:02.511245,479392984,65248,246,-39.36087521254,-51.49532806923,74.12542513888,2,1,18 +2025-03-11T12:43:02.526870,479392984,65248,246,-39.26192328352,-51.39811434864,73.958530807435,2,1,18 +2025-03-11T12:43:02.542495,479392984,65248,246,-39.14883536464,-51.28701295368,73.80542406217,2,1,18 +2025-03-11T12:43:02.558120,479392984,65248,246,-39.045171439,-51.189791080125,73.606174668265,2,1,18 +2025-03-11T12:43:02.573745,479392984,65248,246,-38.94621950998,-51.08795628771,73.41153469843,2,1,18 +2025-03-11T12:43:02.589370,479392984,65248,246,-38.85197957758,-50.98612964826,73.22614387573,2,1,18 +2025-03-11T12:43:02.604995,479392984,65248,246,-38.7388916587,-50.870407181475,73.04067030901,2,1,18 +2025-03-11T12:43:02.620620,479392984,65248,246,-38.63051573644,-50.75931393948,72.845979697165,2,1,18 +2025-03-11T12:43:02.636245,479392984,65248,246,-38.53627580404,-50.652866228205,72.632843236075,2,1,18 +2025-03-11T12:43:02.651870,479392984,65248,246,-38.42789988178,-50.546394058035,72.4289287981,2,1,18 +2025-03-11T12:43:02.667495,479392984,65248,246,-38.30538796966,-50.43065528532,72.220335754045,2,1,18 +2025-03-11T12:43:02.683120,479392984,65248,246,-38.18758805416,-50.31492466557,72.002507124865,2,1,18 +2025-03-11T12:43:02.698745,479392984,65248,246,-38.08392412852,-50.20383957654,71.77547501257,2,1,18 +2025-03-11T12:43:02.714370,479392984,65248,246,-37.9614122164,-50.083479732,71.566863428515,2,1,18 +2025-03-11T12:43:02.729995,479392984,65248,246,-37.8436123009,-49.953885896775,71.3536003624,2,1,18 +2025-03-11T12:43:02.745620,479392984,65248,246,-37.72110038878,-49.815041764935,71.126429886085,2,1,18 +2025-03-11T12:43:02.761245,479392984,65248,246,-37.59387648004,-49.69467376743,70.899326788765,2,1,18 +2025-03-11T12:43:02.776870,479392984,65248,246,-37.45722857806,-49.56966839217,70.672191589435,2,1,18 +2025-03-11T12:43:02.792495,479392984,65248,246,-37.32058067608,-49.43542087326,70.44039812704,2,1,18 +2025-03-11T12:43:02.808120,479392984,65248,246,-37.19806876396,-49.31506102872,70.194817078465,2,1,18 +2025-03-11T12:43:02.823745,479392984,65248,246,-37.0661328586,-49.180821662775,69.96765158014,2,1,18 +2025-03-11T12:43:02.839370,479392984,65248,246,-36.95304493972,-49.060478124165,69.71746291051,2,1,18 +2025-03-11T12:43:02.854995,479392984,65248,246,-36.82582103098,-48.917004767535,69.4625400148,2,1,18 +2025-03-11T12:43:02.870620,479392984,65248,246,-36.68446113238,-48.768885880185,69.22144178527,2,1,18 +2025-03-11T12:43:02.886245,479392984,65248,246,-36.53838923716,-48.63000098352,68.96651030554,2,1,18 +2025-03-11T12:43:02.901870,479392984,65248,246,-36.38760534532,-48.504971149365,68.70700648174,2,1,18 +2025-03-11T12:43:02.917495,479392984,65248,246,-36.26038143658,-48.36611886456,68.45210212603,2,1,18 +2025-03-11T12:43:02.933120,479392984,65248,246,-36.11902153798,-48.20875783356,68.187860901175,2,1,18 +2025-03-11T12:43:02.948745,479392984,65248,246,-35.97294964276,-48.05600972142,67.92825261838,2,1,18 +2025-03-11T12:43:02.964370,479392984,65248,246,-35.82687774754,-47.91250375293,67.66406023252,2,1,18 +2025-03-11T12:43:02.979995,479392984,65248,246,-35.66195786584,-47.755101957105,67.39054273651,2,1,18 +2025-03-11T12:43:02.995620,479392984,65248,246,-35.49703798414,-47.60694230493,67.12630468663,2,1,18 +2025-03-11T12:43:03.011245,479392984,65248,246,-35.35567808554,-47.454202345755,66.85746081871,2,1,18 +2025-03-11T12:43:03.026870,479392984,65248,246,-35.2048941937,-47.306067152475,66.56089483039,2,1,18 +2025-03-11T12:43:03.042495,479392984,65248,246,-35.04939830524,-47.153302734405,66.27816707026,2,1,18 +2025-03-11T12:43:03.058120,479392984,65248,246,-34.90332641002,-46.98669140679,65.98615488601,2,1,18 +2025-03-11T12:43:03.073745,479392984,65248,246,-34.73840652832,-46.82466853914,65.680270568545,2,1,18 +2025-03-11T12:43:03.089370,479392984,65248,246,-34.56877465,-46.662637518525,65.383621836205,2,1,18 +2025-03-11T12:43:03.104995,479392984,65248,246,-34.4038547683,-46.500614650875,65.082358701805,2,1,18 +2025-03-11T12:43:03.120620,479392984,65248,246,-34.22479889674,-46.32932518068,64.776416961325,2,1,18 +2025-03-11T12:43:03.136245,479392984,65248,246,-34.06459101166,-46.17193153782,64.48442151406,2,1,18 +2025-03-11T12:43:03.151870,479392984,65248,246,-33.91851911644,-45.986835922905,64.196956352875,2,1,18 +2025-03-11T12:43:03.167495,479392984,65248,246,-33.7441752415,-45.815554605675,63.858673111945,2,1,18 +2025-03-11T12:43:03.183120,479392984,65248,246,-33.56040737332,-45.644256982515,63.538861041265,2,1,18 +2025-03-11T12:43:03.198745,479392984,65248,246,-33.38135150176,-45.47296751232,63.21905575159,2,1,18 +2025-03-11T12:43:03.214370,479392984,65248,246,-33.22114361668,-45.301710653985,62.899277585935,2,1,18 +2025-03-11T12:43:03.229995,479392984,65248,246,-33.04679974174,-45.12580826493,62.58408172033,2,1,18 +2025-03-11T12:43:03.245620,479392984,65248,246,-32.86303187356,-44.959131713595,62.24580345739,2,1,18 +2025-03-11T12:43:03.261245,479392984,65248,246,-32.69811199186,-44.778624558645,61.930602613795,2,1,18 +2025-03-11T12:43:03.276870,479392984,65248,246,-32.50963212706,-44.58883449522,61.615330785175,2,1,18 +2025-03-11T12:43:03.292495,479392984,65248,246,-32.34471224536,-44.422190555745,61.277079646255,2,1,18 +2025-03-11T12:43:03.308120,479392984,65248,246,-32.16094437718,-44.24627186076,60.95262785251,2,1,18 +2025-03-11T12:43:03.323745,479392984,65248,246,-31.97246451238,-44.05186072551,60.61885275163,2,1,18 +2025-03-11T12:43:03.339370,479392984,65248,246,-31.77456065434,-43.85743328433,60.271200539545,2,1,18 +2025-03-11T12:43:03.354995,479392984,65248,246,-31.59079278616,-43.672272445695,59.923605750475,2,1,18 +2025-03-11T12:43:03.370620,479392984,65248,246,-31.39288892812,-43.468602860865,59.580537641455,2,1,18 +2025-03-11T12:43:03.386245,479392984,65248,246,-31.20440906332,-43.27881279744,59.237538714445,2,1,18 +2025-03-11T12:43:03.401870,479392984,65248,246,-31.01592919852,-43.09364380584,58.88069477824,2,1,18 +2025-03-11T12:43:03.417495,479392984,65248,246,-30.83216133034,-42.880756536255,58.53298874917,2,1,18 +2025-03-11T12:43:03.433120,479392984,65248,246,-30.63896946892,-42.68633724804,58.1576162197,2,1,18 +2025-03-11T12:43:03.448745,479392984,65248,246,-30.43635361426,-42.49652272572,57.786869851285,2,1,18 +2025-03-11T12:43:03.464370,479392984,65248,246,-30.21960176974,-42.29282052903,57.425289885985,2,1,18 +2025-03-11T12:43:03.479995,479392984,65248,246,-30.03112190494,-42.10765153743,57.06844594978,2,1,18 +2025-03-11T12:43:03.495620,479392984,65248,246,-29.83793004352,-41.903990105565,56.71152107257,2,1,18 +2025-03-11T12:43:03.511245,479392984,65248,246,-29.65416217534,-41.70958712328,56.340783288175,2,1,18 +2025-03-11T12:43:03.526870,479392984,65248,246,-29.44683432406,-41.49665908887,55.960695072625,2,1,18 +2025-03-11T12:43:03.542495,479392984,65248,246,-29.23008247954,-41.26523046123,55.59438268426,2,1,18 +2025-03-11T12:43:03.558120,479392984,65248,246,-29.02746662488,-41.052310579785,55.223543615845,2,1,18 +2025-03-11T12:43:03.573745,479392984,65248,246,-28.8201387736,-40.848624689025,54.852734846425,2,1,18 +2025-03-11T12:43:03.589370,479392984,65248,246,-28.6080989257,-40.6449306453,54.47267692987,2,1,18 +2025-03-11T12:43:03.604995,479392984,65248,246,-28.40548307104,-40.422768620205,54.074073683065,2,1,18 +2025-03-11T12:43:03.620620,479392984,65248,246,-28.17459523666,-40.195936605495,53.6661688441,2,1,18 +2025-03-11T12:43:03.636245,479392984,65248,246,-27.96255538876,-39.99224256177,53.27224737835,2,1,18 +2025-03-11T12:43:03.651870,479392984,65248,246,-27.76936352734,-39.779338986255,52.87831595662,2,1,18 +2025-03-11T12:43:03.667495,479392984,65248,246,-27.52905169972,-39.57559602474,52.488974987905,2,1,18 +2025-03-11T12:43:03.683120,479392984,65248,246,-27.29816386534,-39.35800615368,52.0995919612,2,1,18 +2025-03-11T12:43:03.698745,479392984,65248,246,-27.08141202082,-39.131198597865,51.69170746525,2,1,18 +2025-03-11T12:43:03.714370,479392984,65248,246,-26.88350816278,-38.918286869385,51.270042164125,2,1,18 +2025-03-11T12:43:03.729995,479392984,65248,246,-26.66204432164,-38.68685008878,50.8713747133,2,1,18 +2025-03-11T12:43:03.745620,479392984,65248,246,-26.4405804805,-38.446171164525,50.463427816345,2,1,18 +2025-03-11T12:43:03.761245,479392984,65248,246,-26.21440464274,-38.21934730278,50.064772124515,2,1,18 +2025-03-11T12:43:03.776870,479392984,65248,246,-25.9929408016,-37.98328945035,49.65684376756,2,1,18 +2025-03-11T12:43:03.792495,479392984,65248,246,-25.77147696046,-37.751852669745,49.22582803528,2,1,18 +2025-03-11T12:43:03.808120,479392984,65248,246,-25.53116513284,-37.52038327728,48.81326991124,2,1,18 +2025-03-11T12:43:03.823745,479392984,65248,246,-25.29085330522,-37.29353495664,48.4007303272,2,1,18 +2025-03-11T12:43:03.839370,479392984,65248,246,-25.06938946408,-37.071340319685,47.965130491855,2,1,18 +2025-03-11T12:43:03.854995,479392984,65248,246,-24.84321362632,-36.83527431429,47.5433318047,2,1,18 +2025-03-11T12:43:03.870620,479392984,65248,246,-24.61232579194,-36.59920015593,47.13076870267,2,1,18 +2025-03-11T12:43:03.886245,479392984,65248,246,-24.37201396432,-36.37235183529,46.704365569435,2,1,18 +2025-03-11T12:43:03.901870,479392984,65248,246,-24.12699014008,-36.145495361685,46.268713289065,2,1,18 +2025-03-11T12:43:03.917495,479392984,65248,246,-23.89139030908,-35.895549834885,45.82836068764,2,1,18 +2025-03-11T12:43:03.933120,479392984,65248,246,-23.65107848146,-35.65483829877,45.40652311747,2,1,18 +2025-03-11T12:43:03.948745,479392984,65248,246,-23.41547865046,-35.41413491562,44.975449962175,2,1,18 +2025-03-11T12:43:03.964370,479392984,65248,246,-23.18459081608,-35.164197541785,44.544346507885,2,1,18 +2025-03-11T12:43:03.979995,479392984,65248,246,-22.93956699184,-34.914235709055,44.09473797832,2,1,18 +2025-03-11T12:43:03.995620,479392984,65248,246,-22.69925516422,-34.659660957465,43.649738872825,2,1,18 +2025-03-11T12:43:04.011245,479392984,65248,246,-22.45423133998,-34.400456981085,43.20009326326,2,1,18 +2025-03-11T12:43:04.026870,479392984,65248,246,-22.1997835225,-34.159720986075,42.732023519425,2,1,18 +2025-03-11T12:43:04.042495,479392984,65248,246,-21.9406237084,-33.9189768381,42.291674092975,2,1,18 +2025-03-11T12:43:04.058120,479392984,65248,246,-21.70031188078,-33.678265301985,41.832867058285,2,1,18 +2025-03-11T12:43:04.073745,479392984,65248,246,-21.46000005316,-33.451416981345,41.364873277465,2,1,18 +2025-03-11T12:43:04.089370,479392984,65248,246,-21.21497622892,-33.201455148615,40.9152647479,2,1,18 +2025-03-11T12:43:04.104995,479392984,65248,246,-20.96052841144,-32.93761379448,40.45172348713,2,1,18 +2025-03-11T12:43:04.120620,479392984,65248,246,-20.71079259058,-32.68302273696,39.988226087365,2,1,18 +2025-03-11T12:43:04.136245,479392984,65248,246,-20.45163277648,-32.43765751716,39.520131022525,2,1,18 +2025-03-11T12:43:04.151870,479392984,65248,246,-20.18304896914,-32.187654919605,39.05662503874,2,1,18 +2025-03-11T12:43:04.167495,479392984,65248,246,-19.92388915504,-31.91918434068,38.611543189225,2,1,18 +2025-03-11T12:43:04.183120,479392984,65248,246,-19.6788653308,-31.6599803643,38.129549298205,2,1,18 +2025-03-11T12:43:04.198745,479392984,65248,246,-19.43384150656,-31.40077638792,37.656797773315,2,1,18 +2025-03-11T12:43:04.214370,479392984,65248,246,-19.1841056857,-31.13694318675,37.18402092742,2,1,18 +2025-03-11T12:43:04.229995,479392984,65248,246,-18.91080988174,-30.873069220755,36.715831359565,2,1,18 +2025-03-11T12:43:04.245620,479392984,65248,246,-18.65165006764,-30.61384078548,36.238438308595,2,1,18 +2025-03-11T12:43:04.261245,479392984,65248,246,-18.4066262434,-30.359257880925,35.76108414064,2,1,18 +2025-03-11T12:43:04.276870,479392984,65248,246,-18.1474664293,-30.10002944565,35.2929334558,2,1,18 +2025-03-11T12:43:04.292495,479392984,65248,246,-17.87417062534,-29.836155479655,34.806259155685,2,1,18 +2025-03-11T12:43:04.308120,479392984,65248,246,-17.61029881462,-29.57229781959,34.333461966775,2,1,18 +2025-03-11T12:43:04.323745,479392984,65248,246,-17.32757901742,-29.299165404015,33.84673702465,2,1,18 +2025-03-11T12:43:04.339370,479392984,65248,246,-17.05428321346,-29.04453358167,33.350857438405,2,1,18 +2025-03-11T12:43:04.354995,479392984,65248,246,-16.8045473926,-28.766837165025,32.87802497251,2,1,18 +2025-03-11T12:43:04.370620,479392984,65248,246,-16.5453875785,-28.493745514275,32.40981866767,2,1,18 +2025-03-11T12:43:04.386245,479392984,65248,246,-16.27680377116,-28.21601648577,31.91385316243,2,1,18 +2025-03-11T12:43:04.401870,479392984,65248,246,-16.01764395706,-27.938303763195,31.40865885307,2,1,18 +2025-03-11T12:43:04.417495,479392984,65248,246,-15.73492415986,-27.669792419445,30.90808890175,2,1,18 +2025-03-11T12:43:04.433120,479392984,65248,246,-15.46634035252,-27.405926606415,30.416800199575,2,1,18 +2025-03-11T12:43:04.448745,479392984,65248,246,-15.1789085587,-27.1374071097,29.911602284185,2,1,18 +2025-03-11T12:43:04.464370,479392984,65248,246,-14.91503674798,-26.85044409051,29.40636411382,2,1,18 +2025-03-11T12:43:04.479995,479392984,65248,246,-14.65116493726,-26.568102143145,28.901144483455,2,1,18 +2025-03-11T12:43:04.495620,479392984,65248,246,-14.36373314344,-26.29034050278,28.391288305,2,1,18 +2025-03-11T12:43:04.511245,479392984,65248,246,-14.08572534286,-26.00797409652,27.881427148555,2,1,18 +2025-03-11T12:43:04.526870,479392984,65248,246,-13.81714153552,-25.739487211665,27.376256357185,2,1,18 +2025-03-11T12:43:04.542495,479392984,65248,246,-13.5532697248,-25.4571452643,26.88952145908,2,1,18 +2025-03-11T12:43:04.558120,479392984,65248,246,-13.28468591746,-25.188658379445,26.38435066771,2,1,18 +2025-03-11T12:43:04.573745,479392984,65248,246,-12.99725412364,-24.915517810905,25.874513029255,2,1,18 +2025-03-11T12:43:04.589370,479392984,65248,246,-12.70982232982,-24.63775617054,25.378520399995,2,1,18 +2025-03-11T12:43:04.604995,479392984,65248,246,-12.42710253262,-24.36000268314,24.89177691787,2,1,18 +2025-03-11T12:43:04.620620,479392984,65248,246,-12.14909473204,-24.07763627688,24.36805221223,2,1,18 +2025-03-11T12:43:04.636245,479392984,65248,246,-11.86637493484,-23.813746004955,23.83053133639,2,1,18 +2025-03-11T12:43:04.651870,479392984,65248,246,-11.57894314102,-23.51750007729,23.302116265675,2,1,18 +2025-03-11T12:43:04.667495,479392984,65248,246,-11.30564733706,-23.216657536695,22.78756654717,2,1,18 +2025-03-11T12:43:04.683120,479392984,65248,246,-11.0323515331,-22.92505713975,22.291538640925,2,1,18 +2025-03-11T12:43:04.698745,479392984,65248,246,-10.74491973928,-22.647295499385,21.767818913275,2,1,18 +2025-03-11T12:43:04.714370,479392984,65248,246,-10.44806395222,-22.374138624915,21.234861797485,2,1,18 +2025-03-11T12:43:04.729995,479392984,65248,246,-10.15592016178,-22.10098990341,20.72963856109,2,1,18 +2025-03-11T12:43:04.745620,479392984,65248,246,-9.8779123612,-21.8093813535,20.20587677545,2,1,18 +2025-03-11T12:43:04.761245,479392984,65248,246,-9.60461655724,-21.508538812905,19.672842324685,2,1,18 +2025-03-11T12:43:04.776870,479392984,65248,246,-9.30776077018,-21.216897651135,19.158295781155,2,1,18 +2025-03-11T12:43:04.792495,479392984,65248,246,-9.01090498312,-20.934498633015,18.634543951495,2,1,18 +2025-03-11T12:43:04.808120,479392984,65248,246,-8.73289718254,-20.64751115493,18.110800705855,2,1,18 +2025-03-11T12:43:04.823745,479392984,65248,246,-8.45017738534,-20.34203123658,17.59621888534,2,1,18 +2025-03-11T12:43:04.839370,479392984,65248,246,-8.1580335949,-20.068882515075,17.072510916685,2,1,18 +2025-03-11T12:43:04.854995,479392984,65248,246,-7.87060180108,-19.78187873106,16.5533752921,2,1,18 +2025-03-11T12:43:04.870620,479392984,65248,246,-7.5690340174,-19.49485048815,15.992628676915,2,1,18 +2025-03-11T12:43:04.886245,479392984,65248,246,-7.29102621682,-19.207863010065,15.44577951595,2,1,18 +2025-03-11T12:43:04.901870,479392984,65248,246,-6.99888242638,-18.911608929435,14.91735766423,2,1,18 +2025-03-11T12:43:04.917495,479392984,65248,246,-6.70673863594,-18.61997592063,14.37971198638,2,1,18 +2025-03-11T12:43:04.933120,479392984,65248,246,-6.4145948455,-18.309858624525,13.855855697725,2,1,18 +2025-03-11T12:43:04.948745,479392984,65248,246,-6.12245105506,-18.00898347207,13.33203648907,2,1,18 +2025-03-11T12:43:04.964370,479392984,65248,246,-5.825595268,-17.72658445395,12.812905842475,2,1,18 +2025-03-11T12:43:04.979995,479392984,65248,246,-5.52873948094,-17.43494329218,12.279874566685,2,1,18 +2025-03-11T12:43:04.995620,479392984,65248,246,-5.24601968374,-17.143326589305,11.73762126778,2,1,18 +2025-03-11T12:43:05.011245,479392984,65248,246,-4.9538758933,-16.837830365025,11.204541152995,2,1,18 +2025-03-11T12:43:05.026870,479392984,65248,246,-4.66173210286,-16.53695521257,10.657616029015,2,1,18 +2025-03-11T12:43:05.042495,479392984,65248,246,-4.37430030904,-16.23608821308,10.115318869105,2,1,18 +2025-03-11T12:43:05.058120,479392984,65248,246,-4.08686851522,-15.95370550089,9.582338235325,2,1,18 +2025-03-11T12:43:05.073745,479392984,65248,246,-3.78530073154,-15.671298329805,9.04933725853,2,1,18 +2025-03-11T12:43:05.089370,479392984,65248,246,-3.4931569411,-15.375044249175,8.50243067455,2,1,18 +2025-03-11T12:43:05.104995,479392984,65248,246,-3.17745316756,-15.07874940372,7.955490185545,2,1,18 +2025-03-11T12:43:05.120620,479392984,65248,246,-2.87588538388,-14.768615801685,7.42237796875,2,1,18 +2025-03-11T12:43:05.136245,479392984,65248,246,-2.59316558668,-14.45851481151,6.87542932678,2,1,18 +2025-03-11T12:43:05.151870,479392984,65248,246,-2.29630979962,-14.171494721565,6.3146894926,2,1,18 +2025-03-11T12:43:05.167495,479392984,65248,246,-1.99003001932,-13.861352966565,5.786191677865,2,1,18 +2025-03-11T12:43:05.183120,479392984,65248,246,-1.69317423226,-13.569711804795,5.243918035945,2,1,18 +2025-03-11T12:43:05.198745,479392984,65248,246,-1.40103044182,-13.273457724165,4.71087500116,2,1,18 +2025-03-11T12:43:05.214370,479392984,65248,246,-1.10888665138,-12.977203643535,4.15472605105,2,1,18 +2025-03-11T12:43:05.229995,479392984,65248,246,-0.80260687108,-12.676304032185,3.61240176712,2,1,18 +2025-03-11T12:43:05.245620,479392984,65248,246,-0.50575108402,-12.37079965494,3.06083013907,2,1,18 +2025-03-11T12:43:05.261245,479392984,65248,246,-0.20889529696,-12.08840063682,2.50935121102,2,1,18 +2025-03-11T12:43:05.276870,479392984,65248,246,0.0926724867199999,-11.778267034785,1.976238994225,2,1,18 +2025-03-11T12:43:05.292495,479392984,65248,246,0.3942402704,-11.4773755764,1.44316385743,2,1,18 +2025-03-11T12:43:05.308120,479392984,65248,246,0.69580805408,-11.176484118015,0.891603988375,2,1,18 +2025-03-11T12:43:05.323745,479392984,65248,246,0.99266384114,-10.884842956245,0.316982065,2,1,18 +2025-03-11T12:43:05.339370,479392984,65248,246,1.28009563496,-10.58859702858,-0.21605418878,2,1,18 +2025-03-11T12:43:05.354995,479392984,65248,246,1.58166341864,-10.28308449837,-0.75376904864,2,1,18 +2025-03-11T12:43:05.370620,479392984,65248,246,1.8785192057,-9.9729590493,-1.300738033625,2,1,18 +2025-03-11T12:43:05.386245,479392984,65248,246,2.184798986,-9.676680509775,-1.85690732675,2,1,18 +2025-03-11T12:43:05.401870,479392984,65248,246,2.48636676968,-9.371167979565,-2.399243369675,2,1,18 +2025-03-11T12:43:05.417495,479392984,65248,246,2.7737985635,-9.08416419555,-2.932242543455,2,1,18 +2025-03-11T12:43:05.433120,479392984,65248,246,3.06123035732,-8.76481290876,-3.49771977869,2,1,18 +2025-03-11T12:43:05.448745,479392984,65248,246,3.362798141,-8.4685425222,-4.049261107745,2,1,18 +2025-03-11T12:43:05.464370,479392984,65248,246,3.66436592468,-8.167651063815,-4.586957427605,2,1,18 +2025-03-11T12:43:05.479995,479392984,65248,246,3.98006969822,-7.866735146535,-5.12467409048,2,1,18 +2025-03-11T12:43:05.495620,479392984,65248,246,4.27221348866,-7.56585999408,-5.666978031395,2,1,18 +2025-03-11T12:43:05.511245,479392984,65248,246,4.5643572791,-7.264984841625,-6.195418423115,2,1,18 +2025-03-11T12:43:05.526870,479392984,65248,246,4.8706370594,-6.954843086625,-6.76088570237,2,1,18 +2025-03-11T12:43:05.542495,479392984,65248,246,5.17220484308,-6.667814843715,-7.30776876836,2,1,18 +2025-03-11T12:43:05.558120,479392984,65248,246,5.46906063014,-6.357689394645,-7.854737753345,2,1,18 +2025-03-11T12:43:05.573745,479392984,65248,246,5.76120442058,-6.05681424219,-8.383178145065,2,1,18 +2025-03-11T12:43:05.589370,479392984,65248,246,6.05806020764,-5.75593093677,-8.934731233115,2,1,18 +2025-03-11T12:43:05.604995,479392984,65248,246,6.36905198456,-5.45964424428,-9.500149673375,2,1,18 +2025-03-11T12:43:05.620620,479392984,65248,246,6.661195775,-5.168011235475,-10.056280083485,2,1,18 +2025-03-11T12:43:05.636245,479392984,65248,246,6.9439155722,-4.86715238895,-10.593949279325,2,1,18 +2025-03-11T12:43:05.651870,479392984,65248,246,7.24548335588,-4.56163985874,-11.13628532225,2,1,18 +2025-03-11T12:43:05.667495,479392984,65248,246,7.54705113956,-4.279232687655,-11.68314984824,2,1,18 +2025-03-11T12:43:05.683120,479392984,65248,246,7.84861892324,-3.982962301095,-12.23931236036,2,1,18 +2025-03-11T12:43:05.698745,479392984,65248,246,8.15018670692,-3.668207627235,-12.790927849415,2,1,18 +2025-03-11T12:43:05.714370,479392984,65248,246,8.4517544906,-3.371937240675,-13.337847995405,2,1,18 +2025-03-11T12:43:05.729995,479392984,65248,246,8.74389828104,-3.075683160045,-13.875512213255,2,1,18 +2025-03-11T12:43:05.745620,479392984,65248,246,9.05489005796,-2.78401753938,-14.422427381255,2,1,18 +2025-03-11T12:43:05.761245,479392984,65248,246,9.35174584502,-2.48313423396,-14.94163218785,2,1,18 +2025-03-11T12:43:05.776870,479392984,65248,246,9.64388963546,-2.182259081505,-15.4793149457,2,1,18 +2025-03-11T12:43:05.792495,479392984,65248,246,9.95016941576,-1.881359470155,-16.02163922963,2,1,18 +2025-03-11T12:43:05.808120,479392984,65248,246,10.25173719944,-1.566604796295,-16.57787590175,2,1,18 +2025-03-11T12:43:05.823745,479392984,65248,246,10.55330498312,-1.28419762521,-17.12474042774,2,1,18 +2025-03-11T12:43:05.839370,479392984,65248,246,10.8313127837,-0.9925890753,-17.67622931177,2,1,18 +2025-03-11T12:43:05.854995,479392984,65248,246,11.1140325809,-0.691730228775,-18.209277324545,2,1,18 +2025-03-11T12:43:05.870620,479392984,65248,246,11.41560036458,-0.39083877039,-18.74235246134,2,1,18 +2025-03-11T12:43:05.886245,479392984,65248,246,11.71245615164,-0.103818680444999,-19.279986380195,2,1,18 +2025-03-11T12:43:05.901870,479392984,65248,246,11.99517594884,0.197040166080001,-19.81303439297,2,1,18 +2025-03-11T12:43:05.917495,479392984,65248,246,12.28260774266,0.488665021919999,-20.341430923685,2,1,18 +2025-03-11T12:43:05.933120,479392984,65248,246,12.58417552634,0.77569326483,-20.88369280661,2,1,18 +2025-03-11T12:43:05.948745,479392984,65248,246,12.88574331002,1.08120579504,-21.435271215665,2,1,18 +2025-03-11T12:43:05.964370,479392984,65248,246,13.17788710046,1.37745987567,-21.96831425045,2,1,18 +2025-03-11T12:43:05.979995,479392984,65248,246,13.4700308909,1.66447181265,-22.5059413883,2,1,18 +2025-03-11T12:43:05.995559,479392988,65244,247,13.75746268472,1.951475596665,-23.034319379015,2,1,18 +2025-03-11T12:43:06.011184,479392988,65244,247,14.06374246502,2.243133064365,-23.56274303375,2,1,18 +2025-03-11T12:43:06.026809,479392988,65244,247,14.3653102487,2.54402452275,-24.10043935361,2,1,18 +2025-03-11T12:43:06.042434,479392988,65244,247,14.66216603576,2.83566568452,-24.6334706294,2,1,18 +2025-03-11T12:43:06.058059,479392988,65244,247,14.9543098262,3.13191976515,-25.166513664185,2,1,18 +2025-03-11T12:43:06.073684,479392988,65244,247,15.23231762678,3.43277045871,-25.690312529825,2,1,18 +2025-03-11T12:43:06.089309,479392988,65244,247,15.52917341384,3.71516947683,-26.214064359485,2,1,18 +2025-03-11T12:43:06.104934,479392988,65244,247,15.81660520766,4.002173260845,-26.747063533265,2,1,18 +2025-03-11T12:43:06.120559,479392988,65244,247,16.1087489981,4.284564126,-27.275429764985,2,1,18 +2025-03-11T12:43:06.136184,479392988,65244,247,16.3914687953,4.585422972525,-27.80847777776,2,1,18 +2025-03-11T12:43:06.151809,479392988,65244,247,16.68361258574,4.881677053155,-28.33689962948,2,1,18 +2025-03-11T12:43:06.167434,479392988,65244,247,16.97575637618,5.17331006196,-28.85606057507,2,1,18 +2025-03-11T12:43:06.183059,479392988,65244,247,17.24434018352,5.460281234115,-29.356684343375,2,1,18 +2025-03-11T12:43:06.198684,479392988,65244,247,17.53177197734,5.733421802655,-29.87576434796,2,1,18 +2025-03-11T12:43:06.214309,479392988,65244,247,17.82391576778,6.02505481146,-30.408788842745,2,1,18 +2025-03-11T12:43:06.229934,479392988,65244,247,18.11605955822,6.316687820265,-30.918707422205,2,1,18 +2025-03-11T12:43:06.245559,479392988,65244,247,18.38935536218,6.58980392991,-31.428524717645,2,1,18 +2025-03-11T12:43:06.261184,479392988,65244,247,18.66265116614,6.89526754233,-31.947714159215,2,1,18 +2025-03-11T12:43:06.276809,479392988,65244,247,18.95008295996,7.16840811087,-32.44830943154,2,1,18 +2025-03-11T12:43:06.292434,479392988,65244,247,19.23280275716,7.450782670095,-32.972040918185,2,1,18 +2025-03-11T12:43:06.308059,479392988,65244,247,19.51081055774,7.72852800453,-33.504989449955,2,1,18 +2025-03-11T12:43:06.323684,479392988,65244,247,19.80295434818,7.99705565421,-34.01019414635,2,1,18 +2025-03-11T12:43:06.339309,479392988,65244,247,20.09509813862,8.27482544754,-34.515435922745,2,1,18 +2025-03-11T12:43:06.354934,479392988,65244,247,20.37781793582,8.557200006765,-35.02068267713,2,1,18 +2025-03-11T12:43:06.370559,479392988,65244,247,20.65111373978,8.834937188235,-35.525897329505,2,1,18 +2025-03-11T12:43:06.386184,479392988,65244,247,20.91969754712,9.117287288565,-36.03574492394,2,1,18 +2025-03-11T12:43:06.401809,479392988,65244,247,21.19299335108,9.40888768551,-36.54563637938,2,1,18 +2025-03-11T12:43:06.417434,479392988,65244,247,21.46157715842,9.68199564219,-37.06006807688,2,1,18 +2025-03-11T12:43:06.433059,479392988,65244,247,21.75372094886,9.955144363695,-37.57915486247,2,1,18 +2025-03-11T12:43:06.448684,479392988,65244,247,22.03644074606,10.223655707445,-38.07972481379,2,1,18 +2025-03-11T12:43:06.464309,479392988,65244,247,22.30031255678,10.49675551116,-38.58028618109,2,1,18 +2025-03-11T12:43:06.479934,479392988,65244,247,22.5877443506,10.7698960797,-39.07626027035,2,1,18 +2025-03-11T12:43:06.495559,479392988,65244,247,22.85632815794,11.047625108205,-39.567604592525,2,1,18 +2025-03-11T12:43:06.511184,479392988,65244,247,23.11077597542,11.32995074964,-40.068189477815,2,1,18 +2025-03-11T12:43:06.526809,479392988,65244,247,23.36993578952,11.60304240039,-40.545638148785,2,1,18 +2025-03-11T12:43:06.542434,479392988,65244,247,23.64323159348,11.857674222735,-41.04151773503,2,1,18 +2025-03-11T12:43:06.558059,479392988,65244,247,23.90239140758,12.130765873485,-41.52820877213,2,1,18 +2025-03-11T12:43:06.573684,479392988,65244,247,24.17097521492,12.413115973815,-42.019571634305,2,1,18 +2025-03-11T12:43:06.589309,479392988,65244,247,24.43013502902,12.69082869639,-42.524765943665,2,1,18 +2025-03-11T12:43:06.604934,479392988,65244,247,24.70343083298,12.945460518735,-43.006781980715,2,1,18 +2025-03-11T12:43:06.620559,479392988,65244,247,24.98143863356,13.19547942222,-43.484165075705,2,1,18 +2025-03-11T12:43:06.636184,479392988,65244,247,25.24059844766,13.463950001145,-43.970837572805,2,1,18 +2025-03-11T12:43:06.651809,479392988,65244,247,25.49975826176,13.74166272372,-44.439062417645,2,1,18 +2025-03-11T12:43:06.667434,479392988,65244,247,25.76363007248,13.996278240135,-44.911822526555,2,1,18 +2025-03-11T12:43:06.683059,479392988,65244,247,26.03221387982,14.260144053165,-45.37538413034,2,1,18 +2025-03-11T12:43:06.698684,479392988,65244,247,26.29137369392,14.523993560265,-45.848174538245,2,1,18 +2025-03-11T12:43:06.714309,479392988,65244,247,26.55524550464,14.792472292155,-46.330232633285,2,1,18 +2025-03-11T12:43:06.729934,479392988,65244,247,26.82382931198,15.047095961535,-46.8029995232,2,1,18 +2025-03-11T12:43:06.745559,479392988,65244,247,27.0641411396,15.2970496413,-47.28032837015,2,1,18 +2025-03-11T12:43:06.761184,479392988,65244,247,27.30916496384,15.54701147403,-47.748421631975,2,1,18 +2025-03-11T12:43:06.776809,479392988,65244,247,27.56832477794,15.80161883748,-48.22117495988,2,1,18 +2025-03-11T12:43:06.792434,479392988,65244,247,27.83219658866,16.07009756937,-48.68474832266,2,1,18 +2025-03-11T12:43:06.808059,479392988,65244,247,28.08664440614,16.333938923505,-49.162153132625,2,1,18 +2025-03-11T12:43:06.823684,479392988,65244,247,28.336380227,16.588529981025,-49.611786983195,2,1,18 +2025-03-11T12:43:06.839309,479392988,65244,247,28.58611604786,16.833878894895,-50.061383753765,2,1,18 +2025-03-11T12:43:06.854934,479392988,65244,247,28.84056386534,17.08847810538,-50.543372666795,2,1,18 +2025-03-11T12:43:06.870559,479392988,65244,247,29.07616369634,17.33842363218,-50.99296763435,2,1,18 +2025-03-11T12:43:06.886184,479392988,65244,247,29.32118752058,17.593006536735,-51.41948878859,2,1,18 +2025-03-11T12:43:06.901809,479392988,65244,247,29.5614993482,17.847581288325,-51.86910907715,2,1,18 +2025-03-11T12:43:06.917434,479392988,65244,247,29.80181117582,18.092913896265,-52.31869228571,2,1,18 +2025-03-11T12:43:06.933059,479392988,65244,247,30.05154699668,18.338262810135,-52.782152605475,2,1,18 +2025-03-11T12:43:06.948684,479392988,65244,247,30.28714682768,18.588208336935,-53.24098993916,2,1,18 +2025-03-11T12:43:06.964309,479392988,65244,247,30.53217065192,18.81506481054,-53.681263402595,2,1,18 +2025-03-11T12:43:06.979934,479392988,65244,247,30.78190647278,19.04192943711,-54.103058914775,2,1,18 +2025-03-11T12:43:06.995559,479392988,65244,247,31.02693029702,19.296512341665,-54.538822435145,2,1,18 +2025-03-11T12:43:07.011184,479392988,65244,247,31.27195412126,19.537232030745,-54.99763625084,2,1,18 +2025-03-11T12:43:07.026809,479392988,65244,247,31.51226594888,19.77794356686,-55.433337370205,2,1,18 +2025-03-11T12:43:07.042434,479392988,65244,247,31.76200176974,20.02329248073,-55.85982822545,2,1,18 +2025-03-11T12:43:07.058059,479392988,65244,247,31.99760160074,20.259374792055,-56.27701929155,2,1,18 +2025-03-11T12:43:07.073684,479392988,65244,247,32.23791342836,20.47235989722,-56.703366804785,2,1,18 +2025-03-11T12:43:07.089309,479392988,65244,247,32.4593772695,20.70841774965,-57.11129516174,2,1,18 +2025-03-11T12:43:07.104934,479392988,65244,247,32.68084111064,20.939854530255,-57.53306852789,2,1,18 +2025-03-11T12:43:07.120559,479392988,65244,247,32.91644094164,21.171315769755,-57.95948342012,2,1,18 +2025-03-11T12:43:07.136184,479392988,65244,247,33.1426167794,21.3981396315,-58.38586621034,2,1,18 +2025-03-11T12:43:07.151809,479392988,65244,247,33.36408062054,21.620334268455,-58.79836013036,2,1,18 +2025-03-11T12:43:07.167434,479392988,65244,247,33.5902564583,21.842537058375,-59.23396674671,2,1,18 +2025-03-11T12:43:07.183059,479392988,65244,247,33.83056828592,22.060143235365,-59.632605701555,2,1,18 +2025-03-11T12:43:07.198684,479392988,65244,247,34.05674412368,22.31469352806,-60.031372633385,2,1,18 +2025-03-11T12:43:07.214309,479392988,65244,247,34.28291996144,22.54613846163,-60.43466804828,2,1,18 +2025-03-11T12:43:07.229934,479392988,65244,247,34.51380779582,22.75448618904,-60.824013994985,2,1,18 +2025-03-11T12:43:07.245559,479392988,65244,247,34.7211356471,22.9766563671,-61.23648757199,2,1,18 +2025-03-11T12:43:07.261184,479392988,65244,247,34.92375150176,23.19419732037,-61.635072278795,2,1,18 +2025-03-11T12:43:07.276809,479392988,65244,247,35.1452153429,23.425634100975,-62.019876180425,2,1,18 +2025-03-11T12:43:07.292434,479392988,65244,247,35.36667918404,23.63858659428,-62.413848288185,2,1,18 +2025-03-11T12:43:07.308059,479392988,65244,247,35.57400703532,23.837651413215,-62.80774443293,2,1,18 +2025-03-11T12:43:07.323684,479392988,65244,247,35.78604688322,24.055208672415,-63.187857969485,2,1,18 +2025-03-11T12:43:07.339309,479392988,65244,247,35.99808673112,24.272765931615,-63.57721387217,2,1,18 +2025-03-11T12:43:07.354934,479392988,65244,247,36.21483857564,24.485710271955,-63.96655801586,2,1,18 +2025-03-11T12:43:07.370559,479392988,65244,247,36.4174544303,24.684766937925,-64.355826196535,2,1,18 +2025-03-11T12:43:07.386184,479392988,65244,247,36.62478228158,24.888452828685,-64.73125614902,2,1,18 +2025-03-11T12:43:07.401809,479392988,65244,247,36.84624612272,25.096784250165,-65.10672498452,2,1,18 +2025-03-11T12:43:07.417434,479392988,65244,247,37.03472598752,25.300437529065,-65.482127812985,2,1,18 +2025-03-11T12:43:07.433059,479392988,65244,247,37.22320585232,25.49946973614,-65.84826973532,2,1,18 +2025-03-11T12:43:07.448684,479392988,65244,247,37.43524570022,25.712405923515,-66.21450118268,2,1,18 +2025-03-11T12:43:07.464309,479392988,65244,247,37.6425735515,25.916091814275,-66.5853099521,2,1,18 +2025-03-11T12:43:07.479934,479392988,65244,247,37.86403739264,26.124423235755,-66.956157604535,2,1,18 +2025-03-11T12:43:07.495559,479392988,65244,247,38.07136524392,26.31424591104,-67.30380483863,2,1,18 +2025-03-11T12:43:07.511184,479392988,65244,247,38.26455710534,26.508665199255,-67.65145026971,2,1,18 +2025-03-11T12:43:07.526809,479392988,65244,247,38.45303697014,26.70769740633,-68.01297100898,2,1,18 +2025-03-11T12:43:07.542434,479392988,65244,247,38.62266884846,26.91131807337,-68.351377248905,2,1,18 +2025-03-11T12:43:07.558059,479392988,65244,247,38.81114871326,27.110350280445,-68.69903443898,2,1,18 +2025-03-11T12:43:07.573684,479392988,65244,247,39.01376456792,27.290922659115,-69.0558801782,2,1,18 +2025-03-11T12:43:07.589309,479392988,65244,247,39.20695642934,27.462236588205,-69.408054092345,2,1,18 +2025-03-11T12:43:07.604934,479392988,65244,247,39.3860123009,27.647389273875,-69.75564210041,2,1,18 +2025-03-11T12:43:07.620559,479392988,65244,247,39.58391615894,27.841816715055,-70.112536678625,2,1,18 +2025-03-11T12:43:07.636184,479392988,65244,247,39.77710802036,28.022372787795,-70.432399391315,2,1,18 +2025-03-11T12:43:07.651809,479392988,65244,247,39.97029988178,28.18906564506,-70.770691216265,2,1,18 +2025-03-11T12:43:07.667434,479392988,65244,247,40.14935575334,28.37421833073,-71.104415675135,2,1,18 +2025-03-11T12:43:07.683059,479392988,65244,247,40.3284116249,28.545507800925,-71.428842147875,2,1,18 +2025-03-11T12:43:07.698684,479392988,65244,247,40.49804350322,28.72602310884,-71.734807406345,2,1,18 +2025-03-11T12:43:07.714309,479392988,65244,247,40.65353939168,28.91575610151,-72.03154703567,2,1,18 +2025-03-11T12:43:07.729934,479392988,65244,247,40.7996112869,29.082367429125,-72.355907501375,2,1,18 +2025-03-11T12:43:07.745559,479392988,65244,247,40.97395516184,29.25826981818,-72.675724550045,2,1,18 +2025-03-11T12:43:07.761184,479392988,65244,247,41.1530110334,29.42493821655,-73.00475366585,2,1,18 +2025-03-11T12:43:07.776809,479392988,65244,247,41.33677890158,29.59623583971,-73.319944553465,2,1,18 +2025-03-11T12:43:07.792434,479392988,65244,247,41.5064107799,29.78137221945,-73.61206480274,2,1,18 +2025-03-11T12:43:07.808059,479392988,65244,247,41.68075465484,29.938790321205,-73.908701776085,2,1,18 +2025-03-11T12:43:07.823684,479392988,65244,247,41.8362505433,30.119281170225,-74.210025508475,2,1,18 +2025-03-11T12:43:07.839309,479392988,65244,247,41.9776104419,30.285884344875,-74.51127327785,2,1,18 +2025-03-11T12:43:07.854934,479392988,65244,247,42.1425303236,30.420180781575,-74.807803989185,2,1,18 +2025-03-11T12:43:07.870559,479392988,65244,247,42.31216220192,30.59145394584,-75.095247435395,2,1,18 +2025-03-11T12:43:07.886184,479392988,65244,247,42.47708208362,30.767340028965,-75.387323823665,2,1,18 +2025-03-11T12:43:07.901809,479392988,65244,247,42.63257797208,30.91548337521,-75.670033043795,2,1,18 +2025-03-11T12:43:07.917434,479392988,65244,247,42.78336186392,31.07286071214,-75.95277256292,2,1,18 +2025-03-11T12:43:07.933059,479392988,65244,247,42.93414575576,31.216374833595,-76.24932001124,2,1,18 +2025-03-11T12:43:07.948684,479392988,65244,247,43.09435364084,31.346042045505,-76.51809830318,2,1,18 +2025-03-11T12:43:07.964309,479392988,65244,247,43.2498495293,31.5034275354,-76.80084460331,2,1,18 +2025-03-11T12:43:07.979934,479392988,65244,247,43.39592142452,31.651554575715,-77.060434346105,2,1,18 +2025-03-11T12:43:07.995559,479392988,65244,247,43.54670531636,31.80431084082,-77.310807043775,2,1,18 +2025-03-11T12:43:08.011184,479392988,65244,247,43.68335321834,31.952421575205,-77.565762041495,2,1,18 +2025-03-11T12:43:08.026809,479392988,65244,247,43.8152891237,32.091282012975,-77.825294361275,2,1,18 +2025-03-11T12:43:08.042434,479392988,65244,247,43.94251303244,32.24861858508,-78.089515243115,2,1,18 +2025-03-11T12:43:08.058059,479392988,65244,247,44.0980089209,32.387519787675,-78.344460284855,2,1,18 +2025-03-11T12:43:08.073684,479392988,65244,247,44.2393688195,32.517154387725,-78.59934790358,2,1,18 +2025-03-11T12:43:08.089309,479392988,65244,247,44.38544071472,32.65603928439,-78.83579465105,2,1,18 +2025-03-11T12:43:08.104934,479392988,65244,247,44.5220886167,32.785665731475,-79.08143312264,2,1,18 +2025-03-11T12:43:08.120559,479392988,65244,247,44.65402452206,32.90142081012,-79.327009193225,2,1,18 +2025-03-11T12:43:08.136184,479392988,65244,247,44.7812484308,33.040273094925,-79.563428816675,2,1,18 +2025-03-11T12:43:08.151809,479392988,65244,247,44.90376034292,33.19298044224,-79.79065491299,2,1,18 +2025-03-11T12:43:08.167434,479392988,65244,247,45.03098425166,33.30872736792,-80.02698183644,2,1,18 +2025-03-11T12:43:08.183059,479392988,65244,247,45.15349616378,33.415223996985,-80.254022532755,2,1,18 +2025-03-11T12:43:08.198684,479392988,65244,247,45.2760080759,33.5309627697,-80.476479126005,2,1,18 +2025-03-11T12:43:08.214309,479392988,65244,247,45.40794398126,33.665202135645,-80.70364462433,2,1,18 +2025-03-11T12:43:08.229934,479392988,65244,247,45.52574389676,33.79479597087,-80.926150056575,2,1,18 +2025-03-11T12:43:08.245559,479392988,65244,247,45.64825580888,33.892050456285,-81.130047757565,2,1,18 +2025-03-11T12:43:08.261184,479392988,65244,247,45.770767721,34.007789229,-81.34788316775,2,1,18 +2025-03-11T12:43:08.276809,479392988,65244,247,45.88385563988,34.13737491126,-81.55189708673,2,1,18 +2025-03-11T12:43:08.292434,479392988,65244,247,45.9828075689,34.257693990975,-81.76047476576,2,1,18 +2025-03-11T12:43:08.308059,479392988,65244,247,46.09118349116,34.34106080202,-81.95967532067,2,1,18 +2025-03-11T12:43:08.323684,479392988,65244,247,46.1948474168,34.43366160375,-82.14504262538,2,1,18 +2025-03-11T12:43:08.339309,479392988,65244,247,46.29851134244,34.558609908255,-82.344403259285,2,1,18 +2025-03-11T12:43:08.354934,479392988,65244,247,46.41159926132,34.66509023139,-82.539082112135,2,1,18 +2025-03-11T12:43:08.370559,479392988,65244,247,46.52939917682,34.77157870749,-82.72452537986,2,1,18 +2025-03-11T12:43:08.386184,479392988,65244,247,46.63306310246,34.86417950922,-82.90989268457,2,1,18 +2025-03-11T12:43:08.401809,479392988,65244,247,46.72730303486,34.94752186137,-83.08596698114,2,1,18 +2025-03-11T12:43:08.417434,479392988,65244,247,46.8309669605,35.04936480675,-83.275992548915,2,1,18 +2025-03-11T12:43:08.433059,479392988,65244,247,46.92991888952,35.14657852734,-83.447508063425,2,1,18 +2025-03-11T12:43:08.448684,479392988,65244,247,47.01002283206,35.24375963607,-83.60513290472,2,1,18 +2025-03-11T12:43:08.464309,479392988,65244,247,47.10426276446,35.36407056282,-83.758249605965,2,1,18 +2025-03-11T12:43:08.479934,479392988,65244,247,47.18907870362,35.45663875269,-83.9112415052,2,1,18 +2025-03-11T12:43:08.495559,479392988,65244,247,47.2786066394,35.521488664575,-84.068750128505,2,1,18 +2025-03-11T12:43:08.511184,479392988,65244,247,47.35871058194,35.600185486005,-84.23554317593,2,1,18 +2025-03-11T12:43:08.526809,479392988,65244,247,47.4435265211,35.6788904604,-84.406964187425,2,1,18 +2025-03-11T12:43:08.542434,479392988,65244,247,47.51891846702,35.77144234434,-84.546078975455,2,1,18 +2025-03-11T12:43:08.558059,479392988,65244,247,47.59431041294,35.859373156455,-84.694417589615,2,1,18 +2025-03-11T12:43:08.573684,479392988,65244,247,47.66970235886,35.942682896745,-84.833495297645,2,1,18 +2025-03-11T12:43:08.589309,479392988,65244,247,47.75451829802,36.03063001479,-84.98646865688,2,1,18 +2025-03-11T12:43:08.604934,479392988,65244,247,47.83462224056,36.104705764395,-85.134758432045,2,1,18 +2025-03-11T12:43:08.620559,479392988,65244,247,47.91001418648,36.16491014556,-85.26912225701,2,1,18 +2025-03-11T12:43:08.636184,479392988,65244,247,47.9854061324,36.234356670375,-85.394280795845,2,1,18 +2025-03-11T12:43:08.651809,479392988,65244,247,48.0560860817,36.313037185875,-85.510227267545,2,1,18 +2025-03-11T12:43:08.667434,479392988,65244,247,48.13619002424,36.373249720005,-85.626113141255,2,1,18 +2025-03-11T12:43:08.683059,479392988,65244,247,48.21158197016,36.438075172995,-85.75125314009,2,1,18 +2025-03-11T12:43:08.698684,479392988,65244,247,48.2681259296,36.4982469423,-85.87172629184,2,1,18 +2025-03-11T12:43:08.714309,479392988,65244,247,48.31053389918,36.563015324535,-85.973712908315,2,1,18 +2025-03-11T12:43:08.729934,479392988,65244,247,48.36707785862,36.618566022015,-86.094167520065,2,1,18 +2025-03-11T12:43:08.745559,479392988,65244,247,48.4330458113,36.683375169075,-86.20080922463,2,1,18 +2025-03-11T12:43:08.761184,479392988,65244,247,48.49430176736,36.73893401952,-86.302785885125,2,1,18 +2025-03-11T12:43:08.776809,479392988,65244,247,48.55555772342,36.794492869965,-86.390898996425,2,1,18 +2025-03-11T12:43:08.792434,479392988,65244,247,48.597965693,36.8407769649,-86.48356908677,2,1,18 +2025-03-11T12:43:08.808059,479392988,65244,247,48.6450856592,36.882448140975,-86.57622741812,2,1,18 +2025-03-11T12:43:08.823684,479392988,65244,247,48.6922056254,36.937982532525,-86.64121427108,2,1,18 +2025-03-11T12:43:08.839309,479392988,65244,247,48.7393255916,36.975032636775,-86.738475245495,2,1,18 +2025-03-11T12:43:08.854934,479392988,65244,247,48.79115755442,37.01209089399,-86.826500634785,2,1,18 +2025-03-11T12:43:08.870559,479392988,65244,247,48.833565524,37.06299606075,-86.909946899,2,1,18 +2025-03-11T12:43:08.886184,479392988,65244,247,48.87126149696,37.095408787245,-86.970206306885,2,1,18 +2025-03-11T12:43:08.901809,479392988,65244,247,48.9042454733,37.137055504425,-87.048980746025,2,1,18 +2025-03-11T12:43:08.917434,479392988,65244,247,48.94194144626,37.16946823092,-87.11848252004,2,1,18 +2025-03-11T12:43:08.933059,479392988,65244,247,48.96550142936,37.21109864217,-87.164895115715,2,1,18 +2025-03-11T12:43:08.948684,479392988,65244,247,48.9984854057,37.2435032157,-87.215905376465,2,1,18 +2025-03-11T12:43:08.964309,479392988,65244,247,49.0220453888,37.280512555125,-87.26229943214,2,1,18 +2025-03-11T12:43:08.979934,479392988,65244,247,49.05031736852,37.317530047515,-87.313321451885,2,1,18 +2025-03-11T12:43:08.995559,479392988,65244,247,49.07858934824,37.33144218078,-87.378114320825,2,1,18 +2025-03-11T12:43:09.011184,479392988,65244,247,49.11157332458,37.349983538835,-87.447553693835,2,1,18 +2025-03-11T12:43:09.026809,479392988,65244,247,49.13513330768,37.36850859096,-87.480010040315,2,1,18 +2025-03-11T12:43:09.042434,479392988,65244,247,49.14926929754,37.39163840898,-87.50785018172,2,1,18 +2025-03-11T12:43:09.058059,479392988,65244,247,49.15398129416,37.419372992895,-87.51258938579,2,1,18 +2025-03-11T12:43:09.073684,479392988,65244,247,49.17754127726,37.44714018867,-87.540461629205,2,1,18 +2025-03-11T12:43:09.089309,479392988,65244,247,49.19638926374,37.461036016005,-87.56365028855,2,1,18 +2025-03-11T12:43:09.104934,479392988,65244,247,49.22937324008,37.465714158585,-87.572958661715,2,1,18 +2025-03-11T12:43:09.120559,479392988,65244,247,49.23879723332,37.46110939269,-87.60530196518,2,1,18 +2025-03-11T12:43:09.136184,479392988,65244,247,49.25293322318,37.46575492341,-87.61920439739,2,1,18 +2025-03-11T12:43:09.151809,479392988,65244,247,49.2576452198,37.484247363675,-87.637770070655,2,1,18 +2025-03-11T12:43:09.167434,479392988,65244,247,49.26235721642,37.49349766029,-87.66554103005,2,1,18 +2025-03-11T12:43:09.183059,479392988,65244,247,49.26706921304,37.47964259778,-87.66087100799,2,1,18 +2025-03-11T12:43:09.198684,479392988,65244,247,49.26706921304,37.47040045413,-87.665455111055,2,1,18 +2025-03-11T12:43:09.214309,479392988,65244,247,49.24822122656,37.47036784227,-87.65156443784,2,1,18 +2025-03-11T12:43:09.229934,479392988,65244,247,49.24822122656,37.465746770445,-87.64230353171,2,1,18 +2025-03-11T12:43:09.245559,479392988,65244,247,49.2340852367,37.46572231155,-87.651525554825,2,1,18 +2025-03-11T12:43:09.261184,479392988,65244,247,49.22466124346,37.461084933795,-87.633008720555,2,1,18 +2025-03-11T12:43:09.276809,479392988,65244,247,49.22466124346,37.45646386197,-87.61912663136,2,1,18 +2025-03-11T12:43:09.292434,479392988,65244,247,49.20581325698,37.43794696281,-87.595919432015,2,1,18 +2025-03-11T12:43:09.308059,479392988,65244,247,49.19638926374,37.41020422593,-87.568067531615,2,1,18 +2025-03-11T12:43:09.323684,479392988,65244,247,49.19167726712,37.38709071384,-87.544862135285,2,1,18 +2025-03-11T12:43:09.339309,479392988,65244,247,49.18225327388,37.37783226426,-87.49397847956,2,1,18 +2025-03-11T12:43:09.354934,479392988,65244,247,49.1634052874,37.36855750875,-87.44770244489,2,1,18 +2025-03-11T12:43:09.370559,479392988,65244,247,49.13042131106,37.350016150695,-87.401368987205,2,1,18 +2025-03-11T12:43:09.386184,479392988,65244,247,49.10686132796,37.326870026745,-87.36427291766,2,1,18 +2025-03-11T12:43:09.401809,479392988,65244,247,49.08330134486,37.29910283097,-87.345643040375,2,1,18 +2025-03-11T12:43:09.417434,479392988,65244,247,49.05502936514,37.266706410405,-87.299260743695,2,1,18 +2025-03-11T12:43:09.433059,479392988,65244,247,49.03146938204,37.22969707098,-87.257487871085,2,1,18 +2025-03-11T12:43:09.448684,479392988,65244,247,49.00319740232,37.22040600954,-87.20657709134,2,1,18 +2025-03-11T12:43:09.464309,479392988,65244,247,48.96550142936,37.187993283045,-87.155560049585,2,1,18 +2025-03-11T12:43:09.479934,479392988,65244,247,48.93722944964,37.14635471883,-87.07679239145,2,1,18 +2025-03-11T12:43:09.495559,479392988,65244,247,48.91838146316,37.10935353237,-87.007299201455,2,1,18 +2025-03-11T12:43:09.511184,479392988,65244,247,48.87597349358,37.06769050926,-86.928511200305,2,1,18 +2025-03-11T12:43:09.526809,479392988,65244,247,48.82885352738,37.03988254866,-86.85901440428,2,1,18 +2025-03-11T12:43:09.542434,479392988,65244,247,48.7864455578,36.99821952555,-86.784847586195,2,1,18 +2025-03-11T12:43:09.558059,479392988,65244,247,48.7393255916,36.95192727765,-86.710655447105,2,1,18 +2025-03-11T12:43:09.573684,479392988,65244,247,48.68749362878,36.91024794861,-86.61799033475,2,1,18 +2025-03-11T12:43:09.589309,479392988,65244,247,48.63094966934,36.859318322955,-86.502175446065,2,1,18 +2025-03-11T12:43:09.604934,479392988,65244,247,48.58382970314,36.813026075055,-86.41411975778,2,1,18 +2025-03-11T12:43:09.620559,479392988,65244,247,48.54613373018,36.76212906126,-86.33068027457,2,1,18 +2025-03-11T12:43:09.636184,479392988,65244,247,48.5037257606,36.688118535375,-86.22403539503,2,1,18 +2025-03-11T12:43:09.651809,479392988,65244,247,48.44246980454,36.63255968493,-86.13592228373,2,1,18 +2025-03-11T12:43:09.667434,479392988,65244,247,48.3859258451,36.581630059275,-86.04321331037,2,1,18 +2025-03-11T12:43:09.683059,479392988,65244,247,48.31995789242,36.53068412769,-85.91352131048,2,1,18 +2025-03-11T12:43:09.698684,479392988,65244,247,48.25870193636,36.447398846295,-85.774463945465,2,1,18 +2025-03-11T12:43:09.714309,479392988,65244,247,48.1974459803,36.368734636725,-85.658531035775,2,1,18 +2025-03-11T12:43:09.729934,479392988,65244,247,48.13619002424,36.32241792993,-85.53810672302,2,1,18 +2025-03-11T12:43:09.745559,479392988,65244,247,48.05137408508,36.25757617101,-85.422195528305,2,1,18 +2025-03-11T12:43:09.761184,479392988,65244,247,47.98069413578,36.183516727335,-85.30164641354,2,1,18 +2025-03-11T12:43:09.776809,479392988,65244,247,47.91001418648,36.10021514001,-85.162575486515,2,1,18 +2025-03-11T12:43:09.792434,479392988,65244,247,47.82991024394,36.007655103105,-85.02345391748,2,1,18 +2025-03-11T12:43:09.808059,479392988,65244,247,47.75923029464,35.938216731255,-84.89830215965,2,1,18 +2025-03-11T12:43:09.823684,479392988,65244,247,47.69797433858,35.86417359351,-84.750039508505,2,1,18 +2025-03-11T12:43:09.839309,479392988,65244,247,47.62258239266,35.79934814052,-84.611035960475,2,1,18 +2025-03-11T12:43:09.854934,479392988,65244,247,47.54719044674,35.729901615705,-84.472013872445,2,1,18 +2025-03-11T12:43:09.870559,479392988,65244,247,47.47179850082,35.637349731765,-84.305171986025,2,1,18 +2025-03-11T12:43:09.886184,479392988,65244,247,47.3728465718,35.540136011175,-84.13827765458,2,1,18 +2025-03-11T12:43:09.901809,479392988,65244,247,47.2786066394,35.456793659025,-83.985309273335,2,1,18 +2025-03-11T12:43:09.917434,479392988,65244,247,47.19379070024,35.373467612805,-83.82311208797,2,1,18 +2025-03-11T12:43:09.933059,479392988,65244,247,47.09955076784,35.290125260655,-83.6470377914,2,1,18 +2025-03-11T12:43:09.948684,479392988,65244,247,47.00531083544,35.197540764855,-83.494032330155,2,1,18 +2025-03-11T12:43:09.964309,479392988,65244,247,46.9016469098,35.09107674765,-83.336336503835,2,1,18 +2025-03-11T12:43:09.979934,479392988,65244,247,46.81683097064,34.993887485955,-83.178704881535,2,1,18 +2025-03-11T12:43:09.995422,479392992,65235,248,46.72259103824,34.90592406198,-82.993369678835,2,1,18 +2025-03-11T12:43:10.011047,479392992,65235,248,46.62363910922,34.79946819774,-82.80795353513,2,1,18 +2025-03-11T12:43:10.026672,479392992,65235,248,46.51997518358,34.68838310871,-82.617890887355,2,1,18 +2025-03-11T12:43:10.042297,479392992,65235,248,46.42102325456,34.577306172645,-82.41397147139,2,1,18 +2025-03-11T12:43:10.057922,479392992,65235,248,46.31735932892,34.475463227265,-82.214703537485,2,1,18 +2025-03-11T12:43:10.073547,479392992,65235,248,46.2184073999,34.3643862912,-82.024647670715,2,1,18 +2025-03-11T12:43:10.089172,479392992,65235,248,46.11003147764,34.25791412103,-81.825354415805,2,1,18 +2025-03-11T12:43:10.104797,479392992,65235,248,45.99223156214,34.14218350128,-81.616768152755,2,1,18 +2025-03-11T12:43:10.120422,479392992,65235,248,45.86971965002,34.026444728565,-81.38969037644,2,1,18 +2025-03-11T12:43:10.136047,479392992,65235,248,45.770767721,33.929231007975,-81.17196303128,2,1,18 +2025-03-11T12:43:10.151672,479392992,65235,248,45.66239179874,33.804274550505,-80.96335325024,2,1,18 +2025-03-11T12:43:10.167297,479392992,65235,248,45.54459188324,33.67468071528,-80.750090184125,2,1,18 +2025-03-11T12:43:10.182922,479392992,65235,248,45.41265597788,33.55430456481,-80.536843854995,2,1,18 +2025-03-11T12:43:10.198547,479392992,65235,248,45.2760080759,33.433920261375,-80.318969561795,2,1,18 +2025-03-11T12:43:10.214172,479392992,65235,248,45.1582081604,33.318189641625,-80.08727738342,2,1,18 +2025-03-11T12:43:10.229797,479392992,65235,248,45.02156025842,33.183942122715,-79.86010510409,2,1,18 +2025-03-11T12:43:10.245422,479392992,65235,248,44.90376034292,33.06359043114,-79.64225793491,2,1,18 +2025-03-11T12:43:10.261047,479392992,65235,248,44.78596042742,32.92937552409,-79.392006864275,2,1,18 +2025-03-11T12:43:10.276672,479392992,65235,248,44.65873651868,32.77666002381,-79.15091043776,2,1,18 +2025-03-11T12:43:10.292297,479392992,65235,248,44.53151260994,32.66091309813,-78.919204697375,2,1,18 +2025-03-11T12:43:10.307922,479392992,65235,248,44.39957670458,32.535915875835,-78.67359154679,2,1,18 +2025-03-11T12:43:10.323547,479392992,65235,248,44.25350480936,32.38778883552,-78.414001803995,2,1,18 +2025-03-11T12:43:10.339172,479392992,65235,248,44.10743291414,32.23504072338,-78.168257070395,2,1,18 +2025-03-11T12:43:10.354797,479392992,65235,248,43.96136101892,32.09153475489,-77.9086858676,2,1,18 +2025-03-11T12:43:10.370422,479392992,65235,248,43.82942511356,31.95267431712,-77.64915354782,2,1,18 +2025-03-11T12:43:10.386047,479392992,65235,248,43.68806521496,31.82303971707,-77.3804023799,2,1,18 +2025-03-11T12:43:10.401672,479392992,65235,248,43.54670531636,31.688784045195,-77.11163267198,2,1,18 +2025-03-11T12:43:10.417297,479392992,65235,248,43.40063342114,31.54065700488,-76.83817937999,2,1,18 +2025-03-11T12:43:10.432922,479392992,65235,248,43.26398551916,31.39716734232,-76.578621739205,2,1,18 +2025-03-11T12:43:10.448547,479392992,65235,248,43.11791362394,31.25366137383,-76.31905053641,2,1,18 +2025-03-11T12:43:10.464172,479392992,65235,248,42.9671297321,31.0962840369,-76.045553383415,2,1,18 +2025-03-11T12:43:10.479797,479392992,65235,248,42.80692184702,30.943511465865,-75.75357647615,2,1,18 +2025-03-11T12:43:10.495422,479392992,65235,248,42.64200196532,30.772246454565,-75.475382177075,2,1,18 +2025-03-11T12:43:10.511047,479392992,65235,248,42.47708208362,30.610223586915,-75.18798259187,2,1,18 +2025-03-11T12:43:10.526672,479392992,65235,248,42.32629819178,30.46670946546,-74.90067750968,2,1,18 +2025-03-11T12:43:10.542297,479392992,65235,248,42.15666631346,30.304678444845,-74.59478641121,2,1,18 +2025-03-11T12:43:10.557922,479392992,65235,248,42.001170425,30.1380508113,-74.29351829882,2,1,18 +2025-03-11T12:43:10.573547,479392992,65235,248,41.85509852978,29.980681627335,-74.0107855607,2,1,18 +2025-03-11T12:43:10.589172,479392992,65235,248,41.69960264132,29.82329613744,-73.72803926057,2,1,18 +2025-03-11T12:43:10.604797,479392992,65235,248,41.53939475624,29.652039279105,-73.42212464411,2,1,18 +2025-03-11T12:43:10.620422,479392992,65235,248,41.3650508813,29.47613689005,-73.11154996157,2,1,18 +2025-03-11T12:43:10.636047,479392992,65235,248,41.18128301312,29.300218195065,-72.78247698476,2,1,18 +2025-03-11T12:43:10.651672,479392992,65235,248,40.99280314832,29.124291347115,-72.46726077614,2,1,18 +2025-03-11T12:43:10.667297,479392992,65235,248,40.82788326662,28.94840526399,-72.152078472545,2,1,18 +2025-03-11T12:43:10.682922,479392992,65235,248,40.66767538154,28.76328519018,-71.84148705302,2,1,18 +2025-03-11T12:43:10.698547,479392992,65235,248,40.48861950998,28.610480007285,-71.521755923345,2,1,18 +2025-03-11T12:43:10.714172,479392992,65235,248,40.31427563504,28.43457761823,-71.19731769161,2,1,18 +2025-03-11T12:43:10.729797,479392992,65235,248,40.116371777,28.244771248875,-70.87278993485,2,1,18 +2025-03-11T12:43:10.745422,479392992,65235,248,39.91846791896,28.059585951345,-70.53903835196,2,1,18 +2025-03-11T12:43:10.761047,479392992,65235,248,39.74883604064,27.874449571605,-70.19608508897,2,1,18 +2025-03-11T12:43:10.776672,479392992,65235,248,39.56506817246,27.68928873297,-69.880838581355,2,1,18 +2025-03-11T12:43:10.792297,479392992,65235,248,39.37658830766,27.49487759772,-69.55168466354,2,1,18 +2025-03-11T12:43:10.807922,479392992,65235,248,39.18810844286,27.30970860612,-69.1994619104,2,1,18 +2025-03-11T12:43:10.823547,479392992,65235,248,39.00434057468,27.124547767485,-68.8426247552,2,1,18 +2025-03-11T12:43:10.839172,479392992,65235,248,38.82528470312,26.930152938165,-68.48113611794,2,1,18 +2025-03-11T12:43:10.854797,479392992,65235,248,38.62266884846,26.749580559495,-68.12429037872,2,1,18 +2025-03-11T12:43:10.870422,479392992,65235,248,38.4436129769,26.555185730175,-67.76280174146,2,1,18 +2025-03-11T12:43:10.886047,479392992,65235,248,38.26926910196,26.346935838345,-67.40588544827,2,1,18 +2025-03-11T12:43:10.901672,479392992,65235,248,38.0666532473,26.16174238785,-67.05826353518,2,1,18 +2025-03-11T12:43:10.917297,479392992,65235,248,37.87346138588,25.958080955985,-66.7105810241,2,1,18 +2025-03-11T12:43:10.932922,479392992,65235,248,37.67084553122,25.768266433665,-66.35369820488,2,1,18 +2025-03-11T12:43:10.948547,479392992,65235,248,37.4540936867,25.55994316515,-65.978236150385,2,1,18 +2025-03-11T12:43:10.964172,479392992,65235,248,37.25618982866,25.360894652145,-65.61208066604,2,1,18 +2025-03-11T12:43:10.979797,479392992,65235,248,37.05828597062,25.16184613914,-65.245925181695,2,1,18 +2025-03-11T12:43:10.995422,479392992,65235,248,36.8650941092,24.958184707275,-64.879757938355,2,1,18 +2025-03-11T12:43:11.011047,479392992,65235,248,36.64363026806,24.749853285795,-64.495046736725,2,1,18 +2025-03-11T12:43:11.026672,479392992,65235,248,36.42687842354,24.53228787363,-64.114926419165,2,1,18 +2025-03-11T12:43:11.042297,479392992,65235,248,36.21955057226,24.314738767395,-63.73944084668,2,1,18 +2025-03-11T12:43:11.057922,479392992,65235,248,36.00751072436,24.097181508195,-63.368569676255,2,1,18 +2025-03-11T12:43:11.073547,479392992,65235,248,35.79075887984,23.87961609603,-62.96534344337,2,1,18 +2025-03-11T12:43:11.089172,479392992,65235,248,35.57871903194,23.67130098048,-62.57140343762,2,1,18 +2025-03-11T12:43:11.104797,479392992,65235,248,35.37610317728,23.449138955385,-62.15893664162,2,1,18 +2025-03-11T12:43:11.120422,479392992,65235,248,35.15935133276,23.236194615045,-61.7603501318,2,1,18 +2025-03-11T12:43:11.136047,479392992,65235,248,34.933175495,23.01861289695,-61.366352703035,2,1,18 +2025-03-11T12:43:11.151672,479392992,65235,248,34.72584764372,22.801063790715,-60.977003581355,2,1,18 +2025-03-11T12:43:11.167297,479392992,65235,248,34.50438380258,22.583490225585,-60.583012933595,2,1,18 +2025-03-11T12:43:11.182922,479392992,65235,248,34.28291996144,22.365916660455,-60.179779919705,2,1,18 +2025-03-11T12:43:11.198547,479392992,65235,248,34.07088011354,22.14373832943,-59.79040547702,2,1,18 +2025-03-11T12:43:11.214172,479392992,65235,248,33.83056828592,21.91689000879,-59.373244709915,2,1,18 +2025-03-11T12:43:11.229797,479392992,65235,248,33.59496845492,21.680807697465,-58.94219009462,2,1,18 +2025-03-11T12:43:11.245422,479392992,65235,248,33.38292860702,21.44014507914,-58.543499125805,2,1,18 +2025-03-11T12:43:11.261047,479392992,65235,248,33.1661767625,21.222579666975,-58.117166977595,2,1,18 +2025-03-11T12:43:11.276672,479392992,65235,248,32.94000092474,20.99575580523,-57.69540537044,2,1,18 +2025-03-11T12:43:11.292297,479392992,65235,248,32.69968909712,20.755044269115,-57.2828101664,2,1,18 +2025-03-11T12:43:11.307922,479392992,65235,248,32.46408926612,20.51896195779,-56.84713436804,2,1,18 +2025-03-11T12:43:11.323547,479392992,65235,248,32.23791342836,20.28751702422,-56.42073303782,2,1,18 +2025-03-11T12:43:11.339172,479392992,65235,248,31.9881776075,20.065273469475,-56.003577248705,2,1,18 +2025-03-11T12:43:11.354797,479392992,65235,248,31.75728977312,19.819957167465,-55.57711351748,2,1,18 +2025-03-11T12:43:11.370422,479392992,65235,248,31.5169779455,19.574624559525,-55.132151491985,2,1,18 +2025-03-11T12:43:11.386047,479392992,65235,248,31.27666611788,19.33391302341,-54.701071555685,2,1,18 +2025-03-11T12:43:11.401672,479392992,65235,248,31.03635429026,19.093201487295,-54.251506887125,2,1,18 +2025-03-11T12:43:11.417297,479392992,65235,248,30.79604246264,18.857111023005,-53.78809720937,2,1,18 +2025-03-11T12:43:11.432922,479392992,65235,248,30.5510186384,18.616391333925,-53.33390457674,2,1,18 +2025-03-11T12:43:11.448547,479392992,65235,248,30.3154188074,18.375687950775,-52.89821023838,2,1,18 +2025-03-11T12:43:11.464172,479392992,65235,248,30.07039498316,18.134968261695,-52.467123521075,2,1,18 +2025-03-11T12:43:11.479797,479392992,65235,248,29.8206591623,17.884998276,-52.045235308895,2,1,18 +2025-03-11T12:43:11.495422,479392992,65235,248,29.5850593313,17.6350527492,-51.6141250736,2,1,18 +2025-03-11T12:43:11.511047,479392992,65235,248,29.33532351044,17.38970383533,-51.14604357077,2,1,18 +2025-03-11T12:43:11.526672,479392992,65235,248,29.08558768958,17.12587063416,-50.67788790794,2,1,18 +2025-03-11T12:43:11.542297,479392992,65235,248,28.84056386534,16.87590880143,-50.219037012245,2,1,18 +2025-03-11T12:43:11.557922,479392992,65235,248,28.58140405124,16.625922509805,-49.7647869566,2,1,18 +2025-03-11T12:43:11.573547,479392992,65235,248,28.31753224052,16.375928065215,-49.296666570755,2,1,18 +2025-03-11T12:43:11.589172,479392992,65235,248,28.06308442304,16.125949926555,-48.83780211305,2,1,18 +2025-03-11T12:43:11.604797,479392992,65235,248,27.82277259542,15.86675410314,-48.37892091836,2,1,18 +2025-03-11T12:43:11.620422,479392992,65235,248,27.57774877118,15.61679227041,-47.920070022665,2,1,18 +2025-03-11T12:43:11.636047,479392992,65235,248,27.31858895708,15.35294276331,-47.44727961476,2,1,18 +2025-03-11T12:43:11.651672,479392992,65235,248,27.06885313622,15.08910956214,-46.9698815858,2,1,18 +2025-03-11T12:43:11.667297,479392992,65235,248,26.80026932888,14.839106964585,-46.49251205282,2,1,18 +2025-03-11T12:43:11.682922,479392992,65235,248,26.55053350802,14.584515907065,-46.02439346999,2,1,18 +2025-03-11T12:43:11.698547,479392992,65235,248,26.30550968378,14.306827643385,-45.556188968165,2,1,18 +2025-03-11T12:43:11.714172,479392992,65235,248,26.04163787306,14.047591055145,-45.06954677006,2,1,18 +2025-03-11T12:43:11.729797,479392992,65235,248,25.77776606234,13.79297553873,-44.57830192889,2,1,18 +2025-03-11T12:43:11.745422,479392992,65235,248,25.51860624824,13.533747103455,-44.096287694855,2,1,18 +2025-03-11T12:43:11.761047,479392992,65235,248,25.24531044428,13.265252065635,-43.623458403935,2,1,18 +2025-03-11T12:43:11.776672,479392992,65235,248,24.98143863356,12.99215226192,-43.14600295196,2,1,18 +2025-03-11T12:43:11.792297,479392992,65235,248,24.71756682284,12.72367353003,-42.659323673855,2,1,18 +2025-03-11T12:43:11.807922,479392992,65235,248,24.45369501212,12.46443694179,-42.177302658815,2,1,18 +2025-03-11T12:43:11.823547,479392992,65235,248,24.18511120478,12.205192200585,-41.690653679705,2,1,18 +2025-03-11T12:43:11.839172,479392992,65235,248,23.92123939406,11.927471325045,-41.190073772405,2,1,18 +2025-03-11T12:43:11.854797,479392992,65235,248,23.65265558672,11.64974229654,-40.69872945023,2,1,18 +2025-03-11T12:43:11.870422,479392992,65235,248,23.37935978276,11.385868330545,-40.21667633318,2,1,18 +2025-03-11T12:43:11.886047,479392992,65235,248,23.1060639788,11.108131149075,-39.729946413065,2,1,18 +2025-03-11T12:43:11.901672,479392992,65235,248,22.83748017146,10.82115997692,-39.215459095565,2,1,18 +2025-03-11T12:43:11.917297,479392992,65235,248,22.56889636412,10.53880987659,-38.73333859952,2,1,18 +2025-03-11T12:43:11.932922,479392992,65235,248,22.28617656692,10.274919604665,-38.228166005135,2,1,18 +2025-03-11T12:43:11.948547,479392992,65235,248,22.0223047562,10.015683016425,-37.727660257835,2,1,18 +2025-03-11T12:43:11.964172,479392992,65235,248,21.74900895224,9.73332476313,-37.22242706546,2,1,18 +2025-03-11T12:43:11.979797,479392992,65235,248,21.46628915504,9.44632913208,-36.72178295414,2,1,18 +2025-03-11T12:43:11.995422,479392992,65235,248,21.18828135446,9.168583797645,-36.221182703825,2,1,18 +2025-03-11T12:43:12.011047,479392992,65235,248,20.90556155726,8.900072453895,-35.70674920331,2,1,18 +2025-03-11T12:43:12.026672,479392992,65235,248,20.6322657533,8.622335272425,-35.19691336787,2,1,18 +2025-03-11T12:43:12.042297,479392992,65235,248,20.3495459561,8.335339641375,-34.682405707355,2,1,18 +2025-03-11T12:43:12.057922,479392992,65235,248,20.08567414538,8.04375555036,-34.17714899699,2,1,18 +2025-03-11T12:43:12.073547,479392992,65235,248,19.81237834142,7.76601836889,-33.67655552768,2,1,18 +2025-03-11T12:43:12.089172,479392992,65235,248,19.5249465476,7.506741015825,-33.16215232616,2,1,18 +2025-03-11T12:43:12.104797,479392992,65235,248,19.24693874702,7.233616753215,-32.64770706665,2,1,18 +2025-03-11T12:43:12.120422,479392992,65235,248,18.95479495658,6.93274160076,-32.11926667493,2,1,18 +2025-03-11T12:43:12.136047,479392992,65235,248,18.68621114924,6.63190721313,-31.600102554365,2,1,18 +2025-03-11T12:43:12.151672,479392992,65235,248,18.39877935542,6.35876664459,-31.08102254978,2,1,18 +2025-03-11T12:43:12.167297,479392992,65235,248,18.1113475616,6.090247147875,-30.548097536,2,1,18 +2025-03-11T12:43:12.182922,479392992,65235,248,17.83805175764,5.80788889458,-30.03824316056,2,1,18 +2025-03-11T12:43:12.198547,479392992,65235,248,17.5459079672,5.525498029425,-29.51911929497,2,1,18 +2025-03-11T12:43:12.214172,479392992,65235,248,17.26318817,5.238502398375,-28.99074808526,2,1,18 +2025-03-11T12:43:12.229797,479392992,65235,248,16.97104437956,4.96535367687,-28.485524848865,2,1,18 +2025-03-11T12:43:12.245422,479392992,65235,248,16.68832458236,4.65987375852,-27.975564211415,2,1,18 +2025-03-11T12:43:12.261047,479392992,65235,248,16.40089278854,4.35900675903,-27.4471306007,2,1,18 +2025-03-11T12:43:12.276672,479392992,65235,248,16.12288498796,4.062777137295,-26.918729091995,2,1,18 +2025-03-11T12:43:12.292297,479392992,65235,248,15.83074119752,3.77114412849,-26.381083414145,2,1,18 +2025-03-11T12:43:12.307922,479392992,65235,248,15.52917341384,3.49335802923,-25.861964526545,2,1,18 +2025-03-11T12:43:12.323547,479392992,65235,248,15.22760563016,3.192466570845,-25.342752938945,2,1,18 +2025-03-11T12:43:12.339172,479392992,65235,248,14.93546183972,2.89159141839,-24.81893373029,2,1,18 +2025-03-11T12:43:12.354797,479392992,65235,248,14.65745403914,2.60922501213,-24.27672429239,2,1,18 +2025-03-11T12:43:12.370422,479392992,65235,248,14.37002224532,2.32684229994,-23.74374365861,2,1,18 +2025-03-11T12:43:12.386047,479392992,65235,248,14.07316645826,2.03520113817,-23.22919711508,2,1,18 +2025-03-11T12:43:12.401672,479392992,65235,248,13.78102266782,1.72970491389,-22.686874634165,2,1,18 +2025-03-11T12:43:12.417297,479392992,65235,248,13.47474288752,1.42880530254,-22.126065617975,2,1,18 +2025-03-11T12:43:12.432922,479392992,65235,248,13.20144708356,1.137204905595,-21.59306824721,2,1,18 +2025-03-11T12:43:12.448547,479392992,65235,248,12.92343928298,0.854838499334999,-21.06010117544,2,1,18 +2025-03-11T12:43:12.464172,479392992,65235,248,12.6218714993,0.57243132825,-20.517857832515,2,1,18 +2025-03-11T12:43:12.479797,479392992,65235,248,12.33443970548,0.27156432876,-19.98018185567,2,1,18 +2025-03-11T12:43:12.495422,479392992,65235,248,12.03758391842,-0.0339400484850003,-19.451716142945,2,1,18 +2025-03-11T12:43:12.511047,479392992,65235,248,11.74072813136,-0.330202282080001,-18.91404514409,2,1,18 +2025-03-11T12:43:12.526672,479392992,65235,248,11.45329633754,-0.631069281569999,-18.367126801115,2,1,18 +2025-03-11T12:43:12.542297,479392992,65235,248,11.15172855386,-0.918097524479999,-17.81562255206,2,1,18 +2025-03-11T12:43:12.557922,479392992,65235,248,10.84073677694,-1.209763145145,-17.282570933255,2,1,18 +2025-03-11T12:43:12.573547,479392992,65235,248,10.55330498312,-1.50600907281,-16.740292313345,2,1,18 +2025-03-11T12:43:12.589172,479392992,65235,248,10.2658731893,-1.811497144125,-16.225703711825,2,1,18 +2025-03-11T12:43:12.604797,479392992,65235,248,9.96430540562,-2.107767530685,-15.697268298095,2,1,18 +2025-03-11T12:43:12.620422,479392992,65235,248,9.65802562532,-2.40404607021,-15.1503413711,2,1,18 +2025-03-11T12:43:12.636047,479392992,65235,248,9.35645784164,-2.695695384945,-14.608060948175,2,1,18 +2025-03-11T12:43:12.651672,479392992,65235,248,9.0643140512,-2.991949465575,-14.08426027952,2,1,18 +2025-03-11T12:43:12.667297,479392992,65235,248,8.76274626752,-3.288219852135,-13.532718950465,2,1,18 +2025-03-11T12:43:12.682922,479392992,65235,248,8.46589048046,-3.60296637303,-12.95800432709,2,1,18 +2025-03-11T12:43:12.698547,479392992,65235,248,8.1925946765,-3.913051057275,-12.41106924713,2,1,18 +2025-03-11T12:43:12.714172,479392992,65235,248,7.89573888944,-4.20931329087,-11.864155882145,2,1,18 +2025-03-11T12:43:12.729797,479392992,65235,248,7.5800351159,-4.51022920815,-11.32643921927,2,1,18 +2025-03-11T12:43:12.745422,479392992,65235,248,7.28317932884,-4.806491441745,-10.78414703735,2,1,18 +2025-03-11T12:43:12.761047,479392992,65235,248,6.98632354178,-5.10275367534,-10.237233672365,2,1,18 +2025-03-11T12:43:12.776672,479392992,65235,248,6.68946775472,-5.41287912441,-9.69026468738,2,1,18 +2025-03-11T12:43:12.792297,479392992,65235,248,6.3784759778,-5.71840796055,-9.147915082445,2,1,18 +2025-03-11T12:43:12.807922,479392992,65235,248,6.07690819412,-6.02392049076,-8.60557903952,2,1,18 +2025-03-11T12:43:12.823547,479392992,65235,248,5.77534041044,-6.31094873367,-8.05869597353,2,1,18 +2025-03-11T12:43:12.839172,479392992,65235,248,5.50204460648,-6.61641234609,-7.53026416583,2,1,18 +2025-03-11T12:43:12.854797,479392992,65235,248,5.20518881942,-6.91729565151,-6.96022634552,2,1,18 +2025-03-11T12:43:12.870422,479392992,65235,248,4.89890903912,-7.21819526286,-6.394796146265,2,1,18 +2025-03-11T12:43:12.886047,479392992,65235,248,4.59734125544,-7.509844577595,-5.866379272535,2,1,18 +2025-03-11T12:43:12.901672,479392992,65235,248,4.31462145824,-7.81070342412,-5.3148465275,2,1,18 +2025-03-11T12:43:12.917297,479392992,65235,248,4.01305367456,-8.102352738855,-4.76794492151,2,1,18 +2025-03-11T12:43:12.932922,479392992,65235,248,3.70677389426,-8.394010206555,-4.230278900645,2,1,18 +2025-03-11T12:43:12.948547,479392992,65235,248,3.40520611058,-8.699522736765,-3.67870049159,2,1,18 +2025-03-11T12:43:12.964172,479392992,65235,248,3.11777431676,-9.00501080808,-3.131763608615,2,1,18 +2025-03-11T12:43:12.979797,479392992,65235,248,2.81149453646,-9.292047203955,-2.58487376162,2,1,18 +2025-03-11T12:43:12.995422,479392992,65235,248,2.49579076292,-9.58834204941,-2.037933272615,2,1,18 +2025-03-11T12:43:13.011047,479392992,65235,248,2.18951098262,-9.89848380441,-1.49095072562,2,1,18 +2025-03-11T12:43:13.026672,479392992,65235,248,1.89736719218,-10.199358956865,-0.957889150835,2,1,18 +2025-03-11T12:43:13.042297,479392992,65235,248,1.60522340174,-10.514097324795,-0.39704485766,2,1,18 +2025-03-11T12:43:13.057922,479392992,65235,248,1.3130796113,-10.828835692725,0.14993588632,2,1,18 +2025-03-11T12:43:13.073547,479392992,65235,248,1.00208783438,-11.11125916974,0.69681397432,2,1,18 +2025-03-11T12:43:13.089172,479392992,65235,248,0.69580805408,-11.407537709265,1.252983267445,2,1,18 +2025-03-11T12:43:13.104797,479392992,65235,248,0.41308825688,-11.703775483965,1.79525510635,2,1,18 +2025-03-11T12:43:13.120422,479392992,65235,248,0.1115204732,-12.00466694235,2.328330243145,2,1,18 +2025-03-11T12:43:13.136047,479392992,65235,248,-0.19947130372,-12.314816850315,2.875319571145,2,1,18 +2025-03-11T12:43:13.151672,479392992,65235,248,-0.5010390874,-12.611087236875,3.4268609002,2,1,18 +2025-03-11T12:43:13.167297,479392992,65235,248,-0.79789487446,-12.91659161412,3.973811345185,2,1,18 +2025-03-11T12:43:13.182922,479392992,65235,248,-1.09946265814,-13.208240928855,4.502228218915,2,1,18 +2025-03-11T12:43:13.198547,479392992,65235,248,-1.38689445196,-13.50448685652,5.05837038802,2,1,18 +2025-03-11T12:43:13.214172,479392992,65235,248,-1.6790382424,-13.796119865325,5.609879615065,2,1,18 +2025-03-11T12:43:13.229797,479392992,65235,248,-1.97118203284,-14.101616089605,6.15220209598,2,1,18 +2025-03-11T12:43:13.245422,479392992,65235,248,-2.28217380976,-14.388660638445,6.69909872398,2,1,18 +2025-03-11T12:43:13.261047,479392992,65235,248,-2.57902959682,-14.680301800215,7.23212999977,2,1,18 +2025-03-11T12:43:13.276672,479392992,65235,248,-2.86646139064,-14.990410943355,7.75597950742,2,1,18 +2025-03-11T12:43:13.292297,479392992,65235,248,-3.15860518108,-15.30977038311,8.28449405914,2,1,18 +2025-03-11T12:43:13.307922,479392992,65235,248,-3.45074897152,-15.59678232009,8.835984746185,2,1,18 +2025-03-11T12:43:13.323547,479392992,65235,248,-3.75702875182,-15.88843978779,9.38289313318,2,1,18 +2025-03-11T12:43:13.339172,479392992,65235,248,-4.04917254226,-16.17545172477,9.92976263716,2,1,18 +2025-03-11T12:43:13.354797,479392992,65235,248,-4.34602832932,-16.471713958365,10.47205481908,2,1,18 +2025-03-11T12:43:13.370422,479392992,65235,248,-4.63817211976,-16.767968038995,11.014340219995,2,1,18 +2025-03-11T12:43:13.386047,479392992,65235,248,-4.94445190006,-17.087351937645,11.54287511473,2,1,18 +2025-03-11T12:43:13.401672,479392992,65235,248,-5.25544367698,-17.38825970196,12.07134263047,2,1,18 +2025-03-11T12:43:13.417297,479392992,65235,248,-5.5428754708,-17.67064241415,12.61356563038,2,1,18 +2025-03-11T12:43:13.432922,479392992,65235,248,-5.83030726462,-17.94378298269,13.15575155029,2,1,18 +2025-03-11T12:43:13.448547,479392992,65235,248,-6.11773905844,-18.23540783853,13.67028453181,2,1,18 +2025-03-11T12:43:13.464172,479392992,65235,248,-6.40045885564,-18.52240346958,14.19865574152,2,1,18 +2025-03-11T12:43:13.479797,479392992,65235,248,-6.69260264608,-18.823278622035,14.73633849937,2,1,18 +2025-03-11T12:43:13.495422,479392992,65235,248,-6.98474643652,-19.119532702665,15.269381534155,2,1,18 +2025-03-11T12:43:13.511047,479392992,65235,248,-7.2863142202,-19.40193987375,15.79314014482,2,1,18 +2025-03-11T12:43:13.526672,479392992,65235,248,-7.5690340174,-19.69817764845,16.30306370227,2,1,18 +2025-03-11T12:43:13.542297,479392992,65235,248,-7.8517538146,-19.99441542315,16.82222962585,2,1,18 +2025-03-11T12:43:13.557922,479392992,65235,248,-8.14389760504,-20.28142736013,17.364477946765,2,1,18 +2025-03-11T12:43:13.573547,479392992,65235,248,-8.4407533921,-20.56382637825,17.906714508685,2,1,18 +2025-03-11T12:43:13.589172,479392992,65235,248,-8.72818518592,-20.85545123409,18.41662630714,2,1,18 +2025-03-11T12:43:13.604797,479392992,65235,248,-9.02032897636,-21.137842099245,18.940371355795,2,1,18 +2025-03-11T12:43:13.620422,479392992,65235,248,-9.30776077018,-21.42484588326,19.464128163445,2,1,18 +2025-03-11T12:43:13.636047,479392992,65235,248,-9.58105657414,-21.716446280205,19.992504351145,2,1,18 +2025-03-11T12:43:13.651672,479392992,65235,248,-9.86377637134,-22.012684054905,20.502427908595,2,1,18 +2025-03-11T12:43:13.667297,479392992,65235,248,-10.1606321584,-22.322809503975,21.02166979519,2,1,18 +2025-03-11T12:43:13.682922,479392992,65235,248,-10.43863995898,-22.595933766585,21.540736237765,2,1,18 +2025-03-11T12:43:13.698547,479392992,65235,248,-10.73078374942,-22.86908248809,22.06444420642,2,1,18 +2025-03-11T12:43:13.714172,479392992,65235,248,-11.01350354662,-23.15607811914,22.588194233065,2,1,18 +2025-03-11T12:43:13.729797,479392992,65235,248,-11.30564733706,-23.419984696995,23.116486304785,2,1,18 +2025-03-11T12:43:13.745422,479392992,65235,248,-11.57894314102,-23.706964022115,23.64946513555,2,1,18 +2025-03-11T12:43:13.761047,479392992,65235,248,-11.85223894498,-24.00780656271,24.15939367099,2,1,18 +2025-03-11T12:43:13.776672,479392992,65235,248,-12.13024674556,-24.304036184445,24.66468926437,2,1,18 +2025-03-11T12:43:13.792297,479392992,65235,248,-12.41296654276,-24.600273959145,25.17461282182,2,1,18 +2025-03-11T12:43:13.807922,479392992,65235,248,-12.69097434334,-24.873398221755,25.684436898265,2,1,18 +2025-03-11T12:43:13.823547,479392992,65235,248,-12.9642701473,-25.1465143314,26.18039064451,2,1,18 +2025-03-11T12:43:13.839172,479392992,65235,248,-13.25170194112,-25.433518115415,26.6856627199,2,1,18 +2025-03-11T12:43:13.854797,479392992,65235,248,-13.5297097417,-25.7020213062,27.195468256345,2,1,18 +2025-03-11T12:43:13.870422,479392992,65235,248,-13.79829354904,-25.970508191055,27.700639047715,2,1,18 +2025-03-11T12:43:13.886047,479392992,65235,248,-14.07630134962,-26.243632453665,28.205841941095,2,1,18 +2025-03-11T12:43:13.901672,479392992,65235,248,-14.3543091502,-26.51213564445,28.711026294475,2,1,18 +2025-03-11T12:43:13.917297,479392992,65235,248,-14.6370289474,-26.78988913185,29.211633325795,2,1,18 +2025-03-11T12:43:13.932922,479392992,65235,248,-14.91503674798,-27.08149768176,29.73077392837,2,1,18 +2025-03-11T12:43:13.948547,479392992,65235,248,-15.18362055532,-27.35460563844,30.212857344415,2,1,18 +2025-03-11T12:43:13.964172,479392992,65235,248,-15.44749236604,-27.627705442155,30.70879752865,2,1,18 +2025-03-11T12:43:13.979797,479392992,65235,248,-15.72078817,-27.914684767275,31.214049261025,2,1,18 +2025-03-11T12:43:13.995376,479392996,65232,249,-15.98937197734,-28.18317165213,31.7053565032,2,1,18 +2025-03-11T12:43:14.011001,479392996,65232,249,-16.24853179144,-28.44702115923,32.1920104603,2,1,18 +2025-03-11T12:43:14.026626,479392996,65232,249,-16.52653959202,-28.724766493665,32.68798952755,2,1,18 +2025-03-11T12:43:14.042251,479392996,65232,249,-16.8045473926,-28.997890756275,33.170086505605,2,1,18 +2025-03-11T12:43:14.057876,479392996,65232,249,-17.06841920332,-29.25250627269,33.66595252984,2,1,18 +2025-03-11T12:43:14.073501,479392996,65232,249,-17.33229101404,-29.497879645455,34.143296741815,2,1,18 +2025-03-11T12:43:14.089126,479392996,65232,249,-17.60087482138,-29.75712438666,34.639188087055,2,1,18 +2025-03-11T12:43:14.104751,479392996,65232,249,-17.86945862872,-30.03023234334,35.13051386923,2,1,18 +2025-03-11T12:43:14.120376,479392996,65232,249,-18.13804243606,-30.307961371845,35.60799464221,2,1,18 +2025-03-11T12:43:14.136001,479392996,65232,249,-18.41133824002,-30.58107748149,36.085463656195,2,1,18 +2025-03-11T12:43:14.151626,479392996,65232,249,-18.67049805412,-30.849548060415,36.53978787184,2,1,18 +2025-03-11T12:43:14.167251,479392996,65232,249,-18.92023387498,-31.104139117935,37.00790645467,2,1,18 +2025-03-11T12:43:14.182876,479392996,65232,249,-19.16996969584,-31.35410910363,37.489870046695,2,1,18 +2025-03-11T12:43:14.198501,479392996,65232,249,-19.4197055167,-31.613321232975,37.95338598646,2,1,18 +2025-03-11T12:43:14.214126,479392996,65232,249,-19.6788653308,-31.87254966825,38.435400220495,2,1,18 +2025-03-11T12:43:14.229751,479392996,65232,249,-19.9380251449,-32.11791488805,38.91735883453,2,1,18 +2025-03-11T12:43:14.245376,479392996,65232,249,-20.20189695562,-32.363288260815,39.376218314245,2,1,18 +2025-03-11T12:43:14.261001,479392996,65232,249,-20.45163277648,-32.636363605635,39.83054750788,2,1,18 +2025-03-11T12:43:14.276626,479392996,65232,249,-20.70608059396,-32.895583887945,40.298691411715,2,1,18 +2025-03-11T12:43:14.292251,479392996,65232,249,-20.9511044182,-33.1501667925,40.76680321354,2,1,18 +2025-03-11T12:43:14.307876,479392996,65232,249,-21.20555223568,-33.39090278751,41.22100940818,2,1,18 +2025-03-11T12:43:14.323501,479392996,65232,249,-21.45528805654,-33.63625170138,41.675227361815,2,1,18 +2025-03-11T12:43:14.339126,479392996,65232,249,-21.7050238774,-33.886221687075,42.13870622158,2,1,18 +2025-03-11T12:43:14.354751,479392996,65232,249,-21.94533570502,-34.140796438665,42.574462960945,2,1,18 +2025-03-11T12:43:14.370376,479392996,65232,249,-22.18564753264,-34.386129046605,43.0379097187,2,1,18 +2025-03-11T12:43:14.386001,479392996,65232,249,-22.43067135688,-34.62222766386,43.487462628265,2,1,18 +2025-03-11T12:43:14.401626,479392996,65232,249,-22.68511917436,-34.867584730695,43.932444996775,2,1,18 +2025-03-11T12:43:14.417251,479392996,65232,249,-22.92543100198,-35.122159482285,44.372822919205,2,1,18 +2025-03-11T12:43:14.432876,479392996,65232,249,-23.1657428296,-35.37211316205,44.831667033895,2,1,18 +2025-03-11T12:43:14.448501,479392996,65232,249,-23.41547865046,-35.61746207592,45.25815788914,2,1,18 +2025-03-11T12:43:14.464126,479392996,65232,249,-23.66992646794,-35.862819142755,45.69389789152,2,1,18 +2025-03-11T12:43:14.479751,479392996,65232,249,-23.91023829556,-36.098909607045,46.13420165395,2,1,18 +2025-03-11T12:43:14.495376,479392996,65232,249,-24.1317021367,-36.334967459475,46.551372377035,2,1,18 +2025-03-11T12:43:14.511001,479392996,65232,249,-24.36258997108,-36.561799474185,46.991625497455,2,1,18 +2025-03-11T12:43:14.526626,479392996,65232,249,-24.58405381222,-36.77475196749,47.4271882528,2,1,18 +2025-03-11T12:43:14.542251,479392996,65232,249,-24.8149416466,-37.015447197675,47.844391077895,2,1,18 +2025-03-11T12:43:14.557876,479392996,65232,249,-25.05996547084,-37.256166886755,48.252371879875,2,1,18 +2025-03-11T12:43:14.573501,479392996,65232,249,-25.30027729846,-37.48763627922,48.674172370045,2,1,18 +2025-03-11T12:43:14.589126,479392996,65232,249,-25.52645313622,-37.723702284615,49.091349874135,2,1,18 +2025-03-11T12:43:14.604751,479392996,65232,249,-25.75262897398,-37.94128400271,49.51307440129,2,1,18 +2025-03-11T12:43:14.620376,479392996,65232,249,-25.97880481174,-38.17272893628,49.93023336538,2,1,18 +2025-03-11T12:43:14.636001,479392996,65232,249,-26.21440464274,-38.40419017578,50.33816352535,2,1,18 +2025-03-11T12:43:14.651626,479392996,65232,249,-26.4405804805,-38.649498324825,50.76462047557,2,1,18 +2025-03-11T12:43:14.667251,479392996,65232,249,-26.66675631826,-38.87632218657,51.1632761674,2,1,18 +2025-03-11T12:43:14.682876,479392996,65232,249,-26.89293215602,-39.08004068919,51.56183915923,2,1,18 +2025-03-11T12:43:14.698501,479392996,65232,249,-27.10968400054,-39.30222717318,51.95122038292,2,1,18 +2025-03-11T12:43:14.714126,479392996,65232,249,-27.32172384844,-39.51978443238,52.34519746867,2,1,18 +2025-03-11T12:43:14.729751,479392996,65232,249,-27.53847569296,-39.74197091637,52.757684607685,2,1,18 +2025-03-11T12:43:14.745376,479392996,65232,249,-27.7599395341,-39.964165553325,53.15631497851,2,1,18 +2025-03-11T12:43:14.761001,479392996,65232,249,-27.97669137862,-40.17248882184,53.550261765265,2,1,18 +2025-03-11T12:43:14.776626,479392996,65232,249,-28.18873122652,-40.37156179374,53.93030114182,2,1,18 +2025-03-11T12:43:14.792251,479392996,65232,249,-28.41019506766,-40.57989321522,54.30576997732,2,1,18 +2025-03-11T12:43:14.807876,479392996,65232,249,-28.61752291894,-40.77433696233,54.699647582065,2,1,18 +2025-03-11T12:43:14.823501,479392996,65232,249,-28.8201387736,-40.996498987425,55.093629645805,2,1,18 +2025-03-11T12:43:14.839126,479392996,65232,249,-29.02275462826,-41.214039940695,55.487593169545,2,1,18 +2025-03-11T12:43:14.854751,479392996,65232,249,-29.21123449306,-41.44079857872,55.87233106414,2,1,18 +2025-03-11T12:43:14.870376,479392996,65232,249,-29.41385034772,-41.644476316515,56.233890686425,2,1,18 +2025-03-11T12:43:14.886001,479392996,65232,249,-29.62589019562,-41.852791432065,56.60472477685,2,1,18 +2025-03-11T12:43:14.901626,479392996,65232,249,-29.82379405366,-42.03335565777,56.94770018587,2,1,18 +2025-03-11T12:43:14.917251,479392996,65232,249,-30.02640990832,-42.237033395565,57.29539625896,2,1,18 +2025-03-11T12:43:14.932876,479392996,65232,249,-30.21488977312,-42.440686674465,57.670799087425,2,1,18 +2025-03-11T12:43:14.948501,479392996,65232,249,-30.41750562778,-42.639743340435,58.027718986645,2,1,18 +2025-03-11T12:43:14.964126,479392996,65232,249,-30.62954547568,-42.83419524051,58.384633907875,2,1,18 +2025-03-11T12:43:14.979751,479392996,65232,249,-30.82744933372,-43.02862268169,58.746149669155,2,1,18 +2025-03-11T12:43:14.995376,479392996,65232,249,-31.01592919852,-43.236897032415,59.116949854555,2,1,18 +2025-03-11T12:43:15.011001,479392996,65232,249,-31.20912105994,-43.426695248805,59.48768266096,2,1,18 +2025-03-11T12:43:15.026626,479392996,65232,249,-31.37875293826,-43.611831628545,59.81215119169,2,1,18 +2025-03-11T12:43:15.042251,479392996,65232,249,-31.56723280306,-43.79237954832,60.13662830644,2,1,18 +2025-03-11T12:43:15.057876,479392996,65232,249,-31.76042466448,-43.986798836535,60.479652554455,2,1,18 +2025-03-11T12:43:15.073501,479392996,65232,249,-31.95832852252,-44.162741990415,60.83647297267,2,1,18 +2025-03-11T12:43:15.089126,479392996,65232,249,-32.15623238056,-44.35254835977,61.17024309556,2,1,18 +2025-03-11T12:43:15.104751,479392996,65232,249,-32.33528825212,-44.533079973615,61.48546428217,2,1,18 +2025-03-11T12:43:15.120376,479392996,65232,249,-32.5190561203,-44.722861884075,61.819214062045,2,1,18 +2025-03-11T12:43:15.136001,479392996,65232,249,-32.71224798172,-44.903417956815,62.166803873125,2,1,18 +2025-03-11T12:43:15.151626,479392996,65232,249,-32.90543984314,-45.065489742255,62.50045597501,2,1,18 +2025-03-11T12:43:15.167251,479392996,65232,249,-33.0609357316,-45.245980591275,62.815643256595,2,1,18 +2025-03-11T12:43:15.182876,479392996,65232,249,-33.21643162006,-45.43109251212,63.13084907818,2,1,18 +2025-03-11T12:43:15.198501,479392996,65232,249,-33.390775495,-45.611615973,63.44144230072,2,1,18 +2025-03-11T12:43:15.214126,479392996,65232,249,-33.56983136656,-45.76904222772,63.76581315346,2,1,18 +2025-03-11T12:43:15.229751,479392996,65232,249,-33.74888723812,-45.940331697915,64.076376077005,2,1,18 +2025-03-11T12:43:15.245376,479392996,65232,249,-33.91380711982,-46.12545992469,64.377731911405,2,1,18 +2025-03-11T12:43:15.261001,479392996,65232,249,-34.08815099476,-46.292120170095,64.679027147815,2,1,18 +2025-03-11T12:43:15.276626,479392996,65232,249,-34.26720686632,-46.45416749664,64.984931808295,2,1,18 +2025-03-11T12:43:15.292251,479392996,65232,249,-34.40856676492,-46.625391743115,65.27695575154,2,1,18 +2025-03-11T12:43:15.307876,479392996,65232,249,-34.55463866014,-46.787381998905,65.56894939579,2,1,18 +2025-03-11T12:43:15.323501,479392996,65232,249,-34.7101345486,-46.949388560625,65.874820151245,2,1,18 +2025-03-11T12:43:15.339126,479392996,65232,249,-34.8750544303,-47.1160325001,66.166859459515,2,1,18 +2025-03-11T12:43:15.354751,479392996,65232,249,-35.03055031876,-47.273417989995,66.46346930884,2,1,18 +2025-03-11T12:43:15.370376,479392996,65232,249,-35.1813342106,-47.430795326925,66.75083001103,2,1,18 +2025-03-11T12:43:15.386001,479392996,65232,249,-35.3462540923,-47.574333907275,67.03353425317,2,1,18 +2025-03-11T12:43:15.401626,479392996,65232,249,-35.51588597062,-47.722501712415,67.307021450185,2,1,18 +2025-03-11T12:43:15.417251,479392996,65232,249,-35.6760938557,-47.861411067975,67.566594455995,2,1,18 +2025-03-11T12:43:15.432876,479392996,65232,249,-35.82216575092,-48.00953810829,67.82618419879,2,1,18 +2025-03-11T12:43:15.448501,479392996,65232,249,-35.94938965966,-48.15301146492,68.076485911435,2,1,18 +2025-03-11T12:43:15.464126,479392996,65232,249,-36.1001735515,-48.305767730025,68.35920689056,2,1,18 +2025-03-11T12:43:15.479751,479392996,65232,249,-36.25095744334,-48.444660779655,68.641872249685,2,1,18 +2025-03-11T12:43:15.495376,479392996,65232,249,-36.39702933856,-48.59278781997,68.869113711025,2,1,18 +2025-03-11T12:43:15.511001,479392996,65232,249,-36.53367724054,-48.740898554355,69.124068708745,2,1,18 +2025-03-11T12:43:15.526626,479392996,65232,249,-36.67503713914,-48.870533154405,69.392819876665,2,1,18 +2025-03-11T12:43:15.542251,479392996,65232,249,-36.80226104788,-49.032490798335,69.638574566245,2,1,18 +2025-03-11T12:43:15.557876,479392996,65232,249,-36.92477296,-49.1574717147,69.88417415482,2,1,18 +2025-03-11T12:43:15.573501,479392996,65232,249,-37.05670886536,-49.273226793345,70.120507859275,2,1,18 +2025-03-11T12:43:15.589126,479392996,65232,249,-37.1839327741,-49.4213212218,70.347722196595,2,1,18 +2025-03-11T12:43:15.604751,479392996,65232,249,-37.3252926727,-49.555576893675,70.588764806125,2,1,18 +2025-03-11T12:43:15.620376,479392996,65232,249,-37.46194057468,-49.66671905346,70.834329117715,2,1,18 +2025-03-11T12:43:15.636001,479392996,65232,249,-37.57974049018,-49.79169181686,71.052194826895,2,1,18 +2025-03-11T12:43:15.651626,479392996,65232,249,-37.71167639554,-49.91206796733,71.274683522155,2,1,18 +2025-03-11T12:43:15.667251,479392996,65232,249,-37.83890030428,-50.032435964835,71.501786619475,2,1,18 +2025-03-11T12:43:15.682876,479392996,65232,249,-37.95198822316,-50.14815843162,71.72885083378,2,1,18 +2025-03-11T12:43:15.698501,479392996,65232,249,-38.06978813866,-50.28237333867,71.93751125683,2,1,18 +2025-03-11T12:43:15.714126,479392996,65232,249,-38.19230005078,-50.40273318321,72.15998639008,2,1,18 +2025-03-11T12:43:15.729751,479392996,65232,249,-38.31952395952,-50.504616893415,72.373151778205,2,1,18 +2025-03-11T12:43:15.745376,479392996,65232,249,-38.42789988178,-50.629573350885,72.581761559245,2,1,18 +2025-03-11T12:43:15.761001,479392996,65232,249,-38.53156380742,-50.74527951174,72.77184274702,2,1,18 +2025-03-11T12:43:15.776626,479392996,65232,249,-38.64936372292,-50.84252584419,72.96187011781,2,1,18 +2025-03-11T12:43:15.792251,479392996,65232,249,-38.7624516418,-50.939764023675,73.16575425679,2,1,18 +2025-03-11T12:43:15.807876,479392996,65232,249,-38.85197957758,-51.06006679746,73.351212458485,2,1,18 +2025-03-11T12:43:15.823501,479392996,65232,249,-38.94150751336,-51.16650635577,73.531993857115,2,1,18 +2025-03-11T12:43:15.839126,479392996,65232,249,-39.05459543224,-51.25912346343,73.717374723835,2,1,18 +2025-03-11T12:43:15.854751,479392996,65232,249,-39.15825935788,-51.347103193335,73.88885993935,2,1,18 +2025-03-11T12:43:15.870376,479392996,65232,249,-39.26192328352,-51.439703995065,74.07422724406,2,1,18 +2025-03-11T12:43:15.886001,479392996,65232,249,-39.3514512193,-51.546143553375,74.27349337495,2,1,18 +2025-03-11T12:43:15.901626,479392996,65232,249,-39.4456911517,-51.643349121,74.45886565765,2,1,18 +2025-03-11T12:43:15.917251,479392996,65232,249,-39.53521908748,-51.735925463835,74.616485520955,2,1,18 +2025-03-11T12:43:15.932876,479392996,65232,249,-39.62945901988,-51.837752103285,74.764906879135,2,1,18 +2025-03-11T12:43:15.948501,479392996,65232,249,-39.72369895228,-51.921094455435,74.922496443445,2,1,18 +2025-03-11T12:43:15.964126,479392996,65232,249,-39.81793888468,-52.004436807585,75.08470719082,2,1,18 +2025-03-11T12:43:15.979751,479392996,65232,249,-39.90275482384,-52.09238392563,75.24230173312,2,1,18 +2025-03-11T12:43:15.995376,479392996,65232,249,-39.98285876638,-52.184943962535,75.39528685135,2,1,18 +2025-03-11T12:43:16.011001,479392996,65232,249,-40.05353871568,-52.254382334385,75.562029256765,2,1,18 +2025-03-11T12:43:16.026626,479392996,65232,249,-40.13835465484,-52.32384516513,75.719549639065,2,1,18 +2025-03-11T12:43:16.042251,479392996,65232,249,-40.21845859738,-52.407163058385,75.86787649423,2,1,18 +2025-03-11T12:43:16.057876,479392996,65232,249,-40.29856253992,-52.48123880799,75.988439171005,2,1,18 +2025-03-11T12:43:16.073501,479392996,65232,249,-40.3645304926,-52.56453224235,76.11363976783,2,1,18 +2025-03-11T12:43:16.089126,479392996,65232,249,-40.43049844528,-52.63858353306,76.238803284655,2,1,18 +2025-03-11T12:43:16.104751,479392996,65232,249,-40.49646639796,-52.70339268012,76.368550904545,2,1,18 +2025-03-11T12:43:16.120376,479392996,65232,249,-40.57185834388,-52.76821813311,76.498312086445,2,1,18 +2025-03-11T12:43:16.136001,479392996,65232,249,-40.64253829318,-52.842277576785,76.614240018145,2,1,18 +2025-03-11T12:43:16.151626,479392996,65232,249,-40.71321824248,-52.911715948635,76.739391775975,2,1,18 +2025-03-11T12:43:16.167251,479392996,65232,249,-40.77447419854,-52.98575908638,76.855306145665,2,1,18 +2025-03-11T12:43:16.182876,479392996,65232,249,-40.84044215122,-53.036705017965,76.94340749797,2,1,18 +2025-03-11T12:43:16.198501,479392996,65232,249,-40.91112210052,-53.087659102515,77.036136814345,2,1,18 +2025-03-11T12:43:16.214126,479392996,65232,249,-40.9770900532,-53.161710393225,77.14281559891,2,1,18 +2025-03-11T12:43:16.229751,479392996,65232,249,-41.0242100194,-53.217244784775,77.249393099455,2,1,18 +2025-03-11T12:43:16.245376,479392996,65232,249,-41.0713299856,-53.263537032675,77.34669115387,2,1,18 +2025-03-11T12:43:16.261001,479392996,65232,249,-41.10902595856,-53.32367619012,77.416304167885,2,1,18 +2025-03-11T12:43:16.276626,479392996,65232,249,-41.15143392814,-53.369960285055,77.495110709035,2,1,18 +2025-03-11T12:43:16.292251,479392996,65232,249,-41.20797788758,-53.416268838885,77.597043508525,2,1,18 +2025-03-11T12:43:16.307876,479392996,65232,249,-41.2598098504,-53.46256923975,77.70821189314,2,1,18 +2025-03-11T12:43:16.323501,479392996,65232,249,-41.29279382674,-53.51345810058,77.791644595345,2,1,18 +2025-03-11T12:43:16.339126,479392996,65232,249,-41.33520179632,-53.541257908215,77.851892244235,2,1,18 +2025-03-11T12:43:16.354751,479392996,65232,249,-41.36347377604,-53.578275400605,77.93064136237,2,1,18 +2025-03-11T12:43:16.370376,479392996,65232,249,-41.39174575576,-53.624535036645,77.99556401131,2,1,18 +2025-03-11T12:43:16.386001,479392996,65232,249,-41.42944172872,-53.65694776314,78.065065785325,2,1,18 +2025-03-11T12:43:16.401626,479392996,65232,249,-41.46713770168,-53.698602633285,78.12536227321,2,1,18 +2025-03-11T12:43:16.417251,479392996,65232,249,-41.50483367464,-53.735636431605,78.18101903803,2,1,18 +2025-03-11T12:43:16.432876,479392996,65232,249,-41.53781765098,-53.758798861485,78.218128669585,2,1,18 +2025-03-11T12:43:16.448501,479392996,65232,249,-41.57080162732,-53.763477004065,78.259785324205,2,1,18 +2025-03-11T12:43:16.464126,479392996,65232,249,-41.60378560366,-53.78201836212,78.31536114802,2,1,18 +2025-03-11T12:43:16.479751,479392996,65232,249,-41.63676958,-53.800559720175,78.370936971835,2,1,18 +2025-03-11T12:43:16.495376,479392996,65232,249,-41.6603295631,-53.8190847723,78.41725686751,2,1,18 +2025-03-11T12:43:16.511001,479392996,65232,249,-41.67917754958,-53.842222743285,78.449724972985,2,1,18 +2025-03-11T12:43:16.526626,479392996,65232,249,-41.69802553606,-53.86536071427,78.47295071233,2,1,18 +2025-03-11T12:43:16.542251,479392996,65232,249,-41.71216152592,-53.87924838864,78.49613259067,2,1,18 +2025-03-11T12:43:16.557876,479392996,65232,249,-41.7310095124,-53.88852314415,78.53316625921,2,1,18 +2025-03-11T12:43:16.573501,479392996,65232,249,-41.74514550226,-53.88392653122,78.570137526745,2,1,18 +2025-03-11T12:43:16.589126,479392996,65232,249,-41.7545694955,-53.907048196275,78.60259207021,2,1,18 +2025-03-11T12:43:16.604751,479392996,65232,249,-41.76870548536,-53.920935870645,78.61653158242,2,1,18 +2025-03-11T12:43:16.620376,479392996,65232,249,-41.7545694955,-53.925532483575,78.60266623021,2,1,18 +2025-03-11T12:43:16.636001,479392996,65232,249,-41.75928149212,-53.948645995665,78.593523345085,2,1,18 +2025-03-11T12:43:16.651626,479392996,65232,249,-41.76870548536,-53.930178014295,78.593462747095,2,1,18 +2025-03-11T12:43:16.667251,479392996,65232,249,-41.75928149212,-53.911677421065,78.58875384202,2,1,18 +2025-03-11T12:43:16.682876,479392996,65232,249,-41.7545694955,-53.916290339925,78.579523234885,2,1,18 +2025-03-11T12:43:16.698501,479392996,65232,249,-41.74985749888,-53.911661115135,78.57949791388,2,1,18 +2025-03-11T12:43:16.714126,479392996,65232,249,-41.74985749888,-53.902418971485,78.584082016945,2,1,18 +2025-03-11T12:43:16.729751,479392996,65232,249,-41.74985749888,-53.90704004331,78.574858190815,2,1,18 +2025-03-11T12:43:16.745376,479392996,65232,249,-41.74514550226,-53.91165296217,78.551764034485,2,1,18 +2025-03-11T12:43:16.761001,479392996,65232,249,-41.7310095124,-53.88852314415,78.537787442275,2,1,18 +2025-03-11T12:43:16.776626,479392996,65232,249,-41.72158551916,-53.87002255092,78.491487889615,2,1,18 +2025-03-11T12:43:16.792251,479392996,65232,249,-41.69331353944,-53.856110417655,78.45904330213,2,1,18 +2025-03-11T12:43:16.807876,479392996,65232,249,-41.67917754958,-53.823738455985,78.42654489766,2,1,18 +2025-03-11T12:43:16.823501,479392996,65232,249,-41.6603295631,-53.805221556825,78.384852966055,2,1,18 +2025-03-11T12:43:16.839126,479392996,65232,249,-41.64148157662,-53.795946801315,78.357061663645,2,1,18 +2025-03-11T12:43:16.854751,479392996,65232,249,-41.60849760028,-53.76816329961,78.31069112596,2,1,18 +2025-03-11T12:43:16.870376,479392996,65232,249,-41.57551362394,-53.73575872608,78.25043849908,2,1,18 +2025-03-11T12:43:16.886001,479392996,65232,249,-41.54724164422,-53.712604449165,78.21333564853,2,1,18 +2025-03-11T12:43:16.901626,479392996,65232,249,-41.5189696645,-53.6802080286,78.15771098572,2,1,18 +2025-03-11T12:43:16.917251,479392996,65232,249,-41.4954096814,-53.63857761735,78.092813657785,2,1,18 +2025-03-11T12:43:16.932876,479392996,65232,249,-41.45771370844,-53.60154381903,78.06026280829,2,1,18 +2025-03-11T12:43:16.948501,479392996,65232,249,-41.42001773548,-53.569131092535,77.98613985121,2,1,18 +2025-03-11T12:43:16.964126,479392996,65232,249,-41.38232176252,-53.541339437865,77.907414251065,2,1,18 +2025-03-11T12:43:16.979751,479392996,65232,249,-41.34462578956,-53.49044242407,77.81935358479,2,1,18 +2025-03-11T12:43:16.995376,479392996,65232,249,-41.3069298166,-53.448787553925,77.759057096905,2,1,18 +2025-03-11T12:43:17.011001,479392996,65232,249,-41.27865783688,-53.402527917885,77.68027089877,2,1,18 +2025-03-11T12:43:17.026626,479392996,65232,249,-41.2362498673,-53.35624382295,77.596843174555,2,1,18 +2025-03-11T12:43:17.042251,479392996,65232,249,-41.165569918,-53.31453188205,77.518014487375,2,1,18 +2025-03-11T12:43:17.057876,479392996,65232,249,-41.09960196532,-53.27744916594,77.453074670395,2,1,18 +2025-03-11T12:43:17.073501,479392996,65232,249,-41.0477700025,-53.221906621425,77.35111157191,2,1,18 +2025-03-11T12:43:17.089126,479392996,65232,249,-41.01478602616,-53.17563883242,77.23534912825,2,1,18 +2025-03-11T12:43:17.104751,479392996,65232,249,-40.97237805658,-53.11549152201,77.133381051775,2,1,18 +2025-03-11T12:43:17.120376,479392996,65232,249,-40.91583409714,-53.064561896355,77.03605089535,2,1,18 +2025-03-11T12:43:17.136001,479392996,65232,249,-40.85457814108,-52.99976090226,76.92941597179,2,1,18 +2025-03-11T12:43:17.151626,479392996,65232,249,-40.80745817488,-52.92574222341,76.804279578985,2,1,18 +2025-03-11T12:43:17.167251,479392996,65232,249,-40.73677822558,-52.86554599521,76.697649633415,2,1,18 +2025-03-11T12:43:17.182876,479392996,65232,249,-40.66609827628,-52.80534976701,76.58639850478,2,1,18 +2025-03-11T12:43:17.198501,479392996,65232,249,-40.60955431684,-52.745177997705,76.452061803835,2,1,18 +2025-03-11T12:43:17.214126,479392996,65232,249,-40.53887436754,-52.666497482205,76.317630599875,2,1,18 +2025-03-11T12:43:17.229751,479392996,65232,249,-40.46348242162,-52.592429885565,76.187832337975,2,1,18 +2025-03-11T12:43:17.245376,479392996,65232,249,-40.3880904757,-52.509120145275,76.05337581301,2,1,18 +2025-03-11T12:43:17.261001,479392996,65232,249,-40.3174105264,-52.4350607016,75.92820551518,2,1,18 +2025-03-11T12:43:17.276626,479392996,65232,249,-40.25144257372,-52.356388339065,75.793781092225,2,1,18 +2025-03-11T12:43:17.292251,479392996,65232,249,-40.16662663456,-52.28692550832,75.654745442185,2,1,18 +2025-03-11T12:43:17.307876,479392996,65232,249,-40.07238670216,-52.21282529982,75.506435324005,2,1,18 +2025-03-11T12:43:17.323501,479392996,65232,249,-39.98285876638,-52.129491100635,75.35809490683,2,1,18 +2025-03-11T12:43:17.339126,479392996,65232,249,-39.90275482384,-52.060036422855,75.209823671665,2,1,18 +2025-03-11T12:43:17.354751,479392996,65232,249,-39.82736287792,-51.98134775439,75.024552672985,2,1,18 +2025-03-11T12:43:17.370376,479392996,65232,249,-39.74254693876,-51.87953742087,74.84379659536,2,1,18 +2025-03-11T12:43:17.386001,479392996,65232,249,-39.66715499284,-51.77774339328,74.70464472733,2,1,18 +2025-03-11T12:43:17.401626,479392996,65232,249,-39.57762705706,-51.68978812227,74.537801037895,2,1,18 +2025-03-11T12:43:17.417251,479392996,65232,249,-39.47867512804,-51.615679760805,74.375620589515,2,1,18 +2025-03-11T12:43:17.432876,479392996,65232,249,-39.3750112024,-51.51845788725,74.217961843195,2,1,18 +2025-03-11T12:43:17.448501,479392996,65232,249,-39.27605927338,-51.416623094835,74.037185422555,2,1,18 +2025-03-11T12:43:17.464126,479392996,65232,249,-39.16768335112,-51.32401414014,73.86105370297,2,1,18 +2025-03-11T12:43:17.479751,479392996,65232,249,-39.07815541534,-51.222195653655,73.666427295145,2,1,18 +2025-03-11T12:43:17.495376,479392996,65232,249,-38.97920348632,-51.115739789415,73.467147602245,2,1,18 +2025-03-11T12:43:17.511001,479392996,65232,249,-38.87553956068,-51.00927577221,73.263239945275,2,1,18 +2025-03-11T12:43:17.526626,479392996,65232,249,-38.76716363842,-50.907424673865,73.07782877956,2,1,18 +2025-03-11T12:43:17.542251,479392996,65232,249,-38.65878771616,-50.800952503695,72.88777789078,2,1,18 +2025-03-11T12:43:17.557876,479392996,65232,249,-38.55512379052,-50.699109558315,72.679267590745,2,1,18 +2025-03-11T12:43:17.573501,479392996,65232,249,-38.44203587164,-50.578766019705,72.475290751765,2,1,18 +2025-03-11T12:43:17.589126,479392996,65232,249,-38.32423595614,-50.463035399955,72.266704488715,2,1,18 +2025-03-11T12:43:17.604751,479392996,65232,249,-38.21586003388,-50.33345787066,72.05345498461,2,1,18 +2025-03-11T12:43:17.620376,479392996,65232,249,-38.10748411162,-50.20850141319,71.821739288245,2,1,18 +2025-03-11T12:43:17.636001,479392996,65232,249,-37.9849721995,-50.083520496825,71.608487981125,2,1,18 +2025-03-11T12:43:17.651626,479392996,65232,249,-37.85303629414,-49.95852327453,71.413707844255,2,1,18 +2025-03-11T12:43:17.667251,479392996,65232,249,-37.72110038878,-49.83814712406,71.200461515125,2,1,18 +2025-03-11T12:43:17.682876,479392996,65232,249,-37.60330047328,-49.708553288835,70.98719844901,2,1,18 +2025-03-11T12:43:17.698501,479392996,65232,249,-37.47607656454,-49.592806363155,70.755492708625,2,1,18 +2025-03-11T12:43:17.714126,479392996,65232,249,-37.3488526558,-49.463196222,70.51448898211,2,1,18 +2025-03-11T12:43:17.729751,479392996,65232,249,-37.22162874706,-49.33820715267,70.255019063335,2,1,18 +2025-03-11T12:43:17.745376,479392996,65232,249,-37.08026884846,-49.21781469627,70.004789707675,2,1,18 +2025-03-11T12:43:17.761001,479392996,65232,249,-36.93890894986,-49.07893795257,69.74986500895,2,1,18 +2025-03-11T12:43:17.776626,479392996,65232,249,-36.8069730445,-48.9400775148,69.50881742143,2,1,18 +2025-03-11T12:43:17.792251,479392996,65232,249,-36.68446113238,-48.80123338296,69.27702576205,2,1,18 +2025-03-11T12:43:17.807876,479392996,65232,249,-36.56194922026,-48.648526035645,69.03593611654,2,1,18 +2025-03-11T12:43:17.823501,479392996,65232,249,-36.43472531152,-48.514294822665,68.767186751635,2,1,18 +2025-03-11T12:43:17.839126,479392996,65232,249,-36.2886534163,-48.380030997825,68.50765262884,2,1,18 +2025-03-11T12:43:17.854751,479392996,65232,249,-36.13786952446,-48.23651687637,68.25731701117,2,1,18 +2025-03-11T12:43:17.870376,479392996,65232,249,-35.98708563262,-48.09762382674,67.993136384305,2,1,18 +2025-03-11T12:43:17.886001,479392996,65232,249,-35.84572573402,-47.944883867565,67.71967133332,2,1,18 +2025-03-11T12:43:17.901626,479392996,65232,249,-35.69022984556,-47.792119449495,67.432322390125,2,1,18 +2025-03-11T12:43:17.917251,479392996,65232,249,-35.53944595372,-47.634742112565,67.154204054065,2,1,18 +2025-03-11T12:43:17.932876,479392996,65232,249,-35.37923806864,-47.48196954153,66.8622271468,2,1,18 +2025-03-11T12:43:17.948501,479392996,65232,249,-35.2284541768,-47.3245922046,66.579487627675,2,1,18 +2025-03-11T12:43:17.964126,479392996,65232,249,-35.08238228158,-47.18108623611,66.306052875685,2,1,18 +2025-03-11T12:43:17.979751,479392996,65232,249,-34.92688639312,-47.014458602565,66.023269495555,2,1,18 +2025-03-11T12:43:17.995330,479393000,65229,250,-34.76196651142,-46.852435734915,65.73586991035,2,1,18 +2025-03-11T12:43:18.010955,479393000,65229,250,-34.60175862634,-46.695042092055,65.44849564615,2,1,18 +2025-03-11T12:43:18.026580,479393000,65229,250,-34.44626273788,-46.54689874581,65.151922876825,2,1,18 +2025-03-11T12:43:18.042205,479393000,65229,250,-34.27663085956,-46.38024665337,64.864497970615,2,1,18 +2025-03-11T12:43:18.057830,479393000,65229,250,-34.11642297448,-46.20436872321,64.57242836335,2,1,18 +2025-03-11T12:43:18.073455,479393000,65229,250,-33.96563908264,-46.033128170805,64.2665273089,2,1,18 +2025-03-11T12:43:18.089080,479393000,65229,250,-33.80071920094,-45.861863159505,63.942121179175,2,1,18 +2025-03-11T12:43:18.104705,479393000,65229,250,-33.63108732262,-45.67210570794,63.62225529151,2,1,18 +2025-03-11T12:43:18.120330,479393000,65229,250,-33.45674344768,-45.50082439071,63.30245678284,2,1,18 +2025-03-11T12:43:18.135955,479393000,65229,250,-33.2729755795,-45.3387689112,62.987302975225,2,1,18 +2025-03-11T12:43:18.151580,479393000,65229,250,-33.0844957147,-45.16284206325,62.653602034345,2,1,18 +2025-03-11T12:43:18.167205,479393000,65229,250,-32.8960158499,-44.9869152153,62.32452227653,2,1,18 +2025-03-11T12:43:18.182830,479393000,65229,250,-32.7310959682,-44.80640806035,62.018563799065,2,1,18 +2025-03-11T12:43:18.198455,479393000,65229,250,-32.5661760865,-44.6259009054,61.7126053216,2,1,18 +2025-03-11T12:43:18.214080,479393000,65229,250,-32.38240821832,-44.43611899494,61.369613175595,2,1,18 +2025-03-11T12:43:18.229705,479393000,65229,250,-32.1892163569,-44.26480506585,61.031302810645,2,1,18 +2025-03-11T12:43:18.245330,479393000,65229,250,-32.01016048534,-44.093515595655,60.69301278871,2,1,18 +2025-03-11T12:43:18.260955,479393000,65229,250,-31.83110461378,-43.889878622685,60.345350620645,2,1,18 +2025-03-11T12:43:18.276580,479393000,65229,250,-31.6237767625,-43.69081380375,60.002287489615,2,1,18 +2025-03-11T12:43:18.292205,479393000,65229,250,-31.44472089094,-43.52414540538,59.68250073994,2,1,18 +2025-03-11T12:43:18.307830,479393000,65229,250,-31.2468170329,-43.325096892375,59.334829987855,2,1,18 +2025-03-11T12:43:18.323455,479393000,65229,250,-31.0583371681,-43.121443613475,58.97791189165,2,1,18 +2025-03-11T12:43:18.339080,479393000,65229,250,-30.8698573033,-42.927032478225,58.62565205851,2,1,18 +2025-03-11T12:43:18.354705,479393000,65229,250,-30.67195344526,-42.732605037045,58.26413629723,2,1,18 +2025-03-11T12:43:18.370330,479393000,65229,250,-30.47876158384,-42.53818574883,57.893384950825,2,1,18 +2025-03-11T12:43:18.385955,479393000,65229,250,-30.29499371566,-42.33916169472,57.53187099256,2,1,18 +2025-03-11T12:43:18.401580,479393000,65229,250,-30.10651385086,-42.140129487645,57.165729070225,2,1,18 +2025-03-11T12:43:18.417205,479393000,65229,250,-29.89918599958,-41.94106466871,56.785696474675,2,1,18 +2025-03-11T12:43:18.432830,479393000,65229,250,-29.68243415506,-41.741983543845,56.41951386631,2,1,18 +2025-03-11T12:43:18.448455,479393000,65229,250,-29.48453029702,-41.529071815365,56.05792394503,2,1,18 +2025-03-11T12:43:18.464080,479393000,65229,250,-29.27720244574,-41.316143780955,55.691699278675,2,1,18 +2025-03-11T12:43:18.479705,479393000,65229,250,-29.06987459446,-41.11707896202,55.30704550006,2,1,18 +2025-03-11T12:43:18.495330,479393000,65229,250,-28.85783474656,-40.904142774645,54.92232932044,2,1,18 +2025-03-11T12:43:18.510955,479393000,65229,250,-28.65993088852,-40.69585211799,54.53303084077,2,1,18 +2025-03-11T12:43:18.526580,479393000,65229,250,-28.45260303724,-40.48292408358,54.139079076025,2,1,18 +2025-03-11T12:43:18.542205,479393000,65229,250,-28.2311391961,-40.269971590275,53.763591700525,2,1,18 +2025-03-11T12:43:18.557830,479393000,65229,250,-28.0190993482,-40.043172187425,53.369577534775,2,1,18 +2025-03-11T12:43:18.573455,479393000,65229,250,-27.80234750368,-39.82560677526,52.97559366802,2,1,18 +2025-03-11T12:43:18.589080,479393000,65229,250,-27.58559565916,-39.608041363095,52.5769886182,2,1,18 +2025-03-11T12:43:18.604705,479393000,65229,250,-27.3594198214,-39.38121750135,52.19681765863,2,1,18 +2025-03-11T12:43:18.620330,479393000,65229,250,-27.14266797688,-39.163652089185,51.77972787655,2,1,18 +2025-03-11T12:43:18.635955,479393000,65229,250,-26.93062812898,-38.95995804546,51.37656404467,2,1,18 +2025-03-11T12:43:18.651580,479393000,65229,250,-26.71387628446,-38.73777156147,50.98718282098,2,1,18 +2025-03-11T12:43:18.667205,479393000,65229,250,-26.49241244332,-38.497092637215,50.597720656285,2,1,18 +2025-03-11T12:43:18.682830,479393000,65229,250,-26.25681261232,-38.256389254065,50.17588986712,2,1,18 +2025-03-11T12:43:18.698455,479393000,65229,250,-26.02592477794,-38.038799383005,49.75415855896,2,1,18 +2025-03-11T12:43:18.714080,479393000,65229,250,-25.79974894018,-37.82121766491,49.332434031805,2,1,18 +2025-03-11T12:43:18.729705,479393000,65229,250,-25.57828509904,-37.60364409978,48.892231553395,2,1,18 +2025-03-11T12:43:18.745330,479393000,65229,250,-25.3568212579,-37.376828391,48.470476727245,2,1,18 +2025-03-11T12:43:18.760955,479393000,65229,250,-25.13064542014,-37.13614131378,48.05790186622,2,1,18 +2025-03-11T12:43:18.776580,479393000,65229,250,-24.89975758576,-36.895446083595,47.64532022419,2,1,18 +2025-03-11T12:43:18.792205,479393000,65229,250,-24.66415775476,-36.663984844095,47.214284148895,2,1,18 +2025-03-11T12:43:18.807830,479393000,65229,250,-24.42384592714,-36.437136523455,46.78788101566,2,1,18 +2025-03-11T12:43:18.823455,479393000,65229,250,-24.18353409952,-36.201046059165,46.36606198549,2,1,18 +2025-03-11T12:43:18.839080,479393000,65229,250,-23.94793426852,-35.95572160419,45.921106741,2,1,18 +2025-03-11T12:43:18.854705,479393000,65229,250,-23.71704643414,-35.70116315853,45.485363563645,2,1,18 +2025-03-11T12:43:18.870330,479393000,65229,250,-23.4720226099,-35.465064541275,45.04505302021,2,1,18 +2025-03-11T12:43:18.885955,479393000,65229,250,-23.2364227789,-35.22898222995,44.613998404915,2,1,18 +2025-03-11T12:43:18.901580,479393000,65229,250,-23.0008229479,-34.983657774975,44.178285526555,2,1,18 +2025-03-11T12:43:18.917205,479393000,65229,250,-22.75108712704,-34.73368778928,43.728670215985,2,1,18 +2025-03-11T12:43:18.932830,479393000,65229,250,-22.49663930956,-34.488330722445,43.274445481345,2,1,18 +2025-03-11T12:43:18.948455,479393000,65229,250,-22.25161548532,-34.247611033365,42.81563166565,2,1,18 +2025-03-11T12:43:18.964080,479393000,65229,250,-22.01601565432,-33.98380229109,42.36135989503,2,1,18 +2025-03-11T12:43:18.979705,479393000,65229,250,-21.75685584022,-33.752300286765,41.916426365515,2,1,18 +2025-03-11T12:43:18.995330,479393000,65229,250,-21.50240802274,-33.51618536358,41.462238710875,2,1,18 +2025-03-11T12:43:19.010955,479393000,65229,250,-21.26680819174,-33.24775554948,41.007948400255,2,1,18 +2025-03-11T12:43:19.026580,479393000,65229,250,-21.02649636412,-32.997801869715,40.576831383955,2,1,18 +2025-03-11T12:43:19.042205,479393000,65229,250,-20.7626245534,-32.75242849695,40.10872953811,2,1,18 +2025-03-11T12:43:19.057830,479393000,65229,250,-20.5034647393,-32.502442205325,39.66834303166,2,1,18 +2025-03-11T12:43:19.073455,479393000,65229,250,-20.24901692182,-32.24784299484,39.190975301695,2,1,18 +2025-03-11T12:43:19.089080,479393000,65229,250,-20.00399309758,-31.993260090285,38.72286349987,2,1,18 +2025-03-11T12:43:19.104705,479393000,65229,250,-19.75896927334,-31.734056113905,38.245490791915,2,1,18 +2025-03-11T12:43:19.120330,479393000,65229,250,-19.49980945924,-31.470206606805,37.758836834815,2,1,18 +2025-03-11T12:43:19.135955,479393000,65229,250,-19.22651365528,-31.201711568985,37.304492276155,2,1,18 +2025-03-11T12:43:19.151580,479393000,65229,250,-18.97677783442,-30.937878367815,36.836336613325,2,1,18 +2025-03-11T12:43:19.167205,479393000,65229,250,-18.7129060237,-30.67402070775,36.372781790545,2,1,18 +2025-03-11T12:43:19.182830,479393000,65229,250,-18.46788219946,-30.41481673137,35.881545533395,2,1,18 +2025-03-11T12:43:19.198455,479393000,65229,250,-18.19929839212,-30.15095091834,35.40874156348,2,1,18 +2025-03-11T12:43:19.214080,479393000,65229,250,-17.93071458478,-29.900948320785,34.9313720305,2,1,18 +2025-03-11T12:43:19.229705,479393000,65229,250,-17.66213077744,-29.627840364105,34.44466743139,2,1,18 +2025-03-11T12:43:19.245330,479393000,65229,250,-17.3935469701,-29.35935347925,33.944117823085,2,1,18 +2025-03-11T12:43:19.260955,479393000,65229,250,-17.13909915262,-29.08164890964,33.462036210055,2,1,18 +2025-03-11T12:43:19.276580,479393000,65229,250,-16.8752273419,-28.808549105925,32.979959575015,2,1,18 +2025-03-11T12:43:19.292205,479393000,65229,250,-16.60664353456,-28.54930436472,32.493310595905,2,1,18 +2025-03-11T12:43:19.307830,479393000,65229,250,-16.32863573398,-28.280801173935,31.99274742559,2,1,18 +2025-03-11T12:43:19.323455,479393000,65229,250,-16.06005192664,-28.007693217255,31.49680046035,2,1,18 +2025-03-11T12:43:19.339080,479393000,65229,250,-15.78675612268,-27.73457710761,30.98698316491,2,1,18 +2025-03-11T12:43:19.354705,479393000,65229,250,-15.51346031872,-27.461460997965,30.49565060173,2,1,18 +2025-03-11T12:43:19.370330,479393000,65229,250,-15.24016451476,-27.183723816495,30.01354186468,2,1,18 +2025-03-11T12:43:19.385955,479393000,65229,250,-14.95744471756,-26.91983354457,29.51299045336,2,1,18 +2025-03-11T12:43:19.401580,479393000,65229,250,-14.69357290684,-26.665218028155,29.03098797832,2,1,18 +2025-03-11T12:43:19.417205,479393000,65229,250,-14.43912508936,-26.387513458545,28.55814873142,2,1,18 +2025-03-11T12:43:19.432830,479393000,65229,250,-14.1658292854,-26.10515520525,28.04829435598,2,1,18 +2025-03-11T12:43:19.448455,479393000,65229,250,-13.87839749158,-25.827393564885,27.5153322622,2,1,18 +2025-03-11T12:43:19.464080,479393000,65229,250,-13.59096569776,-25.54038978087,27.02854491907,2,1,18 +2025-03-11T12:43:19.479705,479393000,65229,250,-13.3176698938,-25.25341045575,26.53715673589,2,1,18 +2025-03-11T12:43:19.495330,479393000,65229,250,-13.0349500966,-24.971035896525,26.03653116457,2,1,18 +2025-03-11T12:43:19.510955,479393000,65229,250,-12.76636628926,-24.67482258072,25.517385584005,2,1,18 +2025-03-11T12:43:19.526580,479393000,65229,250,-12.4930704853,-24.39708539925,24.989065016305,2,1,18 +2025-03-11T12:43:19.542205,479393000,65229,250,-12.2103506881,-24.11933191185,24.460730886595,2,1,18 +2025-03-11T12:43:19.557830,479393000,65229,250,-11.93234288752,-23.85544979289,23.95094389015,2,1,18 +2025-03-11T12:43:19.573455,479393000,65229,250,-11.65433508694,-23.577704458455,23.44572245677,2,1,18 +2025-03-11T12:43:19.589080,479393000,65229,250,-11.38103928298,-23.290725133335,22.9266071752,2,1,18 +2025-03-11T12:43:19.604705,479393000,65229,250,-11.1030314824,-23.008358727075,22.42136720182,2,1,18 +2025-03-11T12:43:19.620330,479393000,65229,250,-10.82502368182,-22.72137124899,21.902245139245,2,1,18 +2025-03-11T12:43:19.635955,479393000,65229,250,-10.54230388462,-22.42513347429,21.38770039873,2,1,18 +2025-03-11T12:43:19.651580,479393000,65229,250,-10.2548720908,-22.13350861845,20.850061501885,2,1,18 +2025-03-11T12:43:19.667205,479393000,65229,250,-9.95330430712,-21.84648037554,20.32628435122,2,1,18 +2025-03-11T12:43:19.682830,479393000,65229,250,-9.6423125302,-21.56867797035,19.78866716935,2,1,18 +2025-03-11T12:43:19.698455,479393000,65229,250,-9.34545674314,-21.290900024055,19.251070330495,2,1,18 +2025-03-11T12:43:19.714080,479393000,65229,250,-9.06273694594,-21.003904393005,18.73656266998,2,1,18 +2025-03-11T12:43:19.729705,479393000,65229,250,-8.77530515212,-20.70765846534,18.208147599265,2,1,18 +2025-03-11T12:43:19.745330,479393000,65229,250,-8.50200934816,-20.425300212045,17.69367204076,2,1,18 +2025-03-11T12:43:19.760955,479393000,65229,250,-8.19572956786,-20.133642744345,17.183733118285,2,1,18 +2025-03-11T12:43:19.776580,479393000,65229,250,-7.91300977066,-19.837404969645,16.655324828575,2,1,18 +2025-03-11T12:43:19.792205,479393000,65229,250,-7.62086598022,-19.559635176315,16.11311358766,2,1,18 +2025-03-11T12:43:19.807830,479393000,65229,250,-7.3334341864,-19.249526033175,15.56153698162,2,1,18 +2025-03-11T12:43:19.823455,479393000,65229,250,-7.04600239258,-18.95328010551,15.033121910905,2,1,18 +2025-03-11T12:43:19.839080,479393000,65229,250,-6.76328259538,-18.66628447446,14.50012951813,2,1,18 +2025-03-11T12:43:19.854705,479393000,65229,250,-6.47113880494,-18.374651465655,13.967105023345,2,1,18 +2025-03-11T12:43:19.870330,479393000,65229,250,-6.18370701112,-18.07840553799,13.46641705102,2,1,18 +2025-03-11T12:43:19.885955,479393000,65229,250,-5.90098721392,-17.77292561964,12.92872931518,2,1,18 +2025-03-11T12:43:19.901580,479393000,65229,250,-5.60413142686,-17.476663386045,12.38643713326,2,1,18 +2025-03-11T12:43:19.917205,479393000,65229,250,-5.3072756398,-17.194264367925,11.85344293747,2,1,18 +2025-03-11T12:43:19.932830,479393000,65229,250,-5.0245558426,-16.90264766505,11.3065684555,2,1,18 +2025-03-11T12:43:19.948455,479393000,65229,250,-4.72770005554,-16.606385431455,10.768897456645,2,1,18 +2025-03-11T12:43:19.964080,479393000,65229,250,-4.44026826172,-16.31013950379,10.2312400198,2,1,18 +2025-03-11T12:43:19.979705,479393000,65229,250,-4.13870047804,-16.027732332705,9.67513312768,2,1,18 +2025-03-11T12:43:19.995330,479393000,65229,250,-3.83713269436,-15.740704089795,9.142113610885,2,1,18 +2025-03-11T12:43:20.010955,479393000,65229,250,-3.55441289716,-15.43060309962,8.61827088424,2,1,18 +2025-03-11T12:43:20.026580,479393000,65229,250,-3.24813311686,-15.12046134462,8.071288337245,2,1,18 +2025-03-11T12:43:20.042205,479393000,65229,250,-2.9512773298,-14.824199111025,7.52437497226,2,1,18 +2025-03-11T12:43:20.057830,479393000,65229,250,-2.65913353936,-14.52332395857,6.991313397475,2,1,18 +2025-03-11T12:43:20.073455,479393000,65229,250,-2.35756575568,-14.213190356535,6.45820118068,2,1,18 +2025-03-11T12:43:20.089080,479393000,65229,250,-2.07013396186,-13.91694442887,5.90668019464,2,1,18 +2025-03-11T12:43:20.104705,479393000,65229,250,-1.78270216804,-13.62531957303,5.3551777486,2,1,18 +2025-03-11T12:43:20.120330,479393000,65229,250,-1.48113438436,-13.32904918647,4.840605884065,2,1,18 +2025-03-11T12:43:20.135955,479393000,65229,250,-1.17956660068,-13.037399871735,4.293704278075,2,1,18 +2025-03-11T12:43:20.151580,479393000,65229,250,-0.877998817,-12.75499270065,3.77918803354,2,1,18 +2025-03-11T12:43:20.167205,479393000,65229,250,-0.58585502656,-12.454117548195,3.23226290956,2,1,18 +2025-03-11T12:43:20.182830,479393000,65229,250,-0.2889992395,-12.1578553146,2.676107178445,2,1,18 +2025-03-11T12:43:20.198455,479393000,65229,250,0.00785654755999987,-11.861593081005,2.124572630395,2,1,18 +2025-03-11T12:43:20.214080,479393000,65229,250,0.30942433124,-11.55145947897,1.577596864405,2,1,18 +2025-03-11T12:43:20.229705,479393000,65229,250,0.6062801183,-11.245955101725,1.03988878555,2,1,18 +2025-03-11T12:43:20.245330,479393000,65229,250,0.8889999155,-10.940475183375,0.479095134385,2,1,18 +2025-03-11T12:43:20.260955,479393000,65229,250,1.19056769918,-10.63958372499,-0.0632223685400004,2,1,18 +2025-03-11T12:43:20.276580,479393000,65229,250,1.5015594761,-10.338675960675,-0.614795799605,2,1,18 +2025-03-11T12:43:20.292205,479393000,65229,250,1.8078392564,-10.019292062025,-1.1618154266,2,1,18 +2025-03-11T12:43:20.307830,479393000,65229,250,2.09998304684,-9.72765905322,-1.713324653645,2,1,18 +2025-03-11T12:43:20.323455,479393000,65229,250,2.40155083052,-9.426767594835,-2.241778607375,2,1,18 +2025-03-11T12:43:20.339080,479393000,65229,250,2.7031186142,-9.1351182801,-2.76557429804,2,1,18 +2025-03-11T12:43:20.354705,479393000,65229,250,2.99997440126,-8.829613902855,-3.32638829222,2,1,18 +2025-03-11T12:43:20.370330,479393000,65229,250,3.30154218494,-8.524101372645,-3.887209067405,2,1,18 +2025-03-11T12:43:20.385955,479393000,65229,250,3.60782196524,-8.22782283312,-4.4341359944,2,1,18 +2025-03-11T12:43:20.401580,479393000,65229,250,3.9046777523,-7.922318455875,-4.971844073255,2,1,18 +2025-03-11T12:43:20.417205,479393000,65229,250,4.2109575326,-7.639903131825,-5.51871538025,2,1,18 +2025-03-11T12:43:20.432830,479393000,65229,250,4.51252531628,-7.352874888915,-6.0840831785,2,1,18 +2025-03-11T12:43:20.448455,479393000,65229,250,4.80466910672,-7.04275759281,-6.63104538248,2,1,18 +2025-03-11T12:43:20.464080,479393000,65229,250,5.10152489378,-6.737253215565,-7.18261701053,2,1,18 +2025-03-11T12:43:20.479705,479393000,65229,250,5.39838068084,-6.445612053795,-7.74337538471,2,1,18 +2025-03-11T12:43:20.495330,479393000,65229,250,5.70937245776,-6.12622000218,-8.285780609645,2,1,18 +2025-03-11T12:43:20.510955,479393000,65229,250,6.01565223806,-5.829941462655,-8.81422280438,2,1,18 +2025-03-11T12:43:20.526580,479393000,65229,250,6.32193201836,-5.52442077948,-9.36580799444,2,1,18 +2025-03-11T12:43:20.542205,479393000,65229,250,6.6140758088,-5.223545627025,-9.908111935355,2,1,18 +2025-03-11T12:43:20.557830,479393000,65229,250,6.90150760262,-4.92729969936,-10.450390555265,2,1,18 +2025-03-11T12:43:20.573455,479393000,65229,250,7.19836338968,-4.640279609415,-11.00650920638,2,1,18 +2025-03-11T12:43:20.589080,479393000,65229,250,7.49993117336,-4.33938815103,-11.5626902585,2,1,18 +2025-03-11T12:43:20.604705,479393000,65229,250,7.80149895704,-4.047738836295,-12.10034949836,2,1,18 +2025-03-11T12:43:20.620330,479393000,65229,250,8.09364274748,-3.75610582749,-12.642616359275,2,1,18 +2025-03-11T12:43:20.635955,479393000,65229,250,8.39992252778,-3.450585144315,-13.18958036627,2,1,18 +2025-03-11T12:43:20.651580,479393000,65229,250,8.70149031146,-3.145072614105,-13.70881049387,2,1,18 +2025-03-11T12:43:20.667205,479393000,65229,250,9.00777009176,-2.83955193093,-14.255774500865,2,1,18 +2025-03-11T12:43:20.682830,479393000,65229,250,9.29048988896,-2.54331415623,-14.81653107203,2,1,18 +2025-03-11T12:43:20.698455,479393000,65229,250,9.57792168278,-2.256310372215,-15.363393795005,2,1,18 +2025-03-11T12:43:20.714080,479393000,65229,250,9.87477746984,-1.946184923145,-15.887256864665,2,1,18 +2025-03-11T12:43:20.729705,479393000,65229,250,10.17634525352,-1.649914536585,-16.43879819372,2,1,18 +2025-03-11T12:43:20.745330,479393000,65229,250,10.46848904396,-1.33979724048,-16.981139214635,2,1,18 +2025-03-11T12:43:20.760955,479393000,65229,250,10.7606328344,-1.038922088025,-17.509579606355,2,1,18 +2025-03-11T12:43:20.776580,479393000,65229,250,11.05277662484,-0.75653122287,-18.0610517534,2,1,18 +2025-03-11T12:43:20.792205,479393000,65229,250,11.35434440852,-0.455639764485,-18.621853988585,2,1,18 +2025-03-11T12:43:20.807830,479393000,65229,250,11.65120019558,-0.15013538724,-19.15956206744,2,1,18 +2025-03-11T12:43:20.823455,479393000,65229,250,11.95276797926,0.13689285567,-19.68796040117,2,1,18 +2025-03-11T12:43:20.839080,479393000,65229,250,12.2449117697,0.4331469363,-20.211761069825,2,1,18 +2025-03-11T12:43:20.854705,479393000,65229,250,12.53705556014,0.72015887328,-20.749388207675,2,1,18 +2025-03-11T12:43:20.870330,479393000,65229,250,12.81977535734,1.00715450433,-21.25465350206,2,1,18 +2025-03-11T12:43:20.885955,479393000,65229,250,13.12134314102,1.29418274724,-21.77380946966,2,1,18 +2025-03-11T12:43:20.901580,479393000,65229,250,13.4229109247,1.58121099015,-22.316071352585,2,1,18 +2025-03-11T12:43:20.917205,479393000,65229,250,13.7056307219,1.872827693025,-22.83983991923,2,1,18 +2025-03-11T12:43:20.932830,479393000,65229,250,13.99777451234,2.18294498913,-23.38680212321,2,1,18 +2025-03-11T12:43:20.948455,479393000,65229,250,14.27578231292,2.479174610865,-23.91058244885,2,1,18 +2025-03-11T12:43:20.964080,479393000,65229,250,14.55850211012,2.766170241915,-24.43895365856,2,1,18 +2025-03-11T12:43:20.979705,479393000,65229,250,14.85064590056,3.043940035245,-24.962680167215,2,1,18 +2025-03-11T12:43:20.995330,479393000,65229,250,15.142789691,3.330951972225,-25.48644375587,2,1,18 +2025-03-11T12:43:21.010955,479393000,65229,250,15.43493348144,3.636448196505,-26.028766236785,2,1,18 +2025-03-11T12:43:21.026580,479393000,65229,250,15.7317892685,3.928089358275,-26.561797512575,2,1,18 +2025-03-11T12:43:21.042205,479393000,65229,250,16.02864505556,4.21510944822,-27.076325516105,2,1,18 +2025-03-11T12:43:21.057830,479393000,65229,250,16.31136485276,4.515968294745,-27.586267613555,2,1,18 +2025-03-11T12:43:21.073455,479393000,65229,250,16.59879664658,4.81221422241,-28.11468268427,2,1,18 +2025-03-11T12:43:21.089080,479393000,65229,250,16.89094043702,5.094605087565,-28.638427732925,2,1,18 +2025-03-11T12:43:21.104705,479393000,65229,250,17.17837223084,5.367745656105,-29.152886554445,2,1,18 +2025-03-11T12:43:21.120330,479393000,65229,250,17.45638003142,5.668596349665,-29.676685420085,2,1,18 +2025-03-11T12:43:21.135955,479393000,65229,250,17.71553984552,5.96479335954,-30.218923353965,2,1,18 +2025-03-11T12:43:21.151580,479393000,65229,250,18.00297163934,6.25641821538,-30.74731988468,2,1,18 +2025-03-11T12:43:21.167205,479393000,65229,250,18.31867541288,6.543470917185,-31.266496195295,2,1,18 +2025-03-11T12:43:21.182830,479393000,65229,250,18.59668321346,6.82121625162,-31.771717628675,2,1,18 +2025-03-11T12:43:21.198455,479393000,65229,250,18.86055502418,7.103558198985,-32.290800808235,2,1,18 +2025-03-11T12:43:21.214080,479393000,65229,250,19.147986818,7.385940911175,-32.80067552669,2,1,18 +2025-03-11T12:43:21.229705,479393000,65229,250,19.4307066152,7.67755761405,-33.31982291027,2,1,18 +2025-03-11T12:43:21.245330,479393000,65229,250,19.70871441578,7.973787235785,-33.838982052845,2,1,18 +2025-03-11T12:43:21.260955,479393000,65229,250,19.9961462096,8.2607910198,-34.335011762105,2,1,18 +2025-03-11T12:43:21.276580,479393000,65229,250,20.27415401018,8.538536354235,-34.83561201242,2,1,18 +2025-03-11T12:43:21.292205,479393000,65229,250,20.54273781752,8.820886454565,-35.354701972985,2,1,18 +2025-03-11T12:43:21.307830,479393000,65229,250,20.83488160796,9.080171960595,-35.864490772445,2,1,18 +2025-03-11T12:43:21.323455,479393000,65229,250,21.11760140516,9.348683304345,-36.3604395407,2,1,18 +2025-03-11T12:43:21.339080,479393000,65229,250,21.40032120236,9.61257357627,-36.874854501215,2,1,18 +2025-03-11T12:43:21.354705,479393000,65229,250,21.6689050097,9.8949236766,-37.38470209565,2,1,18 +2025-03-11T12:43:21.370330,479393000,65229,250,21.93748881704,10.181894848755,-37.885325863955,2,1,18 +2025-03-11T12:43:21.385955,479393000,65229,250,22.21549661762,10.45964018319,-38.37668374814,2,1,18 +2025-03-11T12:43:21.401580,479393000,65229,250,22.49821641482,10.742014742415,-38.863445770265,2,1,18 +2025-03-11T12:43:21.417205,479393000,65229,250,22.7762242154,11.005896861375,-39.368611583645,2,1,18 +2025-03-11T12:43:21.432830,479393000,65229,250,23.04009602612,11.26051237779,-39.878341157075,2,1,18 +2025-03-11T12:43:21.448455,479393000,65229,250,23.32281582332,11.53826586519,-40.37432700533,2,1,18 +2025-03-11T12:43:21.464080,479393000,65229,250,23.58197563742,11.81135751594,-40.86101804243,2,1,18 +2025-03-11T12:43:21.479705,479393000,65229,250,23.84113545152,12.06596487939,-41.36611965179,2,1,18 +2025-03-11T12:43:21.495330,479393000,65229,250,24.11443125548,12.35294420451,-41.862129018035,2,1,18 +2025-03-11T12:43:21.510955,479393000,65229,250,24.38772705944,12.62143924233,-42.33957949202,2,1,18 +2025-03-11T12:43:21.526580,479393000,65229,250,24.65159887016,12.876054758745,-42.844687882385,2,1,18 +2025-03-11T12:43:21.542205,479393000,65229,250,24.9201826775,13.130678428125,-43.33593950456,2,1,18 +2025-03-11T12:43:21.557830,479393000,65229,250,25.17463049498,13.40376192591,-43.804139028395,2,1,18 +2025-03-11T12:43:21.573455,479393000,65229,250,25.4385023057,13.667619585975,-44.286178583435,2,1,18 +2025-03-11T12:43:21.589080,479393000,65229,250,25.71651010628,13.93612277676,-44.763635838425,2,1,18 +2025-03-11T12:43:21.604705,479393000,65229,250,25.97095792376,14.218448418195,-45.23187244226,2,1,18 +2025-03-11T12:43:21.620330,479393000,65229,250,26.22069374462,14.48690269119,-45.70928901122,2,1,18 +2025-03-11T12:43:21.635955,479393000,65229,250,26.48927755196,14.727663145095,-46.163515548875,2,1,18 +2025-03-11T12:43:21.651580,479393000,65229,250,26.75314936268,14.97303651786,-46.62237502859,2,1,18 +2025-03-11T12:43:21.667205,479393000,65229,250,27.02644516664,15.23228941203,-47.11365197177,2,1,18 +2025-03-11T12:43:21.682830,479393000,65229,250,27.2761809875,15.4961226132,-47.604913549925,2,1,18 +2025-03-11T12:43:21.698455,479393000,65229,250,27.53062880498,15.75534289551,-48.06381508763,2,1,18 +2025-03-11T12:43:21.714080,479393000,65229,250,27.78507662246,16.00532103417,-48.5273007284,2,1,18 +2025-03-11T12:43:21.729705,479393000,65229,250,28.02538845008,16.264516857585,-49.000045472285,2,1,18 +2025-03-11T12:43:21.745330,479393000,65229,250,28.27041227432,16.542205121265,-49.463628791045,2,1,18 +2025-03-11T12:43:21.760955,479393000,65229,250,28.52014809518,16.80141725061,-49.91790236468,2,1,18 +2025-03-11T12:43:21.776580,479393000,65229,250,28.76988391604,17.051387236305,-50.362896492185,2,1,18 +2025-03-11T12:43:21.792205,479393000,65229,250,29.01490774028,17.292106925385,-50.82171030788,2,1,18 +2025-03-11T12:43:21.807830,479393000,65229,250,29.2552195679,17.546681676975,-51.275951779505,2,1,18 +2025-03-11T12:43:21.823455,479393000,65229,250,29.50024339214,17.79202243788,-51.72554176907,2,1,18 +2025-03-11T12:43:21.839080,479393000,65229,250,29.75469120962,18.03275843289,-52.175126780645,2,1,18 +2025-03-11T12:43:21.854705,479393000,65229,250,30.00442703048,18.282728418585,-52.597014992825,2,1,18 +2025-03-11T12:43:21.870330,479393000,65229,250,30.27772283444,18.50963380998,-53.04657150842,2,1,18 +2025-03-11T12:43:21.885955,479393000,65229,250,30.51803466206,18.75496641792,-53.482291167785,2,1,18 +2025-03-11T12:43:21.901580,479393000,65229,250,30.73007450996,18.995629036245,-53.941057516445,2,1,18 +2025-03-11T12:43:21.917205,479393000,65229,250,30.96567434096,19.236332419395,-54.376751854805,2,1,18 +2025-03-11T12:43:21.932830,479393000,65229,250,31.20598616858,19.481665027335,-54.81247151417,2,1,18 +2025-03-11T12:43:21.948455,479393000,65229,250,31.45100999282,19.731626860065,-55.234352945345,2,1,18 +2025-03-11T12:43:21.964080,479393000,65229,250,31.69132182044,19.976959468005,-55.674693787775,2,1,18 +2025-03-11T12:43:21.979705,479393000,65229,250,31.9410576413,20.194581950925,-56.105694586085,2,1,18 +2025-03-11T12:43:21.995300,479393004,65227,251,32.1766574723,20.416801046775,-56.513587666055,2,1,18 +2025-03-11T12:43:22.010925,479393004,65227,251,32.40754530668,20.643633061485,-56.95846196954,2,1,18 +2025-03-11T12:43:22.026550,479393004,65227,251,32.65256913092,20.87973167874,-57.37566659765,2,1,18 +2025-03-11T12:43:22.042175,479393004,65227,251,32.87403297206,21.120410602995,-57.802098226865,2,1,18 +2025-03-11T12:43:22.057800,479393004,65227,251,33.10492080644,21.356484761355,-58.22852487809,2,1,18 +2025-03-11T12:43:22.073425,479393004,65227,251,33.31696065434,21.583284164205,-58.645644959165,2,1,18 +2025-03-11T12:43:22.089050,479393004,65227,251,33.55256048534,21.82860861918,-59.044388373005,2,1,18 +2025-03-11T12:43:22.104675,479393004,65227,251,33.78344831972,22.04619849024,-59.45225613197,2,1,18 +2025-03-11T12:43:22.120300,479393004,65227,251,33.990776171,22.245263309175,-59.855394642845,2,1,18 +2025-03-11T12:43:22.135925,479393004,65227,251,34.21695200876,22.467466099095,-60.28638007613,2,1,18 +2025-03-11T12:43:22.151550,479393004,65227,251,34.4384158499,22.694281807875,-60.69889253615,2,1,18 +2025-03-11T12:43:22.167175,479393004,65227,251,34.6504556978,22.930323354375,-61.097564964965,2,1,18 +2025-03-11T12:43:22.182800,479393004,65227,251,34.87191953894,23.15251799133,-61.491574152725,2,1,18 +2025-03-11T12:43:22.198425,479393004,65227,251,35.09338338008,23.365470484635,-61.885546260485,2,1,18 +2025-03-11T12:43:22.214050,479393004,65227,251,35.3101352246,23.57379375315,-62.274871864175,2,1,18 +2025-03-11T12:43:22.229675,479393004,65227,251,35.54102305898,23.79138362421,-62.659633707815,2,1,18 +2025-03-11T12:43:22.245300,479393004,65227,251,35.7577749035,23.990464749075,-63.05354341457,2,1,18 +2025-03-11T12:43:22.260925,479393004,65227,251,35.9698147514,24.20340093645,-63.44750196032,2,1,18 +2025-03-11T12:43:22.276550,479393004,65227,251,36.18656659592,24.43482956409,-63.823056714815,2,1,18 +2025-03-11T12:43:22.292175,479393004,65227,251,36.39860644382,24.64314467964,-64.207754354435,2,1,18 +2025-03-11T12:43:22.307800,479393004,65227,251,36.6059342951,24.851451642225,-64.59244521305,2,1,18 +2025-03-11T12:43:22.323425,479393004,65227,251,36.80383815314,25.055121227055,-64.95399805433,2,1,18 +2025-03-11T12:43:22.339050,479393004,65227,251,37.01116600442,25.258807117815,-65.33404918988,2,1,18 +2025-03-11T12:43:22.354675,479393004,65227,251,37.20435786584,25.467089621505,-65.71871970548,2,1,18 +2025-03-11T12:43:22.370300,479393004,65227,251,37.40226172388,25.661517062685,-66.094099015955,2,1,18 +2025-03-11T12:43:22.385925,479393004,65227,251,37.60487757854,25.88367908778,-66.45573279824,2,1,18 +2025-03-11T12:43:22.401550,479393004,65227,251,37.8074934332,26.059630394625,-66.807938814395,2,1,18 +2025-03-11T12:43:22.417175,479393004,65227,251,38.01482128448,26.24021092626,-67.187897249945,2,1,18 +2025-03-11T12:43:22.432800,479393004,65227,251,38.22214913576,26.439275745195,-67.53558156404,2,1,18 +2025-03-11T12:43:22.448425,479393004,65227,251,38.41062900056,26.62906580862,-67.87858049105,2,1,18 +2025-03-11T12:43:22.464050,479393004,65227,251,38.5849728755,26.832694628625,-68.230857061175,2,1,18 +2025-03-11T12:43:22.479675,479393004,65227,251,38.7734527403,27.02248469205,-68.583098354315,2,1,18 +2025-03-11T12:43:22.495300,479393004,65227,251,38.97135659834,27.221533205055,-68.91228437414,2,1,18 +2025-03-11T12:43:22.510925,479393004,65227,251,39.16454845976,27.420573565095,-69.255327162155,2,1,18 +2025-03-11T12:43:22.526550,479393004,65227,251,39.34831632794,27.61497654738,-69.593716665095,2,1,18 +2025-03-11T12:43:22.542175,479393004,65227,251,39.53208419612,27.790895242365,-69.932032008035,2,1,18 +2025-03-11T12:43:22.557800,479393004,65227,251,39.72056406092,27.957579946665,-70.27955941811,2,1,18 +2025-03-11T12:43:22.573425,479393004,65227,251,39.90904392572,28.14737001009,-70.617937162055,2,1,18 +2025-03-11T12:43:22.589050,479393004,65227,251,40.07396380742,28.323256093215,-70.956225380975,2,1,18 +2025-03-11T12:43:22.604675,479393004,65227,251,40.24830768236,28.49915848227,-71.276042429645,2,1,18 +2025-03-11T12:43:22.620300,479393004,65227,251,40.43207555054,28.67969824908,-71.595891580325,2,1,18 +2025-03-11T12:43:22.635925,479393004,65227,251,40.6111314221,28.850987719275,-71.91569687,2,1,18 +2025-03-11T12:43:22.651550,479393004,65227,251,40.78547529704,29.02689010833,-72.23551391867,2,1,18 +2025-03-11T12:43:22.667175,479393004,65227,251,40.95510717536,29.207405416245,-72.555342726335,2,1,18 +2025-03-11T12:43:22.682800,479393004,65227,251,41.12473905368,29.38792072416,-72.870550350935,2,1,18 +2025-03-11T12:43:22.698425,479393004,65227,251,41.29908292862,29.563823113215,-73.16726148428,2,1,18 +2025-03-11T12:43:22.714050,479393004,65227,251,41.47813880018,29.74435472706,-73.477861487825,2,1,18 +2025-03-11T12:43:22.729675,479393004,65227,251,41.65719467174,29.906402053605,-73.783766148305,2,1,18 +2025-03-11T12:43:22.745300,479393004,65227,251,41.82211455344,30.06380384943,-74.08963192577,2,1,18 +2025-03-11T12:43:22.760925,479393004,65227,251,41.96818644866,30.22579410522,-74.39086793615,2,1,18 +2025-03-11T12:43:22.776550,479393004,65227,251,42.10954634726,30.397018351695,-74.682891879395,2,1,18 +2025-03-11T12:43:22.792175,479393004,65227,251,42.27917822558,30.54980722866,-74.970261165605,2,1,18 +2025-03-11T12:43:22.807800,479393004,65227,251,42.43467411404,30.70257164673,-75.23912537654,2,1,18 +2025-03-11T12:43:22.823425,479393004,65227,251,42.58545800588,30.864570055485,-75.521883435665,2,1,18 +2025-03-11T12:43:22.839050,479393004,65227,251,42.74566589096,31.021963698345,-75.800015333735,2,1,18 +2025-03-11T12:43:22.854675,479393004,65227,251,42.89173778618,31.17933288231,-76.064263339595,2,1,18 +2025-03-11T12:43:22.870300,479393004,65227,251,43.0378096814,31.327459922625,-76.32385308239,2,1,18 +2025-03-11T12:43:22.885925,479393004,65227,251,43.18388157662,31.46634481929,-76.611132843575,2,1,18 +2025-03-11T12:43:22.901550,479393004,65227,251,43.3440894617,31.609875246675,-76.879966755515,2,1,18 +2025-03-11T12:43:22.917175,479393004,65227,251,43.49016135692,31.77648657429,-77.162736573635,2,1,18 +2025-03-11T12:43:22.932800,479393004,65227,251,43.63152125552,31.92460546164,-77.431561901555,2,1,18 +2025-03-11T12:43:22.948425,479393004,65227,251,43.77759315074,32.05886928648,-77.695717207415,2,1,18 +2025-03-11T12:43:22.964050,479393004,65227,251,43.9330890392,32.188528345425,-77.932140436895,2,1,18 +2025-03-11T12:43:22.979675,479393004,65227,251,44.08387293104,32.336663538705,-78.19635814376,2,1,18 +2025-03-11T12:43:22.995300,479393004,65227,251,44.22052083302,32.470911057615,-78.465121070675,2,1,18 +2025-03-11T12:43:23.010925,479393004,65227,251,44.34774474176,32.605142270595,-78.692279787995,2,1,18 +2025-03-11T12:43:23.026550,479393004,65227,251,44.47968064712,32.74862378019,-78.924103549385,2,1,18 +2025-03-11T12:43:23.042175,479393004,65227,251,44.61161655248,32.882863146135,-79.1789961461,2,1,18 +2025-03-11T12:43:23.057800,479393004,65227,251,44.74355245784,33.01710251208,-79.42926755975,2,1,18 +2025-03-11T12:43:23.073425,479393004,65227,251,44.8754883632,33.15596294985,-79.656451598075,2,1,18 +2025-03-11T12:43:23.089050,479393004,65227,251,44.9932882787,33.28093571325,-79.892802039515,2,1,18 +2025-03-11T12:43:23.104675,479393004,65227,251,45.1110881942,33.396666333,-80.119873034825,2,1,18 +2025-03-11T12:43:23.120300,479393004,65227,251,45.24302409956,33.51704248347,-80.34698291315,2,1,18 +2025-03-11T12:43:23.135925,479393004,65227,251,45.37496000492,33.642039705765,-80.56949014841,2,1,18 +2025-03-11T12:43:23.151550,479393004,65227,251,45.49275992042,33.75314925369,-80.77805787146,2,1,18 +2025-03-11T12:43:23.167175,479393004,65227,251,45.61527183254,33.868888026405,-80.986650915515,2,1,18 +2025-03-11T12:43:23.182800,479393004,65227,251,45.71422376156,33.97996496247,-81.213676246805,2,1,18 +2025-03-11T12:43:23.198425,479393004,65227,251,45.82259968382,34.091058204465,-81.43609395704,2,1,18 +2025-03-11T12:43:23.214050,479393004,65227,251,45.93097560608,34.197530374635,-81.630766028885,2,1,18 +2025-03-11T12:43:23.229675,479393004,65227,251,46.0534875182,34.31326914735,-81.807010791485,2,1,18 +2025-03-11T12:43:23.245300,479393004,65227,251,46.15715144384,34.43359638003,-82.010974068455,2,1,18 +2025-03-11T12:43:23.260925,479393004,65227,251,46.27023936272,34.540076703165,-82.21027410437,2,1,18 +2025-03-11T12:43:23.276550,479393004,65227,251,46.37861528498,34.646548873335,-82.39108262702,2,1,18 +2025-03-11T12:43:23.292175,479393004,65227,251,46.477567214,34.74838366575,-82.567237864595,2,1,18 +2025-03-11T12:43:23.307800,479393004,65227,251,46.58594313626,34.850234764095,-82.757270213375,2,1,18 +2025-03-11T12:43:23.323425,479393004,65227,251,46.69903105514,34.952094015405,-82.942688160095,2,1,18 +2025-03-11T12:43:23.339050,479393004,65227,251,46.80269498078,35.044694817135,-83.128055464805,2,1,18 +2025-03-11T12:43:23.354675,479393004,65227,251,46.88279892332,35.13725485404,-83.29490413223,2,1,18 +2025-03-11T12:43:23.370300,479393004,65227,251,46.98646284896,35.22061351212,-83.475613173875,2,1,18 +2025-03-11T12:43:23.385925,479393004,65227,251,47.07599078474,35.29932663948,-83.64241978331,2,1,18 +2025-03-11T12:43:23.401550,479393004,65227,251,47.15609472728,35.391886676385,-83.800026084605,2,1,18 +2025-03-11T12:43:23.417175,479393004,65227,251,47.25033465968,35.493713315835,-83.976174541175,2,1,18 +2025-03-11T12:43:23.432800,479393004,65227,251,47.34457459208,35.586297811635,-84.14766473468,2,1,18 +2025-03-11T12:43:23.448425,479393004,65227,251,47.419966538,35.6834707674,-84.28679806271,2,1,18 +2025-03-11T12:43:23.464050,479393004,65227,251,47.50478247716,35.743691454495,-84.42579663275,2,1,18 +2025-03-11T12:43:23.479675,479393004,65227,251,47.57546242646,35.813129826345,-84.592539038165,2,1,18 +2025-03-11T12:43:23.495300,479393004,65227,251,47.66027836562,35.887213728915,-84.750077960465,2,1,18 +2025-03-11T12:43:23.510925,479393004,65227,251,47.74509430478,35.961297631485,-84.889132150505,2,1,18 +2025-03-11T12:43:23.526550,479393004,65227,251,47.8204862507,36.03998629995,-85.01432776934,2,1,18 +2025-03-11T12:43:23.542175,479393004,65227,251,47.8911662,36.114045743625,-85.15798279943,2,1,18 +2025-03-11T12:43:23.557800,479393004,65227,251,47.96655814592,36.206597627565,-85.28785522133,2,1,18 +2025-03-11T12:43:23.573425,479393004,65227,251,48.04195009184,36.29452843968,-85.39922437097,2,1,18 +2025-03-11T12:43:23.589050,479393004,65227,251,48.10791804452,36.373200802215,-85.524406427795,2,1,18 +2025-03-11T12:43:23.604675,479393004,65227,251,48.16917400058,36.41951750901,-85.640209557485,2,1,18 +2025-03-11T12:43:23.620300,479393004,65227,251,48.22571796002,36.47506820649,-85.75604298617,2,1,18 +2025-03-11T12:43:23.635925,479393004,65227,251,48.2916859127,36.526014138075,-85.862629070735,2,1,18 +2025-03-11T12:43:23.651550,479393004,65227,251,48.35294186876,36.604678347645,-85.950834882035,2,1,18 +2025-03-11T12:43:23.667175,479393004,65227,251,48.41419782482,36.664858269915,-86.06207244866,2,1,18 +2025-03-11T12:43:23.682800,479393004,65227,251,48.46602978764,36.715779742605,-86.17788055634,2,1,18 +2025-03-11T12:43:23.698425,479393004,65227,251,48.51314975384,36.762071990505,-86.26131506156,2,1,18 +2025-03-11T12:43:23.714050,479393004,65227,251,48.55555772342,36.80835608544,-86.35860633497,2,1,18 +2025-03-11T12:43:23.729675,479393004,65227,251,48.6215256761,36.850059873375,-86.4697765226,2,1,18 +2025-03-11T12:43:23.745300,479393004,65227,251,48.6686456423,36.89173104945,-86.55319248782,2,1,18 +2025-03-11T12:43:23.760925,479393004,65227,251,48.7157656085,36.933402225525,-86.622744903845,2,1,18 +2025-03-11T12:43:23.776550,479393004,65227,251,48.7628855747,36.988936617075,-86.71083767213,2,1,18 +2025-03-11T12:43:23.792175,479393004,65227,251,48.80529354428,37.04446285566,-86.78968129328,2,1,18 +2025-03-11T12:43:23.807800,479393004,65227,251,48.833565524,37.086101419875,-86.84534303609,2,1,18 +2025-03-11T12:43:23.823425,479393004,65227,251,48.87126149696,37.104650930895,-86.91941037317,2,1,18 +2025-03-11T12:43:23.839050,479393004,65227,251,48.91366946654,37.137071810355,-86.993540111255,2,1,18 +2025-03-11T12:43:23.854675,479393004,65227,251,48.94665344288,37.178718527535,-87.063072184265,2,1,18 +2025-03-11T12:43:23.870300,479393004,65227,251,48.98434941584,37.215752325855,-87.118728949085,2,1,18 +2025-03-11T12:43:23.885925,479393004,65227,251,49.03146938204,37.25742350193,-87.19752373124,2,1,18 +2025-03-11T12:43:23.901550,479393004,65227,251,49.05974136176,37.28519885067,-87.257751037115,2,1,18 +2025-03-11T12:43:23.917175,479393004,65227,251,49.08330134486,37.29910283097,-87.299431209725,2,1,18 +2025-03-11T12:43:23.932800,479393004,65227,251,49.11157332458,37.33612032336,-87.345832046405,2,1,18 +2025-03-11T12:43:23.948425,479393004,65227,251,49.13042131106,37.359258294345,-87.38754251801,2,1,18 +2025-03-11T12:43:23.964050,479393004,65227,251,49.1398453043,37.387001031225,-87.429257967605,2,1,18 +2025-03-11T12:43:23.979675,479393004,65227,251,49.1634052874,37.410147155175,-87.480217586345,2,1,18 +2025-03-11T12:43:23.995300,479393004,65227,251,49.18225327388,37.419421910685,-87.498766522625,2,1,18 +2025-03-11T12:43:24.010925,479393004,65227,251,49.19638926374,37.433309585055,-87.49884248564,2,1,18 +2025-03-11T12:43:24.026550,479393004,65227,251,49.21523725022,37.451826484215,-87.50818613579,2,1,18 +2025-03-11T12:43:24.042175,479393004,65227,251,49.22466124346,37.461084933795,-87.540585059255,2,1,18 +2025-03-11T12:43:24.057800,479393004,65227,251,49.22937324008,37.47033523041,-87.554492469455,2,1,18 +2025-03-11T12:43:24.073425,479393004,65227,251,49.24350922994,37.48422290478,-87.57305316473,2,1,18 +2025-03-11T12:43:24.089050,479393004,65227,251,49.24822122656,37.493473201395,-87.600824124125,2,1,18 +2025-03-11T12:43:24.104675,479393004,65227,251,49.26235721642,37.488876588465,-87.6193106594,2,1,18 +2025-03-11T12:43:24.120300,479393004,65227,251,49.24822122656,37.493473201395,-87.610066490255,2,1,18 +2025-03-11T12:43:24.135925,479393004,65227,251,49.24350922994,37.488843976605,-87.58231407086,2,1,18 +2025-03-11T12:43:24.151550,479393004,65227,251,49.24822122656,37.48885212957,-87.58694203493,2,1,18 +2025-03-11T12:43:24.167175,479393004,65227,251,49.2340852367,37.4749644552,-87.586866071915,2,1,18 +2025-03-11T12:43:24.182800,479393004,65227,251,49.2340852367,37.46572231155,-87.568344259655,2,1,18 +2025-03-11T12:43:24.198425,479393004,65227,251,49.23879723332,37.438004033565,-87.54051270227,2,1,18 +2025-03-11T12:43:24.214050,479393004,65227,251,49.22937324008,37.419503440335,-87.508076698805,2,1,18 +2025-03-11T12:43:24.229675,479393004,65227,251,49.21523725022,37.41947898144,-87.48957162353,2,1,18 +2025-03-11T12:43:24.245300,479393004,65227,251,49.2105252536,37.405607613,-87.480266856395,2,1,18 +2025-03-11T12:43:24.260925,479393004,65227,251,49.19167726712,37.40557500114,-87.443270267855,2,1,18 +2025-03-11T12:43:24.276550,479393004,65227,251,49.16811728402,37.387049949015,-87.39695037218,2,1,18 +2025-03-11T12:43:24.292175,479393004,65227,251,49.15398129416,37.354677987345,-87.369073150775,2,1,18 +2025-03-11T12:43:24.307800,479393004,65227,251,49.13513330768,37.317676800885,-87.32730705917,2,1,18 +2025-03-11T12:43:24.323425,479393004,65227,251,49.09743733472,37.30374836169,-87.285606543545,2,1,18 +2025-03-11T12:43:24.339050,479393004,65227,251,49.069165355,37.280594084775,-87.22539777767,2,1,18 +2025-03-11T12:43:24.354675,479393004,65227,251,49.05974136176,37.234367060595,-87.16974461888,2,1,18 +2025-03-11T12:43:24.370300,479393004,65227,251,49.02675738542,37.211204630715,-87.109529072,2,1,18 +2025-03-11T12:43:24.385925,479393004,65227,251,48.97963741922,37.183396670115,-87.05389582517,2,1,18 +2025-03-11T12:43:24.401550,479393004,65227,251,48.93251745302,37.146346565865,-87.002846681405,2,1,18 +2025-03-11T12:43:24.417175,479393004,65227,251,48.89482148006,37.109312767545,-86.928705184325,2,1,18 +2025-03-11T12:43:24.432800,479393004,65227,251,48.87126149696,37.067682356295,-86.85456549026,2,1,18 +2025-03-11T12:43:24.448425,479393004,65227,251,48.833565524,37.02602748615,-86.78964781931,2,1,18 +2025-03-11T12:43:24.464050,479393004,65227,251,48.80529354428,36.993631065585,-86.720159607305,2,1,18 +2025-03-11T12:43:24.479675,479393004,65227,251,48.77230956794,36.94736327658,-86.62750307897,2,1,18 +2025-03-11T12:43:24.495300,479393004,65227,251,48.71105361188,36.89642549796,-86.5486508738,2,1,18 +2025-03-11T12:43:24.510925,479393004,65227,251,48.64037366258,36.831608197935,-86.45124475436,2,1,18 +2025-03-11T12:43:24.526550,479393004,65227,251,48.60267768962,36.77146904049,-86.353904641955,2,1,18 +2025-03-11T12:43:24.542175,479393004,65227,251,48.55555772342,36.72517679259,-86.288954868995,2,1,18 +2025-03-11T12:43:24.557800,479393004,65227,251,48.50843775722,36.692747760165,-86.19171243458,2,1,18 +2025-03-11T12:43:24.573425,479393004,65227,251,48.44718180116,36.641809981545,-86.10361786328,2,1,18 +2025-03-11T12:43:24.589050,479393004,65227,251,48.38121384848,36.595485121785,-85.978565586455,2,1,18 +2025-03-11T12:43:24.604675,479393004,65227,251,48.30582190256,36.530659668795,-85.87191031988,2,1,18 +2025-03-11T12:43:24.620300,479393004,65227,251,48.23985394988,36.475092665385,-85.765305695315,2,1,18 +2025-03-11T12:43:24.635925,479393004,65227,251,48.18802198706,36.41030797722,-85.63557841844,2,1,18 +2025-03-11T12:43:24.651550,479393004,65227,251,48.12205403438,36.331635614685,-85.51501754468,2,1,18 +2025-03-11T12:43:24.667175,479393004,65227,251,48.05137408508,36.24833402736,-85.39905253298,2,1,18 +2025-03-11T12:43:24.682800,479393004,65227,251,47.99011812902,36.174290889615,-85.287759346355,2,1,18 +2025-03-11T12:43:24.698425,479393004,65227,251,47.92415017634,36.118723886205,-85.158048806465,2,1,18 +2025-03-11T12:43:24.714050,479393004,65227,251,47.85818222366,36.05853581097,-85.019077360445,2,1,18 +2025-03-11T12:43:24.729675,479393004,65227,251,47.77807828112,35.97983898954,-84.884632594475,2,1,18 +2025-03-11T12:43:24.745300,479393004,65227,251,47.71211032844,35.882682339705,-84.73164927926,2,1,18 +2025-03-11T12:43:24.760925,479393004,65227,251,47.655566369,35.81326842675,-84.59265431525,2,1,18 +2025-03-11T12:43:24.776550,479393004,65227,251,47.58017442308,35.73920083011,-84.439750138025,2,1,18 +2025-03-11T12:43:24.792175,479393004,65227,251,47.50478247716,35.660512161645,-84.291448603865,2,1,18 +2025-03-11T12:43:24.807800,479393004,65227,251,47.41054254476,35.57254873767,-84.13846168262,2,1,18 +2025-03-11T12:43:24.823425,479393004,65227,251,47.33043860222,35.470746557115,-83.971575935195,2,1,18 +2025-03-11T12:43:24.839050,479393004,65227,251,47.24562266306,35.368936223595,-83.804683406765,2,1,18 +2025-03-11T12:43:24.854675,479393004,65227,251,47.14195873742,35.285577565515,-83.637837914315,2,1,18 +2025-03-11T12:43:24.870300,479393004,65227,251,47.03829481178,35.192976763785,-83.45709179267,2,1,18 +2025-03-11T12:43:24.885925,479393004,65227,251,46.94405487938,35.10501333981,-83.285620139165,2,1,18 +2025-03-11T12:43:24.901550,479393004,65227,251,46.84510295036,35.02628390652,-83.11879996772,2,1,18 +2025-03-11T12:43:24.917175,479393004,65227,251,46.74615102134,34.933691257755,-82.96578772547,2,1,18 +2025-03-11T12:43:24.932800,479393004,65227,251,46.64719909232,34.836477537165,-82.780408661765,2,1,18 +2025-03-11T12:43:24.948425,479393004,65227,251,46.54353516668,34.73001351996,-82.5626374556,2,1,18 +2025-03-11T12:43:24.964050,479393004,65227,251,46.43515924442,34.628162421615,-82.367983923755,2,1,18 +2025-03-11T12:43:24.979675,479393004,65227,251,46.3362073154,34.521706557375,-82.20105251231,2,1,18 +2025-03-11T12:43:24.995300,479393004,65227,251,46.23254338976,34.401379324695,-81.983225686145,2,1,18 +2025-03-11T12:43:25.010925,479393004,65227,251,46.11945547088,34.290277929735,-81.78390711023,2,1,18 +2025-03-11T12:43:25.026550,479393004,65227,251,46.006367552,34.1837976066,-81.59847062351,2,1,18 +2025-03-11T12:43:25.042175,479393004,65227,251,45.89799162974,34.06808329278,-81.3991402886,2,1,18 +2025-03-11T12:43:25.057800,479393004,65227,251,45.78019171424,33.95235267303,-81.204417574745,2,1,18 +2025-03-11T12:43:25.073425,479393004,65227,251,45.66710379536,33.83200913442,-80.972713637375,2,1,18 +2025-03-11T12:43:25.089050,479393004,65227,251,45.55401587648,33.716286667635,-80.7548917892,2,1,18 +2025-03-11T12:43:25.104675,479393004,65227,251,45.43150396436,33.59130575127,-80.527776932885,2,1,18 +2025-03-11T12:43:25.120300,479393004,65227,251,45.3231280421,33.461728221975,-80.300663879585,2,1,18 +2025-03-11T12:43:25.135925,479393004,65227,251,45.19119213674,33.350594215155,-80.087454630455,2,1,18 +2025-03-11T12:43:25.151550,479393004,65227,251,45.06868022462,33.23485544244,-79.86037685414,2,1,18 +2025-03-11T12:43:25.167175,479393004,65227,251,44.95559230574,33.100648688355,-79.62861729677,2,1,18 +2025-03-11T12:43:25.182800,479393004,65227,251,44.8048084139,32.9571345669,-79.392145228295,2,1,18 +2025-03-11T12:43:25.198425,479393004,65227,251,44.67287250854,32.822895200955,-79.15573736384,2,1,18 +2025-03-11T12:43:25.214050,479393004,65227,251,44.54093660318,32.702519050485,-78.928627485515,2,1,18 +2025-03-11T12:43:25.229675,479393004,65227,251,44.39957670458,32.572884450435,-78.67373986679,2,1,18 +2025-03-11T12:43:25.245300,479393004,65227,251,44.25350480936,32.429378481945,-78.414168663995,2,1,18 +2025-03-11T12:43:25.260925,479393004,65227,251,44.12628090062,32.28128405349,-78.17309077748,2,1,18 +2025-03-11T12:43:25.276550,479393004,65227,251,43.9802090054,32.151641300475,-77.91819637775,2,1,18 +2025-03-11T12:43:25.292175,479393004,65227,251,43.83413711018,32.008135331985,-77.64476162576,2,1,18 +2025-03-11T12:43:25.307800,479393004,65227,251,43.69277721158,31.85539537281,-77.380538940905,2,1,18 +2025-03-11T12:43:25.323425,479393004,65227,251,43.5561293096,31.71190571025,-77.134844849315,2,1,18 +2025-03-11T12:43:25.339050,479393004,65227,251,43.41948140762,31.55917390404,-76.8660077624,2,1,18 +2025-03-11T12:43:25.354675,479393004,65227,251,43.28754550226,31.41107132262,-76.601817179555,2,1,18 +2025-03-11T12:43:25.370300,479393004,65227,251,43.14618560366,31.27219457892,-76.323786565505,2,1,18 +2025-03-11T12:43:25.385925,479393004,65227,251,42.9906897152,31.114809089025,-76.050282631505,2,1,18 +2025-03-11T12:43:25.401550,479393004,65227,251,42.83990582336,30.96205282392,-75.78604638464,2,1,18 +2025-03-11T12:43:25.417175,479393004,65227,251,42.69383392814,30.813925783605,-75.507971909585,2,1,18 +2025-03-11T12:43:25.432800,479393004,65227,251,42.52891404644,30.64728184413,-75.22055378438,2,1,18 +2025-03-11T12:43:25.448425,479393004,65227,251,42.37341815798,30.489896354235,-74.914701568925,2,1,18 +2025-03-11T12:43:25.464050,479393004,65227,251,42.22734626276,30.32328502662,-74.61806820161,2,1,18 +2025-03-11T12:43:25.479675,479393004,65227,251,42.05771438444,30.14739079053,-74.3306062154,2,1,18 +2025-03-11T12:43:25.495300,479393004,65227,251,41.88808250612,29.99922298539,-74.038634286125,2,1,18 +2025-03-11T12:43:25.510925,479393004,65227,251,41.7184506278,29.83257089295,-73.72810346459,2,1,18 +2025-03-11T12:43:25.526550,479393004,65227,251,41.55824274272,29.679798321915,-73.43150537426,2,1,18 +2025-03-11T12:43:25.542175,479393004,65227,251,41.37918687116,29.50850885172,-73.148669549105,2,1,18 +2025-03-11T12:43:25.557800,479393004,65227,251,41.2001309996,29.337219381525,-72.815000710235,2,1,18 +2025-03-11T12:43:25.573425,479393004,65227,251,41.0352111179,29.17057544205,-72.495234303575,2,1,18 +2025-03-11T12:43:25.589050,479393004,65227,251,40.85615524634,28.99466490003,-72.19389520616,2,1,18 +2025-03-11T12:43:25.604675,479393004,65227,251,40.67709937478,28.82799650166,-71.855623724225,2,1,18 +2025-03-11T12:43:25.620300,479393004,65227,251,40.4933315066,28.642835663025,-71.526513667415,2,1,18 +2025-03-11T12:43:25.635925,479393004,65227,251,40.31898763166,28.443827914845,-71.20198273568,2,1,18 +2025-03-11T12:43:25.651550,479393004,65227,251,40.14464375672,28.263304453965,-70.886768330075,2,1,18 +2025-03-11T12:43:25.667175,479393004,65227,251,39.96558788516,28.087393911945,-70.553080951205,2,1,18 +2025-03-11T12:43:25.682800,479393004,65227,251,39.79595600684,27.902257532205,-70.219370054345,2,1,18 +2025-03-11T12:43:25.698425,479393004,65227,251,39.61218813866,27.721717765395,-69.899520903665,2,1,18 +2025-03-11T12:43:25.714050,479393004,65227,251,39.42370827386,27.536548773795,-69.57040406585,2,1,18 +2025-03-11T12:43:25.729675,479393004,65227,251,39.23522840906,27.360621925845,-69.232081941905,2,1,18 +2025-03-11T12:43:25.745300,479393004,65227,251,39.04674854426,27.19855829337,-68.88457307183,2,1,18 +2025-03-11T12:43:25.760925,479393004,65227,251,38.86298067608,27.013397454735,-68.532357099695,2,1,18 +2025-03-11T12:43:25.776550,479393004,65227,251,38.67450081128,26.809744175835,-68.17543900349,2,1,18 +2025-03-11T12:43:25.792175,479393004,65227,251,38.47188495662,26.60606643804,-67.8277429304,2,1,18 +2025-03-11T12:43:25.807800,479393004,65227,251,38.27398109858,26.39315470956,-67.46615300912,2,1,18 +2025-03-11T12:43:25.823425,479393004,65227,251,38.08078923716,26.20335649317,-67.10004138578,2,1,18 +2025-03-11T12:43:25.839050,479393004,65227,251,37.89702136898,25.999711367235,-66.738508887515,2,1,18 +2025-03-11T12:43:25.854675,479393004,65227,251,37.7132535008,25.809929456775,-66.381653192315,2,1,18 +2025-03-11T12:43:25.870300,479393004,65227,251,37.52006163938,25.610889096735,-66.01088330591,2,1,18 +2025-03-11T12:43:25.885925,479393004,65227,251,37.30802179148,25.384089693885,-65.630732689355,2,1,18 +2025-03-11T12:43:25.901550,479393004,65227,251,37.09598194358,25.16191136286,-65.28757007732,2,1,18 +2025-03-11T12:43:25.917175,479393004,65227,251,36.89336608892,24.958233625065,-64.916768088905,2,1,18 +2025-03-11T12:43:25.932800,479393004,65227,251,36.69075023426,24.768419102745,-64.532158171295,2,1,18 +2025-03-11T12:43:25.948425,479393004,65227,251,36.47399838974,24.564716906055,-64.1567146568,2,1,18 +2025-03-11T12:43:25.964050,479393004,65227,251,36.25724654522,24.33790935024,-63.771936076175,2,1,18 +2025-03-11T12:43:25.979675,479393004,65227,251,36.04520669732,24.134215306515,-63.38263579349,2,1,18 +2025-03-11T12:43:25.995223,479393008,65222,252,35.8284548528,23.921270966175,-62.997912832865,2,1,18 +2025-03-11T12:43:26.010848,479393008,65222,252,35.6164150049,23.703713706975,-62.613178113245,2,1,18 +2025-03-11T12:43:26.026473,479393008,65222,252,35.40908715362,23.500027816215,-62.233126977695,2,1,18 +2025-03-11T12:43:26.042098,479393008,65222,252,35.20175930234,23.287099781805,-61.825311663755,2,1,18 +2025-03-11T12:43:26.057723,479393008,65222,252,34.98500745782,23.07877651329,-61.44060724313,2,1,18 +2025-03-11T12:43:26.073348,479393008,65222,252,34.7682556133,22.861211101125,-61.04200219331,2,1,18 +2025-03-11T12:43:26.088973,479393008,65222,252,34.55150376878,22.639024617135,-60.62489387123,2,1,18 +2025-03-11T12:43:26.104598,479393008,65222,252,34.33003992764,22.412208908355,-60.235487326535,2,1,18 +2025-03-11T12:43:26.120223,479393008,65222,252,34.11328808312,22.19464349619,-59.846124642845,2,1,18 +2025-03-11T12:43:26.135848,479393008,65222,252,33.88711224536,21.97244070627,-59.429002758755,2,1,18 +2025-03-11T12:43:26.151473,479393008,65222,252,33.65622441098,21.731745476085,-59.00255756753,2,1,18 +2025-03-11T12:43:26.167098,479393008,65222,252,33.43947256646,21.500316848445,-58.57616979932,2,1,18 +2025-03-11T12:43:26.182723,479393008,65222,252,33.2132967287,21.278114058525,-58.14056318297,2,1,18 +2025-03-11T12:43:26.198348,479393008,65222,252,32.98240889432,21.032797756515,-57.723341817875,2,1,18 +2025-03-11T12:43:26.213973,479393008,65222,252,32.75623305656,20.78748960747,-57.315369599915,2,1,18 +2025-03-11T12:43:26.229598,479393008,65222,252,32.5300572188,20.560665745725,-56.907471541955,2,1,18 +2025-03-11T12:43:26.245223,479393008,65222,252,32.2944573878,20.3430677217,-56.48573345279,2,1,18 +2025-03-11T12:43:26.260848,479393008,65222,252,32.0588575568,20.106985410375,-56.045436471365,2,1,18 +2025-03-11T12:43:26.276473,479393008,65222,252,31.80912173594,19.87549971198,-55.614380053055,2,1,18 +2025-03-11T12:43:26.292098,479393008,65222,252,31.57352190494,19.64403847248,-55.18334397776,2,1,18 +2025-03-11T12:43:26.307723,479393008,65222,252,31.33792207394,19.40333508933,-54.733786090205,2,1,18 +2025-03-11T12:43:26.323348,479393008,65222,252,31.09761024632,19.16724462504,-54.293482327775,2,1,18 +2025-03-11T12:43:26.338973,479393008,65222,252,30.86201041532,18.912678026415,-53.88083828474,2,1,18 +2025-03-11T12:43:26.354598,479393008,65222,252,30.61698659108,18.671958337335,-53.449751567435,2,1,18 +2025-03-11T12:43:26.370223,479393008,65222,252,30.37196276684,18.440480791905,-52.995596014805,2,1,18 +2025-03-11T12:43:26.385848,479393008,65222,252,30.13165093922,18.19976925579,-52.55065252931,2,1,18 +2025-03-11T12:43:26.401473,479393008,65222,252,29.8913391116,17.940573432375,-52.10101370075,2,1,18 +2025-03-11T12:43:26.417098,479393008,65222,252,29.64631528736,17.67674838417,-51.64672836812,2,1,18 +2025-03-11T12:43:26.432723,479393008,65222,252,29.40129146312,17.43602869509,-51.18329336936,2,1,18 +2025-03-11T12:43:26.448348,479393008,65222,252,29.1609796355,17.20918037445,-50.738405503865,2,1,18 +2025-03-11T12:43:26.463973,479393008,65222,252,28.91595581126,16.945355326245,-50.293362537365,2,1,18 +2025-03-11T12:43:26.479598,479393008,65222,252,28.66150799378,16.69075611576,-49.829858356595,2,1,18 +2025-03-11T12:43:26.495223,479393008,65222,252,28.40234817968,16.44539089596,-49.37562684095,2,1,18 +2025-03-11T12:43:26.510848,479393008,65222,252,28.15261235882,16.186178766615,-48.90748971812,2,1,18 +2025-03-11T12:43:26.526473,479393008,65222,252,27.91701252782,15.936233239815,-48.448652384435,2,1,18 +2025-03-11T12:43:26.542098,479393008,65222,252,27.6531407171,15.667754507925,-47.975836655525,2,1,18 +2025-03-11T12:43:26.557723,479393008,65222,252,27.393980903,15.394662857175,-47.507630350685,2,1,18 +2025-03-11T12:43:26.573348,479393008,65222,252,27.14424508214,15.140071799655,-47.048754133985,2,1,18 +2025-03-11T12:43:26.588973,479393008,65222,252,26.88979726466,14.890093660995,-46.58064731015,2,1,18 +2025-03-11T12:43:26.604598,479393008,65222,252,26.63534944718,14.64473659416,-46.11718020938,2,1,18 +2025-03-11T12:43:26.620223,479393008,65222,252,26.37147763646,14.38550000592,-45.639780377405,2,1,18 +2025-03-11T12:43:26.635848,479393008,65222,252,26.0981818325,14.1170049681,-45.148466354225,2,1,18 +2025-03-11T12:43:26.651473,479393008,65222,252,25.82959802516,13.839275939595,-44.66636439818,2,1,18 +2025-03-11T12:43:26.667098,479393008,65222,252,25.57043821106,13.58004750432,-44.193592530275,2,1,18 +2025-03-11T12:43:26.682723,479393008,65222,252,25.31127839696,13.320819069045,-43.725441845435,2,1,18 +2025-03-11T12:43:26.698348,479393008,65222,252,25.05211858286,13.05234849012,-43.2433905314,2,1,18 +2025-03-11T12:43:26.713973,479393008,65222,252,24.79767076538,12.788507135985,-42.76136453837,2,1,18 +2025-03-11T12:43:26.729598,479393008,65222,252,24.52437496142,12.51539102634,-42.274653158255,2,1,18 +2025-03-11T12:43:26.745223,479393008,65222,252,24.23223117098,12.242242304835,-41.792535837185,2,1,18 +2025-03-11T12:43:26.760848,479393008,65222,252,23.98249535012,11.97378803184,-41.287392169835,2,1,18 +2025-03-11T12:43:26.776473,479393008,65222,252,23.7186235394,11.709930371775,-40.796110248665,2,1,18 +2025-03-11T12:43:26.792098,479393008,65222,252,23.45475172868,11.44607271171,-40.304828327495,2,1,18 +2025-03-11T12:43:26.807723,479393008,65222,252,23.19087991796,11.172972907995,-39.795024594065,2,1,18 +2025-03-11T12:43:26.823348,479393008,65222,252,22.90816012076,10.904461564245,-39.30831819194,2,1,18 +2025-03-11T12:43:26.838973,479393008,65222,252,22.63957631342,10.63597467939,-38.798526217505,2,1,18 +2025-03-11T12:43:26.854598,479393008,65222,252,22.36156851284,10.348987201305,-38.311752436385,2,1,18 +2025-03-11T12:43:26.870223,479393008,65222,252,22.08827270888,10.06662894801,-37.820382793205,2,1,18 +2025-03-11T12:43:26.885848,479393008,65222,252,21.80084091506,9.79348837947,-37.31054515475,2,1,18 +2025-03-11T12:43:26.901473,479393008,65222,252,21.51812111786,9.529598107545,-36.796130194235,2,1,18 +2025-03-11T12:43:26.917098,479393008,65222,252,21.2448253139,9.251860926075,-36.29091554186,2,1,18 +2025-03-11T12:43:26.932723,479393008,65222,252,20.97152950994,8.974123744605,-35.78107970642,2,1,18 +2025-03-11T12:43:26.948348,479393008,65222,252,20.7029457026,8.68715257245,-35.27583475505,2,1,18 +2025-03-11T12:43:26.963973,479393008,65222,252,20.41551390878,8.409390932085,-34.77059975966,2,1,18 +2025-03-11T12:43:26.979598,479393008,65222,252,20.14221810482,8.150138037915,-34.27008045035,2,1,18 +2025-03-11T12:43:26.995223,479393008,65222,252,19.86892230086,7.872400856445,-33.74175988265,2,1,18 +2025-03-11T12:43:27.010848,479393008,65222,252,19.5720665138,7.580759694675,-33.23645570525,2,1,18 +2025-03-11T12:43:27.026473,479393008,65222,252,19.29405871322,7.28453007294,-32.72191774574,2,1,18 +2025-03-11T12:43:27.042098,479393008,65222,252,19.02076290926,7.002171819645,-32.207442187235,2,1,18 +2025-03-11T12:43:27.057723,479393008,65222,252,18.74275510868,6.729047557035,-31.692996927725,2,1,18 +2025-03-11T12:43:27.073348,479393008,65222,252,18.46003531148,6.42818871051,-31.183054830275,2,1,18 +2025-03-11T12:43:27.088973,479393008,65222,252,18.1820275109,6.14582230425,-30.677814856895,2,1,18 +2025-03-11T12:43:27.104598,479393008,65222,252,17.89459571708,5.840334232935,-30.15860507231,2,1,18 +2025-03-11T12:43:27.120223,479393008,65222,252,17.60716392326,5.55333044892,-29.620984715465,2,1,18 +2025-03-11T12:43:27.135848,479393008,65222,252,17.32444412606,5.289440176995,-29.092706205755,2,1,18 +2025-03-11T12:43:27.151473,479393008,65222,252,17.03230033562,5.00704931184,-28.55047642484,2,1,18 +2025-03-11T12:43:27.167098,479393008,65222,252,16.75429253504,4.72468290558,-28.022130536135,2,1,18 +2025-03-11T12:43:27.182723,479393008,65222,252,16.45743674798,4.428420671985,-27.516807818735,2,1,18 +2025-03-11T12:43:27.198348,479393008,65222,252,16.16058096092,4.127537366565,-27.00684537827,2,1,18 +2025-03-11T12:43:27.213973,479393008,65222,252,15.86843717048,3.849767573235,-26.473876503485,2,1,18 +2025-03-11T12:43:27.229598,479393008,65222,252,15.58571737328,3.55815087036,-25.95010793684,2,1,18 +2025-03-11T12:43:27.245223,479393008,65222,252,15.29828557946,3.261904942695,-25.42631404919,2,1,18 +2025-03-11T12:43:27.260848,479393008,65222,252,15.00614178902,2.97951407754,-24.88870545134,2,1,18 +2025-03-11T12:43:27.276473,479393008,65222,252,14.71399799858,2.697123212385,-24.36033921962,2,1,18 +2025-03-11T12:43:27.292098,479393008,65222,252,14.42656620476,2.41011942837,-23.831961228905,2,1,18 +2025-03-11T12:43:27.307723,479393008,65222,252,14.13442241432,2.109244275915,-23.312763203315,2,1,18 +2025-03-11T12:43:27.323348,479393008,65222,252,13.82814263402,1.81296573639,-22.779699825515,2,1,18 +2025-03-11T12:43:27.338973,479393008,65222,252,13.5407108402,1.5305830242,-22.237476825605,2,1,18 +2025-03-11T12:43:27.354598,479393008,65222,252,13.24856704976,1.229707871745,-21.709036433885,2,1,18 +2025-03-11T12:43:27.370223,479393008,65222,252,12.94228726946,0.938050404045001,-21.17137041302,2,1,18 +2025-03-11T12:43:27.385848,479393008,65222,252,12.64071948578,0.632537873835001,-20.647519102355,2,1,18 +2025-03-11T12:43:27.401473,479393008,65222,252,12.35328769196,0.322428730695,-20.10980604551,2,1,18 +2025-03-11T12:43:27.417098,479393008,65222,252,12.06585589814,0.0261828030300002,-19.54904269334,2,1,18 +2025-03-11T12:43:27.432723,479393008,65222,252,11.77842410432,-0.256199909159999,-19.02530442569,2,1,18 +2025-03-11T12:43:27.448348,479393008,65222,252,11.50512830036,-0.56166352158,-18.4691455196,2,1,18 +2025-03-11T12:43:27.463973,479393008,65222,252,11.21769650654,-0.867151592895,-17.92682981969,2,1,18 +2025-03-11T12:43:27.479598,479393008,65222,252,10.92084071948,-1.14492953919,-17.398475346965,2,1,18 +2025-03-11T12:43:27.495223,479393008,65222,252,10.62869692904,-1.43194147617,-16.860848209115,2,1,18 +2025-03-11T12:43:27.510848,479393008,65222,252,10.3365531386,-1.7281955568,-16.32780517433,2,1,18 +2025-03-11T12:43:27.526473,479393008,65222,252,10.02084936506,-2.02911147408,-15.78546732839,2,1,18 +2025-03-11T12:43:27.542098,479393008,65222,252,9.71928158138,-2.330002932465,-15.233907459335,2,1,18 +2025-03-11T12:43:27.557723,479393008,65222,252,9.43184978756,-2.62624886013,-14.67776529023,2,1,18 +2025-03-11T12:43:27.573348,479393008,65222,252,9.12557000726,-2.91790632783,-14.15396281856,2,1,18 +2025-03-11T12:43:27.588973,479393008,65222,252,8.8287142202,-3.20030534595,-13.62096862277,2,1,18 +2025-03-11T12:43:27.604598,479393008,65222,252,8.53657042976,-3.50580157023,-13.07402495879,2,1,18 +2025-03-11T12:43:27.620223,479393008,65222,252,8.2397146427,-3.820548091125,-12.52241625074,2,1,18 +2025-03-11T12:43:27.635848,479393008,65222,252,7.9334348624,-4.1260687743,-11.975452243745,2,1,18 +2025-03-11T12:43:27.651473,479393008,65222,252,7.64600306858,-4.422314701965,-11.442415989965,2,1,18 +2025-03-11T12:43:27.667098,479393008,65222,252,7.3444352849,-4.718585088525,-10.877011111715,2,1,18 +2025-03-11T12:43:27.682723,479393008,65222,252,7.0381555046,-5.01486362805,-10.33008418472,2,1,18 +2025-03-11T12:43:27.698348,479393008,65222,252,6.74129971754,-5.329610148945,-9.792339025865,2,1,18 +2025-03-11T12:43:27.713973,479393008,65222,252,6.44444393048,-5.639735598015,-9.259233590075,2,1,18 +2025-03-11T12:43:27.729598,479393008,65222,252,6.1428761468,-5.936005984575,-8.70769226102,2,1,18 +2025-03-11T12:43:27.745223,479393008,65222,252,5.85544435298,-6.22300976859,-8.15620835498,2,1,18 +2025-03-11T12:43:27.760848,479393008,65222,252,5.55858856592,-6.52389307401,-7.609276449995,2,1,18 +2025-03-11T12:43:27.776473,479393008,65222,252,5.25702078224,-6.84788989152,-7.062245064005,2,1,18 +2025-03-11T12:43:27.792098,479393008,65222,252,4.9648769918,-7.1349018285,-6.51075437696,2,1,18 +2025-03-11T12:43:27.807723,479393008,65222,252,4.66330920812,-7.417308999585,-5.94540511871,2,1,18 +2025-03-11T12:43:27.823348,479393008,65222,252,4.36645342106,-7.72281337683,-5.36610639227,2,1,18 +2025-03-11T12:43:27.838973,479393008,65222,252,4.04132565428,-8.028366671865,-4.828357627385,2,1,18 +2025-03-11T12:43:27.854598,479393008,65222,252,3.73033387736,-8.32927443618,-4.290647745515,2,1,18 +2025-03-11T12:43:27.870223,479393008,65222,252,3.4334780903,-8.634778813425,-3.757560849725,2,1,18 +2025-03-11T12:43:27.885848,479393008,65222,252,3.14133429986,-8.93565396588,-3.219878091875,2,1,18 +2025-03-11T12:43:27.901473,479393008,65222,252,2.8444785128,-9.2365372713,-2.677567369955,2,1,18 +2025-03-11T12:43:27.917098,479393008,65222,252,2.54291072912,-9.555913016985,-2.1259333409,2,1,18 +2025-03-11T12:43:27.932723,479393008,65222,252,2.25076693868,-9.84754602579,-1.583666479985,2,1,18 +2025-03-11T12:43:27.948348,479393008,65222,252,1.95391115162,-10.12994504391,-1.02756636887,2,1,18 +2025-03-11T12:43:27.963973,479393008,65222,252,1.65705536456,-10.426207277505,-0.47603182082,2,1,18 +2025-03-11T12:43:27.979598,479393008,65222,252,1.3601995775,-10.727090582925,0.061657718035,2,1,18 +2025-03-11T12:43:27.995223,479393008,65222,252,1.0539197972,-11.0326112661,0.59013699277,2,1,18 +2025-03-11T12:43:28.010848,479393008,65222,252,0.75706401014,-11.328873499695,1.127807991625,2,1,18 +2025-03-11T12:43:28.026473,479393008,65222,252,0.46963221632,-11.620498355535,1.65620452234,2,1,18 +2025-03-11T12:43:28.042098,479393008,65222,252,0.17277642926,-11.939865948255,2.23555886878,2,1,18 +2025-03-11T12:43:28.057723,479393008,65222,252,-0.13350335104,-12.250007703255,2.791783781905,2,1,18 +2025-03-11T12:43:28.073348,479393008,65222,252,-0.43507113472,-12.537035946165,3.3248032987,2,1,18 +2025-03-11T12:43:28.088973,479393008,65222,252,-0.74606291164,-12.833322638655,3.86249464057,2,1,18 +2025-03-11T12:43:28.104598,479393008,65222,252,-1.0429186987,-13.134205944075,4.42329009475,2,1,18 +2025-03-11T12:43:28.120223,479393008,65222,252,-1.33506248914,-13.43508109653,4.9609728526,2,1,18 +2025-03-11T12:43:28.135848,479393008,65222,252,-1.62720627958,-13.73133517716,5.48939470432,2,1,18 +2025-03-11T12:43:28.151473,479393008,65222,252,-1.92877406326,-14.02760556372,6.013208934985,2,1,18 +2025-03-11T12:43:28.167098,479393008,65222,252,-2.2209178537,-14.328480716175,6.550891692835,2,1,18 +2025-03-11T12:43:28.182723,479393008,65222,252,-2.51777364076,-14.61550080612,7.093146794755,2,1,18 +2025-03-11T12:43:28.198348,479393008,65222,252,-2.81934142444,-14.93025547998,7.630898734615,2,1,18 +2025-03-11T12:43:28.213973,479393008,65222,252,-3.12090920812,-15.221904794715,8.159315608345,2,1,18 +2025-03-11T12:43:28.229598,479393008,65222,252,-3.40834100194,-15.513529650555,8.70619687132,2,1,18 +2025-03-11T12:43:28.245223,479393008,65222,252,-3.705196789,-15.8005497405,9.23920960711,2,1,18 +2025-03-11T12:43:28.260848,479393008,65222,252,-4.00205257606,-16.106054117745,9.7722965029,2,1,18 +2025-03-11T12:43:28.276473,479393008,65222,252,-4.29890836312,-16.41155849499,10.310004581755,2,1,18 +2025-03-11T12:43:28.292098,479393008,65222,252,-4.58162816032,-16.70779626969,10.84303405453,2,1,18 +2025-03-11T12:43:28.307723,479393008,65222,252,-4.87848394738,-16.99943743146,11.389928879515,2,1,18 +2025-03-11T12:43:28.323348,479393008,65222,252,-5.18005173106,-17.300328889845,11.91376165018,2,1,18 +2025-03-11T12:43:28.338973,479393008,65222,252,-5.4721955215,-17.605825114125,12.456084131095,2,1,18 +2025-03-11T12:43:28.354598,479393008,65222,252,-5.76433931194,-17.902079194755,12.99836953201,2,1,18 +2025-03-11T12:43:28.370223,479393008,65222,252,-6.061195099,-18.193720356525,13.52215844167,2,1,18 +2025-03-11T12:43:28.385848,479393008,65222,252,-6.35805088606,-18.48074044647,14.059792360525,2,1,18 +2025-03-11T12:43:28.401473,479393008,65222,252,-6.63605868664,-18.767727924555,14.592777972295,2,1,18 +2025-03-11T12:43:28.417098,479393008,65222,252,-6.91877848384,-19.054723555605,15.130391548135,2,1,18 +2025-03-11T12:43:28.432723,479393008,65222,252,-7.20621027766,-19.346348411445,15.64954571272,2,1,18 +2025-03-11T12:43:28.448348,479393008,65222,252,-7.4983540681,-19.642602492075,16.17796756444,2,1,18 +2025-03-11T12:43:28.463973,479393008,65222,252,-7.79520985516,-19.925001510195,16.72020412636,2,1,18 +2025-03-11T12:43:28.479598,479393008,65222,252,-8.09206564222,-20.225884815615,17.248651299085,2,1,18 +2025-03-11T12:43:28.495223,479393008,65222,252,-8.37949743604,-20.52213074328,17.772445186735,2,1,18 +2025-03-11T12:43:28.510848,479393008,65222,252,-8.66221723324,-20.80912637433,18.29619521338,2,1,18 +2025-03-11T12:43:28.526473,479393008,65222,252,-8.94493703044,-21.10536414903,18.80611877083,2,1,18 +2025-03-11T12:43:28.542098,479393008,65222,252,-9.2417928175,-21.3970053108,19.343771229685,2,1,18 +2025-03-11T12:43:28.557723,479393008,65222,252,-9.52922461132,-21.684009094815,19.867528037335,2,1,18 +2025-03-11T12:43:28.573348,479393008,65222,252,-9.8072324119,-21.975617644725,20.382047456845,2,1,18 +2025-03-11T12:43:28.588973,479393008,65222,252,-10.07110422262,-22.25795959209,20.9149941856,2,1,18 +2025-03-11T12:43:28.604598,479393008,65222,252,-10.3491120232,-22.5310838547,21.43868181124,2,1,18 +2025-03-11T12:43:28.620223,479393008,65222,252,-10.65067980688,-22.822733169435,21.94861395271,2,1,18 +2025-03-11T12:43:28.635848,479393008,65222,252,-10.92868760746,-23.114341719345,22.47237573835,2,1,18 +2025-03-11T12:43:28.651473,479393008,65222,252,-11.2208313979,-23.392111512675,23.0099657962,2,1,18 +2025-03-11T12:43:28.667098,479393008,65222,252,-11.5271111782,-23.66066362125,23.519812018675,2,1,18 +2025-03-11T12:43:28.682723,479393008,65222,252,-11.8098309754,-23.933796036825,24.03426405919,2,1,18 +2025-03-11T12:43:28.698348,479393008,65222,252,-12.08783877598,-24.216162443085,24.553367581765,2,1,18 +2025-03-11T12:43:28.713973,479393008,65222,252,-12.37055857318,-24.49853700231,25.04937197002,2,1,18 +2025-03-11T12:43:28.729598,479393008,65222,252,-12.64385437714,-24.780895255605,25.54998397933,2,1,18 +2025-03-11T12:43:28.745223,479393008,65222,252,-12.92186217772,-25.072503805515,26.050639849645,2,1,18 +2025-03-11T12:43:28.760848,479393008,65222,252,-13.19044598506,-25.354853905845,26.56972981021,2,1,18 +2025-03-11T12:43:28.776473,479393008,65222,252,-13.45431779578,-25.64643799686,27.084228886705,2,1,18 +2025-03-11T12:43:28.792098,479393008,65222,252,-13.73232559636,-25.93804654677,27.58488475702,2,1,18 +2025-03-11T12:43:28.807723,479393008,65222,252,-14.01504539356,-26.211178962345,28.071609699145,2,1,18 +2025-03-11T12:43:28.823348,479393008,65222,252,-14.28834119752,-26.479674000165,28.572166088455,2,1,18 +2025-03-11T12:43:28.838973,479393008,65222,252,-14.57106099472,-26.748185343915,29.06811485671,2,1,18 +2025-03-11T12:43:28.854598,479393008,65222,252,-14.85378079192,-27.016696687665,29.564063624965,2,1,18 +2025-03-11T12:43:28.870223,479393008,65222,252,-15.1317885925,-27.289820950275,30.06464533528,2,1,18 +2025-03-11T12:43:28.885848,479393008,65222,252,-15.39566040322,-27.558299682165,30.560566979515,2,1,18 +2025-03-11T12:43:28.901473,479393008,65222,252,-15.65953221394,-27.82215734223,31.06571244988,2,1,18 +2025-03-11T12:43:28.917098,479393008,65222,252,-15.94696400776,-28.09529791077,31.547822989945,2,1,18 +2025-03-11T12:43:28.932723,479393008,65222,252,-16.22025981172,-28.359171876765,32.029876106995,2,1,18 +2025-03-11T12:43:28.948348,479393008,65222,252,-16.49355561568,-28.627666914585,32.53505367937,2,1,18 +2025-03-11T12:43:28.963973,479393008,65222,252,-16.7574274264,-28.9007667183,33.01713031441,2,1,18 +2025-03-11T12:43:28.979598,479393008,65222,252,-17.0165872405,-29.17385836905,33.508442534575,2,1,18 +2025-03-11T12:43:28.995223,479393008,65222,252,-17.28517104784,-29.45620846938,33.995184213685,2,1,18 +2025-03-11T12:43:29.010848,479393008,65222,252,-17.54904285856,-29.720066129445,34.477223768725,2,1,18 +2025-03-11T12:43:29.026473,479393008,65222,252,-17.80820267266,-29.965431349245,34.96842474889,2,1,18 +2025-03-11T12:43:29.042098,479393008,65222,252,-18.05793849352,-30.24312776589,35.450499580915,2,1,18 +2025-03-11T12:43:29.057723,479393008,65222,252,-18.29825032114,-30.530050020255,35.927976747865,2,1,18 +2025-03-11T12:43:29.073348,479393008,65222,252,-18.56212213186,-30.77542339302,36.40532095984,2,1,18 +2025-03-11T12:43:29.088973,479393008,65222,252,-18.83541793582,-31.03467628719,36.87811317076,2,1,18 +2025-03-11T12:43:29.104598,479393008,65222,252,-19.10400174316,-31.29854210022,37.35553832374,2,1,18 +2025-03-11T12:43:29.120223,479393008,65222,252,-19.35844956064,-31.55776238253,37.82830341064,2,1,18 +2025-03-11T12:43:29.135848,479393008,65222,252,-19.62703336798,-31.81238605191,38.30569148362,2,1,18 +2025-03-11T12:43:29.151473,479393008,65222,252,-19.90032917194,-32.057775730605,38.792291623735,2,1,18 +2025-03-11T12:43:29.167098,479393008,65222,252,-20.15477698942,-32.31237494109,39.274280536765,2,1,18 +2025-03-11T12:43:29.182723,479393008,65222,252,-20.39980081366,-32.57157891747,39.73316851246,2,1,18 +2025-03-11T12:43:29.198348,479393008,65222,252,-20.63540064466,-32.835387659745,40.173576733885,2,1,18 +2025-03-11T12:43:29.213973,479393008,65222,252,-20.87571247228,-33.06685705221,40.623104322445,2,1,18 +2025-03-11T12:43:29.229598,479393008,65222,252,-21.139584283,-33.32609364045,41.077398239095,2,1,18 +2025-03-11T12:43:29.245223,479393008,65222,252,-21.39403210048,-33.571450707285,41.550107705995,2,1,18 +2025-03-11T12:43:29.260848,479393008,65222,252,-21.63905592472,-33.82603361184,42.00897714169,2,1,18 +2025-03-11T12:43:29.276473,479393008,65222,252,-21.88407974896,-34.080616516395,42.458604211255,2,1,18 +2025-03-11T12:43:29.292098,479393008,65222,252,-22.13852756644,-34.330594655055,42.8989839367,2,1,18 +2025-03-11T12:43:29.307723,479393008,65222,252,-22.38355139068,-34.57593541596,43.36243747546,2,1,18 +2025-03-11T12:43:29.323348,479393008,65222,252,-22.62857521492,-34.821276176865,43.802785098895,2,1,18 +2025-03-11T12:43:29.338973,479393008,65222,252,-22.86888704254,-35.057366641155,44.23846767826,2,1,18 +2025-03-11T12:43:29.354598,479393008,65222,252,-23.11391086678,-35.31194954571,44.67423119863,2,1,18 +2025-03-11T12:43:29.370223,479393008,65222,252,-23.3542226944,-35.55728215365,45.119193224125,2,1,18 +2025-03-11T12:43:29.385848,479393008,65222,252,-23.58511052878,-35.79335631201,45.559483424545,2,1,18 +2025-03-11T12:43:29.401473,479393008,65222,252,-23.83013435302,-36.02483385744,45.99053306185,2,1,18 +2025-03-11T12:43:29.417098,479393008,65222,252,-24.07044618064,-36.265545393555,46.435476547345,2,1,18 +2025-03-11T12:43:29.432723,479393008,65222,252,-24.30604601164,-36.497006633055,46.861891439575,2,1,18 +2025-03-11T12:43:29.448348,479393008,65222,252,-24.54164584264,-36.728467872555,47.29292751487,2,1,18 +2025-03-11T12:43:29.463973,479393008,65222,252,-24.77724567364,-36.96455018388,47.72860331323,2,1,18 +2025-03-11T12:43:29.479598,479393008,65222,252,-24.99870951478,-37.20060803631,48.14115285325,2,1,18 +2025-03-11T12:43:29.495223,479393008,65222,252,-25.22017335592,-37.45515017604,48.558397736335,2,1,18 +2025-03-11T12:43:29.510848,479393008,65222,252,-25.46048518354,-37.68199849668,48.96631613731,2,1,18 +2025-03-11T12:43:29.526473,479393008,65222,252,-25.70550900778,-37.908854970285,49.39272605155,2,1,18 +2025-03-11T12:43:29.542098,479393008,65222,252,-25.93168484554,-38.121815616555,49.823674404835,2,1,18 +2025-03-11T12:43:29.557723,479393008,65222,252,-26.15314868668,-38.348631325335,50.226944498725,2,1,18 +2025-03-11T12:43:29.573348,479393008,65222,252,-26.36518853458,-38.57080965636,50.6440460398,2,1,18 +2025-03-11T12:43:29.588973,479393008,65222,252,-26.58665237572,-38.79762536514,51.05655849982,2,1,18 +2025-03-11T12:43:29.604598,479393008,65222,252,-26.80340422024,-39.01981184913,51.44593972351,2,1,18 +2025-03-11T12:43:29.620223,479393008,65222,252,-27.02015606476,-39.24199833312,51.85380567946,2,1,18 +2025-03-11T12:43:29.635848,479393008,65222,252,-27.24633190252,-39.45495897939,52.257026934355,2,1,18 +2025-03-11T12:43:29.651473,479393008,65222,252,-27.48664373014,-39.667944084555,52.660268532265,2,1,18 +2025-03-11T12:43:29.667098,479393008,65222,252,-27.70810757128,-39.876275506035,53.04960091696,2,1,18 +2025-03-11T12:43:29.682723,479393008,65222,252,-27.9248594158,-40.116946277325,53.434435117585,2,1,18 +2025-03-11T12:43:29.698348,479393008,65222,252,-28.13218726708,-40.34373752721,53.823821319265,2,1,18 +2025-03-11T12:43:29.713973,479393008,65222,252,-28.33951511836,-40.552044489795,54.213133360945,2,1,18 +2025-03-11T12:43:29.729598,479393008,65222,252,-28.54213097302,-40.769585443065,54.59323333549,2,1,18 +2025-03-11T12:43:29.745223,479393008,65222,252,-28.7494588243,-40.973271333825,54.987148020235,2,1,18 +2025-03-11T12:43:29.760848,479393008,65222,252,-28.97092266544,-41.172360611655,55.3672009588,2,1,18 +2025-03-11T12:43:29.776473,479393008,65222,252,-29.18767450996,-41.376062808345,55.724159741035,2,1,18 +2025-03-11T12:43:29.792098,479393008,65222,252,-29.39029036462,-41.60746697709,56.09507296945,2,1,18 +2025-03-11T12:43:29.807723,479393008,65222,252,-29.5976182159,-41.806531796025,56.475105565,2,1,18 +2025-03-11T12:43:29.823348,479393008,65222,252,-29.80023407056,-42.01020953382,56.836665187285,2,1,18 +2025-03-11T12:43:29.838973,479393008,65222,252,-30.01227391846,-42.195419290245,57.212027760775,2,1,18 +2025-03-11T12:43:29.854598,479393008,65222,252,-30.21488977312,-42.394475956215,57.58281120919,2,1,18 +2025-03-11T12:43:29.870223,479393008,65222,252,-30.41279363116,-42.58428232557,57.948929613535,2,1,18 +2025-03-11T12:43:29.885848,479393008,65222,252,-30.60127349596,-42.774072388995,58.30579208974,2,1,18 +2025-03-11T12:43:29.901473,479393008,65222,252,-30.78504136414,-42.96847537128,58.67190869107,2,1,18 +2025-03-11T12:43:29.917098,479393008,65222,252,-30.97352122894,-43.176749722005,59.019602961145,2,1,18 +2025-03-11T12:43:29.932723,479393008,65222,252,-31.16671309036,-43.38965329752,59.376564918355,2,1,18 +2025-03-11T12:43:29.948348,479393008,65222,252,-31.35519295516,-43.579443360945,59.738048577625,2,1,18 +2025-03-11T12:43:29.963973,479393008,65222,252,-31.54367281996,-43.75074913707,60.09483689383,2,1,18 +2025-03-11T12:43:29.979598,479393008,65222,252,-31.741576678,-43.931313362775,60.43781230285,2,1,18 +2025-03-11T12:43:29.995178,479393012,65219,253,-31.91592055294,-44.12570003913,60.762324694585,2,1,18 +2025-03-11T12:43:30.010803,479393012,65219,253,-32.10911241436,-44.31549825552,61.100709219535,2,1,18 +2025-03-11T12:43:30.026428,479393012,65219,253,-32.29759227916,-44.496046175295,61.434428700415,2,1,18 +2025-03-11T12:43:30.042053,479393012,65219,253,-32.48136014734,-44.69044915758,61.75895465416,2,1,18 +2025-03-11T12:43:30.057678,479393012,65219,253,-32.6604160189,-44.87560184325,62.0834367469,2,1,18 +2025-03-11T12:43:30.073303,479393012,65219,253,-32.8488958837,-45.056149763025,62.39867149552,2,1,18 +2025-03-11T12:43:30.088928,479393012,65219,253,-33.0138157654,-45.23203584615,62.732338531375,2,1,18 +2025-03-11T12:43:30.104553,479393012,65219,253,-33.2022956302,-45.4079626941,63.066039472255,2,1,18 +2025-03-11T12:43:30.120178,479393012,65219,253,-33.38135150176,-45.579252164295,63.362738846605,2,1,18 +2025-03-11T12:43:30.135803,479393012,65219,253,-33.54155938684,-45.74126687898,63.6639952,2,1,18 +2025-03-11T12:43:30.151428,479393012,65219,253,-33.70647926854,-45.91253189028,63.97453778053,2,1,18 +2025-03-11T12:43:30.167053,479393012,65219,253,-33.88082314348,-46.08381320751,64.298957472265,2,1,18 +2025-03-11T12:43:30.182678,479393012,65219,253,-34.04574302518,-46.25507821881,64.60487886973,2,1,18 +2025-03-11T12:43:30.198303,479393012,65219,253,-34.20595091026,-46.42171400532,64.90153258006,2,1,18 +2025-03-11T12:43:30.213928,479393012,65219,253,-34.36615879534,-46.592970863655,65.193583647325,2,1,18 +2025-03-11T12:43:30.229553,479393012,65219,253,-34.53579067366,-46.750380812445,65.490213839665,2,1,18 +2025-03-11T12:43:30.245178,479393012,65219,253,-34.69128656212,-46.893903086865,65.77752570286,2,1,18 +2025-03-11T12:43:30.260803,479393012,65219,253,-34.86563043706,-47.05132118862,66.06954149314,2,1,18 +2025-03-11T12:43:30.276428,479393012,65219,253,-35.02583832214,-47.222578046955,66.361592560405,2,1,18 +2025-03-11T12:43:30.292053,479393012,65219,253,-35.17662221398,-47.389197527535,66.65361152566,2,1,18 +2025-03-11T12:43:30.307678,479393012,65219,253,-35.34154209568,-47.53735717971,66.950197856995,2,1,18 +2025-03-11T12:43:30.323303,479393012,65219,253,-35.49703798414,-47.68087945413,67.223646170995,2,1,18 +2025-03-11T12:43:30.338928,479393012,65219,253,-35.6289738895,-47.82898203555,67.47859438771,2,1,18 +2025-03-11T12:43:30.354553,479393012,65219,253,-35.76562179148,-47.995577057235,67.76135064382,2,1,18 +2025-03-11T12:43:30.370178,479393012,65219,253,-35.92582967656,-48.13910748462,68.025563372695,2,1,18 +2025-03-11T12:43:30.385803,479393012,65219,253,-36.08132556502,-48.28262975904,68.27590577137,2,1,18 +2025-03-11T12:43:30.401428,479393012,65219,253,-36.22739746024,-48.42613572753,68.54009815723,2,1,18 +2025-03-11T12:43:30.417053,479393012,65219,253,-36.36875735884,-48.55577032758,68.79036459289,2,1,18 +2025-03-11T12:43:30.432678,479393012,65219,253,-36.49126927096,-48.689993387595,69.04986481066,2,1,18 +2025-03-11T12:43:30.448303,479393012,65219,253,-36.62320517632,-48.83347489719,69.30017330431,2,1,18 +2025-03-11T12:43:30.463928,479393012,65219,253,-36.77870106478,-48.981618243435,69.55515542605,2,1,18 +2025-03-11T12:43:30.479553,479393012,65219,253,-36.92948495662,-49.120511293065,69.810093686785,2,1,18 +2025-03-11T12:43:30.495178,479393012,65219,253,-37.05199686874,-49.26397649673,70.051146252295,2,1,18 +2025-03-11T12:43:30.510803,479393012,65219,253,-37.18864477072,-49.39822401564,70.30142444695,2,1,18 +2025-03-11T12:43:30.526428,479393012,65219,253,-37.31115668284,-49.541689219305,70.54247701246,2,1,18 +2025-03-11T12:43:30.542053,479393012,65219,253,-37.4430925882,-49.671307513425,70.760381604655,2,1,18 +2025-03-11T12:43:30.557678,479393012,65219,253,-37.57502849356,-49.78706259207,70.992094126045,2,1,18 +2025-03-11T12:43:30.573303,479393012,65219,253,-37.69754040568,-49.902801364785,71.242277817685,2,1,18 +2025-03-11T12:43:30.588928,479393012,65219,253,-37.82476431442,-50.01392721864,71.47396501807,2,1,18 +2025-03-11T12:43:30.604553,479393012,65219,253,-37.92842824006,-50.138875523145,71.673325651975,2,1,18 +2025-03-11T12:43:30.620178,479393012,65219,253,-38.02738016908,-50.254573531035,71.88650597407,2,1,18 +2025-03-11T12:43:30.635803,479393012,65219,253,-38.15460407782,-50.379562600365,72.12286997752,2,1,18 +2025-03-11T12:43:30.651428,479393012,65219,253,-38.2676919967,-50.490663995325,72.340673285695,2,1,18 +2025-03-11T12:43:30.667053,479393012,65219,253,-38.3854919122,-50.60177354325,72.539998642615,2,1,18 +2025-03-11T12:43:30.682678,479393012,65219,253,-38.5032918277,-50.722125234825,72.72549753034,2,1,18 +2025-03-11T12:43:30.698303,479393012,65219,253,-38.61166774996,-50.82397633317,72.920151062185,2,1,18 +2025-03-11T12:43:30.713928,479393012,65219,253,-38.72004367222,-50.925827431515,73.137910509355,2,1,18 +2025-03-11T12:43:30.729553,479393012,65219,253,-38.82841959448,-51.023057458035,73.32330313507,2,1,18 +2025-03-11T12:43:30.745178,479393012,65219,253,-38.94150751336,-51.12029563752,73.49946017566,2,1,18 +2025-03-11T12:43:30.760803,479393012,65219,253,-39.04988343562,-51.25449423864,73.685001121375,2,1,18 +2025-03-11T12:43:30.776428,479393012,65219,253,-39.15354736126,-51.360958255845,73.870424046085,2,1,18 +2025-03-11T12:43:30.792053,479393012,65219,253,-39.24778729366,-51.44892167982,74.05113806572,2,1,18 +2025-03-11T12:43:30.807678,479393012,65219,253,-39.33731522944,-51.532255879005,74.236447947415,2,1,18 +2025-03-11T12:43:30.823303,479393012,65219,253,-39.43626715846,-51.63409067142,74.417224368055,2,1,18 +2025-03-11T12:43:30.838928,479393012,65219,253,-39.52108309762,-51.731279933115,74.59796190568,2,1,18 +2025-03-11T12:43:30.854553,479393012,65219,253,-39.59647504354,-51.84693717618,74.760275309035,2,1,18 +2025-03-11T12:43:30.870178,479393012,65219,253,-39.69071497594,-51.93027952833,74.91324369028,2,1,18 +2025-03-11T12:43:30.885803,479393012,65219,253,-39.79437890158,-51.999774970935,75.06154883047,2,1,18 +2025-03-11T12:43:30.901428,479393012,65219,253,-39.88390683736,-52.07386702647,75.237579266035,2,1,18 +2025-03-11T12:43:30.917053,479393012,65219,253,-39.9640107799,-52.166427063375,75.40442793346,2,1,18 +2025-03-11T12:43:30.932678,479393012,65219,253,-40.03940272582,-52.249736803665,75.55274800762,2,1,18 +2025-03-11T12:43:30.948303,479393012,65219,253,-40.11008267512,-52.32379624734,75.68716067158,2,1,18 +2025-03-11T12:43:30.963928,479393012,65219,253,-40.19489861428,-52.402501221735,75.812369852425,2,1,18 +2025-03-11T12:43:30.979553,479393012,65219,253,-40.2702905602,-52.4811898902,75.951429020455,2,1,18 +2025-03-11T12:43:30.995178,479393012,65219,253,-40.34568250612,-52.550636415015,76.108935840745,2,1,18 +2025-03-11T12:43:31.010803,479393012,65219,253,-40.42107445204,-52.633946155305,76.24339236571,2,1,18 +2025-03-11T12:43:31.026428,479393012,65219,253,-40.49646639796,-52.689529464645,76.35463173535,2,1,18 +2025-03-11T12:43:31.042053,479393012,65219,253,-40.56243435064,-52.745096468055,76.47509990911,2,1,18 +2025-03-11T12:43:31.057678,479393012,65219,253,-40.61426631346,-52.82836544352,76.586416613725,2,1,18 +2025-03-11T12:43:31.073303,479393012,65219,253,-40.694370256,-52.902441193125,76.69773692437,2,1,18 +2025-03-11T12:43:31.088928,479393012,65219,253,-40.75562621206,-52.95800004357,76.81357713406,2,1,18 +2025-03-11T12:43:31.104553,479393012,65219,253,-40.80745817488,-53.00892151626,76.915521692545,2,1,18 +2025-03-11T12:43:31.120178,479393012,65219,253,-40.86400213432,-53.07371435739,77.01290746897,2,1,18 +2025-03-11T12:43:31.135803,479393012,65219,253,-40.92525809038,-53.147757495135,77.1103371064,2,1,18 +2025-03-11T12:43:31.151428,479393012,65219,253,-40.99122604306,-53.203324498545,77.23080528016,2,1,18 +2025-03-11T12:43:31.167053,479393012,65219,253,-41.04305800588,-53.26810918671,77.332805458645,2,1,18 +2025-03-11T12:43:31.182678,479393012,65219,253,-41.09960196532,-53.319038812365,77.416272065875,2,1,18 +2025-03-11T12:43:31.198303,479393012,65219,253,-41.13729793828,-53.356072610685,77.508898295215,2,1,18 +2025-03-11T12:43:31.213928,479393012,65219,253,-41.17499391124,-53.38848533718,77.592263618425,2,1,18 +2025-03-11T12:43:31.229553,479393012,65219,253,-41.23153787068,-53.42555174736,77.666432239525,2,1,18 +2025-03-11T12:43:31.245178,479393012,65219,253,-41.27394584026,-53.462593698645,77.763686432935,2,1,18 +2025-03-11T12:43:31.260803,479393012,65219,253,-41.3304897997,-53.5135233243,77.8425318571,2,1,18 +2025-03-11T12:43:31.276428,479393012,65219,253,-41.37289776928,-53.56442849106,77.92135693825,2,1,18 +2025-03-11T12:43:31.292053,479393012,65219,253,-41.41059374224,-53.60146228938,77.99549843533,2,1,18 +2025-03-11T12:43:31.307678,479393012,65219,253,-41.43886572196,-53.633858709945,78.046501915075,2,1,18 +2025-03-11T12:43:31.323303,479393012,65219,253,-41.4718496983,-53.657021139825,78.097475095825,2,1,18 +2025-03-11T12:43:31.338928,479393012,65219,253,-41.50954567126,-53.69867600997,78.16701394984,2,1,18 +2025-03-11T12:43:31.354553,479393012,65219,253,-41.54724164422,-53.74495195194,78.245813709985,2,1,18 +2025-03-11T12:43:31.370178,479393012,65219,253,-41.58022562056,-53.75887223817,78.3013709938,2,1,18 +2025-03-11T12:43:31.385803,479393012,65219,253,-41.60378560366,-53.777397290295,78.34306970641,2,1,18 +2025-03-11T12:43:31.401428,479393012,65219,253,-41.62263359014,-53.80053526128,78.37091662882,2,1,18 +2025-03-11T12:43:31.417053,479393012,65219,253,-41.65561756648,-53.837560906635,78.398839514245,2,1,18 +2025-03-11T12:43:31.432678,479393012,65219,253,-41.67917754958,-53.86532810241,78.43595412379,2,1,18 +2025-03-11T12:43:31.448303,479393012,65219,253,-41.7074495293,-53.8838613075,78.48228080047,2,1,18 +2025-03-11T12:43:31.463928,479393012,65219,253,-41.71216152592,-53.88849053229,78.5054120368,2,1,18 +2025-03-11T12:43:31.479553,479393012,65219,253,-41.72629751578,-53.888514991185,78.52853829514,2,1,18 +2025-03-11T12:43:31.495178,479393012,65219,253,-41.72629751578,-53.897757134835,78.560923656595,2,1,18 +2025-03-11T12:43:31.510803,479393012,65219,253,-41.7310095124,-53.911628503275,78.565607240665,2,1,18 +2025-03-11T12:43:31.526428,479393012,65219,253,-41.73572150902,-53.93012094354,78.55644581554,2,1,18 +2025-03-11T12:43:31.542053,479393012,65219,253,-41.73572150902,-53.93012094354,78.561066998605,2,1,18 +2025-03-11T12:43:31.557678,479393012,65219,253,-41.74514550226,-53.93013724947,78.59342884207,2,1,18 +2025-03-11T12:43:31.573303,479393012,65219,253,-41.7545694955,-53.93939569905,78.60272185021,2,1,18 +2025-03-11T12:43:31.588928,479393012,65219,253,-41.75928149212,-53.930161708365,78.602691551215,2,1,18 +2025-03-11T12:43:31.604553,479393012,65219,253,-41.74985749888,-53.911661115135,78.602603829205,2,1,18 +2025-03-11T12:43:31.620178,479393012,65219,253,-41.74514550226,-53.916274033995,78.607236771265,2,1,18 +2025-03-11T12:43:31.635803,479393012,65219,253,-41.74985749888,-53.911661115135,78.584119096945,2,1,18 +2025-03-11T12:43:31.651428,479393012,65219,253,-41.74514550226,-53.90241081852,78.55634813755,2,1,18 +2025-03-11T12:43:31.667053,479393012,65219,253,-41.72629751578,-53.897757134835,78.551681290465,2,1,18 +2025-03-11T12:43:31.682678,479393012,65219,253,-41.71216152592,-53.89773267594,78.54241858132,2,1,18 +2025-03-11T12:43:31.698303,479393012,65219,253,-41.7074495293,-53.888482379325,78.514647621925,2,1,18 +2025-03-11T12:43:31.713928,479393012,65219,253,-41.69331353944,-53.856110417655,78.472906851325,2,1,18 +2025-03-11T12:43:31.729553,479393012,65219,253,-41.66504155972,-53.837577212565,78.435822540775,2,1,18 +2025-03-11T12:43:31.745178,479393012,65219,253,-41.6603295631,-53.823705844125,78.41727540751,2,1,18 +2025-03-11T12:43:31.760803,479393012,65219,253,-41.65090556986,-53.80982632272,78.37099439485,2,1,18 +2025-03-11T12:43:31.776428,479393012,65219,253,-41.6132095969,-53.80051895535,78.31544887003,2,1,18 +2025-03-11T12:43:31.792053,479393012,65219,253,-41.5896496138,-53.76813068775,78.287558086615,2,1,18 +2025-03-11T12:43:31.807678,479393012,65219,253,-41.5660896307,-53.740363491975,78.227337561745,2,1,18 +2025-03-11T12:43:31.823303,479393012,65219,253,-41.51425766788,-53.69406309111,78.18086574004,2,1,18 +2025-03-11T12:43:31.838928,479393012,65219,253,-41.48127369154,-53.657037445755,78.11135220703,2,1,18 +2025-03-11T12:43:31.854553,479393012,65219,253,-41.45300171182,-53.629262097015,78.04650371809,2,1,18 +2025-03-11T12:43:31.870178,479393012,65219,253,-41.42001773548,-53.587615379835,77.99545637734,2,1,18 +2025-03-11T12:43:31.885803,479393012,65219,253,-41.36818577266,-53.545936050795,77.930518363375,2,1,18 +2025-03-11T12:43:31.901428,479393012,65219,253,-41.34933778618,-53.508934864335,77.847161624185,2,1,18 +2025-03-11T12:43:31.917053,479393012,65219,253,-41.3069298166,-53.476513984875,77.7730318861,2,1,18 +2025-03-11T12:43:31.932678,479393012,65219,253,-41.26452184702,-53.444093105415,77.69428096495,2,1,18 +2025-03-11T12:43:31.948303,479393012,65219,253,-41.22682587406,-53.397817163445,77.61086002174,2,1,18 +2025-03-11T12:43:31.963928,479393012,65219,253,-41.17028191462,-53.34688753779,77.522772231445,2,1,18 +2025-03-11T12:43:31.979553,479393012,65219,253,-41.12316194842,-53.277489930765,77.43462384316,2,1,18 +2025-03-11T12:43:31.995178,479393012,65219,253,-41.08075397884,-53.23120583583,77.34657493588,2,1,18 +2025-03-11T12:43:32.010803,479393012,65219,253,-41.0242100194,-53.189518353825,77.24466067639,2,1,18 +2025-03-11T12:43:32.026428,479393012,65219,253,-40.96766605996,-53.124725512695,77.156517266095,2,1,18 +2025-03-11T12:43:32.042053,479393012,65219,253,-40.92054609376,-53.069191121145,77.063803314745,2,1,18 +2025-03-11T12:43:32.057678,479393012,65219,253,-40.87342612756,-53.022898873245,76.9572628942,2,1,18 +2025-03-11T12:43:32.073303,479393012,65219,253,-40.80745817488,-52.96271079801,76.84601854657,2,1,18 +2025-03-11T12:43:32.088928,479393012,65219,253,-40.7414902222,-52.89790165095,76.739376842005,2,1,18 +2025-03-11T12:43:32.104553,479393012,65219,253,-40.67552226952,-52.828471432065,76.618853048245,2,1,18 +2025-03-11T12:43:32.120178,479393012,65219,253,-40.60484232022,-52.759033060215,76.493701290415,2,1,18 +2025-03-11T12:43:32.135803,479393012,65219,253,-40.53887436754,-52.694223913155,76.382438402785,2,1,18 +2025-03-11T12:43:32.151428,479393012,65219,253,-40.4823304081,-52.638673215675,76.25736260797,2,1,18 +2025-03-11T12:43:32.167053,479393012,65219,253,-40.4116504588,-52.569234843825,76.11372611788,2,1,18 +2025-03-11T12:43:32.182678,479393012,65219,253,-40.3409705095,-52.472070041025,75.974599570855,2,1,18 +2025-03-11T12:43:32.198303,479393012,65219,253,-40.26086656696,-52.374888932295,75.82621709569,2,1,18 +2025-03-11T12:43:32.213928,479393012,65219,253,-40.18547462104,-52.30544240748,75.67795264153,2,1,18 +2025-03-11T12:43:32.229553,479393012,65219,253,-40.11008267512,-52.235995882665,75.51120345511,2,1,18 +2025-03-11T12:43:32.245178,479393012,65219,253,-40.02526673596,-52.14804876462,75.367472462005,2,1,18 +2025-03-11T12:43:32.260803,479393012,65219,253,-39.9404507968,-52.0647227184,75.228381191965,2,1,18 +2025-03-11T12:43:32.276428,479393012,65219,253,-39.8462108644,-51.976759294425,75.061530721525,2,1,18 +2025-03-11T12:43:32.292053,479393012,65219,253,-39.76610692186,-51.879578185695,74.8946635141,2,1,18 +2025-03-11T12:43:32.307678,479393012,65219,253,-39.67657898608,-51.791622914685,74.75092573999,2,1,18 +2025-03-11T12:43:32.323303,479393012,65219,253,-39.5870510503,-51.69904657185,74.593305876685,2,1,18 +2025-03-11T12:43:32.338928,479393012,65219,253,-39.4928111179,-51.6157042197,74.407989213985,2,1,18 +2025-03-11T12:43:32.354553,479393012,65219,253,-39.39385918888,-51.52773264276,74.218026047215,2,1,18 +2025-03-11T12:43:32.370178,479393012,65219,253,-39.29961925648,-51.449011362435,74.041970290645,2,1,18 +2025-03-11T12:43:32.385803,479393012,65219,253,-39.19124333422,-51.351781335915,73.86582003106,2,1,18 +2025-03-11T12:43:32.401428,479393012,65219,253,-39.09700340182,-51.240712552815,73.694255677555,2,1,18 +2025-03-11T12:43:32.417053,479393012,65219,253,-39.00747546604,-51.134272994505,73.49961072973,2,1,18 +2025-03-11T12:43:32.432678,479393012,65219,253,-38.90852353702,-51.027817130265,73.31881576909,2,1,18 +2025-03-11T12:43:32.448303,479393012,65219,253,-38.80014761476,-50.92596603192,73.124162237245,2,1,18 +2025-03-11T12:43:32.463928,479393012,65219,253,-38.6917716925,-50.81949386175,72.924868982335,2,1,18 +2025-03-11T12:43:32.479553,479393012,65219,253,-38.59281976348,-50.689932638385,72.73936013863,2,1,18 +2025-03-11T12:43:32.495178,479393012,65219,253,-38.48444384122,-50.583460468215,72.535445700655,2,1,18 +2025-03-11T12:43:32.510803,479393012,65219,253,-38.38077991558,-50.48623859466,72.31771157449,2,1,18 +2025-03-11T12:43:32.526428,479393012,65219,253,-38.2676919967,-50.379758271525,72.099926806315,2,1,18 +2025-03-11T12:43:32.542053,479393012,65219,253,-38.13575609134,-50.268624264705,71.895959923315,2,1,18 +2025-03-11T12:43:32.557678,479393012,65219,253,-38.00382018598,-50.14362704241,71.682695054185,2,1,18 +2025-03-11T12:43:32.573303,479393012,65219,253,-37.8907322671,-50.000178144675,71.478625515205,2,1,18 +2025-03-11T12:43:32.588928,479393012,65219,253,-37.77764434822,-49.86597139059,71.237623591705,2,1,18 +2025-03-11T12:43:32.604553,479393012,65219,253,-37.64570844286,-49.750216311945,71.01977461951,2,1,18 +2025-03-11T12:43:32.620178,479393012,65219,253,-37.52319653074,-49.61599325193,70.79724386626,2,1,18 +2025-03-11T12:43:32.635803,479393012,65219,253,-37.395972622,-49.50024632625,70.56091694281,2,1,18 +2025-03-11T12:43:32.651428,479393012,65219,253,-37.26403671664,-49.375249103955,70.31068260916,2,1,18 +2025-03-11T12:43:32.667053,479393012,65219,253,-37.13210081128,-49.24100973801,70.07889592777,2,1,18 +2025-03-11T12:43:32.682678,479393012,65219,253,-37.00958889916,-49.106786677995,69.833259259195,2,1,18 +2025-03-11T12:43:32.698303,479393012,65219,253,-36.87294099718,-48.972539159085,69.59222343067,2,1,18 +2025-03-11T12:43:32.713928,479393012,65219,253,-36.72686910196,-48.83365426242,69.341913134005,2,1,18 +2025-03-11T12:43:32.729553,479393012,65219,253,-36.5949331966,-48.69479382465,69.091623180355,2,1,18 +2025-03-11T12:43:32.745178,479393012,65219,253,-36.453573298,-48.5466749373,68.8274190355,2,1,18 +2025-03-11T12:43:32.760803,479393012,65219,253,-36.32163739264,-48.40781449953,68.56788671572,2,1,18 +2025-03-11T12:43:32.776428,479393012,65219,253,-36.17556549742,-48.27355067469,68.317594959055,2,1,18 +2025-03-11T12:43:32.792053,479393012,65219,253,-36.02478160558,-48.130036553235,68.058016975255,2,1,18 +2025-03-11T12:43:32.807678,479393012,65219,253,-35.88342170698,-47.981917665885,67.78457046427,2,1,18 +2025-03-11T12:43:32.823303,479393012,65219,253,-35.73263781514,-47.833782472605,67.511110391275,2,1,18 +2025-03-11T12:43:32.838928,479393012,65219,253,-35.59127791654,-47.68104251343,67.233024157225,2,1,18 +2025-03-11T12:43:32.854553,479393012,65219,253,-35.42635803484,-47.523640717605,66.95488547815,2,1,18 +2025-03-11T12:43:32.870178,479393012,65219,253,-35.26615014976,-47.36162600292,66.681356223145,2,1,18 +2025-03-11T12:43:32.885803,479393012,65219,253,-35.1106542613,-47.204240513025,66.389367556885,2,1,18 +2025-03-11T12:43:32.901428,479393012,65219,253,-34.95515837284,-47.04685502313,66.10200007369,2,1,18 +2025-03-11T12:43:32.917053,479393012,65219,253,-34.79966248438,-46.87560631776,65.80995578743,2,1,18 +2025-03-11T12:43:32.932678,479393012,65219,253,-34.63474260268,-46.73206773741,65.50876681303,2,1,18 +2025-03-11T12:43:32.948303,479393012,65219,253,-34.46982272098,-46.574665941585,65.212143401695,2,1,18 +2025-03-11T12:43:32.963928,479393012,65219,253,-34.3096148359,-46.4126512269,64.93861414669,2,1,18 +2025-03-11T12:43:32.979553,479393012,65219,253,-34.13527096096,-46.24136990967,64.64654273641,2,1,18 +2025-03-11T12:43:32.995178,479393012,65219,253,-33.97035107926,-46.07010489837,64.340621338945,2,1,18 +2025-03-11T12:43:33.010803,479393012,65219,253,-33.81014319418,-45.88498482456,64.043893468615,2,1,18 +2025-03-11T12:43:33.026428,479393012,65219,253,-33.6499353091,-45.713727966225,63.728736486025,2,1,18 +2025-03-11T12:43:33.042053,479393012,65219,253,-33.48972742402,-45.56095539519,63.4182748465,2,1,18 +2025-03-11T12:43:33.057678,479393012,65219,253,-33.31538354908,-45.394295149785,63.093873694765,2,1,18 +2025-03-11T12:43:33.073303,479393012,65219,253,-33.13632767752,-45.21376353594,62.76478895896,2,1,18 +2025-03-11T12:43:33.088928,479393012,65219,253,-32.95255980934,-45.02398162548,62.43566036215,2,1,18 +2025-03-11T12:43:33.104553,479393012,65219,253,-32.78292793102,-44.84808738939,62.10198654529,2,1,18 +2025-03-11T12:43:33.120178,479393012,65219,253,-32.60387205946,-44.658313631895,61.74975881416,2,1,18 +2025-03-11T12:43:33.135803,479393012,65219,253,-32.41539219466,-44.48700785577,61.42531877941,2,1,18 +2025-03-11T12:43:33.151428,479393012,65219,253,-32.2363363231,-44.306476241925,61.114718775865,2,1,18 +2025-03-11T12:43:33.167053,479393012,65219,253,-32.06199244816,-44.107468493745,60.794809027195,2,1,18 +2025-03-11T12:43:33.182678,479393012,65219,253,-31.87822457998,-43.899202295985,60.437879171995,2,1,18 +2025-03-11T12:43:33.198303,479393012,65219,253,-31.68974471518,-43.71865437621,60.09029614192,2,1,18 +2025-03-11T12:43:33.213928,479393012,65219,253,-31.49655285376,-43.533477231645,59.728824241645,2,1,18 +2025-03-11T12:43:33.229553,479393012,65219,253,-31.29864899572,-43.348291934115,59.385830292625,2,1,18 +2025-03-11T12:43:33.245178,479393012,65219,253,-31.11488112754,-43.149267880005,59.038179883555,2,1,18 +2025-03-11T12:43:33.260803,479393012,65219,253,-30.92168926612,-42.95484859179,58.672049720215,2,1,18 +2025-03-11T12:43:33.276428,479393012,65219,253,-30.7284974047,-42.77429251905,58.31983872607,2,1,18 +2025-03-11T12:43:33.292053,479393012,65219,253,-30.53059354666,-42.58910722152,57.97684477705,2,1,18 +2025-03-11T12:43:33.307678,479393012,65219,253,-30.327977692,-42.376187340075,57.6106268917,2,1,18 +2025-03-11T12:43:33.323303,479393012,65219,253,-30.1394978272,-42.172534061175,57.244466429365,2,1,18 +2025-03-11T12:43:33.338928,479393012,65219,253,-29.93688197254,-41.97809846703,56.88294388708,2,1,18 +2025-03-11T12:43:33.354553,479393012,65219,253,-29.7389781145,-41.769807810375,56.5213725058,2,1,18 +2025-03-11T12:43:33.370178,479393012,65219,253,-29.53165026322,-41.56150084779,56.15978756251,2,1,18 +2025-03-11T12:43:33.385803,479393012,65219,253,-29.32903440856,-41.35320203817,55.78434585103,2,1,18 +2025-03-11T12:43:33.401428,479393012,65219,253,-29.11699456066,-41.14488692262,55.413511760605,2,1,18 +2025-03-11T12:43:33.417053,479393012,65219,253,-28.90024271614,-40.945805797755,55.03808678611,2,1,18 +2025-03-11T12:43:33.432678,479393012,65219,253,-28.678778875,-40.718990088975,54.65330142448,2,1,18 +2025-03-11T12:43:33.448303,479393012,65219,253,-28.47145102372,-40.524546341865,54.27328736893,2,1,18 +2025-03-11T12:43:33.463928,479393012,65219,253,-28.25941117582,-40.32085229814,53.86088117092,2,1,18 +2025-03-11T12:43:33.479553,479393012,65219,253,-28.04737132792,-40.10329503894,53.46690408517,2,1,18 +2025-03-11T12:43:33.495178,479393012,65219,253,-27.84004347664,-39.876503789055,53.082139066555,2,1,18 +2025-03-11T12:43:33.510803,479393012,65219,253,-27.62800362874,-39.65432545803,52.68352225774,2,1,18 +2025-03-11T12:43:33.526428,479393012,65219,253,-27.42538777408,-39.44602664841,52.28035344787,2,1,18 +2025-03-11T12:43:33.542053,479393012,65219,253,-27.1944999397,-39.223815705525,51.87708833197,2,1,18 +2025-03-11T12:43:33.557678,479393012,65219,253,-26.96832410194,-38.992370771955,51.46917173401,2,1,18 +2025-03-11T12:43:33.573303,479393012,65219,253,-26.75628425404,-38.765571369105,51.06591520213,2,1,18 +2025-03-11T12:43:33.588928,479393012,65219,253,-26.53010841628,-38.54798965101,50.6672965903,2,1,18 +2025-03-11T12:43:33.604553,479393012,65219,253,-26.30393257852,-38.32578686109,50.254795889275,2,1,18 +2025-03-11T12:43:33.620178,479393012,65219,253,-26.07775674076,-38.12206835847,49.828505799055,2,1,18 +2025-03-11T12:43:33.635803,479393012,65219,253,-25.84215690976,-37.895228190795,49.420594179085,2,1,18 +2025-03-11T12:43:33.651428,479393012,65219,253,-25.615981072,-37.64992004175,49.01724314419,2,1,18 +2025-03-11T12:43:33.667053,479393012,65219,253,-25.38980523424,-37.413854036355,48.6000656401,2,1,18 +2025-03-11T12:43:33.682678,479393012,65219,253,-25.14949340662,-37.177763572065,48.15976187767,2,1,18 +2025-03-11T12:43:33.698303,479393012,65219,253,-24.92331756886,-36.937076494845,47.72408110132,2,1,18 +2025-03-11T12:43:33.713928,479393012,65219,253,-24.68771773786,-36.687130968045,47.292970866025,2,1,18 +2025-03-11T12:43:33.729553,479393012,65219,253,-24.45211790686,-36.455669728545,46.848071241535,2,1,18 +2025-03-11T12:43:33.745178,479393012,65219,253,-24.22123007248,-36.238079857485,46.417097567245,2,1,18 +2025-03-11T12:43:33.760803,479393012,65219,253,-23.99976623134,-36.011264148705,45.99996392416,2,1,18 +2025-03-11T12:43:33.776428,479393012,65219,253,-23.76416640034,-35.789045052855,45.568964928865,2,1,18 +2025-03-11T12:43:33.792053,479393012,65219,253,-23.52385457272,-35.543712444915,45.12400290337,2,1,18 +2025-03-11T12:43:33.807678,479393012,65219,253,-23.27883074848,-35.28912954036,44.688239383,2,1,18 +2025-03-11T12:43:33.823303,479393012,65219,253,-23.04323091748,-35.03918401356,44.257129147705,2,1,18 +2025-03-11T12:43:33.838928,479393012,65219,253,-22.80291908986,-34.798472477445,43.816806845275,2,1,18 +2025-03-11T12:43:33.854553,479393012,65219,253,-22.56260726224,-34.54851879768,43.357962730585,2,1,18 +2025-03-11T12:43:33.870178,479393012,65219,253,-22.31287144138,-34.307790955635,42.908384500015,2,1,18 +2025-03-11T12:43:33.885803,479393012,65219,253,-22.07727161038,-34.048603285185,42.481858367785,2,1,18 +2025-03-11T12:43:33.901428,479393012,65219,253,-21.82753578952,-33.79863329949,42.013758324955,2,1,18 +2025-03-11T12:43:33.917053,479393012,65219,253,-21.58251196528,-33.553292538585,41.55492596926,2,1,18 +2025-03-11T12:43:33.932678,479393012,65219,253,-21.34220013766,-33.31258100247,41.1053613007,2,1,18 +2025-03-11T12:43:33.948303,479393012,65219,253,-21.08304032356,-33.044110423545,40.64641590199,2,1,18 +2025-03-11T12:43:33.963928,479393012,65219,253,-20.82388050946,-32.79412413192,40.18754466328,2,1,18 +2025-03-11T12:43:33.979553,479393012,65219,253,-20.56000869874,-32.548750759155,39.728685183565,2,1,18 +2025-03-11T12:43:33.995101,479393016,65214,254,-20.31027287788,-32.28953862981,39.269790426865,2,1,18 +2025-03-11T12:43:34.010726,479393016,65214,254,-20.06053705702,-32.030326500465,38.801653304035,2,1,18 +2025-03-11T12:43:34.026351,479393016,65214,254,-19.7966652463,-31.7664688404,38.328856115125,2,1,18 +2025-03-11T12:43:34.041976,479393016,65214,254,-19.53279343558,-31.50723225216,37.856077466215,2,1,18 +2025-03-11T12:43:34.057601,479393016,65214,254,-19.2783456181,-31.252633041675,37.37870973625,2,1,18 +2025-03-11T12:43:34.073226,479393016,65214,254,-19.02389780062,-30.984170615715,36.91514993548,2,1,18 +2025-03-11T12:43:34.088851,479393016,65214,254,-18.77416197976,-30.72495848637,36.451633995715,2,1,18 +2025-03-11T12:43:34.104476,479393016,65214,254,-18.5244261589,-30.456504213375,35.983459792885,2,1,18 +2025-03-11T12:43:34.120101,479393016,65214,254,-18.25113035494,-30.206493462855,35.501462295835,2,1,18 +2025-03-11T12:43:34.135726,479393016,65214,254,-17.9825465476,-29.933385506175,35.01937887979,2,1,18 +2025-03-11T12:43:34.151351,479393016,65214,254,-17.70453874702,-29.669503387215,34.528076615605,2,1,18 +2025-03-11T12:43:34.166976,479393016,65214,254,-17.43595493968,-29.414879717835,34.041446176495,2,1,18 +2025-03-11T12:43:34.182601,479393016,65214,254,-17.17208312896,-29.137158842295,33.56397218452,2,1,18 +2025-03-11T12:43:34.198226,479393016,65214,254,-16.898787325,-28.8732848763,33.068055518275,2,1,18 +2025-03-11T12:43:34.213851,479393016,65214,254,-16.63020351766,-28.614040135095,32.5767853561,2,1,18 +2025-03-11T12:43:34.229476,479393016,65214,254,-16.37575570018,-28.35019878096,32.1040017292,2,1,18 +2025-03-11T12:43:34.245101,479393016,65214,254,-16.10717189284,-28.06784868063,31.61726005009,2,1,18 +2025-03-11T12:43:34.260726,479393016,65214,254,-15.82916409226,-27.790103346195,31.10279625058,2,1,18 +2025-03-11T12:43:34.276351,479393016,65214,254,-15.56529228154,-27.52624568613,30.606893146345,2,1,18 +2025-03-11T12:43:34.291976,479393016,65214,254,-15.2967084742,-27.27162201675,30.111020341105,2,1,18 +2025-03-11T12:43:34.307601,479393016,65214,254,-15.02341267024,-26.989263763455,29.61502951486,2,1,18 +2025-03-11T12:43:34.323226,479393016,65214,254,-14.7548288629,-26.7022925913,29.114405746555,2,1,18 +2025-03-11T12:43:34.338851,479393016,65214,254,-14.49095705218,-26.429192787585,28.623086745385,2,1,18 +2025-03-11T12:43:34.354476,479393016,65214,254,-14.21766124822,-26.14683453429,28.113232369945,2,1,18 +2025-03-11T12:43:34.370101,479393016,65214,254,-13.93494145102,-25.87832319054,27.603420052495,2,1,18 +2025-03-11T12:43:34.385726,479393016,65214,254,-13.6475096572,-25.5866983347,27.12123535243,2,1,18 +2025-03-11T12:43:34.401351,479393016,65214,254,-13.36478986,-25.322808062775,26.625305124175,2,1,18 +2025-03-11T12:43:34.416976,479393016,65214,254,-13.1056300459,-25.040474268375,26.110849908685,2,1,18 +2025-03-11T12:43:34.432601,479393016,65214,254,-12.82762224532,-24.758107862115,25.577882836915,2,1,18 +2025-03-11T12:43:34.448226,479393016,65214,254,-12.54961444474,-24.484983599505,25.054195211275,2,1,18 +2025-03-11T12:43:34.463851,479393016,65214,254,-12.26689464754,-24.19336689663,24.544290193825,2,1,18 +2025-03-11T12:43:34.479476,479393016,65214,254,-11.97946285372,-23.92022632809,24.039073738435,2,1,18 +2025-03-11T12:43:34.495101,479393016,65214,254,-11.69674305652,-23.62398855339,23.547634913245,2,1,18 +2025-03-11T12:43:34.510726,479393016,65214,254,-11.41873525594,-23.35086429078,23.0378108368,2,1,18 +2025-03-11T12:43:34.526351,479393016,65214,254,-11.13130346212,-23.073102650415,22.52333347528,2,1,18 +2025-03-11T12:43:34.541976,479393016,65214,254,-10.85329566154,-22.790736244155,22.004229952705,2,1,18 +2025-03-11T12:43:34.557601,479393016,65214,254,-10.57528786096,-22.50374876607,21.48510789013,2,1,18 +2025-03-11T12:43:34.573226,479393016,65214,254,-10.29256806376,-22.21675313502,20.97522141268,2,1,18 +2025-03-11T12:43:34.588851,479393016,65214,254,-10.00042427332,-21.934362269865,20.45609754709,2,1,18 +2025-03-11T12:43:34.604476,479393016,65214,254,-9.7129924795,-21.651979557675,19.927738096375,2,1,18 +2025-03-11T12:43:34.620101,479393016,65214,254,-9.43969667554,-21.36037916073,19.39474072561,2,1,18 +2025-03-11T12:43:34.635726,479393016,65214,254,-9.15226488172,-21.06875430489,18.86172301183,2,1,18 +2025-03-11T12:43:34.651351,479393016,65214,254,-8.86954508452,-20.79100081749,18.33338888212,2,1,18 +2025-03-11T12:43:34.666976,479393016,65214,254,-8.57268929746,-20.50860179937,17.80039468633,2,1,18 +2025-03-11T12:43:34.682601,479393016,65214,254,-8.28996950026,-20.207742952845,17.267346673555,2,1,18 +2025-03-11T12:43:34.698226,479393016,65214,254,-7.99782570982,-19.902246728565,16.7435089249,2,1,18 +2025-03-11T12:43:34.713851,479393016,65214,254,-7.710393916,-19.6060008009,16.21971503725,2,1,18 +2025-03-11T12:43:34.729476,479393016,65214,254,-7.4276741188,-19.314384098025,15.677461738345,2,1,18 +2025-03-11T12:43:34.745101,479393016,65214,254,-7.12610633512,-19.02273478329,15.15366604768,2,1,18 +2025-03-11T12:43:34.760726,479393016,65214,254,-6.82925054806,-18.73109362152,14.62987713802,2,1,18 +2025-03-11T12:43:34.776351,479393016,65214,254,-6.54653075086,-18.439476918645,14.10148738831,2,1,18 +2025-03-11T12:43:34.791976,479393016,65214,254,-6.25438696042,-18.14784390984,13.559220527395,2,1,18 +2025-03-11T12:43:34.807601,479393016,65214,254,-5.95753117336,-17.860823819895,13.035450157735,2,1,18 +2025-03-11T12:43:34.823226,479393016,65214,254,-5.65596338968,-17.56917450516,12.497790917875,2,1,18 +2025-03-11T12:43:34.838851,479393016,65214,254,-5.36853159586,-17.26830750567,11.964736124095,2,1,18 +2025-03-11T12:43:34.854476,479393016,65214,254,-5.08109980204,-16.98592479348,11.41789194112,2,1,18 +2025-03-11T12:43:34.870101,479393016,65214,254,-4.7889560116,-16.694291784675,10.875625080205,2,1,18 +2025-03-11T12:43:34.885726,479393016,65214,254,-4.49210022454,-16.38878740743,10.32867463522,2,1,18 +2025-03-11T12:43:34.901351,479393016,65214,254,-4.18582044424,-16.09712993973,9.77714506516,2,1,18 +2025-03-11T12:43:34.916976,479393016,65214,254,-3.8936766538,-15.8008758591,9.262586762635,2,1,18 +2025-03-11T12:43:34.932601,479393016,65214,254,-3.60153286336,-15.49537963482,8.72950664785,2,1,18 +2025-03-11T12:43:34.948226,479393016,65214,254,-3.29996507968,-15.18986710461,8.187170604925,2,1,18 +2025-03-11T12:43:34.963851,479393016,65214,254,-3.01724528248,-14.89362932991,7.65414113215,2,1,18 +2025-03-11T12:43:34.979476,479393016,65214,254,-2.7156774988,-14.583495727875,7.093301816965,2,1,18 +2025-03-11T12:43:34.995101,479393016,65214,254,-2.41882171174,-14.27799135063,6.55559373811,2,1,18 +2025-03-11T12:43:35.010726,479393016,65214,254,-2.13610191454,-13.99099571958,6.022601345335,2,1,18 +2025-03-11T12:43:35.026351,479393016,65214,254,-1.8439581241,-13.69474163895,5.494179493615,2,1,18 +2025-03-11T12:43:35.041976,479393016,65214,254,-1.5612383269,-13.403124936075,4.956547377775,2,1,18 +2025-03-11T12:43:35.057601,479393016,65214,254,-1.25967054322,-13.125338836815,4.418943757915,2,1,18 +2025-03-11T12:43:35.073226,479393016,65214,254,-0.9486787663,-12.83367321615,3.86740740685,2,1,18 +2025-03-11T12:43:35.088851,479393016,65214,254,-0.64711098262,-12.514297470465,3.32039456086,2,1,18 +2025-03-11T12:43:35.104476,479393016,65214,254,-0.35025519556,-12.20879309322,2.773444115875,2,1,18 +2025-03-11T12:43:35.120101,479393016,65214,254,-0.0533994085000001,-11.912530859625,2.212667201695,2,1,18 +2025-03-11T12:43:35.135726,479393016,65214,254,0.23874438194,-11.62089785082,1.67040034078,2,1,18 +2025-03-11T12:43:35.151351,479393016,65214,254,0.54031216562,-11.31538532061,1.128064297855,2,1,18 +2025-03-11T12:43:35.166976,479393016,65214,254,0.83716795268,-11.01450201519,0.604238308195,2,1,18 +2025-03-11T12:43:35.182601,479393016,65214,254,1.14344773298,-10.718223475665,0.06655374733,2,1,18 +2025-03-11T12:43:35.198226,479393016,65214,254,1.45915150652,-10.42192863021,-0.494250290870001,2,1,18 +2025-03-11T12:43:35.213851,479393016,65214,254,1.75129529696,-10.10719026228,-1.064336950175,2,1,18 +2025-03-11T12:43:35.229476,479393016,65214,254,2.04815108402,-9.81554910051,-1.606610592095,2,1,18 +2025-03-11T12:43:35.245101,479393016,65214,254,2.3497188677,-9.5100365703,-2.14894663502,2,1,18 +2025-03-11T12:43:35.260726,479393016,65214,254,2.65128665138,-9.20452404009,-2.691282677945,2,1,18 +2025-03-11T12:43:35.276351,479393016,65214,254,2.95756643168,-8.91286657239,-3.23819106494,2,1,18 +2025-03-11T12:43:35.291976,479393016,65214,254,3.23086223564,-8.61664510362,-3.789691707965,2,1,18 +2025-03-11T12:43:35.307601,479393016,65214,254,3.5277180227,-8.311140726375,-4.341263336015,2,1,18 +2025-03-11T12:43:35.323226,479393016,65214,254,3.84342179624,-8.000982665445,-4.86977471276,2,1,18 +2025-03-11T12:43:35.338851,479393016,65214,254,4.14970157654,-7.71394626957,-5.416664559755,2,1,18 +2025-03-11T12:43:35.354476,479393016,65214,254,4.43713337036,-7.42232141373,-5.96354582273,2,1,18 +2025-03-11T12:43:35.370101,479393016,65214,254,4.73398915742,-7.13068025196,-6.519683013845,2,1,18 +2025-03-11T12:43:35.385726,479393016,65214,254,5.04026893772,-6.825159568785,-7.04816228858,2,1,18 +2025-03-11T12:43:35.401351,479393016,65214,254,5.33712472478,-6.505791976065,-7.567441255175,2,1,18 +2025-03-11T12:43:35.416976,479393016,65214,254,5.6481165017,-6.200263139925,-8.132896775435,2,1,18 +2025-03-11T12:43:35.432601,479393016,65214,254,5.9308362989,-5.90864643705,-8.67515007434,2,1,18 +2025-03-11T12:43:35.448226,479393016,65214,254,6.2135560961,-5.617029734175,-9.22202455631,2,1,18 +2025-03-11T12:43:35.463851,479393016,65214,254,6.51041188316,-5.32076750058,-9.759695555165,2,1,18 +2025-03-11T12:43:35.479476,479393016,65214,254,6.81669166346,-5.024488961055,-10.31586484829,2,1,18 +2025-03-11T12:43:35.495101,479393016,65214,254,7.12768344038,-4.72358119674,-10.88130182855,2,1,18 +2025-03-11T12:43:35.510726,479393016,65214,254,7.42925122406,-4.41806866653,-11.40977432228,2,1,18 +2025-03-11T12:43:35.526351,479393016,65214,254,7.73553100436,-4.11716905518,-11.95209860621,2,1,18 +2025-03-11T12:43:35.541976,479393016,65214,254,8.02296279818,-3.81630205569,-12.50363813225,2,1,18 +2025-03-11T12:43:35.557601,479393016,65214,254,8.31981858524,-3.510797678445,-13.03672502804,2,1,18 +2025-03-11T12:43:35.573226,479393016,65214,254,8.63081036216,-3.20064777048,-13.57447198991,2,1,18 +2025-03-11T12:43:35.588851,479393016,65214,254,8.93237814584,-2.908998455745,-14.1213735959,2,1,18 +2025-03-11T12:43:35.604476,479393016,65214,254,9.21980993966,-2.608131456255,-14.66367075581,2,1,18 +2025-03-11T12:43:35.620101,479393016,65214,254,9.51666572672,-2.30262707901,-15.173651736275,2,1,18 +2025-03-11T12:43:35.635726,479393016,65214,254,9.81352151378,-2.02022806089,-15.702024749,2,1,18 +2025-03-11T12:43:35.651351,479393016,65214,254,10.11037730084,-1.714723683645,-16.267459926245,2,1,18 +2025-03-11T12:43:35.666976,479393016,65214,254,10.3836731048,-1.409260071225,-16.805134100075,2,1,18 +2025-03-11T12:43:35.682601,479393016,65214,254,10.68524088848,-1.122231828315,-17.342774799935,2,1,18 +2025-03-11T12:43:35.698226,479393016,65214,254,10.99152066878,-0.82595328879,-17.88970172693,2,1,18 +2025-03-11T12:43:35.713851,479393016,65214,254,11.29780044908,-0.538916892915,-18.43197039086,2,1,18 +2025-03-11T12:43:35.729476,479393016,65214,254,11.59465623614,-0.247275731144999,-18.97424403278,2,1,18 +2025-03-11T12:43:35.745101,479393016,65214,254,11.88208802996,0.0628334119949994,-19.511957089625,2,1,18 +2025-03-11T12:43:35.760726,479393016,65214,254,12.17894381702,0.354474573765001,-20.04960954848,2,1,18 +2025-03-11T12:43:35.776351,479393016,65214,254,12.47108760746,0.64610758257,-20.58725522633,2,1,18 +2025-03-11T12:43:35.791976,479393016,65214,254,12.7632313979,0.933119519550001,-21.14336709644,2,1,18 +2025-03-11T12:43:35.807601,479393016,65214,254,13.06008718496,1.22476068132,-21.6671560061,2,1,18 +2025-03-11T12:43:35.823226,479393016,65214,254,13.3522309754,1.525635833775,-22.18635403169,2,1,18 +2025-03-11T12:43:35.838851,479393016,65214,254,13.64437476584,1.821889914405,-22.70553351728,2,1,18 +2025-03-11T12:43:35.854476,479393016,65214,254,13.93651855628,2.118143995035,-23.238576552065,2,1,18 +2025-03-11T12:43:35.870101,479393016,65214,254,14.23337434334,2.41440622863,-23.79473228318,2,1,18 +2025-03-11T12:43:35.885726,479393016,65214,254,14.52080613716,2.692167868995,-24.332315560025,2,1,18 +2025-03-11T12:43:35.901351,479393016,65214,254,14.79881393774,2.993018562555,-24.856114425665,2,1,18 +2025-03-11T12:43:35.916976,479393016,65214,254,15.09095772818,3.29389371501,-25.384554817385,2,1,18 +2025-03-11T12:43:35.932601,479393016,65214,254,15.37367752538,3.58088934606,-25.912926027095,2,1,18 +2025-03-11T12:43:35.948226,479393016,65214,254,15.67524530906,3.863296517145,-26.43668463776,2,1,18 +2025-03-11T12:43:35.963851,479393016,65214,254,15.96267710288,4.154921372985,-26.96045998541,2,1,18 +2025-03-11T12:43:35.979476,479393016,65214,254,16.24539690008,4.42805378856,-27.484154392055,2,1,18 +2025-03-11T12:43:35.995101,479393016,65214,254,16.53754069052,4.72430786919,-28.021818609905,2,1,18 +2025-03-11T12:43:36.010726,479393016,65214,254,16.83439647758,5.020570102785,-28.527141327305,2,1,18 +2025-03-11T12:43:36.026351,479393016,65214,254,17.12654026802,5.307582039765,-29.04166254983,2,1,18 +2025-03-11T12:43:36.041976,479393016,65214,254,17.4045480686,5.59456951785,-29.5746481616,2,1,18 +2025-03-11T12:43:36.057601,479393016,65214,254,17.69197986242,5.863089014565,-30.08908844312,2,1,18 +2025-03-11T12:43:36.073226,479393016,65214,254,17.98883564948,6.15010910451,-30.617479995845,2,1,18 +2025-03-11T12:43:36.088851,479393016,65214,254,18.26684345006,6.43247551077,-31.141204701485,2,1,18 +2025-03-11T12:43:36.104476,479393016,65214,254,18.5354272574,6.7148256111,-31.65105229592,2,1,18 +2025-03-11T12:43:36.120101,479393016,65214,254,18.81343505798,7.00643416101,-32.160950532365,2,1,18 +2025-03-11T12:43:36.135726,479393016,65214,254,19.1008668518,7.302680088675,-32.68012323695,2,1,18 +2025-03-11T12:43:36.151351,479393016,65214,254,19.39301064224,7.57582881018,-33.203831205605,2,1,18 +2025-03-11T12:43:36.166976,479393016,65214,254,19.6663064462,7.858187063475,-33.71830676411,2,1,18 +2025-03-11T12:43:36.182601,479393016,65214,254,19.9490262434,8.15904591,-34.21900649543,2,1,18 +2025-03-11T12:43:36.198226,479393016,65214,254,20.2317460406,8.441420469225,-34.724253249815,2,1,18 +2025-03-11T12:43:36.213851,479393016,65214,254,20.49561785132,8.69603598564,-35.243225189375,2,1,18 +2025-03-11T12:43:36.229476,479393016,65214,254,20.7736256519,8.983023463725,-35.75310488582,2,1,18 +2025-03-11T12:43:36.245101,479393016,65214,254,21.05163345248,9.27001094181,-36.24912103307,2,1,18 +2025-03-11T12:43:36.260726,479393016,65214,254,21.32021725982,9.54311889849,-36.749689181375,2,1,18 +2025-03-11T12:43:36.276351,479393016,65214,254,21.5982250604,9.8162431611,-37.254892074755,2,1,18 +2025-03-11T12:43:36.291976,479393016,65214,254,21.87623286098,10.08012528006,-37.769300254265,2,1,18 +2025-03-11T12:43:36.307601,479393016,65214,254,22.1636646548,10.348644776775,-38.26987698659,2,1,18 +2025-03-11T12:43:36.323226,479393016,65214,254,22.43224846214,10.630994877105,-38.761239848765,2,1,18 +2025-03-11T12:43:36.338851,479393016,65214,254,22.71025626272,10.91798235519,-39.257255996015,2,1,18 +2025-03-11T12:43:36.354476,479393016,65214,254,22.97884007006,11.20033245552,-39.743997675125,2,1,18 +2025-03-11T12:43:36.370101,479393016,65214,254,23.24271188078,11.473432259235,-40.23993785936,2,1,18 +2025-03-11T12:43:36.385726,479393016,65214,254,23.51600768474,11.741927297055,-40.726630699475,2,1,18 +2025-03-11T12:43:36.401351,479393016,65214,254,23.79401548532,12.005809416015,-41.21793296366,2,1,18 +2025-03-11T12:43:36.416976,479393016,65214,254,24.06259929266,12.29278058817,-41.718556731965,2,1,18 +2025-03-11T12:43:36.432601,479393016,65214,254,24.31704711014,12.56124301413,-42.209843631125,2,1,18 +2025-03-11T12:43:36.448226,479393016,65214,254,24.58563091748,12.82510882716,-42.69188996717,2,1,18 +2025-03-11T12:43:36.463851,479393016,65214,254,24.8495027282,13.09358755905,-43.17394806221,2,1,18 +2025-03-11T12:43:36.479476,479393016,65214,254,25.1086625423,13.352815994325,-43.67906821157,2,1,18 +2025-03-11T12:43:36.495101,479393016,65214,254,25.37724634964,13.616681807355,-44.170356913745,2,1,18 +2025-03-11T12:43:36.510726,479393016,65214,254,25.63640616374,13.87591024263,-44.64312878165,2,1,18 +2025-03-11T12:43:36.526351,479393016,65214,254,25.90027797446,14.13514683087,-45.10666506443,2,1,18 +2025-03-11T12:43:36.541976,479393016,65214,254,26.15943778856,14.38975419432,-45.588660758465,2,1,18 +2025-03-11T12:43:36.557601,479393016,65214,254,26.43744558914,14.64439416963,-46.05219884426,2,1,18 +2025-03-11T12:43:36.573226,479393016,65214,254,26.70131739986,14.908251829695,-46.529617216235,2,1,18 +2025-03-11T12:43:36.588851,479393016,65214,254,26.95105322072,15.16746395904,-47.006996705195,2,1,18 +2025-03-11T12:43:36.604476,479393016,65214,254,27.2055010382,15.422063169525,-47.47512206903,2,1,18 +2025-03-11T12:43:36.620101,479393016,65214,254,27.46937284892,15.690541901415,-47.92945306568,2,1,18 +2025-03-11T12:43:36.635726,479393016,65214,254,27.72853266302,15.954391408515,-48.39762229052,2,1,18 +2025-03-11T12:43:36.651351,479393016,65214,254,27.9829804805,16.19974847535,-48.86108939129,2,1,18 +2025-03-11T12:43:36.666976,479393016,65214,254,28.2185803115,16.4404518585,-49.319889644975,2,1,18 +2025-03-11T12:43:36.682601,479393016,65214,254,28.46831613236,16.70428505967,-49.79266649087,2,1,18 +2025-03-11T12:43:36.698226,479393016,65214,254,28.71805195322,16.963497189015,-50.24231888144,2,1,18 +2025-03-11T12:43:36.713851,479393016,65214,254,28.96778777408,17.22270931836,-50.705834821205,2,1,18 +2025-03-11T12:43:36.729476,479393016,65214,254,29.21281159832,17.468050079265,-51.15542481077,2,1,18 +2025-03-11T12:43:36.745101,479393016,65214,254,29.4672594158,17.70416500245,-51.59112773315,2,1,18 +2025-03-11T12:43:36.760726,479393016,65214,254,29.70757124342,17.94949761039,-52.04995330784,2,1,18 +2025-03-11T12:43:36.776351,479393016,65214,254,29.94788307104,18.190209146505,-52.50876034253,2,1,18 +2025-03-11T12:43:36.791976,479393016,65214,254,30.19290689528,18.430928835585,-52.96295297516,2,1,18 +2025-03-11T12:43:36.807601,479393016,65214,254,30.4332187229,18.6716403717,-53.380169362265,2,1,18 +2025-03-11T12:43:36.823226,479393016,65214,254,30.68766654038,18.93086065401,-53.82982853384,2,1,18 +2025-03-11T12:43:36.838851,479393016,65214,254,30.93740236124,19.16696742423,-54.265524675215,2,1,18 +2025-03-11T12:43:36.854476,479393016,65214,254,31.17771418886,19.398436816695,-54.70118871458,2,1,18 +2025-03-11T12:43:36.870101,479393016,65214,254,31.41331401986,19.64376127167,-55.132280409875,2,1,18 +2025-03-11T12:43:36.885726,479393016,65214,254,31.63948985762,19.87520620524,-55.55406055703,2,1,18 +2025-03-11T12:43:36.901351,479393016,65214,254,31.88451368186,20.10668375067,-55.994352560465,2,1,18 +2025-03-11T12:43:36.916976,479393016,65214,254,32.12011351286,20.342766061995,-56.41616480963,2,1,18 +2025-03-11T12:43:36.932601,479393016,65214,254,32.35571334386,20.58809051697,-56.847256504925,2,1,18 +2025-03-11T12:43:36.948226,479393016,65214,254,32.58660117824,20.82416467533,-57.296789071475,2,1,18 +2025-03-11T12:43:36.963851,479393016,65214,254,32.82220100924,21.06486805848,-57.723241043705,2,1,18 +2025-03-11T12:43:36.979476,479393016,65214,254,33.03895285376,21.291675614295,-58.12650435659,2,1,18 +2025-03-11T12:43:36.995101,479393016,65214,254,33.2604166949,21.527733466725,-58.53905389661,2,1,18 +2025-03-11T12:43:37.010726,479393016,65214,254,33.48659253266,21.73607304117,-58.9561201607,2,1,18 +2025-03-11T12:43:37.026351,479393016,65214,254,33.72690436028,21.96292136181,-59.36865974474,2,1,18 +2025-03-11T12:43:37.041976,479393016,65214,254,33.96250419128,22.199003673135,-59.77660844471,2,1,18 +2025-03-11T12:43:37.057601,479393016,65214,254,34.17454403918,22.416560932335,-60.193691445785,2,1,18 +2025-03-11T12:43:37.073226,479393016,65214,254,34.38658388708,22.634118191535,-60.606153263795,2,1,18 +2025-03-11T12:43:37.088851,479393016,65214,254,34.60804772822,22.860933900315,-60.99555980849,2,1,18 +2025-03-11T12:43:37.104476,479393016,65214,254,34.83422356598,23.092378833885,-61.41271877258,2,1,18 +2025-03-11T12:43:37.120101,479393016,65214,254,35.05568740712,23.319194542665,-61.811367683405,2,1,18 +2025-03-11T12:43:37.135726,479393016,65214,254,35.26772725502,23.536751801865,-62.205344769155,2,1,18 +2025-03-11T12:43:37.151351,479393016,65214,254,35.48447909954,23.749696142205,-62.603931278975,2,1,18 +2025-03-11T12:43:37.166976,479393016,65214,254,35.6870949542,23.957994951825,-62.988615356585,2,1,18 +2025-03-11T12:43:37.182601,479393016,65214,254,35.8991348021,24.14320470825,-63.37784147927,2,1,18 +2025-03-11T12:43:37.198226,479393016,65214,254,36.11588664662,24.360770120415,-63.762582979895,2,1,18 +2025-03-11T12:43:37.213851,479393016,65214,254,36.33263849114,24.57833553258,-64.142703297455,2,1,18 +2025-03-11T12:43:37.229476,479393016,65214,254,36.5352543458,24.791255414025,-64.54126946426,2,1,18 +2025-03-11T12:43:37.245101,479393016,65214,254,36.74258219708,24.994941304785,-64.91207823368,2,1,18 +2025-03-11T12:43:37.260726,479393016,65214,254,36.95462204498,25.194014276685,-65.27825406104,2,1,18 +2025-03-11T12:43:37.276351,479393016,65214,254,37.15723789964,25.393070942655,-65.639795143325,2,1,18 +2025-03-11T12:43:37.291976,479393016,65214,254,37.35514175768,25.61984588661,-66.001440684605,2,1,18 +2025-03-11T12:43:37.307601,479393016,65214,254,37.55304561572,25.846620830565,-66.35846504282,2,1,18 +2025-03-11T12:43:37.323226,479393016,65214,254,37.75566147038,26.03181428106,-66.70608695591,2,1,18 +2025-03-11T12:43:37.338851,479393016,65214,254,37.95356532842,26.230862794065,-67.07686362332,2,1,18 +2025-03-11T12:43:37.354476,479393016,65214,254,38.14675718984,26.429903154105,-67.429148777465,2,1,18 +2025-03-11T12:43:37.370101,479393016,65214,254,38.33994905126,26.628943514145,-67.776812748545,2,1,18 +2025-03-11T12:43:37.385726,479393016,65214,254,38.53314091268,26.818741730535,-68.12906082269,2,1,18 +2025-03-11T12:43:37.401351,479393016,65214,254,38.73575676734,27.00393518103,-68.48592510191,2,1,18 +2025-03-11T12:43:37.416976,479393016,65214,254,38.93366062538,27.212225837685,-68.833632933995,2,1,18 +2025-03-11T12:43:37.432601,479393016,65214,254,39.12214049018,27.39277375746,-69.185837147135,2,1,18 +2025-03-11T12:43:37.448226,479393016,65214,254,39.30119636174,27.564063227655,-69.528748352135,2,1,18 +2025-03-11T12:43:37.463851,479393016,65214,254,39.49910021978,27.758490668835,-69.881021747285,2,1,18 +2025-03-11T12:43:37.479476,479393016,65214,254,39.6922920812,27.9436678134,-70.219387732235,2,1,18 +2025-03-11T12:43:37.495101,479393016,65214,254,39.88548394262,28.110360670665,-70.557679557185,2,1,18 +2025-03-11T12:43:37.510726,479393016,65214,254,40.06453981418,28.29089228451,-70.891385476055,2,1,18 +2025-03-11T12:43:37.526351,479393016,65214,254,40.22474769926,28.45752807102,-71.21114510171,2,1,18 +2025-03-11T12:43:37.541976,479393016,65214,254,40.38966758096,28.64727736962,-71.526383025305,2,1,18 +2025-03-11T12:43:37.557601,479393016,65214,254,40.57814744576,28.827825289395,-71.86472368925,2,1,18 +2025-03-11T12:43:37.573226,479393016,65214,254,40.74777932408,28.994477381835,-72.193739243045,2,1,18 +2025-03-11T12:43:37.588851,479393016,65214,254,40.92683519564,29.18425113933,-72.50437632659,2,1,18 +2025-03-11T12:43:37.604476,479393016,65214,254,41.09646707396,29.34166108812,-72.805627701995,2,1,18 +2025-03-11T12:43:37.620101,479393016,65214,254,41.26609895228,29.51755532421,-73.1069532374,2,1,18 +2025-03-11T12:43:37.635726,479393016,65214,254,41.42630683736,29.688812182545,-73.41286785386,2,1,18 +2025-03-11T12:43:37.651351,479393016,65214,254,41.59122671906,29.850835050195,-73.73261572052,2,1,18 +2025-03-11T12:43:37.666976,479393016,65214,254,41.765570594,30.00825315195,-74.04311624306,2,1,18 +2025-03-11T12:43:37.682601,479393016,65214,254,41.92577847908,30.16564679481,-74.335111690325,2,1,18 +2025-03-11T12:43:37.698226,479393016,65214,254,42.0954103574,30.33229888725,-74.61791541347,2,1,18 +2025-03-11T12:43:37.713851,479393016,65214,254,42.24148225262,30.489668071215,-74.91913288385,2,1,18 +2025-03-11T12:43:37.729476,479393016,65214,254,42.38755414784,30.633174039705,-75.215673551165,2,1,18 +2025-03-11T12:43:37.745101,479393016,65214,254,42.55247402954,30.804439051005,-75.49386785024,2,1,18 +2025-03-11T12:43:37.760726,479393016,65214,254,42.71739391124,30.966461918655,-75.772025069315,2,1,18 +2025-03-11T12:43:37.776351,479393016,65214,254,42.8728897997,31.1330895522,-76.045566083315,2,1,18 +2025-03-11T12:43:37.791976,479393016,65214,254,43.01896169492,31.29507980799,-76.34218091063,2,1,18 +2025-03-11T12:43:37.807601,479393016,65214,254,43.16974558676,31.447836073095,-76.606417157495,2,1,18 +2025-03-11T12:43:37.823226,479393016,65214,254,43.32524147522,31.59597941934,-76.879884011495,2,1,18 +2025-03-11T12:43:37.838851,479393016,65214,254,43.48073736368,31.73950169376,-77.144089959365,2,1,18 +2025-03-11T12:43:37.854476,479393016,65214,254,43.62209726228,31.873757365635,-77.40823848422,2,1,18 +2025-03-11T12:43:37.870101,479393016,65214,254,43.75403316764,32.003375659755,-77.65849135787,2,1,18 +2025-03-11T12:43:37.885726,479393016,65214,254,43.88125707638,32.15147008821,-77.899569244385,2,1,18 +2025-03-11T12:43:37.901351,479393016,65214,254,44.02261697498,32.304210047385,-78.168413112305,2,1,18 +2025-03-11T12:43:37.916976,479393016,65214,254,44.16397687358,32.45695000656,-78.428014614095,2,1,18 +2025-03-11T12:43:37.932601,479393016,65214,254,44.29591277894,32.58656830068,-78.678267487745,2,1,18 +2025-03-11T12:43:37.948226,479393016,65214,254,44.43727267754,32.71620290073,-78.919291557275,2,1,18 +2025-03-11T12:43:37.963851,479393016,65214,254,44.57392057952,32.855071491465,-79.146482376605,2,1,18 +2025-03-11T12:43:37.979476,479393016,65214,254,44.70114448826,32.970818417145,-79.37818811699,2,1,18 +2025-03-11T12:43:37.995040,479393020,65210,255,44.83779239024,33.095823792405,-79.609944499385,2,1,18 +2025-03-11T12:43:38.010665,479393020,65210,255,44.96501629898,33.22543393356,-79.84170585977,2,1,18 +2025-03-11T12:43:38.026290,479393020,65210,255,45.10637619758,33.359689605435,-80.068884920105,2,1,18 +2025-03-11T12:43:38.041915,479393020,65210,255,45.2288881097,33.4846705218,-80.291378593355,2,1,18 +2025-03-11T12:43:38.057540,479393020,65210,255,45.33726403196,33.595763763795,-80.52303866972,2,1,18 +2025-03-11T12:43:38.073165,479393020,65210,255,45.44563995422,33.72534129309,-80.745530539955,2,1,18 +2025-03-11T12:43:38.088790,479393020,65210,255,45.5822878562,33.845725596525,-80.96802601622,2,1,18 +2025-03-11T12:43:38.104415,479393020,65210,255,45.7000877717,33.952214072625,-81.17657519927,2,1,18 +2025-03-11T12:43:38.120040,479393020,65210,255,45.8178876872,34.0725657642,-81.389801185385,2,1,18 +2025-03-11T12:43:38.135665,479393020,65210,255,45.9356876027,34.174433168475,-81.6029530115,2,1,18 +2025-03-11T12:43:38.151290,479393020,65210,255,46.04877552158,34.285534563435,-81.802271587415,2,1,18 +2025-03-11T12:43:38.166915,479393020,65210,255,46.15715144384,34.401248877255,-82.001601922325,2,1,18 +2025-03-11T12:43:38.182540,479393020,65210,255,46.2655273661,34.5030999756,-82.21474018643,2,1,18 +2025-03-11T12:43:38.198165,479393020,65210,255,46.36919129174,34.60494292098,-82.40938693727,2,1,18 +2025-03-11T12:43:38.213790,479393020,65210,255,46.46343122414,34.711390632255,-82.58555393384,2,1,18 +2025-03-11T12:43:38.229415,479393020,65210,255,46.5718071464,34.82248387425,-82.78486572875,2,1,18 +2025-03-11T12:43:38.245040,479393020,65210,255,46.6660470788,34.919689441875,-82.96099564532,2,1,18 +2025-03-11T12:43:38.260665,479393020,65210,255,46.76499900782,35.035387449765,-83.127964136765,2,1,18 +2025-03-11T12:43:38.276290,479393020,65210,255,46.85923894022,35.137214089215,-83.29949141027,2,1,18 +2025-03-11T12:43:38.291915,479393020,65210,255,46.95819086924,35.23904888163,-83.45254073252,2,1,18 +2025-03-11T12:43:38.307540,479393020,65210,255,47.0430068084,35.336238143325,-83.62865708708,2,1,18 +2025-03-11T12:43:38.323165,479393020,65210,255,47.1372467408,35.41495942365,-83.800091660585,2,1,18 +2025-03-11T12:43:38.338790,479393020,65210,255,47.23619866982,35.46596242599,-83.96680059203,2,1,18 +2025-03-11T12:43:38.354415,479393020,65210,255,47.3257266056,35.549296625175,-84.14748929066,2,1,18 +2025-03-11T12:43:38.370040,479393020,65210,255,47.41525454138,35.637251896185,-84.29122706477,2,1,18 +2025-03-11T12:43:38.385665,479393020,65210,255,47.49535848392,35.734433004915,-84.430367173805,2,1,18 +2025-03-11T12:43:38.401290,479393020,65210,255,47.58017442308,35.827001194785,-84.57411670691,2,1,18 +2025-03-11T12:43:38.416915,479393020,65210,255,47.65085437238,35.90106063846,-84.713150553935,2,1,18 +2025-03-11T12:43:38.432540,479393020,65210,255,47.71211032844,35.97048270438,-84.85215229895,2,1,18 +2025-03-11T12:43:38.448165,479393020,65210,255,47.80163826422,36.04919583174,-85.000474176125,2,1,18 +2025-03-11T12:43:38.463790,479393020,65210,255,47.87231821352,36.123255275415,-85.144129206215,2,1,18 +2025-03-11T12:43:38.479415,479393020,65210,255,47.94299816282,36.19731471909,-85.27392068711,2,1,18 +2025-03-11T12:43:38.495040,479393020,65210,255,48.02310210536,36.27601154052,-85.403744270015,2,1,18 +2025-03-11T12:43:38.510665,479393020,65210,255,48.08435806142,36.340812534615,-85.52424274277,2,1,18 +2025-03-11T12:43:38.526290,479393020,65210,255,48.1503260141,36.424105968975,-85.64482215653,2,1,18 +2025-03-11T12:43:38.541915,479393020,65210,255,48.20686997354,36.479656666455,-85.760655585215,2,1,18 +2025-03-11T12:43:38.557540,479393020,65210,255,48.27283792622,36.53984474169,-85.86727874978,2,1,18 +2025-03-11T12:43:38.573165,479393020,65210,255,48.3388058789,36.5954117451,-85.983125740475,2,1,18 +2025-03-11T12:43:38.588790,479393020,65210,255,48.40477383158,36.65097874851,-86.1082150973,2,1,18 +2025-03-11T12:43:38.604415,479393020,65210,255,48.4566057944,36.706521293025,-86.210178195785,2,1,18 +2025-03-11T12:43:38.620040,479393020,65210,255,48.48958977074,36.757410153855,-86.27512616573,2,1,18 +2025-03-11T12:43:38.635665,479393020,65210,255,48.5508457268,36.8129690043,-86.38172400929,2,1,18 +2025-03-11T12:43:38.651290,479393020,65210,255,48.61210168286,36.859285711095,-86.46980004059,2,1,18 +2025-03-11T12:43:38.666915,479393020,65210,255,48.66393364568,36.89634396831,-86.553204246815,2,1,18 +2025-03-11T12:43:38.682540,479393020,65210,255,48.70634161526,36.93800699142,-86.63661343103,2,1,18 +2025-03-11T12:43:38.698165,479393020,65210,255,48.74874958484,36.97967001453,-86.73388616444,2,1,18 +2025-03-11T12:43:38.713790,479393020,65210,255,48.79586955104,37.030583334255,-86.794233294335,2,1,18 +2025-03-11T12:43:38.729415,479393020,65210,255,48.83827752062,37.081488501015,-86.85919482629,2,1,18 +2025-03-11T12:43:38.745040,479393020,65210,255,48.87126149696,37.132377361845,-86.942627528495,2,1,18 +2025-03-11T12:43:38.760665,479393020,65210,255,48.90895746992,37.16479008834,-87.02137166864,2,1,18 +2025-03-11T12:43:38.776290,479393020,65210,255,48.9513654395,37.192589895975,-87.086240500595,2,1,18 +2025-03-11T12:43:38.791915,479393020,65210,255,48.98906141246,37.21576047882,-87.151084011545,2,1,18 +2025-03-11T12:43:38.807540,479393020,65210,255,49.01262139556,37.243527674595,-87.192819804155,2,1,18 +2025-03-11T12:43:38.823165,479393020,65210,255,49.0456053719,37.26206903265,-87.253016811035,2,1,18 +2025-03-11T12:43:38.838790,479393020,65210,255,49.07858934824,37.299094678005,-87.29942442872,2,1,18 +2025-03-11T12:43:38.854415,479393020,65210,255,49.10686132796,37.336112170395,-87.33658289927,2,1,18 +2025-03-11T12:43:38.870040,479393020,65210,255,49.13042131106,37.340774007045,-87.36898362575,2,1,18 +2025-03-11T12:43:38.885665,479393020,65210,255,49.14926929754,37.359290906205,-87.41529674042,2,1,18 +2025-03-11T12:43:38.901290,479393020,65210,255,49.1634052874,37.3962839397,-87.452434867955,2,1,18 +2025-03-11T12:43:38.916915,479393020,65210,255,49.16811728402,37.41939745179,-87.494124996545,2,1,18 +2025-03-11T12:43:38.932540,479393020,65210,255,49.1869652705,37.43791435095,-87.521953378955,2,1,18 +2025-03-11T12:43:38.948165,479393020,65210,255,49.20110126036,37.43331773802,-87.54968228036,2,1,18 +2025-03-11T12:43:38.963790,479393020,65210,255,49.2105252536,37.437955115775,-87.572820297695,2,1,18 +2025-03-11T12:43:38.979415,479393020,65210,255,49.21994924684,37.456455709005,-87.57752920277,2,1,18 +2025-03-11T12:43:38.995040,479393020,65210,255,49.22937324008,37.474956302235,-87.58685929091,2,1,18 +2025-03-11T12:43:39.010665,479393020,65210,255,49.2340852367,37.48420659885,-87.605387884175,2,1,18 +2025-03-11T12:43:39.026290,479393020,65210,255,49.24350922994,37.48422290478,-87.642370910705,2,1,18 +2025-03-11T12:43:39.041915,479393020,65210,255,49.25293322318,37.47499706706,-87.642347392715,2,1,18 +2025-03-11T12:43:39.057540,479393020,65210,255,49.2576452198,37.484247363675,-87.637770070655,2,1,18 +2025-03-11T12:43:39.073165,479393020,65210,255,49.25293322318,37.479618138885,-87.642365932715,2,1,18 +2025-03-11T12:43:39.088790,479393020,65210,255,49.24822122656,37.46112569862,-87.609936710255,2,1,18 +2025-03-11T12:43:39.104415,479393020,65210,255,49.2576452198,37.4518998609,-87.591428460005,2,1,18 +2025-03-11T12:43:39.120040,479393020,65210,255,49.25293322318,37.433407420635,-87.568241603675,2,1,18 +2025-03-11T12:43:39.135665,479393020,65210,255,49.23879723332,37.43338296174,-87.5497365284,2,1,18 +2025-03-11T12:43:39.151290,479393020,65210,255,49.21523725022,37.43796326874,-87.503509332725,2,1,18 +2025-03-11T12:43:39.166915,479393020,65210,255,49.19638926374,37.41020422593,-87.48026505338,2,1,18 +2025-03-11T12:43:39.182540,479393020,65210,255,49.17754127726,37.387066254945,-87.475524046295,2,1,18 +2025-03-11T12:43:39.198165,479393020,65210,255,49.15869329078,37.36392828396,-87.45229830695,2,1,18 +2025-03-11T12:43:39.213790,479393020,65210,255,49.15398129416,37.354677987345,-87.41066379836,2,1,18 +2025-03-11T12:43:39.229415,479393020,65210,255,49.12099731782,37.322273413815,-87.34116880535,2,1,18 +2025-03-11T12:43:39.245040,479393020,65210,255,49.10214933134,37.303756514655,-87.290234507615,2,1,18 +2025-03-11T12:43:39.260665,479393020,65210,255,49.08801334148,37.280626696635,-87.248530817015,2,1,18 +2025-03-11T12:43:39.276290,479393020,65210,255,49.069165355,37.25748872565,-87.21606271154,2,1,18 +2025-03-11T12:43:39.291915,479393020,65210,255,49.02675738542,37.229688918015,-87.160436245715,2,1,18 +2025-03-11T12:43:39.307540,479393020,65210,255,48.98906141246,37.192655119695,-87.0909159317,2,1,18 +2025-03-11T12:43:39.323165,479393020,65210,255,48.9513654395,37.1787266805,-87.030730683815,2,1,18 +2025-03-11T12:43:39.338790,479393020,65210,255,48.92309345978,37.15095133176,-86.956639828745,2,1,18 +2025-03-11T12:43:39.354415,479393020,65210,255,48.86654950034,37.10464277793,-86.9147824091,2,1,18 +2025-03-11T12:43:39.370040,479393020,65210,255,48.83827752062,37.063004213715,-86.84987830016,2,1,18 +2025-03-11T12:43:39.385665,479393020,65210,255,48.80058154766,37.01210719992,-86.771060000015,2,1,18 +2025-03-11T12:43:39.401290,479393020,65210,255,48.75817357808,36.97968632046,-86.664581980475,2,1,18 +2025-03-11T12:43:39.416915,479393020,65210,255,48.72047760512,36.938031450315,-86.581179577265,2,1,18 +2025-03-11T12:43:39.432540,479393020,65210,255,48.67335763892,36.88711813059,-86.51159008124,2,1,18 +2025-03-11T12:43:39.448165,479393020,65210,255,48.60738968624,36.836172199005,-86.41886754587,2,1,18 +2025-03-11T12:43:39.463790,479393020,65210,255,48.55555772342,36.766766439015,-86.307606461255,2,1,18 +2025-03-11T12:43:39.479415,479393020,65210,255,48.51786175046,36.711248353395,-86.21952725498,2,1,18 +2025-03-11T12:43:39.495040,479393020,65210,255,48.47074178426,36.64185074637,-86.122136500565,2,1,18 +2025-03-11T12:43:39.510665,479393020,65210,255,48.41890982144,36.577066058205,-86.02013632208,2,1,18 +2025-03-11T12:43:39.526290,479393020,65210,255,48.36707785862,36.52152351369,-85.918173223595,2,1,18 +2025-03-11T12:43:39.541915,479393020,65210,255,48.3152458958,36.456738825525,-85.811551862045,2,1,18 +2025-03-11T12:43:39.557540,479393020,65210,255,48.24927794312,36.391929678465,-85.691046608285,2,1,18 +2025-03-11T12:43:39.573165,479393020,65210,255,48.16917400058,36.33633821616,-85.57055809151,2,1,18 +2025-03-11T12:43:39.588790,479393020,65210,255,48.09849405128,36.27614198796,-85.440822230615,2,1,18 +2025-03-11T12:43:39.604415,479393020,65210,255,48.03723809522,36.211340993865,-85.306460208665,2,1,18 +2025-03-11T12:43:39.620040,479393020,65210,255,47.97127014254,36.14191077498,-85.195178781035,2,1,18 +2025-03-11T12:43:39.635665,479393020,65210,255,47.90059019324,36.067851331305,-85.060766117075,2,1,18 +2025-03-11T12:43:39.651290,479393020,65210,255,47.8204862507,35.9752912944,-84.926265731105,2,1,18 +2025-03-11T12:43:39.666915,479393020,65210,255,47.74038230816,35.88735232932,-84.77792033594,2,1,18 +2025-03-11T12:43:39.682540,479393020,65210,255,47.66027836562,35.813276579715,-84.620388194645,2,1,18 +2025-03-11T12:43:39.698165,479393020,65210,255,47.58959841632,35.743838207865,-84.48137288762,2,1,18 +2025-03-11T12:43:39.713790,479393020,65210,255,47.50007048054,35.674367224155,-84.32846690738,2,1,18 +2025-03-11T12:43:39.729415,479393020,65210,255,47.40111855152,35.595637790865,-84.166267919,2,1,18 +2025-03-11T12:43:39.745040,479393020,65210,255,47.31630261236,35.49844852917,-84.004015113635,2,1,18 +2025-03-11T12:43:39.760665,479393020,65210,255,47.24091066644,35.410517717055,-83.84181295028,2,1,18 +2025-03-11T12:43:39.776290,479393020,65210,255,47.13253474418,35.331771977835,-83.67960039989,2,1,18 +2025-03-11T12:43:39.791915,479393020,65210,255,47.03829481178,35.239187482035,-83.526594938645,2,1,18 +2025-03-11T12:43:39.807540,479393020,65210,255,46.93934288276,35.141973761445,-83.345837058005,2,1,18 +2025-03-11T12:43:39.823165,479393020,65210,255,46.8545269436,35.04478449975,-83.151235971185,2,1,18 +2025-03-11T12:43:39.838790,479393020,65210,255,46.76499900782,34.93834494144,-82.979696938685,2,1,18 +2025-03-11T12:43:39.854415,479393020,65210,255,46.65662308556,34.836493843095,-82.817391688295,2,1,18 +2025-03-11T12:43:39.870040,479393020,65210,255,46.56238315316,34.73004613182,-82.64584587479,2,1,18 +2025-03-11T12:43:39.885665,479393020,65210,255,46.45871922752,34.623582114615,-82.46042295008,2,1,18 +2025-03-11T12:43:39.901290,479393020,65210,255,46.3597672985,34.5217473222,-82.27964652944,2,1,18 +2025-03-11T12:43:39.916915,479393020,65210,255,46.26081536948,34.410670386135,-82.0988330288,2,1,18 +2025-03-11T12:43:39.932540,479393020,65210,255,46.16186344046,34.322698809195,-81.904248678965,2,1,18 +2025-03-11T12:43:39.948165,479393020,65210,255,46.0534875182,34.22084771085,-81.71883751325,2,1,18 +2025-03-11T12:43:39.963790,479393020,65210,255,45.94511159594,34.109754468855,-81.524146901405,2,1,18 +2025-03-11T12:43:39.979415,479393020,65210,255,45.8178876872,33.994007543175,-81.315547076345,2,1,18 +2025-03-11T12:43:39.995040,479393020,65210,255,45.7000877717,33.8736558516,-81.097699907165,2,1,18 +2025-03-11T12:43:40.010665,479393020,65210,255,45.57757585958,33.75329600706,-80.865982407785,2,1,18 +2025-03-11T12:43:40.026290,479393020,65210,255,45.4644879407,33.63295246845,-80.643520836545,2,1,18 +2025-03-11T12:43:40.041915,479393020,65210,255,45.34197602858,33.50335048026,-80.430250989425,2,1,18 +2025-03-11T12:43:40.057540,479393020,65210,255,45.21946411646,33.36450634842,-80.189216963915,2,1,18 +2025-03-11T12:43:40.073165,479393020,65210,255,45.10637619758,33.239541737985,-79.957494486545,2,1,18 +2025-03-11T12:43:40.088790,479393020,65210,255,44.97444029222,33.11454451569,-79.73960843435,2,1,18 +2025-03-11T12:43:40.104415,479393020,65210,255,44.84721638348,32.99879759001,-79.5032815109,2,1,18 +2025-03-11T12:43:40.120040,479393020,65210,255,44.71528047812,32.86917929589,-79.257649820315,2,1,18 +2025-03-11T12:43:40.135665,479393020,65210,255,44.58805656938,32.739569154735,-79.03513082606,2,1,18 +2025-03-11T12:43:40.151290,479393020,65210,255,44.46083266064,32.605337941755,-78.803350925675,2,1,18 +2025-03-11T12:43:40.166915,479393020,65210,255,44.31476076542,32.471074116915,-78.54381680288,2,1,18 +2025-03-11T12:43:40.182540,479393020,65210,255,44.17340086682,32.332197373215,-78.29351328722,2,1,18 +2025-03-11T12:43:40.198165,479393020,65210,255,44.03675296484,32.188707710655,-78.02933446337,2,1,18 +2025-03-11T12:43:40.213790,479393020,65210,255,43.90010506286,32.04059697627,-77.788243014845,2,1,18 +2025-03-11T12:43:40.229415,479393020,65210,255,43.76345716088,31.88786517006,-77.524027110995,2,1,18 +2025-03-11T12:43:40.245040,479393020,65210,255,43.61267326904,31.744351048605,-77.255206761065,2,1,18 +2025-03-11T12:43:40.260665,479393020,65210,255,43.48073736368,31.596248467185,-77.004879727415,2,1,18 +2025-03-11T12:43:40.276290,479393020,65210,255,43.33466546846,31.452742498695,-76.749929707685,2,1,18 +2025-03-11T12:43:40.291915,479393020,65210,255,43.17445758338,31.304590999485,-76.48569843881,2,1,18 +2025-03-11T12:43:40.307540,479393020,65210,255,43.00953770168,31.161052419135,-76.216857745865,2,1,18 +2025-03-11T12:43:40.323165,479393020,65210,255,42.85404181322,31.008288001065,-75.92950880267,2,1,18 +2025-03-11T12:43:40.338790,479393020,65210,255,42.71268191462,30.850926970065,-75.64216166249,2,1,18 +2025-03-11T12:43:40.354415,479393020,65210,255,42.55718602616,30.68429933652,-75.345514733165,2,1,18 +2025-03-11T12:43:40.370040,479393020,65210,255,42.41111413094,30.53155122438,-75.053558168915,2,1,18 +2025-03-11T12:43:40.385665,479393020,65210,255,42.2603302391,30.37417388745,-74.756955100595,2,1,18 +2025-03-11T12:43:40.401290,479393020,65210,255,42.08598636416,30.207513642045,-74.464902230315,2,1,18 +2025-03-11T12:43:40.416915,479393020,65210,255,41.92577847908,30.04549892736,-74.168267059985,2,1,18 +2025-03-11T12:43:40.432540,479393020,65210,255,41.75614660076,29.883467906745,-73.84851241232,2,1,18 +2025-03-11T12:43:40.448165,479393020,65210,255,41.60536270892,29.726090569815,-73.547288160935,2,1,18 +2025-03-11T12:43:40.463790,479393020,65210,255,41.44515482384,29.54559156783,-73.259821196735,2,1,18 +2025-03-11T12:43:40.479415,479393020,65210,255,41.2708109489,29.369689178775,-72.935382965,2,1,18 +2025-03-11T12:43:40.495040,479393020,65210,255,41.1058910672,29.189182023825,-72.629424487535,2,1,18 +2025-03-11T12:43:40.510665,479393020,65210,255,40.93625918888,29.02715100321,-72.33739693826,2,1,18 +2025-03-11T12:43:40.526290,479393020,65210,255,40.77133930718,28.85588599191,-72.022233174665,2,1,18 +2025-03-11T12:43:40.541915,479393020,65210,255,40.59228343562,28.67073330624,-71.688508715795,2,1,18 +2025-03-11T12:43:40.557540,479393020,65210,255,40.40851556744,28.48095139578,-71.36400130205,2,1,18 +2025-03-11T12:43:40.573165,479393020,65210,255,40.22474769926,28.323516988095,-71.04424485137,2,1,18 +2025-03-11T12:43:40.588790,479393020,65210,255,40.0456918277,28.1337432306,-70.724365401695,2,1,18 +2025-03-11T12:43:40.604415,479393020,65210,255,39.87134795276,27.957840841545,-70.37220007157,2,1,18 +2025-03-11T12:43:40.620040,479393020,65210,255,39.6922920812,27.772688155875,-70.02923324657,2,1,18 +2025-03-11T12:43:40.635665,479393020,65210,255,39.51794820626,27.582922551345,-69.70011821177,2,1,18 +2025-03-11T12:43:40.651290,479393020,65210,255,39.31062035498,27.41158416336,-69.361787503805,2,1,18 +2025-03-11T12:43:40.666915,479393020,65210,255,39.11271649694,27.21715672218,-69.000271742525,2,1,18 +2025-03-11T12:43:40.682540,479393020,65210,255,38.93366062538,27.01351974921,-68.647988391395,2,1,18 +2025-03-11T12:43:40.698165,479393020,65210,255,38.74046876396,26.819100460995,-68.291100594185,2,1,18 +2025-03-11T12:43:40.713790,479393020,65210,255,38.55198889916,26.63855254122,-67.938896381045,2,1,18 +2025-03-11T12:43:40.729415,479393020,65210,255,38.35408504112,26.430261884565,-67.59118854896,2,1,18 +2025-03-11T12:43:40.745040,479393020,65210,255,38.17031717294,26.24510104593,-67.238972576825,2,1,18 +2025-03-11T12:43:40.760665,479393020,65210,255,37.9724133149,26.055294676575,-66.886717721675,2,1,18 +2025-03-11T12:43:40.776290,479393020,65210,255,37.78864544672,25.84240740699,-66.52514814341,2,1,18 +2025-03-11T12:43:40.791915,479393020,65210,255,37.5954535853,25.629503831475,-66.154322637005,2,1,18 +2025-03-11T12:43:40.807540,479393020,65210,255,37.3834137374,25.439673003225,-65.788183889645,2,1,18 +2025-03-11T12:43:40.823165,479393020,65210,255,37.17608588612,25.235987112465,-65.417375120225,2,1,18 +2025-03-11T12:43:40.838790,479393020,65210,255,36.97347003146,25.02306723102,-65.041914868745,2,1,18 +2025-03-11T12:43:40.854415,479393020,65210,255,36.76143018356,24.819373187295,-64.67109931832,2,1,18 +2025-03-11T12:43:40.870040,479393020,65210,255,36.5352543458,24.606412541025,-64.286362795685,2,1,18 +2025-03-11T12:43:40.885665,479393020,65210,255,36.3232144979,24.38423421,-63.892367169935,2,1,18 +2025-03-11T12:43:40.901290,479393020,65210,255,36.12531063986,24.17132248152,-63.50767133333,2,1,18 +2025-03-11T12:43:40.916915,479393020,65210,255,35.90855879534,23.96762028483,-63.141470184965,2,1,18 +2025-03-11T12:43:40.932540,479393020,65210,255,35.67767096096,23.754651485595,-62.756726881325,2,1,18 +2025-03-11T12:43:40.948165,479393020,65210,255,35.47034310968,23.54634452301,-62.34430892432,2,1,18 +2025-03-11T12:43:40.963790,479393020,65210,255,35.26772725502,23.324182497915,-61.95032686058,2,1,18 +2025-03-11T12:43:40.979415,479393020,65210,255,35.05568740712,23.106625238715,-61.551728591765,2,1,18 +2025-03-11T12:43:40.995040,479393020,65210,255,34.84364755922,22.879825835865,-61.15309324295,2,1,18 +2025-03-11T12:43:41.010665,479393020,65210,255,34.6268957147,22.666881495525,-60.76374909926,2,1,18 +2025-03-11T12:43:41.026290,479393020,65210,255,34.40543187356,22.45392900222,-60.3697769915,2,1,18 +2025-03-11T12:43:41.041915,479393020,65210,255,34.1792560358,22.2317262123,-59.96189747354,2,1,18 +2025-03-11T12:43:41.057540,479393020,65210,255,33.9436562048,22.004886044625,-59.55398585357,2,1,18 +2025-03-11T12:43:41.073165,479393020,65210,255,33.72219236366,21.787312479495,-59.146131656615,2,1,18 +2025-03-11T12:43:41.088790,479393020,65210,255,33.50072852252,21.54663355524,-58.715078844335,2,1,18 +2025-03-11T12:43:41.104415,479393020,65210,255,33.27455268476,21.319809693495,-58.30255960331,2,1,18 +2025-03-11T12:43:41.120040,479393020,65210,255,33.048376847,21.097606903575,-57.890058902285,2,1,18 +2025-03-11T12:43:41.135665,479393020,65210,255,32.812777016,20.8707667359,-57.454420183925,2,1,18 +2025-03-11T12:43:41.151290,479393020,65210,255,32.577177185,20.643926568225,-57.02340264863,2,1,18 +2025-03-11T12:43:41.166915,479393020,65210,255,32.34628935062,20.41247348169,-56.587752171275,2,1,18 +2025-03-11T12:43:41.182540,479393020,65210,255,32.11068951962,20.17177009854,-56.161300199045,2,1,18 +2025-03-11T12:43:41.198165,479393020,65210,255,31.87980168524,19.921832724705,-55.739439110885,2,1,18 +2025-03-11T12:43:41.213790,479393020,65210,255,31.64420185424,19.681129341555,-55.30836595559,2,1,18 +2025-03-11T12:43:41.229415,479393020,65210,255,31.40860202324,19.440425958405,-54.88191398336,2,1,18 +2025-03-11T12:43:41.245040,479393020,65210,255,31.17300219224,19.190480431605,-54.450803748065,2,1,18 +2025-03-11T12:43:41.260665,479393020,65210,255,30.91855437476,18.95436550842,-54.01972200875,2,1,18 +2025-03-11T12:43:41.276290,479393020,65210,255,30.67353055052,18.72288796299,-53.579430005315,2,1,18 +2025-03-11T12:43:41.291915,479393020,65210,255,30.45206670938,18.482209038735,-53.12527127771,2,1,18 +2025-03-11T12:43:41.307540,479393020,65210,255,30.21175488176,18.24149750262,-52.689570158345,2,1,18 +2025-03-11T12:43:41.323165,479393020,65210,255,29.9620190609,17.99614858875,-52.24459457084,2,1,18 +2025-03-11T12:43:41.338790,479393020,65210,255,29.71228324004,17.755420746705,-51.790395157205,2,1,18 +2025-03-11T12:43:41.354415,479393020,65210,255,29.4672594158,17.50083784215,-51.336146904575,2,1,18 +2025-03-11T12:43:41.370040,479393020,65210,255,29.22223559156,17.23239172212,-50.89570658114,2,1,18 +2025-03-11T12:43:41.385665,479393020,65210,255,28.98192376394,16.98705911418,-50.44612337258,2,1,18 +2025-03-11T12:43:41.401290,479393020,65210,255,28.7368999397,16.732476209625,-49.987253936885,2,1,18 +2025-03-11T12:43:41.416915,479393020,65210,255,28.48716411884,16.48250622393,-49.52377507712,2,1,18 +2025-03-11T12:43:41.432540,479393020,65210,255,28.23271630136,16.237149157095,-49.06030797635,2,1,18 +2025-03-11T12:43:41.448165,479393020,65210,255,27.97826848388,15.98254994661,-48.59680379558,2,1,18 +2025-03-11T12:43:41.463790,479393020,65210,255,27.71439667316,15.73255550202,-48.128683409735,2,1,18 +2025-03-11T12:43:41.479415,479393020,65210,255,27.44581286582,15.46868968899,-47.65587943982,2,1,18 +2025-03-11T12:43:41.495040,479393020,65210,255,27.18665305172,15.21408232554,-47.173883745785,2,1,18 +2025-03-11T12:43:41.510665,479393020,65210,255,26.92749323762,14.95947496209,-46.72885751627,2,1,18 +2025-03-11T12:43:41.526290,479393020,65210,255,26.67304542014,14.69101253613,-46.2652977155,2,1,18 +2025-03-11T12:43:41.541915,479393020,65210,255,26.42330959928,14.42717933496,-45.783278503475,2,1,18 +2025-03-11T12:43:41.557540,479393020,65210,255,26.17357377842,14.16334613379,-45.30125929145,2,1,18 +2025-03-11T12:43:41.573165,479393020,65210,255,25.92383795756,13.89951293262,-44.828482445555,2,1,18 +2025-03-11T12:43:41.588790,479393020,65210,255,25.65996614684,13.644897416205,-44.36034351971,2,1,18 +2025-03-11T12:43:41.604415,479393020,65210,255,25.3913823395,13.3671683877,-43.887483929795,2,1,18 +2025-03-11T12:43:41.620040,479393020,65210,255,25.11808653554,13.08943120623,-43.396132826615,2,1,18 +2025-03-11T12:43:41.635665,479393020,65210,255,24.85421472482,12.834815689815,-42.904887985445,2,1,18 +2025-03-11T12:43:41.651290,479393020,65210,255,24.58091892086,12.57094172382,-42.413592502265,2,1,18 +2025-03-11T12:43:41.666915,479393020,65210,255,24.31704711014,12.30246299193,-41.91767085803,2,1,18 +2025-03-11T12:43:41.682540,479393020,65210,255,24.04375130618,12.038589025935,-41.44486010711,2,1,18 +2025-03-11T12:43:41.698165,479393020,65210,255,23.78459149208,11.765497375185,-40.953547886945,2,1,18 +2025-03-11T12:43:41.713790,479393020,65210,255,23.5065836915,11.501615256225,-40.4437608905,2,1,18 +2025-03-11T12:43:41.729415,479393020,65210,255,23.25213587402,11.214668542965,-39.95239983134,2,1,18 +2025-03-11T12:43:41.745040,479393020,65210,255,22.99297605992,10.932334748565,-39.461050531175,2,1,18 +2025-03-11T12:43:41.760665,479393020,65210,255,22.72439225258,10.66384786371,-38.97898565513,2,1,18 +2025-03-11T12:43:41.776290,479393020,65210,255,22.446384452,10.39996574475,-38.496925757075,2,1,18 +2025-03-11T12:43:41.791915,479393020,65210,255,22.17308864804,10.126849635105,-37.987108461635,2,1,18 +2025-03-11T12:43:41.807540,479393020,65210,255,21.9045048407,9.844499534775,-37.4772608672,2,1,18 +2025-03-11T12:43:41.823165,479393020,65210,255,21.63120903674,9.56214128148,-36.972027674825,2,1,18 +2025-03-11T12:43:41.838790,479393020,65210,255,21.34848923954,9.307493153205,-36.471513343505,2,1,18 +2025-03-11T12:43:41.854415,479393020,65210,255,21.06576944234,9.038981809455,-35.980185758315,2,1,18 +2025-03-11T12:43:41.870040,479393020,65210,255,20.78304964514,8.74736510658,-35.479523106995,2,1,18 +2025-03-11T12:43:41.885665,479393020,65210,255,20.50032984794,8.47885376283,-34.95584724035,2,1,18 +2025-03-11T12:43:41.901290,479393020,65210,255,20.22703404398,8.19187443771,-34.450595507975,2,1,18 +2025-03-11T12:43:41.916915,479393020,65210,255,19.95373824002,7.90489511259,-33.9453437756,2,1,18 +2025-03-11T12:43:41.932540,479393020,65210,255,19.68044243606,7.61791578747,-33.42622849403,2,1,18 +2025-03-11T12:43:41.948165,479393020,65210,255,19.39772263886,7.33092015642,-32.89785728432,2,1,18 +2025-03-11T12:43:41.963790,479393020,65210,255,19.11500284166,7.05316666902,-32.37876552074,2,1,18 +2025-03-11T12:43:41.979415,479393020,65210,255,18.8181470546,6.766146579075,-31.878101066405,2,1,18 +2025-03-11T12:43:41.994979,479393024,65206,256,18.54013925402,6.50688553194,-31.391438525285,2,1,18 +2025-03-11T12:43:42.010604,479393024,65206,256,18.2527074602,6.22450281975,-30.8723214407,2,1,18 +2025-03-11T12:43:42.026229,479393024,65206,256,17.97469965962,5.92365212619,-30.343901391995,2,1,18 +2025-03-11T12:43:42.041854,479393024,65206,256,17.6872678658,5.627406198525,-29.820107504345,2,1,18 +2025-03-11T12:43:42.057479,479393024,65206,256,17.39983607198,5.354265629985,-29.31026986589,2,1,18 +2025-03-11T12:43:42.073104,479393024,65206,256,17.12654026802,5.07190737669,-28.795794307385,2,1,18 +2025-03-11T12:43:42.088729,479393024,65206,256,16.84382047082,4.771048530165,-28.258125111545,2,1,18 +2025-03-11T12:43:42.104354,479393024,65206,256,16.56581267024,4.488682123905,-27.725158039775,2,1,18 +2025-03-11T12:43:42.119979,479393024,65206,256,16.26424488656,4.201653880995,-27.206002072175,2,1,18 +2025-03-11T12:43:42.135604,479393024,65206,256,15.96267710288,3.914625638085,-26.67298255538,2,1,18 +2025-03-11T12:43:42.151229,479393024,65206,256,15.6611093192,3.62297632335,-26.13532331552,2,1,18 +2025-03-11T12:43:42.166854,479393024,65206,256,15.38310151862,3.34060991709,-25.579250328425,2,1,18 +2025-03-11T12:43:42.182479,479393024,65206,256,15.10038172142,3.04437214239,-25.050842038715,2,1,18 +2025-03-11T12:43:42.198104,479393024,65206,256,14.8129499276,2.757368358375,-24.53170641413,2,1,18 +2025-03-11T12:43:42.213729,479393024,65206,256,14.51138214392,2.470340115465,-24.01255044653,2,1,18 +2025-03-11T12:43:42.229354,479393024,65206,256,14.20981436024,2.16944865708,-23.488717675865,2,1,18 +2025-03-11T12:43:42.244979,479393024,65206,256,13.90824657656,1.87317827052,-22.95566107907,2,1,18 +2025-03-11T12:43:42.260604,479393024,65206,256,13.62552677936,1.563077280345,-22.41795480323,2,1,18 +2025-03-11T12:43:42.276229,479393024,65206,256,13.3522309754,1.26223473975,-21.87105680327,2,1,18 +2025-03-11T12:43:42.291854,479393024,65206,256,13.06479918158,0.975230955735,-21.324194080295,2,1,18 +2025-03-11T12:43:42.307479,479393024,65206,256,12.75380740466,0.669702119595001,-20.80032920762,2,1,18 +2025-03-11T12:43:42.323104,479393024,65206,256,12.4569516176,0.378060957825,-20.26729793183,2,1,18 +2025-03-11T12:43:42.338729,479393024,65206,256,12.16480782716,0.0956700926699998,-19.725068150915,2,1,18 +2025-03-11T12:43:42.354354,479393024,65206,256,11.87266403672,-0.20058398796,-19.21050984839,2,1,18 +2025-03-11T12:43:42.369979,479393024,65206,256,11.57580824966,-0.501467293379999,-18.672820309535,2,1,18 +2025-03-11T12:43:42.385604,479393024,65206,256,11.26952846936,-0.80236690473,-18.130496025605,2,1,18 +2025-03-11T12:43:42.401229,479393024,65206,256,10.9726726823,-1.098629138325,-17.59282502675,2,1,18 +2025-03-11T12:43:42.416854,479393024,65206,256,10.68052889186,-1.39026214713,-17.032073433575,2,1,18 +2025-03-11T12:43:42.432479,479393024,65206,256,10.39780909466,-1.67725777818,-16.494459857735,2,1,18 +2025-03-11T12:43:42.448104,479393024,65206,256,10.11508929746,-1.987358768355,-15.97061713109,2,1,18 +2025-03-11T12:43:42.463729,479393024,65206,256,9.82294550702,-2.283612848985,-15.437574096305,2,1,18 +2025-03-11T12:43:42.479354,479393024,65206,256,9.5355137132,-2.57985877665,-14.867568378005,2,1,18 +2025-03-11T12:43:42.494979,479393024,65206,256,9.22452193628,-2.87614546914,-14.31601348694,2,1,18 +2025-03-11T12:43:42.510604,479393024,65206,256,8.9229541526,-3.16317371205,-13.755266871755,2,1,18 +2025-03-11T12:43:42.526229,479393024,65206,256,8.62609836554,-3.459435945645,-13.20835350677,2,1,18 +2025-03-11T12:43:42.541854,479393024,65206,256,8.34337856834,-3.76029479217,-12.666063127865,2,1,18 +2025-03-11T12:43:42.557479,479393024,65206,256,8.04652278128,-4.047314882115,-12.123808025945,2,1,18 +2025-03-11T12:43:42.573104,479393024,65206,256,7.7449549976,-4.343585268675,-11.586130246085,2,1,18 +2025-03-11T12:43:42.588729,479393024,65206,256,7.42925122406,-4.644501185955,-11.053034766275,2,1,18 +2025-03-11T12:43:42.604354,479393024,65206,256,7.12297144376,-4.945400797305,-10.510710482345,2,1,18 +2025-03-11T12:43:42.619979,479393024,65206,256,6.81669166346,-5.25092148048,-9.96374647535,2,1,18 +2025-03-11T12:43:42.635604,479393024,65206,256,6.5198358764,-5.56104692955,-9.43064103956,2,1,18 +2025-03-11T12:43:42.651229,479393024,65206,256,6.23240408258,-5.86191392904,-8.87910151352,2,1,18 +2025-03-11T12:43:42.666854,479393024,65206,256,5.92612430228,-6.158192468565,-8.32755340346,2,1,18 +2025-03-11T12:43:42.682479,479393024,65206,256,5.61984452198,-6.468334223565,-7.79443440566,2,1,18 +2025-03-11T12:43:42.698104,479393024,65206,256,5.3182767383,-6.76922568195,-7.24749571967,2,1,18 +2025-03-11T12:43:42.713729,479393024,65206,256,5.02142095124,-7.07935113102,-6.700526734685,2,1,18 +2025-03-11T12:43:42.729354,479393024,65206,256,4.72456516418,-7.36175014914,-6.158290172765,2,1,18 +2025-03-11T12:43:42.744979,479393024,65206,256,4.43242137374,-7.653383157945,-5.602159762655,2,1,18 +2025-03-11T12:43:42.760604,479393024,65206,256,4.14498957992,-7.94962908561,-5.03677522742,2,1,18 +2025-03-11T12:43:42.776229,479393024,65206,256,3.85284578948,-8.25512530989,-4.485210380375,2,1,18 +2025-03-11T12:43:42.791854,479393024,65206,256,3.5512780058,-8.5606378401,-3.956737886645,2,1,18 +2025-03-11T12:43:42.807479,479393024,65206,256,3.24971022212,-8.870771442135,-3.409762120655,2,1,18 +2025-03-11T12:43:42.823104,479393024,65206,256,2.94814243844,-9.157799685045,-2.8582578716,2,1,18 +2025-03-11T12:43:42.838729,479393024,65206,256,2.64186265814,-9.467941440045,-2.30665414154,2,1,18 +2025-03-11T12:43:42.854354,479393024,65206,256,2.34029487446,-9.791938257555,-1.78734985394,2,1,18 +2025-03-11T12:43:42.869979,479393024,65206,256,2.04815108402,-10.097434481835,-1.235785006895,2,1,18 +2025-03-11T12:43:42.885604,479393024,65206,256,1.74658330034,-10.393704868395,-0.67500131171,2,1,18 +2025-03-11T12:43:42.901229,479393024,65206,256,1.43559152342,-10.689991560885,-0.11882523758,2,1,18 +2025-03-11T12:43:42.916854,479393024,65206,256,1.13402373974,-10.986261947445,0.42809490841,2,1,18 +2025-03-11T12:43:42.932479,479393024,65206,256,0.83245595606,-11.291774477655,0.979673317465,2,1,18 +2025-03-11T12:43:42.948104,479393024,65206,256,0.535600169,-11.60652099855,1.51741847632,2,1,18 +2025-03-11T12:43:42.963729,479393024,65206,256,0.24345637856,-11.89353293553,2.04580324804,2,1,18 +2025-03-11T12:43:42.979354,479393024,65206,256,-0.0675353983600001,-12.185198556195,2.588097232975,2,1,18 +2025-03-11T12:43:42.994979,479393024,65206,256,-0.36910318204,-12.47684787093,3.125756472835,2,1,18 +2025-03-11T12:43:43.010604,479393024,65206,256,-0.66124697248,-12.77310195156,3.65879950762,2,1,18 +2025-03-11T12:43:43.026229,479393024,65206,256,-0.94396676968,-13.07858186991,4.20572960959,2,1,18 +2025-03-11T12:43:43.041854,479393024,65206,256,-1.24082255674,-13.384086247155,4.761922420705,2,1,18 +2025-03-11T12:43:43.057479,479393024,65206,256,-1.53296634718,-13.68496139961,5.32271109388,2,1,18 +2025-03-11T12:43:43.073104,479393024,65206,256,-1.83924612748,-13.95813458001,5.860302954745,2,1,18 +2025-03-11T12:43:43.088729,479393024,65206,256,-2.13138991792,-14.24514651699,6.40255127566,2,1,18 +2025-03-11T12:43:43.104354,479393024,65206,256,-2.4329577016,-14.5691433345,6.94034029552,2,1,18 +2025-03-11T12:43:43.119979,479393024,65206,256,-2.72981348866,-14.874647711745,7.505775472765,2,1,18 +2025-03-11T12:43:43.135604,479393024,65206,256,-3.0219572791,-15.16628072055,8.052663516745,2,1,18 +2025-03-11T12:43:43.151229,479393024,65206,256,-3.30938907292,-15.444042360915,8.585625610525,2,1,18 +2025-03-11T12:43:43.166854,479393024,65206,256,-3.6109568566,-15.75417596295,9.132601376515,2,1,18 +2025-03-11T12:43:43.182479,479393024,65206,256,-3.90310064704,-16.06891433088,9.661097388235,2,1,18 +2025-03-11T12:43:43.198104,479393024,65206,256,-4.20466843072,-16.351321501965,10.180234815835,2,1,18 +2025-03-11T12:43:43.213729,479393024,65206,256,-4.49681222116,-16.647575582595,10.717899033685,2,1,18 +2025-03-11T12:43:43.229354,479393024,65206,256,-4.7889560116,-16.943829663225,11.27866916686,2,1,18 +2025-03-11T12:43:43.244979,479393024,65206,256,-5.08109980204,-17.240083743855,11.830196933905,2,1,18 +2025-03-11T12:43:43.260604,479393024,65206,256,-5.36853159586,-17.53632967152,12.344748455425,2,1,18 +2025-03-11T12:43:43.276229,479393024,65206,256,-5.66538738292,-17.83721297694,12.868574445085,2,1,18 +2025-03-11T12:43:43.291854,479393024,65206,256,-5.95753117336,-18.138088129395,13.40163601987,2,1,18 +2025-03-11T12:43:43.307479,479393024,65206,256,-6.2496749638,-18.443584353675,13.93009495159,2,1,18 +2025-03-11T12:43:43.323104,479393024,65206,256,-6.53710675762,-18.72134599404,14.46305704537,2,1,18 +2025-03-11T12:43:43.338729,479393024,65206,256,-6.84338653792,-18.999140246265,15.0052886293,2,1,18 +2025-03-11T12:43:43.354354,479393024,65206,256,-7.13553032836,-19.29077325507,15.547555490215,2,1,18 +2025-03-11T12:43:43.369979,479393024,65206,256,-7.41825012556,-19.58701102977,16.066721413795,2,1,18 +2025-03-11T12:43:43.385604,479393024,65206,256,-7.710393916,-19.878644038575,16.613609457775,2,1,18 +2025-03-11T12:43:43.401229,479393024,65206,256,-7.99782570982,-20.16564782259,17.137366265425,2,1,18 +2025-03-11T12:43:43.416854,479393024,65206,256,-8.29468149688,-20.452667912535,17.64727308589,2,1,18 +2025-03-11T12:43:43.432479,479393024,65206,256,-8.57740129408,-20.758147830885,18.171097272535,2,1,18 +2025-03-11T12:43:43.448104,479393024,65206,256,-8.85540909466,-21.04513530897,18.70870406737,2,1,18 +2025-03-11T12:43:43.463729,479393024,65206,256,-9.13812889186,-21.31364665272,19.250864666275,2,1,18 +2025-03-11T12:43:43.479354,479393024,65206,256,-9.4302726823,-21.596037517875,19.77460971493,2,1,18 +2025-03-11T12:43:43.494979,479393024,65206,256,-9.71770447612,-21.896904517365,20.29842214258,2,1,18 +2025-03-11T12:43:43.510604,479393024,65206,256,-10.00513626994,-22.179287229555,20.817539227165,2,1,18 +2025-03-11T12:43:43.526229,479393024,65206,256,-10.28785606714,-22.466282860605,21.336668070745,2,1,18 +2025-03-11T12:43:43.541854,479393024,65206,256,-10.59413584744,-22.75331925648,21.832724904025,2,1,18 +2025-03-11T12:43:43.557479,479393024,65206,256,-10.88156764126,-23.03570196867,22.36108435474,2,1,18 +2025-03-11T12:43:43.573104,479393024,65206,256,-11.15957544184,-23.33655266223,22.86639848812,2,1,18 +2025-03-11T12:43:43.588729,479393024,65206,256,-11.42815924918,-23.60966061891,23.39007255175,2,1,18 +2025-03-11T12:43:43.604354,479393024,65206,256,-11.715591043,-23.878180115625,23.899891650205,2,1,18 +2025-03-11T12:43:43.619979,479393024,65206,256,-12.00773483344,-24.16057098078,24.409773149665,2,1,18 +2025-03-11T12:43:43.635604,479393024,65206,256,-12.29045463064,-24.44756661183,24.92428081018,2,1,18 +2025-03-11T12:43:43.651229,479393024,65206,256,-12.56846243122,-24.734554089915,25.443402872755,2,1,18 +2025-03-11T12:43:43.666854,479393024,65206,256,-12.83704623856,-25.02152526207,25.94402664106,2,1,18 +2025-03-11T12:43:43.682479,479393024,65206,256,-13.11034204252,-25.285399228065,26.44456449037,2,1,18 +2025-03-11T12:43:43.698104,479393024,65206,256,-13.39306183972,-25.55853164364,26.959016530885,2,1,18 +2025-03-11T12:43:43.713729,479393024,65206,256,-13.6710696403,-25.845519121725,27.46889622733,2,1,18 +2025-03-11T12:43:43.729354,479393024,65206,256,-13.93965344764,-26.13249029388,27.9741411787,2,1,18 +2025-03-11T12:43:43.744979,479393024,65206,256,-14.21766124822,-26.39637241284,28.47006462595,2,1,18 +2025-03-11T12:43:43.760604,479393024,65206,256,-14.49095705218,-26.65562530701,28.975205118325,2,1,18 +2025-03-11T12:43:43.776229,479393024,65206,256,-14.76425285614,-26.928741416655,29.4804012307,2,1,18 +2025-03-11T12:43:43.791854,479393024,65206,256,-15.03283666348,-27.220333660635,29.96717998981,2,1,18 +2025-03-11T12:43:43.807479,479393024,65206,256,-15.2967084742,-27.51191775165,30.472436700175,2,1,18 +2025-03-11T12:43:43.823104,479393024,65206,256,-15.57000427816,-27.78041278947,30.97761427255,2,1,18 +2025-03-11T12:43:43.838729,479393024,65206,256,-15.8621480686,-28.025835080025,31.464241536685,2,1,18 +2025-03-11T12:43:43.854354,479393024,65206,256,-16.13073187594,-28.280458749405,31.950871975795,2,1,18 +2025-03-11T12:43:43.869979,479393024,65206,256,-16.3804676968,-28.5489130224,32.456015643145,2,1,18 +2025-03-11T12:43:43.885604,479393024,65206,256,-16.64433950752,-28.82663389794,32.94273200125,2,1,18 +2025-03-11T12:43:43.901229,479393024,65206,256,-16.93177130134,-29.09977446648,33.424842541315,2,1,18 +2025-03-11T12:43:43.916854,479393024,65206,256,-17.21449109854,-29.38677009753,33.91162310344,2,1,18 +2025-03-11T12:43:43.932479,479393024,65206,256,-17.47836290926,-29.64600668577,34.398265301545,2,1,18 +2025-03-11T12:43:43.948104,479393024,65206,256,-17.75165871322,-29.89601743629,34.880262798595,2,1,18 +2025-03-11T12:43:43.963729,479393024,65206,256,-18.02495451718,-30.159891402285,35.362315915645,2,1,18 +2025-03-11T12:43:43.979354,479393024,65206,256,-18.27940233466,-30.437595971895,35.835155162545,2,1,18 +2025-03-11T12:43:43.994979,479393024,65206,256,-18.53385015214,-30.69219518238,36.29403816025,2,1,18 +2025-03-11T12:43:44.010604,479393024,65206,256,-18.78829796962,-30.946794392865,36.771405890215,2,1,18 +2025-03-11T12:43:44.026229,479393024,65206,256,-19.03803379048,-31.20600652221,37.239543013045,2,1,18 +2025-03-11T12:43:44.041854,479393024,65206,256,-19.29248160796,-31.460605732695,37.721531926075,2,1,18 +2025-03-11T12:43:44.057479,479393024,65206,256,-19.54692942544,-31.72444708683,38.203557919105,2,1,18 +2025-03-11T12:43:44.073104,479393024,65206,256,-19.80137724292,-31.997530584615,38.66251507681,2,1,18 +2025-03-11T12:43:44.088729,479393024,65206,256,-20.04640106716,-32.26135563282,39.121421592505,2,1,18 +2025-03-11T12:43:44.104354,479393024,65206,256,-20.30556088126,-32.511341924445,39.59415638041,2,1,18 +2025-03-11T12:43:44.119979,479393024,65206,256,-20.56000869874,-32.77518327858,40.06694000731,2,1,18 +2025-03-11T12:43:44.135604,479393024,65206,256,-20.81916851284,-33.01130635473,40.53499799215,2,1,18 +2025-03-11T12:43:44.151229,479393024,65206,256,-21.08304032356,-33.275164014795,40.984689265735,2,1,18 +2025-03-11T12:43:44.166854,479393024,65206,256,-21.33748814104,-33.515900009805,41.429653094245,2,1,18 +2025-03-11T12:43:44.182479,479393024,65206,256,-21.5872239619,-33.761248923675,41.88387104788,2,1,18 +2025-03-11T12:43:44.198104,479393024,65206,256,-21.8228237929,-33.997331235,42.32878921237,2,1,18 +2025-03-11T12:43:44.213729,479393024,65206,256,-22.0584236239,-34.251897833625,42.77378153686,2,1,18 +2025-03-11T12:43:44.229354,479393024,65206,256,-22.30344744814,-34.52496502548,43.223482766425,2,1,18 +2025-03-11T12:43:44.244979,479393024,65206,256,-22.55789526562,-34.77494316414,43.66386249187,2,1,18 +2025-03-11T12:43:44.260604,479393024,65206,256,-22.81705507972,-35.01106624029,44.099572195255,2,1,18 +2025-03-11T12:43:44.276229,479393024,65206,256,-23.06207890396,-35.256407001195,44.544541001755,2,1,18 +2025-03-11T12:43:44.291854,479393024,65206,256,-23.31181472482,-35.49713484324,45.003361598455,2,1,18 +2025-03-11T12:43:44.307479,479393024,65206,256,-23.55683854906,-35.733233460495,45.448293324955,2,1,18 +2025-03-11T12:43:44.323104,479393024,65206,256,-23.78301438682,-35.96929946589,45.883955561305,2,1,18 +2025-03-11T12:43:44.338729,479393024,65206,256,-24.00447822796,-36.20535731832,46.31036865052,2,1,18 +2025-03-11T12:43:44.354354,479393024,65206,256,-24.24007805896,-36.44606070147,46.750684171945,2,1,18 +2025-03-11T12:43:44.369979,479393024,65206,256,-24.4851018832,-36.68678039055,47.17252852312,2,1,18 +2025-03-11T12:43:44.385604,479393024,65206,256,-24.71598971758,-36.918233477085,47.608179000475,2,1,18 +2025-03-11T12:43:44.401229,479393024,65206,256,-24.95158954858,-37.140452572935,48.043799178835,2,1,18 +2025-03-11T12:43:44.416854,479393024,65206,256,-25.19661337282,-37.36730904654,48.46558791001,2,1,18 +2025-03-11T12:43:44.432479,479393024,65206,256,-25.41807721396,-37.61260904262,48.882795713095,2,1,18 +2025-03-11T12:43:44.448104,479393024,65206,256,-25.64425305172,-37.84405397619,49.30457586025,2,1,18 +2025-03-11T12:43:44.463729,479393024,65206,256,-25.86571689286,-38.057006469495,49.712411517205,2,1,18 +2025-03-11T12:43:44.479354,479393024,65206,256,-26.07775674076,-38.28842694417,50.115686589085,2,1,18 +2025-03-11T12:43:44.494979,479393024,65206,256,-26.30393257852,-38.52911402139,50.51901908398,2,1,18 +2025-03-11T12:43:44.510604,479393024,65206,256,-26.52539641966,-38.74668758652,50.917630914805,2,1,18 +2025-03-11T12:43:44.526229,479393024,65206,256,-26.7468602608,-38.96426115165,51.320863928695,2,1,18 +2025-03-11T12:43:44.541854,479393024,65206,256,-26.97303609856,-39.17722179792,51.719464000525,2,1,18 +2025-03-11T12:43:44.557479,479393024,65206,256,-27.19921193632,-39.385561372365,52.13190908155,2,1,18 +2025-03-11T12:43:44.573104,479393024,65206,256,-27.42067577746,-39.612377081145,52.549042724635,2,1,18 +2025-03-11T12:43:44.588729,479393024,65206,256,-27.6421396186,-39.839192789925,52.95693400159,2,1,18 +2025-03-11T12:43:44.604354,479393024,65206,256,-27.84946746988,-40.05674189616,53.34628312327,2,1,18 +2025-03-11T12:43:44.619979,479393024,65206,256,-28.05208332454,-40.29276713673,53.717214891685,2,1,18 +2025-03-11T12:43:44.635604,479393024,65206,256,-28.26883516906,-40.50571147707,54.115801401505,2,1,18 +2025-03-11T12:43:44.651229,479393024,65206,256,-28.47616302034,-40.714018439655,54.505113443185,2,1,18 +2025-03-11T12:43:44.666854,479393024,65206,256,-28.68820286824,-40.931575698855,54.899090528935,2,1,18 +2025-03-11T12:43:44.682479,479393024,65206,256,-28.90966670938,-41.13528604851,55.2791620075,2,1,18 +2025-03-11T12:43:44.698104,479393024,65206,256,-29.11228256404,-41.338963786305,55.631479263655,2,1,18 +2025-03-11T12:43:44.713729,479393024,65206,256,-29.32903440856,-41.551908126645,56.002338675085,2,1,18 +2025-03-11T12:43:44.729354,479393024,65206,256,-29.54578625308,-41.755610323335,56.38702455571,2,1,18 +2025-03-11T12:43:44.744979,479393024,65206,256,-29.7389781145,-41.95002961155,56.757775902115,2,1,18 +2025-03-11T12:43:44.760604,479393024,65206,256,-29.93216997592,-42.135206756115,57.114626619325,2,1,18 +2025-03-11T12:43:44.776229,479393024,65206,256,-30.13478583058,-42.334263422085,57.48541006774,2,1,18 +2025-03-11T12:43:44.791854,479393024,65206,256,-30.33740168524,-42.55642544718,57.85166503309,2,1,18 +2025-03-11T12:43:44.807479,479393024,65206,256,-30.52588155004,-42.76007872608,58.208583129295,2,1,18 +2025-03-11T12:43:44.823104,479393024,65206,256,-30.7284974047,-42.963756463875,58.57014275158,2,1,18 +2025-03-11T12:43:44.838729,479393024,65206,256,-30.92640126274,-43.14432068958,58.92236052673,2,1,18 +2025-03-11T12:43:44.854354,479393024,65206,256,-31.1290171174,-43.3341352119,59.283864529015,2,1,18 +2025-03-11T12:43:44.869979,479393024,65206,256,-31.3174969822,-43.5377884908,59.63154025909,2,1,18 +2025-03-11T12:43:44.885604,479393024,65206,256,-31.49655285376,-43.727562248295,59.96528325796,2,1,18 +2025-03-11T12:43:44.901229,479393024,65206,256,-31.68974471518,-43.91273939286,60.317512792105,2,1,18 +2025-03-11T12:43:44.916854,479393024,65206,256,-31.88764857322,-44.111787905865,60.651319994995,2,1,18 +2025-03-11T12:43:44.932479,479393024,65206,256,-32.06199244816,-44.283069223095,60.989603235925,2,1,18 +2025-03-11T12:43:44.948104,479393024,65206,256,-32.23162432648,-44.458963459185,61.31865586972,2,1,18 +2025-03-11T12:43:44.963729,479393024,65206,256,-32.41539219466,-44.64412429782,61.65700829266,2,1,18 +2025-03-11T12:43:44.979354,479393024,65206,256,-32.59916006284,-44.81542192098,61.990683912535,2,1,18 +2025-03-11T12:43:44.994979,479393024,65206,256,-32.79235192426,-45.000599065545,62.31518634829,2,1,18 +2025-03-11T12:43:45.010604,479393024,65206,256,-32.97611979244,-45.190380976005,62.639693762035,2,1,18 +2025-03-11T12:43:45.026229,479393024,65206,256,-33.15046366738,-45.35704122141,62.959473730705,2,1,18 +2025-03-11T12:43:45.041854,479393024,65206,256,-33.31538354908,-45.52830623271,63.279258677365,2,1,18 +2025-03-11T12:43:45.057479,479393024,65206,256,-33.50386341388,-45.70423308066,63.59909606905,2,1,18 +2025-03-11T12:43:45.073104,479393024,65206,256,-33.6734952922,-45.8708851731,63.918869256715,2,1,18 +2025-03-11T12:43:45.088729,479393024,65206,256,-33.8384151739,-46.0421501844,64.220169471115,2,1,18 +2025-03-11T12:43:45.104354,479393024,65206,256,-34.01747104546,-46.21806072642,64.535372117725,2,1,18 +2025-03-11T12:43:45.119979,479393024,65206,256,-34.18239092716,-46.38932573772,64.83205114906,2,1,18 +2025-03-11T12:43:45.135604,479393024,65206,256,-34.333174819,-46.542082002825,65.142499226575,2,1,18 +2025-03-11T12:43:45.151229,479393024,65206,256,-34.48867070746,-46.694846420895,65.42984816977,2,1,18 +2025-03-11T12:43:45.166854,479393024,65206,256,-34.65359058916,-46.856869288545,65.71262657191,2,1,18 +2025-03-11T12:43:45.182479,479393024,65206,256,-34.82322246748,-47.023521380985,66.004672661185,2,1,18 +2025-03-11T12:43:45.198104,479393024,65206,256,-34.97871835594,-47.185527942705,66.296679867445,2,1,18 +2025-03-11T12:43:45.213729,479393024,65206,256,-35.12479025116,-47.34289712667,66.58403378863,2,1,18 +2025-03-11T12:43:45.229354,479393024,65206,256,-35.28971013286,-47.491056778845,66.8759989369,2,1,18 +2025-03-11T12:43:45.244979,479393024,65206,256,-35.45463001456,-47.625353215545,67.154044915975,2,1,18 +2025-03-11T12:43:45.260604,479393024,65206,256,-35.61954989626,-47.787376083195,67.427580951985,2,1,18 +2025-03-11T12:43:45.276229,479393024,65206,256,-35.76562179148,-47.940124195335,67.70567396704,2,1,18 +2025-03-11T12:43:45.291854,479393024,65206,256,-35.89284570022,-48.08821862379,67.974478951945,2,1,18 +2025-03-11T12:43:45.307479,479393024,65206,256,-36.04362959206,-48.240974888895,68.234094015745,2,1,18 +2025-03-11T12:43:45.323104,479393024,65206,256,-36.18498949066,-48.370609488945,68.502845183665,2,1,18 +2025-03-11T12:43:45.338729,479393024,65206,256,-36.3122133994,-48.5002196301,68.785439557765,2,1,18 +2025-03-11T12:43:45.354354,479393024,65206,256,-36.43943730814,-48.657556202205,69.02655452428,2,1,18 +2025-03-11T12:43:45.369979,479393024,65206,256,-36.59022119998,-48.805691395485,69.26766631582,2,1,18 +2025-03-11T12:43:45.385604,479393024,65206,256,-36.74100509182,-48.94920551694,69.504138384295,2,1,18 +2025-03-11T12:43:45.401229,479393024,65206,256,-36.8776529938,-49.0926951795,69.76369602508,2,1,18 +2025-03-11T12:43:45.416854,479393024,65206,256,-37.00958889916,-49.22231347362,70.027812447925,2,1,18 +2025-03-11T12:43:45.432479,479393024,65206,256,-37.13210081128,-49.35191546181,70.2734305765,2,1,18 +2025-03-11T12:43:45.448104,479393024,65206,256,-37.26874871326,-49.481541908895,70.505205498895,2,1,18 +2025-03-11T12:43:45.463729,479393024,65206,256,-37.40068461862,-49.61578127484,70.72312863109,2,1,18 +2025-03-11T12:43:45.479354,479393024,65206,256,-37.5137725375,-49.749988028925,70.941024639265,2,1,18 +2025-03-11T12:43:45.494979,479393024,65206,256,-37.64099644624,-49.865734954605,71.177351562715,2,1,18 +2025-03-11T12:43:45.510604,479393024,65206,256,-37.7729323516,-49.995353248725,71.40449852104,2,1,18 +2025-03-11T12:43:45.526229,479393024,65206,256,-37.90486825696,-50.12035047102,71.6270057563,2,1,18 +2025-03-11T12:43:45.541854,479393024,65206,256,-38.02738016908,-50.21298388461,71.84012728342,2,1,18 +2025-03-11T12:43:45.557479,479393024,65206,256,-38.15460407782,-50.32873081029,72.03948474235,2,1,18 +2025-03-11T12:43:45.573104,479393024,65206,256,-38.25826800346,-50.462921258445,72.25274600545,2,1,18 +2025-03-11T12:43:45.588729,479393024,65206,256,-38.36664392572,-50.569393428615,72.475145175685,2,1,18 +2025-03-11T12:43:45.604354,479393024,65206,256,-38.4797318446,-50.671252679925,72.669805488535,2,1,18 +2025-03-11T12:43:45.619979,479393024,65206,256,-38.58810776686,-50.76386163462,72.88290667264,2,1,18 +2025-03-11T12:43:45.635604,479393024,65206,256,-38.6917716925,-50.8841888673,73.07762758348,2,1,18 +2025-03-11T12:43:45.651229,479393024,65206,256,-38.79072362152,-50.99064473154,73.281528459445,2,1,18 +2025-03-11T12:43:45.666854,479393024,65206,256,-38.90852353702,-51.101754279465,73.462369084105,2,1,18 +2025-03-11T12:43:45.682479,479393024,65206,256,-39.02632345252,-51.20362168374,73.64779381183,2,1,18 +2025-03-11T12:43:45.698104,479393024,65206,256,-39.12056338492,-51.300827251365,73.8239237284,2,1,18 +2025-03-11T12:43:45.713729,479393024,65206,256,-39.2100913207,-51.407266809675,74.01394749316,2,1,18 +2025-03-11T12:43:45.729354,479393024,65206,256,-39.3043312531,-51.509093449125,74.1808535836,2,1,18 +2025-03-11T12:43:45.744979,479393024,65206,256,-39.40328318212,-51.597065026065,74.35233201811,2,1,18 +2025-03-11T12:43:45.760604,479393024,65206,256,-39.48809912128,-51.69425428776,74.523827189605,2,1,18 +2025-03-11T12:43:45.776229,479393024,65206,256,-39.58233905368,-51.77759663991,74.69528030311,2,1,18 +2025-03-11T12:43:45.791854,479393024,65206,256,-39.67657898608,-51.86093899206,74.866733416615,2,1,18 +2025-03-11T12:43:45.807479,479393024,65206,256,-39.76139492524,-51.939643966455,75.015048512785,2,1,18 +2025-03-11T12:43:45.823104,479393024,65206,256,-39.85563485764,-52.022986318605,75.16801689403,2,1,18 +2025-03-11T12:43:45.838729,479393024,65206,256,-39.94516279342,-52.129425876915,75.31182882814,2,1,18 +2025-03-11T12:43:45.854354,479393024,65206,256,-40.0346907292,-52.226623291575,75.460224865315,2,1,18 +2025-03-11T12:43:45.869979,479393024,65206,256,-40.11008267512,-52.30531196004,75.617768765605,2,1,18 +2025-03-11T12:43:45.885604,479393024,65206,256,-40.17133863118,-52.39321831326,75.76608703675,2,1,18 +2025-03-11T12:43:45.901229,479393024,65206,256,-40.25615457034,-52.471923287655,75.909780949855,2,1,18 +2025-03-11T12:43:45.916854,479393024,65206,256,-40.33625851288,-52.53675689361,76.053412461955,2,1,18 +2025-03-11T12:43:45.932479,479393024,65206,256,-40.41636245542,-52.60621157139,76.20168369712,2,1,18 +2025-03-11T12:43:45.948104,479393024,65206,256,-40.47761841148,-52.680254709135,76.33608279907,2,1,18 +2025-03-11T12:43:45.963729,479393024,65206,256,-40.54358636416,-52.745063856195,76.45658805283,2,1,18 +2025-03-11T12:43:45.979354,479393024,65206,256,-40.60955431684,-52.82373621873,76.56790656046,2,1,18 diff --git a/imap_processing/tests/mag/validation/L1c/T024/mag-l1b-l1c-t024-mago-normal-out.csv b/imap_processing/tests/mag/validation/L1c/T024/mag-l1b-l1c-t024-mago-normal-out.csv new file mode 100644 index 0000000000..e76fe3592a --- /dev/null +++ b/imap_processing/tests/mag/validation/L1c/T024/mag-l1b-l1c-t024-mago-normal-out.csv @@ -0,0 +1,687 @@ +t,x,y,z,interp +2025-03-11 12:38:02.500,-39.48337874134229,-51.698155157340466,74.56669784297581,True +2025-03-11 12:38:03.000,-41.392420875196116,-53.59168450123556,78.02540159866886,True +2025-03-11 12:38:03.500,-41.300530549088336,-53.478222202643295,77.8311125070998,True +2025-03-11 12:38:04.000,-39.23133474820145,-51.36271578555935,73.99964306129236,True +2025-03-11 12:38:04.500,-35.264705442542045,-47.34834118155224,66.70615537249458,True +2025-03-11 12:38:05.000,-29.569367551299425,-41.62062978700782,56.28926449505733,True +2025-03-11 12:38:05.500,-22.417426733050103,-34.41434051973331,43.18998635094511,True +2025-03-11 12:38:06.000,-14.095581516186945,-26.042462887128675,27.97899376163789,True +2025-03-11 12:38:06.500,-4.994673305172923,-16.892779181851626,11.32767552200333,True +2025-03-11 12:38:07.000,4.493530265144109,-7.36217319934962,-6.0133119785234594,True +2025-03-11 12:38:07.500,13.947196417066065,2.1299482232302136,-23.28664868491617,True +2025-03-11 12:38:08.000,22.967824166001424,11.165945557805559,-39.724737117034394,True +2025-03-11 12:38:08.500,31.124488388992237,19.340264367622638,-54.594832876765814,True +2025-03-11 12:38:09.000,38.06278409868033,26.30607189722774,-67.26384843045697,True +2025-03-11 12:38:09.500,43.49675807031214,31.753107127609457,-77.16515529257812,True +2025-03-11 12:38:10.000,47.16708296966651,35.41822720381701,-83.85878583542033,True +2025-03-11 12:38:10.500,48.92909376737454,37.16367444930852,-87.03425215685918,True +2025-03-11 12:38:11.000,48.70528445143922,36.89802175327486,-86.56876127550396,True +2025-03-11 12:38:11.500,46.483320101540386,34.63728810963973,-82.48037915390853,True +2025-03-11 12:38:12.000,42.367948715660155,30.491956875491187,-74.94435554224421,True +2025-03-11 12:38:12.500,36.56414266779506,24.62474305781378,-64.29791171113914,True +2025-03-11 12:38:13.000,29.3017267725159,17.32152438738599,-50.998064238525345,True +2025-03-11 12:38:13.500,20.91084113165995,8.89159505998924,-35.65826132638853,True +2025-03-11 12:38:14.000,11.758499356245043,-0.3038897442991112,-18.928118755522803,True +2025-03-11 12:38:14.500,2.2511161528811225,-9.851494246970132,-1.5578095266854304,True +2025-03-11 12:38:15.000,-7.192686597345188,-19.330728005644858,15.662283299109003,True +2025-03-11 12:38:15.500,-16.142149283096177,-28.316679551143345,32.01735344868622,True +2025-03-11 12:38:16.000,-24.218032342953425,-36.410755163305744,46.74797371983441,True +2025-03-11 12:38:16.500,-31.05388449118574,-43.263397320711455,59.218006358540045,True +2025-03-11 12:38:17.000,-36.35841390742533,-48.57374128583139,68.87256290189741,True +2025-03-11 12:38:17.500,-39.89775421254162,-52.10452498983413,75.3094225640219,True +2025-03-11 12:38:18.000,-41.50320456865734,-53.69713576834479,78.21476003863292,True +2025-03-11 12:38:18.500,-41.12450262239942,-53.28543780211867,77.4691877115032,True +2025-03-11 12:38:19.000,-38.76269288533573,-50.89867097527674,73.1161060669024,True +2025-03-11 12:38:19.500,-34.52975623303054,-46.602630065336136,65.32745535635615,True +2025-03-11 12:38:20.000,-28.608168806975137,-40.633461848338456,54.467371870447806,True +2025-03-11 12:38:20.500,-21.24781751704238,-33.232028434297675,41.00956595188781,True +2025-03-11 12:38:21.000,-12.785130376955253,-24.72366628056431,25.53586954975229,True +2025-03-11 12:38:21.500,-3.59564033433374,-15.491750502926784,8.749626961544251,True +2025-03-11 12:38:22.000,5.904109622469513,-5.9420143834412835,-8.626280848286605,True +2025-03-11 12:38:22.500,15.317810005697183,3.5006365527278267,-25.816181924296234,True +2025-03-11 12:38:23.000,24.232303816960254,12.432141169420442,-42.06459021050311,True +2025-03-11 12:38:23.500,32.227686512233106,20.454692421067175,-56.656475689209984,True +2025-03-11 12:38:24.000,38.966407953712086,27.210801749615726,-68.94199239776988,True +2025-03-11 12:38:24.500,44.15274518493091,32.399701390425086,-78.37613381593974,True +2025-03-11 12:38:25.000,47.55054181164894,35.79412508015059,-84.55678255640554,True +2025-03-11 12:38:25.500,49.02592638310792,37.244323543048196,-87.19987020067978,True +2025-03-11 12:38:26.000,48.492894716803825,36.67673064500238,-86.20247080699308,True +2025-03-11 12:38:26.500,45.97229936771847,34.13431765389727,-81.57158197501379,True +2025-03-11 12:38:27.000,41.5953043816031,29.72299428408917,-73.54204219863222,True +2025-03-11 12:38:27.500,35.55072076066626,23.63161346523217,-62.465598764322905,True +2025-03-11 12:38:28.000,28.101938162995992,16.117366833078236,-48.827541850053635,True +2025-03-11 12:38:28.500,19.57515649084604,7.5398968248279425,-33.2308244921912,True +2025-03-11 12:38:29.000,10.351545136987498,-1.7266459402224634,-16.36813857954382,True +2025-03-11 12:38:29.500,0.8173522258440885,-11.293745419184392,1.020434586244742,True +2025-03-11 12:38:30.000,-8.575767740564276,-20.719181787486924,18.168167694391755,True +2025-03-11 12:38:30.500,-17.419909302752323,-29.591129598927967,34.32666251944495,True +2025-03-11 12:38:31.000,-25.33235016607856,-37.52162325697218,48.75715687467536,True +2025-03-11 12:38:31.500,-31.962129410418555,-44.16913413004535,60.83886880776394,True +2025-03-11 12:38:32.000,-37.01692378452356,-49.22755646001784,70.04038526483866,True +2025-03-11 12:38:32.500,-40.26658170348544,-52.47479790980725,75.94628046460953,True +2025-03-11 12:38:33.000,-41.581652103911765,-53.76669081611928,78.30997435320624,True +2025-03-11 12:38:33.500,-40.898601257938914,-53.05403538666861,77.01501716935026,True +2025-03-11 12:38:34.000,-38.25078681927391,-50.35957058111995,72.134256205935,True +2025-03-11 12:38:34.500,-33.7415653839107,-45.82014986560411,63.87126285834449,True +2025-03-11 12:38:35.000,-27.58324207075972,-39.608319982432526,52.60412446656228,True +2025-03-11 12:38:35.500,-20.04634056270675,-32.01839753998791,38.81502303112939,True +2025-03-11 12:38:36.000,-11.452927881732117,-23.378579907613567,23.093337417226614,True +2025-03-11 12:38:36.500,-2.193421593498365,-14.068086924810235,6.160612630152638,True +2025-03-11 12:38:37.000,7.329870197665629,-4.502085902451958,-11.23685260820362,True +2025-03-11 12:38:37.500,16.705493688439475,4.891453879051084,-28.339369598919166,True +2025-03-11 12:38:38.000,25.50138385386585,13.718594638001791,-44.38356457460193,True +2025-03-11 12:38:38.500,33.33846199213424,21.563028552112627,-58.660153139495726,True +2025-03-11 12:38:39.000,39.863442113304366,28.09172408090994,-70.55778625560654,True +2025-03-11 12:38:39.500,44.79296441894758,33.02194573767789,-79.53442126162412,True +2025-03-11 12:38:40.000,47.89314230787685,36.124050268423,-85.19055735067714,True +2025-03-11 12:38:40.500,49.06437088314963,37.286450854803135,-87.3009670237554,True +2025-03-11 12:38:41.000,48.24851435457375,36.428478703087364,-85.76137349671704,True +2025-03-11 12:38:41.500,45.4487436691462,33.60002643356527,-80.60926551763973,True +2025-03-11 12:38:42.000,40.80721478156247,28.917008944593604,-72.09548688886586,True +2025-03-11 12:38:42.500,34.53455955828024,22.601598166729378,-60.60964537033661,True +2025-03-11 12:38:43.000,26.896815980046135,14.910164463218983,-46.63395707893295,True +2025-03-11 12:38:43.500,18.240091472513424,6.208199972502064,-30.77848418181744,True +2025-03-11 12:38:44.000,8.944955483671162,-3.1432591691315417,-13.793999207860633,True +2025-03-11 12:38:44.500,-0.5854571606807468,-12.72181540057339,3.5998558008906545,True +2025-03-11 12:38:45.000,-9.919878846175632,-22.085270611551323,20.656841879218238,True +2025-03-11 12:38:45.500,-18.656614920673075,-30.837898640982615,36.589310399085846,True +2025-03-11 12:38:46.000,-26.39872867700502,-38.608862846817686,50.719412779515245,True +2025-03-11 12:38:46.500,-32.80645968919808,-45.03461932296549,62.399530715057026,True +2025-03-11 12:38:47.000,-37.61158922395901,-49.821127138297456,71.13304111412063,True +2025-03-11 12:38:47.500,-40.58897188421346,-52.78456230867032,76.54065836785661,True +2025-03-11 12:38:48.000,-41.608856953284295,-53.777309827034344,78.35968979019053,True +2025-03-11 12:38:48.500,-40.62071743852938,-52.76565496957629,76.5259484642223,True +2025-03-11 12:38:49.000,-37.70071143997189,-49.80113409091209,71.12338622651187,True +2025-03-11 12:38:49.500,-32.938351025792926,-44.98867009104535,62.3809258681083,True +2025-03-11 12:38:50.000,-26.559203667225194,-38.5588508236567,50.687030508850924,True +2025-03-11 12:38:50.500,-18.82019256084029,-30.786959025458998,36.56668897499949,True +2025-03-11 12:38:51.000,-10.101591372658019,-22.020140785765307,20.62553869879782,True +2025-03-11 12:38:51.500,-0.7646121748636276,-12.64683782170654,3.5711877360912045,True +2025-03-11 12:38:52.000,8.756096573433119,-3.085312562307453,-13.862096628342675,True +2025-03-11 12:38:52.500,18.065690019315273,6.26254980630111,-30.86483395201937,True +2025-03-11 12:38:53.000,26.73920247213678,14.966275277980516,-46.70524699628821,True +2025-03-11 12:38:53.500,34.39053245800078,22.636439228630287,-60.65279179409788,True +2025-03-11 12:38:54.000,40.70417102449501,28.94399196498157,-72.14355452083626,True +2025-03-11 12:38:54.500,45.37309200967193,33.615583980013774,-80.65046665306014,True +2025-03-11 12:38:55.000,48.20420184694976,36.43837689403223,-85.77750186446153,True +2025-03-11 12:38:55.500,49.07543129556055,37.28372720525683,-87.30698312701378,True +2025-03-11 12:38:56.000,47.94717853011375,36.117510739720565,-85.20477793801261,True +2025-03-11 12:38:56.500,44.861804136380854,33.00875110584607,-79.5313111387357,True +2025-03-11 12:38:57.000,39.95794459694336,28.070182729666215,-70.54381530911076,True +2025-03-11 12:38:57.500,33.46317394977832,21.51884216171674,-58.66449202590476,True +2025-03-11 12:38:58.000,25.655907879226213,13.654285093659029,-44.375992719656274,True +2025-03-11 12:38:58.500,16.879994852491066,4.833503693201802,-28.333833966888797,True +2025-03-11 12:38:59.000,7.5193123662190136,-4.5689735768884185,-11.224799038805712,True +2025-03-11 12:38:59.500,-2.0081000147164882,-14.142677289407283,6.185477389063177,True +2025-03-11 12:39:00.000,-11.277802670936365,-23.439283883443448,23.122971142351908,True +2025-03-11 12:39:00.500,-19.888451407340714,-32.06590689702022,38.830685867396696,True +2025-03-11 12:39:01.000,-27.44921287627525,-39.65955014233474,52.615316841586534,True +2025-03-11 12:39:01.500,-33.64706337788089,-45.849028322027394,63.90209767520601,True +2025-03-11 12:39:02.000,-38.183915505017886,-50.37916431605998,72.16102841695884,True +2025-03-11 12:39:02.500,-40.85696571964916,-53.06060319002041,77.03324434539522,True +2025-03-11 12:39:03.000,-41.58609080727003,-53.75226257409568,78.31705603603803,True +2025-03-11 12:39:03.500,-40.30972428667868,-52.44223200799126,75.93658113378886,True +2025-03-11 12:39:04.000,-37.088853597217714,-49.18699005205201,70.01309259041558,True +2025-03-11 12:39:04.500,-32.06415301119788,-44.12545346502828,60.803149406939475,True +2025-03-11 12:39:05.000,-25.460148935052757,-37.477203183147076,48.69666718020801,True +2025-03-11 12:39:05.500,-17.576601929686586,-29.53188464181913,34.23832675682969,True +2025-03-11 12:39:06.000,-8.738331199496535,-20.645154484118674,18.079483968526162,True +2025-03-11 12:39:06.500,0.6478693772006872,-11.221931324331873,0.9345565209115236,True +2025-03-11 12:39:07.000,10.166890477745072,-1.6655034932011394,-16.459543705927903,True +2025-03-11 12:39:07.500,19.399109463911103,7.600769960930812,-33.318303978349455,True +2025-03-11 12:39:08.000,27.944261412843243,16.179757869993185,-48.90175631529834,True +2025-03-11 12:39:08.500,35.41069157297453,23.67087941464591,-62.49904877399037,True +2025-03-11 12:39:09.000,41.49302670554599,29.753056157031544,-73.56086458177633,True +2025-03-11 12:39:09.500,45.90586042572053,34.15554194909089,-81.58002976336897,True +2025-03-11 12:39:10.000,48.44793187890722,36.68171315151742,-86.18247638103004,True +2025-03-11 12:39:10.500,49.02057520243472,37.24133085278151,-87.19744041706649,True +2025-03-11 12:39:11.000,47.603429122224306,35.7903416093299,-84.59346762793531,True +2025-03-11 12:39:11.500,44.237518190378786,32.393761833498964,-78.43257908905002,True +2025-03-11 12:39:12.000,39.087733735333344,27.18869725950493,-68.99097377010419,True +2025-03-11 12:39:12.500,32.38026016082745,20.426646130589177,-56.70574330499879,True +2025-03-11 12:39:13.000,24.410499538777966,12.403688209845054,-42.113243465352696,True +2025-03-11 12:39:13.500,15.520637427134487,3.4614712636290377,-25.84531155564847,True +2025-03-11 12:39:14.000,6.109593438005786,-5.993621025333496,-8.64587938025505,True +2025-03-11 12:39:14.500,-3.40085602500157,-15.54599779666801,8.725335372901732,True +2025-03-11 12:39:15.000,-12.608508507201696,-24.778335700342662,25.510593680956624,True +2025-03-11 12:39:15.500,-21.08641339921859,-33.27988196875477,40.9796195226584,True +2025-03-11 12:39:16.000,-28.460498384597845,-40.67348914364082,54.437269276344274,True +2025-03-11 12:39:16.500,-34.42491272273886,-46.62495003189194,65.2884315805311,True +2025-03-11 12:39:17.000,-38.69913063376106,-50.89609043095145,73.06180304811987,True +2025-03-11 12:39:17.500,-41.10183197228323,-53.27915485160516,77.40849802316437,True +2025-03-11 12:39:18.000,-41.51988903054547,-53.68078759084159,78.14591828198195,True +2025-03-11 12:39:18.500,-39.946980446245846,-52.07528039396979,75.23109910164612,True +2025-03-11 12:39:19.000,-36.44495587964211,-48.538808815064186,68.7971763492074,True +2025-03-11 12:39:19.500,-31.168416469436064,-43.21705423164672,59.12468739771795,True +2025-03-11 12:39:20.000,-24.346156464969123,-36.36091553911764,46.64129867241143,True +2025-03-11 12:39:20.500,-16.28972359949516,-28.25707029022684,31.908215428092927,True +2025-03-11 12:39:21.000,-7.342084403354016,-19.270744953160357,15.564231530633643,True +2025-03-11 12:39:21.500,2.0815100974241947,-9.796120677277806,-1.6696479519285916,True +2025-03-11 12:39:22.000,11.583249072513738,-0.24619832820021506,-19.023576100907555,True +2025-03-11 12:39:22.500,20.74614473120912,8.947831946633565,-35.71081731006878,True +2025-03-11 12:39:23.000,29.149599589144444,17.37175986211042,-51.036634843775396,True +2025-03-11 12:39:23.500,36.43457486502399,24.682121877087347,-64.31962171480114,True +2025-03-11 12:39:24.000,42.275169305212216,30.53480229369746,-74.9608338557657,True +2025-03-11 12:39:24.500,46.419905872795674,34.66592019646589,-82.49200683353558,True +2025-03-11 12:39:25.000,48.67298333692916,36.90884155373926,-86.57500408149829,True +2025-03-11 12:39:25.500,48.94934315386266,37.15790772548182,-87.03718534624866,True +2025-03-11 12:39:26.000,47.234058734825254,35.391766477691526,-83.84501672451442,True +2025-03-11 12:39:26.500,43.592928903577715,31.707990459255765,-77.16600366011951,True +2025-03-11 12:39:27.000,38.18701317276568,26.271239309372767,-67.2861791664773,True +2025-03-11 12:39:27.500,31.269446142123517,19.294214075139234,-54.61551917396661,True +2025-03-11 12:39:28.000,23.129290631239314,11.114035996563112,-39.72908931261678,True +2025-03-11 12:39:28.500,14.136078839775086,2.0723138123247584,-23.29462452817308,True +2025-03-11 12:39:29.000,4.675107983395238,-7.426394350457381,-6.014215255013678,True +2025-03-11 12:39:29.500,-4.819416815930464,-16.958387865992066,11.302197428736251,True +2025-03-11 12:39:30.000,-13.9289834179108,-26.101352184558486,27.94411953869485,True +2025-03-11 12:39:30.500,-22.261354569148168,-34.46016159085746,43.15520030818349,True +2025-03-11 12:39:31.000,-29.436977824891635,-41.664870267708864,56.26223410794079,True +2025-03-11 12:39:31.500,-35.15327507133209,-47.39878396786509,66.67746636181411,True +2025-03-11 12:39:32.000,-39.169672026037105,-51.39860565144422,73.9623355121635,True +2025-03-11 12:39:32.500,-41.27153474401782,-53.479444412268755,77.7837117817113,True +2025-03-11 12:39:33.000,-41.39285161202648,-53.576278285982255,77.96555571871671,True +2025-03-11 12:39:33.500,-39.53184123082893,-51.684692114420244,74.52875032714677,True +2025-03-11 12:39:34.000,-35.752043270621755,-47.86192833994724,67.5864111077181,True +2025-03-11 12:39:34.500,-30.236931685668566,-42.29747629247019,57.47543017484265,True +2025-03-11 12:39:35.000,-23.218192708878558,-35.223509474586464,44.63049579024153,True +2025-03-11 12:39:35.500,-15.002769396916877,-26.95712343798174,29.61427929310072,True +2025-03-11 12:39:36.000,-5.963634295851054,-17.873828553830524,13.0951837837559,True +2025-03-11 12:39:36.500,3.4975264667676282,-8.35909263698582,-4.21027885494592,True +2025-03-11 12:39:37.000,12.975506987669789,1.1600329956432047,-21.53254194977658,True +2025-03-11 12:39:37.500,22.043851548668734,10.262937822263325,-38.08119693819611,True +2025-03-11 12:39:38.000,30.313819892727118,18.54917976273794,-53.16102090909967,True +2025-03-11 12:39:38.500,37.405457066943825,25.643212966546116,-66.08114009433457,True +2025-03-11 12:39:39.000,43.006033248584835,31.253687414169946,-76.2961430905379,True +2025-03-11 12:39:39.500,46.87637775675373,35.11953167112178,-83.32372570995717,True +2025-03-11 12:39:40.000,48.84849991238925,37.065020676803314,-86.88629219535237,True +2025-03-11 12:39:40.500,48.823735071081614,37.01412916047393,-86.79985355242458,True +2025-03-11 12:39:41.000,46.80833072546274,34.97220974564118,-83.0804483863084,True +2025-03-11 12:39:41.500,42.89111600677903,31.014595694407653,-75.93869653091859,True +2025-03-11 12:39:42.000,37.24071054773325,25.320574490969364,-65.59636130259949,True +2025-03-11 12:39:42.500,30.117653850932054,18.15144797202091,-52.57104598642161,True +2025-03-11 12:39:43.000,21.82926537115902,9.818094789350564,-37.38864105064177,True +2025-03-11 12:39:43.500,12.74172250121451,0.6750853690847418,-20.74223044638292,True +2025-03-11 12:39:44.000,3.2567326184519283,-8.85741617412136,-3.4180622106269007,True +2025-03-11 12:39:44.500,-6.210841323539032,-18.35914210868674,13.85715995430538,True +2025-03-11 12:39:45.000,-15.238253538528918,-27.41210076917648,30.3363539316253,True +2025-03-11 12:39:45.500,-23.421819546714385,-35.62509801418509,45.27359250332695,True +2025-03-11 12:39:46.000,-30.415653761507187,-42.62590349665274,57.99929695912924,True +2025-03-11 12:39:46.500,-35.88570891169349,-48.10264699936937,67.94654309643259,True +2025-03-11 12:39:47.000,-39.613227662286036,-51.818967217492336,74.70306367670234,True +2025-03-11 12:39:47.500,-41.43460790215812,-53.62011031241679,77.98850452557264,True +2025-03-11 12:39:48.000,-41.25169007621834,-53.42254325122312,77.63170348758224,True +2025-03-11 12:39:48.500,-39.090153910536856,-51.223077701550906,73.6561928240331,True +2025-03-11 12:39:49.000,-35.04572639052059,-47.12425118067844,66.22065961441248,True +2025-03-11 12:39:49.500,-29.289775564373713,-41.323198918863575,55.65642037204652,True +2025-03-11 12:39:50.000,-22.07104187794966,-34.06761001718462,42.43830921360538,True +2025-03-11 12:39:50.500,-13.709062331236266,-25.653140429146205,27.1588903212462,True +2025-03-11 12:39:51.000,-4.575321027304156,-16.475496378579283,10.46336415784109,True +2025-03-11 12:39:51.500,4.9209236298589865,-6.943131147841367,-6.884907148538314,True +2025-03-11 12:39:52.000,14.371824121511457,2.540845407102113,-24.12971846333312,True +2025-03-11 12:39:52.500,23.340523968189746,11.547245527008073,-40.485075169719124,True +2025-03-11 12:39:53.000,31.459654245954262,19.682633253439867,-55.2636818920768,True +2025-03-11 12:39:53.500,38.34328449734498,26.588038937382812,-67.81666559703548,True +2025-03-11 12:39:54.000,43.691570104575646,31.942045266264156,-77.56195490507906,True +2025-03-11 12:39:54.500,47.2900570523299,35.53329770697879,-84.09405404048044,True +2025-03-11 12:39:55.000,48.96117306367872,37.191082518579584,-87.11417439741705,True +2025-03-11 12:39:55.500,48.630948828943815,36.83684191818305,-86.49082179969703,True +2025-03-11 12:39:56.000,46.336821386633304,34.48817432063956,-82.26800723864704,True +2025-03-11 12:39:56.500,42.16296705993237,30.25587063927919,-74.60081832912321,True +2025-03-11 12:39:57.000,36.27884081498352,24.328532088611095,-63.819458501679435,True +2025-03-11 12:39:57.500,28.9569293886267,16.969702034503765,-50.43284047794495,True +2025-03-11 12:39:58.000,20.52042937574162,8.489902227190054,-35.01318546731836,True +2025-03-11 12:39:58.500,11.35081535730706,-0.7298975852534016,-18.245192139703597,True +2025-03-11 12:39:59.000,1.847961971129638,-10.289597373226687,-0.8809424057435818,True +2025-03-11 12:39:59.500,-7.582785358301228,-19.75342994262434,16.33125111391277,True +2025-03-11 12:40:00.000,-16.51205635599527,-28.700495805792137,32.61934846820677,True +2025-03-11 12:40:00.500,-24.53777722327315,-36.754633899588924,47.26305055020755,True +2025-03-11 12:40:01.000,-31.32484146309804,-43.55171269904106,59.614550294820496,True +2025-03-11 12:40:01.500,-36.54151298226967,-48.77407320769703,69.13240220817319,True +2025-03-11 12:40:02.000,-39.999804954114005,-52.21760730055831,75.40455940889598,True +2025-03-11 12:40:02.500,-41.520479633250616,-53.722463456346254,78.14849178589202,True +2025-03-11 12:40:03.000,-41.054293262688255,-53.22111528866156,77.2490522133061,True +2025-03-11 12:40:03.500,-38.597366290938275,-50.72992529145595,72.7271707164638,True +2025-03-11 12:40:04.000,-34.27798084152829,-46.3591233997479,64.80052716794042,True +2025-03-11 12:40:04.500,-28.281930763996375,-40.33111781261497,53.8273130729859,True +2025-03-11 12:40:05.000,-20.878481940229467,-32.87482091656004,40.27294555753045,True +2025-03-11 12:40:05.500,-12.38357382071308,-24.323532691851376,24.73809884316497,True +2025-03-11 12:40:06.000,-3.1635228393880257,-15.06038320005008,7.894589862062661,True +2025-03-11 12:40:06.500,6.347165010245354,-5.4971349924371475,-9.484119231851889,True +2025-03-11 12:40:07.000,15.745050002822573,3.939806501708534,-26.64745385014177,True +2025-03-11 12:40:07.500,24.62275952599382,12.84048755780207,-42.841848333214415,True +2025-03-11 12:40:08.000,32.580398678807306,20.813004615543093,-57.33542440383423,True +2025-03-11 12:40:08.500,39.252221873319506,27.503204885854466,-69.51100638337576,True +2025-03-11 12:40:09.000,44.36888731286754,32.61120633822453,-78.81787414659888,True +2025-03-11 12:40:09.500,47.67703974136199,35.91224218535859,-84.8317237436524,True +2025-03-11 12:40:10.000,49.054954694353064,37.272799663628554,-87.31153851658648,True +2025-03-11 12:40:10.500,48.42820256631475,36.61974941884408,-86.14233674256509,True +2025-03-11 12:40:11.000,45.828597164508835,33.975221732726325,-81.35907273712841,True +2025-03-11 12:40:11.500,41.36243843218132,29.485142453169658,-73.19069587453019,True +2025-03-11 12:40:12.000,35.25211162529902,23.336922535438944,-61.97459955327927,True +2025-03-11 12:40:12.500,27.75886692737508,15.777950898383015,-48.237780001367376,True +2025-03-11 12:40:13.000,19.194089140279495,7.158096999839728,-32.576910212900906,True +2025-03-11 12:40:13.500,9.947652699503928,-2.142114185309028,-15.675224125441044,True +2025-03-11 12:40:14.000,0.4157967050261914,-11.707580318747604,1.7329714257128936,True +2025-03-11 12:40:14.500,-8.956442981407745,-21.118921232107066,18.851707881614015,True +2025-03-11 12:40:15.000,-17.771217386830497,-29.953884744679712,34.93421341258814,True +2025-03-11 12:40:15.500,-25.64184168331467,-37.83450902920424,49.26868375457364,True +2025-03-11 12:40:16.000,-32.20743405356157,-44.422728990033605,61.22673512885471,True +2025-03-11 12:40:16.500,-37.18345583186763,-49.4079448521788,70.29469240252106,True +2025-03-11 12:40:17.000,-40.35682257070775,-52.563671400090435,76.05215458343196,True +2025-03-11 12:40:17.500,-41.58803488252807,-53.76469329324493,78.26154732731065,True +2025-03-11 12:40:18.000,-40.812962821680216,-52.974995805757494,76.80014427186094,True +2025-03-11 12:40:18.500,-38.068651558287485,-50.195607055335515,71.76880754987465,True +2025-03-11 12:40:19.000,-33.48549152415838,-45.567883189674504,63.350711635340275,True +2025-03-11 12:40:19.500,-27.260400795336558,-39.29883363642282,51.9558931072417,True +2025-03-11 12:40:20.000,-19.66574647234475,-31.64406685044693,38.04677643387849,True +2025-03-11 12:40:20.500,-11.03300814623249,-22.968456587292003,22.272513078058044,True +2025-03-11 12:40:21.000,-1.749648916276091,-13.64084252824592,5.305778601530558,True +2025-03-11 12:40:21.500,7.774319042253291,-4.06371983262067,-12.08919443003482,True +2025-03-11 12:40:22.000,17.124081489491807,5.315477063628001,-29.171675691524598,True +2025-03-11 12:40:22.500,25.884783011516,14.102070877623873,-45.15436023121232,True +2025-03-11 12:40:23.000,33.663605616142824,21.90669380472667,-59.3366002075116,True +2025-03-11 12:40:23.500,40.11942013298644,28.37040213497368,-71.10039271083974,True +2025-03-11 12:40:24.000,44.96893847058941,33.217691924559645,-79.93703548080386,True +2025-03-11 12:40:24.500,47.99916383881031,36.2461676661673,-85.44239023932145,True +2025-03-11 12:40:25.000,49.08456901844073,37.30359699383964,-87.37743137752648,True +2025-03-11 12:40:25.500,48.16260793296146,36.35557202090513,-85.64977596357029,True +2025-03-11 12:40:26.000,45.27895846334534,33.433951390398164,-80.3461643619852,True +2025-03-11 12:40:26.500,40.55747094078829,28.669632497169765,-71.69561584886307,True +2025-03-11 12:40:27.000,34.22686241768043,22.280576361606887,-60.085310784725024,True +2025-03-11 12:40:27.500,26.545048014291105,14.550558034662508,-46.02815567070794,True +2025-03-11 12:40:28.000,17.847935539263243,5.805113537168844,-30.12077682040007,True +2025-03-11 12:40:28.500,8.531042287075076,-3.5597133331713717,-13.09126006538439,True +2025-03-11 12:40:29.000,-0.9902217456608164,-13.126838266444203,4.313582979968453,True +2025-03-11 12:40:29.500,-10.302741508389325,-22.482406408993555,21.328023615513235,True +2025-03-11 12:40:30.000,-18.999354776781846,-31.215223122846197,37.195019050223145,True +2025-03-11 12:40:30.500,-26.707217342773355,-38.92562268596723,51.252366303751245,True +2025-03-11 12:40:31.000,-33.0571301524256,-45.2818094970782,62.83985457710808,True +2025-03-11 12:40:31.500,-37.776992327599636,-50.00184963209819,71.42712025590694,True +2025-03-11 12:40:32.000,-40.667764741103085,-52.87935754803595,76.66726546896885,True +2025-03-11 12:40:32.500,-41.59858496231558,-53.77778969765967,78.31908937152015,True +2025-03-11 12:40:33.000,-40.52243759619559,-52.67797093400179,76.32604791403588,True +2025-03-11 12:40:33.500,-37.5000545514381,-49.62293238272569,70.77763571439425,True +2025-03-11 12:40:34.000,-32.65697855006335,-44.7338065824022,61.91158038907588,True +2025-03-11 12:40:34.500,-26.21304476416065,-38.22660521187004,50.09125110829744,True +2025-03-11 12:40:35.000,-18.442215460905423,-30.404724127339815,35.873046056320426,True +2025-03-11 12:40:35.500,-9.694436970749322,-21.605905646919638,19.876499103382894,True +2025-03-11 12:40:36.000,-0.3427466060863018,-12.208294998959284,2.790382327188039,True +2025-03-11 12:40:36.500,9.180918815662062,-2.6384761119365048,-14.642641873937993,True +2025-03-11 12:40:37.000,18.464338398317583,6.671560264234118,-31.602095877372626,True +2025-03-11 12:40:37.500,27.101551965389813,15.33287732016789,-47.36687728511466,True +2025-03-11 12:40:38.000,34.70786048272204,22.959856474184086,-61.24003724225125,True +2025-03-11 12:40:38.500,40.93824313542834,29.210932679591345,-72.60629559903579,True +2025-03-11 12:40:39.000,45.53580301584515,33.79568012266928,-80.9627291595198,True +2025-03-11 12:40:39.500,48.28785441257737,36.53430984065077,-85.94822720038073,True +2025-03-11 12:40:40.000,49.0696504090984,37.29673564983975,-87.33436767961348,True +2025-03-11 12:40:40.500,47.85659503148462,36.043201047786475,-85.06703897194352,True +2025-03-11 12:40:41.000,44.69473621450341,32.83470212878162,-79.25227817836378,True +2025-03-11 12:40:41.500,39.725356843609504,27.815043497640374,-70.14237466213378,True +2025-03-11 12:40:42.000,33.16203599854603,21.20329357945898,-58.11129824838723,True +2025-03-11 12:40:42.500,25.29182260659521,13.295099546413782,-43.73934223784692,True +2025-03-11 12:40:43.000,16.476968832173696,4.436101824913116,-27.62485973160577,True +2025-03-11 12:40:43.500,7.098319639620279,-4.985184652763688,-10.486327148559193,True +2025-03-11 12:40:44.000,-2.415592162056481,-14.54599147340478,6.913745159079491,True +2025-03-11 12:40:44.500,-11.662969508486992,-23.825107664738407,23.81717613514312,True +2025-03-11 12:40:45.000,-20.230402044440908,-32.42133252340408,39.445657906369235,True +2025-03-11 12:40:45.500,-27.737172277100107,-39.95979150601728,53.14696636670135,True +2025-03-11 12:40:46.000,-33.86530966814708,-46.08227731655427,64.28905056524404,True +2025-03-11 12:40:46.500,-38.32651524204395,-50.53333641000517,72.39588074347401,True +2025-03-11 12:40:47.000,-40.92708850438083,-53.129244197022196,77.11103749420968,True +2025-03-11 12:40:47.500,-41.558621763479756,-53.74145469400072,78.22887953882098,True +2025-03-11 12:40:48.000,-40.189209129703656,-52.34195721086868,75.6889644399904,True +2025-03-11 12:40:48.500,-36.883830576356964,-48.99944232322805,69.6177143201463,True +2025-03-11 12:40:49.000,-31.7848542535321,-43.8570399434845,60.26754846584975,True +2025-03-11 12:40:49.500,-25.123747353210558,-37.13259263508164,48.0671982058324,True +2025-03-11 12:40:50.000,-17.17091161538288,-29.143910654685758,33.53005223192454,True +2025-03-11 12:40:50.500,-8.30652062882442,-20.236127655644136,17.322990246817948,True +2025-03-11 12:40:51.000,1.0844761626168147,-10.79436524843329,0.154829728549321,True +2025-03-11 12:40:51.500,10.605936999789163,-1.2369691487322683,-17.233870721231977,True +2025-03-11 12:40:52.000,19.818209415434193,8.009144226803407,-34.054334156527744,True +2025-03-11 12:40:52.500,28.32464125956104,16.53437469638811,-49.5736989915415,True +2025-03-11 12:40:53.000,35.73943436248741,23.967925707244945,-63.093777506451396,True +2025-03-11 12:40:53.500,41.749100996023714,29.98822144299778,-74.03547519578372,True +2025-03-11 12:40:54.000,46.08045115495465,34.31747440793444,-81.87305282283648,True +2025-03-11 12:40:54.500,48.53828026602024,36.76578533997499,-86.3330478384991,True +2025-03-11 12:40:55.000,49.018705807079236,37.218548850771406,-87.17277069979554,True +2025-03-11 12:40:55.500,47.50803215352892,35.67808645545435,-84.3604810181695,True +2025-03-11 12:40:56.000,44.05343050331722,32.19136408722618,-78.0347482501375,True +2025-03-11 12:40:56.500,38.82748189701181,26.9160940063406,-68.45655288555916,True +2025-03-11 12:40:57.000,32.05811881697499,20.097369462333326,-56.053712861376745,True +2025-03-11 12:40:57.500,24.03216560303691,12.01847090676253,-41.37003578107513,True +2025-03-11 12:40:58.000,15.100359497325293,3.0523500930731613,-25.054289661872208,True +2025-03-11 12:40:58.500,5.672853858727993,-6.412219110037414,-7.826052955465478,True +2025-03-11 12:40:59.000,-3.8301043363192937,-15.962058212753552,9.533220806876379,True +2025-03-11 12:40:59.500,-13.000671507334024,-25.176939289954838,26.28429654616212,True +2025-03-11 12:41:00.000,-21.44043258313816,-33.62993002856349,41.67412074749722,True +2025-03-11 12:41:00.500,-28.760131569126305,-40.97027491235254,55.02513414477342,True +2025-03-11 12:41:01.000,-34.65448991326082,-46.86272799338882,65.75197657023679,True +2025-03-11 12:41:01.500,-38.84297862674552,-51.047060017751235,73.36170232228503,True +2025-03-11 12:41:02.000,-41.14153893713815,-53.335118667328786,77.5200865763817,True +2025-03-11 12:41:02.500,-41.482514600836026,-53.64728850492867,78.06822033300028,True +2025-03-11 12:41:03.000,-39.82620708604727,-51.95045991364504,74.99964615046348,True +2025-03-11 12:41:03.500,-36.246990082361066,-48.327143525527845,68.42609340604737,True +2025-03-11 12:41:04.000,-30.899886757463598,-42.936866638387116,58.61955281902312,True +2025-03-11 12:41:04.500,-24.01203766172248,-36.00803619925242,46.02095632784712,True +2025-03-11 12:41:05.000,-15.907677492876497,-27.858529806515506,31.201660911527487,True +2025-03-11 12:41:05.500,-6.939917565045442,-18.836211822270485,14.793657972263084,True +2025-03-11 12:41:06.000,2.5095986135466077,-9.353610627089818,-2.4537604672327338,True +2025-03-11 12:41:06.500,12.014697618288233,0.18480085963123,-19.789934468655705,True +2025-03-11 12:41:07.000,21.140228408731403,9.350731182934798,-36.46924013934196,True +2025-03-11 12:41:07.500,29.50939074968318,17.732946762137107,-51.73867273129183,True +2025-03-11 12:41:08.000,36.74262067240261,24.975970712192893,-64.91833914484394,True +2025-03-11 12:41:08.500,42.50939411990723,30.760246687403992,-75.43105416076264,True +2025-03-11 12:41:09.000,46.56905759727984,34.818965364738595,-82.81628800386135,True +2025-03-11 12:41:09.500,48.737556537376236,36.96943983698602,-86.73972478770075,True +2025-03-11 12:41:10.000,48.921048597317125,37.13016641909575,-87.02727725295529,True +2025-03-11 12:41:10.500,47.10965017552071,35.28540128473882,-83.68946986266403,True +2025-03-11 12:41:11.000,43.38397907081819,31.514476249927576,-76.86171414682313,True +2025-03-11 12:41:11.500,37.90637913251734,25.999504187771038,-66.82358299625136,True +2025-03-11 12:41:12.000,30.92536886506218,18.971142705852117,-54.03881777977985,True +2025-03-11 12:41:12.500,22.74793392021385,10.738011502874535,-39.07809205596095,True +2025-03-11 12:41:13.000,13.727881317895203,1.6536764978559537,-22.58079975572605,True +2025-03-11 12:41:13.500,4.26284424188177,-7.850383000868466,-5.288589681413527,True +2025-03-11 12:41:14.000,-5.228049918347212,-17.369488260697917,12.049703661796183,True +2025-03-11 12:41:14.500,-14.319299773773391,-26.494605284212827,28.629806120610198,True +2025-03-11 12:41:15.000,-22.608595647244837,-34.813526915976446,43.775039274353574,True +2025-03-11 12:41:15.500,-29.73947599370595,-41.94814583014028,56.761448054308346,True +2025-03-11 12:41:16.000,-35.39164821595919,-47.59766785663306,67.07713004949767,True +2025-03-11 12:41:16.500,-39.30926640577691,-51.515404553261305,74.22161033363615,True +2025-03-11 12:41:17.000,-41.32802559791369,-53.518002463686244,77.87975274674082,True +2025-03-11 12:41:17.500,-41.36065630953451,-53.525057160385884,77.8955367254247,True +2025-03-11 12:41:18.000,-39.405113960340266,-51.527219617403006,74.24077653120199,True +2025-03-11 12:41:18.500,-35.54955820451035,-47.62947093571359,67.15581725745515,True +2025-03-11 12:41:19.000,-29.964925385610854,-41.99240699567971,56.91000927881416,True +2025-03-11 12:41:19.500,-22.875194217549268,-34.868651401820145,43.95089947546545,True +2025-03-11 12:41:20.000,-14.62154055420238,-26.56285801786063,28.858796860008084,True +2025-03-11 12:41:20.500,-5.54629416036126,-17.453972076352002,12.278589620314184,True +2025-03-11 12:41:21.000,3.921586181916793,-7.930428277767495,-5.018334585325819,True +2025-03-11 12:41:21.500,13.397190168595019,1.578809574485569,-22.2845454796944,True +2025-03-11 12:41:22.000,22.45033714717233,10.661838039433258,-38.78717671383445,True +2025-03-11 12:41:22.500,30.667940596006737,18.905998595554223,-53.784020705420176,True +2025-03-11 12:41:23.000,37.69382071868354,25.937282742814542,-66.59121393974374,True +2025-03-11 12:41:23.500,43.230239088623875,31.467108381131435,-76.66465029687124,True +2025-03-11 12:41:24.000,47.00810800374296,35.256135751174135,-83.56133736401776,True +2025-03-11 12:41:24.500,48.882671683735644,37.11046886400703,-86.95868230481054,True +2025-03-11 12:41:25.000,48.77420030628227,36.96421193564041,-86.70645128322667,True +2025-03-11 12:41:25.500,46.67502018965473,34.838174544891544,-82.82600138041079,True +2025-03-11 12:41:26.000,42.681419427000186,30.805311966553823,-75.49296781966709,True +2025-03-11 12:41:26.500,36.96364137747345,25.03965882597553,-65.01157096700736,True +2025-03-11 12:41:27.000,29.774219024130694,17.815676503331844,-51.85572453272526,True +2025-03-11 12:41:27.500,21.436127895664836,9.437908139043724,-36.61045404667788,True +2025-03-11 12:41:28.000,12.321033533237717,0.2729145927844923,-19.951401289787984,True +2025-03-11 12:41:28.500,2.8303020355519863,-9.259234698845697,-2.610951461388104,True +2025-03-11 12:41:29.000,-6.621350196847497,-18.747583305692313,14.64137808686706,True +2025-03-11 12:41:29.500,-15.617953998706,-27.78202948042154,31.05533753156081,True +2025-03-11 12:41:30.000,-23.75565700325387,-35.94551240570143,45.90403051645016,True +2025-03-11 12:41:30.500,-30.687207686682243,-42.889306748033135,58.52096441927989,True +2025-03-11 12:41:31.000,-36.09145567202749,-48.28839321865064,68.35264377532857,True +2025-03-11 12:41:31.500,-39.735412782431496,-51.939490063422035,74.94808650406284,True +2025-03-11 12:41:32.000,-41.46760103261243,-53.64952411949325,78.05590074797588,True +2025-03-11 12:41:32.500,-41.192728056224055,-53.35537456125545,77.52674452015107,True +2025-03-11 12:41:33.000,-38.94601181150826,-51.07667710952143,73.38054017734872,True +2025-03-11 12:41:33.500,-34.81078796602982,-46.9028087133285,65.78776840560298,True +2025-03-11 12:41:34.000,-28.975612765694915,-41.01747262436301,55.10088093314658,True +2025-03-11 12:41:34.500,-21.70192251433157,-33.69390776054623,41.798814085319705,True +2025-03-11 12:41:35.000,-13.293873004398625,-25.243424948769512,26.436955821198882,True +2025-03-11 12:41:35.500,-4.140210449892482,-16.047598436687874,9.70813455773894,True +2025-03-11 12:41:36.000,5.36349338388827,-6.4927496874078505,-7.652720621420377,True +2025-03-11 12:41:36.500,14.788841634964585,2.9736583706960626,-24.86916426530529,True +2025-03-11 12:41:37.000,23.7429134985166,11.950587365511463,-41.19998976737575,True +2025-03-11 12:41:37.500,31.80142625321783,20.041295945357593,-55.9079579450956,True +2025-03-11 12:41:38.000,38.62519496536187,26.87316503150565,-68.33813181324626,True +2025-03-11 12:41:38.500,43.91522295126725,32.152979461902255,-77.95282426276866,True +2025-03-11 12:41:39.000,47.41828841755223,35.65274578064051,-84.33069429344347,True +2025-03-11 12:41:39.500,49.00816865931213,37.21780397017704,-87.18768359694906,True +2025-03-11 12:41:40.000,48.602478587651206,36.77548113782827,-86.38943279877697,True +2025-03-11 12:41:40.500,46.19988001283636,34.35018440339918,-81.9883061670109,True +2025-03-11 12:41:41.000,41.92250914307996,30.03436381942215,-74.16224212214014,True +2025-03-11 12:41:41.500,35.96811225818156,24.046191219033126,-63.25597627134461,True +2025-03-11 12:41:42.000,28.602295035990462,16.623437748234068,-49.75063771303955,True +2025-03-11 12:41:42.500,20.129390576215627,8.09836895872491,-34.240659255496,True +2025-03-11 12:41:43.000,10.92605700062207,-1.1506782269483182,-17.432754612069264,True +2025-03-11 12:41:43.500,1.4101656398425033,-10.698870499341984,-0.058860998496849434,True +2025-03-11 12:41:44.000,-7.993198649682144,-20.152352561962033,17.120830325252243,True +2025-03-11 12:41:44.500,-16.880429049741622,-29.069145505878996,33.362282738073844,True +2025-03-11 12:41:45.000,-24.864709063020747,-37.07581811007343,47.912497233994145,True +2025-03-11 12:41:45.500,-31.580267834277652,-43.80616871151793,60.14419832633562,True +2025-03-11 12:41:46.000,-36.738340092646474,-48.96579094895695,69.52195807197675,True +2025-03-11 12:41:46.500,-40.10911980027117,-52.33063771726398,75.64554532692325,True +2025-03-11 12:41:47.000,-41.54011499865405,-53.74327140574583,78.21669202854008,True +2025-03-11 12:41:47.500,-40.977100083822506,-53.14881909291708,77.17083323681157,True +2025-03-11 12:41:48.000,-38.43820422382416,-50.55599137756702,72.49352680507413,True +2025-03-11 12:41:48.500,-34.046479548928474,-46.12125953791064,64.41761475090976,True +2025-03-11 12:41:49.000,-27.973333922629372,-40.0080891663616,53.31643671077926,True +2025-03-11 12:41:49.500,-20.508992665006353,-32.49408923932948,39.70031091785388,True +2025-03-11 12:41:50.000,-11.965950312858608,-23.90441858528831,24.084423899893938,True +2025-03-11 12:41:50.500,-2.741399318476569,-14.62059114990608,7.2062768916558815,True +2025-03-11 12:41:51.000,6.780878497501262,-5.055889150511252,-10.180976120604573,True +2025-03-11 12:41:51.500,16.166102694747615,4.3606255463485715,-27.31414002808218,True +2025-03-11 12:41:52.000,24.998932287290916,13.228054175915624,-43.450888765412536,True +2025-03-11 12:41:52.500,32.900117618602934,21.147121825723865,-57.864248479210076,True +2025-03-11 12:41:53.000,39.51844656516334,27.769186153652974,-69.91716033752584,True +2025-03-11 12:41:53.500,44.548631863697715,32.790135469238265,-79.0763984504639,True +2025-03-11 12:41:54.000,47.78130958148437,36.02626313995563,-84.97389183088245,True +2025-03-11 12:41:54.500,49.07541363005152,37.286869983592325,-87.28896401548757,True +2025-03-11 12:41:55.000,48.349649501215445,36.54980508579911,-85.95302415633365,True +2025-03-11 12:41:55.500,45.67131085290338,33.825969423788024,-81.01363597703005,True +2025-03-11 12:41:56.000,41.141761890339865,29.25313737155747,-72.69353887961952,True +2025-03-11 12:41:56.500,34.95740901925562,23.02992910226915,-61.376583239305084,True +2025-03-11 12:41:57.000,27.39013066453819,15.42140739265458,-47.547851079144365,True +2025-03-11 12:41:57.500,18.784564063364584,6.761197018961903,-31.796632364361944,True +2025-03-11 12:41:58.000,9.513529335332944,-2.554232068226381,-14.856465903204596,True +2025-03-11 12:41:58.500,-0.006910305247440969,-12.126123580738264,2.547195442380695,True +2025-03-11 12:41:59.000,-9.365326501561686,-21.520277142382042,19.638372730326445,True +2025-03-11 12:41:59.500,-18.15023807125718,-30.3233588638547,35.66764750762798,True +2025-03-11 12:42:00.000,-25.961832881737138,-38.16456698820215,49.90747447032411,True +2025-03-11 12:42:00.500,-32.462414978131164,-44.671088958029216,61.7507871335122,True +2025-03-11 12:42:01.000,-37.36725918323357,-49.572777550871436,70.66882621462095,True +2025-03-11 12:42:01.500,-40.44381486679971,-52.64823784346892,76.27447064165497,True +2025-03-11 12:42:02.000,-41.57748234919245,-53.7769187251045,78.32144348487033,True +2025-03-11 12:42:02.500,-40.71462644851552,-52.88393125117086,76.70167893438892,True +2025-03-11 12:42:03.000,-37.89802307226317,-50.025782233306956,71.50047854003483,True +2025-03-11 12:42:03.500,-33.2306197327276,-45.314634765291515,62.953697146296136,True +2025-03-11 12:42:04.000,-26.945692789481683,-38.97626433523232,51.416369066406965,True +2025-03-11 12:42:04.500,-19.292521791140732,-31.276645951099653,37.41605170534113,True +2025-03-11 12:42:05.000,-10.630247807661902,-22.564164902749027,21.567794693432667,True +2025-03-11 12:42:05.500,-1.3202282922290731,-13.210609473182249,4.580023638725771,True +2025-03-11 12:42:06.000,8.201479201063755,-3.6443302145794068,-12.772497744395176,True +2025-03-11 12:42:06.500,17.532401112978143,5.7297009998354484,-29.797527034463478,True +2025-03-11 12:42:07.000,26.25504500972153,14.482132581495899,-45.727942406109584,True +2025-03-11 12:42:07.500,33.97973556176681,22.22585072937334,-59.83209662235518,True +2025-03-11 12:42:08.000,40.366690703581654,28.629189458378114,-71.48225871095971,True +2025-03-11 12:42:08.500,45.141418318998916,33.399402759330016,-80.1831522800264,True +2025-03-11 12:42:09.000,48.08929112912729,36.33357993063487,-85.5313145956531,True +2025-03-11 12:42:09.500,49.08408042339972,37.30937253842937,-87.30721478005918,True +2025-03-11 12:42:10.000,48.075403900605565,36.26879792861595,-85.4304257769199,True +2025-03-11 12:42:10.500,45.10598159158144,33.267015356661695,-79.96918448672236,True +2025-03-11 12:42:11.000,40.30521613625366,28.421229742057914,-71.17939736385922,True +2025-03-11 12:42:11.500,33.89429865080643,21.95179105132228,-59.43642430786371,True +2025-03-11 12:42:12.000,26.15177140863591,14.161625651273278,-45.27938003617824,True +2025-03-11 12:42:12.500,17.427771555700357,5.3910849973269945,-29.31877791522905,True +2025-03-11 12:42:13.000,8.094561300044283,-3.9954079364899955,-12.256919341906077,True +2025-03-11 12:42:13.500,-1.4411504759821383,-13.565551377153568,5.1345699221307335,True +2025-03-11 12:42:14.000,-10.728919406619486,-22.89154235807781,22.1038086105778,True +2025-03-11 12:42:14.500,-19.39104489125777,-31.588957522352068,37.90552001671285,True +2025-03-11 12:42:15.000,-27.0238466837392,-39.24135302515631,51.850604429463566,True +2025-03-11 12:42:15.500,-33.29632701098051,-45.51993666834138,63.282907971115165,True +2025-03-11 12:42:16.000,-37.9408655545595,-50.159408229538165,71.72739714365137,True +2025-03-11 12:42:16.500,-40.73692254875154,-52.94539239634668,76.81532003368943,True +2025-03-11 12:42:17.000,-41.576655819368234,-53.7616693139843,78.30915351626784,True +2025-03-11 12:42:17.500,-40.414012462093865,-52.57873440806862,76.14524842819286,True +2025-03-11 12:42:18.000,-37.30363546048953,-49.42948170595791,70.43917197826914,True +2025-03-11 12:42:18.500,-32.394157768832464,-44.46404332433135,61.41843099930142,True +2025-03-11 12:42:19.000,-25.875195099095734,-37.895694765048304,49.497328778824965,True +2025-03-11 12:42:19.500,-18.0541877275298,-30.02393130582743,35.18339789557781,True +2025-03-11 12:42:20.000,-9.269283832046094,-21.179603237047314,19.132030884171847,True +2025-03-11 12:42:20.500,0.08059855312315552,-11.7752115365555,2.021225029311181,True +2025-03-11 12:42:21.000,9.607713791758119,-2.217419667886968,-15.374169340683018,True +2025-03-11 12:42:21.500,18.872636140268245,7.078355111558184,-32.298701235761555,True +2025-03-11 12:42:22.000,27.468688307448176,15.71843260062003,-47.995950225006766,True +2025-03-11 12:42:22.500,35.02022703039482,23.277115681490468,-61.75200350743691,True +2025-03-11 12:42:23.000,41.18472528225125,29.450634139222927,-72.97444144673962,True +2025-03-11 12:42:23.500,45.70656746684234,33.9648582015491,-81.19644728768239,True +2025-03-11 12:42:24.000,48.36979956768504,36.607983893090896,-86.0339726703734,True +2025-03-11 12:42:24.500,49.06294665500292,37.28139102910268,-87.25846839088098,True +2025-03-11 12:42:25.000,47.754670031861835,35.939694322106675,-84.83501331054082,True +2025-03-11 12:42:25.500,44.503719483465765,32.64864391810579,-78.85518138362673,True +2025-03-11 12:42:26.000,39.446258165748574,27.557165697712694,-69.58495885797433,True +2025-03-11 12:42:26.500,32.822966725201624,20.8968194338017,-57.44886771618472,True +2025-03-11 12:42:27.000,24.912328911093137,12.940984986664521,-42.97883433496196,True +2025-03-11 12:42:27.500,16.063236588019844,4.041011685849739,-26.812322683305954,True +2025-03-11 12:42:28.000,6.675061047295298,-5.388213462671294,-9.659322784912256,True +2025-03-11 12:42:28.500,-2.8490179481731546,-14.954206617497341,7.73802663511459,True +2025-03-11 12:42:29.000,-12.070162758339373,-24.221873511185088,24.580256228743078,True +2025-03-11 12:42:29.500,-20.608401561386543,-32.779417118134866,40.14819505925923,True +2025-03-11 12:42:30.000,-28.06206646033647,-40.244807239685585,53.736032367804995,True +2025-03-11 12:42:30.500,-34.11337499824376,-46.30582642604435,64.77213230618437,True +2025-03-11 12:42:31.000,-38.48293412524845,-50.68163247985724,72.73425350900308,True +2025-03-11 12:42:31.500,-41.00476805263624,-53.1917283715982,77.29380966073784,True +2025-03-11 12:42:32.000,-41.54834241370347,-53.70196812981408,78.2379585793466,True +2025-03-11 12:42:32.500,-40.09290163536964,-52.221294153744104,75.5568077845144,True +2025-03-11 12:42:33.000,-36.70008752930468,-48.79410983039729,69.33057791186947,True +2025-03-11 12:42:33.500,-31.521875755294552,-43.57281300507997,59.84754698524242,True +2025-03-11 12:42:34.000,-24.789000110647546,-36.79589986626431,47.52459031690941,True +2025-03-11 12:42:34.500,-16.797940341060812,-28.754042387638663,32.90769904577851,True +2025-03-11 12:42:35.000,-7.89404841212021,-19.80644699327597,16.643159812954593,True +2025-03-11 12:42:35.500,1.5159551869781034,-10.348252280493645,-0.5656848256488016,True +2025-03-11 12:42:36.000,11.020014080489467,-0.7955099332333355,-17.948549507372675,True +2025-03-11 12:42:36.500,20.20830739963976,8.429637987366817,-34.716891653256894,True +2025-03-11 12:42:37.000,28.67911711401556,16.919762866231988,-50.1942240345938,True +2025-03-11 12:42:37.500,36.04205156005455,24.29500374589095,-63.64577967132253,True +2025-03-11 12:42:38.000,41.98119878994914,30.22960493087741,-74.4578246183252,True +2025-03-11 12:42:38.500,46.23256965745867,34.479245583400456,-82.18060860335271,True +2025-03-11 12:42:39.000,48.60107321271725,36.83614819760571,-86.44843174443847,True +2025-03-11 12:42:39.500,48.98966152367662,37.203765610041245,-87.11845304175932,True +2025-03-11 12:42:40.000,47.38901655124674,35.5690154062074,-84.14558345867079,True +2025-03-11 12:42:40.500,43.85510801102393,31.993701214717767,-77.65355570841264,True +2025-03-11 12:42:41.000,38.561575754845855,26.63425521795682,-67.9300482484017,True +2025-03-11 12:42:41.500,31.725279771186596,19.752749520292028,-55.41342334238114,True +2025-03-11 12:42:42.000,23.654520024213042,11.632319421356549,-40.64961425270262,True +2025-03-11 12:42:42.500,14.696595052623616,2.636383737035198,-24.289233661416873,True +2025-03-11 12:42:43.000,5.263851474004406,-6.847670691076806,-7.056254571660816,True +2025-03-11 12:42:43.500,-4.246490479209708,-16.39339816939829,10.298683755847373,True +2025-03-11 12:42:44.000,-13.395434643691688,-25.579006445538994,27.0082423590826,True +2025-03-11 12:42:44.500,-21.780779514244248,-33.99157525163149,42.309181162133946,True +2025-03-11 12:42:45.000,-29.052212114834976,-41.26495441454741,55.55129531680983,True +2025-03-11 12:42:45.500,-34.8732881422892,-47.09030683185952,66.14235963171458,True +2025-03-11 12:42:46.000,-38.975852446652745,-51.19943431675872,73.61869268392324,True +2025-03-11 12:42:46.500,-41.19458811282637,-53.407154769045434,77.65269290566626,True +2025-03-11 12:42:47.000,-41.441263196048965,-53.62381958477269,78.06203348991394,True +2025-03-11 12:42:47.500,-39.69411960441499,-51.84553143650586,74.8265961460848,True +2025-03-11 12:42:48.000,-36.02558935318683,-48.15137398007107,68.09097052616647,True +2025-03-11 12:42:48.500,-30.60396572760343,-42.67192795697295,58.1478147956963,True +2025-03-11 12:42:49.000,-23.668762043139616,-35.67346380408121,45.463973708743225,True +2025-03-11 12:42:49.500,-15.51183101196807,-27.473543132124853,30.555305549815014,True +2025-03-11 12:42:50.000,-6.510149999870292,-18.432312484356657,14.095422140775806,True +2025-03-11 12:42:50.500,2.9408219008036207,-8.942714247905151,-3.1884231693131335,True +2025-03-11 12:42:51.000,12.423271061774567,0.590475818271948,-20.511509582254877,True +2025-03-11 12:42:51.500,21.52723118434028,9.73267650934746,-37.12871899130767,True +2025-03-11 12:42:52.000,29.851253463113895,18.07828997921438,-52.316282243182776,True +2025-03-11 12:42:52.500,37.02264630475396,25.255749435793266,-65.39053350113728,True +2025-03-11 12:42:53.000,42.72002391775539,30.97796065985969,-75.76272893834013,True +2025-03-11 12:42:53.500,46.6981127205344,34.946982520203846,-82.99770775016563,True +2025-03-11 12:42:54.000,48.78147806664521,37.01023789148521,-86.80223826231723,True +2025-03-11 12:42:54.500,48.875425958171064,37.0732527588018,-86.91854774264723,True +2025-03-11 12:42:55.000,46.97037510627666,35.139516482892375,-83.3971695783592,True +2025-03-11 12:42:55.500,43.17516304307932,31.290565853026735,-76.4499375437191,True +2025-03-11 12:42:56.000,37.62305471408208,25.703177402005934,-66.2937263961596,True +2025-03-11 12:42:56.500,30.580438746909557,18.612936250939374,-53.39241580926425,True +2025-03-11 12:42:57.000,22.348075368377042,10.32938739719645,-38.30951318054571,True +2025-03-11 12:42:57.500,13.298659892352632,1.233849498822446,-21.751966255813223,True +2025-03-11 12:42:58.000,3.8278845672953974,-8.275774158846268,-4.44418408023223,True +2025-03-11 12:42:58.500,-5.6498312023608035,-17.789100738651047,12.832809286326423,True +2025-03-11 12:42:59.000,-14.709607119407082,-26.882860979270713,29.343324474949572,True +2025-03-11 12:42:59.500,-22.9481872673837,-35.15529364085161,44.39321434317563,True +2025-03-11 12:43:00.000,-30.01053052439329,-42.2381582889231,57.26938265783389,True +2025-03-11 12:43:00.500,-35.59114928442929,-47.811597016368935,67.41670161002003,True +2025-03-11 12:43:01.000,-39.43215330625873,-51.65357221485287,74.4098964716011,True +2025-03-11 12:43:01.500,-41.36650194977132,-53.57045099701456,77.89738815523653,True +2025-03-11 12:43:02.000,-41.310865923616966,-53.490929045314616,77.75414836027016,True +2025-03-11 12:43:02.500,-39.265258218597076,-51.407625560988606,73.98054537362955,True +2025-03-11 12:43:03.000,-35.324571814277036,-47.4212048053012,66.76104634504293,True +2025-03-11 12:43:03.500,-29.659222540864462,-41.709698727920795,56.381330394371076,True +2025-03-11 12:43:04.000,-22.525653270740804,-34.51200523212998,43.32734904379768,True +2025-03-11 12:43:04.500,-14.22618107952102,-26.162443552378964,28.14592308157865,True +2025-03-11 12:43:05.000,-5.130318083758372,-17.02304088259615,11.518264767061705,True +2025-03-11 12:43:05.500,4.352818885802742,-7.488649877970113,-5.823927577735958,True +2025-03-11 12:43:06.000,13.819481932969037,2.0089821990455583,-23.112697206674557,True +2025-03-11 12:43:06.500,22.8417306309007,11.05933774990789,-39.56979013189422,True +2025-03-11 12:43:07.000,31.00240174074392,19.26047993636131,-54.48080751826633,True +2025-03-11 12:43:07.500,37.977110198562606,26.239515052039646,-67.17696471386513,True +2025-03-11 12:43:08.000,43.43276616210334,31.6992324113747,-77.11983093728303,True +2025-03-11 12:43:08.500,47.14216698113799,35.390713804430774,-83.84940880527446,True +2025-03-11 12:43:09.000,48.92873476086683,37.16600363934371,-87.08095275122282,True +2025-03-11 12:43:09.500,48.725132855283306,36.9328217400935,-86.67063461733213,True +2025-03-11 12:43:10.000,46.536958295744896,34.70472566230447,-82.62361158260202,True +2025-03-11 12:43:10.500,42.455937870697845,30.586590012284624,-75.12872315500609,True +2025-03-11 12:43:11.000,36.664438742447345,24.75930025258151,-64.53526316436086,True +2025-03-11 12:43:11.500,29.417104548396242,17.464020747448284,-51.2775428663959,True +2025-03-11 12:43:12.000,21.048420286036013,9.035054310739131,-35.94869406242303,True +2025-03-11 12:43:12.500,11.91385274171011,-0.14852058804770515,-19.244164772505968,True +2025-03-11 12:43:13.000,2.4164889774335463,-9.691434866407041,-1.8865545773011507,True +2025-03-11 12:43:13.500,-7.0325304535131705,-19.16643225100522,15.344962488513067,True +2025-03-11 12:43:14.000,-16.000989145090703,-28.17462001210039,31.71329255476584,True +2025-03-11 12:43:14.500,-24.095813532567455,-36.288542404390846,46.490052861343,True +2025-03-11 12:43:15.000,-30.948488914719157,-43.1550742097948,58.98321883715124,True +2025-03-11 12:43:15.500,-36.279819440339296,-48.488793932725926,68.68500188290044,True +2025-03-11 12:43:16.000,-39.84285330798704,-52.04276409915597,75.15121031706565,True +2025-03-11 12:43:16.500,-41.48830366811891,-53.669416282564235,78.11296485762053,True +2025-03-11 12:43:17.000,-41.131137937396005,-53.27790782485626,77.43490562153526,True +2025-03-11 12:43:17.500,-38.79006808848988,-50.918279091482006,73.1274815103599,True +2025-03-11 12:43:18.000,-34.57703017953195,-46.66538446567049,65.39608012269169,True +2025-03-11 12:43:18.500,-28.68011767043351,-40.71777885016109,54.5889097745014,True +2025-03-11 12:43:19.000,-21.348755694860458,-33.333719787354234,41.17093207386536,True +2025-03-11 12:43:19.500,-12.901661419687173,-24.83330246112409,25.735973092341172,True +2025-03-11 12:43:20.000,-3.7254247300454764,-15.603259177382355,8.950536245563367,True +2025-03-11 12:43:20.500,5.784988816674641,-6.052688205576955,-8.417047702102051,True +2025-03-11 12:43:21.000,15.19949099194913,3.4025458412502214,-25.588906113885855,True +2025-03-11 12:43:21.500,24.11793725275696,12.356304572638376,-41.85472526925836,True +2025-03-11 12:43:22.000,32.13416509368126,20.390802041849707,-56.47254552854412,True +2025-03-11 12:43:22.500,38.89783949621458,27.15097699084294,-68.79039216232403,True +2025-03-11 12:43:23.000,44.09745121260359,32.3644788907961,-78.25322331632586,True +2025-03-11 12:43:23.500,47.52517112989401,35.770072836197556,-84.47467189441673,True +2025-03-11 12:43:24.000,49.02207746506404,37.251471116864266,-87.17788921224917,True +2025-03-11 12:43:24.500,48.5235268408543,36.71870514200771,-86.22480501249714,True +2025-03-11 12:43:25.000,46.04195436797667,34.2092981746639,-81.65677855721506,True +2025-03-11 12:43:25.500,41.68626644353755,29.81624857471659,-73.68627185386977,True +2025-03-11 12:43:26.000,35.66207004115004,23.749546119209988,-62.66537551211002,True +2025-03-11 12:43:26.500,28.238994077732443,16.26808953660182,-49.06702552355026,True +2025-03-11 12:43:27.000,19.718930719709416,7.705305716736632,-33.49230255096848,True +2025-03-11 12:43:27.500,10.494595506624677,-1.5548798121072362,-16.64710915946301,True +2025-03-11 12:43:28.000,0.9750987114635797,-11.117498961362651,0.7357704197525037,True +2025-03-11 12:43:28.500,-8.41787627631399,-20.560134738869994,17.851682055168105,True +2025-03-11 12:43:29.000,-17.275876971464683,-29.450154434494827,34.014064790708275,True +2025-03-11 12:43:29.500,-25.20016771146105,-37.39896072187647,48.49221062277213,True +2025-03-11 12:43:30.000,-31.855457914356045,-44.05892453007085,60.61303887971233,True +2025-03-11 12:43:30.500,-36.936197197231614,-49.14391899517369,69.85953497475153,True +2025-03-11 12:43:31.000,-40.21043796660754,-52.41606805197634,75.8307049921076,True +2025-03-11 12:43:31.500,-41.55889592435423,-53.740750086308964,78.24716587839002,True +2025-03-11 12:43:32.000,-40.9004955850978,-53.05713205566987,77.01924662127598,True +2025-03-11 12:43:32.500,-38.282992266456695,-50.39953512737017,72.18340489179914,True +2025-03-11 12:43:33.000,-33.79864354483055,-45.87564742743948,63.976297157451725,True +2025-03-11 12:43:33.500,-27.66236777933817,-39.693106383296154,52.73610326095124,True +2025-03-11 12:43:34.000,-20.140037828899104,-32.118210935708035,38.95735618774326,True +2025-03-11 12:43:34.500,-11.558146859124756,-23.491411896306378,23.275150549724156,True +2025-03-11 12:43:35.000,-2.31117676044666,-14.18981278084569,6.359625305218719,True +2025-03-11 12:43:35.500,7.21048948610853,-4.629815116911079,-11.006312124970988,True +2025-03-11 12:43:36.000,16.58358060235758,4.7719858033625275,-28.087814886730193,True +2025-03-11 12:43:36.500,25.38470815661394,13.608668580179911,-44.15115790783409,True +2025-03-11 12:43:37.000,33.23212361947943,21.47816631152485,-58.47539218839141,True +2025-03-11 12:43:37.500,39.780227294414274,28.03757142607367,-70.4115810232125,True +2025-03-11 12:43:38.000,44.729930821046835,32.98970976928442,-79.42625917284087,True +2025-03-11 12:43:38.500,47.87586009097136,36.12597226157488,-85.1376953192955,True +2025-03-11 12:43:39.000,49.07463123041269,37.2999383491329,-87.29166805164215,True +2025-03-11 12:43:39.500,48.282039514534986,36.47036183155032,-85.78666382177715,True +2025-03-11 12:43:40.000,45.509919583257116,33.66859789971377,-80.72115692000565,True +2025-03-11 12:43:40.500,40.90750810908038,29.009675320046725,-72.28509850273481,True +2025-03-11 12:43:41.000,34.65456346072994,22.70900415669469,-60.82562605043662,True +2025-03-11 12:43:41.500,27.03671747938943,15.039976713623155,-46.892100892608994,True +2025-03-11 12:43:42.000,18.395407388327428,6.345904308910269,-31.100914630646663,True +2025-03-11 12:43:42.500,9.099221366724812,-2.9855899239368107,-14.114322074383846,True +2025-03-11 12:43:43.000,-0.4293731583500951,-12.559563426124912,3.290200776377021,True +2025-03-11 12:43:43.500,-9.767689547685627,-21.936480263296325,20.355322608614642,True +2025-03-11 12:43:44.000,-18.519017420098336,-30.69803264877226,36.30722587116333,True +2025-03-11 12:43:44.500,-26.27522922443226,-38.48173020975407,50.452864405107114,True +2025-03-11 12:43:45.000,-32.713243015839616,-44.92463776848176,62.1791840800156,True diff --git a/imap_processing/tests/spice/test_data/fake_spin_data.csv b/imap_processing/tests/spice/test_data/fake_spin_data.csv index 1c5c8dae9b..9a25eb9199 100644 --- a/imap_processing/tests/spice/test_data/fake_spin_data.csv +++ b/imap_processing/tests/spice/test_data/fake_spin_data.csv @@ -13,7 +13,9 @@ spin_number,spin_start_sec_sclk,spin_start_subsec_sclk,spin_start_utc,spin_perio 7,105,0,2024-04-11 00:01:45.000000,15.0,0,1,0,0 # invalid spin phase 8,120,0,2024-04-11 00:02:00.000000,15.0,1,0,0,0 -# 1 good spin -9,135,0,2024-04-11 00:02:15.000000,15.0,1,1,0,0 +# 1 good spin with slightly shorter period estimate +9,135,0,2024-04-11 00:02:15.000000,14.5,1,1,0,0 +# Spin that starts 0.5s after estimated end of spin 9 (tests gap handling) +10,150,0,2024-04-11 00:02:30.000000,15.0,1,1,0,0 # Thruster firing on -10,150,0,2024-04-11 00:02:30.000000,15.0,1,1,0,1 \ No newline at end of file +11,165,0,2024-04-11 00:02:45.000000,15.0,1,1,0,1 \ No newline at end of file diff --git a/imap_processing/tests/spice/test_data/imap_001.tf b/imap_processing/tests/spice/test_data/imap_001.tf new file mode 100644 index 0000000000..d615115bda --- /dev/null +++ b/imap_processing/tests/spice/test_data/imap_001.tf @@ -0,0 +1,3105 @@ +KPL/FK + +Interstellar Mapping and Acceleration Probe Frames Kernel +======================================================================== + + This frames kernel contains the current set of coordinate frame + definitions for the Interstellar Mapping and Acceleration Probe + (IMAP) spacecraft, structures, and science instruments. + + This kernel also contains NAIF ID/name mapping for the IMAP + instruments. + + +Version and Date +======================================================================== + + The TEXT_KERNEL_ID stores version information of loaded project text + kernels. Each entry associated with the keyword is a string that + consists of four parts: the kernel name, version, entry date, and + type. For example, the frames kernel might have an entry as follows: + + + TEXT_KERNEL_ID += 'IMAP_FRAMES V1.0.0 2024-XXXX-NN FK' + | | | | + | | | | + KERNEL NAME <-------+ | | | + | | V + VERSION <------+ | KERNEL TYPE + | + V + ENTRY DATE + + + Interstellar Mapping and Acceleration Probe Frames Kernel Version: + + \begindata + + TEXT_KERNEL_ID += 'IMAP_FRAMES V1.0.0 2024-XXXX-NN FK' + + \begintext + + Version 1.0.0 -- XXXX NN, 2024 -- Douglas Rodgers + Lillian Nguyen + Nicholas Dutton + + Initial complete release. Frame/Body codes for thrusters redefined + + Version 0.0.1 -- July 9, 2021 -- Ian Wick Murphy + + Modifying dart_008.tf to add basic IMAP frame components. This + includes IMAP, IMAP_THRUSTER, and CK/SCLK IDs. Also adding a place + holder for the IMAP-Lo instrument with the ID -43001 and IMAP_LO + name. Future work includes adding more detailed instrument frames, + and reaching out to mechanical for an "official" IMAP_SPACECRAFT + frame definition. + + +References +======================================================================== + + 1. "Frames Required Reading" + + 2. "Kernel Pool Required Reading" + + 3. "C-Kernel Required Reading" + + 4. "7516-9067: IMAP Mechanical Interface Control Document", + Johns Hopkins Applied Physics Laboratory + + 5. "7516-9050: IMAP Coordinate Frame & Technical Definitions Doc.", + Johns Hopkins Applied Physics Laboratory + + 6. "7516-0011: IMAP Mechanical Interface Control Drawing", + [EXPORT CONTROLLED], Johns Hopkins Applied Physics Laboratory + + 7. "7523-0008: IMAP ULTRA Mechanical Interface Control Drawing", + [EXPORT CONTROLLED], Johns Hopkins Applied Physics Laboratory + + 8. "058991000: IMAP SWAPI Mechanical Interface Control Drawing", + Princeton University Space Physics + + 9. "GLOWS-CBK-DWG-2020-08-25-019-v4.4: IMAP GLOWS Mechanical + Interface Control Drawing", Centrum Badag Kosmicznych, Polska + Akademia Nauks + + 10. Responses from IMAP instrument teams on their base frame axis + definitions, received in email. + + 11. "Euler angles", Wikimedia Foundation, 2024-04-22, + https://en.wikipedia.org/wiki/Euler_angles + + 12. "7516-9059: IMAP-Lo to Spacecraft Interface Control Document", + [EXPORT CONTROLLED], Johns Hopkins Applied Physics Laboratory + + 13. "DRAFT Rev H: IMAP-Lo Mechanical Interface Control Drawing", + [EXPORT CONTROLLED], Univ. of New Hampshire Space Science Center + + 14. McComas et al, "IMAP: A New NASA Mission", + Space Sci Rev (2018) 214:116 + + 15. "IMAP-HI SENSOR HEAD Mechanical Interface Control Drawing", + [EXPORT CONTROLLED], Los Alamos National Laboratory + + 16. "IMAP-MAG-SENSOR Drawing Rev 6", Imperial College London + + +Contact Information +======================================================================== + + Douglas Rodgers, JHU/APL, Douglas.Rodgers@jhuapl.edu + + Lillian Nguyen, JHU/APL, Lillian.Nguyen@jhuapl.edu + + Nicholas Dutton, JHU/APL, Nicholas.Dutton@jhuapl.edu + + Ian Wick Murphy, JHU/APL, Ian.Murphy@jhuapl.edu + + +Implementation Notes +======================================================================== + + This file is used by the SPICE system as follows: programs that make + use of this frame kernel must `load' the kernel, normally during + program initialization. Loading the kernel associates the data items + with their names in a data structure called the `kernel pool'. The + SPICELIB routine FURNSH loads a kernel into the pool as shown below: + + FORTRAN: (SPICELIB) + + CALL FURNSH ( frame_kernel_name ) + + C: (CSPICE) + + furnsh_c ( frame_kernel_name ); + + IDL: (ICY) + + cspice_furnsh, frame_kernel_name + + MATLAB: (MICE) + + cspice_furnsh ( frame_kernel_name ) + + This file was created and may be updated with a text editor or word + processor. + + +Viewing ASCII Artwork +======================================================================== + + Artwork must be viewed in a text editor with monospaced font and + compact single-spaced lines. The following give the proper aspect + ratio: + + Andale Regular + Menlo Regular + Courier New Regular + PT Mono Regular + + The common monospaced font (at the time of writing) Monaco Regular + gives an aspect ratio that is too tall. Other fonts undoubtedly + will render the diagrams properly or improperly. + + As a guide, the following axis will be square when measured from the + bottom of the lower-most vertical line to the end of each axis. + + | + | + | + |_______ + + +IMAP NAIF ID Codes -- Definitions +======================================================================== + + This section contains name to NAIF ID mappings for the IMAP mission. + Once the contents of this file are loaded into the KERNEL POOL, these + mappings become available within SPICE, making it possible to use + names instead of ID code in high level SPICE routine calls. + + \begindata + + NAIF_BODY_NAME += ( 'IMAP' ) + NAIF_BODY_CODE += ( -43 ) + + NAIF_BODY_NAME += ( 'IMAP_SPACECRAFT' ) + NAIF_BODY_CODE += ( -43000 ) + + NAIF_BODY_NAME += ( 'IMAP_THRUSTER_A1' ) + NAIF_BODY_CODE += ( -43010 ) + + NAIF_BODY_NAME += ( 'IMAP_THRUSTER_A2' ) + NAIF_BODY_CODE += ( -43011 ) + + NAIF_BODY_NAME += ( 'IMAP_THRUSTER_A3' ) + NAIF_BODY_CODE += ( -43012 ) + + NAIF_BODY_NAME += ( 'IMAP_THRUSTER_A4' ) + NAIF_BODY_CODE += ( -43013 ) + + NAIF_BODY_NAME += ( 'IMAP_THRUSTER_R1' ) + NAIF_BODY_CODE += ( -43020 ) + + NAIF_BODY_NAME += ( 'IMAP_THRUSTER_R2' ) + NAIF_BODY_CODE += ( -43021 ) + + NAIF_BODY_NAME += ( 'IMAP_THRUSTER_R3' ) + NAIF_BODY_CODE += ( -43022 ) + + NAIF_BODY_NAME += ( 'IMAP_THRUSTER_R4' ) + NAIF_BODY_CODE += ( -43023 ) + + NAIF_BODY_NAME += ( 'IMAP_THRUSTER_R5' ) + NAIF_BODY_CODE += ( -43024 ) + + NAIF_BODY_NAME += ( 'IMAP_THRUSTER_R6' ) + NAIF_BODY_CODE += ( -43025 ) + + NAIF_BODY_NAME += ( 'IMAP_THRUSTER_R7' ) + NAIF_BODY_CODE += ( -43026 ) + + NAIF_BODY_NAME += ( 'IMAP_THRUSTER_R8' ) + NAIF_BODY_CODE += ( -43027 ) + + NAIF_BODY_NAME += ( 'IMAP_SUN_SENSOR_PZ' ) + NAIF_BODY_CODE += ( -43030 ) + + NAIF_BODY_NAME += ( 'IMAP_SUN_SENSOR_MZ' ) + NAIF_BODY_CODE += ( -43031 ) + + NAIF_BODY_NAME += ( 'IMAP_STAR_TRACKER_PX' ) + NAIF_BODY_CODE += ( -43040 ) + + NAIF_BODY_NAME += ( 'IMAP_STAR_TRACKER_MX' ) + NAIF_BODY_CODE += ( -43041 ) + + NAIF_BODY_NAME += ( 'IMAP_LOW_GAIN_ANTENNA' ) + NAIF_BODY_CODE += ( -43050 ) + + NAIF_BODY_NAME += ( 'IMAP_MED_GAIN_ANTENNA' ) + NAIF_BODY_CODE += ( -43051 ) + + NAIF_BODY_NAME += ( 'IMAP_LO_BASE' ) + NAIF_BODY_CODE += ( -43100 ) + + NAIF_BODY_NAME += ( 'IMAP_LO' ) + NAIF_BODY_CODE += ( -43101 ) + + NAIF_BODY_NAME += ( 'IMAP_LO_STAR_SENSOR' ) + NAIF_BODY_CODE += ( -43102 ) + + NAIF_BODY_NAME += ( 'IMAP_HI_45' ) + NAIF_BODY_CODE += ( -43150 ) + + NAIF_BODY_NAME += ( 'IMAP_HI_90' ) + NAIF_BODY_CODE += ( -43175 ) + + NAIF_BODY_NAME += ( 'IMAP_ULTRA_45' ) + NAIF_BODY_CODE += ( -43200 ) + + NAIF_BODY_NAME += ( 'IMAP_ULTRA_90' ) + NAIF_BODY_CODE += ( -43225 ) + + NAIF_BODY_NAME += ( 'IMAP_MAG_BOOM' ) + NAIF_BODY_CODE += ( -43250 ) + + NAIF_BODY_NAME += ( 'IMAP_MAG_I' ) + NAIF_BODY_CODE += ( -43251 ) + + NAIF_BODY_NAME += ( 'IMAP_MAG_O' ) + NAIF_BODY_CODE += ( -43251 ) + + NAIF_BODY_NAME += ( 'IMAP_SWE' ) + NAIF_BODY_CODE += ( -43300 ) + + NAIF_BODY_NAME += ( 'IMAP_SWE_DETECTOR_P63' ) + NAIF_BODY_CODE += ( -43301 ) + + NAIF_BODY_NAME += ( 'IMAP_SWE_DETECTOR_P42' ) + NAIF_BODY_CODE += ( -43302 ) + + NAIF_BODY_NAME += ( 'IMAP_SWE_DETECTOR_P21' ) + NAIF_BODY_CODE += ( -43303 ) + + NAIF_BODY_NAME += ( 'IMAP_SWE_DETECTOR_000' ) + NAIF_BODY_CODE += ( -43304 ) + + NAIF_BODY_NAME += ( 'IMAP_SWE_DETECTOR_M21' ) + NAIF_BODY_CODE += ( -43305 ) + + NAIF_BODY_NAME += ( 'IMAP_SWE_DETECTOR_M42' ) + NAIF_BODY_CODE += ( -43306 ) + + NAIF_BODY_NAME += ( 'IMAP_SWE_DETECTOR_M63' ) + NAIF_BODY_CODE += ( -43307 ) + + NAIF_BODY_NAME += ( 'IMAP_SWAPI' ) + NAIF_BODY_CODE += ( -433510 ) + + NAIF_BODY_NAME += ( 'IMAP_SWAPI_APERTURE_L' ) + NAIF_BODY_CODE += ( -43351 ) + + NAIF_BODY_NAME += ( 'IMAP_SWAPI_APERTURE_R' ) + NAIF_BODY_CODE += ( -43352 ) + + NAIF_BODY_NAME += ( 'IMAP_SWAPI_SUNGLASSES' ) + NAIF_BODY_CODE += ( -43353 ) + + NAIF_BODY_NAME += ( 'IMAP_CODICE' ) + NAIF_BODY_CODE += ( -43400 ) + + NAIF_BODY_NAME += ( 'IMAP_CODICE_LO_APERTURE_01' ) + NAIF_BODY_CODE += ( -43401 ) + + NAIF_BODY_NAME += ( 'IMAP_CODICE_LO_APERTURE_02' ) + NAIF_BODY_CODE += ( -43402 ) + + NAIF_BODY_NAME += ( 'IMAP_CODICE_LO_APERTURE_03' ) + NAIF_BODY_CODE += ( -43403 ) + + NAIF_BODY_NAME += ( 'IMAP_CODICE_LO_APERTURE_04' ) + NAIF_BODY_CODE += ( -43404 ) + + NAIF_BODY_NAME += ( 'IMAP_CODICE_LO_APERTURE_05' ) + NAIF_BODY_CODE += ( -43405 ) + + NAIF_BODY_NAME += ( 'IMAP_CODICE_LO_APERTURE_06' ) + NAIF_BODY_CODE += ( -43406 ) + + NAIF_BODY_NAME += ( 'IMAP_CODICE_LO_APERTURE_07' ) + NAIF_BODY_CODE += ( -43407 ) + + NAIF_BODY_NAME += ( 'IMAP_CODICE_LO_APERTURE_08' ) + NAIF_BODY_CODE += ( -43408 ) + + NAIF_BODY_NAME += ( 'IMAP_CODICE_LO_APERTURE_09' ) + NAIF_BODY_CODE += ( -43409 ) + + NAIF_BODY_NAME += ( 'IMAP_CODICE_LO_APERTURE_10' ) + NAIF_BODY_CODE += ( -43410 ) + + NAIF_BODY_NAME += ( 'IMAP_CODICE_LO_APERTURE_11' ) + NAIF_BODY_CODE += ( -43411 ) + + NAIF_BODY_NAME += ( 'IMAP_CODICE_LO_APERTURE_12' ) + NAIF_BODY_CODE += ( -43412 ) + + NAIF_BODY_NAME += ( 'IMAP_CODICE_LO_APERTURE_13' ) + NAIF_BODY_CODE += ( -43413 ) + + NAIF_BODY_NAME += ( 'IMAP_CODICE_LO_APERTURE_14' ) + NAIF_BODY_CODE += ( -43414 ) + + NAIF_BODY_NAME += ( 'IMAP_CODICE_LO_APERTURE_15' ) + NAIF_BODY_CODE += ( -43415 ) + + NAIF_BODY_NAME += ( 'IMAP_CODICE_LO_APERTURE_16' ) + NAIF_BODY_CODE += ( -43416 ) + + NAIF_BODY_NAME += ( 'IMAP_CODICE_LO_APERTURE_17' ) + NAIF_BODY_CODE += ( -43417 ) + + NAIF_BODY_NAME += ( 'IMAP_CODICE_LO_APERTURE_18' ) + NAIF_BODY_CODE += ( -43418 ) + + NAIF_BODY_NAME += ( 'IMAP_CODICE_LO_APERTURE_19' ) + NAIF_BODY_CODE += ( -43419 ) + + NAIF_BODY_NAME += ( 'IMAP_CODICE_LO_APERTURE_20' ) + NAIF_BODY_CODE += ( -43420 ) + + NAIF_BODY_NAME += ( 'IMAP_CODICE_LO_APERTURE_21' ) + NAIF_BODY_CODE += ( -43421 ) + + NAIF_BODY_NAME += ( 'IMAP_CODICE_LO_APERTURE_22' ) + NAIF_BODY_CODE += ( -43422 ) + + NAIF_BODY_NAME += ( 'IMAP_CODICE_LO_APERTURE_23' ) + NAIF_BODY_CODE += ( -43423 ) + + NAIF_BODY_NAME += ( 'IMAP_CODICE_LO_APERTURE_24' ) + NAIF_BODY_CODE += ( -43424 ) + + NAIF_BODY_NAME += ( 'IMAP_CODICE_HI_APERTURE_01' ) + NAIF_BODY_CODE += ( -43425 ) + + NAIF_BODY_NAME += ( 'IMAP_CODICE_HI_APERTURE_02' ) + NAIF_BODY_CODE += ( -43426 ) + + NAIF_BODY_NAME += ( 'IMAP_CODICE_HI_APERTURE_03' ) + NAIF_BODY_CODE += ( -43427 ) + + NAIF_BODY_NAME += ( 'IMAP_CODICE_HI_APERTURE_04' ) + NAIF_BODY_CODE += ( -43428 ) + + NAIF_BODY_NAME += ( 'IMAP_CODICE_HI_APERTURE_05' ) + NAIF_BODY_CODE += ( -43429 ) + + NAIF_BODY_NAME += ( 'IMAP_CODICE_HI_APERTURE_06' ) + NAIF_BODY_CODE += ( -43430 ) + + NAIF_BODY_NAME += ( 'IMAP_CODICE_HI_APERTURE_07' ) + NAIF_BODY_CODE += ( -43431 ) + + NAIF_BODY_NAME += ( 'IMAP_CODICE_HI_APERTURE_08' ) + NAIF_BODY_CODE += ( -43432 ) + + NAIF_BODY_NAME += ( 'IMAP_CODICE_HI_APERTURE_09' ) + NAIF_BODY_CODE += ( -43433 ) + + NAIF_BODY_NAME += ( 'IMAP_CODICE_HI_APERTURE_10' ) + NAIF_BODY_CODE += ( -43434 ) + + NAIF_BODY_NAME += ( 'IMAP_CODICE_HI_APERTURE_11' ) + NAIF_BODY_CODE += ( -43435 ) + + NAIF_BODY_NAME += ( 'IMAP_CODICE_HI_APERTURE_12' ) + NAIF_BODY_CODE += ( -43436 ) + + NAIF_BODY_NAME += ( 'IMAP_HIT' ) + NAIF_BODY_CODE += ( -43500 ) + + NAIF_BODY_NAME += ( 'IMAP_HIT_L1_APERTURE_01' ) + NAIF_BODY_CODE += ( -43501 ) + + NAIF_BODY_NAME += ( 'IMAP_HIT_L1_APERTURE_02' ) + NAIF_BODY_CODE += ( -43502 ) + + NAIF_BODY_NAME += ( 'IMAP_HIT_L1_APERTURE_03' ) + NAIF_BODY_CODE += ( -43503 ) + + NAIF_BODY_NAME += ( 'IMAP_HIT_L1_APERTURE_04' ) + NAIF_BODY_CODE += ( -43504 ) + + NAIF_BODY_NAME += ( 'IMAP_HIT_L1_APERTURE_05' ) + NAIF_BODY_CODE += ( -43505 ) + + NAIF_BODY_NAME += ( 'IMAP_HIT_L1_APERTURE_06' ) + NAIF_BODY_CODE += ( -43506 ) + + NAIF_BODY_NAME += ( 'IMAP_HIT_L1_APERTURE_07' ) + NAIF_BODY_CODE += ( -43507 ) + + NAIF_BODY_NAME += ( 'IMAP_HIT_L1_APERTURE_08' ) + NAIF_BODY_CODE += ( -43508 ) + + NAIF_BODY_NAME += ( 'IMAP_HIT_L1_APERTURE_09' ) + NAIF_BODY_CODE += ( -43509 ) + + NAIF_BODY_NAME += ( 'IMAP_HIT_L1_APERTURE_10' ) + NAIF_BODY_CODE += ( -43510 ) + + NAIF_BODY_NAME += ( 'IMAP_IDEX' ) + NAIF_BODY_CODE += ( -43700 ) + + NAIF_BODY_NAME += ( 'IMAP_IDEX_DETECTOR' ) + NAIF_BODY_CODE += ( -43701 ) + + NAIF_BODY_NAME += ( 'IMAP_IDEX_FULL_SCIENCE' ) + NAIF_BODY_CODE += ( -43702 ) + + + NAIF_BODY_NAME += ( 'IMAP_GLOWS' ) + NAIF_BODY_CODE += ( -43751 ) + + \begintext + +Removed by Tim Plummer due to missing frame definition + NAIF_BODY_NAME += ( 'IMAP_GLOWS_BASE' ) + NAIF_BODY_CODE += ( -43750 ) + +IMAP NAIF ID Codes -- Definitions +======================================================================== + + The ID codes -43900 to -43999 have been reserved for the IMAP dynamic + frames kernel and are not utilized in this file. + + The following frames are defined in this kernel file: + + Frame Name Relative To Type NAIF ID + ========================== =============== ======= ======= + + Spacecraft (000-099) + -------------------------- + IMAP_SPACECRAFT J2000 CK -43000 + IMAP_THRUSTER_A1 IMAP_SPACECRAFT FIXED -43010 + IMAP_THRUSTER_A2 IMAP_SPACECRAFT FIXED -43011 + IMAP_THRUSTER_A3 IMAP_SPACECRAFT FIXED -43012 + IMAP_THRUSTER_A4 IMAP_SPACECRAFT FIXED -43013 + IMAP_THRUSTER_R1 IMAP_SPACECRAFT FIXED -43020 + IMAP_THRUSTER_R2 IMAP_SPACECRAFT FIXED -43021 + IMAP_THRUSTER_R3 IMAP_SPACECRAFT FIXED -43022 + IMAP_THRUSTER_R4 IMAP_SPACECRAFT FIXED -43023 + IMAP_THRUSTER_R5 IMAP_SPACECRAFT FIXED -43024 + IMAP_THRUSTER_R6 IMAP_SPACECRAFT FIXED -43025 + IMAP_THRUSTER_R7 IMAP_SPACECRAFT FIXED -43026 + IMAP_THRUSTER_R8 IMAP_SPACECRAFT FIXED -43027 + IMAP_SUN_SENSOR_PZ IMAP_SPACECRAFT FIXED -43030 + IMAP_SUN_SENSOR_MZ IMAP_SPACECRAFT FIXED -43031 + IMAP_STAR_TRACKER_PX IMAP_SPACECRAFT FIXED -43040 + IMAP_STAR_TRACKER_MX IMAP_SPACECRAFT FIXED -43041 + IMAP_LOW_GAIN_ANTENNA IMAP_SPACECRAFT FIXED -43050 + IMAP_MED_GAIN_ANTENNA IMAP_SPACECRAFT FIXED -43051 + + IMAP-Lo (100-149) + -------------------------- + IMAP_LO_BASE IMAP_SPACECRAFT FIXED -43100 + IMAP_LO IMAP_LO_BASE CK -43101 + IMAP_LO_STAR_SENSOR IMAP_LO FIXED -43102 + + IMAP-Hi (150-199) + -------------------------- + IMAP_HI_45 IMAP_SPACECRAFT FIXED -43150 + IMAP_HI_90 IMAP_SPACECRAFT FIXED -43151 + + IMAP-Ultra (200-249) + -------------------------- + IMAP_ULTRA_45 IMAP_SPACECRAFT FIXED -43200 + IMAP_ULTRA_90 IMAP_SPACECRAFT FIXED -43201 + + MAG (250-299) + -------------------------- + IMAP_MAG_BOOM IMAP_SPACECRAFT FIXED -43250 + IMAP_MAG_I IMAP_MAG_BOOM FIXED -43251 + IMAP_MAG_O IMAP_MAG_BOOM FIXED -43252 + + SWE (300-349) + -------------------------- + IMAP_SWE IMAP_SPACECRAFT FIXED -43300 + IMAP_SWE_DETECTOR_P63 IMAP_SWE FIXED -43301 + IMAP_SWE_DETECTOR_P42 IMAP_SWE FIXED -43302 + IMAP_SWE_DETECTOR_P21 IMAP_SWE FIXED -43303 + IMAP_SWE_DETECTOR_000 IMAP_SWE FIXED -43304 + IMAP_SWE_DETECTOR_M21 IMAP_SWE FIXED -43305 + IMAP_SWE_DETECTOR_M42 IMAP_SWE FIXED -43306 + IMAP_SWE_DETECTOR_M63 IMAP_SWE FIXED -43307 + + SWAPI (350-399) + -------------------------- + IMAP_SWAPI IMAP_SPACECRAFT FIXED -43350 + IMAP_SWAPI_APERTURE_L IMAP_SWAPI FIXED -43351 + IMAP_SWAPI_APERTURE_R IMAP_SWAPI FIXED -43352 + IMAP_SWAPI_SUNGLASSES IMAP_SWAPI FIXED -43353 + + CODICE (400-499) + -------------------------- + IMAP_CODICE IMAP_SPACECRAFT FIXED -43400 + IMAP_CODICE_LO_APERTURE_01 IMAP_CODICE FIXED -43401 + IMAP_CODICE_LO_APERTURE_02 IMAP_CODICE FIXED -43402 + IMAP_CODICE_LO_APERTURE_03 IMAP_CODICE FIXED -43403 + IMAP_CODICE_LO_APERTURE_04 IMAP_CODICE FIXED -43404 + IMAP_CODICE_LO_APERTURE_05 IMAP_CODICE FIXED -43405 + IMAP_CODICE_LO_APERTURE_06 IMAP_CODICE FIXED -43406 + IMAP_CODICE_LO_APERTURE_07 IMAP_CODICE FIXED -43407 + IMAP_CODICE_LO_APERTURE_08 IMAP_CODICE FIXED -43408 + IMAP_CODICE_LO_APERTURE_09 IMAP_CODICE FIXED -43409 + IMAP_CODICE_LO_APERTURE_10 IMAP_CODICE FIXED -43410 + IMAP_CODICE_LO_APERTURE_11 IMAP_CODICE FIXED -43411 + IMAP_CODICE_LO_APERTURE_12 IMAP_CODICE FIXED -43412 + IMAP_CODICE_LO_APERTURE_13 IMAP_CODICE FIXED -43413 + IMAP_CODICE_LO_APERTURE_14 IMAP_CODICE FIXED -43414 + IMAP_CODICE_LO_APERTURE_15 IMAP_CODICE FIXED -43415 + IMAP_CODICE_LO_APERTURE_16 IMAP_CODICE FIXED -43416 + IMAP_CODICE_LO_APERTURE_17 IMAP_CODICE FIXED -43417 + IMAP_CODICE_LO_APERTURE_18 IMAP_CODICE FIXED -43418 + IMAP_CODICE_LO_APERTURE_19 IMAP_CODICE FIXED -43419 + IMAP_CODICE_LO_APERTURE_20 IMAP_CODICE FIXED -43420 + IMAP_CODICE_LO_APERTURE_21 IMAP_CODICE FIXED -43421 + IMAP_CODICE_LO_APERTURE_22 IMAP_CODICE FIXED -43422 + IMAP_CODICE_LO_APERTURE_23 IMAP_CODICE FIXED -43423 + IMAP_CODICE_LO_APERTURE_24 IMAP_CODICE FIXED -43424 + IMAP_CODICE_HI_APERTURE_01 IMAP_CODICE FIXED -43425 + IMAP_CODICE_HI_APERTURE_02 IMAP_CODICE FIXED -43426 + IMAP_CODICE_HI_APERTURE_03 IMAP_CODICE FIXED -43427 + IMAP_CODICE_HI_APERTURE_04 IMAP_CODICE FIXED -43428 + IMAP_CODICE_HI_APERTURE_05 IMAP_CODICE FIXED -43429 + IMAP_CODICE_HI_APERTURE_06 IMAP_CODICE FIXED -43430 + IMAP_CODICE_HI_APERTURE_07 IMAP_CODICE FIXED -43431 + IMAP_CODICE_HI_APERTURE_08 IMAP_CODICE FIXED -43432 + IMAP_CODICE_HI_APERTURE_09 IMAP_CODICE FIXED -43433 + IMAP_CODICE_HI_APERTURE_10 IMAP_CODICE FIXED -43434 + IMAP_CODICE_HI_APERTURE_11 IMAP_CODICE FIXED -43435 + IMAP_CODICE_HI_APERTURE_12 IMAP_CODICE FIXED -43436 + + HIT (500-699) + -------------------------- + IMAP_HIT IMAP_SPACECRAFT FIXED -43500 + IMAP_HIT_L1_APERTURE_01 IMAP_HIT FIXED -43501 + IMAP_HIT_L1_APERTURE_02 IMAP_HIT FIXED -43502 + IMAP_HIT_L1_APERTURE_03 IMAP_HIT FIXED -43503 + IMAP_HIT_L1_APERTURE_04 IMAP_HIT FIXED -43504 + IMAP_HIT_L1_APERTURE_05 IMAP_HIT FIXED -43505 + IMAP_HIT_L1_APERTURE_06 IMAP_HIT FIXED -43506 + IMAP_HIT_L1_APERTURE_07 IMAP_HIT FIXED -43507 + IMAP_HIT_L1_APERTURE_08 IMAP_HIT FIXED -43508 + IMAP_HIT_L1_APERTURE_09 IMAP_HIT FIXED -43509 + IMAP_HIT_L1_APERTURE_10 IMAP_HIT FIXED -43510 + + IDEX (700-749) + -------------------------- + IMAP_IDEX IMAP_SPACECRAFT FIXED -43700 + IMAP_IDEX_DETECTOR IMAP_IDEX FIXED -43701 + IMAP_IDEX_FULL_SCIENCE IMAP_IDEX FIXED -43702 + + GLOWS (750-799) + -------------------------- + IMAP_GLOWS_BASE IMAP_SPACECRAFT FIXED -43750 + IMAP_GLOWS IMAP_GLOWS_BASE FIXED -43751 + + +IMAP Frame Tree +======================================================================== + + The diagram below illustrates the IMAP frame hierarchy: + + J2000 + | + |<---ck + | + IMAP_SPACECRAFT + | + IMAP_THRUSTER_A1 + | + |... + | + IMAP_THRUSTER_A4 + | + IMAP_THRUSTER_R1 + | + |... + | + IMAP_THRUSTER_R8 + | + IMAP_SUN_SENSOR_PZ + | + IMAP_SUN_SENSOR_MZ + | + IMAP_STAR_TRACKER_PX + | + IMAP_STAR_TRACKER_MX + | + IMAP_LOW_GAIN_ANTENNA + | + IMAP_MED_GAIN_ANTENNA + | + IMAP_LO_BASE + | | + | |<---ck + | | + | IMAP_LO + | | + | IMAP_LO_STAR_SENSOR + | + IMAP_HI_45 + | + IMAP_HI_90 + | + IMAP_ULTRA_45 + | + IMAP_ULTRA_90 + | + IMAP_MAG_BOOM + | | + | IMAP_MAP_I + | | + | IMAP_MAP_O + | + IMAP_SWE + | | + | IMAP_SWE_DETECTOR_P63 + | | + | IMAP_SWE_DETECTOR_P42 + | | + | IMAP_SWE_DETECTOR_P21 + | | + | IMAP_SWE_DETECTOR_000 + | | + | IMAP_SWE_DETECTOR_M21 + | | + | IMAP_SWE_DETECTOR_M42 + | | + | IMAP_SWE_DETECTOR_M63 + | + IMAP_SWAPI + | | + | IMAP_SWAPI_APERTURE_L + | | + | IMAP_SWAPI_APERTURE_R + | | + | IMAP_SWAPI_SUNGLASSES + | + IMAP_CODICE + | | + | IMAP_CODICE_LO_APERTURE_01 + | | + | |... + | | + | IMAP_CODICE_LO_APERTURE_24 + | | + | IMAP_CODICE_HI_APERTURE_01 + | | + | |... + | | + | IMAP_CODICE_HI_APERTURE_12 + | + IMAP_HIT + | | + | IMAP_HIT_L1_APERTURE_01 + | | + | |... + | | + | IMAP_HIT_L1_APERTURE_10 + | + IMAP_IDEX + | | + | IMAP_IDEX_DETECTOR + | | + | IMAP_IDEX_FULL_SCIENCE + | + IMAP_GLOWS_BASE + | + IMAP_GLOWS + +IMAP Spacecraft Frame +======================================================================== + + \begindata + + FRAME_IMAP_SPACECRAFT = -43000 + FRAME_-43000_NAME = 'IMAP_SPACECRAFT' + FRAME_-43000_CLASS = 3 + FRAME_-43000_CLASS_ID = -43000 + FRAME_-43000_CENTER = -43 + CK_-43000_SCLK = -43 + CK_-43000_SPK = -43 + + \begintext + + + The orientation of the spacecraft body frame with respect to an + inertial frame, J2000 for IMAP, is provided by a C-kernel (see [3] + for details). + + The spacecraft coordinate frames are defined by the IMAP control + documents (see [4,5], NB, figure 2.2). There are two frames described + there: Observatory Mechanical Design Reference Frame (most relevant) + and Observatory Pointing and Dynamics Reference Frame (less relevant + for this frame kernel). + + + Observatory Mechanical Design Reference Frame (IMAP_SPACECRAFT) + --------------------------------------------------------------------- + + If not explicitly stated, references to 'spacecraft mechanical frame' + 'spacecraft frame', or 'S/C frame' will refer to this frame. + + All instruments and component placements and orientations are defined + using this coordinate frame reference. + + Origin: Center of the launch vehicle adapter ring at the + observatory/launch vehicle interface plane + + +Z axis: Perpendicular to the launch vehicle interface plane pointed + in the direction of the top deck (runs through the center + of the central cylinder structure element) + + +Y axis: Direction of the vector orthogonal to the +Z axis and + parallel to the deployed MAG boom + + +X axis: The third orthogonal axis defined using an X, Y, Z ordered + right hand rule + + NB: The Observatory Pointing and Dynamics Reference Frame is also + defined in [5]. It is identical to the observatory mechanical design + reference frame, but with the origin translated to the observatory + center of mass (which changes with boom deployment and fuel usage). + The offset difference between the mechanical and dynamic frame is + within the uncertainty range of the ephemeris, so the mechanical + design frame is used here for definiteness. + + Three different views [5,6] of the spacecraft with labeled components + are presented below for illustrative purposes. + + + IMAP -Z Bottom View (Figure 3-2 in [5], G-G in [6] rotated 180Β°) + --------------------------------------------------------------------- + --------- + | +X axis | -------------------- + --------- | +Z axis facing Sun | + . | into page | + /|\ -------------------- + | + | + | + _ + HI 45 /`~~__HI 90 `+ direction of + , = .^ - /_ ``-. '. positive + .+ + `^~/ ./ ~ rotation + ^ + + . -- ' `` \ _-~ \ + _ / ',= ' \~'` \ IMAP \ + ULTRA /' '-_ .~ ' \,.=.. \ LO \|/ + 90 / ~ _,.,_ + + \ ' + / ,~' +' `'+ + + \ + / ~^ .' , = .'. '- ='' -`` --------- + ^/ / , = . + + \ \~'` | +Y axis |-----> + | . + + + + . \ --------- ___ + | | + + ' = ' | \--------------------| | + SWAPI| | ' = ', - . | /--------------------|___| + _+_: ' + + ' / MAG boom + \_ __\__ \ + + / /^*~, + + | SWE '. ' = ' .' ULTRA / + `~-' '~..,___,..~' 45 /~,* + _\ / /~,*` + * / CODICE ^*._/ *` HIT + *\ _/`. / + * / /~ _ _ ,.-^-., _ _ _ / + '=' + + + GLOWS + + + '-.,.-' + IDEX + + + IMAP +X Side View (F-F in [6]) + --------------------------------------------------------------------- + --------- + | +Z axis | + --------- --------------------- + . | +X axis out of page | + /|\ --------------------- + | LGA + __________________|______|^|_________ ___ + SWAPI|__________________|__________________|====================| | + #|-| | | .-==-, | / MAG boom '---' + #|-| {|## | | / \ | | + | {|## | |{ HI 90 }| IMAP LO| + | {|## | _.._ | \ / | _., | + | ULTRA | / \ | `-==-' | / __`',| + | 90 | \ HI 45/ | | \ \_\ ;| + | | '----` | | ~._ + | + '-------------------|----------/--------' + | | \_________O_________/ | | ----------------> + |__| ----------- /_\ --------- + STAR | S/C FRAME | MGA | +Y axis | + TRACKERS | ORIGIN | --------- + ----------- + + + IMAP -X Side View (C-C in [6]) + --------------------------------------------------------------------- + --------- + | +Z axis | + ------------------- --------- + | +X axis into page | . + ------------------- /|\ + LGA | + ___ _________|^|______|__________________ + | |====================|__________________|_____________ __ _|SWAPI + '---' MAG boom \ __ | | | // \ /--|# + |( )=|__|| | | \\__/ \--|# + | HIT | _|_ IDEX | CODICE | + | | ,.' | '., | | + | ____ | [ \ | / ] | SWE| + ULTRA ##',', |,.'|'.,| GLOWS (#)| + 45 ####'. + | + \\(O) |-|| + '----####/----- + | + --------------' + <---------------- | | \______'-.O.-'______/ | | + --------- /_\ ----------- |__| + | +Y axis | MGA | S/C FRAME | STAR + --------- | ORIGIN | TRACKERS + ----------- + + + IMAP Component Location - Azimuth and Elevation + --------------------------------------------------------------------- + + Payload and subsystem component locations are specified[5,6] in the + Observatory Mechanical Design Reference Frame (described above). + Locations are defined in azimuth and elevation (and resultant + direction cosign matrices) of these angles[6] in the same reference + frame. The azimuth and elevation angle diagram is provided below. + + In general, descriptions in this kernel treat the +Z direction as + "up" and the -Z direction as "down." Locations referred to as "above" + are generally closer to the Sun, and vice versa for "below." The + "upper" side of the spacecraft is the plane of the solar panels, + while the "lower" side may refer to the area near the adapter ring. + If ambiguity could arise, more thorough descriptions will be used. + + + Toward Sun + + +Z axis + . + | + . + | + . Component + | Location/ + . Orientation + | @ + Toward . .'| + MAG | +` | + .~ '` Boom S/C . .` \ | + .~ '` FRAME |.` : | + / ~'` ORIGIN O | | + *--- .~ '` \ Elevation + .~ '` \ | | + .~ '` \ ; |~ + .~ '\ \ / | ^~ + +Y axis \ \ + | ^~ + '. '~, \ | ^~ + '~ Azimuth \ | ^~ + '~. `^~-> \| -X axis + ' ~ ., _ _ ,.~ + ``'`` + + + IMAP Component Orientation - Azimuth and Elevation + --------------------------------------------------------------------- + + In addition to the rotation matrices, azimuth and elevation are used + to specify look direction (i.e., boresight) of the science payload + components and thrusters. However, these two angles are not adequate + to specify the complete orientation of the components--a secondary + axis must be specified to complete the rotation. + + The look direction, D, in the frame of the spacecraft for azimuth, az + and elevation, el, is: + + D = [ -cos(el) x sin(az), cos(el) x cos(az), sin(el) ] + + For all practical purposes, the look direction (primary axis) + corresponds to one of the six axis-aligned directions of the local + coordinate system of the instrument: X', Y', Z', -X', -Y', -Z'. While + the azimuth/elevation of the instrument look direction is provided in + the spacecraft MICD[4], the local coordinate axis in which it + corresponds is provided in the instrument's MICD. + + The secondary axis, S, must be perpendicular to D for the following + discussion. It will generally be specified in one of two ways: + + 1) S is one of the six axis-aligned directions of the + spacecraft coordinate system: X, Y, Z, -X, -Y, -Z + + 2) S lies in the plane perpendicular to one of the axes of the + spacecraft coordinate system: X, Y, Z, -X, -Y, -Z + + Similar to the look direction, this direction will then be assigned + to correspond to one of the six instrument directions X', Y', Z', + -X', -Y', -Z'. + + For definiteness, it is assumed that the third axes, N = D x S, + completes the righthanded coordinate system. + + The rotation matrix specifying the component frame, X'Y'Z', in the + spacecraft frame, XYZ, is: + + Ux Uy Uz + + [ X ] [ R11 R12 R13 ] [ X'] + [ ] [ ] [ ] + [ Y ] = [ R21 R22 R23 ] [ Y'] + [ ] [ ] [ ] + [ Z ] [ R31 R32 R33 ] [ Z'] + + with Ux, Uy, Uz specifying the unit column vectors of the rotation. + Because the primary and secondary axes, D and S, lie along the local + axes of the instrument coordinate system (X'Y'Z'), they are simply + the column vectors of the rotation matrix (assuming properly unit). + + + IMAP Component Orientation - Euler Angles + --------------------------------------------------------------------- + + When the orientation is not specified in azimuth/elevation, or the + secondary is not well-defined, we try to deduce the most straight- + forward definition using a simple secondary axis. Sometimes a + single axis-aligned rotation applied BEFORE the general rotation + allows a simple secondary axis to notionally be used to accurately + define the coordinates; see Hi 45 or Hi 90 for this case. + + It is also possible to deduce the Euler angles to produce more + precise rotation matrices. For most components, before final + alignments are calculated, these angles are in whole degrees. + (However, see Hi 45 for a counterexample). + + The spacecraft subsystems such as the star trackers have complete + rotation matrices that fully define the orientation of each + component. These matrices, while complete, are not conducive to + visualizing the orientation of a component on the spacecraft bus. + + As it happens, when applied to rotations, the azimuth and elevation + are nearly identitical to the first two Euler angles of the ZXZ + intrinsic rotation. For the Euler angles (A, B, Y), this is defined + as follows[11]. + + Let xyz represent the coordinate axes of the fixed frame, and XYZ + are the axes of the fully rotated frame expressed in the xyz frame. + Three successive, ordered rotations about the axes are performed: + + 1) Righthanded rotation about z by the angle A ∈ [-Ο€, Ο€); the rotated + frame is defined x'y'z', with z' = z. The new frame x'y'z' is + expressed in the coordinates of the original frame xyz. + + 2) Righthanded rotation about x' by the angle B ∈ [0,Ο€]; the rotated + frame is defined x"y"z", with x" = x'. The new frame x"y"z" is + expressed in the coordinates of the original frame xyz. + + 3) Righthanded rotation about z" by the angle Y ∈ [-Ο€,Ο€); the rotated + frame is defined XYZ, with Z = z". The final frame XYZ is + expressed in the coordinates of the original frame xyz. + + + Euler Angles + Intrinsic ZXZ Rotation + + z axis + . + | Y axis + _._. / + , B ` | / + Z axis ,-` . / + ^, ^ | / + ^, . / + ^, | / + ^, . / + ^, | / _ X axis + ^, . / _ ~ ^ + ^, |/ _ ~ ^ ^ + .~ ~ ^ | + .~ '` \ ^~ ; + .~ '` \ \ ^~ ; + .~ '` ', \ ^~ , + .~ '` ` A \ ^ Y + x axis `^~-> \ , ~ + \ ~` ^~ + \- ^ ^~ + \ y axis + \ + x'=x" axis + + + Comparing the two figures, we see that A = azimuth and B appears to + coincide with elevation. However, while B lies on the range [0,Ο€], + conventionally, elevation ∈ [-Ο€/2,Ο€/2]. This range for elevation does + not capture all possible orientations, e.g., a playing card facing + upward cannot be placed facing downward with elevation ∈ [-Ο€/2,Ο€/2]. + + So, we need to supplement the azimuth and elevation nomenclature with + fully specified Euler angles. + + The technical documents [4,5,6] give rotation matrix elements to six + decimal places, which is not sufficient for accurate pointing in the + SPICE toolkit. The remedy to this inaccuracy is provided below. + + Given an insufficiently-accurate rotation matrix, M, with column + vectors Vx, Vy, Vz: + + Vx Vy Vz + + [ M11 M12 M13 ] + [ ] + M = [ M21 M22 M23 ] + [ ] + [ M31 M32 M33 ] + + A rotation matrix, R, with column unit vectors Ux, Uy, Uz: + + Ux Uy Uz + + [ R11 R12 R13 ] + [ ] + R = [ R21 R22 R23 ] + [ ] + [ R31 R32 R33 ] + + is calculated so that column vectors are orthonormal to within double + precision accuracy (an operation SPICE calls "sharpening"): + + Uz = Vz / |Vz| + + Uy = Uz x (Vx / |Vx|) + + Ux = Uy x Uz + + These calculations are done outside of the SPICE library, but using + numerically stable algorithms as SPICE does. Sharpening by starting + with the X or Y direction, as opposed to Z, can be accomplished by + cyclically permuting x,y,z above. SPICE, for example, starts with X. + + With a precise (though not necessarily accurate) rotation matrix, + the instrinsic ZXZ Euler angles (A, B, Y) are calculated: + + A' = atan2(R13, -R23) + ______________ + B' = atan2(\/ 1 - R33 x R33 , R33) + + Y' = atan2(R31, R32) + + These values are rounded to regain the assumed original orientation: + + A = round(A') to nearest 1/1000th degree + + B = round(B') to nearest 1/1000th degree + + Y = round(Y') to nearest 1/1000th degree + + And finally, the rotation matrix elements are recalculated: + + R11 = c1 x c3 - s1 x c2 x s3 + + R21 = s1 x c3 + c1 x c2 x s3 + + R31 = s2 x s3 + + R12 = -c1 x s3 - s1 x c2 x c3 + + R22 = -s1 x s3 + c1 x c2 x c3 + + R32 = s2 x c3 + + R13 = s1 x s2 + + R23 = -c1 x s2 + + R33 = c2 + + where: + + c1 = cos(A) + + s1 = sin(A) + + c2 = cos(B) + + s2 = sin(B) + + c3 = cos(Y) + + s3 = sin(Y) + + When B = 0, the angles A and Y are degenerate; Y = 0 in this case. + + In the subsequent frames defined below, when Euler angles (A, B, Y) + are referenced without further discussion, they will refer to the + Euler angles as defined here. Otherwise, definitions will be given + inline with the discussion. + + + When Look Direction is Well-Defined + --------------------------------------------------------------------- + + When the look direction is well-defined, but the secondary axis is + not, we replace the column of the imprecise rotation matrix with + the exact look direction, and proceed with the calculations above. + + +IMAP Thruster Frames +======================================================================== + + There are four axial (A) thrusters and eight radial (R) thrusters on + IMAP[6]. The table below shows the thruster positions defined in the + spacecraft frame[6], at the intersection of the thrust axis and the + nozzle exit plane. The unit direction vectors listed in the table + below point in the direction of the thruster exhaust. The positional + information may be captured in the IMAP structure SPK, while the + orientation information is captured here. + + + Thruster ID X (mm) Y (mm) Z (mm) UnitDir (X,Y,Z) + ---------------- ------ -------- -------- ------- --------------- + IMAP_THRUSTER_A1 -43010 1007.28 516.50 1312.40 ( 0, 0, 1 ) + IMAP_THRUSTER_A2 -43011 -1007.28 -516.50 1312.40 ( 0, 0, 1 ) + IMAP_THRUSTER_A3 -43012 -1007.28 -516.50 101.77 ( 0, 0, -1 ) + IMAP_THRUSTER_A4 -43013 1007.28 516.50 101.77 ( 0, 0, -1 ) + IMAP_THRUSTER_R1 -43020 -126.90 1237.78 841.12 (-0.5, 0.866,0) + IMAP_THRUSTER_R2 -43021 126.90 -1237.78 841.12 ( 0.5,-0.866,0) + IMAP_THRUSTER_R3 -43022 -1008.49 728.79 841.12 (-0.5, 0.866,0) + IMAP_THRUSTER_R4 -43023 1008.49 -728.79 841.12 ( 0.5,-0.866,0) + IMAP_THRUSTER_R5 -43024 -126.90 1237.78 447.42 (-0.5, 0.866,0) + IMAP_THRUSTER_R6 -43025 126.90 -1237.78 447.42 ( 0.5,-0.866,0) + IMAP_THRUSTER_R7 -43026 -1008.49 728.79 447.42 (-0.5, 0.866,0) + IMAP_THRUSTER_R8 -43027 1008.49 -728.79 447.42 ( 0.5,-0.866,0) + + + Thruster Locations and Directions + --------------------------------------------------------------------- + + The four axial thrusters[6] are directed along the spacecraft Z axis, + with A1,A2 located on the +Z side of the spacecraft and A3,A4 located + on the -Z side. A1,A2 fire in the +Z direction, while A3,A4 fire in + the -Z direction. A1 and A4 are aligned in the Z direction, while + A2 and A3 are aligned but on the opposite side of the S/C as A1/A4. + + The eight radial thrusters[6] are grouped into four pairs (R1/R5, + R2/R6, R3/R7, R4/R8); each pair is aligned along the Z direction and + fire in the same direction. There are two distinct firing directions, + all perpendicular to the spacecraft Z axis: R1/R5 & R3/R7 fire toward + the +Y direction (with a slight -X component), while R2/R6 & R4/R8 + fire in the -Y direction (with a slight +X component). Thrusters + R1-R4 are located above the center of mass (towards the Sun), while + thrusters R5-R8 are located below the center of mass (away from the + Sun). The table below shows the azimuth of location and direction of + radial thrusters calculated from using thruster table above. + + + Location Azim Direction Azim + -------------- -------------- + R1/R5 5.85Β° 30.0Β° + R2/R6 180Β° + 5.85Β° 180Β° + 30.0Β° + R3/R7 54.15Β° 30.0Β° + R4/R8 180Β° + 54.15Β° 180Β° + 30.0Β° + + + +X axis +Z axis facing Sun + . into page + /|\ + | + | + | A1 (on +Z side) + A4 (on -Z side) + R4/R8 Dir /`~~__ / + '~._ , = .^ - /_ ``-. / + /~._ .+ + `^~/ .\/ + 30Β°| '~. + . -- ' `` @\ _-~ + - - + - - - -# R4/R8 \~'` \ + /' '-_ . \,.=.. \ + / ~ _,.,_ + + \ + R2/R6 Dir / ,~' +' `'+ + + \ + '~._ / ~^ .' , = .'. '- ='' -`` + /~._ ^/ / , = . + + \ \~'` + 30Β°| '~. | . + + + + . \ +Y axis -----> + - - + - - - -|# R2/R6 | + + ' = ' | \ + | | ' = ', - . | R1/R5 #._- - - - - + - - + _+_: ' + + ' / '~._ | + \_ __\__ \ + + / /^*~, '~._ / 30Β° + + | \ '. ' = ' .' / / '~. + `~-' '~..,___,..~' / /~,* R1/R5 Dir + _\ / /~,*` + * / \ ^*._/ *` + *\ _/`. R3/R7 #/._- - - - - + - - + * / /\@_ _ ,.-^-., _ _ _ / '~._ | + '=' | + + '~._ / 30Β° + | + + '~. + | '-.,.-' R3/R7 Dir + | + A2 (on +Z side) + A3 (on -Z side) + + + Axial Thruster Frames + --------------------------------------------------------------------- + + Each axial thruster has a frame defined so that the thruster exhaust + exits in the +Z' direction. The +Y' axis is chosen to lie in the + direction of the MAG boom. X' = Y' x Z' completes the frame. + + [X] [ 1 0 0 ] [X'] + [Y] = [ 0 1 0 ] [Y'] + [Z]S/C [ 0 0 1 ] [Z']Axial Thrusters A1,A2 + + [X] [ -1 0 0 ] [X'] + [Y] = [ 0 1 0 ] [Y'] + [Z]S/C [ 0 0 -1 ] [Z']Axial Thrusters A3,A4 + + + Axial Thruster + Exhaust Direction + + +Z' axis + | + | + _. -|- ._ + ,' | ', + , | , + | -.,_|_,.- | + ' ' + ' ' + ; ; + ; ; + : ; + , , Toward + ',_,' ^~ MAG + .~ '` ^~ ^~ Boom + .~ '` ^~ ^~ + .~ '` ^~ ^~ + .~ '` ^~ ^~ \ + +X' axis ^~ --* + ^~ + ^~ + +Y' axis + + + \begindata + + FRAME_IMAP_THRUSTER_A1 = -43010 + FRAME_-43010_NAME = 'IMAP_THRUSTER_A1' + FRAME_-43010_CLASS = 4 + FRAME_-43010_CLASS_ID = -43010 + FRAME_-43010_CENTER = -43 + TKFRAME_-43010_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43010_SPEC = 'MATRIX' + TKFRAME_-43010_MATRIX = ( 1, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 1 ) + + FRAME_IMAP_THRUSTER_A2 = -43011 + FRAME_-43011_NAME = 'IMAP_THRUSTER_A2' + FRAME_-43011_CLASS = 4 + FRAME_-43011_CLASS_ID = -43011 + FRAME_-43011_CENTER = -43 + TKFRAME_-43011_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43011_SPEC = 'MATRIX' + TKFRAME_-43011_MATRIX = ( 1, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 1 ) + + FRAME_IMAP_THRUSTER_A3 = -43012 + FRAME_-43012_NAME = 'IMAP_THRUSTER_A3' + FRAME_-43012_CLASS = 4 + FRAME_-43012_CLASS_ID = -43012 + FRAME_-43012_CENTER = -43 + TKFRAME_-43012_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43012_SPEC = 'MATRIX' + TKFRAME_-43012_MATRIX = ( -1, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + -1 ) + + FRAME_IMAP_THRUSTER_A4 = -43013 + FRAME_-43013_NAME = 'IMAP_THRUSTER_A4' + FRAME_-43013_CLASS = 4 + FRAME_-43013_CLASS_ID = -43013 + FRAME_-43013_CENTER = -43 + TKFRAME_-43013_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43013_SPEC = 'MATRIX' + TKFRAME_-43013_MATRIX = ( -1, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + -1 ) + + \begintext + + + Radial Thrusters + --------------------------------------------------------------------- + + Each radial thruster has a frame defined so that the thruster exhaust + exits in the +Y' direction. The +Z' axis is chosen to lie along the + spacecraft +Z axis (toward Sun). X' = Y' x Z' completes the frame. + + [X] [ cos( 30) -sin( 30) 0 ] [X'] + [Y] = [ sin( 30) cos( 30) 0 ] [Y'] + [Z]S/C [ 0 0 1 ] [Z']Rad. Thrusters R1,R3,R5,R7 + + [X] [ cos(210) -sin(210) 0 ] [X'] + [Y] = [ sin(210) cos(210) 0 ] [Y'] + [Z]S/C [ 0 0 1 ] [Z']Rad. Thrusters R2,R4,R6,R8 + + + Toward Sun + + +Z' axis + . + | + . + | + . + | + . + Radial Thruster | + Exhaust Direction . + | + .~ '` . + /.~ '` _,,~ ~ ~ ~ ~ ~ ~ ~ | + *-- .;-. \ ~ + ,' '. ~ ^~ + ; \ ~' ^~ + | .~ '`: ~' ^~ + .~ '` | ~' ^~ + ~ '` \ ; _ ~' ^~ + +Y' axis '.,_._;-' ^~ + ^~ + -X' axis + + + \begindata + + FRAME_IMAP_THRUSTER_R1 = -43020 + FRAME_-43020_NAME = 'IMAP_THRUSTER_R1' + FRAME_-43020_CLASS = 4 + FRAME_-43020_CLASS_ID = -43020 + FRAME_-43020_CENTER = -43 + TKFRAME_-43020_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43020_SPEC = 'MATRIX' + TKFRAME_-43020_MATRIX = ( 0.86602540378443865, + 0.50000000000000000, + 0.00000000000000000, + -0.50000000000000000, + 0.86602540378443865, + 0.00000000000000000, + 0.00000000000000000, + 0.00000000000000000, + 1.00000000000000000 ) + + FRAME_IMAP_THRUSTER_R2 = -43021 + FRAME_-43021_NAME = 'IMAP_THRUSTER_R1' + FRAME_-43021_CLASS = 4 + FRAME_-43021_CLASS_ID = -43021 + FRAME_-43021_CENTER = -43 + TKFRAME_-43021_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43021_SPEC = 'MATRIX' + TKFRAME_-43021_MATRIX = ( -0.86602540378443865, + -0.50000000000000000, + 0.00000000000000000, + 0.50000000000000000, + -0.86602540378443865, + 0.00000000000000000, + 0.00000000000000000, + 0.00000000000000000, + 1.00000000000000000 ) + + FRAME_IMAP_THRUSTER_R3 = -43022 + FRAME_-43022_NAME = 'IMAP_THRUSTER_R3' + FRAME_-43022_CLASS = 4 + FRAME_-43022_CLASS_ID = -43022 + FRAME_-43022_CENTER = -43 + TKFRAME_-43022_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43022_SPEC = 'MATRIX' + TKFRAME_-43022_MATRIX = ( 0.86602540378443865, + 0.50000000000000000, + 0.00000000000000000, + -0.50000000000000000, + 0.86602540378443865, + 0.00000000000000000, + 0.00000000000000000, + 0.00000000000000000, + 1.00000000000000000 ) + + FRAME_IMAP_THRUSTER_R4 = -43023 + FRAME_-43023_NAME = 'IMAP_THRUSTER_R4' + FRAME_-43023_CLASS = 4 + FRAME_-43023_CLASS_ID = -43023 + FRAME_-43023_CENTER = -43 + TKFRAME_-43023_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43023_SPEC = 'MATRIX' + TKFRAME_-43023_MATRIX = ( -0.86602540378443865, + -0.50000000000000000, + 0.00000000000000000, + 0.50000000000000000, + -0.86602540378443865, + 0.00000000000000000, + 0.00000000000000000, + 0.00000000000000000, + 1.00000000000000000 ) + + FRAME_IMAP_THRUSTER_R5 = -43024 + FRAME_-43024_NAME = 'IMAP_THRUSTER_R5' + FRAME_-43024_CLASS = 4 + FRAME_-43024_CLASS_ID = -43024 + FRAME_-43024_CENTER = -43 + TKFRAME_-43024_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43024_SPEC = 'MATRIX' + TKFRAME_-43024_MATRIX = ( 0.86602540378443865, + 0.50000000000000000, + 0.00000000000000000, + -0.50000000000000000, + 0.86602540378443865, + 0.00000000000000000, + 0.00000000000000000, + 0.00000000000000000, + 1.00000000000000000 ) + + FRAME_IMAP_THRUSTER_R6 = -43025 + FRAME_-43025_NAME = 'IMAP_THRUSTER_R6' + FRAME_-43025_CLASS = 4 + FRAME_-43025_CLASS_ID = -43025 + FRAME_-43025_CENTER = -43 + TKFRAME_-43025_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43025_SPEC = 'MATRIX' + TKFRAME_-43025_MATRIX = ( -0.86602540378443865, + -0.50000000000000000, + 0.00000000000000000, + 0.50000000000000000, + -0.86602540378443865, + 0.00000000000000000, + 0.00000000000000000, + 0.00000000000000000, + 1.00000000000000000 ) + + FRAME_IMAP_THRUSTER_R7 = -43026 + FRAME_-43026_NAME = 'IMAP_THRUSTER_R7' + FRAME_-43026_CLASS = 4 + FRAME_-43026_CLASS_ID = -43026 + FRAME_-43026_CENTER = -43 + TKFRAME_-43026_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43026_SPEC = 'MATRIX' + TKFRAME_-43026_MATRIX = ( 0.86602540378443865, + 0.50000000000000000, + 0.00000000000000000, + -0.50000000000000000, + 0.86602540378443865, + 0.00000000000000000, + 0.00000000000000000, + 0.00000000000000000, + 1.00000000000000000 ) + + FRAME_IMAP_THRUSTER_R8 = -43027 + FRAME_-43027_NAME = 'IMAP_THRUSTER_R6' + FRAME_-43027_CLASS = 4 + FRAME_-43027_CLASS_ID = -43027 + FRAME_-43027_CENTER = -43 + TKFRAME_-43027_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43027_SPEC = 'MATRIX' + TKFRAME_-43027_MATRIX = ( -0.86602540378443865, + -0.50000000000000000, + 0.00000000000000000, + 0.50000000000000000, + -0.86602540378443865, + 0.00000000000000000, + 0.00000000000000000, + 0.00000000000000000, + 1.00000000000000000 ) + + \begintext + + +IMAP Digital Sun Sensor and Star Tracker Frames +======================================================================== + + There are two digital sun sensors (DSS)[6]: one on the +Z side of the + spacecraft pointing in +Z direction, and one on the -Z side pointing + mostly in the radial direction with a 30Β° tilt in the -Z direction. + They are approximated aligned along the spacecraft Z axis, though the + origins are offset from absolute alignment by a few centimeters (see + table below). Azimuthally, the sun sensors are located near the SWAPI + instrument approximately 18Β° off of the Y-Z plane. + + There are two star trackers mounted adjacent to each other on the + underside of the spacecraft close to the -Z digital star sensor[6]. + Their boresights are generally downward (towards -Z), with an angular + separation of 24Β°. One is angled toward the +X direction, the other + angled towards the -X direction. + + Positional information may be captured in the IMAP structure SPK, + while the orientation information is captured here. + + + Digital Sun Sensor ID X (mm) Y (mm) Z (mm) Loc. Azim + -------------------- ------ -------- -------- -------- --------- + IMAP_SUN_SENSOR_PZ -43030 -364.22 -1121.90 1301.67 162.014Β° + IMAP_SUN_SENSOR_MZ -43031 -379.11 -1167.77 72.89 162.014Β° + + + Digital Star Tracker ID X (mm) Y (mm) Z (mm) Loc. Azim + -------------------- ------ -------- -------- -------- --------- + IMAP_STAR_TRACKER_PX -43040 -45.75 -906.66 159.88 177.111Β° + IMAP_STAR_TRACKER_MX -43041 -188.05 -881.57 142.79 167.959Β° + + + ##################################################################### + # / _- __.----# + # ,' ~` _.~^' # + # / ~` ,~^ # + # ,' +Z axis facing Sun .` .^ +X axis # + # / into page / .^ . # + # | : /_,-----,_ /|\# + # | ~ ~` ^. | # + # | ^ ^ ^_ | # + # | / / , | # + # | , , ; | # + # | ; ; } | # + # | ___ : : ~ ___# + # -Y axis ___| .` `. | | }/ _# + # <------ |===| ;+X Star; | |. ;/ (` # + # | ;Tracker; | |' ; \ (,_# + # | `, ,` | | ', , \___# + # | '---' : : '-.,_____,.-` _,~# + # | _,;@ ; ; ," # + # /| | @*^^'` : : ; # + # /^' { _,;| ,---, ; ; ^ # + # \ *^^'` | .^ ^. ~ ~ { # + # | SWAPI { _, |-X Star| \ \ | # + # \ _,;*^ \ .Tracker. \ * { # + # | *^^'` \ -Z DSS ^.___.^ ^, `~_ \ # + # \ } \ _} ^_ "~_ ^, # + # ^^'"\\ \*^ ^, '-_ ~_ # + # \ (+Z DSS not visible) "~_ " -, '- # + ##################################################################### + + + Digital Sun Sensors (DSS) + --------------------------------------------------------------------- + + Each DSS has a frame defined so that the look-direction is along the + +Z' axis. The digital image rows and columns are aligned with the X' + and Y' axes of the frame. + + + DSS Look Direction + Local Frame + + +Z' axis + | + | + | + | + | + | + .~|'`^~ + .~ '` | ^~ + .~ '` __,=# | ,_ ^~ + .~ '` __,=#^^^ |@ ^%,_ ^~ + ~ ,=#^^^ | ^%,_ ^~ + | ^~ ,.~^~ ^%,_ ^~ + | ^~ ,.~ '` ^~ ^% ,^ + | ,.^~' @ ^~ .~ '` | + ^~.''` ^~ @^~ '` | + .~ '`` ^~ ^~ .~ '` ^~ | + +X' axis ^~ ^~.~ '` ^~.~ '` + ^~ | .~ '` ^~ + ^~ | .~ '` ^~ + ^~ |.~ '` +Y' axis + + + The rotation matrices orienting each DSS on the spacecraft are + given by [6]: + + [X] [ 0.951057 0.309017 0.000000 ] [X'] + [Y] = [ -0.309017 0.951057 0.000000 ] [Y'] + [Z]S/C [ 0.000000 0.000000 1.000000 ] [Z'] +Z DSS + + [X] [ 0.951078 -0.154380 -0.267616 ] [X'] + [Y] = [ -0.308952 -0.475579 -0.823640 ] [Y'] + [Z]S/C [ -0.000116 0.866025 -0.500000 ] [Z'] -Z DSS + + Using the method described in a previous section, the Euler angles + rounded to 1/1000th of a degree are: + + +Z DSS: (A, B, Y) = ( -18.000Β°, 0.000Β°, 0.000Β° ) + + -Z DSS: (A, B, Y) = ( -18.000Β°, 120.000Β°, -0.008Β° ) + + Using the formulas described in the Euler angles section above, the + rotation matrices have been recalculated to double precision. + + + \begindata + + FRAME_IMAP_SUN_SENSOR_PZ = -43030 + FRAME_-43030_NAME = 'IMAP_SUN_SENSOR_PZ' + FRAME_-43030_CLASS = 4 + FRAME_-43030_CLASS_ID = -43030 + FRAME_-43030_CENTER = -43 + TKFRAME_-43030_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43030_SPEC = 'MATRIX' + TKFRAME_-43030_MATRIX = ( 0.95105651629515350, + -0.30901699437494734, + 0.00000000000000000, + 0.30901699437494734, + 0.95105651629515350, + 0.00000000000000000, + -0.00000000000000000, + -0.00000000000000000, + 1.00000000000000000 ) + + FRAME_IMAP_SUN_SENSOR_MZ = -43031 + FRAME_-43031_NAME = 'IMAP_SUN_SENSOR_MZ' + FRAME_-43031_CLASS = 4 + FRAME_-43031_CLASS_ID = -43031 + FRAME_-43031_CENTER = -43 + TKFRAME_-43031_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43031_SPEC = 'MATRIX' + TKFRAME_-43031_MATRIX = ( 0.95107808048040110, + -0.30895059509261280, + -0.00012091995722272, + -0.15437570314113858, + -0.47557140042407403, + 0.86602539534263330, + -0.26761656732981740, + -0.82363910354633210, + -0.49999999999999983 ) + + \begintext + + + Star Trackers + --------------------------------------------------------------------- + + Each star tracker has a frame defined so that the look-direction is + along the +Z' axis. The digital image rows and columns are aligned + with the X' and Y' axes of the frame. + + + Star Tracker Look Direction + Local Frame + + +Z' axis + + | + | + | + | + _. -|- ._ + ,' | ', + | .~ '` ^~ ,| + .~ '` ~ .,_ _,.^~' | + .~ '` | ^~ + .~ '` |, ,| ^~ + +X' axis ' -.,_ _,.- ' ^~ + | | ^~ + | | ^~ + | | +Y' axis + '-.,_ _,.-' + + + + When oriented on the spacecraft: + + - The tracker X' axis mostly points towards the spacecraft -X axis + - The tracker Y' axis mostly points towards the spacecraft +Y axis + - The tracker Z' axis mostly points towards the spacecraft -Z axis + + + ##################################################################### + # { { # + # ) ) # + # @ @ # + # { { # + # _,~--~,_ | | # + # ," ", ,-----,' # + # ; ; | | # + # +X Star / \ | | # + # Tracker { __,.- +Y' '-----' # + # | ..-^" |: | | # + # { ; ;} | | # + # {\ ; / } { { # + # {^, : ,^ ; @ @ # + # . ~_ ; _~ ,` | | # + # `, '~--~" ,^ "' | | # + # '"^--,__ ` ' "^ { { # + # `^ +X' `"` ) ) # + # "' ^' | | # + # ^' '~ { { # + # ^, __,,.~*^# ) ) # + # ', _,.~-'^'`__,,.~*^# | | # + # #-*~^'_,.~-'^'` '" { { # + # #-*~^' "^ @ @ # + # '" `"` | | # + # `^ ^` { { # + # "` _,~^^^~-.,'^ ) )# + # ^' _-" _,~--~,_ ".' ( # + # '^/ ," ", \` \ # + # , ; ;', \ # + # |/ \| # + # { __,.- +Y' Spacecraft Axes # + # -X Star | ..-^" | # + # Tracker { ; } +X # + # \ ; / | # + # ^, : ,^ | # + # ~_ ; _~ | # + # '~--~" | # + # ` x-------- +Y # + # +X' +Z into # + # Page # + ##################################################################### + + + The rotation matrices orienting each star tracker on the spacecraft + are given by [6]: + + [X] [ -0.963287 0.173648 0.204753 ] [X'] + [Y] = [ 0.169854 0.984808 -0.036104 ] [Y'] + [Z]S/C [ -0.207912 0.000000 -0.978148 ] [Z']+X Star Tracker + + + [X] [ -0.963287 0.173648 -0.204753 ] [X'] + [Y] = [ 0.169854 0.984808 0.036104 ] [Y'] + [Z]S/C [ 0.207912 0.000000 -0.978148 ] [Z']-X Star Tracker + + Using the method described in a previous section, the Euler angles + rounded to 1/1000th of a degree are: + + +X Star Tracker: (A, B, Y) = ( 80.000Β°, 168.000Β°, -90.000Β° ) + + -X Star Tracker: (A, B, Y) = ( -100.000Β°, 168.000Β°, 90.000Β° ) + + Use the formulas described in the Euler angles section above, the + rotation matrices have been recalculated to double precision. + + + \begindata + + FRAME_IMAP_STAR_TRACKER_PX = -43040 + FRAME_-43040_NAME = 'IMAP_STAR_TRACKER_PX' + FRAME_-43040_CLASS = 4 + FRAME_-43040_CLASS_ID = -43040 + FRAME_-43040_CENTER = -43 + TKFRAME_-43040_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43040_SPEC = 'MATRIX' + TKFRAME_-43040_MATRIX = ( -0.96328734079294150, + 0.16985354835670569, + -0.20791169081775915, + 0.17364817766693050, + 0.98480775301220800, + 0.00000000000000001, + 0.20475304505920630, + -0.03610348622615415, + -0.97814760073380570 ) + + FRAME_IMAP_STAR_TRACKER_MX = -43041 + FRAME_-43041_NAME = 'IMAP_STAR_TRACKER_MX' + FRAME_-43041_CLASS = 4 + FRAME_-43041_CLASS_ID = -43041 + FRAME_-43041_CENTER = -43 + TKFRAME_-43041_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43041_SPEC = 'MATRIX' + TKFRAME_-43041_MATRIX = ( -0.96328734079294150, + 0.16985354835670533, + 0.20791169081775915, + 0.17364817766693014, + 0.98480775301220800, + 0.00000000000000001, + -0.20475304505920630, + 0.03610348622615410, + -0.97814760073380570 ) + + \begintext + + +IMAP Antenna Frames +======================================================================== + + There are two antennas on the spacecraft. The low gain antenna (LGA) + is located on the +Z side of the spacecraft pointing toward +Z, while + the medium gain antenna (MGA) is located on the -Z side pointing in + the -Z direction. + + + --------- + | +Z axis | + ------------------- --------- + | +X axis into page | #-----# . + ------------------- | LGA | /|\ + #-----# | + ___ _________|^|______|__________________ + | |====================|__________________|_____________ __ _|SWAPI + '---' MAG boom \ __ | | | // \ /--|# + |( )=|__|| | | \\__/ \--|# + | HIT | _|_ IDEX | CODICE | + | | ,.' | '., | | + | ____ | [ \ | / ] | SWE| + ULTRA ##',', |,.'|'.,| GLOWS (#)| + 45 ####'. + | + \\(O) |-|| + '----####/----- + | + --------------' + <---------------- | | \______'-.O.-'______/ | | + --------- /_\ ----------- |__| + | +Y axis | #-----# | S/C FRAME | STAR + --------- | MGA | | ORIGIN | TRACKERS + #-----# ----------- + + + ##################################################################### + # .-----------------------------------------------------.# + # |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|# + # | | | | | | | | | | | | | | | | | | |# + # ,, _,~'-----|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|# + # \ \" ' _,~|___ |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|# + # \ \ " | | | | | | SOLAR PANELS | | | | | | |# + # \ \: |--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|# + # \,' |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|# + # HIT | | | | | | | | | | | | | | | |# + # |--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|# + # |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|# + # \ ___ | | | | | | | | | | |# + # THRUSTER R3 --> ,~\ |# #| |--|--|--|--|--|--|--|--|--|--|# + # ^, |# #| |__|__|__|__|__|__|__|__|__|__|# + # ^~---|---| | | | | | | | | | |# + # Spacecraft Axes | '-----------------------------'# + # | ^/~., ,.~\^ # + # +X #-----# { * `"*,_____,*"` * } # + # # LGA # { * | | * } # + # | #-----# \ * | | * / # + # | ~. * | | * .~ # + # | "|~####|####~|" # + # | # + # +Y --------+ IDEX # + # +Z out # + # of page # + ##################################################################### + + + ##################################################################### + # / #####~._ half of ~` _.~^' # + # / #########~._ ULTRA 45 ~` ,~^_ # + # HIT ,###########/ .` .^ ~ # + # (just out / ########/ / .^ ,` # + # of view) , : / , # + # / ~ ~` | # + # , ^ ^ , # + # / / / , # + # , , , , # + # / +Z into __ ; ; - # + # , page .`##`. : : `- . , _ ___# + # |/ +Y ------x ;#**#; | | / _# + # |\ | `.##.` | | ,.----., / (` # + # ' | | | | _~` `~_\ (,_# + # \ | #-----# | | ~ ~\___# + # ' # MGA # : : ,` `, # + # \ +X #-----# ; ;, , # + # ' : :| | # + # \ _.-----. ; ; , # + # '~ '^, ~ ~ , # + # -| IMAP / \ \ \ , # + # ' | LO | ' \ * - # + # | ' ; \ ^, `~_ _,.` # + # | ; :,_ . ^_ "~_ ~ ^ # + # ' ; | ^, '-_ # + # \ - ; "~_ " -, # + ##################################################################### + + + The LGA frame is coincident with the spacecraft XYZ axis, while the + MGA secondary axis is chosen so that Y' coincides with spacecraft Y. + This selection is identical to the axial thrusters A3,A4. + + [X] [ 1 0 0 ] [X'] + [Y] = [ 0 1 0 ] [Y'] + [Z]S/C [ 0 0 1 ] [Z']Low Gain Antenna + + [X] [ -1 0 0 ] [X'] + [Y] = [ 0 1 0 ] [Y'] + [Z]S/C [ 0 0 -1 ] [Z']Medium Gain Antenna + + + \begindata + + FRAME_IMAP_LOW_GAIN_ANTENNA = -43050 + FRAME_-43050_NAME = 'IMAP_LOW_GAIN_ANTENNA' + FRAME_-43050_CLASS = 4 + FRAME_-43050_CLASS_ID = -43050 + FRAME_-43050_CENTER = -43 + TKFRAME_-43050_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43050_SPEC = 'MATRIX' + TKFRAME_-43050_MATRIX = ( 1, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 1 ) + + FRAME_IMAP_MED_GAIN_ANTENNA = -43051 + FRAME_-43051_NAME = 'IMAP_MED_GAIN_ANTENNA' + FRAME_-43051_CLASS = 4 + FRAME_-43051_CLASS_ID = -43051 + FRAME_-43051_CENTER = -43 + TKFRAME_-43051_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43051_SPEC = 'MATRIX' + TKFRAME_-43051_MATRIX = ( -1, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + -1 ) + + \begintext + + +IMAP-Lo Frames +======================================================================== + + IMAP-Lo is a single-pixel energetic neutral atom (ENA) imager mounted + on a pivot platform and equipped with a star sensor that pivots with + the ENA sensor [12,13]. The instrument is mounted for imaging in the + radial direction of the rotating spacecraft with the pivot allowing + orientation of the boresight from a polar angle of 60Β° (slightly + towards the Sun) to 180Β° (directed away from the Sun). + + + --------- + | +Z axis | + --------- --------------------- + . | +X axis out of page | + /|\ --------------------- + | LGA + __________________|______|^|_________ ___ + SWAPI|__________________|__________________|====================| | + #|-| | | .-==-, | / MAG boom '---' + #|-| {|## | | / \ | | + | {|## | |{ HI 90 }| IMAP LO| _. IMAP LO + | {|## | _.._ | \ / | _., | _.-' BORESIGHT + | ULTRA | / \ | `-==-' | / __`'_.-' + | 90 | \ HI 45/ | | \ \.-';| + | | '----` | | ~._.+ | + '-------------------|----------/--------' + | | \_________O_________/ | | ----------------> + |__| ----------- /_\ --------- + STAR | S/C FRAME | MGA | +Y axis | + TRACKERS | ORIGIN | --------- + ----------- + + + IMAP-Lo Local Frame + + Pivot +Z' axis + Angle | + ,.~'^ ^ ^-| + .-'` | + .` _~-, Star Sensor + .` | ** \___ _ | + Boresight | / \_-'`~~~~~~`'-.- - + . |/___ ,^~~~~~~%##### ', '. + `'. ^~~~~~~%%######### ` '. + `'. /~~~~~~, - - ~~~#####\ . + /. ~~~ / `.~~%###, . + .~~~`'./ .~~### . + .~~~~ `'. |~~~%#" .`. + "~~~~%| O :~~~~ ' . . + |~~~ # . /~~~~~ | . \ + |~~~%##`. /~~~~~ / . | + \~~%### ~`- -'~~~~~~ / . . + +,~%######~~~~~~~~ ,- ~@@@~ . + | ' ~ ######%%%%_,^ ,~@@@~ Rotation Axis + '. - .%##%.- .' . ^~. + .~ '` `. .' .` ^~. + .~ '` ' . _ .' .` ^~. + .~ '` ` '.''`` ,.` +X' axis + -Y' axis `-.,,, . ` + + + The local IMAP-Lo base frame is defined so the sensor pivots about + the +X' axis. When the pivot angle is 90Β°, the boresight is aligned + with the local -Y' axis. The +Z' axis, from which the pivot angle is + measured, aligns with the spacecraft +Z axis. + + The boresight look-direction is defined for the azimuth-elevation: + + LO (azim, elev) = ( +330Β°, -90Β° to +30Β° ) + + At 0Β° elevation (90Β° polar angle), the boresight direction and + primary axis in the spacecraft frame of reference is: + + D = -Y' = [ -cos(0) x sin(330), cos(0) x cos(330), sin(0) ] + + The secondary axis is the +X' local axis, perpendicular to both + the boresight direction D and the spacecraft -Z axis: + + S = +X' = D x -Z = Y' x [ 0, 0, 1 ] + + The tertiary axis is: + + N = D x S = Y' x ( Y' x [ 0, 0, 1 ] ) + + The rotation matrix formed using the column vectors is: + + R = [ +S, -D, +N ] + + From the spacecraft MICD[6], the single-precision rotation matrices + orienting IMAP-Lo on the spacecraft: + + [X] [ -0.866025 -0.500000 0.000000 ] [X'] + [Y] = [ 0.500000 -0.866025 0.000000 ] [Y'] + [Z]S/C [ 0.000000 0.000000 1.000000 ] [Z']IMAP-Lo + + consistent with calculating the matrix R to single precision. + + For reference, the ZYZ intrinsic Euler angles orienting X'Y'Z' in + the spacecraft XYZ coordinate system are: + + IMAP-Lo: (A, B, Y) = ( 150.000Β°, 0.000Β°, 0.000Β° ) + + Using the formulas described in the Euler angles section above, the + rotation matrix generated from these Euler angles is consistent with + the rotation matrix using the azimuth/elevation look direction. + + + IMAP-Lo Orientation + --------------------------------------------------------------------- + + The orientation of IMAP-Lo must be specified in a separate C-kernel. + To facilitate this specification, a base frame representing the fixed + transformation of the local X'Y'Z' frame to the spacecraft frame has + been provided. + + Ideally, the C-kernel will simply specify transformation within the + local IMAP-Lo frame, and be generated using only the pivot angle. + The implementation of this is outside the scope of this kernel. + + + \begindata + + FRAME_IMAP_LO_BASE = -43100 + FRAME_-43100_NAME = 'IMAP_LO_BASE' + FRAME_-43100_CLASS = 4 + FRAME_-43100_CLASS_ID = -43100 + FRAME_-43100_CENTER = -43 + TKFRAME_-43100_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43100_SPEC = 'MATRIX' + TKFRAME_-43100_MATRIX = ( -0.86602540378443865, + 0.50000000000000000, + 0.00000000000000000, + -0.50000000000000000, + -0.86602540378443865, + 0.00000000000000000, + 0.00000000000000000, + 0.00000000000000000, + 1.00000000000000000 ) + + FRAME_IMAP_LO = -43101 + FRAME_-43101_NAME = 'IMAP_LO' + FRAME_-43101_CLASS = 3 + FRAME_-43101_CLASS_ID = -43101 + FRAME_-43101_CENTER = -43 + + FRAME_IMAP_LO_STAR_SENSOR = -43102 + FRAME_-43102_NAME = 'IMAP_LO_STAR_SENSOR' + FRAME_-43102_CLASS = 4 + FRAME_-43102_CLASS_ID = -43102 + FRAME_-43102_CENTER = -43 + TKFRAME_-43102_RELATIVE = 'IMAP_LO' + TKFRAME_-43102_SPEC = 'MATRIX' + TKFRAME_-43102_MATRIX = ( 1, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 1 ) + + \begintext + + +IMAP-Hi Frames +======================================================================== + + IMAP-Hi consists of two identical, single-pixel high energy neutral + atom (ENA) imagers. Hi 90 is oriented with its boresight + perpendicular to the spacecraft spin axis, while Hi 45 is radially + outward but with the boresight angled 45Β° from the -Z axis. + + --------- + | +X axis | + --------- -------------------- + . | +Z axis facing Sun | + HI 45 BORESIGHT /|\ | into page | + . | . -------------------- + " .~15Β°~.| .~15Β°~." + \ | / HI 90 BORESIGHT + , | , + ; /`~~__ , `+ direction of + , = .^ - /_ ``-. '. positive + .+ + `^~/ ./ ~ rotation + ^ + + . -- ' `` \ _-~ \ + _ / ',= ' \~'` \ IMAP \ + ULTRA /' '-_ .~ ' \,.=.. \ LO \|/ + 90 / ~ _,.,_ + + \ ' + / ,~' +' `'+ + + \ + / ~^ .' , = .'. '- ='' -`` --------- + ^/ / , = . + + \ \~'` | +Y axis |-----> + | . + + + + . \ --------- ___ + | | + + ' = ' | \--------------------| | + SWAPI| | ' = ', - . | /--------------------|___| + _+_: ' + + ' / MAG boom + \_ __\__ \ + + / /^*~, + + | SWE '. ' = ' .' ULTRA / + `~-' '~..,___,..~' 45 /~,* + _\ / /~,*` + * / CODICE ^*._/ *` HIT + *\ _/`. / + * / /~ _ _ ,.-^-., _ _ _ / + '=' + + + GLOWS + + + '-.,.-' + IDEX + + + --------- + | +Z axis | + --------- --------------------- + . | +X axis out of page | + /|\ --------------------- + | LGA + __________________|______|^|_________ ___ + SWAPI|__________________|__________________|====================| | + #|-| | | .-==-, | / MAG boom '---' + #|-| {|## | | / \ | | + | {|## | |{ HI 90 }| IMAP LO| + | {|## | _.._ | \ / | _., | + | ULTRA | / \ | `-==-' | / __`',| + | 90 | \ HI 45/ | | \ \_\ ;| + | | '----` | | ~._ + | + '-------------------|----------/--------' + | | \_________O_________/ | | ----------------> + |__| ----------- /_\ --------- + STAR | S/C FRAME | MGA | +Y axis | + TRACKERS | ORIGIN | --------- + ----------- + + + ##################################################################### + #______________________________________________ # + # / _ | || | IMAP HI 90 # + #----~. / |_| O o | || |==== hidden # + # ULTRA 90 /\ x x = | || | behind s/c # + # / \__________| || || <---- struct here # + # ##### -- #### | || |] # + # ## % ## / \###\ / ___ || |} HI 90 Boresight # + # /## % ##\--|####| |____|*#*| || |}_________________ # + # |## % ##|--|####| | |*#*| || |} # + # |## % ##| |####| | --- || |} # + # |## % ##|--|####| | || |] +Z # + # |## % ##|--|####| \ || || # + # \## % ##/ |####| | || . | # + # ## % ## \ /###/ | || .'. | # + # ##### -- #### | || . /, | # + #--------------- | |.` _~ x------ +X # + # | ,` ,~` `~ +Y into # + # ______ / .` ~` _ \ page # + # .=.=.=.=. |( ) ()| / ___ * -' ~' `', | # + # | | | | | |( ) ()| |____|*#*|| ~ .`_ _ / ~ # + #__#_#_#_#_#__|______| |*#*||` / //// / ~ # + #----------------| .----- / ` ` ' ~ # + # |_ _ _| | | .'_ / '`.,_ ,~' ~. # + # | | | | | | .' -, | _, ` ":. # + #__/_/_/_/___/___|________|______;_\_ ,.-' |:. # + # | | / ":. # + #_______________________________________| | _45Β° ":. # + #___ ____ __ || || || | |-~" " # + # / / / / // |_____||_____||_____| | HI 45 # + #_/ /___/ /_/ | /|\ \|/ Boresight # + # / ' # + # | --------- # + # / | -Z axis | # + #=========== --------- # + ##################################################################### + + + The local IMAP-Hi frame[15]--identical for both sensors--is defined + with the boresight aligned with the +Y' axis, the rectangular vent + ports aligned with the +Z' axis, and X' = Y' x Z'. + + + IMAP HI 45 + -------------- + + The boresight look-direction is defined for the azimuth-elevation: + + HI 45 (azim, elev) = ( +255Β°, -45Β° ) + + The boresight direction is the +Y' local axis of instrument, and the + primary axis in the spacecraft frame of reference is: + + D = +Y' = [ -cos(-45) x sin(255), cos(-45) x cos(255), sin(-45) ] + + The secondary axis is the +Z' local axis, NOTIONALLY perpendicular to + both the boresight direction D and the spacecraft Z axis: + + S = +Z' = D x Z = Y' x [ 0, 0, 1 ] + + The tertiary axis is NOTIONALLY: + + N = D x S = Y' x ( Y' x [ 0, 0, 1 ] ) + + The rotation matrix formed using the column vectors is NOTIONALLY: + + RN = [ +N, +D, +S ] + + HOWEVER, the actual alignment is modified by a rotation about the + local Y' axis by 3Β° as a consequence of the angular offset of the + mounting inserts by the same amount. This rotation about local Y' is: + + [ cos(3) 0 sin(3) ] + RY' = [ 0 1 0 ] + [ -sin(3) 0 cos(3) ] + + The final rotation that orients HI 45 on the spacecraft is the matrix + multiplication: + + R = RN x RY' + + From the spacecraft MICD[6], the single-precision rotation matrices + orienting IMAP-HI 45 on the spacecraft: + + [X] [ -0.668531 0.683013 -0.294210 ] [X'] + [Y] = [ 0.233315 -0.183013 -0.955024 ] [Y'] + [Z]S/C [ -0.706183 -0.707107 -0.037007 ] [Z']HI 45 + + Using the method described in a Euler discussion section, the Euler + angles rounded to 1/1000th of a degree are: + + HI 45: (A, B, Y) = ( -17.122Β°, 92.121Β°, -135.037Β° ) + + Using the formulas described in the Euler angles section above, the + rotation matrix generated from these Euler angles is consistent with + the rotation matrix using the azimuth/elevation look direction; + however, the full double-precision Euler angles are necessary to + generate the proper precise rotation matrix. + + + \begindata + + FRAME_IMAP_HI_45 = -43150 + FRAME_-43150_NAME = 'IMAP_HI_45' + FRAME_-43150_CLASS = 4 + FRAME_-43150_CLASS_ID = -43150 + FRAME_-43150_CENTER = -43 + TKFRAME_-43150_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43150_SPEC = 'MATRIX' + TKFRAME_-43150_MATRIX = ( -0.66853111450276550, + 0.23331454112339850, + -0.70613771591812640, + 0.68301270189221940, + -0.18301270189221924, + -0.70710678118654750, + -0.29421046547595930, + -0.95502391375634550, + -0.03700710955926802 ) + + \begintext + + + IMAP HI 90 + -------------- + + The boresight look-direction is defined for the azimuth-elevation: + + HI 90 (azim, elev) = ( +285Β°, 0Β° ) + + The boresight direction is the +Y' local axis of instrument, and the + primary axis in the spacecraft frame of reference is: + + D = +Y' = [ -cos(0) x sin(285), cos(0) x cos(285), sin(0) ] + + The secondary axis is the +Z' local axis, NOTIONALLY perpendicular to + both the boresight direction D and the spacecraft Z axis: + + S = -Z' = D x Z = -Y' x [ 0, 0, 1 ] + + The tertiary axis is NOTIONALLY: + + N = D x S = Y' x ( Y' x [ 0, 0, 1 ] ) + + The rotation matrix formed using the column vectors is NOTIONALLY: + + RN = [ +N, +D, +S ] + + HOWEVER, the actual alignment is modified by a rotation about the + local Y' axis by 15Β° as a consequence of the angular offset of the + mounting inserts by the same amount. This rotation about local Y' is: + + [ cos(15) 0 sin(15) ] + RY' = [ 0 1 0 ] + [ -sin(15) 0 cos(15) ] + + The final rotation that orients HI 45 on the spacecraft is the matrix + multiplication: + + R = RN x RY' + + From the spacecraft MICD[6], the single-precision rotation matrices + orienting IMAP-HI 45 on the spacecraft: + + [X] [ 0.066987 0.965926 -0.250000 ] [X'] + [Y] = [ -0.250000 0.258819 0.933013 ] [Y'] + [Z]S/C [ 0.965926 0.000000 0.258819 ] [Z']HI 90 + + Using the method described in a Euler discussion section, the Euler + angles rounded to 1/1000th of a degree are: + + HI 90: (A, B, Y) = ( -165.000Β°, 75.000Β°, 90.000Β° ) + + Using the formulas described in the Euler angles section above, the + rotation matrix generated from these Euler angles is consistent with + the rotation matrix using the azimuth/elevation look direction. + + + \begindata + + FRAME_IMAP_HI_90 = -43151 + FRAME_-43151_NAME = 'IMAP_HI_90' + FRAME_-43151_CLASS = 4 + FRAME_-43151_CLASS_ID = -43151 + FRAME_-43151_CENTER = -43 + TKFRAME_-43151_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43151_SPEC = 'MATRIX' + TKFRAME_-43151_MATRIX = ( 0.06698729810778055, + -0.25000000000000000, + 0.96592582628906829, + 0.96592582628906829, + 0.25881904510252074, + 0.00000000000000000, + -0.25000000000000000, + 0.93301270189221940, + 0.25881904510252074 ) + + \begintext + + +IMAP-Ultra Frames +======================================================================== + + The IMAP-Ultra instrument[7,14] consists of two identical sensors for + imaging the emission of energetic neural atoms (ENAs) produced in the + heliosheath and beyond. Ultra 90 is mounted perpendicular to the IMAP + spin axis (+Z), while Ultra 45 is mounted at 45 degrees from the + anti-sunward spin axis (-Z). + + + --------- + | +X axis | -------------------- + --------- | +Z axis facing Sun | + . | into page | + /|\ -------------------- + | + | + | + _ + HI 45 /`~~__HI 90 `+ direction of + , = .^ - /_ ``-. '. positive + .+ + `^~/ ./ ~ rotation + ULTRA ^ + + . -- ' `` \ _-~ \ + 90 _ / ',= ' \~'` \ IMAP \ + . /' '-_ .~ ' \,.=.. \ LO \|/ + `;. / ~ _,.,_ + + \ ' + / `/ ,~' +' `'+ + + \ + 30Β° / ~^ .' , = .'. '- ='' -`` --------- + | ^/ / , = . + + \ \~'` | +Y axis |-----> + ---- | . + + + + . \ --------- ___ + | | + + ' = ' | \--------------------| | + SWAPI| | ' = ', - . | /--------------------|___| + _+_: ' + + ' / | MAG boom + \_ __\__ \ + + / /^*~, . + + | SWE '. ' = ' .' ULTRA / 33Β° + `~-' '~..,___,..~' 45 / ; + _\ / /`., / + * / CODICE ^*._/ `'./ + *\ _/`. / `'. + * / /~ _ _ ,.-^-., _ _ _ / + '=' + + + GLOWS + + + '-.,.-' + IDEX + + + Each sensor comprises two separate assemblies of collector plates. + Each assembly of collector plates is fanned out in a cylindrical + pattern, and the cyclindrical axes of the fanned-out plates are + parallel and offset in the direction perpendicular to the axes. + + The orientations of Ultra 45 and 90 are analogous to IMAP Hi 45 and + 90; see the diagram for IMAP Hi above. Take special note that the + angle with the spacecraft Z axis and the boresights for IMAP Hi are + the same as the angle with the spacecraft Z axis and the "outward" + directions for Ultra. + + + ##################################################################### + # # + # One half of one IMAP Ultra sensor showing # + # assembly of fanned-out collector plates # + # Outward # + # . Assemblies are mirror-symmetric # + # /|\ about the leftmost edge of drawing # + # | # + # | ,--. , # + # || | | ; , 63.42Β° FOR # + # | | | | ; ; ; 60.31Β° FOV # + # | | | | : ; ; ; ; # + # \|/ | | | : ; ; ; / # + # ' | ;_ _|_ ; ; ; ; / / . # + # S/C | | ``'''^-,/, / / / .' # + # | | ___ `''., / / . . # + #_________;-|__|_ `'"^~-,._ /^~ `^., / ,' ' . # + #---------'- | |_| `'":., _ `^, . ,' .' # + #--------. ,-| | @ `'~/ \ `'. .` .' , # + # ,'`.' | | @ @ @ @ '~,.;, '. .' .' # + # .',' | | @ @ @ @ @ `;, /~_':' .' ,' # + #.'`,' _| |_ @ @ @ `;, / '. .' ,'` # + # `, |_|-|_| @ @ '. '. .' ,. # + #'-,'. |-| @ @ @ ', `.` ;' # + # '.'-. | | @ @ ;, \,;`' .-`# + # `-.'. | | @ @ ", ', ,.'` ,^# + #_________:'-| | @ @ @ @ :, _,\' .-`` # + #-----------||-|-, @ /~,".' ;'.' # + #=== ||---|@ @ @ @ @ ,\ ' ,.^` # + #___________||_/-~_ _ @ @ _, _,-' ,.-'` # + # @| | | || `- , @ @ \,\' ,'` +Z' # + #----' | | || `~,@ @ ,~`' _,'` # + # | | || ',@ .^\_,'` ,.'` | # + #______'-'__||-@--~-~, \ .;` .'` | # + #___________||/ ~ # ~ | {.'` | # + # |* ||*| + <------------ Collector plate +------ +Y'# + #____ --||\ ~ ~ | axis of symmetry +X' out # + #_ *| ||-@-^~-~^-------| of page # + #*| | ||_______________| # + #___*|_______|_|_|__|__|_|_| | # + ##################################################################### + + + The local IMAP-Ultra frame[14]--identical for both sensors--is + defined with the collector-plate-fan axes of symmetry aligned with + the +X' axis, the cylindrical axes offset in the +Y' axis, and the + Z' axis perpendicular to both and outward as in the diagram below. + + + IMAP ULTRA 45 + -------------- + + The outward look-direction is defined for the azimuth-elevation: + + ULTRA 45 (azim, elev) = ( +33Β°, -45Β° ) + + The look-direction is the +Z' local axis of instrument, and the + primary axis in the spacecraft frame of reference is: + + D = +Z' = [ -cos(-45) x sin(33), cos(-45) x cos(33), sin(-45) ] + + The secondary axis is the +X' local axis, lying in the plane spanned + by the look-direction D and the spacecraft Z axis. An equivalent + definition is selecting the secondary axis as the +Y' local axis, + perpendicular to both the look-direction D and the spacecraft Z axis. + + S = +Y' = D x Z = Z' x [ 0, 0, 1 ] + + The tertiary axis is: + + N = D x S = Z' x Y' = Z' x ( Z' x [ 0, 0, 1 ] ) + + The rotation matrix formed using the column vectors is: + + R = [ -N, +S, +D ] + + The rotation matrices orienting the IMAP-Ultra 45 sensor on the + spacecraft is given by [6]: + + [X] [ -0.385118 0.838671 -0.385118 ] [X'] + [Y] = [ 0.593030 0.544639 0.593030 ] [Y'] + [Z]S/C [ 0.707107 0.000000 -0.707107 ] [Z']ULTRA 45 + + Using the method described in a Euler discussion section, the Euler + angles rounded to 1/1000th of a degree are: + + ULTRA 45: (A, B, Y) = ( -147.000Β°, 135.000Β°, 90.000Β° ) + + Using the formulas described in the Euler angles section above, the + rotation matrix generated from these Euler angles is consistent with + the rotation matrix using the azimuth/elevation look direction. + + + \begindata + + FRAME_IMAP_ULTRA_45 = -43200 + FRAME_-43200_NAME = 'IMAP_ULTRA_45' + FRAME_-43200_CLASS = 4 + FRAME_-43200_CLASS_ID = -43200 + FRAME_-43200_CENTER = -43 + TKFRAME_-43200_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43200_SPEC = 'MATRIX' + TKFRAME_-43200_MATRIX = ( -0.38511795495802310, + 0.59302964577578240, + 0.70710678118654760, + 0.83867056794542390, + 0.54463903501502710, + 0.00000000000000000, + -0.38511795495802320, + 0.59302964577578250, + -0.70710678118654750 ) + + \begintext + + + IMAP ULTRA 90 + -------------- + + The outward look-direction is defined for the azimuth-elevation: + + ULTRA 90 (azim, elev) = ( +210Β°, 0Β° ) + + The look-direction is the +Z' local axis of instrument, and the + primary axis in the spacecraft frame of reference is: + + D = +Z' = [ -cos(0) x sin(210), cos(0) x cos(210), sin(0) ] + + The secondary axis is the +X' local axis, lying along spacecraft + -Z axis. + + S = +X' = +Z = [ 0, 0, 1 ] + + The tertiary axis is: + + N = D x S = Z' x X' = Z' x [ 0, 0, 1 ] + + The rotation matrix formed using the column vectors is: + + R = [ +S, +N, +D ] + + The rotation matrices orienting the IMAP-Ultra 90 sensor on the + spacecraft is given by [6]: + + [X] [ 0.000000 -0.866025 0.500000 ] [X'] + [Y] = [ 0.000000 -0.500000 -0.866025 ] [Y'] + [Z]S/C [ 1.000000 0.000000 0.000000 ] [Z']ULTRA 90 + + Using the method described in a Euler discussion section, the Euler + angles rounded to 1/1000th of a degree are: + + ULTRA 90: (A, B, Y) = ( 30.000Β°, 90.000Β°, 90.000Β° ) + + Using the formulas described in the Euler angles section above, the + rotation matrix generated from these Euler angles is consistent with + the rotation matrix using the azimuth/elevation look direction. + + + \begindata + + FRAME_IMAP_ULTRA_90 = -43201 + FRAME_-43201_NAME = 'IMAP_ULTRA_90' + FRAME_-43201_CLASS = 4 + FRAME_-43201_CLASS_ID = -43201 + FRAME_-43201_CENTER = -43 + TKFRAME_-43201_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43201_SPEC = 'MATRIX' + TKFRAME_-43201_MATRIX = ( 0.00000000000000000, + 0.00000000000000000, + 1.00000000000000000, + -0.86602540378443865, + -0.50000000000000000, + 0.00000000000000006, + 0.50000000000000000, + -0.86602540378443865, + 0.00000000000000000 ) + + \begintext + + +IMAP Magnetometer (MAG) Frames +======================================================================== + + The IMAP magnetometer (MAG)[7,16] consists of a pair of identical + triaxial fluxgate magnetometers mounted on a ~2.5 meter boom. MAG-O + is positioned at the end of the boom, while MAG-I is mounted ~0.75 + meters from MAG-O. + + + --------- + | +X axis | -------------------- + --------- | +Z axis facing Sun | + . | into page | + /|\ -------------------- + | + | + | + _ + HI 45 /`~~__HI 90 `+ direction of + , = .^ - /_ ``-. '. positive + .+ + `^~/ ./ ~ rotation + ^ + + . -- ' `` \ _-~ \ + _ / ',= ' \~'` \ IMAP \ + ULTRA /' '-_ .~ ' \,.=.. \ LO \|/ + 90 / ~ _,.,_ + + \ ' + / ,~' +' `'+ + + \ + / ~^ .' , = .'. '- ='' -`` + ^/ / , = . + + \ \~'` +Y axis -----> + | . + + + + . \ ___ ___ + | | + + ' = ' | \------------| |---| | + SWAPI| | ' = ', - . | /------------|___|---|___| + _+_: ' + + ' / MAG-I MAG-O + \_ __\__ \ + + / /^*~, + + | SWE '. ' = ' .' ULTRA / MAGS and boom + `~-' '~..,___,..~' 45 /~,* not to scale + _\ / /~,*` + * / CODICE ^*._/ *` HIT + *\ _/`. / + * / /~ _ _ ,.-^-., _ _ _ / + '=' + + + GLOWS + + + '-.,.-' + IDEX + + + ---------------------------- + S/C +Z axis | Deployed Magnetometer Boom | S/C +X axis + . | (approximately to scale) | out of page + /|\ ---------------------------- + | + | S/C +Y axis --------> + @================================================================= + #\ | | | | + \ `'` `'` + Boom Deployment Hinge MAG-I MAG-O + + +X' ------x +Y' into + | page + MAG Local | + Coord System | + + +Z' + + + Each MAG instrument is contained in a cylindrial casing with the + local Z' axis along the cylindrical axis of symmetry. The local X' + axis is along the boom, and the local Y' axis is perp to the boom. + + When deployed, the boom sticks out in the +Y axis of the spacecraft, + with the MAG +X' axis in the -Y direction. The MAG +Z' axis is in the + spacecraft -Z' direction, and +Y' is spacecraft -X. + + [X] [ 0 -1 0 ] [X'] + [Y] = [ -1 0 0 ] [Y'] + [Z]S/C [ 0 0 -1 ] [Z']MAG deployed + + Prior to deployment, the boom is stowed pointing in the -Y direction + of the spacecraft, with the MAG +X' axis in the +Y direction. The MAG + +Z' axis is in the spacecraft +Z' direction, and +Y' is spacecraft -X + + [X] [ 0 +1 0 ] [X'] + [Y] = [ -1 0 0 ] [Y'] + [Z]S/C [ 0 0 +1 ] [Z']MAG undeployed + + To facilitate possible operations prior to the boom deployment, a + frame for the deployed boom is provided; the MAG-I and MAG-O frames + are provided relative to this frame. If needed, the IMAP_MAG_BOOM + can be modified to facilitate arbitrary operational reality. + + + \begindata + + FRAME_IMAP_MAG_BOOM = -43250 + FRAME_-43250_NAME = 'IMAP_MAG_BOOM' + FRAME_-43250_CLASS = 4 + FRAME_-43250_CLASS_ID = -43250 + FRAME_-43250_CENTER = -43 + TKFRAME_-43250_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43250_SPEC = 'MATRIX' + TKFRAME_-43250_MATRIX = ( 1, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 1 ) + + FRAME_IMAP_MAG_I = -43251 + FRAME_-43251_NAME = 'IMAP_MAG_I' + FRAME_-43251_CLASS = 4 + FRAME_-43251_CLASS_ID = -43251 + FRAME_-43251_CENTER = -43 + TKFRAME_-43251_RELATIVE = 'IMAP_MAG_BOOM' + TKFRAME_-43251_SPEC = 'MATRIX' + TKFRAME_-43251_MATRIX = ( 0, + -1, + 0, + -1, + 0, + 0, + 0, + 0, + -1 ) + + FRAME_IMAP_MAG_O = -43252 + FRAME_-43252_NAME = 'IMAP_MAG_O' + FRAME_-43252_CLASS = 4 + FRAME_-43252_CLASS_ID = -43252 + FRAME_-43252_CENTER = -43 + TKFRAME_-43252_RELATIVE = 'IMAP_MAG_BOOM' + TKFRAME_-43252_SPEC = 'MATRIX' + TKFRAME_-43252_MATRIX = ( 0, + -1, + 0, + -1, + 0, + 0, + 0, + 0, + -1 ) + + \begintext + + +IMAP Solar Wind Electron (SWE) Frames +======================================================================== + + TODO: FIX ME...The orientation of the spacecraft body frame with + respect to an inertial + frame, for IMAP - ECLIPJ2000, is provided by a C-kernel (see [3] + for details). + + This frame specifies the rotating X,Y and pointing Z coordinate body + frame. + + \begindata + + FRAME_IMAP_SWE = -43300 + FRAME_-43300_NAME = 'IMAP_SWE' + FRAME_-43300_CLASS = 4 + FRAME_-43300_CLASS_ID = -43300 + FRAME_-43300_CENTER = -43 + TKFRAME_-43300_SPEC = 'MATRIX' + TKFRAME_-43300_MATRIX = ( 0.453990, + 0.891007, + 0.000000, + -0.891007, + 0.453990, + 0.000000, + 0.000000, + 0.000000, + 1.000000 ) + TKFRAME_-43300_RELATIVE = 'IMAP_SPACECRAFT' + +\begintext + + +IMAP Solar Wind and Pickup Ion (SWAPI) Frames +======================================================================== + + TODO: add diagrams + + SWAPI has the following nominal alignment to the spacecraft frame, + reference Table 1 of [6]. The azimuth and elevation angles are + illustrated in the 'IMAP I&T Component Placement' section near the top + of this document. + + azimuth | elevation + (deg) | (deg) + ---------+--------- + 168 | 0 + + The SWAPI base frame is defined in the instrument MICD [8] as follows: + + * -Z axis is the axis of symmetry of the instrument, pointing + away from the spacecraft body. + * +Y axis is along the aperture center, in the anti-sunward direction. + + The azimuth and elevation give the outward axis of symmetry, -Z in the + instrument frame: + + -Z = -[ -sin(az) * cos(el), cos(az) * cos(el), sin(el) ] + instr + + The instrument +Y axis is in the sunward direction, towards the + spacecraft +Z axis: + + Y = [ 0 0 1 ] + instr + + Taking the cross product and normalizing, we arrive at the instrumet +X + axis: + Y x Z + X = --------- + instr | Y x Z | + + And adjusting Y: + + Z x X + Y = --------- + instr | Z x X | + + This definition is captured in the keywords below. + + \begindata + + FRAME_IMAP_SWAPI = -43350 + FRAME_-43350_NAME = 'IMAP_SWAPI' + FRAME_-43350_CLASS = 4 + FRAME_-43350_CLASS_ID = -43350 + FRAME_-43350_CENTER = -43 + TKFRAME_-43350_SPEC = 'MATRIX' + TKFRAME_-43350_MATRIX = ( -0.97814760073381, + 0.20791169081776, + 0.00000000000000, + 0.00000000000000, + 0.00000000000000, + 1.00000000000000, + 0.20791169081776, + 0.97814760073381, + 0.00000000000000 ) + TKFRAME_-43350_RELATIVE = 'IMAP_SPACECRAFT' + +\begintext + + +IMAP Compact Dual Ion Composition Experiment (CoDICE) Frames +======================================================================== + + TODO: FIX ME...The orientation of the spacecraft body frame with + respect to an inertial + frame, for IMAP - ECLIPJ2000, is provided by a C-kernel (see [3] + for details). + + This frame specifies the rotating X,Y and pointing Z coordinate body + frame. + + \begindata + + FRAME_IMAP_CODICE = -43400 + FRAME_-43400_NAME = 'IMAP_CODICE' + FRAME_-43400_CLASS = 4 + FRAME_-43400_CLASS_ID = -43400 + FRAME_-43400_CENTER = -43 + TKFRAME_-43400_SPEC = 'MATRIX' + TKFRAME_-43400_MATRIX = ( 0.694626, + 0.719371, + 0.000000, + -0.719371, + 0.694626, + 0.000000, + 0.000000, + 0.000000, + 1.000000 ) + TKFRAME_-43400_RELATIVE = 'IMAP_SPACECRAFT' + +\begintext + + +IMAP High-energy Ion Telescope (HIT) Frames +======================================================================== + + TODO: FIX ME...The orientation of the spacecraft body frame with + respect to an inertial + frame, for IMAP - ECLIPJ2000, is provided by a C-kernel (see [3] + for details). + + This frame specifies the rotating X,Y and pointing Z coordinate body + frame. + + \begindata + + FRAME_IMAP_HIT = -43500 + FRAME_-43500_NAME = 'IMAP_HIT' + FRAME_-43500_CLASS = 4 + FRAME_-43500_CLASS_ID = -43500 + FRAME_-43500_CENTER = -43 + TKFRAME_-43500_SPEC = 'MATRIX' + TKFRAME_-43500_MATRIX = ( 0.866025, + 0.500000, + 0.000000, + -0.500000, + 0.866025, + 0.000000, + 0.000000, + 0.000000, + 1.000000 ) + TKFRAME_-43500_RELATIVE = 'IMAP_SPACECRAFT' + +\begintext + + +IMAP Interstellar Dust Experiment (IDEX) Frames +======================================================================== + + TODO: FIX ME...The orientation of the spacecraft body frame with + respect to an inertial + frame, for IMAP - ECLIPJ2000, is provided by a C-kernel (see [3] + for details). + + This frame specifies the rotating X,Y and pointing Z coordinate body + frame. + + \begindata + + FRAME_IMAP_IDEX = -43700 + FRAME_-43700_NAME = 'IMAP_IDEX' + FRAME_-43700_CLASS = 4 + FRAME_-43700_CLASS_ID = -43700 + FRAME_-43700_CENTER = -43 + TKFRAME_-43700_SPEC = 'MATRIX' + TKFRAME_-43700_MATRIX = ( 0.000000, + 1.000000, + 0.000000, + -0.707107, + 0.000000, + -0.707107, + -0.707107, + 0.000000, + 0.707107 ) + TKFRAME_-43700_RELATIVE = 'IMAP_SPACECRAFT' + +\begintext + + +IMAP GLObal solar Wind Structure (GLOWS) Frames +======================================================================== + + TODO: add diagrams + + GLOWS has the following nominal alignment to the spacecraft frame, + reference Table 1 of [6]. The azimuth and elevation angles are + illustrated in the 'IMAP I&T Component Placement' section near the top + of this document. + + azimuth | elevation + (deg) | (deg) + ---------+--------- + 127 | 15 + + The GLOWS base frame is defined by the instrument team as follows [10]: + + * +Z axis points in the anti-boresight direction + * +Y axis points in the anti-sunward direction. + + The azimuth and elevation give the outward axis of symmetry, -Z in the + instrument frame: + + Z = -[ -sin(az) * cos(el), cos(az) * cos(el), sin(el) ] + instr + + The instrument +Y axis is in the anti-sunward direction, towards the + spacecraft -Z axis: + + Y = [ 0 0 -1 ] + instr + + Taking the cross product and normalizing, we arrive at the instrumet +X + axis: + Y x Z + X = --------- + instr | Y x Z | + + And adjusting Y: + + Z x X + Y = --------- + instr | Z x X | + + This definition is captured in the keywords below. + + \begindata + + FRAME_IMAP_GLOWS = -43751 + FRAME_-43751_NAME = 'IMAP_GLOWS' + FRAME_-43751_CLASS = 4 + FRAME_-43751_CLASS_ID = -43751 + FRAME_-43751_CENTER = -43 + TKFRAME_-43751_SPEC = 'MATRIX' + TKFRAME_-43751_MATRIX = ( 0.60181502315205, + -0.79863551004729, + 0.00000000000000, + -0.20670208009540, + -0.15576118962056, + -0.96592582628907, + 0.77142266494622, + 0.58130867351132, + -0.25881904510252 ) + TKFRAME_-43751_RELATIVE = 'IMAP_SPACECRAFT' + +\begintext + + Generic axis + + +Z axis + | + | + | + | + | + | + | + | + | + | + | + | + .~ ~ + .~ '` ^~ + .~ '` ^~ + .~ '` ^~ + .~ '` ^~ + +X axis ^~ + ^~ + ^~ + +Y axis + +End of FK file. \ No newline at end of file diff --git a/imap_processing/tests/spice/test_data/imap_130.tf b/imap_processing/tests/spice/test_data/imap_130.tf new file mode 100644 index 0000000000..5bdb8a5d54 --- /dev/null +++ b/imap_processing/tests/spice/test_data/imap_130.tf @@ -0,0 +1,3527 @@ +KPL/FK + +Interstellar Mapping and Acceleration Probe Frames Kernel +======================================================================== + + This frames kernel contains the current set of coordinate frame + definitions for the Interstellar Mapping and Acceleration Probe + (IMAP) spacecraft, structures, and science instruments. + + This kernel also contains NAIF ID/name mapping for the IMAP + instruments. + + +Version and Date +======================================================================== + + The TEXT_KERNEL_ID stores version information of loaded project text + kernels. Each entry associated with the keyword is a string that + consists of four parts: the kernel name, version, entry date, and + type. For example, the frames kernel might have an entry as follows: + + + TEXT_KERNEL_ID += 'IMAP_FRAMES V1.0.0 2024-XXXX-NN FK' + | | | | + | | | | + KERNEL NAME <-------+ | | | + | | V + VERSION <------+ | KERNEL TYPE + | + V + ENTRY DATE + + + Interstellar Mapping and Acceleration Probe Frames Kernel Version: + + \begindata + + TEXT_KERNEL_ID += 'IMAP_FRAMES V1.3.0 2025-NOV-13 FK' + + \begintext + + + Version 1.3.0 -- Nov 13, 2025 -- Lillian Nguyen + + Inserted a nominal base frame for MAG. + Corrected frame name to ID mapping for HI-90, ULTRA-90, MAG-O. + (Note: Release version number 1.1.0 was inadvertently skipped.) + + Version 1.2.0 -- Oct 21, 2025 -- Lillian Nguyen + + Updated SWAPI frame with launch site alignments. + Added instrument coordinate system diagrams for SWAPI, CoDICE, and GLOWS. + Removed unimplemented SWAPI and CODICE aperture frame IDs. + + Version 1.0.0 -- Sept 19, 2025 -- Douglas Rodgers + Lillian Nguyen + Nicholas Dutton + + This release includes: + -Launch site alignment for LO, MAG, SWE, GLOWS, ULTRA, HI, HIT, CODICE. + -Nominal (ideal) alignments for SWAPI. + Frames not yet implemented: + -SWAPI Apertures and Sunglasses + -CODICE Apertures + + Version 0.0.1 -- July 9, 2021 -- Ian Wick Murphy + + Modifying dart_008.tf to add basic IMAP frame components. This + includes IMAP, IMAP_THRUSTER, and CK/SCLK IDs. Also adding a place + holder for the IMAP-Lo instrument with the ID -43001 and IMAP_LO + name. Future work includes adding more detailed instrument frames, + and reaching out to mechanical for an "official" IMAP_SPACECRAFT + frame definition. + + +References +======================================================================== + + 1. "Frames Required Reading" + + 2. "Kernel Pool Required Reading" + + 3. "C-Kernel Required Reading" + + 4. "7516-9067: IMAP Mechanical Interface Control Document", + Johns Hopkins Applied Physics Laboratory + + 5. "7516-9050: IMAP Coordinate Frame & Technical Definitions Doc.", + Johns Hopkins Applied Physics Laboratory + + 6. "7516-0011: IMAP Mechanical Interface Control Drawing", + [EXPORT CONTROLLED], Johns Hopkins Applied Physics Laboratory + + 7. "7523-0008: IMAP ULTRA Mechanical Interface Control Drawing", + [EXPORT CONTROLLED], Johns Hopkins Applied Physics Laboratory + + 8. "058991000: IMAP SWAPI Mechanical Interface Control Drawing", + Princeton University Space Physics + + 9. "GLOWS-CBK-DWG-2020-08-25-019-v4.4: IMAP GLOWS Mechanical + Interface Control Drawing", Centrum Badag Kosmicznych, Polska + Akademia Nauks + + 10. Responses from IMAP instrument teams on their base frame axis + definitions, received in email. + + 11. "Euler angles", Wikimedia Foundation, 2024-04-22, + https://en.wikipedia.org/wiki/Euler_angles + + 12. "7516-9059: IMAP-Lo to Spacecraft Interface Control Document", + [EXPORT CONTROLLED], Johns Hopkins Applied Physics Laboratory + + 13. "DRAFT Rev H: IMAP-Lo Mechanical Interface Control Drawing", + [EXPORT CONTROLLED], Univ. of New Hampshire Space Science Center + + 14. McComas et al, "IMAP: A New NASA Mission", + Space Sci Rev (2018) 214:116 + + 15. "IMAP-HI SENSOR HEAD Mechanical Interface Control Drawing", + [EXPORT CONTROLLED], Los Alamos National Laboratory + + 16. "IMAP-MAG-SENSOR Drawing Rev 6", Imperial College London + + 17. "Launch Site Alignments Report", Anthony Fanelli, Aug. 7, 2025 + + 18. "IMAP-SWE INSTRUMENT MICD", Drawing No. CN102M-i0000, Rev A, + Los Alamos National Laboratory + + 19. https://imap.princeton.edu/spacecraft/instruments/solar-wind-electron-swe/ + swe-technical-overview + + 20. "IMAP-HI SENSOR HEAD MICD", Drawing No. CN106M-i0000, Rev A, + Los Alamos National Laboratory + + 21. β€œHIT TOP LEVEL ASSY MICD”, Drawing No. 2309580, Rev A, Goddard Space + Flight Center + + 22. "IDEX, MECHANICAL INTERFACE CONTROL DOCUMENT (MICD)", Doc Num 165014, + Rev E, Laboratory for Lunar and Space Physics + + 23. IMAP CODICE MICD, Drawing No. 268503001, Rev. C, Southwest Research + Institute + + +Contact Information +======================================================================== + + Douglas Rodgers, JHU/APL, Douglas.Rodgers@jhuapl.edu + + Lillian Nguyen, JHU/APL, Lillian.Nguyen@jhuapl.edu + + Nicholas Dutton, JHU/APL, Nicholas.Dutton@jhuapl.edu + + Ian Wick Murphy, JHU/APL, Ian.Murphy@jhuapl.edu + + +Implementation Notes +======================================================================== + + This file is used by the SPICE system as follows: programs that make + use of this frame kernel must `load' the kernel, normally during + program initialization. Loading the kernel associates the data items + with their names in a data structure called the `kernel pool'. The + SPICELIB routine FURNSH loads a kernel into the pool as shown below: + + FORTRAN: (SPICELIB) + + CALL FURNSH ( frame_kernel_name ) + + C: (CSPICE) + + furnsh_c ( frame_kernel_name ); + + IDL: (ICY) + + cspice_furnsh, frame_kernel_name + + MATLAB: (MICE) + + cspice_furnsh ( frame_kernel_name ) + + This file was created and may be updated with a text editor or word + processor. + + +Viewing ASCII Artwork +======================================================================== + + Artwork must be viewed in a text editor with monospaced font and + compact single-spaced lines. The following give the proper aspect + ratio: + + Andale Regular + Menlo Regular + Courier New Regular + PT Mono Regular + + The common monospaced font (at the time of writing) Monaco Regular + gives an aspect ratio that is too tall. Other fonts undoubtedly + will render the diagrams properly or improperly. + + As a guide, the following axis will be square when measured from the + bottom of the lower-most vertical line to the end of each axis. + + | + | + | + |_______ + + +IMAP NAIF ID Codes -- Definitions +======================================================================== + + This section contains name to NAIF ID mappings for the IMAP mission. + Once the contents of this file are loaded into the KERNEL POOL, these + mappings become available within SPICE, making it possible to use + names instead of ID code in high level SPICE routine calls. + + \begindata + + NAIF_BODY_NAME += ( 'IMAP' ) + NAIF_BODY_CODE += ( -43 ) + + NAIF_BODY_NAME += ( 'IMAP_SPACECRAFT' ) + NAIF_BODY_CODE += ( -43000 ) + + NAIF_BODY_NAME += ( 'IMAP_THRUSTER_A1' ) + NAIF_BODY_CODE += ( -43010 ) + + NAIF_BODY_NAME += ( 'IMAP_THRUSTER_A2' ) + NAIF_BODY_CODE += ( -43011 ) + + NAIF_BODY_NAME += ( 'IMAP_THRUSTER_A3' ) + NAIF_BODY_CODE += ( -43012 ) + + NAIF_BODY_NAME += ( 'IMAP_THRUSTER_A4' ) + NAIF_BODY_CODE += ( -43013 ) + + NAIF_BODY_NAME += ( 'IMAP_THRUSTER_R1' ) + NAIF_BODY_CODE += ( -43020 ) + + NAIF_BODY_NAME += ( 'IMAP_THRUSTER_R2' ) + NAIF_BODY_CODE += ( -43021 ) + + NAIF_BODY_NAME += ( 'IMAP_THRUSTER_R3' ) + NAIF_BODY_CODE += ( -43022 ) + + NAIF_BODY_NAME += ( 'IMAP_THRUSTER_R4' ) + NAIF_BODY_CODE += ( -43023 ) + + NAIF_BODY_NAME += ( 'IMAP_THRUSTER_R5' ) + NAIF_BODY_CODE += ( -43024 ) + + NAIF_BODY_NAME += ( 'IMAP_THRUSTER_R6' ) + NAIF_BODY_CODE += ( -43025 ) + + NAIF_BODY_NAME += ( 'IMAP_THRUSTER_R7' ) + NAIF_BODY_CODE += ( -43026 ) + + NAIF_BODY_NAME += ( 'IMAP_THRUSTER_R8' ) + NAIF_BODY_CODE += ( -43027 ) + + NAIF_BODY_NAME += ( 'IMAP_SUN_SENSOR_PZ' ) + NAIF_BODY_CODE += ( -43030 ) + + NAIF_BODY_NAME += ( 'IMAP_SUN_SENSOR_MZ' ) + NAIF_BODY_CODE += ( -43031 ) + + NAIF_BODY_NAME += ( 'IMAP_STAR_TRACKER_PX' ) + NAIF_BODY_CODE += ( -43040 ) + + NAIF_BODY_NAME += ( 'IMAP_STAR_TRACKER_MX' ) + NAIF_BODY_CODE += ( -43041 ) + + NAIF_BODY_NAME += ( 'IMAP_LOW_GAIN_ANTENNA' ) + NAIF_BODY_CODE += ( -43050 ) + + NAIF_BODY_NAME += ( 'IMAP_MED_GAIN_ANTENNA' ) + NAIF_BODY_CODE += ( -43051 ) + + NAIF_BODY_NAME += ( 'IMAP_LO_BASE' ) + NAIF_BODY_CODE += ( -43100 ) + + NAIF_BODY_NAME += ( 'IMAP_LO' ) + NAIF_BODY_CODE += ( -43101 ) + + NAIF_BODY_NAME += ( 'IMAP_LO_STAR_SENSOR' ) + NAIF_BODY_CODE += ( -43102 ) + + NAIF_BODY_NAME += ( 'IMAP_HI_45' ) + NAIF_BODY_CODE += ( -43150 ) + + NAIF_BODY_NAME += ( 'IMAP_HI_90' ) + NAIF_BODY_CODE += ( -43151 ) + + NAIF_BODY_NAME += ( 'IMAP_ULTRA_45' ) + NAIF_BODY_CODE += ( -43200 ) + + NAIF_BODY_NAME += ( 'IMAP_ULTRA_90' ) + NAIF_BODY_CODE += ( -43201 ) + + NAIF_BODY_NAME += ( 'IMAP_MAG_BOOM' ) + NAIF_BODY_CODE += ( -43250 ) + + NAIF_BODY_NAME += ( 'IMAP_MAG_I' ) + NAIF_BODY_CODE += ( -43251 ) + + NAIF_BODY_NAME += ( 'IMAP_MAG_O' ) + NAIF_BODY_CODE += ( -43252 ) + + NAIF_BODY_NAME += ( 'IMAP_MAG_BASE' ) + NAIF_BODY_CODE += ( -43253 ) + + NAIF_BODY_NAME += ( 'IMAP_SWE' ) + NAIF_BODY_CODE += ( -43300 ) + + NAIF_BODY_NAME += ( 'IMAP_SWE_DETECTOR_P63' ) + NAIF_BODY_CODE += ( -43301 ) + + NAIF_BODY_NAME += ( 'IMAP_SWE_DETECTOR_P42' ) + NAIF_BODY_CODE += ( -43302 ) + + NAIF_BODY_NAME += ( 'IMAP_SWE_DETECTOR_P21' ) + NAIF_BODY_CODE += ( -43303 ) + + NAIF_BODY_NAME += ( 'IMAP_SWE_DETECTOR_000' ) + NAIF_BODY_CODE += ( -43304 ) + + NAIF_BODY_NAME += ( 'IMAP_SWE_DETECTOR_M21' ) + NAIF_BODY_CODE += ( -43305 ) + + NAIF_BODY_NAME += ( 'IMAP_SWE_DETECTOR_M42' ) + NAIF_BODY_CODE += ( -43306 ) + + NAIF_BODY_NAME += ( 'IMAP_SWE_DETECTOR_M63' ) + NAIF_BODY_CODE += ( -43307 ) + + NAIF_BODY_NAME += ( 'IMAP_SWAPI' ) + NAIF_BODY_CODE += ( -43350 ) + + NAIF_BODY_NAME += ( 'IMAP_CODICE' ) + NAIF_BODY_CODE += ( -43400 ) + + NAIF_BODY_NAME += ( 'IMAP_HIT' ) + NAIF_BODY_CODE += ( -43500 ) + + NAIF_BODY_NAME += ( 'IMAP_HIT_L1_APERTURE_01' ) + NAIF_BODY_CODE += ( -43501 ) + + NAIF_BODY_NAME += ( 'IMAP_HIT_L1_APERTURE_02' ) + NAIF_BODY_CODE += ( -43502 ) + + NAIF_BODY_NAME += ( 'IMAP_HIT_L1_APERTURE_03' ) + NAIF_BODY_CODE += ( -43503 ) + + NAIF_BODY_NAME += ( 'IMAP_HIT_L1_APERTURE_04' ) + NAIF_BODY_CODE += ( -43504 ) + + NAIF_BODY_NAME += ( 'IMAP_HIT_L1_APERTURE_05' ) + NAIF_BODY_CODE += ( -43505 ) + + NAIF_BODY_NAME += ( 'IMAP_HIT_L1_APERTURE_06' ) + NAIF_BODY_CODE += ( -43506 ) + + NAIF_BODY_NAME += ( 'IMAP_HIT_L1_APERTURE_07' ) + NAIF_BODY_CODE += ( -43507 ) + + NAIF_BODY_NAME += ( 'IMAP_HIT_L1_APERTURE_08' ) + NAIF_BODY_CODE += ( -43508 ) + + NAIF_BODY_NAME += ( 'IMAP_HIT_L1_APERTURE_09' ) + NAIF_BODY_CODE += ( -43509 ) + + NAIF_BODY_NAME += ( 'IMAP_HIT_L1_APERTURE_10' ) + NAIF_BODY_CODE += ( -43510 ) + + NAIF_BODY_NAME += ( 'IMAP_IDEX' ) + NAIF_BODY_CODE += ( -43700 ) + + NAIF_BODY_NAME += ( 'IMAP_IDEX_DETECTOR' ) + NAIF_BODY_CODE += ( -43701 ) + + NAIF_BODY_NAME += ( 'IMAP_IDEX_FULL_SCIENCE' ) + NAIF_BODY_CODE += ( -43702 ) + + NAIF_BODY_NAME += ( 'IMAP_GLOWS' ) + NAIF_BODY_CODE += ( -43750 ) + + \begintext + + +IMAP NAIF ID Codes -- Definitions +======================================================================== + + The ID codes -43900 to -43999 have been reserved for the IMAP dynamic + frames kernel and are not utilized in this file. + + The following frames are defined in this kernel file: + + Frame Name Relative To Type NAIF ID + ========================== =============== ======= ======= + + Spacecraft (000-099) + -------------------------- + IMAP_SPACECRAFT J2000 CK -43000 + IMAP_THRUSTER_A1 IMAP_SPACECRAFT FIXED -43010 + IMAP_THRUSTER_A2 IMAP_SPACECRAFT FIXED -43011 + IMAP_THRUSTER_A3 IMAP_SPACECRAFT FIXED -43012 + IMAP_THRUSTER_A4 IMAP_SPACECRAFT FIXED -43013 + IMAP_THRUSTER_R1 IMAP_SPACECRAFT FIXED -43020 + IMAP_THRUSTER_R2 IMAP_SPACECRAFT FIXED -43021 + IMAP_THRUSTER_R3 IMAP_SPACECRAFT FIXED -43022 + IMAP_THRUSTER_R4 IMAP_SPACECRAFT FIXED -43023 + IMAP_THRUSTER_R5 IMAP_SPACECRAFT FIXED -43024 + IMAP_THRUSTER_R6 IMAP_SPACECRAFT FIXED -43025 + IMAP_THRUSTER_R7 IMAP_SPACECRAFT FIXED -43026 + IMAP_THRUSTER_R8 IMAP_SPACECRAFT FIXED -43027 + IMAP_SUN_SENSOR_PZ IMAP_SPACECRAFT FIXED -43030 + IMAP_SUN_SENSOR_MZ IMAP_SPACECRAFT FIXED -43031 + IMAP_STAR_TRACKER_PX IMAP_SPACECRAFT FIXED -43040 + IMAP_STAR_TRACKER_MX IMAP_SPACECRAFT FIXED -43041 + IMAP_LOW_GAIN_ANTENNA IMAP_SPACECRAFT FIXED -43050 + IMAP_MED_GAIN_ANTENNA IMAP_SPACECRAFT FIXED -43051 + + IMAP-Lo (100-149) + -------------------------- + IMAP_LO_BASE IMAP_SPACECRAFT FIXED -43100 + IMAP_LO IMAP_LO_BASE CK -43101 + IMAP_LO_STAR_SENSOR IMAP_LO FIXED -43102 + + IMAP-Hi (150-199) + -------------------------- + IMAP_HI_45 IMAP_SPACECRAFT FIXED -43150 + IMAP_HI_90 IMAP_SPACECRAFT FIXED -43151 + + IMAP-Ultra (200-249) + -------------------------- + IMAP_ULTRA_45 IMAP_SPACECRAFT FIXED -43200 + IMAP_ULTRA_90 IMAP_SPACECRAFT FIXED -43201 + + MAG (250-299) + -------------------------- + IMAP_MAG_BOOM IMAP_SPACECRAFT FIXED -43250 + IMAP_MAG_BASE IMAP_SPACECRAFT FIXED -43253 + IMAP_MAG_I IMAP_MAG_BASE FIXED -43251 + IMAP_MAG_O IMAP_MAG_BASE FIXED -43252 + + SWE (300-349) + -------------------------- + IMAP_SWE IMAP_SPACECRAFT FIXED -43300 + IMAP_SWE_DETECTOR_P63 IMAP_SWE FIXED -43301 + IMAP_SWE_DETECTOR_P42 IMAP_SWE FIXED -43302 + IMAP_SWE_DETECTOR_P21 IMAP_SWE FIXED -43303 + IMAP_SWE_DETECTOR_000 IMAP_SWE FIXED -43304 + IMAP_SWE_DETECTOR_M21 IMAP_SWE FIXED -43305 + IMAP_SWE_DETECTOR_M42 IMAP_SWE FIXED -43306 + IMAP_SWE_DETECTOR_M63 IMAP_SWE FIXED -43307 + + SWAPI (350-399) + -------------------------- + IMAP_SWAPI IMAP_SPACECRAFT FIXED -43350 + + CODICE (400-499) + -------------------------- + IMAP_CODICE IMAP_SPACECRAFT FIXED -43400 + + HIT (500-699) + -------------------------- + IMAP_HIT IMAP_SPACECRAFT FIXED -43500 + IMAP_HIT_L1_APERTURE_01 IMAP_HIT FIXED -43501 + IMAP_HIT_L1_APERTURE_02 IMAP_HIT FIXED -43502 + IMAP_HIT_L1_APERTURE_03 IMAP_HIT FIXED -43503 + IMAP_HIT_L1_APERTURE_04 IMAP_HIT FIXED -43504 + IMAP_HIT_L1_APERTURE_05 IMAP_HIT FIXED -43505 + IMAP_HIT_L1_APERTURE_06 IMAP_HIT FIXED -43506 + IMAP_HIT_L1_APERTURE_07 IMAP_HIT FIXED -43507 + IMAP_HIT_L1_APERTURE_08 IMAP_HIT FIXED -43508 + IMAP_HIT_L1_APERTURE_09 IMAP_HIT FIXED -43509 + IMAP_HIT_L1_APERTURE_10 IMAP_HIT FIXED -43510 + + IDEX (700-749) + -------------------------- + IMAP_IDEX IMAP_SPACECRAFT FIXED -43700 + IMAP_IDEX_DETECTOR IMAP_IDEX FIXED -43701 + IMAP_IDEX_FULL_SCIENCE IMAP_IDEX FIXED -43702 + + GLOWS (750-799) + -------------------------- + IMAP_GLOWS IMAP_SPACECRAFT FIXED -43750 + + +IMAP Frame Tree +======================================================================== + + The diagram below illustrates the IMAP frame hierarchy: + + J2000 + | + |<---ck + | + IMAP_SPACECRAFT + | + IMAP_THRUSTER_A1 + | + |... + | + IMAP_THRUSTER_A4 + | + IMAP_THRUSTER_R1 + | + |... + | + IMAP_THRUSTER_R8 + | + IMAP_SUN_SENSOR_PZ + | + IMAP_SUN_SENSOR_MZ + | + IMAP_STAR_TRACKER_PX + | + IMAP_STAR_TRACKER_MX + | + IMAP_LOW_GAIN_ANTENNA + | + IMAP_MED_GAIN_ANTENNA + | + IMAP_LO_BASE + | | + | |<---ck + | | + | IMAP_LO + | | + | IMAP_LO_STAR_SENSOR + | + IMAP_HI_45 + | + IMAP_HI_90 + | + IMAP_ULTRA_45 + | + IMAP_ULTRA_90 + | + IMAP_MAG_BOOM + | + IMAP_MAG_BASE + | | + | IMAP_MAG_I + | | + | IMAP_MAG_O + | + IMAP_SWE + | | + | IMAP_SWE_DETECTOR_P63 + | | + | IMAP_SWE_DETECTOR_P42 + | | + | IMAP_SWE_DETECTOR_P21 + | | + | IMAP_SWE_DETECTOR_000 + | | + | IMAP_SWE_DETECTOR_M21 + | | + | IMAP_SWE_DETECTOR_M42 + | | + | IMAP_SWE_DETECTOR_M63 + | + IMAP_SWAPI + | + IMAP_CODICE + | + IMAP_HIT + | | + | IMAP_HIT_L1_APERTURE_01 + | | + | |... + | | + | IMAP_HIT_L1_APERTURE_10 + | + IMAP_IDEX + | | + | IMAP_IDEX_DETECTOR + | | + | IMAP_IDEX_FULL_SCIENCE + | + IMAP_GLOWS + +IMAP Spacecraft Frame +======================================================================== + + \begindata + + FRAME_IMAP_SPACECRAFT = -43000 + FRAME_-43000_NAME = 'IMAP_SPACECRAFT' + FRAME_-43000_CLASS = 3 + FRAME_-43000_CLASS_ID = -43000 + FRAME_-43000_CENTER = -43 + CK_-43000_SCLK = -43 + CK_-43000_SPK = -43 + + \begintext + + + The orientation of the spacecraft body frame with respect to an + inertial frame, J2000 for IMAP, is provided by a C-kernel (see [3] + for details). + + The spacecraft coordinate frames are defined by the IMAP control + documents (see [4,5], NB, figure 2.2). There are two frames described + there: Observatory Mechanical Design Reference Frame (most relevant) + and Observatory Pointing and Dynamics Reference Frame (less relevant + for this frame kernel). + + + Observatory Mechanical Design Reference Frame (IMAP_SPACECRAFT) + --------------------------------------------------------------------- + + If not explicitly stated, references to 'spacecraft mechanical frame' + 'spacecraft frame', or 'S/C frame' will refer to this frame. + + All instruments and component placements and orientations are defined + using this coordinate frame reference. + + Origin: Center of the launch vehicle adapter ring at the + observatory/launch vehicle interface plane + + +Z axis: Perpendicular to the launch vehicle interface plane pointed + in the direction of the top deck (runs through the center + of the central cylinder structure element) + + +Y axis: Direction of the vector orthogonal to the +Z axis and + parallel to the deployed MAG boom + + +X axis: The third orthogonal axis defined using an X, Y, Z ordered + right hand rule + + NB: The Observatory Pointing and Dynamics Reference Frame is also + defined in [5]. It is identical to the observatory mechanical design + reference frame, but with the origin translated to the observatory + center of mass (which changes with boom deployment and fuel usage). + The offset difference between the mechanical and dynamic frame is + within the uncertainty range of the ephemeris, so the mechanical + design frame is used here for definiteness. + + Three different views [5,6] of the spacecraft with labeled components + are presented below for illustrative purposes. + + + IMAP -Z Bottom View (Figure 3-2 in [5], G-G in [6] rotated 180 deg) + --------------------------------------------------------------------- + ------------- + | S/C +X axis | ----------------------- + ------------- | S/C +Z axis into page | + . | (facing Sun) | + /|\ ----------------------- + | + | + | + _ + HI 45 /`~~__HI 90 `+ direction of + , = .^ - /_ ``-. '. positive + .+ + `^~/ ./ ~ rotation + ^ + + . -- ' `` \ _-~ \ + _ / ',= ' \~'` \ IMAP \ + ULTRA /' '-_ .~ ' \,.=.. \ LO \|/ + 90 / ~ _,.,_ + + \ ' + / ,~' +' `'+ + + \ + / ~^ .' , = .'. '- ='' -`` ------------- + ^/ / , = . + + \ \~'` | S/C +Y axis |-----> + | . + + + + . \ ------------- ___ + | | + + ' = ' | \--------------------| | + SWAPI| | ' = ', - . | /--------------------|___| + _+_: ' + + ' / MAG boom + \_ __\__ \ + + / /^*~, + + | SWE '. ' = ' .' ULTRA / + `~-' '~..,___,..~' 45 /~,* + _\ / /~,*` + * / CODICE ^*._/ *` HIT + *\ _/`. / + * / /~ _ _ ,.-^-., _ _ _ / + '=' + + + GLOWS + + + '-.,.-' + IDEX + + + IMAP +X Side View (F-F in [6]) + --------------------------------------------------------------------- + ------------- + | S/C +Z axis | + ------------- ------------------------- + . | S/C +X axis out of page | + /|\ ------------------------- + | LGA + __________________|______|^|_________ ___ + SWAPI|__________________|__________________|====================| | + #|-| | | .-==-, | / MAG boom '---' + #|-| {|## | | / \ | | + | {|## | |{ HI 90 }| IMAP LO| + | {|## | _.._ | \ / | _., | + | ULTRA | / \ | `-==-' | / __`',| + | 90 | \ HI 45/ | | \ \_\ ;| + | | '----` | | ~._ + | + '-------------------|----------/--------' + | | \_________O_________/ | | ----------------> + |__| ----------- /_\ ------------- + STAR | S/C FRAME | MGA | S/C +Y axis | + TRACKERS | ORIGIN | ------------- + ----------- + + + IMAP -X Side View (C-C in [6]) + --------------------------------------------------------------------- + ------------- + | S/C +Z axis | + ----------------------- ------------- + | S/C +X axis into page | . + ----------------------- /|\ + LGA | + ___ _________|^|______|__________________ + | |====================|__________________|_____________ __ _|SWAPI + '---' MAG boom \ __ | | | // \ /--|# + |( )=|__|| | | \\__/ \--|# + | HIT | _|_ IDEX | CODICE | + | | ,.' | '., | | + | ____ | [ \ | / ] | SWE| + ULTRA ##',', |,.'|'.,| GLOWS (#)| + 45 ####'. + | + \\(O) |-|| + '----####/----- + | + --------------' + <---------------- | | \______'-.O.-'______/ | | + ------------- /_\ ----------- |__| + | S/C +Y axis | MGA | S/C FRAME | STAR + ------------- | ORIGIN | TRACKERS + ----------- + + + IMAP Component Location - Nominal Azimuth and Elevation + --------------------------------------------------------------------- + + Payload and subsystem component locations are specified [5,6] in the + Observatory Mechanical Design Reference Frame (described above). + Locations are defined in azimuth and elevation (and resultant + direction cosine matrices) of these angles [6] in the same reference + frame. The azimuth and elevation angle diagram is provided below. + + In general, descriptions in this kernel treat the +Z direction as + "up" and the -Z direction as "down." Locations referred to as "above" + are generally closer to the Sun, and vice versa for "below." The + "upper" side of the spacecraft is the plane of the solar panels, + while the "lower" side may refer to the area near the adapter ring. + If ambiguity could arise, more thorough descriptions will be used. + + + Toward Sun + + S/C +Z axis + . + | + . + | + . Component + | Location/ + . Orientation + | @ + Toward . .'| + MAG | +` | + .~ '` Boom S/C . .` \ | + .~ '` FRAME |.` : | + / ~'` ORIGIN O | | + *--- .~ '` \ Elevation + .~ '` \ | | + .~ '` \ ; |~ + .~ '\ \ / | ^~ + S/C +Y axis \ \ + | ^~ + '. '~, \ | ^~ + '~ Azimuth \ | ^~ + '~. `^~-> \| S/C -X axis + ' ~ ., _ _ ,.~ + ``'`` + + + IMAP Component Orientation - Azimuth and Elevation + --------------------------------------------------------------------- + + In addition to the rotation matrices, azimuth and elevation are used + to specify look direction (i.e., boresight) of the science payload + components and thrusters. However, these two angles are not adequate + to specify the complete orientation of the components--a secondary + axis must be specified to complete the rotation. + + The look direction, D, in the frame of the spacecraft for azimuth, az + and elevation, el, is: + + D = [ -cos(el) x sin(az), cos(el) x cos(az), sin(el) ] + + For all practical purposes, the look direction (primary axis) + corresponds to one of the six axis-aligned directions of the local + coordinate system of the instrument: X', Y', Z', -X', -Y', -Z'. While + the azimuth/elevation of the instrument look direction is provided in + the spacecraft MICD[4], the local coordinate axis in which it + corresponds is provided in the instrument's MICD. + + The secondary axis, S, must be perpendicular to D for the following + discussion. It will generally be specified in one of two ways: + + 1) S is one of the six axis-aligned directions of the + spacecraft coordinate system: X, Y, Z, -X, -Y, -Z + + 2) S lies in the plane perpendicular to one of the axes of the + spacecraft coordinate system: X, Y, Z, -X, -Y, -Z + + Similar to the look direction, this direction will then be assigned + to correspond to one of the six instrument directions X', Y', Z', + -X', -Y', -Z'. + + For definiteness, it is assumed that the third axes, N = D x S, + completes the righthanded coordinate system. + + The rotation matrix specifying the component frame, X'Y'Z', in the + spacecraft frame, XYZ, is: + + Ux Uy Uz + + [ X ] [ R11 R12 R13 ] [ X'] + [ ] [ ] [ ] + [ Y ] = [ R21 R22 R23 ] [ Y'] + [ ] [ ] [ ] + [ Z ] [ R31 R32 R33 ] [ Z'] + + with Ux, Uy, Uz specifying the unit column vectors of the rotation. + Because the primary and secondary axes, D and S, lie along the local + axes of the instrument coordinate system (X'Y'Z'), they are simply + the column vectors of the rotation matrix (assuming properly unit). + + The instrument teams have defined the primary and secondary axes of + the instrument-specific coordinate frames in [10]. Those definitions + are described in the instrument-specific sections that follow. When + a coordinate system has not been defined by the team, one is chosen + in a convenient manner. + + IMAP Component Orientation - Euler Angles + --------------------------------------------------------------------- + + When the orientation is not specified in azimuth/elevation, or the + secondary is not well-defined, we try to deduce the most straight- + forward definition using a simple secondary axis. Sometimes a + single axis-aligned rotation applied BEFORE the general rotation + allows a simple secondary axis to notionally be used to accurately + define the coordinates; see Hi 45 or Hi 90 for this case. + + It is also possible to deduce the Euler angles to produce more + precise rotation matrices. For most components, before final + alignments are calculated, these angles are in whole degrees. + (However, see Hi 45 for a counterexample). + + The spacecraft subsystems such as the star trackers have complete + rotation matrices that fully define the orientation of each + component. These matrices, while complete, are not conducive to + visualizing the orientation of a component on the spacecraft bus. + + As it happens, when applied to rotations, the azimuth and elevation + are nearly identitical to the first two Euler angles of the ZXZ + intrinsic rotation. For the Euler angles (A, B, Y), this is defined + as follows[11]. + + Let xyz represent the coordinate axes of the fixed frame, and XYZ + are the axes of the fully rotated frame expressed in the xyz frame. + Three successive, ordered rotations about the axes are performed: + + 1) Righthanded rotation about z by the angle A ∈ [-Ο€, Ο€); the rotated + frame is defined x'y'z', with z' = z. The new frame x'y'z' is + expressed in the coordinates of the original frame xyz. + + 2) Righthanded rotation about x' by the angle B ∈ [0,Ο€]; the rotated + frame is defined x"y"z", with x" = x'. The new frame x"y"z" is + expressed in the coordinates of the original frame xyz. + + 3) Righthanded rotation about z" by the angle Y ∈ [-Ο€,Ο€); the rotated + frame is defined XYZ, with Z = z". The final frame XYZ is + expressed in the coordinates of the original frame xyz. + + + Euler Angles + Intrinsic ZXZ Rotation + + z axis + . + | Y axis + _._. / + , B ` | / + Z axis ,-` . / + ^, ^ | / + ^, . / + ^, | / + ^, . / + ^, | / _ X axis + ^, . / _ ~ ^ + ^, |/ _ ~ ^ ^ + .~ ~ ^ | + .~ '` \ ^~ ; + .~ '` \ \ ^~ ; + .~ '` ', \ ^~ , + .~ '` ` A \ ^ Y + x axis `^~-> \ , ~ + \ ~` ^~ + \- ^ ^~ + \ y axis + \ + x'=x" axis + + + Comparing the two figures, we see that A = azimuth and B appears to + coincide with elevation. However, while B lies on the range [0,Ο€], + conventionally, elevation ∈ [-Ο€/2,Ο€/2]. This range for elevation does + not capture all possible orientations, e.g., a playing card facing + upward cannot be placed facing downward with elevation ∈ [-Ο€/2,Ο€/2]. + + So, we need to supplement the azimuth and elevation nomenclature with + fully specified Euler angles. + + The technical documents [4,5,6] give rotation matrix elements to six + decimal places, which is not sufficient for accurate pointing in the + SPICE toolkit. The remedy to this inaccuracy is provided below. + + Given an insufficiently-accurate rotation matrix, M, with column + vectors Vx, Vy, Vz: + + Vx Vy Vz + + [ M11 M12 M13 ] + [ ] + M = [ M21 M22 M23 ] + [ ] + [ M31 M32 M33 ] + + A rotation matrix, R, with column unit vectors Ux, Uy, Uz: + + Ux Uy Uz + + [ R11 R12 R13 ] + [ ] + R = [ R21 R22 R23 ] + [ ] + [ R31 R32 R33 ] + + is calculated so that column vectors are orthonormal to within double + precision accuracy (an operation SPICE calls "sharpening"): + + Uz = Vz / |Vz| + + Uy = Uz x (Vx / |Vx|) + + Ux = Uy x Uz + + These calculations are done outside of the SPICE library, but using + numerically stable algorithms as SPICE does. Sharpening by starting + with the X or Y direction, as opposed to Z, can be accomplished by + cyclically permuting x,y,z above. SPICE, for example, starts with X. + + With a precise (though not necessarily accurate) rotation matrix, + the instrinsic ZXZ Euler angles (A, B, Y) are calculated: + + A' = atan2(R13, -R23) + ______________ + B' = atan2(\/ 1 - R33 x R33 , R33) + + Y' = atan2(R31, R32) + + These values are rounded to regain the assumed original orientation: + + A = round(A') to nearest 1/1000th degree + + B = round(B') to nearest 1/1000th degree + + Y = round(Y') to nearest 1/1000th degree + + And finally, the rotation matrix elements are recalculated: + + R11 = c1 x c3 - s1 x c2 x s3 + + R21 = s1 x c3 + c1 x c2 x s3 + + R31 = s2 x s3 + + R12 = -c1 x s3 - s1 x c2 x c3 + + R22 = -s1 x s3 + c1 x c2 x c3 + + R32 = s2 x c3 + + R13 = s1 x s2 + + R23 = -c1 x s2 + + R33 = c2 + + where: + + c1 = cos(A) + + s1 = sin(A) + + c2 = cos(B) + + s2 = sin(B) + + c3 = cos(Y) + + s3 = sin(Y) + + When B = 0, the angles A and Y are degenerate; Y = 0 in this case. + + In the subsequent frames defined below, when Euler angles (A, B, Y) + are referenced without further discussion, they will refer to the + Euler angles as defined here. Otherwise, definitions will be given + inline with the discussion. + + + When Look Direction is Well-Defined + --------------------------------------------------------------------- + + When the look direction is well-defined, but the secondary axis is + not, we replace the column of the imprecise rotation matrix with + the exact look direction, and proceed with the calculations above. + + +IMAP Thruster Frames +======================================================================== + + There are four axial (A) thrusters and eight radial (R) thrusters on + IMAP[6]. The table below shows the thruster positions defined in the + spacecraft frame[6], at the intersection of the thrust axis and the + nozzle exit plane. The unit direction vectors listed in the table + below point in the direction of the thruster exhaust. The positional + information may be captured in the IMAP structure SPK, while the + orientation information is captured here. + + + Thruster ID X (mm) Y (mm) Z (mm) UnitDir (X,Y,Z) + ---------------- ------ -------- -------- ------- --------------- + IMAP_THRUSTER_A1 -43010 1007.28 516.50 1312.40 ( 0, 0, 1 ) + IMAP_THRUSTER_A2 -43011 -1007.28 -516.50 1312.40 ( 0, 0, 1 ) + IMAP_THRUSTER_A3 -43012 -1007.28 -516.50 101.77 ( 0, 0, -1 ) + IMAP_THRUSTER_A4 -43013 1007.28 516.50 101.77 ( 0, 0, -1 ) + IMAP_THRUSTER_R1 -43020 -126.90 1237.78 841.12 (-0.5, 0.866,0) + IMAP_THRUSTER_R2 -43021 126.90 -1237.78 841.12 ( 0.5,-0.866,0) + IMAP_THRUSTER_R3 -43022 -1008.49 728.79 841.12 (-0.5, 0.866,0) + IMAP_THRUSTER_R4 -43023 1008.49 -728.79 841.12 ( 0.5,-0.866,0) + IMAP_THRUSTER_R5 -43024 -126.90 1237.78 447.42 (-0.5, 0.866,0) + IMAP_THRUSTER_R6 -43025 126.90 -1237.78 447.42 ( 0.5,-0.866,0) + IMAP_THRUSTER_R7 -43026 -1008.49 728.79 447.42 (-0.5, 0.866,0) + IMAP_THRUSTER_R8 -43027 1008.49 -728.79 447.42 ( 0.5,-0.866,0) + + + Thruster Locations and Directions + --------------------------------------------------------------------- + + The four axial thrusters[6] are directed along the spacecraft Z axis, + with A1,A2 located on the +Z side of the spacecraft and A3,A4 located + on the -Z side. A1,A2 fire in the +Z direction, while A3,A4 fire in + the -Z direction. A1 and A4 are aligned in the Z direction, while + A2 and A3 are aligned but on the opposite side of the S/C as A1/A4. + + The eight radial thrusters[6] are grouped into four pairs (R1/R5, + R2/R6, R3/R7, R4/R8); each pair is aligned along the Z direction and + fire in the same direction. There are two distinct firing directions, + all perpendicular to the spacecraft Z axis: R1/R5 & R3/R7 fire toward + the +Y direction (with a slight -X component), while R2/R6 & R4/R8 + fire in the -Y direction (with a slight +X component). Thrusters + R1-R4 are located above the center of mass (towards the Sun), while + thrusters R5-R8 are located below the center of mass (away from the + Sun). The table below shows the azimuth of location and direction of + radial thrusters calculated from using thruster table above. + + + Location Azim Direction Azim + ------------------- ------------------ + R1/R5 5.85 deg 30.0 deg + R2/R6 180 deg + 5.85 deg 180 deg + 30.0 deg + R3/R7 54.15 deg 30.0 deg + R4/R8 180 deg + 54.15 deg 180 deg + 30.0 deg + + + S/C +X axis S/C +Z axis into page + . (facing Sun) + /|\ + | + | + | A1 (on +Z side) + A4 (on -Z side) + R4/R8 Dir /`~~__ / + '~._ , = .^ - /_ ``-. / + /~._ .+ + `^~/ .\/ + 30 | '~. + . -- ' `` @\ _-~ + - - + - - - -# R4/R8 \~'` \ + /' '-_ . \,.=.. \ + / ~ _,.,_ + + \ + R2/R6 Dir / ,~' +' `'+ + + \ + '~._ / ~^ .' , = .'. '- ='' -`` + /~._ ^/ / , = . + + \ \~'` + 30 | '~. | . + + + + . \ S/C +Y axis -----> + - - + - - - -|# R2/R6 | + + ' = ' | \ + | | ' = ', - . | R1/R5 #._- - - - - + - - + _+_: ' + + ' / '~._ | + \_ __\__ \ + + / /^*~, '~._ / 30 deg + + | \ '. ' = ' .' / / '~. + `~-' '~..,___,..~' / /~,* R1/R5 Dir + _\ / /~,*` + * / \ ^*._/ *` + *\ _/`. R3/R7 #/._- - - - - + - - + * / /\@_ _ ,.-^-., _ _ _ / '~._ | + '=' | + + '~._ / 30 deg + | + + '~. + | '-.,.-' R3/R7 Dir + | + A2 (on +Z side) + A3 (on -Z side) + + + Axial Thruster Frames + --------------------------------------------------------------------- + + Each axial thruster has a frame defined so that the thruster exhaust + exits in the +Z' direction. The +Y' axis is chosen to lie in the + direction of the MAG boom. X' = Y' x Z' completes the frame. + + [X] [ 1 0 0 ] [X'] + [Y] = [ 0 1 0 ] [Y'] + [Z]S/C [ 0 0 1 ] [Z']Axial Thrusters A1,A2 + + [X] [ -1 0 0 ] [X'] + [Y] = [ 0 1 0 ] [Y'] + [Z]S/C [ 0 0 -1 ] [Z']Axial Thrusters A3,A4 + + + Axial Thruster + Exhaust Direction + + S/C +Z' axis + | + | + _. -|- ._ + ,' | ', + , | , + | -.,_|_,.- | + ' ' + ' ' + ; ; + ; ; + : ; + , , Toward + ',_,' ^~ MAG + .~ '` ^~ ^~ Boom + .~ '` ^~ ^~ + .~ '` ^~ ^~ + .~ '` ^~ ^~ \ + S/C +X' axis ^~ --* + ^~ + ^~ + S/C +Y' axis + + + \begindata + + FRAME_IMAP_THRUSTER_A1 = -43010 + FRAME_-43010_NAME = 'IMAP_THRUSTER_A1' + FRAME_-43010_CLASS = 4 + FRAME_-43010_CLASS_ID = -43010 + FRAME_-43010_CENTER = -43 + TKFRAME_-43010_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43010_SPEC = 'MATRIX' + TKFRAME_-43010_MATRIX = ( 1, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 1 ) + + FRAME_IMAP_THRUSTER_A2 = -43011 + FRAME_-43011_NAME = 'IMAP_THRUSTER_A2' + FRAME_-43011_CLASS = 4 + FRAME_-43011_CLASS_ID = -43011 + FRAME_-43011_CENTER = -43 + TKFRAME_-43011_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43011_SPEC = 'MATRIX' + TKFRAME_-43011_MATRIX = ( 1, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 1 ) + + FRAME_IMAP_THRUSTER_A3 = -43012 + FRAME_-43012_NAME = 'IMAP_THRUSTER_A3' + FRAME_-43012_CLASS = 4 + FRAME_-43012_CLASS_ID = -43012 + FRAME_-43012_CENTER = -43 + TKFRAME_-43012_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43012_SPEC = 'MATRIX' + TKFRAME_-43012_MATRIX = ( -1, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + -1 ) + + FRAME_IMAP_THRUSTER_A4 = -43013 + FRAME_-43013_NAME = 'IMAP_THRUSTER_A4' + FRAME_-43013_CLASS = 4 + FRAME_-43013_CLASS_ID = -43013 + FRAME_-43013_CENTER = -43 + TKFRAME_-43013_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43013_SPEC = 'MATRIX' + TKFRAME_-43013_MATRIX = ( -1, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + -1 ) + + \begintext + + + Radial Thrusters + --------------------------------------------------------------------- + + Each radial thruster has a frame defined so that the thruster exhaust + exits in the +Y' direction. The +Z' axis is chosen to lie along the + spacecraft +Z axis (toward Sun). X' = Y' x Z' completes the frame. + + [X] [ cos( 30) -sin( 30) 0 ] [X'] + [Y] = [ sin( 30) cos( 30) 0 ] [Y'] + [Z]S/C [ 0 0 1 ] [Z']Rad. Thrusters R1,R3,R5,R7 + + [X] [ cos(210) -sin(210) 0 ] [X'] + [Y] = [ sin(210) cos(210) 0 ] [Y'] + [Z]S/C [ 0 0 1 ] [Z']Rad. Thrusters R2,R4,R6,R8 + + + Toward Sun + + S/C +Z' axis + . + | + . + | + . + | + . + Radial Thruster | + Exhaust Direction . + | + .~ '` . + /.~ '` _,,~ ~ ~ ~ ~ ~ ~ ~ | + *-- .;-. \ ~ + ,' '. ~ ^~ + ; \ ~' ^~ + | .~ '`: ~' ^~ + .~ '` | ~' ^~ + ~ '` \ ; _ ~' ^~ + S/C +Y' axis '.,_._;-' ^~ + ^~ + S/C -X' axis + + + \begindata + + FRAME_IMAP_THRUSTER_R1 = -43020 + FRAME_-43020_NAME = 'IMAP_THRUSTER_R1' + FRAME_-43020_CLASS = 4 + FRAME_-43020_CLASS_ID = -43020 + FRAME_-43020_CENTER = -43 + TKFRAME_-43020_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43020_SPEC = 'MATRIX' + TKFRAME_-43020_MATRIX = ( 0.86602540378443865, + 0.50000000000000000, + 0.00000000000000000, + -0.50000000000000000, + 0.86602540378443865, + 0.00000000000000000, + 0.00000000000000000, + 0.00000000000000000, + 1.00000000000000000 ) + + FRAME_IMAP_THRUSTER_R2 = -43021 + FRAME_-43021_NAME = 'IMAP_THRUSTER_R1' + FRAME_-43021_CLASS = 4 + FRAME_-43021_CLASS_ID = -43021 + FRAME_-43021_CENTER = -43 + TKFRAME_-43021_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43021_SPEC = 'MATRIX' + TKFRAME_-43021_MATRIX = ( -0.86602540378443865, + -0.50000000000000000, + 0.00000000000000000, + 0.50000000000000000, + -0.86602540378443865, + 0.00000000000000000, + 0.00000000000000000, + 0.00000000000000000, + 1.00000000000000000 ) + + FRAME_IMAP_THRUSTER_R3 = -43022 + FRAME_-43022_NAME = 'IMAP_THRUSTER_R3' + FRAME_-43022_CLASS = 4 + FRAME_-43022_CLASS_ID = -43022 + FRAME_-43022_CENTER = -43 + TKFRAME_-43022_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43022_SPEC = 'MATRIX' + TKFRAME_-43022_MATRIX = ( 0.86602540378443865, + 0.50000000000000000, + 0.00000000000000000, + -0.50000000000000000, + 0.86602540378443865, + 0.00000000000000000, + 0.00000000000000000, + 0.00000000000000000, + 1.00000000000000000 ) + + FRAME_IMAP_THRUSTER_R4 = -43023 + FRAME_-43023_NAME = 'IMAP_THRUSTER_R4' + FRAME_-43023_CLASS = 4 + FRAME_-43023_CLASS_ID = -43023 + FRAME_-43023_CENTER = -43 + TKFRAME_-43023_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43023_SPEC = 'MATRIX' + TKFRAME_-43023_MATRIX = ( -0.86602540378443865, + -0.50000000000000000, + 0.00000000000000000, + 0.50000000000000000, + -0.86602540378443865, + 0.00000000000000000, + 0.00000000000000000, + 0.00000000000000000, + 1.00000000000000000 ) + + FRAME_IMAP_THRUSTER_R5 = -43024 + FRAME_-43024_NAME = 'IMAP_THRUSTER_R5' + FRAME_-43024_CLASS = 4 + FRAME_-43024_CLASS_ID = -43024 + FRAME_-43024_CENTER = -43 + TKFRAME_-43024_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43024_SPEC = 'MATRIX' + TKFRAME_-43024_MATRIX = ( 0.86602540378443865, + 0.50000000000000000, + 0.00000000000000000, + -0.50000000000000000, + 0.86602540378443865, + 0.00000000000000000, + 0.00000000000000000, + 0.00000000000000000, + 1.00000000000000000 ) + + FRAME_IMAP_THRUSTER_R6 = -43025 + FRAME_-43025_NAME = 'IMAP_THRUSTER_R6' + FRAME_-43025_CLASS = 4 + FRAME_-43025_CLASS_ID = -43025 + FRAME_-43025_CENTER = -43 + TKFRAME_-43025_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43025_SPEC = 'MATRIX' + TKFRAME_-43025_MATRIX = ( -0.86602540378443865, + -0.50000000000000000, + 0.00000000000000000, + 0.50000000000000000, + -0.86602540378443865, + 0.00000000000000000, + 0.00000000000000000, + 0.00000000000000000, + 1.00000000000000000 ) + + FRAME_IMAP_THRUSTER_R7 = -43026 + FRAME_-43026_NAME = 'IMAP_THRUSTER_R7' + FRAME_-43026_CLASS = 4 + FRAME_-43026_CLASS_ID = -43026 + FRAME_-43026_CENTER = -43 + TKFRAME_-43026_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43026_SPEC = 'MATRIX' + TKFRAME_-43026_MATRIX = ( 0.86602540378443865, + 0.50000000000000000, + 0.00000000000000000, + -0.50000000000000000, + 0.86602540378443865, + 0.00000000000000000, + 0.00000000000000000, + 0.00000000000000000, + 1.00000000000000000 ) + + FRAME_IMAP_THRUSTER_R8 = -43027 + FRAME_-43027_NAME = 'IMAP_THRUSTER_R6' + FRAME_-43027_CLASS = 4 + FRAME_-43027_CLASS_ID = -43027 + FRAME_-43027_CENTER = -43 + TKFRAME_-43027_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43027_SPEC = 'MATRIX' + TKFRAME_-43027_MATRIX = ( -0.86602540378443865, + -0.50000000000000000, + 0.00000000000000000, + 0.50000000000000000, + -0.86602540378443865, + 0.00000000000000000, + 0.00000000000000000, + 0.00000000000000000, + 1.00000000000000000 ) + + \begintext + + +IMAP Digital Sun Sensor and Star Tracker Frames +======================================================================== + + There are two digital sun sensors (DSS)[6]: one on the +Z side of the + spacecraft pointing in +Z direction, and one on the -Z side pointing + mostly in the radial direction with a 30 deg tilt in the -Z direction. + They are approximated aligned along the spacecraft Z axis, though the + origins are offset from absolute alignment by a few centimeters (see + table below). Azimuthally, the sun sensors are located near the SWAPI + instrument approximately 18 deg off of the Y-Z plane. + + There are two star trackers mounted adjacent to each other on the + underside of the spacecraft close to the -Z digital star sensor[6]. + Their boresights are generally downward (towards -Z), with an angular + separation of 24 deg. One is angled toward the +X direction, the other + angled towards the -X direction. + + Positional information may be captured in the IMAP structure SPK, + while the orientation information is captured here. + + + Digital Sun Sensor ID X (mm) Y (mm) Z (mm) Loc. Azim + -------------------- ------ -------- -------- -------- --------- + IMAP_SUN_SENSOR_PZ -43030 -364.22 -1121.90 1301.67 162.014 deg + IMAP_SUN_SENSOR_MZ -43031 -379.11 -1167.77 72.89 162.014 deg + + + Digital Star Tracker ID X (mm) Y (mm) Z (mm) Loc. Azim + -------------------- ------ -------- -------- -------- --------- + IMAP_STAR_TRACKER_PX -43040 -45.75 -906.66 159.88 177.111 deg + IMAP_STAR_TRACKER_MX -43041 -188.05 -881.57 142.79 167.959 deg + + + ##################################################################### + # / _- __.----# + # ,' ~` _.~^' # + # / ~` ,~^ S/C # + # ,' S/C +Z axis into page .` .^ +X axis # + # / (facing Sun) / .^ . # + # | : /_,-----,_ /|\# + # | ~ ~` ^. | # + # | ^ ^ ^_ | # + # | / / , | # + # | , , ; | # + # | ; ; } | # + # S/C | ___ : : ~ ___# + # -Y axis ___| .` `. | | }/ _# + # <------ |===| ;+X Star; | |. ;/ (` # + # | ;Tracker; | |' ; \ (,_# + # | `, ,` | | ', , \___# + # | '---' : : '-.,_____,.-` _,~# + # | _,;@ ; ; ," # + # /| | @*^^'` : : ; # + # /^' { _,;| ,---, ; ; ^ # + # \ *^^'` | .^ ^. ~ ~ { # + # | SWAPI { _, |-X Star| \ \ | # + # \ _,;*^ \ .Tracker. \ * { # + # | *^^'` \ -Z DSS ^.___.^ ^, `~_ \ # + # \ } \ _} ^_ "~_ ^, # + # ^^'"\\ \*^ ^, '-_ ~_ # + # \ (+Z DSS not visible) "~_ " -, '- # + ##################################################################### + + + Digital Sun Sensors (DSS) + --------------------------------------------------------------------- + + Each DSS has a frame defined so that the look-direction is along the + +Z' axis. The digital image rows and columns are aligned with the X' + and Y' axes of the frame. + + + DSS Look Direction + Local Frame + + +Z' axis + | + | + | + | + | + | + .~|'`^~ + .~ '` | ^~ + .~ '` __,=# | ,_ ^~ + .~ '` __,=#^^^ |@ ^%,_ ^~ + ~ ,=#^^^ | ^%,_ ^~ + | ^~ ,.~^~ ^%,_ ^~ + | ^~ ,.~ '` ^~ ^% ,^ + | ,.^~' @ ^~ .~ '` | + ^~.''` ^~ @^~ '` | + .~ '`` ^~ ^~ .~ '` ^~ | + +X' axis ^~ ^~.~ '` ^~.~ '` + ^~ | .~ '` ^~ + ^~ | .~ '` ^~ + ^~ |.~ '` +Y' axis + + + The rotation matrices orienting each DSS on the spacecraft are + given by [6]: + + [X] [ 0.951057 0.309017 0.000000 ] [X'] + [Y] = [ -0.309017 0.951057 0.000000 ] [Y'] + [Z]S/C [ 0.000000 0.000000 1.000000 ] [Z'] +Z DSS + + [X] [ 0.951078 -0.154380 -0.267616 ] [X'] + [Y] = [ -0.308952 -0.475579 -0.823640 ] [Y'] + [Z]S/C [ -0.000116 0.866025 -0.500000 ] [Z'] -Z DSS + + Using the method described in a previous section, the Euler angles + rounded to 1/1000th of a degree are: + + +Z DSS: (A, B, Y) = ( -18.000, 0.000, 0.000 ) + + -Z DSS: (A, B, Y) = ( -18.000, 120.000, -0.008 ) + + Using the formulas described in the Euler angles section above, the + rotation matrices have been recalculated to double precision. + + + \begindata + + FRAME_IMAP_SUN_SENSOR_PZ = -43030 + FRAME_-43030_NAME = 'IMAP_SUN_SENSOR_PZ' + FRAME_-43030_CLASS = 4 + FRAME_-43030_CLASS_ID = -43030 + FRAME_-43030_CENTER = -43 + TKFRAME_-43030_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43030_SPEC = 'MATRIX' + TKFRAME_-43030_MATRIX = ( 0.95105651629515350, + -0.30901699437494734, + 0.00000000000000000, + 0.30901699437494734, + 0.95105651629515350, + 0.00000000000000000, + -0.00000000000000000, + -0.00000000000000000, + 1.00000000000000000 ) + + FRAME_IMAP_SUN_SENSOR_MZ = -43031 + FRAME_-43031_NAME = 'IMAP_SUN_SENSOR_MZ' + FRAME_-43031_CLASS = 4 + FRAME_-43031_CLASS_ID = -43031 + FRAME_-43031_CENTER = -43 + TKFRAME_-43031_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43031_SPEC = 'MATRIX' + TKFRAME_-43031_MATRIX = ( 0.95107808048040110, + -0.30895059509261280, + -0.00012091995722272, + -0.15437570314113858, + -0.47557140042407403, + 0.86602539534263330, + -0.26761656732981740, + -0.82363910354633210, + -0.49999999999999983 ) + + \begintext + + + Star Trackers + --------------------------------------------------------------------- + + Each star tracker has a frame defined so that the look-direction is + along the +Z' axis. The digital image rows and columns are aligned + with the X' and Y' axes of the frame. + + + Star Tracker Look Direction + Local Frame + + +Z' axis + + | + | + | + | + _. -|- ._ + ,' | ', + | .~ '` ^~ ,| + .~ '` ~ .,_ _,.^~' | + .~ '` | ^~ + .~ '` |, ,| ^~ + +X' axis ' -.,_ _,.- ' ^~ + | | ^~ + | | ^~ + | | +Y' axis + '-.,_ _,.-' + + + + When oriented on the spacecraft: + + - The tracker X' axis mostly points towards the spacecraft -X axis + - The tracker Y' axis mostly points towards the spacecraft +Y axis + - The tracker Z' axis mostly points towards the spacecraft -Z axis + + + ##################################################################### + # { { # + # ) ) # + # @ @ # + # { { # + # _,~--~,_ | | # + # ," ", ,-----,' # + # ; ; | | # + # +X Star / \ | | # + # Tracker { __,.- +Y' '-----' # + # | ..-^" |: | | # + # { ; ;} | | # + # {\ ; / } { { # + # {^, : ,^ ; @ @ # + # . ~_ ; _~ ,` | | # + # `, '~--~" ,^ "' | | # + # '"^--,__ ` ' "^ { { # + # `^ +X' `"` ) ) # + # "' ^' | | # + # ^' '~ { { # + # ^, __,,.~*^# ) ) # + # ', _,.~-'^'`__,,.~*^# | | # + # #-*~^'_,.~-'^'` '" { { # + # #-*~^' "^ @ @ # + # '" `"` | | # + # `^ ^` { { # + # "` _,~^^^~-.,'^ ) )# + # ^' _-" _,~--~,_ ".' ( # + # '^/ ," ", \` \ # + # , ; ;', \ # + # |/ \| # + # { __,.- +Y' Spacecraft Axes # + # -X Star | ..-^" | # + # Tracker { ; } +X # + # \ ; / ^ # + # ^, : ,^ | # + # ~_ ; _~ | # + # '~--~" | # + # ` x-------> +Y # + # +X' +Z into # + # Page # + ##################################################################### + + + The rotation matrices orienting each star tracker on the spacecraft + are given by [6]: + + [X] [ -0.963287 0.173648 0.204753 ] [X'] + [Y] = [ 0.169854 0.984808 -0.036104 ] [Y'] + [Z]S/C [ -0.207912 0.000000 -0.978148 ] [Z']+X Star Tracker + + + [X] [ -0.963287 0.173648 -0.204753 ] [X'] + [Y] = [ 0.169854 0.984808 0.036104 ] [Y'] + [Z]S/C [ 0.207912 0.000000 -0.978148 ] [Z']-X Star Tracker + + Using the method described in a previous section, the Euler angles + rounded to 1/1000th of a degree are: + + +X Star Tracker: (A, B, Y) = ( 80.000, 168.000, -90.000 ) + + -X Star Tracker: (A, B, Y) = ( -100.000, 168.000, 90.000 ) + + Use the formulas described in the Euler angles section above, the + rotation matrices have been recalculated to double precision. + + + \begindata + + FRAME_IMAP_STAR_TRACKER_PX = -43040 + FRAME_-43040_NAME = 'IMAP_STAR_TRACKER_PX' + FRAME_-43040_CLASS = 4 + FRAME_-43040_CLASS_ID = -43040 + FRAME_-43040_CENTER = -43 + TKFRAME_-43040_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43040_SPEC = 'MATRIX' + TKFRAME_-43040_MATRIX = ( -0.96328734079294150, + 0.16985354835670569, + -0.20791169081775915, + 0.17364817766693050, + 0.98480775301220800, + 0.00000000000000001, + 0.20475304505920630, + -0.03610348622615415, + -0.97814760073380570 ) + + FRAME_IMAP_STAR_TRACKER_MX = -43041 + FRAME_-43041_NAME = 'IMAP_STAR_TRACKER_MX' + FRAME_-43041_CLASS = 4 + FRAME_-43041_CLASS_ID = -43041 + FRAME_-43041_CENTER = -43 + TKFRAME_-43041_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43041_SPEC = 'MATRIX' + TKFRAME_-43041_MATRIX = ( -0.96328734079294150, + 0.16985354835670533, + 0.20791169081775915, + 0.17364817766693014, + 0.98480775301220800, + 0.00000000000000001, + -0.20475304505920630, + 0.03610348622615410, + -0.97814760073380570 ) + + \begintext + + +IMAP Antenna Frames +======================================================================== + + There are two antennas on the spacecraft. The low gain antenna (LGA) + is located on the +Z side of the spacecraft pointing toward +Z, while + the medium gain antenna (MGA) is located on the -Z side pointing in + the -Z direction. + + + ------------- + | S/C +Z axis | + ----------------------- ------------- + | S/C +X axis into page | #-----# . + ----------------------- | LGA | /|\ + #-----# | + ___ _________|^|______|__________________ + | |====================|__________________|_____________ __ _|SWAPI + '---' MAG boom \ __ | | | // \ /--|# + |( )=|__|| | | \\__/ \--|# + | HIT | _|_ IDEX | CODICE | + | | ,.' | '., | | + | ____ | [ \ | / ] | SWE| + ULTRA ##',', |,.'|'.,| GLOWS (#)| + 45 ####'. + | + \\(O) |-|| + '----####/----- + | + --------------' + <---------------- | | \______'-.O.-'______/ | | + ------------- /_\ ----------- |__| + | S/C +Y axis | #-----# | S/C FRAME | STAR + ------------- | MGA | | ORIGIN | TRACKERS + #-----# ----------- + + + ##################################################################### + # .-----------------------------------------------------.# + # |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|# + # | | | | | | | | | | | | | | | | | | |# + # ,, _,~'-----|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|# + # \ \" ' _,~|___ |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|# + # \ \ " | | | | | | SOLAR PANELS | | | | | | |# + # \ \: |--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|# + # \,' |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|# + # HIT | | | | | | | | | | | | | | | |# + # |--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|# + # |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|# + # \ ___ | | | | | | | | | | |# + # THRUSTER R3 --> ,~\ |# #| |--|--|--|--|--|--|--|--|--|--|# + # ^, |# #| |__|__|__|__|__|__|__|__|__|__|# + # ^~---|---| | | | | | | | | | |# + # Spacecraft Axes | '-----------------------------'# + # | ^/~., ,.~\^ # + # #-----# { * `"*,_____,*"` * } # + # +X # LGA # { * | | * } # + # ^ #-----# \ * | | * / # + # | ~. * | | * .~ # + # | "|~####|####~|" # + # | # + # +Y <-------o IDEX # + # +Z out # + # of page # + ##################################################################### + + + ##################################################################### + # / #####~._ half of ~` _.~^' # + # / #########~._ ULTRA 45 ~` ,~^_ # + # HIT ,###########/ .` .^ ~ # + # (just out / ########/ / .^ ,` # + # of view) , : / , # + # / ~ ~` | # + # , ^ ^ , # + # / / / , # + # , , , , # + # / S/C +Z into __ ; ; - # + # , page .`##`. : : `- . , _ ___# + # |/ S/C +Y <----x ;#**#; | | / _# + # |\ | `.##.` | | ,.----., / (` # + # ' | | | | _~` `~_\ (,_# + # \ v #-----# | | ~ ~\___# + # ' S/C +X # MGA # : : ,` `, # + # \ #-----# ; ;, , # + # ' : :| | # + # \ _.-----. ; ; , # + # '~ '^, ~ ~ , # + # -| IMAP / \ \ \ , # + # ' | LO | ' \ * - # + # | ' ; \ ^, `~_ _,.` # + # | ; :,_ . ^_ "~_ ~ ^ # + # ' ; | ^, '-_ # + # \ - ; "~_ " -, # + ##################################################################### + + + The LGA frame is coincident with the spacecraft XYZ axis, while the + MGA secondary axis is chosen so that Y' coincides with spacecraft Y. + This selection is identical to the axial thrusters A3,A4. + + [X] [ 1 0 0 ] [X'] + [Y] = [ 0 1 0 ] [Y'] + [Z]S/C [ 0 0 1 ] [Z']Low Gain Antenna + + [X] [ -1 0 0 ] [X'] + [Y] = [ 0 1 0 ] [Y'] + [Z]S/C [ 0 0 -1 ] [Z']Medium Gain Antenna + + + \begindata + + FRAME_IMAP_LOW_GAIN_ANTENNA = -43050 + FRAME_-43050_NAME = 'IMAP_LOW_GAIN_ANTENNA' + FRAME_-43050_CLASS = 4 + FRAME_-43050_CLASS_ID = -43050 + FRAME_-43050_CENTER = -43 + TKFRAME_-43050_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43050_SPEC = 'MATRIX' + TKFRAME_-43050_MATRIX = ( 1, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 1 ) + + FRAME_IMAP_MED_GAIN_ANTENNA = -43051 + FRAME_-43051_NAME = 'IMAP_MED_GAIN_ANTENNA' + FRAME_-43051_CLASS = 4 + FRAME_-43051_CLASS_ID = -43051 + FRAME_-43051_CENTER = -43 + TKFRAME_-43051_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43051_SPEC = 'MATRIX' + TKFRAME_-43051_MATRIX = ( -1, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + -1 ) + + \begintext + + +IMAP-Lo Frames +======================================================================== + + IMAP-Lo is a single-pixel energetic neutral atom (ENA) imager mounted + on a pivot platform and equipped with a star sensor that pivots with + the ENA sensor [12,13]. The instrument is mounted for imaging in the + radial direction of the rotating spacecraft with the pivot allowing + orientation of the boresight from a polar angle of 60 deg (slightly + towards the Sun) to 180 deg (directed away from the Sun). + + + ------------- + | S/C +Z axis | + ------------- ------------------------- + . | S/C +X axis out of page | + /|\ ------------------------- + | LGA + __________________|______|^|_________ ___ + SWAPI|__________________|__________________|====================| | + #|-| | | .-==-, | / MAG boom '---' + #|-| {|## | | / \ | | + | {|## | |{ HI 90 }| IMAP LO| _. IMAP LO + | {|## | _.._ | \ / | _., | _.-' BORESIGHT + | ULTRA | / \ | `-==-' | / __`'_.-' + | 90 | \ HI 45/ | | \ \.-';| + | | '----` | | ~._.+ | + '-------------------|----------/--------' + | | \_________O_________/ | | ----------------> + |__| ----------- /_\ ------------- + STAR | S/C FRAME | MGA | S/C +Y axis | + TRACKERS | ORIGIN | ------------- + ----------- + + + IMAP-Lo Local Frame + + Pivot +Z' axis + Angle | + ,.~'^ ^ ^-| + .-'` | + .` _~-, Star Sensor + .` | ** \___ _ | + Boresight | / \_-'`~~~~~~`'-.- - + . |/___ ,^~~~~~~%##### ', '. + `'. ^~~~~~~%%######### ` '. + `'. /~~~~~~, - - ~~~#####\ . + /. ~~~ / `.~~%###, . + .~~~`'./ .~~### . + .~~~~ `'. |~~~%#" .`. + "~~~~%| O :~~~~ ' . . + |~~~ # . /~~~~~ | . \ + |~~~%##`. /~~~~~ / . | + \~~%### ~`- -'~~~~~~ / . . + +,~%######~~~~~~~~ ,- ~@@@~ . + | ' ~ ######%%%%_,^ ,~@@@~ Rotation Axis + '. - .%##%.- .' . ^~. + .~ '` `. .' .` ^~. + .~ '` ' . _ .' .` ^~. + .~ '` ` '.''`` ,.` +X' axis + -Y' axis `-.,,, . ` + + + The local IMAP-Lo base frame is defined so the sensor pivots about + the +X' axis. When the pivot angle is 90 deg, the boresight is aligned + with the local -Y' axis. The +Z' axis, from which the pivot angle is + measured, aligns with the spacecraft +Z axis at pivot angle 0. + + The nominal boresight look-direction is defined in [6] for the + azimuth-elevation (deg): + + LO (azim, elev) = ( +330, -90 to +30 ) + + At 0 deg elevation (90 deg polar angle), the boresight direction and + primary axis in the spacecraft frame of reference is: + + D = -Y' = [ -cos(0) x sin(330), cos(0) x cos(330), sin(0) ] + + The secondary axis is the +X' local axis, perpendicular to both + the boresight direction D and the spacecraft -Z axis: + + S = +X' = D x -Z = Y' x [ 0, 0, 1 ] + + The tertiary axis is: + + N = D x S = Y' x ( Y' x [ 0, 0, 1 ] ) + + The rotation matrix formed using the column vectors is: + + R = [ +S, -D, +N ] + + From the spacecraft MICD[6], the single-precision rotation matrices + orienting IMAP-Lo on the spacecraft: + + [X] [ -0.866025 -0.500000 0.000000 ] [X'] + [Y] = [ 0.500000 -0.866025 0.000000 ] [Y'] + [Z]S/C [ 0.000000 0.000000 1.000000 ] [Z']IMAP-Lo + + consistent with calculating the matrix R to single precision. + + For reference, the ZYZ intrinsic Euler angles orienting X'Y'Z' in + the spacecraft XYZ coordinate system are (deg): + + IMAP-Lo: (A, B, Y) = ( 150.000, 0.000, 0.000 ) + + Using the formulas described in the Euler angles section above, the + rotation matrix generated from these Euler angles is consistent with + the rotation matrix using the azimuth/elevation look direction. + + + IMAP-Lo Orientation + --------------------------------------------------------------------- + + The orientation of IMAP-Lo must be specified in a separate C-kernel. + To facilitate this specification, a base frame representing the fixed + transformation of the local X'Y'Z' frame to the spacecraft frame has + been provided. + + The C-kernel will simply specify transformation within the + local IMAP-Lo frame, and be generated using only the pivot angle. + The implementation of this is outside the scope of this kernel. + + The IMAP-Lo base frame is defined such that + -Y is the IMAP-Lo look direction at 0 degree pivot angle (nominally + aligned with the S/C +Z axis) + +X is the pivot angle, measured from 0 degrees. + + The rotation taking vectors from the IMAP-Lo base frame to the + S/C frame is defined below. + + \begindata + + FRAME_IMAP_LO_BASE = -43100 + FRAME_-43100_NAME = 'IMAP_LO_BASE' + FRAME_-43100_CLASS = 4 + FRAME_-43100_CLASS_ID = -43100 + FRAME_-43100_CENTER = -43 + TKFRAME_-43100_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43100_SPEC = 'MATRIX' + TKFRAME_-43100_MATRIX = ( -0.86602540378443865, + 0.50000000000000000, + 0.00000000000000000, + 0.00000000000000000, + 0.00000000000000000, + -1.00000000000000000, + -0.50000000000000000, + -0.86602540378443865, + 0.00000000000000000) + + \begintext + + The IMAP-Lo frame describes the articulation of the pivot and is + captured in a SPICE C-Kernel (CK) file [1]. The IMAP-Lo CK frame + rotates the base frame about its +X axis by the pivot angle shown + in the diagram above. + + \begindata + + FRAME_IMAP_LO = -43101 + FRAME_-43101_NAME = 'IMAP_LO' + FRAME_-43101_CLASS = 3 + FRAME_-43101_CLASS_ID = -43101 + FRAME_-43101_CENTER = -43 + + \begintext + + The IMAP-Lo star sensor frame is nominally aligned with the IMAP-Lo + frame. The offset is determined from the measured alignments [17] and + is captured in the definition below. + + \begindata + + FRAME_IMAP_LO_STAR_SENSOR = -43102 + FRAME_-43102_NAME = 'IMAP_LO_STAR_SENSOR' + FRAME_-43102_CLASS = 4 + FRAME_-43102_CLASS_ID = -43102 + FRAME_-43102_CENTER = -43 + TKFRAME_-43102_RELATIVE = 'IMAP_LO' + TKFRAME_-43102_SPEC = 'MATRIX' + TKFRAME_-43102_MATRIX = ( 0.999991181093041, + -0.004199686195312, + -0.000019287445755, + 0.004199730484764, + 0.999980635401645, + 0.004592503193045, + 0.000000000000000, + -0.004592543694261, + 0.999989454215601 ) + + \begintext + + +IMAP-Hi Frames +======================================================================== + + IMAP-Hi consists of two identical, single-pixel high energy neutral + atom (ENA) imagers. Hi 90 is oriented with its boresight + perpendicular to the spacecraft spin axis, while Hi 45 is radially + outward but with the boresight angled 45 deg from the -Z axis. + + ------------- + | S/C +X axis | + ------------- + ----------------------- + Hi 45 BORESIGHT . Hi 90 BORESIGHT | S/C +Z axis into page | + \ /|\ / | (facing Sun) | + \ 15 deg | 15 deg / ----------------------- + " .~'^'~.| .~'^'~." + \ | / + , | , + ; /`~~__ , `+ direction of + , = .^ - /_ ``-. '. positive + .+ + `^~/ ./ ~ rotation + ^ + + . -- ' `` \ _-~ \ + _ / ',= ' \~'` \ IMAP \ + ULTRA /' '-_ .~ ' \,.=.. \ Lo \|/ + 90 / ~ _,.,_ + + \ ' + / ,~' +' `'+ + + \ + / ~^ .' , = .'. '- ='' -`` ------------- + ^/ / , = . + + \ \~'` | S/C +Y axis |-----> + | . + + + + . \ ------------- ___ + | | + + ' = ' | \--------------------| | + SWAPI| | ' = ', - . | /--------------------|___| + _+_: ' + + ' / MAG boom + \_ __\__ \ + + / /^*~, + + | SWE '. ' = ' .' ULTRA / + `~-' '~..,___,..~' 45 /~,* + _\ / /~,*` + * / CODICE ^*._/ *` HIT + *\ _/`. / + * / /~ _ _ ,.-^-., _ _ _ / + '=' + + + GLOWS + + + '-.,.-' + IDEX + + + ------------- + | S/C +Z axis | + ------------- ------------------------- + . | S/C +X axis out of page | + /|\ ------------------------- + | LGA + __________________|______|^|_________ ___ + SWAPI|__________________|__________________|====================| | + #|-| | | .-==-, | / MAG boom '---' + #|-| {|## | | / \ | | + | {|## | |{ HI 90 }| IMAP LO| + | {|## | _.._ | \ / | _., | + | ULTRA | / \ | `-==-' | / __`',| + | 90 | \ HI 45/ | | \ \_\ ;| + | | '----` | | ~._ + | + '-------------------|----------/--------' + | | \_________O_________/ | | ----------------> + |__| ----------- /_\ ------------- + STAR | S/C FRAME | MGA | S/C +Y axis | + TRACKERS | ORIGIN | ------------- + ----------- + + + ####################################################################### + #______________________________________________ # + # / _ | || | IMAP Hi 90 # + #----~. / |_| O o | || |==== hidden # + # ULTRA 90 /\ x x = | || | behind S/C # + # / \__________| || || <---- struct here # + # ##### -- #### | || |] # + # ## % ## / \###\ / ___ || |} Hi 90 Boresight # + # /## % ##\--|####| |____|*#*| || |}________________\ # + # |## % ##|--|####| | |*#*| || |} / # + # |## % ##| |####| | --- || |} # + # |## % ##|--|####| | || |] # + # |## % ##|--|####| \ || || S/C +Z # + # \## % ##/ |####| | || . ^ # + # ## % ## \ /###/ | || .'. | # + # ##### -- #### | || . /, | # + #--------------- | |.` _~ x----> S/C +X # + # | ,` ,~` `~ S/C +Y # + # ______ / .` ~` _ \ into page # + # .=.=.=.=. |( ) ()| / ___ * -' ~' `', | # + # | | | | | |( ) ()| |____|*#*|| ~ .`_ _ / ~ # + #__#_#_#_#_#__|______| |*#*||` / //// / ~ # + #----------------| .----- / ` ` ' ~ # + # |_ _ _| | | .'_ / '`.,_ ,~' ~. # + # | | | | | | .' -, | _, ` ":. # + #__/_/_/_/___/___|________|______;_\_ ,.-' |:. # + # | | / ":. # + #_______________________________________| | _45 deg ":. # + #___ ____ __ || || || | |-~" " # + # / / / / // |_____||_____||_____| | Hi 45 # + #_/ /___/ /_/ | /|\ \|/ Boresight # + # / ' # + # | ------------- # + # / | S/C -Z axis | # + #=========== ------------- # + ####################################################################### + + + The local IMAP-Hi frame[15]--identical for both sensors--is defined + with the boresight aligned with the +Y' axis, the rectangular vent + ports aligned with the +Z' axis, and X' = Y' x Z'. + + The local coordinate system is shown below, looking into the sensor. + The vent ports are aligned as shown with the Z' axis. + + +Z' + ^ + | + | + _____|_____ + .-'` | '-. + .' ____|____ '. + / .' | '. \ + / .' |'|'| '. \ + / / | | | \ \ + | / |_|_| \ | + +X' /_____|__ |__________| | | + \ | | | | + | \ |'''| / | + \ \ | | / / + \ '. |___| .' / + \ '. .' / + '. '-------' .' + '-. .-' + '-.........-' + + + IMAP HI 45 + -------------- + + The nominal boresight look-direction is defined in [6] for the + azimuth-elevation (deg): + + HI 45 (azim, elev) = ( +255, -45 ) + + The boresight direction is the +Y' local axis of instrument, and the + primary axis in the spacecraft frame of reference is: + + D = +Y' = [ -cos(-45) x sin(255), cos(-45) x cos(255), sin(-45) ] + + The secondary axis is the +Z' local axis, NOTIONALLY perpendicular to + both the boresight direction D and the spacecraft Z axis: + + S = +Z' = D x Z = Y' x [ 0, 0, 1 ] + + The tertiary axis is NOTIONALLY: + + N = D x S = Y' x ( Y' x [ 0, 0, 1 ] ) + + The rotation matrix formed using the column vectors is NOTIONALLY: + + RN = [ +N, +D, +S ] + + HOWEVER, the actual alignment is modified by a rotation about the + local Y' axis by 3 deg as a consequence of the angular offset of the + mounting inserts by the same amount. This rotation about local Y' is: + + [ cos(3) 0 sin(3) ] + RY' = [ 0 1 0 ] + [ -sin(3) 0 cos(3) ] + + The final rotation that orients HI 45 on the spacecraft is the matrix + multiplication: + + R = RN x RY' + + From the spacecraft MICD[6], the single-precision rotation matrices + orienting IMAP-HI 45 on the spacecraft: + + [X] [ -0.668531 0.683013 -0.294210 ] [X'] + [Y] = [ 0.233315 -0.183013 -0.955024 ] [Y'] + [Z]S/C [ -0.706138 -0.707107 -0.037007 ] [Z']HI 45 + + Using the method described in a Euler discussion section, the Euler + angles rounded to 1/1000th of a degree are: + + HI 45: (A, B, Y) = ( -17.122, 92.121, -135.037 ) + + Using the formulas described in the Euler angles section above, the + rotation matrix generated from these Euler angles is consistent with + the rotation matrix using the azimuth/elevation look direction; + however, the full double-precision Euler angles are necessary to + generate the proper precise rotation matrix. + + Applying the method described above to the measured alignment vector + in [17], + + D = +Y' = [ 0.683178772, -0.185278978, -0.706355764 ], + + we arrive at the definition below. + + \begindata + + FRAME_IMAP_HI_45 = -43150 + FRAME_-43150_NAME = 'IMAP_HI_45' + FRAME_-43150_CLASS = 4 + FRAME_-43150_CLASS_ID = -43150 + FRAME_-43150_CENTER = -43 + TKFRAME_-43150_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43150_SPEC = 'MATRIX' + TKFRAME_-43150_MATRIX = ( -0.667096841004280 + 0.235144007037882 + -0.706886907981948 + 0.683178772158437 + -0.185278978042968 + -0.706355764163813 + -0.297066608682633 + -0.954137828748825 + -0.037046373051589 ) + + \begintext + + + IMAP HI 90 + -------------- + + The nominal boresight look-direction is defined in [6] for the + azimuth-elevation (deg): + + HI 90 (azim, elev) = ( +285, 0 ) + + The boresight direction is the +Y' local axis of instrument, and the + primary axis in the spacecraft frame of reference is: + + D = +Y' = [ -cos(0) x sin(285), cos(0) x cos(285), sin(0) ] + + The secondary axis is the +Z' local axis, NOTIONALLY perpendicular to + both the boresight direction D and the spacecraft Z axis: + + S = -Z' = D x Z = -Y' x [ 0, 0, 1 ] + + The tertiary axis is NOTIONALLY: + + N = D x S = Y' x ( Y' x [ 0, 0, 1 ] ) + + The rotation matrix formed using the column vectors is NOTIONALLY: + + RN = [ +N, +D, +S ] + + HOWEVER, the actual alignment is modified by a rotation about the + local Y' axis by 15 deg as a consequence of the angular offset of the + mounting inserts by the same amount. This rotation about local Y' is: + + [ cos(15) 0 sin(15) ] + RY' = [ 0 1 0 ] + [ -sin(15) 0 cos(15) ] + + The final rotation that orients HI 45 on the spacecraft is the matrix + multiplication: + + R = RN x RY' + + From the spacecraft MICD[6], the single-precision rotation matrices + orienting IMAP-HI 45 on the spacecraft: + + [X] [ 0.066987 0.965926 -0.250000 ] [X'] + [Y] = [ -0.250000 0.258819 0.933013 ] [Y'] + [Z]S/C [ 0.965926 0.000000 0.258819 ] [Z']HI 90 + + Using the method described in a Euler discussion section, the Euler + angles rounded to 1/1000th of a degree are: + + HI 90: (A, B, Y) = ( -165.000, 75.000, 90.000 ) + + Using the formulas described in the Euler angles section above, the + rotation matrix generated from these Euler angles is consistent with + the rotation matrix using the azimuth/elevation look direction. + + Applying the method described above to the measured alignment vector + in [17], + + D = +Y' = [ 0.965176886, 0.261597765, 0.000434036 ], + + we arrive at the definition below. + + \begindata + + FRAME_IMAP_HI_90 = -43151 + FRAME_-43151_NAME = 'IMAP_HI_90' + FRAME_-43151_CLASS = 4 + FRAME_-43151_CLASS_ID = -43151 + FRAME_-43151_CENTER = -43 + TKFRAME_-43151_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43151_SPEC = 'MATRIX' + TKFRAME_-43151_MATRIX = ( 0.067301842956904 + -0.249915857460229 + 0.965925735305009 + 0.965176885850928 + 0.261597764959596 + 0.000434035999933 + -0.252792485951837 + 0.932259981742251 + 0.258819020723416 ) + + \begintext + + +IMAP-Ultra Frames +======================================================================== + + The IMAP-Ultra instrument[7,14] consists of two identical sensors for + imaging the emission of energetic neural atoms (ENAs) produced in the + heliosheath and beyond. Ultra 90 is mounted perpendicular to the IMAP + spin axis (+Z), while Ultra 45 is mounted at 45 degrees from the + anti-sunward spin axis (-Z). + + + ------------- + | S/C +X axis | ----------------------- + ------------- | S/C +Z axis into page | + . | (facing Sun) | + /|\ ----------------------- + | + | + | + _ + HI 45 /`~~__HI 90 `+ direction of + , = .^ - /_ ``-. '. positive + .+ + `^~/ ./ ~ rotation + ULTRA ^ + + . -- ' `` \ _-~ \ + 90 _ / ',= ' \~'` \ IMAP \ + . /' '-_ .~ ' \,.=.. \ LO \|/ + `;. / ~ _,.,_ + + \ ' + / `/ ,~' +' `'+ + + \ + 30 / ~^ .' , = .'. '- ='' -`` ------------- + | ^/ / , = . + + \ \~'` | S/C +Y axis |-----> + ---- | . + + + + . \ ------------- ___ + | | + + ' = ' | \--------------------| | + SWAPI| | ' = ', - . | /--------------------|___| + _+_: ' + + ' / | MAG boom + \_ __\__ \ + + / /^*~, . + + | SWE '. ' = ' .' ULTRA / 33 deg + `~-' '~..,___,..~' 45 / ; + _\ / /`., / + * / CODICE ^*._/ `'./ + *\ _/`. / `'. + * / /~ _ _ ,.-^-., _ _ _ / + '=' + + + GLOWS + + + '-.,.-' + IDEX + + + Each sensor comprises two separate assemblies of collector plates. + Each assembly of collector plates is fanned out in a cylindrical + pattern, and the cyclindrical axes of the fanned-out plates are + parallel and offset in the direction perpendicular to the axes. + + The orientations of Ultra 45 and 90 are analogous to IMAP Hi 45 and + 90; see the diagram for IMAP Hi above. Take special note that the + angle with the spacecraft Z axis and the boresights for IMAP Hi are + the same as the angle with the spacecraft Z axis and the "outward" + directions for Ultra. + + + ######################################################################### + # # + # One half of one IMAP Ultra sensor showing # + # assembly of fanned-out collector plates # + # Outward # + # . Assemblies are mirror-symmetric # + # /|\ about the leftmost edge of drawing # + # | # + # | ,--. , # + # || | | ; , 63.42 deg FOR # + # | | | | ; ; ; 60.31 deg FOV # + # | | | | : ; ; ; ; # + # \|/ | | | : ; ; ; / # + # ' | ;_ _|_ ; ; ; ; / / . # + # S/C | | ``'''^-,/, / / / .' # + # | | ___ `''., / / . . # + #_________;-|__|_ `'"^~-,._ /^~ `^., / ,' ' . # + #---------'- | |_| `'":., _ `^, . ,' .' # + #--------. ,-| | @ `'~/ \ `'. .` .' , # + # ,'`.' | | @ @ @ @ '~,.;, '. .' .' # + # .',' | | @ @ @ @ @ `;, /~_':' .' ,' # + #.'`,' _| |_ @ @ @ `;, / '. .' ,'` # + # `, |_|-|_| @ @ '. '. .' ,. # + #'-,'. |-| @ @ @ ', `.` ;' # + # '.'-. | | @ @ ;, \,;`' .-` # + # `-.'. | | @ @ ", ', ,.'` ,^ # + #_________:'-| | @ @ @ @ :, _,\' .-`` # + #-----------||-|-, @ /~,".' ;'.' # + #=== ||---|@ @ @ @ @ ,\ ' ,.^` # + #___________||_/-~_ _ @ @ _, _,-' ,.-'` # + # @| | | || `- , @ @ \,\' ,'` +Z' # + #----' | | || `~,@ @ ,~`' _,'` ^ # + # | | || ',@ .^\_,'` ,.'` | # + #______'-'__||-@--~-~, \ .;` .'` | # + #___________||/ ~ # ~ | {.'` | # + # |* ||*| + <------------ Collector plate o------> +Y' # + #____ --||\ ~ ~ | axis of symmetry Instrument # + #_ *| ||-@-^~-~^-------| Coordinates # + #*| | ||_______________| # + #___*|_______|_|_|__|__|_|_| | # + ######################################################################### + + + The local IMAP-Ultra frame[14]--identical for both sensors--is + defined with the collector-plate-fan axes of symmetry aligned with + the +X' axis, the cylindrical axes offset in the +Y' axis, and the + Z' axis perpendicular to both and outward as in the diagram below. + + + IMAP ULTRA 45 + -------------- + + The nominal outward look-direction is defined in [6] for the + azimuth-elevation (deg): + + ULTRA 45 (azim, elev) = ( +33, -45 ) + + The look-direction is the +Z' local axis of instrument, and the + primary axis in the spacecraft frame of reference is: + + D = +Z' = [ -cos(-45) x sin(33), cos(-45) x cos(33), sin(-45) ] + + The secondary axis is the +X' local axis, lying in the plane spanned + by the look-direction D and the spacecraft Z axis. An equivalent + definition is selecting the secondary axis as the +Y' local axis, + perpendicular to both the look-direction D and the spacecraft Z axis. + + S = +Y' = D x Z = Z' x [ 0, 0, 1 ] + + The tertiary axis is: + + N = D x S = Z' x Y' = Z' x ( Z' x [ 0, 0, 1 ] ) + + The rotation matrix formed using the column vectors is: + + R = [ -N, +S, +D ] + + The rotation matrices orienting the IMAP-Ultra 45 sensor on the + spacecraft is given by [6]: + + [X] [ -0.385118 0.838671 -0.385118 ] [X'] + [Y] = [ 0.593030 0.544639 0.593030 ] [Y'] + [Z]S/C [ 0.707107 0.000000 -0.707107 ] [Z']ULTRA 45 + + Using the method described in a Euler discussion section, the Euler + angles rounded to 1/1000th of a degree are: + + ULTRA 45: (A, B, Y) = ( -147.000, 135.000, 90.000 ) + + Using the formulas described in the Euler angles section above, the + rotation matrix generated from these Euler angles is consistent with + the rotation matrix using the azimuth/elevation look direction. + + The measured alignment vectors [17] correspond to the instrument +Z + and +X coordinates: + + D = +Z' = [0.499259504; -0.866451261; -0.001469775]; + -N = +X' = [0.0033786069; -0.0046688268; 0.9999833934]; + + Using the calculation described above, we arrive at the rotation + below, taking vectors from the ULTRA 45 frame to the S/C frame. + + \begindata + + FRAME_IMAP_ULTRA_45 = -43200 + FRAME_-43200_NAME = 'IMAP_ULTRA_45' + FRAME_-43200_CLASS = 4 + FRAME_-43200_CLASS_ID = -43200 + FRAME_-43200_CENTER = -43 + TKFRAME_-43200_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43200_SPEC = 'MATRIX' + TKFRAME_-43200_MATRIX = ( -0.381247548031845 + 0.595862003625695 + 0.706823018693420 + 0.841149671034019 + 0.540797922474097 + -0.002199537920242 + -0.383559041138477 + 0.593705381214347 + -0.707387010255390 ) + + \begintext + + + IMAP ULTRA 90 + -------------- + + The nominal outward look-direction is defined in [6] for the + azimuth-elevation (deg): + + ULTRA 90 (azim, elev) = ( +210, 0 ) + + The look-direction is the +Z' local axis of instrument, and the + primary axis in the spacecraft frame of reference is: + + D = +Z' = [ -cos(0) x sin(210), cos(0) x cos(210), sin(0) ] + + The secondary axis is the +X' local axis, lying along spacecraft + +Z axis. + + S = +X' = [ 0, 0, 1 ] + + The tertiary axis is: + + N = D x S = Z' x X' = Z' x [ 0, 0, 1 ] + + The rotation matrix formed using the column vectors is: + + R = [ +N, +S, +D ] + + The rotation matrices orienting the IMAP-Ultra 90 sensor on the + spacecraft is given by [6]: + + [X] [ 0.000000 -0.866025 0.500000 ] [X'] + [Y] = [ 0.000000 -0.500000 -0.866025 ] [Y'] + [Z]S/C [ 1.000000 0.000000 0.000000 ] [Z']ULTRA 90 + + Using the method described in a Euler discussion section, the Euler + angles rounded to 1/1000th of a degree are: + + ULTRA 90: (A, B, Y) = ( 30.000, 90.000, 90.000 ) + + Using the formulas described in the Euler angles section above, the + rotation matrix generated from these Euler angles is consistent with + the rotation matrix using the azimuth/elevation look direction. + + The measured alignment vectors [17] correspond to the instrument +Z + and +X coordinates: + + D = +Z' = [0.499259504; -0.866451261; -0.001469775]; + N = +X' = [0.0033786069; -0.0046688268; 0.9999833934]; + + Using the calculation described above, we arrive at the rotation + below, taking vectors from the ULTRA 90 frame to the S/C frame. + + \begindata + + FRAME_IMAP_ULTRA_90 = -43201 + FRAME_-43201_NAME = 'IMAP_ULTRA_90' + FRAME_-43201_CLASS = 4 + FRAME_-43201_CLASS_ID = -43201 + FRAME_-43201_CENTER = -43 + TKFRAME_-43201_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43201_SPEC = 'MATRIX' + TKFRAME_-43201_MATRIX = ( 0.001250593582091 + -0.000975706837283 + 0.999998742005139 + -0.866451604965052 + -0.499260713960047 + 0.000596447474492 + 0.499259503934755 + -0.866451260886769 + -0.001469774999808 ) + + \begintext + + +IMAP Magnetometer (MAG) Frames +======================================================================== + + The IMAP magnetometer (MAG)[7,16] consists of a pair of identical + triaxial fluxgate magnetometers mounted on a ~2.5 meter boom. MAG-O + is positioned at the end of the boom, while MAG-I is mounted ~0.75 + meters from MAG-O. + + + ------------- + | S/C +X axis | ----------------------- + ------------- | S/C +Z axis into page | + . | (facing Sun) | + /|\ ----------------------- + | + | + | + _ + HI 45 /`~~__HI 90 `+ direction of + , = .^ - /_ ``-. '. positive + .+ + `^~/ ./ ~ rotation + ^ + + . -- ' `` \ _-~ \ + _ / ',= ' \~'` \ IMAP \ + ULTRA /' '-_ .~ ' \,.=.. \ LO \|/ + 90 / ~ _,.,_ + + \ ' + / ,~' +' `'+ + + \ + / ~^ .' , = .'. '- ='' -`` + ^/ / , = . + + \ \~'` S/C +Y axis -----> + | . + + + + . \ ___ ___ + | | + + ' = ' | \------------| |---| | + SWAPI| | ' = ', - . | /------------|___|---|___| + _+_: ' + + ' / MAG-I MAG-O + \_ __\__ \ + + / /^*~, + + | SWE '. ' = ' .' ULTRA / MAGS and boom + `~-' '~..,___,..~' 45 /~,* not to scale + _\ / /~,*` + * / CODICE ^*._/ *` HIT + *\ _/`. / + * / /~ _ _ ,.-^-., _ _ _ / + '=' + + + GLOWS + + + '-.,.-' + IDEX + + + ---------------------------- + S/C +Z axis | Deployed Magnetometer Boom | S/C +X axis + . | (approximately to scale) | out of page + /|\ ---------------------------- + | + | S/C +Y axis --------> + @================================================================= + #\ | | | | + \ `'` `'` + Boom Deployment Hinge MAG-I MAG-O + + +X' <-----x +Y' into + | page + MAG Local | + Coord System v + +Z' + + + Each MAG instrument is contained in a cylindrial casing with the + local Z' axis along the cylindrical axis of symmetry. The local X' + axis is along the boom, and the local Y' axis is perp to the boom. + + When deployed, the boom sticks out in the +Y axis of the spacecraft, + with the MAG +X' axis in the -Y direction. The MAG +Z' axis is in the + spacecraft -Z' direction, and +Y' is spacecraft -X. + + [X] [ 0 -1 0 ] [X'] + [Y] = [ -1 0 0 ] [Y'] + [Z]S/C [ 0 0 -1 ] [Z']MAG deployed + + Prior to deployment, the boom is stowed pointing in the -Y direction + of the spacecraft, with the MAG +X' axis in the +Y direction. The MAG + +Z' axis is in the spacecraft +Z' direction, and +Y' is spacecraft -X + + [X] [ 0 +1 0 ] [X'] + [Y] = [ -1 0 0 ] [Y'] + [Z]S/C [ 0 0 +1 ] [Z']MAG undeployed + + The MAG local coordinate system is shown in the diagram above. The + matrix taking vectors from the MAG coordinate system to the spacecraft + coordinate system is provided below in the IMAP_MAG_BASE frame definition. + It represents a nominal, or idealized, orientation. The measured + alignments [17] are given in frames IMAP_MAG_I and IMAP_MAG_O. + + \begindata + + FRAME_IMAP_MAG_BOOM = -43250 + FRAME_-43250_NAME = 'IMAP_MAG_BOOM' + FRAME_-43250_CLASS = 4 + FRAME_-43250_CLASS_ID = -43250 + FRAME_-43250_CENTER = -43 + TKFRAME_-43250_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43250_SPEC = 'MATRIX' + TKFRAME_-43250_MATRIX = ( 0.999895975249542, + -0.013794792994061, + -0.004212168802143, + 0.013794915371822, + 0.999904845627765, + -0.000000000000000, + 0.004211767995864, + -0.000058106512157, + 0.999991128777642 ) + + FRAME_IMAP_MAG_BASE = -43253 + FRAME_-43253_NAME = 'IMAP_MAG_BASE' + FRAME_-43253_CLASS = 4 + FRAME_-43253_CLASS_ID = -43253 + FRAME_-43253_CENTER = -43 + TKFRAME_-43253_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43253_SPEC = 'MATRIX' + TKFRAME_-43253_MATRIX = ( 0.0, + -1.0, + 0.0, + -1.0, + 0.0, + 0.0, + 0.0, + 0.0, + -1.0 ) + + FRAME_IMAP_MAG_I = -43251 + FRAME_-43251_NAME = 'IMAP_MAG_I' + FRAME_-43251_CLASS = 4 + FRAME_-43251_CLASS_ID = -43251 + FRAME_-43251_CENTER = -43 + TKFRAME_-43251_RELATIVE = 'IMAP_MAG_BASE' + TKFRAME_-43251_SPEC = 'MATRIX' + TKFRAME_-43251_MATRIX = ( 0.999999871280306 + 0.000507384835577 + 0.0 + -0.000507348727136 + 0.999928705504181 + -0.011930067309210 + -0.000006053135240 + 0.011930065773575 + 0.999928834214714 ) + + FRAME_IMAP_MAG_O = -43252 + FRAME_-43252_NAME = 'IMAP_MAG_O' + FRAME_-43252_CLASS = 4 + FRAME_-43252_CLASS_ID = -43252 + FRAME_-43252_CENTER = -43 + TKFRAME_-43252_RELATIVE = 'IMAP_MAG_BASE' + TKFRAME_-43252_SPEC = 'MATRIX' + TKFRAME_-43252_MATRIX = ( 0.999946560385648 + 0.010338102964849 + 0.0 + -0.010337900188807 + 0.999926946999490 + -0.006263264641177 + -0.000064750274757 + 0.006262929934730 + 0.999980385565654 ) + + \begintext + + +IMAP Solar Wind Electron (SWE) Frames +======================================================================== + + The SWE instrument frame is defined in [18] as + + * -X is the outward facing direction of the center of the field of view, + pointing away from the S/C body + * +Z is nominally aligned with S/C +Z + * +Y complements the right-handed frame + + A view of the instrument looking down the Y' axis is illustrated below. + + + . ^ S/C +Z + P63 . ^ +Z' | (spin axis) + . . | | + P43 `. . |_________ SWE Sensor | + . `. . || | | + P21 `. `. . || | + ` . `. `..|| | + 000 -X' <--------x | + . ' .' .'.| +Y' (into page ) + M21 .' .' . | | + ' .' . |__________|______________ + M43 .' . | | Mounting Plate + ' . _|_______________________|_____ + M631 . | / / / / / / / / / / / / / / / + . |/ / Spacecraft Deck / / / / / / + + + + [17] provides the measured value of the instrument -X axis. + Taking the cross product with the +Z axis and normalizing + results in the frame definition below. + + \begindata + + FRAME_IMAP_SWE = -43300 + FRAME_-43300_NAME = 'IMAP_SWE' + FRAME_-43300_CLASS = 4 + FRAME_-43300_CLASS_ID = -43300 + FRAME_-43300_CENTER = -43 + TKFRAME_-43300_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43300_SPEC = 'MATRIX' + TKFRAME_-43300_MATRIX = ( 0.453749717807575, + 0.891129167735826, + 0.000000000000000, + -0.891129167735826, + 0.453749717807575, + 0.000000000000000, + 0.000000000000000, + 0.000000000000000, + 1.000000000000000 ) + +\begintext + + The frames for the individual SWE detectors is defined as follows: + +Y is aligned with the +Y axis in the SWE frame + +Z is the outward facing direction of the center of the CEM field of + view, pointing away from the S/C body + +X complements the right-handed frame + + The orientation of each detector frame is a fixed offset from SWE frame, + achieved by rotating the SWE frame about its +Y axis by the angle in the + table below. + + The table below contains nominal rotation offsets, as specified in [19], + for each of the CEMs: + + Rotation about +Y + Detector from SWE frame + ---------- ------------------------ + P63 +63 degrees + P42 +42 degrees + P21 +21 degrees + 000 0 degrees + M21 -21 degrees + M42 -42 degrees + M63 -63 degrees + + \begindata + + FRAME_IMAP_SWE_DETECTOR_P63 = -43301 + FRAME_-43301_NAME = 'IMAP_SWE_DETECTOR_P63' + FRAME_-43301_CLASS = 4 + FRAME_-43301_CLASS_ID = -43301 + FRAME_-43301_CENTER = -43 + TKFRAME_-43301_RELATIVE = 'IMAP_SWE' + TKFRAME_-43301_SPEC = 'ANGLES' + TKFRAME_-43301_ANGLES = ( 0, 63.0, 0 ) + TKFRAME_-43301_AXES = ( 1, 2, 3 ) + TKFRAME_-43301_UNITS = 'DEGREES' + + FRAME_IMAP_SWE_DETECTOR_P42 = -43302 + FRAME_-43302_NAME = 'IMAP_SWE_DETECTOR_P42' + FRAME_-43302_CLASS = 4 + FRAME_-43302_CLASS_ID = -43302 + FRAME_-43302_CENTER = -43 + TKFRAME_-43302_RELATIVE = 'IMAP_SWE' + TKFRAME_-43302_SPEC = 'ANGLES' + TKFRAME_-43302_ANGLES = ( 0, 42.0, 0 ) + TKFRAME_-43302_AXES = ( 1, 2, 3 ) + TKFRAME_-43302_UNITS = 'DEGREES' + + FRAME_IMAP_SWE_DETECTOR_P21 = -43303 + FRAME_-43303_NAME = 'IMAP_SWE_DETECTOR_P21' + FRAME_-43303_CLASS = 4 + FRAME_-43303_CLASS_ID = -43303 + FRAME_-43303_CENTER = -43 + TKFRAME_-43303_RELATIVE = 'IMAP_SWE' + TKFRAME_-43303_SPEC = 'ANGLES' + TKFRAME_-43303_ANGLES = ( 0, 21.0, 0 ) + TKFRAME_-43303_AXES = ( 1, 2, 3 ) + TKFRAME_-43303_UNITS = 'DEGREES' + + FRAME_IMAP_SWE_DETECTOR_000 = -43304 + FRAME_-43304_NAME = 'IMAP_SWE_DETECTOR_000' + FRAME_-43304_CLASS = 4 + FRAME_-43304_CLASS_ID = -43304 + FRAME_-43304_CENTER = -43 + TKFRAME_-43304_RELATIVE = 'IMAP_SWE' + TKFRAME_-43304_SPEC = 'ANGLES' + TKFRAME_-43304_ANGLES = ( 0, 0, 0 ) + TKFRAME_-43304_AXES = ( 1, 2, 3 ) + TKFRAME_-43304_UNITS = 'DEGREES' + + FRAME_IMAP_SWE_DETECTOR_M21 = -43305 + FRAME_-43305_NAME = 'IMAP_SWE_DETECTOR_M21' + FRAME_-43305_CLASS = 4 + FRAME_-43305_CLASS_ID = -43305 + FRAME_-43305_CENTER = -43 + TKFRAME_-43305_RELATIVE = 'IMAP_SWE' + TKFRAME_-43305_SPEC = 'ANGLES' + TKFRAME_-43305_ANGLES = ( 0 -21.0, 0 ) + TKFRAME_-43305_AXES = ( 1, 2, 3 ) + TKFRAME_-43305_UNITS = 'DEGREES' + + FRAME_IMAP_SWE_DETECTOR_M42 = -43306 + FRAME_-43306_NAME = 'IMAP_SWE_DETECTOR_M42' + FRAME_-43306_CLASS = 4 + FRAME_-43306_CLASS_ID = -43306 + FRAME_-43306_CENTER = -43 + TKFRAME_-43306_RELATIVE = 'IMAP_SWE' + TKFRAME_-43306_SPEC = 'ANGLES' + TKFRAME_-43306_ANGLES = ( 0, -42.0, 0 ) + TKFRAME_-43306_AXES = ( 1, 2, 3 ) + TKFRAME_-43306_UNITS = 'DEGREES' + + FRAME_IMAP_SWE_DETECTOR_M63 = -43307 + FRAME_-43307_NAME = 'IMAP_SWE_DETECTOR_M63' + FRAME_-43307_CLASS = 4 + FRAME_-43307_CLASS_ID = -43307 + FRAME_-43307_CENTER = -43 + TKFRAME_-43307_RELATIVE = 'IMAP_SWE' + TKFRAME_-43307_SPEC = 'ANGLES' + TKFRAME_-43307_ANGLES = ( 0, -63.0, 0 ) + TKFRAME_-43307_AXES = ( 1, 2, 3 ) + TKFRAME_-43307_UNITS = 'DEGREES' + + \begintext + + +IMAP Solar Wind and Pickup Ion (SWAPI) Frames +======================================================================== + + SWAPI has the following nominal alignment to the spacecraft frame, + reference Table 1 of [6]. The azimuth and elevation angles are + illustrated in the 'IMAP I&T Component Placement' section near the + top of this document. + + azimuth | elevation + (deg) | (deg) + ---------+--------- + 168 | 0 + + The SWAPI base frame is defined in the instrument MICD [8] as follows: + + * -Z axis is the axis of symmetry of the instrument, pointing + away from the spacecraft body. + * +Y axis is along the aperture center, in the anti-sunward direction. + + Two views of the instrument are illustrated below. The diagram on the left + is looking down the top of the instrument towards the spacecraft body. The + diagram on the right is a side view of the instrument assembly. In both + diagrams the sunglasses aperture vanes point to the right (+Y direction). + The labeled coordinate axes are in the instrument reference frame. + + -Z' + +X' ^ + ^ _______|________ + | | | |---- + . ***|*** . | o---------------> +Y' + * | * .-' |________________|---- (towards + * | *.-' . ' ' . Sun) + * | * '--------------------' + * o----------> +Y' / \ + * * | | + * *'-. |\ /| | + *. .* `-. _|_|____|_|_ | + ******* | | | + | | v + spacecraft body | | spacecraft + behind page |____________| body + + + The nominal azimuth and elevation give the outward axis of symmetry, -Z in the + instrument frame: + + -Z = -[ -sin(az) * cos(el), cos(az) * cos(el), sin(el) ] + instr + + [17] provides measured values of the above nominal instrument alignment. The + following measured vectors are parallel to the spacecraft axes listed: + + -Y = Tophat Topplate Rib = [ -0.00142, -0.01019, -0.99995 ] + + -Z = Top of Aperture Grid Frame = [ -0.20761, -0.97821, 0.001128 ] + -Z = Top of Lower Outer ESA Mounting Flange = [ -0.20775, -0.97818, 0.00003 ] + + Since two measurements were taken for instrument -Z, we use their average. + The X axis completes the right-handed coordinate system. + + \begindata + + FRAME_IMAP_SWAPI = -43350 + FRAME_-43350_NAME = 'IMAP_SWAPI' + FRAME_-43350_CLASS = 4 + FRAME_-43350_CLASS_ID = -43350 + FRAME_-43350_CENTER = -43 + TKFRAME_-43350_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43350_SPEC = 'MATRIX' + TKFRAME_-43350_MATRIX = ( -0.978196569749791 + 0.207679902805407 + -0.000727255443315 + -0.000591151927685 + 0.000717413380944 + 0.999999567928626 + 0.207680334815652 + 0.978196577017512 + -0.000579000933447 ) + + \begintext + + +IMAP Compact Dual Ion Composition Experiment (CoDICE) Frames +======================================================================== + + CoDICE has the following nominal alignment to the spacecraft frame, + reference Table 1 of [6]. The azimuth and elevation angles are + illustrated in the 'IMAP I&T Component Placement' section near the + top of this document. + + azimuth | elevation + (deg) | (deg) + ---------+--------- + 136 | 0 + + + The CoDICE local coordinate system is defined [23] as follows: + + * -X is the axis of symmetry of the instrument, pointing + away from the spacecraft body. + * +Z is aligned with the spacecraft +Z axis + + A diagram of the CoDICE local coordinate system is shown below. + + -X' + ^ + ________|_______ + |________|_______| + \ | / + / | \ + | o----------> +Z' + \ / (towards Sun) + \ \ \ / / / + |''''''''''''| + | | | + | | | + | | | + | | | + | | v + | | spacecraft + | | body + |____________| + + The alignment measurements in [17] give the three axes of the + instrument coordinate system and are captured below. + + \begindata + + FRAME_IMAP_CODICE = -43400 + FRAME_-43400_NAME = 'IMAP_CODICE' + FRAME_-43400_CLASS = 4 + FRAME_-43400_CLASS_ID = -43400 + FRAME_-43400_CENTER = -43 + TKFRAME_-43400_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43400_SPEC = 'MATRIX' + TKFRAME_-43400_MATRIX = ( 0.695804588908984 + 0.718231138906051 + 0.000071825599991 + -0.717601202113529 + 0.696453711110183 + 0.000861978000136 + 0.000267138000086 + 0.000252966000082 + 0.999999932322743 ) + +\begintext + + +IMAP High-energy Ion Telescope (HIT) Frames +======================================================================== + + HIT has the following nominal alignment to the spacecraft frame, + reference Table 1 of [6]. The azimuth and elevation angles are + illustrated in the 'IMAP I&T Component Placement' section near the top + of this document. + + azimuth | elevation + (deg) | (deg) + ---------+--------- + 30 | 0 + + + The HIT local coordinate system is defined for convenience as follows: + + * +Y is the axis of symmetry of the instrument, pointing + away from the spacecraft body. + * +Z is aligned with Boresight Vector #2 in [21]. It is the + outward pointing vector in the center of the five-detector + grouping on the sunward side of the spacecraft. + + A diagram of the HIT local coordinate system is shown below. The ten + apertures are numbered for convenience and may not be consistent with + actual aperture names. + + There are two groups, or sectors, of apertures, A1-A5 and A5-A10. Each + group of five detectors spans a 130 degree field of view in the HIT XY + plane [21] and is located symmetrically on opposite sides of the sensor + head. Thus, each individual detector has a 130/5 = 26 degree field of + view in the HIT XY plane. The space between sectors is 50 degrees. + + + HIT local coordinate system + ---------------------------- + + S/C +Z axis +Z' + (facing Sun) ^ + ^ ` + | . + | ` + | | . + \ | A3` / + \ A2 | . / + A1 \ | ` / A4 + '-. \_..--+--.._/ .-' + '-. .' . '. .-' + 50 deg space ||'-..' ` ' .-' + between detector||||/ . \ A5 + groups A1-A5 ||||. ` . ___ + and A6-A10 ||||| . |---'''' + ___....---| o .... ||||||| 50 deg space + ' +Y'out) ```` '||||| + A10 \ /|||||``` --- + .-''. .''-.|| ````--> -X' + .-' '. .' '-. + .-' / ''--+--'' \ '-. + A9 / | \ A6 + / A8 | A7 \ + / | \ + | + + + [17] gives a measured value for the instrument +Y axis expressed + in the spacecraft coordinate system: + + +Y = [ -0.494627173, 0.869103932, -0.00152133 ] + + and the instrument -X axis: + + -X = [ -0.721687951, -0.411326605, -0.556755714 ] + + The +Z axis completes the right-handed coordinate system. + + \begindata + + FRAME_IMAP_HIT = -43500 + FRAME_-43500_NAME = 'IMAP_HIT' + FRAME_-43500_CLASS = 4 + FRAME_-43500_CLASS_ID = -43500 + FRAME_-43500_CENTER = -43 + TKFRAME_-43500_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43500_SPEC = 'MATRIX' + TKFRAME_-43500_MATRIX = ( 0.721525796505660 + 0.411611615432541 + 0.556755245164234 + -0.494627173165007 + 0.869103932289932 + -0.001521330000507 + -0.484504369994396 + -0.274288594220012 + 0.830675196774975 ) + + \begintext + + Each L1 aperture coordinate frame is defined as a rotation about the HIT + center axis (Y axis in the HIT local coordinate system): + + * +X is the aperture boresight, or outward pointing center vector. + * +Y is aligned with the HIT frame +Y. + + Note that for aperture L1 03, the boresight (aperture +X axis) is coaligned + with the HIT frame +Z axis, as shown in the diagram above. + + The rotations required to take the HIT +X axis to the aperture +Z axis are + described here and in the definitions below. + + Rotation about +Y + L1 Aperture from HIT frame + ----------- ------------------------------- + 01 50/2 + 26 * 4.5 = 142 degrees + 02 50/2 + 26 * 3.5 = 116 degrees + 03 50/2 + 26 * 2.5 = 90 degrees + 04 50/2 + 26 * 1.5 = 64 degrees + 05 50/2 + 26 * 0.5 = 38 degrees + 06 -50/2 - 26 * 0.5 = -38 degrees + 07 -50/2 - 26 * 1.5 = -64 degrees + 08 -50/2 - 26 * 2.5 = -90 degrees + 09 -50/2 - 26 * 3.5 = -116 degrees + 10 -50/2 - 26 * 4.5 = -142 degrees + + \begindata + + FRAME_IMAP_HIT_L1_APERTURE_01 = -43501 + FRAME_-43501_NAME = 'IMAP_HIT_L1_APERTURE_01' + FRAME_-43501_CLASS = 4 + FRAME_-43501_CLASS_ID = -43501 + FRAME_-43501_CENTER = -43 + TKFRAME_-43501_RELATIVE = 'IMAP_HIT' + TKFRAME_-43501_SPEC = 'ANGLES' + TKFRAME_-43501_ANGLES = ( 0, 142, 0 ) + TKFRAME_-43501_AXES = ( 1, 2, 3 ) + TKFRAME_-43501_UNITS = 'DEGREES' + + FRAME_IMAP_HIT_L1_APERTURE_02 = -43502 + FRAME_-43502_NAME = 'IMAP_HIT_L1_APERTURE_02' + FRAME_-43502_CLASS = 4 + FRAME_-43502_CLASS_ID = -43502 + FRAME_-43502_CENTER = -43 + TKFRAME_-43502_RELATIVE = 'IMAP_HIT' + TKFRAME_-43502_SPEC = 'ANGLES' + TKFRAME_-43502_ANGLES = ( 0, 116, 0 ) + TKFRAME_-43502_AXES = ( 1, 2, 3 ) + TKFRAME_-43502_UNITS = 'DEGREES' + + FRAME_IMAP_HIT_L1_APERTURE_03 = -43503 + FRAME_-43503_NAME = 'IMAP_HIT_L1_APERTURE_03' + FRAME_-43503_CLASS = 4 + FRAME_-43503_CLASS_ID = -43503 + FRAME_-43503_CENTER = -43 + TKFRAME_-43503_RELATIVE = 'IMAP_HIT' + TKFRAME_-43503_SPEC = 'ANGLES' + TKFRAME_-43503_ANGLES = ( 0, 90, 0 ) + TKFRAME_-43503_AXES = ( 1, 2, 3 ) + TKFRAME_-43503_UNITS = 'DEGREES' + + FRAME_IMAP_HIT_L1_APERTURE_04 = -43504 + FRAME_-43504_NAME = 'IMAP_HIT_L1_APERTURE_04' + FRAME_-43504_CLASS = 4 + FRAME_-43504_CLASS_ID = -43504 + FRAME_-43504_CENTER = -43 + TKFRAME_-43504_RELATIVE = 'IMAP_HIT' + TKFRAME_-43504_SPEC = 'ANGLES' + TKFRAME_-43504_ANGLES = ( 0, 64, 0 ) + TKFRAME_-43504_AXES = ( 1, 2, 3 ) + TKFRAME_-43504_UNITS = 'DEGREES' + + FRAME_IMAP_HIT_L1_APERTURE_05 = -43505 + FRAME_-43505_NAME = 'IMAP_HIT_L1_APERTURE_05' + FRAME_-43505_CLASS = 4 + FRAME_-43505_CLASS_ID = -43505 + FRAME_-43505_CENTER = -43 + TKFRAME_-43505_RELATIVE = 'IMAP_HIT' + TKFRAME_-43505_SPEC = 'ANGLES' + TKFRAME_-43505_ANGLES = ( 0, 38, 0 ) + TKFRAME_-43505_AXES = ( 1, 2, 3 ) + TKFRAME_-43505_UNITS = 'DEGREES' + + FRAME_IMAP_HIT_L1_APERTURE_06 = -43506 + FRAME_-43506_NAME = 'IMAP_HIT_L1_APERTURE_06' + FRAME_-43506_CLASS = 4 + FRAME_-43506_CLASS_ID = -43506 + FRAME_-43506_CENTER = -43 + TKFRAME_-43506_RELATIVE = 'IMAP_HIT' + TKFRAME_-43506_SPEC = 'ANGLES' + TKFRAME_-43506_ANGLES = ( 0, -38, 0 ) + TKFRAME_-43506_AXES = ( 1, 2, 3 ) + TKFRAME_-43506_UNITS = 'DEGREES' + + FRAME_IMAP_HIT_L1_APERTURE_07 = -43507 + FRAME_-43507_NAME = 'IMAP_HIT_L1_APERTURE_07' + FRAME_-43507_CLASS = 4 + FRAME_-43507_CLASS_ID = -43507 + FRAME_-43507_CENTER = -43 + TKFRAME_-43507_RELATIVE = 'IMAP_HIT' + TKFRAME_-43507_SPEC = 'ANGLES' + TKFRAME_-43507_ANGLES = ( 0, -64, 0 ) + TKFRAME_-43507_AXES = ( 1, 2, 3 ) + TKFRAME_-43507_UNITS = 'DEGREES' + + FRAME_IMAP_HIT_L1_APERTURE_08 = -43508 + FRAME_-43508_NAME = 'IMAP_HIT_L1_APERTURE_08' + FRAME_-43508_CLASS = 4 + FRAME_-43508_CLASS_ID = -43508 + FRAME_-43508_CENTER = -43 + TKFRAME_-43508_RELATIVE = 'IMAP_HIT' + TKFRAME_-43508_SPEC = 'ANGLES' + TKFRAME_-43508_ANGLES = ( 0, -90, 0 ) + TKFRAME_-43508_AXES = ( 1, 2, 3 ) + TKFRAME_-43508_UNITS = 'DEGREES' + + FRAME_IMAP_HIT_L1_APERTURE_09 = -43509 + FRAME_-43509_NAME = 'IMAP_HIT_L1_APERTURE_09' + FRAME_-43509_CLASS = 4 + FRAME_-43509_CLASS_ID = -43509 + FRAME_-43509_CENTER = -43 + TKFRAME_-43509_RELATIVE = 'IMAP_HIT' + TKFRAME_-43509_SPEC = 'ANGLES' + TKFRAME_-43509_ANGLES = ( 0, -116, 0 ) + TKFRAME_-43509_AXES = ( 1, 2, 3 ) + TKFRAME_-43509_UNITS = 'DEGREES' + + FRAME_IMAP_HIT_L1_APERTURE_10 = -43510 + FRAME_-43510_NAME = 'FRAME_IMAP_HIT_L1_APERTURE_10' + FRAME_-43510_CLASS = 4 + FRAME_-43510_CLASS_ID = -43510 + FRAME_-43510_CENTER = -43 + TKFRAME_-43510_RELATIVE = 'IMAP_HIT' + TKFRAME_-43510_SPEC = 'ANGLES' + TKFRAME_-43510_ANGLES = ( 0, -142, 0 ) + TKFRAME_-43510_AXES = ( 1, 2, 3 ) + TKFRAME_-43510_UNITS = 'DEGREES' + + + \begintext + + +IMAP Interstellar Dust Experiment (IDEX) Frames +======================================================================== + + IDEX is located on the -X side of the spacecraft as shown below. + + ------------- + | S/C +Z axis | + ----------------------- ------------- + | S/C +X axis into page | #-----# . + ----------------------- | LGA | /|\ + #-----# | + ___ _________|^|______|__________________ + | |====================|__________________|_____________ __ _|SWAPI + '---' MAG boom \ __ | | | // \ /--|# + |( )=|__|| | | \\__/ \--|# + | HIT | _|_ IDEX | CODICE | + | | ,.' | '., | | + | ____ | [ \ | / ] | SWE| + ULTRA ##',', |,.'|'.,| GLOWS (#)| + 45 ####'. + | + \\(O) |-|| + '----####/----- + | + --------------' + <---------------- | | \______'-.O.-'______/ | | + ------------- /_\ ----------- |__| + | S/C +Y axis | #-----# | S/C FRAME | STAR + ------------- | MGA | | ORIGIN | TRACKERS + #-----# ----------- + + IDEX has the following nominal alignment to the spacecraft frame, + reference Table 1 of [6]. The azimuth and elevation angles are + illustrated in the 'IMAP I&T Component Placement' section near the + top of this document. + + azimuth | elevation + (deg) | (deg) + ---------+--------- + +90 | -45 + + The local IDEX frame is defined in [22]: + * +Y axis is the boresight, pointing outward through the opening along + the instrument axis of symmetry + * +Z axis is in the direction of S/C +Z + + [17] gives the measured value of the +Y axis of the IDEX coordinate + system: + + +Y = [ 0.683178772 -0.185278978 -0.706355764 ] + + Instrument +Z is aligned with spacecraft +Z: + + +Z = [ 0 0 1 ] + + The IDEX +X axis is determined from the cross product. By adjusting the +Z + axis and normalizing, we arrive at the following definition. + + \begindata + + FRAME_IMAP_IDEX = -43700 + FRAME_-43700_NAME = 'IMAP_IDEX' + FRAME_-43700_CLASS = 4 + FRAME_-43700_CLASS_ID = -43700 + FRAME_-43700_CENTER = -43 + TKFRAME_-43700_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43700_SPEC = 'MATRIX' + TKFRAME_-43700_MATRIX = ( 0.001346490209331 + 0.999999093481647 + 0.000000000000000 + -0.707321249357286 + 0.000952402000481 + -0.706891606357069 + -0.706890965546854 + 0.000951822627018 + 0.707321890557561 ) + + \begintext + + The following frames are defined as identity offsets off the IDEX frame. + + + \begindata + + FRAME_IMAP_IDEX_DETECTOR = -43701 + FRAME_-43701_NAME = 'IMAP_IDEX_DETECTOR' + FRAME_-43701_CLASS = 4 + FRAME_-43701_CLASS_ID = -43701 + FRAME_-43701_CENTER = -43 + TKFRAME_-43701_RELATIVE = 'IMAP_IDEX' + TKFRAME_-43701_SPEC = 'MATRIX' + TKFRAME_-43701_MATRIX = ( 1.0 + 0.0 + 0.0 + 0.0 + 1.0 + 0.0 + 0.0 + 0.0 + 1.0 ) + + FRAME_IMAP_IDEX_FULL_SCIENCE= -43702 + FRAME_-43702_NAME = 'IMAP_IDEX_FULL_SCIENCE' + FRAME_-43702_CLASS = 4 + FRAME_-43702_CLASS_ID = -43702 + FRAME_-43702_CENTER = -43 + TKFRAME_-43702_RELATIVE = 'IMAP_IDEX' + TKFRAME_-43702_SPEC = 'MATRIX' + TKFRAME_-43702_MATRIX = ( 1.0 + 0.0 + 0.0 + 0.0 + 1.0 + 0.0 + 0.0 + 0.0 + 1.0 ) + + \begintext + + +IMAP GLObal solar Wind Structure (GLOWS) Frames +======================================================================== + + GLOWS has the following nominal alignment to the spacecraft frame, + reference Table 1 of [6]. The azimuth and elevation angles are + illustrated in the 'IMAP I&T Component Placement' section near the top + of this document. + + azimuth | elevation + (deg) | (deg) + ---------+--------- + 127 | 15 + + The GLOWS base frame is defined by the instrument team as follows [10]: + + * +Z axis points in the anti-boresight direction + * +Y axis points in the anti-sunward direction (towards S/C -Z) + + A diagram of the GLOWS local coordinate system is shown below. + ______________________ + | | .-'| __ -Z' + S/C +Z | | .-' | _.-*/ + (sunward) | | .-' |.-*' + ^ | | _.-*'\ _.-*'| + | | '.-*' _.-*' | + | | \ o*' \ _.-' + | | \ \_.-*' ' + | \.-*'\ + |________________________| \ + \ + v +Y' + + The azimuth and elevation give the nominal outward axis of symmetry, + -Z in the instrument frame: + + Z = -[ -sin(az) * cos(el), cos(az) * cos(el), sin(el) ] + instr + + The alignment report [17] gives the measured outward axis of symmetry, + -Z in the instrument frame: + + -Z = [ -0.7699232700, -0.5831000067, 0.2592538148 ] + instr + + The instrument +Y axis is in the anti-sunward direction, towards the + spacecraft -Z axis: + + Y = [ 0 0 -1 ] + instr + + Taking the cross product and normalizing, we arrive at the instrument +X + axis: + Y x Z + X = --------- + instr | Y x Z | + + And adjusting Y: + + Z x X + Y = --------- + instr | Z x X | + + This definition is captured in the keywords below. + + \begindata + + FRAME_IMAP_GLOWS = -43750 + FRAME_-43750_NAME = 'IMAP_GLOWS' + FRAME_-43750_CLASS = 4 + FRAME_-43750_CLASS_ID = -43750 + FRAME_-43750_CENTER = -43 + TKFRAME_-43750_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43750_SPEC = 'MATRIX' + TKFRAME_-43750_MATRIX = ( 0.603742428089898 + -0.797179453149737 + 0.000000000000000 + -0.206671814310344 + -0.156522527639751 + -0.965809225215277 + 0.769923270000000 + 0.583100006700000 + -0.259253814800000 ) + +\begintext + +End of FK file. \ No newline at end of file diff --git a/imap_processing/tests/spice/test_data/imap_science_120.tf b/imap_processing/tests/spice/test_data/imap_science_120.tf new file mode 100644 index 0000000000..2a39657f34 --- /dev/null +++ b/imap_processing/tests/spice/test_data/imap_science_120.tf @@ -0,0 +1,1105 @@ +KPL/FK + +Interstellar Mapping and Acceleration Probe (IMAP) Dynamic Frames Kernel +======================================================================== + + This kernel contains SPICE frame definitions to support the + IMAP mission. + + This kernel is composed of primarily dynamic frames, but in general + it holds frame definitions for all instrument-agnostic frames, CK + frames used in science data processing and mapping. + + +Version and Date +------------------------------------------------------------------------ + + The TEXT_KERNEL_ID stores version information of loaded project + text kernels. Each entry associated with the keyword is a string + that consists of four parts: the kernel name, version, entry date, + and type. + + IMAP Dynamic Frame Kernel Version: + + \begindata + + TEXT_KERNEL_ID = 'IMAP_DYNAMIC_FRAMES V0.0.1 2025-JUNE-26 FK' + + \begintext + + Version 0.0.0 -- April 10, 2024 -- Nick Dutton (JHU/APL) + Version 0.0.1 -- June 26, 2025 -- Nick Dutton (JHU/APL) + Version 1.0.0 -- July 8, 2025 -- Nick and Doug (JHU/APL) + Version 1.1.0 -- Nov 19, 2025 -- Nick and Doug (JHU/APL) + Version 1.2.0 -- Feb. 24, 2026 -- Nick and Doug (JHU/APL) + + +References +------------------------------------------------------------------------ + + 1. NAIF SPICE `Kernel Pool Required Reading' + + 2. NAIF SPICE `Frames Required Reading' + + 3. "IMAP Coordinate Frame Science.pdf" + + 4. stereo_rtn.tf, at + https://soho.nascom.nasa.gov/solarsoft/stereo/... + ...gen/data/spice/gen/stereo_rtn.tf + + 5. heliospheric.tf, at + https://soho.nascom.nasa.gov/solarsoft/stereo/... + ...gen/data/spice/gen/heliospheric.tf + + 6. "Geophysical Coordinate Transformations", C. T. Russell + + 7. "Heliospheric Coordinate Systems", M. Franz and D. Harper + + 8. "Global observations of the interstellar interaction from the + Interstellar Boundary Explorer (IBEX)", D. J. McComas, et al. + + 9. "Very Local Interstellar Medium Revealed by a Complete Solar + Cycle of Interstellar Neutral Helium Observations with IBEX", + P. Swaczyna, et al. + + 10. Lagrange L1 definition and SPK, Min-Kun Chung, + https://naif.jpl.nasa.gov/pub/naif/... + ...generic_kernels/spk/lagrange_point/ + + 11. "Variability in the Position of the IBEX Ribbon over Nine Years: + More Observational Evidence for a Secondary ENA Source", M. A. + Dayeh, et al. + + +Contact Information +------------------------------------------------------------------------ + + Direct questions, comments, or concerns about the contents of this + kernel to: + + Nick Dutton, JHUAPL, Nicholas.Dutton@jhuapl.edu + + or + + Doug Rodgers, JHUAPL, Douglas.Rodgers@jhuapl.edu + + or + + Lillian Nguyen, JHUAPL, Lillian.Nguyen@jhuapl.edu + + +Implementation Notes +------------------------------------------------------------------------ + + This file is used by the SPICE system as follows: programs that make + use of this frame kernel must `load' the kernel normally during + program initialization. Loading the kernel associates the data items + with their names in a data structure called the `kernel pool'. The + SPICELIB routine FURNSH loads a kernel into the pool as shown below: + + Python: (SpiceyPy) + + spiceypy.furnsh( frame_kernel_name ) + + IDL: (ICY) + + cspice_furnsh, frame_kernel_name + + MATLAB: (MICE) + + cspice_furnsh ( frame_kernel_name ) + + C: (CSPICE) + + furnsh_c ( frame_kernel_name ); + + FORTRAN: (SPICELIB) + + CALL FURNSH ( frame_kernel_name ) + + This file was created, and may be updated with, a text editor or word + processor. + + +IMAP Science Frames +======================================================================== + + This frame kernel defines a series of frames listed in [3] that + support IMAP data reduction and analysis. All of the frame names + assigned an IMAP NAIF ID (beginning with -43) defined by this kernel + are prefixed with 'IMAP_' to avoid conflict with alternative + definitions not specific to the project. + + The project-specific ID codes -43900 to -43999 have been set aside to + support these dynamic frames. + + + Frame Name Relative To Type NAIF ID + ====================== =============== ======== ======= + + IMAP Based Frames: + ---------------------- + IMAP_OMD IMAP_SPACECRAFT FIXED -43900 + IMAP_DPS [n/a] CK -43901 + + Earth Based Frames: + ---------------------- + IMAP_EARTHFIXED IAU_EARTH FIXED -43910 + IMAP_ECLIPDATE J2000 DYNAMIC -43911 + IMAP_MDI ECLIPJ2000 FIXED -43912 + IMAP_MDR J2000 DYNAMIC -43913 + IMAP_GMC IAU_EARTH DYNAMIC -43914 + IMAP_GEI J2000 FIXED -43915 + IMAP_GSE J2000 DYNAMIC -43916 + IMAP_GSM J2000 DYNAMIC -43917 + IMAP_SMD J2000 DYNAMIC -43918 + + Sun Based Frames: + ---------------------- + IMAP_RTN J2000 DYNAMIC -43920 + IMAP_HCI (ie, HGI_J2K) J2000 DYNAMIC -43921 + IMAP_HCD (ie, HGI_D) J2000 DYNAMIC -43922 + IMAP_HGC (ie, HGS_D) IAU_SUN FIXED -43923 + IMAP_HAE ECLIPJ2000 FIXED -43924 + IMAP_HAED IMAP_ECLIPDATE FIXED -43925 + IMAP_HEE J2000 DYNAMIC -43926 + IMAP_HRE J2000 DYNAMIC -43927 + IMAP_HNU J2000 DYNAMIC -43928 + IMAP_GCS GALACTIC FIXED -43929 + IMAP_HRC ECLIPJ2000. FIXED. -43930 + + +IMAP Based Frames +======================================================================== + + These dynamic frames are used for analyzing data in a reference + frame tied to the dynamics of IMAP. + + + Observatory Mechanical Design (OMD) Frame ([3]) + --------------------------------------------------------------------- + + Alias for IMAP_SPACECRAFT frame defined in the primary + 'imap_vNNN.tf' frame kernel. From that file: + + Origin: Center of the launch vehicle adapter ring at the + observatory/launch vehicle interface plane + + +Z axis: Perpendicular to the launch vehicle interface plane + pointed in the direction of the top deck (runs through + the center of the central cylinder structure element) + + +Y axis: Direction of the vector orthogonal to the +Z axis and + parallel to the deployed MAG boom + + +X axis: The third orthogonal axis defined using an X, Y, Z + ordered right hand rule + + \begindata + + FRAME_IMAP_OMD = -43900 + FRAME_-43900_NAME = 'IMAP_OMD' + FRAME_-43900_CLASS = 4 + FRAME_-43900_CLASS_ID = -43900 + FRAME_-43900_CENTER = -43 + TKFRAME_-43900_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43900_SPEC = 'MATRIX' + TKFRAME_-43900_MATRIX = ( 1 0 0 + 0 1 0 + 0 0 1 ) + + \begintext + + + Despun Pointing Sets (DPS) Frame ([3]) + --------------------------------------------------------------------- + + Coordinate frame used for ENA imager data processing and + intentionally designed for use in producing all-sky map products. + + This is provided by a CK file external to this file. Notionally, + the frame is defined: + + +Z axis is parallel to the nominal spin axis of the spacecraft. + The axis is notionally a time-average of the spin axis of the + exact orientation (IMAP_SPACECRAFT or IMAP_OMD). + + Y = Z cross Necliptic where Necliptic is the the unit normal + (North) to the ecliptic plane. + + This is a quasi-inertial reference frame and will have a unique + transformation matrix, valid between repointings of the spacecraft + + \begindata + + FRAME_IMAP_DPS = -43901 + FRAME_-43901_NAME = 'IMAP_DPS' + FRAME_-43901_CLASS = 3 + FRAME_-43901_CLASS_ID = -43901 + FRAME_-43901_CENTER = -43 + CK_-43901_SCLK = -43 + CK_-43901_SPK = -43 + + \begintext + + +Earth Based Frames +======================================================================== + + These dynamic frames are used for analyzing data in a reference + frame tied to the dynamics of Earth. + + + Earth-Fixed Frame (IMAP_EARTHFIXED) + --------------------------------------------------------------------- + + Some of these Earth based dynamic frames reference vectors in an + Earth-fixed frame. To support loading of either rotation model + (IAU_EARTH or ITRF93), the following keywords control which model + is used. The model is enabled by surrounding its keyword-value + block with the \begindata and \begintext markers (currently + IAU_EARTH). + + IAU_EARTH based model is currently employed: + + \begindata + + FRAME_IMAP_EARTHFIXED = -43910 + FRAME_-43910_NAME = 'IMAP_EARTHFIXED' + FRAME_-43910_CLASS = 4 + FRAME_-43910_CLASS_ID = -43910 + FRAME_-43910_CENTER = 399 + TKFRAME_-43910_RELATIVE = 'IAU_EARTH' + TKFRAME_-43910_SPEC = 'MATRIX' + TKFRAME_-43910_MATRIX = ( 1 0 0 + 0 1 0 + 0 0 1 ) + + \begintext + + Alternately, the more precise ITRF93-based model could be used: + + FRAME_IMAP_EARTHFIXED = -43910 + FRAME_-43910_NAME = 'IMAP_EARTHFIXED' + FRAME_-43910_CLASS = 4 + FRAME_-43910_CLASS_ID = -43910 + FRAME_-43910_CENTER = 399 + TKFRAME_-43910_RELATIVE = 'ITRF93' + TKFRAME_-43910_SPEC = 'MATRIX' + TKFRAME_-43910_MATRIX = ( 1 0 0 + 0 1 0 + 0 0 1 ) + + However, using the ITRF93 frame requires supplying SPICE with + sufficient binary PCK data to cover the period of interest. + The IAU_EARTH frame just requires a text PCK with Earth data + to be loaded. + + + Mean Ecliptic of Date (IMAP_ECLIPDATE) ([2],[5]) + --------------------------------------------------------------------- + + Mean Ecliptic of Date is the more precise, rotating counterpart + to the inertial Mean Ecliptic and Equinox of J2000 (ECLIPJ2000). + + If computations involving this frame (or frames relative to this) + are too expensive, the user may instruct SPICE to ignore + rotational effects by changing 'ROTATING' to 'INERTIAL'. + + The X axis is the first point in Aries for the mean ecliptic of + date and the Z axis points along the ecliptic north pole. + + The Y axis is Z cross X, completing the right-handed reference + frame. + + \begindata + + FRAME_IMAP_ECLIPDATE = -43911 + FRAME_-43911_NAME = 'IMAP_ECLIPDATE' + FRAME_-43911_CLASS = 5 + FRAME_-43911_CLASS_ID = -43911 + FRAME_-43911_CENTER = 399 + FRAME_-43911_RELATIVE = 'J2000' + FRAME_-43911_DEF_STYLE = 'PARAMETERIZED' + FRAME_-43911_FAMILY = 'MEAN_ECLIPTIC_AND_EQUINOX_OF_DATE' + FRAME_-43911_PREC_MODEL = 'EARTH_IAU_1976' + FRAME_-43911_OBLIQ_MODEL = 'EARTH_IAU_1980' + FRAME_-43911_ROTATION_STATE = 'ROTATING' + + \begintext + + + Mission Design Inertial (MDI) Frame ([3]) + --------------------------------------------------------------------- + + Alias for SPICE ECLIPJ2000. + + Primary coordinate frame used to define IMAP's trajectory and + orbit, as well as for some science data products. + + The X axis is the first point in Aries for the mean ecliptic of + J2000 and the Z axis points along the ecliptic north pole. + + The Y axis is Z cross X, completing the right-handed reference + frame. + + \begindata + + FRAME_IMAP_MDI = -43912 + FRAME_-43912_NAME = 'IMAP_MDI' + FRAME_-43912_CLASS = 4 + FRAME_-43912_CLASS_ID = -43912 + FRAME_-43912_CENTER = 399 + TKFRAME_-43912_RELATIVE = 'IMAP_EARTHFIXED' + TKFRAME_-43912_SPEC = 'MATRIX' + TKFRAME_-43912_MATRIX = ( 1 0 0 + 0 1 0 + 0 0 1 ) + + \begintext + + + Mission Design Rotating (MDR) Frame ([3],[10]) + --------------------------------------------------------------------- + + IMAP observatory body coordinate frame. + + The origin of the frame is the L1 point of the Sun and the Earth- + Moon barycenter defined in SPK 'L1_de431.bsp' by reference [10]; + this author assigned the NAIF body code 391 to this L1 point. + + The position of the Earth-Moon barycenter relative to the Sun is + the primary vector: the X axis points from the Sun to the + Earth-Moon barycenter. + + The northern surface normal to the mean ecliptic of date is the + secondary vector: the Z axis is the component of this vector + orthogonal to the X axis. Combined with the definition of the + X axis, this yields a unit vector along the angular momentum + vector of the Earth-Moon barycenter orbiting the Sun. + + The Y axis is Z cross X, completing the right-handed reference + frame. + + All vectors are geometric: no aberration corrections are used. + + \begindata + + FRAME_IMAP_MDR = -43913 + FRAME_-43913_NAME = 'IMAP_MDR' + FRAME_-43913_CLASS = 5 + FRAME_-43913_CLASS_ID = -43913 + FRAME_-43913_CENTER = 391 + FRAME_-43913_RELATIVE = 'J2000' + FRAME_-43913_DEF_STYLE = 'PARAMETERIZED' + FRAME_-43913_FAMILY = 'TWO-VECTOR' + FRAME_-43913_PRI_AXIS = 'X' + FRAME_-43913_PRI_VECTOR_DEF = 'OBSERVER_TARGET_POSITION' + FRAME_-43913_PRI_OBSERVER = 'SUN' + FRAME_-43913_PRI_TARGET = 'EARTH MOON BARYCENTER' + FRAME_-43913_PRI_ABCORR = 'NONE' + FRAME_-43913_SEC_AXIS = 'Z' + FRAME_-43913_SEC_VECTOR_DEF = 'CONSTANT' + FRAME_-43913_SEC_FRAME = 'IMAP_ECLIPDATE' + FRAME_-43913_SEC_SPEC = 'RECTANGULAR' + FRAME_-43913_SEC_VECTOR = ( 0, 0, 1 ) + + \begintext + + + Geomagnetic Coordinate (GMC) Frame (IGRF-14 Modeled Pole) ([6]) + --------------------------------------------------------------------- + + The geomagnetic coordinate (GMC) system is defined so that its + Z-axis is parallel to the magnetic dipole. The geographic + coordinates, D, of the dipole axis are found from the + International Geomagnetic Reference Field. + + The Y-axis of this system is perpendicular to the geographic poles + such that if D is the dipole position and S is the south pole + Y=DxS. The X-axis completes a right-handed orthogonal set. + + The implementation of this frame is complicated in that the + definition of the IGRF dipole is a function of time and the IGRF + model cannot be directly incorporated into SPICE. However, SPICE + does allow one to define time dependent Euler angles. Meaning, you + can define a single Euler angle that rotates the Geocentric + Equatorial Inertial (GEI) system to GMC for a given ephem time t: + + V = r(t) * V + GEI GMC + + where r(t) is a time dependent Euler angle representation of a + rotation. SPICE allows for the time dependence to be represented + by a polynomial expansion. This expansion can be fit using the + IGRF model, thus representing the IGRF dipole axis. + + IGRF-14 (the 14th version) was fit for the period of 1990-2035, + which encompasses the mission and will also make this kernel + useful for performing Magnetic dipole frame transformations for + the 1990's and the 2000's. However, IGRF-14 is not as accurate for + this entire time interval. The years between 1945-2020 are labeled + definitive, although only back to 1990 was used in the polynomial + fit. 2020-2025 is provisional, and may change with IGRF-15. + 2025-2030 was only a prediction. Beyond 2030, the predict is so + far in the future as to not be valid. So to make the polynomials + behave nicely in this region (in case someone does try to use this + frame during that time), the 2030 prediction was extended until + 2035. So for low precision, this kernel can be used for the years + 2025-2035. Any times less than 1990 and greater than 2035 were not + used in the fit, and therefore may be vastly incorrect as the + polynomials may diverge outside of this region. These coefficients + will be refit when IGRF-15 is released. + + Also, since the rest of the magnetic dipole frames are defined + from this one, similar time ranges should be used for those frames + + Definitive Provisional Predict Not Valid + |--------------------------|+++++++++++|###########|???????????| + 1990 2020 2025 2030 2035 + + In addition to the error inherit in the model itself, the + polynomial expansion cannot perfectly be fit the IGRF dipole. The + maximum error on the fit is 0.2 milliradians, or 0.01 degrees, + while the average error is 59 microradians or 0.003 degrees. + + The GMC frame is achieved by first rotating the IAU_EARTH frame + about Z by the longitude degrees, and then rotating about the + Y axis by the amount of latitude. + + NOTE: ITRF93 is much more accurate than IAU_EARTH, if precise + Earth-Fixed coordinates are desired, then ITRF93 should be + incorporated by changing RELATIVE of the IMAP_EARTHFIXED frame. + + \begindata + + FRAME_IMAP_GMC = -43914 + FRAME_-43914_NAME = 'IMAP_GMC' + FRAME_-43914_CLASS = 5 + FRAME_-43914_CLASS_ID = -43914 + FRAME_-43914_CENTER = 399 + FRAME_-43914_RELATIVE = 'IMAP_EARTHFIXED' + FRAME_-43914_DEF_STYLE = 'PARAMETERIZED' + FRAME_-43914_FAMILY = 'EULER' + FRAME_-43914_EPOCH = @2010-JAN-1/00:00:00 + FRAME_-43914_AXES = ( 3, 2, 1 ) + FRAME_-43914_UNITS = 'DEGREES' + FRAME_-43914_ANGLE_1_COEFFS = ( +72.21459071369075 + +2.5468902895893966E-9 + -9.716151847392007E-19 + -1.0433860683683533E-26 + +2.362766949492718E-36 + +3.3213862072412154E-44 + -3.5122239525813096E-54 + -4.264324158308002E-62 + +2.495064964115813E-72 + +1.8605789215176264E-80 ) + FRAME_-43914_ANGLE_2_COEFFS = ( -9.981781660857344 + +1.8136204417470554E-9 + +7.130241121790372E-19 + -2.215929597148403E-27 + -3.900143352851885E-36 + +6.599160686982152E-45 + +8.376429421972708E-54 + -1.07431639798394E-62 + -5.913960690205374E-72 + +6.775302680782905E-81 ) + FRAME_-43914_ANGLE_3_COEFFS = ( 0 ) + + \begintext + + + Geocentric Equatorial Inertial (GEI) Frame ([3],[6]) + --------------------------------------------------------------------- + + Alias for SPICE J2000 frame. + + The Geocentric Equatorial Inertial System (GEI) has its X-axis + pointing from the Earth towards the first point of Aries (the + position of the Sun at the vernal equinox). This direction is the + intersection of the Earth's equatorial plane and the ecliptic + plane and thus the X-axis lies in both planes. The Z-axis is + parallel to the rotation axis of the Earth and Y completes the + right-handed orthogonal set (Y = Z x X). + + \begindata + + FRAME_IMAP_GEI = -43915 + FRAME_-43915_NAME = 'IMAP_GEI' + FRAME_-43915_CLASS = 4 + FRAME_-43915_CLASS_ID = -43915 + FRAME_-43915_CENTER = 399 + TKFRAME_-43915_RELATIVE = 'J2000' + TKFRAME_-43915_SPEC = 'MATRIX' + TKFRAME_-43915_MATRIX = ( 1 0 0 + 0 1 0 + 0 0 1 ) + + \begintext + + + Geocentric Solar Ecliptic (GSE) Frame ([3],[5]) + --------------------------------------------------------------------- + + Rotating geocentric frame in which Sun and Earth are fixed and the + Z axis is the unit normal to the Ecliptic plane. + + The position of the Sun relative to the Earth is the primary + vector: the X axis points from the Earth to the Sun. + + The northern surface normal to the mean ecliptic of date + (IMAP_ECLIPDATE) is the secondary vector: the Z axis is the + component of this vector orthogonal to the X axis. + + The Y axis is Z cross X, completing the right-handed frame. + + All vectors are geometric: no aberration corrections are used. + + \begindata + + FRAME_IMAP_GSE = -43916 + FRAME_-43916_NAME = 'IMAP_GSE' + FRAME_-43916_CLASS = 5 + FRAME_-43916_CLASS_ID = -43916 + FRAME_-43916_CENTER = 399 + FRAME_-43916_RELATIVE = 'J2000' + FRAME_-43916_DEF_STYLE = 'PARAMETERIZED' + FRAME_-43916_FAMILY = 'TWO-VECTOR' + FRAME_-43916_PRI_AXIS = 'X' + FRAME_-43916_PRI_VECTOR_DEF = 'OBSERVER_TARGET_POSITION' + FRAME_-43916_PRI_OBSERVER = 'EARTH' + FRAME_-43916_PRI_TARGET = 'SUN' + FRAME_-43916_PRI_ABCORR = 'NONE' + FRAME_-43916_SEC_AXIS = 'Z' + FRAME_-43916_SEC_VECTOR_DEF = 'CONSTANT' + FRAME_-43916_SEC_FRAME = 'IMAP_ECLIPDATE' + FRAME_-43916_SEC_SPEC = 'RECTANGULAR' + FRAME_-43916_SEC_VECTOR = ( 0, 0, 1 ) + + \begintext + + + Geocentric Solar Magnetospheric (GSM) Frame ([3],[5],[6]) + --------------------------------------------------------------------- + + Rotating geocentric frame in which Sun and Earth are fixed and the + XZ plane contains Earth's magnetic dipole moment. Specifically, + the dipole moment will vary in the XZ plane about the Z axis of + this frame. + + The position of the Sun relative to the Earth is the primary + vector: the X axis points from the Earth to the Sun. + + Earth's magnetic dipole axis (the +Z axis of IMAP_GMC) is the + secondary vector: the Z axis is the component of this vector + orthogonal to the X axis. + + The Y axis is Z cross X, completing the right-handed frame. + + All vectors are geometric: no aberration corrections are used. + + \begindata + + FRAME_IMAP_GSM = -43917 + FRAME_-43917_NAME = 'IMAP_GSM' + FRAME_-43917_CLASS = 5 + FRAME_-43917_CLASS_ID = -43917 + FRAME_-43917_CENTER = 399 + FRAME_-43917_RELATIVE = 'J2000' + FRAME_-43917_DEF_STYLE = 'PARAMETERIZED' + FRAME_-43917_FAMILY = 'TWO-VECTOR' + FRAME_-43917_PRI_AXIS = 'X' + FRAME_-43917_PRI_VECTOR_DEF = 'OBSERVER_TARGET_POSITION' + FRAME_-43917_PRI_OBSERVER = 'EARTH' + FRAME_-43917_PRI_TARGET = 'SUN' + FRAME_-43917_PRI_ABCORR = 'NONE' + FRAME_-43917_SEC_AXIS = 'Z' + FRAME_-43917_SEC_VECTOR_DEF = 'CONSTANT' + FRAME_-43917_SEC_FRAME = 'IMAP_GMC' + FRAME_-43917_SEC_SPEC = 'RECTANGULAR' + FRAME_-43917_SEC_VECTOR = (0, 0, 1) + + \begintext + + + Solar Magnetic of Date (SMD) Frame ([3],[5],[6]) + --------------------------------------------------------------------- + + Rotating geocentric frame in which the Z axis is aligned with + Earth's magnetic dipole moment, and the XZ plane contains the + Earth-Sun vector. Specifically, the Earth-Sun vector will vary in + the XZ plane about the X axis of this frame. + + Earth's magnetic dipole axis (the +Z axis of IMAP_GMC) is the + primary vector and aligns with the Z axis of this frame. + + The position of the Sun relative to the Earth is the secondary + vector: the X axis is the component of the Earth-Sun vector + orthogonal to the Z axis. + + The Y axis is Z cross X, completing the right-handed frame. + + All vectors are geometric: no aberration corrections are used. + + \begindata + + FRAME_IMAP_SMD = -43918 + FRAME_-43918_NAME = 'IMAP_SMD' + FRAME_-43918_CLASS = 5 + FRAME_-43918_CLASS_ID = -43918 + FRAME_-43918_CENTER = 399 + FRAME_-43918_RELATIVE = 'J2000' + FRAME_-43918_DEF_STYLE = 'PARAMETERIZED' + FRAME_-43918_FAMILY = 'TWO-VECTOR' + FRAME_-43918_PRI_AXIS = 'Z' + FRAME_-43918_PRI_VECTOR_DEF = 'CONSTANT' + FRAME_-43918_PRI_FRAME = 'IMAP_GMC' + FRAME_-43918_PRI_SPEC = 'RECTANGULAR' + FRAME_-43918_PRI_VECTOR = (0, 0, 1) + FRAME_-43918_SEC_AXIS = 'X' + FRAME_-43918_SEC_VECTOR_DEF = 'OBSERVER_TARGET_POSITION' + FRAME_-43918_SEC_OBSERVER = 'EARTH' + FRAME_-43918_SEC_TARGET = 'SUN' + FRAME_-43918_SEC_ABCORR = 'NONE' + + \begintext + + +Sun Based Frames +======================================================================== + + These dynamic frames are used for analyzing data in a reference + frame tied to the dynamics of the Sun. + + + Heliocentric Radial Tangential Normal (RTN) Frame ([3],[7]) + --------------------------------------------------------------------- + + The position of the spacecraft relative to the Sun is the primary + vector: the X axis points from the Sun center to the spacecraft. + + The solar rotation axis is the secondary vector: the Z axis is + the component of the solar north direction perpendicular to X. + + The Y axis is Z cross X, completing the right-handed reference + frame. + + All vectors are geometric: no aberration corrections are used. + + \begindata + + FRAME_IMAP_RTN = -43920 + FRAME_-43920_NAME = 'IMAP_RTN' + FRAME_-43920_CLASS = 5 + FRAME_-43920_CLASS_ID = -43920 + FRAME_-43920_CENTER = 10 + FRAME_-43920_RELATIVE = 'J2000' + FRAME_-43920_DEF_STYLE = 'PARAMETERIZED' + FRAME_-43920_FAMILY = 'TWO-VECTOR' + FRAME_-43920_PRI_AXIS = 'X' + FRAME_-43920_PRI_VECTOR_DEF = 'OBSERVER_TARGET_POSITION' + FRAME_-43920_PRI_OBSERVER = 'SUN' + FRAME_-43920_PRI_TARGET = 'IMAP' + FRAME_-43920_PRI_ABCORR = 'NONE' + FRAME_-43920_PRI_FRAME = 'IAU_SUN' + FRAME_-43920_SEC_AXIS = 'Z' + FRAME_-43920_SEC_VECTOR_DEF = 'CONSTANT' + FRAME_-43920_SEC_FRAME = 'IAU_SUN' + FRAME_-43920_SEC_SPEC = 'RECTANGULAR' + FRAME_-43920_SEC_VECTOR = ( 0, 0, 1 ) + + \begintext + + + Heliocentric Inertial (HCI) Frame ([3],[5],[7]) + --------------------------------------------------------------------- + + Referred to as "Heliographic Inertial (HGI) frame at epoch J2000" + in [3], but named as in [7] to avoid confusion with HGI of J1900. + + The X-Y Plane lies in the solar equator, +Z axis is parallel to + the Sun's rotation vector. + + The solar rotation axis is the primary vector: the Z axis points + in the solar north direction. + + The ascending node on the Earth ecliptic of J2000 of the solar + equator forms the X axis. This is accomplished by using the +Z + axis of the ecliptic of J2000 as the secondary vector and HCI +Y + as the secondary axis. + + The Y axis is Z cross X, completing the right-handed reference + frame. + + \begindata + + FRAME_IMAP_HCI = -43921 + FRAME_-43921_NAME = 'IMAP_HCI' + FRAME_-43921_CLASS = 5 + FRAME_-43921_CLASS_ID = -43921 + FRAME_-43921_CENTER = 10 + FRAME_-43921_RELATIVE = 'J2000' + FRAME_-43921_DEF_STYLE = 'PARAMETERIZED' + FRAME_-43921_FAMILY = 'TWO-VECTOR' + FRAME_-43921_PRI_AXIS = 'Z' + FRAME_-43921_PRI_VECTOR_DEF = 'CONSTANT' + FRAME_-43921_PRI_FRAME = 'IAU_SUN' + FRAME_-43921_PRI_SPEC = 'RECTANGULAR' + FRAME_-43921_PRI_VECTOR = ( 0, 0, 1 ) + FRAME_-43921_SEC_AXIS = 'Y' + FRAME_-43921_SEC_VECTOR_DEF = 'CONSTANT' + FRAME_-43921_SEC_FRAME = 'ECLIPJ2000' + FRAME_-43921_SEC_SPEC = 'RECTANGULAR' + FRAME_-43921_SEC_VECTOR = ( 0, 0, 1 ) + + \begintext + + + Heliocentric of Date (HCD) Frame ([3],[5],[7]) + --------------------------------------------------------------------- + + Referred to as "Heliographic Inertial (HGI) frame true to + reference date" in [3], but named as in [7] without "inertial." + + The X-Y Plane lies in the solar equator, +Z axis is parallel to + the Sun's rotation vector. + + The solar rotation axis is the primary vector: the Z axis points + in the solar north direction. + + The ascending node on the Earth ecliptic of date of the solar + equator forms the X axis. This is accomplished by using the +Z + axis of the ecliptic of date as the secondary vector and HCD +Y + as the secondary axis. + + The Y axis is Z cross X, completing the right-handed reference + frame. + + \begindata + + FRAME_IMAP_HCD = -43922 + FRAME_-43922_NAME = 'IMAP_HCD' + FRAME_-43922_CLASS = 5 + FRAME_-43922_CLASS_ID = -43922 + FRAME_-43922_CENTER = 10 + FRAME_-43922_RELATIVE = 'J2000' + FRAME_-43922_DEF_STYLE = 'PARAMETERIZED' + FRAME_-43922_FAMILY = 'TWO-VECTOR' + FRAME_-43922_PRI_AXIS = 'Z' + FRAME_-43922_PRI_VECTOR_DEF = 'CONSTANT' + FRAME_-43922_PRI_FRAME = 'IAU_SUN' + FRAME_-43922_PRI_SPEC = 'RECTANGULAR' + FRAME_-43922_PRI_VECTOR = ( 0, 0, 1 ) + FRAME_-43922_SEC_AXIS = 'Y' + FRAME_-43922_SEC_VECTOR_DEF = 'CONSTANT' + FRAME_-43922_SEC_FRAME = 'IMAP_ECLIPDATE' + FRAME_-43922_SEC_SPEC = 'RECTANGULAR' + FRAME_-43922_SEC_VECTOR = ( 0, 0, 1 ) + + \begintext + + + Heliographic Coordinates (HGC) Frame ([3],[7]) + --------------------------------------------------------------------- + + Cartesian counterpart to the spherical coordinates defined in [3], + "Heliographic Spherical (HGS) coordinate frame true to ref. date". + + Alias for SPICE IAU_SUN (Carrington heliographic coordinates) + in which the frame rotates with the surface of the sun with a + sidereal period of exactly 25.38 days. + + The Z axis is the solar rotation axis. + + The X axis is the intersection of the Carrington prime meridian + and the heliographic equator. + + The Y axis is Z cross X, completing the right-handed reference + frame. + + \begindata + + FRAME_IMAP_HGC = -43923 + FRAME_-43923_NAME = 'IMAP_HGC' + FRAME_-43923_CLASS = 4 + FRAME_-43923_CLASS_ID = -43923 + FRAME_-43923_CENTER = 10 + TKFRAME_-43923_RELATIVE = 'IAU_SUN' + TKFRAME_-43923_SPEC = 'MATRIX' + TKFRAME_-43923_MATRIX = ( 1 0 0 + 0 1 0 + 0 0 1 ) + \begintext + + + Heliocentric Aries Ecliptic (HAE) Frame ([3],[7]) + --------------------------------------------------------------------- + + Alias for SPICE ECLIPJ2000. + + The Z axis is the normal to the mean ecliptic at J2000. + + The X axis is the unit vector from Earth to the first point of + Aries at J2000. + + The Y axis is Z cross X, completing the right-handed reference + frame. + + \begindata + + FRAME_IMAP_HAE = -43924 + FRAME_-43924_NAME = 'IMAP_HAE' + FRAME_-43924_CLASS = 4 + FRAME_-43924_CLASS_ID = -43924 + FRAME_-43924_CENTER = 10 + TKFRAME_-43924_RELATIVE = 'ECLIPJ2000' + TKFRAME_-43924_SPEC = 'MATRIX' + TKFRAME_-43924_MATRIX = ( 1 0 0 + 0 1 0 + 0 0 1 ) + \begintext + + + Heliocentric Aries Ecliptic of Date (HAED) Frame ([3],[7]) + --------------------------------------------------------------------- + + Same orientation as IMAP_ECLIPDATE, but with Sun at the center + instead of Earth. + + The Z axis is the normal to the mean ecliptic of date. + + The X axis is the unit vector from Earth to the first point of + Aries of date. + + The Y axis is Z cross X, completing the right-handed reference + frame. + + \begindata + + FRAME_IMAP_HAED = -43925 + FRAME_-43925_NAME = 'IMAP_HAED' + FRAME_-43925_CLASS = 4 + FRAME_-43925_CLASS_ID = -43925 + FRAME_-43925_CENTER = 10 + TKFRAME_-43925_RELATIVE = 'IMAP_ECLIPDATE' + TKFRAME_-43925_SPEC = 'MATRIX' + TKFRAME_-43925_MATRIX = ( 1 0 0 + 0 1 0 + 0 0 1 ) + \begintext + + + Heliocentric Earth Ecliptic (HEE) Frame ([3],[7]) + --------------------------------------------------------------------- + + The position of the Earth relative to the Sun is the primary + vector: the X axis points from the Sun to the Earth. + + The northern surface normal to the mean ecliptic of date is the + secondary vector: the Z axis is the component of this vector + orthogonal to the X axis. + + The Y axis is Z cross X, completing the right-handed reference + frame. + + All vectors are geometric: no aberration corrections are used. + + \begindata + + FRAME_IMAP_HEE = -43926 + FRAME_-43926_NAME = 'IMAP_HEE' + FRAME_-43926_CLASS = 5 + FRAME_-43926_CLASS_ID = -43926 + FRAME_-43926_CENTER = 10 + FRAME_-43926_RELATIVE = 'J2000' + FRAME_-43926_DEF_STYLE = 'PARAMETERIZED' + FRAME_-43926_FAMILY = 'TWO-VECTOR' + FRAME_-43926_PRI_AXIS = 'X' + FRAME_-43926_PRI_VECTOR_DEF = 'OBSERVER_TARGET_POSITION' + FRAME_-43926_PRI_OBSERVER = 'SUN' + FRAME_-43926_PRI_TARGET = 'EARTH' + FRAME_-43926_PRI_ABCORR = 'NONE' + FRAME_-43926_SEC_AXIS = 'Z' + FRAME_-43926_SEC_VECTOR_DEF = 'CONSTANT' + FRAME_-43926_SEC_FRAME = 'IMAP_ECLIPDATE' + FRAME_-43926_SEC_SPEC = 'RECTANGULAR' + FRAME_-43926_SEC_VECTOR = ( 0, 0, 1 ) + + \begintext + + + Heliospheric Ram Ecliptic (HRE) Frame ([3],[8],[9]) + --------------------------------------------------------------------- + + This is a heliocentric frame oriented with respect to the current, + nominal ram direction of the Sun's motion relative to the local + interstellar medium and the ecliptic plane, otherwise known as the + heliospheric "nose" direction. + + The nose direction is the primary vector: the X axis points in the + direction [-0.24785821221964, -0.964645013724845, 0.0895896429900153] + in the ECLIPJ2000 (IMAP_HAE) frame. This unit vector corresponds + to coordinates 255.59 degrees longitude, 5.14 degrees latitude in + ECLIPJ2000. + + The northern surface normal to the mean ecliptic of J2000 is the + secondary vector: the Z axis is the component of this vector + orthogonal to the X axis. + + The Y axis is Z cross X, completing the right-handed reference + frame. + + \begindata + + FRAME_IMAP_HRE = -43927 + FRAME_-43927_NAME = 'IMAP_HRE' + FRAME_-43927_CLASS = 5 + FRAME_-43927_CLASS_ID = -43927 + FRAME_-43927_CENTER = 10 + FRAME_-43927_RELATIVE = 'J2000' + FRAME_-43927_DEF_STYLE = 'PARAMETERIZED' + FRAME_-43927_FAMILY = 'TWO-VECTOR' + FRAME_-43927_PRI_AXIS = 'X' + FRAME_-43927_PRI_VECTOR_DEF = 'CONSTANT' + FRAME_-43927_PRI_FRAME = 'ECLIPJ2000' + FRAME_-43927_PRI_SPEC = 'RECTANGULAR' + FRAME_-43927_PRI_VECTOR = (-0.24785821221964, + -0.964645013724845, + 0.0895896429900153 ) + FRAME_-43927_SEC_AXIS = 'Z' + FRAME_-43927_SEC_VECTOR_DEF = 'CONSTANT' + FRAME_-43927_SEC_FRAME = 'ECLIPJ2000' + FRAME_-43927_SEC_SPEC = 'RECTANGULAR' + FRAME_-43927_SEC_VECTOR = ( 0, 0, 1 ) + + \begintext + + + Heliospheric Nose Upfield (HNU) Frame ([3],[8],[9]) + --------------------------------------------------------------------- + + Heliocentric frame oriented with respect to the current nominal + ram direction of the Sun's motion relative to the local + interstellar medium and the current best estimate of the + unperturbed magnetic field direction in the upstream local + interstellar medium. + + The nominal upfield direction of the ISM B-field is the primary + vector: the Z axis points in the direction + ~[-0.5583, -0.6046, 0.5681] in the ECLIPJ2000 (IMAP_HAE) frame. + This unit vector corresponds to 227.28 degrees longitude, 34.62 + degrees latitude in ECLIPJ2000. + + The nose direction ~[-0.2477, -0.9647, 0.0896] in the ECLIPJ2000 + (IMAP_HAE) frame is the secondary vector, which corresponds to + coordinates 255.59 degrees longitude, 5.14 degrees latitude in + ECLIPJ2000. The X axis is the component of this vector orthogonal + to the Z axis. + + The Y axis is Z cross X, completing the right-handed reference + frame. + + \begindata + + FRAME_IMAP_HNU = -43928 + FRAME_-43928_NAME = 'IMAP_HNU' + FRAME_-43928_CLASS = 5 + FRAME_-43928_CLASS_ID = -43928 + FRAME_-43928_CENTER = 10 + FRAME_-43928_RELATIVE = 'J2000' + FRAME_-43928_DEF_STYLE = 'PARAMETERIZED' + FRAME_-43928_FAMILY = 'TWO-VECTOR' + FRAME_-43928_PRI_AXIS = 'Z' + FRAME_-43928_PRI_VECTOR_DEF = 'CONSTANT' + FRAME_-43928_PRI_FRAME = 'ECLIPJ2000' + FRAME_-43928_PRI_SPEC = 'RECTANGULAR' + FRAME_-43928_PRI_VECTOR = ( -0.558294509871844, + -0.60459437847959, + 0.568131039248724 ) + FRAME_-43928_SEC_AXIS = 'X' + FRAME_-43928_SEC_VECTOR_DEF = 'CONSTANT' + FRAME_-43928_SEC_FRAME = 'ECLIPJ2000' + FRAME_-43928_SEC_SPEC = 'RECTANGULAR' + FRAME_-43928_SEC_VECTOR = (-0.24785821221964, + -0.964645013724845, + 0.0895896429900153 ) + + \begintext + + + Galactic Coordinate System (GCS) Frame ([3]) + --------------------------------------------------------------------- + + Alias for SPICE galactic system II frame GALACTIC. + + The primary axis is the normal to the galactic equatorial plane: + Z axis is this unit vector. + + The secondary axis is the vector from the Sun to the galatic + center (represented by Sagittarious): X axis is the component of + this vector orthogonal to the Z axis. + + The Y axis is Z cross X, completing the right-handed reference + frame. + + \begindata + + FRAME_IMAP_GCS = -43929 + FRAME_-43929_NAME = 'IMAP_GCS' + FRAME_-43929_CLASS = 4 + FRAME_-43929_CLASS_ID = -43929 + FRAME_-43929_CENTER = 10 + TKFRAME_-43929_RELATIVE = 'GALACTIC' + TKFRAME_-43929_SPEC = 'MATRIX' + TKFRAME_-43929_MATRIX = ( 1 0 0 + 0 1 0 + 0 0 1 ) + \begintext + + Heliospheric Ribbon Centered (HRC) Frame ([11]) + --------------------------------------------------------------------- + + Heliocentric frame oriented with respect to the current estimate + for the mean ribbon center described in Reference 11. + + The weighted mean (across IBEX energies and time) is the primary + vector (+Z) for the frame and is aligned with 218.33 degrees + longitude in IMAP_HAE, and 40.38 degrees latitude IMAP_HAE. + + The nose direction ~[-0.2477, -0.9647, 0.0896] in the ECLIPJ2000 + (IMAP_HAE) frame is the secondary vector: the X axis is the + component of this vector orthogonal to the Z axis. + + The Y axis is Z cross X, completing the right-handed reference + frame. + + \begindata + + FRAME_IMAP_HRC = -43930 + FRAME_-43930_NAME = 'IMAP_HRC' + FRAME_-43930_CLASS = 5 + FRAME_-43930_CLASS_ID = -43930 + FRAME_-43930_CENTER = 10 + FRAME_-43930_RELATIVE = 'J2000' + FRAME_-43930_DEF_STYLE = 'PARAMETERIZED' + FRAME_-43930_FAMILY = 'TWO-VECTOR' + FRAME_-43930_PRI_AXIS = 'Z' + FRAME_-43930_PRI_VECTOR_DEF = 'CONSTANT' + FRAME_-43930_PRI_FRAME = 'ECLIPJ2000' + FRAME_-43930_PRI_SPEC = 'RECTANGULAR' + FRAME_-43930_PRI_VECTOR = ( -0.597567491320518, + -0.472438613169605, + 0.647854034565876 ) + FRAME_-43930_SEC_AXIS = 'X' + FRAME_-43930_SEC_VECTOR_DEF = 'CONSTANT' + FRAME_-43930_SEC_FRAME = 'ECLIPJ2000' + FRAME_-43930_SEC_SPEC = 'RECTANGULAR' + FRAME_-43930_SEC_VECTOR = (-0.24785821221964, + -0.964645013724845, + 0.0895896429900153 ) + + \begintext + + + +END OF FILE \ No newline at end of file diff --git a/imap_processing/tests/spice/test_data/imap_sclk_0036.tsc b/imap_processing/tests/spice/test_data/imap_sclk_0036.tsc new file mode 100644 index 0000000000..eba174e01b --- /dev/null +++ b/imap_processing/tests/spice/test_data/imap_sclk_0036.tsc @@ -0,0 +1,192 @@ +\begintext + +FILENAME = "imap_sclk_0036.tsc" +CREATION_DATE = "06-Nov-2025" + + +IMAP Spacecraft Clock Kernel (SCLK) +=========================================================================== + + This file is a SPICE spacecraft clock (SCLK) kernel containing + information required for time conversions involving the on-board + IMAP spacecraft clock. + +Version +-------------------------------------------------------- + + IMAP SCLK Kernel Version: + + IMAP version 0.3 - April 22, 2022 -- Mike Ruffolo + Updated to use NAIF SC ID 43 + + IMAP Version 0.2 - June 2, 2021 -- Caroline Cocca + Updated to use temporary spacecraft id of 225 + + IMAP Version 0.1 - March 6, 2015 -- Eric Melin + Updated text to replace references to RBSP with SPP + + IMAP Version 0.0 - August 7, 2014 -- Eric Melin + The initial SPP spice kernel. + This file was created by using RBSPA initial kernel and + modifying the spacecraft ID. + + +Usage +-------------------------------------------------------- + + This file is used by the SPICE system as follows: programs that + make use of this SCLK kernel must 'load' the kernel, normally + during program initialization. Loading the kernel associates + the data items with their names in a data structure called the + 'kernel pool'. The SPICELIB routine FURNSH loads text kernel + files, such as this one, into the pool as shown below: + + FORTRAN: + + CALL FURNSH ( SCLK_kernel_name ) + + C: + + furnsh_c ( SCLK_kernel_name ); + + Once loaded, the SCLK time conversion routines will be able to + access the necessary data located in this kernel for their + designed purposes. + +References +-------------------------------------------------------- + + 1. "SCLK Required Reading" + +Inquiries +-------------------------------------------------------- + + If you have any questions regarding this file or its usage, + contact: + + Scott Turner + (443)778-1693 + Scott.Turner@jhuapl.edu + +Kernel Data +-------------------------------------------------------- + + The first block of keyword equals value assignments define the + type, parallel time system, and format of the spacecraft clock. + These fields are invariant from SCLK kernel update to SCLK + kernel update. + + The IMAP spacecraft clock is represented by the SPICE + type 1 SCLK kernel. It uses TDT, Terrestrial Dynamical Time, + as its parallel time system. + +\begindata + +SCLK_KERNEL_ID = ( @2009-07-09T12:20:32 ) +SCLK_DATA_TYPE_43 = ( 1 ) +SCLK01_TIME_SYSTEM_43 = ( 2 ) + + +\begintext + + In a particular partition of the IMAP spacecraft clock, + the clock read-out consists of two separate stages: + + 1/18424652:24251 + + The first stage, a 32 bit field, represents the spacecraft + clock seconds count. The second, a 16 bit field, represents + counts of 20 microsecond increments of the spacecraft clock. + + The following keywords and their values establish this structure: + +\begindata + +SCLK01_N_FIELDS_43 = ( 2 ) +SCLK01_MODULI_43 = ( 4294967296 50000 ) +SCLK01_OFFSETS_43 = ( 0 0 ) +SCLK01_OUTPUT_DELIM_43 = ( 2 ) + + +\begintext + + This concludes the invariant portion of the SCLK kernel data. The + remaining sections of the kernel may require updates as the clock + correlation coefficients evolve in time. The first section below + establishes the clock partitions. The data in this section consists + of two parallel arrays, which denote the start and end values in + ticks of each partition of the spacecraft clock. + + SPICE utilizes these two arrays to map from spacecraft clock ticks, + determined with the usual modulo arithmetic, to encoded SCLK--the + internal, monotonically increasing sequence used to tag various + data sources with spacecraft clock. + +\begindata + +SCLK_PARTITION_START_43 = ( 0.00000000000000e+00 ) + +SCLK_PARTITION_END_43 = ( 2.14748364799999e+14 ) + +\begintext + + The remaining section of the SCLK kernel defines the clock correlation + coefficients. Each line contains a 'coefficient triple': + + Encoded SCLK at which Rate is introduced. + Corresponding TDT Epoch at which Rate is introduced. + Rate in TDT (seconds) / most significant clock count (~seconds). + + SPICE uses linear extrapolation to convert between the parallel time + system and encoded SCLK. The triples are stored in the array defined + below. + + The first time triplet below was entered manually and represents the + approximate time (in TDT) at which SCLK = zero. The current plan for + IMAP is that the given epoch will be used for both Observatory I&T + and launch. Note that the conversion from UTC to TDT used 34 leap + seconds. + +\begindata + +SCLK01_COEFFICIENTS_43 = ( + + 0 @01-JAN-2010-00:01:06.184000 1.00000000000 + 24822451300000 @24-SEP-2025-22:31:35.831485 1.00000000000 + 24827384750000 @26-SEP-2025-01:56:04.742538 1.00000000000 + 24831795450000 @27-SEP-2025-02:26:18.660826 0.99999908847 + 24837318950000 @28-SEP-2025-09:07:28.560129 0.99999908853 + 24841014800000 @29-SEP-2025-05:39:25.492756 0.99999908837 + 24846929950000 @30-SEP-2025-14:31:08.384908 0.99999908797 + 24852240150000 @01-OCT-2025-20:01:12.288047 0.99999908597 + 24856920150000 @02-OCT-2025-22:01:12.202494 0.99999909228 + 24861600150000 @04-OCT-2025-00:01:12.117531 0.99999908917 + 24875640150000 @07-OCT-2025-06:01:11.861770 0.99999908927 + 24878880150000 @08-OCT-2025-00:01:11.802755 0.99999908938 + 24884280150000 @09-OCT-2025-06:01:11.704408 0.99999908946 + 24888780150000 @10-OCT-2025-07:01:11.622459 0.99999909028 + 24889500150000 @10-OCT-2025-11:01:11.609359 0.99999908975 + 24895440150000 @11-OCT-2025-20:01:11.501221 0.99999909028 + 24906060150000 @14-OCT-2025-07:01:11.307997 0.99999909096 + 24907680150000 @14-OCT-2025-16:01:11.278544 0.99999909107 + 24914520150000 @16-OCT-2025-06:01:11.154203 0.99999909156 + 24922079900000 @18-OCT-2025-00:01:06.016851 0.99999909164 + 24927660150000 @19-OCT-2025-07:01:10.915474 0.99999909233 + 24930000150000 @19-OCT-2025-20:01:10.872995 0.99999909238 + 24935220150000 @21-OCT-2025-01:01:10.778239 0.99999909249 + 24940620150000 @22-OCT-2025-07:01:10.680227 0.99999909327 + 24942240150000 @22-OCT-2025-16:01:10.650849 0.99999909292 + 24948000150000 @24-OCT-2025-00:01:10.546353 0.99999909324 + 24952679900000 @25-OCT-2025-02:01:05.461485 0.99999909350 + 24957900150000 @26-OCT-2025-07:01:10.366842 0.99999909385 + 24960240150000 @26-OCT-2025-20:01:10.324434 0.99999909393 + 24966540150000 @28-OCT-2025-07:01:10.210269 0.99999909430 + 24969240150000 @28-OCT-2025-22:01:10.161361 0.99999909430 + 24973740150000 @29-OCT-2025-23:01:10.079848 0.99999909479 + 24982380200000 @31-OCT-2025-23:01:10.923427 0.99999909520 + 24990660150000 @02-NOV-2025-21:01:09.773593 0.99999909537 + 24994800200000 @03-NOV-2025-20:01:10.698688 0.99999909590 + 24999660200000 @04-NOV-2025-23:01:10.610809 0.99999909621 + 25003800150000 @05-NOV-2025-22:01:09.535976 0.99999909583 + +) diff --git a/imap_processing/tests/spice/test_data/imap_wkcp.tf b/imap_processing/tests/spice/test_data/imap_wkcp.tf deleted file mode 100644 index 10ceb4ddf6..0000000000 --- a/imap_processing/tests/spice/test_data/imap_wkcp.tf +++ /dev/null @@ -1,1806 +0,0 @@ -KPL/FK - -Interstellar Mapping and Acceleration Probe Frames Kernel -======================================================================== - - This frames kernel contains the current set of coordinate frame - definitions for the Interstellar Mapping and Acceleration Probe - (IMAP) spacecraft, structures, and science instruments. - - This kernel also contains NAIF ID/name mapping for the IMAP - instruments. - - -Version and Date -======================================================================== - - The TEXT_KERNEL_ID stores version information of loaded project text - kernels. Each entry associated with the keyword is a string that - consists of four parts: the kernel name, version, entry date, and - type. For example, the frames kernel might have an entry as follows: - - - TEXT_KERNEL_ID += 'IMAP_FRAMES V1.0.0 2024-XXXX-NN FK' - | | | | - | | | | - KERNEL NAME <-------+ | | | - | | V - VERSION <------+ | KERNEL TYPE - | - V - ENTRY DATE - - - Interstellar Mapping and Acceleration Probe Frames Kernel Version: - - \begindata - - TEXT_KERNEL_ID += 'IMAP_FRAMES V1.0.0 2024-XXXX-NN FK' - - \begintext - - Version 1.0.0 -- XXXX NN, 2024 -- Douglas Rodgers - Lillian Nguyen - Nicholas Dutton - - Initial complete release. Frame/Body codes for thrusters redefined - - Version 0.0.1 -- July 9, 2021 -- Ian Wick Murphy - - Modifying dart_008.tf to add basic IMAP frame components. This - includes IMAP, IMAP_THRUSTER, and CK/SCLK IDs. Also adding a place - holder for the IMAP-Lo instrument with the ID -43001 and IMAP_LO - name. Future work includes adding more detailed instrument frames, - and reaching out to mechanical for an "official" IMAP_SPACECRAFT - frame definition. - - -References -======================================================================== - - 1. "Frames Required Reading" - - 2. "Kernel Pool Required Reading" - - 3. "C-Kernel Required Reading" - - 4. "7516-9067: IMAP Mechanical Interface Control Document", - Johns Hopkins Applied Physics Laboratory - - 5. "7516-9050: IMAP Coordinate Frame & Technical Definitions Doc.", - Johns Hopkins Applied Physics Laboratory - - 6. "7516-0011: IMAP Mechanical Interface Control Drawing", - [EXPORT CONTROLLED], Johns Hopkins Applied Physics Laboratory - - 7. "7523-0008: IMAP ULTRA Mechanical Interface Control Drawing", - [EXPORT CONTROLLED], Johns Hopkins Applied Physics Laboratory - - 8. "058991000: IMAP SWAPI Mechanical Interface Control Drawing", - Princeton University Space Physics - - 9. "GLOWS-CBK-DWG-2020-08-25-019-v4.4: IMAP GLOWS Mechanical - Interface Control Drawing", Centrum Badag Kosmicznych, Polska - Akademia Nauks - - 10. Responses from IMAP instrument teams on their base frame axis - definitions, received in email. - - -Contact Information -======================================================================== - - Douglas Rodgers, JHU/APL, Douglas.Rodgers@jhuapl.edu - - Lillian Nguyen, JHU/APL, Lillian.Nguyen@jhuapl.edu - - Nicholas Dutton, JHU/APL, Nicholas.Dutton@jhuapl.edu - - Ian Wick Murphy, JHU/APL, Ian.Murphy@jhuapl.edu - - -Implementation Notes -======================================================================== - - This file is used by the SPICE system as follows: programs that make - use of this frame kernel must `load' the kernel, normally during - program initialization. Loading the kernel associates the data items - with their names in a data structure called the `kernel pool'. The - SPICELIB routine FURNSH loads a kernel into the pool as shown below: - - FORTRAN: (SPICELIB) - - CALL FURNSH ( frame_kernel_name ) - - C: (CSPICE) - - furnsh_c ( frame_kernel_name ); - - IDL: (ICY) - - cspice_furnsh, frame_kernel_name - - MATLAB: (MICE) - - cspice_furnsh ( frame_kernel_name ) - - This file was created and may be updated with a text editor or word - processor. - - -IMAP NAIF ID Codes -- Definitions -======================================================================== - - This section contains name to NAIF ID mappings for the IMAP mission. - Once the contents of this file are loaded into the KERNEL POOL, these - mappings become available within SPICE, making it possible to use - names instead of ID code in high level SPICE routine calls. - - \begindata - - NAIF_BODY_NAME += ( 'IMAP' ) - NAIF_BODY_CODE += ( -43 ) - - NAIF_BODY_NAME += ( 'IMAP_SPACECRAFT' ) - NAIF_BODY_CODE += ( -43000 ) - - NAIF_BODY_NAME += ( 'IMAP_THRUSTER_A1' ) - NAIF_BODY_CODE += ( -43010 ) - - NAIF_BODY_NAME += ( 'IMAP_THRUSTER_A2' ) - NAIF_BODY_CODE += ( -43011 ) - - NAIF_BODY_NAME += ( 'IMAP_THRUSTER_A3' ) - NAIF_BODY_CODE += ( -43012 ) - - NAIF_BODY_NAME += ( 'IMAP_THRUSTER_A4' ) - NAIF_BODY_CODE += ( -43013 ) - - NAIF_BODY_NAME += ( 'IMAP_THRUSTER_R1' ) - NAIF_BODY_CODE += ( -43020 ) - - NAIF_BODY_NAME += ( 'IMAP_THRUSTER_R2' ) - NAIF_BODY_CODE += ( -43021 ) - - NAIF_BODY_NAME += ( 'IMAP_THRUSTER_R3' ) - NAIF_BODY_CODE += ( -43022 ) - - NAIF_BODY_NAME += ( 'IMAP_THRUSTER_R4' ) - NAIF_BODY_CODE += ( -43023 ) - - NAIF_BODY_NAME += ( 'IMAP_THRUSTER_R5' ) - NAIF_BODY_CODE += ( -43024 ) - - NAIF_BODY_NAME += ( 'IMAP_THRUSTER_R6' ) - NAIF_BODY_CODE += ( -43025 ) - - NAIF_BODY_NAME += ( 'IMAP_THRUSTER_R7' ) - NAIF_BODY_CODE += ( -43026 ) - - NAIF_BODY_NAME += ( 'IMAP_THRUSTER_R8' ) - NAIF_BODY_CODE += ( -43027 ) - - NAIF_BODY_NAME += ( 'IMAP_SUN_SENSOR_PZ' ) - NAIF_BODY_CODE += ( -42030 ) - - NAIF_BODY_NAME += ( 'IMAP_SUN_SENSOR_MZ' ) - NAIF_BODY_CODE += ( -42031 ) - - NAIF_BODY_NAME += ( 'IMAP_STAR_TRACKER_PX' ) - NAIF_BODY_CODE += ( -42040 ) - - NAIF_BODY_NAME += ( 'IMAP_STAR_TRACKER_MX' ) - NAIF_BODY_CODE += ( -42041 ) - - NAIF_BODY_NAME += ( 'IMAP_LOW_GAIN_ANTENNA' ) - NAIF_BODY_CODE += ( -42050 ) - - NAIF_BODY_NAME += ( 'IMAP_MED_GAIN_ANTENNA' ) - NAIF_BODY_CODE += ( -42051 ) - - NAIF_BODY_NAME += ( 'IMAP_NUTATION_DAMPER_01' ) - NAIF_BODY_CODE += ( -42060 ) - - NAIF_BODY_NAME += ( 'IMAP_NUTATION_DAMPER_02' ) - NAIF_BODY_CODE += ( -42061 ) - - NAIF_BODY_NAME += ( 'IMAP_LO_ENA_SENSOR' ) - NAIF_BODY_CODE += ( -42102 ) - - NAIF_BODY_NAME += ( 'IMAP_LO_STAR_SENSOR' ) - NAIF_BODY_CODE += ( -42103 ) - - NAIF_BODY_NAME += ( 'IMAP_HI_45' ) - NAIF_BODY_CODE += ( -42150 ) - - NAIF_BODY_NAME += ( 'IMAP_HI_90' ) - NAIF_BODY_CODE += ( -42175 ) - - NAIF_BODY_NAME += ( 'IMAP_ULTRA_45' ) - NAIF_BODY_CODE += ( -42200 ) - - NAIF_BODY_NAME += ( 'IMAP_ULTRA_90' ) - NAIF_BODY_CODE += ( -42225 ) - - NAIF_BODY_NAME += ( 'IMAP_MAG' ) - NAIF_BODY_CODE += ( -42250 ) - - NAIF_BODY_NAME += ( 'IMAP_SWE_DETECTOR_P63' ) - NAIF_BODY_CODE += ( -42301 ) - - NAIF_BODY_NAME += ( 'IMAP_SWE_DETECTOR_P42' ) - NAIF_BODY_CODE += ( -42302 ) - - NAIF_BODY_NAME += ( 'IMAP_SWE_DETECTOR_P21' ) - NAIF_BODY_CODE += ( -42303 ) - - NAIF_BODY_NAME += ( 'IMAP_SWE_DETECTOR_000' ) - NAIF_BODY_CODE += ( -42304 ) - - NAIF_BODY_NAME += ( 'IMAP_SWE_DETECTOR_M21' ) - NAIF_BODY_CODE += ( -42305 ) - - NAIF_BODY_NAME += ( 'IMAP_SWE_DETECTOR_M42' ) - NAIF_BODY_CODE += ( -42306 ) - - NAIF_BODY_NAME += ( 'IMAP_SWE_DETECTOR_M63' ) - NAIF_BODY_CODE += ( -42307 ) - - NAIF_BODY_NAME += ( 'IMAP_SWAPI_APERTURE_L' ) - NAIF_BODY_CODE += ( -42351 ) - - NAIF_BODY_NAME += ( 'IMAP_SWAPI_APERTURE_R' ) - NAIF_BODY_CODE += ( -42352 ) - - NAIF_BODY_NAME += ( 'IMAP_SWAPI_SUNGLASSES' ) - NAIF_BODY_CODE += ( -42353 ) - - NAIF_BODY_NAME += ( 'IMAP_CODICE_LO_APERTURE_01' ) - NAIF_BODY_CODE += ( -42401 ) - - NAIF_BODY_NAME += ( 'IMAP_CODICE_LO_APERTURE_02' ) - NAIF_BODY_CODE += ( -42402 ) - - NAIF_BODY_NAME += ( 'IMAP_CODICE_LO_APERTURE_03' ) - NAIF_BODY_CODE += ( -42403 ) - - NAIF_BODY_NAME += ( 'IMAP_CODICE_LO_APERTURE_04' ) - NAIF_BODY_CODE += ( -42404 ) - - NAIF_BODY_NAME += ( 'IMAP_CODICE_LO_APERTURE_05' ) - NAIF_BODY_CODE += ( -42405 ) - - NAIF_BODY_NAME += ( 'IMAP_CODICE_LO_APERTURE_06' ) - NAIF_BODY_CODE += ( -42406 ) - - NAIF_BODY_NAME += ( 'IMAP_CODICE_LO_APERTURE_07' ) - NAIF_BODY_CODE += ( -42407 ) - - NAIF_BODY_NAME += ( 'IMAP_CODICE_LO_APERTURE_08' ) - NAIF_BODY_CODE += ( -42408 ) - - NAIF_BODY_NAME += ( 'IMAP_CODICE_LO_APERTURE_09' ) - NAIF_BODY_CODE += ( -42409 ) - - NAIF_BODY_NAME += ( 'IMAP_CODICE_LO_APERTURE_10' ) - NAIF_BODY_CODE += ( -42410 ) - - NAIF_BODY_NAME += ( 'IMAP_CODICE_LO_APERTURE_11' ) - NAIF_BODY_CODE += ( -42411 ) - - NAIF_BODY_NAME += ( 'IMAP_CODICE_LO_APERTURE_12' ) - NAIF_BODY_CODE += ( -42412 ) - - NAIF_BODY_NAME += ( 'IMAP_CODICE_LO_APERTURE_13' ) - NAIF_BODY_CODE += ( -42413 ) - - NAIF_BODY_NAME += ( 'IMAP_CODICE_LO_APERTURE_14' ) - NAIF_BODY_CODE += ( -42414 ) - - NAIF_BODY_NAME += ( 'IMAP_CODICE_LO_APERTURE_15' ) - NAIF_BODY_CODE += ( -42415 ) - - NAIF_BODY_NAME += ( 'IMAP_CODICE_LO_APERTURE_16' ) - NAIF_BODY_CODE += ( -42416 ) - - NAIF_BODY_NAME += ( 'IMAP_CODICE_LO_APERTURE_17' ) - NAIF_BODY_CODE += ( -42417 ) - - NAIF_BODY_NAME += ( 'IMAP_CODICE_LO_APERTURE_18' ) - NAIF_BODY_CODE += ( -42418 ) - - NAIF_BODY_NAME += ( 'IMAP_CODICE_LO_APERTURE_19' ) - NAIF_BODY_CODE += ( -42419 ) - - NAIF_BODY_NAME += ( 'IMAP_CODICE_LO_APERTURE_20' ) - NAIF_BODY_CODE += ( -42420 ) - - NAIF_BODY_NAME += ( 'IMAP_CODICE_LO_APERTURE_21' ) - NAIF_BODY_CODE += ( -42421 ) - - NAIF_BODY_NAME += ( 'IMAP_CODICE_LO_APERTURE_22' ) - NAIF_BODY_CODE += ( -42422 ) - - NAIF_BODY_NAME += ( 'IMAP_CODICE_LO_APERTURE_23' ) - NAIF_BODY_CODE += ( -42423 ) - - NAIF_BODY_NAME += ( 'IMAP_CODICE_LO_APERTURE_24' ) - NAIF_BODY_CODE += ( -42424 ) - - NAIF_BODY_NAME += ( 'IMAP_CODICE_HI_APERTURE_01' ) - NAIF_BODY_CODE += ( -42425 ) - - NAIF_BODY_NAME += ( 'IMAP_CODICE_HI_APERTURE_02' ) - NAIF_BODY_CODE += ( -42426 ) - - NAIF_BODY_NAME += ( 'IMAP_CODICE_HI_APERTURE_03' ) - NAIF_BODY_CODE += ( -42427 ) - - NAIF_BODY_NAME += ( 'IMAP_CODICE_HI_APERTURE_04' ) - NAIF_BODY_CODE += ( -42428 ) - - NAIF_BODY_NAME += ( 'IMAP_CODICE_HI_APERTURE_05' ) - NAIF_BODY_CODE += ( -42429 ) - - NAIF_BODY_NAME += ( 'IMAP_CODICE_HI_APERTURE_06' ) - NAIF_BODY_CODE += ( -42430 ) - - NAIF_BODY_NAME += ( 'IMAP_CODICE_HI_APERTURE_07' ) - NAIF_BODY_CODE += ( -42431 ) - - NAIF_BODY_NAME += ( 'IMAP_CODICE_HI_APERTURE_08' ) - NAIF_BODY_CODE += ( -42432 ) - - NAIF_BODY_NAME += ( 'IMAP_CODICE_HI_APERTURE_09' ) - NAIF_BODY_CODE += ( -42433 ) - - NAIF_BODY_NAME += ( 'IMAP_CODICE_HI_APERTURE_10' ) - NAIF_BODY_CODE += ( -42434 ) - - NAIF_BODY_NAME += ( 'IMAP_CODICE_HI_APERTURE_11' ) - NAIF_BODY_CODE += ( -42435 ) - - NAIF_BODY_NAME += ( 'IMAP_CODICE_HI_APERTURE_12' ) - NAIF_BODY_CODE += ( -42436 ) - - NAIF_BODY_NAME += ( 'IMAP_HIT_L1_APERTURE_01' ) - NAIF_BODY_CODE += ( -42501 ) - - NAIF_BODY_NAME += ( 'IMAP_HIT_L1_APERTURE_02' ) - NAIF_BODY_CODE += ( -42502 ) - - NAIF_BODY_NAME += ( 'IMAP_HIT_L1_APERTURE_03' ) - NAIF_BODY_CODE += ( -42503 ) - - NAIF_BODY_NAME += ( 'IMAP_HIT_L1_APERTURE_04' ) - NAIF_BODY_CODE += ( -42504 ) - - NAIF_BODY_NAME += ( 'IMAP_HIT_L1_APERTURE_05' ) - NAIF_BODY_CODE += ( -42505 ) - - NAIF_BODY_NAME += ( 'IMAP_HIT_L1_APERTURE_06' ) - NAIF_BODY_CODE += ( -42506 ) - - NAIF_BODY_NAME += ( 'IMAP_HIT_L1_APERTURE_07' ) - NAIF_BODY_CODE += ( -42507 ) - - NAIF_BODY_NAME += ( 'IMAP_HIT_L1_APERTURE_08' ) - NAIF_BODY_CODE += ( -42508 ) - - NAIF_BODY_NAME += ( 'IMAP_HIT_L1_APERTURE_09' ) - NAIF_BODY_CODE += ( -42509 ) - - NAIF_BODY_NAME += ( 'IMAP_HIT_L1_APERTURE_10' ) - NAIF_BODY_CODE += ( -42510 ) - - NAIF_BODY_NAME += ( 'IMAP_IDEX_DETECTOR' ) - NAIF_BODY_CODE += ( -42701 ) - - NAIF_BODY_NAME += ( 'IMAP_IDEX_FULL_SCIENCE' ) - NAIF_BODY_CODE += ( -42702 ) - - NAIF_BODY_NAME += ( 'IMAP_GLOWS' ) - NAIF_BODY_CODE += ( -42750 ) - - \begintext - - -IMAP NAIF ID Codes -- Definitions -======================================================================== - - The ID codes -43900 to -43999 have been reserved for the IMAP dynamic - frames kernel and are not utilized in this file. - - The following frames are defined in this kernel file: - - Frame Name Relative To Type NAIF ID - ========================== =============== ======= ======= - - Spacecraft (000-099) - -------------------------- - IMAP_SPACECRAFT J2000 CK -43000 - IMAP_THRUSTER_A1 IMAP_SPACECRAFT FIXED -43010 - IMAP_THRUSTER_A2 IMAP_SPACECRAFT FIXED -43011 - IMAP_THRUSTER_A3 IMAP_SPACECRAFT FIXED -43012 - IMAP_THRUSTER_A4 IMAP_SPACECRAFT FIXED -43013 - IMAP_THRUSTER_R1 IMAP_SPACECRAFT FIXED -43020 - IMAP_THRUSTER_R2 IMAP_SPACECRAFT FIXED -43021 - IMAP_THRUSTER_R3 IMAP_SPACECRAFT FIXED -43022 - IMAP_THRUSTER_R4 IMAP_SPACECRAFT FIXED -43023 - IMAP_THRUSTER_R5 IMAP_SPACECRAFT FIXED -43024 - IMAP_THRUSTER_R6 IMAP_SPACECRAFT FIXED -43025 - IMAP_THRUSTER_R7 IMAP_SPACECRAFT FIXED -43026 - IMAP_THRUSTER_R8 IMAP_SPACECRAFT FIXED -43027 - IMAP_SUN_SENSOR_PZ IMAP_SPACECRAFT FIXED -42030 - IMAP_SUN_SENSOR_MZ IMAP_SPACECRAFT FIXED -42031 - IMAP_STAR_TRACKER_PX IMAP_SPACECRAFT FIXED -42040 - IMAP_STAR_TRACKER_MX IMAP_SPACECRAFT FIXED -42041 - IMAP_LOW_GAIN_ANTENNA IMAP_SPACECRAFT FIXED -42050 - IMAP_MED_GAIN_ANTENNA IMAP_SPACECRAFT FIXED -42051 - IMAP_NUTATION_DAMPER_01 IMAP_SPACECRAFT FIXED -42060 - IMAP_NUTATION_DAMPER_02 IMAP_SPACECRAFT FIXED -42061 - - IMAP-Lo (100-149) - -------------------------- - IMAP_LO_BASE IMAP_SPACECRAFT FIXED -42100 - IMAP_LO_PIVOT IMAP_LO_BASE CK -42101 - IMAP_LO_ENA_SENSOR IMAP_LO_PIVOT FIXED -42102 - IMAP_LO_STAR_SENSOR IMAP_LO_PIVOT FIXED -42103 - - IMAP-Hi (150-199) - -------------------------- - IMAP_HI_45 IMAP_SPACECRAFT FIXED -42150 - IMAP_HI_90 IMAP_SPACECRAFT FIXED -42175 - - IMAP-Ultra (200-249) - -------------------------- - IMAP_ULTRA_45 IMAP_SPACECRAFT FIXED -42200 - IMAP_ULTRA_90 IMAP_SPACECRAFT FIXED -42225 - - MAG (250-299) - -------------------------- - IMAP_MAG IMAP_SPACECRAFT FIXED -42250 - - SWE (300-349) - -------------------------- - IMAP_SWE IMAP_SPACECRAFT FIXED -42300 - IMAP_SWE_DETECTOR_P63 IMAP_SWE FIXED -42301 - IMAP_SWE_DETECTOR_P42 IMAP_SWE FIXED -42302 - IMAP_SWE_DETECTOR_P21 IMAP_SWE FIXED -42303 - IMAP_SWE_DETECTOR_000 IMAP_SWE FIXED -42304 - IMAP_SWE_DETECTOR_M21 IMAP_SWE FIXED -42305 - IMAP_SWE_DETECTOR_M42 IMAP_SWE FIXED -42306 - IMAP_SWE_DETECTOR_M63 IMAP_SWE FIXED -42307 - - SWAPI (350-399) - -------------------------- - IMAP_SWAPI IMAP_SPACECRAFT FIXED -42350 - IMAP_SWAPI_APERTURE_L IMAP_SWAPI FIXED -42351 - IMAP_SWAPI_APERTURE_R IMAP_SWAPI FIXED -42352 - IMAP_SWAPI_SUNGLASSES IMAP_SWAPI FIXED -42353 - - CODICE (400-499) - -------------------------- - IMAP_CODICE IMAP_SPACECRAFT FIXED -42400 - IMAP_CODICE_LO_APERTURE_01 IMAP_CODICE FIXED -42401 - IMAP_CODICE_LO_APERTURE_02 IMAP_CODICE FIXED -42402 - IMAP_CODICE_LO_APERTURE_03 IMAP_CODICE FIXED -42403 - IMAP_CODICE_LO_APERTURE_04 IMAP_CODICE FIXED -42404 - IMAP_CODICE_LO_APERTURE_05 IMAP_CODICE FIXED -42405 - IMAP_CODICE_LO_APERTURE_06 IMAP_CODICE FIXED -42406 - IMAP_CODICE_LO_APERTURE_07 IMAP_CODICE FIXED -42407 - IMAP_CODICE_LO_APERTURE_08 IMAP_CODICE FIXED -42408 - IMAP_CODICE_LO_APERTURE_09 IMAP_CODICE FIXED -42409 - IMAP_CODICE_LO_APERTURE_10 IMAP_CODICE FIXED -42410 - IMAP_CODICE_LO_APERTURE_11 IMAP_CODICE FIXED -42411 - IMAP_CODICE_LO_APERTURE_12 IMAP_CODICE FIXED -42412 - IMAP_CODICE_LO_APERTURE_13 IMAP_CODICE FIXED -42413 - IMAP_CODICE_LO_APERTURE_14 IMAP_CODICE FIXED -42414 - IMAP_CODICE_LO_APERTURE_15 IMAP_CODICE FIXED -42415 - IMAP_CODICE_LO_APERTURE_16 IMAP_CODICE FIXED -42416 - IMAP_CODICE_LO_APERTURE_17 IMAP_CODICE FIXED -42417 - IMAP_CODICE_LO_APERTURE_18 IMAP_CODICE FIXED -42418 - IMAP_CODICE_LO_APERTURE_19 IMAP_CODICE FIXED -42419 - IMAP_CODICE_LO_APERTURE_20 IMAP_CODICE FIXED -42420 - IMAP_CODICE_LO_APERTURE_21 IMAP_CODICE FIXED -42421 - IMAP_CODICE_LO_APERTURE_22 IMAP_CODICE FIXED -42422 - IMAP_CODICE_LO_APERTURE_23 IMAP_CODICE FIXED -42423 - IMAP_CODICE_LO_APERTURE_24 IMAP_CODICE FIXED -42424 - IMAP_CODICE_HI_APERTURE_01 IMAP_CODICE FIXED -42425 - IMAP_CODICE_HI_APERTURE_02 IMAP_CODICE FIXED -42426 - IMAP_CODICE_HI_APERTURE_03 IMAP_CODICE FIXED -42427 - IMAP_CODICE_HI_APERTURE_04 IMAP_CODICE FIXED -42428 - IMAP_CODICE_HI_APERTURE_05 IMAP_CODICE FIXED -42429 - IMAP_CODICE_HI_APERTURE_06 IMAP_CODICE FIXED -42430 - IMAP_CODICE_HI_APERTURE_07 IMAP_CODICE FIXED -42431 - IMAP_CODICE_HI_APERTURE_08 IMAP_CODICE FIXED -42432 - IMAP_CODICE_HI_APERTURE_09 IMAP_CODICE FIXED -42433 - IMAP_CODICE_HI_APERTURE_10 IMAP_CODICE FIXED -42434 - IMAP_CODICE_HI_APERTURE_11 IMAP_CODICE FIXED -42435 - IMAP_CODICE_HI_APERTURE_12 IMAP_CODICE FIXED -42436 - - HIT (500-699) - -------------------------- - IMAP_HIT IMAP_SPACECRAFT FIXED -42500 - IMAP_HIT_L1_APERTURE_01 IMAP_HIT FIXED -42501 - IMAP_HIT_L1_APERTURE_02 IMAP_HIT FIXED -42502 - IMAP_HIT_L1_APERTURE_03 IMAP_HIT FIXED -42503 - IMAP_HIT_L1_APERTURE_04 IMAP_HIT FIXED -42504 - IMAP_HIT_L1_APERTURE_05 IMAP_HIT FIXED -42505 - IMAP_HIT_L1_APERTURE_06 IMAP_HIT FIXED -42506 - IMAP_HIT_L1_APERTURE_07 IMAP_HIT FIXED -42507 - IMAP_HIT_L1_APERTURE_08 IMAP_HIT FIXED -42508 - IMAP_HIT_L1_APERTURE_09 IMAP_HIT FIXED -42509 - IMAP_HIT_L1_APERTURE_10 IMAP_HIT FIXED -42510 - - IDEX (700-749) - -------------------------- - IMAP_IDEX IMAP_SPACECRAFT FIXED -42700 - IMAP_IDEX_DETECTOR IMAP_IDEX FIXED -42701 - IMAP_IDEX_FULL_SCIENCE IMAP_IDEX FIXED -42702 - - GLOWS (750-799) - -------------------------- - IMAP_GLOWS IMAP_SPACECRAFT FIXED -42750 - - -IMAP Frame Tree -======================================================================== - - The diagram below illustrates the IMAP frame hierarchy: - - J2000 - | - |<---ck - | - IMAP_SPACECRAFT - | - IMAP_THRUSTER_A1 - | - |... - | - IMAP_THRUSTER_A4 - | - IMAP_THRUSTER_R1 - | - |... - | - IMAP_THRUSTER_R8 - | - IMAP_SUN_SENSOR_PZ - | - IMAP_SUN_SENSOR_MZ - | - IMAP_STAR_TRACKER_PX - | - IMAP_STAR_TRACKER_MX - | - IMAP_LOW_GAIN_ANTENNA - | - IMAP_MED_GAIN_ANTENNA - | - IMAP_NUTATION_DAMPER_01 - | - IMAP_NUTATION_DAMPER_02 - | - IMAP_LO_BASE - | | - | |<---ck - | | - | IMAP_LO_PIVOT - | | - | IMAP_LO_ENA_SENSOR - | | - | IMAP_LO_STAR_SENSOR - | - IMAP_HI_45 - | - IMAP_HI_90 - | - IMAP_ULTRA_45 - | - IMAP_ULTRA_90 - | - IMAP_MAG - | - IMAP_SWE - | | - | IMAP_SWE_DETECTOR_P63 - | | - | IMAP_SWE_DETECTOR_P42 - | | - | IMAP_SWE_DETECTOR_P21 - | | - | IMAP_SWE_DETECTOR_000 - | | - | IMAP_SWE_DETECTOR_M21 - | | - | IMAP_SWE_DETECTOR_M42 - | | - | IMAP_SWE_DETECTOR_M63 - | - IMAP_SWAPI - | | - | IMAP_SWAPI_APERTURE_L - | | - | IMAP_SWAPI_APERTURE_R - | | - | IMAP_SWAPI_SUNGLASSES - | - IMAP_CODICE - | | - | IMAP_CODICE_LO_APERTURE_01 - | | - | |... - | | - | IMAP_CODICE_LO_APERTURE_24 - | | - | IMAP_CODICE_HI_APERTURE_01 - | | - | |... - | | - | IMAP_CODICE_HI_APERTURE_12 - | - IMAP_HIT - | | - | IMAP_HIT_L1_APERTURE_01 - | | - | |... - | | - | IMAP_HIT_L1_APERTURE_10 - | - IMAP_IDEX - | | - | IMAP_IDEX_DETECTOR - | | - | IMAP_IDEX_FULL_SCIENCE - | - IMAP_GLOWS - - -IMAP Spacecraft Frame -======================================================================== - - The orientation of the spacecraft body frame with respect to an - inertial frame, J2000 for IMAP, is provided by a C-kernel (see [3] - for details). - - The spacecraft coordinate frames are defined by the IMAP control - documents (see [4,5], NB, figure 2.2). There are two frames described - there: Observatory Mechanical Design Reference Frame (most relevant) - and Observatory Pointing and Dynamics Reference Frame (less relevant - for this frame kernel). - - - Observatory Mechanical Design Reference Frame (IMAP_SPACECRAFT) - --------------------------------------------------------------------- - - If not explicitly stated, references to 'spacecraft mechanical frame' - 'spacecraft frame', or 'S/C frame' will refer to this frame. - - All instruments and component placements and orientations are defined - using this coordinate frame reference. - - Origin: Center of the launch vehicle adapter ring at the - observatory/launch vehicle interface plane - - +Z axis: Perpendicular to the launch vehicle interface plane pointed - in the direction of the top deck (runs through the center - of the central cylinder structure element) - - +Y axis: Direction of the vector orthogonal to the +Z axis and - parallel to the deployed MAG boom - - +X axis: The third orthogonal axis defined using an X, Y, Z ordered - right hand rule - - NB: The Observatory Pointing and Dynamics Reference Frame is also - defined in [5]. It is identical to the observatory mechanical design - reference frame, but with the origin translated to the observatory - center of mass (which changes with boom deployment and fuel usage). - The offset difference between the mechanical and dynamic frame is - within the uncertainty range of the ephemeris, so the mechanical - design frame is used here for definiteness. - - Three different views [5,6] of the spacecraft with labeled components - are presented below for illustrative purposes. - - - IMAP -Z Bottom View (Figure 3-2 in [5], G-G in [6] rotated 180Β°) - --------------------------------------------------------------------- - --------- - | +X axis | -------------------- - --------- | +Z axis facing Sun | - . | into page | - /|\ -------------------- - | - | - | - _ - HI 45 /`~~__HI 90 `+ direction of - , = .^ - /_ ``-. '. positive - .+ + `^~/ ./ ~ rotation - ^ + + . -- ' `` \ _-~ \ - _ / ',= ' \~'` \ IMAP \ - ULTRA /' '-_ .~ ' \,.=.. \ LO \|/ - 90 / ~ _,.,_ + + \ ' - / ,~' +' `'+ + + \ - / ~^ .' , = .'. '- ='' -`` --------- - ^/ / , = . + + \ \~'` | +Y axis |-----> - | . + + + + . \ --------- ___ - | | + + ' = ' | \--------------------| | - SWAPI| | ' = ', - . | /--------------------|___| - _+_: ' + + ' / MAG boom - \_ __\__ \ + + / /^*~, - + | SWE '. ' = ' .' ULTRA / - `~-' '~..,___,..~' 45 /~,* - _\ / /~,*` - * / CODICE ^*._/ *` HIT - *\ _/`. / - * / /~ _ _ ,.-^-., _ _ _ / - '=' + + - GLOWS + + - '-.,.-' - IDEX - - - IMAP +X Side View (F-F in [6]) - --------------------------------------------------------------------- - --------- - | +Z axis | - --------- --------------------- - . | +X axis out of page | - /|\ --------------------- - | LGA - __________________|______|^|_________ ___ - SWAPI|__________________|__________________|====================| | - #|-| | | .-==-, | / MAG boom '---' - #|-| {|## | | / \ | | - | {|## | |{ HI 90 }| IMAP LO| - | {|## | _.._ | \ / | _., | - | ULTRA | / \ | `-==-' | / __`',| - | 90 | \ HI 45/ | | \ \_\ ;| - | | '----` | | ~._ + | - '-------------------|----------/--------' - | | \_________O_________/ | | ----------------> - |__| ----------- /_\ --------- - STAR | S/C FRAME | MGA | +Y axis | - TRACKERS | ORIGIN | --------- - ----------- - - - IMAP -X Side View (C-C in [6]) - --------------------------------------------------------------------- - --------- - | +Z axis | - ------------------- --------- - | +X axis into page | . - ------------------- /|\ - LGA | - ___ _________|^|______|__________________ - | |====================|__________________|_____________ __ _|SWAPI - '---' MAG boom \ __ | | | // \ /--|# - |( )=|__|| | | \\__/ \--|# - | HIT | _|_ IDEX | CODICE | - | | ,.' | '., | | - | ____ | [ \ | / ] | SWE| - ULTRA ##',', |,.'|'.,| GLOWS (#)| - 45 ####'. + | + \\(O) |-|| - '----####/----- + | + --------------' - <---------------- | | \______'-.O.-'______/ | | - --------- /_\ ----------- |__| - | +Y axis | MGA | S/C FRAME | STAR - --------- | ORIGIN | TRACKERS - ----------- - - - IMAP Component Location and Orientation - --------------------------------------------------------------------- - - Payload and subsystem component locations are specified[5,6] in the - Observatory Mechanical Design Reference Frame (described above). - Boresights are defined in azimuth and elevation (and resultant - direction cosign matrices) of these angles[6] in the same reference - frame. The azimuth and elevation angle diagram is provided below. - - In general, descriptions in this kernel treat the +Z direction as - "up" and the -Z direction as "down." Locations referred to as "above" - are generally closer to the Sun, and vice versa for "below." The - "upper" side of the spacecraft is the plane of the solar panels, - while the "lower" side may refer to the area near the adapter ring. - If ambiguity could arise, more thorough descriptions will be used. - - - Toward Sun - - +Z axis - . - | - . - | - . Component - | Location/ - . Orientation - | @ - Toward . .'| - MAG | +` | - .~ '` Boom S/C . .` \ | - .~ '` FRAME |.` : | - / ~'` ORIGIN O | | - *--- .~ '` \ Elevation - .~ '` \ | | - .~ '` \ ; |~ - .~ '\ \ / | ^~ - +Y axis \ \ + | ^~ - '. '~, \ | ^~ - '~ Azimuth \ | ^~ - '~. `^~-> \| -X axis - ' ~ ., _ _ ,.~ - ``'`` - - - \begindata - - FRAME_IMAP_SPACECRAFT = -43000 - FRAME_-43000_NAME = 'IMAP_SPACECRAFT' - FRAME_-43000_CLASS = 3 - FRAME_-43000_CLASS_ID = -43000 - FRAME_-43000_CENTER = -43 - CK_-43000_SCLK = -43 - CK_-43000_SPK = -43 - - \begintext - - -IMAP Thruster Frames -======================================================================== - - There are four axial (A) thrusters and eight radial (R) thrusters on - IMAP[6]. The table below shows the thruster positions defined in the - spacecraft frame[6], at the intersection of the thrust axis and the - nozzle exit plane. The unit direction vectors listed in the table - below point in the direction of the thruster exhaust. The positional - information is captured in the IMAP structure SPK, while the - orientation information is captured here. - - - Thruster ID X (mm) Y (mm) Z (mm) UnitDir (X,Y,Z) - ---------------- ------ -------- -------- ------- --------------- - IMAP_THRUSTER_A1 -43010 1007.28 516.50 1312.40 ( 0, 0, 1 ) - IMAP_THRUSTER_A2 -43011 -1007.28 -516.50 1312.40 ( 0, 0, 1 ) - IMAP_THRUSTER_A3 -43012 -1007.28 -516.50 101.77 ( 0, 0, -1 ) - IMAP_THRUSTER_A4 -43013 1007.28 516.50 101.77 ( 0, 0, -1 ) - IMAP_THRUSTER_R1 -43020 -126.90 1237.78 841.12 (-0.5, 0.866,0) - IMAP_THRUSTER_R2 -43021 126.90 -1237.78 841.12 ( 0.5,-0.866,0) - IMAP_THRUSTER_R3 -43022 -1008.49 728.79 841.12 (-0.5, 0.866,0) - IMAP_THRUSTER_R4 -43023 1008.49 -728.79 841.12 ( 0.5,-0.866,0) - IMAP_THRUSTER_R5 -43024 -126.90 1237.78 447.42 (-0.5, 0.866,0) - IMAP_THRUSTER_R6 -43025 126.90 -1237.78 447.42 ( 0.5,-0.866,0) - IMAP_THRUSTER_R7 -43026 -1008.49 728.79 447.42 (-0.5, 0.866,0) - IMAP_THRUSTER_R8 -43027 1008.49 -728.79 447.42 ( 0.5,-0.866,0) - - - Thruster Locations and Directions - --------------------------------------------------------------------- - - The four axial thrusters[6] are directed along the spacecraft Z axis, - with A1,A2 located on the +Z side of the spacecraft and A3,A4 located - on the -Z side. A1,A2 fire in the +Z direction, while A3,A4 fire in - the -Z direction. A1 and A4 are aligned in the Z direction, while - A2 and A3 are aligned but on the opposite side of the S/C as A1/A4. - - The eight radial thrusters[6] are grouped into four pairs (R1/R5, - R2/R6, R3/R7, R4/R8); each pair is aligned along the Z direction and - fire in the same direction. There are two distinct firing directions, - all perpendicular to the spacecraft Z axis: R1/R5 & R3/R7 fire toward - the +Y direction (with a slight -X component), while R2/R6 & R4/R8 - fire in the -Y direction (with a slight +X component). Thrusters - R1-R4 are located above the center of mass (towards the Sun), while - thrusters R5-R8 are located below the center of mass (away from the - Sun). The table below shows the azimuth of location and direction of - radial thrusters calculated from using thruster table above. - - - Location Azim Direction Azim - -------------- -------------- - R1/R5 5.85Β° 30.0Β° - R2/R6 180Β° + 5.85Β° 180Β° + 30.0Β° - R3/R7 54.15Β° 30.0Β° - R4/R8 180Β° + 54.15Β° 180Β° + 30.0Β° - - - +X axis +Z axis facing Sun - . into page - /|\ - | - | - | A1 (on +Z side) - A4 (on -Z side) - R4/R8 Dir /`~~__ / - '~._ , = .^ - /_ ``-. / - /~._ .+ + `^~/ .\/ - 30Β°| '~. + . -- ' `` @\ _-~ - - - + - - - -# R4/R8 \~'` \ - /' '-_ . \,.=.. \ - / ~ _,.,_ + + \ - R2/R6 Dir / ,~' +' `'+ + + \ - '~._ / ~^ .' , = .'. '- ='' -`` - /~._ ^/ / , = . + + \ \~'` - 30Β°| '~. | . + + + + . \ +Y axis -----> - - - + - - - -|# R2/R6 | + + ' = ' | \ - | | ' = ', - . | R1/R5 #._- - - - - + - - - _+_: ' + + ' / '~._ | - \_ __\__ \ + + / /^*~, '~._ / 30Β° - + | \ '. ' = ' .' / / '~. - `~-' '~..,___,..~' / /~,* R1/R5 Dir - _\ / /~,*` - * / \ ^*._/ *` - *\ _/`. R3/R7 #/._- - - - - + - - - * / /\@_ _ ,.-^-., _ _ _ / '~._ | - '=' | + + '~._ / 30Β° - | + + '~. - | '-.,.-' R3/R7 Dir - | - A2 (on +Z side) - A3 (on -Z side) - - - Axial Thruster Frames - --------------------------------------------------------------------- - - Each axial thruster has a frame defined so that the thruster exhaust - exits in the +Z' direction. The +Y' axis is chosen to lie in the - direction of the MAG boom. X' = Y' x Z' completes the frame. - - [X] [ 1 0 0 ] [X'] - [Y] = [ 0 1 0 ] [Y'] - [Z]S/C [ 0 0 1 ] [Z']Axial Thrusters A1,A2 - - [X] [ -1 0 0 ] [X'] - [Y] = [ 0 1 0 ] [Y'] - [Z]S/C [ 0 0 -1 ] [Z']Axial Thrusters A3,A4 - - - Axial Thruster - Exhaust Direction - - +Z' axis - | - | - _. -|- ._ - ,' | ', - |, | ,| - | ' -.,_|_,.- ' | - ' ' - \ / - \ / - \ / - \ / - \ / Toward - ',_,' ^~ MAG - .~ '` ^~ ^~ Boom - .~ '` ^~ ^~ - .~ '` ^~ ^~ - .~ '` ^~ ^~ \ - +X' axis ^~ --* - ^~ - ^~ - +Y' axis - - - \begindata - - FRAME_IMAP_THRUSTER_A1 = -43010 - FRAME_-43010_NAME = 'IMAP_THRUSTER_A1' - FRAME_-43010_CLASS = 4 - FRAME_-43010_CLASS_ID = -43010 - FRAME_-43010_CENTER = -43 - TKFRAME_-43010_RELATIVE = 'IMAP_SPACECRAFT' - TKFRAME_-43010_SPEC = 'MATRIX' - TKFRAME_-43010_MATRIX = ( 1, - 0, - 0, - 0, - 1, - 0, - 0, - 0, - 1 ) - - FRAME_IMAP_THRUSTER_A2 = -43011 - FRAME_-43011_NAME = 'IMAP_THRUSTER_A2' - FRAME_-43011_CLASS = 4 - FRAME_-43011_CLASS_ID = -43011 - FRAME_-43011_CENTER = -43 - TKFRAME_-43011_RELATIVE = 'IMAP_SPACECRAFT' - TKFRAME_-43011_SPEC = 'MATRIX' - TKFRAME_-43011_MATRIX = ( 1, - 0, - 0, - 0, - 1, - 0, - 0, - 0, - 1 ) - - FRAME_IMAP_THRUSTER_A3 = -43012 - FRAME_-43012_NAME = 'IMAP_THRUSTER_A3' - FRAME_-43012_CLASS = 4 - FRAME_-43012_CLASS_ID = -43012 - FRAME_-43012_CENTER = -43 - TKFRAME_-43012_RELATIVE = 'IMAP_SPACECRAFT' - TKFRAME_-43012_SPEC = 'MATRIX' - TKFRAME_-43012_MATRIX = ( -1, - 0, - 0, - 0, - 1, - 0, - 0, - 0, - -1 ) - - FRAME_IMAP_THRUSTER_A4 = -43013 - FRAME_-43013_NAME = 'IMAP_THRUSTER_A4' - FRAME_-43013_CLASS = 4 - FRAME_-43013_CLASS_ID = -43013 - FRAME_-43013_CENTER = -43 - TKFRAME_-43013_RELATIVE = 'IMAP_SPACECRAFT' - TKFRAME_-43013_SPEC = 'MATRIX' - TKFRAME_-43013_MATRIX = ( -1, - 0, - 0, - 0, - 1, - 0, - 0, - 0, - -1 ) - - \begintext - - - Radial Thrusters - --------------------------------------------------------------------- - - Each radial thruster has a frame defined so that the thruster exhaust - exits in the +Y' direction. The +Z' axis is chosen to lie along the - spacecraft +Z axis (toward Sun). X' = Y' x Z' completes the frame. - - [X] [ cos( 30) -sin( 30) 0 ] [X'] - [Y] = [ sin( 30) cos( 30) 0 ] [Y'] - [Z]S/C [ 0 0 1 ] [Z']Rad. Thrusters R1,R3,R5,R7 - - [X] [ cos(210) -sin(210) 0 ] [X'] - [Y] = [ sin(210) cos(210) 0 ] [Y'] - [Z]S/C [ 0 0 1 ] [Z']Rad. Thrusters R2,R4,R6,R8 - - - Toward Sun - - +Z' axis - . - | - . - | - . - | - . - Radial Thruster | - Exhaust Direction . - | - .~ '` . - /.~ '` _,,~ ~ ~ ~ ~ ~ ~ ~ | - *-- .;-. \ ~ - ,' '. ~ ^~ - ; \ ~' ^~ - | .~ '`: ~' ^~ - .~ '` | ~' ^~ - ~ '` \ ; _ ~' ^~ - +Y' axis '.,_._;-' ^~ - ^~ - -X' axis - - - \begindata - - FRAME_IMAP_THRUSTER_R1 = -43020 - FRAME_-43020_NAME = 'IMAP_THRUSTER_R1' - FRAME_-43020_CLASS = 4 - FRAME_-43020_CLASS_ID = -43020 - FRAME_-43020_CENTER = -43 - TKFRAME_-43020_RELATIVE = 'IMAP_SPACECRAFT' - TKFRAME_-43020_SPEC = 'MATRIX' - TKFRAME_-43020_MATRIX = ( 0.86602540378443865, - 0.50000000000000000, - 0.00000000000000000, - -0.50000000000000000, - 0.86602540378443865, - 0.00000000000000000, - 0.00000000000000000, - 0.00000000000000000, - 1.00000000000000000 ) - - FRAME_IMAP_THRUSTER_R2 = -43021 - FRAME_-43021_NAME = 'IMAP_THRUSTER_R1' - FRAME_-43021_CLASS = 4 - FRAME_-43021_CLASS_ID = -43021 - FRAME_-43021_CENTER = -43 - TKFRAME_-43021_RELATIVE = 'IMAP_SPACECRAFT' - TKFRAME_-43021_SPEC = 'MATRIX' - TKFRAME_-43021_MATRIX = ( -0.86602540378443865, - -0.50000000000000000, - 0.00000000000000000, - 0.50000000000000000, - -0.86602540378443865, - 0.00000000000000000, - 0.00000000000000000, - 0.00000000000000000, - 1.00000000000000000 ) - - FRAME_IMAP_THRUSTER_R3 = -43022 - FRAME_-43022_NAME = 'IMAP_THRUSTER_R3' - FRAME_-43022_CLASS = 4 - FRAME_-43022_CLASS_ID = -43022 - FRAME_-43022_CENTER = -43 - TKFRAME_-43022_RELATIVE = 'IMAP_SPACECRAFT' - TKFRAME_-43022_SPEC = 'MATRIX' - TKFRAME_-43022_MATRIX = ( 0.86602540378443865, - 0.50000000000000000, - 0.00000000000000000, - -0.50000000000000000, - 0.86602540378443865, - 0.00000000000000000, - 0.00000000000000000, - 0.00000000000000000, - 1.00000000000000000 ) - - FRAME_IMAP_THRUSTER_R4 = -43023 - FRAME_-43023_NAME = 'IMAP_THRUSTER_R4' - FRAME_-43023_CLASS = 4 - FRAME_-43023_CLASS_ID = -43023 - FRAME_-43023_CENTER = -43 - TKFRAME_-43023_RELATIVE = 'IMAP_SPACECRAFT' - TKFRAME_-43023_SPEC = 'MATRIX' - TKFRAME_-43023_MATRIX = ( -0.86602540378443865, - -0.50000000000000000, - 0.00000000000000000, - 0.50000000000000000, - -0.86602540378443865, - 0.00000000000000000, - 0.00000000000000000, - 0.00000000000000000, - 1.00000000000000000 ) - - FRAME_IMAP_THRUSTER_R5 = -43024 - FRAME_-43024_NAME = 'IMAP_THRUSTER_R5' - FRAME_-43024_CLASS = 4 - FRAME_-43024_CLASS_ID = -43024 - FRAME_-43024_CENTER = -43 - TKFRAME_-43024_RELATIVE = 'IMAP_SPACECRAFT' - TKFRAME_-43024_SPEC = 'MATRIX' - TKFRAME_-43024_MATRIX = ( 0.86602540378443865, - 0.50000000000000000, - 0.00000000000000000, - -0.50000000000000000, - 0.86602540378443865, - 0.00000000000000000, - 0.00000000000000000, - 0.00000000000000000, - 1.00000000000000000 ) - - FRAME_IMAP_THRUSTER_R6 = -43025 - FRAME_-43025_NAME = 'IMAP_THRUSTER_R6' - FRAME_-43025_CLASS = 4 - FRAME_-43025_CLASS_ID = -43025 - FRAME_-43025_CENTER = -43 - TKFRAME_-43025_RELATIVE = 'IMAP_SPACECRAFT' - TKFRAME_-43025_SPEC = 'MATRIX' - TKFRAME_-43025_MATRIX = ( -0.86602540378443865, - -0.50000000000000000, - 0.00000000000000000, - 0.50000000000000000, - -0.86602540378443865, - 0.00000000000000000, - 0.00000000000000000, - 0.00000000000000000, - 1.00000000000000000 ) - - FRAME_IMAP_THRUSTER_R7 = -43026 - FRAME_-43026_NAME = 'IMAP_THRUSTER_R7' - FRAME_-43026_CLASS = 4 - FRAME_-43026_CLASS_ID = -43026 - FRAME_-43026_CENTER = -43 - TKFRAME_-43026_RELATIVE = 'IMAP_SPACECRAFT' - TKFRAME_-43026_SPEC = 'MATRIX' - TKFRAME_-43026_MATRIX = ( 0.86602540378443865, - 0.50000000000000000, - 0.00000000000000000, - -0.50000000000000000, - 0.86602540378443865, - 0.00000000000000000, - 0.00000000000000000, - 0.00000000000000000, - 1.00000000000000000 ) - - FRAME_IMAP_THRUSTER_R8 = -43027 - FRAME_-43027_NAME = 'IMAP_THRUSTER_R6' - FRAME_-43027_CLASS = 4 - FRAME_-43027_CLASS_ID = -43027 - FRAME_-43027_CENTER = -43 - TKFRAME_-43027_RELATIVE = 'IMAP_SPACECRAFT' - TKFRAME_-43027_SPEC = 'MATRIX' - TKFRAME_-43027_MATRIX = ( -0.86602540378443865, - -0.50000000000000000, - 0.00000000000000000, - 0.50000000000000000, - -0.86602540378443865, - 0.00000000000000000, - 0.00000000000000000, - 0.00000000000000000, - 1.00000000000000000 ) - - \begintext - - -IMAP Sun Sensor Frames -======================================================================== - - There are two digital sun sensors (DSS): one on the +Z side of the - spacecraft pointing in +Z direction, and one on the -Z side pointing - mostly in the radial direction with a mild tilt in the -Z direction. - The positional information is captured in the IMAP structure SPK, - while the orientation information is captured here. - - Each DSS has a frame defined so that the look-direction is along the - +Z' axis (toward Sun). The digital image rows and columns are aligned - with the X' and Y' axes of the frame. - - [X] [ cos(az) -sin(az) 0 ] [X'] - [Y] = [ sin(az) cos(az) 0 ] [Y'] - [Z]S/C [ 0 0 1 ] [Z']Digital Sun Sensor - - -IMAP Star Trackers Frames -======================================================================== - - -IMAP Antenna Frames -======================================================================== - - -IMAP-Lo Frames -======================================================================== - - TODO: FIX ME...The orientation of the spacecraft body frame with - respect to an inertial - frame, for IMAP - ECLIPJ2000, is provided by a C-kernel (see [3] - for details). - - This frame specifies the rotating X,Y and pointing Z coordinate body - frame. - - \begindata - - FRAME_IMAP_LO_BASE = -43100 - FRAME_-43100_NAME = 'IMAP_LO_BASE' - FRAME_-43100_CLASS = 4 - FRAME_-43100_CLASS_ID = -43100 - FRAME_-43100_CENTER = -43 - TKFRAME_-43100_SPEC = 'MATRIX' - TKFRAME_-43100_MATRIX = ( -0.866025, - 0.500000, - 0.000000, - -0.500000, - -0.866025, - 0.000000, - 0.000000, - 0.000000, - 1.000000 ) - TKFRAME_-43100_RELATIVE = 'IMAP_SPACECRAFT' - - \begintext - - -IMAP-Hi Frames -======================================================================== - - TODO: general discussion of Ultra. - - - IMAP-Hi 45 Frames - ===================================================================== - - \begindata - - FRAME_IMAP_HI_45 = -43150 - FRAME_-43150_NAME = 'IMAP_HI_45' - FRAME_-43150_CLASS = 4 - FRAME_-43150_CLASS_ID = -43150 - FRAME_-43150_CENTER = -43 - TKFRAME_-43150_SPEC = 'MATRIX' - TKFRAME_-43150_MATRIX = ( 0.066987, - -0.250000, - 0.965926, - 0.965926, - 0.258819, - 0.000000, - -0.250000, - 0.933013, - 0.258819 ) - TKFRAME_-43150_RELATIVE = 'IMAP_SPACECRAFT' - - \begintext - - - IMAP-Hi 90 Frames - ===================================================================== - - TODO: FIX ME...The orientation of the spacecraft body frame with - respect to an inertial - frame, for IMAP - ECLIPJ2000, is provided by a C-kernel (see [3] - for details). - - This frame specifies the rotating X,Y and pointing Z coordinate body - frame. - - \begindata - - FRAME_IMAP_HI_90 = -43160 - FRAME_-43160_NAME = 'IMAP_HI_90' - FRAME_-43160_CLASS = 4 - FRAME_-43160_CLASS_ID = -43160 - FRAME_-43160_CENTER = -43 - TKFRAME_-43160_SPEC = 'MATRIX' - TKFRAME_-43160_MATRIX = ( -0.668531, - 0.233315, - -0.706138, - 0.683013, - -0.183013, - -0.707107, - -0.294210, - -0.955024, - -0.037007 ) - TKFRAME_-43160_RELATIVE = 'IMAP_SPACECRAFT' - - \begintext - - -IMAP-Ultra Frames -======================================================================== - - TODO: general discussion of Ultra. - - - IMAP-Ultra 45 Frames - ===================================================================== - - TODO: add diagrams - - ULTRA-45 has the following nominal alignment to the spacecraft frame, - reference Table 1 of [6]. The azimuth and elevation angles are - illustrated in the 'IMAP I&T Component Placement' section near the top - of this document. - - azimuth | elevation - (deg) | (deg) - ---------+--------- - 127 | 15 - - The ULTRA-45 base frame is defined by the instrument team as follows [10]: - - * +Z axis is the boresight (center axis of the instrument pointing - away from the spacecraft body). - * +X axis is along the instrument slit, in the anti-sunward direction. - - The azimuth and elevation give the instrument boresight vector, +Z in - the instrument frame: - - Z = [ -sin(az) * cos(el), cos(az) * cos(el), sin(el) ] - instr - - The instrument +X axis is in the anti-sunward direction, towards the - spacecraft -Z axis: - - X = [ 0 0 -1 ] - instr - - Taking the cross product and normalizing, we arrive at the instrumet +Y - axis: - Z x X - Y = --------- - instr | Z x X | - - And adjusting X: - - Y x Z - X = --------- - instr | Y x Z | - - This definition is captured in the keywords below. - - \begindata - - FRAME_IMAP_ULTRA_45 = -43200 - FRAME_-43200_NAME = 'IMAP_ULTRA_45' - FRAME_-43200_CLASS = 4 - FRAME_-43200_CLASS_ID = -43200 - FRAME_-43200_CENTER = -43 - TKFRAME_-43200_SPEC = 'MATRIX' - TKFRAME_-43200_MATRIX = ( 0.385117954958023, - -0.593029645775782, - -0.707106781186548, - -0.838670567945424, - -0.544639035015027, - -0.000000000000000, - -0.385117954958023, - 0.593029645775783, - -0.707106781186547 ) - TKFRAME_-43200_RELATIVE = 'IMAP_SPACECRAFT' - - \begintext - - - IMAP-Ultra 45 Frames - ===================================================================== - - TODO: FIX ME...The orientation of the spacecraft body frame with - respect to an inertial - frame, for IMAP - ECLIPJ2000, is provided by a C-kernel (see [3] - for details). - - This frame specifies the rotating X,Y and pointing Z coordinate body - frame. - - \begindata - - FRAME_IMAP_ULTRA_90 = -43210 - FRAME_-43210_NAME = 'IMAP_ULTRA_90' - FRAME_-43210_CLASS = 4 - FRAME_-43210_CLASS_ID = -43210 - FRAME_-43210_CENTER = -43 - TKFRAME_-43210_SPEC = 'MATRIX' - TKFRAME_-43210_MATRIX = ( 0.000000, - 0.000000, - 1.000000, - -0.866025, - -0.500000, - 0.000000, - 0.500000, - -0.866025, - 0.000000 ) - TKFRAME_-43210_RELATIVE = 'IMAP_SPACECRAFT' - - \begintext - - -IMAP Magnetometer (MAG) Frames -======================================================================== - - TODO: FIX ME...The orientation of the spacecraft body frame with - respect to an inertial - frame, for IMAP - ECLIPJ2000, is provided by a C-kernel (see [3] - for details). - - Basically just maps Z-inst to Y-body - - This frame specifies the rotating X,Y and pointing Z coordinate body - frame. - - \begindata - - FRAME_IMAP_MAG = -43250 - FRAME_-43250_NAME = 'IMAP_MAG' - FRAME_-43250_CLASS = 4 - FRAME_-43250_CLASS_ID = -43250 - FRAME_-43250_CENTER = -43 - TKFRAME_-43250_SPEC = 'MATRIX' - TKFRAME_-43250_MATRIX = ( 0.000000, - -1.000000, - 0.000000, - -1.000000, - 0.000000, - 0.000000, - 0.000000, - 0.000000, - -1.000000 ) - TKFRAME_-43250_RELATIVE = 'IMAP_SPACECRAFT' - -\begintext - - -IMAP Solar Wind Electron (SWE) Frames -======================================================================== - - TODO: FIX ME...The orientation of the spacecraft body frame with - respect to an inertial - frame, for IMAP - ECLIPJ2000, is provided by a C-kernel (see [3] - for details). - - This frame specifies the rotating X,Y and pointing Z coordinate body - frame. - - \begindata - - FRAME_IMAP_SWE = -43300 - FRAME_-43300_NAME = 'IMAP_SWE' - FRAME_-43300_CLASS = 4 - FRAME_-43300_CLASS_ID = -43300 - FRAME_-43300_CENTER = -43 - TKFRAME_-43300_SPEC = 'MATRIX' - TKFRAME_-43300_MATRIX = ( 0.453990, - 0.891007, - 0.000000, - -0.891007, - 0.453990, - 0.000000, - 0.000000, - 0.000000, - 1.000000 ) - TKFRAME_-43300_RELATIVE = 'IMAP_SPACECRAFT' - -\begintext - - -IMAP Solar Wind and Pickup Ion (SWAPI) Frames -======================================================================== - - TODO: add diagrams - - SWAPI has the following nominal alignment to the spacecraft frame, - reference Table 1 of [6]. The azimuth and elevation angles are - illustrated in the 'IMAP I&T Component Placement' section near the top - of this document. - - azimuth | elevation - (deg) | (deg) - ---------+--------- - 168 | 0 - - The SWAPI base frame is defined in the instrument MICD [8] as follows: - - * -Z axis is the axis of symmetry of the instrument, pointing - away from the spacecraft body. - * +Y axis is along the aperture center, in the anti-sunward direction. - - The azimuth and elevation give the outward axis of symmetry, -Z in the - instrument frame: - - -Z = -[ -sin(az) * cos(el), cos(az) * cos(el), sin(el) ] - instr - - The instrument +Y axis is in the sunward direction, towards the - spacecraft +Z axis: - - Y = [ 0 0 1 ] - instr - - Taking the cross product and normalizing, we arrive at the instrumet +X - axis: - Y x Z - X = --------- - instr | Y x Z | - - And adjusting Y: - - Z x X - Y = --------- - instr | Z x X | - - This definition is captured in the keywords below. - - \begindata - - FRAME_IMAP_SWAPI = -43350 - FRAME_-43350_NAME = 'IMAP_SWAPI' - FRAME_-43350_CLASS = 4 - FRAME_-43350_CLASS_ID = -43350 - FRAME_-43350_CENTER = -43 - TKFRAME_-43350_SPEC = 'MATRIX' - TKFRAME_-43350_MATRIX = ( -0.97814760073381, - 0.20791169081776, - 0.00000000000000, - 0.00000000000000, - 0.00000000000000, - 1.00000000000000, - 0.20791169081776, - 0.97814760073381, - 0.00000000000000 ) - TKFRAME_-43350_RELATIVE = 'IMAP_SPACECRAFT' - -\begintext - - -IMAP Compact Dual Ion Composition Experiment (CoDICE) Frames -======================================================================== - - TODO: FIX ME...The orientation of the spacecraft body frame with - respect to an inertial - frame, for IMAP - ECLIPJ2000, is provided by a C-kernel (see [3] - for details). - - This frame specifies the rotating X,Y and pointing Z coordinate body - frame. - - \begindata - - FRAME_IMAP_CODICE = -43400 - FRAME_-43400_NAME = 'IMAP_CODICE' - FRAME_-43400_CLASS = 4 - FRAME_-43400_CLASS_ID = -43400 - FRAME_-43400_CENTER = -43 - TKFRAME_-43400_SPEC = 'MATRIX' - TKFRAME_-43400_MATRIX = ( 0.694626, - 0.719371, - 0.000000, - -0.719371, - 0.694626, - 0.000000, - 0.000000, - 0.000000, - 1.000000 ) - TKFRAME_-43400_RELATIVE = 'IMAP_SPACECRAFT' - -\begintext - - -IMAP High-energy Ion Telescope (HIT) Frames -======================================================================== - - TODO: FIX ME...The orientation of the spacecraft body frame with - respect to an inertial - frame, for IMAP - ECLIPJ2000, is provided by a C-kernel (see [3] - for details). - - This frame specifies the rotating X,Y and pointing Z coordinate body - frame. - - \begindata - - FRAME_IMAP_HIT = -43500 - FRAME_-43500_NAME = 'IMAP_HIT' - FRAME_-43500_CLASS = 4 - FRAME_-43500_CLASS_ID = -43500 - FRAME_-43500_CENTER = -43 - TKFRAME_-43500_SPEC = 'MATRIX' - TKFRAME_-43500_MATRIX = ( 0.866025, - 0.500000, - 0.000000, - -0.500000, - 0.866025, - 0.000000, - 0.000000, - 0.000000, - 1.000000 ) - TKFRAME_-43500_RELATIVE = 'IMAP_SPACECRAFT' - -\begintext - - -IMAP Interstellar Dust Experiment (IDEX) Frames -======================================================================== - - TODO: FIX ME...The orientation of the spacecraft body frame with - respect to an inertial - frame, for IMAP - ECLIPJ2000, is provided by a C-kernel (see [3] - for details). - - This frame specifies the rotating X,Y and pointing Z coordinate body - frame. - - \begindata - - FRAME_IMAP_IDEX = -43700 - FRAME_-43700_NAME = 'IMAP_IDEX' - FRAME_-43700_CLASS = 4 - FRAME_-43700_CLASS_ID = -43700 - FRAME_-43700_CENTER = -43 - TKFRAME_-43700_SPEC = 'MATRIX' - TKFRAME_-43700_MATRIX = ( 0.000000, - 1.000000, - 0.000000, - -0.707107, - 0.000000, - -0.707107, - -0.707107, - 0.000000, - 0.707107 ) - TKFRAME_-43700_RELATIVE = 'IMAP_SPACECRAFT' - -\begintext - - -IMAP GLObal solar Wind Structure (GLOWS) Frames -======================================================================== - - TODO: add diagrams - - GLOWS has the following nominal alignment to the spacecraft frame, - reference Table 1 of [6]. The azimuth and elevation angles are - illustrated in the 'IMAP I&T Component Placement' section near the top - of this document. - - azimuth | elevation - (deg) | (deg) - ---------+--------- - 127 | 15 - - The GLOWS base frame is defined by the instrument team as follows [10]: - - * +Z axis points in the anti-boresight direction - * +Y axis points in the anti-sunward direction. - - The azimuth and elevation give the outward axis of symmetry, -Z in the - instrument frame: - - Z = -[ -sin(az) * cos(el), cos(az) * cos(el), sin(el) ] - instr - - The instrument +Y axis is in the anti-sunward direction, towards the - spacecraft -Z axis: - - Y = [ 0 0 -1 ] - instr - - Taking the cross product and normalizing, we arrive at the instrumet +X - axis: - Y x Z - X = --------- - instr | Y x Z | - - And adjusting Y: - - Z x X - Y = --------- - instr | Z x X | - - This definition is captured in the keywords below. - - \begindata - - FRAME_IMAP_GLOWS = -43750 - FRAME_-43750_NAME = 'IMAP_GLOWS' - FRAME_-43750_CLASS = 4 - FRAME_-43750_CLASS_ID = -43750 - FRAME_-43750_CENTER = -43 - TKFRAME_-43750_SPEC = 'MATRIX' - TKFRAME_-43750_MATRIX = ( 0.60181502315205, - -0.79863551004729, - 0.00000000000000, - -0.20670208009540, - -0.15576118962056, - -0.96592582628907, - 0.77142266494622, - 0.58130867351132, - -0.25881904510252 ) - TKFRAME_-43750_RELATIVE = 'IMAP_SPACECRAFT' - -\begintext - - Generic axis - - +Z axis - . - | - . - | - . - | - . - | - . - | - . - | - .~ ~ - .~ '` ^~ - .~ '` ^~ - .~ '` ^~ - .~ '` ^~ - +X axis ^~ - ^~ - ^~ - +Y axis - -End of FK file. \ No newline at end of file diff --git a/imap_processing/tests/spice/test_geometry.py b/imap_processing/tests/spice/test_geometry.py index 585d482c93..8e0465ba03 100644 --- a/imap_processing/tests/spice/test_geometry.py +++ b/imap_processing/tests/spice/test_geometry.py @@ -19,11 +19,19 @@ get_spacecraft_to_instrument_spin_phase_offset, imap_state, instrument_pointing, + lo_instrument_pointing, solar_longitude, spherical_to_cartesian, ) +def test_spice_frame_enum(furnish_kernels): + """Test that the SpiceFrame enum values match imap frames kernel.""" + with furnish_kernels(["imap_130.tf", "imap_science_120.tf"]): + for frame in SpiceFrame: + assert frame.value == spiceypy.namfrm(frame.name) + + @pytest.mark.parametrize( "et", [ @@ -52,10 +60,10 @@ def test_imap_state_ecliptic(imap_ena_sim_metakernel): [ # Expected spin-phase offsets based on 7516-0011_drw.pdf (SpiceFrame.IMAP_LO_BASE, (60, 0)), # (330 + 90) % 360 = 60 - # Note HI_45 and HI_90 appear to be swapped in imap_wkcp.tf so the - # expected values are swapped here. - (SpiceFrame.IMAP_HI_45, (15, 0)), # 255 + 90 = 345 - (SpiceFrame.IMAP_HI_90, (345, -45)), # (285 + 90) % 360 = 15 + # TODO: we need a Lo-pivot CK to test IMAP_LO + # (SpiceFrame.IMAP_LO, (60, 0)), # (330 + 90) % 360 = 60 + (SpiceFrame.IMAP_HI_45, (345, -45)), # 255 + 90 = 345 + (SpiceFrame.IMAP_HI_90, (15, 0)), # (285 + 90) % 360 = 15 (SpiceFrame.IMAP_ULTRA_45, (123, -45)), # 33 + 90 = 123 (SpiceFrame.IMAP_ULTRA_90, (300, 0)), # 210 + 90 = 300 (SpiceFrame.IMAP_SWAPI, (258, 0)), # 168 + 90 = 258 @@ -64,23 +72,26 @@ def test_imap_state_ecliptic(imap_ena_sim_metakernel): (SpiceFrame.IMAP_HIT, (120, 0)), # 30 + 90 = 120 (SpiceFrame.IMAP_SWE, (243, 0)), # 153 + 90 = 243 (SpiceFrame.IMAP_GLOWS, (217, 15)), # 127 + 90 = 217 - (SpiceFrame.IMAP_MAG, (90, 0)), # 0 + 90 = 90 + (SpiceFrame.IMAP_MAG_I, (90, 0)), # 0 + 90 = 90 + (SpiceFrame.IMAP_MAG_O, (90, 0)), # 0 + 90 = 90 ], ) def test_get_instrument_mounting_az_el( furnish_kernels, spice_test_data_path, instrument, expected_az_el ): """Test coverage for get_instrument_mounting_az_el()""" - with furnish_kernels([spice_test_data_path / "imap_wkcp.tf"]): + with furnish_kernels([spice_test_data_path / "imap_130.tf"]): result = get_instrument_mounting_az_el(instrument) - np.testing.assert_allclose(result, expected_az_el, atol=1e-2) + # Testing as built angles against nominal. Allow for 0.75 degrees of + # mounting error. + np.testing.assert_allclose(result, expected_az_el, atol=0.75) @pytest.mark.parametrize( "instrument", [ # Expected spin-phase offsets based on 7516-0011_drw.pdf - SpiceFrame.IMAP_LO_BASE, + SpiceFrame.IMAP_LO, SpiceFrame.IMAP_HI_45, SpiceFrame.IMAP_HI_90, SpiceFrame.IMAP_ULTRA_45, @@ -91,7 +102,8 @@ def test_get_instrument_mounting_az_el( SpiceFrame.IMAP_HIT, SpiceFrame.IMAP_SWE, SpiceFrame.IMAP_GLOWS, - SpiceFrame.IMAP_MAG, + SpiceFrame.IMAP_MAG_I, + SpiceFrame.IMAP_MAG_O, ], ) def test_get_spacecraft_to_instrument_spin_phase_offset( @@ -99,15 +111,13 @@ def test_get_spacecraft_to_instrument_spin_phase_offset( ): """Test coverage for get_spacecraft_to_instrument_spin_phase_offset()""" # Test that the offset is close to SPICE derived mounting azimuth - with furnish_kernels([spice_test_data_path / "imap_wkcp.tf"]): - # TODO: Remove this switch when we get a new imap_frames kernel - # Hi 45 and Hi 90 are swapped in the imap_wkcp.tf kernel - if instrument == SpiceFrame.IMAP_HI_45: - expected = get_instrument_mounting_az_el(SpiceFrame.IMAP_HI_90)[0] / 360 - elif instrument == SpiceFrame.IMAP_HI_90: - expected = get_instrument_mounting_az_el(SpiceFrame.IMAP_HI_45)[0] / 360 - else: - expected = get_instrument_mounting_az_el(instrument)[0] / 360 + with furnish_kernels([spice_test_data_path / "imap_130.tf"]): + # Lo requires an additional kernel to use the below function. So here, + # we use the IMAP_LO_BASE frame to verify + verify_inst = ( + instrument if instrument != SpiceFrame.IMAP_LO else SpiceFrame.IMAP_LO_BASE + ) + expected = get_instrument_mounting_az_el(verify_inst)[0] / 360 result = get_spacecraft_to_instrument_spin_phase_offset(instrument) np.testing.assert_almost_equal(result, expected, decimal=5) @@ -158,8 +168,8 @@ def test_frame_transform(et_strings, position, from_frame, to_frame, furnish_ker kernels = [ "naif0012.tls", "imap_sclk_0000.tsc", - "imap_wkcp.tf", - "imap_science_100.tf", + "imap_130.tf", + "imap_science_120.tf", "sim_1yr_imap_attitude.bc", "sim_1yr_imap_pointing_frame.bc", ] @@ -282,14 +292,56 @@ def test_frame_transform_az_el_same_frame(spice_frame): np.testing.assert_allclose(result, az_el_points) +def test_frame_transform_az_el_3d_input(furnish_kernels): + """Test frame_transform_az_el with 3D input array.""" + kernels = [ + "naif0012.tls", + "imap_001.tf", + "imap_sclk_0000.tsc", + "imap_science_120.tf", + "sim_1yr_imap_attitude.bc", + "sim_1yr_imap_pointing_frame.bc", + ] + with furnish_kernels(kernels): + et = spiceypy.utc2et("2025-06-12T12:00:00.000") + + # Create 3D az_el array with shape (3, 4, 2) + # This represents 3 energy bins with 4 az/el positions each + az_el_3d = np.array( + [ + [[0, 0], [90, 0], [180, 0], [270, 0]], + [[45, 30], [135, 30], [225, 30], [315, 30]], + [[0, -45], [90, -45], [180, -45], [270, -45]], + ] + ) + + result = frame_transform_az_el( + et, az_el_3d, SpiceFrame.IMAP_SPACECRAFT, SpiceFrame.IMAP_DPS, degrees=True + ) + + # Check that output shape matches input shape + assert result.shape == az_el_3d.shape + + # Verify by comparing against processing each 2D slice independently + for i in range(az_el_3d.shape[0]): + expected_slice = frame_transform_az_el( + et, + az_el_3d[i], + SpiceFrame.IMAP_SPACECRAFT, + SpiceFrame.IMAP_DPS, + degrees=True, + ) + np.testing.assert_allclose(result[i], expected_slice, atol=1e-10) + + @pytest.mark.external_kernel def test_get_rotation_matrix(furnish_kernels): """Test coverage for get_rotation_matrix().""" kernels = [ "naif0012.tls", - "imap_wkcp.tf", + "imap_130.tf", "imap_sclk_0000.tsc", - "imap_science_100.tf", + "imap_science_120.tf", "sim_1yr_imap_attitude.bc", "sim_1yr_imap_pointing_frame.bc", "de440s.bsp", @@ -301,23 +353,89 @@ def test_get_rotation_matrix(furnish_kernels): et, SpiceFrame.IMAP_IDEX, SpiceFrame.IMAP_SPACECRAFT ) assert rotation.shape == (3, 3) + assert np.isfinite(rotation).all() # test array of et input rotation = get_rotation_matrix( np.arange(10) + et, SpiceFrame.IMAP_IDEX, SpiceFrame.IMAP_SPACECRAFT ) assert rotation.shape == (10, 3, 3) + for i in range(10): + assert np.isfinite(rotation[i]).all() rotation = get_rotation_matrix( et, SpiceFrame.IMAP_SPACECRAFT, SpiceFrame.IMAP_GSE ) assert rotation.shape == (3, 3) + assert np.isfinite(rotation).all() + + +@pytest.mark.external_kernel +def test_get_rotation_matrix_no_transformation_defined_for_et_allowed(furnish_kernels): + """Test error is swallowed and NaN matrix is returned for undefined SPICE + transformation when allow_spice_noframeconnect is True in get_rotation_matrix().""" + kernels = [ + "naif0012.tls", + "imap_130.tf", + "imap_sclk_0000.tsc", + "imap_science_120.tf", + "sim_1yr_imap_attitude.bc", + "sim_1yr_imap_pointing_frame.bc", + "de440s.bsp", + ] + with furnish_kernels(kernels): + # Midnight is not defined in pointing frame + et = spiceypy.utc2et("2026-01-01T00:00:00.000") + rotation = get_rotation_matrix( + et, + SpiceFrame.IMAP_MAG_O, + SpiceFrame.IMAP_DPS, + allow_spice_noframeconnect=True, + ) + assert np.isnan(rotation).all() + + # one hour after midnight should have coverage + ets = np.array([et, et + 3600]) + rotations = get_rotation_matrix( + ets, + SpiceFrame.IMAP_MAG_O, + SpiceFrame.IMAP_DPS, + allow_spice_noframeconnect=True, + ) + assert rotations.shape == (2, 3, 3) + assert np.isnan(rotations[0]).all() + assert np.isfinite(rotations[1]).all() + + +@pytest.mark.external_kernel +def test_get_rotation_matrix_no_transformation_defined_for_et_not_allowed( + furnish_kernels, +): + """Test error is thrown for undefined SPICE transformation when + allow_spice_noframeconnect is False (default) in get_rotation_matrix().""" + kernels = [ + "naif0012.tls", + "imap_130.tf", + "imap_sclk_0000.tsc", + "imap_science_120.tf", + "sim_1yr_imap_attitude.bc", + "sim_1yr_imap_pointing_frame.bc", + "de440s.bsp", + ] + with furnish_kernels(kernels): + # Midnight is not defined in pointing frame + et = spiceypy.utc2et("2026-01-01T00:00:00.000") + with pytest.raises( + spiceypy.utils.exceptions.SpiceNOFRAMECONNECT, + match=r"SPICE\(NOFRAMECONNECT\)", + ): + get_rotation_matrix(et, SpiceFrame.IMAP_MAG_O, SpiceFrame.IMAP_DPS) def test_instrument_pointing(furnish_kernels): kernels = [ "naif0012.tls", - "imap_wkcp.tf", + "imap_130.tf", "imap_sclk_0000.tsc", - "imap_science_100.tf", + "imap_science_120.tf", "sim_1yr_imap_attitude.bc", "sim_1yr_imap_pointing_frame.bc", ] @@ -341,6 +459,96 @@ def test_instrument_pointing(furnish_kernels): assert ins_pointing.shape == (3, 3) +@pytest.mark.parametrize( + "frame", + [ + SpiceFrame.IMAP_LO_BASE, + SpiceFrame.IMAP_HI_45, + SpiceFrame.IMAP_HI_90, + SpiceFrame.IMAP_ULTRA_45, + SpiceFrame.IMAP_ULTRA_90, + SpiceFrame.IMAP_MAG_I, + SpiceFrame.IMAP_MAG_O, + SpiceFrame.IMAP_SWE, + SpiceFrame.IMAP_SWAPI, + SpiceFrame.IMAP_CODICE, + SpiceFrame.IMAP_HIT, + SpiceFrame.IMAP_IDEX, + SpiceFrame.IMAP_GLOWS, + ], +) +def test_instrument_pointing_all_instruments(frame, furnish_kernels): + """Test the ability to compute instrument pointing for all but Lo.""" + kernels = [ + "naif0012.tls", + "imap_130.tf", + "imap_sclk_0000.tsc", + "imap_science_120.tf", + "sim_1yr_imap_attitude.bc", + "sim_1yr_imap_pointing_frame.bc", + ] + with furnish_kernels(kernels): + et = spiceypy.utc2et("2025-06-12T12:00:00.000") + # This only tests functionality, not values + _ = instrument_pointing(et, frame, SpiceFrame.ECLIPJ2000) + + +@pytest.mark.parametrize( + "frame", + [ + SpiceFrame.IMAP_LO, + SpiceFrame.IMAP_LO_STAR_SENSOR, + ], +) +@pytest.mark.xfail(reason="LO and LO_STAR_SENSOR require Lo pivot CK") +def test_instrument_pointing_lo_ck(frame, furnish_kernels): + """Test calculating Lo pointing.""" + kernels = [ + "naif0012.tls", + "imap_130.tf", + "imap_sclk_0000.tsc", + "imap_science_120.tf", + "sim_1yr_imap_attitude.bc", + "sim_1yr_imap_pointing_frame.bc", + ] + with furnish_kernels(kernels): + et = spiceypy.utc2et("2025-06-12T12:00:00.000") + _ = instrument_pointing(et, frame, SpiceFrame.ECLIPJ2000) + + +@pytest.mark.parametrize( + "pivot_angle, expected", + [ + (0, [0.0, 0.0, 1.0]), # Aligned with SC +Z + (75, [0.483, 0.837, 0.259]), # Rotated 75Β° + (90, [0.5, 0.866, 0.0]), # Rotated 90Β° (perpendicular to SC +Z) + (105, [0.483, 0.837, -0.259]), # Rotated 105Β° + ], +) +def test_lo_instrument_pointing_pivot_angle(pivot_angle, expected, furnish_kernels): + kernels = ["imap_130.tf"] + with furnish_kernels(kernels): + et = 0 # Use fixed frames, no time-dependent kernels needed + + # Get Lo boresight in spacecraft frame + boresight_sc = lo_instrument_pointing( + et, pivot_angle, SpiceFrame.IMAP_SPACECRAFT, cartesian=True + ) + + # Verify angle from spacecraft +Z axis equals pivot angle + sc_z_axis = np.array([0, 0, 1]) + angle_from_sc_z = np.rad2deg( + np.arccos(np.clip(np.dot(boresight_sc, sc_z_axis), -1, 1)) + ) + np.testing.assert_allclose(angle_from_sc_z, pivot_angle, atol=1e-8) + + # Verify components match expected values + np.testing.assert_allclose(boresight_sc, expected, atol=1e-3) + + # Verify boresight is a unit vector + np.testing.assert_allclose(np.linalg.norm(boresight_sc), 1.0, atol=1e-10) + + @pytest.mark.external_kernel def test_basis_vectors(imap_ena_sim_metakernel): """Test coverage for basis_vectors().""" diff --git a/imap_processing/tests/spice/test_pointing_frame.py b/imap_processing/tests/spice/test_pointing_frame.py index e04be71351..0a2105e38c 100644 --- a/imap_processing/tests/spice/test_pointing_frame.py +++ b/imap_processing/tests/spice/test_pointing_frame.py @@ -1,5 +1,6 @@ """Test coverage for imap_processing.spice.repoint.py""" +from datetime import datetime from pathlib import Path from unittest import mock @@ -9,16 +10,19 @@ from imap_data_access import SPICEInput from imap_processing.spice import IMAP_SC_ID -from imap_processing.spice.geometry import SpiceFrame +from imap_processing.spice.geometry import ( + SpiceFrame, + spherical_to_cartesian, +) from imap_processing.spice.pointing_frame import ( POINTING_SEGMENT_DTYPE, - _average_quaternions, _create_rotation_matrix, + _mean_spin_axis, calculate_pointing_attitude_segments, generate_pointing_attitude_kernel, write_pointing_frame_ck, ) -from imap_processing.spice.time import TICK_DURATION +from imap_processing.spice.time import TICK_DURATION, met_to_sclkticks, sct_to_et @pytest.fixture @@ -27,14 +31,30 @@ def furnish_pointing_frame_kernels(furnish_kernels, spice_test_data_path): required_kernels = [ "naif0012.tls", "imap_sclk_0000.tsc", - "imap_wkcp.tf", - "imap_science_100.tf", + "imap_130.tf", + "imap_science_120.tf", "imap_sim_ck_2hr_2secsampling_with_nutation.bc", ] with furnish_kernels(required_kernels): yield [str(spice_test_data_path / k) for k in required_kernels] +@pytest.fixture +def furnish_flight_ah_kernels(furnish_kernels, spice_test_data_path): + """List SPICE kernels.""" + required_kernels = [ + "naif0012.tls", + "imap_sclk_0000.tsc", + "imap_130.tf", + "imap_science_120.tf", + "imap_2025_338_2025_339_001.ah.bc", + "imap_2025_339_2025_339_001.ah.bc", + "imap_2025_339_2025_340_001.ah.bc", + ] + with furnish_kernels(required_kernels): + yield [str(spice_test_data_path / k) for k in required_kernels] + + @pytest.fixture def et_times(furnish_pointing_frame_kernels): """Tests get_et_times function.""" @@ -55,27 +75,45 @@ def et_times(furnish_pointing_frame_kernels): return et_times +@mock.patch("imap_processing.spice.pointing_frame.spiceypy.et2datetime") @mock.patch( "imap_processing.spice.pointing_frame.write_pointing_frame_ck", autospec=True ) @mock.patch( "imap_processing.spice.pointing_frame.calculate_pointing_attitude_segments", autospec=True, - return_value=None, + return_value=[{"start_sclk_ticks": 0, "end_sclk_ticks": 1}], ) -def test_generate_pointing_attitude_kernel(mock_gen_attitude_segments, mock_write_ck): +def test_generate_pointing_attitude_kernel( + mock_gen_attitude_segments, mock_write_ck, mock_et2datetime +): """Test coverage for generate_pointing_attitude_kernel function.""" start_date = "2024_111" end_date = "2024_222" version = "02" + mock_et2datetime.side_effect = [ + datetime.strptime(date_str, "%Y_%j") for date_str in [start_date, end_date] + ] ck_path = Path(f"/bogus/file/path/imap_{start_date}_{end_date}_{version}.ah.bc") - pointing_ck_path = generate_pointing_attitude_kernel(ck_path)[0] + pointing_ck_path = generate_pointing_attitude_kernel([ck_path])[0] assert pointing_ck_path.name == f"imap_dps_{start_date}_{end_date}_{version}.ah.bc" # Verify that file is valid pointing_attitude kernel with imap-data-access spice_input = SPICEInput(pointing_ck_path.name) assert spice_input.source[0] == "pointing_attitude" +@mock.patch( + "imap_processing.spice.pointing_frame.calculate_pointing_attitude_segments", + autospec=True, + return_value=[], +) +def test_generate_pointing_attitude_kernel_no_pointings(mock_gen_attitude_segments): + """Test when no pointings are covered by the input CK.""" + ck_path = Path("/bogus/file/path/imap_2025_100_2025_101_001.ah.bc") + with pytest.raises(ValueError, match="No Pointings covered"): + _ = generate_pointing_attitude_kernel([ck_path])[0] + + @pytest.mark.parametrize( "segment_start_offset, segment_end_offset, quaternion, segment_id", [ @@ -146,20 +184,26 @@ def test_write_pointing_frame_ck( assert parent_file in lines[5] -def test_average_quaternions(et_times, furnish_pointing_frame_kernels): - """Tests average_quaternions function.""" - q_avg = _average_quaternions(et_times) +@pytest.mark.external_test_data +def test_mean_spin_axis(furnish_flight_ah_kernels): + """Tests _mean_spin_axis function.""" + # Pointing 69 start/end times as defined in imap_2025_351_01.repoint + met_range = np.array([502624925, 502711208]) + et_range = sct_to_et(met_to_sclkticks(met_range)) + et_times = np.linspace(et_range[0], et_range[1], int(et_range[1] - et_range[0])) + z_avg = _mean_spin_axis(et_times) - # Generated from MATLAB code results - q_avg_expected = np.array([-0.6611, 0.4981, -0.5019, -0.2509]) - np.testing.assert_allclose(q_avg, q_avg_expected, atol=1e-4) + # Generated from GLOWS average spin-axis + exp_z_avg_lat = 0.065 + exp_z_avg_lon = 249.86 + z_avg_expected = spherical_to_cartesian(np.array([1, exp_z_avg_lon, exp_z_avg_lat])) + np.testing.assert_allclose(z_avg, z_avg_expected, atol=1e-4) def test_create_rotation_matrix(et_times, furnish_pointing_frame_kernels): """Tests create_rotation_matrix function.""" - q_avg = _average_quaternions(et_times) - rotation_matrix = _create_rotation_matrix(q_avg) - z_avg = spiceypy.q2m(list(q_avg))[:, 2] + z_avg = _mean_spin_axis(et_times) + rotation_matrix = _create_rotation_matrix(z_avg) rotation_matrix_expected = np.array( [ @@ -207,7 +251,7 @@ def test_calculate_pointing_attitude_segments( ) segment_data = calculate_pointing_attitude_segments( - spice_test_data_path / "imap_sim_ck_2hr_2secsampling_with_nutation.bc", + [spice_test_data_path / "imap_sim_ck_2hr_2secsampling_with_nutation.bc"], ) # Nick Dutton's MATLAB code result @@ -224,12 +268,6 @@ def test_calculate_pointing_attitude_segments( decimal=4, ) - # Tests error handling when incorrect kernel is loaded. - with pytest.raises( - ValueError, match="Error: Expected CK kernel .*badname_kernel.bc" - ): # Replace match string with expected error message - calculate_pointing_attitude_segments(tmp_path / "badname_kernel.bc") - def test_multiple_pointings( furnish_pointing_frame_kernels, @@ -237,31 +275,45 @@ def test_multiple_pointings( use_fake_repoint_data_for_time, ): """Tests create_pointing_frame function with multiple pointing kernels.""" - # Define 3 repoints: - # 1. Starts 10 second before the input CK start, ends one second + # Define 4 repoints: + # 1. Starts and ends before the input CK start + # 2. Starts 10 seconds before the input CK start, ends one second # after the CK start - # 2. Starts one hour after CK start, ends 1 second after it starts - # 3. Starts one second before the CK ends, ends 10 seconds after the CK ends + # 3. Starts one hour after CK start, ends 1-hour + 1-second after it starts + # 4. Starts one second before the CK ends, ends 10 seconds after the CK ends + # 5. Starts and ends after the CK end # Result is 2 pointings ck_met_start, ck_met_end = get_ck_met_coverage(furnish_pointing_frame_kernels[-1]) repoint_start_met = np.array( - [ck_met_start - 10, ck_met_start + 60 * 60, ck_met_end - 1] + [ + ck_met_start - 60, + ck_met_start - 10, + ck_met_start + 60 * 60, + ck_met_end - 1, + ck_met_end + 10, + ] ) repoint_end_met = np.array( - [ck_met_start + 1, ck_met_start + 60 * 60 + 1, ck_met_end + 10] + [ + ck_met_start - 30, + ck_met_start + 1, + ck_met_start + 60 * 60 + 1, + ck_met_end + 10, + ck_met_end + 20, + ] ) use_fake_repoint_data_for_time(repoint_start_met, repoint_end_met) segment_data = calculate_pointing_attitude_segments( - spice_test_data_path / "imap_sim_ck_2hr_2secsampling_with_nutation.bc", + [spice_test_data_path / "imap_sim_ck_2hr_2secsampling_with_nutation.bc"], ) - # Pointings are between repoints, so we expect one less than repoints - assert len(segment_data["start_sclk_ticks"]) == len(repoint_start_met) - 1 + # The way we defined the repoints, we expect two pointing segments + assert len(segment_data["start_sclk_ticks"]) == 2 np.testing.assert_allclose( - segment_data["start_sclk_ticks"], repoint_end_met[:-1] / TICK_DURATION + segment_data["start_sclk_ticks"], repoint_end_met[1:3] / TICK_DURATION ) np.testing.assert_allclose( - segment_data["end_sclk_ticks"], repoint_start_met[1:] / TICK_DURATION + segment_data["end_sclk_ticks"], repoint_start_met[2:4] / TICK_DURATION ) diff --git a/imap_processing/tests/spice/test_repoint.py b/imap_processing/tests/spice/test_repoint.py index 46e407e780..8ec2859d3d 100644 --- a/imap_processing/tests/spice/test_repoint.py +++ b/imap_processing/tests/spice/test_repoint.py @@ -1,6 +1,7 @@ """Test coverage for imap_processing.spice.repoint.py""" from pathlib import Path +from unittest import mock import numpy as np import pandas as pd @@ -81,6 +82,75 @@ def test_get_pointing_times(fake_repoint_data): assert pointing_end_time == expected_times[1] +def test_get_pointing_times_from_id(fake_repoint_data): + """Test coverage for get_pointing_times_from_id function.""" + id = 0 + # These are the expected start and end times for the pointing that + # corresponds to repoint 0 in the fake data. + # The first repoint has start time 0.1 and end time 5.1 and the + # second repoint has start time 15.2 and end time 20.2 + # So the pointing period is from 5.1 to 15.2 + expected_times = (5.1, 15.2) + + pointing_start_time, pointing_end_time = repoint.get_pointing_times_from_id(id) + + assert pointing_start_time == expected_times[0] + assert pointing_end_time == expected_times[1] + + # Test with string id + str_id = "repoint00000" + pointing_start_time, pointing_end_time = repoint.get_pointing_times_from_id(str_id) + + assert pointing_start_time == expected_times[0] + assert pointing_end_time == expected_times[1] + + +def test_get_pointing_times_from_id_no_end_time(fake_repoint_data): + """Test coverage for get_pointing_times_from_id function.""" + id = 2 + with pytest.raises(ValueError, match="Pointing end time not found"): + repoint.get_pointing_times_from_id(id) + + +def test_get_pointing_times_from_no_id(fake_repoint_data): + """Test coverage for get_pointing_times_from_id function.""" + id = 3 + with pytest.raises(ValueError, match="Repoint ID 3 not found in repoint table."): + repoint.get_pointing_times_from_id(id) + + +def test_get_pointing_mid_time(fake_repoint_data, monkeypatch): + """Test coverage for get_pointing_mid_time function.""" + times = 6 + expected_times = (5.1, 15.2) + + expected_mid_time = np.mean(expected_times) + + mid_time = repoint.get_pointing_mid_time(times) + + assert mid_time == expected_mid_time + + +@pytest.mark.external_kernel +@mock.patch("imap_processing.spice.repoint.imap_state") +@mock.patch("imap_processing.spice.repoint.get_pointing_times") +def test_mid_point_state(mock_get_pointing_times, mock_imap_state, furnish_kernels): + """Test coverage for imap_state()""" + met = 5 + mock_get_pointing_times.return_value = (5.1, 15.2) + # Mock the imap_state function + mock_imap_state.return_value = np.array( + [1.0, 2.0, 3.0, 0.1, 0.2, 0.3], # Example position and velocity data + ) + kernels = [ + "naif0012.tls", + "imap_sclk_0000.tsc", + ] + with furnish_kernels(kernels): + state = repoint.get_mid_point_state(met) + assert state.shape == (6,) + + @pytest.mark.parametrize( "query_times, match_str", [ diff --git a/imap_processing/tests/spice/test_spin.py b/imap_processing/tests/spice/test_spin.py index c7a79ca760..808e093dc9 100644 --- a/imap_processing/tests/spice/test_spin.py +++ b/imap_processing/tests/spice/test_spin.py @@ -44,10 +44,11 @@ def test_set_spin_table_paths(monkeypatch): "2024-04-11 00:00:15.000000", 15.0, True, - 1, + True, 0, False, 15.0, + 15.0, # actual_spin_period 0.0, ] ], @@ -62,10 +63,11 @@ def test_set_spin_table_paths(monkeypatch): "2024-04-11 00:00:15.000000", 15.0, True, - 1, + True, 0, False, 15.0, + 15.0, # actual_spin_period 0.1 / 15, ], [ @@ -75,10 +77,11 @@ def test_set_spin_table_paths(monkeypatch): "2024-04-11 00:00:30.000000", 15.0, True, - 1, + True, 0, False, 30.0, + 15.0, # actual_spin_period 0.2 / 15, ], ], @@ -114,6 +117,7 @@ def test_get_spin_number(fake_spin_data, met_time, spin_number_expected): [ (15, 0.0), # Scalar test (np.array([15.1, 30.1]), np.array([0.1 / 15, 0.1 / 15])), # Array test + # Query time 50 is in spin 3 (45-60), uses spin_period_sec=15 (spin 4 missing) (np.array([50]), np.array([5 / 15])), # Single element array test # The first spin has thruster firing set, but should return valid value (5.0, 5 / 15), @@ -123,18 +127,24 @@ def test_get_spin_number(fake_spin_data, met_time, spin_number_expected): (np.array([121, 122, 123]), np.full(3, np.nan)), # Test that invalid spin period causes nans (np.array([110, 111]), np.full(2, np.nan)), - # Test for time in missing spin + # Test for time in gap (spin 4 missing) - invalid because (65-45)/15 > 1 (65, np.nan), (np.array([65.1, 66]), np.full(2, np.nan)), # Combined test ( np.array([7.5, 30, 61, 75, 106, 121, 136]), + # 61 is in spin 3, uses spin_period_sec=15, (61-45)/15 > 1 β†’ invalid np.array([0.5, 0, np.nan, 0, np.nan, np.nan, 1 / 15]), ), # Test that this spin phase range [0, 1) is valid which # is same as [0, 360) degree angle. At 15 seconds the spacecraft # has completed a full spin (np.array([0, 15]), np.zeros(2)), + # Test gap between estimated spin end and actual next spin start + # Spin 9: start=135, spin_period_sec=14.5, estimated_end=149.5 + # Spin 10: start=150 (actual start is 0.5s after estimated end) + # Query at 149.7 should be valid: (149.7-135)/15 = 0.98 < 1 + (149.7, 14.7 / 15), ], ) def test_get_spacecraft_spin_phase(query_met_times, expected, fake_spin_data): @@ -184,7 +194,7 @@ def test_get_spin_angle(spin_phases, degrees, expected, context): np.testing.assert_array_equal(spin_angles, expected) -@pytest.mark.parametrize("query_met_times", [-1, 165]) +@pytest.mark.parametrize("query_met_times", [-1, 181]) def test_get_spacecraft_spin_phase_value_error(query_met_times, fake_spin_data): """Test get_spacecraft_spin_phase() for raising ValueError.""" with pytest.raises(ValueError, match="Query times"): @@ -214,6 +224,7 @@ def test_get_spin_data(use_fake_spin_data_for_time): "spin_period_source", "thruster_firing", "spin_start_met", + "actual_spin_period", }, "Spin data must have the specified fields." @@ -265,7 +276,7 @@ def test_get_spin_table_merge(tmp_path, use_test_spin_data_csv): @pytest.mark.parametrize( "instrument", [ - SpiceFrame.IMAP_LO_BASE, + SpiceFrame.IMAP_LO, SpiceFrame.IMAP_HI_45, SpiceFrame.IMAP_HI_90, SpiceFrame.IMAP_ULTRA_45, @@ -276,7 +287,8 @@ def test_get_spin_table_merge(tmp_path, use_test_spin_data_csv): SpiceFrame.IMAP_HIT, SpiceFrame.IMAP_SWE, SpiceFrame.IMAP_GLOWS, - SpiceFrame.IMAP_MAG, + SpiceFrame.IMAP_MAG_I, + SpiceFrame.IMAP_MAG_O, ], ) def test_get_instrument_spin_phase( @@ -284,11 +296,19 @@ def test_get_instrument_spin_phase( ): """Test coverage for get_instrument_spin_phase()""" met_times = np.array([7.5, 30, 61, 75, 106, 121, 136]) + # Time 61 is in missing spin gap, should be invalid expected_nan_mask = np.array([False, False, True, False, True, True, False]) - with furnish_kernels([spice_test_data_path / "imap_wkcp.tf"]): + with furnish_kernels([spice_test_data_path / "imap_130.tf"]): inst_phase = spin.get_instrument_spin_phase(met_times, instrument) assert inst_phase.shape == met_times.shape np.testing.assert_array_equal(np.isnan(inst_phase), expected_nan_mask) assert np.logical_and( 0 <= inst_phase[~expected_nan_mask], inst_phase[~expected_nan_mask] < 1 ).all() + + +def test_get_spin_start_met(fake_spin_data): + # Make sure we aren't actually interpolating and rather repeating existing values + # when we have a linear ramp of data points between spins + start_mets = spin.interpolate_spin_data(np.linspace(32, 37, 3))["spin_start_met"] + np.testing.assert_array_equal(start_mets, [30, 30, 30]) diff --git a/imap_processing/tests/spice/test_time.py b/imap_processing/tests/spice/test_time.py index 87f5f0e501..2dd62d0bf5 100644 --- a/imap_processing/tests/spice/test_time.py +++ b/imap_processing/tests/spice/test_time.py @@ -8,6 +8,7 @@ from imap_processing.spice.time import ( TICK_DURATION, epoch_to_doy, + epoch_to_fractional_doy, et_to_datetime64, et_to_met, et_to_ttj2000ns, @@ -297,3 +298,108 @@ def test_ttj2000ns_to_met(): ttj2000ns_array = met_to_ttj2000ns(met_array) roundtrip_met_array = ttj2000ns_to_met(ttj2000ns_array) np.testing.assert_array_almost_equal(roundtrip_met_array, met_array) + + +class TestEpochToFractionalDoy: + """Tests for epoch_to_fractional_doy function.""" + + def test_january_first_midnight(self): + """Test that January 1st 00:00:00 returns exactly 1.0.""" + # January 1st at midnight should be DOY 1.0 + utc = "2025-01-01T00:00:00.000" + et = spiceypy.str2et(utc) + epoch = int(spiceypy.unitim(et, "ET", "TT") * 1e9) + + doy = epoch_to_fractional_doy(epoch) + + assert doy == 1.0 + + def test_january_first_noon(self): + """Test that January 1st 12:00:00 returns 1.5.""" + # January 1st at noon should be DOY 1.5 + utc = "2025-01-01T12:00:00.000" + et = spiceypy.str2et(utc) + epoch = int(spiceypy.unitim(et, "ET", "TT") * 1e9) + + doy = epoch_to_fractional_doy(epoch) + + np.testing.assert_almost_equal(doy, 1.5, decimal=6) + + def test_known_mid_year_date(self): + """Test a known mid-year date (July 1st = DOY 182 in non-leap year).""" + # July 1st 00:00:00 in 2025 (non-leap year) should be DOY 182.0 + utc = "2025-07-01T00:00:00.000" + et = spiceypy.str2et(utc) + epoch = int(spiceypy.unitim(et, "ET", "TT") * 1e9) + + doy = epoch_to_fractional_doy(epoch) + + # July 1st is day 182 in a non-leap year + # Jan(31) + Feb(28) + Mar(31) + Apr(30) + May(31) + Jun(30) = 181 days + # So July 1 is day 182 + assert doy == 182.0 + + def test_leap_year_date(self): + """Test leap year handling (Feb 29th exists in 2024).""" + # March 1st 00:00:00 in 2024 (leap year) should be DOY 61.0 + utc = "2024-03-01T00:00:00.000" + et = spiceypy.str2et(utc) + epoch = int(spiceypy.unitim(et, "ET", "TT") * 1e9) + + doy = epoch_to_fractional_doy(epoch) + + # In leap year: Jan(31) + Feb(29) = 60 days, so March 1 is day 61 + assert doy == 61.0 + + def test_end_of_year(self): + """Test December 31st returns DOY 365 (non-leap) or 366 (leap).""" + # December 31st 00:00:00 in 2025 (non-leap year) should be DOY 365.0 + utc = "2025-12-31T00:00:00.000" + et = spiceypy.str2et(utc) + epoch = int(spiceypy.unitim(et, "ET", "TT") * 1e9) + + doy = epoch_to_fractional_doy(epoch) + + assert doy == 365.0 + + def test_fractional_time_components(self): + """Test that hours, minutes, and seconds contribute correctly.""" + # January 2nd at 06:30:00 should be DOY 2.0 + 6.5/24 = 2.270833... + utc = "2025-01-02T06:30:00.000" + et = spiceypy.str2et(utc) + epoch = int(spiceypy.unitim(et, "ET", "TT") * 1e9) + + doy = epoch_to_fractional_doy(epoch) + + # Expected: 2.0 + 6/24 + 30/1440 = 2.0 + 0.25 + 0.02083... = 2.270833... + expected_doy = 2.0 + 6.0 / 24.0 + 30.0 / 1440.0 + np.testing.assert_almost_equal(doy, expected_doy, decimal=4) + + def test_subsecond_precision(self): + """Test that subsecond precision is preserved.""" + # January 1st at 00:00:00.5 should be DOY 1.0 + 0.5/86400 + utc = "2025-01-01T00:00:00.500" + et = spiceypy.str2et(utc) + epoch = int(spiceypy.unitim(et, "ET", "TT") * 1e9) + + doy = epoch_to_fractional_doy(epoch) + + # Expected: 1.0 + 0.5/86400 = 1.00000578703... + expected_doy = 1.0 + 0.5 / 86400.0 + np.testing.assert_almost_equal(doy, expected_doy, decimal=4) + + def test_array_input(self): + """Test that np.array as input works.""" + # Test various dates throughout the year + test_dates = [ + "2025-01-01T00:00:00.000", + "2025-06-15T12:30:45.123", + "2025-12-31T23:59:59.999", + "2024-02-29T12:00:00.000", # Leap year + ] + + ets = spiceypy.str2et(test_dates) + epochs = et_to_ttj2000ns(ets) + doys = epoch_to_fractional_doy(epochs) + assert np.all(doys >= 1.0) + assert np.all(doys < 367.0) diff --git a/imap_processing/tests/swapi/test_swapi_l1.py b/imap_processing/tests/swapi/test_swapi_l1.py index 3e78270fe9..49ddd2fa50 100644 --- a/imap_processing/tests/swapi/test_swapi_l1.py +++ b/imap_processing/tests/swapi/test_swapi_l1.py @@ -203,7 +203,7 @@ def first_get_file_paths_side_effect(descriptor): collection_obj.deserialize( json.dumps(processing_input), ) - processed_data = swapi_l1(collection_obj) + processed_data = swapi_l1(collection_obj, descriptor="hk") # hk cdf file l1a_hk_cdf_filename = "imap_swapi_l1a_hk_20240924_v999.cdf" hk_cdf_path = write_cdf(processed_data[0]) @@ -231,7 +231,7 @@ def second_get_file_paths_side_effect(descriptor): json.dumps(processing_input), ) - processed_data = swapi_l1(collection_obj) + processed_data = swapi_l1(collection_obj, descriptor="sci") assert processed_data[0].attrs["Apid"] == f"{SWAPIAPID.SWP_SCI}" diff --git a/imap_processing/tests/swapi/test_swapi_l2.py b/imap_processing/tests/swapi/test_swapi_l2.py index 4a9c287f4e..b8273de459 100644 --- a/imap_processing/tests/swapi/test_swapi_l2.py +++ b/imap_processing/tests/swapi/test_swapi_l2.py @@ -1,6 +1,7 @@ import json from unittest.mock import patch +import cdflib import numpy as np import pandas as pd import pytest @@ -16,6 +17,8 @@ ) from imap_processing.swapi.swapi_utils import read_swapi_lut_table +SWAPI_RATE_VALIDMAX = 65535 / SWAPI_LIVETIME + @pytest.fixture(scope="session") def esa_unit_conversion_table() -> pd.DataFrame: @@ -82,7 +85,7 @@ def first_get_file_paths_side_effect(descriptor): json.dumps(processing_input), ) # Create HK CDF File - processed_hk_data = swapi_l1(collection_obj) + processed_hk_data = swapi_l1(collection_obj, descriptor="hk") hk_cdf_filename = "imap_swapi_l1a_hk_20240924_v999.cdf" hk_cdf_path = write_cdf(processed_hk_data[0]) assert hk_cdf_path.name == hk_cdf_filename @@ -106,12 +109,18 @@ def second_get_file_paths_side_effect(descriptor): json.dumps(processing_input), ) # Create L1 CDF File - processed_sci_data = swapi_l1(collection_obj) + processed_sci_data = swapi_l1(collection_obj, descriptor="sci") cdf_filename = "imap_swapi_l1_sci_20240924_v999.cdf" cdf_path = write_cdf(processed_sci_data[0]) assert cdf_path.name == cdf_filename l1_dataset = load_cdf(cdf_path) + # Since L2 data's date is before any date supported by ESA unit conversion LUT + # and earliest date doesn't have energy data besides 'Sweep #' 0, + # we need to update sweep_id to be 0 instead of 1 to get valid energy values. + l1_dataset["sweep_table"].values[:] = 0 + + # Create L2 CDF File l2_dataset = swapi_l2( l1_dataset, esa_table_df=esa_unit_conversion_table, @@ -119,15 +128,32 @@ def second_get_file_paths_side_effect(descriptor): ) l2_cdf = write_cdf(l2_dataset) assert l2_cdf.name == "imap_swapi_l2_sci_20240924_v999.cdf" + cdf_file = cdflib.CDF(l2_cdf) + esa_energy_info = cdf_file.varinq("esa_energy") + sci_start_time_attrs = cdf_file.varattsget("sci_start_time") + assert esa_energy_info.Data_Type_Description == "CDF_DOUBLE" + assert sci_start_time_attrs["FORMAT"] == "A23" + + rate_variables = [ + "swp_pcem_rate", + "swp_scem_rate", + "swp_coin_rate", + "swp_pcem_rate_stat_uncert_plus", + "swp_pcem_rate_stat_uncert_minus", + "swp_scem_rate_stat_uncert_plus", + "swp_scem_rate_stat_uncert_minus", + "swp_coin_rate_stat_uncert_plus", + "swp_coin_rate_stat_uncert_minus", + ] + for variable in rate_variables: + variable_attrs = cdf_file.varattsget(variable) + assert np.isclose(variable_attrs["VALIDMAX"], SWAPI_RATE_VALIDMAX) # Test uncertainty variables are as expected np.testing.assert_array_equal( l2_dataset["swp_pcem_rate_stat_uncert_plus"], l1_dataset["swp_pcem_counts_stat_uncert_plus"] / SWAPI_LIVETIME, ) - # Since L2 data's date is before any date in ESA unit conversion table, - # check that it returns nan in first 63 energy steps - assert np.isnan(l2_dataset["swp_esa_energy"].values[0, :63]).all() # Check fine steps fine_energies = [ 4290.0, @@ -140,7 +166,7 @@ def second_get_file_paths_side_effect(descriptor): 3687.0, 3608.0, ] - assert np.all(l2_dataset["swp_esa_energy"].values[0, -9:] == fine_energies) + assert np.all(l2_dataset["esa_energy"].values[0, -9:] == fine_energies) def test_solve_full_sweep_energy(esa_unit_conversion_table, lut_notes_table): @@ -223,14 +249,14 @@ def test_solve_full_sweep_energy(esa_unit_conversion_table, lut_notes_table): 107, ] ) - assert np.all(sweeps_energy_value[:, :63] == fixed_energy_values) + np.testing.assert_array_equal(sweeps_energy_value[0, :63], fixed_energy_values) # Now, test that the last 9 fine energy values are as expected for first sweep. # I manually picked those values from LUT table. expected_fine_energies = np.array( [3220.0, 3151.0, 3083.0, 3017.0, 2953.0, 2889.0, 2827.0, 2767.0, 2707.0] ) - assert np.all(sweeps_energy_value[0, -9:] == expected_fine_energies) + np.testing.assert_array_equal(sweeps_energy_value[0, -9:], expected_fine_energies) # Test that we get different values for date later than 2025-05-19 data_time = [np.datetime64("2025-05-20T00:00:00", "ns")] @@ -304,12 +330,12 @@ def test_solve_full_sweep_energy(esa_unit_conversion_table, lut_notes_table): 100, ] ) - assert np.all(sweeps_energy_value[:, :63] == new_fixed_energy_values) + np.testing.assert_array_equal(sweeps_energy_value[0, :63], new_fixed_energy_values) # Test mismatch values for 9 fine steps x 4 steps. mismatch_value = [1] with pytest.raises( - ValueError, match="These ESA_LVL5 values not found in lut-notes table" + ValueError, match="ESA DAC value '1' not found in LUT notes table" ): solve_full_sweep_energy( np.array(mismatch_value), @@ -318,3 +344,42 @@ def test_solve_full_sweep_energy(esa_unit_conversion_table, lut_notes_table): lut_notes_table, data_time, ) + + +def test_solve_full_sweep_energy_id3(esa_unit_conversion_table, lut_notes_table): + """Test the solve_full_sweep_energy function for sweep id 3 case""" + # Modify the current conversion table we have to have entries for sweep id 3 + esa_unit_conversion_table = esa_unit_conversion_table.copy(deep=True) + esa_unit_conversion_table.loc[ + esa_unit_conversion_table["Sweep #"] == 2, "Sweep #" + ] = 3 + # Update the first 3 fine energies to be 0 rather than "solve" / negative + # This makes 6 fine energy steps for sweep id 3 + # Get sweep 3 rows and set Energy values at indices 63-66 (inclusive) to 0 + sweep_3_mask = esa_unit_conversion_table["Sweep #"] == 3 + sweep_3_indices = esa_unit_conversion_table[sweep_3_mask].index + esa_unit_conversion_table.loc[sweep_3_indices[63:66], "Energy"] = 0 + + # Update the ESA Index Number in lut_notes_table for sweep id 3 + # to match the 6 fine energy steps + esa_unit_conversion_table.loc[sweep_3_indices[66:], "ESA Index Number"] = np.array( + [-40, -24, -8, 8, 24, 40] + ) + + esa_lvl5_arr = [4663] + sweep_table = [3] + data_time = [np.datetime64("2025-12-24T00:00:00", "ns")] + esa_lvl5_hex = np.vectorize(lambda x: format(x, "X"))(esa_lvl5_arr) + sweeps_energy_value = solve_full_sweep_energy( + esa_lvl5_hex, sweep_table, esa_unit_conversion_table, lut_notes_table, data_time + ) + assert sweeps_energy_value.shape == (1, 72) + + # The first 3 fine step values should be 0 for sweep id 3 + np.testing.assert_array_equal( + sweeps_energy_value[0, 63:66], np.array([0.0, 0.0, 0.0]) + ) + # The -6th value (first fine step) should be the same as the last index-80 + # 4663 corresponds to 383rd index in lut_notes_table + assert sweeps_energy_value[0, -6] == lut_notes_table["Energy"].values[383 - 80] + assert sweeps_energy_value[0, -1] == lut_notes_table["Energy"].values[383] diff --git a/imap_processing/tests/swe/lut/imap_swe_l1b-in-flight-cal_20240510_20260716_v000.csv b/imap_processing/tests/swe/lut/imap_swe_l1b-in-flight-cal_20240510_20260716_v000.csv index 7f2742aa60..c149a8adde 100644 --- a/imap_processing/tests/swe/lut/imap_swe_l1b-in-flight-cal_20240510_20260716_v000.csv +++ b/imap_processing/tests/swe/lut/imap_swe_l1b-in-flight-cal_20240510_20260716_v000.csv @@ -1,3 +1,4 @@ met_time,cem1,cem2,cem3,cem4,cem5,cem6,cem7 453050308,1,1,1,1,1,1,1 -1782864000,1,1,1,1,1,1,1 +553051294,1,1,1,1,1,1,1 +1782864000,2,2,2,2,2,2,2 \ No newline at end of file diff --git a/imap_processing/tests/swe/test_swe_l1b.py b/imap_processing/tests/swe/test_swe_l1b.py index cb9addeff3..11e010db24 100644 --- a/imap_processing/tests/swe/test_swe_l1b.py +++ b/imap_processing/tests/swe/test_swe_l1b.py @@ -12,6 +12,7 @@ from imap_processing import imap_module_directory from imap_processing.cdf.utils import load_cdf, write_cdf +from imap_processing.quality_flags import SweL1bFlags from imap_processing.swe.l1a.swe_l1a import swe_l1a from imap_processing.swe.l1a.swe_science import swe_science from imap_processing.swe.l1b.swe_l1b import ( @@ -79,7 +80,7 @@ def test_in_flight_calibration_factor(l1a_test_data): imap_module_directory / "tests/swe/lut/imap_swe_l1b-in-flight-cal_20240510_20260716_v000.csv" ] - calibrated_count = apply_in_flight_calibration( + calibrated_count, _ = apply_in_flight_calibration( one_full_cycle_data, acquisition_time, in_flight_cal_files, @@ -110,6 +111,59 @@ def test_in_flight_calibration_factor(l1a_test_data): ) +def test_quality_flags_last_cal_interval(): + """Test that LAST_CAL_INTERVAL flag is set correctly per epoch. + + The test LUT has cal_times = [453050308, 553051294, 1782864000]. + LAST_CAL_INTERVAL is set when any acquisition time > cal_times[-2] = 553051294. + The halfway met_time point of the last calibration interval is 1167957647. + """ + in_flight_cal_files = [ + imap_module_directory + / "tests/swe/lut/imap_swe_l1b-in-flight-cal_20240510_20260716_v000.csv" + ] + n_cycles = 3 + counts = np.ones( + ( + n_cycles, + swe_constants.N_ESA_STEPS, + swe_constants.N_ANGLE_SECTORS, + swe_constants.N_CEMS, + ) + ) + # cycle 0: all times before last cal interval + acq_time = np.full( + (n_cycles, swe_constants.N_ESA_STEPS, swe_constants.N_ANGLE_SECTORS), + 453051355.0, + ) + # cycle 1: all times in last cal interval, halfway between MET with CEM detector + # factor 1.0 and MET with CEM detector factor 2.0 + acq_time[1, :, :] = 1167957647.0 + # cycle 2: mixed - one time (for first ESA level and first angle sector) in last + # cal interval, halfway between MET with CEM detector factor 1.0 and MET with CEM + # detector factor 2.0 + acq_time[2, 0, 0] = 1167957647.0 + + corrected_counts, flags = apply_in_flight_calibration( + counts, acq_time, in_flight_cal_files + ) + + assert not (flags[0] & SweL1bFlags.LAST_CAL_INTERVAL.value) + # all counts for cycle 0 stay the same + np.testing.assert_allclose(corrected_counts[0, ...], 1) + + assert flags[1] & SweL1bFlags.LAST_CAL_INTERVAL.value + # all counts for cycle 1 scale by a factor of 1.5 + np.testing.assert_allclose(corrected_counts[1, ...], 1.5) + + assert flags[2] & SweL1bFlags.LAST_CAL_INTERVAL.value + # all counts for cycle 2 + the first ESA level + the first angle sector + # scale by a factor of 1.5 + np.testing.assert_allclose(corrected_counts[2, 0, 0, :], 1.5) + # all other counts for cycle 2 remain the same + np.testing.assert_allclose(corrected_counts[2, 1:, 1:, :], 1) + + def test_swe_l1b_conversion(decom_test_data_derived): """Test that calculate engineering unit(EU) matches validation data. diff --git a/imap_processing/tests/swe/test_swe_l2.py b/imap_processing/tests/swe/test_swe_l2.py index 24b4f8b732..f86c1c380d 100644 --- a/imap_processing/tests/swe/test_swe_l2.py +++ b/imap_processing/tests/swe/test_swe_l2.py @@ -11,6 +11,7 @@ from imap_processing import imap_module_directory from imap_processing.cdf.utils import write_cdf +from imap_processing.quality_flags import SweL1bFlags from imap_processing.swe.l1a.swe_l1a import swe_l1a from imap_processing.swe.l1b.swe_l1b import swe_l1b from imap_processing.swe.l2.swe_l2 import ( @@ -24,6 +25,18 @@ pytestmark = pytest.mark.external_test_data +OLD_GEOMETRIC_FACTORS = np.array( + [ + 435e-6, + 599e-6, + 808e-6, + 781e-6, + 876e-6, + 548e-6, + 432e-6, + ] +) + @patch( "imap_processing.swe.utils.swe_constants.GEOMETRIC_FACTORS", @@ -255,6 +268,10 @@ def test_put_data_into_angle_bins(): np.testing.assert_array_equal(even_col_mean_data, expected_mean_data) +@patch( + "imap_processing.swe.utils.swe_constants.GEOMETRIC_FACTORS", + new=OLD_GEOMETRIC_FACTORS, +) @patch("imap_data_access.processing_input.ProcessingInputCollection.get_file_paths") @patch( "imap_processing.spice.spin.get_spacecraft_to_instrument_spin_phase_offset", @@ -313,8 +330,22 @@ def get_file_paths_side_effect(descriptor): dependencies = ProcessingInputCollection(science_input, inflight_anc, eu_anc) l1b_dataset = swe_l1b(dependencies)[0] l1b_dataset.attrs["Data_version"] = "000" + + # Test data acquisition times (~453051355) are before cal_times[-2] (553051294), + # so no epoch should have LAST_CAL_INTERVAL set. + assert not np.any( + l1b_dataset["data_quality"].values & SweL1bFlags.LAST_CAL_INTERVAL.value + ) + l2_dataset = swe_l2(l1b_dataset) + # Verify data_quality is propagated from L1B to L2 for downstream (L3) use. + assert "data_quality" in l2_dataset + np.testing.assert_array_equal( + l2_dataset["data_quality"].values, + l1b_dataset["data_quality"].values, + ) + assert isinstance(l2_dataset, xr.Dataset) assert l2_dataset["phase_space_density_spin_sector"].shape == ( 6, @@ -364,6 +395,10 @@ def get_file_paths_side_effect(descriptor): np.testing.assert_allclose(bin_psd_data, bin_psd_val, rtol=1e-6) +@patch( + "imap_processing.swe.utils.swe_constants.GEOMETRIC_FACTORS", + new=OLD_GEOMETRIC_FACTORS, +) @patch("imap_data_access.processing_input.ProcessingInputCollection.get_file_paths") @patch( "imap_processing.spice.spin.get_spacecraft_to_instrument_spin_phase_offset", diff --git a/imap_processing/tests/test_cli.py b/imap_processing/tests/test_cli.py index 8f846924ba..bef5bc06bf 100644 --- a/imap_processing/tests/test_cli.py +++ b/imap_processing/tests/test_cli.py @@ -8,6 +8,7 @@ from unittest import mock from unittest.mock import Mock, sentinel +import imap_data_access.io import numpy as np import pytest import spiceypy @@ -17,6 +18,7 @@ ProcessingInputCollection, ScienceInput, SPICEInput, + SpinInput, ) from imap_processing.cli import ( @@ -26,7 +28,6 @@ Hit, Idex, Lo, - ProcessInstrument, Spacecraft, Swe, Ultra, @@ -188,8 +189,9 @@ def test_validate_args( _validate_args(args) -@mock.patch("imap_processing.cli.codice_l1a.process_codice_l1a") -def test_codice(mock_codice_l1a, mock_instrument_dependencies): +@mock.patch("imap_processing.cli.codice_l1a.process_l1a") +@mock.patch("imap_processing.cli.filter_day_boundary_data") +def test_codice(mock_filter, mock_process_l1a, mock_instrument_dependencies): """Test coverage for cli.CoDICE class""" test_dataset = xr.Dataset({}, attrs={"cdf_filename": "file0"}) @@ -199,7 +201,8 @@ def test_codice(mock_codice_l1a, mock_instrument_dependencies): mocks = mock_instrument_dependencies mocks["mock_query"].return_value = [{"file_path": "/path/to/file0"}] mocks["mock_download"].return_value = "file0" - mock_codice_l1a.return_value = [test_dataset] + mock_process_l1a.return_value = [test_dataset] + mock_filter.side_effect = lambda ds, _: ds mocks["mock_write_cdf"].side_effect = ["/path/to/file0"] mocks["mock_pre_processing"].return_value = input_collection @@ -210,7 +213,7 @@ def test_codice(mock_codice_l1a, mock_instrument_dependencies): instrument = Codice("l1a", "hskp", dependency_str, "20230822", None, "v001", False) instrument.process() - assert mock_codice_l1a.call_count == 1 + assert mock_process_l1a.call_count == 1 # Assert that write_cdf was called with the expected arguments assert mock_instrument_dependencies["mock_write_cdf"].call_count == 1 @@ -281,11 +284,12 @@ def test_post_processing_returns_empty_list_if_invoked_with_no_data( @pytest.mark.parametrize( - "data_level, function_name, science_input, anc_input, n_prods", + "data_level, data_descriptor, function_name, science_input, anc_input, n_prods", [ - ("l1a", "hi_l1a", ["imap_hi_l0_raw_20231212_v001.pkts"], [], 2), + ("l1a", "sci", "hi_l1a", ["imap_hi_l0_raw_20231212_v001.pkts"], [], 2), ( "l1b", + "90sensor-de", "annotate_direct_events", [ "imap_hi_l1a_90sensor-de_20241105_v001.cdf", @@ -294,22 +298,34 @@ def test_post_processing_returns_empty_list_if_invoked_with_no_data( ["imap_hi_90sensor-esa-energies_20240101_v001.csv"], 1, ), - ("l1b", "housekeeping", ["imap_hi_l0_raw_20231212_v001.pkts"], [], 2), + ("l1b", "sci", "housekeeping", ["imap_hi_l0_raw_20231212_v001.pkts"], [], 2), ( "l1c", + "45sensor-pset", "hi_l1c", - ["imap_hi_l1b_45sensor-de_20250415_v001.cdf"], - ["imap_hi_calibration-prod-config_20240101_v001.csv"], + [ + "imap_hi_l1b_45sensor-de_20250415_v001.cdf", + "imap_hi_l1b_45sensor-goodtimes_20250415_v001.cdf", + ], + [ + "imap_hi_45sensor-cal-prod_20240101_v001.csv", + "imap_hi_45sensor-backgrounds_20240101_v001.csv", + ], 1, ), ( "l2", + "h90-ena-h-sf-nsp-full-hae-4deg-3mo", "hi_l2", [ "imap_hi_l1c_90sensor-pset_20250415_v001.cdf", "imap_hi_l1c_90sensor-pset_20250416_v001.cdf", ], - [], + [ + "imap_hi_calibration-prod-config_20240101_v001.csv", + "imap_hi_90sensor-esa-energies_20240101_v001.csv", + "imap_hi_90sensor-esa-eta-fit-factors_20240101_v001.csv", + ], 1, ), ], @@ -317,6 +333,7 @@ def test_post_processing_returns_empty_list_if_invoked_with_no_data( def test_hi( mock_instrument_dependencies, data_level, + data_descriptor, function_name, science_input, anc_input, @@ -342,7 +359,13 @@ def test_hi( '[{"type": "science","files": ["imap_hi_l0_raw_20231212_v001.pkts"]}]' ) instrument = Hi( - data_level, "sci", dependency_str, "20231212", "20231213", "v005", False + data_level, + data_descriptor, + dependency_str, + "20231212", + "repoint00001", + "v005", + False, ) instrument.process() @@ -350,8 +373,66 @@ def test_hi( assert mock_instrument_dependencies["mock_write_cdf"].call_count == n_prods +@mock.patch("imap_processing.cli.hi_goodtimes.hi_goodtimes", autospec=True) +def test_hi_l1b_goodtimes(mock_hi_goodtimes, mock_instrument_dependencies): + """Test coverage for cli.Hi class with l1b goodtimes descriptor""" + mocks = mock_instrument_dependencies + # goodtimes now returns xr.Dataset for CDF writing + mock_goodtimes_ds = xr.Dataset() + mock_hi_goodtimes.return_value = [mock_goodtimes_ds] + mocks["mock_write_cdf"].return_value = Path("/path/to/goodtimes_output.cdf") + + # set load_cdf to return empty datasets + mocks["mock_load_cdf"].return_value = xr.Dataset() + # Set up the input collection with required dependencies + input_collection = ProcessingInputCollection( + ScienceInput("imap_hi_l1b_45sensor-de_20250415-repoint00001_v001.cdf"), + ScienceInput("imap_hi_l1b_45sensor-de_20250415-repoint00002_v001.cdf"), + ScienceInput("imap_hi_l1b_45sensor-de_20250415-repoint00003_v001.cdf"), + ScienceInput("imap_hi_l1b_45sensor-de_20250415-repoint00004_v001.cdf"), + ScienceInput("imap_hi_l1b_45sensor-de_20250415-repoint00005_v001.cdf"), + ScienceInput("imap_hi_l1b_45sensor-de_20250415-repoint00006_v001.cdf"), + ScienceInput("imap_hi_l1b_45sensor-de_20250415-repoint00007_v001.cdf"), + ScienceInput("imap_hi_l1b_45sensor-hk_20250415-repoint00004_v001.cdf"), + ScienceInput("imap_hi_l1a_45sensor-diagfee_20250415-repoint00004_v001.cdf"), + AncillaryInput("imap_hi_45sensor-cal-prod_20240101_v001.csv"), + ) + mocks["mock_pre_processing"].return_value = input_collection + + dependency_str = input_collection.serialize() + instrument = Hi( + "l1b", + "goodtimes", + dependency_str, + "20250415", + "repoint00004", + "v005", + False, + ) + + instrument.process() + + # Verify load_cdf was called for DE files and HK file + assert mocks["mock_load_cdf"].call_count == 9 # 7 DE + 1 HK + 1 DIAG_FEE + + # Verify hi_goodtimes was called with correct arguments + assert mock_hi_goodtimes.call_count == 1 + call_args = mock_hi_goodtimes.call_args + + # Check that datasets (not paths) were passed for l1b_de_datasets and l1b_hk + assert call_args.args[0] == "repoint00004" # current_repointing + assert isinstance(call_args.args[1], list) # l1b_de_datasets is a list + assert len(call_args.args[1]) == 7 # 7 DE datasets + assert isinstance(call_args.args[2], xr.Dataset) # l1b_hk is a dataset + assert isinstance(call_args.args[3], xr.Dataset) # l1a_diagfee is a dataset + + # goodtimes now returns xr.Dataset, so write_cdf should be called + assert mocks["mock_write_cdf"].call_count == 1 + + @mock.patch("imap_processing.cli.lo_l2.lo_l2", autospec=True) -def test_lo_l2(mock_lo_l2, mock_instrument_dependencies): +@mock.patch("imap_processing.cli.Lo.pre_processing") +def test_lo_l2(mock_lo_pre_processing, mock_lo_l2, mock_instrument_dependencies): mocks = mock_instrument_dependencies descriptor = "some-ena-map-descriptor" @@ -367,7 +448,7 @@ def test_lo_l2(mock_lo_l2, mock_instrument_dependencies): ) mocks["mock_load_cdf"].side_effect = [mock_loaded_pset_1, sentinel.loaded_pset_2] - mocks["mock_pre_processing"].return_value = processing_input + mock_lo_pre_processing.return_value = processing_input output_l2_dataset = xr.Dataset() mock_lo_l2.return_value = [output_l2_dataset] @@ -391,6 +472,42 @@ def test_lo_l2(mock_lo_l2, mock_instrument_dependencies): mocks["mock_write_cdf"].assert_called_once_with(output_l2_dataset) +@mock.patch("imap_processing.cli.load_cdf") +@mock.patch("imap_processing.cli.ProcessInstrument.pre_processing") +def test_lo_pre_processing_pivot_angle_filter(mock_super_pre_processing, mock_load_cdf): + valid_pset = "imap_lo_l1c_pset_20250415_v001.cdf" + invalid_pset = "imap_lo_l1c_pset_20250416_v001.cdf" + non_pset = "imap_lo_l1a_de_20260415-repoint00217_v001.cdf" + + base_collection = ProcessingInputCollection( + ScienceInput(valid_pset, invalid_pset), + ScienceInput(non_pset), + ) + mock_super_pre_processing.return_value = base_collection + mock_load_cdf.side_effect = [ + xr.Dataset({"pivot_angle": xr.DataArray(90.1)}), + xr.Dataset({"pivot_angle": xr.DataArray(30.0)}), + ] + + instrument = Lo( + "l2", + "some-descriptor", + base_collection.serialize(), + "20250415", + "20250416", + "v001", + False, + ) + result = instrument.pre_processing() + + result_inputs = list(result.get_processing_inputs()) + assert len(result_inputs) == 2 + + pset_input, non_pset_input = result_inputs + assert [str(fp.filename) for fp in pset_input.imap_file_paths] == [valid_pset] + assert [str(fp.filename) for fp in non_pset_input.imap_file_paths] == [non_pset] + + @mock.patch("imap_processing.cli.quaternions.process_quaternions", autospec=True) def test_spacecraft(mock_spacecraft_l1a, mock_instrument_dependencies): """Test coverage for cli.Spacecraft class""" @@ -444,7 +561,7 @@ def test_spacecraft_pointing_kernel( mocks["mock_pre_processing"].return_value = input_collection instrument = Spacecraft( - "spice", "pointing_kernel", dependency_str, "20240410", "12345", "v005", False + "l1a", "pointing-attitude", dependency_str, "20240410", "12345", "v005", False ) instrument.process() @@ -540,6 +657,34 @@ def test_ultra_l2(mock_ultra_l2, mock_instrument_dependencies): assert mock_instrument_dependencies["mock_write_cdf"].call_count == 1 +@mock.patch("imap_processing.cli.idex_l1b") +def test_idex_l1b(mock_idex_l1b, mock_instrument_dependencies): + """Test coverage for cli.Idex class with l1b data level""" + mocks = mock_instrument_dependencies + new_ds = xr.Dataset(data_vars={"epoch": [1]}) + mocks["mock_load_cdf"].side_effect = [new_ds] + input_collection = ProcessingInputCollection( + ScienceInput( + "imap_idex_l1a_sci-1week_20251017_v001.cdf", + "imap_idex_l1a_sci-1week_20251012_v001.cdf", + ), + SPICEInput("naif0012.tls", "imap_sclk_0000.tsc"), + SpinInput("imap_2025_306_2025_307_01.spin"), + ) + mocks["mock_pre_processing"].return_value = input_collection + + dependency_str = input_collection.serialize() + instrument = Idex( + "l1b", "sci-1week", dependency_str, "20251017", None, "v001", False + ) + + instrument.process() + assert mock_idex_l1b.call_count == 1 + # Assert that the dataset with the newer epoch value was passed to idex_l1b for + # processing + xr.testing.assert_equal(mock_idex_l1b.call_args[0][0], new_ds) + + @mock.patch("imap_processing.cli.idex_l2b") def test_idex_l2b(mock_idex_l2b, mock_instrument_dependencies): """Test coverage for cli.Idex class with l2b data level""" @@ -563,6 +708,7 @@ def test_idex_l2b(mock_idex_l2b, mock_instrument_dependencies): assert mock_instrument_dependencies["mock_write_cdf"].call_count == 2 +@pytest.mark.xfail(reason="To be fixed in ticket #3215", strict=False) @mock.patch("imap_processing.cli.hit_l1a") def test_hit_l1a(mock_hit_l1a, mock_instrument_dependencies): """Test coverage for cli.Hit class with l1a data level""" @@ -681,22 +827,27 @@ def do_processing_side_effect(*args, **kwargs): instrument.process() +@mock.patch("imap_processing.cli.filter_day_boundary_data") @mock.patch("imap_processing.cli.swe_l1a") @pytest.mark.parametrize( - "query_return, expected_error", + "query_return, expected_warning", [ - ([], None), + ([], False), ( [ '{"file_path": ' '"/path/to/imap_swe_l1a_test_20100105_v001.cdf", "instrument": "swe"}' ], - ProcessInstrument.ImapFileExistsError, + True, ), ], ) def test_post_processing( - mock_swe_l1a, mock_instrument_dependencies, query_return, expected_error + mock_swe_l1a, + mock_filter, + mock_instrument_dependencies, + query_return, + expected_warning, ): """Test coverage for post processing""" mocks = mock_instrument_dependencies @@ -709,8 +860,17 @@ def test_post_processing( ].return_value = "/path/to/imap_swe_l1a_test_20100105_v001.cdf" mocks["mock_query"].return_value = query_return + # Setup for testing file exists handling in upload_products + if expected_warning: + # Mock the upload method to simulate a file exists error + mocks["mock_upload"].side_effect = imap_data_access.io.IMAPDataAccessError( + '409 Conflict: {"error": "FileAlreadyExists", ' + '"message": "The file already exists."}' + ) + test_ds = xr.Dataset() mock_swe_l1a.return_value = [test_ds] + mock_filter.side_effect = lambda ds, _: ds input_collection = ProcessingInputCollection( ScienceInput("imap_swe_l0_raw_20100105_v001.pkts"), SPICEInput("naif0012.tls", "imap_sclk_0001.tsc"), @@ -723,16 +883,18 @@ def test_post_processing( ) instrument = Swe("l1a", "raw", dependency_str, "20100105", None, "v001", True) - if expected_error: - with pytest.raises(expected_error): - instrument.process() - else: - # This function calls both the instrument.do_processing() and - # instrument.post_processing() + # Now we expect the process to complete without errors in both cases + # The current implementation should skip over the file exists error + with mock.patch("logging.Logger.warning") as mock_warning: instrument.process() - assert mock_swe_l1a.call_count == 1 - # This test is testing that one file was uploaded - assert mocks["mock_upload"].call_count == 1 + if expected_warning: + # Verify that we saw a warning about skipping upload + assert any( + "Skipping upload" in str(call) for call in mock_warning.call_args_list + ) + else: + # This is testing that one file was uploaded successfully + assert mocks["mock_upload"].call_count == 1 # Test parent injection assert test_ds.attrs["Parents"] == [ diff --git a/imap_processing/tests/test_utils.py b/imap_processing/tests/test_utils.py index 6dd5853a15..2f65770de5 100644 --- a/imap_processing/tests/test_utils.py +++ b/imap_processing/tests/test_utils.py @@ -1,12 +1,16 @@ """Tests coverage for imap_processing/utils.py""" +from unittest import mock + import numpy as np import pandas as pd import pytest import xarray as xr from imap_processing import imap_module_directory, utils +from imap_processing.spice.time import str_yyyymmdd_to_ttj2000ns from imap_processing.ultra.utils.ultra_l1_utils import extract_data_dict +from imap_processing.utils import check_epochs_within_day_offsets def test_convert_raw_to_eu(tmp_path): @@ -262,6 +266,114 @@ def test_packet_file_to_datasets_flat_definition(): utils.packet_file_to_datasets(packet_files, packet_definition) +def test_combine_segmented_packets(): + """Test combine_segmented_packets function.""" + + # unsegmented, first, middle, last, unsegmented + sequence_flags = xr.DataArray(np.array([3, 1, 0, 2, 3]), dims=["epoch"]) + + binary_data = xr.DataArray( + np.array( + [ + b"ABC", + b"123", + b"456", + b"789", + b"abc", + ], + dtype=object, + ), + dims=["epoch"], + ) + + ds = xr.Dataset(data_vars={"seq_flgs": sequence_flags, "packetdata": binary_data}) + + combined_ds = utils.combine_segmented_packets(ds, "packetdata") + + expected_ds = xr.Dataset( + data_vars={ + "seq_flgs": xr.DataArray(np.array([3, 1, 3]), dims=["epoch"]), + "packetdata": xr.DataArray( + np.array( + [ + b"ABC", + b"123456789", + b"abc", + ], + dtype=object, + ), + dims=["epoch"], + ), + } + ) + + xr.testing.assert_equal(combined_ds, expected_ds) + + +def test_combine_single_segmented_packets(caplog): + """Test combine_segmented_packets function when there are missing segments.""" + + # Create a dataset with the MIDDLE and LAST segments missing. + # unsegmented, first, unsegmented + sequence_flags = xr.DataArray(np.array([3, 1, 3]), dims=["epoch"]) + + binary_data = xr.DataArray( + np.array( + [ + b"ABC", + b"123", + b"abc", + ], + dtype=object, + ), + dims=["epoch"], + ) + shcoarse = xr.DataArray(np.array([0, 1, 2]), dims=["epoch"]) + + ds = xr.Dataset( + data_vars={ + "seq_flgs": sequence_flags, + "packetdata": binary_data, + "shcoarse": shcoarse, + } + ) + + combined_ds = utils.combine_segmented_packets(ds, "packetdata") + + # The combined dataset should only have the unsegmented packets + # and a warning should be logged about the missing segments. + expected_ds = xr.Dataset( + data_vars={ + "seq_flgs": xr.DataArray(np.array([3, 3]), dims=["epoch"]), + "packetdata": xr.DataArray( + np.array( + [b"ABC", b"abc"], + dtype=object, + ), + dims=["epoch"], + ), + "shcoarse": xr.DataArray(np.array([0, 2]), dims=["epoch"]), + } + ) + + xr.testing.assert_equal(combined_ds, expected_ds) + + # check that a warning was logged + assert "Incorrect/incomplete sequence flags in group 2." in caplog.text + + +def test_check_source_sequence_counter(caplog): + """Test _check_source_sequence_counter function.""" + data_vars = { + "src_seq_ctr": (["epoch"], np.array([0, 1, 3, 4, 6])), + } + ds = xr.Dataset(data_vars=data_vars) + + utils._check_source_sequence_counter(ds, apid=1234) + + assert "Found [2] gap(s) in source sequence counter for APID 1234" in caplog.text + + def test_extract_data_dict(): """Test extract_data_dict function.""" data_vars = { @@ -288,3 +400,63 @@ def test_extract_data_dict(): } np.testing.assert_array_equal(result["field_a"], np.array([1, 2, 3])) np.testing.assert_array_equal(result["spin_number"], np.array([0, 1, 2])) + + +def test_filter_day_boundary_data(): + """Test filter_day_boundary_data filters epochs outside the processing day.""" + + start_date = "20250901" + start = str_yyyymmdd_to_ttj2000ns(start_date) + one_day_ns = np.int64(86_400 * 1_000_000_000) + + # Epochs: one before the day, three within, one after + epoch_values = np.array( + [ + start - 1, # before day boundary + start, # exactly at start (included) + start + one_day_ns // 2, # midday (included) + start + one_day_ns - 1, # last ns of day (included) + start + one_day_ns, # exactly at next day start (excluded) + ], + dtype=np.int64, + ) + ds = xr.Dataset( + {"value": ("epoch", np.arange(len(epoch_values)))}, + coords={"epoch": epoch_values}, + ) + + result = utils.filter_day_boundary_data(ds, start_date) + + assert result.sizes["epoch"] == 3 + np.testing.assert_array_equal(result["epoch"].values, epoch_values[1:4]) + + +@pytest.mark.parametrize( + "epoch_ns,raises", + [ + # midday of expected day β€” passes + (int(1.5 * 86400 * 1e9), False), + # exactly at lower tolerance boundary (24h before day start) β€” passes + (0, False), + # 1 ns before lower bound β€” more than 24h outside, raises + (-1, True), + # 1 ns past upper bound β€” more than 24h outside, raises + (int(3 * 86400 * 1e9 + 1), True), + ], +) +def test_check_epochs_within_day(epoch_ns, raises): + """_check_epochs_within_day raises only when epoch is >24h outside expected day.""" + # lower = expected_day - 1 day (J2000 ns = 0), upper = expected_day + 2 days + lower_ns = 0 + upper_ns = int(3 * 86400 * 1e9) + day = np.datetime64("2025-01-01", "D") + ds = xr.Dataset({"epoch": xr.DataArray(np.array([epoch_ns], dtype=np.int64))}) + with mock.patch( + "imap_processing.utils.str_yyyymmdd_to_ttj2000ns", + side_effect=[lower_ns, upper_ns], + ): + if raises: + with pytest.raises(ValueError, match="more than 24 hours outside"): + check_epochs_within_day_offsets([ds], day) + else: + check_epochs_within_day_offsets([ds], day) diff --git a/imap_processing/tests/ultra/data/l1/imap_ultra_l1b-45sensor-de-product-lookup_20251001_v001.csv b/imap_processing/tests/ultra/data/l1/imap_ultra_l1b-45sensor-de-product-lookup_20251001_v001.csv new file mode 100644 index 0000000000..f3c31692cf --- /dev/null +++ b/imap_processing/tests/ultra/data/l1/imap_ultra_l1b-45sensor-de-product-lookup_20251001_v001.csv @@ -0,0 +1,2 @@ +repointing_id_start,repointing_id_end,de_product +0,,imap_ultra_l1b_45sensor-de diff --git a/imap_processing/tests/ultra/data/l1/imap_ultra_l1c-45sensor-de-product-lookup_20251001_v001.csv b/imap_processing/tests/ultra/data/l1/imap_ultra_l1c-45sensor-de-product-lookup_20251001_v001.csv new file mode 100644 index 0000000000..f3c31692cf --- /dev/null +++ b/imap_processing/tests/ultra/data/l1/imap_ultra_l1c-45sensor-de-product-lookup_20251001_v001.csv @@ -0,0 +1,2 @@ +repointing_id_start,repointing_id_end,de_product +0,,imap_ultra_l1b_45sensor-de diff --git a/imap_processing/tests/ultra/mock_data.py b/imap_processing/tests/ultra/mock_data.py index dab7147ad3..ff8cd6b424 100644 --- a/imap_processing/tests/ultra/mock_data.py +++ b/imap_processing/tests/ultra/mock_data.py @@ -6,6 +6,7 @@ import xarray as xr from imap_processing.ena_maps.utils.coordinates import CoordNames +from imap_processing.quality_flags import ImapPSETUltraFlags from imap_processing.spice.time import str_to_et from imap_processing.ultra.l1c.ultra_l1c_pset_bins import build_energy_bins @@ -166,6 +167,7 @@ def get_binomial_counts(distance_scaling, lat_bin, central_lat_bin): ], sensitivity, ), + "epoch_delta": ([CoordNames.TIME.value], np.array([10], dtype=np.float64)), }, coords={ CoordNames.TIME.value: [ @@ -192,7 +194,8 @@ def get_binomial_counts(distance_scaling, lat_bin, central_lat_bin): # TODO: Add ability to mock with/without energy dim to exposure_factor # The Helio frame L1C will have the energy dimension, but the spacecraft frame will not. def mock_l1c_pset_product_healpix( - nside: int = DEFAULT_HEALPIX_NSIDE_L1C, + nside: int = 32, + counts_nside: int = 128, stripe_center_lat: int = 0, width_scale: float = 10.0, counts_scaling_params: tuple[int, float] = (100, 0.01), @@ -263,19 +266,19 @@ def mock_l1c_pset_product_healpix( energy_bin_delta = np.diff(energy_intervals, axis=1).squeeze() num_energy_bins = len(energy_bin_midpoints) npix = hp.nside2npix(nside) - counts = np.zeros(npix) - exposure_time = np.zeros(npix) - + counts_npix = hp.nside2npix(counts_nside) + # counts are binned at a higher resolution than the other variables. See L1c + # code for more details. # Get latitude for each healpix pixel - pix_indices = np.arange(npix) - lon_pix, lat_pix = hp.pix2ang(nside, pix_indices, lonlat=True) - - counts = np.zeros(shape=(num_energy_bins, npix)) + counts_pix_indices = np.arange(counts_npix) + counts_lon_pix, counts_lat_pix = hp.pix2ang( + counts_nside, counts_pix_indices, lonlat=True + ) # Calculate probability based on distance from target latitude - lat_diff = np.abs(lat_pix - stripe_center_lat) + counts_lat_diff = np.abs(counts_lat_pix - stripe_center_lat) prob_scaling_factor = counts_scaling_params[1] * np.exp( - -(lat_diff**2) / (2 * width_scale**2) + -(counts_lat_diff**2) / (2 * width_scale**2) ) # Generate counts using binomial distribution rng = np.random.default_rng(seed=42) @@ -285,6 +288,12 @@ def mock_l1c_pset_product_healpix( for _ in range(num_energy_bins) ] ) + # Get latitude for each healpix pixel + pix_indices = np.arange(npix) + lon_pix, lat_pix = hp.pix2ang(nside, pix_indices, lonlat=True) + + # Calculate probability based on distance from target latitude + lat_diff = np.abs(lat_pix - stripe_center_lat) # Generate exposure times using gaussian distribution, but wider prob_scaling_factor_exptime = counts_scaling_params[1] * np.exp( @@ -316,7 +325,11 @@ def mock_l1c_pset_product_healpix( counts = counts.astype(int) # add an epoch dimension counts = np.expand_dims(counts, axis=0) - sensitivity = np.ones_like(counts) + ones_ds = np.ones((num_energy_bins, npix)) # pointing independent + sensitivity = ones_ds + geometric_function = ones_ds + efficiency = ones_ds + scatter = ones_ds # Determine the epoch, which is TT time in nanoseconds since J2000 epoch tdb_et = str_to_et(timestr) @@ -333,7 +346,7 @@ def mock_l1c_pset_product_healpix( [ CoordNames.TIME.value, CoordNames.ENERGY_ULTRA_L1C.value, - CoordNames.HEALPIX_INDEX.value, + CoordNames.COUNTS_HEALPIX_INDEX.value, ], counts, ), @@ -343,7 +356,7 @@ def mock_l1c_pset_product_healpix( CoordNames.ENERGY_ULTRA_L1C.value, CoordNames.HEALPIX_INDEX.value, ], - np.full_like(counts, 0.05, dtype=float), + np.full((1, num_energy_bins, npix), 0.05, dtype=float), ), "exposure_factor": ( exposure_dims, # special case: optionally energy dependent exposure @@ -351,12 +364,39 @@ def mock_l1c_pset_product_healpix( ), "sensitivity": ( [ - CoordNames.TIME.value, CoordNames.ENERGY_ULTRA_L1C.value, CoordNames.HEALPIX_INDEX.value, ], sensitivity, ), + "scatter_theta": ( + [ + CoordNames.ENERGY_ULTRA_L1C.value, + CoordNames.HEALPIX_INDEX.value, + ], + scatter, + ), + "scatter_phi": ( + [ + CoordNames.ENERGY_ULTRA_L1C.value, + CoordNames.HEALPIX_INDEX.value, + ], + scatter, + ), + "efficiency": ( + [ + CoordNames.ENERGY_ULTRA_L1C.value, + CoordNames.HEALPIX_INDEX.value, + ], + efficiency, + ), + "geometric_function": ( + [ + CoordNames.ENERGY_ULTRA_L1C.value, + CoordNames.HEALPIX_INDEX.value, + ], + geometric_function, + ), CoordNames.AZIMUTH_L1C.value: ( [CoordNames.HEALPIX_INDEX.value], lon_pix, @@ -369,6 +409,11 @@ def mock_l1c_pset_product_healpix( [CoordNames.ENERGY_ULTRA_L1C.value], energy_bin_delta, ), + "quality_flags": ( + [CoordNames.TIME.value, CoordNames.HEALPIX_INDEX.value], + np.full((1, npix), ImapPSETUltraFlags.NONE.value, dtype=np.uint16), + ), + "epoch_delta": ([CoordNames.TIME.value], np.array([10], dtype=np.float64)), }, coords={ CoordNames.TIME.value: [ diff --git a/imap_processing/tests/ultra/unit/conftest.py b/imap_processing/tests/ultra/unit/conftest.py index 5143106dc1..bfd8a54990 100644 --- a/imap_processing/tests/ultra/unit/conftest.py +++ b/imap_processing/tests/ultra/unit/conftest.py @@ -8,6 +8,7 @@ import xarray as xr from imap_processing import imap_module_directory +from imap_processing.ultra.constants import UltraConstants from imap_processing.ultra.l0.decom_ultra import ( process_ultra_cmd_echo, process_ultra_energy_rates, @@ -27,6 +28,7 @@ ULTRA_EXTOF_HIGH_ANGULAR, ULTRA_EXTOF_HIGH_ENERGY, ULTRA_EXTOF_HIGH_TIME, + ULTRA_HK, ULTRA_MACROS_CHECKSUM, ULTRA_PHXTOF_HIGH_ANGULAR, ULTRA_PHXTOF_HIGH_ENERGY, @@ -38,6 +40,11 @@ ULTRA_RATES, ) from imap_processing.ultra.l1a.ultra_l1a import ultra_l1a +from imap_processing.ultra.l1b.ultra_l1b_culling import ( + get_binned_energy_ranges, + get_energy_range_flags, +) +from imap_processing.ultra.l1c.l1c_lookup_utils import build_energy_bins from imap_processing.utils import packet_file_to_datasets @@ -265,50 +272,35 @@ def tof_high_angular_test_path(): @pytest.fixture def tof_high_energy_test_path(): """Returns the xtce test data directory.""" - filename = ( - "ultra45_raw_sc_enaphxtofhnrgimg_FM45_UltraFM45Extra_TV_Tests_" - "2024-01-22T0930_20240122T093008.csv" - ) + filename = "ultra45_l1b_raw_sc_enaphxtofhnrgimg_20240122_00_SDCStyle.csv" return imap_module_directory / "tests" / "ultra" / "data" / "l0" / filename @pytest.fixture def tof_high_time_test_path(): """Returns the xtce test data directory.""" - filename = ( - "ultra45_raw_sc_ultraenaphxtofhtimeresimg_FM45_UltraFM45Extra_" - "TV_Tests_2024-01-22T0930_20240122T093008.csv" - ) + filename = "ultra45_l1b_raw_sc_enaphxtofhtimeimg_20240122_00_SDCStyle.csv" return imap_module_directory / "tests" / "ultra" / "data" / "l0" / filename @pytest.fixture def extof_high_angular_test_path(): """Returns the xtce test data directory.""" - filename = ( - "ultra45_raw_sc_enaextofhangimg_FM45_UltraFM45Extra_TV_Tests_" - "2024-01-22T0930_20240122T093008.csv" - ) + filename = "ultra45_l1b_raw_sc_enaextofhangimg_20240122_00_SDCStyle.csv" return imap_module_directory / "tests" / "ultra" / "data" / "l0" / filename @pytest.fixture def extof_high_time_test_path(): """Returns the xtce test data directory.""" - filename = ( - "ultra45_raw_sc_ionexhtimeimg_FM45_UltraFM45Extra_TV_Tests_" - "2024-01-22T0930_20240122T093008.csv" - ) + filename = "ultra45_l1b_raw_sc_ionextofhtimeimg_20240122_00_SDCStyle.csv" return imap_module_directory / "tests" / "ultra" / "data" / "l0" / filename @pytest.fixture def extof_high_energy_test_path(): """Returns the xtce test data directory.""" - filename = ( - "ultra45_raw_sc_ionextofhnrgimg_FM45_UltraFM45Extra_TV_Tests_" - "2024-01-22T0930_20240122T093008.csv" - ) + filename = "ultra45_l1b_raw_sc_ionextofhnrgimg_20240122_00_SDCStyle.csv" return imap_module_directory / "tests" / "ultra" / "data" / "l0" / filename @@ -453,6 +445,13 @@ def aux_dataset(ccsds_path_theta_0): return test_data[0] +@pytest.fixture +def status_dataset(ccsds_path_theta_0): + """L1A test data""" + test_data = ultra_l1a(ccsds_path_theta_0, apid_input=ULTRA_HK.apid[3]) + return test_data[0] + + @pytest.fixture def faux_aux_dataset(): """Fixture to compute and return aux test data.""" @@ -490,6 +489,8 @@ def ancillary_files(): return { "l1b-45sensor-logistic-interpolation": path / "imap_ultra_l1b-45sensor-logistic-interpolation_20250101_v000.csv", + "l1b-90sensor-logistic-interpolation": path + / "imap_ultra_l1b-45sensor-logistic-interpolation_20250101_v000.csv", "l1b-sensor-gf-noblades": path / "imap_ultra_l1b-sensor-gf-noblades_20250101_v000.csv", "l1b-sensor-gf-blades": path @@ -529,98 +530,62 @@ def ancillary_files(): "l1b-90sensor-tofxesteep": path / "imap_ultra_l1b-90sensor-tofxesteep_20250101_v000.pgm", "l1b-tofxph": path / "imap_ultra_l1b-tofxph_20250101_v000.pgm", - "l1b-90sensor-scattering-calibration": path + "l1b-90sensor-scattering-calibration-data": path / "imap_ultra_l1b-90sensor-scattering-calibration-data_20250101_v000.csv", "l1c-90sensor-dps-exposure": path / "imap_ultra_l1c-90sensor-dps-exposure_20250101_v000.csv", "l1c-90sensor-efficiencies": path / "imap_ultra_l1c-90sensor-efficiencies_20250101_v000.csv", "l1c-90sensor-gf": path / "imap_ultra_l1c-90sensor-gf_20250101_v000.csv", - "l1c-90sensor-sc-pointing-theta-n32": path - / "imap_ultra_l1c-90sensor-sc-pointing-theta-n32-test_20250101_v000.csv", - "l1c-90sensor-sc-pointing-phi-n32": path - / "imap_ultra_l1c-90sensor-sc-pointing-phi-n32-test_20250101_v000.csv", - "l1c-90sensor-sc-pointing-index-n32": path - / "imap_ultra_l1c-90sensor-sc-pointing-index-n32-test_20250101_v000.csv", - "l1c-90sensor-sc-pointing-bsf-n32": path - / "imap_ultra_l1c-90sensor-sc-pointing-bsf-n32-test_20250101_v000.csv", - "l1c-45sensor-sc-pointing-theta-n32": path - / "imap_ultra_l1c-90sensor-sc-pointing-theta-n32-test_20250101_v000.csv", - "l1c-45sensor-sc-pointing-phi-n32": path - / "imap_ultra_l1c-90sensor-sc-pointing-phi-n32-test_20250101_v000.csv", - "l1c-45sensor-sc-pointing-index-n32": path - / "imap_ultra_l1c-90sensor-sc-pointing-index-n32-test_20250101_v000.csv", - "l1c-45sensor-sc-pointing-bsf-n32": path - / "imap_ultra_l1c-90sensor-sc-pointing-bsf-n32-test_20250101_v000.csv", + "l1c-90sensor-sc-pointing-theta": path + / "imap_ultra_l1c-90sensor-sc-pointing-theta-test_20250101_v000.csv", + "l1c-90sensor-sc-pointing-phi": path + / "imap_ultra_l1c-90sensor-sc-pointing-phi-test_20250101_v000.csv", + "l1c-90sensor-sc-pointing-index": path + / "imap_ultra_l1c-90sensor-sc-pointing-index-test_20250101_v000.csv", + "l1c-90sensor-sc-pointing-bsf": path + / "imap_ultra_l1c-90sensor-sc-pointing-bsf-test_20250101_v000.csv", + "l1c-45sensor-sc-pointing-theta": path + / "imap_ultra_l1c-90sensor-sc-pointing-theta-test_20250101_v000.csv", + "l1c-45sensor-sc-pointing-phi": path + / "imap_ultra_l1c-90sensor-sc-pointing-phi-test_20250101_v000.csv", + "l1c-45sensor-sc-pointing-index": path + / "imap_ultra_l1c-90sensor-sc-pointing-index-test_20250101_v000.csv", + "l1c-45sensor-sc-pointing-bsf": path + / "imap_ultra_l1c-90sensor-sc-pointing-bsf-test_20250101_v000.csv", "l1b-scattering-thresholds-per-energy": path / "imap_ultra_l1b-scattering-thresholds-per-energy_20250101_v000.csv", + "l1c-45sensor-static-dead-times": path + / "imap_ultra_l1c-45sensor-static-dead-times_20250101_v000.csv", + "l1c-90sensor-static-dead-times": path + / "imap_ultra_l1c-90sensor-static-dead-times_20250101_v000.csv", + "l1c-45sensor-de-product-lookup": path + / "imap_ultra_l1c-45sensor-de-product-lookup_20251001_v001.csv", + "l1c-90sensor-de-product-lookup": path + / "imap_ultra_l1c-45sensor-de-product-lookup_20251001_v001.csv", } -@pytest.fixture -def deadtime_datasets(): - """Fixture to create params and rates datasets needed to calculate the spacecraft - exposure time.""" - # Simulate a test rates dataset. - epoch = 200 - test_l1a_rates_dataset = xr.Dataset( - { - "fifo_valid_events": (["epoch"], np.random.randint(100, 200, epoch)), - "event_active_time": (["epoch"], np.random.uniform(0, 10, epoch)), - "start_pos": (["epoch"], np.random.randint(0, 5, epoch)), - "start_rf": (["epoch"], np.random.randint(0, 5, epoch)), - "start_lf": (["epoch"], np.random.randint(0, 5, epoch)), - "coin_tn": (["epoch"], np.random.randint(0, 5, epoch)), - "coin_bn": (["epoch"], np.random.randint(0, 5, epoch)), - "stop_tn": (["epoch"], np.random.randint(0, 5, epoch)), - "stop_bn": (["epoch"], np.random.randint(0, 5, epoch)), - "shcoarse": (["epoch"], np.arange(epoch)), - "spin": (["epoch"], 127 + (np.arange(epoch) % (141 - 127))), - } - ) - # Sector mode (image rates cadence = 3) happens 3 times a day (per pointing). - # each time the mode changes, it is recorded in the params packet. - # Create a test params dataset that simulates the mode changing to 3, 3 times. - modes = np.tile(np.arange(4), 3) - test_l1a_params_dataset = xr.Dataset( - { - "imageratescadence": (["epoch"], modes), - }, - coords={"epoch": ("epoch", np.arange(0, epoch, epoch / len(modes)))}, - ) - return {"rates": test_l1a_rates_dataset, "params": test_l1a_params_dataset} - - -@pytest.fixture -def random_spin_data(): - """Fixture for random spin data.""" - with mock.patch( - "imap_processing.ultra.l1c.ultra_l1c_pset_bins.get_spacecraft_spin_phase" - ) as mock_spin_phases: - mock_spin_phases.side_effect = lambda time: np.random.random(time.shape) - yield - - @pytest.fixture def mock_spacecraft_pointing_lookups(): """Test lookup tables fixture.""" - pix = hp.nside2npix(8) # reduced for testing - steps = 5 # Reduced for testing - for_indices_by_spin_phase = np.random.choice( - [True, False], size=(pix, steps), p=[0.1, 0.9] - ) - theta_vals = np.random.uniform(-60, 60, size=(pix, steps)) - phi_vals = np.random.uniform(-60, 60, size=(pix, steps)) + np.random.seed(42) + pix = hp.nside2npix(128) # reduced for testing + steps = 2 # Reduced for testing + for_indices_by_spin_phase = xr.DataArray( + np.random.choice([True, False], size=(steps, pix), p=[0.1, 0.9]), + dims=("spin_phase_step", "pixel"), + ) + theta_vals = np.random.uniform(-60, 60, size=(steps, pix)) + phi_vals = np.random.uniform(-60, 60, size=(steps, pix)) # Ra and Dec pixel shape needs to be the default healpix pixel count - ra_and_dec = np.random.uniform(-80, 80, size=(hp.nside2npix(128), 2)) - boundary_scale_factors = np.ones((pix, steps)) + ra_and_dec = np.random.uniform(-80, 80, size=(steps, pix)) + boundary_scale_factors = np.ones((steps, pix)) + with ( mock.patch( "imap_processing.ultra.l1c.spacecraft_pset.get_spacecraft_pointing_lookup_tables" ) as mock_lookup, - mock.patch( - "imap_processing.ultra.l1c.helio_pset.get_spacecraft_pointing_lookup_tables" - ) as mock_lookup_helio, ): mock_lookup.return_value = ( for_indices_by_spin_phase, @@ -629,11 +594,110 @@ def mock_spacecraft_pointing_lookups(): ra_and_dec, boundary_scale_factors, ) - mock_lookup_helio.return_value = ( - for_indices_by_spin_phase, - theta_vals, - phi_vals, - ra_and_dec, - boundary_scale_factors, + yield mock_lookup + + +@pytest.fixture +def mock_helio_pointing_lookups(): + """Test lookup tables fixture returning an xarray Dataset.""" + np.random.seed(42) + pix = hp.nside2npix(32) # reduced for testing + steps = 2 # Reduced for testing + energy = 46 + + # Ra and Dec pixel shape needs to be the default healpix pixel count + ra_and_dec = np.random.uniform(-80, 80, size=(steps, pix)) + + index_map = np.random.choice([True, False], size=(steps, energy, pix), p=[0.1, 0.9]) + index_map = index_map.astype(bool) + theta_map = np.random.uniform(-60, 60, size=(steps, energy, pix)) + phi_map = np.random.uniform(-60, 60, size=(steps, energy, pix)) + bsf_map = np.ones((steps, energy, pix)) + with ( + mock.patch( + "imap_processing.ultra.l1c.helio_pset.make_helio_index_maps_with_nominal_kernels" + ) as mock_lookup, + ): + ds = xr.Dataset( + data_vars={ + "index": ( + ["spin_phase_step", "energy", "pixel"], + index_map, + {"long_name": "Pixel in FOV flag"}, + ), + "theta": ( + ["spin_phase_step", "energy", "pixel"], + theta_map, + {"long_name": "Instrument theta angle", "units": "degrees"}, + ), + "phi": ( + ["spin_phase_step", "energy", "pixel"], + phi_map, + {"long_name": "Instrument phi angle", "units": "degrees"}, + ), + "bsf": ( + ["spin_phase_step", "energy", "pixel"], + bsf_map, + {"long_name": "Boundary scale factor", "units": "fractional"}, + ), + "ra_and_dec": (["spin_phase_step", "pixel"], ra_and_dec), + }, + coords={ + "spin_phase_step": np.arange(steps), + "energy": np.arange(energy), + "pixel": np.arange(pix), + }, ) + mock_lookup.return_value = ds + yield mock_lookup + + +@pytest.fixture +def mock_goodtimes_dataset(): + """Create a mock goodtimes dataset.""" + # Set up bit flags + intervals, _, _ = build_energy_bins() + energy_ranges = get_binned_energy_ranges(intervals) + energy_flags = get_energy_range_flags(energy_ranges) + + energy_flags_padded = np.zeros(UltraConstants.MAX_ENERGY_RANGES, dtype=np.uint16) + energy_flags_padded[: len(energy_flags)] = energy_flags + + energy_ranges_padded = np.full( + UltraConstants.MAX_ENERGY_RANGE_EDGES, -1.0e31, dtype=np.float32 + ) + energy_ranges_padded[: len(energy_ranges)] = energy_ranges + + nspins = 100 + flags = 2 ** np.arange(9) + quality = np.zeros(nspins, dtype=np.uint16) + quality[0] = flags[0] # Set the first flag for the first spin + quality[1] = flags[1] # Set the second flag for the second + quality[2] = flags[2] # Set the third flag for the third spin + return xr.Dataset( + { + "spin_number": ("epoch", np.zeros(nspins)), + "energy_range_flags": ("energy_flags", energy_flags_padded), + "quality_low_voltage": ("spin_number", quality), + "quality_high_energy": ("spin_number", np.zeros(nspins, dtype=np.uint16)), + "quality_statistics": ("spin_number", np.zeros(nspins, dtype=np.uint16)), + "energy_range_edges": ("energy_ranges", energy_ranges_padded), + "spin_period": ( + "spin_number", + np.full(nspins, 15), + ), # nominal spin period of 15 seconds + "quality_upstream_ion_1": ( + "spin_number", + np.zeros(nspins, dtype=np.uint16), + ), + "quality_upstream_ion_2": ( + "spin_number", + np.zeros(nspins, dtype=np.uint16), + ), + "quality_spectral": ( + "spin_number", + np.zeros(nspins, dtype=np.uint16), + ), + } + ) diff --git a/imap_processing/tests/ultra/unit/test_badtimes.py b/imap_processing/tests/ultra/unit/test_badtimes.py index 214135ce8c..c0a4df5b8b 100644 --- a/imap_processing/tests/ultra/unit/test_badtimes.py +++ b/imap_processing/tests/ultra/unit/test_badtimes.py @@ -3,7 +3,7 @@ from imap_processing.quality_flags import ImapAttitudeUltraFlags, ImapRatesUltraFlags from imap_processing.ultra.l1b.badtimes import calculate_badtimes -from imap_processing.ultra.l1b.cullingmask import calculate_cullingmask +from imap_processing.ultra.l1b.goodtimes import calculate_goodtimes def test_calculate_badtimes(): @@ -42,15 +42,15 @@ def test_calculate_badtimes(): }, ) - culling_ds = calculate_cullingmask(ds, name="imap_ultra_l1b_45sensor-badtimes") + goodtimes_ds = calculate_goodtimes(ds, name="imap_ultra_l1b_45sensor-badtimes") badtimes_ds = calculate_badtimes( ds, - culling_ds["spin_number"].values, + goodtimes_ds["spin_number"].values, name="imap_ultra_l1b_45sensor-badtimes", ) assert not np.any( - np.isin(culling_ds["spin_number"].values, badtimes_ds["spin_number"].values) + np.isin(goodtimes_ds["spin_number"].values, badtimes_ds["spin_number"].values) ) diff --git a/imap_processing/tests/ultra/unit/test_de.py b/imap_processing/tests/ultra/unit/test_de.py index f338562f66..f54721d7de 100644 --- a/imap_processing/tests/ultra/unit/test_de.py +++ b/imap_processing/tests/ultra/unit/test_de.py @@ -6,7 +6,9 @@ from imap_processing import imap_module_directory from imap_processing.cdf.utils import load_cdf +from imap_processing.spice.repoint import get_repoint_data from imap_processing.ultra.constants import UltraConstants +from imap_processing.ultra.l1b.de import calculate_events_in_pointing TEST_PATH = imap_module_directory / "tests" / "ultra" / "data" / "l1" @@ -119,3 +121,24 @@ def test_calculate_de(df_filt): len(l1b_de_dataset["epoch"]), 3, ) + + +def test_calculate_events_in_pointing(use_fake_repoint_data_for_time): + """Tests calculate_events_in_pointing function.""" + use_fake_repoint_data_for_time(np.arange(511000000, 511000000 + 86400 * 5, 86400)) + repoint_id = 1 + repoint_data = get_repoint_data() + pointing_start = repoint_data[repoint_data["repoint_id"] == repoint_id][ + "repoint_end_met" + ].values[0] + # Create array of event times that are all within a pointing. + event_times = np.arange(pointing_start, pointing_start + 10) + # Edit the first event time to be during a repoint. + event_times[0] = pointing_start - 1 + in_pointing = calculate_events_in_pointing( + repoint_id, + event_times, + ) + # The first event should be False (not during a pointing), and the rest True. + assert np.all(not in_pointing[0]) + assert np.all(in_pointing[1:]) diff --git a/imap_processing/tests/ultra/unit/test_decom_apid_884.py b/imap_processing/tests/ultra/unit/test_decom_apid_884.py index 8d871428d0..ac6472d1ab 100644 --- a/imap_processing/tests/ultra/unit/test_decom_apid_884.py +++ b/imap_processing/tests/ultra/unit/test_decom_apid_884.py @@ -1,5 +1,3 @@ -import json - import numpy as np import pandas as pd import pytest @@ -28,20 +26,38 @@ def test_phxtof_high_energy_decom(decom_test_data, tof_high_energy_test_path): decom_ultra = decom_test_data df = pd.read_csv(tof_high_energy_test_path, index_col="SequenceCount") - np.testing.assert_array_equal(df.Spin, decom_ultra["spin"].values.flatten()) - np.testing.assert_array_equal( - df.AbortFlag, decom_ultra["abortflag"].values.flatten() - ) - np.testing.assert_array_equal( - df.StartDelay, decom_ultra["startdelay"].values.flatten() + # Check metadata values + # The validation csvs provided only includes the last packet's spin value, + # abortflag, and startdelay + epoch = len(df["Epoch"].values) + decom_ultra = decom_ultra.isel(epoch=slice(0, epoch)) + np.testing.assert_array_equal(df.Spin, decom_ultra["spin"][:, -1]) + np.testing.assert_array_equal(df.AbortFlag, decom_ultra["abortflag"][:, -1]) + np.testing.assert_array_equal(df.StartDelay, decom_ultra["startdelay"][:, -1]) + + # Validation data from the IT team organizes image data into columns + # named UltraImage_Plane_Row_Col, where Plane, Row, and Col are 0-indexed. + # Each row corresponds to the epoch dimension. + colnames = df.columns.tolist() + + def column_name_sort(name): + return ( + int(name.split("_")[-3]), + int(name.split("_")[-2]), + int(name.split("_")[-1]), + ) + + images = sorted( + [name for name in colnames if "UltraImage" in name], key=column_name_sort ) - for count in df.index.get_level_values("SequenceCount").values: - df_data = df[ - df.index.get_level_values("SequenceCount") == count - ].UltraImage.values[0] - rows, cols = np.where(decom_ultra["src_seq_ctr"] == count) - decom_data = decom_ultra["packetdata"][rows[0]][cols[0]] - df_data_array = np.array(json.loads(df_data)[0]) + epoch = len(df["Epoch"].values) + planes = max([int(name.split("_")[-3]) for name in images]) + 1 + row = max([int(name.split("_")[-2]) for name in images]) + 1 + col = max([int(name.split("_")[-1]) for name in images]) + 1 + # Reshape the dataframe data into a 4D numpy array + df_data = df[images].to_numpy().reshape(epoch, planes, row, col) + # Only check up to the expected number of planes in the decom data + df_data = df_data[:, : ULTRA_PHXTOF_HIGH_ENERGY.image_planes, :, :] - np.testing.assert_array_equal(df_data_array, decom_data) + np.testing.assert_array_equal(df_data, decom_ultra["packetdata"]) diff --git a/imap_processing/tests/ultra/unit/test_decom_apid_885.py b/imap_processing/tests/ultra/unit/test_decom_apid_885.py index 68a7b3ffa0..c4215e510c 100644 --- a/imap_processing/tests/ultra/unit/test_decom_apid_885.py +++ b/imap_processing/tests/ultra/unit/test_decom_apid_885.py @@ -1,5 +1,3 @@ -import json - import numpy as np import pandas as pd import pytest @@ -28,20 +26,38 @@ def test_tof_high_time_decom(decom_test_data, tof_high_time_test_path): decom_ultra = decom_test_data df = pd.read_csv(tof_high_time_test_path, index_col="SequenceCount") - np.testing.assert_array_equal(df.Spin, decom_ultra["spin"].values.flatten()) - np.testing.assert_array_equal( - df.AbortFlag, decom_ultra["abortflag"].values.flatten() - ) - np.testing.assert_array_equal( - df.StartDelay, decom_ultra["startdelay"].values.flatten() + # Check metadata values + # The validation csvs provided only includes the last packet's spin value, + # abortflag, and startdelay + epoch = len(df["Epoch"].values) + decom_ultra = decom_ultra.isel(epoch=slice(0, epoch)) + np.testing.assert_array_equal(df.Spin, decom_ultra["spin"][:, -1]) + np.testing.assert_array_equal(df.AbortFlag, decom_ultra["abortflag"][:, -1]) + np.testing.assert_array_equal(df.StartDelay, decom_ultra["startdelay"][:, -1]) + + # Validation data from the IT team organizes image data into columns + # named UltraImage_Plane_Row_Col, where Plane, Row, and Col are 0-indexed. + # Each row corresponds to the epoch dimension. + colnames = df.columns.tolist() + + def column_name_sort(name): + return ( + int(name.split("_")[-3]), + int(name.split("_")[-2]), + int(name.split("_")[-1]), + ) + + images = sorted( + [name for name in colnames if "UltraImage" in name], key=column_name_sort ) - for count in df.index.get_level_values("SequenceCount").values: - df_data = df[ - df.index.get_level_values("SequenceCount") == count - ].UltraImage.values[0] - rows, cols = np.where(decom_ultra["src_seq_ctr"] == count) - decom_data = decom_ultra["packetdata"][rows[0]][cols[0]] - df_data_array = np.array(json.loads(df_data)[0]) + epoch = len(df["Epoch"].values) + planes = max([int(name.split("_")[-3]) for name in images]) + 1 + row = max([int(name.split("_")[-2]) for name in images]) + 1 + col = max([int(name.split("_")[-1]) for name in images]) + 1 + # Reshape the dataframe data into a 4D numpy array + df_data = df[images].to_numpy().reshape(epoch, planes, row, col) + # Only check up to the expected number of planes in the decom data + df_data = df_data[:, : ULTRA_PHXTOF_HIGH_TIME.image_planes, :, :] - np.testing.assert_array_equal(df_data_array, decom_data) + np.testing.assert_array_equal(df_data, decom_ultra["packetdata"]) diff --git a/imap_processing/tests/ultra/unit/test_decom_apid_886.py b/imap_processing/tests/ultra/unit/test_decom_apid_886.py index cca88c065e..156c7374cb 100644 --- a/imap_processing/tests/ultra/unit/test_decom_apid_886.py +++ b/imap_processing/tests/ultra/unit/test_decom_apid_886.py @@ -1,5 +1,3 @@ -import json - import numpy as np import pandas as pd import pytest @@ -28,20 +26,36 @@ def test_extof_high_ang_decom(decom_test_data, extof_high_angular_test_path): decom_ultra = decom_test_data df = pd.read_csv(extof_high_angular_test_path, index_col="SequenceCount") - np.testing.assert_array_equal(df.Spin, decom_ultra["spin"].values.flatten()) - np.testing.assert_array_equal( - df.AbortFlag, decom_ultra["abortflag"].values.flatten() - ) - np.testing.assert_array_equal( - df.StartDelay, decom_ultra["startdelay"].values.flatten() + # Check metadata values + # The validation csvs provided only includes the last packet's spin value, + # abortflag, and startdelay + np.testing.assert_array_equal(df.Spin, decom_ultra["spin"][:, -1]) + np.testing.assert_array_equal(df.AbortFlag, decom_ultra["abortflag"][:, -1]) + np.testing.assert_array_equal(df.StartDelay, decom_ultra["startdelay"][:, -1]) + + # Validation data from the IT team organizes image data into columns + # named UltraImage_Plane_Row_Col, where Plane, Row, and Col are 0-indexed. + # Each row corresponds to the epoch dimension. + colnames = df.columns.tolist() + + def column_name_sort(name): + return ( + int(name.split("_")[-3]), + int(name.split("_")[-2]), + int(name.split("_")[-1]), + ) + + images = sorted( + [name for name in colnames if "UltraImage" in name], key=column_name_sort ) - for count in df.index.get_level_values("SequenceCount").values: - df_data = df[ - df.index.get_level_values("SequenceCount") == count - ].UltraImage.values[0] - rows, cols = np.where(decom_ultra["src_seq_ctr"] == count) - decom_data = decom_ultra["packetdata"][rows[0]][cols[0]] - df_data_array = np.array(json.loads(df_data)[0]) + epoch = len(df["Epoch"].values) + planes = max([int(name.split("_")[-3]) for name in images]) + 1 + row = max([int(name.split("_")[-2]) for name in images]) + 1 + col = max([int(name.split("_")[-1]) for name in images]) + 1 + # Reshape the dataframe data into a 4D numpy array + df_data = df[images].to_numpy().reshape(epoch, planes, row, col) + # Only check up to the expected number of planes in the decom data + df_data = df_data[:, : ULTRA_EXTOF_HIGH_ANGULAR.image_planes, :, :] - np.testing.assert_array_equal(df_data_array, decom_data) + np.testing.assert_array_equal(df_data, decom_ultra["packetdata"]) diff --git a/imap_processing/tests/ultra/unit/test_decom_apid_887.py b/imap_processing/tests/ultra/unit/test_decom_apid_887.py index 9a0f2be896..f2f9d2de04 100644 --- a/imap_processing/tests/ultra/unit/test_decom_apid_887.py +++ b/imap_processing/tests/ultra/unit/test_decom_apid_887.py @@ -1,5 +1,3 @@ -import json - import numpy as np import pandas as pd import pytest @@ -30,20 +28,36 @@ def test_extof_high_nrg_decom(decom_test_data, extof_high_energy_test_path): decom_ultra = decom_test_data df = pd.read_csv(extof_high_energy_test_path, index_col="SequenceCount") - np.testing.assert_array_equal(df.Spin, decom_ultra["spin"].values.flatten()) - np.testing.assert_array_equal( - df.AbortFlag, decom_ultra["abortflag"].values.flatten() - ) - np.testing.assert_array_equal( - df.StartDelay, decom_ultra["startdelay"].values.flatten() + # Check metadata values + # The validation csvs provided only includes the last packet's spin value, + # abortflag, and startdelay + np.testing.assert_array_equal(df.Spin, decom_ultra["spin"][:, -1]) + np.testing.assert_array_equal(df.AbortFlag, decom_ultra["abortflag"][:, -1]) + np.testing.assert_array_equal(df.StartDelay, decom_ultra["startdelay"][:, -1]) + + # Validation data from the IT team organizes image data into columns + # named UltraImage_Plane_Row_Col, where Plane, Row, and Col are 0-indexed. + # Each row corresponds to the epoch dimension. + colnames = df.columns.tolist() + + def column_name_sort(name): + return ( + int(name.split("_")[-3]), + int(name.split("_")[-2]), + int(name.split("_")[-1]), + ) + + images = sorted( + [name for name in colnames if "UltraImage" in name], key=column_name_sort ) - for count in df.index.get_level_values("SequenceCount").values: - df_data = df[ - df.index.get_level_values("SequenceCount") == count - ].UltraImage.values[0] - rows, cols = np.where(decom_ultra["src_seq_ctr"] == count) - decom_data = decom_ultra["packetdata"][rows[0]][cols[0]] - df_data_array = np.array(json.loads(df_data)[0]) + epoch = len(df["Epoch"].values) + planes = max([int(name.split("_")[-3]) for name in images]) + 1 + row = max([int(name.split("_")[-2]) for name in images]) + 1 + col = max([int(name.split("_")[-1]) for name in images]) + 1 + # Reshape the dataframe data into a 4D numpy array + df_data = df[images].to_numpy().reshape(epoch, planes, row, col) + # Only check up to the expected number of planes in the decom data + df_data = df_data[:, : ULTRA_EXTOF_HIGH_ENERGY.image_planes, :, :] - np.testing.assert_array_equal(df_data_array, decom_data) + np.testing.assert_array_equal(df_data, decom_ultra["packetdata"]) diff --git a/imap_processing/tests/ultra/unit/test_decom_apid_888.py b/imap_processing/tests/ultra/unit/test_decom_apid_888.py index 099a2927d8..db9a9d6fad 100644 --- a/imap_processing/tests/ultra/unit/test_decom_apid_888.py +++ b/imap_processing/tests/ultra/unit/test_decom_apid_888.py @@ -1,5 +1,3 @@ -import json - import numpy as np import pandas as pd import pytest @@ -30,20 +28,36 @@ def test_extof_high_time_decom(decom_test_data, extof_high_time_test_path): decom_ultra = decom_test_data df = pd.read_csv(extof_high_time_test_path, index_col="SequenceCount") - np.testing.assert_array_equal(df.Spin, decom_ultra["spin"].values.flatten()) - np.testing.assert_array_equal( - df.AbortFlag, decom_ultra["abortflag"].values.flatten() - ) - np.testing.assert_array_equal( - df.StartDelay, decom_ultra["startdelay"].values.flatten() + # Check metadata values + # The validation csvs provided only includes the last packet's spin value, + # abortflag, and startdelay + np.testing.assert_array_equal(df.Spin, decom_ultra["spin"][:, -1]) + np.testing.assert_array_equal(df.AbortFlag, decom_ultra["abortflag"][:, -1]) + np.testing.assert_array_equal(df.StartDelay, decom_ultra["startdelay"][:, -1]) + + # Validation data from the IT team organizes image data into columns + # named UltraImage_Plane_Row_Col, where Plane, Row, and Col are 0-indexed. + # Each row corresponds to the epoch dimension. + colnames = df.columns.tolist() + + def column_name_sort(name): + return ( + int(name.split("_")[-3]), + int(name.split("_")[-2]), + int(name.split("_")[-1]), + ) + + images = sorted( + [name for name in colnames if "UltraImage" in name], key=column_name_sort ) - for count in df.index.get_level_values("SequenceCount").values: - df_data = df[ - df.index.get_level_values("SequenceCount") == count - ].UltraImage.values[0] - rows, cols = np.where(decom_ultra["src_seq_ctr"] == count) - decom_data = decom_ultra["packetdata"][rows[0]][cols[0]] - df_data_array = np.array(json.loads(df_data)[0]) + epoch = len(df["Epoch"].values) + planes = max([int(name.split("_")[-3]) for name in images]) + 1 + row = max([int(name.split("_")[-2]) for name in images]) + 1 + col = max([int(name.split("_")[-1]) for name in images]) + 1 + # Reshape the dataframe data into a 4D numpy array + df_data = df[images].to_numpy().reshape(epoch, planes, row, col) + # Only check up to the expected number of planes in the decom data + df_data = df_data[:, : ULTRA_EXTOF_HIGH_TIME.image_planes, :, :] - np.testing.assert_array_equal(df_data_array, decom_data) + np.testing.assert_array_equal(df_data, decom_ultra["packetdata"]) diff --git a/imap_processing/tests/ultra/unit/test_cullingmask.py b/imap_processing/tests/ultra/unit/test_goodtimes.py similarity index 71% rename from imap_processing/tests/ultra/unit/test_cullingmask.py rename to imap_processing/tests/ultra/unit/test_goodtimes.py index 8c840ca01b..6d63262aa3 100644 --- a/imap_processing/tests/ultra/unit/test_cullingmask.py +++ b/imap_processing/tests/ultra/unit/test_goodtimes.py @@ -2,11 +2,11 @@ import xarray as xr from imap_processing.quality_flags import ImapAttitudeUltraFlags, ImapRatesUltraFlags -from imap_processing.ultra.l1b.cullingmask import calculate_cullingmask +from imap_processing.ultra.l1b.goodtimes import calculate_goodtimes -def test_calculate_cullingmask_attitude(): - """Test calculate_cullingmask for attitude culling.""" +def test_calculate_goodtimes_attitude(): + """Test calculate_goodtimes for attitude culling.""" spin_numbers = np.array([0, 1]) energy_bins = np.array([10, 20, 30, 40]) @@ -22,11 +22,14 @@ def test_calculate_cullingmask_attitude(): ImapRatesUltraFlags.NONE.value, dtype=np.uint16, ) - + quality_low_voltage = np.full_like( + quality_attitude, ImapAttitudeUltraFlags.NONE.value + ) ds = xr.Dataset( { "epoch": (("spin_number",), np.array([0, 1], dtype="datetime64[ns]")), "quality_attitude": (("spin_number",), quality_attitude), + "quality_low_voltage": (("spin_number",), quality_low_voltage), "quality_ena_rates": ( ("energy_bin_geometric_mean", "spin_number"), quality_ena_rates, @@ -39,13 +42,15 @@ def test_calculate_cullingmask_attitude(): }, ) - result_ds = calculate_cullingmask(ds, name="imap_ultra_l1b_45sensor-cullingmask") + result_ds = calculate_goodtimes(ds, name="imap_ultra_l1b_45sensor-goodtimes") + for var in ["quality_attitude", "quality_low_voltage", "quality_ena_rates"]: + assert var in result_ds np.testing.assert_array_equal(result_ds["spin_number"].values, np.array([0, 1])) -def test_calculate_cullingmask_rates(): - """Test calculate_cullingmask for rates culling.""" +def test_calculate_goodtimes_rates(): + """Test calculate_goodtimes for rates culling.""" spin_numbers = np.array([0, 1, 2, 3]) energy_bins = np.array([10, 20, 30, 40]) spin_start_time = np.array([0, 1, 2, 3]) @@ -79,14 +84,14 @@ def test_calculate_cullingmask_rates(): }, ) - result_ds = calculate_cullingmask(ds, name="imap_ultra_l1b_45sensor-cullingmask") + result_ds = calculate_goodtimes(ds, name="imap_ultra_l1b_45sensor-goodtimes") expected_spins = np.array([1, 2]) np.testing.assert_array_equal(result_ds["spin_number"].values, expected_spins) -def test_calculate_cullingmask_empty(): - """Test calculate_cullingmask when all spins are culled (empty case).""" +def test_calculate_goodtimes_empty(): + """Test calculate_goodtimes when all spins are culled (empty case).""" spin_numbers = np.array([0, 1, 2]) energy_bins = np.array([10, 20, 30]) @@ -118,15 +123,15 @@ def test_calculate_cullingmask_empty(): }, ) - cullingmask_ds = calculate_cullingmask( + goodtimes_ds = calculate_goodtimes( ds, - name="imap_ultra_l1b_45sensor-cullingmask", + name="imap_ultra_l1b_45sensor-goodtimes", ) - assert cullingmask_ds["spin_number"].values[0] == 4294967295 - assert cullingmask_ds["spin_start_time"].values[0] == -1.0e31 - assert cullingmask_ds["spin_period"].values[0] == -1.0e31 - assert cullingmask_ds["spin_rate"].values[0] == -1.0e31 - assert cullingmask_ds["quality_attitude"].values[0] == 65535 - assert np.all(cullingmask_ds["ena_rates"].values == -1.0e31) - assert np.all(cullingmask_ds["quality_ena_rates"].values == 65535) + assert goodtimes_ds["spin_number"].values[0] == 4294967295 + assert goodtimes_ds["spin_start_time"].values[0] == -1.0e31 + assert goodtimes_ds["spin_period"].values[0] == -1.0e31 + assert goodtimes_ds["spin_rate"].values[0] == -1.0e31 + assert goodtimes_ds["quality_attitude"].values[0] == 65535 + assert np.all(goodtimes_ds["ena_rates"].values == -1.0e31) + assert np.all(goodtimes_ds["quality_ena_rates"].values == 65535) diff --git a/imap_processing/tests/ultra/unit/test_helio_pset.py b/imap_processing/tests/ultra/unit/test_helio_pset.py new file mode 100644 index 0000000000..6a4390cc29 --- /dev/null +++ b/imap_processing/tests/ultra/unit/test_helio_pset.py @@ -0,0 +1,118 @@ +from unittest import mock + +import numpy as np +import pandas as pd +import pytest +import xarray as xr + +from imap_processing import imap_module_directory +from imap_processing.cdf.utils import load_cdf +from imap_processing.tests.conftest import _download_external_data +from imap_processing.ultra.constants import UltraConstants +from imap_processing.ultra.l1c.helio_pset import calculate_helio_pset + +TEST_PATH = imap_module_directory / "tests" / "ultra" / "data" / "l1" + + +@pytest.mark.skip(reason="Long running test for validation purposes.") +def test_validate_exposure_time_and_sensitivities( + ancillary_files, rates_dataset, imap_ena_sim_metakernel, aux_dataset +): + """Validates exposure time and sensitivities for ebin 0.""" + sens_filename = "SENS-IMAP_ULTRA_90-IMAP_DPS-HELIO-nside32-ebin0.csv" + exposure_filename = "Exposures-IMAP_ULTRA_90-IMAP_DPS-HELIO-nside32-ebin0.csv" + de_filename = "imap_ultra_l1b_90sensor-de_20000101-repoint00000_v000.cdf" + test_data = [ + (sens_filename, "ultra/data/l1/"), + (exposure_filename, "ultra/data/l1/"), + (de_filename, "ultra/data/l1/"), + ] + _download_external_data(test_data) + l1b_de = TEST_PATH / de_filename + l1b_de = load_cdf(l1b_de) + sensitivities_ebin_0 = pd.read_csv(TEST_PATH / sens_filename) + exposure_factor_ebin_0 = pd.read_csv(TEST_PATH / exposure_filename) + + test_deadtimes = ( + pd.read_csv(TEST_PATH / "test_p0_ebin0_deadtimes.csv", header=None) + .to_numpy() + .squeeze() + ) + npix = 12288 # nside 32 + # Create a minimal dataset to pass to the function + dataset = xr.Dataset( + { + "spin_number": (["epoch"], np.array([1, 2, 3])), + } + ) + dataset.attrs["Repointing"] = "repoint00000" + + pointing_range_met = (472374890.0, 582378000.0) + # Create mock spin data that has 5525 nominal spins + # Create DataFrame + nspins = 5522 + nominal_spin_seconds = 15.0 + spin_data = pd.DataFrame( + { + "spin_start_met": np.linspace( + pointing_range_met[0], pointing_range_met[1], nspins + ), + "spin_period_sec": np.full(nspins, nominal_spin_seconds), + "spin_phase_valid": np.ones(nspins), + "spin_period_valid": np.ones(nspins), + } + ) + with ( + # Mock the pointing times + mock.patch( + "imap_processing.ultra.l1c.helio_pset.get_pointing_times_from_id", + return_value=pointing_range_met, + ), + # Mock deadtimes to be all ones + mock.patch( + "imap_processing.ultra.l1c.ultra_l1c_pset_bins." + "get_deadtime_ratios_by_spin_phase", + return_value=xr.DataArray(test_deadtimes, dims="spin_phase_step"), + ), + # Mock spin data to match nominal spins in a pointing period + mock.patch( + "imap_processing.ultra.l1c.ultra_l1c_pset_bins.get_spin_data", + return_value=spin_data, + ), + # Mock background rates to be constant 0.1 + mock.patch( + "imap_processing.ultra.l1c.helio_pset.get_spacecraft_background_rates", + return_value=np.ones((46, npix)), + ), + # Mock culling mask (no culling) + mock.patch("imap_processing.ultra.l1c.helio_pset.compute_culling_mask"), + ): + pset = calculate_helio_pset( + l1b_de, + dataset, + rates_dataset, + aux_dataset, + "imap_ultra_l1c_90sensor-heliopset", + ancillary_files, + 90, + UltraConstants.TOFXPH_SPECIES_GROUPS["proton"], + ) + + # Validate exposure times for ebin 0 + exposure_times = pset["exposure_factor"][0, 0, :].values + expected_exposure_times = exposure_factor_ebin_0["P0"].to_numpy() + np.testing.assert_allclose( + exposure_times, + expected_exposure_times, + atol=95, # TODO This is due to the helio index map differences + err_msg="Exposure times do not match expected values for ebin 0.", + ) + # Validate sensitivities for ebin 0 + sensitivity = pset["sensitivity"][0, :].values + expected_sensitivity = sensitivities_ebin_0["Sensitivity (cm2)"].to_numpy() + np.testing.assert_allclose( + sensitivity, + expected_sensitivity, + atol=0.0006, # TODO This is due to the helio index map differences + err_msg="Sensitivities times do not match expected values for ebin 0.", + ) diff --git a/imap_processing/tests/ultra/unit/test_l1c_lookup_utils.py b/imap_processing/tests/ultra/unit/test_l1c_lookup_utils.py index f1cb26deeb..d2149d4ea2 100644 --- a/imap_processing/tests/ultra/unit/test_l1c_lookup_utils.py +++ b/imap_processing/tests/ultra/unit/test_l1c_lookup_utils.py @@ -1,10 +1,14 @@ import astropy_healpix.healpy as hp import numpy as np import pytest +import xarray as xr from imap_processing.ultra.l1c.l1c_lookup_utils import ( + calculate_accepted_pixels, get_scattering_thresholds_for_energy, get_spacecraft_pointing_lookup_tables, + get_static_deadtime_ratios, + in_restricted_fov, mask_below_fwhm_scattering_threshold, ) @@ -24,10 +28,11 @@ def test_get_spacecraft_pointing_lookup_tables(ancillary_files): # Test shapes # There should be 498 spin phase steps. In the real test files there will be 15000 cols = 498 - assert for_indices_by_spin_phase.shape == (npix, cols) - assert theta_vals.shape == (npix, cols) - assert phi_vals.shape == (npix, cols) - assert ra_and_dec.shape == (npix, 2) + assert for_indices_by_spin_phase.shape == (cols, npix) + assert theta_vals.shape == (cols, npix) + assert phi_vals.shape == (cols, npix) + assert ra_and_dec.shape == (2, npix) + assert boundary_scale_factors.shape == (cols, npix) # Value tests assert for_indices_by_spin_phase.dtype == bool @@ -59,7 +64,7 @@ def test_get_mask_below_fwhm_scattering_threshold(ancillary_files): # Only indices where both the theta and phi coefficients are below the FWHM # threshold should be True. expected_pixel_mask = np.array([[False], [True], [False]]) - pixel_mask = mask_below_fwhm_scattering_threshold( + pixel_mask, scat_theta, scat_phi = mask_below_fwhm_scattering_threshold( theta_coeffs, phi_coeffs, energy[np.newaxis, :], thresholds ) np.testing.assert_array_equal(pixel_mask.shape, (3, 1)) @@ -87,8 +92,113 @@ def test_get_mask_below_fwhm_scattering_threshold_zero(ancillary_files): ) # Since energy is zero, all should be False although some pixels are below threshold expected_pixel_mask = np.array([[False], [False], [False]]) - pixel_mask = mask_below_fwhm_scattering_threshold( + pixel_mask, scat_theta, scat_phi = mask_below_fwhm_scattering_threshold( theta_coeffs, phi_coeffs, energy, thresholds ) np.testing.assert_array_equal(pixel_mask.shape, (3, 1)) np.testing.assert_array_equal(pixel_mask, expected_pixel_mask) + + +@pytest.mark.external_test_data +def test_get_static_deadtime_ratios(ancillary_files): + """Test get_static_deadtime_ratios function.""" + # test 45 + spin_phase, dt_ratio = get_static_deadtime_ratios(45, ancillary_files) + # Test shape + # TODO confirm if the duplicate row in the 45 LUT is a mistake + np.testing.assert_array_equal(dt_ratio.shape, (720,)) + # Test values + assert np.all((dt_ratio >= 0.0) & (dt_ratio <= 1.0)) + # test 90 + spin_phase, dt_ratio = get_static_deadtime_ratios(90, ancillary_files) + # Test shape + np.testing.assert_array_equal(dt_ratio.shape, (721,)) + # Test the values + assert np.all((dt_ratio >= 0.0) & (dt_ratio <= 1.0)) + + +def test_in_restricted_fov(): + """Test in_restricted_fov function.""" + # Create mock theta and phi values + # First two values are outside the restricted FOV, the rest are inside + theta_vals = np.array([[-50, 49, 10, 40, 35]]) + # The last value is outside the restricted FOV + phi_vals = np.array([[20, 30, 40, 50, 70]]) # shape (1, 5) + accepted_pixels = in_restricted_fov(theta_vals, phi_vals, 45) + expected_accepted_pixels = np.array([[False, False, True, True, False]]) + np.testing.assert_array_equal(accepted_pixels, expected_accepted_pixels) + + +def test_calculate_accepted_pixels(ancillary_files): + """Test calculate_accepted_pixels function.""" + # Make array with ones (we are only testing the shape here) + for_pixels = np.ones((50, 10)) + theta_vals = np.ones((50, 10)) * 20 # All theta values are 20 + phi_vals = np.ones((50, 5)) * 15 # All phi + with pytest.raises(ValueError, match="Shape mismatch"): + calculate_accepted_pixels(for_pixels, theta_vals, phi_vals, ancillary_files, 45) + + +@pytest.mark.external_test_data +def test_calculate_accepted_pixels_reject(ancillary_files): + """Test calculate_accepted_pixels function.""" + nside = 8 + pix = hp.nside2npix(nside) + steps = 5 # Reduced for testing + energy_dim = 46 + np.random.seed(42) + mock_theta = np.random.uniform(-60, 60, (steps, energy_dim, pix)) + mock_phi = np.random.uniform(-60, 60, (steps, energy_dim, pix)) + for_pixels = xr.DataArray( + np.zeros((steps, energy_dim, pix)).astype(bool), + dims=("spin_phase_step", "energy", "pixel"), + ) + # Simulate first 100 pixels are in the FOR for all spin phases + inside_inds = 100 + for_pixels[:, :, :inside_inds] = True + valid_spun_pixels, fwhm_theta, fwhm_phi, thresholds = calculate_accepted_pixels( + for_pixels, + mock_theta, + mock_phi, + ancillary_files, + 45, + reject_scattering=True, + ) + assert valid_spun_pixels.shape == (steps, energy_dim, pix) + # Check that some pixels are rejected + assert not np.array_equal(valid_spun_pixels, for_pixels) + + +@pytest.mark.external_test_data +def test_calculate_accepted_pixels_restrict_fov(ancillary_files): + """Test calculate_accepted_pixels function for FOV restrictions.""" + nside = 8 + pix = hp.nside2npix(nside) + steps = 5 # Reduced for testing + energy_dim = 46 + np.random.seed(42) + mock_theta = np.random.uniform(-60, 60, (steps, energy_dim, pix)) + mock_phi = np.random.uniform(-60, 60, (steps, energy_dim, pix)) + # Create for_pixels with all True values to isolate the effect of FOV restrictions + for_pixels = xr.DataArray( + np.ones((steps, energy_dim, pix)).astype(bool), + dims=("spin_phase_step", "energy", "pixel"), + ) + # Set first 30 pixels to be outside of the FOR for all spin phases and energies + outside_inds = 30 + for_pixels[:, :, :outside_inds] = False + valid_spun_pixels, fwhm_theta, fwhm_phi, thresholds = calculate_accepted_pixels( + for_pixels, + mock_theta, + mock_phi, + ancillary_files, + 45, + apply_fov_restriction=True, + ) + assert valid_spun_pixels.shape == (steps, energy_dim, pix) + # In this case, the valid spun pixels should be the same as the pixels that are + # in the restricted FOV except the first 30 pixels which are outside the FOR and + # should be False for all spin phases and energies. + expected_accepted_px = in_restricted_fov(mock_theta, mock_phi, 45) + expected_accepted_px[:, :, :outside_inds] = False + assert np.array_equal(expected_accepted_px, valid_spun_pixels) diff --git a/imap_processing/tests/ultra/unit/test_lookup_utils.py b/imap_processing/tests/ultra/unit/test_lookup_utils.py index fabe3a8804..fe82d26668 100644 --- a/imap_processing/tests/ultra/unit/test_lookup_utils.py +++ b/imap_processing/tests/ultra/unit/test_lookup_utils.py @@ -9,6 +9,7 @@ from imap_processing.ultra.l1b.lookup_utils import ( get_angular_profiles, get_back_position, + get_de_product_name, get_ebins, get_energy_efficiencies, get_energy_norm, @@ -113,10 +114,14 @@ def test_get_angular_profiles(): def test_get_energy_efficiencies(ancillary_files): """Tests function get_get_energy_efficiencies.""" - u45_efficiencies = get_energy_efficiencies(ancillary_files) + u45_efficiencies = get_energy_efficiencies(ancillary_files, "ultra45") assert u45_efficiencies.shape == (58081, 157) + # Test that the function can also read the ultra90 efficiencies + u90_efficiencies = get_energy_efficiencies(ancillary_files, "ultra90") + assert u90_efficiencies.shape == (58081, 157) + @pytest.mark.external_test_data def test_get_geometric_function(ancillary_files): @@ -211,3 +216,80 @@ def test_get_scattering_thresholds(ancillary_files): assert thresholds[(8.0, 10.0)] == 8.0 assert thresholds[(10.0, 20.0)] == 6.0 assert thresholds[(20.0, np.inf)] == 4.0 + + +def test_get_de_product_name_no_repoint(): + """Tests function get_de_product_name when the lookup is missing the repoint.""" + ancillary_files = { + "l1b-45sensor-de-product-lookup": TEST_PATH + / "imap_ultra_l1b-45sensor-de-product-lookup_20251001_v001.csv" + } + with mock.patch( + "imap_processing.ultra.l1b.lookup_utils.pd.read_csv" + ) as mock_read_csv: + mock_read_csv.return_value = pd.DataFrame( + { + "repointing_id_start": [1, 2], + "repointing_id_end": [3, 4], + "de_product": [ + "imap_ultra_l1b_45sensor-de", + "imap_ultra_l1b_45sensor-priority-1-de", + ], + } + ) + with pytest.raises(ValueError, match="No DE product found for repoint ID 0"): + get_de_product_name("repoint00000", 45, "l1b", ancillary_files) + + +def test_get_de_product_name_multiple_products(): + """Tests function get_de_product_name when the lookup is ambiguous.""" + ancillary_files = { + "l1b-45sensor-de-product-lookup": TEST_PATH + / "imap_ultra_l1b-45sensor-de-product-lookup_20251001_v001.csv" + } + with mock.patch( + "imap_processing.ultra.l1b.lookup_utils.pd.read_csv" + ) as mock_read_csv: + mock_read_csv.return_value = pd.DataFrame( + { + "repointing_id_start": [2, 2], + "repointing_id_end": [3, 4], + "de_product": [ + "imap_ultra_l1b_45sensor-de", + "imap_ultra_l1b_45sensor-priority-1-de", + ], + } + ) + with pytest.raises(ValueError, match="Multiple DE products found"): + get_de_product_name("repoint00002", 45, "l1b", ancillary_files) + + +def test_get_de_product_name(): + """Tests function get_de_product_name.""" + ancillary_files = { + "l1b-45sensor-de-product-lookup": TEST_PATH + / "imap_ultra_l1b-45sensor-de-product-lookup_20251001_v001.csv" + } + with mock.patch( + "imap_processing.ultra.l1b.lookup_utils.pd.read_csv" + ) as mock_read_csv: + mock_read_csv.return_value = pd.DataFrame( + { + "repointing_id_start": [0, 2, 4], + "repointing_id_end": [1, 4, np.nan], + "de_product": [ + "imap_ultra_l1b_45sensor-de", + "imap_ultra_l1b_45sensor-priority-1-de", + "imap_ultra_l1b_45sensor-priority-2-de", + ], + } + ) + # Test with a repoint in the future. Should return the priority 2 de product + # since the last repoint range does not have an end and should be assumed to + # cover all future repoints. + de_product = get_de_product_name("repoint00100", 45, "l1b", ancillary_files) + assert de_product == "imap_ultra_l1b_45sensor-priority-2-de" + + # Test with valid repoint that falls in the second range. + de_product = get_de_product_name("repoint00003", 45, "l1b", ancillary_files) + assert de_product == "imap_ultra_l1b_45sensor-priority-1-de" diff --git a/imap_processing/tests/ultra/unit/test_make_helio_index_maps.py b/imap_processing/tests/ultra/unit/test_make_helio_index_maps.py new file mode 100644 index 0000000000..936a1ac44e --- /dev/null +++ b/imap_processing/tests/ultra/unit/test_make_helio_index_maps.py @@ -0,0 +1,185 @@ +import numpy as np +import pandas as pd +import pytest +import spiceypy as sp + +from imap_processing import imap_module_directory +from imap_processing.spice.geometry import SpiceFrame +from imap_processing.tests.conftest import _download_external_data +from imap_processing.ultra.l1c.make_helio_index_maps import make_helio_index_maps + +TEST_PATH = imap_module_directory / "tests" / "ultra" / "data" / "l1" + + +@pytest.fixture +def helio_index_kernels(furnish_kernels, _download_kernels): + kernels = [ + "imap_sclk_0000.tsc", + "naif0012.tls", + "imap_spk_demo.bsp", + "sim_1yr_imap_attitude.bc", + "imap_001.tf", + "de440s.bsp", + "imap_science_120.tf", + "sim_1yr_imap_pointing_frame.bc", + ] + with furnish_kernels(kernels) as k: + yield k + + +@pytest.mark.skip(reason="Long running test for validation purposes.") +def test_make_helio_index_maps( + helio_index_kernels, use_fake_repoint_data_for_time, spice_test_data_path +): + """Test make_helio_index_maps.""" + # Get coverage window + ck_kernel, _, _, _ = sp.kdata(1, "ck") + ck_cover = sp.ckcov( + ck_kernel, SpiceFrame.IMAP_DPS.value, True, "INTERVAL", 0, "TDB" + ) + et_start, et_end = sp.wnfetd(ck_cover, 0) + + ds = make_helio_index_maps( + nside=32, + spin_duration=15.0, + start_et=et_start, + num_steps=720, + instrument_frame=SpiceFrame.IMAP_ULTRA_90, + compute_bsf=False, + ) + index_file = "IMAP_ULTRA_90-HELIO-IMAP_DPS-nside32-steps720-ebin0-index.csv" + theta_file = "IMAP_ULTRA_90-HELIO-IMAP_DPS-nside32-steps720-ebin0-theta.csv" + phi_file = "IMAP_ULTRA_90-HELIO-IMAP_DPS-nside32-steps720-ebin0-phi.csv" + test_data = [ + (index_file, "ultra/data/l1/"), + (theta_file, "ultra/data/l1/"), + (phi_file, "ultra/data/l1/"), + ] + _download_external_data(test_data) + # Load expected data + expected_index = pd.read_csv( + TEST_PATH / index_file, + header=None, + skiprows=1, + ).to_numpy() + expected_theta = pd.read_csv( + TEST_PATH / theta_file, + header=None, + skiprows=1, + ).to_numpy() + expected_phi = pd.read_csv( + TEST_PATH / phi_file, + header=None, + skiprows=1, + ).to_numpy() + + # Skip ra and dec cols + expected_index_all_steps = expected_index[:, 2:] + expected_theta_all_steps = expected_theta[:, 2:] + expected_phi_all_steps = expected_phi[:, 2:] + + # Replace nans with zero + expected_index_all_steps = np.nan_to_num(expected_index_all_steps, nan=0) + + # Get outputs + index_all_steps = ds.index[:, 0, :].values.T + theta_all_steps = ds.theta[:, 0, :].values.T + phi_all_steps = ds.phi[:, 0, :].values.T + + # Test index mismatch percentage + mismatch_count = np.sum(index_all_steps != expected_index_all_steps) + mismatch_pct = 100 * mismatch_count / index_all_steps.size + assert mismatch_pct < 0.02 + + both_valid_mask = (expected_index_all_steps != 0) & (index_all_steps != 0) + + np.testing.assert_allclose( + theta_all_steps[both_valid_mask], + expected_theta_all_steps[both_valid_mask], + rtol=1e-4, + ) + + np.testing.assert_allclose( + phi_all_steps[both_valid_mask], + expected_phi_all_steps[both_valid_mask], + rtol=1e-4, + atol=0.05, + ) + + +@pytest.mark.skip(reason="Long running test for validation purposes.") +def test_make_helio_index_maps_45(helio_index_kernels, use_fake_repoint_data_for_time): + """Test make_helio_index_maps.""" + ck_kernel, _, _, _ = sp.kdata(1, "ck") + ck_cover = sp.ckcov( + ck_kernel, SpiceFrame.IMAP_DPS.value, True, "INTERVAL", 0, "TDB" + ) + et_start, et_end = sp.wnfetd(ck_cover, 0) + ds = make_helio_index_maps( + nside=32, + spin_duration=15.0, + start_et=et_start, + num_steps=720, + instrument_frame=SpiceFrame.IMAP_ULTRA_45, + compute_bsf=False, + ) + + index_file = "IMAP_ULTRA_45-HELIO-IMAP_DPS-nside32-steps720-ebin0-index.csv" + theta_file = "IMAP_ULTRA_45-HELIO-IMAP_DPS-nside32-steps720-ebin0-theta.csv" + phi_file = "IMAP_ULTRA_45-HELIO-IMAP_DPS-nside32-steps720-ebin0-phi.csv" + test_data = [ + (index_file, "ultra/data/l1/"), + (theta_file, "ultra/data/l1/"), + (phi_file, "ultra/data/l1/"), + ] + _download_external_data(test_data) + # Load expected data + expected_index = pd.read_csv( + TEST_PATH / index_file, + header=None, + skiprows=1, + ).to_numpy() + expected_theta = pd.read_csv( + TEST_PATH / theta_file, + header=None, + skiprows=1, + ).to_numpy() + expected_phi = pd.read_csv( + TEST_PATH / phi_file, + header=None, + skiprows=1, + ).to_numpy() + + # Skip ra and dec cols + expected_index_all_steps = expected_index[:, 2:] + expected_theta_all_steps = expected_theta[:, 2:] + expected_phi_all_steps = expected_phi[:, 2:] + + # Replace nans with zero + expected_index_all_steps = np.nan_to_num(expected_index_all_steps, nan=0) + + # Get outputs + index_all_steps = ds.index[:, 0, :].values.T + theta_all_steps = ds.theta[:, 0, :].values.T + phi_all_steps = ds.phi[:, 0, :].values.T + + # Test index mismatch percentage + mismatch_count = np.sum(index_all_steps != expected_index_all_steps) + mismatch_pct = 100 * mismatch_count / index_all_steps.size + assert mismatch_pct < 0.02 + + both_valid_mask = (expected_index_all_steps != 0) & (index_all_steps != 0) + + np.testing.assert_allclose( + theta_all_steps[both_valid_mask], + expected_theta_all_steps[both_valid_mask], + rtol=1e-4, + atol=0.05, + ) + + np.testing.assert_allclose( + phi_all_steps[both_valid_mask], + expected_phi_all_steps[both_valid_mask], + rtol=1e-4, + atol=0.05, + ) diff --git a/imap_processing/tests/ultra/unit/test_spacecraft_pset.py b/imap_processing/tests/ultra/unit/test_spacecraft_pset.py index 6656e6022f..381e357b28 100644 --- a/imap_processing/tests/ultra/unit/test_spacecraft_pset.py +++ b/imap_processing/tests/ultra/unit/test_spacecraft_pset.py @@ -1,5 +1,7 @@ """Tests Spacecraft PSET for ULTRA L1c.""" +from unittest import mock + import numpy as np import pandas as pd import pytest @@ -7,7 +9,11 @@ import xarray as xr from imap_processing import imap_module_directory +from imap_processing.cdf.utils import load_cdf from imap_processing.spice.geometry import SpiceFrame +from imap_processing.spice.time import met_to_sclkticks, sct_to_et +from imap_processing.tests.conftest import _download_external_data +from imap_processing.ultra.constants import UltraConstants from imap_processing.ultra.l1b.ultra_l1b_annotated import ( get_annotated_particle_velocity, ) @@ -25,8 +31,9 @@ @pytest.mark.external_test_data @pytest.mark.external_kernel def test_calculate_spacecraft_pset( - random_spin_data, - deadtime_datasets, + aux_dataset, + rates_dataset, + mock_goodtimes_dataset, imap_ena_sim_metakernel, use_fake_spin_data_for_time, ancillary_files, @@ -35,7 +42,11 @@ def test_calculate_spacecraft_pset( """Tests calculate_spacecraft_pset function.""" # Simulate a spin table from MET = 0 to MET = 141 * 15 seconds use_fake_spin_data_for_time(start_met=0, end_met=141 * 15) - + # Ensure rate and aux data have the correct time range + t_rates = np.linspace(0, 141 * 15, len(rates_dataset.shcoarse.data)) + rates_dataset.shcoarse.data = t_rates + aux_dataset.timespinstart.data = t_rates[: len(aux_dataset.timespinstart.data)] + aux_dataset.timespinstart.data[-1] = t_rates[-1] # This is just setting up the data so that it is in the format of l1b_de_dataset. test_path = TEST_PATH / "ultra-90_raw_event_data_shortened.csv" df = pd.read_csv(test_path) @@ -63,12 +74,15 @@ def test_calculate_spacecraft_pset( test_l1b_de_dataset = xr.Dataset( { "species": (["epoch"], species), + "ebin": (["epoch"], np.ones(len(species), dtype=np.uint8)), "velocity_dps_sc": ( ["epoch", "component"], particle_velocity_dps_spacecraft, ), + "theta": (["epoch"], np.zeros(len(species), dtype=np.float32)), + "phi": (["epoch"], np.zeros(len(species), dtype=np.float32)), "energy_spacecraft": (["epoch"], energy_dps_spacecraft), - "spin_number": (["epoch"], df["Spin"].values), + "spin": (["epoch"], df["Spin"].values), "quality_scattering": ( ["epoch"], np.zeros(len(df["Spin"].values), dtype=np.uint16), @@ -77,23 +91,28 @@ def test_calculate_spacecraft_pset( ["epoch"], np.zeros(len(df["Spin"].values), dtype=np.uint16), ), + "event_times": sct_to_et(met_to_sclkticks(df["MET"].values)), }, coords={ "epoch": ("epoch", epoch), "component": ("component", ["vx", "vy", "vz"]), }, + attrs={"Repointing": "repoint00001"}, ) - - spacecraft_pset = calculate_spacecraft_pset( - test_l1b_de_dataset, - test_l1b_de_dataset, # placeholder for extendedspin_dataset - test_l1b_de_dataset, # placeholder for cullingmask_dataset - deadtime_datasets["rates"], - deadtime_datasets["params"], - "imap_ultra_l1c_45sensor-spacecraftpset", - ancillary_files, - 45, - ) + with mock.patch( + "imap_processing.ultra.l1c.spacecraft_pset.get_pointing_times_from_id", + return_value=(482374890.0, 482374000.0), + ): + spacecraft_pset = calculate_spacecraft_pset( + test_l1b_de_dataset, + mock_goodtimes_dataset, + rates_dataset, + aux_dataset, + "imap_ultra_l1c_45sensor-spacecraftpset", + ancillary_files, + 45, + UltraConstants.TOFXPH_SPECIES_GROUPS["proton"], + ) assert "pixel_index" in spacecraft_pset.coords assert "epoch" in spacecraft_pset.coords assert "energy_bin_geometric_mean" in spacecraft_pset.coords @@ -102,9 +121,10 @@ def test_calculate_spacecraft_pset( @pytest.mark.external_test_data @pytest.mark.external_kernel def test_calculate_spacecraft_pset_with_cdf( - random_spin_data, ancillary_files, - deadtime_datasets, + aux_dataset, + rates_dataset, + mock_goodtimes_dataset, imap_ena_sim_metakernel, use_fake_spin_data_for_time, mock_spacecraft_pointing_lookups, @@ -122,7 +142,11 @@ def test_calculate_spacecraft_pset_with_cdf( de_dict["epoch"] = df_subset["epoch"].values species_bin = np.full(len(df_subset), 1, dtype=np.uint8) - + # Ensure rate and aux data have the correct time range + t_rates = np.linspace(0, 141 * 15, len(rates_dataset.shcoarse.data)) + rates_dataset.shcoarse.data = t_rates + aux_dataset.timespinstart.data = t_rates[: len(aux_dataset.timespinstart.data)] + aux_dataset.timespinstart.data[-1] = t_rates[-1] # PosYSlit is True for left (start_type = 1) # PosYSlit is False for right (start_type = 2) start_type = np.where(df_subset["PosYSlit"].values, 1, 2) @@ -151,27 +175,164 @@ def test_calculate_spacecraft_pset_with_cdf( de_dict["velocity_dps_sc"] = sc_dps_velocity de_dict["energy_spacecraft"] = get_de_energy_kev(sc_dps_velocity, species_bin) # Made up data for spin_number and energy_bin_geometric_mean - de_dict["spin_number"] = np.full(len(sc_dps_velocity), 128) - de_dict["energy_bin_geometric_mean"] = np.zeros(len(sc_dps_velocity)) + de_dict["spin"] = np.full(len(sc_dps_velocity), 0) de_dict["quality_scattering"] = np.zeros(len(sc_dps_velocity), dtype=np.uint16) de_dict["quality_outliers"] = np.zeros(len(sc_dps_velocity), dtype=np.uint16) - de_dict["species"] = np.ones(len(sc_dps_velocity), dtype=np.uint8) + de_dict["ebin"] = np.ones(len(sc_dps_velocity), dtype=np.uint8) + de_dict["theta"] = np.zeros(len(df_subset), dtype=np.float32) + de_dict["phi"] = np.zeros(len(df_subset), dtype=np.float32) + de_dict["event_times"] = 817561854.185627 + ( + df_subset["tdb"].values - df_subset["tdb"].values[0] + ) + de_dict["theta"] = np.zeros(len(df_subset), dtype=np.float32) + de_dict["phi"] = np.zeros(len(df_subset), dtype=np.float32) name = "imap_ultra_l1b_45sensor-de" dataset = create_dataset(de_dict, name, "l1b") - - spacecraft_pset = calculate_spacecraft_pset( - dataset, - dataset, # placeholder for extendedspin_dataset - dataset, # placeholder for cullingmask_dataset - deadtime_datasets["rates"], - deadtime_datasets["params"], - "imap_ultra_l1c_45sensor-spacecraftpset", - ancillary_files, - 45, - ) + dataset.attrs["Repointing"] = "repoint00000" + with mock.patch( + "imap_processing.ultra.l1c.spacecraft_pset.get_pointing_times_from_id", + return_value=(472374890.0, 582378000.0), + ): + spacecraft_pset = calculate_spacecraft_pset( + dataset, + mock_goodtimes_dataset, + rates_dataset, + aux_dataset, + "imap_ultra_l1c_45sensor-spacecraftpset", + ancillary_files, + 45, + UltraConstants.TOFXPH_SPECIES_GROUPS["proton"], + ) # TODO: validate with output histogram data once we have it in healpix. assert ( spacecraft_pset.attrs["Logical_source"] == "imap_ultra_l1c_45sensor-spacecraftpset" ) + + +@pytest.mark.skip(reason="Long running test for validation purposes.") +def test_validate_exposure_time_and_sensitivities( + ancillary_files, rates_dataset, aux_dataset +): + """Validates exposure time and sensitivities for ebin 0.""" + test_data = [ + ( + "imap_ultra_l1c-90sensor-sc-pointing-theta_20250101_v001.csv", + "ultra/data/l1/", + ), + ("imap_ultra_l1c-90sensor-sc-pointing-phi_20250101_v001.csv", "ultra/data/l1/"), + ( + "imap_ultra_l1c-90sensor-sc-pointing-index_20250101_v001.csv", + "ultra/data/l1/", + ), + ("imap_ultra_l1c-90sensor-sc-pointing-bsf_20250101_v001.csv", "ultra/data/l1/"), + ("Exposures-IMAP_ULTRA_90-IMAP_DPS-SC-nside32-ebin0.csv", "ultra/data/l1/"), + ("SENS-IMAP_ULTRA_90-IMAP_DPS-SC-nside32-ebin0.csv", "ultra/data/l1/"), + ("imap_ultra_l1b_45sensor-de_20000101-repoint00000_v000.cdf", "ultra/data/l1/"), + ] + _download_external_data(test_data) + l1b_de = TEST_PATH / "imap_ultra_l1b_45sensor-de_20000101-repoint00000_v000.cdf" + l1b_de = load_cdf(l1b_de) + sensitivities_ebin_0 = pd.read_csv( + TEST_PATH / "SENS-IMAP_ULTRA_90-IMAP_DPS-SC-nside32-ebin0.csv" + ) + exposure_factor_ebin_0 = pd.read_csv( + TEST_PATH / "Exposures-IMAP_ULTRA_90-IMAP_DPS-SC-nside32-ebin0.csv" + ) + test_deadtimes = ( + pd.read_csv(TEST_PATH / "test_p0_ebin0_deadtimes.csv", header=None) + .to_numpy() + .squeeze() + ) + npix = 12288 # nside 32 + # Create a minimal dataset to pass to the function + dataset = xr.Dataset( + { + "spin": (["epoch"], np.array([1, 2, 3])), + } + ) + dataset.attrs["Repointing"] = "repoint00000" + + ancillary_files["l1c-90sensor-sc-pointing-theta"] = ( + TEST_PATH / "imap_ultra_l1c-90sensor-sc-pointing-theta_20250101_v001.csv" + ) + ancillary_files["l1c-90sensor-sc-pointing-phi"] = ( + TEST_PATH / "imap_ultra_l1c-90sensor-sc-pointing-phi_20250101_v001.csv" + ) + ancillary_files["l1c-90sensor-sc-pointing-index"] = ( + TEST_PATH / "imap_ultra_l1c-90sensor-sc-pointing-index_20250101_v001.csv" + ) + ancillary_files["l1c-90sensor-sc-pointing-bsf"] = ( + TEST_PATH / "imap_ultra_l1c-90sensor-sc-pointing-bsf_20250101_v001.csv" + ) + + pointing_range_met = (472374890.0, 582378000.0) + # Create mock spin data that has 5525 nominal spins + # Create DataFrame + nspins = 5522 + nominal_spin_seconds = 15.0 + spin_data = pd.DataFrame( + { + "spin_start_met": np.linspace( + pointing_range_met[0], pointing_range_met[1], nspins + ), + "spin_period_sec": np.full(nspins, nominal_spin_seconds), + "spin_phase_valid": np.ones(nspins), + "spin_period_valid": np.ones(nspins), + } + ) + with ( + # Mock the pointing times + mock.patch( + "imap_processing.ultra.l1c.spacecraft_pset.get_pointing_times_from_id", + return_value=pointing_range_met, + ), + # Mock deadtimes to be all ones + mock.patch( + "imap_processing.ultra.l1c.ultra_l1c_pset_bins." + "get_deadtime_ratios_by_spin_phase", + return_value=xr.DataArray(test_deadtimes, dims="spin_phase_step"), + ), + # Mock spin data to match nominal spins in a pointing period + mock.patch( + "imap_processing.ultra.l1c.ultra_l1c_pset_bins.get_spin_data", + return_value=spin_data, + ), + # Mock background rates to be constant 0.1 + mock.patch( + "imap_processing.ultra.l1c.spacecraft_pset.get_spacecraft_background_rates", + return_value=np.ones((46, npix)), + ), + # Mock culling mask (no culling) + mock.patch("imap_processing.ultra.l1c.spacecraft_pset.compute_culling_mask"), + ): + pset = calculate_spacecraft_pset( + l1b_de, + dataset, + rates_dataset, + aux_dataset, + "imap_ultra_l1c_90sensor-spacecraftpset", + ancillary_files, + 90, + UltraConstants.TOFXPH_SPECIES_GROUPS["proton"], + ) + + # Validate exposure times for ebin 0 + exposure_times = pset["exposure_factor"][0, 0, :].values + expected_exposure_times = exposure_factor_ebin_0["P0"].to_numpy() + np.testing.assert_allclose( + exposure_times, + expected_exposure_times, + rtol=1e-8, + err_msg="Exposure times do not match expected values for ebin 0.", + ) + # Validate sensitivities for ebin 0 + sensitivity = pset["sensitivity"][0, :].values + expected_sensitivity = sensitivities_ebin_0["Sensitivity (cm2)"].to_numpy() + np.testing.assert_allclose( + sensitivity, + expected_sensitivity, + rtol=0.15, + err_msg="Sensitivities times do not match expected values for ebin 0.", + ) diff --git a/imap_processing/tests/ultra/unit/test_ultra_l1a.py b/imap_processing/tests/ultra/unit/test_ultra_l1a.py index 298d6133f0..42c71b7802 100644 --- a/imap_processing/tests/ultra/unit/test_ultra_l1a.py +++ b/imap_processing/tests/ultra/unit/test_ultra_l1a.py @@ -1,6 +1,5 @@ """Test ULTRA L1a CDFs.""" -import numpy as np import pytest import xarray as xr @@ -60,7 +59,7 @@ def test_xarray_phxtof_high_angular(ccsds_path_theta_0): ) # Spot check metadata data and attributes - specific_epoch_data = test_data[0].sel(epoch=test_data[0].epoch[0], sid=0)[ + specific_epoch_data = test_data[0].sel(epoch=test_data[0].epoch[0], plane=0)[ "packetdata" ] assert (specific_epoch_data == test_data[0]["packetdata"][0][0]).all() @@ -73,7 +72,7 @@ def test_xarray_phxtof_high_energy(ccsds_path_extra): test_data = ultra_l1a(ccsds_path_extra, apid_input=ULTRA_PHXTOF_HIGH_ENERGY.apid[0]) # Spot check metadata data and attributes - specific_epoch_data = test_data[0].sel(epoch=test_data[0].epoch[0], sid=0)[ + specific_epoch_data = test_data[0].sel(epoch=test_data[0].epoch[0], plane=0)[ "packetdata" ] assert (specific_epoch_data == test_data[0]["packetdata"][0][0]).all() @@ -86,7 +85,7 @@ def test_xarray_phxtof_high_time(ccsds_path_extra): test_data = ultra_l1a(ccsds_path_extra, apid_input=ULTRA_PHXTOF_HIGH_TIME.apid[0]) # Spot check metadata data and attributes - specific_epoch_data = test_data[0].sel(epoch=test_data[0].epoch[0], sid=0)[ + specific_epoch_data = test_data[0].sel(epoch=test_data[0].epoch[0], plane=0)[ "packetdata" ] assert (specific_epoch_data == test_data[0]["packetdata"][0][0]).all() @@ -99,7 +98,7 @@ def test_xarray_extof_high_angular(ccsds_path_extra): test_data = ultra_l1a(ccsds_path_extra, apid_input=ULTRA_EXTOF_HIGH_ANGULAR.apid[0]) # Spot check metadata data and attributes - specific_epoch_data = test_data[0].sel(epoch=test_data[0].epoch[0], sid=0)[ + specific_epoch_data = test_data[0].sel(epoch=test_data[0].epoch[0], plane=0)[ "packetdata" ] assert (specific_epoch_data == test_data[0]["packetdata"][0][0]).all() @@ -112,7 +111,7 @@ def test_xarray_extof_high_energy(ccsds_path_extra): test_data = ultra_l1a(ccsds_path_extra, apid_input=ULTRA_EXTOF_HIGH_ENERGY.apid[0]) # Spot check metadata data and attributes - specific_epoch_data = test_data[0].sel(epoch=test_data[0].epoch[0], sid=0)[ + specific_epoch_data = test_data[0].sel(epoch=test_data[0].epoch[0], plane=0)[ "packetdata" ] assert (specific_epoch_data == test_data[0]["packetdata"][0][0]).all() @@ -125,7 +124,7 @@ def test_xarray_extof_high_time(ccsds_path_extra): test_data = ultra_l1a(ccsds_path_extra, apid_input=ULTRA_EXTOF_HIGH_TIME.apid[0]) # Spot check metadata data and attributes - specific_epoch_data = test_data[0].sel(epoch=test_data[0].epoch[0], sid=0)[ + specific_epoch_data = test_data[0].sel(epoch=test_data[0].epoch[0], plane=0)[ "packetdata" ] assert (specific_epoch_data == test_data[0]["packetdata"][0][0]).all() @@ -178,8 +177,13 @@ def test_cdf_rates(ccsds_path_theta_0): def test_cdf_energy_rates(ccsds_path_functional): """Tests that CDF file can be created.""" - test_data = ultra_l1a(ccsds_path_functional, apid_input=ULTRA_ENERGY_RATES.apid[0]) - test_data[0].attrs["Data_version"] = "999" + test_data = ultra_l1a( + ccsds_path_functional, + apid_input=ULTRA_ENERGY_RATES.apid[0], + create_derived_l1b=True, + ) + assert len(test_data) == 2 # l1a and l1b + test_data[0].attrs["Repointing"] = "repoint99999" test_data_path = write_cdf(test_data[0], istp=True) @@ -189,6 +193,17 @@ def test_cdf_energy_rates(ccsds_path_functional): == "imap_ultra_l1a_45sensor-energy-rates_20240122-repoint99999_v999.cdf" ) + # L1b dataset + assert "1B" in test_data[1].attrs["Data_type"] + test_data[1].attrs["Repointing"] = "repoint99999" + test_data_path = write_cdf(test_data[1], istp=True) + + assert test_data_path.exists() + assert ( + test_data_path.name + == "imap_ultra_l1b_45sensor-energy-rates_20240122-repoint99999_v999.cdf" + ) + def test_cdf_macrodump(ccsds_path_functional): """Tests that CDF file can be created.""" @@ -284,7 +299,7 @@ def test_cdf_extof_high_time(ccsds_path_extra): test_data_path = write_cdf(test_data[0], istp=True) assert test_data_path.exists() assert ( - test_data_path.name == "imap_ultra_l1a_45sensor-histogram-ena-extof-hi-time_" + test_data_path.name == "imap_ultra_l1a_45sensor-histogram-ion-extof-hi-time_" "20240122-repoint99999_v999.cdf" ) @@ -298,7 +313,7 @@ def test_cdf_extof_high_energy(ccsds_path_extra): test_data_path = write_cdf(test_data[0], istp=True) assert test_data_path.exists() assert ( - test_data_path.name == "imap_ultra_l1a_45sensor-histogram-ena-extof-hi-nrg_" + test_data_path.name == "imap_ultra_l1a_45sensor-histogram-ion-extof-hi-nrg_" "20240122-repoint99999_v999.cdf" ) @@ -492,14 +507,18 @@ def test_cdf_startup(ccsds_path_all_apids): def test_get_event_id(): """Test get_event_id""" - data = np.array([445015662, 445015663, 445015664, 445015664]) - decom_events = get_event_id(data) - counters_for_met = [] - for i in range(len(decom_events)): - event_id = decom_events[i] - met_extracted = event_id >> np.int64(31) - - assert met_extracted == np.int64(data[i]) - counters_for_met.append(event_id & np.int64(0x7FFFFFFF)) - - assert counters_for_met == [0, 0, 0, 1] + # example event bytes + event_data = ( + b"\x929\xc4=\x05\x13\xf2dC\x0c`\x002\xb2\xb3\x80\nUQ\xb5BH" + b'\xe6\x114\x10O\t\xb1\x08\x0e`\x00\xd6\x89"\x00)UF\xd6I' + ) + met = 445015657 + count = 2 + event_ids = get_event_id(event_data, count, met, 166) + assert len(event_ids) == count + # Check that they are all unique + assert len(set(event_ids)) == count + # Check that they are all strings of 50 characters + assert all( + isinstance(event_id, str) and len(event_id) == 50 for event_id in event_ids + ) diff --git a/imap_processing/tests/ultra/unit/test_ultra_l1b.py b/imap_processing/tests/ultra/unit/test_ultra_l1b.py index a99c6b83ed..38551dd4fe 100644 --- a/imap_processing/tests/ultra/unit/test_ultra_l1b.py +++ b/imap_processing/tests/ultra/unit/test_ultra_l1b.py @@ -6,6 +6,9 @@ from imap_processing import imap_module_directory from imap_processing.cdf.utils import load_cdf, write_cdf +from imap_processing.quality_flags import ImapDEOutliersUltraFlags +from imap_processing.ultra.constants import UltraConstants +from imap_processing.ultra.l1b.de import FILLVAL_FLOAT32 from imap_processing.ultra.l1b.ultra_l1b import ultra_l1b from imap_processing.ultra.utils.ultra_l1_utils import create_dataset @@ -61,16 +64,53 @@ def mock_data_l1b_extendedspin_dict(): ) spin_start_time = np.array([0, 1, 2], dtype="uint64") quality = np.zeros((2, 3), dtype="uint16") + # These should be shape: (3,) + energy_dep_flags = np.zeros(len(spin), dtype="uint16") + energy_range_flags = np.zeros(UltraConstants.MAX_ENERGY_RANGES, dtype=np.uint16) + energy_range_flags[:5] = 1 # Set first 5 to 1 for testing + energy_range_edges = np.ones( + UltraConstants.MAX_ENERGY_RANGE_EDGES, dtype=np.float32 + ) + energy_range_edges[:4] = [3.0, 5.0, 7.0, 10.0] # Example values + energy_range_edges[4:] = -1.0e31 # Fill remaining with fillval data_dict = { "epoch": epoch, "spin_number": spin, "energy_bin_geometric_mean": energy, "spin_start_time": spin_start_time, "quality_ena_rates": quality, + "quality_low_voltage": energy_dep_flags, + "quality_high_energy": energy_dep_flags, + "quality_statistics": energy_dep_flags, + "energy_range_flags": energy_range_flags, + "energy_range_edges": energy_range_edges, } return data_dict +@pytest.fixture +def mock_get_annotated_particle_velocity(): + """ + Mock behavior of get_annotated_particle_velocity. + + Returns NaN-filled arrays matching the expected output shape. + """ + + def side_effect_func(event_times, position, ultra_frame, dps_frame, sc_frame): + num_events = event_times.size + return ( + np.full((num_events, 3), np.nan), # sc_velocity + np.full((num_events, 3), np.nan), # sc_dps_velocity + np.full((num_events, 3), np.nan), # helio_velocity + ) + + with mock.patch( + "imap_processing.ultra.l1b.de.get_annotated_particle_velocity" + ) as mocked_func: + mocked_func.side_effect = side_effect_func + yield mocked_func + + def test_create_extendedspin_dataset(mock_data_l1b_extendedspin_dict): """Tests that dataset is created as expected.""" dataset = create_dataset( @@ -101,35 +141,23 @@ def test_create_de_dataset(mock_data_l1b_de_dict): @pytest.mark.external_test_data -@mock.patch("imap_processing.ultra.l1b.de.get_annotated_particle_velocity") def test_cdf_de( - mock_get_annotated_particle_velocity, de_dataset, + aux_dataset, use_fake_spin_data_for_time, ancillary_files, + use_fake_repoint_data_for_time, + mock_get_annotated_particle_velocity, ): """Tests that CDF file is created and contains same attributes as xarray.""" data_dict = {} + de_dataset.attrs["Repointing"] = "repoint00001" data_dict[de_dataset.attrs["Logical_source"]] = de_dataset + data_dict[aux_dataset.attrs["Logical_source"]] = aux_dataset # Create a spin table that cover spin 0-141 - use_fake_spin_data_for_time(0, 141 * 15) - - # Mock get_annotated_particle_velocity to avoid needing kernels - def side_effect_func(event_times, position, ultra_frame, dps_frame, sc_frame): - """ - Mock behavior of get_annotated_particle_velocity. - - Returns NaN-filled arrays matching the expected output shape. - """ - num_events = event_times.size - return ( - np.full((num_events, 3), np.nan), # sc_velocity - np.full((num_events, 3), np.nan), # sc_dps_velocity - np.full((num_events, 3), np.nan), # helio_velocity - ) - - mock_get_annotated_particle_velocity.side_effect = side_effect_func + use_fake_spin_data_for_time(511000000, 511000000 + 86400 * 5) + use_fake_repoint_data_for_time(np.arange(511000000, 511000000 + 86400 * 5, 86400)) l1b_de_dataset = ultra_l1b(data_dict, ancillary_files) @@ -146,11 +174,41 @@ def side_effect_func(event_times, position, ultra_frame, dps_frame, sc_frame): test_data_path.name == "imap_ultra_l1b_45sensor-de_20240207-repoint99999_v999.cdf" ) + # check that event_id exists in the dataset + assert "event_id" in l1b_de_dataset[0].variables +@pytest.mark.external_test_data +def test_cdf_de_flags( + mock_get_annotated_particle_velocity, + de_dataset, + aux_dataset, + use_fake_spin_data_for_time, + ancillary_files, + use_fake_repoint_data_for_time, +): + """Tests that the de code flags events not in a repointing.""" + data_dict = {} + de_dataset.attrs["Repointing"] = "repoint00000" + data_dict[de_dataset.attrs["Logical_source"]] = de_dataset + data_dict[aux_dataset.attrs["Logical_source"]] = aux_dataset + # Create a spin table that cover spin 0-141 + use_fake_spin_data_for_time(511000000, 511000000 + 86400 * 5) + # Use repoint data that will NOT cover the event times to test flag setting + use_fake_repoint_data_for_time(np.arange(0, +86400 * 5, 86400)) + + l1b_de_dataset = ultra_l1b(data_dict, ancillary_files) + # All valid events should be flagged as DURINGREPOINT since the repoint data does + # not cover any of the event times + valid_events = l1b_de_dataset[0]["event_times"] != FILLVAL_FLOAT32 + flags = l1b_de_dataset[0]["quality_outliers"].values[valid_events] + assert np.all((flags & ImapDEOutliersUltraFlags.DURINGREPOINT.value) != 0) + + +@mock.patch("imap_processing.ultra.l1b.extendedspin.UltraConstants.SPIN_BIN_SIZE", 5) @pytest.mark.external_test_data def test_ultra_l1b_extendedspin( - use_fake_spin_data_for_time, faux_aux_dataset, rates_dataset + use_fake_spin_data_for_time, aux_dataset, rates_dataset, status_dataset ): """Tests that L1b data is created.""" use_fake_spin_data_for_time(0, 141 * 15) @@ -158,7 +216,6 @@ def test_ultra_l1b_extendedspin( TEST_PATH / "imap_ultra_l1b_45sensor-de_20240207-repoint99999_v999.cdf" ) l1b_de_dataset = load_cdf(l1b_de_dataset_path) - data_dict = { key: l1b_de_dataset for key in [ @@ -166,10 +223,14 @@ def test_ultra_l1b_extendedspin( "imap_ultra_l1a_45sensor-params", ] } - data_dict["imap_ultra_l1a_45sensor-aux"] = faux_aux_dataset + data_dict["imap_ultra_l1a_45sensor-aux"] = aux_dataset data_dict["imap_ultra_l1a_45sensor-rates"] = rates_dataset + data_dict["imap_ultra_l1b_45sensor-status"] = status_dataset - ancillary_files = {} + ancillary_files = { + "l1b-45sensor-de-product-lookup": TEST_PATH + / "imap_ultra_l1b-45sensor-de-product-lookup_20251001_v001.csv" + } l1b_extendedspin_dataset = ultra_l1b(data_dict, ancillary_files) assert len(l1b_extendedspin_dataset) == 1 @@ -179,8 +240,11 @@ def test_ultra_l1b_extendedspin( ) +@mock.patch("imap_processing.ultra.l1b.extendedspin.UltraConstants.SPIN_BIN_SIZE", 5) @pytest.mark.external_test_data -def test_cdf_extendedspin(use_fake_spin_data_for_time, faux_aux_dataset, rates_dataset): +def test_cdf_extendedspin( + use_fake_spin_data_for_time, aux_dataset, rates_dataset, status_dataset +): use_fake_spin_data_for_time(0, 141 * 15) l1b_de_dataset_path = ( TEST_PATH / "imap_ultra_l1b_45sensor-de_20240207-repoint99999_v999.cdf" @@ -194,15 +258,20 @@ def test_cdf_extendedspin(use_fake_spin_data_for_time, faux_aux_dataset, rates_d "imap_ultra_l1a_45sensor-params", ] } - data_dict["imap_ultra_l1a_45sensor-aux"] = faux_aux_dataset + data_dict["imap_ultra_l1a_45sensor-aux"] = aux_dataset data_dict["imap_ultra_l1a_45sensor-rates"] = rates_dataset + data_dict["imap_ultra_l1b_45sensor-status"] = status_dataset - ancillary_files = {} + ancillary_files = { + "l1b-45sensor-de-product-lookup": TEST_PATH + / "imap_ultra_l1b-45sensor-de-product-lookup_20251001_v001.csv" + } l1b_extendedspin_dataset = ultra_l1b(data_dict, ancillary_files) """Tests that CDF file is created and contains same attributes as xarray.""" l1b_extendedspin_dataset[0].attrs["Data_version"] = "999" l1b_extendedspin_dataset[0].attrs["Repointing"] = "repoint99999" - test_data_path = write_cdf(l1b_extendedspin_dataset[0], istp=True) + l1b_extendedspin_dataset[0].attrs["Start_date"] = "20240207" + test_data_path = write_cdf(l1b_extendedspin_dataset[0]) assert test_data_path.exists() assert ( test_data_path.name @@ -210,8 +279,11 @@ def test_cdf_extendedspin(use_fake_spin_data_for_time, faux_aux_dataset, rates_d ) +@mock.patch("imap_processing.ultra.l1b.extendedspin.UltraConstants.SPIN_BIN_SIZE", 5) @pytest.mark.external_test_data -def test_cdf_cullingmask(use_fake_spin_data_for_time, faux_aux_dataset, rates_dataset): +def test_cdf_goodtimes( + use_fake_spin_data_for_time, aux_dataset, rates_dataset, status_dataset +): """Tests that CDF file is created and contains same attributes as xarray.""" use_fake_spin_data_for_time(0, 141 * 15) l1b_de_dataset_path = ( @@ -226,28 +298,36 @@ def test_cdf_cullingmask(use_fake_spin_data_for_time, faux_aux_dataset, rates_da "imap_ultra_l1a_45sensor-params", ] } - data_dict["imap_ultra_l1a_45sensor-aux"] = faux_aux_dataset + data_dict["imap_ultra_l1a_45sensor-aux"] = aux_dataset data_dict["imap_ultra_l1a_45sensor-rates"] = rates_dataset + data_dict["imap_ultra_l1b_45sensor-status"] = status_dataset - ancillary_files = {} + ancillary_files = { + "l1b-45sensor-de-product-lookup": TEST_PATH + / "imap_ultra_l1b-45sensor-de-product-lookup_20251001_v001.csv" + } l1b_extendedspin_dataset = ultra_l1b(data_dict, ancillary_files) - cullingmask_dataset = ultra_l1b( + goodtimes_dataset = ultra_l1b( {"imap_ultra_l1b_45sensor-extendedspin": l1b_extendedspin_dataset[0]}, ancillary_files, ) - cullingmask_dataset[0].attrs["Data_version"] = "999" - cullingmask_dataset[0].attrs["Repointing"] = "repoint99999" - test_data_path = write_cdf(cullingmask_dataset[0], istp=True) + goodtimes_dataset[0].attrs["Data_version"] = "999" + goodtimes_dataset[0].attrs["Repointing"] = "repoint99999" + goodtimes_dataset[0].attrs["Start_date"] = "20240207" + test_data_path = write_cdf(goodtimes_dataset[0]) assert test_data_path.exists() assert ( test_data_path.name - == "imap_ultra_l1b_45sensor-cullingmask_20240207-repoint99999_v999.cdf" + == "imap_ultra_l1b_45sensor-goodtimes_20240207-repoint99999_v999.cdf" ) +@mock.patch("imap_processing.ultra.l1b.extendedspin.UltraConstants.SPIN_BIN_SIZE", 5) @pytest.mark.external_test_data -def test_cdf_badtimes(use_fake_spin_data_for_time, faux_aux_dataset, rates_dataset): +def test_cdf_badtimes( + use_fake_spin_data_for_time, aux_dataset, rates_dataset, status_dataset +): """Tests that CDF file is created and contains same attributes as xarray.""" use_fake_spin_data_for_time(0, 141 * 15) l1b_de_dataset_path = ( @@ -262,14 +342,18 @@ def test_cdf_badtimes(use_fake_spin_data_for_time, faux_aux_dataset, rates_datas "imap_ultra_l1a_45sensor-params", ] } - data_dict["imap_ultra_l1a_45sensor-aux"] = faux_aux_dataset + data_dict["imap_ultra_l1a_45sensor-aux"] = aux_dataset data_dict["imap_ultra_l1a_45sensor-rates"] = rates_dataset + data_dict["imap_ultra_l1b_45sensor-status"] = status_dataset - ancillary_files = {} + ancillary_files = { + "l1b-45sensor-de-product-lookup": TEST_PATH + / "imap_ultra_l1b-45sensor-de-product-lookup_20251001_v001.csv" + } l1b_extendedspin_dataset = ultra_l1b(data_dict, ancillary_files) ancillary_files = {} - cullingmask_dataset = ultra_l1b( + goodtimes_dataset = ultra_l1b( {"imap_ultra_l1b_45sensor-extendedspin": l1b_extendedspin_dataset[0]}, ancillary_files, ) @@ -277,13 +361,14 @@ def test_cdf_badtimes(use_fake_spin_data_for_time, faux_aux_dataset, rates_datas l1b_badtimes_dataset = ultra_l1b( { "imap_ultra_l1b_45sensor-extendedspin": l1b_extendedspin_dataset[0], - "imap_ultra_l1b_45sensor-cullingmask": cullingmask_dataset[0], + "imap_ultra_l1b_45sensor-goodtimes": goodtimes_dataset[0], }, ancillary_files, ) l1b_badtimes_dataset[0].attrs["Data_version"] = "999" l1b_badtimes_dataset[0].attrs["Repointing"] = "repoint99999" - test_data_path = write_cdf(l1b_badtimes_dataset[0], istp=True) + l1b_badtimes_dataset[0].attrs["Start_date"] = "20240207" + test_data_path = write_cdf(l1b_badtimes_dataset[0]) assert test_data_path.exists() assert ( test_data_path.name @@ -301,3 +386,34 @@ def test_ultra_l1b_error(mock_data_l1a_rates_dict): ValueError, match="Data dictionary does not contain the expected keys." ): ultra_l1b(mock_data_l1a_rates_dict, ancillary_files) + + +@pytest.mark.external_test_data +def test_ultra_l1b_priority_de( + mock_get_annotated_particle_velocity, + de_dataset, + aux_dataset, + use_fake_spin_data_for_time, + ancillary_files, + use_fake_repoint_data_for_time, +): + """Tests that priority de datasets can be created""" + data_dict = {} + # Create a spin table that cover spin 0-141 + use_fake_spin_data_for_time(443640487, 443642460) + # Use repoint data that will NOT cover the event times to test flag setting + use_fake_repoint_data_for_time(np.arange(0, +86400 * 5, 86400)) + de_dataset.attrs["Repointing"] = "repoint00001" + # Set the logical source to match the priority de key + # Use the de dataset because it should be treated the same as the priority dataset + # and the priority dataset takes a long time to create. + data_dict["imap_ultra_l1a_45sensor-priority-1-de"] = de_dataset + data_dict[aux_dataset.attrs["Logical_source"]] = aux_dataset + + l1b_de_dataset = ultra_l1b(data_dict, ancillary_files) + + assert l1b_de_dataset[0] + assert ( + l1b_de_dataset[0].attrs["Logical_source"] + == "imap_ultra_l1b_45sensor-priority-1-de" + ) diff --git a/imap_processing/tests/ultra/unit/test_ultra_l1b_annotated.py b/imap_processing/tests/ultra/unit/test_ultra_l1b_annotated.py index 76975baea1..3b90564f79 100644 --- a/imap_processing/tests/ultra/unit/test_ultra_l1b_annotated.py +++ b/imap_processing/tests/ultra/unit/test_ultra_l1b_annotated.py @@ -14,10 +14,10 @@ def furnish_kernels(spice_test_data_path, furnish_kernels): """List SPICE kernels.""" required_kernels = [ - "imap_science_100.tf", + "imap_science_120.tf", "imap_sclk_0000.tsc", "sim_1yr_imap_attitude.bc", - "imap_wkcp.tf", + "imap_130.tf", "naif0012.tls", "sim_1yr_imap_pointing_frame.bc", "de440s.bsp", diff --git a/imap_processing/tests/ultra/unit/test_ultra_l1b_culling.py b/imap_processing/tests/ultra/unit/test_ultra_l1b_culling.py index 357c7d789b..94852f9b9b 100644 --- a/imap_processing/tests/ultra/unit/test_ultra_l1b_culling.py +++ b/imap_processing/tests/ultra/unit/test_ultra_l1b_culling.py @@ -1,8 +1,11 @@ """Tests Culling for ULTRA L1b.""" +from unittest import mock + import numpy as np import pandas as pd import pytest +import xarray as xr from imap_processing import imap_module_directory from imap_processing.quality_flags import ( @@ -16,22 +19,60 @@ from imap_processing.ultra.l1b.ultra_l1b_culling import ( compare_aux_univ_spin_table, count_rejected_events_per_spin, + expand_bin_flags_to_spins, flag_attitude, + flag_high_energy, flag_hk, flag_imap_instruments, + flag_low_voltage, flag_rates, flag_scattering, + flag_spectral_events, + flag_statistical_outliers, + flag_upstream_ion, + get_binned_energy_ranges, + get_binned_spins_edges, get_de_rejection_mask, + get_energy_and_spin_dependent_rejection_mask, get_energy_histogram, + get_energy_range_flags, get_n_sigma, + get_poisson_stats, get_pulses_per_spin, - get_spin_and_duration, get_spin_data, + get_valid_earth_angle_events, + get_valid_events_per_energy_range, ) +from imap_processing.ultra.l1b.ultra_l1b_extended import get_spin_info +from imap_processing.ultra.l1c.l1c_lookup_utils import build_energy_bins TEST_PATH = imap_module_directory / "tests" / "ultra" / "data" / "l1" +@pytest.fixture +def setup_repoint_47_data(): + """Fixture to set up data for validation test using repoint 47.""" + de_df = pd.read_csv(TEST_PATH / "de_test_data_repoint00047.csv") + de_ds = xr.Dataset( + { + "de_event_met": ("epoch", de_df.event_times.values), + "energy_spacecraft": ("epoch", de_df.energy_spacecraft.values), + "quality_outliers": ("epoch", de_df.quality_outliers.values), + "quality_scattering": ("epoch", de_df.quality_scattering.values), + "ebin": ("epoch", de_df.ebin.values), + } + ) + xspin = pd.read_csv(TEST_PATH / "extendedspin_test_data_repoint00047.csv") + spin_bin_size = UltraConstants.SPIN_BIN_SIZE + spin_tbin_edges = get_binned_spins_edges( + xspin.spin_number.values, + xspin.spin_period.values, + xspin.spin_start_time.values, + spin_bin_size, + ) + return de_ds, xspin, spin_tbin_edges + + @pytest.fixture def test_data(use_fake_spin_data_for_time): """Fixture to compute and return test data.""" @@ -173,18 +214,34 @@ def test_compare_aux_univ_spin_table(use_fake_spin_data_for_time, faux_aux_datas def test_get_duration(rates_l1_test_path, use_fake_spin_data_for_time): """Tests get_duration function.""" use_fake_spin_data_for_time(start_met=0, end_met=141 * 15) - df = pd.read_csv(rates_l1_test_path) + # Should be evenly spaced spins of 15 seconds each except the first one has 14. + num_spins = 15 + spin_start_times = np.concatenate([[0], np.arange(14, 222, num_spins)]) + spin_numbers = np.arange(127, 142) + num_spins = len(spin_numbers) + + aux_ds = xr.Dataset( + data_vars={ + "timespinstart": ("epoch", spin_start_times), + "timespinstartsub": ("epoch", np.ones_like(spin_start_times)), + "duration": ("epoch", np.full(num_spins, 15)), + "spinnumber": ("epoch", spin_numbers), + }, + coords={"epoch": ("epoch", np.arange(num_spins))}, + ) + met = df["TimeTag"] - df["TimeTag"].values[0] spin = df["Spin"] - spin_number, duration = get_spin_and_duration(met, spin) - + spin_ds = get_spin_info(aux_ds, met) + spin_number = spin_ds["spin_number"].values + duration = spin_ds["spin_duration"].values assert np.array_equal(spin, spin_number) assert np.all(duration == 15) -def test_get_pulses(rates_l1_test_path, use_fake_spin_data_for_time): +def test_get_pulses(rates_l1_test_path, use_fake_spin_data_for_time, aux_dataset): """Tests get_pulses_per_spin function.""" df = pd.read_csv(rates_l1_test_path) @@ -214,7 +271,7 @@ def test_get_pulses(rates_l1_test_path, use_fake_spin_data_for_time): "spin": df["Spin"], } - pulses = get_pulses_per_spin(pulse_dict) + pulses = get_pulses_per_spin(aux_dataset, pulse_dict) unique_spins = np.unique(pulse_dict["spin"]) start_pulses_total = pulse_dict["start_rf"] + pulse_dict["start_lf"] @@ -277,6 +334,11 @@ def test_get_de_rejection_mask(): counted, np.array([False, True, True, True, True, False, True, True, False]) ) + counts_no_scattering = get_de_rejection_mask( + quality_scattering, quality_outliers, reject_scattering=False + ) + np.testing.assert_array_equal(counts_no_scattering, quality_outliers.astype(bool)) + def test_count_rejected_events_per_spin(): """Tests count_rejected_events_per_spin function.""" @@ -290,3 +352,644 @@ def test_count_rejected_events_per_spin(): ) np.testing.assert_array_equal(counted, np.array([2, 2, 2])) + + +def test_flag_low_voltage(test_data): + """Tests flag_low_voltage function.""" + n_spins = 20 + mock_status_dataset = xr.Dataset( + data_vars={ + "shcoarse": np.arange(n_spins), + # Set Voltage below threshold + "rightdeflection_v": np.full(n_spins, 0.5), + "leftdeflection_v": np.full(n_spins, 1.5), + } + ) + spins = np.arange(n_spins) + spin_bin_size = 5 + spin_period = np.full(n_spins, 15.0) + spin_starttime = np.arange(n_spins) + spin_tbin_edges = get_binned_spins_edges( + spins, spin_period, spin_starttime, spin_bin_size + ) + quality_flags = flag_low_voltage(spin_tbin_edges, mock_status_dataset) + + # There should be an extra bin edge for the last bin to indicate the end of the last + # spin bin + assert len(spin_tbin_edges) == (n_spins // 5) + 1 + # Check quality flag shape + assert quality_flags.shape == (len(spin_tbin_edges) - 1,) + # Check that every spin is flagged for low voltage + assert np.all(quality_flags) + + # Set only the first spin to be below threshold + mock_status_dataset["rightdeflection_v"].data[1:] += 5000 + mock_status_dataset["leftdeflection_v"].data[1:] += 5000 + quality_flags = flag_low_voltage(spin_tbin_edges, mock_status_dataset) + # Check that only the first spin is flagged for low voltage + assert np.all(quality_flags[0]) + # The rest should not be flagged + assert np.all(quality_flags[1:] == 0) + + +def test_flag_low_voltage_incomplete_bins(test_data): + """Tests flag_low_voltage function when there is an incomplete spin bin.""" + n_spins = 12 # Not a multiple of spin_bin_size to test incomplete bins + mock_status_dataset = xr.Dataset( + data_vars={ + "shcoarse": np.arange(n_spins), + # Set Voltage below threshold + "rightdeflection_v": np.full(n_spins, 0.5), + "leftdeflection_v": np.full(n_spins, 1.5), + } + ) + + spins = np.arange(n_spins) + spin_bin_size = 5 + spin_period = np.full(n_spins, 15.0) + spin_starttime = np.arange(n_spins) + spin_tbin_edges = get_binned_spins_edges( + spins, spin_period, spin_starttime, spin_bin_size + ) + quality_flags = flag_low_voltage(spin_tbin_edges, mock_status_dataset) + + # check quality flag + assert quality_flags.shape == (n_spins // spin_bin_size,) + assert np.all(quality_flags) + + +def test_expand_bin_flags_to_spins(caplog): + """Tests expand_bin_flags_to_spins function.""" + spin_bin_size = 5 + n_spins = 12 + # Mock the shape of binned quality flags for 12 spins and a bin size of 5 + binned_qf = np.full((n_spins // spin_bin_size), 1) + quality_flags = expand_bin_flags_to_spins(n_spins, binned_qf, spin_bin_size) + # Check the size + assert quality_flags.shape == (n_spins,) + # The first 10 spins should be flagged since they fall into the first two bins + assert np.all(quality_flags[:10] == 1) + # The last 2 spins should not be flagged since they fall into the last incomplete + # bin + assert np.all(quality_flags[10:] == 0) + binned_qf = np.full((n_spins // spin_bin_size) + 1, 1) + # test that a warning is logged when there are incomplete bins found + expand_bin_flags_to_spins(n_spins, binned_qf, spin_bin_size) + assert "Found incomplete spin bin at the end with 3 spins" in caplog.text + + +def test_get_energy_and_spin_dependent_rejection_mask(): + """Tests get_energy_and_spin_dependent_rejection_mask function.""" + n_spins = 10 + energy_range_flags = np.zeros(16, dtype=np.uint16) + energy_range_flags[:3] = [2**1, 2**2, 2**3] # Example flags for 3 energy bins + energy_range_edges = np.full(17, -1.0e31, dtype=np.float32) + energy_range_edges[:4] = [ + 3, + 5, + 7, + 18, + ] # Example energy bin edges (4 edges = 3 bins) + goodtimes_dataset = xr.Dataset( + data_vars={ + "spin_number": np.arange(n_spins), + "quality_low_voltage": np.full(n_spins, 0), + "quality_high_energy": np.full(n_spins, 0), + "quality_statistics": np.full(n_spins, 0), + "energy_range_flags": energy_range_flags, + "energy_range_edges": energy_range_edges, + "quality_upstream_ion_1": np.full(n_spins, 0), + "quality_upstream_ion_2": np.full(n_spins, 0), + "quality_spectral": np.full(n_spins, 0), + } + ) + # update quality flags to test that events get rejected + # For spin 0, set energy bin 0 to be bad (flag = 2) + goodtimes_dataset["quality_low_voltage"].data[0] = 2 + # For spin 2, set energy bin 1 to be bad (flag = 4) + goodtimes_dataset["quality_high_energy"].data[2] = 4 + # For spin 4, set energy bin 2 to be bad (flag = 8) + # Energy corresponding to spin 5 will not be rejected since it is not + # within an energy bin + goodtimes_dataset["quality_high_energy"].data[4] = 8 + # Create 6 fake events + energy = np.array( + [4, 5, 6, 9, 18, 15] + ) # Energy values that fall into different bins + spin_number = np.arange(6) + rejected = get_energy_and_spin_dependent_rejection_mask( + goodtimes_dataset, energy, spin_number + ) + + np.testing.assert_array_equal( + rejected, np.array([True, False, True, False, False, False]) + ) + + +@pytest.mark.external_test_data +def test_validate_voltage_cull(): + """Validate that low voltage spins are correctly flagged""" + # read test data from csv files + xspin = pd.read_csv(TEST_PATH / "extendedspin_test_data_repoint00047.csv") + validation_low_voltage_qf = np.loadtxt( + TEST_PATH / "voltage_culling_results_repoint00047.csv", + delimiter=",", + dtype=np.uint16, + ) + status_df = pd.read_csv(TEST_PATH / "status_test_data_repoint00047.csv") + # build the status dataset including the variables needed for the low voltage flag + status_ds = xr.Dataset( + { + "shcoarse": ("epoch", status_df.shcoarse.values), + "rightdeflection_v": ("epoch", status_df.rightdeflection_v.values), + "leftdeflection_v": ("epoch", status_df.leftdeflection_v.values), + } + ) + # Use constants from the code to ensure consistency with the actual culling code + spin_bin_size = UltraConstants.SPIN_BIN_SIZE + lv_threshold = 3000 + spin_tbin_edges = get_binned_spins_edges( + xspin.spin_number.values, + xspin.spin_period.values, + xspin.spin_start_time.values, + spin_bin_size, + ) + lv_flags = flag_low_voltage(spin_tbin_edges, status_ds, lv_threshold) + + assert np.array_equal(lv_flags, validation_low_voltage_qf) + + +@mock.patch("imap_processing.ultra.l1b.ultra_l1b_culling.sp.spkezr") +def test_get_valid_earth_angle_events(mock_spkezr): + """Tests get_valid_earth_angle_events function.""" + np.random.seed(0) + de_dps_velocity = np.random.random((12, 3)) + de_dataset = xr.Dataset( + { + "velocity_dps_sc": (("epoch", "component"), de_dps_velocity), + "event_times": ("epoch", np.arange(12)), + } + ) + earth_angle_threshold = np.radians(45) + np.random.seed(0) + mock_imap_state = np.random.random(6) # Mock IMAP state for testing + mock_spkezr.return_value = (mock_imap_state, None) + # Calculate the expected flag exactly the way ULTRA IT does to ensure we are + # getting the same results. + # First negate the state vector: the state from imap_state(observer=EARTH) + # gives the position of IMAP as seen from Earth (Earth to IMAP), while + # the ULTRA code below expects the vector from IMAP to Earth. + pos = mock_imap_state[:3] + upos = pos / np.sqrt(np.sum(pos**2)) + zax0 = np.cross(upos, [0, 1, 0]) + zax = zax0 / np.sqrt(np.sum(zax0**2)) + yax = np.cross(zax, upos) + + vde = np.sqrt(np.sum(de_dps_velocity**2, 1)) + uv = de_dps_velocity / vde[:, np.newaxis] + local_uv = np.array([upos, yax, zax]) @ np.transpose(-uv) + expected_flags = local_uv[0, :] < np.cos(earth_angle_threshold) + + actual_flags = get_valid_earth_angle_events(de_dataset, earth_angle_threshold) + np.testing.assert_array_equal(actual_flags, expected_flags) + + +def test_get_valid_events_per_energy_range(): + """Tests get_valid_events_per_energy_range function.""" + np.random.seed(0) + energy_range_edges = np.array([3, 5, 7, 18]) # 3 example energy bins + # example energy values that fall into different bins + # - Events 1-3 and 8 fall into the second bin (5-7) + # - Events 4-7 fall into the third bin (7-18) + # - The rest of the event energies don't fall into any bins and should be + # invalid for that energy range + energy = np.array([5, 5, 6, 9, 10, 11, 12, 6, 7, 1, 20, 63]) + # Mark event 2 (energy bin 2) and 5 (energy bin 3) as outliers + quality_outliers = np.array([0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0]) + # Mark event 1 (energy bin 2), 9 (energy bin 3), and 11 and 12 (No energy bin) + quality_scattering = np.array([1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1]) + ebin = np.full(len(energy), 10) + # mark event 6 as having an invalid ebin + ebin[5] = -1 + de_dps_velocity = np.random.random((len(energy), 3)) + + de_dataset = xr.Dataset( + { + "de_dps_velocity": (("epoch", "component"), de_dps_velocity), + "event_times": ("epoch", np.arange(len(energy))), + "energy_spacecraft": ("epoch", energy), + "quality_outliers": ("epoch", quality_outliers), + "quality_scattering": ("epoch", quality_scattering), + "ebin": ("epoch", ebin), + } + ) + keepout_angle = np.radians(180) + valid_events = get_valid_events_per_energy_range( + de_dataset, energy_range_edges, keepout_angle, 90 + ) + + # Assert that for the first energy bin (3-5), all are false + assert np.array_equal(valid_events[0], np.full(len(valid_events[0]), False)) + # Assert that for the second energy bin (5-7), all are false except + # events 3 and 8 (event 1 had an outlier flag, event 2 had a scattering flag) + expected_flags_ebin2 = np.array( + [ + False, + False, + True, + False, + False, + False, + False, + True, + False, + False, + False, + False, + ] + ) + assert np.array_equal(valid_events[1], expected_flags_ebin2) + # Assert that for the third energy bin (7-18), all are false except events 4 and 7 + # (event 5 was marked as an outlier and event 6 has an invalid ebin) + expected_flags_ebin3 = np.array( + [ + False, + False, + False, + True, + False, + False, + True, + False, + False, + False, + False, + False, + ] + ) + assert np.array_equal(valid_events[2], expected_flags_ebin3) + + +@mock.patch("imap_processing.ultra.l1b.ultra_l1b_culling.sp.spkezr") +def test_get_valid_events_per_energy_range_ultra45(mock_spkezr): + """Tests get_valid_events_per_energy_range function.""" + np.random.seed(0) + mock_imap_state = np.random.random(6) # Mock IMAP state for testing + mock_spkezr.return_value = (mock_imap_state, None) + energy_range_edges = np.array([3, 5, 7, 18]) # 3 example energy bins + energy = np.arange(18) + + # mark all events with valid outlier and scattering flags and valid ebins. + de_dps_velocity = np.random.random((len(energy), 3)) + + de_dataset = xr.Dataset( + { + "velocity_dps_sc": (("epoch", "component"), de_dps_velocity), + "event_times": ("epoch", np.full(len(energy), 798033671)), + "energy_spacecraft": ("epoch", energy), + "quality_outliers": ("epoch", np.full(len(energy), 0)), + "quality_scattering": ("epoch", np.full(len(energy), 0)), + "ebin": ("epoch", np.full(len(energy), 10)), + } + ) + # ensure that all events fail the earth angle check by setting a very large + # keepout angle + keepout_angle = np.radians(360) + valid_events = get_valid_events_per_energy_range( + de_dataset, energy_range_edges, keepout_angle, 45 + ) + + # although all events were valid for outliers, scattering, and ebin, all events + # failed the earth angle check for ultra45 + assert not np.any(valid_events) + + +@mock.patch( + "imap_processing.ultra.l1b.ultra_l1b_culling.UltraConstants.HIGH_ENERGY_CULL_CHANNEL", + 2, +) +@mock.patch( + "imap_processing.ultra.l1b.ultra_l1b_culling.UltraConstants.HIGH_ENERGY_COMBINED_SPIN_BIN_RADIUS", + None, +) +def test_flag_high_energy(): + """Tests flag_high_energy function.""" + # 7-18 is the culling energy bin and shown in the mock.patch above + # Flag energy ranges will compare the counts from this energy range at each spin bin + # to the culling threshold to determine if the spin bin should be flagged for high + # energy. + energy_range_edges = np.array([3, 5, 7, 18, 25]) # Example energy bin edges + # Spin bin 1 (events 0-3) 4 events fall within the culling energy bin + # - This is above all the energy thresholds except the second one (10), + # so it should be flagged for all energy ranges except flag the 2nd + # Spin bin 2 (events 4-7) only 1 event falls within the culling energy bin + # - This is above the lowest energy threshold (1) but below the rest, so + # it should only be flagged at the last energy range + # Spin bin 3 (events 8-11) No events fall within the culling energy bin, + # so it should not be flagged for any energy range + energy = np.array([17, 16, 12, 15, 5, 8, 4, 6, 4, 1, 22, 20]) + cull_thresholds = np.array([3, 10, 2, 1]) + de_dataset = xr.Dataset( + { + "de_event_met": ("epoch", np.arange(len(energy))), + "energy_spacecraft": ("epoch", energy), + "quality_outliers": ("epoch", np.full(len(energy), 0)), + "quality_scattering": ("epoch", np.full(len(energy), 0)), + "ebin": ("epoch", np.full(len(energy), 10)), + } + ) + # make one ebin invalid to make sure the valid events filtering is working + de_dataset["ebin"].data[-1] = -1 + spin_tbin_edges = np.arange( + start=0, stop=len(energy) + 1, step=4 + ) # create spin bins of 4 seconds + quality_flags = flag_high_energy( + de_dataset, + spin_tbin_edges, + energy_range_edges, + None, + cull_thresholds, + 90, + ) + + # check shape + np.testing.assert_array_equal( + quality_flags.shape, (len(energy_range_edges) - 1, len(spin_tbin_edges) - 1) + ) + # Assert that the first spin bin is flagged for high energy for all energy ranges + # except the second one + assert quality_flags[0, 0] + assert not quality_flags[1, 0] + assert quality_flags[2, 0] + assert quality_flags[3, 0] + # Assert that the second spin bin is only flagged for high energy for the last + # # energy range + assert quality_flags[3, 1] + assert not np.any(quality_flags[0:3, 1]) + # # Assert that the third spin bin is not flagged for any energy range + assert not np.any(quality_flags[:, 2]) + + +@mock.patch( + "imap_processing.ultra.l1b.ultra_l1b_culling.UltraConstants.HIGH_ENERGY_CULL_CHANNEL", + 4, +) +@mock.patch( + "imap_processing.ultra.l1b.ultra_l1b_culling.UltraConstants.HIGH_ENERGY_COMBINED_SPIN_BIN_RADIUS", + 3, +) +@pytest.mark.external_test_data +def test_validate_high_energy_cull(setup_repoint_47_data): + """Validate that high energy spins are correctly flagged""" + # Mock thresholds to match the test data (I used fake ones to create more + # complexity) + mock_thresholds = np.array([0.05, 1.5, 0.6, 119.2, 0.2]) * 20 + expected_qf = pd.read_csv( + TEST_PATH / "validate_high_energy_culling_results_repoint00047_v2.csv" + ).to_numpy() + de_ds, _, spin_tbin_edges = setup_repoint_47_data + # Get the energy ranges + energy_ranges = np.array([4.2, 9.4425, 21.2116, 47.2388, 105.202, 316.335]) + e_flags = flag_high_energy( + de_ds, spin_tbin_edges, energy_ranges, None, mock_thresholds + ) + np.testing.assert_array_equal(e_flags, ~expected_qf.astype(bool)) + + +def test_flag_statistical_outliers(): + """Tests flag_statistical_outliers function.""" + energy_range_edges = np.array([3, 5, 7, 18, 25]) # Example energy bin edges + n_spin_bins = 12 + spin_step = 7 + energy = np.full(spin_step * n_spin_bins, 0) + # Make sure there are at least 3 other bins with counts in each energy bin so that + # the statistics can be calculated. + energy[::spin_step] = 3 + energy[1::spin_step] = 5 + energy[2::spin_step] = 7 + energy[3::spin_step] = 18 + # Make the last spin bin have higher counts. It should get flagged as an outlier. + energy[-spin_step:] = 23 + + de_dataset = xr.Dataset( + { + "de_event_met": ("epoch", np.arange(len(energy))), + "energy_spacecraft": ("epoch", energy), + "quality_outliers": ("epoch", np.full(len(energy), 0)), + "quality_scattering": ("epoch", np.full(len(energy), 0)), + "ebin": ("epoch", np.full(len(energy), 10)), + } + ) + spin_tbin_edges = np.arange( + start=0, stop=len(energy) + 1, step=spin_step + ) # create spin bins of 7 seconds + quality_flags, convergence, iterations, std_diff = flag_statistical_outliers( + de_dataset, + spin_tbin_edges, + energy_range_edges, + np.zeros((len(energy_range_edges) - 1, len(spin_tbin_edges) - 1), dtype=bool), + combine_flags_across_energy_bins=True, + ) + + # check shape + np.testing.assert_array_equal( + quality_flags.shape, (len(energy_range_edges) - 1, len(spin_tbin_edges) - 1) + ) + # check that none of the flags are set except for the last spin bin + # since combine_flags_across_energy_bins is True, the entire last spin bin should + # be flagged even though only one energy bin had high counts + expected_flags = np.zeros( + (len(energy_range_edges) - 1, len(spin_tbin_edges) - 1), dtype=bool + ) + expected_flags[:, -1] = True + np.testing.assert_array_equal(quality_flags, expected_flags) + # all energy bins should have converged + # The first 2 didn't have enough events to calculate statistics, but they should + # still be marked as converged + assert np.all(convergence) + # All energy bins should have iterated 1 time except the last one which should have + # iterated twice. + assert np.all(iterations[:-1] == 1) + assert iterations[-1] == 2 + # Check that all std_diff values were set (not zero) except the last one + assert np.all(std_diff[:-1] != 0) + assert std_diff[-1] == 0 + + +def test_flag_statistical_outliers_invalid_events(): + """Tests flag_statistical_outliers function when there are no valid events.""" + energy_range_edges = np.array([3, 5, 7, 18, 25]) # Example energy bin edges + energy = np.arange(25) + de_dataset = xr.Dataset( + { + "de_event_met": ("epoch", np.arange(len(energy))), + "energy_spacecraft": ("epoch", energy), + "quality_outliers": ("epoch", np.full(len(energy), 0)), + "quality_scattering": ("epoch", np.full(len(energy), 0)), + "ebin": ("epoch", np.full(len(energy), 10)), + } + ) + spin_tbin_edges = np.arange( + start=0, stop=len(energy) + 1, step=5 + ) # create spin bins of 5 seconds + mask = np.ones((len(energy_range_edges) - 1, len(spin_tbin_edges) - 1), dtype=bool) + quality_flags, convergence, iterations, std_diff = flag_statistical_outliers( + de_dataset, + spin_tbin_edges, + energy_range_edges, + mask, + ) + # check that all flags are set because the mask marks all events as invalid. + np.testing.assert_array_equal( + quality_flags, np.ones_like(quality_flags, dtype=bool) + ) + # check that all energy bins are marked as converged (no valid events is not a + # failure case for convergence since we just can't calculate statistics. + assert np.all(convergence) + # check that there were no iterations + assert np.sum(iterations) == 0 + # Check that std_diff is all invalid (-1) + assert np.all(std_diff == -1) + + +def test_get_poisson_stats(): + """Tests get_poisson_stats function.""" + counts = np.full(20, 0) + counts[-1] = 100 # Make the last bin have high counts + std_diff, outlier_mask = get_poisson_stats(counts) + # std_diff should be counts/sqrt(counts) = sqrt(counts) + assert ( + std_diff == np.std(counts) / np.sqrt(5) - 1 + ) # std_diff should be counts/sqrt(counts) = sqrt(counts) + assert ( + np.sum(outlier_mask) == 1 + ) # Only the last bin should be flagged as an outlier + assert outlier_mask[-1] + + +@pytest.mark.external_test_data +def test_validate_stat_cull(setup_repoint_47_data): + """Validate that statistical-outlier quality flags match expected results.""" + # read test data from csv files + results_df = pd.read_csv( + TEST_PATH / "validate_stat_culling_results_repoint00047_v3.csv" + ) + de_ds, _, spin_tbin_edges = setup_repoint_47_data + # Get the energy ranges + energy_ranges = get_binned_energy_ranges(build_energy_bins()[0]) + + # Create a mask of flagged events to test that the stat cull algorithm + # properly ignores these. The test data was created using this exact mask as well. + mask = np.zeros((len(energy_ranges) - 1, len(spin_tbin_edges) - 1), dtype=bool) + mask[0:2, 0:2] = ( + True # This will mark the first 2 energy bins and first 2 spin bins as flagged + ) + # ignored in the statistics calculation and flagging. + flags, con, it, std = flag_statistical_outliers( + de_ds, spin_tbin_edges, energy_ranges, mask, 90 + ) + expected_qf = results_df.iloc[:, :-3].values.astype(bool) + converge = results_df["converge"].values + iterations = results_df["iterations"].values + std_diff = results_df["std_diff"].values + # check that the flags match the expected results + np.testing.assert_array_equal(flags, ~expected_qf.astype(bool)) + np.testing.assert_array_equal(con, converge) + np.testing.assert_array_equal(it, iterations) + np.testing.assert_allclose(std, std_diff, rtol=1e-10) + + +def test_get_energy_range_flags(): + """Tests get_binned_energy_range_flags function.""" + # Get energy bins used at l1c + intervals, _, _ = build_energy_bins() + # Get the energy ranges + energy_ranges = get_binned_energy_ranges(intervals) + flags = get_energy_range_flags(energy_ranges) + + np.testing.assert_array_equal(flags, 2 ** np.arange(6)) + + +def test_get_binned_energy_ranges(): + """Tests get_binned_energy_ranges function.""" + intervals, _, _ = build_energy_bins() + energy_ranges = get_binned_energy_ranges(intervals) + expected_energy_ranges = np.array( + [3.0, 6.96, 15.71, 34.9866, 77.9161, 116.276, 316.335] + ) + np.testing.assert_array_equal(energy_ranges, expected_energy_ranges) + + +@pytest.mark.external_test_data +def test_validate_upstream_ion_cull(setup_repoint_47_data): + """Validate that upstream ion quality flags match expected results.""" + # read test data from csv files + expected_results = pd.read_csv( + TEST_PATH / "validate_upstream_ion_1_culling_results_repoint00047_v1.csv" + ).to_numpy() + de_ds, _, spin_tbin_edges = setup_repoint_47_data + intervals, _, _ = build_energy_bins() + energy_ranges = get_binned_energy_ranges(intervals) + mask = np.zeros((len(energy_ranges) - 1, len(spin_tbin_edges) - 1), dtype=bool) + mask[0:2, 0:2] = ( + True # This will mark the first 2 energy bins and first 2 spin bins as flagged + ) + flags = flag_upstream_ion( + de_ds, + spin_tbin_edges, + energy_ranges, + mask, + UltraConstants.UPSTREAM_ION_ENERGY_CHANNELS_1, + 90, + ) + # Combine the flags with the mask to get the final expected results since the + # masked bins should be flagged as well. + results = flags | mask + np.testing.assert_array_equal(results, ~expected_results.astype(bool)) + + +@pytest.mark.external_test_data +def test_upstream_ion_cull_invalid_channels(setup_repoint_47_data): + """Validate upstream ion error handling.""" + de_ds, _, spin_tbin_edges = setup_repoint_47_data + intervals, _, _ = build_energy_bins() + energy_ranges = get_binned_energy_ranges(intervals) + mask = np.zeros((len(energy_ranges) - 1, len(spin_tbin_edges) - 1), dtype=bool) + with pytest.raises( + ValueError, + match="Channels provided for upstream ion flagging" + " must be within the bounds of the energy ranges.", + ): + flag_upstream_ion( + de_ds, + spin_tbin_edges, + energy_ranges, + mask, + [5, 6, 7], # Invalid channels that are out of bounds + 90, + ) + + +@pytest.mark.external_test_data +def test_validate_spectral_cull(setup_repoint_47_data): + """Validate that spectral flags match expected results.""" + # read test data from csv files + expected_results = pd.read_csv( + TEST_PATH / "validate_spectral_culling_results_repoint00047_v1.csv" + ).to_numpy() + de_ds, _, spin_tbin_edges = setup_repoint_47_data + intervals, _, _ = build_energy_bins() + energy_ranges = get_binned_energy_ranges(intervals) + mask = np.zeros((len(energy_ranges) - 1, len(spin_tbin_edges) - 1), dtype=bool) + mask[0:2, 0:2] = ( + True # This will mark the first 2 energy bins and first 2 spin bins as flagged + ) + flags = flag_spectral_events( + de_ds, + spin_tbin_edges, + energy_ranges, + UltraConstants.SPECTRAL_ENERGY_CHANNELS, + 90, + ) + results = flags | mask + np.testing.assert_array_equal(results, ~expected_results.astype(bool)) diff --git a/imap_processing/tests/ultra/unit/test_ultra_l1b_extended.py b/imap_processing/tests/ultra/unit/test_ultra_l1b_extended.py index 2cd124fd03..75ebe65571 100644 --- a/imap_processing/tests/ultra/unit/test_ultra_l1b_extended.py +++ b/imap_processing/tests/ultra/unit/test_ultra_l1b_extended.py @@ -3,10 +3,12 @@ import numpy as np import pandas as pd import pytest +from scipy.interpolate import RegularGridInterpolator from imap_processing import imap_module_directory from imap_processing.quality_flags import ImapDEOutliersUltraFlags -from imap_processing.spice.spin import get_spin_data +from imap_processing.spice.time import met_to_ttj2000ns, ttj2000ns_to_et +from imap_processing.ultra.constants import UltraConstants from imap_processing.ultra.l1b.lookup_utils import get_angular_profiles from imap_processing.ultra.l1b.ultra_l1b_extended import ( CoinType, @@ -21,16 +23,17 @@ get_de_energy_kev, get_de_velocity, get_efficiency, + get_efficiency_interpolator, get_energy_pulse_height, get_energy_ssd, - get_eventtimes, + get_event_times, get_front_x_position, get_front_y_position, get_fwhm, get_path_length, get_ph_tof_and_back_positions, get_phi_theta, - get_spin_number, + get_spin_info, get_ssd_back_position_and_tof_offset, get_ssd_tof, interpolate_fwhm, @@ -265,55 +268,55 @@ def test_get_de_velocity(test_fixture): np.testing.assert_allclose( v_x[test_tof > 0], - df_ph["vx"].astype("float").values[test_tof > 0], + -df_ph["vx"].astype("float").values[test_tof > 0], atol=1e-01, rtol=0, ) np.testing.assert_allclose( v_y[test_tof > 0], - df_ph["vy"].astype("float").values[test_tof > 0], + -df_ph["vy"].astype("float").values[test_tof > 0], atol=1e-01, rtol=0, ) np.testing.assert_allclose( v_z[test_tof > 0], - df_ph["vz"].astype("float").values[test_tof > 0], + -df_ph["vz"].astype("float").values[test_tof > 0], atol=1e-01, rtol=0, ) np.testing.assert_allclose( vhat[test_tof > 0][:, 0], - df_ph["vhatX"].astype("float").values[test_tof > 0], + -df_ph["vhatX"].astype("float").values[test_tof > 0], atol=1e-01, rtol=0, ) np.testing.assert_allclose( vhat[test_tof > 0][:, 1], - df_ph["vhatY"].astype("float").values[test_tof > 0], + -df_ph["vhatY"].astype("float").values[test_tof > 0], atol=1e-01, rtol=0, ) np.testing.assert_allclose( vhat[test_tof > 0][:, 2], - df_ph["vhatZ"].astype("float").values[test_tof > 0], + -df_ph["vhatZ"].astype("float").values[test_tof > 0], atol=1e-01, rtol=0, ) np.testing.assert_allclose( r[test_tof > 0][:, 0], - -df_ph["vhatX"].astype("float").values[test_tof > 0], + df_ph["vhatX"].astype("float").values[test_tof > 0], atol=1e-01, rtol=0, ) np.testing.assert_allclose( r[test_tof > 0][:, 1], - -df_ph["vhatY"].astype("float").values[test_tof > 0], + df_ph["vhatY"].astype("float").values[test_tof > 0], atol=1e-01, rtol=0, ) np.testing.assert_allclose( r[test_tof > 0][:, 2], - -df_ph["vhatZ"].astype("float").values[test_tof > 0], + df_ph["vhatZ"].astype("float").values[test_tof > 0], atol=1e-01, rtol=0, ) @@ -340,11 +343,7 @@ def test_get_de_energy_kev(test_fixture): df_ph = df_filt[np.isin(df_filt["StopType"], [StopType.PH.value])] df_ph = df_ph[df_ph["energy_revised"].astype("str") != "FILL"] - species_bin_ph = determine_species( - df_ph["TOF"].astype("float").to_numpy(), - df_ph["r"].astype("float").to_numpy(), - "PH", - ) + species_bin_ph = np.ones_like(df_ph["Energy"].values, dtype=np.uint8) test_xf, test_yf, test_xb, test_yb, test_d, test_tof = ( df_ph[col].astype("float").values for col in ["Xf", "Yf", "Xb", "Yb", "d", "TOF"] @@ -356,12 +355,13 @@ def test_get_de_energy_kev(test_fixture): test_d, test_tof, ) - - energy = get_de_energy_kev(v, species_bin_ph) + quality_flags = np.zeros_like(species_bin_ph) + energy = get_de_energy_kev(v, species_bin_ph, quality_flags) index_hydrogen = np.where(species_bin_ph == 1) actual_energy = energy[index_hydrogen[0]] expected_energy = df_ph["energy_revised"].astype("float") - + # All flags should be zero + assert np.sum(quality_flags) == 0 np.testing.assert_allclose(actual_energy, expected_energy, atol=1e-01, rtol=0) @@ -456,28 +456,47 @@ def test_get_ctof(test_fixture): @pytest.mark.external_test_data -def test_determine_species(test_fixture): +def test_determine_species(): """Tests determine_species function.""" - df_filt, _, _, _ = test_fixture - df_ph = df_filt[np.isin(df_filt["StopType"], [StopType.PH.value])] - df_ssd = df_filt[np.isin(df_filt["StopType"], [StopType.SSD.value])] - species_bin_ph = determine_species( - df_ph["TOF"].astype("float").to_numpy(), - df_ph["r"].astype("float").to_numpy(), + species_bin_ph_proton = determine_species( + np.array(UltraConstants.TOFXPH_SPECIES_GROUPS["proton"], dtype=np.uint8), "PH", ) - species_bin_ssd = determine_species( - df_ssd["TOF"].astype("float").to_numpy(), - df_ssd["r"].astype("float").to_numpy(), + species_bin_ph_non_proton = determine_species( + np.array(UltraConstants.TOFXPH_SPECIES_GROUPS["non_proton"], dtype=np.uint8), + "PH", + ) + + species_bin_ssd_proton = determine_species( + np.array(UltraConstants.TOFXE_SPECIES_GROUPS["proton"], dtype=np.uint8), + "SSD", + ) + + species_bin_ssd_non_proton = determine_species( + np.array(UltraConstants.TOFXE_SPECIES_GROUPS["non_proton"], dtype=np.uint8), "SSD", ) np.testing.assert_array_equal( - species_bin_ph, np.full(len(df_ph), 1, dtype=np.uint8) + species_bin_ph_proton, + np.full(len(UltraConstants.TOFXPH_SPECIES_GROUPS["proton"]), 1, dtype=np.uint8), ) np.testing.assert_array_equal( - species_bin_ssd, np.full(len(df_ssd), 1, dtype=np.uint8) + species_bin_ssd_proton, + np.full(len(UltraConstants.TOFXE_SPECIES_GROUPS["proton"]), 1, dtype=np.uint8), + ) + np.testing.assert_array_equal( + species_bin_ph_non_proton, + np.full( + len(UltraConstants.TOFXPH_SPECIES_GROUPS["non_proton"]), 0, dtype=np.uint8 + ), + ) + np.testing.assert_array_equal( + species_bin_ssd_non_proton, + np.full( + len(UltraConstants.TOFXE_SPECIES_GROUPS["non_proton"]), 0, dtype=np.uint8 + ), ) @@ -501,59 +520,93 @@ def test_get_phi_theta(test_fixture): @pytest.mark.external_test_data -def test_get_spin_number(test_fixture, use_fake_spin_data_for_time): - """Tests that get_spin_number assigns the correct spin number.""" +def test_get_eventtimes(test_fixture, aux_dataset): + """Tests get_eventtimes function.""" df_filt, _, _, de_dataset = test_fixture - # Simulate a spin table from MET = 0 to MET = 500*15 seconds - use_fake_spin_data_for_time(start_met=0, end_met=500 * 15) + event_times, spin_start_times = get_event_times( + aux_dataset, + de_dataset["shcoarse"].values, + de_dataset["phase_angle"].values, + ) + + # Check shapes + assert ( + event_times.shape == spin_start_times.shape == de_dataset["phase_angle"].shape + ) - de_met = np.array([0, 0, 5760, 5760, 5760, 5760, 5760, 5760]) - de_spin = np.array([128, 128, 129, 129, 130, 130, 131, 131], dtype=np.uint8) + t1_start_sec = aux_dataset["timespinstart"].values[0] + t1_start_subsec = aux_dataset["timespinstartsub"].values[0] + t1_start_dur = aux_dataset["duration"].values[0] - spin_number = get_spin_number(de_met, de_spin) + expected_first_event_time = ( + t1_start_sec + + (t1_start_subsec + t1_start_dur * de_dataset["phase_angle"].values[0] / 720.0) + / 1000.0 + ) + # Check first event + assert ( + ttj2000ns_to_et(met_to_ttj2000ns(expected_first_event_time)) == event_times[0] + ) - assert np.array_equal(spin_number & 0xFF, de_spin) + # Check that each calculated event times fall within the expected range + # Use the coarse time to determine the expected range + spin_starts = ttj2000ns_to_et(met_to_ttj2000ns(aux_dataset["timespinstart"].values)) + for i, coarse_time in enumerate(de_dataset["shcoarse"].values): + boundary = np.searchsorted(spin_starts, coarse_time, side="right") - 1 + if boundary < 0 or boundary >= len(spin_starts) - 1: + continue + start_time = spin_starts[boundary] + end_time = spin_starts[boundary + 1] + assert start_time <= int(event_times[i]) <= end_time @pytest.mark.external_test_data -def test_get_eventtimes(test_fixture, use_fake_spin_data_for_time): - """Tests get_eventtimes function.""" +def test_get_spin_and_duration(test_fixture, aux_dataset): + """Tests get_spin_info function.""" df_filt, _, _, de_dataset = test_fixture - # Create a spin table that cover spin 0-141 - use_fake_spin_data_for_time(0, 141 * 15) - event_times, spin_starts, spin_period_sec = get_eventtimes( - de_dataset["spin"].values, de_dataset["phase_angle"].values + spin_ds = get_spin_info( + aux_dataset, + de_dataset["shcoarse"].values, ) - spin_df = get_spin_data() - expected_min_df = spin_df[spin_df["spin_number"] == de_dataset["spin"].values.min()] - expected_max_df = spin_df[spin_df["spin_number"] == de_dataset["spin"].values.max()] - spin_period_sec_min = expected_min_df["spin_period_sec"].values[0] - spin_period_sec_max = expected_max_df["spin_period_sec"].values[0] - - spin_start_min = ( - expected_min_df["spin_start_sec_sclk"] - + expected_min_df["spin_start_subsec_sclk"] / 1e6 - ) - spin_start_max = ( - expected_max_df["spin_start_sec_sclk"] - + expected_max_df["spin_start_subsec_sclk"] / 1e6 + # Check shapes + assert ( + spin_ds.spin_number.shape + == spin_ds.spin_duration.shape + == de_dataset["shcoarse"].shape ) - assert spin_start_min.values[0] == spin_starts.min() - assert spin_start_max.values[0] == spin_starts.max() + t1_spin_number = aux_dataset["spinnumber"].values[0] + t1_start_dur = aux_dataset["duration"].values[0] + # Check the first event spin number and duration + assert spin_ds.spin_number[0] == t1_spin_number + assert spin_ds.spin_duration[0] == t1_start_dur - event_times_min = spin_start_min.values[0] + spin_period_sec_min * ( - de_dataset["phase_angle"][0] / 720 - ) - event_times_max = spin_start_max.values[0] + spin_period_sec_max * ( - de_dataset["phase_angle"][-1] / 720 - ) - assert event_times_min == event_times.min() - assert event_times_max == event_times.max() +@pytest.mark.external_test_data +def test_get_event_times_out_of_range( + test_fixture, aux_dataset, use_fake_spin_data_for_time +): + """Tests get_event_times with out of range values.""" + df_filt, _, _, de_dataset = test_fixture + # Get min time from aux_dataset + min_time = aux_dataset["timespinstart"].values.min() + # Set some coarse times to be out of range (less than min_time) + coarse_times = de_dataset["shcoarse"].values.copy() + # Set first coarse time to be out of range of the aux data + coarse_times[0] = min_time - 1000 + # set spin data that DOES cover the range of coarse_times + use_fake_spin_data_for_time(min_time - 1000, min_time + 10000) + # This should not raise an error. + event_times, spin_starts = get_event_times( + aux_dataset, + coarse_times, + de_dataset["phase_angle"].values, + ) + assert event_times.shape == coarse_times.shape + assert spin_starts.shape == coarse_times.shape @pytest.mark.external_test_data @@ -643,7 +696,7 @@ def test_get_efficiency(): / "imap_ultra_l1b-45sensor-logistic-interpolation_20250101_v000.csv" } - efficiency = get_efficiency(energy, phi, theta, ancillary_files) + efficiency = get_efficiency(energy, phi, theta, ancillary_files, "ultra45") expected_efficiency = np.array([0.0593281, 0.21803386, 0.0593281, 0.0628940]) np.testing.assert_allclose(efficiency, expected_efficiency, atol=1e-03, rtol=0) @@ -712,15 +765,24 @@ def test_is_back_tof_valid(test_fixture, ancillary_files): df_filt, _, _, de_dataset = test_fixture df_ph = df_filt[np.isin(df_filt["StopType"], [StopType.PH.value])] - valid = is_back_tof_valid( - de_dataset, - df_filt.Xf.astype("float").values, + # Get the ph inds + ph_mask = ( + (de_dataset["stop_type"] == StopType.Top.value) + | (de_dataset["stop_type"] == StopType.Bottom.value) + ).values + quality_flags = np.zeros(len(np.nonzero(ph_mask)[0]), dtype=np.uint16) + valid, quality_flags = is_back_tof_valid( + de_dataset.isel(epoch=np.nonzero(ph_mask)[0]), + df_filt.Xf.astype("float").values[ph_mask], "ultra45", ancillary_files, + quality_flags, ) + back_tof_valid_bool = df_ph["BackTOFValid"].astype(int).astype(bool).values np.testing.assert_equal(back_tof_valid_bool, valid) + assert np.any(quality_flags) @pytest.mark.external_test_data @@ -729,14 +791,47 @@ def test_is_coin_ph_valid(test_fixture, ancillary_files): df_filt, _, _, de_dataset = test_fixture df_ph = df_filt[np.isin(df_filt["StopType"], [StopType.PH.value])] - valid = is_coin_ph_valid( - df_ph["eTOF"].astype(float).values, - df_ph["Xc"].astype(float).values, - df_ph["Xb"].astype(float).values, + # Test data + ctof = df_ph["cTOF"].astype(float).values + etof = df_ph["eTOF"].astype(float).values + xc = df_ph["Xc"].astype(float).values + xb = df_ph["Xb"].astype(float).values + stop_north_tdc = df_ph["StopNorthTDC"].astype(int).values + stop_south_tdc = df_ph["StopSouthTDC"].astype(int).values + stop_east_tdc = df_ph["StopEastTDC"].astype(int).values + stop_west_tdc = df_ph["StopWestTDC"].astype(int).values + quality_flags = np.full( + len(ctof), ImapDEOutliersUltraFlags.NONE.value, dtype=np.uint16 + ) + + combined_mask, quality_flags = is_coin_ph_valid( + etof, + xc, + xb, + stop_north_tdc, + stop_south_tdc, + stop_east_tdc, + stop_west_tdc, "ultra45", ancillary_files, + quality_flags, ) - coin_ph_valid_bool = df_ph["CoinPHValid"].astype(int).astype(bool).values - valid = np.asarray(valid, dtype=bool) - np.testing.assert_equal(coin_ph_valid_bool, valid) + assert len(etof) == np.count_nonzero(combined_mask) + np.count_nonzero( + quality_flags + ) + + +@pytest.mark.external_test_data +def test_get_efficiency_interpolator(ancillary_files): + + # Test that the interpolator is created and that the min/max values are correct + eff_interpolator, theta_min_max, phi_min_max, e_min_max = ( + get_efficiency_interpolator(ancillary_files, "ultra45") + ) + + assert isinstance(eff_interpolator, RegularGridInterpolator) + + assert theta_min_max == (-52.7, 52.7) + assert phi_min_max == (-60, 60) + assert e_min_max == (3, 80) diff --git a/imap_processing/tests/ultra/unit/test_ultra_l1c.py b/imap_processing/tests/ultra/unit/test_ultra_l1c.py index 72df701d99..bb8b8d1d40 100644 --- a/imap_processing/tests/ultra/unit/test_ultra_l1c.py +++ b/imap_processing/tests/ultra/unit/test_ultra_l1c.py @@ -1,5 +1,6 @@ from unittest import mock +import astropy_healpix.healpy as hp import numpy as np import pandas as pd import pytest @@ -8,6 +9,9 @@ from imap_processing import imap_module_directory from imap_processing.cdf.utils import write_cdf from imap_processing.spice.geometry import SpiceFrame +from imap_processing.spice.time import ( + et_to_met, +) from imap_processing.ultra.l1b.ultra_l1b_annotated import ( get_annotated_particle_velocity, ) @@ -58,22 +62,22 @@ def mock_data_l1b_dict(): data_vars=data_vars_histogram, coords=coords, attrs=attrs_histogram ) - data_vars_cullingmask = { + data_vars_goodtimes = { "spin_number": ("epoch", np.zeros(5)), } - attrs_cullingmask = { - "Logical_source": "imap_ultra_l1b_45sensor-cullingmask", + attrs_goodtimes = { + "Logical_source": "imap_ultra_l1b_45sensor-goodtimes", "Logical_source_description": "IMAP Mission ULTRA Instrument " "Level-1B Culling Mask Data", } - dataset_cullingmask = xr.Dataset( - data_vars_cullingmask, coords={"epoch": epoch}, attrs=attrs_cullingmask + dataset_goodtimes = xr.Dataset( + data_vars_goodtimes, coords={"epoch": epoch}, attrs=attrs_goodtimes ) data_dict = { - "imap_ultra_l1b_45sensor-cullingmask": dataset_cullingmask, + "imap_ultra_l1b_45sensor-goodtimes": dataset_goodtimes, "imap_ultra_l1a_45sensor-histogram": dataset_histogram, } return data_dict @@ -102,30 +106,6 @@ def test_create_dataset(mock_data_l1c_dict): np.testing.assert_array_equal(dataset["sid"], np.zeros(3)) -def test_ultra_l1c(mock_data_l1b_dict): - """Tests that L1c data is created.""" - path = imap_module_directory / "tests" / "ultra" / "data" / "l1" - ancillary_files = { - "l1c-90sensor-dps-exposure": path - / "imap_ultra_l1c-90sensor-dps-exposure_20250101_v000.csv", - "l1c-90sensor-efficiencies": path - / "imap_ultra_l1c-90sensor-efficiencies_20250101_v000.csv", - "l1c-90sensor-gf": path / "imap_ultra_l1c-90sensor-gf_20250101_v000.csv", - } - - output_datasets = ultra_l1c(mock_data_l1b_dict, ancillary_files, has_spice=False) - - assert len(output_datasets) == 1 - assert ( - output_datasets[0].attrs["Logical_source"] - == "imap_ultra_l1c_45sensor-histogram" - ) - assert ( - output_datasets[0].attrs["Logical_source_description"] - == "IMAP-Ultra Instrument Level-1C Pointing Set Grid Histogram Data." - ) - - def test_ultra_l1c_error(mock_data_l1b_dict): """Tests that L1b data throws an error.""" mock_data_l1b_dict["bad_key"] = mock_data_l1b_dict.pop( @@ -135,15 +115,16 @@ def test_ultra_l1c_error(mock_data_l1b_dict): with pytest.raises( ValueError, match="Data dictionary does not contain the expected keys." ): - ultra_l1c(mock_data_l1b_dict, ancillary_files, has_spice=False) + ultra_l1c(mock_data_l1b_dict, ancillary_files, "45sensor-spacecraftpset") @pytest.mark.external_test_data @pytest.mark.external_kernel def test_calculate_spacecraft_pset_with_cdf( - random_spin_data, ancillary_files, - deadtime_datasets, + rates_dataset, + aux_dataset, + mock_goodtimes_dataset, imap_ena_sim_metakernel, use_fake_spin_data_for_time, mock_spacecraft_pointing_lookups, @@ -158,7 +139,11 @@ def test_calculate_spacecraft_pset_with_cdf( df_subset = df[df["pointing_number"] == pointing].copy() de_dict = {} - + # Ensure rate and aux data are in the correct time window + t_rates = np.linspace(0, 141 * 15, len(rates_dataset.shcoarse.data)) + rates_dataset.shcoarse.data = t_rates + aux_dataset.timespinstart.data = t_rates[: len(aux_dataset.timespinstart.data)] + aux_dataset.timespinstart.data[-1] = t_rates[-1] de_dict["epoch"] = df_subset["epoch"].values species_bin = np.full(len(df_subset), 1, dtype=np.uint8) @@ -191,24 +176,35 @@ def test_calculate_spacecraft_pset_with_cdf( de_dict["velocity_dps_sc"] = sc_dps_velocity de_dict["energy_spacecraft"] = get_de_energy_kev(sc_dps_velocity, species_bin) # Made up data for spin_number and energy_bin_geometric_mean - de_dict["spin_number"] = np.full(len(sc_dps_velocity), 128) - de_dict["energy_bin_geometric_mean"] = np.zeros(len(sc_dps_velocity)) + de_dict["spin"] = np.full(len(sc_dps_velocity), 0) de_dict["species"] = np.ones(len(sc_dps_velocity), dtype=np.uint8) + de_dict["ebin"] = np.ones(len(sc_dps_velocity), dtype=np.uint8) + de_dict["theta"] = np.zeros(len(df_subset), dtype=np.float32) + de_dict["phi"] = np.zeros(len(df_subset), dtype=np.float32) + de_dict["event_times"] = df_subset["tdb"].values name = "imap_ultra_l1b_45sensor-de" dataset = create_dataset(de_dict, name, "l1b") - + dataset.attrs["Repointing"] = "repoint00001" data_dict = { "imap_ultra_l1b_45sensor-de": dataset, "imap_ultra_l1b_45sensor-extendedspin": dataset, # placeholder - "imap_ultra_l1b_45sensor-cullingmask": dataset, # placeholder - "imap_ultra_l1a_45sensor-rates": deadtime_datasets["rates"], - "imap_ultra_l1a_45sensor-params": deadtime_datasets["params"], + "imap_ultra_l1b_45sensor-goodtimes": mock_goodtimes_dataset, # placeholder + "imap_ultra_l1a_45sensor-rates": rates_dataset, + "imap_ultra_l1a_45sensor-aux": aux_dataset, } - - output_datasets = ultra_l1c(data_dict, ancillary_files, has_spice=False) + with ( + mock.patch( + "imap_processing.ultra.l1c.spacecraft_pset.get_pointing_times_from_id", + return_value=(482374890.0, 482374000.0), + ), + ): + output_datasets = ultra_l1c( + data_dict, ancillary_files, "45sensor-spacecraftpset" + ) output_datasets[0].attrs["Data_version"] = "999" output_datasets[0].attrs["Repointing"] = f"repoint{pointing + 1:05d}" + output_datasets[0].attrs["Start_date"] = "20250415" test_data_path = write_cdf(output_datasets[0], istp=True) assert test_data_path.exists() @@ -221,27 +217,38 @@ def test_calculate_spacecraft_pset_with_cdf( @pytest.mark.external_test_data @pytest.mark.external_kernel def test_calculate_helio_pset_with_cdf( - random_spin_data, ancillary_files, imap_ena_sim_metakernel, - mock_spacecraft_pointing_lookups, - deadtime_datasets, + mock_helio_pointing_lookups, + aux_dataset, + rates_dataset, + mock_goodtimes_dataset, use_fake_spin_data_for_time, ): """Tests ultra_l1c function with imported test data.""" # Simulate a spin table from MET = 0 to MET = 141 * 15 seconds - use_fake_spin_data_for_time(start_met=0, end_met=141 * 15) + use_fake_spin_data_for_time( + start_met=et_to_met(817561854.185627), + end_met=et_to_met(817561854.185627 + 141 * 15), + ) df = pd.read_csv(TEST_PATH / "IMAP-Ultra45_r1_L1_V0_shortened.csv") + # Ensure rate and aux data are in the correct time window + t_off = 56970125 + rates_dataset.shcoarse.data += t_off + aux_dataset.timespinstart.data += t_off # Select a single pointing number pointing = 0 df_subset = df[df["pointing_number"] == pointing].copy() - de_dict = {} de_dict["epoch"] = df_subset["epoch"].values + de_dict["spin"] = np.full((len(df_subset["epoch"].values)), 0) # Fake SCLK in seconds that matches SPICE. de_dict["event_times"] = np.full(len(df_subset), 2.41187e13) + de_dict["ebin"] = np.ones(len(df_subset), dtype=np.uint8) + de_dict["theta"] = np.zeros(len(df_subset), dtype=np.float32) + de_dict["phi"] = np.zeros(len(df_subset), dtype=np.float32) species_bin = np.full(len(df_subset), 1, dtype=np.uint8) # PosYSlit is True for left (start_type = 1) @@ -273,24 +280,44 @@ def test_calculate_helio_pset_with_cdf( de_dict["quality_scattering"] = np.zeros(len(helio_dps_velocity), dtype=np.uint16) de_dict["quality_outliers"] = np.zeros(len(helio_dps_velocity), dtype=np.uint16) de_dict["species"] = np.ones(len(helio_dps_velocity), dtype=np.uint8) + de_dict["event_times"] = df_subset["tdb"].values name = "imap_ultra_l1b_45sensor-de" dataset = create_dataset(de_dict, name, "l1b") - + dataset.attrs["Repointing"] = "repoint00001" data_dict = { "imap_ultra_l1b_45sensor-de": dataset, "imap_ultra_l1b_45sensor-extendedspin": xr.Dataset(), # placeholder - "imap_ultra_l1b_45sensor-cullingmask": xr.Dataset(), # placeholder - "imap_ultra_l1a_45sensor-rates": deadtime_datasets["rates"], - "imap_ultra_l1a_45sensor-params": deadtime_datasets["params"], + "imap_ultra_l1b_45sensor-goodtimes": mock_goodtimes_dataset, + "imap_ultra_l1a_45sensor-rates": rates_dataset, + "imap_ultra_l1a_45sensor-aux": aux_dataset, } - with mock.patch( - "imap_processing.ultra.l1c.helio_pset.get_pointing_times", - return_value=(482374890.0, 482374000.0), + n_pix = hp.nside2npix(32) + mock_eff = np.ones((46, n_pix)) + mock_gf = mock_eff * 2 + with ( + mock.patch( + "imap_processing.ultra.l1c.helio_pset.get_pointing_times_from_id", + return_value=(482374890.0, 482374000.0), + ), + # Mock efficiencies and geometric function to known values + mock.patch( + "imap_processing.ultra.l1c.helio_pset.get_efficiencies_and_geometric_function", + return_value=(mock_gf, mock_eff), + ), ): - output_datasets = ultra_l1c(data_dict, ancillary_files, has_spice=True) + output_datasets = ultra_l1c(data_dict, ancillary_files, "45sensor-heliopset") output_datasets[0].attrs["Data_version"] = "999" output_datasets[0].attrs["Repointing"] = f"repoint{pointing + 1:05d}" + + # Although the arrays are different, their sums should be equal. The helio adjusted + # ones are just rebinned. + np.testing.assert_array_equal( + np.sum(output_datasets[0]["efficiency"]), np.sum(mock_eff) + ) + np.testing.assert_array_equal( + np.sum(output_datasets[0]["geometric_function"]), np.sum(mock_gf) + ) test_data_path = write_cdf(output_datasets[0], istp=True) assert test_data_path.exists() diff --git a/imap_processing/tests/ultra/unit/test_ultra_l1c_culling.py b/imap_processing/tests/ultra/unit/test_ultra_l1c_culling.py index 4224226c6b..217283c570 100644 --- a/imap_processing/tests/ultra/unit/test_ultra_l1c_culling.py +++ b/imap_processing/tests/ultra/unit/test_ultra_l1c_culling.py @@ -5,6 +5,7 @@ import pytest import spiceypy +from imap_processing.quality_flags import ImapPSETUltraFlags from imap_processing.spice.geometry import SpiceBody from imap_processing.ultra.l1c.ultra_l1c_culling import compute_culling_mask @@ -18,7 +19,7 @@ def test_compute_culling_mask(furnish_kernels, spice_test_data_path): } kernels = [ - "imap_science_100.tf", + "imap_science_120.tf", "sim_1yr_imap_pointing_frame.bc", "imap_spk_demo.bsp", "imap_sclk_0000.tsc", @@ -32,9 +33,17 @@ def test_compute_culling_mask(furnish_kernels, spice_test_data_path): et_end = 817644684.1856259 step_seconds = 1800 # 30 minutes et_steps = np.arange(et_start, et_end, step_seconds) + nside = 128 + npix = hp.nside2npix(nside) + + spacecraft_pset_quality_flags = np.full( + npix, ImapPSETUltraFlags.NONE.value, dtype=np.uint16 + ) with furnish_kernels(kernels): - mask, _ = compute_culling_mask(et_steps, keepout_radius_km) + mask, _ = compute_culling_mask( + et_steps, keepout_radius_km, spacecraft_pset_quality_flags + ) assert mask.shape[0] == len(et_steps) assert mask.shape[1] == hp.nside2npix(128) @@ -50,7 +59,7 @@ def test_compare_sincpt_with_culling_mask_deterministic(furnish_kernels): with furnish_kernels( [ - "imap_science_100.tf", + "imap_science_120.tf", "imap_sclk_0000.tsc", "sim_1yr_imap_pointing_frame.bc", "imap_spk_demo.bsp", @@ -60,13 +69,37 @@ def test_compare_sincpt_with_culling_mask_deterministic(furnish_kernels): "de440s.bsp", ] ): - et = np.array([817561854.185627]) + et = np.array([817561854.185627, 817561854.185628]) keepout_radius_km = 6378.1 # Earth radius nside = 128 + npix = hp.nside2npix(nside) + spacecraft_pset_quality_flags = np.full( + npix, ImapPSETUltraFlags.NONE.value, dtype=np.uint16 + ) # Compute culling mask and IMAP-to-Earth unit vector mask, unit_vectors = compute_culling_mask( - et, keepout_radius_km, observer=SpiceBody.EARTH, nside=nside + et, + keepout_radius_km, + spacecraft_pset_quality_flags, + observer=SpiceBody.EARTH, + nside=nside, + ) + + culled = np.any(~mask, axis=0) + # Culled pixels must have the flag set (bitwise check is safest) + assert np.all( + (spacecraft_pset_quality_flags[culled] & ImapPSETUltraFlags.EARTH_FOV.value) + == ImapPSETUltraFlags.EARTH_FOV.value + ) + + # Non-culled pixels must not have the flag + assert np.all( + ( + spacecraft_pset_quality_flags[~culled] + & ImapPSETUltraFlags.EARTH_FOV.value + ) + == 0 ) # Computes the 3D unit vectors pointing to the centers of all HEALPix pixels diff --git a/imap_processing/tests/ultra/unit/test_ultra_l1c_pset_bins.py b/imap_processing/tests/ultra/unit/test_ultra_l1c_pset_bins.py index a05e89ee4e..9fedf82fae 100644 --- a/imap_processing/tests/ultra/unit/test_ultra_l1c_pset_bins.py +++ b/imap_processing/tests/ultra/unit/test_ultra_l1c_pset_bins.py @@ -1,5 +1,6 @@ "Tests pointing sets" +import logging from unittest import mock import astropy_healpix.healpy as hp @@ -7,19 +8,21 @@ import pandas as pd import pytest import xarray as xr +from scipy import interpolate from imap_processing import imap_module_directory +from imap_processing.ultra.constants import UltraConstants from imap_processing.ultra.l1c import ultra_l1c_pset_bins from imap_processing.ultra.l1c.spacecraft_pset import ( - calculate_pixels_within_scattering_threshold, + calculate_accepted_pixels, ) from imap_processing.ultra.l1c.ultra_l1c_pset_bins import ( - apply_deadtime_correction, build_energy_bins, + calculate_exposure_time, get_deadtime_ratios, get_deadtime_ratios_by_spin_phase, + get_efficiencies_and_geometric_function, get_energy_delta_minus_plus, - get_helio_adjusted_data, get_sectored_rates, get_spacecraft_background_rates, get_spacecraft_count_rate_uncertainty, @@ -31,6 +34,25 @@ TEST_PATH = imap_module_directory / "tests" / "ultra" / "data" / "l1" +@pytest.fixture +def spun_index_data(ancillary_files): + """Spun index test data fixture.""" + nside = 8 + pix = hp.nside2npix(nside) + steps = 500 # Reduced for testing + np.random.seed(42) + mock_theta = np.random.uniform(-60, 60, (steps, pix)) + mock_phi = np.random.uniform(-60, 60, (steps, pix)) + spin_phase_steps = xr.DataArray( + np.zeros((steps, pix)).astype(bool), dims=("spin_phase_step", "pixel") + ) + # Simulate first 100 pixels are in the FOR for all spin phases + inside_inds = 100 + spin_phase_steps[:, :inside_inds] = True + + return mock_theta, mock_phi, spin_phase_steps, inside_inds, pix, steps + + @pytest.fixture def test_data(): """Test data fixture.""" @@ -49,15 +71,15 @@ def test_build_energy_bins(): energy_bin_start = [interval[0] for interval in intervals] energy_bin_end = [interval[1] for interval in intervals] - assert energy_bin_start[0] == 3.385 - assert np.allclose(energy_bin_start[1], 4.137, atol=1e-3) - assert len(intervals) == 24 + assert energy_bin_start[0] == 3 + assert np.allclose(energy_bin_start[1], 3.4, atol=1e-3) + assert len(intervals) == 46 assert energy_midpoints[0] == (energy_bin_start[0] + energy_bin_end[0]) / 2 # Comparison to expected values. - np.testing.assert_allclose(energy_bin_end[1], 5.056, atol=1e-3) - np.testing.assert_allclose(energy_bin_start[-1], 341.989, atol=1e-3) - np.testing.assert_allclose(energy_bin_end[-1], 100000, atol=1e-3) + np.testing.assert_allclose(energy_bin_end[1], 3.8) + np.testing.assert_allclose(energy_bin_start[-1], 286.208, atol=1e-3) + np.testing.assert_allclose(energy_bin_end[-1], 316.334, atol=1e-3) expected_geometric_means = np.sqrt( np.array(energy_bin_start) * np.array(energy_bin_end) @@ -77,7 +99,7 @@ def test_get_energy_delta_minus_plus(monkeypatch): expected_bins_energy_delta_plus = np.array([1, 3, 13, 1134]) expected_bins_energy_delta_minus = np.array([0, 1, 2, 80]) - def mock_build_energy_bins(): + def mock_build_energy_bins(energy_bins=None): return mock_intervals, mock_midpoints, mock_geometric_means monkeypatch.setattr( @@ -96,16 +118,12 @@ def test_get_spacecraft_histogram(test_data): energy_bin_edges, _, _ = build_energy_bins() subset_energy_bin_edges = energy_bin_edges[:3] - hist, latitude, longitude, n_pix = get_spacecraft_histogram( - v, energy, subset_energy_bin_edges, nside=1 - ) + hist, n_pix = get_spacecraft_histogram(v, energy, subset_energy_bin_edges, nside=1) assert hist.shape == (len(subset_energy_bin_edges), hp.nside2npix(1)) assert n_pix == hp.nside2npix(1) - assert latitude.shape == (n_pix,) - assert longitude.shape == (n_pix,) - # Spot check that 1 count is in the first energy bin - assert np.sum(hist[1, :]) == 2 + # Spot check that 2 counts are in the second energy bin + assert np.sum(hist[2, :]) == 2 # Test overlapping energy bins overlapping_bins = [ @@ -113,14 +131,10 @@ def test_get_spacecraft_histogram(test_data): (2.5, 4.137), (3.385, 5.057), ] - hist, latitude, longitude, n_pix = get_spacecraft_histogram( - v, energy, overlapping_bins, nside=1 - ) + hist, n_pix = get_spacecraft_histogram(v, energy, overlapping_bins, nside=1) # Spot check that 3 counts are in the third energy bin assert np.sum(hist[2, :]) == 3 assert n_pix == hp.nside2npix(1) - assert latitude.shape == (n_pix,) - assert longitude.shape == (n_pix,) def mock_imap_state(time, ref_frame): @@ -128,52 +142,33 @@ def mock_imap_state(time, ref_frame): return np.array([0, 0, 0, 0, 0, 0]) -def test_get_sectored_rates(): +def test_get_sectored_rates(rates_dataset): """Tests get_sectored_rates function.""" + sectored_rates = get_sectored_rates(rates_dataset) + expected_sectored_rates = rates_dataset.isel(epoch=slice(14, None)) + xr.testing.assert_equal(sectored_rates, expected_sectored_rates) - # Simulate a test rates dataset. - epoch = 60 - test_l1a_rates_dataset = xr.Dataset( - { - "test_data": (["epoch"], np.arange(epoch)), - }, - ) - # Sector mode (image rates cadence = 3) happens 3 times a day (per pointing). - # each time the mode changes, it is recorded in the params packet. - # Create a test params dataset that simulates the mode changing to 3, 3 times. - modes = np.tile(np.array([1, 3]), 3) - test_l1a_params_dataset = xr.Dataset( - { - "imageratescadence": (["epoch"], modes), - }, - coords={"epoch": ("epoch", np.arange(0, epoch, epoch / len(modes)))}, - ) - sectored_rates = get_sectored_rates(test_l1a_rates_dataset, test_l1a_params_dataset) - np.testing.assert_array_equal( - sectored_rates["test_data"].data, - np.hstack([np.arange(10, 20), np.arange(30, 40), np.arange(50, 60)]), - ) - # Test with one mode shift in the middle of the dataset. - modes = np.array([1, 3, 1]) - test_l1a_params_dataset = xr.Dataset( - { - "imageratescadence": (["epoch"], modes), - }, - coords={"epoch": ("epoch", np.arange(0, epoch, epoch / len(modes)))}, - ) - sectored_rates = get_sectored_rates(test_l1a_rates_dataset, test_l1a_params_dataset) - np.testing.assert_array_equal(sectored_rates["test_data"].data, np.arange(20, 40)) - # Test with one mode shift in the middle of the dataset. - modes = np.array([1, 3, 1]) - test_l1a_params_dataset = xr.Dataset( +def test_get_sectored_rates_manual(): + """Tests get_sectored_rates function.""" + # This dataset has 2 sections where it goes into sectored mode. + test_spins = np.concatenate([np.full(15, 0), np.array([10, 11]), np.full(15, 12)]) + rates_dataset = xr.Dataset( { - "imageratescadence": (["epoch"], modes), - }, - coords={"epoch": ("epoch", np.arange(0, epoch, epoch / len(modes)))}, + "epoch": ("epoch", np.arange(32)), + "spin": ("epoch", test_spins), + } ) - sectored_rates = get_sectored_rates(test_l1a_rates_dataset, test_l1a_params_dataset) - np.testing.assert_array_equal(sectored_rates["test_data"].data, np.arange(20, 40)) + sectored_rates = get_sectored_rates(rates_dataset) + # The sectored rates should be the first and last 15 epochs. + expected_sectored_rates = xr.concat( + [ + rates_dataset.isel(epoch=slice(0, 15)), + rates_dataset.isel(epoch=slice(17, 32)), + ], + dim="epoch", + ) + xr.testing.assert_equal(sectored_rates, expected_sectored_rates) def test_get_deadtime_ratios(): @@ -193,14 +188,16 @@ def test_get_deadtime_ratios(): "stop_bn": (["epoch"], np.random.randint(0, 5, epoch)), } ) + durations = np.full(epoch, 15) + sectored_rates_ds["spin_durations"] = (["epoch"], durations) deadtime_correction_factors = get_deadtime_ratios(sectored_rates_ds) assert deadtime_correction_factors.shape == (sectored_rates_ds.sizes["epoch"],) assert np.all(deadtime_correction_factors >= 0) -def test_get_deadtime_interpolator(random_spin_data): +def test_get_deadtime_interpolator(use_fake_spin_data_for_time, aux_dataset): """Tests get_deadtime_correction_factors function.""" - + use_fake_spin_data_for_time(1, 10) sector_rate_seconds = 20 * 60 # 20 minutes in seconds num_sectors = 3 # Number of sectors per pointing num_spins = sector_rate_seconds * num_sectors / 15 # 15 seconds per spin @@ -211,13 +208,18 @@ def test_get_deadtime_interpolator(random_spin_data): deadtime_ratios = xr.DataArray( np.random.uniform(0.1, 1.0, num_deadtimes), dims=["epoch"] ) - sectored_rates_ds = xr.Dataset({"epoch": ("epoch", np.ones_like(deadtime_ratios))}) + sectored_rates_ds = xr.Dataset( + {"epoch": ("epoch", np.ones_like(deadtime_ratios))}, + {"shcoarse": ("epoch", np.ones_like(deadtime_ratios))}, + ) with mock.patch( "imap_processing.ultra.l1c.ultra_l1c_pset_bins.get_deadtime_ratios", return_value=deadtime_ratios, ): - deadtime_ratios = get_deadtime_ratios_by_spin_phase(sectored_rates_ds) - np.testing.assert_array_equal(deadtime_ratios.shape, (15000)) + deadtime_ratios = get_deadtime_ratios_by_spin_phase( + sectored_rates_ds, aux_dataset, spin_steps=num_deadtimes + ) + np.testing.assert_array_equal(deadtime_ratios.shape, (num_deadtimes)) with mock.patch( "imap_processing.ultra.l1c.ultra_l1c_pset_bins.get_deadtime_ratios", @@ -226,107 +228,219 @@ def test_get_deadtime_interpolator(random_spin_data): # Assert value error is raised for NaN values with pytest.raises( ValueError, - match="Dead time ratios contain NaN values, cannot create interpolator.", + match="All dead time ratios are NaN, cannot interpolate", ): - get_deadtime_ratios_by_spin_phase(sectored_rates_ds) + get_deadtime_ratios_by_spin_phase( + sectored_rates_ds, aux_dataset, spin_steps=num_deadtimes + ) + + +@pytest.mark.external_test_data +def test_get_deadtime_interpolator_no_sectored_rates(ancillary_files, aux_dataset): + """Tests get_deadtime_correction_factors function.""" + + num_deadtimes = 15000 # Standard number of spin phases + sensor = 45 + # If the sectored rates dataset is None, the function should use the + # static deadtime ratios lookup. + dt_ratios = get_deadtime_ratios_by_spin_phase( + sectored_rates=None, + aux_dataset=aux_dataset, + spin_steps=num_deadtimes, + sensor_id=sensor, + ancillary_files=ancillary_files, + ) + spin_phase, dts = ultra_l1c_pset_bins.get_static_deadtime_ratios( + sensor, ancillary_files + ) + # Calculate the nominal spin phases at the supplied resolution and query the pchip + # interpolator to get the deadtime ratios. + nominal_spin_phases = np.arange(0, 360, 360 / num_deadtimes) + expected_dt_ratios = interpolate.PchipInterpolator(spin_phase, dts)( + nominal_spin_phases + ) + np.testing.assert_array_equal(dt_ratios, expected_dt_ratios) @pytest.mark.external_kernel -def test_apply_deadtime_correction(imap_ena_sim_metakernel, ancillary_files): +def test_apply_deadtime_correction( + imap_ena_sim_metakernel, ancillary_files, spun_index_data +): """Tests apply_deadtime_correction function.""" - nside = 8 - pix = hp.nside2npix(nside) - steps = 500 # Reduced for testing - mock_theta = np.random.uniform(-60, 60, (pix, steps)) - mock_phi = np.random.uniform(-60, 60, (pix, steps)) - spin_phase_steps = np.zeros((pix, steps)).astype(bool) # Spin phase steps 1-15000, - # Simulate first 100 pixels are in the FOR for all spin phases - inside_inds = 100 - spin_phase_steps[:inside_inds, :] = True - deadtime_ratios = np.ones(steps) - exposure_pointing = pd.Series(np.ones(pix)) + mock_theta, mock_phi, spin_phase_steps, inside_inds, pix, steps = spun_index_data + deadtime_ratios = xr.DataArray(np.ones(steps), dims="spin_phase_step") + valid_spun_pixels, fwhm_theta, fwhm_phi, thresholds = calculate_accepted_pixels( + spin_phase_steps, + mock_theta, + mock_phi, + ancillary_files, + 45, + reject_scattering=False, + ) + boundary_sf = xr.DataArray(np.ones((pix, steps)), dims=("pixel", "spin_phase_step")) + exposure_pointing_adjusted = calculate_exposure_time( + deadtime_ratios, + valid_spun_pixels, + boundary_sf, + apply_bsf=True, + ) + # The adjusted exposure should be of shape (46,npix) + np.testing.assert_array_equal(exposure_pointing_adjusted.shape, (46, pix)) + # Check that the pixels inside the FOR have adjusted exposure > 0. + assert np.all(exposure_pointing_adjusted[:, :inside_inds] > 0) + # Assert that pixels outside the FOR remain at 0. + assert np.all(exposure_pointing_adjusted[:, inside_inds:] == 0) + # Test that fwhm values are not all nans or zeros + assert np.any(fwhm_theta > 0) + assert np.any(fwhm_phi > 0) - pixels_below_threshold = calculate_pixels_within_scattering_threshold( - spin_phase_steps, mock_theta, mock_phi, ancillary_files, 45 + +@pytest.mark.external_kernel +def test_apply_deadtime_correction_energy_dep( + imap_ena_sim_metakernel, ancillary_files, spun_index_data +): + """Tests apply_deadtime_correction function when scattering rejection is on.""" + mock_theta, mock_phi, spin_phase_steps, inside_inds, pix, steps = spun_index_data + deadtime_ratios = xr.DataArray(np.ones(steps), dims="spin_phase_step") + boundary_sf = xr.DataArray(np.ones((steps, pix)), dims=("spin_phase_step", "pixel")) + + valid_spun_pixels, fwhm_theta, fwhm_phi, thresholds = calculate_accepted_pixels( + spin_phase_steps, + mock_theta, + mock_phi, + ancillary_files, + 45, + reject_scattering=True, ) - boundary_sf = np.ones((pix, steps)) - exposure_pointing_adjusted = apply_deadtime_correction( - exposure_pointing, deadtime_ratios, pixels_below_threshold, boundary_sf + + exposure_pointing_adjusted = calculate_exposure_time( + deadtime_ratios, + valid_spun_pixels, + boundary_sf, + apply_bsf=True, ) - # The adjusted exposure should now be a function of pixels and energy (24) - np.testing.assert_array_equal(exposure_pointing_adjusted.shape, (24, pix)) - # Check that the pixels inside the FOR have adjusted exposure > 1.0 + # The adjusted exposure should be of shape (46,npix) + np.testing.assert_array_equal(exposure_pointing_adjusted.shape, (46, pix)) + # Check that the pixels inside the FOR have adjusted exposure > 0. # Subset the energy dimension to check values in the last energy bin. These # Should have pixels that are below the FWHM scattering threshold and therefore, # have the exposure adjusted. - last_energy_bin_vals = np.where(build_energy_bins()[2] >= 30)[0] - assert np.all(exposure_pointing_adjusted[last_energy_bin_vals, :inside_inds] > 1.0) - # Assert that pixels outside the FOR remain at 1.0 - assert np.all(exposure_pointing_adjusted[:, inside_inds:] == 1.0) + last_energy_bin_vals = np.where(build_energy_bins()[2] >= 40)[0] + assert np.all(exposure_pointing_adjusted[last_energy_bin_vals, :inside_inds] > 0) + # Assert that pixels outside the FOR remain at 0. + assert np.all(exposure_pointing_adjusted[:, inside_inds:] == 0) + + +@pytest.mark.external_kernel +def test_get_eff_and_gf(imap_ena_sim_metakernel, ancillary_files, spun_index_data): + """Tests apply_deadtime_correction function when scattering rejection is on.""" + nside = 8 + pix = hp.nside2npix(nside) + steps = 5 # Reduced for testing + energy_dim = 46 + np.random.seed(42) + mock_theta = np.random.uniform(-60, 60, (steps, energy_dim, pix)) + mock_phi = np.random.uniform(-60, 60, (steps, energy_dim, pix)) + spin_phase_steps = xr.DataArray( + np.zeros((steps, energy_dim, pix)).astype(bool), + dims=("spin_phase_step", "energy", "pixel"), + ) + # Simulate first 100 pixels are in the FOR for all spin phases + inside_inds = 100 + spin_phase_steps[:, :, :inside_inds] = True + valid_spun_pixels, fwhm_theta, fwhm_phi, thresholds = calculate_accepted_pixels( + spin_phase_steps, + mock_theta, + mock_phi, + ancillary_files, + 45, + reject_scattering=False, + ) + boundary_sf = xr.DataArray( + np.ones((steps, energy_dim, pix)), dims=("spin_phase_step", "energy", "pixel") + ) + eff, gf = get_efficiencies_and_geometric_function( + valid_spun_pixels, + boundary_sf, + mock_theta, + mock_phi, + npix=pix, + sensor_id=45, + ancillary_files=ancillary_files, + apply_bsf=False, + ) + # The efficiencies should be of shape (energy_dim,npix) + np.testing.assert_array_equal(eff.shape, (energy_dim, pix)) + np.testing.assert_array_equal(gf.shape, (energy_dim, pix)) + # Check that the pixels inside the FOR have efficiencies and geometric factors > 0. + assert np.all(eff[:, :inside_inds] > 0) + assert np.all(gf[:, :inside_inds] > 0) + # Assert that pixels outside the FOR remain at 0. + assert np.all(eff[:, inside_inds:] == 0) + assert np.all(gf[:, inside_inds:] == 0) @pytest.mark.external_test_data def test_get_spacecraft_exposure_times( - deadtime_datasets, random_spin_data, imap_ena_sim_metakernel, ancillary_files + rates_dataset, + imap_ena_sim_metakernel, + ancillary_files, + use_fake_spin_data_for_time, + aux_dataset, + mock_goodtimes_dataset, + caplog, ): """Test get_spacecraft_exposure_times function.""" - constant_exposure = ( - TEST_PATH / "imap_ultra_l1c-90sensor-dps-exposure_20250101_v000.csv" - ) - steps = 500 # reduced for testing - rates = deadtime_datasets["rates"] - params = deadtime_datasets["params"] - shape = 786 - df_exposure = pd.read_csv(constant_exposure)[:shape] # Subset for testing - - pix = len(df_exposure) - mock_theta = np.random.uniform(-60, 60, (pix, steps)) - mock_phi = np.random.uniform(-60, 60, (pix, steps)) - spin_phase_steps = np.random.randint(0, 2, (pix, steps)).astype( - bool + data_start_time = 445015665.0 + data_end_time = 453070000.0 + use_fake_spin_data_for_time(data_start_time, data_end_time) + steps = 200 # reduced for testing + + pix = 786 + mock_theta = np.random.uniform(-60, 60, (steps, pix)) + mock_phi = np.random.uniform(-60, 60, (steps, pix)) + np.random.seed(42) + spin_phase_steps = xr.DataArray( + np.random.randint(0, 2, (steps, pix)).astype(bool), + dims=("spin_phase_step", "pixel"), ) # Spin phase steps, random 0 or 1 - pixels_below_threshold = calculate_pixels_within_scattering_threshold( - spin_phase_steps, mock_theta, mock_phi, ancillary_files, 45 + pixels_below_threshold, fwhm_theta, fwhm_phi, thresholds = ( + calculate_accepted_pixels( + spin_phase_steps, mock_theta, mock_phi, ancillary_files, 45 + ) ) - boundary_sf = np.ones((pix, steps)) - exposure_pointing, deadtimes = get_spacecraft_exposure_times( - df_exposure, rates, params, pixels_below_threshold, boundary_sf + boundary_sf = xr.DataArray(np.ones((steps, pix)), dims=("spin_phase_step", "pixel")) + caplog.set_level(logging.INFO) + ( + exposure_pointing, + deadtimes, + ) = get_spacecraft_exposure_times( + rates_dataset, + pixels_below_threshold, + boundary_sf, + aux_dataset, + build_energy_bins()[2], + goodtimes_dataset=mock_goodtimes_dataset, ) - np.testing.assert_array_equal(exposure_pointing.shape, (24, shape)) - np.testing.assert_array_equal(deadtimes.shape, (15000,)) - - -@pytest.mark.external_kernel -def test_get_helio_exposure_time_and_sensitivity(imap_ena_sim_metakernel): - """Tests get_helio_exposure_times function.""" - - start_time = 829485054.185627 - end_time = 829567884.185627 - - mid_time = np.average([start_time, end_time]) - - _, energy_midpoints, _ = build_energy_bins() - nside = 128 - npix = hp.nside2npix(nside) - shape = (len(energy_midpoints), npix) - exposure = np.ones(shape) - eff = np.ones(shape) - gf = np.ones(shape) - mock_ra = np.random.uniform(-80, 80, (npix)) - mock_dec = np.random.uniform(-80, 80, (npix)) - - helio_exposure, helio_eff, helio_gf = get_helio_adjusted_data( - mid_time, exposure, gf, eff, mock_ra, mock_dec - ) - - for helio_array, array in zip( - [helio_exposure, helio_eff, helio_gf], [exposure, eff, gf], strict=False - ): - total_input = np.sum(array) - total_output = np.sum(total_input) - assert np.allclose(total_input, total_output, atol=1e-6) - assert helio_array.shape == shape + np.testing.assert_array_equal(exposure_pointing.shape, (46, pix)) + np.testing.assert_array_equal(deadtimes.shape, (steps,)) + + # Check that the number of good spins per energy bin is logged correctly + # The first 3 energy bins were not used in the goodtimes culling and therefore + # should have all 100 spins. + # Energy range 1,2,3 (which maps to the next UltraConstants.N_CULL_EBINS * 3 bins) + # should have 99 spins because there was a flag set to true for one spin + # in the mock_goodtimes_dataset. The rest of the energy bins should have 100 spins + # because the goodtimes dataset did not flag any spins for those energy bins. + expected_good_spins = np.full(46, 100.0) + expected_good_spins[ + UltraConstants.BASE_CULL_EBIN : UltraConstants.N_CULL_EBINS * 3 + + UltraConstants.BASE_CULL_EBIN + ] = 99.0 + # The goodtimes dataset has flags set to True for energy bin 0-3 and for the + # first three spins. + assert f"Found {expected_good_spins.tolist()} valid spins" in caplog.text def test_get_spacecraft_background_rates( @@ -335,6 +449,23 @@ def test_get_spacecraft_background_rates( "Tests calculate_background_rates function." # Simulate a spin table from MET = 0 to MET = 141 * 15 seconds use_fake_spin_data_for_time(start_met=0, end_met=141 * 15) + + # Should be evenly spaced spins of 15 seconds each except the first one has 14. + num_spins = 15 + spin_start_times = np.concatenate([[0], np.arange(14, 222, num_spins)]) + 445015651 + spin_numbers = np.arange(127, 142) + num_spins = len(spin_numbers) + + aux_ds = xr.Dataset( + data_vars={ + "timespinstart": ("epoch", spin_start_times), + "timespinstartsub": ("epoch", np.ones_like(spin_start_times)), + "duration": ("epoch", np.full(num_spins, 15)), + "spinnumber": ("epoch", spin_numbers), + }, + coords={"epoch": ("epoch", np.arange(num_spins))}, + ) + df = pd.read_csv(rates_l1_test_path) rates = { @@ -360,10 +491,15 @@ def test_get_spacecraft_background_rates( "spin": df["Spin"], } energy_bin_edges, _, _ = build_energy_bins() - cullingmask_spin_number = np.array([130, 131]) + goodtimes_spin_number = np.array([130, 131]) background_rates = get_spacecraft_background_rates( - rates, "ultra45", ancillary_files, energy_bin_edges, cullingmask_spin_number + rates, + aux_ds, + "ultra45", + ancillary_files, + energy_bin_edges, + goodtimes_spin_number, ) assert background_rates.shape == (len(energy_bin_edges), hp.nside2npix(128)) diff --git a/imap_processing/tests/ultra/unit/test_ultra_l2.py b/imap_processing/tests/ultra/unit/test_ultra_l2.py index bd3a9a7e59..c5faa01c8c 100644 --- a/imap_processing/tests/ultra/unit/test_ultra_l2.py +++ b/imap_processing/tests/ultra/unit/test_ultra_l2.py @@ -7,11 +7,28 @@ import xarray as xr from astropy_healpix.healpy import nside2pixarea +from imap_processing import imap_module_directory from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes +from imap_processing.cdf.utils import write_cdf from imap_processing.ena_maps import ena_maps from imap_processing.ena_maps.utils.coordinates import CoordNames +from imap_processing.quality_flags import ImapPSETUltraFlags from imap_processing.tests.ultra.mock_data import mock_l1c_pset_product_healpix +from imap_processing.ultra.l1c.ultra_l1c_pset_bins import get_energy_delta_minus_plus from imap_processing.ultra.l2 import ultra_l2 +from imap_processing.ultra.l2.ultra_l2 import ( + VARIABLES_TO_AVERAGE_OVER_COARSE_ENERGY_BINS, + build_default_coarse_bin_edges, +) + +ENERGY_BIN_EDGES_PATH = ( + imap_module_directory + / "tests" + / "ultra" + / "data" + / "l2" + / "imap_ultra_l2-energy-bin-group-sizes_20250101_v000.csv" +) class TestUltraL2: @@ -19,7 +36,7 @@ class TestUltraL2: def _setup_spice_kernels_list(self, spice_test_data_path, furnish_kernels): self.required_kernel_names = [ "naif0012.tls", - "imap_science_100.tf", + "imap_science_120.tf", "imap_sclk_0000.tsc", "sim_1yr_imap_attitude.bc", "sim_1yr_imap_pointing_frame.bc", @@ -29,7 +46,11 @@ def _setup_spice_kernels_list(self, spice_test_data_path, furnish_kernels): def _mock_single_pset(self, _setup_spice_kernels_list, furnish_kernels): with furnish_kernels(self.required_kernel_names): self.ultra_pset = mock_l1c_pset_product_healpix( - nside=128, stripe_center_lat=0, timestr="2025-05-15T12:00:00" + nside=16, + counts_nside=32, + stripe_center_lat=0, + timestr="2025-05-15T12:00:00", + energy_dependent_exposure=True, ) @pytest.fixture @@ -45,13 +66,15 @@ def _mock_multiple_psets(self, _setup_spice_kernels_list, furnish_kernels): with furnish_kernels(self.required_kernel_names): self.ultra_psets = [ mock_l1c_pset_product_healpix( - nside=128, + nside=16, + counts_nside=32, stripe_center_lat=mid_latitude, width_scale=5, counts_scaling_params=(50, 0.5), peak_exposure=1000, timestr=manual_timestrs[i], head=("90"), + energy_dependent_exposure=True, ) for i, mid_latitude in enumerate( np.arange( @@ -61,6 +84,11 @@ def _mock_multiple_psets(self, _setup_spice_kernels_list, furnish_kernels): ) ) ] + # Add extra ultra specific variables to each pset + for pset in self.ultra_psets: + pset["efficiency"] = xr.ones_like(pset["sensitivity"]) + pset["scatter_theta"] = xr.ones_like(pset["sensitivity"]) + pset["scatter_phi"] = xr.ones_like(pset["sensitivity"]) self.psets_total_counts = np.sum( [pset["counts"].values.sum() for pset in self.ultra_psets] @@ -84,28 +112,130 @@ def mock_data_dict(self, _mock_multiple_psets): ], ) @pytest.mark.usefixtures("_mock_single_pset", "_setup_spice_kernels_list") - def test_generate_ultra_healpix_skymap_single_pset( + def test_generate_ultra_rectangular_skymap_single_pset( self, epoch_dim_for_energy_delta, map_frame, rtol, furnish_kernels ): # Avoid modifying the original pset - pset = self.ultra_pset.copy(deep=True) + pset = mock_l1c_pset_product_healpix( + nside=128, + stripe_center_lat=0, + timestr="2025-05-15T12:00:00", + energy_dependent_exposure=True, + ) + # Set the values in the single input PSET for easy calculation + # of the expected ena_intensity and ena_intensity statistical uncertainty] + counts_fillval = 10 + pset["counts"].values = np.full_like(pset["counts"].values, counts_fillval) + pset["exposure_factor"].values = np.ones_like(pset["exposure_factor"]) + pset["background_rates"].values = np.ones_like(pset["background_rates"].values) + pset["sensitivity"].values = np.ones_like(pset["sensitivity"].values) + pset["geometric_function"].values = np.ones_like(pset["sensitivity"].values) + pset["energy_bin_delta"].values = np.ones_like(pset["energy_bin_delta"].values) + pset["efficiency"] = xr.ones_like(pset["sensitivity"]) + pset["scatter_theta"] = xr.ones_like(pset["sensitivity"]) + pset["scatter_phi"] = xr.ones_like(pset["sensitivity"]) + + pset["energy_bin_delta"].values = np.ones_like(pset["energy_bin_delta"].values) + if epoch_dim_for_energy_delta: + # add an extra dim to the start + pset["energy_bin_delta"] = pset["energy_bin_delta"].expand_dims( + {CoordNames.TIME.value: pset["epoch"].values} + ) + # Create the rectangular skymap in the desired frame. + with furnish_kernels(self.required_kernel_names): + rec_skymap, _ = ultra_l2.generate_ultra_skymap( + ultra_l1c_psets=[ + pset, + ], + output_map_structure=ena_maps.AbstractSkyMap.from_properties_dict( + { + "sky_tiling_type": "RECTANGULAR", + "spice_reference_frame": "ECLIPJ2000", + "values_to_push_project": [ + "counts", + ], + "values_to_pull_project": [ + "exposure_factor", + "sensitivity", + "geometric_function", + "efficiency", + "scatter_theta", + "scatter_phi", + "background_rates", + ], + "spacing_deg": 2.0, + } + ), + build_rectangular_map=True, + ) + + assert rec_skymap.spacing_deg == 2.0 + # Check that required variables are present, and dropped variables are not + expected_vars = [ + "counts", + "background_rates", + "obs_date_range", + "exposure_factor", + "sensitivity", + "geometric_function", + "efficiency", + "scatter_theta", + "scatter_phi", + "obs_date", + ] + for var in expected_vars: + assert var in rec_skymap.data_1d.data_vars + unexpected_vars = ultra_l2.VARIABLES_TO_DROP_AFTER_INTENSITY_CALCULATION + for var in unexpected_vars: + assert var not in rec_skymap.data_1d.data_vars + + @pytest.mark.parametrize("epoch_dim_for_energy_delta", [True, False]) + @pytest.mark.parametrize( + ["map_frame", "rtol"], + [ + # Tight tolerance when 'projecting' to the same frame + ("IMAP_DPS", 1e-8), + # Loose tolerance of 30% error vs naive ena_intensity + # estimate with real projection. + # TODO: Ideally this tolerance will tighten if we can fix the issue with + # the exposure time for uneven numbers of pixels from each PointingSet. + ("ECLIPJ2000", 3e-1), + ], + ) + @pytest.mark.usefixtures("_mock_single_pset", "_setup_spice_kernels_list") + def test_generate_ultra_healpix_skymap_single_pset( + self, epoch_dim_for_energy_delta, map_frame, rtol, furnish_kernels + ): + # Avoid modifying the original pset + pset = mock_l1c_pset_product_healpix( + nside=128, + stripe_center_lat=0, + timestr="2025-05-15T12:00:00", + energy_dependent_exposure=True, + ) # Set the values in the single input PSET for easy calculation # of the expected ena_intensity and ena_intensity statistical uncertainty - pset["counts"].values = np.full_like(pset["counts"].values, 10) - pset["exposure_factor"].values = np.ones_like(pset["exposure_factor"].values) + counts_fillval = 10 + pset["counts"].values = np.full_like(pset["counts"].values, counts_fillval) + pset["exposure_factor"].values = np.ones_like(pset["exposure_factor"]) pset["background_rates"].values = np.ones_like(pset["background_rates"].values) pset["sensitivity"].values = np.ones_like(pset["sensitivity"].values) + pset["geometric_function"].values = np.ones_like(pset["sensitivity"].values) + pset["energy_bin_delta"].values = np.ones_like(pset["energy_bin_delta"].values) + pset["efficiency"] = xr.ones_like(pset["sensitivity"]) + pset["scatter_theta"] = xr.ones_like(pset["sensitivity"]) + pset["scatter_phi"] = xr.ones_like(pset["sensitivity"]) + pset["energy_bin_delta"].values = np.ones_like(pset["energy_bin_delta"].values) if epoch_dim_for_energy_delta: # add an extra dim to the start pset["energy_bin_delta"] = pset["energy_bin_delta"].expand_dims( {CoordNames.TIME.value: pset["epoch"].values} ) - # Create the Healpix skymap in the desired frame. with furnish_kernels(self.required_kernel_names): - hp_skymap, _ = ultra_l2.generate_ultra_healpix_skymap( + hp_skymap, _ = ultra_l2.generate_ultra_skymap( ultra_l1c_psets=[ pset, ], @@ -119,6 +249,10 @@ def test_generate_ultra_healpix_skymap_single_pset( "values_to_pull_project": [ "exposure_factor", "sensitivity", + "geometric_function", + "efficiency", + "scatter_theta", + "scatter_phi", "background_rates", ], "nside": 32, @@ -132,9 +266,17 @@ def test_generate_ultra_healpix_skymap_single_pset( # Check that required variables are present, and dropped variables are not expected_vars = [ + "counts", + "background_rates", "ena_intensity", - "ena_intensity_stat_unc", + "obs_date_range", + "ena_intensity_stat_uncert", "exposure_factor", + "sensitivity", + "geometric_function", + "efficiency", + "scatter_theta", + "scatter_phi", "obs_date", ] for var in expected_vars: @@ -151,11 +293,28 @@ def test_generate_ultra_healpix_skymap_single_pset( # Estimate the expected ena_intensity and its uncertainty expected_ena_intensity = ( - (10 * solid_angle_ratio_map_to_pset / 1) - 1 * solid_angle_ratio_map_to_pset + counts_fillval * solid_angle_ratio_map_to_pset / 1 ) / (1 * hp_skymap.solid_angle * 1) + # 4 fine bins per coarse bin + binned_counts = ( + np.full( + (len(hp_skymap.data_1d["energy_bin_geometric_mean"])), counts_fillval + ) + * 4 + ) + # last bin only has 2 fine bins + binned_counts[-1] = counts_fillval * 2 + energy_bin_deltas = np.full(12, 4) + # The last delta is 2 instead of 4 + energy_bin_deltas[-1] = 2 expected_ena_intensity_unc = ( - (10 * solid_angle_ratio_map_to_pset) ** 0.5 / 1 - ) / (1 * hp_skymap.solid_angle * 1) + (binned_counts * solid_angle_ratio_map_to_pset) ** 0.5 / 1 + ) / (1 * hp_skymap.solid_angle * energy_bin_deltas) + + n_pixels = hp_skymap.data_1d["ena_intensity_stat_uncert"].shape[2] + expected_ena_intensity_unc = np.tile( + expected_ena_intensity_unc[np.newaxis, :, np.newaxis], (1, 1, n_pixels) + ) np.testing.assert_allclose( hp_skymap.data_1d["ena_intensity"].values, @@ -163,11 +322,101 @@ def test_generate_ultra_healpix_skymap_single_pset( rtol=rtol, ) np.testing.assert_allclose( - hp_skymap.data_1d["ena_intensity_stat_unc"].values, expected_ena_intensity_unc, + hp_skymap.data_1d["ena_intensity_stat_uncert"].values, rtol=rtol, ) + @pytest.mark.parametrize("epoch_dim_for_energy_delta", [True, False]) + @pytest.mark.parametrize( + ["map_frame", "rtol"], + [ + # Tight tolerance when 'projecting' to the same frame + ("IMAP_DPS", 1e-8), + # Loose tolerance of 30% error vs naive ena_intensity + # estimate with real projection. + # TODO: Ideally this tolerance will tighten if we can fix the issue with + # the exposure time for uneven numbers of pixels from each PointingSet. + ("ECLIPJ2000", 3e-1), + ], + ) + @pytest.mark.usefixtures("_mock_single_pset", "_setup_spice_kernels_list") + def test_generate_ultra_healpix_skymap_quality_flag( + self, epoch_dim_for_energy_delta, map_frame, rtol, furnish_kernels + ): + # Avoid modifying the original pset + pset = self.ultra_pset.copy(deep=True) + + # Set the values in the single input PSET for easy calculation + # of the expected ena_intensity and ena_intensity statistical uncertainty + pset["counts"].values = np.full_like(pset["counts"].values, 10) + pset["exposure_factor"].values = np.ones_like(pset["exposure_factor"].values) + pset["background_rates"].values = np.ones_like(pset["background_rates"].values) + pset["sensitivity"].values = np.ones_like(pset["sensitivity"].values) + pset["energy_bin_delta"].values = np.ones_like(pset["energy_bin_delta"].values) + + pset_quality = pset.copy(deep=True) + # Flag every other pixel (e.g., even indices) + pset_quality["quality_flags"][0, ::2] = ImapPSETUltraFlags.EARTH_FOV.value + + if epoch_dim_for_energy_delta: + # add an extra dim to the start + pset["energy_bin_delta"] = pset["energy_bin_delta"].expand_dims( + {CoordNames.TIME.value: pset["epoch"].values} + ) + + # Create the Healpix skymap in the desired frame. + with furnish_kernels(self.required_kernel_names): + hp_skymap, _ = ultra_l2.generate_ultra_skymap( + ultra_l1c_psets=[pset, pset_quality], + output_map_structure=ena_maps.AbstractSkyMap.from_properties_dict( + { + "sky_tiling_type": "HEALPIX", + "spice_reference_frame": map_frame, + "values_to_push_project": [ + "counts", + ], + "values_to_pull_project": [ + "exposure_factor", + "sensitivity", + "background_rates", + ], + "nside": 32, + "nested": False, + } + ), + ) + + assert hp_skymap.nside == 32 + assert hp_skymap.nested is False + + # Check that required variables are present, and dropped variables are not + expected_vars = [ + "counts", + "background_rates", + "ena_intensity", + "obs_date_range", + "ena_intensity_stat_uncert", + "exposure_factor", + "obs_date", + ] + for var in expected_vars: + assert var in hp_skymap.data_1d.data_vars + unexpected_vars = ultra_l2.VARIABLES_TO_DROP_AFTER_INTENSITY_CALCULATION + for var in unexpected_vars: + assert var not in hp_skymap.data_1d.data_vars + + energy_bins = 46 # Original number of fine energy bins + n_pix = 12288 + n_counts = 10 * energy_bins * n_pix * 1.5 + + # The total counts in the skymap should be equal to the sum of the counts + # in the individual psets + np.testing.assert_allclose( + hp_skymap.data_1d["counts"].sum(), + n_counts, + ) + @pytest.mark.usefixtures("_mock_multiple_psets", "_setup_spice_kernels_list") def test_generate_ultra_healpix_skymap_multiple_psets(self, furnish_kernels): with patch( @@ -175,7 +424,7 @@ def test_generate_ultra_healpix_skymap_multiple_psets(self, furnish_kernels): [], ): with furnish_kernels(self.required_kernel_names): - hp_skymap, pset_epochs = ultra_l2.generate_ultra_healpix_skymap( + hp_skymap, pset_epochs = ultra_l2.generate_ultra_skymap( ultra_l1c_psets=self.ultra_psets, output_map_structure=ena_maps.AbstractSkyMap.from_properties_dict( { @@ -204,14 +453,19 @@ def test_generate_ultra_healpix_skymap_multiple_psets(self, furnish_kernels): hp_skymap.data_1d["counts"].sum(), self.psets_total_counts, ) - + # The pointing independent variables should have been pulled once + np.testing.assert_allclose( + hp_skymap.data_1d["geometric_function"], + np.ones_like(hp_skymap.data_1d["geometric_function"]), + ) # The map should contain the following variables, # because we did not drop any variables expected_vars = ( ultra_l2.REQUIRED_L1C_VARIABLES_PUSH + ultra_l2.REQUIRED_L1C_VARIABLES_PULL + ultra_l2.VARIABLES_TO_DROP_AFTER_INTENSITY_CALCULATION - + ["ena_intensity", "ena_intensity_stat_unc"] + + ultra_l2.EXPECTED_L1C_POINTING_INDEPENDENT_VARIABLES_PULL + + ["ena_intensity", "ena_intensity_stat_uncert"] ) for var in expected_vars: assert var in hp_skymap.data_1d.data_vars @@ -222,14 +476,23 @@ def test_generate_ultra_healpix_skymap_multiple_psets(self, furnish_kernels): CoordNames.ENERGY_ULTRA_L1C.value, CoordNames.GENERIC_PIXEL.value, ) - assert hp_skymap.data_1d["counts"].dims == counts_dims - assert hp_skymap.data_1d["ena_intensity"].dims == counts_dims - assert hp_skymap.data_1d["ena_intensity_stat_unc"].dims == counts_dims - assert hp_skymap.data_1d["exposure_factor"].dims == ( - CoordNames.TIME.value, + pointing_independent_dims = ( + CoordNames.ENERGY_ULTRA_L1C.value, CoordNames.GENERIC_PIXEL.value, ) + assert hp_skymap.data_1d["counts"].dims == counts_dims + assert hp_skymap.data_1d["ena_intensity"].dims == counts_dims + assert hp_skymap.data_1d["ena_intensity_stat_uncert"].dims == counts_dims + assert hp_skymap.data_1d["exposure_factor"].dims == counts_dims + assert hp_skymap.data_1d["background_rates"].dims == counts_dims + + assert hp_skymap.data_1d["sensitivity"].dims == pointing_independent_dims + assert hp_skymap.data_1d["efficiency"].dims == pointing_independent_dims + assert hp_skymap.data_1d["geometric_function"].dims == pointing_independent_dims + assert hp_skymap.data_1d["scatter_theta"].dims == pointing_independent_dims + assert hp_skymap.data_1d["scatter_phi"].dims == pointing_independent_dims + @pytest.mark.external_test_data @pytest.mark.usefixtures("_setup_spice_kernels_list") def test_ultra_l2_output_unbinned_healpix(self, mock_data_dict, furnish_kernels): map_structure = ena_maps.AbstractSkyMap.from_properties_dict( @@ -242,6 +505,11 @@ def test_ultra_l2_output_unbinned_healpix(self, mock_data_dict, furnish_kernels) "values_to_pull_project": [ "exposure_factor", "sensitivity", + "efficiency", + "sensitivity", + "geometric_function", + "scatter_theta", + "scatter_phi", ], "nside": 16, "nested": True, @@ -253,6 +521,7 @@ def test_ultra_l2_output_unbinned_healpix(self, mock_data_dict, furnish_kernels) ] = ultra_l2.ultra_l2( data_dict=mock_data_dict, output_map_structure=map_structure, + energy_bin_edges_file=ENERGY_BIN_EDGES_PATH, ) assert ( @@ -287,6 +556,22 @@ def test_ultra_l2_output_unbinned_healpix(self, mock_data_dict, furnish_kernels) ) assert map_dataset["solid_angle"].attrs["UNITS"] == "sr" + # Check that the positional uncertainty variables were renamed + assert "positional_uncert_theta" in map_dataset + assert "positional_uncert_phi" in map_dataset + # Check that background_rates was renamed to bg_rate + assert "bg_rate" in map_dataset + # Check energy deltas + assert "energy_delta_plus" in map_dataset + assert "energy_delta_minus" in map_dataset + # Check epoch deltas + assert map_dataset["epoch"].attrs["DELTA_PLUS_VAR"] == "epoch_delta" + assert map_dataset["epoch"].attrs["DELTA_MINUS_VAR"] == "epoch_delta_minus" + assert "epoch_delta" in map_dataset + assert "epoch_delta_minus" in map_dataset + np.testing.assert_array_equal(map_dataset["epoch_delta_minus"].values, 0) + + @pytest.mark.external_test_data @pytest.mark.usefixtures("_setup_spice_kernels_list") def test_ultra_l2_rectangular(self, mock_data_dict, furnish_kernels): rect_map_structure = ena_maps.AbstractSkyMap.from_properties_dict( @@ -325,12 +610,14 @@ def test_ultra_l2_rectangular(self, mock_data_dict, furnish_kernels): ] = ultra_l2.ultra_l2( data_dict=mock_data_dict, output_map_structure=rect_map_structure, + energy_bin_edges_file=ENERGY_BIN_EDGES_PATH, store_subdivision_depth=False, ) [ hp_map_dataset, ] = ultra_l2.ultra_l2( data_dict=mock_data_dict, + energy_bin_edges_file=ENERGY_BIN_EDGES_PATH, output_map_structure=hp_map_structure, ) @@ -351,14 +638,10 @@ def test_ultra_l2_rectangular(self, mock_data_dict, furnish_kernels): ) assert rect_map_dataset["ena_intensity"].dims == expected_ena_intensity_dims assert ( - rect_map_dataset["ena_intensity_stat_unc"].dims + rect_map_dataset["ena_intensity_stat_uncert"].dims == expected_ena_intensity_dims ) - assert rect_map_dataset["exposure_factor"].dims == ( - CoordNames.TIME.value, - CoordNames.AZIMUTH_L2.value, - CoordNames.ELEVATION_L2.value, - ) + assert rect_map_dataset["exposure_factor"].dims == expected_ena_intensity_dims # Check that '_label' coordinates were added for all coordinates except 'epoch' for coord_var in expected_ena_intensity_dims[1:]: @@ -373,9 +656,12 @@ def test_ultra_l2_rectangular(self, mock_data_dict, furnish_kernels): np.testing.assert_allclose( rect_map_dataset["ena_intensity"].mean(), hp_map_dataset["ena_intensity"].mean(), - rtol=1e-2, + rtol=3e-1, atol=1e-12, ) + # Check energy deltas + assert "energy_delta_plus" in rect_map_dataset + assert "energy_delta_minus" in rect_map_dataset # Variable Metadata spot checks ena_intensity_attrs = rect_map_dataset["ena_intensity"].attrs @@ -386,7 +672,7 @@ def test_ultra_l2_rectangular(self, mock_data_dict, furnish_kernels): assert ( ena_intensity_attrs[f"LABL_PTR_{depend_num}"] == f"{depend}_label" ) - assert ena_intensity_attrs["UNITS"] == "counts/(s * cm^2 * Sr * KeV)" + assert ena_intensity_attrs["UNITS"] == "cm -2 s -1 sr -1 keV -1" exposure_attrs = rect_map_dataset["exposure_factor"].attrs assert exposure_attrs["VAR_TYPE"] == "data" @@ -525,19 +811,249 @@ def test_ultra_l2_descriptor_rectmap(self, mock_data_dict, furnish_kernels): assert output_map.attrs["Spice_reference_frame"] == "IMAP_HAE" assert output_map.attrs["Spacing_degrees"] == "6.0" + # Variable Metadata spot checks + assert ( + output_map["ena_intensity"].attrs["CATDESC"] + == "IMAP Ultra90 H Inten, HAE Helio Frame, No Surv Corr, Full Spin," + " 6 deg, 6 Mon" + ) + write_cdf(output_map) @pytest.mark.usefixtures("_setup_spice_kernels_list") def test_ultra_l2_descriptor_hpmap(self, mock_data_dict, furnish_kernels): with furnish_kernels(self.required_kernel_names): output_map = ultra_l2.ultra_l2( data_dict=mock_data_dict, - descriptor="u90-ena-h-sf-nsp-full-hae-nside32-6mo", + descriptor="u90-ena-h-sf-nsp-full-hae-nside32-3mo", )[0] assert "spacecraft frame" in output_map.attrs["Logical_source_description"] + # Check that the logical source contains the expected information from the + # descriptor string assert ( output_map.attrs["Logical_source"] - == "imap_ultra_l2_u90-ena-h-sf-nsp-full-hae-nside32-6mo" + == "imap_ultra_l2_u90-ena-h-sf-nsp-full-hae-nside32-3mo" ) assert output_map.attrs["Spice_reference_frame"] == "IMAP_HAE" assert output_map.attrs["HEALPix_nside"] == "32" + + write_cdf(output_map) + + @pytest.mark.usefixtures("_mock_single_pset") + def test_bin_pset_energy_bins_default(self): + """Test binning with default bin sizes.""" + pset = mock_l1c_pset_product_healpix( + nside=16, + counts_nside=16, + stripe_center_lat=0, + timestr="2025-05-15T12:00:00", + energy_dependent_exposure=True, + ) + # Set the values in the single input PSET + # Create a mock array with known values to test binning + # e.g., 0,0,0,0,1,1,1,1,2,2,2,2,...11,11 + n_fine_bins = pset.energy_bin_geometric_mean.size + n_coarse_bins = len(build_default_coarse_bin_edges()) - 1 + mock_vals = np.repeat(np.arange(n_coarse_bins), 4)[0:n_fine_bins] + mock_array = ( + np.ones_like(pset["exposure_factor"]) * mock_vals[np.newaxis, :, np.newaxis] + ) + pset["counts"].values = ( + np.ones_like(pset["counts"]) * mock_vals[np.newaxis, :, np.newaxis] + ) + pset["exposure_factor"].values = mock_array + pset["sensitivity"].values = mock_array[0] + pset["geometric_function"].values = mock_array[0] + pset["efficiency"].values = mock_array[0] + pset["background_rates"].values = mock_array + pset["scatter_theta"].values = mock_array[0] + pset["scatter_phi"].values = mock_array[0] + pset["energy_bin_delta"].values = np.ones_like(pset["energy_bin_delta"]) + # Bin the pset + binned_pset = ultra_l2.bin_pset_energy_bins( + pset, build_default_coarse_bin_edges() + ) + # Check that the new bin edges are as expected + expected_bin_edges = np.array( + [ + 3.0, + 4.6, + 6.96, + 10.27, + 15.71, + 23.4444, + 34.9866, + 52.2113, + 77.9161, + 116.276, + 173.521, + 258.95, + 316.335, + ] + ) + expected_energy_delta_minus, expected_energy_delta_plus = ( + get_energy_delta_minus_plus(expected_bin_edges) + ) + np.testing.assert_array_equal( + binned_pset["energy_delta_plus"].values, + expected_energy_delta_plus, + ) + np.testing.assert_array_equal( + binned_pset["energy_delta_minus"].values, + expected_energy_delta_minus, + ) + # check that the pinned_pset energy_bin_geometric_mean values have been + # recalculated correctly with the new bin edges + np.testing.assert_array_equal( + binned_pset["energy_bin_geometric_mean"].values, + np.sqrt(expected_bin_edges[:-1] * expected_bin_edges[1:]), + ) + + # Check that the counts have been summed correctly in the new bins + # 4 fine bins per coarse bin + expected_binned_counts = np.arange(n_coarse_bins) * 4 + # The last bin only has 2 fine bins + expected_binned_counts[-1] = (n_coarse_bins - 1) * 2 + # Broadcast to shape (1, n_coarse_bins, n_pixels) + n_pixels = binned_pset["counts"].shape[2] + expected_binned_counts = np.tile( + expected_binned_counts[np.newaxis, :, np.newaxis], (1, 1, n_pixels) + ) + np.testing.assert_array_equal(binned_pset["counts"], expected_binned_counts) + + # Check that the variables that should be averaged over the new bins are + # correct + for var in VARIABLES_TO_AVERAGE_OVER_COARSE_ENERGY_BINS: + num_fine_bins_per_coarse_bin = np.full(n_coarse_bins, 4) + # The last bin only has 2 fine bins + num_fine_bins_per_coarse_bin[-1] = 2 + expected_binned_vals = ( + expected_binned_counts / num_fine_bins_per_coarse_bin[:, np.newaxis] + ) + np.testing.assert_array_equal( + binned_pset[var].squeeze(), expected_binned_vals[0] + ) + + @pytest.mark.usefixtures("_mock_single_pset") + def test_bin_pset_energy_irregular_bins(self): + """Test binning with irregular bin sizes.""" + # Avoid modifying the original pset + pset = self.ultra_pset.copy(deep=True) + pset["counts"].values = np.full(pset["counts"].shape, 2) + # Update Exposure factor to be a ones array. + pset["exposure_factor"].values = np.ones_like(pset["exposure_factor"]) + pset["background_rates"].values = np.ones_like(pset["background_rates"]) + # First group has 10 fine bins, then 30, then 6 + new_bin_edges = np.array([0, 10, 40, 46]) + # Bin the pset + binned_pset = ultra_l2.bin_pset_energy_bins(pset, new_bin_edges) + # Check that the new bin edges are as expected + expected_bin_edges = np.array( + [ + 3.0, + 8.615, + 173.521, + 316.335, + ] + ) + expected_energy_delta_minus, expected_energy_delta_plus = ( + get_energy_delta_minus_plus(expected_bin_edges) + ) + np.testing.assert_array_equal( + binned_pset["energy_delta_plus"].values, + expected_energy_delta_plus, + ) + np.testing.assert_array_equal( + binned_pset["energy_delta_minus"].values, + expected_energy_delta_minus, + ) + # check that the pinned_pset energy_bin_geometric_mean values have been + # recalculated correctly with the new bin edges + np.testing.assert_array_equal( + binned_pset["energy_bin_geometric_mean"].values, + np.sqrt(expected_bin_edges[:-1] * expected_bin_edges[1:]), + ) + # Check that the counts have been summed correctly in the bins + for i, group_size in enumerate([10, 30, 6]): + counts_in_bin = binned_pset["counts"][0, i, :] + expected_counts = np.full( + counts_in_bin.shape, + group_size * 2, + ) + np.testing.assert_array_equal(counts_in_bin, expected_counts) + + # Check that the variables that should be averaged over the new bins are + # correct + # The arrays in the pset pre-binning are all be ones so they should + # remain ones after averaging. + for var in VARIABLES_TO_AVERAGE_OVER_COARSE_ENERGY_BINS: + np.testing.assert_array_equal(np.unique(pset[var]), 1) + + @pytest.mark.usefixtures("_mock_single_pset") + def test_bin_pset_energy_bin_subset(self): + """Test binning with bins that do not include all of the fine bins.""" + # Avoid modifying the original pset + pset = self.ultra_pset.copy(deep=True) + # The bin edges do not cover all fine bins + # In this case, we expect the function to ignore the fine bins outside + # the new bin edges + new_bin_edges = np.array([3, 10, 40]) + # Bin the pset + binned_pset = ultra_l2.bin_pset_energy_bins(pset, new_bin_edges) + # Check that the new bin edges are as expected + expected_bin_edges = np.array( + [ + 4.2, + 8.615, + 173.521, + ] + ) + expected_energy_delta_minus, expected_energy_delta_plus = ( + get_energy_delta_minus_plus(expected_bin_edges) + ) + np.testing.assert_array_equal( + binned_pset["energy_delta_plus"].values, + expected_energy_delta_plus, + ) + np.testing.assert_array_equal( + binned_pset["energy_delta_minus"].values, + expected_energy_delta_minus, + ) + # check that the pinned_pset energy_bin_geometric_mean values have been + # recalculated correctly with the new bin edges + np.testing.assert_array_equal( + binned_pset["energy_bin_geometric_mean"].values, + np.sqrt(expected_bin_edges[:-1] * expected_bin_edges[1:]), + ) + # Check that the shapes are correct + assert binned_pset["counts"].shape[1] == 2 + + for var in VARIABLES_TO_AVERAGE_OVER_COARSE_ENERGY_BINS: + assert binned_pset[var].squeeze().shape[0] == 2 + + with pytest.raises( + ValueError, + match="The given bin_groups contain an index larger than the number of fine" + " energy bins in the pset: 46.", + ): + # Bin the pset - should raise ValueError because the last bin edge is + # out of range + ultra_l2.bin_pset_energy_bins(pset, np.array([0, 10, 48])) + + @pytest.mark.usefixtures("_mock_single_pset") + def test_bin_pset_energy_bins_zero_count_fine_bin(self): + """Test binning with some fine bins having zero values.""" + # Avoid modifying the original pset + pset = self.ultra_pset.copy(deep=True) + # Set values in energy bin 0 to zero + pset["sensitivity"][0, :].values = np.ones(pset["sensitivity"][0, :].shape) + # Bin the pset + binned_pset = ultra_l2.bin_pset_energy_bins( + pset, build_default_coarse_bin_edges() + ) + # Assert that the binned and averaged sensitivity in the first coarse bin is + # equal to the average of the fine bins that were included (which excludes the + # zero count bin) + np.testing.assert_array_equal( + binned_pset["sensitivity"].values, np.ones_like(binned_pset["sensitivity"]) + ) diff --git a/imap_processing/ultra/constants.py b/imap_processing/ultra/constants.py index 410886d2b8..3ef2173129 100644 --- a/imap_processing/ultra/constants.py +++ b/imap_processing/ultra/constants.py @@ -3,6 +3,12 @@ from dataclasses import dataclass from typing import ClassVar +import numpy as np + +from imap_processing import imap_module_directory + +SPICE_DATA_SIM_PATH = imap_module_directory / "ultra/l1c/sim_spice_kernels" + @dataclass(frozen=True) class UltraConstants: @@ -46,7 +52,6 @@ class UltraConstants: # Composite energy threshold for SSD events COMPOSITE_ENERGY_THRESHOLD: int = 1707 - # Geometry-related constants Z_DSTOP: float = 2.6 / 2 # Position of stop foil on Z axis [mm] Z_DS: float = 46.19 - (2.6 / 2) # Position of slit on Z axis [mm] @@ -78,31 +83,174 @@ class UltraConstants: CULLING_RPM_MIN = 2.0 CULLING_RPM_MAX = 6.0 - # Thresholds for culling based on counts (keV). + # Energy Bounds for culling (keV). CULLING_ENERGY_BIN_EDGES: ClassVar[list] = [ - 3.385, - 4.13722222222222, - 5.05660493827161, - 6.18029492455419, - 7.55369379667734, - 9.23229241816119, - 11.2839129555303, - 13.7914491678704, - 16.8562156496194, - 20.6020413495348, - 25.1802727605426, - 30.775888929552, - 37.6149753583414, - 45.9738587713061, - 56.1902718315964, - 68.6769989052845, - 83.93855421757, - 102.591566265919, - 125.38969210279, - 153.254068125632, - 187.310527709106, - 228.93508942224, - 279.809553738294, - 341.989454569026, + 3.0, + 10.0, + 20.0, + 50.0, + 300.0, 1e5, ] + # Counts at l1c are sampled at a finer resolution. + L1C_COUNTS_NSIDE = 128 + + PSET_ENERGY_BIN_EDGES: ClassVar[list] = [ + 3.0, + 3.4, + 3.8, + 4.2, + 4.6, + 5.19, + 5.78, + 6.37, + 6.96, + 7.7875, + 8.615, + 9.4425, + 10.27, + 11.63, + 12.99, + 14.35, + 15.71, + 17.3637, + 19.1914, + 21.2116, + 23.4444, + 25.9122, + 28.6398, + 31.6545, + 34.9866, + 38.6694, + 42.7399, + 47.2388, + 52.2113, + 57.7072, + 63.7817, + 70.4955, + 77.9161, + 86.1178, + 95.1828, + 105.202, + 116.276, + 128.516, + 142.044, + 156.995, + 173.521, + 191.787, + 211.975, + 234.288, + 258.95, + 286.208, + 316.335, + ] + + # Valid event filter constants + # Note these appear similar to image params constants + # but they should be used only for the valid event filter. + ETOFOFF1_EVENTFILTER = 100 + ETOFOFF2_EVENTFILTER = -50 + ETOFSLOPE1_EVENTFILTER = 6667 + ETOFSLOPE2_EVENTFILTER = 7500 + ETOFMAX_EVENTFILTER = 100 + ETOFMIN_EVENTFILTER = 0 + TOFDIFFTPMIN_EVENTFILTER = 226 + TOFDIFFTPMAX_EVENTFILTER = 266 + + TOFXE_SPECIES_GROUPS: ClassVar[dict[str, list[int]]] = { + "proton": [3], + "non_proton": [20, 28, 36], + } + TOFXPH_SPECIES_GROUPS: ClassVar[dict[str, list[int]]] = { + "proton": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19], + "non_proton": [20, 21, 22, 23, 24, 25, 26], + } + + SIM_KERNELS_FOR_HELIO_INDEX_MAPS: ClassVar[list] = [ + str(SPICE_DATA_SIM_PATH / k) + for k in [ + "imap_sclk_0000.tsc", + "naif0012.tls", + "imap_spk_demo.bsp", + "sim_1yr_imap_attitude.bc", + "imap_001.tf", + "imap_science_120.tf", + "sim_1yr_imap_pointing_frame.bc", + ] + ] + + FOV_THETA_OFFSET_DEG = 0.0 + FOV_PHI_LIMIT_DEG = 60.0 + # Restricted FOV theta/phi acceptance limits (degrees). + # Samples outside these bounds are excluded from GF, efficiency, exposure, + # and counts maps at L1C (fine energy bin maps only). + RESTRICTED_FOV_THETA_LOW_DEG_45: float = -46.0 + RESTRICTED_FOV_THETA_HIGH_DEG_45: float = 43.0 + RESTRICTED_FOV_THETA_LOW_DEG_90: float = -43.0 + RESTRICTED_FOV_THETA_HIGH_DEG_90: float = 43.0 + + # For spatiotemporal culling + EARTH_RADIUS_KM: float = 6378.1 + N_RE = 60 + DEFAULT_EARTH_CULLING_RADIUS = EARTH_RADIUS_KM * N_RE + + # L1b extended spin culling parameters + LOW_VOLTAGE_CULL_THRESHOLD = 3400.0 + SPIN_BIN_SIZE = 20 + # Number of energy bins to use in energy dependent culling + N_CULL_EBINS = 8 + # Bin to start culling at + BASE_CULL_EBIN = 0 + # Maximum energy threshold in keV. When creating the energy ranges for culling, + # merge all energy bins above this threshold into one bin. + MAX_ENERGY_THRESHOLD = 116.0 + # Angle threshold in radians for ULTRA 45 degree culling. + # This is only needed for ULTRA 45 since Earth may be in the FOV. + EARTH_ANGLE_45_THRESHOLD = np.radians(15) + # An array of energy thresholds to use for culling. Each one corresponds to + # the number of energy bins used. + # n_bins=len(PSET_ENERGY_BIN_EDGES)[BASE_CULL_EBIN:] // N_CULL_EBINS + # an error will be raised if this does not match n_bins + HIGH_ENERGY_CULL_THRESHOLDS = ( + np.array([4.0, 2.0, 1.20, 0.45, 0.1, 0.1]) * SPIN_BIN_SIZE + ) + # Use the channel defined below to determine which spins are contaminated + HIGH_ENERGY_CULL_CHANNEL = 5 + # For the high energy cull, we want to combine spin bins because an SEP event is + # expected to be over a longer time period. Low voltage and statistical culling + # will still be done on the original spin bins. The variable below defines the + # radius (in number of spin bins) to use when combining for the high energy cull. + HIGH_ENERGY_COMBINED_SPIN_BIN_RADIUS = 5 + # Number of iterations to perform for statistical outlier culling. + STAT_CULLING_N_ITER = 5 + # Sigma threshold to use for statistical outlier culling. + STAT_CULLING_STD_THRESHOLD = 0.05 + # Energy channels for the upstream ion cull + # The algorithm will be run twice with the different sets of channels below. + UPSTREAM_ION_ENERGY_CHANNELS_1: ClassVar[list] = [0, 1, 2] + UPSTREAM_ION_ENERGY_CHANNELS_2: ClassVar[list] = [2, 3, 4] + UPSTREAM_SIG_THRESHOLD = 2.5 + # Spectral culling parameters + SPECTRAL_ENERGY_CHANNELS: ClassVar[list] = [0, 1, 2, 3] + SPECTRAL_SIG_THRESHOLD = 1 + # Set dimensions for extended spin/goodtime support variables + # ISTP requires fixed dimensions, so we set these to the maximum we expect to need + # and pad with fill values if we use fewer bins. + MAX_ENERGY_RANGES = 16 + MAX_ENERGY_RANGE_EDGES = MAX_ENERGY_RANGES + 1 + + # L1C PSET constants + + # When True, applies the FOV restrictions defined above to the L1C fine energy bin + # maps (GF, efficiency, exposure, counts). This culls regions of the instrument + # field of view with poor efficiency calibration from inclusion into the map making + # process. + APPLY_FOV_RESTRICTIONS_L1C: bool = True + + # When True, applies the boundary scale factors from the ancillary file to exposure + # time, efficiency, and geometric factor maps. + APPLY_BOUNDARY_SCALE_FACTORS_L1C: bool = False + + # When True, applies the scattering rejection mask based on the FWHM thresholds + # to the L1C fine energy bin maps. + APPLY_SCATTERING_REJECTION_L1C: bool = False diff --git a/imap_processing/ultra/l0/decom_tools.py b/imap_processing/ultra/l0/decom_tools.py index 9d37d82db8..a39647fd41 100644 --- a/imap_processing/ultra/l0/decom_tools.py +++ b/imap_processing/ultra/l0/decom_tools.py @@ -157,6 +157,7 @@ def decompress_image( pixel0: int, binary_data: str, packet_props: PacketProperties, + planes_per_packet: int = 1, ) -> NDArray: """ Will decompress a binary string representing an image into a matrix of pixel values. @@ -174,11 +175,15 @@ def decompress_image( packet_props : PacketProperties Properties of the packet, including width bit, mantissa bit length and pixel window dimensions. + planes_per_packet : int + Number of image planes in the packet. Default is 1. Returns ------- - p_decom : NDArray - A 2D numpy array representing pixel values. + planes : NDArray + A 3D numpy array representing pixel values. + The last two dimensions correspond to the image dimensions, and the first + is the number of image planes. Each pixel is stored as an unsigned 16-bit integer (uint16). Notes @@ -199,51 +204,58 @@ def decompress_image( ) blocks_per_row = cols // pixels_per_block - - # Compressed pixel matrix - p = np.zeros((rows, cols), dtype=np.uint16) - # Decompressed pixel matrix - p_decom = np.zeros((rows, cols), dtype=np.int16) - + current_pixel0 = pixel0 # Use the parameter for first plane + planes = [] + plane_num = 0 pos = 0 # Starting position in the binary string - - for i in range(rows): - for j in range(blocks_per_row): - # Read the width for the block. - w, pos = read_and_advance(binary_data, width_bit, pos) - for k in range(pixels_per_block): - # Handle the special case in which the width is 0 - if w == 0: - value = 0 - else: - # Find the value of each pixel in the block - value, pos = read_and_advance(binary_data, w, pos) - - # if the least significant bit of value is set (odd) - if value & 0x01: - # value >> 1: shifts bits of value one place to the right - # ~: bitwise NOT operator (flips bits) - delta_f = ~(value >> 1) - else: - delta_f = value >> 1 - - # Calculate the new pixel value and update pixel0 - column_index = j * pixels_per_block + k - # 0xff is the hexadecimal representation of the number 255, - # Keeps only the last 8 bits of the result of pixel0 - delta_f - # This operation ensures that the result is within the range - # of an 8-bit byte (0-255) - # Use np.int16 for the arithmetic operation to avoid overflow - # Then implicitly cast back to the p's uint16 dtype for storage - p[i][column_index] = np.int16(pixel0) - delta_f - # Perform logarithmic decompression on the pixel value - p_decom[i][column_index] = log_decompression( - p[i][column_index], mantissa_bit_length - ) - pixel0 = p[i][column_index] - pixel0 = p[i][0] - - return p_decom + while plane_num < planes_per_packet: + # Compressed pixel matrix + p: np.ndarray = np.zeros((rows, cols), dtype=np.uint16) + # Decompressed pixel matrix + p_decom: np.ndarray = np.zeros((rows, cols), dtype=np.int16) + + for i in range(rows): + for j in range(blocks_per_row): + # Read the width for the block. + w, pos = read_and_advance(binary_data, width_bit, pos) + for k in range(pixels_per_block): + # Handle the special case in which the width is 0 + if w == 0: + value = 0 + else: + # Find the value of each pixel in the block + value, pos = read_and_advance(binary_data, w, pos) + + # if the least significant bit of value is set (odd) + if value & 0x01: + # value >> 1: shifts bits of value one place to the right + # ~: bitwise NOT operator (flips bits) + delta_f = ~(value >> 1) + else: + delta_f = value >> 1 + + # Calculate the new pixel value and update pixel0 + column_index = j * pixels_per_block + k + # 0xff is the hexadecimal representation of the number 255, + # Keeps only the last 8 bits of the result of pixel0 - delta_f + # This operation ensures that the result is within the range + # of an 8-bit byte (0-255) + # Use np.int16 for the arithmetic operation to avoid overflow + # Then implicitly cast back to the p's uint16 dtype for storage + p[i][column_index] = np.int16(current_pixel0) - delta_f + # Perform logarithmic decompression on the pixel value + p_decom[i][column_index] = log_decompression( + int(p[i][column_index]), mantissa_bit_length + ) + current_pixel0 = int(p[i][column_index]) + current_pixel0 = p[i][0] # type: ignore[assignment] + planes.append(p_decom) + plane_num += 1 + # Read P00 for the next plane (if not the last plane) + if plane_num < planes_per_packet: + current_pixel0, pos = read_and_advance(binary_data, 8, pos) + + return np.stack(planes) def read_image_raw_events_binary( diff --git a/imap_processing/ultra/l0/decom_ultra.py b/imap_processing/ultra/l0/decom_ultra.py index adaf86ccc2..b87d42dcdb 100644 --- a/imap_processing/ultra/l0/decom_ultra.py +++ b/imap_processing/ultra/l0/decom_ultra.py @@ -7,7 +7,6 @@ import numpy as np import xarray as xr -from numpy.typing import NDArray from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes from imap_processing.ultra.l0.decom_tools import ( @@ -32,16 +31,76 @@ ULTRA_RATES, PacketProperties, ) -from imap_processing.utils import convert_to_binary_string +from imap_processing.utils import ( + combine_segmented_packets, + convert_to_binary_string, +) -logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) +def extract_initial_items_from_combined_packets( + packets: xr.Dataset, +) -> xr.Dataset: + """ + Extract metadata fields from the beginning of combined event_data packets. + + Extracts bit fields from the first 20 bytes of each event_data array + and adds them as new variables to the dataset. + + Parameters + ---------- + packets : xarray.Dataset + Dataset containing combined packets with event_data. + + Returns + ------- + xarray.Dataset + Dataset with extracted metadata fields added. + """ + # Initialize arrays for extracted fields + n_packets = len(packets.epoch) + + # Preallocate arrays + sid: np.ndarray = np.zeros(n_packets, dtype=np.uint8) + spin: np.ndarray = np.zeros(n_packets, dtype=np.uint8) + abortflag: np.ndarray = np.zeros(n_packets, dtype=np.uint8) + startdelay: np.ndarray = np.zeros(n_packets, dtype=np.uint16) + p00: np.ndarray = np.zeros(n_packets, dtype=np.uint8) + + # Extract the data array outside of the loop + binary_data = packets["packetdata"].data + # Extract fields from each packet + for pkt_idx in range(n_packets): + event_data = binary_data[pkt_idx] + + sid[pkt_idx] = event_data[0] + spin[pkt_idx] = event_data[1] + abortflag[pkt_idx] = (event_data[2] >> 7) & 0x1 + startdelay[pkt_idx] = int.from_bytes(event_data[2:4], byteorder="big") & 0x7FFF + p00[pkt_idx] = event_data[4] + + # Remove the first 5 bytes after extraction + binary_data[pkt_idx] = event_data[5:] + + # Add extracted fields to dataset + packets["sid"] = xr.DataArray(sid, dims=["epoch"]) + packets["spin"] = xr.DataArray(spin, dims=["epoch"]) + packets["abortflag"] = xr.DataArray(abortflag, dims=["epoch"]) + packets["startdelay"] = xr.DataArray(startdelay, dims=["epoch"]) + packets["p00"] = xr.DataArray(p00, dims=["epoch"]) + + return packets + + def process_ultra_tof(ds: xr.Dataset, packet_props: PacketProperties) -> xr.Dataset: """ Unpack and decode Ultra TOF packets. + The TOF packets contain image data that may be split across multiple segmented + packets. This function combines the segmented packets and decompresses the image + data. + Parameters ---------- ds : xarray.Dataset @@ -55,6 +114,11 @@ def process_ultra_tof(ds: xr.Dataset, packet_props: PacketProperties) -> xr.Data dataset : xarray.Dataset Dataset containing the decoded and decompressed data. """ + # Combine segmented packets + ds = combine_segmented_packets(ds, binary_field_name="packetdata") + # Extract the header keys from each of the combined packetdata fields. + ds = extract_initial_items_from_combined_packets(ds) + scalar_keys = [key for key in ds.data_vars if key not in ("packetdata", "sid")] image_planes = packet_props.image_planes @@ -81,94 +145,115 @@ def process_ultra_tof(ds: xr.Dataset, packet_props: PacketProperties) -> xr.Data decom_data: defaultdict[str, list[np.ndarray]] = defaultdict(list) decom_data["packetdata"] = [] valid_epoch = [] - for val, group in ds.groupby("epoch"): if set(group["sid"].values) >= set( np.arange(0, image_planes, planes_per_packet) ): + plane_count = 0 valid_epoch.append(val) group.sortby("sid") for key in scalar_keys: - decom_data[key].append(group[key].values) + # Repeat the scalar values for each image plane. There may be cases + # where the last packet has fewer planes than the planes_per_packet, so + # we slice to ensure the correct length. + decom_data[key].append( + np.tile(group[key].values, planes_per_packet)[:image_planes] + ) image = [] for i in range(num_image_packets): binary = convert_to_binary_string(group["packetdata"].values[i]) + # Determine how many planes to decompress in this packet. + # the last packet might have fewer planes than planes_per_packet. + # Take the minimum of the remaining planes or the max planes per packet + # value. + planes_in_packet = min(image_planes - plane_count, planes_per_packet) decompressed = decompress_image( group["p00"].values[i], binary, packet_props, + planes_in_packet, ) image.append(decompressed) + plane_count += planes_in_packet - decom_data["packetdata"].append(np.stack(image)) + decom_data["packetdata"].append(np.concatenate(image, axis=0)) for key in scalar_keys: - decom_data[key] = np.stack(decom_data[key]) + decom_data[key] = np.stack(decom_data[key], axis=0) - decom_data["packetdata"] = np.stack(decom_data["packetdata"]) + decom_data["packetdata"] = np.stack(decom_data["packetdata"], axis=0) coords = { "epoch": np.array(valid_epoch, dtype=np.uint64), - "sid": xr.DataArray(np.arange(num_image_packets), dims=["sid"], name="sid"), + "plane": xr.DataArray(np.arange(image_planes), dims=["plane"], name="plane"), "row": xr.DataArray(np.arange(rows), dims=["row"], name="row"), "column": xr.DataArray(np.arange(cols), dims=["column"], name="column"), } dataset = xr.Dataset(coords=coords) - # Add scalar keys (2D: epoch x sid) + # Add scalar keys (2D: epoch x packets) for key in scalar_keys: dataset[key] = xr.DataArray( decom_data[key], - dims=["epoch", "sid"], + dims=["epoch", "plane"], ) # Add PACKETDATA (4D: epoch x sid x row x column) dataset["packetdata"] = xr.DataArray( decom_data["packetdata"], - dims=["epoch", "sid", "row", "column"], + dims=["epoch", "plane", "row", "column"], ) return dataset -def get_event_id(shcoarse: NDArray) -> NDArray: +def get_event_id( + event_data: bytes, count: int, shcoarse: int, bits_per_event: int +) -> list: """ Get unique event IDs using data from events packets. Parameters ---------- - shcoarse : numpy.ndarray - SHCOARSE (MET). + event_data : bytes + Raw event data from the packet. + count : int + Number of events in the packet. + shcoarse : int + The met value for the packet. + bits_per_event : int + Bits allocated for each event in the packet. This differs between event data + and energy event data packets. Returns ------- event_ids : numpy.ndarray Ultra events data with calculated unique event IDs as 64-bit integers. """ + binary = convert_to_binary_string(event_data) + # For all packets with event data, parses the binary string event_ids = [] - packet_counters = {} - - for met in shcoarse: - # Initialize the counter for a new packet (MET value) - if met not in packet_counters: - packet_counters[met] = 0 - else: - packet_counters[met] += 1 - - # Left shift SHCOARSE (u32) by 31 bits, to make room for our event counters - # (31 rather than 32 to keep it positive in the int64 representation) - # Append the current number of events in this packet to the right-most bits - # This makes each event a unique value including the MET and event number - # in the packet - # NOTE: CDF does not allow for uint64 values, - # so we use int64 representation here - event_id = (np.int64(met) << np.int64(31)) | np.int64(packet_counters[met]) - event_ids.append(event_id) - - return np.array(event_ids, dtype=np.int64) + # Get the met value and convert to hex (4 bytes -> 8 hex ) + met_hex = format(shcoarse, "08x") + for i in range(count): + start_bit = i * bits_per_event + if start_bit + bits_per_event > len(binary): + logger.warning( + f"Event ID calculation warning: event {i} expected {bits_per_event} " + f"bits starting at bit {start_bit} ({start_bit + bits_per_event} total)" + f", but binary string is only {len(binary)} bits. Truncating to " + f"available bits." + ) + event_bits = binary[start_bit : start_bit + bits_per_event] + # Convert the event bits to an integer, then to a hex string, and concatenate + # with the met hex to create the event ID. + # Prepend "00" to the event bits to get an integral number of bytes + # (168 bits --> 21 bytes) + event_ids.append(met_hex + format(int("00" + event_bits, 2), "042x")) + return event_ids def process_ultra_events(ds: xr.Dataset, apid: int) -> xr.Dataset: @@ -196,8 +281,10 @@ def process_ultra_events(ds: xr.Dataset, apid: int) -> xr.Dataset: ) if apid in all_event_apids: field_ranges = EVENT_FIELD_RANGES + bits_per_event = 166 elif apid in ULTRA_ENERGY_EVENTS.apid: field_ranges = ENERGY_EVENT_FIELD_RANGES + bits_per_event = 41 else: raise ValueError(f"APID {apid} not recognized for Ultra events processing.") @@ -216,11 +303,12 @@ def process_ultra_events(ds: xr.Dataset, apid: int) -> xr.Dataset: counts = ds["count"].values eventdata_array = ds["eventdata"].values - + event_ids: list[str] = [] for i, count in enumerate(counts): if count == 0: all_events.append(empty_event) all_indices.append(i) + event_ids.append("0x0") else: # Here there are multiple images in a single packet, # so we need to loop through each image and decompress it. @@ -230,6 +318,10 @@ def process_ultra_events(ds: xr.Dataset, apid: int) -> xr.Dataset: all_events.extend(event_data_list) # Keep track of how many times does the event occurred at this epoch. all_indices.extend([i] * count) + ids = get_event_id( + eventdata_array[i], count, ds["shcoarse"].values[i], bits_per_event + ) + event_ids.extend(ids) # Now we have the event data, we need to create the xarray dataset. # We cannot append to the existing dataset (sorted_packets) @@ -245,11 +337,9 @@ def process_ultra_events(ds: xr.Dataset, apid: int) -> xr.Dataset: for key in field_ranges: expanded_data[key] = np.array([event[key] for event in all_events]) - event_ids = get_event_id(expanded_data["shcoarse"]) - coords = { "epoch": ds["epoch"].values[idx], - "event_id": ("epoch", event_ids), + "event_id": ("epoch", np.array(event_ids)), } dataset = xr.Dataset(coords=coords) @@ -389,7 +479,7 @@ def process_ultra_cmd_echo(ds: xr.Dataset) -> xr.Dataset: fill = 0xFF max_len = 10 - arg_array = np.full((len(ds["epoch"]), max_len), fill, dtype=np.uint8) + arg_array: np.ndarray = np.full((len(ds["epoch"]), max_len), fill, dtype=np.uint8) for i, arg in enumerate(ds["args"].values): # Converts to the numeric representations of each byte. @@ -434,7 +524,7 @@ def process_ultra_macros_checksum(ds: xr.Dataset) -> xr.Dataset: Dataset with unpacked and decoded checksum values. """ # big endian uint16 - packed_dtype = np.dtype(">u2") + packed_dtype: np.dtype = np.dtype(">u2") fill = np.iinfo(packed_dtype).max n_epochs = ds.sizes["epoch"] max_len = 256 diff --git a/imap_processing/ultra/l0/ultra_utils.py b/imap_processing/ultra/l0/ultra_utils.py index 8b4873d169..70ded1e2ac 100644 --- a/imap_processing/ultra/l0/ultra_utils.py +++ b/imap_processing/ultra/l0/ultra_utils.py @@ -137,8 +137,8 @@ class PacketProperties(NamedTuple): ULTRA_EXTOF_HIGH_TIME = PacketProperties( apid=[888, 952], logical_source=[ - "imap_ultra_l1a_45sensor-histogram-ena-extof-hi-time", - "imap_ultra_l1a_90sensor-histogram-ena-extof-hi-time", + "imap_ultra_l1a_45sensor-histogram-ion-extof-hi-time", + "imap_ultra_l1a_90sensor-histogram-ion-extof-hi-time", ], addition_to_logical_desc="Energy By Time of Flight High Time Images", width=4, @@ -153,8 +153,8 @@ class PacketProperties(NamedTuple): ULTRA_EXTOF_HIGH_ENERGY = PacketProperties( apid=[887, 951], logical_source=[ - "imap_ultra_l1a_45sensor-histogram-ena-extof-hi-nrg", - "imap_ultra_l1a_90sensor-histogram-ena-extof-hi-nrg", + "imap_ultra_l1a_45sensor-histogram-ion-extof-hi-nrg", + "imap_ultra_l1a_90sensor-histogram-ion-extof-hi-nrg", ], addition_to_logical_desc="Energy By Time of Flight High Energy Images", width=4, diff --git a/imap_processing/ultra/l1a/ultra_l1a.py b/imap_processing/ultra/l1a/ultra_l1a.py index 3a017694c8..6228f3b257 100644 --- a/imap_processing/ultra/l1a/ultra_l1a.py +++ b/imap_processing/ultra/l1a/ultra_l1a.py @@ -43,7 +43,7 @@ def ultra_l1a( # noqa: PLR0912 - packet_file: str, apid_input: int | None = None + packet_file: str, apid_input: int | None = None, create_derived_l1b: bool = False ) -> list[xr.Dataset]: """ Will process ULTRA L0 data into L1A CDF files at output_filepath. @@ -54,6 +54,8 @@ def ultra_l1a( # noqa: PLR0912 Path to the CCSDS data packet file. apid_input : Optional[int] Optional apid. + create_derived_l1b : bool + Whether to create the l1b datasets with derived values. Returns ------- @@ -63,8 +65,17 @@ def ultra_l1a( # noqa: PLR0912 xtce = str( f"{imap_module_directory}/ultra/packet_definitions/ULTRA_SCI_COMBINED.xml" ) - + # Keep a list to track the two versions, l1a and l1b with the derived values. + decommutated_packet_datasets = [] datasets_by_apid = packet_file_to_datasets(packet_file, xtce) + decommutated_packet_datasets.append(datasets_by_apid) + if create_derived_l1b: + # For the housekeeping products, we can create the l1b at the same time + # as the l1a since there is no additional processing needed. + datasets_by_apid = packet_file_to_datasets( + packet_file, xtce, use_derived_value=True + ) + decommutated_packet_datasets.append(datasets_by_apid) output_datasets = [] @@ -109,77 +120,115 @@ def ultra_l1a( # noqa: PLR0912 attr_mgr.add_instrument_global_attrs("ultra") attr_mgr.add_instrument_variable_attrs("ultra", "l1a") - for apid in apids: - if apid in ULTRA_AUX.apid: - decom_ultra_dataset = datasets_by_apid[apid] - gattr_key = ULTRA_AUX.logical_source[ULTRA_AUX.apid.index(apid)] - elif apid in all_l1a_image_apids: - packet_props = all_l1a_image_apids[apid] - decom_ultra_dataset = process_ultra_tof( - datasets_by_apid[apid], packet_props - ) - gattr_key = packet_props.logical_source[packet_props.apid.index(apid)] - elif apid in ULTRA_RATES.apid: - decom_ultra_dataset = process_ultra_rates(datasets_by_apid[apid]) - decom_ultra_dataset = decom_ultra_dataset.drop_vars("fastdata_00") - gattr_key = ULTRA_RATES.logical_source[ULTRA_RATES.apid.index(apid)] - elif apid in ULTRA_ENERGY_RATES.apid: - decom_ultra_dataset = process_ultra_energy_rates(datasets_by_apid[apid]) - decom_ultra_dataset = decom_ultra_dataset.drop_vars("ratedata") - gattr_key = ULTRA_ENERGY_RATES.logical_source[ - ULTRA_ENERGY_RATES.apid.index(apid) - ] - elif apid in all_event_apids: - decom_ultra_dataset = process_ultra_events(datasets_by_apid[apid], apid) - gattr_key = all_event_apids[apid] + for i, datasets_by_apid in enumerate(decommutated_packet_datasets): + for apid in apids: + logger.info(f"Processing APID: {apid}") + if apid in ULTRA_AUX.apid: + decom_ultra_dataset = datasets_by_apid[apid] + gattr_key = ULTRA_AUX.logical_source[ULTRA_AUX.apid.index(apid)] + elif apid in all_l1a_image_apids: + packet_props = all_l1a_image_apids[apid] + decom_ultra_dataset = process_ultra_tof( + datasets_by_apid[apid], packet_props + ) + gattr_key = packet_props.logical_source[packet_props.apid.index(apid)] + elif apid in ULTRA_RATES.apid: + decom_ultra_dataset = process_ultra_rates(datasets_by_apid[apid]) + decom_ultra_dataset = decom_ultra_dataset.drop_vars("fastdata_00") + gattr_key = ULTRA_RATES.logical_source[ULTRA_RATES.apid.index(apid)] + elif apid in ULTRA_ENERGY_RATES.apid: + decom_ultra_dataset = process_ultra_energy_rates(datasets_by_apid[apid]) + decom_ultra_dataset = decom_ultra_dataset.drop_vars("ratedata") + gattr_key = ULTRA_ENERGY_RATES.logical_source[ + ULTRA_ENERGY_RATES.apid.index(apid) + ] + elif apid in all_event_apids: + # We don't want to process the event l1b datasets since those l1b + # products need more information + if i == 1: + continue + decom_ultra_dataset = process_ultra_events(datasets_by_apid[apid], apid) + gattr_key = all_event_apids[apid] + # Add coordinate attributes + attrs = attr_mgr.get_variable_attributes("event_id") + decom_ultra_dataset.coords["event_id"].attrs.update(attrs) + elif apid in ULTRA_ENERGY_SPECTRA.apid: + decom_ultra_dataset = process_ultra_energy_spectra( + datasets_by_apid[apid] + ) + decom_ultra_dataset = decom_ultra_dataset.drop_vars("compdata") + gattr_key = ULTRA_ENERGY_SPECTRA.logical_source[ + ULTRA_ENERGY_SPECTRA.apid.index(apid) + ] + elif apid in ULTRA_MACROS_CHECKSUM.apid: + decom_ultra_dataset = process_ultra_macros_checksum( + datasets_by_apid[apid] + ) + gattr_key = ULTRA_MACROS_CHECKSUM.logical_source[ + ULTRA_MACROS_CHECKSUM.apid.index(apid) + ] + elif apid in ULTRA_HK.apid: + decom_ultra_dataset = datasets_by_apid[apid] + gattr_key = ULTRA_HK.logical_source[ULTRA_HK.apid.index(apid)] + elif apid in ULTRA_CMD_TEXT.apid: + decom_ultra_dataset = datasets_by_apid[apid] + decoded_strings = [ + s.decode("ascii").rstrip("\x00") + for s in decom_ultra_dataset["text"].values + ] + decom_ultra_dataset = decom_ultra_dataset.drop_vars("text") + decom_ultra_dataset["text"] = xr.DataArray( + decoded_strings, + dims=["epoch"], + coords={"epoch": decom_ultra_dataset["epoch"]}, + ) + gattr_key = ULTRA_CMD_TEXT.logical_source[ + ULTRA_CMD_TEXT.apid.index(apid) + ] + elif apid in ULTRA_CMD_ECHO.apid: + decom_ultra_dataset = process_ultra_cmd_echo(datasets_by_apid[apid]) + gattr_key = ULTRA_CMD_ECHO.logical_source[ + ULTRA_CMD_ECHO.apid.index(apid) + ] + else: + logger.error(f"APID {apid} not recognized.") + continue + + decom_ultra_dataset.attrs.update(attr_mgr.get_global_attributes(gattr_key)) + + if i == 1: + # Derived values dataset at l1b + # We already have the l1a attributes, just update the l1a -> l1b + # in the metadata. + decom_ultra_dataset.attrs["Data_type"] = decom_ultra_dataset.attrs[ + "Data_type" + ].replace("1A", "1B") + decom_ultra_dataset.attrs["Logical_source"] = decom_ultra_dataset.attrs[ + "Logical_source" + ].replace("l1a", "l1b") + decom_ultra_dataset.attrs["Logical_source_description"] = ( + decom_ultra_dataset.attrs["Logical_source_description"].replace( + "1A", "1B" + ) + ) + + # Add data variable attributes + for key in decom_ultra_dataset.data_vars: + attrs = attr_mgr.get_variable_attributes(key.lower()) + decom_ultra_dataset.data_vars[key].attrs.update(attrs) + if i == 1: + # For l1b datasets, the FILLVAL and VALIDMIN/MAX may be + # different datatypes, so we can't use them directly from l1a. + # just remove them for now since we don't really have a need for + # for them currently. + for attr_key in ["FILLVAL", "VALIDMIN", "VALIDMAX"]: + if attr_key in decom_ultra_dataset.data_vars[key].attrs: + decom_ultra_dataset.data_vars[key].attrs.pop(attr_key) + # Add coordinate attributes - attrs = attr_mgr.get_variable_attributes("event_id") - decom_ultra_dataset.coords["event_id"].attrs.update(attrs) - elif apid in ULTRA_ENERGY_SPECTRA.apid: - decom_ultra_dataset = process_ultra_energy_spectra(datasets_by_apid[apid]) - decom_ultra_dataset = decom_ultra_dataset.drop_vars("compdata") - gattr_key = ULTRA_ENERGY_SPECTRA.logical_source[ - ULTRA_ENERGY_SPECTRA.apid.index(apid) - ] - elif apid in ULTRA_MACROS_CHECKSUM.apid: - decom_ultra_dataset = process_ultra_macros_checksum(datasets_by_apid[apid]) - gattr_key = ULTRA_MACROS_CHECKSUM.logical_source[ - ULTRA_MACROS_CHECKSUM.apid.index(apid) - ] - elif apid in ULTRA_HK.apid: - decom_ultra_dataset = datasets_by_apid[apid] - gattr_key = ULTRA_HK.logical_source[ULTRA_HK.apid.index(apid)] - elif apid in ULTRA_CMD_TEXT.apid: - decom_ultra_dataset = datasets_by_apid[apid] - decoded_strings = [ - s.decode("ascii").rstrip("\x00") - for s in decom_ultra_dataset["text"].values - ] - decom_ultra_dataset = decom_ultra_dataset.drop_vars("text") - decom_ultra_dataset["text"] = xr.DataArray( - decoded_strings, - dims=["epoch"], - coords={"epoch": decom_ultra_dataset["epoch"]}, - ) - gattr_key = ULTRA_CMD_TEXT.logical_source[ULTRA_CMD_TEXT.apid.index(apid)] - elif apid in ULTRA_CMD_ECHO.apid: - decom_ultra_dataset = process_ultra_cmd_echo(datasets_by_apid[apid]) - gattr_key = ULTRA_CMD_ECHO.logical_source[ULTRA_CMD_ECHO.apid.index(apid)] - else: - logger.error(f"APID {apid} not recognized.") - continue - - decom_ultra_dataset.attrs.update(attr_mgr.get_global_attributes(gattr_key)) - - # Add data variable attributes - for key in decom_ultra_dataset.data_vars: - attrs = attr_mgr.get_variable_attributes(key.lower()) - decom_ultra_dataset.data_vars[key].attrs.update(attrs) - - # Add coordinate attributes - attrs = attr_mgr.get_variable_attributes("epoch", check_schema=False) - decom_ultra_dataset.coords["epoch"].attrs.update(attrs) - - output_datasets.append(decom_ultra_dataset) + attrs = attr_mgr.get_variable_attributes("epoch", check_schema=False) + decom_ultra_dataset.coords["epoch"].attrs.update(attrs) + + output_datasets.append(decom_ultra_dataset) return output_datasets diff --git a/imap_processing/ultra/l1b/badtimes.py b/imap_processing/ultra/l1b/badtimes.py index c5c024ccc3..c78520a49e 100644 --- a/imap_processing/ultra/l1b/badtimes.py +++ b/imap_processing/ultra/l1b/badtimes.py @@ -7,13 +7,14 @@ from imap_processing.ultra.utils.ultra_l1_utils import create_dataset, extract_data_dict FILLVAL_UINT16 = 65535 +FILLVAL_FLOAT32 = -1.0e31 FILLVAL_FLOAT64 = -1.0e31 FILLVAL_UINT32 = 4294967295 def calculate_badtimes( extendedspin_dataset: xr.Dataset, - cullingmask_spins: NDArray, + goodtimes_spins: NDArray, name: str, ) -> xr.Dataset: """ @@ -23,7 +24,7 @@ def calculate_badtimes( ---------- extendedspin_dataset : xarray.Dataset Dataset containing the data. - cullingmask_spins : np.ndarray + goodtimes_spins : np.ndarray Dataset containing the culled data. name : str Name of the dataset. @@ -33,11 +34,9 @@ def calculate_badtimes( badtimes_dataset : xarray.Dataset Dataset containing the extendedspin data that has been culled. """ + n_bins = extendedspin_dataset.sizes["energy_bin_geometric_mean"] culled_spins = np.setdiff1d( - extendedspin_dataset["spin_number"].values, cullingmask_spins - ) - extendedspin_dataset = extendedspin_dataset.assign_coords( - epoch=("spin_number", extendedspin_dataset["epoch"].values) + extendedspin_dataset["spin_number"].values, goodtimes_spins ) filtered_dataset = extendedspin_dataset.sel(spin_number=culled_spins) @@ -48,9 +47,6 @@ def calculate_badtimes( if badtimes_dataset["spin_number"].size == 0: badtimes_dataset = badtimes_dataset.drop_dims("spin_number") badtimes_dataset = badtimes_dataset.expand_dims(spin_number=[FILLVAL_UINT32]) - badtimes_dataset = badtimes_dataset.assign_coords( - epoch=("spin_number", [extendedspin_dataset["epoch"].values[0]]) - ) badtimes_dataset["spin_start_time"] = xr.DataArray( np.array([FILLVAL_FLOAT64], dtype="float64"), dims=["spin_number"] ) @@ -60,16 +56,44 @@ def calculate_badtimes( badtimes_dataset["spin_rate"] = xr.DataArray( np.array([FILLVAL_FLOAT64], dtype="float64"), dims=["spin_number"] ) + badtimes_dataset["start_pulses_per_spin"] = xr.DataArray( + np.array([FILLVAL_FLOAT32], dtype="float32"), + dims=["spin_number"], + ) + badtimes_dataset["stop_pulses_per_spin"] = xr.DataArray( + np.array([FILLVAL_FLOAT32], dtype="float32"), + dims=["spin_number"], + ) + badtimes_dataset["coin_pulses_per_spin"] = xr.DataArray( + np.array([FILLVAL_FLOAT32], dtype="float32"), + dims=["spin_number"], + ) + badtimes_dataset["rejected_events_per_spin"] = xr.DataArray( + np.array([FILLVAL_UINT32], dtype="uint32"), + dims=["spin_number"], + ) badtimes_dataset["quality_attitude"] = xr.DataArray( np.array([FILLVAL_UINT16], dtype="uint16"), dims=["spin_number"] ) + badtimes_dataset["quality_hk"] = xr.DataArray( + np.array([FILLVAL_UINT16], dtype="uint16"), + dims=["spin_number"], + ) + badtimes_dataset["quality_instruments"] = xr.DataArray( + np.array([FILLVAL_UINT16], dtype="uint16"), + dims=["spin_number"], + ) badtimes_dataset["quality_ena_rates"] = ( ("energy_bin_geometric_mean", "spin_number"), - np.full((3, 1), FILLVAL_UINT16, dtype="uint16"), + np.full((n_bins, 1), FILLVAL_UINT16, dtype="uint16"), ) badtimes_dataset["ena_rates"] = ( ("energy_bin_geometric_mean", "spin_number"), - np.full((3, 1), FILLVAL_FLOAT64, dtype="float64"), + np.full((n_bins, 1), FILLVAL_FLOAT64, dtype="float64"), + ) + badtimes_dataset["ena_rates_threshold"] = ( + ("energy_bin_geometric_mean", "spin_number"), + np.full((n_bins, 1), FILLVAL_FLOAT32, dtype="float32"), ) return badtimes_dataset diff --git a/imap_processing/ultra/l1b/cullingmask.py b/imap_processing/ultra/l1b/cullingmask.py deleted file mode 100644 index 11a50ad061..0000000000 --- a/imap_processing/ultra/l1b/cullingmask.py +++ /dev/null @@ -1,90 +0,0 @@ -"""Calculate Culling Mask.""" - -import numpy as np -import xarray as xr - -from imap_processing.ultra.l1b.quality_flag_filters import SPIN_QUALITY_FLAG_FILTERS -from imap_processing.ultra.utils.ultra_l1_utils import create_dataset, extract_data_dict - -FILLVAL_UINT16 = 65535 -FILLVAL_FLOAT64 = -1.0e31 -FILLVAL_UINT32 = 4294967295 - - -def calculate_cullingmask(extendedspin_dataset: xr.Dataset, name: str) -> xr.Dataset: - """ - Create dataset with defined datatype for Culling Mask Data. - - Parameters - ---------- - extendedspin_dataset : xarray.Dataset - Dataset containing the data. - name : str - Name of the dataset. - - Returns - ------- - cullingmask_dataset : xarray.Dataset - Dataset containing the extendedspin data that remains after culling. - """ - # If the spin rate was too high or low then the spin should be thrown out. - # If the rates at any energy level are too high then throw out the entire spin. - good_mask = ( - ( - extendedspin_dataset["quality_attitude"] - & sum(flag.value for flag in SPIN_QUALITY_FLAG_FILTERS["quality_attitude"]) - ) - == 0 - ) & ( - ( - ( - extendedspin_dataset["quality_ena_rates"] - & sum( - flag.value - for flag in SPIN_QUALITY_FLAG_FILTERS["quality_ena_rates"] - ) - ) - == 0 - ).all(dim="energy_bin_geometric_mean") - ) - extendedspin_dataset = extendedspin_dataset.assign_coords( - epoch=("spin_number", extendedspin_dataset["epoch"].values) - ) - filtered_dataset = extendedspin_dataset.sel( - spin_number=extendedspin_dataset["spin_number"][good_mask] - ) - - data_dict = extract_data_dict(filtered_dataset) - - cullingmask_dataset = create_dataset(data_dict, name, "l1b") - - if cullingmask_dataset["spin_number"].size == 0: - cullingmask_dataset = cullingmask_dataset.drop_dims("spin_number") - cullingmask_dataset = cullingmask_dataset.expand_dims( - spin_number=[FILLVAL_UINT32] - ) - cullingmask_dataset = cullingmask_dataset.assign_coords( - epoch=("spin_number", [extendedspin_dataset["epoch"].values[0]]) - ) - cullingmask_dataset["spin_start_time"] = xr.DataArray( - np.array([FILLVAL_FLOAT64], dtype="float64"), dims=["spin_number"] - ) - cullingmask_dataset["spin_period"] = xr.DataArray( - np.array([FILLVAL_FLOAT64], dtype="float64"), dims=["spin_number"] - ) - cullingmask_dataset["spin_rate"] = xr.DataArray( - np.array([FILLVAL_FLOAT64], dtype="float64"), dims=["spin_number"] - ) - cullingmask_dataset["quality_attitude"] = xr.DataArray( - np.array([FILLVAL_UINT16], dtype="uint16"), dims=["spin_number"] - ) - cullingmask_dataset["quality_ena_rates"] = ( - ("energy_bin_geometric_mean", "spin_number"), - np.full((3, 1), FILLVAL_UINT16, dtype="uint16"), - ) - cullingmask_dataset["ena_rates"] = ( - ("energy_bin_geometric_mean", "spin_number"), - np.full((3, 1), FILLVAL_FLOAT64, dtype="float64"), - ) - - return cullingmask_dataset diff --git a/imap_processing/ultra/l1b/de.py b/imap_processing/ultra/l1b/de.py index b052548159..0122f756b8 100644 --- a/imap_processing/ultra/l1b/de.py +++ b/imap_processing/ultra/l1b/de.py @@ -9,6 +9,10 @@ ImapDEScatteringUltraFlags, ) from imap_processing.spice.geometry import SpiceFrame +from imap_processing.spice.repoint import get_pointing_times_from_id +from imap_processing.spice.time import ( + et_to_met, +) from imap_processing.ultra.l1b.lookup_utils import get_geometric_factor from imap_processing.ultra.l1b.ultra_l1b_annotated import ( get_annotated_particle_velocity, @@ -26,14 +30,14 @@ get_efficiency, get_energy_pulse_height, get_energy_ssd, - get_eventtimes, + get_event_times, get_front_x_position, get_front_y_position, get_fwhm, get_path_length, get_ph_tof_and_back_positions, get_phi_theta, - get_spin_number, + get_spin_info, get_ssd_back_position_and_tof_offset, get_ssd_tof, is_back_tof_valid, @@ -42,11 +46,12 @@ from imap_processing.ultra.utils.ultra_l1_utils import create_dataset FILLVAL_UINT8 = 255 +FILLVAL_UINT32 = 4294967295 FILLVAL_FLOAT32 = -1.0e31 def calculate_de( - de_dataset: xr.Dataset, name: str, ancillary_files: dict + de_dataset: xr.Dataset, aux_dataset: xr.Dataset, name: str, ancillary_files: dict ) -> xr.Dataset: """ Create dataset with defined datatypes for Direct Event Data. @@ -55,6 +60,8 @@ def calculate_de( ---------- de_dataset : xarray.Dataset L1a dataset containing direct event data. + aux_dataset : xarray.Dataset + L1a dataset containing auxiliary data. name : str Name of the l1a dataset. ancillary_files : dict @@ -68,12 +75,12 @@ def calculate_de( de_dict = {} sensor = parse_filename_like(name)["sensor"][0:2] - # Define epoch and spin. + # Define epoch de_dict["epoch"] = de_dataset["epoch"].data - spin_number = get_spin_number( - de_dataset["shcoarse"].values, de_dataset["spin"].values - ) - de_dict["spin"] = spin_number + + repoint_id = de_dataset.attrs.get("Repointing", None) + if repoint_id is not None: + repoint_id = int(repoint_id.replace("repoint", "")) # Add already populated fields. keys = [ @@ -82,7 +89,7 @@ def calculate_de( "event_type", "de_event_met", "phase_angle", - "spin", + "event_id", ] dataset_keys = [ "coin_type", @@ -90,16 +97,15 @@ def calculate_de( "stop_type", "shcoarse", "phase_angle", - "spin", + "event_id", ] - + # Populate de_dict with existing fields from de_dataset de_dict.update( { key: de_dataset[dataset_key] for key, dataset_key in zip(keys, dataset_keys, strict=False) } ) - valid_mask = de_dataset["start_type"].data != FILLVAL_UINT8 ph_mask = np.isin( de_dataset["stop_type"].data, [StopType.Top.value, StopType.Bottom.value] @@ -109,40 +115,79 @@ def calculate_de( valid_indices = np.nonzero(valid_mask)[0] ph_indices = np.nonzero(valid_mask & ph_mask)[0] ssd_indices = np.nonzero(valid_mask & ssd_mask)[0] - # Instantiate arrays - xf = np.full(len(de_dataset["epoch"]), FILLVAL_FLOAT32, dtype=np.float32) - yf = np.full(len(de_dataset["epoch"]), FILLVAL_FLOAT32, dtype=np.float32) - xb = np.full(len(de_dataset["epoch"]), FILLVAL_FLOAT32, dtype=np.float32) - yb = np.full(len(de_dataset["epoch"]), FILLVAL_FLOAT32, dtype=np.float32) - xc = np.full(len(de_dataset["epoch"]), FILLVAL_FLOAT32, dtype=np.float32) - d = np.full(len(de_dataset["epoch"]), FILLVAL_FLOAT32, dtype=np.float64) - r = np.full(len(de_dataset["epoch"]), FILLVAL_FLOAT32, dtype=np.float32) - phi = np.full(len(de_dataset["epoch"]), FILLVAL_FLOAT32, dtype=np.float32) - theta = np.full(len(de_dataset["epoch"]), FILLVAL_FLOAT32, dtype=np.float32) - tof = np.full(len(de_dataset["epoch"]), FILLVAL_FLOAT32, dtype=np.float32) - etof = np.full(len(de_dataset["epoch"]), FILLVAL_FLOAT32, dtype=np.float32) - ctof = np.full(len(de_dataset["epoch"]), FILLVAL_FLOAT32, dtype=np.float32) - tof_energy = np.full(len(de_dataset["epoch"]), FILLVAL_FLOAT32, dtype=np.float32) - magnitude_v = np.full(len(de_dataset["epoch"]), FILLVAL_FLOAT32, dtype=np.float32) - energy = np.full(len(de_dataset["epoch"]), FILLVAL_FLOAT32, dtype=np.float32) - e_bin = np.full(len(de_dataset["epoch"]), FILLVAL_UINT8, dtype=np.uint8) - species_bin = np.full(len(de_dataset["epoch"]), FILLVAL_UINT8, dtype=np.uint8) - t2 = np.full(len(de_dataset["epoch"]), FILLVAL_FLOAT32, dtype=np.float32) - event_times = np.full(len(de_dataset["epoch"]), FILLVAL_FLOAT32, dtype=np.float32) + xf: np.ndarray = np.full( + len(de_dataset["epoch"]), FILLVAL_FLOAT32, dtype=np.float32 + ) + yf: np.ndarray = np.full( + len(de_dataset["epoch"]), FILLVAL_FLOAT32, dtype=np.float32 + ) + xb: np.ndarray = np.full( + len(de_dataset["epoch"]), FILLVAL_FLOAT32, dtype=np.float32 + ) + yb: np.ndarray = np.full( + len(de_dataset["epoch"]), FILLVAL_FLOAT32, dtype=np.float32 + ) + xc: np.ndarray = np.full( + len(de_dataset["epoch"]), FILLVAL_FLOAT32, dtype=np.float32 + ) + d: np.ndarray = np.full(len(de_dataset["epoch"]), FILLVAL_FLOAT32, dtype=np.float64) + r: np.ndarray = np.full(len(de_dataset["epoch"]), FILLVAL_FLOAT32, dtype=np.float32) + phi: np.ndarray = np.full( + len(de_dataset["epoch"]), FILLVAL_FLOAT32, dtype=np.float32 + ) + theta: np.ndarray = np.full( + len(de_dataset["epoch"]), FILLVAL_FLOAT32, dtype=np.float32 + ) + tof: np.ndarray = np.full( + len(de_dataset["epoch"]), FILLVAL_FLOAT32, dtype=np.float32 + ) + etof: np.ndarray = np.full( + len(de_dataset["epoch"]), FILLVAL_FLOAT32, dtype=np.float32 + ) + ctof: np.ndarray = np.full( + len(de_dataset["epoch"]), FILLVAL_FLOAT32, dtype=np.float32 + ) + tof_energy: np.ndarray = np.full( + len(de_dataset["epoch"]), FILLVAL_FLOAT32, dtype=np.float32 + ) + magnitude_v: np.ndarray = np.full( + len(de_dataset["epoch"]), FILLVAL_FLOAT32, dtype=np.float32 + ) + energy: np.ndarray = np.full( + len(de_dataset["epoch"]), FILLVAL_FLOAT32, dtype=np.float32 + ) + e_bin: np.ndarray = np.full(len(de_dataset["epoch"]), FILLVAL_UINT8, dtype=np.uint8) + e_bin_l1a: np.ndarray = np.full( + len(de_dataset["epoch"]), FILLVAL_UINT8, dtype=np.uint8 + ) + species_bin: np.ndarray = np.full( + len(de_dataset["epoch"]), FILLVAL_UINT8, dtype=np.uint8 + ) + t2: np.ndarray = np.full( + len(de_dataset["epoch"]), FILLVAL_FLOAT32, dtype=np.float32 + ) + event_times: np.ndarray = np.full( + len(de_dataset["epoch"]), FILLVAL_FLOAT32, dtype=np.float64 + ) + spin_starts: np.ndarray = np.full( + len(de_dataset["epoch"]), FILLVAL_FLOAT32, dtype=np.float64 + ) shape = (len(de_dataset["epoch"]), 3) - sc_velocity = np.full(shape, FILLVAL_FLOAT32, dtype=np.float32) - sc_dps_velocity = np.full(shape, FILLVAL_FLOAT32, dtype=np.float32) - helio_velocity = np.full(shape, FILLVAL_FLOAT32, dtype=np.float32) - spin_starts = np.full(len(de_dataset["epoch"]), FILLVAL_FLOAT32, dtype=np.float64) - velocities = np.full(shape, FILLVAL_FLOAT32, dtype=np.float32) - v_hat = np.full(shape, FILLVAL_FLOAT32, dtype=np.float32) - r_hat = np.full(shape, FILLVAL_FLOAT32, dtype=np.float32) - - start_type = np.full(len(de_dataset["epoch"]), FILLVAL_UINT8, dtype=np.uint8) + sc_velocity: np.ndarray = np.full(shape, FILLVAL_FLOAT32, dtype=np.float32) + sc_dps_velocity: np.ndarray = np.full(shape, FILLVAL_FLOAT32, dtype=np.float32) + helio_velocity: np.ndarray = np.full(shape, FILLVAL_FLOAT32, dtype=np.float32) + velocities: np.ndarray = np.full(shape, FILLVAL_FLOAT32, dtype=np.float32) + v_hat: np.ndarray = np.full(shape, FILLVAL_FLOAT32, dtype=np.float32) + r_hat: np.ndarray = np.full(shape, FILLVAL_FLOAT32, dtype=np.float32) + + start_type: np.ndarray = np.full( + len(de_dataset["epoch"]), FILLVAL_UINT8, dtype=np.uint8 + ) quality_flags = np.full( de_dataset["epoch"].shape, ImapDEOutliersUltraFlags.NONE.value, dtype=np.uint16 ) + scattering_quality_flags = np.full( de_dataset["epoch"].shape, ImapDEScatteringUltraFlags.NONE.value, @@ -155,17 +200,19 @@ def calculate_de( f"ultra{sensor}", ancillary_files, ) + start_type[valid_indices] = de_dataset["start_type"].data[valid_indices] + spin_ds = get_spin_info(aux_dataset, de_dataset["shcoarse"].data) - ( - event_times[valid_indices], - spin_starts[valid_indices], - _, - ) = get_eventtimes( - de_dict["spin"][valid_indices], - de_dataset["phase_angle"].data[valid_indices], + (event_times[valid_mask], spin_starts[valid_mask]) = get_event_times( + aux_dataset, + de_dataset["shcoarse"].data[valid_mask], + de_dataset["phase_angle"].data[valid_mask], + spin_ds.isel(epoch=valid_mask), ) + de_dict["spin"] = spin_ds.spin_number.data + de_dict["event_times"] = event_times.astype(np.float64) # Pulse height ph_result = get_ph_tof_and_back_positions( de_dataset, xf, f"ultra{sensor}", ancillary_files @@ -196,26 +243,37 @@ def calculate_de( (xb[ph_indices], yb[ph_indices]), d[ph_indices], ) - species_bin[ph_indices] = determine_species(tof[ph_indices], r[ph_indices], "PH") etof[ph_indices], xc[ph_indices] = get_coincidence_positions( de_dataset.isel(epoch=ph_indices), t2[ph_indices], f"ultra{sensor}", ancillary_files, ) - backtofvalid = is_back_tof_valid( - de_dataset, - xf, + backtofvalid_quality_flags = np.zeros(len(ph_indices), dtype=quality_flags.dtype) + backtofvalid, backtofvalid_quality_flags = is_back_tof_valid( + de_dataset.isel(epoch=ph_indices), + xf[ph_indices], f"ultra{sensor}", ancillary_files, + backtofvalid_quality_flags, ) - coinphvalid = is_coin_ph_valid( + + coinphvalid_quality_flags = np.zeros(len(ph_indices), dtype=quality_flags.dtype) + coinphvalid, coinphvalid_quality_flags = is_coin_ph_valid( etof[ph_indices], xc[ph_indices], xb[ph_indices], + de_dataset["stop_north_tdc"][ph_indices].values, + de_dataset["stop_south_tdc"][ph_indices].values, + de_dataset["stop_east_tdc"][ph_indices].values, + de_dataset["stop_west_tdc"][ph_indices].values, f"ultra{sensor}", ancillary_files, + coinphvalid_quality_flags, ) + quality_flags[ph_indices] |= coinphvalid_quality_flags + quality_flags[ph_indices] |= backtofvalid_quality_flags + e_bin[ph_indices] = determine_ebin_pulse_height( energy[ph_indices], tof[ph_indices], @@ -224,6 +282,7 @@ def calculate_de( coinphvalid, ancillary_files, ) + species_bin[ph_indices] = determine_species(e_bin[ph_indices], "PH") ctof[ph_indices], magnitude_v[ph_indices] = get_ctof( tof[ph_indices], r[ph_indices], "PH" ) @@ -257,9 +316,7 @@ def calculate_de( f"ultra{sensor}", ancillary_files, ) - species_bin[ssd_indices] = determine_species( - tof[ssd_indices], r[ssd_indices], "SSD" - ) + species_bin[ssd_indices] = determine_species(e_bin[ssd_indices], "SSD") ctof[ssd_indices], magnitude_v[ssd_indices] = get_ctof( tof[ssd_indices], r[ssd_indices], "SSD" ) @@ -289,42 +346,63 @@ def calculate_de( de_dict["tof_start_stop"][valid_indices], ) ) - de_dict["direct_event_velocity"] = velocities.astype(np.float32) de_dict["direct_event_unit_velocity"] = v_hat.astype(np.float32) de_dict["direct_event_unit_position"] = r_hat.astype(np.float32) tof_energy[valid_indices] = get_de_energy_kev( - velocities[valid_indices], species_bin[valid_indices] + velocities[valid_indices], + species_bin[valid_indices], + quality_flags[valid_indices], ) de_dict["tof_energy"] = tof_energy de_dict["energy"] = energy - de_dict["ebin"] = e_bin + de_dict["computed_ebin"] = e_bin + valid_ebin = de_dataset["bin"].values != FILLVAL_UINT32 + e_bin_l1a[valid_ebin] = de_dataset["bin"].values[valid_ebin] + de_dict["ebin"] = e_bin_l1a de_dict["species"] = species_bin # Annotated Events. ultra_frame = getattr(SpiceFrame, f"IMAP_ULTRA_{sensor}") # Account for counts=0 (event times have FILL value) - valid_events = event_times != FILLVAL_FLOAT32 - if np.any(valid_events): - ( - sc_velocity[valid_events], - sc_dps_velocity[valid_events], - helio_velocity[valid_events], - ) = get_annotated_particle_velocity( - event_times[valid_events], - de_dict["direct_event_velocity"][valid_events], - ultra_frame, - SpiceFrame.IMAP_DPS, - SpiceFrame.IMAP_SPACECRAFT, + valid_events = (event_times != FILLVAL_FLOAT32).copy() + if repoint_id is not None: + # Check all valid event times to see which are in the pointing + in_pointing = calculate_events_in_pointing( + repoint_id, et_to_met(event_times[valid_events]) ) + # Initialize an array of all events as False + events_to_flag: np.ndarray = np.zeros(len(quality_flags), dtype=bool) + # Identify valid events that are outside the pointing + events_to_flag[valid_events] = ~in_pointing + # Update quality flags for valid events that are not in the pointing + quality_flags[events_to_flag] |= ImapDEOutliersUltraFlags.DURINGREPOINT.value + # Update valid_events to only include times within a pointing + valid_events[valid_events] &= in_pointing + + ( + sc_velocity[valid_events], + sc_dps_velocity[valid_events], + helio_velocity[valid_events], + ) = get_annotated_particle_velocity( + event_times[valid_events], + velocities.astype(np.float32)[valid_events], + ultra_frame, + SpiceFrame.IMAP_DPS, + SpiceFrame.IMAP_SPACECRAFT, + ) de_dict["velocity_sc"] = sc_velocity de_dict["velocity_dps_sc"] = sc_dps_velocity de_dict["velocity_dps_helio"] = helio_velocity - de_dict["energy_spacecraft"] = get_de_energy_kev(sc_dps_velocity, species_bin) - de_dict["energy_heliosphere"] = get_de_energy_kev(helio_velocity, species_bin) + de_dict["energy_spacecraft"] = get_de_energy_kev( + sc_dps_velocity, species_bin, quality_flags + ) + de_dict["energy_heliosphere"] = get_de_energy_kev( + helio_velocity, species_bin, quality_flags + ) de_dict["phi_fwhm"], de_dict["theta_fwhm"] = get_fwhm( start_type, @@ -335,7 +413,11 @@ def calculate_de( ancillary_files, ) de_dict["event_efficiency"] = get_efficiency( - de_dict["tof_energy"], de_dict["phi"], de_dict["theta"], ancillary_files + de_dict["tof_energy"], + de_dict["phi"], + de_dict["theta"], + ancillary_files, + f"ultra{sensor}", ) de_dict["geometric_factor_blades"] = get_geometric_factor( de_dict["phi"], @@ -351,6 +433,7 @@ def calculate_de( ancillary_files, "l1b-sensor-gf-noblades", ) + de_dict["quality_outliers"] = quality_flags flag_scattering( de_dict["tof_energy"], @@ -365,3 +448,31 @@ def calculate_de( dataset = create_dataset(de_dict, name, "l1b") return dataset + + +def calculate_events_in_pointing( + repoint_id: int, + event_times: np.ndarray, +) -> np.ndarray: + """ + Calculate boolean array of events within a pointing. + + Parameters + ---------- + repoint_id : int + The repointing ID. + event_times : np.ndarray + Array of event times in MET. + + Returns + ------- + in_pointing : np.ndarray + Boolean array indicating whether each event is within the pointing period + combined with the valid_events mask. + """ + pointing_start_met, pointing_end_met = get_pointing_times_from_id(repoint_id) + # Check which events are within the pointing + in_pointing = (event_times >= pointing_start_met) & ( + event_times <= pointing_end_met + ) + return in_pointing diff --git a/imap_processing/ultra/l1b/extendedspin.py b/imap_processing/ultra/l1b/extendedspin.py index c8b8d1edda..8fdd394999 100644 --- a/imap_processing/ultra/l1b/extendedspin.py +++ b/imap_processing/ultra/l1b/extendedspin.py @@ -2,23 +2,37 @@ import numpy as np import xarray as xr +from numpy.typing import NDArray +from imap_processing.ultra.constants import UltraConstants from imap_processing.ultra.l1b.ultra_l1b_culling import ( count_rejected_events_per_spin, + expand_bin_flags_to_spins, flag_attitude, + flag_high_energy, flag_hk, flag_imap_instruments, + flag_low_voltage, flag_rates, + flag_spectral_events, + flag_statistical_outliers, + flag_upstream_ion, + get_binned_energy_ranges, + get_binned_spins_edges, get_energy_histogram, + get_energy_range_flags, get_pulses_per_spin, ) +from imap_processing.ultra.l1c.l1c_lookup_utils import build_energy_bins from imap_processing.ultra.utils.ultra_l1_utils import create_dataset FILLVAL_UINT16 = 65535 +FILLVAL_FLOAT32 = -1.0e31 def calculate_extendedspin( dict_datasets: dict[str, xr.Dataset], + de_dataset: xr.Dataset, name: str, instrument_id: int, ) -> xr.Dataset: @@ -29,6 +43,8 @@ def calculate_extendedspin( ---------- dict_datasets : dict Dictionary containing all the datasets. + de_dataset : xarray.Dataset + Dataset containing the direct event data. name : str Name of the dataset. instrument_id : int @@ -41,14 +57,14 @@ def calculate_extendedspin( """ aux_dataset = dict_datasets[f"imap_ultra_l1a_{instrument_id}sensor-aux"] rates_dataset = dict_datasets[f"imap_ultra_l1a_{instrument_id}sensor-rates"] - de_dataset = dict_datasets[f"imap_ultra_l1b_{instrument_id}sensor-de"] + status_dataset = dict_datasets[f"imap_ultra_l1b_{instrument_id}sensor-status"] extendedspin_dict = {} - rates_qf, spin, energy_midpoints, n_sigma_per_energy = flag_rates( + rates_qf, spin, energy_bin_geometric_mean, n_sigma_per_energy = flag_rates( de_dataset["spin"].values, de_dataset["energy"].values, ) - count_rates, _, counts, _ = get_energy_histogram( + count_rates, _, _counts, _ = get_energy_histogram( de_dataset["spin"].values, de_dataset["energy"].values ) attitude_qf, spin_rates, spin_period, spin_starttime = flag_attitude( @@ -58,14 +74,74 @@ def calculate_extendedspin( hk_qf = flag_hk(de_dataset["spin"].values) inst_qf = flag_imap_instruments(de_dataset["spin"].values) - # Get the first epoch for each spin. - mask = xr.DataArray(np.isin(de_dataset["spin"], spin), dims="epoch") - filtered_dataset = de_dataset.where(mask, drop=True) - _, first_indices = np.unique(filtered_dataset["spin"].values, return_index=True) - first_epochs = filtered_dataset["epoch"].values[first_indices] - + spin_bin_size = UltraConstants.SPIN_BIN_SIZE + spin_tbin_edges = get_binned_spins_edges( + spin, spin_period, spin_starttime, spin_bin_size + ) + # Calculate goodtime quality flags. + # The culling algorithms should be called in the following order + # 1. Low voltage + # 2. High energy (energy dependent) + # 3. Upstream ion (with first set of energy channels) + # 4. Upstream ion (with second set of energy channels) + # 5. Spectral cull + # 6. Statistical outliers (energy dependent) + voltage_qf = flag_low_voltage(spin_tbin_edges, status_dataset) + # Get energy bins used at l1c + intervals, _, _ = build_energy_bins() + # Get the energy ranges + energy_ranges = get_binned_energy_ranges(intervals) + energy_bin_flags = get_energy_range_flags(energy_ranges) + # Calculate the high energy quality flags + energy_thresholds = UltraConstants.HIGH_ENERGY_CULL_THRESHOLDS + high_energy_qf = flag_high_energy( + de_dataset, + spin_tbin_edges, + energy_ranges, + voltage_qf, + energy_thresholds, + instrument_id, + ) + # For the following culls, mask the spins that have already been flagged for + # low voltage + mask = np.repeat( + voltage_qf[np.newaxis, :], len(energy_ranges) - 1, axis=0 + ) # Shape (n_energy_bins, n_spins_bins) + upstream_ion_qf_1 = flag_upstream_ion( + de_dataset, + spin_tbin_edges, + energy_ranges, + mask, + UltraConstants.UPSTREAM_ION_ENERGY_CHANNELS_1, + instrument_id, + ) + upstream_ion_qf_2 = flag_upstream_ion( + de_dataset, + spin_tbin_edges, + energy_ranges, + mask, + UltraConstants.UPSTREAM_ION_ENERGY_CHANNELS_2, + instrument_id, + ) + spectral_qf = flag_spectral_events( + de_dataset, + spin_tbin_edges, + energy_ranges, + UltraConstants.SPECTRAL_ENERGY_CHANNELS, + instrument_id, + ) + # Update mask to include high energy, upstream ion flags and spectral flags + # before flagging statistical outliers + mask = mask | upstream_ion_qf_1 | upstream_ion_qf_2 | spectral_qf | high_energy_qf + stat_outliers_qf, _, _, _ = flag_statistical_outliers( + de_dataset, + spin_tbin_edges, + energy_ranges, + mask, + instrument_id, + ) # Get the number of pulses per spin. - pulses = get_pulses_per_spin(rates_dataset) + pulses = get_pulses_per_spin(aux_dataset, rates_dataset) # Track rejected events in each spin based on # quality flags in de l1b data. @@ -74,25 +150,106 @@ def calculate_extendedspin( de_dataset["quality_scattering"].values, de_dataset["quality_outliers"].values, ) + # These will be the coordinates. - extendedspin_dict["epoch"] = first_epochs extendedspin_dict["spin_number"] = spin - extendedspin_dict["energy_bin_geometric_mean"] = energy_midpoints + extendedspin_dict["energy_bin_geometric_mean"] = energy_bin_geometric_mean extendedspin_dict["ena_rates"] = count_rates extendedspin_dict["ena_rates_threshold"] = n_sigma_per_energy extendedspin_dict["spin_start_time"] = spin_starttime extendedspin_dict["spin_period"] = spin_period extendedspin_dict["spin_rate"] = spin_rates - extendedspin_dict["start_pulses_per_spin"] = pulses.start_per_spin - extendedspin_dict["stop_pulses_per_spin"] = pulses.stop_per_spin - extendedspin_dict["coin_pulses_per_spin"] = pulses.coin_per_spin + + # Get index of pulses.unique_spins corresponding to each spin. + idx: NDArray[np.intp] = np.searchsorted(pulses.unique_spins, spin) + + # Validate that the spin values match + valid = (idx < pulses.unique_spins.size) & (pulses.unique_spins[idx] == spin) + + start_per_spin: np.ndarray = np.full(len(spin), FILLVAL_FLOAT32, dtype=np.float32) + stop_per_spin: np.ndarray = np.full(len(spin), FILLVAL_FLOAT32, dtype=np.float32) + coin_per_spin: np.ndarray = np.full(len(spin), FILLVAL_FLOAT32, dtype=np.float32) + + # Fill only the valid ones + start_per_spin[valid] = pulses.start_per_spin[idx[valid]] + stop_per_spin[valid] = pulses.stop_per_spin[idx[valid]] + coin_per_spin[valid] = pulses.coin_per_spin[idx[valid]] + + # To be consistent with the ULTRA IT implementation, apply the low voltage mask + # to the high energy and upstream ion flags + upstream_ion_qf_2 |= voltage_qf + upstream_ion_qf_1 |= voltage_qf + high_energy_qf |= voltage_qf + spectral_qf |= voltage_qf + # high energy and statistical outlier flags are energy dependent boolean arrays + # with shape (n_energy_bins, n_spin_bins). We want to collapse the energy dimension + # using a bitwise OR to get a single boolean flag per spin. + high_energy_qf = np.bitwise_or.reduce( + high_energy_qf * energy_bin_flags[:, np.newaxis], axis=0 + ) + stat_outliers_qf = np.bitwise_or.reduce( + stat_outliers_qf * energy_bin_flags[:, np.newaxis], axis=0 + ) + # Low voltage and upstream ion flags are shape (n_spin_bins,) but we want to + # convert from a boolean to a bitwise flag to be consistent with the other flags, + # where each spin that is flagged will have the bitflag of all the energy flags + # combined. + combined_flags = np.bitwise_or.reduce(energy_bin_flags) + voltage_qf = voltage_qf * combined_flags + upstream_ion_qf_1 = upstream_ion_qf_1 * combined_flags + upstream_ion_qf_2 = upstream_ion_qf_2 * combined_flags + spectral_qf = spectral_qf * combined_flags + # Expand binned quality flags to individual spins. + high_energy_qf = expand_bin_flags_to_spins(len(spin), high_energy_qf, spin_bin_size) + voltage_qf = expand_bin_flags_to_spins(len(spin), voltage_qf, spin_bin_size) + spectral_qf = expand_bin_flags_to_spins(len(spin), spectral_qf, spin_bin_size) + upstream_ion_qf_1 = expand_bin_flags_to_spins( + len(spin), upstream_ion_qf_1, spin_bin_size + ) + upstream_ion_qf_2 = expand_bin_flags_to_spins( + len(spin), upstream_ion_qf_2, spin_bin_size + ) + stat_outliers_qf = expand_bin_flags_to_spins( + len(spin), stat_outliers_qf, spin_bin_size + ) + # account for rates spins which are not in the direct event spins + extendedspin_dict["start_pulses_per_spin"] = start_per_spin + extendedspin_dict["stop_pulses_per_spin"] = stop_per_spin + extendedspin_dict["coin_pulses_per_spin"] = coin_per_spin extendedspin_dict["rejected_events_per_spin"] = rejected_counts extendedspin_dict["quality_attitude"] = attitude_qf extendedspin_dict["quality_ena_rates"] = rates_qf extendedspin_dict["quality_hk"] = hk_qf extendedspin_dict["quality_instruments"] = inst_qf + extendedspin_dict["quality_low_voltage"] = voltage_qf # shape (nspin,) + extendedspin_dict["quality_upstream_ion_1"] = upstream_ion_qf_1 # shape (nspin,) + extendedspin_dict["quality_upstream_ion_2"] = upstream_ion_qf_2 # shape (nspin,) + extendedspin_dict["quality_spectral"] = spectral_qf # shape (nspin,) + extendedspin_dict["quality_statistics"] = stat_outliers_qf # shape (nspin,) + extendedspin_dict["quality_high_energy"] = high_energy_qf # shape (nspin,) + # ISTP requires stable dimension sizes, so this field must always remain size 16. + # If fewer bins are used, pad the remaining entries with 0. + energy_flags: np.ndarray = np.full( + UltraConstants.MAX_ENERGY_RANGES, 0, dtype=np.uint16 + ) + energy_flags[: len(energy_bin_flags)] = energy_bin_flags + extendedspin_dict["energy_range_flags"] = energy_flags + extendedspin_dict["energy_range_flags_dim"] = np.arange( + UltraConstants.MAX_ENERGY_RANGES + ) - extendedspin_dataset = create_dataset(extendedspin_dict, name, "l1b") + # Initialize array of energy range edges with fill value, then fill in the valid + # energy ranges. Set the length to be the max number of energy bins we expect to + # use for culling. The number of edges is one more than the number of bins (17). + ranges: np.ndarray = np.full( + (UltraConstants.MAX_ENERGY_RANGE_EDGES,), FILLVAL_FLOAT32, dtype=np.float32 + ) + ranges[: len(energy_ranges)] = energy_ranges + extendedspin_dict["energy_range_edges"] = ranges + extendedspin_dict["energy_range_edges_dim"] = np.arange( + UltraConstants.MAX_ENERGY_RANGE_EDGES + ) + extendedspin_dataset = create_dataset(extendedspin_dict, name, "l1b") return extendedspin_dataset diff --git a/imap_processing/ultra/l1b/goodtimes.py b/imap_processing/ultra/l1b/goodtimes.py new file mode 100644 index 0000000000..5a57191e5a --- /dev/null +++ b/imap_processing/ultra/l1b/goodtimes.py @@ -0,0 +1,128 @@ +"""Calculate Goodtimes.""" + +import numpy as np +import xarray as xr + +from imap_processing.ultra.l1b.quality_flag_filters import SPIN_QUALITY_FLAG_FILTERS +from imap_processing.ultra.utils.ultra_l1_utils import create_dataset, extract_data_dict + +FILLVAL_UINT16 = 65535 +FILLVAL_FLOAT32 = -1.0e31 +FILLVAL_FLOAT64 = -1.0e31 +FILLVAL_UINT32 = 4294967295 + + +def calculate_goodtimes(extendedspin_dataset: xr.Dataset, name: str) -> xr.Dataset: + """ + Create dataset with defined datatype for Goodtimes Data. + + Parameters + ---------- + extendedspin_dataset : xarray.Dataset + Dataset containing the data. + name : str + Name of the dataset. + + Returns + ------- + goodtimes_dataset : xarray.Dataset + Dataset containing the extendedspin data that remains after culling. + """ + n_bins = extendedspin_dataset.sizes["energy_bin_geometric_mean"] + # If the spin rate was too high or low then the spin should be thrown out. + # If the rates at any energy level are too high then throw out the entire spin. + good_mask = ( + ( + extendedspin_dataset["quality_attitude"] + & sum(flag.value for flag in SPIN_QUALITY_FLAG_FILTERS["quality_attitude"]) + ) + == 0 + ) & ( + ( + ( + extendedspin_dataset["quality_ena_rates"] + & sum( + flag.value + for flag in SPIN_QUALITY_FLAG_FILTERS["quality_ena_rates"] + ) + ) + == 0 + ).all(dim="energy_bin_geometric_mean") + ) + filtered_dataset = extendedspin_dataset.sel( + spin_number=extendedspin_dataset["spin_number"][good_mask] + ) + + data_dict = extract_data_dict(filtered_dataset) + goodtimes_dataset = create_dataset(data_dict, name, "l1b") + if goodtimes_dataset["spin_number"].size == 0: + goodtimes_dataset = goodtimes_dataset.drop_dims("spin_number") + goodtimes_dataset = goodtimes_dataset.expand_dims(spin_number=[FILLVAL_UINT32]) + goodtimes_dataset["spin_start_time"] = xr.DataArray( + np.array([FILLVAL_FLOAT64], dtype="float64"), dims=["spin_number"] + ) + goodtimes_dataset["spin_period"] = xr.DataArray( + np.array([FILLVAL_FLOAT64], dtype="float64"), dims=["spin_number"] + ) + goodtimes_dataset["spin_rate"] = xr.DataArray( + np.array([FILLVAL_FLOAT64], dtype="float64"), dims=["spin_number"] + ) + goodtimes_dataset["start_pulses_per_spin"] = xr.DataArray( + np.array([FILLVAL_FLOAT32], dtype="float32"), + dims=["spin_number"], + ) + goodtimes_dataset["stop_pulses_per_spin"] = xr.DataArray( + np.array([FILLVAL_FLOAT32], dtype="float32"), + dims=["spin_number"], + ) + goodtimes_dataset["coin_pulses_per_spin"] = xr.DataArray( + np.array([FILLVAL_FLOAT32], dtype="float32"), + dims=["spin_number"], + ) + goodtimes_dataset["rejected_events_per_spin"] = xr.DataArray( + np.array([FILLVAL_UINT32], dtype="uint32"), + dims=["spin_number"], + ) + goodtimes_dataset["quality_attitude"] = xr.DataArray( + np.array([FILLVAL_UINT16], dtype="uint16"), dims=["spin_number"] + ) + goodtimes_dataset["quality_low_voltage"] = xr.DataArray( + np.array([FILLVAL_UINT16], dtype="uint16"), dims=["spin_number"] + ) + goodtimes_dataset["quality_high_energy"] = xr.DataArray( + np.array([FILLVAL_UINT16], dtype="uint16"), dims=["spin_number"] + ) + goodtimes_dataset["quality_upstream_ion_1"] = xr.DataArray( + np.array([FILLVAL_UINT16], dtype="uint16"), dims=["spin_number"] + ) + goodtimes_dataset["quality_upstream_ion_2"] = xr.DataArray( + np.array([FILLVAL_UINT16], dtype="uint16"), dims=["spin_number"] + ) + goodtimes_dataset["quality_spectral"] = xr.DataArray( + np.array([FILLVAL_UINT16], dtype="uint16"), dims=["spin_number"] + ) + goodtimes_dataset["quality_statistics"] = xr.DataArray( + np.array([FILLVAL_UINT16], dtype="uint16"), dims=["spin_number"] + ) + goodtimes_dataset["quality_hk"] = xr.DataArray( + np.array([FILLVAL_UINT16], dtype="uint16"), + dims=["spin_number"], + ) + goodtimes_dataset["quality_instruments"] = xr.DataArray( + np.array([FILLVAL_UINT16], dtype="uint16"), + dims=["spin_number"], + ) + goodtimes_dataset["quality_ena_rates"] = ( + ("energy_bin_geometric_mean", "spin_number"), + np.full((n_bins, 1), FILLVAL_UINT16, dtype="uint16"), + ) + goodtimes_dataset["ena_rates"] = ( + ("energy_bin_geometric_mean", "spin_number"), + np.full((n_bins, 1), FILLVAL_FLOAT64, dtype="float64"), + ) + goodtimes_dataset["ena_rates_threshold"] = ( + ("energy_bin_geometric_mean", "spin_number"), + np.full((n_bins, 1), FILLVAL_FLOAT32, dtype="float32"), + ) + + return goodtimes_dataset diff --git a/imap_processing/ultra/l1b/lookup_utils.py b/imap_processing/ultra/l1b/lookup_utils.py index a6e1bca9b2..fb9dad25c8 100644 --- a/imap_processing/ultra/l1b/lookup_utils.py +++ b/imap_processing/ultra/l1b/lookup_utils.py @@ -1,5 +1,7 @@ """Contains tools for lookup tables for l1b.""" +import logging + import numpy as np import numpy.typing as npt import pandas as pd @@ -7,6 +9,9 @@ from numpy.typing import NDArray from imap_processing.quality_flags import ImapDEOutliersUltraFlags +from imap_processing.ultra.constants import UltraConstants + +logger = logging.getLogger(__name__) def get_y_adjust(dy_lut: np.ndarray, ancillary_files: dict) -> npt.NDArray: @@ -209,7 +214,7 @@ def get_angular_profiles( return lookup_table -def get_energy_efficiencies(ancillary_files: dict) -> pd.DataFrame: +def get_energy_efficiencies(ancillary_files: dict, sensor: str) -> pd.DataFrame: """ Lookup table for efficiencies for theta and phi. @@ -220,14 +225,22 @@ def get_energy_efficiencies(ancillary_files: dict) -> pd.DataFrame: ---------- ancillary_files : dict[Path] Ancillary files. + sensor : str + Sensor name: "ultra45" or "ultra90". Returns ------- lookup_table : DataFrame Efficiencies lookup table for a given sensor. """ - # TODO: add sensor to input when new lookup tables are available. - lookup_table = pd.read_csv(ancillary_files["l1b-45sensor-logistic-interpolation"]) + if sensor == "ultra45": + lookup_table = pd.read_csv( + ancillary_files["l1b-45sensor-logistic-interpolation"] + ) + else: + lookup_table = pd.read_csv( + ancillary_files["l1b-90sensor-logistic-interpolation"] + ) return lookup_table @@ -319,7 +332,7 @@ def get_geometric_factor( # Fetch geometric factor values at nearest (phi, theta) pairs geometric_factor = geometric_factor_tables["gf_table"][phi_idx, theta_idx] - outside_fov = ~is_inside_fov(np.deg2rad(phi), np.deg2rad(theta)) + outside_fov = ~is_inside_fov(np.deg2rad(theta), np.deg2rad(phi)) quality_flag[outside_fov] |= ImapDEOutliersUltraFlags.FOV.value return geometric_factor @@ -345,7 +358,7 @@ def load_scattering_lookup_tables(ancillary_files: dict, instrument_id: int) -> # TODO remove the line below when the 45 sensor scattering coefficients are # delivered. instrument_id = 90 - descriptor = f"l1b-{instrument_id}sensor-scattering-calibration" + descriptor = f"l1b-{instrument_id}sensor-scattering-calibration-data" theta_grid = pd.read_csv( ancillary_files[descriptor], header=None, skiprows=7, nrows=241 ).to_numpy(dtype=float) @@ -434,7 +447,7 @@ def get_scattering_coefficients( ) -def is_inside_fov(phi: np.ndarray, theta: np.ndarray) -> np.ndarray: +def is_inside_fov(theta: np.ndarray, phi: np.ndarray) -> np.ndarray: """ Determine angles in the field of view (FOV). @@ -445,10 +458,10 @@ def is_inside_fov(phi: np.ndarray, theta: np.ndarray) -> np.ndarray: Parameters ---------- - phi : np.ndarray - Azimuth angles in radians. theta : np.ndarray Elevation angles in radians. + phi : np.ndarray + Azimuth angles in radians. Returns ------- @@ -456,10 +469,16 @@ def is_inside_fov(phi: np.ndarray, theta: np.ndarray) -> np.ndarray: Boolean array indicating if the angle is in the FOV, False otherwise. """ numerator = 5.0 * np.cos(phi) - denominator = 1 + 2.80 * np.cos(phi) + denominator = 1.0 + 2.80 * np.cos(phi) # Equation 19 in the Ultra Algorithm Document. - theta_nom = np.arctan(numerator / denominator) - return np.abs(theta) <= theta_nom + theta_nom = np.arctan(numerator / denominator) - np.radians( + UltraConstants.FOV_THETA_OFFSET_DEG + ) + + theta_check = np.abs(theta) <= np.abs(theta_nom) + phi_check = np.abs(phi) <= np.radians(UltraConstants.FOV_PHI_LIMIT_DEG) + + return theta_check & phi_check def get_ph_corrected( @@ -601,3 +620,71 @@ def get_scattering_thresholds(ancillary_files: dict) -> dict: threshold_dict = {(row[0], row[1]): row[2] for row in thresholds} return threshold_dict + + +def get_de_product_name( + repoint: str, sensor: int, data_level: str, ancillary_files: dict +) -> str: + """ + Get the name of the de product to use for processing. + + This will be either the raw de product or a priority 1-4 de product, depending on + the pointing and data level. + + Note: Currently the lookup tables are identical between ultra45 and ultra90, + but this function accounts for the possibility of them being different in the + future. + + Parameters + ---------- + repoint : str + The repointing ID in the format "repointXXXXX" where XXXXX is the repointing + number. + sensor : int + Sensor number, either 45 or 90. + data_level : str + Data level, either "l1b" or "l1c". + ancillary_files : dict + Ancillary files containing the lookup tables to determine which DE product + to use based on the repointing ID. + + Returns + ------- + de_product_name : str + Name of the de product to use for processing. + """ + if data_level not in ["l1b", "l1c"]: + raise ValueError(f"Invalid data level: {data_level}. Must be 'l1b' or 'l1c'.") + # load the lookup table. + # The lookup table will have columns for repointing_id_start, repointing_id_end, + # and de_product. If repointing_id_end is NaN that indicates that the de_product + # should be used for all repoint IDs greater than or equal to repointing_id_start. + file_name = f"{data_level}-{sensor}sensor-de-product-lookup" + de_lookup = pd.read_csv(ancillary_files[file_name]) + repoint_id = int(repoint.replace("repoint", "")) + # Filter the dataset to find where the current repoint ID falls within the + # repointing_id_start and repointing_id_end range. OR if repointing_id_end is NaN, + # then just check if repoint_id is greater than or equal to repointing_id_start + repoint_row = de_lookup[ + (de_lookup["repointing_id_start"] <= repoint_id) + & ( + (de_lookup["repointing_id_end"] > repoint_id) + | (pd.isna(de_lookup["repointing_id_end"])) + ) + ] + if repoint_row.empty: + raise ValueError( + f"No DE product found for repoint ID {repoint_id} in {file_name}" + ) + if len(repoint_row) > 1: + raise ValueError( + f"Multiple DE products found for repoint ID {repoint_id} using " + f"ancillary file {file_name}. Check that the " + f"repointing_id_start and repointing_id_end values are correct" + f" and not overlapping." + ) + product = repoint_row["de_product"].values[0] + logger.info( + f"Using DE product {product} for repoint ID {repoint_id} based on lookup table" + ) + return product diff --git a/imap_processing/ultra/l1b/quality_flag_filters.py b/imap_processing/ultra/l1b/quality_flag_filters.py index 42843d37b2..faa3921a58 100644 --- a/imap_processing/ultra/l1b/quality_flag_filters.py +++ b/imap_processing/ultra/l1b/quality_flag_filters.py @@ -8,15 +8,33 @@ ) SPIN_QUALITY_FLAG_FILTERS: dict[str, list[FlagNameMixin]] = { - "quality_attitude": [], + "quality_attitude": [], # This is empty for now but can be populated with attitude + # flags in the future "quality_ena_rates": [ ImapRatesUltraFlags.FIRSTSPIN, ImapRatesUltraFlags.LASTSPIN, ], } +# The following quality flag arrays contain flags that are dynamically created +# In ULTRA l1b extended spin. The flags are created based on the number +# Of bins that were used to group energies. If the flag array is in this list, +# Then all flags in the array will be used for filtering. +ENERGY_DEPENDENT_SPIN_QUALITY_FLAG_FILTERS: list = [ + "quality_low_voltage", + "quality_upstream_ion_1", + "quality_upstream_ion_2", + "quality_spectral", + "quality_high_energy", + "quality_statistics", +] DE_QUALITY_FLAG_FILTERS: dict[str, list[FlagNameMixin]] = { - "quality_outliers": [ImapDEOutliersUltraFlags.FOV], + "quality_outliers": [ + ImapDEOutliersUltraFlags.FOV, + ImapDEOutliersUltraFlags.DURINGREPOINT, + ImapDEOutliersUltraFlags.COINPH, + ImapDEOutliersUltraFlags.BACKTOF, + ], "quality_scattering": [ ImapDEScatteringUltraFlags.ABOVE_THRESHOLD, ], diff --git a/imap_processing/ultra/l1b/ultra_l1b.py b/imap_processing/ultra/l1b/ultra_l1b.py index 21d7bacbd4..d698193145 100644 --- a/imap_processing/ultra/l1b/ultra_l1b.py +++ b/imap_processing/ultra/l1b/ultra_l1b.py @@ -1,11 +1,17 @@ """Calculate ULTRA L1b.""" +import logging +import re + import xarray as xr from imap_processing.ultra.l1b.badtimes import calculate_badtimes -from imap_processing.ultra.l1b.cullingmask import calculate_cullingmask from imap_processing.ultra.l1b.de import calculate_de from imap_processing.ultra.l1b.extendedspin import calculate_extendedspin +from imap_processing.ultra.l1b.goodtimes import calculate_goodtimes +from imap_processing.ultra.l1b.lookup_utils import get_de_product_name + +logger = logging.getLogger(__name__) def ultra_l1b(data_dict: dict, ancillary_files: dict) -> list[xr.Dataset]: @@ -29,17 +35,32 @@ def ultra_l1b(data_dict: dict, ancillary_files: dict) -> list[xr.Dataset]: General flow: 1. l1a data products are created (upstream to this code) 2. l1b de is created here and dropped in s3 kicking off processing again - 3. l1b extended, culling, badtimes created here + 3. l1b extended, goodtimes, badtimes created here """ output_datasets = [] - # Account for possibility of having 45 and 90 in dictionary. for instrument_id in [45, 90]: + # Find any de product if it is in the data_dict + l1a_de_products = [ + name + for name in data_dict.keys() + if re.search(rf"^imap_ultra_l1a_{instrument_id}sensor.*-de$", name) + ] # L1b de data will be created if L1a de data is available - if f"imap_ultra_l1a_{instrument_id}sensor-de" in data_dict: + # Including priority de products + if l1a_de_products: + l1a_de_product = l1a_de_products[0] + if len(l1a_de_products) > 1: + raise ValueError( + f"Multiple L1a de products found for instrument {instrument_id}. " + f"Expected only one but found {len(l1a_de_products)}: " + f"{l1a_de_products}" + ) + l1b_de_product = l1a_de_product.replace("l1a", "l1b") de_dataset = calculate_de( - data_dict[f"imap_ultra_l1a_{instrument_id}sensor-de"], - f"imap_ultra_l1b_{instrument_id}sensor-de", + data_dict[l1a_de_product], + data_dict[f"imap_ultra_l1a_{instrument_id}sensor-aux"], + l1b_de_product, ancillary_files, ) output_datasets.append(de_dataset) @@ -50,7 +71,25 @@ def ultra_l1b(data_dict: dict, ancillary_files: dict) -> list[xr.Dataset]: and f"imap_ultra_l1a_{instrument_id}sensor-rates" in data_dict and f"imap_ultra_l1a_{instrument_id}sensor-aux" in data_dict and f"imap_ultra_l1a_{instrument_id}sensor-params" in data_dict + and f"imap_ultra_l1b_{instrument_id}sensor-status" in data_dict ): + # get repoint number + repoint = data_dict[f"imap_ultra_l1b_{instrument_id}sensor-de"].attrs.get( + "Repointing", None + ) + if repoint is None: + raise ValueError("Repointing ID attribute is missing from the dataset.") + # Determine which l1b de product to use in calculating the goodtimes + # Will be either the raw de product or a priority 1-4 de product. + de_product_desc = get_de_product_name( + repoint, instrument_id, "l1b", ancillary_files + ) + if de_product_desc not in data_dict: + raise ValueError( + f"Selected L1B DE product '{de_product_desc}' for instrument " + f"{instrument_id} is not present in data_dict. Available L1B DE " + f"products: {data_dict.keys()}" + ) extendedspin_dataset = calculate_extendedspin( { f"imap_ultra_l1a_{instrument_id}sensor-aux": data_dict[ @@ -62,32 +101,33 @@ def ultra_l1b(data_dict: dict, ancillary_files: dict) -> list[xr.Dataset]: f"imap_ultra_l1a_{instrument_id}sensor-rates": data_dict[ f"imap_ultra_l1a_{instrument_id}sensor-rates" ], - f"imap_ultra_l1b_{instrument_id}sensor-de": data_dict[ - f"imap_ultra_l1b_{instrument_id}sensor-de" + f"imap_ultra_l1b_{instrument_id}sensor-status": data_dict[ + f"imap_ultra_l1b_{instrument_id}sensor-status" ], }, + data_dict[de_product_desc], f"imap_ultra_l1b_{instrument_id}sensor-extendedspin", instrument_id, ) output_datasets.append(extendedspin_dataset) elif ( f"imap_ultra_l1b_{instrument_id}sensor-extendedspin" in data_dict - and f"imap_ultra_l1b_{instrument_id}sensor-cullingmask" in data_dict + and f"imap_ultra_l1b_{instrument_id}sensor-goodtimes" in data_dict ): badtimes_dataset = calculate_badtimes( data_dict[f"imap_ultra_l1b_{instrument_id}sensor-extendedspin"], - data_dict[f"imap_ultra_l1b_{instrument_id}sensor-cullingmask"][ + data_dict[f"imap_ultra_l1b_{instrument_id}sensor-goodtimes"][ "spin_number" ].values, f"imap_ultra_l1b_{instrument_id}sensor-badtimes", ) output_datasets.append(badtimes_dataset) elif f"imap_ultra_l1b_{instrument_id}sensor-extendedspin" in data_dict: - cullingmask_dataset = calculate_cullingmask( + goodtimes_dataset = calculate_goodtimes( data_dict[f"imap_ultra_l1b_{instrument_id}sensor-extendedspin"], - f"imap_ultra_l1b_{instrument_id}sensor-cullingmask", + f"imap_ultra_l1b_{instrument_id}sensor-goodtimes", ) - output_datasets.append(cullingmask_dataset) + output_datasets.append(goodtimes_dataset) if not output_datasets: raise ValueError("Data dictionary does not contain the expected keys.") diff --git a/imap_processing/ultra/l1b/ultra_l1b_annotated.py b/imap_processing/ultra/l1b/ultra_l1b_annotated.py index c7fb167365..8731ab9f01 100644 --- a/imap_processing/ultra/l1b/ultra_l1b_annotated.py +++ b/imap_processing/ultra/l1b/ultra_l1b_annotated.py @@ -52,7 +52,6 @@ def get_annotated_particle_velocity( from_frame=instrument_frame, to_frame=spacecraft_frame, ) - # Particle velocity in the pointing (DPS) frame wrt spacecraft. particle_velocity_dps_spacecraft = frame_transform( et=time, diff --git a/imap_processing/ultra/l1b/ultra_l1b_culling.py b/imap_processing/ultra/l1b/ultra_l1b_culling.py index 3764261649..3ec5c2a9b0 100644 --- a/imap_processing/ultra/l1b/ultra_l1b_culling.py +++ b/imap_processing/ultra/l1b/ultra_l1b_culling.py @@ -5,7 +5,9 @@ import numpy as np import pandas as pd +import spiceypy as sp import xarray as xr +from numpy.lib.stride_tricks import sliding_window_view from numpy.typing import NDArray from imap_processing.quality_flags import ( @@ -15,15 +17,23 @@ ImapInstrumentUltraFlags, ImapRatesUltraFlags, ) +from imap_processing.spice.geometry import ( + SpiceBody, + SpiceFrame, +) from imap_processing.spice.spin import get_spin_data from imap_processing.ultra.constants import UltraConstants from imap_processing.ultra.l1b.lookup_utils import ( get_scattering_coefficients, get_scattering_thresholds, ) -from imap_processing.ultra.l1b.quality_flag_filters import DE_QUALITY_FLAG_FILTERS +from imap_processing.ultra.l1b.quality_flag_filters import ( + DE_QUALITY_FLAG_FILTERS, + ENERGY_DEPENDENT_SPIN_QUALITY_FLAG_FILTERS, +) +from imap_processing.ultra.l1b.ultra_l1b_extended import get_spin_info +from imap_processing.ultra.l1c.l1c_lookup_utils import build_energy_bins -logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) SPIN_DURATION = 15 # Default spin duration in seconds. @@ -31,6 +41,7 @@ RateResult = namedtuple( "RateResult", [ + "unique_spins", "start_per_spin", "stop_per_spin", "coin_per_spin", @@ -70,8 +81,7 @@ def get_energy_histogram( spin_df = get_spin_data() unique_spin_number = np.unique(spin_number) - spin_edges = unique_spin_number.astype(np.uint16) - spin_edges = np.append(spin_edges, spin_edges.max() + 1) + spin_edges: np.ndarray = np.append(unique_spin_number, unique_spin_number.max() + 1) # Counts per spin at each energy bin. hist, _ = np.histogramdd( @@ -128,12 +138,11 @@ def flag_attitude( spins = np.unique(spin_number) # Get unique spins spin_df = get_spin_data() # Load spin data - spin_period = spin_df.loc[spin_df.spin_number.isin(spins), "spin_period_sec"] - spin_starttime = spin_df.loc[spin_df.spin_number.isin(spins), "spin_start_met"] - spin_phase_valid = spin_df.loc[spin_df.spin_number.isin(spins), "spin_phase_valid"] - spin_period_valid = spin_df.loc[ - spin_df.spin_number.isin(spins), "spin_period_valid" - ] + spin_df = spin_df[spin_df.spin_number.isin(spins)] + spin_period = spin_df["spin_period_sec"].values + spin_starttime = spin_df["spin_start_met"].values + spin_phase_valid = spin_df["spin_phase_valid"].values + spin_period_valid = spin_df["spin_period_valid"].values spin_rates = 60 / spin_period # 60 seconds in a minute bad_spin_rate_indices = (spin_rates < UltraConstants.CULLING_RPM_MIN) | ( spin_rates > UltraConstants.CULLING_RPM_MAX @@ -249,12 +258,12 @@ def flag_rates( Quality flags. spin : NDArray Spin data. - energy_midpoints : NDArray - Energy midpoint data. + energy_bin_geometric_mean : NDArray + Energy bin geometric mean. n_sigma_per_energy_reshape : NDArray N sigma per energy. """ - count_rates, spin_edges, counts, duration = get_energy_histogram( + count_rates, _spin_edges, _counts, duration = get_energy_histogram( spin_number, energy ) quality_flags = np.full( @@ -264,7 +273,7 @@ def flag_rates( threshold = get_n_sigma(count_rates, duration, sigma=sigma) bin_edges = np.array(UltraConstants.CULLING_ENERGY_BIN_EDGES) - energy_midpoints = np.sqrt(bin_edges[:-1] * bin_edges[1:]) + energy_bin_geometric_mean = np.sqrt(bin_edges[:-1] * bin_edges[1:]) spin = np.unique(spin_number) # Indices where the counts exceed the threshold @@ -275,7 +284,7 @@ def flag_rates( quality_flags[:, 0] |= ImapRatesUltraFlags.FIRSTSPIN.value quality_flags[:, -1] |= ImapRatesUltraFlags.LASTSPIN.value - return quality_flags, spin, energy_midpoints, threshold + return quality_flags, spin, energy_bin_geometric_mean, threshold def compare_aux_univ_spin_table( @@ -312,7 +321,7 @@ def compare_aux_univ_spin_table( .loc[present_in_both] ) - mismatch_indices = np.zeros(len(spins), dtype=bool) + mismatch_indices: np.ndarray = np.zeros(len(spins), dtype=bool) fields_to_compare = [ ("timespinstart", "spin_start_sec_sclk"), @@ -323,7 +332,7 @@ def compare_aux_univ_spin_table( ] # Compare fields - mismatch = np.zeros(len(df_aux), dtype=bool) + mismatch: np.ndarray = np.zeros(len(df_aux), dtype=bool) for aux_field, spin_field in fields_to_compare: mismatch |= df_aux[aux_field].values != df_univ[spin_field].values @@ -339,91 +348,21 @@ def compare_aux_univ_spin_table( return mismatch_indices -# TODO: Make this a common util since it is being used for the de and rates packets. -def get_spin_and_duration(met: NDArray, spin: NDArray) -> tuple[NDArray, NDArray]: - """ - Get the spin number and duration. - - Parameters - ---------- - met : NDArray - Mission elapsed time. - spin : NDArray - Spin number 0-255. - - Returns - ------- - assigned_spin_number : NDArray - Spin number for packet data product. - """ - # Packet data. - # Since the spin number in the direct events packet - # is only 8 bits it goes from 0-255. - # Within a pointing that means we will always have duplicate spin numbers. - # In other words, different spins will be represented by the same spin number. - # Just to make certain that we won't accidentally combine - # multiple spins we need to sort by time here. - sort_idx = np.argsort(met) - packet_met_sorted = met[sort_idx] - packet_spin_sorted = spin[sort_idx] - # Here we are finding the start and end indices of each spin in the sorted array. - is_new_spin = np.concatenate( - [[True], packet_spin_sorted.values[1:] != packet_spin_sorted.values[:-1]] - ) - spin_start_indices = np.where(is_new_spin)[0] - spin_end_indices = np.append(spin_start_indices[1:], len(packet_met_sorted)) - - # Universal Spin Table. - spin_df = get_spin_data() - # Retrieve the met values of the start of the spin. - spin_start_mets = spin_df["spin_start_met"].values - # Retrieve the corresponding spin numbers. - spin_numbers = spin_df["spin_number"].values - spin_period_sec = spin_df["spin_period_sec"].values - assigned_spin_number_sorted = np.empty(packet_spin_sorted.shape, dtype=np.uint32) - assigned_spin_duration_sorted = np.empty(packet_spin_sorted.shape, dtype=np.float32) - # These last 8 bits are the same as the spin number in the DE packet. - # So this will give us choices of which spins are - # available to assign to the packet data. - possible_spins = spin_numbers & 0xFF - - # Assign each group based on time. - for start, end in zip(spin_start_indices, spin_end_indices, strict=False): - # Now that we have the possible spins from the Universal Spin Table, - # we match the times of those spins to the nearest times in the DE data. - possible_times = spin_start_mets[ - possible_spins == packet_spin_sorted.values[start] - ] - # Get nearest time for matching spins. - nearest_idx = np.abs(possible_times - packet_met_sorted.values[start]).argmin() - nearest_value = possible_times[nearest_idx] - assigned_spin_number_sorted[start:end] = spin_numbers[ - spin_start_mets == nearest_value - ] - assigned_spin_duration_sorted[start:end] = spin_period_sec[ - spin_start_mets == nearest_value - ] - - # Undo the sort to match original order. - assigned_spin_number = np.empty_like(assigned_spin_number_sorted) - assigned_spin_number[sort_idx] = assigned_spin_number_sorted - assigned_duration = np.empty_like(assigned_spin_duration_sorted) - assigned_duration[sort_idx] = assigned_spin_duration_sorted - - return assigned_spin_number, assigned_duration - - -def get_pulses_per_spin(rates: xr.Dataset) -> RateResult: +def get_pulses_per_spin(aux: xr.Dataset, rates: xr.Dataset) -> RateResult: """ Get the total number of pulses per spin. Parameters ---------- + aux : xr.Dataset + Auxiliary dataset. rates : xr.Dataset Rates dataset. Returns ------- + unique_spins : NDArray + Unique spin numbers. start_per_spin : NDArray Total start pulses per spin. stop_per_spin : NDArray @@ -437,7 +376,8 @@ def get_pulses_per_spin(rates: xr.Dataset) -> RateResult: coin_pulses : NDArray Total coincidence pulses. """ - spin_number, duration = get_spin_and_duration(rates["shcoarse"], rates["spin"]) + spin_ds = get_spin_info(aux, rates["shcoarse"].values) + spin_number = spin_ds["spin_number"].values # Top coin pulses top_coin_pulses = np.stack( @@ -474,6 +414,7 @@ def get_pulses_per_spin(rates: xr.Dataset) -> RateResult: coin_per_spin = np.bincount(spin_idx, weights=coin_pulses) return RateResult( + unique_spins=unique_spins, start_per_spin=start_per_spin, stop_per_spin=stop_per_spin, coin_per_spin=coin_per_spin, @@ -510,7 +451,13 @@ def flag_scattering( Quality flags. """ scattering_thresholds = get_scattering_thresholds(ancillary_files) - + _, _, energy_bin_geometric_means = build_energy_bins() + energy_bin_inds = np.digitize(tof_energy, UltraConstants.PSET_ENERGY_BIN_EDGES) + # Clip indices to valid range (events outside the energy bins get assigned + # to the nearest bin. These events have already been flagged and + # will be ignored in l1c) + energy_bin_inds = np.clip(energy_bin_inds, 1, len(energy_bin_geometric_means)) + energy_geom_means = energy_bin_geometric_means[energy_bin_inds - 1] for (e_min, e_max), threshold in scattering_thresholds.items(): event_mask = (tof_energy >= e_min) & (tof_energy < e_max) # Input the theta and phi values for the current energy range. @@ -524,8 +471,11 @@ def flag_scattering( ) # FWHM_PHI = A_PHI * E^G_PHI # FWHM_THETA = A_THETA * E^G_THETA - fwhm_theta = theta_coeffs[:, 0] * tof_energy[event_mask] ** theta_coeffs[:, 1] - fwhm_phi = phi_coeffs[:, 0] * tof_energy[event_mask] ** phi_coeffs[:, 1] + # Use the geometric mean of the energy bin for the scattering check + fwhm_theta = ( + theta_coeffs[:, 0] * energy_geom_means[event_mask] ** theta_coeffs[:, 1] + ) + fwhm_phi = phi_coeffs[:, 0] * energy_geom_means[event_mask] ** phi_coeffs[:, 1] is_nan = np.isnan(fwhm_theta) | np.isnan(fwhm_phi) quality_flags[np.where(event_mask)[0][is_nan]] |= ( ImapDEScatteringUltraFlags.NAN_PHI_OR_THETA.value @@ -542,7 +492,9 @@ def flag_scattering( def get_de_rejection_mask( - quality_scattering: NDArray, quality_outliers: NDArray + quality_scattering: NDArray, + quality_outliers: NDArray, + reject_scattering: bool = True, ) -> NDArray: """ Create boolean mask where event is rejected due to relevant flags. @@ -553,6 +505,8 @@ def get_de_rejection_mask( Quality scattering flags. quality_outliers : NDArray Quality outliers flags. + reject_scattering : bool + Whether to reject based on scattering flags. Returns ------- @@ -566,10 +520,74 @@ def get_de_rejection_mask( outliers_mask = sum( flag.value for flag in DE_QUALITY_FLAG_FILTERS["quality_outliers"] ) + if reject_scattering: + # Boolean mask where event is rejected due to relevant flags + rejected = ((quality_scattering & scattering_mask) != 0) | ( + (quality_outliers & outliers_mask) != 0 + ) + else: + rejected = (quality_outliers & outliers_mask) != 0 - # Boolean mask where event is rejected due to relevant flags - rejected = ((quality_scattering & scattering_mask) != 0) | ( - (quality_outliers & outliers_mask) != 0 + return rejected + + +def get_energy_and_spin_dependent_rejection_mask( + goodtimes_dataset: xr.Dataset, + energy: np.ndarray, + spin_number: np.ndarray, +) -> NDArray: + """ + Create boolean mask where event is rejected due to relevant flags. + + Parameters + ---------- + goodtimes_dataset : xr.Dataset + Dataset containing valid spins and energy bin flags. + energy : np.ndarray + The particle energy at each direct event. + spin_number : np.ndarray + Spin number at each direct event. + + Returns + ------- + rejected : NDArray + Rejected events where True = rejected. + """ + # Get the ebin flags for each energy bin from the goodtimes dataset. + energy_range_edges = goodtimes_dataset["energy_range_edges"].values + # Filter out fill values from energy_range_edges (negative or zero) + energy_range_edges = energy_range_edges[energy_range_edges > 0] + # Get the quality flag arrays "turned on" for energy dependent culling from the + # goodtimes dataset. + flag_arrays = [ + goodtimes_dataset[flag_name].values + for flag_name in ENERGY_DEPENDENT_SPIN_QUALITY_FLAG_FILTERS + ] + # Initialize all events to not rejected + rejected = np.zeros_like(energy, dtype=bool) + ebin_flags = goodtimes_dataset["energy_range_flags"].values + # Filter out fill values (0s) from energy_range_flags + ebin_flags = ebin_flags[ebin_flags > 0] + # Get the index of the spin number in the goodtimes dataset for each event + # all spin numbers should be present in the goodtimes dataset since we have already + # filtered any events that are not + spin_idx = np.searchsorted(goodtimes_dataset.spin_number, spin_number) + event_energy_bins: NDArray = (np.digitize(energy, energy_range_edges) - 1).astype( + np.intp + ) + in_valid_bin = (event_energy_bins >= 0) & (event_energy_bins < len(ebin_flags)) + # get the flags for each event + event_flags = np.zeros_like(energy, dtype=np.uint16) + event_flags[in_valid_bin] = ebin_flags[event_energy_bins[in_valid_bin]] + for qf_array in flag_arrays: + # select the quality flag for each event + quality_flags_at_events = qf_array[spin_idx] + # If that flag is "turned on" for the spin of that event, and the event is in + # an energy bin that is flagged for culling, then we reject that event. + rejected |= quality_flags_at_events & event_flags > 0 + + logger.info( + "Rejected %d events based on energy and spin dependent flags.", np.sum(rejected) ) return rejected @@ -607,3 +625,798 @@ def count_rejected_events_per_spin( ) return rejected_counts + + +def flag_low_voltage( + spin_tbin_edges: NDArray, + status_dataset: xr.Dataset, + voltage_threshold: float = UltraConstants.LOW_VOLTAGE_CULL_THRESHOLD, +) -> NDArray: + """ + Flag low voltage events. + + Parameters + ---------- + spin_tbin_edges : NDArray + Edges of the spin time bins. + status_dataset : xarray.Dataset + Status dataset containing voltage information. + voltage_threshold : float + Voltage threshold below which to flag low voltage events. + + Returns + ------- + quality_flags : NDArray + Boolean quality flags shaped (n_spin_bins,). + """ + spin_bin_size = len(spin_tbin_edges) - 1 + # initialize all spins to have no low voltage flag + quality_flags: np.ndarray = np.zeros(spin_bin_size, dtype=bool) + # Get the min voltage across both deflection plate at each epoch + min_voltage = np.minimum( + status_dataset["rightdeflection_v"].data, + status_dataset["leftdeflection_v"].data, + ) + # Get the indices where the min voltage is below the threshold + low_voltage_inds = np.nonzero(min_voltage < voltage_threshold)[0] + + if not low_voltage_inds.size: + return quality_flags + + low_voltage_times = status_dataset["shcoarse"].data[low_voltage_inds] + # For each low voltage time, find the corresponding spin time + lv_spin_inds = np.atleast_1d( + np.searchsorted(spin_tbin_edges, low_voltage_times, side="right") - 1 + ) + # Ensure that the indices are within the valid range of spin groups + valid_bin_inds = (lv_spin_inds >= 0) & (lv_spin_inds < spin_bin_size) + lv_spin_inds = lv_spin_inds[valid_bin_inds] + # For each low voltage ind, flag the corresponding flag + quality_flags[lv_spin_inds] = True + + num_culled: int = np.sum(quality_flags) + logger.info( + f"Low voltage culling removed {num_culled} spin bins across all energy " + f"channels. Voltage threshold: {voltage_threshold} V." + ) + + return quality_flags + + +def flag_high_energy( + de_dataset: xr.Dataset, + spin_tbin_edges: NDArray, + energy_ranges: NDArray, + mask: NDArray = None, + energy_thresholds: np.ndarray = UltraConstants.HIGH_ENERGY_CULL_THRESHOLDS, + sensor_id: int = 90, +) -> NDArray: + """ + Flag high energy events. + + Parameters + ---------- + de_dataset : xr.Dataset + Direct event dataset. + spin_tbin_edges : NDArray + Edges of the spin time bins. + energy_ranges : numpy.ndarray + Array of energy range edges. + mask : numpy.ndarray, optional + Mask indicating which events to consider for high energy flagging + (e.g., after low voltage culling). True indicates the spin bins that should + NOT be considered for high energy flagging. + energy_thresholds : numpy.ndarray + Array of count thresholds for flagging high energy events corresponding to + each energy range. + sensor_id : int + Sensor ID (e.g., 45 or 90). + + Returns + ------- + quality_flags : numpy.ndarray + Boolean quality flags shaped (n_energy_bins, n_spin_bins). + """ + # expand energy thresholds to have shape (n_energy_bins, 1) for comparison with + # the counts per spin + energy_thresholds = energy_thresholds[:, np.newaxis] # Shape (n_energy_bins, 1) + cull_channel = UltraConstants.HIGH_ENERGY_CULL_CHANNEL + n_energy_bins = len(energy_ranges) - 1 + if len(energy_thresholds) != n_energy_bins: + raise ValueError( + f"Length of energy_thresholds ({len(energy_thresholds)}) must match" + f" the number of energy bins ({n_energy_bins})." + ) + if cull_channel >= n_energy_bins: + raise ValueError( + f"HIGH_ENERGY_CULL_CHANNEL ({cull_channel}) is out of bounds" + f" for {n_energy_bins} energy ranges." + ) + + # Initialize all spin bins to have no high energy flag + spin_bin_size = len(spin_tbin_edges) - 1 + quality_flags: np.ndarray = np.zeros((n_energy_bins, spin_bin_size), dtype=bool) + # Get valid events and counts at each spin bin for the + # designated culling channel. + de_counts = get_valid_de_count_summary( + de_dataset, + energy_ranges, + spin_tbin_edges, + UltraConstants.HIGH_ENERGY_COMBINED_SPIN_BIN_RADIUS, + sensor_id, + ) + cull_channel_counts = de_counts[cull_channel] + # flag spins where the counts in the cull channel exceed the threshold for that + # energy range + flagged = ( + cull_channel_counts[np.newaxis, :] >= energy_thresholds + ) # (n_energy_bins, n_spin_bins) + + if mask is not None: + quality_flags[:, ~mask] = flagged[:, ~mask] + else: + quality_flags = flagged + + num_culled: int = np.sum(quality_flags) + logger.info( + f"High energy culling removed {num_culled} spin bins across {n_energy_bins} " + f"energy channels. Energy thresholds: {energy_thresholds.flatten()}, " + ) + + return quality_flags + + +def flag_statistical_outliers( + de_dataset: xr.Dataset, + spin_tbin_edges: NDArray, + energy_ranges: NDArray, + mask: NDArray, + sensor_id: int = 90, + n_iterations: int = UltraConstants.STAT_CULLING_N_ITER, + std_threshold: float = UltraConstants.STAT_CULLING_STD_THRESHOLD, + combine_flags_across_energy_bins: bool = True, +) -> tuple[NDArray, NDArray, NDArray, NDArray]: + """ + Flag statistical outlier events based on count rates per spin. + + After low voltage and high energy spins have been flagged, there still appears to + be some time dependency in the signal. This algorithm identifies those outliers. + + Iterative algorithm to identify areas consistent with Poisson statistics + For each energy range: + 1. Flag where there are less than 3 bins with counts + 2. Calculate the mean (ΞΌ) and standard deviation (Οƒ) of the counts in each bin. + 3. Find bins where the counts, c, yield |(c-ΞΌ)/Οƒ|>3,Β  cull these bins + 4. Calculate Ξ΅=Οƒ/√μ-1 + 5. If Ξ΅ is less than a threshold value (0.05 for now) stop iterating + 6. If number of iterations exceeds threshold (5 for now), stop iterating + 7. Return to step 1 + + Parameters + ---------- + de_dataset : xr.Dataset + Direct event dataset. + spin_tbin_edges : numpy.ndarray + Edges of the spin time bins. + energy_ranges : numpy.ndarray + Array of energy range edges. + mask : numpy.ndarray + Mask indicating which events to consider for statistical outlier flagging. + This should be a 2d boolean array of shape (n_energy_bins, n_spin_bins) where + True indicates the spin bins that have been flagged in previous steps (e.g., + after low voltage and high energy culling) and should be excluded from the + outlier flagging process. + sensor_id : int + Sensor ID (e.g., 45 or 90). + n_iterations : int + Maximum number of iterations to perform for outlier flagging. + std_threshold : float + Threshold for standard deviation difference from Poisson stats to determine + convergence. + combine_flags_across_energy_bins : bool + Whether to link energy channels such that if a spin bin is flagged in any energy + channel, it is flagged in all energy channels. + + Returns + ------- + quality_stats : numpy.ndarray + Quality flags for statistical outliers, shaped (n_energy_bins, n_spin_bins). + convergence : numpy.ndarray + Boolean array of shape (n_energy_bins,) indicating whether the outlier flagging + converged for each energy bin. + iterations : numpy.ndarray + Array of shape (n_energy_bins,) indicating how many iterations were performed + for each energy bin. + std_diff : numpy.ndarray + Array of shape (n_energy_bins,) containing the final standard deviation + difference from Poisson stats for each energy bin. + """ + # Initialize all spin bins to have no outlier flag + spin_bin_size = len(spin_tbin_edges) - 1 + n_energy_bins = len(energy_ranges) - 1 + # make a copy of the current mask to avoid modifying the original mask passed in. + # This contains flags from previous steps (e.g., after low voltage and high + # energy culling) and will be updated iteratively to include the outlier flags as + # well + curr_mask = mask.copy() + # Initialize quality_stats to keep track of which bins are flagged as outliers for + # each energy bin + quality_stats: np.ndarray = np.zeros((n_energy_bins, spin_bin_size), dtype=bool) + # Initialize a mask to keep track of spin bins that have been flagged across all + # energy bins + all_channel_mask: np.ndarray = curr_mask[0, :].copy() + # Initialize convergence array to keep track of poisson stats + convergence = np.full(n_energy_bins, False) + # Keep track of how many iterations we have done of flagging outliers and + # recalculating stats per energy bin + iterations = np.zeros(n_energy_bins) + # keep track of the standard deviation difference from poisson stats per energy bin + std_diff: np.ndarray = np.zeros(n_energy_bins, dtype=float) + count_summary = get_valid_de_count_summary( + de_dataset, energy_ranges, spin_tbin_edges, sensor_id=sensor_id + ) # shape (n_energy_bins, n_spin_bins) + for e_idx in range(n_energy_bins): + good_mask = ~curr_mask[e_idx] # spin bins that are not currently flagged + for it in range(n_iterations): + counts = count_summary[e_idx, good_mask] + # Step 1. check if there are less than three valid counts. + # If so, flag all spins for that energy bin and skip to the next iteration + if len(counts) < 3: + quality_stats[e_idx] = True + curr_mask[e_idx] = True + convergence[e_idx] = True + std_diff[e_idx] = -1 + break + # Step 2. Check how close the data is to poisson stats + std_ratio, outlier_mask = get_poisson_stats(counts) + std_diff[e_idx] = std_ratio + # Step 3. Flag bins where the count is more than 3 standard deviations from + # the mean. + outlier_inds = np.where(good_mask)[0][outlier_mask] + # Set the quality flag to True for the outlier inds + quality_stats[e_idx, outlier_inds] = True + all_channel_mask[outlier_inds] = True + good_mask[outlier_inds] = False + iterations[e_idx] = it + 1 + # Check for convergence: if the standard deviation difference from + # poisson stats is below the threshold, then we can stop iterating for this + # energy bin + if std_ratio < std_threshold: + convergence[e_idx] = True + break + + if combine_flags_across_energy_bins: + # If true, then use the all_channel_mask for every energy channel. + quality_stats[:] = all_channel_mask + # Recalculate convergence with the combined mask. + for e_idx in range(n_energy_bins): + if not convergence[e_idx]: + # Select counts that have not been flagged in any channel. + counts = count_summary[e_idx, ~all_channel_mask] + std_ratio, _ = get_poisson_stats(counts) + if std_ratio < std_threshold: + convergence[e_idx] = True + + num_culled: int = np.sum(quality_stats) + logger.info( + f"Statistical culling removed {num_culled} spin bins across {n_energy_bins}" + f" energy channels. Convergence: {convergence} after " + f"{iterations} iterations." + ) + + return quality_stats, convergence, iterations, std_diff + + +def get_poisson_stats(counts: NDArray) -> tuple[float, NDArray]: + """ + Calculate Poisson statistics for a given array of counts. + + For a perfect Poisson distribution, the standard deviation should equal + the square root of the mean. The std_ratio measures how far the observed + distribution deviates from this. + + Outliers are identified as bins where the counts deviate more than 3 + standard deviations from the mean. + + Parameters + ---------- + counts : numpy.ndarray + Array of counts per spin bin for a given energy range. + + Returns + ------- + std_ratio : float + Ratio of the observed standard deviation to the expected Poisson + standard deviation. + sub_mask : numpy.ndarray + Boolean array of the same length as counts. True where a bin is + a statistical outlier (more than 3 sigma from the mean). + """ + std = np.std(counts) + if std == 0: + # If std is 0, then all counts are the same. In this case, we can consider + # there to be no outliers and the distribution to perfectly match Poisson + return 0, np.zeros_like(counts, dtype=bool) + std_ratio = std / np.sqrt(np.mean(counts)) - 1 + sub_mask = np.abs((counts - np.mean(counts)) / std) > 3 + return std_ratio, sub_mask + + +def flag_upstream_ion( + de_dataset: xr.Dataset, + spin_tbin_edges: NDArray, + energy_ranges: NDArray, + mask: NDArray, + channels: list, + sensor_id: int = 90, +) -> NDArray: + """ + Flag upstream ion events. + + Parameters + ---------- + de_dataset : xr.Dataset + Direct event dataset. + spin_tbin_edges : NDArray + Edges of the spin time bins. + energy_ranges : NDArray + Array of energy range edges. + mask : NDArray + Mask indicating which events to consider for upstream ion flagging. This should + be a 2d boolean array of shape (n_energy_bins, n_spin_bins) where True + indicates the spin bins that have been flagged in previous steps + and should be excluded from the upstream ion flagging process. + channels : list + List of energy channel indices to use for upstream ion flagging. + sensor_id : int + Sensor ID (e.g., 45 or 90). + + Returns + ------- + flagged : NDArray + Boolean array of shape (n_spin_bins,) where True indicates spin bins flagged for + upstream ions. These flags are energy independent and should be applied across + all energy channels. + """ + # validate that the channels provided are within the bounds of the energy ranges + if not np.all([ch in range(len(energy_ranges) - 1) for ch in channels]): + raise ValueError( + f"Channels provided for upstream ion flagging must be within the bounds" + f" of the energy ranges. Provided channels: {channels}, number of energy" + f" ranges: {len(energy_ranges) - 1}." + ) + counts_sum = get_valid_de_count_summary( + de_dataset, energy_ranges, spin_tbin_edges, sensor_id=sensor_id + )[channels, :] # shape (num_channels, n_spin_bins) + flagged = np.zeros(counts_sum.shape[1], dtype=bool) + channel_mask = ~mask[channels, :] + weights = channel_mask.sum(axis=0) + # Sum counts where the mask is True (valid) + sum_scaled_counts = np.where(channel_mask, counts_sum, 0).sum(axis=0) + # Get 1D array of valid spin bins + valid_bins = np.flatnonzero(weights > 0) + total_scaled = sum_scaled_counts[valid_bins] + if valid_bins.size == 0 or total_scaled.size == 0: + logger.info( + "Upstream Ion culling found no valid spin bins for evaluation; " + "returning all-False upstream ion flags." + ) + return flagged + + total_mean = np.mean(total_scaled) + # Set a threshold based on poisson stats for the total counts across the channels + thresh = total_mean + UltraConstants.UPSTREAM_SIG_THRESHOLD * np.sqrt(total_mean) + # Flag bins where the total counts across the channels exceed the threshold + flagged[valid_bins[total_scaled > thresh]] = True + + num_culled: int = np.sum(flagged) + logger.info( + f"Upstream Ion culling removed {num_culled} spin bins. These are energy" + f" independent flags and will be applied across all {mask.shape[0]} energy" + f" channels." + ) + return flagged + + +def flag_spectral_events( + de_dataset: xr.Dataset, + spin_tbin_edges: NDArray, + energy_ranges: NDArray, + channels: list, + sensor_id: int = 90, +) -> NDArray: + """ + Flag spectral events. + + Parameters + ---------- + de_dataset : xr.Dataset + Direct event dataset. + spin_tbin_edges : NDArray + Edges of the spin time bins. + energy_ranges : NDArray + Array of energy range edges. + channels : list + List of energy channel indices to use for spectral flagging. + sensor_id : int + Sensor ID (e.g., 45 or 90). + + Returns + ------- + flagged : NDArray + Boolean array of shape (n_spin_bins,) where True indicates spin bins flagged for + spectral anomalies. These flags are energy independent and should be applied + across all energy channels. + """ + # validate that the channels provided are within the bounds of the energy ranges + if not np.all([ch in range(len(energy_ranges) - 1) for ch in channels]): + raise ValueError( + f"Channels provided for spectral flagging must be within the bounds" + f" of the energy ranges. Provided channels: {channels}, number of energy" + f" ranges: {len(energy_ranges) - 1}." + ) + counts_sum = get_valid_de_count_summary( + de_dataset, energy_ranges, spin_tbin_edges, sensor_id=sensor_id + )[channels, :] # shape (num_channels, n_spin_bins) + # Flag spin bins where the signed count difference between adjacent selected + # energy channels exceeds a Poisson-based threshold. For each pair of + # adjacent channels, compute np.diff(counts_sum, axis=0) and compare that + # signed difference to a threshold scaled by the combined Poisson + # uncertainty (sqrt(N1 + N2)) of those two channels for each spin bin. + # If any adjacent channel pair exceeds the threshold for a spin bin, that + # spin bin is flagged across all energy ranges. + diff = np.diff(counts_sum, axis=0) - UltraConstants.SPECTRAL_SIG_THRESHOLD * ( + np.sqrt(counts_sum[:-1] + counts_sum[1:]) + ) # shape (num_channels - 1, n_spin_bins) + flagged = np.any(diff > 0, axis=0) # shape (n_spin_bins,) + num_culled: int = np.sum(flagged) + logger.info( + f"Spectral culling removed {num_culled} spin bins using channels" + f" {channels} and threshold {UltraConstants.SPECTRAL_SIG_THRESHOLD}." + f" These are energy independent flags and will be applied across all" + f" energy channels." + ) + return flagged + + +def get_valid_de_count_summary( + de_dataset: xr.Dataset, + energy_ranges: NDArray, + spin_tbin_edges: NDArray, + combine_spin_bin_radius: int | None = None, + sensor_id: int = 90, +) -> NDArray: + """ + Get a summary of valid counts per energy range and spin bin. + + Parameters + ---------- + de_dataset : xr.Dataset + Direct event dataset. + energy_ranges : numpy.ndarray + Array of energy range edges. + spin_tbin_edges : numpy.ndarray + Array of spin time bin edges. + combine_spin_bin_radius : int + If not None, average counts across this many spin bins x 2 to get a smoother + estimate of the counts per bin. + sensor_id : int + Sensor ID (e.g., 45 or 90). + + Returns + ------- + counts : numpy.ndarray + A 2D array of counts per energy range and spin bin for valid events. + """ + valid_events = get_valid_events_per_energy_range( + de_dataset, energy_ranges, UltraConstants.EARTH_ANGLE_45_THRESHOLD, sensor_id + ) + counts: np.ndarray = np.zeros( + (len(energy_ranges) - 1, len(spin_tbin_edges) - 1), dtype=float + ) + + for i in range(len(energy_ranges) - 1): + counts[i, :], _ = np.histogram( + de_dataset["de_event_met"].values[valid_events[i, :]], bins=spin_tbin_edges + ) + + if combine_spin_bin_radius is not None and combine_spin_bin_radius > 0: + # Pad array along the spin bin axis to ensure sliding_window_view returns + # an array of the correct shape. + counts_padded = np.pad( + counts, + ((0, 0), (combine_spin_bin_radius, combine_spin_bin_radius)), + mode="edge", + ) + window_size = combine_spin_bin_radius * 2 + 1 + windows = sliding_window_view(counts_padded, window_shape=window_size, axis=1) + counts = np.mean(windows, axis=-1) + return counts + + +def get_valid_events_per_energy_range( + de_dataset: xr.Dataset, energy_ranges: NDArray, earth_ang_45: float, sensor_id: int +) -> NDArray: + """ + Get valid events per energy range. + + Parameters + ---------- + de_dataset : xr.Dataset + Direct event dataset. + energy_ranges : numpy.ndarray + Array of energy range edges. + earth_ang_45 : float + Earth angle to use for culling in ULTRA 45. + sensor_id : int + Sensor ID (e.g., 45 or 90). + + Returns + ------- + valid_events_per_range : numpy.ndarray + A boolean array of shape (n_energy_ranges, n_events). + """ + event_energies = de_dataset["energy_spacecraft"].values + valid_events: np.ndarray = np.zeros( + (len(energy_ranges) - 1, len(event_energies)), dtype=bool + ) + valid_outliers = de_dataset["quality_outliers"].values == 0 + valid_scattering = de_dataset["quality_scattering"].values == 0 + # TODO what about species non-proton? For those psets dont cull based on + # High energy? + ebin = de_dataset["ebin"].values + valid_ebin = np.isin(ebin, UltraConstants.TOFXPH_SPECIES_GROUPS["proton"]) + for i in range(len(energy_ranges) - 1): + energy_mask = (event_energies >= energy_ranges[i]) & ( + event_energies < energy_ranges[i + 1] + ) + if not np.any(energy_mask): + continue + # subset the dataset to events within the energy range + de_dataset_subset = de_dataset.isel(epoch=energy_mask) + valid_earth_angle: np.ndarray = np.full(np.sum(energy_mask), True, dtype=bool) + # For ultra45, also apply an Earth angle cut to remove times when + # the Earth is in the field of view. ULTRA 90 does not require this since Earth + # is always outside the field of view. + if sensor_id == 45: + valid_earth_angle = get_valid_earth_angle_events( + de_dataset_subset, earth_ang_45 + ) + + # Flag events at the valid energy ranges if they meet all the criteria for + # valid events: not flagged as outliers, not flagged as scattering, + # in a valid ebin, and (for ultra45) have a valid Earth angle. + valid_events[i, energy_mask] = np.logical_and.reduce( + [ + valid_outliers[energy_mask], + valid_scattering[energy_mask], + valid_ebin[energy_mask], + valid_earth_angle, + ] + ) + + return valid_events + + +def get_valid_earth_angle_events( + de_dataset_subset: xr.Dataset, + earth_ang_45: float = UltraConstants.EARTH_ANGLE_45_THRESHOLD, +) -> NDArray: + """ + Get events where the particle look direction is outside the Earth keepout angle. + + Parameters + ---------- + de_dataset_subset : xr.Dataset + Subset of the direct event dataset. Should contain events within a single + energy bin. + earth_ang_45 : float + Earth keepout angle threshold (in radians) for ULTRA 45 instrument. + + Returns + ------- + valid_earth_angle_events : NDArray + A boolean array indicating which events have Earth angle greater than the + specified threshold. + """ + velocity_dps_sc = de_dataset_subset["velocity_dps_sc"].values + # Use the mean event time to compute the Earth unit vector since the spacecraft + # position doesn't change significantly over the course of the energy bin. + et = np.mean(de_dataset_subset["event_times"].values) + # Compute the unit vector from IMAP to Earth in the DPS frame at the time of the + # events. + # call spkezr to get the state vector from Earth to IMAP in the IMAP_DPS frame + body_state, _ = sp.spkezr( + SpiceBody.EARTH.name, + et, + SpiceFrame.IMAP_DPS.name, + "NONE", + SpiceBody.IMAP.name, + ) + position = body_state[:3] + distance = np.linalg.norm(position) + earth_unit_vector = position / distance + # Calculate the magnitude of the velocity vector for each event + particle_mag = np.linalg.norm(velocity_dps_sc, axis=1) + # Normalize and flip to get where each particle is looking. + unit_look_dirs = ( + -velocity_dps_sc / particle_mag[:, np.newaxis] + ) # shape (n_events, 3) + # Get cos(theta) between each particle look direction and Earth direction + cos_sep = np.dot(unit_look_dirs, earth_unit_vector) # shape (n_events,) + # Clip cos_sep to the valid range of [-1, 1] to avoid numerical issues with arccos + cos_sep = np.clip(cos_sep, -1.0, 1.0) + sep_angle = np.arccos(cos_sep) + # An event is valid if the separation angle between the particle look + # direction and Earth direction is greater than the Earth angle limit + # (i.e., the Earth is outside the field of view). + return sep_angle > earth_ang_45 + + +def get_energy_range_flags(energy_ranges_edges: NDArray) -> NDArray: + """ + Get the energy bin flags for energy dependent culling. + + Parameters + ---------- + energy_ranges_edges : NDArray + Array of energy range edges. + + Returns + ------- + energy_bin_flags : NDArray + Energy bin flags. + """ + num_bins = len(energy_ranges_edges) - 1 + if num_bins > 16: + raise ValueError( + f"Number of culling energy bins ({num_bins}) " + f"cannot exceed 16 due to uint16 bit limitations." + ) + return np.array([2**bit for bit in range(num_bins)], dtype=np.uint16) + + +def get_binned_energy_ranges( + energy_bin_edges: list[tuple[float, float]], + max_energy: float | None = UltraConstants.MAX_ENERGY_THRESHOLD, +) -> NDArray: + """ + Create L1C energy ranges by grouping energy bins. + + Parameters + ---------- + energy_bin_edges : list[tuple[float, float]] + List of (start, stop) tuples for each energy bin. + max_energy : float | None + Maximum energy to include in the energy ranges. If None, don't set a max. + + Returns + ------- + energy_range_edges : NDArray + Array of bin edges. For N energy ranges, returns N+1 edge values. + Range i spans from energy_range_edges[i] to energy_range_edges[i+1]. + """ + # Get indices for group starts + group_start_inds = np.arange( + UltraConstants.BASE_CULL_EBIN, + len(energy_bin_edges), + UltraConstants.N_CULL_EBINS, + ) + energy_starts = [energy_bin_edges[i][0] for i in group_start_inds] + # Append the stop energy of the last bin to cover the full range + last_group_end_ind = int( + min( + int(group_start_inds[-1]) + UltraConstants.N_CULL_EBINS, + len(energy_bin_edges), + ) + ) + energy_ranges: np.ndarray = np.append( + energy_starts, + energy_bin_edges[last_group_end_ind - 1][1], + ) + if max_energy is not None: + # get the first index where the energy range exceeds the max energy + # exclude the last edge since it is the stop energy of the last range + max_reached_idx = np.where(energy_ranges[:-1] > max_energy)[0] + if np.any(energy_ranges[:-1] > max_energy): + max_reached_idx = max_reached_idx[0] + else: + # if no energy range exceeds the max energy, return the original energy + # ranges + return energy_ranges + # Merge all energy ranges above the max energy into a single range and set the + # stop + energy_ranges_lim = energy_ranges[ + : max_reached_idx + 2 + ].copy() # include the first edge above max energy and the last edge + # update the last bin to start at the first original edge above the max energy + # and end at the last edge + energy_ranges_lim[-2] = next( + e[0] for e in energy_bin_edges if e[0] > max_energy + ) + energy_ranges_lim[-1] = energy_ranges[-1] + energy_ranges = energy_ranges_lim + + return energy_ranges + + +def get_binned_spins_edges( + spins: NDArray, + spin_periods: NDArray, + spin_start_times: NDArray, + spin_bin_size: int = UltraConstants.SPIN_BIN_SIZE, +) -> NDArray: + """ + Create spin bins for grouping spins together. + + Parameters + ---------- + spins : NDArray + Unique spin numbers. + spin_periods : NDArray + Spin periods corresponding to the unique spin numbers. + spin_start_times : NDArray + Spin start times corresponding to the unique spin numbers. + spin_bin_size : int + Number of spins to group together for voltage flagging. + + Returns + ------- + spin_tbin_edges : NDArray + Spin time bin edges. + """ + # Create bins based on the number of spins per bin + # We will only use complete bins for culling so use integer division. + n_spin_bins = len(spins) // spin_bin_size + # Get the start time of each bin + spin_tbin_edges = spin_start_times[::spin_bin_size][:n_spin_bins] + if spin_tbin_edges.size == 0: + # If there are no valid spin bins, return an array with a single edge at 0 + raise ValueError( + f"No valid spin bins found for bin size: {spin_bin_size}" + f" and number of spins: {len(spins)}." + ) + # Append the last start time plus the spin period to account for low times + # that occur after the last spin start time + last_spin_idx = min(n_spin_bins * spin_bin_size - 1, len(spins) - 1) + spin_tbin_edges = np.append( + spin_tbin_edges, spin_start_times[last_spin_idx] + spin_periods[last_spin_idx] + ) + return spin_tbin_edges + + +def expand_bin_flags_to_spins( + n_spins: int, binned_quality_flags: NDArray, spin_bin_size: int +) -> NDArray: + """ + Map binned spin flags back to individual spins. + + Parameters + ---------- + n_spins : int + Number of unique spin numbers. + binned_quality_flags : NDArray + Quality flags for each spin bin. + spin_bin_size : int + Number of spins that were grouped together for the binned quality flags. + + Returns + ------- + quality_flags : NDArray + Quality flags mapped to each individual spin. + """ + quality_flags: np.ndarray = np.full( + n_spins, ImapRatesUltraFlags.NONE.value, dtype=np.uint16 + ) + # Repeat each binned flag for the number of spins in each bin + repeated_flags: np.ndarray = np.repeat(binned_quality_flags, spin_bin_size) + if len(repeated_flags) > n_spins: + logger.warning( + f"Found incomplete spin bin at the end with" + f" {len(repeated_flags) - n_spins} spins. These spins will be " + f"ignored." + ) + repeated_flags = repeated_flags[:n_spins] + quality_flags[: len(repeated_flags)] = repeated_flags + + return quality_flags diff --git a/imap_processing/ultra/l1b/ultra_l1b_extended.py b/imap_processing/ultra/l1b/ultra_l1b_extended.py index 8678028c47..78da8bd242 100644 --- a/imap_processing/ultra/l1b/ultra_l1b_extended.py +++ b/imap_processing/ultra/l1b/ultra_l1b_extended.py @@ -7,12 +7,14 @@ import numpy as np import pandas -import xarray +import xarray as xr from numpy import ndarray from numpy.typing import NDArray from scipy.interpolate import LinearNDInterpolator, RegularGridInterpolator -from imap_processing.spice.spin import get_spin_data +from imap_processing.quality_flags import ImapDEOutliersUltraFlags +from imap_processing.spice.spin import interpolate_spin_data +from imap_processing.spice.time import met_to_ttj2000ns, ttj2000ns_to_et from imap_processing.ultra.constants import UltraConstants from imap_processing.ultra.l1b.lookup_utils import ( get_angular_profiles, @@ -169,7 +171,7 @@ def get_front_y_position( def get_ph_tof_and_back_positions( - de_dataset: xarray.Dataset, xf: np.ndarray, sensor: str, ancillary_files: dict + de_dataset: xr.Dataset, xf: np.ndarray, sensor: str, ancillary_files: dict ) -> PHTOFResult: """ Calculate back xb, yb position and tof. @@ -324,7 +326,7 @@ def get_path_length( def get_ssd_back_position_and_tof_offset( - de_dataset: xarray.Dataset, sensor: str, ancillary_files: dict + de_dataset: xr.Dataset, sensor: str, ancillary_files: dict ) -> tuple[np.ndarray, np.ndarray, np.ndarray]: """ Lookup the Y SSD positions (yb), TOF Offset, and SSD number. @@ -354,9 +356,9 @@ def get_ssd_back_position_and_tof_offset( indices = np.nonzero(np.isin(de_dataset["stop_type"], StopType.SSD.value))[0] de_filtered = de_dataset.isel(epoch=indices) - yb = np.zeros(len(indices), dtype=np.float64) - ssd_number = np.zeros(len(indices), dtype=int) - tof_offset = np.zeros(len(indices), dtype=np.float64) + yb: np.ndarray = np.zeros(len(indices), dtype=np.float64) + ssd_number: np.ndarray = np.zeros(len(indices), dtype=int) + tof_offset: np.ndarray = np.zeros(len(indices), dtype=np.float64) for i in range(8): ssd_flag_mask = de_filtered[f"ssd_flag_{i}"].data == 1 @@ -378,7 +380,7 @@ def get_ssd_back_position_and_tof_offset( def calculate_etof_xc( - de_subset: xarray.Dataset, + de_subset: xr.Dataset, particle_tof: np.ndarray, sensor: str, location: str, @@ -432,7 +434,7 @@ def calculate_etof_xc( def get_coincidence_positions( - de_dataset: xarray.Dataset, + de_dataset: xr.Dataset, particle_tof: np.ndarray, sensor: str, ancillary_files: dict, @@ -478,8 +480,8 @@ def get_coincidence_positions( ] de_bottom = de_dataset.isel(epoch=index_bottom) - etof = np.zeros(len(de_dataset["coin_type"]), dtype=np.float64) - xc_array = np.zeros(len(de_dataset["coin_type"]), dtype=np.float64) + etof: np.ndarray = np.zeros(len(de_dataset["coin_type"]), dtype=np.float64) + xc_array: np.ndarray = np.zeros(len(de_dataset["coin_type"]), dtype=np.float64) # Normalized TDCs # For the stop anode, there are mismatches between the coincidence TDCs, @@ -533,15 +535,15 @@ def get_de_velocity( logger.info("Negative tof values found.") # distances in .1 mm - delta_v = np.empty((len(d), 3), dtype=np.float32) + delta_v: np.ndarray = np.empty((len(d), 3), dtype=np.float32) delta_v[:, 0] = (front_position[0] - back_position[0]) * 0.1 delta_v[:, 1] = (front_position[1] - back_position[1]) * 0.1 delta_v[:, 2] = d * 0.1 # Convert from 0.1mm/0.1ns to km/s. - v_x = delta_v[:, 0] / tof * 1e3 - v_y = delta_v[:, 1] / tof * 1e3 - v_z = delta_v[:, 2] / tof * 1e3 + v_x = -delta_v[:, 0] / tof * 1e3 + v_y = -delta_v[:, 1] / tof * 1e3 + v_z = -delta_v[:, 2] / tof * 1e3 v_x[tof < 0] = FILLVAL_FLOAT32 # used as fillvals v_y[tof < 0] = FILLVAL_FLOAT32 @@ -550,13 +552,14 @@ def get_de_velocity( velocities = np.vstack((v_x, v_y, v_z)).T v_hat = velocities / np.linalg.norm(velocities, axis=1)[:, None] + r_hat = -v_hat return velocities, v_hat, r_hat def get_ssd_tof( - de_dataset: xarray.Dataset, xf: np.ndarray, sensor: str, ancillary_files: dict + de_dataset: xr.Dataset, xf: np.ndarray, sensor: str, ancillary_files: dict ) -> NDArray[np.float64]: """ Calculate back xb, yb position for the SSDs. @@ -590,7 +593,7 @@ def get_ssd_tof( tof : np.ndarray Time of flight (tenths of a nanosecond). """ - _, tof_offset, ssd_number = get_ssd_back_position_and_tof_offset( + _, tof_offset, _ssd_number = get_ssd_back_position_and_tof_offset( de_dataset, sensor, ancillary_files ) indices = np.nonzero(np.isin(de_dataset["stop_type"], [StopType.SSD.value]))[0] @@ -614,7 +617,9 @@ def get_ssd_tof( return np.asarray(tof, dtype=np.float64) -def get_de_energy_kev(v: np.ndarray, species: np.ndarray) -> NDArray: +def get_de_energy_kev( + v: np.ndarray, species: np.ndarray, quality_flags: np.ndarray | None = None +) -> NDArray: """ Calculate the direct event energy. @@ -624,6 +629,8 @@ def get_de_energy_kev(v: np.ndarray, species: np.ndarray) -> NDArray: N x 3 array of velocity components (vx, vy, vz) in km/s. species : np.ndarray Species of the particle. + quality_flags : np.ndarray, optional + Quality flags to set when there is an outlier. Returns ------- @@ -646,6 +653,14 @@ def get_de_energy_kev(v: np.ndarray, species: np.ndarray) -> NDArray: energy[valid_mask] = ( 0.5 * UltraConstants.MASS_H * v2[valid_mask] * UltraConstants.J_KEV ) + # Flag out of range energies + if quality_flags is not None: + energy_out_of_range = (energy < UltraConstants.PSET_ENERGY_BIN_EDGES[0]) | ( + energy > UltraConstants.PSET_ENERGY_BIN_EDGES[-1] + ) + quality_flags[energy_out_of_range] |= ( + ImapDEOutliersUltraFlags.INVALID_ENERGY.value + ) return energy @@ -694,12 +709,12 @@ def get_energy_pulse_height( indices_top = np.where(stop_type == 1)[0] indices_bottom = np.where(stop_type == 2)[0] - xlut = np.zeros(len(stop_type), dtype=np.float64) - ylut = np.zeros(len(stop_type), dtype=np.float64) - energy_ph = np.zeros(len(stop_type), dtype=np.float64) + xlut: np.ndarray = np.zeros(len(stop_type), dtype=np.float64) + ylut: np.ndarray = np.zeros(len(stop_type), dtype=np.float64) + energy_ph: np.ndarray = np.zeros(len(stop_type), dtype=np.float64) # Full-length correction arrays - ph_correction = np.zeros(len(stop_type), dtype=np.float64) + ph_correction: np.ndarray = np.zeros(len(stop_type), dtype=np.float64) # Stop type 1 xlut[indices_top] = (xb[indices_top] / 100 - 24.5 / 2) * 20 / 50 # mm @@ -709,7 +724,7 @@ def get_energy_pulse_height( ylut[indices_bottom] = (yb[indices_bottom] / 100 + 82 / 2) * 32 / 82 # mm ph_correction_top, updated_flags_top = get_ph_corrected( - "ultra45", + sensor, "tp", ancillary_files, np.round(xlut[indices_top]), @@ -718,7 +733,7 @@ def get_energy_pulse_height( ) quality_flags[indices_top] = updated_flags_top ph_correction_bottom, updated_flags_bottom = get_ph_corrected( - "ultra45", + sensor, "bt", ancillary_files, np.round(xlut[indices_bottom]), @@ -749,7 +764,7 @@ def get_energy_pulse_height( def get_energy_ssd( - de_dataset: xarray.Dataset, ssd: np.ndarray, ancillary_files: dict + de_dataset: xr.Dataset, ssd: np.ndarray, ancillary_files: dict ) -> NDArray[np.float64]: """ Get SSD energy. @@ -779,7 +794,7 @@ def get_energy_ssd( ssd_indices = np.nonzero(np.isin(de_dataset["stop_type"], StopType.SSD.value))[0] energy = de_dataset["energy_ph"].data[ssd_indices] - composite_energy = np.empty(len(energy), dtype=np.float64) + composite_energy: np.ndarray = np.empty(len(energy), dtype=np.float64) composite_energy[energy >= UltraConstants.COMPOSITE_ENERGY_THRESHOLD] = ( UltraConstants.COMPOSITE_ENERGY_THRESHOLD @@ -828,7 +843,7 @@ def get_ctof( # Multiply times 100 to convert to hundredths of a millimeter. ctof = tof * dmin_ctof * 100 / path_length - magnitude_v = np.full(len(ctof), -1.0e31, dtype=np.float32) + magnitude_v: np.ndarray = np.full(len(ctof), -1.0e31, dtype=np.float32) # Convert from mm/0.1ns to km/s for valid ctof values valid_mask = ctof >= 0 @@ -837,25 +852,16 @@ def get_ctof( return ctof, magnitude_v -def determine_species(tof: np.ndarray, path_length: np.ndarray, type: str) -> NDArray: +def determine_species(e_bin: np.ndarray, type: str) -> NDArray: """ Determine the species for pulse-height events. - Species is determined from the particle velocity. - For velocity, the particle TOF is normalized with respect - to a fixed distance dmin between the front and back detectors. - The normalized TOF is termed the corrected TOF (ctof). - Particle species are determined from ctof using thresholds. - - Further description is available on pages 42-44 of - IMAP-Ultra Flight Software Specification document. + Species is determined using the computed e_bin. Parameters ---------- - tof : np.ndarray - Time of flight of the SSD event (tenths of a nanosecond). - path_length : np.ndarray - Path length (r) (hundredths of a millimeter). + e_bin : np.ndarray + Computed e_bin. type : str Type of data (PH or SSD). @@ -864,11 +870,17 @@ def determine_species(tof: np.ndarray, path_length: np.ndarray, type: str) -> ND species_bin : np.array Species bin. """ - # Event TOF normalization to Z axis - ctof, _ = get_ctof(tof, path_length, type) - # Assign Species 1 ("H") to bins - # TODO: this is a placeholder for future species assignments. - species_bin = np.full(len(ctof), 1, dtype=np.uint8) + if type == "PH": + species_groups = UltraConstants.TOFXPH_SPECIES_GROUPS + if type == "SSD": + species_groups = UltraConstants.TOFXE_SPECIES_GROUPS + + non_proton_bins = species_groups["non_proton"] + proton_bins = species_groups["proton"] + + species_bin = np.full(e_bin.shape, fill_value=2, dtype=int) + species_bin[np.isin(e_bin, non_proton_bins)] = 0 + species_bin[np.isin(e_bin, proton_bins)] = 1 return species_bin @@ -906,108 +918,155 @@ def get_phi_theta( return np.degrees(phi), np.degrees(theta) -def get_spin_number(de_met: NDArray, de_spin: NDArray) -> NDArray: +def get_spin_start_indices( + aux_dataset: xr.Dataset, de_event_met: NDArray +) -> tuple[NDArray, NDArray]: """ - Get the spin number. + Get the spin start indices in the aux dataset for each event. Parameters ---------- - de_met : NDArray - Mission elapsed time. - de_spin : NDArray - Spin number 0-255. + aux_dataset : xarray.Dataset + Auxiliary dataset containing spin information. + de_event_met : numpy.ndarray + Direct event MET. Returns ------- - assigned_spin_number : NDArray - Spin number for DE data product. + start_inds : numpy.ndarray + Spin start indices for each event. + missing_aux_data_mask : numpy.ndarray + Boolean array indicating where there are events out of the aux data range. The + universal spin table should be used to fill in missing data for these events. """ - # DE packet data. - # Since the spin number in the direct events packet - # is only 8 bits it goes from 0-255. - # Within a pointing that means we will always have duplicate spin numbers. - # In other words, different spins will be represented by the same spin number. - # Just to make certain that we won't accidentally combine - # multiple spins we need to sort by time here. - sort_idx = np.argsort(de_met) - de_met_sorted = de_met[sort_idx] - de_spin_sorted = de_spin[sort_idx] - # Here we are finding the start and end indices of each spin in the sorted array. - is_new_spin = np.concatenate([[True], de_spin_sorted[1:] != de_spin_sorted[:-1]]) - spin_start_indices = np.where(is_new_spin)[0] - spin_end_indices = np.append(spin_start_indices[1:], len(de_met_sorted)) - - # Universal Spin Table. - spin_df = get_spin_data() - # Retrieve the met values of the start of the spin. - spin_start_mets = spin_df["spin_start_met"].values - # Retrieve the corresponding spin numbers. - spin_numbers = spin_df["spin_number"].values - assigned_spin_number_sorted = np.empty(de_spin_sorted.shape, dtype=np.uint32) - # These last 8 bits are the same as the spin number in the DE packet. - # So this will give us choices of which spins are - # available to assign to the DE data. - possible_spins = spin_numbers & 0xFF - - # Assign each group based on time. - for start, end in zip(spin_start_indices, spin_end_indices, strict=False): - # Now that we have the possible spins from the Universal Spin Table, - # we match the times of those spins to the nearest times in the DE data. - possible_times = spin_start_mets[possible_spins == de_spin_sorted[start]] - # Get nearest time for matching spins. - nearest_idx = np.abs(possible_times - de_met_sorted[start]).argmin() - nearest_value = possible_times[nearest_idx] - assigned_spin_number_sorted[start:end] = spin_numbers[ - spin_start_mets == nearest_value - ] - - # Undo the sort to match original order. - assigned_spin_number = np.empty_like(assigned_spin_number_sorted) - assigned_spin_number[sort_idx] = assigned_spin_number_sorted + # Get Spin Start Time in seconds + spin_start_sec = aux_dataset["timespinstart"].values + # Check that all events fall within the aux dataset time range. + # The time window spans from the first spin start to the end of the last spin. + first_spin_start = spin_start_sec[0] + # Define the end of the last spin as start time + max duration (15s) + last_spin_end = spin_start_sec[-1] + 15.0 + missing_aux_data_mask = (de_event_met < first_spin_start) | ( + de_event_met > last_spin_end + ) + if np.any(missing_aux_data_mask): + logger.info( + "Coarse MET time contains events outside aux_dataset time range " + f"({first_spin_start} - {last_spin_end}). " + f"Found min={de_event_met.min()}, max={de_event_met.max()}. " + f"Found {np.sum(missing_aux_data_mask)} events not covered by aux data. " + f" Trying to fill missing data using universal spin table." + ) + # Find the spin_start_sec that started directly before each event. + start_inds = ( + np.searchsorted( + spin_start_sec, de_event_met[~missing_aux_data_mask], side="right" + ) + - 1 + ) - return assigned_spin_number + return start_inds, missing_aux_data_mask -def get_eventtimes( - spin: NDArray, phase_angle: NDArray -) -> tuple[NDArray, NDArray, NDArray]: +def get_event_times( + aux_dataset: xr.Dataset, + de_event_met: NDArray, + phase_angle: NDArray, + spin_ds: xr.Dataset | None = None, +) -> tuple[NDArray, NDArray]: """ - Get the event times. + Get the event times, spin start times. + + Use formula from section 3.3.1 of the ULTRA algorithm document. + t_e = t_spin_start + (t_start_sub / 1000) + + (t_spin_duration * theta_event) / (1000 * 720) Parameters ---------- - spin : np.ndarray - Spin number. - phase_angle : np.ndarray + aux_dataset : xarray.Dataset + Auxiliary dataset containing spin information. + de_event_met : numpy.ndarray + Direct event MET. + phase_angle : numpy.ndarray Phase angle. + spin_ds : xarray.Dataset, optional + Pre-computed spin information. If None, will be computed from aux_dataset. Returns ------- - event_times : np.ndarray - Event times. - spin_starts : np.ndarray - Spin start times. - spin_period_sec : np.ndarray - Spin period in seconds. - - Notes - ----- - Equation for event time: - t = t_(spin start) + t_(spin start sub)/1e6 + - t_spin_period_sec * phase_angle/720 + event_times : numpy.ndarray + Event times in et. + spin_start_times: numpy.ndarray + Spin start times in et. """ - spin_df = get_spin_data() - index = np.searchsorted(spin_df["spin_number"].values, spin) - spin_starts = ( - spin_df["spin_start_sec_sclk"].values[index] - + spin_df["spin_start_subsec_sclk"].values[index] / 1e6 + # Get or compute spin info + if spin_ds is None: + spin_ds = get_spin_info(aux_dataset, de_event_met) + + # spin start with subsecond precision + spin_start_times = spin_ds.spin_starts + (spin_ds.spin_start_subs / 1000.0) + + # add the fractional spin offset + event_times = spin_start_times + (spin_ds.spin_duration / 1000.0) * ( + phase_angle / 720.0 + ) + return ( + ttj2000ns_to_et(met_to_ttj2000ns(event_times)), + ttj2000ns_to_et(met_to_ttj2000ns(spin_start_times)), ) - spin_period_sec = spin_df["spin_period_sec"].values[index] - event_times = spin_starts + spin_period_sec * (phase_angle / 720) +def get_spin_info(aux_dataset: xr.Dataset, de_event_met: NDArray) -> xr.Dataset: + """ + Get the spin information for each event. - return event_times, spin_starts, spin_period_sec + The returned dataset contains the spin number, spin duration, + spin start time, and spin start subsecond for each event. + + Parameters + ---------- + aux_dataset : xarray.Dataset + Auxiliary dataset containing spin information. + de_event_met : numpy.ndarray + Direct event MET. + + Returns + ------- + spin_info_per_event : xarray.Dataset + Spin information for each event. + """ + start_inds, missing_events = get_spin_start_indices(aux_dataset, de_event_met) + # Initialize spin info dataset + spin_info_per_event = xr.Dataset() + # Create dict of var name lookups + var_names = { + "spin_number": ("spinnumber", "spin_number"), + "spin_duration": ("duration", "spin_period_sec"), + "spin_starts": ("timespinstart", "spin_start_sec_sclk"), + "spin_start_subs": ("timespinstartsub", "spin_start_subsec_sclk"), + } + # If there is not enough aux data covering an event, query the universal + # spin table using the start time to fill in the missing data. + # This can happen for the first event if the aux data starts after the DE data. + spin_data = ( + interpolate_spin_data(de_event_met[missing_events]) + if np.any(missing_events) + else None + ) + + for var, (aux_name, ut_name) in var_names.items(): + init_array = np.zeros_like(de_event_met, dtype=np.float64) + if np.any(missing_events) and spin_data is not None: + # Get data from universal table for events missing aux data + init_array[missing_events] = spin_data[ut_name].values + if ut_name == "spin_start_subsec_sclk": + # Convert from microseconds to milliseconds to match aux data units + init_array[missing_events] /= 1000.0 + # Get data from aux dataset for the rest of the events + init_array[~missing_events] = aux_dataset[aux_name].values[start_inds] + spin_info_per_event[var] = (("epoch",), init_array) + + return spin_info_per_event def interpolate_fwhm( @@ -1109,7 +1168,10 @@ def get_fwhm( return phi_interp, theta_interp -def get_efficiency_interpolator(ancillary_files: dict) -> RegularGridInterpolator: +def get_efficiency_interpolator( + ancillary_files: dict, + sensor: str, +) -> tuple[RegularGridInterpolator, tuple, tuple, tuple]: """ Return a callable function that interpolates efficiency values for each event. @@ -1117,13 +1179,21 @@ def get_efficiency_interpolator(ancillary_files: dict) -> RegularGridInterpolato ---------- ancillary_files : dict Ancillary files. + sensor : str + Sensor name: "ultra45" or "ultra90". Returns ------- - efficiency : NDArray - Interpolated efficiency values. + interpolator : RegularGridInterpolator + Callable function to interpolate efficiency values. + theta_min_max : tuple + Minimum and maximum theta values in the lookup table. + phi_min_max : tuple + Minimum and maximum phi values in the lookup table. + energy_min_max : tuple + Minimum and maximum energy values in the lookup table. """ - lookup_table = get_energy_efficiencies(ancillary_files) + lookup_table = get_energy_efficiencies(ancillary_files, sensor) theta_vals = np.sort(lookup_table["theta (deg)"].unique()) phi_vals = np.sort(lookup_table["phi (deg)"].unique()) @@ -1134,6 +1204,10 @@ def get_efficiency_interpolator(ancillary_files: dict) -> RegularGridInterpolato efficiency_grid = efficiency_2d.reshape( (len(theta_vals), len(phi_vals), len(energy_vals)) ) + # Find the min and max values for theta and phi + theta_min_max = (theta_vals.min(), theta_vals.max()) + phi_min_max = (phi_vals.min(), phi_vals.max()) + energy_min_max = (np.asarray(energy_vals).min(), np.asarray(energy_vals).max()) interpolator = RegularGridInterpolator( (theta_vals, phi_vals, energy_vals), @@ -1142,7 +1216,7 @@ def get_efficiency_interpolator(ancillary_files: dict) -> RegularGridInterpolato fill_value=FILLVAL_FLOAT32, ) - return interpolator + return interpolator, theta_min_max, phi_min_max, energy_min_max def get_efficiency( @@ -1150,6 +1224,7 @@ def get_efficiency( phi_inst: NDArray, theta_inst: NDArray, ancillary_files: dict, + sensor: str, interpolator: RegularGridInterpolator = None, ) -> np.ndarray: """ @@ -1165,6 +1240,8 @@ def get_efficiency( Instrument-frame elevation angle for each event. ancillary_files : dict Ancillary files. + sensor : str + Sensor name: "ultra45" or "ultra90". interpolator : RegularGridInterpolator, optional Precomputed interpolator to use for efficiency lookup. If None, a new interpolator will be created from the ancillary files. @@ -1175,7 +1252,7 @@ def get_efficiency( Interpolated efficiency values. """ if not interpolator: - interpolator = get_efficiency_interpolator(ancillary_files) + interpolator, _, _, _ = get_efficiency_interpolator(ancillary_files, sensor) return interpolator((theta_inst, phi_inst, energy)) @@ -1314,11 +1391,12 @@ def determine_ebin_ssd( def is_back_tof_valid( - de_dataset: xarray.Dataset, + de_dataset: xr.Dataset, xf: NDArray, sensor: str, ancillary_files: dict, -) -> NDArray: + quality_flags: NDArray, +) -> tuple[NDArray, NDArray]: """ Determine whether back TOF is valid based on stop type. @@ -1333,30 +1411,29 @@ def is_back_tof_valid( Sensor name: "ultra45" or "ultra90". ancillary_files : dict Ancillary files for lookup. + quality_flags : NDArray + Quality flag to set when there is an outlier. Returns ------- valid_mask : NDArray Boolean array indicating whether back TOF is valid. + quality_flags : NDArray + Updated quality flags. Notes ----- From page 33 of the IMAP-Ultra Flight Software Specification document. """ _, _, _, _, tofx, tofy = get_ph_tof_and_back_positions( - de_dataset, xf, "ultra45", ancillary_files + de_dataset, xf, sensor, ancillary_files ) diff = tofy - tofx - indices = np.nonzero( - np.isin(de_dataset["stop_type"], [StopType.Top.value, StopType.Bottom.value]) - )[0] - de_ph = de_dataset.isel(epoch=indices) + top_mask = de_dataset["stop_type"] == StopType.Top.value + bottom_mask = de_dataset["stop_type"] == StopType.Bottom.value - top_mask = de_ph["stop_type"] == StopType.Top.value - bottom_mask = de_ph["stop_type"] == StopType.Bottom.value - - valid = np.zeros_like(diff, dtype=bool) + valid: np.ndarray = np.zeros(len(top_mask), dtype=bool) diff_tp_min = get_image_params("TOFDiffTpMin", sensor, ancillary_files) diff_tp_max = get_image_params("TOFDiffTpMax", sensor, ancillary_files) @@ -1367,62 +1444,101 @@ def is_back_tof_valid( valid[bottom_mask] = (diff[bottom_mask] >= diff_bt_min) & ( diff[bottom_mask] <= diff_bt_max ) - - return valid + quality_flags[~valid] |= ImapDEOutliersUltraFlags.BACKTOF.value + return valid, quality_flags def is_coin_ph_valid( etof: NDArray, xc: NDArray, xb: NDArray, + stop_north_tdc: NDArray, + stop_south_tdc: NDArray, + stop_east_tdc: NDArray, + stop_west_tdc: NDArray, sensor: str, ancillary_files: dict, -) -> NDArray: + quality_flags: NDArray, +) -> tuple[NDArray, NDArray]: """ - Determine whether Coincidence-PH data are valid. - - This is based on thresholds defined in the IMAP-Ultra Flight Software Specification - (see page 36). + Determine event validity. Parameters ---------- etof : NDArray - Electron TOF (tenths of a nanosecond). + Time for the electrons to travel back to the coincidence + anode (tenths of a nanosecond). xc : NDArray - Coincidence X position (hundredths of a mm). + X coincidence position (hundredths of a millimeter). xb : NDArray - Back X position (hundredths of a mm). + Back positions in x direction (hundredths of a millimeter). + stop_north_tdc : NDArray + Stop North Time to Digital Converter. + stop_south_tdc : NDArray + Stop South Time to Digital Converter. + stop_east_tdc : NDArray + Stop East Time to Digital Converter. + stop_west_tdc : NDArray + Stop West Time to Digital Converter. sensor : str Sensor name: "ultra45" or "ultra90". ancillary_files : dict Ancillary files for lookup. + quality_flags : NDArray + Quality flag to set when there is an outlier. Returns ------- - valid_mask : NDArray - Boolean array indicating Coin-PH validity. + combined_mask : NDArray + Boolean array indicating whether back TOF is valid. + quality_flags : NDArray + Updated quality flags. Notes ----- - Logic derived from page 36 of the IMAP-Ultra Flight Software Specification document. + From page 36 of the IMAP-Ultra Flight Software Specification document. """ - etof_min = get_image_params("eTOFMin", sensor, ancillary_files) - etof_max = get_image_params("eTOFMax", sensor, ancillary_files) - - etof_valid = (etof >= etof_min) & (etof <= etof_max) + # Make certain etof is within range for tenths of a nanosecond. + etof_valid = (etof >= UltraConstants.ETOFMIN_EVENTFILTER) & ( + etof <= UltraConstants.ETOFMAX_EVENTFILTER + ) + # Hundredths of a mm. diff_x = xc - xb - etof_offset1 = get_image_params("eTOFOff1", sensor, ancillary_files) - etof_offset2 = get_image_params("eTOFOff2", sensor, ancillary_files) - etof_slope1 = get_image_params("eTOFSlope1", sensor, ancillary_files) - etof_slope2 = get_image_params("eTOFSlope2", sensor, ancillary_files) - t1 = (etof - etof_offset1) * etof_slope1 / 1024 - t2 = (etof - etof_offset2) * etof_slope2 / 1024 + t1 = ( + (etof - UltraConstants.ETOFOFF1_EVENTFILTER) + * UltraConstants.ETOFSLOPE1_EVENTFILTER + / 1024 + ) + t2 = ( + (etof - UltraConstants.ETOFOFF2_EVENTFILTER) + * UltraConstants.ETOFSLOPE2_EVENTFILTER + / 1024 + ) condition_1 = (diff_x >= t1) & (diff_x <= t2) condition_2 = (diff_x >= -t2) & (diff_x <= -t1) spatial_valid = condition_1 | condition_2 - return etof_valid & spatial_valid + sp_n_norm = get_norm(stop_north_tdc, "SpN", sensor, ancillary_files) + sp_s_norm = get_norm(stop_south_tdc, "SpS", sensor, ancillary_files) + sp_e_norm = get_norm(stop_east_tdc, "SpE", sensor, ancillary_files) + sp_w_norm = get_norm(stop_west_tdc, "SpW", sensor, ancillary_files) + + tofx = sp_n_norm + sp_s_norm + tofy = sp_e_norm + sp_w_norm + + # Units in tenths of a nanosecond + delta_tof = tofy - tofx + + delta_tof_mask = (delta_tof >= UltraConstants.TOFDIFFTPMIN_EVENTFILTER) & ( + delta_tof <= UltraConstants.TOFDIFFTPMAX_EVENTFILTER + ) + + combined_mask = etof_valid & spatial_valid & delta_tof_mask + + quality_flags[~combined_mask] |= ImapDEOutliersUltraFlags.COINPH.value + + return combined_mask, quality_flags diff --git a/imap_processing/ultra/l1c/helio_pset.py b/imap_processing/ultra/l1c/helio_pset.py index ab04ab6920..9d562aa5f0 100644 --- a/imap_processing/ultra/l1c/helio_pset.py +++ b/imap_processing/ultra/l1c/helio_pset.py @@ -2,26 +2,36 @@ import logging +import astropy_healpix.healpy as hp import numpy as np -import pandas as pd import xarray as xr -from imap_processing.spice.repoint import get_pointing_times +from imap_processing.cdf.utils import parse_filename_like +from imap_processing.quality_flags import ImapPSETUltraFlags +from imap_processing.spice.geometry import SpiceFrame +from imap_processing.spice.repoint import get_pointing_times_from_id from imap_processing.spice.time import ( - et_to_met, met_to_ttj2000ns, - sct_to_et, ttj2000ns_to_et, ) -from imap_processing.ultra.l1b.ultra_l1b_culling import get_de_rejection_mask +from imap_processing.ultra.constants import UltraConstants +from imap_processing.ultra.l1b.ultra_l1b_culling import ( + get_de_rejection_mask, + get_energy_and_spin_dependent_rejection_mask, +) from imap_processing.ultra.l1c.l1c_lookup_utils import ( - calculate_pixels_within_scattering_threshold, - get_spacecraft_pointing_lookup_tables, + build_energy_bins, + calculate_accepted_pixels, + in_restricted_fov, +) +from imap_processing.ultra.l1c.make_helio_index_maps import ( + make_helio_index_maps_with_nominal_kernels, ) +from imap_processing.ultra.l1c.ultra_l1c_culling import compute_culling_mask from imap_processing.ultra.l1c.ultra_l1c_pset_bins import ( - build_energy_bins, get_efficiencies_and_geometric_function, - get_helio_adjusted_data, + get_energy_delta_minus_plus, + get_spacecraft_background_rates, get_spacecraft_exposure_times, get_spacecraft_histogram, ) @@ -32,15 +42,14 @@ def calculate_helio_pset( de_dataset: xr.Dataset, - extendedspin_dataset: xr.Dataset, - cullingmask_dataset: xr.Dataset, + goodtimes_dataset: xr.Dataset, rates_dataset: xr.Dataset, - params_dataset: xr.Dataset, + aux_dataset: xr.Dataset, name: str, ancillary_files: dict, instrument_id: int, - species_id: int = 1, -) -> xr.Dataset: + species_id: list, +) -> xr.Dataset | None: """ Create dictionary with defined datatype for Pointing Set Grid Data. @@ -48,39 +57,110 @@ def calculate_helio_pset( ---------- de_dataset : xarray.Dataset Dataset containing de data. - extendedspin_dataset : xarray.Dataset - Dataset containing extendedspin data. - cullingmask_dataset : xarray.Dataset - Dataset containing cullingmask data. + goodtimes_dataset : xarray.Dataset + Dataset containing goodtimes data. rates_dataset : xarray.Dataset Dataset containing image rates data. - params_dataset : xarray.Dataset - Dataset containing image parameters data. + aux_dataset : xarray.Dataset + Dataset containing auxiliary data. name : str Name of the dataset. ancillary_files : dict Ancillary files. instrument_id : int Instrument ID, either 45 or 90. - species_id : int - Species ID, default of 1 refers to Hydrogen. + species_id : List + Species ID. Returns ------- dataset : xarray.Dataset Dataset containing the data. """ + nside = 32 + num_spin_steps = 720 + sensor_id = int(parse_filename_like(name)["sensor"][0:2]) pset_dict: dict[str, np.ndarray] = {} # Select only the species we are interested in. - indices = np.where(de_dataset["species"].values == species_id)[0] + indices = np.where(np.isin(de_dataset["ebin"].values, species_id))[0] + if indices.size == 0: + logger.info(f"No data available for {name}") + return None + species_dataset = de_dataset.isel(epoch=indices) rejected = get_de_rejection_mask( species_dataset["quality_scattering"].values, species_dataset["quality_outliers"].values, + UltraConstants.APPLY_SCATTERING_REJECTION_L1C, ) - de_dataset = species_dataset.isel(epoch=~rejected) + species_dataset = species_dataset.isel(epoch=~rejected) + # Check if spin_number is in the goodtimes dataset, if not then we can + # reject all events for that spin without checking energy bin flags. + spin_rejected = ~np.isin( + species_dataset["spin"].values, goodtimes_dataset["spin_number"].values + ) + species_dataset = species_dataset.isel(epoch=~spin_rejected) + + intervals, _, energy_bin_geometric_means = build_energy_bins() + # Now check energy dependent flags. + energy_dependent_rejected = get_energy_and_spin_dependent_rejection_mask( + goodtimes_dataset, + species_dataset["energy_heliosphere"].values, + species_dataset["spin"].values, + ) + species_dataset = species_dataset.isel(epoch=~energy_dependent_rejected) + # Get the start and stop times of the pointing period + repoint_id = species_dataset.attrs.get("Repointing", None) + if repoint_id is None: + raise ValueError("Repointing ID attribute is missing from the dataset.") + instrument_frame = ( + SpiceFrame.IMAP_ULTRA_90 if sensor_id == 90 else SpiceFrame.IMAP_ULTRA_45 + ) + pointing_range_met = get_pointing_times_from_id(repoint_id) + + logger.info("Generating helio pointing lookup tables.") + + helio_pointing_ds = make_helio_index_maps_with_nominal_kernels( + kernel_paths=UltraConstants.SIM_KERNELS_FOR_HELIO_INDEX_MAPS, + nside=nside, + spin_duration=15.0, + num_steps=num_spin_steps, + instrument_frame=instrument_frame, + compute_bsf=UltraConstants.APPLY_BOUNDARY_SCALE_FACTORS_L1C, + ) + boundary_scale_factors = helio_pointing_ds.bsf + theta_vals = helio_pointing_ds.theta + phi_vals = helio_pointing_ds.phi + fov_index = helio_pointing_ds.index + + logger.info("calculating spun FWHM scattering values.") + pixels_below_scattering, scattering_theta, scattering_phi, scattering_thresholds = ( + calculate_accepted_pixels( + fov_index, + theta_vals, + phi_vals, + ancillary_files, + instrument_id, + reject_scattering=UltraConstants.APPLY_SCATTERING_REJECTION_L1C, + apply_fov_restriction=UltraConstants.APPLY_FOV_RESTRICTIONS_L1C, + ) + ) + # Apply restricted FOV filter to counts. + # If a valid event's instrument frame theta/phi falls outside the restricted + # acceptance window it is excluded from the L1C fine energy-bin counts map. + if UltraConstants.APPLY_FOV_RESTRICTIONS_L1C: + fov_accepted = in_restricted_fov( + species_dataset["theta"].values, + species_dataset["phi"].values, + instrument_id, + ) + logger.info( + f"Restricted FOV counts filter: keeping {fov_accepted.sum()} / " + f"{len(fov_accepted)} events." + ) + species_dataset = species_dataset.isel(epoch=fov_accepted) v_mag_helio_spacecraft = np.linalg.norm( species_dataset["velocity_dps_helio"].values, axis=1 ) @@ -88,77 +168,95 @@ def calculate_helio_pset( species_dataset["velocity_dps_helio"].values / v_mag_helio_spacecraft[:, np.newaxis] ) - intervals, _, energy_bin_geometric_means = build_energy_bins() - counts, latitude, longitude, n_pix = get_spacecraft_histogram( + counts, counts_n_pix = get_spacecraft_histogram( vhat_dps_helio, species_dataset["energy_heliosphere"].values, intervals, - nside=128, + nside=UltraConstants.L1C_COUNTS_NSIDE, ) - + n_pix = hp.nside2npix(nside) + helio_pset_quality_flags = np.full( + n_pix, ImapPSETUltraFlags.NONE.value, dtype=np.uint16 + ) + counts_healpix = np.arange(counts_n_pix) + # Determine nside for non "counts" variables from the lookup table healpix = np.arange(n_pix) - # Get lookup table for FOR indices by spin phase step - ( - for_indices_by_spin_phase, - theta_vals, - phi_vals, - ra_and_dec, - boundary_scale_factors, - ) = get_spacecraft_pointing_lookup_tables(ancillary_files, instrument_id) - # Check that the number of rows in the lookup table matches the number of pixels - if for_indices_by_spin_phase.shape[0] != n_pix: - logger.warning( - "The lookup table is expected to have the same number of rows as " - "the number of HEALPix pixels." - ) + # Calculate the corresponding longitude (az) latitude (el) + # center coordinates + longitude, latitude = hp.pix2ang(nside, healpix, lonlat=True) - pixels_below_scattering = calculate_pixels_within_scattering_threshold( - for_indices_by_spin_phase, theta_vals, phi_vals, ancillary_files, instrument_id - ) - # Calculate exposure - constant_exposure = ancillary_files["l1c-90sensor-dps-exposure"] - df_exposure = pd.read_csv(constant_exposure) + logger.info("Calculating spacecraft exposure times with deadtime correction.") exposure_time, deadtime_ratios = get_spacecraft_exposure_times( - df_exposure, rates_dataset, - params_dataset, pixels_below_scattering, boundary_scale_factors, + aux_dataset, + energy_bins=energy_bin_geometric_means, + sensor_id=sensor_id, + ancillary_files=ancillary_files, + apply_bsf=UltraConstants.APPLY_BOUNDARY_SCALE_FACTORS_L1C, + goodtimes_dataset=goodtimes_dataset, ) + logger.info("Calculating spun efficiencies and geometric function.") # calculate efficiency and geometric function as a function of energy - efficiencies, geometric_function = get_efficiencies_and_geometric_function( + geometric_function, efficiencies = get_efficiencies_and_geometric_function( pixels_below_scattering, boundary_scale_factors, - theta_vals, - phi_vals, + theta_vals.values, + phi_vals.values, n_pix, + sensor_id, ancillary_files, + apply_bsf=UltraConstants.APPLY_BOUNDARY_SCALE_FACTORS_L1C, ) - # Get midpoint timestamp for pointing. - # TODO remove sct_to_et conversion - pointing_start, pointing_stop = get_pointing_times( - et_to_met(sct_to_et(species_dataset["event_times"].data[0])) - ) - mid_time = ttj2000ns_to_et(met_to_ttj2000ns((pointing_start + pointing_stop) / 2)) - exposure_time, efficiency, geometric_function = get_helio_adjusted_data( - mid_time, - exposure_time, - geometric_function, - efficiencies, - ra_and_dec[:, 0], - ra_and_dec[:, 1], + + logger.info("Calculating background rates.") + # TODO calculate helio background rates + # Calculate background rates + background_rates = get_spacecraft_background_rates( + rates_dataset, + aux_dataset, + sensor_id, + ancillary_files, + intervals, + goodtimes_dataset["spin_number"].values, + nside=nside, ) + sensitivity = efficiencies * geometric_function - # For ISTP, epoch should be the center of the time bin. - pset_dict["epoch"] = de_dataset.epoch.data[:1].astype(np.int64) + start: float = np.min(species_dataset["event_times"].values) + end: float = np.max(species_dataset["event_times"].values) + + # Convert pointing start and end time to ttj2000ns + pointing_range_ns = met_to_ttj2000ns(pointing_range_met) + # use either the pointing end time + 30 mins or the max event time, + # whichever is smaller. + end = min(end + 1800, ttj2000ns_to_et(pointing_range_ns[1])) + # Time bins in 30 minute intervals in et + time_bins = np.arange(start, end, 1800) + + # Compute mask for culling the Earth + compute_culling_mask( + time_bins, + UltraConstants.DEFAULT_EARTH_CULLING_RADIUS, + helio_pset_quality_flags, + nside=nside, + ) + # Epoch should be the start of the pointing + pset_dict["epoch"] = np.atleast_1d(pointing_range_ns[0]).astype(np.int64) + pset_dict["epoch_delta"] = np.atleast_1d(np.diff(pointing_range_ns)).astype( + np.int64 + ) pset_dict["counts"] = counts[np.newaxis, ...] pset_dict["latitude"] = latitude[np.newaxis, ...] pset_dict["longitude"] = longitude[np.newaxis, ...] pset_dict["energy_bin_geometric_mean"] = energy_bin_geometric_means - pset_dict["helio_exposure_factor"] = exposure_time + pset_dict["background_rates"] = background_rates[np.newaxis, ...] + pset_dict["exposure_factor"] = exposure_time[np.newaxis, ...] pset_dict["pixel_index"] = healpix + pset_dict["counts_pixel_index"] = counts_healpix pset_dict["energy_bin_delta"] = np.diff(intervals, axis=1).squeeze()[ np.newaxis, ... ] @@ -167,6 +265,18 @@ def calculate_helio_pset( pset_dict["geometric_function"] = geometric_function pset_dict["dead_time_ratio"] = deadtime_ratios pset_dict["spin_phase_step"] = np.arange(len(deadtime_ratios)) + pset_dict["quality_flags"] = helio_pset_quality_flags[np.newaxis, ...] + + # Convert FWHM to gaussian uncertainty by dividing by 2.355 + # See algorithm documentation (section 3.5.7, third bullet point) for more details + pset_dict["scatter_theta"] = scattering_theta / 2.355 + pset_dict["scatter_phi"] = scattering_phi / 2.355 + pset_dict["scatter_threshold"] = scattering_thresholds + + # Add the energy delta plus/minus to the dataset + energy_delta_minus, energy_delta_plus = get_energy_delta_minus_plus() + pset_dict["energy_delta_minus"] = energy_delta_minus + pset_dict["energy_delta_plus"] = energy_delta_plus dataset = create_dataset(pset_dict, name, "l1c") diff --git a/imap_processing/ultra/l1c/histogram.py b/imap_processing/ultra/l1c/histogram.py deleted file mode 100644 index 9ab726a700..0000000000 --- a/imap_processing/ultra/l1c/histogram.py +++ /dev/null @@ -1,36 +0,0 @@ -"""Calculate Histogram.""" - -import numpy as np -import xarray as xr - -from imap_processing.ultra.utils.ultra_l1_utils import create_dataset - - -def calculate_histogram(histogram_dataset: xr.Dataset, name: str) -> xr.Dataset: - """ - Create dictionary with defined datatype for Histogram Data. - - Parameters - ---------- - histogram_dataset : xarray.Dataset - Dataset containing histogram data. - name : str - Name of dataset. - - Returns - ------- - dataset : xarray.Dataset - Dataset containing the data. - """ - histogram_dict = {} - - # Placeholder for calculations - # TODO: come back and update this data structure. - epoch = histogram_dataset.coords["epoch"].values - - histogram_dict["epoch"] = epoch - histogram_dict["sid"] = np.zeros(len(epoch), dtype=np.uint8) - - dataset = create_dataset(histogram_dict, name, "l1c") - - return dataset diff --git a/imap_processing/ultra/l1c/l1c_lookup_utils.py b/imap_processing/ultra/l1c/l1c_lookup_utils.py index f4034ee10a..341c5de8e9 100644 --- a/imap_processing/ultra/l1c/l1c_lookup_utils.py +++ b/imap_processing/ultra/l1c/l1c_lookup_utils.py @@ -4,24 +4,65 @@ import numpy as np import pandas as pd +import xarray as xr from numpy._typing import NDArray +from imap_processing.ultra.constants import UltraConstants from imap_processing.ultra.l1b.lookup_utils import ( get_scattering_coefficients, get_scattering_thresholds, load_scattering_lookup_tables, ) -from imap_processing.ultra.l1c.ultra_l1c_pset_bins import build_energy_bins logger = logging.getLogger(__name__) +def in_restricted_fov( + theta: np.ndarray, + phi: np.ndarray, + instrument_id: int, +) -> np.ndarray: + """ + Determine whether the theta/phi pairs are inside the restricted FOV. + + Parameters + ---------- + theta : np.ndarray + Array of theta values in degrees. + phi : np.ndarray + Array of phi values in degrees. + instrument_id : int + Instrument ID, either 45 or 90. + + Returns + ------- + np.ndarray + Boolean array indicating whether each theta/phi pair is within the restricted + FOV. + """ + # Theta limits are dependent on the instrument id + if instrument_id == 90: + low_theta_lim = UltraConstants.RESTRICTED_FOV_THETA_LOW_DEG_90 + high_theta_lim = UltraConstants.RESTRICTED_FOV_THETA_HIGH_DEG_90 + elif instrument_id == 45: + low_theta_lim = UltraConstants.RESTRICTED_FOV_THETA_LOW_DEG_45 + high_theta_lim = UltraConstants.RESTRICTED_FOV_THETA_HIGH_DEG_45 + else: + raise ValueError(f"Invalid instrument ID: {instrument_id}. Must be 45 or 90.") + + return ( + (theta >= low_theta_lim) + & (theta <= high_theta_lim) + & (np.abs(phi) < UltraConstants.FOV_PHI_LIMIT_DEG) + ) + + def mask_below_fwhm_scattering_threshold( theta_coeffs: np.ndarray, phi_coeffs: np.ndarray, energy: np.ndarray, scattering_thresholds: np.ndarray, -) -> np.ndarray: +) -> tuple[NDArray, NDArray, NDArray]: """ Determine indices of theta and phi values below the FWHM scattering threshold. @@ -43,8 +84,12 @@ def mask_below_fwhm_scattering_threshold( Returns ------- - numpy.ndarray + scattering_mask : numpy.ndarray Boolean array indicating indices below the scattering threshold. + fwhm_theta : numpy.ndarray + Calculated FWHM values for theta. + fwhm_phi : numpy.ndarray + Calculated FWHM values for phi. """ # Calculate FWHM for all pixels and all energies fwhm_theta = theta_coeffs[..., 0:1] * ( @@ -58,102 +103,238 @@ def mask_below_fwhm_scattering_threshold( # Combine conditions for both theta and phi. # shape = (npix, energy.shape[1]) - return np.logical_and(fwhm_theta <= thresholds, fwhm_phi <= thresholds) + scattering_mask = np.logical_and(fwhm_theta <= thresholds, fwhm_phi <= thresholds) + return scattering_mask, fwhm_theta, fwhm_phi -def calculate_pixels_within_scattering_threshold( - for_indices_by_spin_phase: np.ndarray, +def calculate_accepted_pixels( # noqa: PLR0912 + for_indices_by_spin_phase: xr.DataArray, theta_vals: np.ndarray, phi_vals: np.ndarray, ancillary_files: dict, instrument_id: int, -) -> list: + reject_scattering: bool = False, + apply_fov_restriction: bool = False, +) -> tuple[xr.DataArray, NDArray, NDArray, NDArray]: """ - Calculate pixels within the FWHM scattering threshold for each spin phase step. + Calculate the accepted pixels based scattering and FOV restrictions. + + This function also calculates a mask for pixels that are below the FWHM threshold + and FWHM scattering values for each pixel, energy bin, and spin phase step. Parameters ---------- - for_indices_by_spin_phase : np.ndarray + for_indices_by_spin_phase : xarray.DataArray A 2D boolean array where cols are spin phase steps are rows are HEALPix pixels. True indicates pixels that are within the Field of Regard (FOR) at that spin phase. theta_vals : np.ndarray - A 2D array of theta values for each HEALPix pixel at each spin phase step. + 2D or 3D array of theta values. Shape is either (spin_phase_step, npix) + or (spin_phase_step, energy_bins, npix) when energy-dependent scattering + rejection is used. phi_vals : np.ndarray - A 2D array of phi values for each HEALPix pixel at each spin phase step. + Array of phi values with the same shape as `theta_vals`, giving the + corresponding phi for each pixel (and energy, if present). ancillary_files : dict Dictionary containing ancillary files. instrument_id : int, Instrument ID, either 45 or 90. + reject_scattering : bool + Whether to reject pixels based on scattering thresholds. + apply_fov_restriction : bool + Whether to apply the restricted FOV theta/phi acceptance test. When + ``True``, any spin-step/pixel combination whose instrument-frame theta + and phi do not satisfy :func:`in_restricted_fov` is skipped entirely: + it is not added to the averaging numerator *or* denominator, and it + does not contribute exposure time. This gates GF, efficiency, and + exposure for the fine L1C energy-bin maps. Returns ------- - pixels_below_scattering : list - A Nested list of arrays indicating pixels within the scattering threshold. - The outer list indicates spin phase steps, the middle list indicates energy - bins, and the inner arrays contain indices indicating pixels that are below - the FWHM scattering threshold. + valid_spun_pixels : xarray.DataArray + Boolean array of shape ``(spin_phase_step, energy_bin, pixel)`` indicating + which pixel samples are accepted for L1C accumulation at each spin step. + Acceptance always requires the sample to be inside the Field of Regard (FOR), + can optionally require passing the restricted theta/phi FOV criteria when + ``apply_fov_restriction=True``, and can optionally require passing the FWHM + scattering threshold when ``reject_scattering=True``. + scattering_fwhm_theta : NDArray + Calculated FWHM scatting values for theta at each energy bin and averaged + over spin phase. + scattering_fwhm_phi : NDArray + Calculated FWHM scatting values for theta at each energy bin and averaged + over spin phase. + scattering_thresholds_for_energy_mean : NDArray + Scattering thresholds corresponding to each energy bin. """ + # Check shapes of theta phi, and index arrays + index_shape = for_indices_by_spin_phase.shape + if theta_vals.shape != index_shape or phi_vals.shape != index_shape: + raise ValueError( + "Shape mismatch between FOR indices and theta/phi values. " + f"FOR indices shape: {index_shape}, " + f"theta shape: {theta_vals.shape}, " + f"phi shape: {phi_vals.shape}." + ) # Load scattering coefficient lookup table scattering_luts = load_scattering_lookup_tables(ancillary_files, instrument_id) - pixels_below_scattering = [] # Get energy bin geometric means energy_bin_geometric_means = build_energy_bins()[2] # Load scattering thresholds for the energy bin geometric means scattering_thresholds_for_energy_mean = get_scattering_thresholds_for_energy( energy_bin_geometric_means, ancillary_files ) - steps = for_indices_by_spin_phase.shape[1] + n_pix = for_indices_by_spin_phase.sizes["pixel"] + # Initialize arrays to accumulate FWHM values for averaging + fwhm_theta_sum = np.zeros((len(energy_bin_geometric_means), n_pix)) + fwhm_phi_sum = np.zeros_like(fwhm_theta_sum) + sample_count = np.zeros_like(fwhm_theta_sum) + + steps = for_indices_by_spin_phase.sizes["spin_phase_step"] energies = energy_bin_geometric_means[np.newaxis, :] + # Initialize DataArray to hold boolean of valid pixels at each spin phase step + # If reject_scattering and apply_fov_restriction are both False, this will just + # be the FOR mask. + spun_dims = ("spin_phase_step", "energy", "pixel") + if reject_scattering or apply_fov_restriction: + valid_pixels = xr.DataArray( + np.zeros((steps, len(energy_bin_geometric_means), n_pix), dtype=bool), + dims=spun_dims, + ) + elif "energy" not in for_indices_by_spin_phase.sizes: + valid_pixels = for_indices_by_spin_phase.expand_dims( + {"energy": len(energy_bin_geometric_means)} + ).transpose(*spun_dims) + else: + valid_pixels = for_indices_by_spin_phase + # TODO refactor loop below and combine the energy dependent and independent cases + # if possible to avoid code duplication. # The "for_indices_by_spin_phase" lookup table contains the boolean values of each # pixel at each spin phase step, indicating whether the pixel is inside the FOR. # It starts at Spin-phase = 0, and increments in fine steps (1 ms), spinning the # spacecraft in the despun frame. At each iteration, query for the pixels in the # FOR, and calculate whether the FWHM value is below the threshold at the energy. for i in range(steps): - # Calculate spin phase for the current iteration - for_inds = for_indices_by_spin_phase[:, i] - - # Skip if no pixels in FOR - if not np.any(for_inds): - logger.info(f"No pixels found in FOR at spin phase step {i}") - pixels_below_scattering.append( - [ - np.array([], dtype=int) - for _ in range(len(energy_bin_geometric_means)) - ] + for_inds = for_indices_by_spin_phase.isel(spin_phase_step=i).values + + if for_inds.ndim > 1: + # Energy dependent FOR indices + for e_ind in range(len(energy_bin_geometric_means)): + # Skip if no pixels in FOR + if not np.any(for_inds[e_ind, :]): + continue + accepted_pix = np.flatnonzero(for_inds[e_ind, :]) + theta = theta_vals[i, e_ind, accepted_pix] + phi = phi_vals[i, e_ind, accepted_pix] + + # Check if we need to restrict the fov further using theta/phi + # acceptance limits + if apply_fov_restriction: + fov_mask = in_restricted_fov(theta, phi, instrument_id) + # update accepted pixel indices to reflect the FOV restriction + accepted_pix = accepted_pix[fov_mask] + theta = theta[fov_mask] + phi = phi[fov_mask] + # update valid pixels to reflect the FOV restriction + valid_pixels[i, e_ind, accepted_pix] = True + + if len(accepted_pix) == 0: + continue + + theta_coeffs, phi_coeffs = get_scattering_coefficients( + theta.data, phi.data, lookup_tables=scattering_luts + ) + # Calculate scattering mask for specified energy + energy = energy_bin_geometric_means[e_ind : e_ind + 1][np.newaxis, :] + scattering_mask, fwhm_theta, fwhm_phi = ( + mask_below_fwhm_scattering_threshold( + theta_coeffs, + phi_coeffs, + energy, + scattering_thresholds=scattering_thresholds_for_energy_mean[ + e_ind : e_ind + 1 + ], + ) + ) + # If rejecting scattering, store the mask + if reject_scattering: + valid_pixels[i, e_ind, accepted_pix] = scattering_mask.flatten() + + # Accumulate FWHM values only where BOTH theta and phi are finite + valid_fwhm = np.isfinite(fwhm_theta) & np.isfinite(fwhm_phi) + fwhm_theta_sum[e_ind, accepted_pix] += np.where( + valid_fwhm, fwhm_theta, 0.0 + ).ravel() + fwhm_phi_sum[e_ind, accepted_pix] += np.where( + valid_fwhm, fwhm_phi, 0.0 + ).ravel() + sample_count[e_ind, accepted_pix] += valid_fwhm.ravel().astype( + sample_count.dtype + ) + + else: + # Energy independent FOR indices + if not np.any(for_inds): + continue + + accepted_pix = np.flatnonzero(for_inds) # Get indices of pixels in FOR for + # this spin phase step + + theta = theta_vals[i, accepted_pix] + phi = phi_vals[i, accepted_pix] + + # Check if we need to apply the restricted FOV mask before calculating + # scattering coefficients + if apply_fov_restriction: + fov_mask = in_restricted_fov(theta, phi, instrument_id) + # update accepted pixel indices to reflect the FOV restriction + accepted_pix = accepted_pix[fov_mask] + theta = theta[fov_mask] + phi = phi[fov_mask] + # update valid pixels to reflect the FOV restriction + valid_pixels[i, :, accepted_pix] = True + + if len(accepted_pix) == 0: + continue + + theta_coeffs, phi_coeffs = get_scattering_coefficients( + theta, phi, lookup_tables=scattering_luts ) - continue - # Using the lookup table, get the indices of the pixels inside the FOR at - # the current spin phase step. - theta = theta_vals[for_inds, i] - phi = phi_vals[for_inds, i] - theta_coeffs, phi_coeffs = get_scattering_coefficients( - theta, phi, lookup_tables=scattering_luts - ) - # Get a mask for pixels below the FWHM scattering threshold - scattering_mask = mask_below_fwhm_scattering_threshold( - theta_coeffs, - phi_coeffs, - energies, - scattering_thresholds=scattering_thresholds_for_energy_mean, - ) - # Extract pixel indices for each energy - for_pixel_indices = np.where(for_inds)[0] - pixels_below_scattering_for_energy = [] + scattering_mask, fwhm_theta, fwhm_phi = ( + mask_below_fwhm_scattering_threshold( + theta_coeffs, + phi_coeffs, + energies, + scattering_thresholds=scattering_thresholds_for_energy_mean, + ) + ) + if reject_scattering: + valid_pixels[i, :, accepted_pix] = scattering_mask.T - for energy_idx in range(len(energy_bin_geometric_means)): - valid_pixels = scattering_mask[:, energy_idx] - pixels_below_scattering_for_energy.append(for_pixel_indices[valid_pixels]) + # Accumulate FWHM values where theta and phi are finite + valid_fwhm = np.isfinite(fwhm_theta) & np.isfinite( + fwhm_phi + ) # (npix, n_energy) + fwhm_theta_sum[:, accepted_pix] += np.where(valid_fwhm, fwhm_theta, 0.0).T + fwhm_phi_sum[:, accepted_pix] += np.where(valid_fwhm, fwhm_phi, 0.0).T + sample_count[:, accepted_pix] += valid_fwhm.T.astype(sample_count.dtype) - pixels_below_scattering.append(pixels_below_scattering_for_energy) + fwhm_phi_avg = np.zeros_like(fwhm_phi_sum) + fwhm_theta_avg = np.zeros_like(fwhm_theta_sum) + np.divide(fwhm_phi_sum, sample_count, out=fwhm_phi_avg, where=sample_count != 0) + np.divide(fwhm_theta_sum, sample_count, out=fwhm_theta_avg, where=sample_count != 0) - return pixels_below_scattering + return ( + valid_pixels, + fwhm_theta_avg, + fwhm_phi_avg, + scattering_thresholds_for_energy_mean, + ) def get_spacecraft_pointing_lookup_tables( ancillary_files: dict, instrument_id: int -) -> tuple[NDArray, NDArray, NDArray, NDArray, NDArray]: +) -> tuple[xr.DataArray, NDArray, NDArray, NDArray, xr.DataArray]: """ Get indices of pixels in the nominal FOR as a function of spin phase. @@ -170,8 +351,8 @@ def get_spacecraft_pointing_lookup_tables( Returns ------- - for_indices_by_spin_phase : NDArray - A 2D boolean array of shape (npix, n_spin_phase_steps). + for_indices_by_spin_phase : xarray.DataArray + A 2D boolean array of shape (n_spin_phase_steps,npix). True indicates pixels that are within the Field of Regard (FOR) at that spin phase. theta_vals : NDArray @@ -180,34 +361,46 @@ def get_spacecraft_pointing_lookup_tables( A 2D array of phi values for each HEALPix pixel at each spin phase step. ra_and_dec : NDArray A 2D array of right ascension and declination values for each HEALPix pixel. - boundary_scale_factors : NDArray + boundary_scale_factors : xarray.DataArray A 2D array of boundary scale factors for each HEALPix pixel at each spin phase step. """ - theta_descriptor = f"l1c-{instrument_id}sensor-sc-pointing-theta-n32" - phi_descriptor = f"l1c-{instrument_id}sensor-sc-pointing-phi-n32" - index_descriptor = f"l1c-{instrument_id}sensor-sc-pointing-index-n32" - bsf_descriptor = f"l1c-{instrument_id}sensor-sc-pointing-bsf-n32" - - theta_vals = pd.read_csv( - ancillary_files[theta_descriptor], header=None, skiprows=1 - ).to_numpy(dtype=float)[:, 2:] - phi_vals = pd.read_csv( - ancillary_files[phi_descriptor], header=None, skiprows=1 - ).to_numpy(dtype=float)[:, 2:] - index_grid = pd.read_csv( - ancillary_files[index_descriptor], header=None, skiprows=1 - ).to_numpy(dtype=float) - boundary_scale_factors = pd.read_csv( - ancillary_files[bsf_descriptor], header=None, skiprows=1 - ).to_numpy(dtype=float)[:, 2:] - - ra_and_dec = index_grid[:, :2] # Shape (npix, 2) + theta_descriptor = f"l1c-{instrument_id}sensor-sc-pointing-theta" + phi_descriptor = f"l1c-{instrument_id}sensor-sc-pointing-phi" + index_descriptor = f"l1c-{instrument_id}sensor-sc-pointing-index" + bsf_descriptor = f"l1c-{instrument_id}sensor-sc-pointing-bsf" + + theta_vals = ( + pd.read_csv(ancillary_files[theta_descriptor], header=None, skiprows=1) + .to_numpy(dtype=float)[:, 2:] + .T + ) + phi_vals = ( + pd.read_csv(ancillary_files[phi_descriptor], header=None, skiprows=1) + .to_numpy(dtype=float)[:, 2:] + .T + ) + index_grid = ( + pd.read_csv(ancillary_files[index_descriptor], header=None, skiprows=1) + .to_numpy(dtype=float) + .T + ) + boundary_scale_factors = ( + pd.read_csv(ancillary_files[bsf_descriptor], header=None, skiprows=1) + .to_numpy(dtype=float)[:, 2:] + .T + ) + + ra_and_dec = index_grid[:2, :] # Shape (npix, 2) # This array indicates whether each pixel is in the nominal FOR at each spin phase # step (15000 steps for a full rotation with 1 ms resolution). - for_indices_by_spin_phase = np.nan_to_num(index_grid[:, 2:], nan=0).astype( - bool - ) # Shape (npix, 15000) + for_indices_by_spin_phase = xr.DataArray( + np.nan_to_num(index_grid[2:, :], nan=0).astype(bool), + dims=("spin_phase_step", "pixel"), + ) + boundary_scale_factors = xr.DataArray( + boundary_scale_factors, dims=("spin_phase_step", "pixel") + ) return ( for_indices_by_spin_phase, theta_vals, @@ -254,3 +447,69 @@ def get_scattering_thresholds_for_energy( threshold = 0 thresholds.append(threshold) return np.array(thresholds) + + +def get_static_deadtime_ratios( + sensor_id: int, ancillary_files: dict +) -> tuple[np.ndarray, np.ndarray]: + """ + Get static deadtime ratios. + + These should only be used when the instrument is operating in a mode that does not + produce sectored rates data. + + Parameters + ---------- + sensor_id : int + Sensor ID, either 45 or 90. + ancillary_files : dict + Dictionary containing ancillary files. + + Returns + ------- + np.ndarray + Array of static deadtime ratios for each energy bin. + """ + descriptor = f"l1c-{sensor_id}sensor-static-dead-times" + df = pd.read_csv(ancillary_files[descriptor]) + # Drop any rows that are duplicates. We only want unique spin phase and dead time + # ratio pairs. + df = df.drop_duplicates() + return df["Spin Phase (deg)"].to_numpy(dtype=float), df["Dead Time Ratio"].to_numpy( + dtype=float + ) + + +def build_energy_bins( + energy_bin_edges: np.ndarray | None = None, +) -> tuple[list[tuple[float, float]], np.ndarray, np.ndarray]: + """ + Build energy bin boundaries. + + Parameters + ---------- + energy_bin_edges : numpy.ndarray, optional + List of energy bin edges. If None, uses default UltraConstants.PSET_ENERGY_BIN. + + Returns + ------- + intervals : list[tuple[float, float]] + Energy bins. + energy_midpoints : np.ndarray + Array of energy bin midpoints. + energy_bin_geometric_means : np.ndarray + Array of geometric means of energy bins. + """ + # Create energy bins. + if energy_bin_edges is None: + energy_bin_edges = np.array(UltraConstants.PSET_ENERGY_BIN_EDGES) + + energy_midpoints = (energy_bin_edges[:-1] + energy_bin_edges[1:]) / 2 + + intervals = [ + (float(energy_bin_edges[i]), float(energy_bin_edges[i + 1])) + for i in range(len(energy_bin_edges) - 1) + ] + energy_bin_geometric_means = np.sqrt(energy_bin_edges[:-1] * energy_bin_edges[1:]) + + return intervals, energy_midpoints, energy_bin_geometric_means diff --git a/imap_processing/ultra/l1c/make_helio_index_maps.py b/imap_processing/ultra/l1c/make_helio_index_maps.py new file mode 100644 index 0000000000..8b9c9baee6 --- /dev/null +++ b/imap_processing/ultra/l1c/make_helio_index_maps.py @@ -0,0 +1,335 @@ +"""Make heliocentric HEALPix index maps for Ultra L1C processing.""" + +import logging + +import astropy_healpix.healpy as hp +import numpy as np +import spiceypy as sp +import xarray as xr + +from imap_processing.spice.geometry import ( + SpiceBody, + SpiceFrame, + get_rotation_matrix, + imap_state, +) +from imap_processing.ultra.constants import UltraConstants +from imap_processing.ultra.l1b.lookup_utils import is_inside_fov +from imap_processing.ultra.l1c.l1c_lookup_utils import build_energy_bins + +logger = logging.getLogger(__name__) + + +def vector_ijk_to_theta_phi( + inst_vecs: np.ndarray, +) -> tuple[np.ndarray, np.ndarray]: + """ + Convert instrument vectors to theta/phi. + + Parameters + ---------- + inst_vecs : np.ndarray + Array of shape (n, 3) with components (x, y, z). + + Returns + ------- + theta : np.ndarray + Declination in radians, range [-Ο€, Ο€]. + phi : np.ndarray + Right ascension in radians, range [-Ο€, Ο€]. + """ + # Extract components + i_comp = inst_vecs[:, 0] # x component + j_comp = inst_vecs[:, 1] # y component + k_comp = inst_vecs[:, 2] # z component + + # Normalize + magnitude = np.linalg.norm(inst_vecs, axis=1) + + # Compute declination and right ascension + theta = np.arcsin(i_comp / magnitude) + phi = np.arctan2(j_comp, k_comp) + + # Wrap to [-Ο€, Ο€] + theta = np.where(theta > np.pi, theta - 2 * np.pi, theta) + phi = np.where(phi > np.pi, phi - 2 * np.pi, phi) + + return theta, phi + + +def make_helio_index_maps_with_nominal_kernels( + kernel_paths: list[str], + nside: int, + spin_duration: float, + num_steps: int, + instrument_frame: SpiceFrame = SpiceFrame.IMAP_ULTRA_90, + compute_bsf: bool = False, + boundary_points: int = 8, +) -> xr.Dataset: + """ + Create index maps with nominal sim kernels. + + This function ensures SPICE kernels are loaded before creating the maps. It uses + a KernelPool context manager to ensure only this function uses the nominal sim + kernels. + + Parameters + ---------- + kernel_paths : list[str] + List of string paths to nominal simulated SPICE kernels. + nside : int + HEALPix nside parameter. + spin_duration : float + Total spin period in seconds. + num_steps : int + Number of spin phase steps. + instrument_frame : SpiceFrame, optional + Instrument frame (default IMAP_ULTRA_90). + compute_bsf : bool, optional + Compute boundary scale factors (default False). + boundary_points : int, optional + Number of boundary points per pixel (default 8). + + Returns + ------- + xr.Dataset + Dataset with helio index maps. + """ + # Get all loaded SPK kernels + spk_kernels = [sp.kdata(i, "spk")[0] for i in range(sp.ktotal("spk"))] + # Find the de440s.bps kernel + de440s_file = next((k for k in spk_kernels if "de440" in k), None) + if de440s_file is None: + raise RuntimeError("de440s.bsp kernel not found in loaded SPK kernels.") + # If found, add to kernel paths + kernel_paths.append(de440s_file) + with sp.KernelPool(kernel_paths): + # calculate the start et of the pointing kernel. + # TODO replace this with a util function + ck_kernel, _, _, _ = sp.kdata(1, "ck") + ck_cover = sp.ckcov( + ck_kernel, SpiceFrame.IMAP_DPS.value, True, "INTERVAL", 0, "TDB" + ) + et_start, _ = sp.wnfetd(ck_cover, 0) + # Call the main function + return make_helio_index_maps( + nside=nside, + spin_duration=spin_duration, + num_steps=num_steps, + start_et=et_start, + instrument_frame=instrument_frame, + compute_bsf=compute_bsf, + boundary_points=boundary_points, + ) + + +def make_helio_index_maps( + nside: int, + spin_duration: float, + num_steps: int, + start_et: float, + instrument_frame: SpiceFrame = SpiceFrame.IMAP_ULTRA_90, + compute_bsf: bool = False, + boundary_points: int = 8, +) -> xr.Dataset: + """ + Create HEALPix index maps for heliocentric observations. + + This function generates exposure maps that account for spacecraft + velocity aberration, multiple energy bins, and spin phase sampling. + + Parameters + ---------- + nside : int + HEALPix nside parameter (determines angular resolution). + spin_duration : float + Total spin period in seconds. + num_steps : int + Number of spin phase steps to sample. + start_et : float + Start ephemeris time. + instrument_frame : SpiceFrame, optional + SpiceFrame of the instrument (default IMAP_ULTRA_90). + compute_bsf : bool, optional + If True, compute boundary scale factors (default False). + boundary_points : int, optional + Number of boundary points to sample per pixel (default 8). + + Returns + ------- + xarray.Dataset + Dataset with dimensions (step, energy, pixel) containing index, + theta, phi, and bsf data variables, plus ra and dec coordinates. + """ + # Get spacecraft velocity at start time + state = imap_state(start_et, ref_frame=SpiceFrame.IMAP_DPS, observer=SpiceBody.SUN) + sc_vel = state[3:6] # Extract [vx, vy, vz] + + logger.info("Spacecraft velocity: %s km/s", sc_vel) + logger.info("Speed: %.2f km/s", np.linalg.norm(sc_vel)) + + # Build energy bins + _, energy_midpoints, energy_bin_geometric_means = build_energy_bins() + num_energy_bins = len(energy_bin_geometric_means) + + # Get number of pixels + npix = hp.nside2npix(nside) + + # Compute RA/Dec for pixel centers + pixel_indices = np.arange(npix) + + # Time parameters + end_et = start_et + spin_duration + dt_step = spin_duration / num_steps + + # Pre-compute all pixel vectors once + pixel_vecs = np.array(hp.pix2vec(nside, pixel_indices, nest=False)).T # (npix, 3) + + # Initialize output arrays + index_map = np.zeros((num_steps, num_energy_bins, npix)) + theta_map = np.zeros((num_steps, num_energy_bins, npix)) + phi_map = np.zeros((num_steps, num_energy_bins, npix)) + bsf_map = np.zeros((num_steps, num_energy_bins, npix)) + + logger.info( + "Processing %d time steps, %d energy bins, %d pixels...", + num_steps, + num_energy_bins, + npix, + ) + if compute_bsf: + logger.info( + "Computing boundary scale factors with %d points per pixel", + boundary_points, + ) + # TODO vectorize loop + time_id = 0 + t = start_et + while t < (end_et - dt_step / 2): + # Get rotation matrix for this time step + rotation_matrix = get_rotation_matrix( + t, + from_frame=SpiceFrame.IMAP_DPS, + to_frame=instrument_frame, + ) + for energy_id in range(num_energy_bins): + # Convert energy to velocity (km/s) + energy_mean = energy_bin_geometric_means[energy_id] + kps = ( + np.sqrt(2 * energy_mean * UltraConstants.KEV_J / UltraConstants.MASS_H) + / 1e3 + ) + + # Transform pixel vectors to heliocentric frame + helio_velocity = ( + sc_vel.reshape(1, 3) + kps * pixel_vecs + ) # Galilean transform + helio_normalized = helio_velocity / np.linalg.norm( + helio_velocity, axis=1, keepdims=True + ) + + # Transform to inst + inst_vecs = helio_normalized @ rotation_matrix.T + theta, phi = vector_ijk_to_theta_phi(inst_vecs) + + phi = np.where(phi > np.pi, phi - 2 * np.pi, phi) + + # Check FOV + in_fov_mask = is_inside_fov(theta, phi) + fov_pixels = np.where(in_fov_mask)[0] + + # Store results for FOV pixels + theta_map[time_id, energy_id, fov_pixels] = np.degrees(theta[fov_pixels]) + phi_map[time_id, energy_id, fov_pixels] = np.degrees(phi[fov_pixels]) + index_map[time_id, energy_id, fov_pixels] = 1.0 + + # Compute boundary scale factor if requested + if compute_bsf: + for pix_id in fov_pixels: + # Get boundary vectors for this pixel + boundary_step = boundary_points // 4 + boundary_vecs = hp.boundaries( + nside, pix_id, step=boundary_step, nest=False + ) + boundary_vecs = boundary_vecs.T + + # Include center pixel + sample_vecs = np.vstack( + [boundary_vecs, pixel_vecs[pix_id : pix_id + 1]] + ) + + # Transform boundary vectors to heliocentric frame + helio_boundary_vel = sc_vel.reshape(1, 3) + kps * sample_vecs + helio_boundary_norm = helio_boundary_vel / np.linalg.norm( + helio_boundary_vel, axis=1, keepdims=True + ) + + # Transform to instrument frame + inst_boundary = helio_boundary_norm @ rotation_matrix + + # Convert to theta/phi + theta_b, phi_b = vector_ijk_to_theta_phi(inst_boundary) + phi_b = np.where(phi_b > np.pi, phi_b - 2 * np.pi, phi_b) + + # Check how many sample points are in FOV + in_fov_boundary = is_inside_fov(theta_b, phi_b) + bsf = np.sum(in_fov_boundary) / len(sample_vecs) + + bsf_map[time_id, energy_id, pix_id] = bsf + + # Increment time + time_id += 1 + t += dt_step + + # Create coordinate arrays + step_indices = np.arange(num_steps) + spin_phases = np.linspace(0, 360, num_steps, endpoint=False) + + # Create xarray Dataset + # Ensure index_map is a boolean type + index_map = index_map.astype(bool) + ds = xr.Dataset( + data_vars={ + "index": ( + ["spin_phase_step", "energy", "pixel"], + index_map, + {"long_name": "Pixel in FOV flag"}, + ), + "theta": ( + ["spin_phase_step", "energy", "pixel"], + theta_map, + {"long_name": "Instrument theta angle", "units": "degrees"}, + ), + "phi": ( + ["spin_phase_step", "energy", "pixel"], + phi_map, + {"long_name": "Instrument phi angle", "units": "degrees"}, + ), + "bsf": ( + ["spin_phase_step", "energy", "pixel"], + bsf_map, + {"long_name": "Boundary scale factor", "units": "fractional"}, + ), + }, + coords={ + "spin_phase_step": (["spin_phase_step"], step_indices), + "energy": ( + ["energy"], + energy_bin_geometric_means, + {"long_name": "Energy bin geometric mean", "units": "keV"}, + ), + "pixel": (["pixel"], pixel_indices), + "spin_phase": ( + ["spin_phase_step"], + spin_phases, + {"long_name": "Spin phase", "units": "degrees"}, + ), + "energy_midpoint": ( + ["energy"], + energy_midpoints, + {"long_name": "Energy bin midpoint", "units": "keV"}, + ), + }, + ) + + return ds diff --git a/imap_processing/ultra/l1c/sim_spice_kernels/imap_001.tf b/imap_processing/ultra/l1c/sim_spice_kernels/imap_001.tf new file mode 100644 index 0000000000..4ca51ccafa --- /dev/null +++ b/imap_processing/ultra/l1c/sim_spice_kernels/imap_001.tf @@ -0,0 +1,3105 @@ +KPL/FK + +Interstellar Mapping and Acceleration Probe Frames Kernel +======================================================================== + + This frames kernel contains the current set of coordinate frame + definitions for the Interstellar Mapping and Acceleration Probe + (IMAP) spacecraft, structures, and science instruments. + + This kernel also contains NAIF ID/name mapping for the IMAP + instruments. + + +Version and Date +======================================================================== + + The TEXT_KERNEL_ID stores version information of loaded project text + kernels. Each entry associated with the keyword is a string that + consists of four parts: the kernel name, version, entry date, and + type. For example, the frames kernel might have an entry as follows: + + + TEXT_KERNEL_ID += 'IMAP_FRAMES V1.0.0 2024-XXXX-NN FK' + | | | | + | | | | + KERNEL NAME <-------+ | | | + | | V + VERSION <------+ | KERNEL TYPE + | + V + ENTRY DATE + + + Interstellar Mapping and Acceleration Probe Frames Kernel Version: + + \begindata + + TEXT_KERNEL_ID += 'IMAP_FRAMES V1.0.0 2024-XXXX-NN FK' + + \begintext + + Version 1.0.0 -- XXXX NN, 2024 -- Douglas Rodgers + Lillian Nguyen + Nicholas Dutton + + Initial complete release. Frame/Body codes for thrusters redefined + + Version 0.0.1 -- July 9, 2021 -- Ian Wick Murphy + + Modifying dart_008.tf to add basic IMAP frame components. This + includes IMAP, IMAP_THRUSTER, and CK/SCLK IDs. Also adding a place + holder for the IMAP-Lo instrument with the ID -43001 and IMAP_LO + name. Future work includes adding more detailed instrument frames, + and reaching out to mechanical for an "official" IMAP_SPACECRAFT + frame definition. + + +References +======================================================================== + + 1. "Frames Required Reading" + + 2. "Kernel Pool Required Reading" + + 3. "C-Kernel Required Reading" + + 4. "7516-9067: IMAP Mechanical Interface Control Document", + Johns Hopkins Applied Physics Laboratory + + 5. "7516-9050: IMAP Coordinate Frame & Technical Definitions Doc.", + Johns Hopkins Applied Physics Laboratory + + 6. "7516-0011: IMAP Mechanical Interface Control Drawing", + [EXPORT CONTROLLED], Johns Hopkins Applied Physics Laboratory + + 7. "7523-0008: IMAP ULTRA Mechanical Interface Control Drawing", + [EXPORT CONTROLLED], Johns Hopkins Applied Physics Laboratory + + 8. "058991000: IMAP SWAPI Mechanical Interface Control Drawing", + Princeton University Space Physics + + 9. "GLOWS-CBK-DWG-2020-08-25-019-v4.4: IMAP GLOWS Mechanical + Interface Control Drawing", Centrum Badag Kosmicznych, Polska + Akademia Nauks + + 10. Responses from IMAP instrument teams on their base frame axis + definitions, received in email. + + 11. "Euler angles", Wikimedia Foundation, 2024-04-22, + https://en.wikipedia.org/wiki/Euler_angles + + 12. "7516-9059: IMAP-Lo to Spacecraft Interface Control Document", + [EXPORT CONTROLLED], Johns Hopkins Applied Physics Laboratory + + 13. "DRAFT Rev H: IMAP-Lo Mechanical Interface Control Drawing", + [EXPORT CONTROLLED], Univ. of New Hampshire Space Science Center + + 14. McComas et al, "IMAP: A New NASA Mission", + Space Sci Rev (2018) 214:116 + + 15. "IMAP-HI SENSOR HEAD Mechanical Interface Control Drawing", + [EXPORT CONTROLLED], Los Alamos National Laboratory + + 16. "IMAP-MAG-SENSOR Drawing Rev 6", Imperial College London + + +Contact Information +======================================================================== + + Douglas Rodgers, JHU/APL, Douglas.Rodgers@jhuapl.edu + + Lillian Nguyen, JHU/APL, Lillian.Nguyen@jhuapl.edu + + Nicholas Dutton, JHU/APL, Nicholas.Dutton@jhuapl.edu + + Ian Wick Murphy, JHU/APL, Ian.Murphy@jhuapl.edu + + +Implementation Notes +======================================================================== + + This file is used by the SPICE system as follows: programs that make + use of this frame kernel must `load' the kernel, normally during + program initialization. Loading the kernel associates the data items + with their names in a data structure called the `kernel pool'. The + SPICELIB routine FURNSH loads a kernel into the pool as shown below: + + FORTRAN: (SPICELIB) + + CALL FURNSH ( frame_kernel_name ) + + C: (CSPICE) + + furnsh_c ( frame_kernel_name ); + + IDL: (ICY) + + cspice_furnsh, frame_kernel_name + + MATLAB: (MICE) + + cspice_furnsh ( frame_kernel_name ) + + This file was created and may be updated with a text editor or word + processor. + + +Viewing ASCII Artwork +======================================================================== + + Artwork must be viewed in a text editor with monospaced font and + compact single-spaced lines. The following give the proper aspect + ratio: + + Andale Regular + Menlo Regular + Courier New Regular + PT Mono Regular + + The common monospaced font (at the time of writing) Monaco Regular + gives an aspect ratio that is too tall. Other fonts undoubtedly + will render the diagrams properly or improperly. + + As a guide, the following axis will be square when measured from the + bottom of the lower-most vertical line to the end of each axis. + + | + | + | + |_______ + + +IMAP NAIF ID Codes -- Definitions +======================================================================== + + This section contains name to NAIF ID mappings for the IMAP mission. + Once the contents of this file are loaded into the KERNEL POOL, these + mappings become available within SPICE, making it possible to use + names instead of ID code in high level SPICE routine calls. + + \begindata + + NAIF_BODY_NAME += ( 'IMAP' ) + NAIF_BODY_CODE += ( -43 ) + + NAIF_BODY_NAME += ( 'IMAP_SPACECRAFT' ) + NAIF_BODY_CODE += ( -43000 ) + + NAIF_BODY_NAME += ( 'IMAP_THRUSTER_A1' ) + NAIF_BODY_CODE += ( -43010 ) + + NAIF_BODY_NAME += ( 'IMAP_THRUSTER_A2' ) + NAIF_BODY_CODE += ( -43011 ) + + NAIF_BODY_NAME += ( 'IMAP_THRUSTER_A3' ) + NAIF_BODY_CODE += ( -43012 ) + + NAIF_BODY_NAME += ( 'IMAP_THRUSTER_A4' ) + NAIF_BODY_CODE += ( -43013 ) + + NAIF_BODY_NAME += ( 'IMAP_THRUSTER_R1' ) + NAIF_BODY_CODE += ( -43020 ) + + NAIF_BODY_NAME += ( 'IMAP_THRUSTER_R2' ) + NAIF_BODY_CODE += ( -43021 ) + + NAIF_BODY_NAME += ( 'IMAP_THRUSTER_R3' ) + NAIF_BODY_CODE += ( -43022 ) + + NAIF_BODY_NAME += ( 'IMAP_THRUSTER_R4' ) + NAIF_BODY_CODE += ( -43023 ) + + NAIF_BODY_NAME += ( 'IMAP_THRUSTER_R5' ) + NAIF_BODY_CODE += ( -43024 ) + + NAIF_BODY_NAME += ( 'IMAP_THRUSTER_R6' ) + NAIF_BODY_CODE += ( -43025 ) + + NAIF_BODY_NAME += ( 'IMAP_THRUSTER_R7' ) + NAIF_BODY_CODE += ( -43026 ) + + NAIF_BODY_NAME += ( 'IMAP_THRUSTER_R8' ) + NAIF_BODY_CODE += ( -43027 ) + + NAIF_BODY_NAME += ( 'IMAP_SUN_SENSOR_PZ' ) + NAIF_BODY_CODE += ( -43030 ) + + NAIF_BODY_NAME += ( 'IMAP_SUN_SENSOR_MZ' ) + NAIF_BODY_CODE += ( -43031 ) + + NAIF_BODY_NAME += ( 'IMAP_STAR_TRACKER_PX' ) + NAIF_BODY_CODE += ( -43040 ) + + NAIF_BODY_NAME += ( 'IMAP_STAR_TRACKER_MX' ) + NAIF_BODY_CODE += ( -43041 ) + + NAIF_BODY_NAME += ( 'IMAP_LOW_GAIN_ANTENNA' ) + NAIF_BODY_CODE += ( -43050 ) + + NAIF_BODY_NAME += ( 'IMAP_MED_GAIN_ANTENNA' ) + NAIF_BODY_CODE += ( -43051 ) + + NAIF_BODY_NAME += ( 'IMAP_LO_BASE' ) + NAIF_BODY_CODE += ( -43100 ) + + NAIF_BODY_NAME += ( 'IMAP_LO' ) + NAIF_BODY_CODE += ( -43101 ) + + NAIF_BODY_NAME += ( 'IMAP_LO_STAR_SENSOR' ) + NAIF_BODY_CODE += ( -43102 ) + + NAIF_BODY_NAME += ( 'IMAP_HI_45' ) + NAIF_BODY_CODE += ( -43150 ) + + NAIF_BODY_NAME += ( 'IMAP_HI_90' ) + NAIF_BODY_CODE += ( -43175 ) + + NAIF_BODY_NAME += ( 'IMAP_ULTRA_45' ) + NAIF_BODY_CODE += ( -43200 ) + + NAIF_BODY_NAME += ( 'IMAP_ULTRA_90' ) + NAIF_BODY_CODE += ( -43225 ) + + NAIF_BODY_NAME += ( 'IMAP_MAG_BOOM' ) + NAIF_BODY_CODE += ( -43250 ) + + NAIF_BODY_NAME += ( 'IMAP_MAG_I' ) + NAIF_BODY_CODE += ( -43251 ) + + NAIF_BODY_NAME += ( 'IMAP_MAG_O' ) + NAIF_BODY_CODE += ( -43251 ) + + NAIF_BODY_NAME += ( 'IMAP_SWE' ) + NAIF_BODY_CODE += ( -43300 ) + + NAIF_BODY_NAME += ( 'IMAP_SWE_DETECTOR_P63' ) + NAIF_BODY_CODE += ( -43301 ) + + NAIF_BODY_NAME += ( 'IMAP_SWE_DETECTOR_P42' ) + NAIF_BODY_CODE += ( -43302 ) + + NAIF_BODY_NAME += ( 'IMAP_SWE_DETECTOR_P21' ) + NAIF_BODY_CODE += ( -43303 ) + + NAIF_BODY_NAME += ( 'IMAP_SWE_DETECTOR_000' ) + NAIF_BODY_CODE += ( -43304 ) + + NAIF_BODY_NAME += ( 'IMAP_SWE_DETECTOR_M21' ) + NAIF_BODY_CODE += ( -43305 ) + + NAIF_BODY_NAME += ( 'IMAP_SWE_DETECTOR_M42' ) + NAIF_BODY_CODE += ( -43306 ) + + NAIF_BODY_NAME += ( 'IMAP_SWE_DETECTOR_M63' ) + NAIF_BODY_CODE += ( -43307 ) + + NAIF_BODY_NAME += ( 'IMAP_SWAPI' ) + NAIF_BODY_CODE += ( -433510 ) + + NAIF_BODY_NAME += ( 'IMAP_SWAPI_APERTURE_L' ) + NAIF_BODY_CODE += ( -43351 ) + + NAIF_BODY_NAME += ( 'IMAP_SWAPI_APERTURE_R' ) + NAIF_BODY_CODE += ( -43352 ) + + NAIF_BODY_NAME += ( 'IMAP_SWAPI_SUNGLASSES' ) + NAIF_BODY_CODE += ( -43353 ) + + NAIF_BODY_NAME += ( 'IMAP_CODICE' ) + NAIF_BODY_CODE += ( -43400 ) + + NAIF_BODY_NAME += ( 'IMAP_CODICE_LO_APERTURE_01' ) + NAIF_BODY_CODE += ( -43401 ) + + NAIF_BODY_NAME += ( 'IMAP_CODICE_LO_APERTURE_02' ) + NAIF_BODY_CODE += ( -43402 ) + + NAIF_BODY_NAME += ( 'IMAP_CODICE_LO_APERTURE_03' ) + NAIF_BODY_CODE += ( -43403 ) + + NAIF_BODY_NAME += ( 'IMAP_CODICE_LO_APERTURE_04' ) + NAIF_BODY_CODE += ( -43404 ) + + NAIF_BODY_NAME += ( 'IMAP_CODICE_LO_APERTURE_05' ) + NAIF_BODY_CODE += ( -43405 ) + + NAIF_BODY_NAME += ( 'IMAP_CODICE_LO_APERTURE_06' ) + NAIF_BODY_CODE += ( -43406 ) + + NAIF_BODY_NAME += ( 'IMAP_CODICE_LO_APERTURE_07' ) + NAIF_BODY_CODE += ( -43407 ) + + NAIF_BODY_NAME += ( 'IMAP_CODICE_LO_APERTURE_08' ) + NAIF_BODY_CODE += ( -43408 ) + + NAIF_BODY_NAME += ( 'IMAP_CODICE_LO_APERTURE_09' ) + NAIF_BODY_CODE += ( -43409 ) + + NAIF_BODY_NAME += ( 'IMAP_CODICE_LO_APERTURE_10' ) + NAIF_BODY_CODE += ( -43410 ) + + NAIF_BODY_NAME += ( 'IMAP_CODICE_LO_APERTURE_11' ) + NAIF_BODY_CODE += ( -43411 ) + + NAIF_BODY_NAME += ( 'IMAP_CODICE_LO_APERTURE_12' ) + NAIF_BODY_CODE += ( -43412 ) + + NAIF_BODY_NAME += ( 'IMAP_CODICE_LO_APERTURE_13' ) + NAIF_BODY_CODE += ( -43413 ) + + NAIF_BODY_NAME += ( 'IMAP_CODICE_LO_APERTURE_14' ) + NAIF_BODY_CODE += ( -43414 ) + + NAIF_BODY_NAME += ( 'IMAP_CODICE_LO_APERTURE_15' ) + NAIF_BODY_CODE += ( -43415 ) + + NAIF_BODY_NAME += ( 'IMAP_CODICE_LO_APERTURE_16' ) + NAIF_BODY_CODE += ( -43416 ) + + NAIF_BODY_NAME += ( 'IMAP_CODICE_LO_APERTURE_17' ) + NAIF_BODY_CODE += ( -43417 ) + + NAIF_BODY_NAME += ( 'IMAP_CODICE_LO_APERTURE_18' ) + NAIF_BODY_CODE += ( -43418 ) + + NAIF_BODY_NAME += ( 'IMAP_CODICE_LO_APERTURE_19' ) + NAIF_BODY_CODE += ( -43419 ) + + NAIF_BODY_NAME += ( 'IMAP_CODICE_LO_APERTURE_20' ) + NAIF_BODY_CODE += ( -43420 ) + + NAIF_BODY_NAME += ( 'IMAP_CODICE_LO_APERTURE_21' ) + NAIF_BODY_CODE += ( -43421 ) + + NAIF_BODY_NAME += ( 'IMAP_CODICE_LO_APERTURE_22' ) + NAIF_BODY_CODE += ( -43422 ) + + NAIF_BODY_NAME += ( 'IMAP_CODICE_LO_APERTURE_23' ) + NAIF_BODY_CODE += ( -43423 ) + + NAIF_BODY_NAME += ( 'IMAP_CODICE_LO_APERTURE_24' ) + NAIF_BODY_CODE += ( -43424 ) + + NAIF_BODY_NAME += ( 'IMAP_CODICE_HI_APERTURE_01' ) + NAIF_BODY_CODE += ( -43425 ) + + NAIF_BODY_NAME += ( 'IMAP_CODICE_HI_APERTURE_02' ) + NAIF_BODY_CODE += ( -43426 ) + + NAIF_BODY_NAME += ( 'IMAP_CODICE_HI_APERTURE_03' ) + NAIF_BODY_CODE += ( -43427 ) + + NAIF_BODY_NAME += ( 'IMAP_CODICE_HI_APERTURE_04' ) + NAIF_BODY_CODE += ( -43428 ) + + NAIF_BODY_NAME += ( 'IMAP_CODICE_HI_APERTURE_05' ) + NAIF_BODY_CODE += ( -43429 ) + + NAIF_BODY_NAME += ( 'IMAP_CODICE_HI_APERTURE_06' ) + NAIF_BODY_CODE += ( -43430 ) + + NAIF_BODY_NAME += ( 'IMAP_CODICE_HI_APERTURE_07' ) + NAIF_BODY_CODE += ( -43431 ) + + NAIF_BODY_NAME += ( 'IMAP_CODICE_HI_APERTURE_08' ) + NAIF_BODY_CODE += ( -43432 ) + + NAIF_BODY_NAME += ( 'IMAP_CODICE_HI_APERTURE_09' ) + NAIF_BODY_CODE += ( -43433 ) + + NAIF_BODY_NAME += ( 'IMAP_CODICE_HI_APERTURE_10' ) + NAIF_BODY_CODE += ( -43434 ) + + NAIF_BODY_NAME += ( 'IMAP_CODICE_HI_APERTURE_11' ) + NAIF_BODY_CODE += ( -43435 ) + + NAIF_BODY_NAME += ( 'IMAP_CODICE_HI_APERTURE_12' ) + NAIF_BODY_CODE += ( -43436 ) + + NAIF_BODY_NAME += ( 'IMAP_HIT' ) + NAIF_BODY_CODE += ( -43500 ) + + NAIF_BODY_NAME += ( 'IMAP_HIT_L1_APERTURE_01' ) + NAIF_BODY_CODE += ( -43501 ) + + NAIF_BODY_NAME += ( 'IMAP_HIT_L1_APERTURE_02' ) + NAIF_BODY_CODE += ( -43502 ) + + NAIF_BODY_NAME += ( 'IMAP_HIT_L1_APERTURE_03' ) + NAIF_BODY_CODE += ( -43503 ) + + NAIF_BODY_NAME += ( 'IMAP_HIT_L1_APERTURE_04' ) + NAIF_BODY_CODE += ( -43504 ) + + NAIF_BODY_NAME += ( 'IMAP_HIT_L1_APERTURE_05' ) + NAIF_BODY_CODE += ( -43505 ) + + NAIF_BODY_NAME += ( 'IMAP_HIT_L1_APERTURE_06' ) + NAIF_BODY_CODE += ( -43506 ) + + NAIF_BODY_NAME += ( 'IMAP_HIT_L1_APERTURE_07' ) + NAIF_BODY_CODE += ( -43507 ) + + NAIF_BODY_NAME += ( 'IMAP_HIT_L1_APERTURE_08' ) + NAIF_BODY_CODE += ( -43508 ) + + NAIF_BODY_NAME += ( 'IMAP_HIT_L1_APERTURE_09' ) + NAIF_BODY_CODE += ( -43509 ) + + NAIF_BODY_NAME += ( 'IMAP_HIT_L1_APERTURE_10' ) + NAIF_BODY_CODE += ( -43510 ) + + NAIF_BODY_NAME += ( 'IMAP_IDEX' ) + NAIF_BODY_CODE += ( -43700 ) + + NAIF_BODY_NAME += ( 'IMAP_IDEX_DETECTOR' ) + NAIF_BODY_CODE += ( -43701 ) + + NAIF_BODY_NAME += ( 'IMAP_IDEX_FULL_SCIENCE' ) + NAIF_BODY_CODE += ( -43702 ) + + + NAIF_BODY_NAME += ( 'IMAP_GLOWS' ) + NAIF_BODY_CODE += ( -43751 ) + + \begintext + +Removed by Tim Plummer due to missing frame definition + NAIF_BODY_NAME += ( 'IMAP_GLOWS_BASE' ) + NAIF_BODY_CODE += ( -43750 ) + +IMAP NAIF ID Codes -- Definitions +======================================================================== + + The ID codes -43900 to -43999 have been reserved for the IMAP dynamic + frames kernel and are not utilized in this file. + + The following frames are defined in this kernel file: + + Frame Name Relative To Type NAIF ID + ========================== =============== ======= ======= + + Spacecraft (000-099) + -------------------------- + IMAP_SPACECRAFT J2000 CK -43000 + IMAP_THRUSTER_A1 IMAP_SPACECRAFT FIXED -43010 + IMAP_THRUSTER_A2 IMAP_SPACECRAFT FIXED -43011 + IMAP_THRUSTER_A3 IMAP_SPACECRAFT FIXED -43012 + IMAP_THRUSTER_A4 IMAP_SPACECRAFT FIXED -43013 + IMAP_THRUSTER_R1 IMAP_SPACECRAFT FIXED -43020 + IMAP_THRUSTER_R2 IMAP_SPACECRAFT FIXED -43021 + IMAP_THRUSTER_R3 IMAP_SPACECRAFT FIXED -43022 + IMAP_THRUSTER_R4 IMAP_SPACECRAFT FIXED -43023 + IMAP_THRUSTER_R5 IMAP_SPACECRAFT FIXED -43024 + IMAP_THRUSTER_R6 IMAP_SPACECRAFT FIXED -43025 + IMAP_THRUSTER_R7 IMAP_SPACECRAFT FIXED -43026 + IMAP_THRUSTER_R8 IMAP_SPACECRAFT FIXED -43027 + IMAP_SUN_SENSOR_PZ IMAP_SPACECRAFT FIXED -43030 + IMAP_SUN_SENSOR_MZ IMAP_SPACECRAFT FIXED -43031 + IMAP_STAR_TRACKER_PX IMAP_SPACECRAFT FIXED -43040 + IMAP_STAR_TRACKER_MX IMAP_SPACECRAFT FIXED -43041 + IMAP_LOW_GAIN_ANTENNA IMAP_SPACECRAFT FIXED -43050 + IMAP_MED_GAIN_ANTENNA IMAP_SPACECRAFT FIXED -43051 + + IMAP-Lo (100-149) + -------------------------- + IMAP_LO_BASE IMAP_SPACECRAFT FIXED -43100 + IMAP_LO IMAP_LO_BASE CK -43101 + IMAP_LO_STAR_SENSOR IMAP_LO FIXED -43102 + + IMAP-Hi (150-199) + -------------------------- + IMAP_HI_45 IMAP_SPACECRAFT FIXED -43150 + IMAP_HI_90 IMAP_SPACECRAFT FIXED -43151 + + IMAP-Ultra (200-249) + -------------------------- + IMAP_ULTRA_45 IMAP_SPACECRAFT FIXED -43200 + IMAP_ULTRA_90 IMAP_SPACECRAFT FIXED -43201 + + MAG (250-299) + -------------------------- + IMAP_MAG_BOOM IMAP_SPACECRAFT FIXED -43250 + IMAP_MAG_I IMAP_MAG_BOOM FIXED -43251 + IMAP_MAG_O IMAP_MAG_BOOM FIXED -43252 + + SWE (300-349) + -------------------------- + IMAP_SWE IMAP_SPACECRAFT FIXED -43300 + IMAP_SWE_DETECTOR_P63 IMAP_SWE FIXED -43301 + IMAP_SWE_DETECTOR_P42 IMAP_SWE FIXED -43302 + IMAP_SWE_DETECTOR_P21 IMAP_SWE FIXED -43303 + IMAP_SWE_DETECTOR_000 IMAP_SWE FIXED -43304 + IMAP_SWE_DETECTOR_M21 IMAP_SWE FIXED -43305 + IMAP_SWE_DETECTOR_M42 IMAP_SWE FIXED -43306 + IMAP_SWE_DETECTOR_M63 IMAP_SWE FIXED -43307 + + SWAPI (350-399) + -------------------------- + IMAP_SWAPI IMAP_SPACECRAFT FIXED -43350 + IMAP_SWAPI_APERTURE_L IMAP_SWAPI FIXED -43351 + IMAP_SWAPI_APERTURE_R IMAP_SWAPI FIXED -43352 + IMAP_SWAPI_SUNGLASSES IMAP_SWAPI FIXED -43353 + + CODICE (400-499) + -------------------------- + IMAP_CODICE IMAP_SPACECRAFT FIXED -43400 + IMAP_CODICE_LO_APERTURE_01 IMAP_CODICE FIXED -43401 + IMAP_CODICE_LO_APERTURE_02 IMAP_CODICE FIXED -43402 + IMAP_CODICE_LO_APERTURE_03 IMAP_CODICE FIXED -43403 + IMAP_CODICE_LO_APERTURE_04 IMAP_CODICE FIXED -43404 + IMAP_CODICE_LO_APERTURE_05 IMAP_CODICE FIXED -43405 + IMAP_CODICE_LO_APERTURE_06 IMAP_CODICE FIXED -43406 + IMAP_CODICE_LO_APERTURE_07 IMAP_CODICE FIXED -43407 + IMAP_CODICE_LO_APERTURE_08 IMAP_CODICE FIXED -43408 + IMAP_CODICE_LO_APERTURE_09 IMAP_CODICE FIXED -43409 + IMAP_CODICE_LO_APERTURE_10 IMAP_CODICE FIXED -43410 + IMAP_CODICE_LO_APERTURE_11 IMAP_CODICE FIXED -43411 + IMAP_CODICE_LO_APERTURE_12 IMAP_CODICE FIXED -43412 + IMAP_CODICE_LO_APERTURE_13 IMAP_CODICE FIXED -43413 + IMAP_CODICE_LO_APERTURE_14 IMAP_CODICE FIXED -43414 + IMAP_CODICE_LO_APERTURE_15 IMAP_CODICE FIXED -43415 + IMAP_CODICE_LO_APERTURE_16 IMAP_CODICE FIXED -43416 + IMAP_CODICE_LO_APERTURE_17 IMAP_CODICE FIXED -43417 + IMAP_CODICE_LO_APERTURE_18 IMAP_CODICE FIXED -43418 + IMAP_CODICE_LO_APERTURE_19 IMAP_CODICE FIXED -43419 + IMAP_CODICE_LO_APERTURE_20 IMAP_CODICE FIXED -43420 + IMAP_CODICE_LO_APERTURE_21 IMAP_CODICE FIXED -43421 + IMAP_CODICE_LO_APERTURE_22 IMAP_CODICE FIXED -43422 + IMAP_CODICE_LO_APERTURE_23 IMAP_CODICE FIXED -43423 + IMAP_CODICE_LO_APERTURE_24 IMAP_CODICE FIXED -43424 + IMAP_CODICE_HI_APERTURE_01 IMAP_CODICE FIXED -43425 + IMAP_CODICE_HI_APERTURE_02 IMAP_CODICE FIXED -43426 + IMAP_CODICE_HI_APERTURE_03 IMAP_CODICE FIXED -43427 + IMAP_CODICE_HI_APERTURE_04 IMAP_CODICE FIXED -43428 + IMAP_CODICE_HI_APERTURE_05 IMAP_CODICE FIXED -43429 + IMAP_CODICE_HI_APERTURE_06 IMAP_CODICE FIXED -43430 + IMAP_CODICE_HI_APERTURE_07 IMAP_CODICE FIXED -43431 + IMAP_CODICE_HI_APERTURE_08 IMAP_CODICE FIXED -43432 + IMAP_CODICE_HI_APERTURE_09 IMAP_CODICE FIXED -43433 + IMAP_CODICE_HI_APERTURE_10 IMAP_CODICE FIXED -43434 + IMAP_CODICE_HI_APERTURE_11 IMAP_CODICE FIXED -43435 + IMAP_CODICE_HI_APERTURE_12 IMAP_CODICE FIXED -43436 + + HIT (500-699) + -------------------------- + IMAP_HIT IMAP_SPACECRAFT FIXED -43500 + IMAP_HIT_L1_APERTURE_01 IMAP_HIT FIXED -43501 + IMAP_HIT_L1_APERTURE_02 IMAP_HIT FIXED -43502 + IMAP_HIT_L1_APERTURE_03 IMAP_HIT FIXED -43503 + IMAP_HIT_L1_APERTURE_04 IMAP_HIT FIXED -43504 + IMAP_HIT_L1_APERTURE_05 IMAP_HIT FIXED -43505 + IMAP_HIT_L1_APERTURE_06 IMAP_HIT FIXED -43506 + IMAP_HIT_L1_APERTURE_07 IMAP_HIT FIXED -43507 + IMAP_HIT_L1_APERTURE_08 IMAP_HIT FIXED -43508 + IMAP_HIT_L1_APERTURE_09 IMAP_HIT FIXED -43509 + IMAP_HIT_L1_APERTURE_10 IMAP_HIT FIXED -43510 + + IDEX (700-749) + -------------------------- + IMAP_IDEX IMAP_SPACECRAFT FIXED -43700 + IMAP_IDEX_DETECTOR IMAP_IDEX FIXED -43701 + IMAP_IDEX_FULL_SCIENCE IMAP_IDEX FIXED -43702 + + GLOWS (750-799) + -------------------------- + IMAP_GLOWS_BASE IMAP_SPACECRAFT FIXED -43750 + IMAP_GLOWS IMAP_GLOWS_BASE FIXED -43751 + + +IMAP Frame Tree +======================================================================== + + The diagram below illustrates the IMAP frame hierarchy: + + J2000 + | + |<---ck + | + IMAP_SPACECRAFT + | + IMAP_THRUSTER_A1 + | + |... + | + IMAP_THRUSTER_A4 + | + IMAP_THRUSTER_R1 + | + |... + | + IMAP_THRUSTER_R8 + | + IMAP_SUN_SENSOR_PZ + | + IMAP_SUN_SENSOR_MZ + | + IMAP_STAR_TRACKER_PX + | + IMAP_STAR_TRACKER_MX + | + IMAP_LOW_GAIN_ANTENNA + | + IMAP_MED_GAIN_ANTENNA + | + IMAP_LO_BASE + | | + | |<---ck + | | + | IMAP_LO + | | + | IMAP_LO_STAR_SENSOR + | + IMAP_HI_45 + | + IMAP_HI_90 + | + IMAP_ULTRA_45 + | + IMAP_ULTRA_90 + | + IMAP_MAG_BOOM + | | + | IMAP_MAP_I + | | + | IMAP_MAP_O + | + IMAP_SWE + | | + | IMAP_SWE_DETECTOR_P63 + | | + | IMAP_SWE_DETECTOR_P42 + | | + | IMAP_SWE_DETECTOR_P21 + | | + | IMAP_SWE_DETECTOR_000 + | | + | IMAP_SWE_DETECTOR_M21 + | | + | IMAP_SWE_DETECTOR_M42 + | | + | IMAP_SWE_DETECTOR_M63 + | + IMAP_SWAPI + | | + | IMAP_SWAPI_APERTURE_L + | | + | IMAP_SWAPI_APERTURE_R + | | + | IMAP_SWAPI_SUNGLASSES + | + IMAP_CODICE + | | + | IMAP_CODICE_LO_APERTURE_01 + | | + | |... + | | + | IMAP_CODICE_LO_APERTURE_24 + | | + | IMAP_CODICE_HI_APERTURE_01 + | | + | |... + | | + | IMAP_CODICE_HI_APERTURE_12 + | + IMAP_HIT + | | + | IMAP_HIT_L1_APERTURE_01 + | | + | |... + | | + | IMAP_HIT_L1_APERTURE_10 + | + IMAP_IDEX + | | + | IMAP_IDEX_DETECTOR + | | + | IMAP_IDEX_FULL_SCIENCE + | + IMAP_GLOWS_BASE + | + IMAP_GLOWS + +IMAP Spacecraft Frame +======================================================================== + + \begindata + + FRAME_IMAP_SPACECRAFT = -43000 + FRAME_-43000_NAME = 'IMAP_SPACECRAFT' + FRAME_-43000_CLASS = 3 + FRAME_-43000_CLASS_ID = -43000 + FRAME_-43000_CENTER = -43 + CK_-43000_SCLK = -43 + CK_-43000_SPK = -43 + + \begintext + + + The orientation of the spacecraft body frame with respect to an + inertial frame, J2000 for IMAP, is provided by a C-kernel (see [3] + for details). + + The spacecraft coordinate frames are defined by the IMAP control + documents (see [4,5], NB, figure 2.2). There are two frames described + there: Observatory Mechanical Design Reference Frame (most relevant) + and Observatory Pointing and Dynamics Reference Frame (less relevant + for this frame kernel). + + + Observatory Mechanical Design Reference Frame (IMAP_SPACECRAFT) + --------------------------------------------------------------------- + + If not explicitly stated, references to 'spacecraft mechanical frame' + 'spacecraft frame', or 'S/C frame' will refer to this frame. + + All instruments and component placements and orientations are defined + using this coordinate frame reference. + + Origin: Center of the launch vehicle adapter ring at the + observatory/launch vehicle interface plane + + +Z axis: Perpendicular to the launch vehicle interface plane pointed + in the direction of the top deck (runs through the center + of the central cylinder structure element) + + +Y axis: Direction of the vector orthogonal to the +Z axis and + parallel to the deployed MAG boom + + +X axis: The third orthogonal axis defined using an X, Y, Z ordered + right hand rule + + NB: The Observatory Pointing and Dynamics Reference Frame is also + defined in [5]. It is identical to the observatory mechanical design + reference frame, but with the origin translated to the observatory + center of mass (which changes with boom deployment and fuel usage). + The offset difference between the mechanical and dynamic frame is + within the uncertainty range of the ephemeris, so the mechanical + design frame is used here for definiteness. + + Three different views [5,6] of the spacecraft with labeled components + are presented below for illustrative purposes. + + + IMAP -Z Bottom View (Figure 3-2 in [5], G-G in [6] rotated 180Β°) + --------------------------------------------------------------------- + --------- + | +X axis | -------------------- + --------- | +Z axis facing Sun | + . | into page | + /|\ -------------------- + | + | + | + _ + HI 45 /`~~__HI 90 `+ direction of + , = .^ - /_ ``-. '. positive + .+ + `^~/ ./ ~ rotation + ^ + + . -- ' `` \ _-~ \ + _ / ',= ' \~'` \ IMAP \ + ULTRA /' '-_ .~ ' \,.=.. \ LO \|/ + 90 / ~ _,.,_ + + \ ' + / ,~' +' `'+ + + \ + / ~^ .' , = .'. '- ='' -`` --------- + ^/ / , = . + + \ \~'` | +Y axis |-----> + | . + + + + . \ --------- ___ + | | + + ' = ' | \--------------------| | + SWAPI| | ' = ', - . | /--------------------|___| + _+_: ' + + ' / MAG boom + \_ __\__ \ + + / /^*~, + + | SWE '. ' = ' .' ULTRA / + `~-' '~..,___,..~' 45 /~,* + _\ / /~,*` + * / CODICE ^*._/ *` HIT + *\ _/`. / + * / /~ _ _ ,.-^-., _ _ _ / + '=' + + + GLOWS + + + '-.,.-' + IDEX + + + IMAP +X Side View (F-F in [6]) + --------------------------------------------------------------------- + --------- + | +Z axis | + --------- --------------------- + . | +X axis out of page | + /|\ --------------------- + | LGA + __________________|______|^|_________ ___ + SWAPI|__________________|__________________|====================| | + #|-| | | .-==-, | / MAG boom '---' + #|-| {|## | | / \ | | + | {|## | |{ HI 90 }| IMAP LO| + | {|## | _.._ | \ / | _., | + | ULTRA | / \ | `-==-' | / __`',| + | 90 | \ HI 45/ | | \ \_\ ;| + | | '----` | | ~._ + | + '-------------------|----------/--------' + | | \_________O_________/ | | ----------------> + |__| ----------- /_\ --------- + STAR | S/C FRAME | MGA | +Y axis | + TRACKERS | ORIGIN | --------- + ----------- + + + IMAP -X Side View (C-C in [6]) + --------------------------------------------------------------------- + --------- + | +Z axis | + ------------------- --------- + | +X axis into page | . + ------------------- /|\ + LGA | + ___ _________|^|______|__________________ + | |====================|__________________|_____________ __ _|SWAPI + '---' MAG boom \ __ | | | // \ /--|# + |( )=|__|| | | \\__/ \--|# + | HIT | _|_ IDEX | CODICE | + | | ,.' | '., | | + | ____ | [ \ | / ] | SWE| + ULTRA ##',', |,.'|'.,| GLOWS (#)| + 45 ####'. + | + \\(O) |-|| + '----####/----- + | + --------------' + <---------------- | | \______'-.O.-'______/ | | + --------- /_\ ----------- |__| + | +Y axis | MGA | S/C FRAME | STAR + --------- | ORIGIN | TRACKERS + ----------- + + + IMAP Component Location - Azimuth and Elevation + --------------------------------------------------------------------- + + Payload and subsystem component locations are specified[5,6] in the + Observatory Mechanical Design Reference Frame (described above). + Locations are defined in azimuth and elevation (and resultant + direction cosign matrices) of these angles[6] in the same reference + frame. The azimuth and elevation angle diagram is provided below. + + In general, descriptions in this kernel treat the +Z direction as + "up" and the -Z direction as "down." Locations referred to as "above" + are generally closer to the Sun, and vice versa for "below." The + "upper" side of the spacecraft is the plane of the solar panels, + while the "lower" side may refer to the area near the adapter ring. + If ambiguity could arise, more thorough descriptions will be used. + + + Toward Sun + + +Z axis + . + | + . + | + . Component + | Location/ + . Orientation + | @ + Toward . .'| + MAG | +` | + .~ '` Boom S/C . .` \ | + .~ '` FRAME |.` : | + / ~'` ORIGIN O | | + *--- .~ '` \ Elevation + .~ '` \ | | + .~ '` \ ; |~ + .~ '\ \ / | ^~ + +Y axis \ \ + | ^~ + '. '~, \ | ^~ + '~ Azimuth \ | ^~ + '~. `^~-> \| -X axis + ' ~ ., _ _ ,.~ + ``'`` + + + IMAP Component Orientation - Azimuth and Elevation + --------------------------------------------------------------------- + + In addition to the rotation matrices, azimuth and elevation are used + to specify look direction (i.e., boresight) of the science payload + components and thrusters. However, these two angles are not adequate + to specify the complete orientation of the components--a secondary + axis must be specified to complete the rotation. + + The look direction, D, in the frame of the spacecraft for azimuth, az + and elevation, el, is: + + D = [ -cos(el) x sin(az), cos(el) x cos(az), sin(el) ] + + For all practical purposes, the look direction (primary axis) + corresponds to one of the six axis-aligned directions of the local + coordinate system of the instrument: X', Y', Z', -X', -Y', -Z'. While + the azimuth/elevation of the instrument look direction is provided in + the spacecraft MICD[4], the local coordinate axis in which it + corresponds is provided in the instrument's MICD. + + The secondary axis, S, must be perpendicular to D for the following + discussion. It will generally be specified in one of two ways: + + 1) S is one of the six axis-aligned directions of the + spacecraft coordinate system: X, Y, Z, -X, -Y, -Z + + 2) S lies in the plane perpendicular to one of the axes of the + spacecraft coordinate system: X, Y, Z, -X, -Y, -Z + + Similar to the look direction, this direction will then be assigned + to correspond to one of the six instrument directions X', Y', Z', + -X', -Y', -Z'. + + For definiteness, it is assumed that the third axes, N = D x S, + completes the righthanded coordinate system. + + The rotation matrix specifying the component frame, X'Y'Z', in the + spacecraft frame, XYZ, is: + + Ux Uy Uz + + [ X ] [ R11 R12 R13 ] [ X'] + [ ] [ ] [ ] + [ Y ] = [ R21 R22 R23 ] [ Y'] + [ ] [ ] [ ] + [ Z ] [ R31 R32 R33 ] [ Z'] + + with Ux, Uy, Uz specifying the unit column vectors of the rotation. + Because the primary and secondary axes, D and S, lie along the local + axes of the instrument coordinate system (X'Y'Z'), they are simply + the column vectors of the rotation matrix (assuming properly unit). + + + IMAP Component Orientation - Euler Angles + --------------------------------------------------------------------- + + When the orientation is not specified in azimuth/elevation, or the + secondary is not well-defined, we try to deduce the most straight- + forward definition using a simple secondary axis. Sometimes a + single axis-aligned rotation applied BEFORE the general rotation + allows a simple secondary axis to notionally be used to accurately + define the coordinates; see Hi 45 or Hi 90 for this case. + + It is also possible to deduce the Euler angles to produce more + precise rotation matrices. For most components, before final + alignments are calculated, these angles are in whole degrees. + (However, see Hi 45 for a counterexample). + + The spacecraft subsystems such as the star trackers have complete + rotation matrices that fully define the orientation of each + component. These matrices, while complete, are not conducive to + visualizing the orientation of a component on the spacecraft bus. + + As it happens, when applied to rotations, the azimuth and elevation + are nearly identitical to the first two Euler angles of the ZXZ + intrinsic rotation. For the Euler angles (A, B, Y), this is defined + as follows[11]. + + Let xyz represent the coordinate axes of the fixed frame, and XYZ + are the axes of the fully rotated frame expressed in the xyz frame. + Three successive, ordered rotations about the axes are performed: + + 1) Righthanded rotation about z by the angle A ∈ [-Ο€, Ο€); the rotated + frame is defined x'y'z', with z' = z. The new frame x'y'z' is + expressed in the coordinates of the original frame xyz. + + 2) Righthanded rotation about x' by the angle B ∈ [0,Ο€]; the rotated + frame is defined x"y"z", with x" = x'. The new frame x"y"z" is + expressed in the coordinates of the original frame xyz. + + 3) Righthanded rotation about z" by the angle Y ∈ [-Ο€,Ο€); the rotated + frame is defined XYZ, with Z = z". The final frame XYZ is + expressed in the coordinates of the original frame xyz. + + + Euler Angles + Intrinsic ZXZ Rotation + + z axis + . + | Y axis + _._. / + , B ` | / + Z axis ,-` . / + ^, ^ | / + ^, . / + ^, | / + ^, . / + ^, | / _ X axis + ^, . / _ ~ ^ + ^, |/ _ ~ ^ ^ + .~ ~ ^ | + .~ '` \ ^~ ; + .~ '` \ \ ^~ ; + .~ '` ', \ ^~ , + .~ '` ` A \ ^ Y + x axis `^~-> \ , ~ + \ ~` ^~ + \- ^ ^~ + \ y axis + \ + x'=x" axis + + + Comparing the two figures, we see that A = azimuth and B appears to + coincide with elevation. However, while B lies on the range [0,Ο€], + conventionally, elevation ∈ [-Ο€/2,Ο€/2]. This range for elevation does + not capture all possible orientations, e.g., a playing card facing + upward cannot be placed facing downward with elevation ∈ [-Ο€/2,Ο€/2]. + + So, we need to supplement the azimuth and elevation nomenclature with + fully specified Euler angles. + + The technical documents [4,5,6] give rotation matrix elements to six + decimal places, which is not sufficient for accurate pointing in the + SPICE toolkit. The remedy to this inaccuracy is provided below. + + Given an insufficiently-accurate rotation matrix, M, with column + vectors Vx, Vy, Vz: + + Vx Vy Vz + + [ M11 M12 M13 ] + [ ] + M = [ M21 M22 M23 ] + [ ] + [ M31 M32 M33 ] + + A rotation matrix, R, with column unit vectors Ux, Uy, Uz: + + Ux Uy Uz + + [ R11 R12 R13 ] + [ ] + R = [ R21 R22 R23 ] + [ ] + [ R31 R32 R33 ] + + is calculated so that column vectors are orthonormal to within double + precision accuracy (an operation SPICE calls "sharpening"): + + Uz = Vz / |Vz| + + Uy = Uz x (Vx / |Vx|) + + Ux = Uy x Uz + + These calculations are done outside of the SPICE library, but using + numerically stable algorithms as SPICE does. Sharpening by starting + with the X or Y direction, as opposed to Z, can be accomplished by + cyclically permuting x,y,z above. SPICE, for example, starts with X. + + With a precise (though not necessarily accurate) rotation matrix, + the instrinsic ZXZ Euler angles (A, B, Y) are calculated: + + A' = atan2(R13, -R23) + ______________ + B' = atan2(\/ 1 - R33 x R33 , R33) + + Y' = atan2(R31, R32) + + These values are rounded to regain the assumed original orientation: + + A = round(A') to nearest 1/1000th degree + + B = round(B') to nearest 1/1000th degree + + Y = round(Y') to nearest 1/1000th degree + + And finally, the rotation matrix elements are recalculated: + + R11 = c1 x c3 - s1 x c2 x s3 + + R21 = s1 x c3 + c1 x c2 x s3 + + R31 = s2 x s3 + + R12 = -c1 x s3 - s1 x c2 x c3 + + R22 = -s1 x s3 + c1 x c2 x c3 + + R32 = s2 x c3 + + R13 = s1 x s2 + + R23 = -c1 x s2 + + R33 = c2 + + where: + + c1 = cos(A) + + s1 = sin(A) + + c2 = cos(B) + + s2 = sin(B) + + c3 = cos(Y) + + s3 = sin(Y) + + When B = 0, the angles A and Y are degenerate; Y = 0 in this case. + + In the subsequent frames defined below, when Euler angles (A, B, Y) + are referenced without further discussion, they will refer to the + Euler angles as defined here. Otherwise, definitions will be given + inline with the discussion. + + + When Look Direction is Well-Defined + --------------------------------------------------------------------- + + When the look direction is well-defined, but the secondary axis is + not, we replace the column of the imprecise rotation matrix with + the exact look direction, and proceed with the calculations above. + + +IMAP Thruster Frames +======================================================================== + + There are four axial (A) thrusters and eight radial (R) thrusters on + IMAP[6]. The table below shows the thruster positions defined in the + spacecraft frame[6], at the intersection of the thrust axis and the + nozzle exit plane. The unit direction vectors listed in the table + below point in the direction of the thruster exhaust. The positional + information may be captured in the IMAP structure SPK, while the + orientation information is captured here. + + + Thruster ID X (mm) Y (mm) Z (mm) UnitDir (X,Y,Z) + ---------------- ------ -------- -------- ------- --------------- + IMAP_THRUSTER_A1 -43010 1007.28 516.50 1312.40 ( 0, 0, 1 ) + IMAP_THRUSTER_A2 -43011 -1007.28 -516.50 1312.40 ( 0, 0, 1 ) + IMAP_THRUSTER_A3 -43012 -1007.28 -516.50 101.77 ( 0, 0, -1 ) + IMAP_THRUSTER_A4 -43013 1007.28 516.50 101.77 ( 0, 0, -1 ) + IMAP_THRUSTER_R1 -43020 -126.90 1237.78 841.12 (-0.5, 0.866,0) + IMAP_THRUSTER_R2 -43021 126.90 -1237.78 841.12 ( 0.5,-0.866,0) + IMAP_THRUSTER_R3 -43022 -1008.49 728.79 841.12 (-0.5, 0.866,0) + IMAP_THRUSTER_R4 -43023 1008.49 -728.79 841.12 ( 0.5,-0.866,0) + IMAP_THRUSTER_R5 -43024 -126.90 1237.78 447.42 (-0.5, 0.866,0) + IMAP_THRUSTER_R6 -43025 126.90 -1237.78 447.42 ( 0.5,-0.866,0) + IMAP_THRUSTER_R7 -43026 -1008.49 728.79 447.42 (-0.5, 0.866,0) + IMAP_THRUSTER_R8 -43027 1008.49 -728.79 447.42 ( 0.5,-0.866,0) + + + Thruster Locations and Directions + --------------------------------------------------------------------- + + The four axial thrusters[6] are directed along the spacecraft Z axis, + with A1,A2 located on the +Z side of the spacecraft and A3,A4 located + on the -Z side. A1,A2 fire in the +Z direction, while A3,A4 fire in + the -Z direction. A1 and A4 are aligned in the Z direction, while + A2 and A3 are aligned but on the opposite side of the S/C as A1/A4. + + The eight radial thrusters[6] are grouped into four pairs (R1/R5, + R2/R6, R3/R7, R4/R8); each pair is aligned along the Z direction and + fire in the same direction. There are two distinct firing directions, + all perpendicular to the spacecraft Z axis: R1/R5 & R3/R7 fire toward + the +Y direction (with a slight -X component), while R2/R6 & R4/R8 + fire in the -Y direction (with a slight +X component). Thrusters + R1-R4 are located above the center of mass (towards the Sun), while + thrusters R5-R8 are located below the center of mass (away from the + Sun). The table below shows the azimuth of location and direction of + radial thrusters calculated from using thruster table above. + + + Location Azim Direction Azim + -------------- -------------- + R1/R5 5.85Β° 30.0Β° + R2/R6 180Β° + 5.85Β° 180Β° + 30.0Β° + R3/R7 54.15Β° 30.0Β° + R4/R8 180Β° + 54.15Β° 180Β° + 30.0Β° + + + +X axis +Z axis facing Sun + . into page + /|\ + | + | + | A1 (on +Z side) + A4 (on -Z side) + R4/R8 Dir /`~~__ / + '~._ , = .^ - /_ ``-. / + /~._ .+ + `^~/ .\/ + 30Β°| '~. + . -- ' `` @\ _-~ + - - + - - - -# R4/R8 \~'` \ + /' '-_ . \,.=.. \ + / ~ _,.,_ + + \ + R2/R6 Dir / ,~' +' `'+ + + \ + '~._ / ~^ .' , = .'. '- ='' -`` + /~._ ^/ / , = . + + \ \~'` + 30Β°| '~. | . + + + + . \ +Y axis -----> + - - + - - - -|# R2/R6 | + + ' = ' | \ + | | ' = ', - . | R1/R5 #._- - - - - + - - + _+_: ' + + ' / '~._ | + \_ __\__ \ + + / /^*~, '~._ / 30Β° + + | \ '. ' = ' .' / / '~. + `~-' '~..,___,..~' / /~,* R1/R5 Dir + _\ / /~,*` + * / \ ^*._/ *` + *\ _/`. R3/R7 #/._- - - - - + - - + * / /\@_ _ ,.-^-., _ _ _ / '~._ | + '=' | + + '~._ / 30Β° + | + + '~. + | '-.,.-' R3/R7 Dir + | + A2 (on +Z side) + A3 (on -Z side) + + + Axial Thruster Frames + --------------------------------------------------------------------- + + Each axial thruster has a frame defined so that the thruster exhaust + exits in the +Z' direction. The +Y' axis is chosen to lie in the + direction of the MAG boom. X' = Y' x Z' completes the frame. + + [X] [ 1 0 0 ] [X'] + [Y] = [ 0 1 0 ] [Y'] + [Z]S/C [ 0 0 1 ] [Z']Axial Thrusters A1,A2 + + [X] [ -1 0 0 ] [X'] + [Y] = [ 0 1 0 ] [Y'] + [Z]S/C [ 0 0 -1 ] [Z']Axial Thrusters A3,A4 + + + Axial Thruster + Exhaust Direction + + +Z' axis + | + | + _. -|- ._ + ,' | ', + , | , + | -.,_|_,.- | + ' ' + ' ' + ; ; + ; ; + : ; + , , Toward + ',_,' ^~ MAG + .~ '` ^~ ^~ Boom + .~ '` ^~ ^~ + .~ '` ^~ ^~ + .~ '` ^~ ^~ \ + +X' axis ^~ --* + ^~ + ^~ + +Y' axis + + + \begindata + + FRAME_IMAP_THRUSTER_A1 = -43010 + FRAME_-43010_NAME = 'IMAP_THRUSTER_A1' + FRAME_-43010_CLASS = 4 + FRAME_-43010_CLASS_ID = -43010 + FRAME_-43010_CENTER = -43 + TKFRAME_-43010_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43010_SPEC = 'MATRIX' + TKFRAME_-43010_MATRIX = ( 1, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 1 ) + + FRAME_IMAP_THRUSTER_A2 = -43011 + FRAME_-43011_NAME = 'IMAP_THRUSTER_A2' + FRAME_-43011_CLASS = 4 + FRAME_-43011_CLASS_ID = -43011 + FRAME_-43011_CENTER = -43 + TKFRAME_-43011_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43011_SPEC = 'MATRIX' + TKFRAME_-43011_MATRIX = ( 1, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 1 ) + + FRAME_IMAP_THRUSTER_A3 = -43012 + FRAME_-43012_NAME = 'IMAP_THRUSTER_A3' + FRAME_-43012_CLASS = 4 + FRAME_-43012_CLASS_ID = -43012 + FRAME_-43012_CENTER = -43 + TKFRAME_-43012_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43012_SPEC = 'MATRIX' + TKFRAME_-43012_MATRIX = ( -1, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + -1 ) + + FRAME_IMAP_THRUSTER_A4 = -43013 + FRAME_-43013_NAME = 'IMAP_THRUSTER_A4' + FRAME_-43013_CLASS = 4 + FRAME_-43013_CLASS_ID = -43013 + FRAME_-43013_CENTER = -43 + TKFRAME_-43013_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43013_SPEC = 'MATRIX' + TKFRAME_-43013_MATRIX = ( -1, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + -1 ) + + \begintext + + + Radial Thrusters + --------------------------------------------------------------------- + + Each radial thruster has a frame defined so that the thruster exhaust + exits in the +Y' direction. The +Z' axis is chosen to lie along the + spacecraft +Z axis (toward Sun). X' = Y' x Z' completes the frame. + + [X] [ cos( 30) -sin( 30) 0 ] [X'] + [Y] = [ sin( 30) cos( 30) 0 ] [Y'] + [Z]S/C [ 0 0 1 ] [Z']Rad. Thrusters R1,R3,R5,R7 + + [X] [ cos(210) -sin(210) 0 ] [X'] + [Y] = [ sin(210) cos(210) 0 ] [Y'] + [Z]S/C [ 0 0 1 ] [Z']Rad. Thrusters R2,R4,R6,R8 + + + Toward Sun + + +Z' axis + . + | + . + | + . + | + . + Radial Thruster | + Exhaust Direction . + | + .~ '` . + /.~ '` _,,~ ~ ~ ~ ~ ~ ~ ~ | + *-- .;-. \ ~ + ,' '. ~ ^~ + ; \ ~' ^~ + | .~ '`: ~' ^~ + .~ '` | ~' ^~ + ~ '` \ ; _ ~' ^~ + +Y' axis '.,_._;-' ^~ + ^~ + -X' axis + + + \begindata + + FRAME_IMAP_THRUSTER_R1 = -43020 + FRAME_-43020_NAME = 'IMAP_THRUSTER_R1' + FRAME_-43020_CLASS = 4 + FRAME_-43020_CLASS_ID = -43020 + FRAME_-43020_CENTER = -43 + TKFRAME_-43020_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43020_SPEC = 'MATRIX' + TKFRAME_-43020_MATRIX = ( 0.86602540378443865, + 0.50000000000000000, + 0.00000000000000000, + -0.50000000000000000, + 0.86602540378443865, + 0.00000000000000000, + 0.00000000000000000, + 0.00000000000000000, + 1.00000000000000000 ) + + FRAME_IMAP_THRUSTER_R2 = -43021 + FRAME_-43021_NAME = 'IMAP_THRUSTER_R1' + FRAME_-43021_CLASS = 4 + FRAME_-43021_CLASS_ID = -43021 + FRAME_-43021_CENTER = -43 + TKFRAME_-43021_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43021_SPEC = 'MATRIX' + TKFRAME_-43021_MATRIX = ( -0.86602540378443865, + -0.50000000000000000, + 0.00000000000000000, + 0.50000000000000000, + -0.86602540378443865, + 0.00000000000000000, + 0.00000000000000000, + 0.00000000000000000, + 1.00000000000000000 ) + + FRAME_IMAP_THRUSTER_R3 = -43022 + FRAME_-43022_NAME = 'IMAP_THRUSTER_R3' + FRAME_-43022_CLASS = 4 + FRAME_-43022_CLASS_ID = -43022 + FRAME_-43022_CENTER = -43 + TKFRAME_-43022_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43022_SPEC = 'MATRIX' + TKFRAME_-43022_MATRIX = ( 0.86602540378443865, + 0.50000000000000000, + 0.00000000000000000, + -0.50000000000000000, + 0.86602540378443865, + 0.00000000000000000, + 0.00000000000000000, + 0.00000000000000000, + 1.00000000000000000 ) + + FRAME_IMAP_THRUSTER_R4 = -43023 + FRAME_-43023_NAME = 'IMAP_THRUSTER_R4' + FRAME_-43023_CLASS = 4 + FRAME_-43023_CLASS_ID = -43023 + FRAME_-43023_CENTER = -43 + TKFRAME_-43023_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43023_SPEC = 'MATRIX' + TKFRAME_-43023_MATRIX = ( -0.86602540378443865, + -0.50000000000000000, + 0.00000000000000000, + 0.50000000000000000, + -0.86602540378443865, + 0.00000000000000000, + 0.00000000000000000, + 0.00000000000000000, + 1.00000000000000000 ) + + FRAME_IMAP_THRUSTER_R5 = -43024 + FRAME_-43024_NAME = 'IMAP_THRUSTER_R5' + FRAME_-43024_CLASS = 4 + FRAME_-43024_CLASS_ID = -43024 + FRAME_-43024_CENTER = -43 + TKFRAME_-43024_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43024_SPEC = 'MATRIX' + TKFRAME_-43024_MATRIX = ( 0.86602540378443865, + 0.50000000000000000, + 0.00000000000000000, + -0.50000000000000000, + 0.86602540378443865, + 0.00000000000000000, + 0.00000000000000000, + 0.00000000000000000, + 1.00000000000000000 ) + + FRAME_IMAP_THRUSTER_R6 = -43025 + FRAME_-43025_NAME = 'IMAP_THRUSTER_R6' + FRAME_-43025_CLASS = 4 + FRAME_-43025_CLASS_ID = -43025 + FRAME_-43025_CENTER = -43 + TKFRAME_-43025_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43025_SPEC = 'MATRIX' + TKFRAME_-43025_MATRIX = ( -0.86602540378443865, + -0.50000000000000000, + 0.00000000000000000, + 0.50000000000000000, + -0.86602540378443865, + 0.00000000000000000, + 0.00000000000000000, + 0.00000000000000000, + 1.00000000000000000 ) + + FRAME_IMAP_THRUSTER_R7 = -43026 + FRAME_-43026_NAME = 'IMAP_THRUSTER_R7' + FRAME_-43026_CLASS = 4 + FRAME_-43026_CLASS_ID = -43026 + FRAME_-43026_CENTER = -43 + TKFRAME_-43026_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43026_SPEC = 'MATRIX' + TKFRAME_-43026_MATRIX = ( 0.86602540378443865, + 0.50000000000000000, + 0.00000000000000000, + -0.50000000000000000, + 0.86602540378443865, + 0.00000000000000000, + 0.00000000000000000, + 0.00000000000000000, + 1.00000000000000000 ) + + FRAME_IMAP_THRUSTER_R8 = -43027 + FRAME_-43027_NAME = 'IMAP_THRUSTER_R6' + FRAME_-43027_CLASS = 4 + FRAME_-43027_CLASS_ID = -43027 + FRAME_-43027_CENTER = -43 + TKFRAME_-43027_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43027_SPEC = 'MATRIX' + TKFRAME_-43027_MATRIX = ( -0.86602540378443865, + -0.50000000000000000, + 0.00000000000000000, + 0.50000000000000000, + -0.86602540378443865, + 0.00000000000000000, + 0.00000000000000000, + 0.00000000000000000, + 1.00000000000000000 ) + + \begintext + + +IMAP Digital Sun Sensor and Star Tracker Frames +======================================================================== + + There are two digital sun sensors (DSS)[6]: one on the +Z side of the + spacecraft pointing in +Z direction, and one on the -Z side pointing + mostly in the radial direction with a 30Β° tilt in the -Z direction. + They are approximated aligned along the spacecraft Z axis, though the + origins are offset from absolute alignment by a few centimeters (see + table below). Azimuthally, the sun sensors are located near the SWAPI + instrument approximately 18Β° off of the Y-Z plane. + + There are two star trackers mounted adjacent to each other on the + underside of the spacecraft close to the -Z digital star sensor[6]. + Their boresights are generally downward (towards -Z), with an angular + separation of 24Β°. One is angled toward the +X direction, the other + angled towards the -X direction. + + Positional information may be captured in the IMAP structure SPK, + while the orientation information is captured here. + + + Digital Sun Sensor ID X (mm) Y (mm) Z (mm) Loc. Azim + -------------------- ------ -------- -------- -------- --------- + IMAP_SUN_SENSOR_PZ -43030 -364.22 -1121.90 1301.67 162.014Β° + IMAP_SUN_SENSOR_MZ -43031 -379.11 -1167.77 72.89 162.014Β° + + + Digital Star Tracker ID X (mm) Y (mm) Z (mm) Loc. Azim + -------------------- ------ -------- -------- -------- --------- + IMAP_STAR_TRACKER_PX -43040 -45.75 -906.66 159.88 177.111Β° + IMAP_STAR_TRACKER_MX -43041 -188.05 -881.57 142.79 167.959Β° + + + ##################################################################### + # / _- __.----# + # ,' ~` _.~^' # + # / ~` ,~^ # + # ,' +Z axis facing Sun .` .^ +X axis # + # / into page / .^ . # + # | : /_,-----,_ /|\# + # | ~ ~` ^. | # + # | ^ ^ ^_ | # + # | / / , | # + # | , , ; | # + # | ; ; } | # + # | ___ : : ~ ___# + # -Y axis ___| .` `. | | }/ _# + # <------ |===| ;+X Star; | |. ;/ (` # + # | ;Tracker; | |' ; \ (,_# + # | `, ,` | | ', , \___# + # | '---' : : '-.,_____,.-` _,~# + # | _,;@ ; ; ," # + # /| | @*^^'` : : ; # + # /^' { _,;| ,---, ; ; ^ # + # \ *^^'` | .^ ^. ~ ~ { # + # | SWAPI { _, |-X Star| \ \ | # + # \ _,;*^ \ .Tracker. \ * { # + # | *^^'` \ -Z DSS ^.___.^ ^, `~_ \ # + # \ } \ _} ^_ "~_ ^, # + # ^^'"\\ \*^ ^, '-_ ~_ # + # \ (+Z DSS not visible) "~_ " -, '- # + ##################################################################### + + + Digital Sun Sensors (DSS) + --------------------------------------------------------------------- + + Each DSS has a frame defined so that the look-direction is along the + +Z' axis. The digital image rows and columns are aligned with the X' + and Y' axes of the frame. + + + DSS Look Direction + Local Frame + + +Z' axis + | + | + | + | + | + | + .~|'`^~ + .~ '` | ^~ + .~ '` __,=# | ,_ ^~ + .~ '` __,=#^^^ |@ ^%,_ ^~ + ~ ,=#^^^ | ^%,_ ^~ + | ^~ ,.~^~ ^%,_ ^~ + | ^~ ,.~ '` ^~ ^% ,^ + | ,.^~' @ ^~ .~ '` | + ^~.''` ^~ @^~ '` | + .~ '`` ^~ ^~ .~ '` ^~ | + +X' axis ^~ ^~.~ '` ^~.~ '` + ^~ | .~ '` ^~ + ^~ | .~ '` ^~ + ^~ |.~ '` +Y' axis + + + The rotation matrices orienting each DSS on the spacecraft are + given by [6]: + + [X] [ 0.951057 0.309017 0.000000 ] [X'] + [Y] = [ -0.309017 0.951057 0.000000 ] [Y'] + [Z]S/C [ 0.000000 0.000000 1.000000 ] [Z'] +Z DSS + + [X] [ 0.951078 -0.154380 -0.267616 ] [X'] + [Y] = [ -0.308952 -0.475579 -0.823640 ] [Y'] + [Z]S/C [ -0.000116 0.866025 -0.500000 ] [Z'] -Z DSS + + Using the method described in a previous section, the Euler angles + rounded to 1/1000th of a degree are: + + +Z DSS: (A, B, Y) = ( -18.000Β°, 0.000Β°, 0.000Β° ) + + -Z DSS: (A, B, Y) = ( -18.000Β°, 120.000Β°, -0.008Β° ) + + Using the formulas described in the Euler angles section above, the + rotation matrices have been recalculated to double precision. + + + \begindata + + FRAME_IMAP_SUN_SENSOR_PZ = -43030 + FRAME_-43030_NAME = 'IMAP_SUN_SENSOR_PZ' + FRAME_-43030_CLASS = 4 + FRAME_-43030_CLASS_ID = -43030 + FRAME_-43030_CENTER = -43 + TKFRAME_-43030_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43030_SPEC = 'MATRIX' + TKFRAME_-43030_MATRIX = ( 0.95105651629515350, + -0.30901699437494734, + 0.00000000000000000, + 0.30901699437494734, + 0.95105651629515350, + 0.00000000000000000, + -0.00000000000000000, + -0.00000000000000000, + 1.00000000000000000 ) + + FRAME_IMAP_SUN_SENSOR_MZ = -43031 + FRAME_-43031_NAME = 'IMAP_SUN_SENSOR_MZ' + FRAME_-43031_CLASS = 4 + FRAME_-43031_CLASS_ID = -43031 + FRAME_-43031_CENTER = -43 + TKFRAME_-43031_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43031_SPEC = 'MATRIX' + TKFRAME_-43031_MATRIX = ( 0.95107808048040110, + -0.30895059509261280, + -0.00012091995722272, + -0.15437570314113858, + -0.47557140042407403, + 0.86602539534263330, + -0.26761656732981740, + -0.82363910354633210, + -0.49999999999999983 ) + + \begintext + + + Star Trackers + --------------------------------------------------------------------- + + Each star tracker has a frame defined so that the look-direction is + along the +Z' axis. The digital image rows and columns are aligned + with the X' and Y' axes of the frame. + + + Star Tracker Look Direction + Local Frame + + +Z' axis + + | + | + | + | + _. -|- ._ + ,' | ', + | .~ '` ^~ ,| + .~ '` ~ .,_ _,.^~' | + .~ '` | ^~ + .~ '` |, ,| ^~ + +X' axis ' -.,_ _,.- ' ^~ + | | ^~ + | | ^~ + | | +Y' axis + '-.,_ _,.-' + + + + When oriented on the spacecraft: + + - The tracker X' axis mostly points towards the spacecraft -X axis + - The tracker Y' axis mostly points towards the spacecraft +Y axis + - The tracker Z' axis mostly points towards the spacecraft -Z axis + + + ##################################################################### + # { { # + # ) ) # + # @ @ # + # { { # + # _,~--~,_ | | # + # ," ", ,-----,' # + # ; ; | | # + # +X Star / \ | | # + # Tracker { __,.- +Y' '-----' # + # | ..-^" |: | | # + # { ; ;} | | # + # {\ ; / } { { # + # {^, : ,^ ; @ @ # + # . ~_ ; _~ ,` | | # + # `, '~--~" ,^ "' | | # + # '"^--,__ ` ' "^ { { # + # `^ +X' `"` ) ) # + # "' ^' | | # + # ^' '~ { { # + # ^, __,,.~*^# ) ) # + # ', _,.~-'^'`__,,.~*^# | | # + # #-*~^'_,.~-'^'` '" { { # + # #-*~^' "^ @ @ # + # '" `"` | | # + # `^ ^` { { # + # "` _,~^^^~-.,'^ ) )# + # ^' _-" _,~--~,_ ".' ( # + # '^/ ," ", \` \ # + # , ; ;', \ # + # |/ \| # + # { __,.- +Y' Spacecraft Axes # + # -X Star | ..-^" | # + # Tracker { ; } +X # + # \ ; / | # + # ^, : ,^ | # + # ~_ ; _~ | # + # '~--~" | # + # ` x-------- +Y # + # +X' +Z into # + # Page # + ##################################################################### + + + The rotation matrices orienting each star tracker on the spacecraft + are given by [6]: + + [X] [ -0.963287 0.173648 0.204753 ] [X'] + [Y] = [ 0.169854 0.984808 -0.036104 ] [Y'] + [Z]S/C [ -0.207912 0.000000 -0.978148 ] [Z']+X Star Tracker + + + [X] [ -0.963287 0.173648 -0.204753 ] [X'] + [Y] = [ 0.169854 0.984808 0.036104 ] [Y'] + [Z]S/C [ 0.207912 0.000000 -0.978148 ] [Z']-X Star Tracker + + Using the method described in a previous section, the Euler angles + rounded to 1/1000th of a degree are: + + +X Star Tracker: (A, B, Y) = ( 80.000Β°, 168.000Β°, -90.000Β° ) + + -X Star Tracker: (A, B, Y) = ( -100.000Β°, 168.000Β°, 90.000Β° ) + + Use the formulas described in the Euler angles section above, the + rotation matrices have been recalculated to double precision. + + + \begindata + + FRAME_IMAP_STAR_TRACKER_PX = -43040 + FRAME_-43040_NAME = 'IMAP_STAR_TRACKER_PX' + FRAME_-43040_CLASS = 4 + FRAME_-43040_CLASS_ID = -43040 + FRAME_-43040_CENTER = -43 + TKFRAME_-43040_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43040_SPEC = 'MATRIX' + TKFRAME_-43040_MATRIX = ( -0.96328734079294150, + 0.16985354835670569, + -0.20791169081775915, + 0.17364817766693050, + 0.98480775301220800, + 0.00000000000000001, + 0.20475304505920630, + -0.03610348622615415, + -0.97814760073380570 ) + + FRAME_IMAP_STAR_TRACKER_MX = -43041 + FRAME_-43041_NAME = 'IMAP_STAR_TRACKER_MX' + FRAME_-43041_CLASS = 4 + FRAME_-43041_CLASS_ID = -43041 + FRAME_-43041_CENTER = -43 + TKFRAME_-43041_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43041_SPEC = 'MATRIX' + TKFRAME_-43041_MATRIX = ( -0.96328734079294150, + 0.16985354835670533, + 0.20791169081775915, + 0.17364817766693014, + 0.98480775301220800, + 0.00000000000000001, + -0.20475304505920630, + 0.03610348622615410, + -0.97814760073380570 ) + + \begintext + + +IMAP Antenna Frames +======================================================================== + + There are two antennas on the spacecraft. The low gain antenna (LGA) + is located on the +Z side of the spacecraft pointing toward +Z, while + the medium gain antenna (MGA) is located on the -Z side pointing in + the -Z direction. + + + --------- + | +Z axis | + ------------------- --------- + | +X axis into page | #-----# . + ------------------- | LGA | /|\ + #-----# | + ___ _________|^|______|__________________ + | |====================|__________________|_____________ __ _|SWAPI + '---' MAG boom \ __ | | | // \ /--|# + |( )=|__|| | | \\__/ \--|# + | HIT | _|_ IDEX | CODICE | + | | ,.' | '., | | + | ____ | [ \ | / ] | SWE| + ULTRA ##',', |,.'|'.,| GLOWS (#)| + 45 ####'. + | + \\(O) |-|| + '----####/----- + | + --------------' + <---------------- | | \______'-.O.-'______/ | | + --------- /_\ ----------- |__| + | +Y axis | #-----# | S/C FRAME | STAR + --------- | MGA | | ORIGIN | TRACKERS + #-----# ----------- + + + ##################################################################### + # .-----------------------------------------------------.# + # |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|# + # | | | | | | | | | | | | | | | | | | |# + # ,, _,~'-----|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|# + # \ \" ' _,~|___ |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|# + # \ \ " | | | | | | SOLAR PANELS | | | | | | |# + # \ \: |--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|# + # \,' |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|# + # HIT | | | | | | | | | | | | | | | |# + # |--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|# + # |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|# + # \ ___ | | | | | | | | | | |# + # THRUSTER R3 --> ,~\ |# #| |--|--|--|--|--|--|--|--|--|--|# + # ^, |# #| |__|__|__|__|__|__|__|__|__|__|# + # ^~---|---| | | | | | | | | | |# + # Spacecraft Axes | '-----------------------------'# + # | ^/~., ,.~\^ # + # +X #-----# { * `"*,_____,*"` * } # + # # LGA # { * | | * } # + # | #-----# \ * | | * / # + # | ~. * | | * .~ # + # | "|~####|####~|" # + # | # + # +Y --------+ IDEX # + # +Z out # + # of page # + ##################################################################### + + + ##################################################################### + # / #####~._ half of ~` _.~^' # + # / #########~._ ULTRA 45 ~` ,~^_ # + # HIT ,###########/ .` .^ ~ # + # (just out / ########/ / .^ ,` # + # of view) , : / , # + # / ~ ~` | # + # , ^ ^ , # + # / / / , # + # , , , , # + # / +Z into __ ; ; - # + # , page .`##`. : : `- . , _ ___# + # |/ +Y ------x ;#**#; | | / _# + # |\ | `.##.` | | ,.----., / (` # + # ' | | | | _~` `~_\ (,_# + # \ | #-----# | | ~ ~\___# + # ' # MGA # : : ,` `, # + # \ +X #-----# ; ;, , # + # ' : :| | # + # \ _.-----. ; ; , # + # '~ '^, ~ ~ , # + # -| IMAP / \ \ \ , # + # ' | LO | ' \ * - # + # | ' ; \ ^, `~_ _,.` # + # | ; :,_ . ^_ "~_ ~ ^ # + # ' ; | ^, '-_ # + # \ - ; "~_ " -, # + ##################################################################### + + + The LGA frame is coincident with the spacecraft XYZ axis, while the + MGA secondary axis is chosen so that Y' coincides with spacecraft Y. + This selection is identical to the axial thrusters A3,A4. + + [X] [ 1 0 0 ] [X'] + [Y] = [ 0 1 0 ] [Y'] + [Z]S/C [ 0 0 1 ] [Z']Low Gain Antenna + + [X] [ -1 0 0 ] [X'] + [Y] = [ 0 1 0 ] [Y'] + [Z]S/C [ 0 0 -1 ] [Z']Medium Gain Antenna + + + \begindata + + FRAME_IMAP_LOW_GAIN_ANTENNA = -43050 + FRAME_-43050_NAME = 'IMAP_LOW_GAIN_ANTENNA' + FRAME_-43050_CLASS = 4 + FRAME_-43050_CLASS_ID = -43050 + FRAME_-43050_CENTER = -43 + TKFRAME_-43050_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43050_SPEC = 'MATRIX' + TKFRAME_-43050_MATRIX = ( 1, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 1 ) + + FRAME_IMAP_MED_GAIN_ANTENNA = -43051 + FRAME_-43051_NAME = 'IMAP_MED_GAIN_ANTENNA' + FRAME_-43051_CLASS = 4 + FRAME_-43051_CLASS_ID = -43051 + FRAME_-43051_CENTER = -43 + TKFRAME_-43051_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43051_SPEC = 'MATRIX' + TKFRAME_-43051_MATRIX = ( -1, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + -1 ) + + \begintext + + +IMAP-Lo Frames +======================================================================== + + IMAP-Lo is a single-pixel energetic neutral atom (ENA) imager mounted + on a pivot platform and equipped with a star sensor that pivots with + the ENA sensor [12,13]. The instrument is mounted for imaging in the + radial direction of the rotating spacecraft with the pivot allowing + orientation of the boresight from a polar angle of 60Β° (slightly + towards the Sun) to 180Β° (directed away from the Sun). + + + --------- + | +Z axis | + --------- --------------------- + . | +X axis out of page | + /|\ --------------------- + | LGA + __________________|______|^|_________ ___ + SWAPI|__________________|__________________|====================| | + #|-| | | .-==-, | / MAG boom '---' + #|-| {|## | | / \ | | + | {|## | |{ HI 90 }| IMAP LO| _. IMAP LO + | {|## | _.._ | \ / | _., | _.-' BORESIGHT + | ULTRA | / \ | `-==-' | / __`'_.-' + | 90 | \ HI 45/ | | \ \.-';| + | | '----` | | ~._.+ | + '-------------------|----------/--------' + | | \_________O_________/ | | ----------------> + |__| ----------- /_\ --------- + STAR | S/C FRAME | MGA | +Y axis | + TRACKERS | ORIGIN | --------- + ----------- + + + IMAP-Lo Local Frame + + Pivot +Z' axis + Angle | + ,.~'^ ^ ^-| + .-'` | + .` _~-, Star Sensor + .` | ** \___ _ | + Boresight | / \_-'`~~~~~~`'-.- - + . |/___ ,^~~~~~~%##### ', '. + `'. ^~~~~~~%%######### ` '. + `'. /~~~~~~, - - ~~~#####\ . + /. ~~~ / `.~~%###, . + .~~~`'./ .~~### . + .~~~~ `'. |~~~%#" .`. + "~~~~%| O :~~~~ ' . . + |~~~ # . /~~~~~ | . \ + |~~~%##`. /~~~~~ / . | + \~~%### ~`- -'~~~~~~ / . . + +,~%######~~~~~~~~ ,- ~@@@~ . + | ' ~ ######%%%%_,^ ,~@@@~ Rotation Axis + '. - .%##%.- .' . ^~. + .~ '` `. .' .` ^~. + .~ '` ' . _ .' .` ^~. + .~ '` ` '.''`` ,.` +X' axis + -Y' axis `-.,,, . ` + + + The local IMAP-Lo base frame is defined so the sensor pivots about + the +X' axis. When the pivot angle is 90Β°, the boresight is aligned + with the local -Y' axis. The +Z' axis, from which the pivot angle is + measured, aligns with the spacecraft +Z axis. + + The boresight look-direction is defined for the azimuth-elevation: + + LO (azim, elev) = ( +330Β°, -90Β° to +30Β° ) + + At 0Β° elevation (90Β° polar angle), the boresight direction and + primary axis in the spacecraft frame of reference is: + + D = -Y' = [ -cos(0) x sin(330), cos(0) x cos(330), sin(0) ] + + The secondary axis is the +X' local axis, perpendicular to both + the boresight direction D and the spacecraft -Z axis: + + S = +X' = D x -Z = Y' x [ 0, 0, 1 ] + + The tertiary axis is: + + N = D x S = Y' x ( Y' x [ 0, 0, 1 ] ) + + The rotation matrix formed using the column vectors is: + + R = [ +S, -D, +N ] + + From the spacecraft MICD[6], the single-precision rotation matrices + orienting IMAP-Lo on the spacecraft: + + [X] [ -0.866025 -0.500000 0.000000 ] [X'] + [Y] = [ 0.500000 -0.866025 0.000000 ] [Y'] + [Z]S/C [ 0.000000 0.000000 1.000000 ] [Z']IMAP-Lo + + consistent with calculating the matrix R to single precision. + + For reference, the ZYZ intrinsic Euler angles orienting X'Y'Z' in + the spacecraft XYZ coordinate system are: + + IMAP-Lo: (A, B, Y) = ( 150.000Β°, 0.000Β°, 0.000Β° ) + + Using the formulas described in the Euler angles section above, the + rotation matrix generated from these Euler angles is consistent with + the rotation matrix using the azimuth/elevation look direction. + + + IMAP-Lo Orientation + --------------------------------------------------------------------- + + The orientation of IMAP-Lo must be specified in a separate C-kernel. + To facilitate this specification, a base frame representing the fixed + transformation of the local X'Y'Z' frame to the spacecraft frame has + been provided. + + Ideally, the C-kernel will simply specify transformation within the + local IMAP-Lo frame, and be generated using only the pivot angle. + The implementation of this is outside the scope of this kernel. + + + \begindata + + FRAME_IMAP_LO_BASE = -43100 + FRAME_-43100_NAME = 'IMAP_LO_BASE' + FRAME_-43100_CLASS = 4 + FRAME_-43100_CLASS_ID = -43100 + FRAME_-43100_CENTER = -43 + TKFRAME_-43100_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43100_SPEC = 'MATRIX' + TKFRAME_-43100_MATRIX = ( -0.86602540378443865, + 0.50000000000000000, + 0.00000000000000000, + -0.50000000000000000, + -0.86602540378443865, + 0.00000000000000000, + 0.00000000000000000, + 0.00000000000000000, + 1.00000000000000000 ) + + FRAME_IMAP_LO = -43101 + FRAME_-43101_NAME = 'IMAP_LO' + FRAME_-43101_CLASS = 3 + FRAME_-43101_CLASS_ID = -43101 + FRAME_-43101_CENTER = -43 + + FRAME_IMAP_LO_STAR_SENSOR = -43102 + FRAME_-43102_NAME = 'IMAP_LO_STAR_SENSOR' + FRAME_-43102_CLASS = 4 + FRAME_-43102_CLASS_ID = -43102 + FRAME_-43102_CENTER = -43 + TKFRAME_-43102_RELATIVE = 'IMAP_LO' + TKFRAME_-43102_SPEC = 'MATRIX' + TKFRAME_-43102_MATRIX = ( 1, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 1 ) + + \begintext + + +IMAP-Hi Frames +======================================================================== + + IMAP-Hi consists of two identical, single-pixel high energy neutral + atom (ENA) imagers. Hi 90 is oriented with its boresight + perpendicular to the spacecraft spin axis, while Hi 45 is radially + outward but with the boresight angled 45Β° from the -Z axis. + + --------- + | +X axis | + --------- -------------------- + . | +Z axis facing Sun | + HI 45 BORESIGHT /|\ | into page | + . | . -------------------- + " .~15Β°~.| .~15Β°~." + \ | / HI 90 BORESIGHT + , | , + ; /`~~__ , `+ direction of + , = .^ - /_ ``-. '. positive + .+ + `^~/ ./ ~ rotation + ^ + + . -- ' `` \ _-~ \ + _ / ',= ' \~'` \ IMAP \ + ULTRA /' '-_ .~ ' \,.=.. \ LO \|/ + 90 / ~ _,.,_ + + \ ' + / ,~' +' `'+ + + \ + / ~^ .' , = .'. '- ='' -`` --------- + ^/ / , = . + + \ \~'` | +Y axis |-----> + | . + + + + . \ --------- ___ + | | + + ' = ' | \--------------------| | + SWAPI| | ' = ', - . | /--------------------|___| + _+_: ' + + ' / MAG boom + \_ __\__ \ + + / /^*~, + + | SWE '. ' = ' .' ULTRA / + `~-' '~..,___,..~' 45 /~,* + _\ / /~,*` + * / CODICE ^*._/ *` HIT + *\ _/`. / + * / /~ _ _ ,.-^-., _ _ _ / + '=' + + + GLOWS + + + '-.,.-' + IDEX + + + --------- + | +Z axis | + --------- --------------------- + . | +X axis out of page | + /|\ --------------------- + | LGA + __________________|______|^|_________ ___ + SWAPI|__________________|__________________|====================| | + #|-| | | .-==-, | / MAG boom '---' + #|-| {|## | | / \ | | + | {|## | |{ HI 90 }| IMAP LO| + | {|## | _.._ | \ / | _., | + | ULTRA | / \ | `-==-' | / __`',| + | 90 | \ HI 45/ | | \ \_\ ;| + | | '----` | | ~._ + | + '-------------------|----------/--------' + | | \_________O_________/ | | ----------------> + |__| ----------- /_\ --------- + STAR | S/C FRAME | MGA | +Y axis | + TRACKERS | ORIGIN | --------- + ----------- + + + ##################################################################### + #______________________________________________ # + # / _ | || | IMAP HI 90 # + #----~. / |_| O o | || |==== hidden # + # ULTRA 90 /\ x x = | || | behind s/c # + # / \__________| || || <---- struct here # + # ##### -- #### | || |] # + # ## % ## / \###\ / ___ || |} HI 90 Boresight # + # /## % ##\--|####| |____|*#*| || |}_________________ # + # |## % ##|--|####| | |*#*| || |} # + # |## % ##| |####| | --- || |} # + # |## % ##|--|####| | || |] +Z # + # |## % ##|--|####| \ || || # + # \## % ##/ |####| | || . | # + # ## % ## \ /###/ | || .'. | # + # ##### -- #### | || . /, | # + #--------------- | |.` _~ x------ +X # + # | ,` ,~` `~ +Y into # + # ______ / .` ~` _ \ page # + # .=.=.=.=. |( ) ()| / ___ * -' ~' `', | # + # | | | | | |( ) ()| |____|*#*|| ~ .`_ _ / ~ # + #__#_#_#_#_#__|______| |*#*||` / //// / ~ # + #----------------| .----- / ` ` ' ~ # + # |_ _ _| | | .'_ / '`.,_ ,~' ~. # + # | | | | | | .' -, | _, ` ":. # + #__/_/_/_/___/___|________|______;_\_ ,.-' |:. # + # | | / ":. # + #_______________________________________| | _45Β° ":. # + #___ ____ __ || || || | |-~" " # + # / / / / // |_____||_____||_____| | HI 45 # + #_/ /___/ /_/ | /|\ \|/ Boresight # + # / ' # + # | --------- # + # / | -Z axis | # + #=========== --------- # + ##################################################################### + + + The local IMAP-Hi frame[15]--identical for both sensors--is defined + with the boresight aligned with the +Y' axis, the rectangular vent + ports aligned with the +Z' axis, and X' = Y' x Z'. + + + IMAP HI 45 + -------------- + + The boresight look-direction is defined for the azimuth-elevation: + + HI 45 (azim, elev) = ( +255Β°, -45Β° ) + + The boresight direction is the +Y' local axis of instrument, and the + primary axis in the spacecraft frame of reference is: + + D = +Y' = [ -cos(-45) x sin(255), cos(-45) x cos(255), sin(-45) ] + + The secondary axis is the +Z' local axis, NOTIONALLY perpendicular to + both the boresight direction D and the spacecraft Z axis: + + S = +Z' = D x Z = Y' x [ 0, 0, 1 ] + + The tertiary axis is NOTIONALLY: + + N = D x S = Y' x ( Y' x [ 0, 0, 1 ] ) + + The rotation matrix formed using the column vectors is NOTIONALLY: + + RN = [ +N, +D, +S ] + + HOWEVER, the actual alignment is modified by a rotation about the + local Y' axis by 3Β° as a consequence of the angular offset of the + mounting inserts by the same amount. This rotation about local Y' is: + + [ cos(3) 0 sin(3) ] + RY' = [ 0 1 0 ] + [ -sin(3) 0 cos(3) ] + + The final rotation that orients HI 45 on the spacecraft is the matrix + multiplication: + + R = RN x RY' + + From the spacecraft MICD[6], the single-precision rotation matrices + orienting IMAP-HI 45 on the spacecraft: + + [X] [ -0.668531 0.683013 -0.294210 ] [X'] + [Y] = [ 0.233315 -0.183013 -0.955024 ] [Y'] + [Z]S/C [ -0.706183 -0.707107 -0.037007 ] [Z']HI 45 + + Using the method described in a Euler discussion section, the Euler + angles rounded to 1/1000th of a degree are: + + HI 45: (A, B, Y) = ( -17.122Β°, 92.121Β°, -135.037Β° ) + + Using the formulas described in the Euler angles section above, the + rotation matrix generated from these Euler angles is consistent with + the rotation matrix using the azimuth/elevation look direction; + however, the full double-precision Euler angles are necessary to + generate the proper precise rotation matrix. + + + \begindata + + FRAME_IMAP_HI_45 = -43150 + FRAME_-43150_NAME = 'IMAP_HI_45' + FRAME_-43150_CLASS = 4 + FRAME_-43150_CLASS_ID = -43150 + FRAME_-43150_CENTER = -43 + TKFRAME_-43150_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43150_SPEC = 'MATRIX' + TKFRAME_-43150_MATRIX = ( -0.66853111450276550, + 0.23331454112339850, + -0.70613771591812640, + 0.68301270189221940, + -0.18301270189221924, + -0.70710678118654750, + -0.29421046547595930, + -0.95502391375634550, + -0.03700710955926802 ) + + \begintext + + + IMAP HI 90 + -------------- + + The boresight look-direction is defined for the azimuth-elevation: + + HI 90 (azim, elev) = ( +285Β°, 0Β° ) + + The boresight direction is the +Y' local axis of instrument, and the + primary axis in the spacecraft frame of reference is: + + D = +Y' = [ -cos(0) x sin(285), cos(0) x cos(285), sin(0) ] + + The secondary axis is the +Z' local axis, NOTIONALLY perpendicular to + both the boresight direction D and the spacecraft Z axis: + + S = -Z' = D x Z = -Y' x [ 0, 0, 1 ] + + The tertiary axis is NOTIONALLY: + + N = D x S = Y' x ( Y' x [ 0, 0, 1 ] ) + + The rotation matrix formed using the column vectors is NOTIONALLY: + + RN = [ +N, +D, +S ] + + HOWEVER, the actual alignment is modified by a rotation about the + local Y' axis by 15Β° as a consequence of the angular offset of the + mounting inserts by the same amount. This rotation about local Y' is: + + [ cos(15) 0 sin(15) ] + RY' = [ 0 1 0 ] + [ -sin(15) 0 cos(15) ] + + The final rotation that orients HI 45 on the spacecraft is the matrix + multiplication: + + R = RN x RY' + + From the spacecraft MICD[6], the single-precision rotation matrices + orienting IMAP-HI 45 on the spacecraft: + + [X] [ 0.066987 0.965926 -0.250000 ] [X'] + [Y] = [ -0.250000 0.258819 0.933013 ] [Y'] + [Z]S/C [ 0.965926 0.000000 0.258819 ] [Z']HI 90 + + Using the method described in a Euler discussion section, the Euler + angles rounded to 1/1000th of a degree are: + + HI 90: (A, B, Y) = ( -165.000Β°, 75.000Β°, 90.000Β° ) + + Using the formulas described in the Euler angles section above, the + rotation matrix generated from these Euler angles is consistent with + the rotation matrix using the azimuth/elevation look direction. + + + \begindata + + FRAME_IMAP_HI_90 = -43151 + FRAME_-43151_NAME = 'IMAP_HI_90' + FRAME_-43151_CLASS = 4 + FRAME_-43151_CLASS_ID = -43151 + FRAME_-43151_CENTER = -43 + TKFRAME_-43151_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43151_SPEC = 'MATRIX' + TKFRAME_-43151_MATRIX = ( 0.06698729810778055, + -0.25000000000000000, + 0.96592582628906829, + 0.96592582628906829, + 0.25881904510252074, + 0.00000000000000000, + -0.25000000000000000, + 0.93301270189221940, + 0.25881904510252074 ) + + \begintext + + +IMAP-Ultra Frames +======================================================================== + + The IMAP-Ultra instrument[7,14] consists of two identical sensors for + imaging the emission of energetic neural atoms (ENAs) produced in the + heliosheath and beyond. Ultra 90 is mounted perpendicular to the IMAP + spin axis (+Z), while Ultra 45 is mounted at 45 degrees from the + anti-sunward spin axis (-Z). + + + --------- + | +X axis | -------------------- + --------- | +Z axis facing Sun | + . | into page | + /|\ -------------------- + | + | + | + _ + HI 45 /`~~__HI 90 `+ direction of + , = .^ - /_ ``-. '. positive + .+ + `^~/ ./ ~ rotation + ULTRA ^ + + . -- ' `` \ _-~ \ + 90 _ / ',= ' \~'` \ IMAP \ + . /' '-_ .~ ' \,.=.. \ LO \|/ + `;. / ~ _,.,_ + + \ ' + / `/ ,~' +' `'+ + + \ + 30Β° / ~^ .' , = .'. '- ='' -`` --------- + | ^/ / , = . + + \ \~'` | +Y axis |-----> + ---- | . + + + + . \ --------- ___ + | | + + ' = ' | \--------------------| | + SWAPI| | ' = ', - . | /--------------------|___| + _+_: ' + + ' / | MAG boom + \_ __\__ \ + + / /^*~, . + + | SWE '. ' = ' .' ULTRA / 33Β° + `~-' '~..,___,..~' 45 / ; + _\ / /`., / + * / CODICE ^*._/ `'./ + *\ _/`. / `'. + * / /~ _ _ ,.-^-., _ _ _ / + '=' + + + GLOWS + + + '-.,.-' + IDEX + + + Each sensor comprises two separate assemblies of collector plates. + Each assembly of collector plates is fanned out in a cylindrical + pattern, and the cyclindrical axes of the fanned-out plates are + parallel and offset in the direction perpendicular to the axes. + + The orientations of Ultra 45 and 90 are analogous to IMAP Hi 45 and + 90; see the diagram for IMAP Hi above. Take special note that the + angle with the spacecraft Z axis and the boresights for IMAP Hi are + the same as the angle with the spacecraft Z axis and the "outward" + directions for Ultra. + + + ##################################################################### + # # + # One half of one IMAP Ultra sensor showing # + # assembly of fanned-out collector plates # + # Outward # + # . Assemblies are mirror-symmetric # + # /|\ about the leftmost edge of drawing # + # | # + # | ,--. , # + # || | | ; , 63.42Β° FOR # + # | | | | ; ; ; 60.31Β° FOV # + # | | | | : ; ; ; ; # + # \|/ | | | : ; ; ; / # + # ' | ;_ _|_ ; ; ; ; / / . # + # S/C | | ``'''^-,/, / / / .' # + # | | ___ `''., / / . . # + #_________;-|__|_ `'"^~-,._ /^~ `^., / ,' ' . # + #---------'- | |_| `'":., _ `^, . ,' .' # + #--------. ,-| | @ `'~/ \ `'. .` .' , # + # ,'`.' | | @ @ @ @ '~,.;, '. .' .' # + # .',' | | @ @ @ @ @ `;, /~_':' .' ,' # + #.'`,' _| |_ @ @ @ `;, / '. .' ,'` # + # `, |_|-|_| @ @ '. '. .' ,. # + #'-,'. |-| @ @ @ ', `.` ;' # + # '.'-. | | @ @ ;, \,;`' .-`# + # `-.'. | | @ @ ", ', ,.'` ,^# + #_________:'-| | @ @ @ @ :, _,\' .-`` # + #-----------||-|-, @ /~,".' ;'.' # + #=== ||---|@ @ @ @ @ ,\ ' ,.^` # + #___________||_/-~_ _ @ @ _, _,-' ,.-'` # + # @| | | || `- , @ @ \,\' ,'` +Z' # + #----' | | || `~,@ @ ,~`' _,'` # + # | | || ',@ .^\_,'` ,.'` | # + #______'-'__||-@--~-~, \ .;` .'` | # + #___________||/ ~ # ~ | {.'` | # + # |* ||*| + <------------ Collector plate +------ +Y'# + #____ --||\ ~ ~ | axis of symmetry +X' out # + #_ *| ||-@-^~-~^-------| of page # + #*| | ||_______________| # + #___*|_______|_|_|__|__|_|_| | # + ##################################################################### + + + The local IMAP-Ultra frame[14]--identical for both sensors--is + defined with the collector-plate-fan axes of symmetry aligned with + the +X' axis, the cylindrical axes offset in the +Y' axis, and the + Z' axis perpendicular to both and outward as in the diagram below. + + + IMAP ULTRA 45 + -------------- + + The outward look-direction is defined for the azimuth-elevation: + + ULTRA 45 (azim, elev) = ( +33Β°, -45Β° ) + + The look-direction is the +Z' local axis of instrument, and the + primary axis in the spacecraft frame of reference is: + + D = +Z' = [ -cos(-45) x sin(33), cos(-45) x cos(33), sin(-45) ] + + The secondary axis is the +X' local axis, lying in the plane spanned + by the look-direction D and the spacecraft Z axis. An equivalent + definition is selecting the secondary axis as the +Y' local axis, + perpendicular to both the look-direction D and the spacecraft Z axis. + + S = +Y' = D x Z = Z' x [ 0, 0, 1 ] + + The tertiary axis is: + + N = D x S = Z' x Y' = Z' x ( Z' x [ 0, 0, 1 ] ) + + The rotation matrix formed using the column vectors is: + + R = [ -N, +S, +D ] + + The rotation matrices orienting the IMAP-Ultra 45 sensor on the + spacecraft is given by [6]: + + [X] [ -0.385118 0.838671 -0.385118 ] [X'] + [Y] = [ 0.593030 0.544639 0.593030 ] [Y'] + [Z]S/C [ 0.707107 0.000000 -0.707107 ] [Z']ULTRA 45 + + Using the method described in a Euler discussion section, the Euler + angles rounded to 1/1000th of a degree are: + + ULTRA 45: (A, B, Y) = ( -147.000Β°, 135.000Β°, 90.000Β° ) + + Using the formulas described in the Euler angles section above, the + rotation matrix generated from these Euler angles is consistent with + the rotation matrix using the azimuth/elevation look direction. + + + \begindata + + FRAME_IMAP_ULTRA_45 = -43200 + FRAME_-43200_NAME = 'IMAP_ULTRA_45' + FRAME_-43200_CLASS = 4 + FRAME_-43200_CLASS_ID = -43200 + FRAME_-43200_CENTER = -43 + TKFRAME_-43200_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43200_SPEC = 'MATRIX' + TKFRAME_-43200_MATRIX = ( -0.38511795495802310, + 0.59302964577578240, + 0.70710678118654760, + 0.83867056794542390, + 0.54463903501502710, + 0.00000000000000000, + -0.38511795495802320, + 0.59302964577578250, + -0.70710678118654750 ) + + \begintext + + + IMAP ULTRA 90 + -------------- + + The outward look-direction is defined for the azimuth-elevation: + + ULTRA 90 (azim, elev) = ( +210Β°, 0Β° ) + + The look-direction is the +Z' local axis of instrument, and the + primary axis in the spacecraft frame of reference is: + + D = +Z' = [ -cos(0) x sin(210), cos(0) x cos(210), sin(0) ] + + The secondary axis is the +X' local axis, lying along spacecraft + -Z axis. + + S = +X' = +Z = [ 0, 0, 1 ] + + The tertiary axis is: + + N = D x S = Z' x X' = Z' x [ 0, 0, 1 ] + + The rotation matrix formed using the column vectors is: + + R = [ +S, +N, +D ] + + The rotation matrices orienting the IMAP-Ultra 90 sensor on the + spacecraft is given by [6]: + + [X] [ 0.000000 -0.866025 0.500000 ] [X'] + [Y] = [ 0.000000 -0.500000 -0.866025 ] [Y'] + [Z]S/C [ 1.000000 0.000000 0.000000 ] [Z']ULTRA 90 + + Using the method described in a Euler discussion section, the Euler + angles rounded to 1/1000th of a degree are: + + ULTRA 90: (A, B, Y) = ( 30.000Β°, 90.000Β°, 90.000Β° ) + + Using the formulas described in the Euler angles section above, the + rotation matrix generated from these Euler angles is consistent with + the rotation matrix using the azimuth/elevation look direction. + + + \begindata + + FRAME_IMAP_ULTRA_90 = -43201 + FRAME_-43201_NAME = 'IMAP_ULTRA_90' + FRAME_-43201_CLASS = 4 + FRAME_-43201_CLASS_ID = -43201 + FRAME_-43201_CENTER = -43 + TKFRAME_-43201_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43201_SPEC = 'MATRIX' + TKFRAME_-43201_MATRIX = ( 0.00000000000000000, + 0.00000000000000000, + 1.00000000000000000, + -0.86602540378443865, + -0.50000000000000000, + 0.00000000000000006, + 0.50000000000000000, + -0.86602540378443865, + 0.00000000000000000 ) + + \begintext + + +IMAP Magnetometer (MAG) Frames +======================================================================== + + The IMAP magnetometer (MAG)[7,16] consists of a pair of identical + triaxial fluxgate magnetometers mounted on a ~2.5 meter boom. MAG-O + is positioned at the end of the boom, while MAG-I is mounted ~0.75 + meters from MAG-O. + + + --------- + | +X axis | -------------------- + --------- | +Z axis facing Sun | + . | into page | + /|\ -------------------- + | + | + | + _ + HI 45 /`~~__HI 90 `+ direction of + , = .^ - /_ ``-. '. positive + .+ + `^~/ ./ ~ rotation + ^ + + . -- ' `` \ _-~ \ + _ / ',= ' \~'` \ IMAP \ + ULTRA /' '-_ .~ ' \,.=.. \ LO \|/ + 90 / ~ _,.,_ + + \ ' + / ,~' +' `'+ + + \ + / ~^ .' , = .'. '- ='' -`` + ^/ / , = . + + \ \~'` +Y axis -----> + | . + + + + . \ ___ ___ + | | + + ' = ' | \------------| |---| | + SWAPI| | ' = ', - . | /------------|___|---|___| + _+_: ' + + ' / MAG-I MAG-O + \_ __\__ \ + + / /^*~, + + | SWE '. ' = ' .' ULTRA / MAGS and boom + `~-' '~..,___,..~' 45 /~,* not to scale + _\ / /~,*` + * / CODICE ^*._/ *` HIT + *\ _/`. / + * / /~ _ _ ,.-^-., _ _ _ / + '=' + + + GLOWS + + + '-.,.-' + IDEX + + + ---------------------------- + S/C +Z axis | Deployed Magnetometer Boom | S/C +X axis + . | (approximately to scale) | out of page + /|\ ---------------------------- + | + | S/C +Y axis --------> + @================================================================= + #\ | | | | + \ `'` `'` + Boom Deployment Hinge MAG-I MAG-O + + +X' ------x +Y' into + | page + MAG Local | + Coord System | + + +Z' + + + Each MAG instrument is contained in a cylindrial casing with the + local Z' axis along the cylindrical axis of symmetry. The local X' + axis is along the boom, and the local Y' axis is perp to the boom. + + When deployed, the boom sticks out in the +Y axis of the spacecraft, + with the MAG +X' axis in the -Y direction. The MAG +Z' axis is in the + spacecraft -Z' direction, and +Y' is spacecraft -X. + + [X] [ 0 -1 0 ] [X'] + [Y] = [ -1 0 0 ] [Y'] + [Z]S/C [ 0 0 -1 ] [Z']MAG deployed + + Prior to deployment, the boom is stowed pointing in the -Y direction + of the spacecraft, with the MAG +X' axis in the +Y direction. The MAG + +Z' axis is in the spacecraft +Z' direction, and +Y' is spacecraft -X + + [X] [ 0 +1 0 ] [X'] + [Y] = [ -1 0 0 ] [Y'] + [Z]S/C [ 0 0 +1 ] [Z']MAG undeployed + + To facilitate possible operations prior to the boom deployment, a + frame for the deployed boom is provided; the MAG-I and MAG-O frames + are provided relative to this frame. If needed, the IMAP_MAG_BOOM + can be modified to facilitate arbitrary operational reality. + + + \begindata + + FRAME_IMAP_MAG_BOOM = -43250 + FRAME_-43250_NAME = 'IMAP_MAG_BOOM' + FRAME_-43250_CLASS = 4 + FRAME_-43250_CLASS_ID = -43250 + FRAME_-43250_CENTER = -43 + TKFRAME_-43250_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43250_SPEC = 'MATRIX' + TKFRAME_-43250_MATRIX = ( 1, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 1 ) + + FRAME_IMAP_MAG_I = -43251 + FRAME_-43251_NAME = 'IMAP_MAG_I' + FRAME_-43251_CLASS = 4 + FRAME_-43251_CLASS_ID = -43251 + FRAME_-43251_CENTER = -43 + TKFRAME_-43251_RELATIVE = 'IMAP_MAG_BOOM' + TKFRAME_-43251_SPEC = 'MATRIX' + TKFRAME_-43251_MATRIX = ( 0, + -1, + 0, + -1, + 0, + 0, + 0, + 0, + -1 ) + + FRAME_IMAP_MAG_O = -43252 + FRAME_-43252_NAME = 'IMAP_MAG_O' + FRAME_-43252_CLASS = 4 + FRAME_-43252_CLASS_ID = -43252 + FRAME_-43252_CENTER = -43 + TKFRAME_-43252_RELATIVE = 'IMAP_MAG_BOOM' + TKFRAME_-43252_SPEC = 'MATRIX' + TKFRAME_-43252_MATRIX = ( 0, + -1, + 0, + -1, + 0, + 0, + 0, + 0, + -1 ) + + \begintext + + +IMAP Solar Wind Electron (SWE) Frames +======================================================================== + + TODO: FIX ME...The orientation of the spacecraft body frame with + respect to an inertial + frame, for IMAP - ECLIPJ2000, is provided by a C-kernel (see [3] + for details). + + This frame specifies the rotating X,Y and pointing Z coordinate body + frame. + + \begindata + + FRAME_IMAP_SWE = -43300 + FRAME_-43300_NAME = 'IMAP_SWE' + FRAME_-43300_CLASS = 4 + FRAME_-43300_CLASS_ID = -43300 + FRAME_-43300_CENTER = -43 + TKFRAME_-43300_SPEC = 'MATRIX' + TKFRAME_-43300_MATRIX = ( 0.453990, + 0.891007, + 0.000000, + -0.891007, + 0.453990, + 0.000000, + 0.000000, + 0.000000, + 1.000000 ) + TKFRAME_-43300_RELATIVE = 'IMAP_SPACECRAFT' + +\begintext + + +IMAP Solar Wind and Pickup Ion (SWAPI) Frames +======================================================================== + + TODO: add diagrams + + SWAPI has the following nominal alignment to the spacecraft frame, + reference Table 1 of [6]. The azimuth and elevation angles are + illustrated in the 'IMAP I&T Component Placement' section near the top + of this document. + + azimuth | elevation + (deg) | (deg) + ---------+--------- + 168 | 0 + + The SWAPI base frame is defined in the instrument MICD [8] as follows: + + * -Z axis is the axis of symmetry of the instrument, pointing + away from the spacecraft body. + * +Y axis is along the aperture center, in the anti-sunward direction. + + The azimuth and elevation give the outward axis of symmetry, -Z in the + instrument frame: + + -Z = -[ -sin(az) * cos(el), cos(az) * cos(el), sin(el) ] + instr + + The instrument +Y axis is in the sunward direction, towards the + spacecraft +Z axis: + + Y = [ 0 0 1 ] + instr + + Taking the cross product and normalizing, we arrive at the instrumet +X + axis: + Y x Z + X = --------- + instr | Y x Z | + + And adjusting Y: + + Z x X + Y = --------- + instr | Z x X | + + This definition is captured in the keywords below. + + \begindata + + FRAME_IMAP_SWAPI = -43350 + FRAME_-43350_NAME = 'IMAP_SWAPI' + FRAME_-43350_CLASS = 4 + FRAME_-43350_CLASS_ID = -43350 + FRAME_-43350_CENTER = -43 + TKFRAME_-43350_SPEC = 'MATRIX' + TKFRAME_-43350_MATRIX = ( -0.97814760073381, + 0.20791169081776, + 0.00000000000000, + 0.00000000000000, + 0.00000000000000, + 1.00000000000000, + 0.20791169081776, + 0.97814760073381, + 0.00000000000000 ) + TKFRAME_-43350_RELATIVE = 'IMAP_SPACECRAFT' + +\begintext + + +IMAP Compact Dual Ion Composition Experiment (CoDICE) Frames +======================================================================== + + TODO: FIX ME...The orientation of the spacecraft body frame with + respect to an inertial + frame, for IMAP - ECLIPJ2000, is provided by a C-kernel (see [3] + for details). + + This frame specifies the rotating X,Y and pointing Z coordinate body + frame. + + \begindata + + FRAME_IMAP_CODICE = -43400 + FRAME_-43400_NAME = 'IMAP_CODICE' + FRAME_-43400_CLASS = 4 + FRAME_-43400_CLASS_ID = -43400 + FRAME_-43400_CENTER = -43 + TKFRAME_-43400_SPEC = 'MATRIX' + TKFRAME_-43400_MATRIX = ( 0.694626, + 0.719371, + 0.000000, + -0.719371, + 0.694626, + 0.000000, + 0.000000, + 0.000000, + 1.000000 ) + TKFRAME_-43400_RELATIVE = 'IMAP_SPACECRAFT' + +\begintext + + +IMAP High-energy Ion Telescope (HIT) Frames +======================================================================== + + TODO: FIX ME...The orientation of the spacecraft body frame with + respect to an inertial + frame, for IMAP - ECLIPJ2000, is provided by a C-kernel (see [3] + for details). + + This frame specifies the rotating X,Y and pointing Z coordinate body + frame. + + \begindata + + FRAME_IMAP_HIT = -43500 + FRAME_-43500_NAME = 'IMAP_HIT' + FRAME_-43500_CLASS = 4 + FRAME_-43500_CLASS_ID = -43500 + FRAME_-43500_CENTER = -43 + TKFRAME_-43500_SPEC = 'MATRIX' + TKFRAME_-43500_MATRIX = ( 0.866025, + 0.500000, + 0.000000, + -0.500000, + 0.866025, + 0.000000, + 0.000000, + 0.000000, + 1.000000 ) + TKFRAME_-43500_RELATIVE = 'IMAP_SPACECRAFT' + +\begintext + + +IMAP Interstellar Dust Experiment (IDEX) Frames +======================================================================== + + TODO: FIX ME...The orientation of the spacecraft body frame with + respect to an inertial + frame, for IMAP - ECLIPJ2000, is provided by a C-kernel (see [3] + for details). + + This frame specifies the rotating X,Y and pointing Z coordinate body + frame. + + \begindata + + FRAME_IMAP_IDEX = -43700 + FRAME_-43700_NAME = 'IMAP_IDEX' + FRAME_-43700_CLASS = 4 + FRAME_-43700_CLASS_ID = -43700 + FRAME_-43700_CENTER = -43 + TKFRAME_-43700_SPEC = 'MATRIX' + TKFRAME_-43700_MATRIX = ( 0.000000, + 1.000000, + 0.000000, + -0.707107, + 0.000000, + -0.707107, + -0.707107, + 0.000000, + 0.707107 ) + TKFRAME_-43700_RELATIVE = 'IMAP_SPACECRAFT' + +\begintext + + +IMAP GLObal solar Wind Structure (GLOWS) Frames +======================================================================== + + TODO: add diagrams + + GLOWS has the following nominal alignment to the spacecraft frame, + reference Table 1 of [6]. The azimuth and elevation angles are + illustrated in the 'IMAP I&T Component Placement' section near the top + of this document. + + azimuth | elevation + (deg) | (deg) + ---------+--------- + 127 | 15 + + The GLOWS base frame is defined by the instrument team as follows [10]: + + * +Z axis points in the anti-boresight direction + * +Y axis points in the anti-sunward direction. + + The azimuth and elevation give the outward axis of symmetry, -Z in the + instrument frame: + + Z = -[ -sin(az) * cos(el), cos(az) * cos(el), sin(el) ] + instr + + The instrument +Y axis is in the anti-sunward direction, towards the + spacecraft -Z axis: + + Y = [ 0 0 -1 ] + instr + + Taking the cross product and normalizing, we arrive at the instrumet +X + axis: + Y x Z + X = --------- + instr | Y x Z | + + And adjusting Y: + + Z x X + Y = --------- + instr | Z x X | + + This definition is captured in the keywords below. + + \begindata + + FRAME_IMAP_GLOWS = -43751 + FRAME_-43751_NAME = 'IMAP_GLOWS' + FRAME_-43751_CLASS = 4 + FRAME_-43751_CLASS_ID = -43751 + FRAME_-43751_CENTER = -43 + TKFRAME_-43751_SPEC = 'MATRIX' + TKFRAME_-43751_MATRIX = ( 0.60181502315205, + -0.79863551004729, + 0.00000000000000, + -0.20670208009540, + -0.15576118962056, + -0.96592582628907, + 0.77142266494622, + 0.58130867351132, + -0.25881904510252 ) + TKFRAME_-43751_RELATIVE = 'IMAP_SPACECRAFT' + +\begintext + + Generic axis + + +Z axis + | + | + | + | + | + | + | + | + | + | + | + | + .~ ~ + .~ '` ^~ + .~ '` ^~ + .~ '` ^~ + .~ '` ^~ + +X axis ^~ + ^~ + ^~ + +Y axis + +End of FK file. \ No newline at end of file diff --git a/imap_processing/tests/spice/test_data/imap_science_100.tf b/imap_processing/ultra/l1c/sim_spice_kernels/imap_science_100.tf similarity index 97% rename from imap_processing/tests/spice/test_data/imap_science_100.tf rename to imap_processing/ultra/l1c/sim_spice_kernels/imap_science_100.tf index 5a83c2283c..b0f16b5043 100644 --- a/imap_processing/tests/spice/test_data/imap_science_100.tf +++ b/imap_processing/ultra/l1c/sim_spice_kernels/imap_science_100.tf @@ -1,1041 +1,1041 @@ -KPL/FK - -Interstellar Mapping and Acceleration Probe (IMAP) Dynamic Frames Kernel -======================================================================== - - This kernel contains SPICE frame definitions to support the - IMAP mission. - - This kernel is composed of primarily dynamic frames, but in general - it holds frame definitions for all instrument-agnostic frames, CK - frames used in science data processing and mapping. - - -Version and Date ------------------------------------------------------------------------- - - The TEXT_KERNEL_ID stores version information of loaded project - text kernels. Each entry associated with the keyword is a string - that consists of four parts: the kernel name, version, entry date, - and type. - - IMAP Dynamic Frame Kernel Version: - - \begindata - - TEXT_KERNEL_ID = 'IMAP_DYNAMIC_FRAMES V0.0.1 2025-JUNE-26 FK' - - \begintext - - Version 0.0.0 -- April 10, 2024 -- Nick Dutton (JHU/APL) - Version 0.0.1 -- June 26, 2025 -- Nick Dutton (JHU/APL) - Version 1.0.0 -- July 8, 2025 -- Nick and Doug (JHU/APL) - - -References ------------------------------------------------------------------------- - - 1. NAIF SPICE `Kernel Pool Required Reading' - - 2. NAIF SPICE `Frames Required Reading' - - 3. "IMAP Coordinate Frame Science.pdf" - - 4. stereo_rtn.tf, at - https://soho.nascom.nasa.gov/solarsoft/stereo/... - ...gen/data/spice/gen/stereo_rtn.tf - - 5. heliospheric.tf, at - https://soho.nascom.nasa.gov/solarsoft/stereo/... - ...gen/data/spice/gen/heliospheric.tf - - 6. "Geophysical Coordinate Transformations", C. T. Russell - - 7. "Heliospheric Coordinate Systems", M. Franz and D. Harper - - 8. "Global observations of the interstellar interaction from the - Interstellar Boundary Explorer (IBEX)", D. J. McComas, et al. - - 9. "Very Local Interstellar Medium Revealed by a Complete Solar - Cycle of Interstellar Neutral Helium Observations with IBEX", - P. Swaczyna, et al. - - 10. Lagrange L1 definition and SPK, Min-Kun Chung, - https://naif.jpl.nasa.gov/pub/naif/... - ...generic_kernels/spk/lagrange_point/ - - -Contact Information ------------------------------------------------------------------------- - - Direct questions, comments, or concerns about the contents of this - kernel to: - - Nick Dutton, JHUAPL, Nicholas.Dutton@jhuapl.edu - - or - - Doug Rodgers, JHUAPL, Douglas.Rodgers@jhuapl.edu - - or - - Lillian Nguyen, JHUAPL, Lillian.Nguyen@jhuapl.edu - - -Implementation Notes ------------------------------------------------------------------------- - - This file is used by the SPICE system as follows: programs that make - use of this frame kernel must `load' the kernel normally during - program initialization. Loading the kernel associates the data items - with their names in a data structure called the `kernel pool'. The - SPICELIB routine FURNSH loads a kernel into the pool as shown below: - - Python: (SpiceyPy) - - spiceypy.furnsh( frame_kernel_name ) - - IDL: (ICY) - - cspice_furnsh, frame_kernel_name - - MATLAB: (MICE) - - cspice_furnsh ( frame_kernel_name ) - - C: (CSPICE) - - furnsh_c ( frame_kernel_name ); - - FORTRAN: (SPICELIB) - - CALL FURNSH ( frame_kernel_name ) - - This file was created, and may be updated with, a text editor or word - processor. - - -IMAP Science Frames -======================================================================== - - This frame kernel defines a series of frames listed in [3] that - support IMAP data reduction and analysis. All of the frame names - assigned an IMAP NAIF ID (beginning with -43) defined by this kernel - are prefixed with 'IMAP_' to avoid conflict with alternative - definitions not specific to the project. - - The project-specific ID codes -43900 to -43999 have been set aside to - support these dynamic frames. - - - Frame Name Relative To Type NAIF ID - ====================== =============== ======== ======= - - IMAP Based Frames: - ---------------------- - IMAP_OMD IMAP_SPACECRAFT FIXED -43900 - IMAP_DPS [n/a] CK -43901 - - Earth Based Frames: - ---------------------- - IMAP_EARTHFIXED IAU_EARTH FIXED -43910 - IMAP_ECLIPDATE J2000 DYNAMIC -43911 - IMAP_MDI ECLIPJ2000 FIXED -43912 - IMAP_MDR J2000 DYNAMIC -43913 - IMAP_GMC IAU_EARTH DYNAMIC -43914 - IMAP_GEI J2000 FIXED -43915 - IMAP_GSE J2000 DYNAMIC -43916 - IMAP_GSM J2000 DYNAMIC -43917 - IMAP_SMD J2000 DYNAMIC -43918 - - Sun Based Frames: - ---------------------- - IMAP_RTN J2000 DYNAMIC -43920 - IMAP_HCI (ie, HGI_J2K) J2000 DYNAMIC -43921 - IMAP_HCD (ie, HGI_D) J2000 DYNAMIC -43922 - IMAP_HGC (ie, HGS_D) IAU_SUN FIXED -43923 - IMAP_HAE ECLIPJ2000 FIXED -43924 - IMAP_HAED IMAP_ECLIPDATE FIXED -43925 - IMAP_HEE J2000 DYNAMIC -43926 - IMAP_HRE J2000 DYNAMIC -43927 - IMAP_HNU J2000 DYNAMIC -43928 - IMAP_GCS GALACTIC FIXED -43929 - - -IMAP Based Frames -======================================================================== - - These dynamic frames are used for analyzing data in a reference - frame tied to the dynamics of IMAP. - - - Observatory Mechanical Design (OMD) Frame ([3]) - --------------------------------------------------------------------- - - Alias for IMAP_SPACECRAFT frame defined in the primary - 'imap_vNNN.tf' frame kernel. From that file: - - Origin: Center of the launch vehicle adapter ring at the - observatory/launch vehicle interface plane - - +Z axis: Perpendicular to the launch vehicle interface plane - pointed in the direction of the top deck (runs through - the center of the central cylinder structure element) - - +Y axis: Direction of the vector orthogonal to the +Z axis and - parallel to the deployed MAG boom - - +X axis: The third orthogonal axis defined using an X, Y, Z - ordered right hand rule - - \begindata - - FRAME_IMAP_EARTHFIXED = -43900 - FRAME_-43900_NAME = 'IMAP_OMD' - FRAME_-43900_CLASS = 4 - FRAME_-43900_CLASS_ID = -43900 - FRAME_-43900_CENTER = -43 - TKFRAME_-43900_RELATIVE = 'IMAP_SPACECRAFT' - TKFRAME_-43900_SPEC = 'MATRIX' - TKFRAME_-43900_MATRIX = ( 1 0 0 - 0 1 0 - 0 0 1 ) - - \begintext - - - Despun Pointing Sets (DPS) Frame ([3]) - --------------------------------------------------------------------- - - Coordinate frame used for ENA imager data processing and - intentionally designed for use in producing all-sky map products. - - This is provided by a CK file external to this file. Notionally, - the frame is defined: - - +Z axis is parallel to the nominal spin axis of the spacecraft. - The axis is notionally a time-average of the spin axis of the - exact orientation (IMAP_SPACECRAFT or IMAP_OMD). - - Y = Z cross Necliptic where Necliptic is the the unit normal - (North) to the ecliptic plane. - - This is a quasi-inertial reference frame and will have a unique - transformation matrix, valid between repointings of the spacecraft - - \begindata - - FRAME_IMAP_DPS = -43901 - FRAME_-43901_NAME = 'IMAP_DPS' - FRAME_-43901_CLASS = 3 - FRAME_-43901_CLASS_ID = -43901 - FRAME_-43901_CENTER = -43 - CK_-43901_SCLK = -43 - CK_-43901_SPK = -43 - - \begintext - - -Earth Based Frames -======================================================================== - - These dynamic frames are used for analyzing data in a reference - frame tied to the dynamics of Earth. - - - Earth-Fixed Frame (IMAP_EARTHFIXED) - --------------------------------------------------------------------- - - Some of these Earth based dynamic frames reference vectors in an - Earth-fixed frame. To support loading of either rotation model - (IAU_EARTH or ITRF93), the following keywords control which model - is used. The model is enabled by surrounding its keyword-value - block with the \begindata and \begintext markers (currently - IAU_EARTH). - - IAU_EARTH based model is currently employed: - - \begindata - - FRAME_IMAP_EARTHFIXED = -43910 - FRAME_-43910_NAME = 'IMAP_EARTHFIXED' - FRAME_-43910_CLASS = 4 - FRAME_-43910_CLASS_ID = -43910 - FRAME_-43910_CENTER = 399 - TKFRAME_-43910_RELATIVE = 'IAU_EARTH' - TKFRAME_-43910_SPEC = 'MATRIX' - TKFRAME_-43910_MATRIX = ( 1 0 0 - 0 1 0 - 0 0 1 ) - - \begintext - - Alternately, the more precise ITRF93-based model could be used: - - FRAME_IMAP_EARTHFIXED = -43910 - FRAME_-43910_NAME = 'IMAP_EARTHFIXED' - FRAME_-43910_CLASS = 4 - FRAME_-43910_CLASS_ID = -43910 - FRAME_-43910_CENTER = 399 - TKFRAME_-43910_RELATIVE = 'ITRF93' - TKFRAME_-43910_SPEC = 'MATRIX' - TKFRAME_-43910_MATRIX = ( 1 0 0 - 0 1 0 - 0 0 1 ) - - However, using the ITRF93 frame requires supplying SPICE with - sufficient binary PCK data to cover the period of interest. - The IAU_EARTH frame just requires a text PCK with Earth data - to be loaded. - - - Mean Ecliptic of Date (IMAP_ECLIPDATE) ([2],[5]) - --------------------------------------------------------------------- - - Mean Ecliptic of Date is the more precise, rotating counterpart - to the inertial Mean Ecliptic and Equinox of J2000 (ECLIPJ2000). - - If computations involving this frame (or frames relative to this) - are too expensive, the user may instruct SPICE to ignore - rotational effects by changing 'ROTATING' to 'INERTIAL'. - - The X axis is the first point in Aries for the mean ecliptic of - date and the Z axis points along the ecliptic north pole. - - The Y axis is Z cross X, completing the right-handed reference - frame. - - \begindata - - FRAME_IMAP_ECLIPDATE = -43911 - FRAME_-43911_NAME = 'IMAP_ECLIPDATE' - FRAME_-43911_CLASS = 5 - FRAME_-43911_CLASS_ID = -43911 - FRAME_-43911_CENTER = 399 - FRAME_-43911_RELATIVE = 'J2000' - FRAME_-43911_DEF_STYLE = 'PARAMETERIZED' - FRAME_-43911_FAMILY = 'MEAN_ECLIPTIC_AND_EQUINOX_OF_DATE' - FRAME_-43911_PREC_MODEL = 'EARTH_IAU_1976' - FRAME_-43911_OBLIQ_MODEL = 'EARTH_IAU_1980' - FRAME_-43911_ROTATION_STATE = 'ROTATING' - - \begintext - - - Mission Design Inertial (MDI) Frame ([3]) - --------------------------------------------------------------------- - - Alias for SPICE ECLIPJ2000. - - Primary coordinate frame used to define IMAP's trajectory and - orbit, as well as for some science data products. - - The X axis is the first point in Aries for the mean ecliptic of - J2000 and the Z axis points along the ecliptic north pole. - - The Y axis is Z cross X, completing the right-handed reference - frame. - - \begindata - - FRAME_IMAP_MDI = -43912 - FRAME_-43912_NAME = 'IMAP_MDI' - FRAME_-43912_CLASS = 4 - FRAME_-43912_CLASS_ID = -43912 - FRAME_-43912_CENTER = 399 - TKFRAME_-43912_RELATIVE = 'IMAP_EARTHFIXED' - TKFRAME_-43912_SPEC = 'MATRIX' - TKFRAME_-43912_MATRIX = ( 1 0 0 - 0 1 0 - 0 0 1 ) - - \begintext - - - Mission Design Rotating (MDR) Frame ([3],[10]) - --------------------------------------------------------------------- - - IMAP observatory body coordinate frame. - - The origin of the frame is the L1 point of the Sun and the Earth- - Moon barycenter defined in SPK 'L1_de431.bsp' by reference [10]; - this author assigned the NAIF body code 391 to this L1 point. - - The position of the Earth-Moon barycenter relative to the Sun is - the primary vector: the X axis points from the Sun to the - Earth-Moon barycenter. - - The northern surface normal to the mean ecliptic of date is the - secondary vector: the Z axis is the component of this vector - orthogonal to the X axis. Combined with the definition of the - X axis, this yields a unit vector along the angular momentum - vector of the Earth-Moon barycenter orbiting the Sun. - - The Y axis is Z cross X, completing the right-handed reference - frame. - - All vectors are geometric: no aberration corrections are used. - - \begindata - - FRAME_IMAP_MDR = -43913 - FRAME_-43913_NAME = 'IMAP_MDR' - FRAME_-43913_CLASS = 5 - FRAME_-43913_CLASS_ID = -43913 - FRAME_-43913_CENTER = 391 - FRAME_-43913_RELATIVE = 'J2000' - FRAME_-43913_DEF_STYLE = 'PARAMETERIZED' - FRAME_-43913_FAMILY = 'TWO-VECTOR' - FRAME_-43913_PRI_AXIS = 'X' - FRAME_-43913_PRI_VECTOR_DEF = 'OBSERVER_TARGET_POSITION' - FRAME_-43913_PRI_OBSERVER = 'SUN' - FRAME_-43913_PRI_TARGET = 'EARTH MOON BARYCENTER' - FRAME_-43913_PRI_ABCORR = 'NONE' - FRAME_-43913_SEC_AXIS = 'Z' - FRAME_-43913_SEC_VECTOR_DEF = 'CONSTANT' - FRAME_-43913_SEC_FRAME = 'IMAP_ECLIPDATE' - FRAME_-43913_SEC_SPEC = 'RECTANGULAR' - FRAME_-43913_SEC_VECTOR = ( 0, 0, 1 ) - - \begintext - - - Geomagnetic Coordinate (GMC) Frame (IGRF-14 Modeled Pole) ([6]) - --------------------------------------------------------------------- - - The geomagnetic coordinate (GMC) system is defined so that its - Z-axis is parallel to the magnetic dipole. The geographic - coordinates, D, of the dipole axis are found from the - International Geomagnetic Reference Field. - - The Y-axis of this system is perpendicular to the geographic poles - such that if D is the dipole position and S is the south pole - Y=DxS. The X-axis completes a right-handed orthogonal set. - - The implementation of this frame is complicated in that the - definition of the IGRF dipole is a function of time and the IGRF - model cannot be directly incorporated into SPICE. However, SPICE - does allow one to define time dependent Euler angles. Meaning, you - can define a single Euler angle that rotates the Geocentric - Equatorial Inertial (GEI) system to GMC for a given ephem time t: - - V = r(t) * V - GEI GMC - - where r(t) is a time dependent Euler angle representation of a - rotation. SPICE allows for the time dependence to be represented - by a polynomial expansion. This expansion can be fit using the - IGRF model, thus representing the IGRF dipole axis. - - IGRF-14 (the 14th version) was fit for the period of 1990-2035, - which encompasses the mission and will also make this kernel - useful for performing Magnetic dipole frame transformations for - the 1990's and the 2000's. However, IGRF-14 is not as accurate for - this entire time interval. The years between 1945-2020 are labeled - definitive, although only back to 1990 was used in the polynomial - fit. 2020-2025 is provisional, and may change with IGRF-15. - 2025-2030 was only a prediction. Beyond 2030, the predict is so - far in the future as to not be valid. So to make the polynomials - behave nicely in this region (in case someone does try to use this - frame during that time), the 2030 prediction was extended until - 2035. So for low precision, this kernel can be used for the years - 2025-2035. Any times less than 1990 and greater than 2035 were not - used in the fit, and therefore may be vastly incorrect as the - polynomials may diverge outside of this region. These coefficients - will be refit when IGRF-15 is released. - - Also, since the rest of the magnetic dipole frames are defined - from this one, similar time ranges should be used for those frames - - Definitive Provisional Predict Not Valid - |--------------------------|+++++++++++|###########|???????????| - 1990 2020 2025 2030 2035 - - In addition to the error inherit in the model itself, the - polynomial expansion cannot perfectly be fit the IGRF dipole. The - maximum error on the fit is 0.2 milliradians, or 0.01 degrees, - while the average error is 59 microradians or 0.003 degrees. - - The GMC frame is achieved by first rotating the IAU_EARTH frame - about Z by the longitude degrees, and then rotating about the - Y axis by the amount of latitude. - - NOTE: ITRF93 is much more accurate than IAU_EARTH, if precise - Earth-Fixed coordinates are desired, then ITRF93 should be - incorporated by changing RELATIVE of the IMAP_EARTHFIXED frame. - - \begindata - - FRAME_IMAP_GMC = -43914 - FRAME_-43914_NAME = 'IMAP_GMC' - FRAME_-43914_CLASS = 5 - FRAME_-43914_CLASS_ID = -43914 - FRAME_-43914_CENTER = 399 - FRAME_-43914_RELATIVE = 'IMAP_EARTHFIXED' - FRAME_-43914_DEF_STYLE = 'PARAMETERIZED' - FRAME_-43914_FAMILY = 'EULER' - FRAME_-43914_EPOCH = @2010-JAN-1/00:00:00 - FRAME_-43914_AXES = ( 3, 2, 1 ) - FRAME_-43914_UNITS = 'DEGREES' - FRAME_-43914_ANGLE_1_COEFFS = ( +72.21459071369075 - +2.5468902895893966E-9 - -9.716151847392007E-19 - -1.0433860683683533E-26 - +2.362766949492718E-36 - +3.3213862072412154E-44 - -3.5122239525813096E-54 - -4.264324158308002E-62 - +2.495064964115813E-72 - +1.8605789215176264E-80 ) - FRAME_-43914_ANGLE_2_COEFFS = ( -9.981781660857344 - +1.8136204417470554E-9 - +7.130241121790372E-19 - -2.215929597148403E-27 - -3.900143352851885E-36 - +6.599160686982152E-45 - +8.376429421972708E-54 - -1.07431639798394E-62 - -5.913960690205374E-72 - +6.775302680782905E-81 ) - FRAME_-43914_ANGLE_3_COEFFS = ( 0 ) - - \begintext - - - Geocentric Equatorial Inertial (GEI) Frame ([3],[6]) - --------------------------------------------------------------------- - - Alias for SPICE J2000 frame. - - The Geocentric Equatorial Inertial System (GEI) has its X-axis - pointing from the Earth towards the first point of Aries (the - position of the Sun at the vernal equinox). This direction is the - intersection of the Earth's equatorial plane and the ecliptic - plane and thus the X-axis lies in both planes. The Z-axis is - parallel to the rotation axis of the Earth and Y completes the - right-handed orthogonal set (Y = Z x X). - - \begindata - - FRAME_IMAP_GEI = -43915 - FRAME_-43915_NAME = 'IMAP_GEI' - FRAME_-43915_CLASS = 4 - FRAME_-43915_CLASS_ID = -43915 - FRAME_-43915_CENTER = 399 - TKFRAME_-43915_RELATIVE = 'J2000' - TKFRAME_-43915_SPEC = 'MATRIX' - TKFRAME_-43915_MATRIX = ( 1 0 0 - 0 1 0 - 0 0 1 ) - - \begintext - - - Geocentric Solar Ecliptic (GSE) Frame ([3],[5]) - --------------------------------------------------------------------- - - Rotating geocentric frame in which Sun and Earth are fixed and the - Z axis is the unit normal to the Ecliptic plane. - - The position of the Sun relative to the Earth is the primary - vector: the X axis points from the Earth to the Sun. - - The northern surface normal to the mean ecliptic of date - (IMAP_ECLIPDATE) is the secondary vector: the Z axis is the - component of this vector orthogonal to the X axis. - - The Y axis is Z cross X, completing the right-handed frame. - - All vectors are geometric: no aberration corrections are used. - - \begindata - - FRAME_IMAP_GSE = -43916 - FRAME_-43916_NAME = 'IMAP_GSE' - FRAME_-43916_CLASS = 5 - FRAME_-43916_CLASS_ID = -43916 - FRAME_-43916_CENTER = 399 - FRAME_-43916_RELATIVE = 'J2000' - FRAME_-43916_DEF_STYLE = 'PARAMETERIZED' - FRAME_-43916_FAMILY = 'TWO-VECTOR' - FRAME_-43916_PRI_AXIS = 'X' - FRAME_-43916_PRI_VECTOR_DEF = 'OBSERVER_TARGET_POSITION' - FRAME_-43916_PRI_OBSERVER = 'EARTH' - FRAME_-43916_PRI_TARGET = 'SUN' - FRAME_-43916_PRI_ABCORR = 'NONE' - FRAME_-43916_SEC_AXIS = 'Z' - FRAME_-43916_SEC_VECTOR_DEF = 'CONSTANT' - FRAME_-43916_SEC_FRAME = 'IMAP_ECLIPDATE' - FRAME_-43916_SEC_SPEC = 'RECTANGULAR' - FRAME_-43916_SEC_VECTOR = ( 0, 0, 1 ) - - \begintext - - - Geocentric Solar Magnetospheric (GSM) Frame ([3],[5],[6]) - --------------------------------------------------------------------- - - Rotating geocentric frame in which Sun and Earth are fixed and the - XZ plane contains Earth's magnetic dipole moment. Specifically, - the dipole moment will vary in the XZ plane about the Z axis of - this frame. - - The position of the Sun relative to the Earth is the primary - vector: the X axis points from the Earth to the Sun. - - Earth's magnetic dipole axis (the +Z axis of IMAP_GMC) is the - secondary vector: the Z axis is the component of this vector - orthogonal to the X axis. - - The Y axis is Z cross X, completing the right-handed frame. - - All vectors are geometric: no aberration corrections are used. - - \begindata - - FRAME_IMAP_GSM = -43917 - FRAME_-43917_NAME = 'IMAP_GSM' - FRAME_-43917_CLASS = 5 - FRAME_-43917_CLASS_ID = -43917 - FRAME_-43917_CENTER = 399 - FRAME_-43917_RELATIVE = 'J2000' - FRAME_-43917_DEF_STYLE = 'PARAMETERIZED' - FRAME_-43917_FAMILY = 'TWO-VECTOR' - FRAME_-43917_PRI_AXIS = 'X' - FRAME_-43917_PRI_VECTOR_DEF = 'OBSERVER_TARGET_POSITION' - FRAME_-43917_PRI_OBSERVER = 'EARTH' - FRAME_-43917_PRI_TARGET = 'SUN' - FRAME_-43917_PRI_ABCORR = 'NONE' - FRAME_-43917_SEC_AXIS = 'Z' - FRAME_-43917_SEC_VECTOR_DEF = 'CONSTANT' - FRAME_-43917_SEC_FRAME = 'IMAP_GMC' - FRAME_-43917_SEC_SPEC = 'RECTANGULAR' - FRAME_-43917_SEC_VECTOR = (0, 0, 1) - - \begintext - - - Solar Magnetic of Date (SMD) Frame ([3],[5],[6]) - --------------------------------------------------------------------- - - Rotating geocentric frame in which the Z axis is aligned with - Earth's magnetic dipole moment, and the XZ plane contains the - Earth-Sun vector. Specifically, the Earth-Sun vector will vary in - the XZ plane about the X axis of this frame. - - Earth's magnetic dipole axis (the +Z axis of IMAP_GMC) is the - primary vector and aligns with the Z axis of this frame. - - The position of the Sun relative to the Earth is the secondary - vector: the X axis is the component of the Earth-Sun vector - orthogonal to the Z axis. - - The Y axis is Z cross X, completing the right-handed frame. - - All vectors are geometric: no aberration corrections are used. - - \begindata - - FRAME_IMAP_SMD = -43918 - FRAME_-43918_NAME = 'IMAP_SMD' - FRAME_-43918_CLASS = 5 - FRAME_-43918_CLASS_ID = -43918 - FRAME_-43918_CENTER = 399 - FRAME_-43918_RELATIVE = 'J2000' - FRAME_-43918_DEF_STYLE = 'PARAMETERIZED' - FRAME_-43918_FAMILY = 'TWO-VECTOR' - FRAME_-43918_PRI_AXIS = 'Z' - FRAME_-43918_PRI_VECTOR_DEF = 'CONSTANT' - FRAME_-43918_PRI_FRAME = 'IMAP_GMC' - FRAME_-43918_PRI_SPEC = 'RECTANGULAR' - FRAME_-43918_PRI_VECTOR = (0, 0, 1) - FRAME_-43918_SEC_AXIS = 'X' - FRAME_-43918_SEC_VECTOR_DEF = 'OBSERVER_TARGET_POSITION' - FRAME_-43918_SEC_OBSERVER = 'EARTH' - FRAME_-43918_SEC_TARGET = 'SUN' - FRAME_-43918_SEC_ABCORR = 'NONE' - - \begintext - - -Sun Based Frames -======================================================================== - - These dynamic frames are used for analyzing data in a reference - frame tied to the dynamics of the Sun. - - - Heliocentric Radial Tangential Normal (RTN) Frame ([3],[7]) - --------------------------------------------------------------------- - - The position of the spacecraft relative to the Sun is the primary - vector: the X axis points from the Sun center to the spacecraft. - - The solar rotation axis is the secondary vector: the Z axis is - the component of the solar north direction perpendicular to X. - - The Y axis is Z cross X, completing the right-handed reference - frame. - - All vectors are geometric: no aberration corrections are used. - - \begindata - - FRAME_IMAP_RTN = -43920 - FRAME_-43920_NAME = 'IMAP_RTN' - FRAME_-43920_CLASS = 5 - FRAME_-43920_CLASS_ID = -43920 - FRAME_-43920_CENTER = 10 - FRAME_-43920_RELATIVE = 'J2000' - FRAME_-43920_DEF_STYLE = 'PARAMETERIZED' - FRAME_-43920_FAMILY = 'TWO-VECTOR' - FRAME_-43920_PRI_AXIS = 'X' - FRAME_-43920_PRI_VECTOR_DEF = 'OBSERVER_TARGET_POSITION' - FRAME_-43920_PRI_OBSERVER = 'SUN' - FRAME_-43920_PRI_TARGET = 'IMAP' - FRAME_-43920_PRI_ABCORR = 'NONE' - FRAME_-43920_PRI_FRAME = 'IAU_SUN' - FRAME_-43920_SEC_AXIS = 'Z' - FRAME_-43920_SEC_VECTOR_DEF = 'CONSTANT' - FRAME_-43920_SEC_FRAME = 'IAU_SUN' - FRAME_-43920_SEC_SPEC = 'RECTANGULAR' - FRAME_-43920_SEC_VECTOR = ( 0, 0, 1 ) - - \begintext - - - Heliocentric Inertial (HCI) Frame ([3],[5],[7]) - --------------------------------------------------------------------- - - Referred to as "Heliographic Inertial (HGI) frame at epoch J2000" - in [3], but named as in [7] to avoid confusion with HGI of J1900. - - The X-Y Plane lies in the solar equator, +Z axis is parallel to - the Sun's rotation vector. - - The solar rotation axis is the primary vector: the Z axis points - in the solar north direction. - - The ascending node on the Earth ecliptic of J2000 of the solar - equator forms the X axis. This is accomplished by using the +Z - axis of the ecliptic of J2000 as the secondary vector and HCI +Y - as the secondary axis. - - The Y axis is Z cross X, completing the right-handed reference - frame. - - \begindata - - FRAME_IMAP_HCI = -43921 - FRAME_-43921_NAME = 'IMAP_HCI' - FRAME_-43921_CLASS = 5 - FRAME_-43921_CLASS_ID = -43921 - FRAME_-43921_CENTER = 10 - FRAME_-43921_RELATIVE = 'J2000' - FRAME_-43921_DEF_STYLE = 'PARAMETERIZED' - FRAME_-43921_FAMILY = 'TWO-VECTOR' - FRAME_-43921_PRI_AXIS = 'Z' - FRAME_-43921_PRI_VECTOR_DEF = 'CONSTANT' - FRAME_-43921_PRI_FRAME = 'IAU_SUN' - FRAME_-43921_PRI_SPEC = 'RECTANGULAR' - FRAME_-43921_PRI_VECTOR = ( 0, 0, 1 ) - FRAME_-43921_SEC_AXIS = 'Y' - FRAME_-43921_SEC_VECTOR_DEF = 'CONSTANT' - FRAME_-43921_SEC_FRAME = 'ECLIPJ2000' - FRAME_-43921_SEC_SPEC = 'RECTANGULAR' - FRAME_-43921_SEC_VECTOR = ( 0, 0, 1 ) - - \begintext - - - Heliocentric of Date (HCD) Frame ([3],[5],[7]) - --------------------------------------------------------------------- - - Referred to as "Heliographic Inertial (HGI) frame true to - reference date" in [3], but named as in [7] without "inertial." - - The X-Y Plane lies in the solar equator, +Z axis is parallel to - the Sun's rotation vector. - - The solar rotation axis is the primary vector: the Z axis points - in the solar north direction. - - The ascending node on the Earth ecliptic of date of the solar - equator forms the X axis. This is accomplished by using the +Z - axis of the ecliptic of date as the secondary vector and HCD +Y - as the secondary axis. - - The Y axis is Z cross X, completing the right-handed reference - frame. - - \begindata - - FRAME_IMAP_HCD = -43922 - FRAME_-43922_NAME = 'IMAP_HCD' - FRAME_-43922_CLASS = 5 - FRAME_-43922_CLASS_ID = -43922 - FRAME_-43922_CENTER = 10 - FRAME_-43922_RELATIVE = 'J2000' - FRAME_-43922_DEF_STYLE = 'PARAMETERIZED' - FRAME_-43922_FAMILY = 'TWO-VECTOR' - FRAME_-43922_PRI_AXIS = 'Z' - FRAME_-43922_PRI_VECTOR_DEF = 'CONSTANT' - FRAME_-43922_PRI_FRAME = 'IAU_SUN' - FRAME_-43922_PRI_SPEC = 'RECTANGULAR' - FRAME_-43922_PRI_VECTOR = ( 0, 0, 1 ) - FRAME_-43922_SEC_AXIS = 'Y' - FRAME_-43922_SEC_VECTOR_DEF = 'CONSTANT' - FRAME_-43922_SEC_FRAME = 'IMAP_ECLIPDATE' - FRAME_-43922_SEC_SPEC = 'RECTANGULAR' - FRAME_-43922_SEC_VECTOR = ( 0, 0, 1 ) - - \begintext - - - Heliographic Coordinates (HGC) Frame ([3],[7]) - --------------------------------------------------------------------- - - Cartesian counterpart to the spherical coordinates defined in [3], - "Heliographic Spherical (HGS) coordinate frame true to ref. date". - - Alias for SPICE IAU_SUN (Carrington heliographic coordinates) - in which the frame rotates with the surface of the sun with a - sidereal period of exactly 25.38 days. - - The Z axis is the solar rotation axis. - - The X axis is the intersection of the Carrington prime meridian - and the heliographic equator. - - The Y axis is Z cross X, completing the right-handed reference - frame. - - \begindata - - FRAME_IMAP_HGC = -43923 - FRAME_-43923_NAME = 'IMAP_HGC' - FRAME_-43923_CLASS = 4 - FRAME_-43923_CLASS_ID = -43923 - FRAME_-43923_CENTER = 10 - TKFRAME_-43923_RELATIVE = 'IAU_SUN' - TKFRAME_-43923_SPEC = 'MATRIX' - TKFRAME_-43923_MATRIX = ( 1 0 0 - 0 1 0 - 0 0 1 ) - \begintext - - - Heliocentric Aries Ecliptic (HAE) Frame ([3],[7]) - --------------------------------------------------------------------- - - Alias for SPICE ECLIPJ2000. - - The Z axis is the normal to the mean ecliptic at J2000. - - The X axis is the unit vector from Earth to the first point of - Aries at J2000. - - The Y axis is Z cross X, completing the right-handed reference - frame. - - \begindata - - FRAME_IMAP_HAE = -43924 - FRAME_-43924_NAME = 'IMAP_HAE' - FRAME_-43924_CLASS = 4 - FRAME_-43924_CLASS_ID = -43924 - FRAME_-43924_CENTER = 10 - TKFRAME_-43924_RELATIVE = 'ECLIPJ2000' - TKFRAME_-43924_SPEC = 'MATRIX' - TKFRAME_-43924_MATRIX = ( 1 0 0 - 0 1 0 - 0 0 1 ) - \begintext - - - Heliocentric Aries Ecliptic of Date (HAED) Frame ([3],[7]) - --------------------------------------------------------------------- - - Same orientation as IMAP_ECLIPDATE, but with Sun at the center - instead of Earth. - - The Z axis is the normal to the mean ecliptic of date. - - The X axis is the unit vector from Earth to the first point of - Aries of date. - - The Y axis is Z cross X, completing the right-handed reference - frame. - - \begindata - - FRAME_IMAP_HAED = -43925 - FRAME_-43925_NAME = 'IMAP_HAED' - FRAME_-43925_CLASS = 4 - FRAME_-43925_CLASS_ID = -43925 - FRAME_-43925_CENTER = 10 - TKFRAME_-43925_RELATIVE = 'IMAP_ECLIPDATE' - TKFRAME_-43925_SPEC = 'MATRIX' - TKFRAME_-43925_MATRIX = ( 1 0 0 - 0 1 0 - 0 0 1 ) - \begintext - - - Heliocentric Earth Ecliptic (HEE) Frame ([3],[7]) - --------------------------------------------------------------------- - - The position of the Earth relative to the Sun is the primary - vector: the X axis points from the Sun to the Earth. - - The northern surface normal to the mean ecliptic of date is the - secondary vector: the Z axis is the component of this vector - orthogonal to the X axis. - - The Y axis is Z cross X, completing the right-handed reference - frame. - - All vectors are geometric: no aberration corrections are used. - - \begindata - - FRAME_IMAP_HEE = -43926 - FRAME_-43926_NAME = 'IMAP_HEE' - FRAME_-43926_CLASS = 5 - FRAME_-43926_CLASS_ID = -43926 - FRAME_-43926_CENTER = 10 - FRAME_-43926_RELATIVE = 'J2000' - FRAME_-43926_DEF_STYLE = 'PARAMETERIZED' - FRAME_-43926_FAMILY = 'TWO-VECTOR' - FRAME_-43926_PRI_AXIS = 'X' - FRAME_-43926_PRI_VECTOR_DEF = 'OBSERVER_TARGET_POSITION' - FRAME_-43926_PRI_OBSERVER = 'SUN' - FRAME_-43926_PRI_TARGET = 'EARTH' - FRAME_-43926_PRI_ABCORR = 'NONE' - FRAME_-43926_SEC_AXIS = 'Z' - FRAME_-43926_SEC_VECTOR_DEF = 'CONSTANT' - FRAME_-43926_SEC_FRAME = 'IMAP_ECLIPDATE' - FRAME_-43926_SEC_SPEC = 'RECTANGULAR' - FRAME_-43926_SEC_VECTOR = ( 0, 0, 1 ) - - \begintext - - - Heliospheric Ram Ecliptic (HRE) Frame ([3],[8],[9]) - --------------------------------------------------------------------- - - This is a heliocentric frame oriented with respect to the current, - nominal ram direction of the Sun's motion relative to the local - interstellar medium and the ecliptic plane, otherwise known as the - heliospheric "nose" direction. - - The nose direction is the primary vector: the X axis points in the - direction [-0.2477, -0.9647, 0.0896] in the ECLIPJ2000 (IMAP_HAE) - frame. - - The northern surface normal to the mean ecliptic of J2000 is the - secondary vector: the Z axis is the component of this vector - orthogonal to the X axis. - - The Y axis is Z cross X, completing the right-handed reference - frame. - - \begindata - - FRAME_IMAP_HRE = -43927 - FRAME_-43927_NAME = 'IMAP_HRE' - FRAME_-43927_CLASS = 5 - FRAME_-43927_CLASS_ID = -43927 - FRAME_-43927_CENTER = 10 - FRAME_-43927_RELATIVE = 'J2000' - FRAME_-43927_DEF_STYLE = 'PARAMETERIZED' - FRAME_-43927_FAMILY = 'TWO-VECTOR' - FRAME_-43927_PRI_AXIS = 'X' - FRAME_-43927_PRI_VECTOR_DEF = 'CONSTANT' - FRAME_-43927_PRI_FRAME = 'ECLIPJ2000' - FRAME_-43927_PRI_SPEC = 'RECTANGULAR' - FRAME_-43927_PRI_VECTOR = ( -0.2477, -0.9647, 0.0896 ) - FRAME_-43927_SEC_AXIS = 'Z' - FRAME_-43927_SEC_VECTOR_DEF = 'CONSTANT' - FRAME_-43927_SEC_FRAME = 'ECLIPJ2000' - FRAME_-43927_SEC_SPEC = 'RECTANGULAR' - FRAME_-43927_SEC_VECTOR = ( 0, 0, 1 ) - - \begintext - - - Heliospheric Nose Upfield (HNU) Frame ([3],[8],[9]) - --------------------------------------------------------------------- - - Heliocentric frame oriented with respect to the current nominal - ram direction of the Sun's motion relative to the local - interstellar medium and the current best estimate of the - unperturbed magnetic field direction in the upstream local - interstellar medium. - - The nominal upfield direction of the ISM B-field is the primary - vector: the Z axis points in the direction - [-0.5583, -0.6046, 0.5681] in the ECLIPJ2000 (IMAP_HAE) frame. - - The nose direction [-0.2477, -0.9647, 0.0896] in the ECLIPJ2000 - (IMAP_HAE) frame is the secondary vector: the X axis is the - component of this vector orthogonal to the Z axis. - - The Y axis is Z cross X, completing the right-handed reference - frame. - - \begindata - - FRAME_IMAP_HNU = -43928 - FRAME_-43928_NAME = 'IMAP_HNU' - FRAME_-43928_CLASS = 5 - FRAME_-43928_CLASS_ID = -43928 - FRAME_-43928_CENTER = 10 - FRAME_-43928_RELATIVE = 'J2000' - FRAME_-43928_DEF_STYLE = 'PARAMETERIZED' - FRAME_-43928_FAMILY = 'TWO-VECTOR' - FRAME_-43928_PRI_AXIS = 'Z' - FRAME_-43928_PRI_VECTOR_DEF = 'CONSTANT' - FRAME_-43928_PRI_FRAME = 'ECLIPJ2000' - FRAME_-43928_PRI_SPEC = 'RECTANGULAR' - FRAME_-43928_PRI_VECTOR = ( -0.5583, -0.6046, 0.5681 ) - FRAME_-43928_SEC_AXIS = 'X' - FRAME_-43928_SEC_VECTOR_DEF = 'CONSTANT' - FRAME_-43928_SEC_FRAME = 'ECLIPJ2000' - FRAME_-43928_SEC_SPEC = 'RECTANGULAR' - FRAME_-43928_SEC_VECTOR = ( -0.2477, -0.9647, 0.0896 ) - - \begintext - - - Galactic Coordinate System (GCS) Frame ([3]) - --------------------------------------------------------------------- - - Alias for SPICE galactic system II frame GALACTIC. - - The primary axis is the normal to the galactic equatorial plane: - Z axis is this unit vector. - - The secondary axis is the vector from the Sun to the galatic - center (represented by Sagittarious): X axis is the component of - this vector orthogonal to the Z axis. - - The Y axis is Z cross X, completing the right-handed reference - frame. - - \begindata - - FRAME_IMAP_GCS = -43929 - FRAME_-43929_NAME = 'IMAP_GCS' - FRAME_-43929_CLASS = 4 - FRAME_-43929_CLASS_ID = -43929 - FRAME_-43929_CENTER = 10 - TKFRAME_-43929_RELATIVE = 'GALACTIC' - TKFRAME_-43929_SPEC = 'MATRIX' - TKFRAME_-43929_MATRIX = ( 1 0 0 - 0 1 0 - 0 0 1 ) - \begintext - - +KPL/FK + +Interstellar Mapping and Acceleration Probe (IMAP) Dynamic Frames Kernel +======================================================================== + + This kernel contains SPICE frame definitions to support the + IMAP mission. + + This kernel is composed of primarily dynamic frames, but in general + it holds frame definitions for all instrument-agnostic frames, CK + frames used in science data processing and mapping. + + +Version and Date +------------------------------------------------------------------------ + + The TEXT_KERNEL_ID stores version information of loaded project + text kernels. Each entry associated with the keyword is a string + that consists of four parts: the kernel name, version, entry date, + and type. + + IMAP Dynamic Frame Kernel Version: + + \begindata + + TEXT_KERNEL_ID = 'IMAP_DYNAMIC_FRAMES V0.0.1 2025-JUNE-26 FK' + + \begintext + + Version 0.0.0 -- April 10, 2024 -- Nick Dutton (JHU/APL) + Version 0.0.1 -- June 26, 2025 -- Nick Dutton (JHU/APL) + Version 1.0.0 -- July 8, 2025 -- Nick and Doug (JHU/APL) + + +References +------------------------------------------------------------------------ + + 1. NAIF SPICE `Kernel Pool Required Reading' + + 2. NAIF SPICE `Frames Required Reading' + + 3. "IMAP Coordinate Frame Science.pdf" + + 4. stereo_rtn.tf, at + https://soho.nascom.nasa.gov/solarsoft/stereo/... + ...gen/data/spice/gen/stereo_rtn.tf + + 5. heliospheric.tf, at + https://soho.nascom.nasa.gov/solarsoft/stereo/... + ...gen/data/spice/gen/heliospheric.tf + + 6. "Geophysical Coordinate Transformations", C. T. Russell + + 7. "Heliospheric Coordinate Systems", M. Franz and D. Harper + + 8. "Global observations of the interstellar interaction from the + Interstellar Boundary Explorer (IBEX)", D. J. McComas, et al. + + 9. "Very Local Interstellar Medium Revealed by a Complete Solar + Cycle of Interstellar Neutral Helium Observations with IBEX", + P. Swaczyna, et al. + + 10. Lagrange L1 definition and SPK, Min-Kun Chung, + https://naif.jpl.nasa.gov/pub/naif/... + ...generic_kernels/spk/lagrange_point/ + + +Contact Information +------------------------------------------------------------------------ + + Direct questions, comments, or concerns about the contents of this + kernel to: + + Nick Dutton, JHUAPL, Nicholas.Dutton@jhuapl.edu + + or + + Doug Rodgers, JHUAPL, Douglas.Rodgers@jhuapl.edu + + or + + Lillian Nguyen, JHUAPL, Lillian.Nguyen@jhuapl.edu + + +Implementation Notes +------------------------------------------------------------------------ + + This file is used by the SPICE system as follows: programs that make + use of this frame kernel must `load' the kernel normally during + program initialization. Loading the kernel associates the data items + with their names in a data structure called the `kernel pool'. The + SPICELIB routine FURNSH loads a kernel into the pool as shown below: + + Python: (SpiceyPy) + + spiceypy.furnsh( frame_kernel_name ) + + IDL: (ICY) + + cspice_furnsh, frame_kernel_name + + MATLAB: (MICE) + + cspice_furnsh ( frame_kernel_name ) + + C: (CSPICE) + + furnsh_c ( frame_kernel_name ); + + FORTRAN: (SPICELIB) + + CALL FURNSH ( frame_kernel_name ) + + This file was created, and may be updated with, a text editor or word + processor. + + +IMAP Science Frames +======================================================================== + + This frame kernel defines a series of frames listed in [3] that + support IMAP data reduction and analysis. All of the frame names + assigned an IMAP NAIF ID (beginning with -43) defined by this kernel + are prefixed with 'IMAP_' to avoid conflict with alternative + definitions not specific to the project. + + The project-specific ID codes -43900 to -43999 have been set aside to + support these dynamic frames. + + + Frame Name Relative To Type NAIF ID + ====================== =============== ======== ======= + + IMAP Based Frames: + ---------------------- + IMAP_OMD IMAP_SPACECRAFT FIXED -43900 + IMAP_DPS [n/a] CK -43901 + + Earth Based Frames: + ---------------------- + IMAP_EARTHFIXED IAU_EARTH FIXED -43910 + IMAP_ECLIPDATE J2000 DYNAMIC -43911 + IMAP_MDI ECLIPJ2000 FIXED -43912 + IMAP_MDR J2000 DYNAMIC -43913 + IMAP_GMC IAU_EARTH DYNAMIC -43914 + IMAP_GEI J2000 FIXED -43915 + IMAP_GSE J2000 DYNAMIC -43916 + IMAP_GSM J2000 DYNAMIC -43917 + IMAP_SMD J2000 DYNAMIC -43918 + + Sun Based Frames: + ---------------------- + IMAP_RTN J2000 DYNAMIC -43920 + IMAP_HCI (ie, HGI_J2K) J2000 DYNAMIC -43921 + IMAP_HCD (ie, HGI_D) J2000 DYNAMIC -43922 + IMAP_HGC (ie, HGS_D) IAU_SUN FIXED -43923 + IMAP_HAE ECLIPJ2000 FIXED -43924 + IMAP_HAED IMAP_ECLIPDATE FIXED -43925 + IMAP_HEE J2000 DYNAMIC -43926 + IMAP_HRE J2000 DYNAMIC -43927 + IMAP_HNU J2000 DYNAMIC -43928 + IMAP_GCS GALACTIC FIXED -43929 + + +IMAP Based Frames +======================================================================== + + These dynamic frames are used for analyzing data in a reference + frame tied to the dynamics of IMAP. + + + Observatory Mechanical Design (OMD) Frame ([3]) + --------------------------------------------------------------------- + + Alias for IMAP_SPACECRAFT frame defined in the primary + 'imap_vNNN.tf' frame kernel. From that file: + + Origin: Center of the launch vehicle adapter ring at the + observatory/launch vehicle interface plane + + +Z axis: Perpendicular to the launch vehicle interface plane + pointed in the direction of the top deck (runs through + the center of the central cylinder structure element) + + +Y axis: Direction of the vector orthogonal to the +Z axis and + parallel to the deployed MAG boom + + +X axis: The third orthogonal axis defined using an X, Y, Z + ordered right hand rule + + \begindata + + FRAME_IMAP_EARTHFIXED = -43900 + FRAME_-43900_NAME = 'IMAP_OMD' + FRAME_-43900_CLASS = 4 + FRAME_-43900_CLASS_ID = -43900 + FRAME_-43900_CENTER = -43 + TKFRAME_-43900_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43900_SPEC = 'MATRIX' + TKFRAME_-43900_MATRIX = ( 1 0 0 + 0 1 0 + 0 0 1 ) + + \begintext + + + Despun Pointing Sets (DPS) Frame ([3]) + --------------------------------------------------------------------- + + Coordinate frame used for ENA imager data processing and + intentionally designed for use in producing all-sky map products. + + This is provided by a CK file external to this file. Notionally, + the frame is defined: + + +Z axis is parallel to the nominal spin axis of the spacecraft. + The axis is notionally a time-average of the spin axis of the + exact orientation (IMAP_SPACECRAFT or IMAP_OMD). + + Y = Z cross Necliptic where Necliptic is the the unit normal + (North) to the ecliptic plane. + + This is a quasi-inertial reference frame and will have a unique + transformation matrix, valid between repointings of the spacecraft + + \begindata + + FRAME_IMAP_DPS = -43901 + FRAME_-43901_NAME = 'IMAP_DPS' + FRAME_-43901_CLASS = 3 + FRAME_-43901_CLASS_ID = -43901 + FRAME_-43901_CENTER = -43 + CK_-43901_SCLK = -43 + CK_-43901_SPK = -43 + + \begintext + + +Earth Based Frames +======================================================================== + + These dynamic frames are used for analyzing data in a reference + frame tied to the dynamics of Earth. + + + Earth-Fixed Frame (IMAP_EARTHFIXED) + --------------------------------------------------------------------- + + Some of these Earth based dynamic frames reference vectors in an + Earth-fixed frame. To support loading of either rotation model + (IAU_EARTH or ITRF93), the following keywords control which model + is used. The model is enabled by surrounding its keyword-value + block with the \begindata and \begintext markers (currently + IAU_EARTH). + + IAU_EARTH based model is currently employed: + + \begindata + + FRAME_IMAP_EARTHFIXED = -43910 + FRAME_-43910_NAME = 'IMAP_EARTHFIXED' + FRAME_-43910_CLASS = 4 + FRAME_-43910_CLASS_ID = -43910 + FRAME_-43910_CENTER = 399 + TKFRAME_-43910_RELATIVE = 'IAU_EARTH' + TKFRAME_-43910_SPEC = 'MATRIX' + TKFRAME_-43910_MATRIX = ( 1 0 0 + 0 1 0 + 0 0 1 ) + + \begintext + + Alternately, the more precise ITRF93-based model could be used: + + FRAME_IMAP_EARTHFIXED = -43910 + FRAME_-43910_NAME = 'IMAP_EARTHFIXED' + FRAME_-43910_CLASS = 4 + FRAME_-43910_CLASS_ID = -43910 + FRAME_-43910_CENTER = 399 + TKFRAME_-43910_RELATIVE = 'ITRF93' + TKFRAME_-43910_SPEC = 'MATRIX' + TKFRAME_-43910_MATRIX = ( 1 0 0 + 0 1 0 + 0 0 1 ) + + However, using the ITRF93 frame requires supplying SPICE with + sufficient binary PCK data to cover the period of interest. + The IAU_EARTH frame just requires a text PCK with Earth data + to be loaded. + + + Mean Ecliptic of Date (IMAP_ECLIPDATE) ([2],[5]) + --------------------------------------------------------------------- + + Mean Ecliptic of Date is the more precise, rotating counterpart + to the inertial Mean Ecliptic and Equinox of J2000 (ECLIPJ2000). + + If computations involving this frame (or frames relative to this) + are too expensive, the user may instruct SPICE to ignore + rotational effects by changing 'ROTATING' to 'INERTIAL'. + + The X axis is the first point in Aries for the mean ecliptic of + date and the Z axis points along the ecliptic north pole. + + The Y axis is Z cross X, completing the right-handed reference + frame. + + \begindata + + FRAME_IMAP_ECLIPDATE = -43911 + FRAME_-43911_NAME = 'IMAP_ECLIPDATE' + FRAME_-43911_CLASS = 5 + FRAME_-43911_CLASS_ID = -43911 + FRAME_-43911_CENTER = 399 + FRAME_-43911_RELATIVE = 'J2000' + FRAME_-43911_DEF_STYLE = 'PARAMETERIZED' + FRAME_-43911_FAMILY = 'MEAN_ECLIPTIC_AND_EQUINOX_OF_DATE' + FRAME_-43911_PREC_MODEL = 'EARTH_IAU_1976' + FRAME_-43911_OBLIQ_MODEL = 'EARTH_IAU_1980' + FRAME_-43911_ROTATION_STATE = 'ROTATING' + + \begintext + + + Mission Design Inertial (MDI) Frame ([3]) + --------------------------------------------------------------------- + + Alias for SPICE ECLIPJ2000. + + Primary coordinate frame used to define IMAP's trajectory and + orbit, as well as for some science data products. + + The X axis is the first point in Aries for the mean ecliptic of + J2000 and the Z axis points along the ecliptic north pole. + + The Y axis is Z cross X, completing the right-handed reference + frame. + + \begindata + + FRAME_IMAP_MDI = -43912 + FRAME_-43912_NAME = 'IMAP_MDI' + FRAME_-43912_CLASS = 4 + FRAME_-43912_CLASS_ID = -43912 + FRAME_-43912_CENTER = 399 + TKFRAME_-43912_RELATIVE = 'IMAP_EARTHFIXED' + TKFRAME_-43912_SPEC = 'MATRIX' + TKFRAME_-43912_MATRIX = ( 1 0 0 + 0 1 0 + 0 0 1 ) + + \begintext + + + Mission Design Rotating (MDR) Frame ([3],[10]) + --------------------------------------------------------------------- + + IMAP observatory body coordinate frame. + + The origin of the frame is the L1 point of the Sun and the Earth- + Moon barycenter defined in SPK 'L1_de431.bsp' by reference [10]; + this author assigned the NAIF body code 391 to this L1 point. + + The position of the Earth-Moon barycenter relative to the Sun is + the primary vector: the X axis points from the Sun to the + Earth-Moon barycenter. + + The northern surface normal to the mean ecliptic of date is the + secondary vector: the Z axis is the component of this vector + orthogonal to the X axis. Combined with the definition of the + X axis, this yields a unit vector along the angular momentum + vector of the Earth-Moon barycenter orbiting the Sun. + + The Y axis is Z cross X, completing the right-handed reference + frame. + + All vectors are geometric: no aberration corrections are used. + + \begindata + + FRAME_IMAP_MDR = -43913 + FRAME_-43913_NAME = 'IMAP_MDR' + FRAME_-43913_CLASS = 5 + FRAME_-43913_CLASS_ID = -43913 + FRAME_-43913_CENTER = 391 + FRAME_-43913_RELATIVE = 'J2000' + FRAME_-43913_DEF_STYLE = 'PARAMETERIZED' + FRAME_-43913_FAMILY = 'TWO-VECTOR' + FRAME_-43913_PRI_AXIS = 'X' + FRAME_-43913_PRI_VECTOR_DEF = 'OBSERVER_TARGET_POSITION' + FRAME_-43913_PRI_OBSERVER = 'SUN' + FRAME_-43913_PRI_TARGET = 'EARTH MOON BARYCENTER' + FRAME_-43913_PRI_ABCORR = 'NONE' + FRAME_-43913_SEC_AXIS = 'Z' + FRAME_-43913_SEC_VECTOR_DEF = 'CONSTANT' + FRAME_-43913_SEC_FRAME = 'IMAP_ECLIPDATE' + FRAME_-43913_SEC_SPEC = 'RECTANGULAR' + FRAME_-43913_SEC_VECTOR = ( 0, 0, 1 ) + + \begintext + + + Geomagnetic Coordinate (GMC) Frame (IGRF-14 Modeled Pole) ([6]) + --------------------------------------------------------------------- + + The geomagnetic coordinate (GMC) system is defined so that its + Z-axis is parallel to the magnetic dipole. The geographic + coordinates, D, of the dipole axis are found from the + International Geomagnetic Reference Field. + + The Y-axis of this system is perpendicular to the geographic poles + such that if D is the dipole position and S is the south pole + Y=DxS. The X-axis completes a right-handed orthogonal set. + + The implementation of this frame is complicated in that the + definition of the IGRF dipole is a function of time and the IGRF + model cannot be directly incorporated into SPICE. However, SPICE + does allow one to define time dependent Euler angles. Meaning, you + can define a single Euler angle that rotates the Geocentric + Equatorial Inertial (GEI) system to GMC for a given ephem time t: + + V = r(t) * V + GEI GMC + + where r(t) is a time dependent Euler angle representation of a + rotation. SPICE allows for the time dependence to be represented + by a polynomial expansion. This expansion can be fit using the + IGRF model, thus representing the IGRF dipole axis. + + IGRF-14 (the 14th version) was fit for the period of 1990-2035, + which encompasses the mission and will also make this kernel + useful for performing Magnetic dipole frame transformations for + the 1990's and the 2000's. However, IGRF-14 is not as accurate for + this entire time interval. The years between 1945-2020 are labeled + definitive, although only back to 1990 was used in the polynomial + fit. 2020-2025 is provisional, and may change with IGRF-15. + 2025-2030 was only a prediction. Beyond 2030, the predict is so + far in the future as to not be valid. So to make the polynomials + behave nicely in this region (in case someone does try to use this + frame during that time), the 2030 prediction was extended until + 2035. So for low precision, this kernel can be used for the years + 2025-2035. Any times less than 1990 and greater than 2035 were not + used in the fit, and therefore may be vastly incorrect as the + polynomials may diverge outside of this region. These coefficients + will be refit when IGRF-15 is released. + + Also, since the rest of the magnetic dipole frames are defined + from this one, similar time ranges should be used for those frames + + Definitive Provisional Predict Not Valid + |--------------------------|+++++++++++|###########|???????????| + 1990 2020 2025 2030 2035 + + In addition to the error inherit in the model itself, the + polynomial expansion cannot perfectly be fit the IGRF dipole. The + maximum error on the fit is 0.2 milliradians, or 0.01 degrees, + while the average error is 59 microradians or 0.003 degrees. + + The GMC frame is achieved by first rotating the IAU_EARTH frame + about Z by the longitude degrees, and then rotating about the + Y axis by the amount of latitude. + + NOTE: ITRF93 is much more accurate than IAU_EARTH, if precise + Earth-Fixed coordinates are desired, then ITRF93 should be + incorporated by changing RELATIVE of the IMAP_EARTHFIXED frame. + + \begindata + + FRAME_IMAP_GMC = -43914 + FRAME_-43914_NAME = 'IMAP_GMC' + FRAME_-43914_CLASS = 5 + FRAME_-43914_CLASS_ID = -43914 + FRAME_-43914_CENTER = 399 + FRAME_-43914_RELATIVE = 'IMAP_EARTHFIXED' + FRAME_-43914_DEF_STYLE = 'PARAMETERIZED' + FRAME_-43914_FAMILY = 'EULER' + FRAME_-43914_EPOCH = @2010-JAN-1/00:00:00 + FRAME_-43914_AXES = ( 3, 2, 1 ) + FRAME_-43914_UNITS = 'DEGREES' + FRAME_-43914_ANGLE_1_COEFFS = ( +72.21459071369075 + +2.5468902895893966E-9 + -9.716151847392007E-19 + -1.0433860683683533E-26 + +2.362766949492718E-36 + +3.3213862072412154E-44 + -3.5122239525813096E-54 + -4.264324158308002E-62 + +2.495064964115813E-72 + +1.8605789215176264E-80 ) + FRAME_-43914_ANGLE_2_COEFFS = ( -9.981781660857344 + +1.8136204417470554E-9 + +7.130241121790372E-19 + -2.215929597148403E-27 + -3.900143352851885E-36 + +6.599160686982152E-45 + +8.376429421972708E-54 + -1.07431639798394E-62 + -5.913960690205374E-72 + +6.775302680782905E-81 ) + FRAME_-43914_ANGLE_3_COEFFS = ( 0 ) + + \begintext + + + Geocentric Equatorial Inertial (GEI) Frame ([3],[6]) + --------------------------------------------------------------------- + + Alias for SPICE J2000 frame. + + The Geocentric Equatorial Inertial System (GEI) has its X-axis + pointing from the Earth towards the first point of Aries (the + position of the Sun at the vernal equinox). This direction is the + intersection of the Earth's equatorial plane and the ecliptic + plane and thus the X-axis lies in both planes. The Z-axis is + parallel to the rotation axis of the Earth and Y completes the + right-handed orthogonal set (Y = Z x X). + + \begindata + + FRAME_IMAP_GEI = -43915 + FRAME_-43915_NAME = 'IMAP_GEI' + FRAME_-43915_CLASS = 4 + FRAME_-43915_CLASS_ID = -43915 + FRAME_-43915_CENTER = 399 + TKFRAME_-43915_RELATIVE = 'J2000' + TKFRAME_-43915_SPEC = 'MATRIX' + TKFRAME_-43915_MATRIX = ( 1 0 0 + 0 1 0 + 0 0 1 ) + + \begintext + + + Geocentric Solar Ecliptic (GSE) Frame ([3],[5]) + --------------------------------------------------------------------- + + Rotating geocentric frame in which Sun and Earth are fixed and the + Z axis is the unit normal to the Ecliptic plane. + + The position of the Sun relative to the Earth is the primary + vector: the X axis points from the Earth to the Sun. + + The northern surface normal to the mean ecliptic of date + (IMAP_ECLIPDATE) is the secondary vector: the Z axis is the + component of this vector orthogonal to the X axis. + + The Y axis is Z cross X, completing the right-handed frame. + + All vectors are geometric: no aberration corrections are used. + + \begindata + + FRAME_IMAP_GSE = -43916 + FRAME_-43916_NAME = 'IMAP_GSE' + FRAME_-43916_CLASS = 5 + FRAME_-43916_CLASS_ID = -43916 + FRAME_-43916_CENTER = 399 + FRAME_-43916_RELATIVE = 'J2000' + FRAME_-43916_DEF_STYLE = 'PARAMETERIZED' + FRAME_-43916_FAMILY = 'TWO-VECTOR' + FRAME_-43916_PRI_AXIS = 'X' + FRAME_-43916_PRI_VECTOR_DEF = 'OBSERVER_TARGET_POSITION' + FRAME_-43916_PRI_OBSERVER = 'EARTH' + FRAME_-43916_PRI_TARGET = 'SUN' + FRAME_-43916_PRI_ABCORR = 'NONE' + FRAME_-43916_SEC_AXIS = 'Z' + FRAME_-43916_SEC_VECTOR_DEF = 'CONSTANT' + FRAME_-43916_SEC_FRAME = 'IMAP_ECLIPDATE' + FRAME_-43916_SEC_SPEC = 'RECTANGULAR' + FRAME_-43916_SEC_VECTOR = ( 0, 0, 1 ) + + \begintext + + + Geocentric Solar Magnetospheric (GSM) Frame ([3],[5],[6]) + --------------------------------------------------------------------- + + Rotating geocentric frame in which Sun and Earth are fixed and the + XZ plane contains Earth's magnetic dipole moment. Specifically, + the dipole moment will vary in the XZ plane about the Z axis of + this frame. + + The position of the Sun relative to the Earth is the primary + vector: the X axis points from the Earth to the Sun. + + Earth's magnetic dipole axis (the +Z axis of IMAP_GMC) is the + secondary vector: the Z axis is the component of this vector + orthogonal to the X axis. + + The Y axis is Z cross X, completing the right-handed frame. + + All vectors are geometric: no aberration corrections are used. + + \begindata + + FRAME_IMAP_GSM = -43917 + FRAME_-43917_NAME = 'IMAP_GSM' + FRAME_-43917_CLASS = 5 + FRAME_-43917_CLASS_ID = -43917 + FRAME_-43917_CENTER = 399 + FRAME_-43917_RELATIVE = 'J2000' + FRAME_-43917_DEF_STYLE = 'PARAMETERIZED' + FRAME_-43917_FAMILY = 'TWO-VECTOR' + FRAME_-43917_PRI_AXIS = 'X' + FRAME_-43917_PRI_VECTOR_DEF = 'OBSERVER_TARGET_POSITION' + FRAME_-43917_PRI_OBSERVER = 'EARTH' + FRAME_-43917_PRI_TARGET = 'SUN' + FRAME_-43917_PRI_ABCORR = 'NONE' + FRAME_-43917_SEC_AXIS = 'Z' + FRAME_-43917_SEC_VECTOR_DEF = 'CONSTANT' + FRAME_-43917_SEC_FRAME = 'IMAP_GMC' + FRAME_-43917_SEC_SPEC = 'RECTANGULAR' + FRAME_-43917_SEC_VECTOR = (0, 0, 1) + + \begintext + + + Solar Magnetic of Date (SMD) Frame ([3],[5],[6]) + --------------------------------------------------------------------- + + Rotating geocentric frame in which the Z axis is aligned with + Earth's magnetic dipole moment, and the XZ plane contains the + Earth-Sun vector. Specifically, the Earth-Sun vector will vary in + the XZ plane about the X axis of this frame. + + Earth's magnetic dipole axis (the +Z axis of IMAP_GMC) is the + primary vector and aligns with the Z axis of this frame. + + The position of the Sun relative to the Earth is the secondary + vector: the X axis is the component of the Earth-Sun vector + orthogonal to the Z axis. + + The Y axis is Z cross X, completing the right-handed frame. + + All vectors are geometric: no aberration corrections are used. + + \begindata + + FRAME_IMAP_SMD = -43918 + FRAME_-43918_NAME = 'IMAP_SMD' + FRAME_-43918_CLASS = 5 + FRAME_-43918_CLASS_ID = -43918 + FRAME_-43918_CENTER = 399 + FRAME_-43918_RELATIVE = 'J2000' + FRAME_-43918_DEF_STYLE = 'PARAMETERIZED' + FRAME_-43918_FAMILY = 'TWO-VECTOR' + FRAME_-43918_PRI_AXIS = 'Z' + FRAME_-43918_PRI_VECTOR_DEF = 'CONSTANT' + FRAME_-43918_PRI_FRAME = 'IMAP_GMC' + FRAME_-43918_PRI_SPEC = 'RECTANGULAR' + FRAME_-43918_PRI_VECTOR = (0, 0, 1) + FRAME_-43918_SEC_AXIS = 'X' + FRAME_-43918_SEC_VECTOR_DEF = 'OBSERVER_TARGET_POSITION' + FRAME_-43918_SEC_OBSERVER = 'EARTH' + FRAME_-43918_SEC_TARGET = 'SUN' + FRAME_-43918_SEC_ABCORR = 'NONE' + + \begintext + + +Sun Based Frames +======================================================================== + + These dynamic frames are used for analyzing data in a reference + frame tied to the dynamics of the Sun. + + + Heliocentric Radial Tangential Normal (RTN) Frame ([3],[7]) + --------------------------------------------------------------------- + + The position of the spacecraft relative to the Sun is the primary + vector: the X axis points from the Sun center to the spacecraft. + + The solar rotation axis is the secondary vector: the Z axis is + the component of the solar north direction perpendicular to X. + + The Y axis is Z cross X, completing the right-handed reference + frame. + + All vectors are geometric: no aberration corrections are used. + + \begindata + + FRAME_IMAP_RTN = -43920 + FRAME_-43920_NAME = 'IMAP_RTN' + FRAME_-43920_CLASS = 5 + FRAME_-43920_CLASS_ID = -43920 + FRAME_-43920_CENTER = 10 + FRAME_-43920_RELATIVE = 'J2000' + FRAME_-43920_DEF_STYLE = 'PARAMETERIZED' + FRAME_-43920_FAMILY = 'TWO-VECTOR' + FRAME_-43920_PRI_AXIS = 'X' + FRAME_-43920_PRI_VECTOR_DEF = 'OBSERVER_TARGET_POSITION' + FRAME_-43920_PRI_OBSERVER = 'SUN' + FRAME_-43920_PRI_TARGET = 'IMAP' + FRAME_-43920_PRI_ABCORR = 'NONE' + FRAME_-43920_PRI_FRAME = 'IAU_SUN' + FRAME_-43920_SEC_AXIS = 'Z' + FRAME_-43920_SEC_VECTOR_DEF = 'CONSTANT' + FRAME_-43920_SEC_FRAME = 'IAU_SUN' + FRAME_-43920_SEC_SPEC = 'RECTANGULAR' + FRAME_-43920_SEC_VECTOR = ( 0, 0, 1 ) + + \begintext + + + Heliocentric Inertial (HCI) Frame ([3],[5],[7]) + --------------------------------------------------------------------- + + Referred to as "Heliographic Inertial (HGI) frame at epoch J2000" + in [3], but named as in [7] to avoid confusion with HGI of J1900. + + The X-Y Plane lies in the solar equator, +Z axis is parallel to + the Sun's rotation vector. + + The solar rotation axis is the primary vector: the Z axis points + in the solar north direction. + + The ascending node on the Earth ecliptic of J2000 of the solar + equator forms the X axis. This is accomplished by using the +Z + axis of the ecliptic of J2000 as the secondary vector and HCI +Y + as the secondary axis. + + The Y axis is Z cross X, completing the right-handed reference + frame. + + \begindata + + FRAME_IMAP_HCI = -43921 + FRAME_-43921_NAME = 'IMAP_HCI' + FRAME_-43921_CLASS = 5 + FRAME_-43921_CLASS_ID = -43921 + FRAME_-43921_CENTER = 10 + FRAME_-43921_RELATIVE = 'J2000' + FRAME_-43921_DEF_STYLE = 'PARAMETERIZED' + FRAME_-43921_FAMILY = 'TWO-VECTOR' + FRAME_-43921_PRI_AXIS = 'Z' + FRAME_-43921_PRI_VECTOR_DEF = 'CONSTANT' + FRAME_-43921_PRI_FRAME = 'IAU_SUN' + FRAME_-43921_PRI_SPEC = 'RECTANGULAR' + FRAME_-43921_PRI_VECTOR = ( 0, 0, 1 ) + FRAME_-43921_SEC_AXIS = 'Y' + FRAME_-43921_SEC_VECTOR_DEF = 'CONSTANT' + FRAME_-43921_SEC_FRAME = 'ECLIPJ2000' + FRAME_-43921_SEC_SPEC = 'RECTANGULAR' + FRAME_-43921_SEC_VECTOR = ( 0, 0, 1 ) + + \begintext + + + Heliocentric of Date (HCD) Frame ([3],[5],[7]) + --------------------------------------------------------------------- + + Referred to as "Heliographic Inertial (HGI) frame true to + reference date" in [3], but named as in [7] without "inertial." + + The X-Y Plane lies in the solar equator, +Z axis is parallel to + the Sun's rotation vector. + + The solar rotation axis is the primary vector: the Z axis points + in the solar north direction. + + The ascending node on the Earth ecliptic of date of the solar + equator forms the X axis. This is accomplished by using the +Z + axis of the ecliptic of date as the secondary vector and HCD +Y + as the secondary axis. + + The Y axis is Z cross X, completing the right-handed reference + frame. + + \begindata + + FRAME_IMAP_HCD = -43922 + FRAME_-43922_NAME = 'IMAP_HCD' + FRAME_-43922_CLASS = 5 + FRAME_-43922_CLASS_ID = -43922 + FRAME_-43922_CENTER = 10 + FRAME_-43922_RELATIVE = 'J2000' + FRAME_-43922_DEF_STYLE = 'PARAMETERIZED' + FRAME_-43922_FAMILY = 'TWO-VECTOR' + FRAME_-43922_PRI_AXIS = 'Z' + FRAME_-43922_PRI_VECTOR_DEF = 'CONSTANT' + FRAME_-43922_PRI_FRAME = 'IAU_SUN' + FRAME_-43922_PRI_SPEC = 'RECTANGULAR' + FRAME_-43922_PRI_VECTOR = ( 0, 0, 1 ) + FRAME_-43922_SEC_AXIS = 'Y' + FRAME_-43922_SEC_VECTOR_DEF = 'CONSTANT' + FRAME_-43922_SEC_FRAME = 'IMAP_ECLIPDATE' + FRAME_-43922_SEC_SPEC = 'RECTANGULAR' + FRAME_-43922_SEC_VECTOR = ( 0, 0, 1 ) + + \begintext + + + Heliographic Coordinates (HGC) Frame ([3],[7]) + --------------------------------------------------------------------- + + Cartesian counterpart to the spherical coordinates defined in [3], + "Heliographic Spherical (HGS) coordinate frame true to ref. date". + + Alias for SPICE IAU_SUN (Carrington heliographic coordinates) + in which the frame rotates with the surface of the sun with a + sidereal period of exactly 25.38 days. + + The Z axis is the solar rotation axis. + + The X axis is the intersection of the Carrington prime meridian + and the heliographic equator. + + The Y axis is Z cross X, completing the right-handed reference + frame. + + \begindata + + FRAME_IMAP_HGC = -43923 + FRAME_-43923_NAME = 'IMAP_HGC' + FRAME_-43923_CLASS = 4 + FRAME_-43923_CLASS_ID = -43923 + FRAME_-43923_CENTER = 10 + TKFRAME_-43923_RELATIVE = 'IAU_SUN' + TKFRAME_-43923_SPEC = 'MATRIX' + TKFRAME_-43923_MATRIX = ( 1 0 0 + 0 1 0 + 0 0 1 ) + \begintext + + + Heliocentric Aries Ecliptic (HAE) Frame ([3],[7]) + --------------------------------------------------------------------- + + Alias for SPICE ECLIPJ2000. + + The Z axis is the normal to the mean ecliptic at J2000. + + The X axis is the unit vector from Earth to the first point of + Aries at J2000. + + The Y axis is Z cross X, completing the right-handed reference + frame. + + \begindata + + FRAME_IMAP_HAE = -43924 + FRAME_-43924_NAME = 'IMAP_HAE' + FRAME_-43924_CLASS = 4 + FRAME_-43924_CLASS_ID = -43924 + FRAME_-43924_CENTER = 10 + TKFRAME_-43924_RELATIVE = 'ECLIPJ2000' + TKFRAME_-43924_SPEC = 'MATRIX' + TKFRAME_-43924_MATRIX = ( 1 0 0 + 0 1 0 + 0 0 1 ) + \begintext + + + Heliocentric Aries Ecliptic of Date (HAED) Frame ([3],[7]) + --------------------------------------------------------------------- + + Same orientation as IMAP_ECLIPDATE, but with Sun at the center + instead of Earth. + + The Z axis is the normal to the mean ecliptic of date. + + The X axis is the unit vector from Earth to the first point of + Aries of date. + + The Y axis is Z cross X, completing the right-handed reference + frame. + + \begindata + + FRAME_IMAP_HAED = -43925 + FRAME_-43925_NAME = 'IMAP_HAED' + FRAME_-43925_CLASS = 4 + FRAME_-43925_CLASS_ID = -43925 + FRAME_-43925_CENTER = 10 + TKFRAME_-43925_RELATIVE = 'IMAP_ECLIPDATE' + TKFRAME_-43925_SPEC = 'MATRIX' + TKFRAME_-43925_MATRIX = ( 1 0 0 + 0 1 0 + 0 0 1 ) + \begintext + + + Heliocentric Earth Ecliptic (HEE) Frame ([3],[7]) + --------------------------------------------------------------------- + + The position of the Earth relative to the Sun is the primary + vector: the X axis points from the Sun to the Earth. + + The northern surface normal to the mean ecliptic of date is the + secondary vector: the Z axis is the component of this vector + orthogonal to the X axis. + + The Y axis is Z cross X, completing the right-handed reference + frame. + + All vectors are geometric: no aberration corrections are used. + + \begindata + + FRAME_IMAP_HEE = -43926 + FRAME_-43926_NAME = 'IMAP_HEE' + FRAME_-43926_CLASS = 5 + FRAME_-43926_CLASS_ID = -43926 + FRAME_-43926_CENTER = 10 + FRAME_-43926_RELATIVE = 'J2000' + FRAME_-43926_DEF_STYLE = 'PARAMETERIZED' + FRAME_-43926_FAMILY = 'TWO-VECTOR' + FRAME_-43926_PRI_AXIS = 'X' + FRAME_-43926_PRI_VECTOR_DEF = 'OBSERVER_TARGET_POSITION' + FRAME_-43926_PRI_OBSERVER = 'SUN' + FRAME_-43926_PRI_TARGET = 'EARTH' + FRAME_-43926_PRI_ABCORR = 'NONE' + FRAME_-43926_SEC_AXIS = 'Z' + FRAME_-43926_SEC_VECTOR_DEF = 'CONSTANT' + FRAME_-43926_SEC_FRAME = 'IMAP_ECLIPDATE' + FRAME_-43926_SEC_SPEC = 'RECTANGULAR' + FRAME_-43926_SEC_VECTOR = ( 0, 0, 1 ) + + \begintext + + + Heliospheric Ram Ecliptic (HRE) Frame ([3],[8],[9]) + --------------------------------------------------------------------- + + This is a heliocentric frame oriented with respect to the current, + nominal ram direction of the Sun's motion relative to the local + interstellar medium and the ecliptic plane, otherwise known as the + heliospheric "nose" direction. + + The nose direction is the primary vector: the X axis points in the + direction [-0.2477, -0.9647, 0.0896] in the ECLIPJ2000 (IMAP_HAE) + frame. + + The northern surface normal to the mean ecliptic of J2000 is the + secondary vector: the Z axis is the component of this vector + orthogonal to the X axis. + + The Y axis is Z cross X, completing the right-handed reference + frame. + + \begindata + + FRAME_IMAP_HRE = -43927 + FRAME_-43927_NAME = 'IMAP_HRE' + FRAME_-43927_CLASS = 5 + FRAME_-43927_CLASS_ID = -43927 + FRAME_-43927_CENTER = 10 + FRAME_-43927_RELATIVE = 'J2000' + FRAME_-43927_DEF_STYLE = 'PARAMETERIZED' + FRAME_-43927_FAMILY = 'TWO-VECTOR' + FRAME_-43927_PRI_AXIS = 'X' + FRAME_-43927_PRI_VECTOR_DEF = 'CONSTANT' + FRAME_-43927_PRI_FRAME = 'ECLIPJ2000' + FRAME_-43927_PRI_SPEC = 'RECTANGULAR' + FRAME_-43927_PRI_VECTOR = ( -0.2477, -0.9647, 0.0896 ) + FRAME_-43927_SEC_AXIS = 'Z' + FRAME_-43927_SEC_VECTOR_DEF = 'CONSTANT' + FRAME_-43927_SEC_FRAME = 'ECLIPJ2000' + FRAME_-43927_SEC_SPEC = 'RECTANGULAR' + FRAME_-43927_SEC_VECTOR = ( 0, 0, 1 ) + + \begintext + + + Heliospheric Nose Upfield (HNU) Frame ([3],[8],[9]) + --------------------------------------------------------------------- + + Heliocentric frame oriented with respect to the current nominal + ram direction of the Sun's motion relative to the local + interstellar medium and the current best estimate of the + unperturbed magnetic field direction in the upstream local + interstellar medium. + + The nominal upfield direction of the ISM B-field is the primary + vector: the Z axis points in the direction + [-0.5583, -0.6046, 0.5681] in the ECLIPJ2000 (IMAP_HAE) frame. + + The nose direction [-0.2477, -0.9647, 0.0896] in the ECLIPJ2000 + (IMAP_HAE) frame is the secondary vector: the X axis is the + component of this vector orthogonal to the Z axis. + + The Y axis is Z cross X, completing the right-handed reference + frame. + + \begindata + + FRAME_IMAP_HNU = -43928 + FRAME_-43928_NAME = 'IMAP_HNU' + FRAME_-43928_CLASS = 5 + FRAME_-43928_CLASS_ID = -43928 + FRAME_-43928_CENTER = 10 + FRAME_-43928_RELATIVE = 'J2000' + FRAME_-43928_DEF_STYLE = 'PARAMETERIZED' + FRAME_-43928_FAMILY = 'TWO-VECTOR' + FRAME_-43928_PRI_AXIS = 'Z' + FRAME_-43928_PRI_VECTOR_DEF = 'CONSTANT' + FRAME_-43928_PRI_FRAME = 'ECLIPJ2000' + FRAME_-43928_PRI_SPEC = 'RECTANGULAR' + FRAME_-43928_PRI_VECTOR = ( -0.5583, -0.6046, 0.5681 ) + FRAME_-43928_SEC_AXIS = 'X' + FRAME_-43928_SEC_VECTOR_DEF = 'CONSTANT' + FRAME_-43928_SEC_FRAME = 'ECLIPJ2000' + FRAME_-43928_SEC_SPEC = 'RECTANGULAR' + FRAME_-43928_SEC_VECTOR = ( -0.2477, -0.9647, 0.0896 ) + + \begintext + + + Galactic Coordinate System (GCS) Frame ([3]) + --------------------------------------------------------------------- + + Alias for SPICE galactic system II frame GALACTIC. + + The primary axis is the normal to the galactic equatorial plane: + Z axis is this unit vector. + + The secondary axis is the vector from the Sun to the galatic + center (represented by Sagittarious): X axis is the component of + this vector orthogonal to the Z axis. + + The Y axis is Z cross X, completing the right-handed reference + frame. + + \begindata + + FRAME_IMAP_GCS = -43929 + FRAME_-43929_NAME = 'IMAP_GCS' + FRAME_-43929_CLASS = 4 + FRAME_-43929_CLASS_ID = -43929 + FRAME_-43929_CENTER = 10 + TKFRAME_-43929_RELATIVE = 'GALACTIC' + TKFRAME_-43929_SPEC = 'MATRIX' + TKFRAME_-43929_MATRIX = ( 1 0 0 + 0 1 0 + 0 0 1 ) + \begintext + + END OF FILE \ No newline at end of file diff --git a/imap_processing/ultra/l1c/sim_spice_kernels/imap_science_120.tf b/imap_processing/ultra/l1c/sim_spice_kernels/imap_science_120.tf new file mode 100644 index 0000000000..70bede066b --- /dev/null +++ b/imap_processing/ultra/l1c/sim_spice_kernels/imap_science_120.tf @@ -0,0 +1,1084 @@ +KPL/FK + +Interstellar Mapping and Acceleration Probe (IMAP) Dynamic Frames Kernel +======================================================================== + + This kernel contains SPICE frame definitions to support the + IMAP mission. + + This kernel is composed of primarily dynamic frames, but in general + it holds frame definitions for all instrument-agnostic frames, CK + frames used in science data processing and mapping. + + +Version and Date +------------------------------------------------------------------------ + + The TEXT_KERNEL_ID stores version information of loaded project + text kernels. Each entry associated with the keyword is a string + that consists of four parts: the kernel name, version, entry date, + and type. + + IMAP Dynamic Frame Kernel Version: + + \begindata + + TEXT_KERNEL_ID = 'IMAP_DYNAMIC_FRAMES V1.2.0 2026-FEB-25 FK' + + \begintext + + Version 0.0.0 -- April 10, 2024 -- Nick Dutton (JHU/APL) + Version 0.0.1 -- June 26, 2025 -- Nick Dutton (JHU/APL) + Version 1.0.0 -- July 8, 2025 -- Nick and Doug (JHU/APL) + Version 1.2.0 -- February 25, 2026 -- Nick Dutton (JHU/APL) + + +References +------------------------------------------------------------------------ + + 1. NAIF SPICE `Kernel Pool Required Reading' + + 2. NAIF SPICE `Frames Required Reading' + + 3. "IMAP Coordinate Frame Science.pdf" + + 4. stereo_rtn.tf, at + https://soho.nascom.nasa.gov/solarsoft/stereo/... + ...gen/data/spice/gen/stereo_rtn.tf + + 5. heliospheric.tf, at + https://soho.nascom.nasa.gov/solarsoft/stereo/... + ...gen/data/spice/gen/heliospheric.tf + + 6. "Geophysical Coordinate Transformations", C. T. Russell + + 7. "Heliospheric Coordinate Systems", M. Franz and D. Harper + + 8. "Global observations of the interstellar interaction from the + Interstellar Boundary Explorer (IBEX)", D. J. McComas, et al. + + 9. "Very Local Interstellar Medium Revealed by a Complete Solar + Cycle of Interstellar Neutral Helium Observations with IBEX", + P. Swaczyna, et al. + + 10. Lagrange L1 definition and SPK, Min-Kun Chung, + https://naif.jpl.nasa.gov/pub/naif/... + ...generic_kernels/spk/lagrange_point/ + + +Contact Information +------------------------------------------------------------------------ + + Direct questions, comments, or concerns about the contents of this + kernel to: + + Nick Dutton, JHUAPL, Nicholas.Dutton@jhuapl.edu + + or + + Doug Rodgers, JHUAPL, Douglas.Rodgers@jhuapl.edu + + or + + Lillian Nguyen, JHUAPL, Lillian.Nguyen@jhuapl.edu + + +Implementation Notes +------------------------------------------------------------------------ + + This file is used by the SPICE system as follows: programs that make + use of this frame kernel must `load' the kernel normally during + program initialization. Loading the kernel associates the data items + with their names in a data structure called the `kernel pool'. The + SPICELIB routine FURNSH loads a kernel into the pool as shown below: + + Python: (SpiceyPy) + + spiceypy.furnsh( frame_kernel_name ) + + IDL: (ICY) + + cspice_furnsh, frame_kernel_name + + MATLAB: (MICE) + + cspice_furnsh ( frame_kernel_name ) + + C: (CSPICE) + + furnsh_c ( frame_kernel_name ); + + FORTRAN: (SPICELIB) + + CALL FURNSH ( frame_kernel_name ) + + This file was created, and may be updated with, a text editor or word + processor. + + +IMAP Science Frames +======================================================================== + + This frame kernel defines a series of frames listed in [3] that + support IMAP data reduction and analysis. All of the frame names + assigned an IMAP NAIF ID (beginning with -43) defined by this kernel + are prefixed with 'IMAP_' to avoid conflict with alternative + definitions not specific to the project. + + The project-specific ID codes -43900 to -43999 have been set aside to + support these dynamic frames. + + + Frame Name Relative To Type NAIF ID + ====================== =============== ======== ======= + + IMAP Based Frames: + ---------------------- + IMAP_OMD IMAP_SPACECRAFT FIXED -43900 + IMAP_DPS [n/a] CK -43901 + + Earth Based Frames: + ---------------------- + IMAP_EARTHFIXED IAU_EARTH FIXED -43910 + IMAP_ECLIPDATE J2000 DYNAMIC -43911 + IMAP_MDI ECLIPJ2000 FIXED -43912 + IMAP_MDR J2000 DYNAMIC -43913 + IMAP_GMC IAU_EARTH DYNAMIC -43914 + IMAP_GEI J2000 FIXED -43915 + IMAP_GSE J2000 DYNAMIC -43916 + IMAP_GSM J2000 DYNAMIC -43917 + IMAP_SMD J2000 DYNAMIC -43918 + + Sun Based Frames: + ---------------------- + IMAP_RTN J2000 DYNAMIC -43920 + IMAP_HCI (ie, HGI_J2K) J2000 DYNAMIC -43921 + IMAP_HCD (ie, HGI_D) J2000 DYNAMIC -43922 + IMAP_HGC (ie, HGS_D) IAU_SUN FIXED -43923 + IMAP_HAE ECLIPJ2000 FIXED -43924 + IMAP_HAED IMAP_ECLIPDATE FIXED -43925 + IMAP_HEE J2000 DYNAMIC -43926 + IMAP_HRE J2000 DYNAMIC -43927 + IMAP_HNU J2000 DYNAMIC -43928 + IMAP_GCS GALACTIC FIXED -43929 + IMAP_HRC J2000 DYNAMIC -43930 + + +IMAP Based Frames +======================================================================== + + These dynamic frames are used for analyzing data in a reference + frame tied to the dynamics of IMAP. + + + Observatory Mechanical Design (OMD) Frame ([3]) + --------------------------------------------------------------------- + + Alias for IMAP_SPACECRAFT frame defined in the primary + 'imap_vNNN.tf' frame kernel. From that file: + + Origin: Center of the launch vehicle adapter ring at the + observatory/launch vehicle interface plane + + +Z axis: Perpendicular to the launch vehicle interface plane + pointed in the direction of the top deck (runs through + the center of the central cylinder structure element) + + +Y axis: Direction of the vector orthogonal to the +Z axis and + parallel to the deployed MAG boom + + +X axis: The third orthogonal axis defined using an X, Y, Z + ordered right hand rule + + \begindata + + FRAME_IMAP_EARTHFIXED = -43900 + FRAME_-43900_NAME = 'IMAP_OMD' + FRAME_-43900_CLASS = 4 + FRAME_-43900_CLASS_ID = -43900 + FRAME_-43900_CENTER = -43 + TKFRAME_-43900_RELATIVE = 'IMAP_SPACECRAFT' + TKFRAME_-43900_SPEC = 'MATRIX' + TKFRAME_-43900_MATRIX = ( 1 0 0 + 0 1 0 + 0 0 1 ) + + \begintext + + + Despun Pointing Sets (DPS) Frame ([3]) + --------------------------------------------------------------------- + + Coordinate frame used for ENA imager data processing and + intentionally designed for use in producing all-sky map products. + + This is provided by a CK file external to this file. Notionally, + the frame is defined: + + +Z axis is parallel to the nominal spin axis of the spacecraft. + The axis is notionally a time-average of the spin axis of the + exact orientation (IMAP_SPACECRAFT or IMAP_OMD). + + Y = Z cross Necliptic where Necliptic is the the unit normal + (North) to the ecliptic plane. + + This is a quasi-inertial reference frame and will have a unique + transformation matrix, valid between repointings of the spacecraft + + \begindata + + FRAME_IMAP_DPS = -43901 + FRAME_-43901_NAME = 'IMAP_DPS' + FRAME_-43901_CLASS = 3 + FRAME_-43901_CLASS_ID = -43901 + FRAME_-43901_CENTER = -43 + CK_-43901_SCLK = -43 + CK_-43901_SPK = -43 + + \begintext + + +Earth Based Frames +======================================================================== + + These dynamic frames are used for analyzing data in a reference + frame tied to the dynamics of Earth. + + + Earth-Fixed Frame (IMAP_EARTHFIXED) + --------------------------------------------------------------------- + + Some of these Earth based dynamic frames reference vectors in an + Earth-fixed frame. To support loading of either rotation model + (IAU_EARTH or ITRF93), the following keywords control which model + is used. The model is enabled by surrounding its keyword-value + block with the \begindata and \begintext markers (currently + IAU_EARTH). + + IAU_EARTH based model is currently employed: + + \begindata + + FRAME_IMAP_EARTHFIXED = -43910 + FRAME_-43910_NAME = 'IMAP_EARTHFIXED' + FRAME_-43910_CLASS = 4 + FRAME_-43910_CLASS_ID = -43910 + FRAME_-43910_CENTER = 399 + TKFRAME_-43910_RELATIVE = 'IAU_EARTH' + TKFRAME_-43910_SPEC = 'MATRIX' + TKFRAME_-43910_MATRIX = ( 1 0 0 + 0 1 0 + 0 0 1 ) + + \begintext + + Alternately, the more precise ITRF93-based model could be used: + + FRAME_IMAP_EARTHFIXED = -43910 + FRAME_-43910_NAME = 'IMAP_EARTHFIXED' + FRAME_-43910_CLASS = 4 + FRAME_-43910_CLASS_ID = -43910 + FRAME_-43910_CENTER = 399 + TKFRAME_-43910_RELATIVE = 'ITRF93' + TKFRAME_-43910_SPEC = 'MATRIX' + TKFRAME_-43910_MATRIX = ( 1 0 0 + 0 1 0 + 0 0 1 ) + + However, using the ITRF93 frame requires supplying SPICE with + sufficient binary PCK data to cover the period of interest. + The IAU_EARTH frame just requires a text PCK with Earth data + to be loaded. + + + Mean Ecliptic of Date (IMAP_ECLIPDATE) ([2],[5]) + --------------------------------------------------------------------- + + Mean Ecliptic of Date is the more precise, rotating counterpart + to the inertial Mean Ecliptic and Equinox of J2000 (ECLIPJ2000). + + If computations involving this frame (or frames relative to this) + are too expensive, the user may instruct SPICE to ignore + rotational effects by changing 'ROTATING' to 'INERTIAL'. + + The X axis is the first point in Aries for the mean ecliptic of + date and the Z axis points along the ecliptic north pole. + + The Y axis is Z cross X, completing the right-handed reference + frame. + + \begindata + + FRAME_IMAP_ECLIPDATE = -43911 + FRAME_-43911_NAME = 'IMAP_ECLIPDATE' + FRAME_-43911_CLASS = 5 + FRAME_-43911_CLASS_ID = -43911 + FRAME_-43911_CENTER = 399 + FRAME_-43911_RELATIVE = 'J2000' + FRAME_-43911_DEF_STYLE = 'PARAMETERIZED' + FRAME_-43911_FAMILY = 'MEAN_ECLIPTIC_AND_EQUINOX_OF_DATE' + FRAME_-43911_PREC_MODEL = 'EARTH_IAU_1976' + FRAME_-43911_OBLIQ_MODEL = 'EARTH_IAU_1980' + FRAME_-43911_ROTATION_STATE = 'ROTATING' + + \begintext + + + Mission Design Inertial (MDI) Frame ([3]) + --------------------------------------------------------------------- + + Alias for SPICE ECLIPJ2000. + + Primary coordinate frame used to define IMAP's trajectory and + orbit, as well as for some science data products. + + The X axis is the first point in Aries for the mean ecliptic of + J2000 and the Z axis points along the ecliptic north pole. + + The Y axis is Z cross X, completing the right-handed reference + frame. + + \begindata + + FRAME_IMAP_MDI = -43912 + FRAME_-43912_NAME = 'IMAP_MDI' + FRAME_-43912_CLASS = 4 + FRAME_-43912_CLASS_ID = -43912 + FRAME_-43912_CENTER = 399 + TKFRAME_-43912_RELATIVE = 'IMAP_EARTHFIXED' + TKFRAME_-43912_SPEC = 'MATRIX' + TKFRAME_-43912_MATRIX = ( 1 0 0 + 0 1 0 + 0 0 1 ) + + \begintext + + + Mission Design Rotating (MDR) Frame ([3],[10]) + --------------------------------------------------------------------- + + IMAP observatory body coordinate frame. + + The origin of the frame is the L1 point of the Sun and the Earth- + Moon barycenter defined in SPK 'L1_de431.bsp' by reference [10]; + this author assigned the NAIF body code 391 to this L1 point. + + The position of the Earth-Moon barycenter relative to the Sun is + the primary vector: the X axis points from the Sun to the + Earth-Moon barycenter. + + The northern surface normal to the mean ecliptic of date is the + secondary vector: the Z axis is the component of this vector + orthogonal to the X axis. Combined with the definition of the + X axis, this yields a unit vector along the angular momentum + vector of the Earth-Moon barycenter orbiting the Sun. + + The Y axis is Z cross X, completing the right-handed reference + frame. + + All vectors are geometric: no aberration corrections are used. + + \begindata + + FRAME_IMAP_MDR = -43913 + FRAME_-43913_NAME = 'IMAP_MDR' + FRAME_-43913_CLASS = 5 + FRAME_-43913_CLASS_ID = -43913 + FRAME_-43913_CENTER = 391 + FRAME_-43913_RELATIVE = 'J2000' + FRAME_-43913_DEF_STYLE = 'PARAMETERIZED' + FRAME_-43913_FAMILY = 'TWO-VECTOR' + FRAME_-43913_PRI_AXIS = 'X' + FRAME_-43913_PRI_VECTOR_DEF = 'OBSERVER_TARGET_POSITION' + FRAME_-43913_PRI_OBSERVER = 'SUN' + FRAME_-43913_PRI_TARGET = 'EARTH MOON BARYCENTER' + FRAME_-43913_PRI_ABCORR = 'NONE' + FRAME_-43913_SEC_AXIS = 'Z' + FRAME_-43913_SEC_VECTOR_DEF = 'CONSTANT' + FRAME_-43913_SEC_FRAME = 'IMAP_ECLIPDATE' + FRAME_-43913_SEC_SPEC = 'RECTANGULAR' + FRAME_-43913_SEC_VECTOR = ( 0, 0, 1 ) + + \begintext + + + Geomagnetic Coordinate (GMC) Frame (IGRF-14 Modeled Pole) ([6]) + --------------------------------------------------------------------- + + The geomagnetic coordinate (GMC) system is defined so that its + Z-axis is parallel to the magnetic dipole. The geographic + coordinates, D, of the dipole axis are found from the + International Geomagnetic Reference Field. + + The Y-axis of this system is perpendicular to the geographic poles + such that if D is the dipole position and S is the south pole + Y=DxS. The X-axis completes a right-handed orthogonal set. + + The implementation of this frame is complicated in that the + definition of the IGRF dipole is a function of time and the IGRF + model cannot be directly incorporated into SPICE. However, SPICE + does allow one to define time dependent Euler angles. Meaning, you + can define a single Euler angle that rotates the Geocentric + Equatorial Inertial (GEI) system to GMC for a given ephem time t: + + V = r(t) * V + GEI GMC + + where r(t) is a time dependent Euler angle representation of a + rotation. SPICE allows for the time dependence to be represented + by a polynomial expansion. This expansion can be fit using the + IGRF model, thus representing the IGRF dipole axis. + + IGRF-14 (the 14th version) was fit for the period of 1990-2035, + which encompasses the mission and will also make this kernel + useful for performing Magnetic dipole frame transformations for + the 1990's and the 2000's. However, IGRF-14 is not as accurate for + this entire time interval. The years between 1945-2020 are labeled + definitive, although only back to 1990 was used in the polynomial + fit. 2020-2025 is provisional, and may change with IGRF-15. + 2025-2030 was only a prediction. Beyond 2030, the predict is so + far in the future as to not be valid. So to make the polynomials + behave nicely in this region (in case someone does try to use this + frame during that time), the 2030 prediction was extended until + 2035. So for low precision, this kernel can be used for the years + 2025-2035. Any times less than 1990 and greater than 2035 were not + used in the fit, and therefore may be vastly incorrect as the + polynomials may diverge outside of this region. These coefficients + will be refit when IGRF-15 is released. + + Also, since the rest of the magnetic dipole frames are defined + from this one, similar time ranges should be used for those frames + + Definitive Provisional Predict Not Valid + |--------------------------|+++++++++++|###########|???????????| + 1990 2020 2025 2030 2035 + + In addition to the error inherit in the model itself, the + polynomial expansion cannot perfectly be fit the IGRF dipole. The + maximum error on the fit is 0.2 milliradians, or 0.01 degrees, + while the average error is 59 microradians or 0.003 degrees. + + The GMC frame is achieved by first rotating the IAU_EARTH frame + about Z by the longitude degrees, and then rotating about the + Y axis by the amount of latitude. + + NOTE: ITRF93 is much more accurate than IAU_EARTH, if precise + Earth-Fixed coordinates are desired, then ITRF93 should be + incorporated by changing RELATIVE of the IMAP_EARTHFIXED frame. + + \begindata + + FRAME_IMAP_GMC = -43914 + FRAME_-43914_NAME = 'IMAP_GMC' + FRAME_-43914_CLASS = 5 + FRAME_-43914_CLASS_ID = -43914 + FRAME_-43914_CENTER = 399 + FRAME_-43914_RELATIVE = 'IMAP_EARTHFIXED' + FRAME_-43914_DEF_STYLE = 'PARAMETERIZED' + FRAME_-43914_FAMILY = 'EULER' + FRAME_-43914_EPOCH = @2010-JAN-1/00:00:00 + FRAME_-43914_AXES = ( 3, 2, 1 ) + FRAME_-43914_UNITS = 'DEGREES' + FRAME_-43914_ANGLE_1_COEFFS = ( +72.21459071369075 + +2.5468902895893966E-9 + -9.716151847392007E-19 + -1.0433860683683533E-26 + +2.362766949492718E-36 + +3.3213862072412154E-44 + -3.5122239525813096E-54 + -4.264324158308002E-62 + +2.495064964115813E-72 + +1.8605789215176264E-80 ) + FRAME_-43914_ANGLE_2_COEFFS = ( -9.981781660857344 + +1.8136204417470554E-9 + +7.130241121790372E-19 + -2.215929597148403E-27 + -3.900143352851885E-36 + +6.599160686982152E-45 + +8.376429421972708E-54 + -1.07431639798394E-62 + -5.913960690205374E-72 + +6.775302680782905E-81 ) + FRAME_-43914_ANGLE_3_COEFFS = ( 0 ) + + \begintext + + + Geocentric Equatorial Inertial (GEI) Frame ([3],[6]) + --------------------------------------------------------------------- + + Alias for SPICE J2000 frame. + + The Geocentric Equatorial Inertial System (GEI) has its X-axis + pointing from the Earth towards the first point of Aries (the + position of the Sun at the vernal equinox). This direction is the + intersection of the Earth's equatorial plane and the ecliptic + plane and thus the X-axis lies in both planes. The Z-axis is + parallel to the rotation axis of the Earth and Y completes the + right-handed orthogonal set (Y = Z x X). + + \begindata + + FRAME_IMAP_GEI = -43915 + FRAME_-43915_NAME = 'IMAP_GEI' + FRAME_-43915_CLASS = 4 + FRAME_-43915_CLASS_ID = -43915 + FRAME_-43915_CENTER = 399 + TKFRAME_-43915_RELATIVE = 'J2000' + TKFRAME_-43915_SPEC = 'MATRIX' + TKFRAME_-43915_MATRIX = ( 1 0 0 + 0 1 0 + 0 0 1 ) + + \begintext + + + Geocentric Solar Ecliptic (GSE) Frame ([3],[5]) + --------------------------------------------------------------------- + + Rotating geocentric frame in which Sun and Earth are fixed and the + Z axis is the unit normal to the Ecliptic plane. + + The position of the Sun relative to the Earth is the primary + vector: the X axis points from the Earth to the Sun. + + The northern surface normal to the mean ecliptic of date + (IMAP_ECLIPDATE) is the secondary vector: the Z axis is the + component of this vector orthogonal to the X axis. + + The Y axis is Z cross X, completing the right-handed frame. + + All vectors are geometric: no aberration corrections are used. + + \begindata + + FRAME_IMAP_GSE = -43916 + FRAME_-43916_NAME = 'IMAP_GSE' + FRAME_-43916_CLASS = 5 + FRAME_-43916_CLASS_ID = -43916 + FRAME_-43916_CENTER = 399 + FRAME_-43916_RELATIVE = 'J2000' + FRAME_-43916_DEF_STYLE = 'PARAMETERIZED' + FRAME_-43916_FAMILY = 'TWO-VECTOR' + FRAME_-43916_PRI_AXIS = 'X' + FRAME_-43916_PRI_VECTOR_DEF = 'OBSERVER_TARGET_POSITION' + FRAME_-43916_PRI_OBSERVER = 'EARTH' + FRAME_-43916_PRI_TARGET = 'SUN' + FRAME_-43916_PRI_ABCORR = 'NONE' + FRAME_-43916_SEC_AXIS = 'Z' + FRAME_-43916_SEC_VECTOR_DEF = 'CONSTANT' + FRAME_-43916_SEC_FRAME = 'IMAP_ECLIPDATE' + FRAME_-43916_SEC_SPEC = 'RECTANGULAR' + FRAME_-43916_SEC_VECTOR = ( 0, 0, 1 ) + + \begintext + + + Geocentric Solar Magnetospheric (GSM) Frame ([3],[5],[6]) + --------------------------------------------------------------------- + + Rotating geocentric frame in which Sun and Earth are fixed and the + XZ plane contains Earth's magnetic dipole moment. Specifically, + the dipole moment will vary in the XZ plane about the Z axis of + this frame. + + The position of the Sun relative to the Earth is the primary + vector: the X axis points from the Earth to the Sun. + + Earth's magnetic dipole axis (the +Z axis of IMAP_GMC) is the + secondary vector: the Z axis is the component of this vector + orthogonal to the X axis. + + The Y axis is Z cross X, completing the right-handed frame. + + All vectors are geometric: no aberration corrections are used. + + \begindata + + FRAME_IMAP_GSM = -43917 + FRAME_-43917_NAME = 'IMAP_GSM' + FRAME_-43917_CLASS = 5 + FRAME_-43917_CLASS_ID = -43917 + FRAME_-43917_CENTER = 399 + FRAME_-43917_RELATIVE = 'J2000' + FRAME_-43917_DEF_STYLE = 'PARAMETERIZED' + FRAME_-43917_FAMILY = 'TWO-VECTOR' + FRAME_-43917_PRI_AXIS = 'X' + FRAME_-43917_PRI_VECTOR_DEF = 'OBSERVER_TARGET_POSITION' + FRAME_-43917_PRI_OBSERVER = 'EARTH' + FRAME_-43917_PRI_TARGET = 'SUN' + FRAME_-43917_PRI_ABCORR = 'NONE' + FRAME_-43917_SEC_AXIS = 'Z' + FRAME_-43917_SEC_VECTOR_DEF = 'CONSTANT' + FRAME_-43917_SEC_FRAME = 'IMAP_GMC' + FRAME_-43917_SEC_SPEC = 'RECTANGULAR' + FRAME_-43917_SEC_VECTOR = (0, 0, 1) + + \begintext + + + Solar Magnetic of Date (SMD) Frame ([3],[5],[6]) + --------------------------------------------------------------------- + + Rotating geocentric frame in which the Z axis is aligned with + Earth's magnetic dipole moment, and the XZ plane contains the + Earth-Sun vector. Specifically, the Earth-Sun vector will vary in + the XZ plane about the X axis of this frame. + + Earth's magnetic dipole axis (the +Z axis of IMAP_GMC) is the + primary vector and aligns with the Z axis of this frame. + + The position of the Sun relative to the Earth is the secondary + vector: the X axis is the component of the Earth-Sun vector + orthogonal to the Z axis. + + The Y axis is Z cross X, completing the right-handed frame. + + All vectors are geometric: no aberration corrections are used. + + \begindata + + FRAME_IMAP_SMD = -43918 + FRAME_-43918_NAME = 'IMAP_SMD' + FRAME_-43918_CLASS = 5 + FRAME_-43918_CLASS_ID = -43918 + FRAME_-43918_CENTER = 399 + FRAME_-43918_RELATIVE = 'J2000' + FRAME_-43918_DEF_STYLE = 'PARAMETERIZED' + FRAME_-43918_FAMILY = 'TWO-VECTOR' + FRAME_-43918_PRI_AXIS = 'Z' + FRAME_-43918_PRI_VECTOR_DEF = 'CONSTANT' + FRAME_-43918_PRI_FRAME = 'IMAP_GMC' + FRAME_-43918_PRI_SPEC = 'RECTANGULAR' + FRAME_-43918_PRI_VECTOR = (0, 0, 1) + FRAME_-43918_SEC_AXIS = 'X' + FRAME_-43918_SEC_VECTOR_DEF = 'OBSERVER_TARGET_POSITION' + FRAME_-43918_SEC_OBSERVER = 'EARTH' + FRAME_-43918_SEC_TARGET = 'SUN' + FRAME_-43918_SEC_ABCORR = 'NONE' + + \begintext + + +Sun Based Frames +======================================================================== + + These dynamic frames are used for analyzing data in a reference + frame tied to the dynamics of the Sun. + + + Heliocentric Radial Tangential Normal (RTN) Frame ([3],[7]) + --------------------------------------------------------------------- + + The position of the spacecraft relative to the Sun is the primary + vector: the X axis points from the Sun center to the spacecraft. + + The solar rotation axis is the secondary vector: the Z axis is + the component of the solar north direction perpendicular to X. + + The Y axis is Z cross X, completing the right-handed reference + frame. + + All vectors are geometric: no aberration corrections are used. + + \begindata + + FRAME_IMAP_RTN = -43920 + FRAME_-43920_NAME = 'IMAP_RTN' + FRAME_-43920_CLASS = 5 + FRAME_-43920_CLASS_ID = -43920 + FRAME_-43920_CENTER = 10 + FRAME_-43920_RELATIVE = 'J2000' + FRAME_-43920_DEF_STYLE = 'PARAMETERIZED' + FRAME_-43920_FAMILY = 'TWO-VECTOR' + FRAME_-43920_PRI_AXIS = 'X' + FRAME_-43920_PRI_VECTOR_DEF = 'OBSERVER_TARGET_POSITION' + FRAME_-43920_PRI_OBSERVER = 'SUN' + FRAME_-43920_PRI_TARGET = 'IMAP' + FRAME_-43920_PRI_ABCORR = 'NONE' + FRAME_-43920_PRI_FRAME = 'IAU_SUN' + FRAME_-43920_SEC_AXIS = 'Z' + FRAME_-43920_SEC_VECTOR_DEF = 'CONSTANT' + FRAME_-43920_SEC_FRAME = 'IAU_SUN' + FRAME_-43920_SEC_SPEC = 'RECTANGULAR' + FRAME_-43920_SEC_VECTOR = ( 0, 0, 1 ) + + \begintext + + + Heliocentric Inertial (HCI) Frame ([3],[5],[7]) + --------------------------------------------------------------------- + + Referred to as "Heliographic Inertial (HGI) frame at epoch J2000" + in [3], but named as in [7] to avoid confusion with HGI of J1900. + + The X-Y Plane lies in the solar equator, +Z axis is parallel to + the Sun's rotation vector. + + The solar rotation axis is the primary vector: the Z axis points + in the solar north direction. + + The ascending node on the Earth ecliptic of J2000 of the solar + equator forms the X axis. This is accomplished by using the +Z + axis of the ecliptic of J2000 as the secondary vector and HCI +Y + as the secondary axis. + + The Y axis is Z cross X, completing the right-handed reference + frame. + + \begindata + + FRAME_IMAP_HCI = -43921 + FRAME_-43921_NAME = 'IMAP_HCI' + FRAME_-43921_CLASS = 5 + FRAME_-43921_CLASS_ID = -43921 + FRAME_-43921_CENTER = 10 + FRAME_-43921_RELATIVE = 'J2000' + FRAME_-43921_DEF_STYLE = 'PARAMETERIZED' + FRAME_-43921_FAMILY = 'TWO-VECTOR' + FRAME_-43921_PRI_AXIS = 'Z' + FRAME_-43921_PRI_VECTOR_DEF = 'CONSTANT' + FRAME_-43921_PRI_FRAME = 'IAU_SUN' + FRAME_-43921_PRI_SPEC = 'RECTANGULAR' + FRAME_-43921_PRI_VECTOR = ( 0, 0, 1 ) + FRAME_-43921_SEC_AXIS = 'Y' + FRAME_-43921_SEC_VECTOR_DEF = 'CONSTANT' + FRAME_-43921_SEC_FRAME = 'ECLIPJ2000' + FRAME_-43921_SEC_SPEC = 'RECTANGULAR' + FRAME_-43921_SEC_VECTOR = ( 0, 0, 1 ) + + \begintext + + + Heliocentric of Date (HCD) Frame ([3],[5],[7]) + --------------------------------------------------------------------- + + Referred to as "Heliographic Inertial (HGI) frame true to + reference date" in [3], but named as in [7] without "inertial." + + The X-Y Plane lies in the solar equator, +Z axis is parallel to + the Sun's rotation vector. + + The solar rotation axis is the primary vector: the Z axis points + in the solar north direction. + + The ascending node on the Earth ecliptic of date of the solar + equator forms the X axis. This is accomplished by using the +Z + axis of the ecliptic of date as the secondary vector and HCD +Y + as the secondary axis. + + The Y axis is Z cross X, completing the right-handed reference + frame. + + \begindata + + FRAME_IMAP_HCD = -43922 + FRAME_-43922_NAME = 'IMAP_HCD' + FRAME_-43922_CLASS = 5 + FRAME_-43922_CLASS_ID = -43922 + FRAME_-43922_CENTER = 10 + FRAME_-43922_RELATIVE = 'J2000' + FRAME_-43922_DEF_STYLE = 'PARAMETERIZED' + FRAME_-43922_FAMILY = 'TWO-VECTOR' + FRAME_-43922_PRI_AXIS = 'Z' + FRAME_-43922_PRI_VECTOR_DEF = 'CONSTANT' + FRAME_-43922_PRI_FRAME = 'IAU_SUN' + FRAME_-43922_PRI_SPEC = 'RECTANGULAR' + FRAME_-43922_PRI_VECTOR = ( 0, 0, 1 ) + FRAME_-43922_SEC_AXIS = 'Y' + FRAME_-43922_SEC_VECTOR_DEF = 'CONSTANT' + FRAME_-43922_SEC_FRAME = 'IMAP_ECLIPDATE' + FRAME_-43922_SEC_SPEC = 'RECTANGULAR' + FRAME_-43922_SEC_VECTOR = ( 0, 0, 1 ) + + \begintext + + + Heliographic Coordinates (HGC) Frame ([3],[7]) + --------------------------------------------------------------------- + + Cartesian counterpart to the spherical coordinates defined in [3], + "Heliographic Spherical (HGS) coordinate frame true to ref. date". + + Alias for SPICE IAU_SUN (Carrington heliographic coordinates) + in which the frame rotates with the surface of the sun with a + sidereal period of exactly 25.38 days. + + The Z axis is the solar rotation axis. + + The X axis is the intersection of the Carrington prime meridian + and the heliographic equator. + + The Y axis is Z cross X, completing the right-handed reference + frame. + + \begindata + + FRAME_IMAP_HGC = -43923 + FRAME_-43923_NAME = 'IMAP_HGC' + FRAME_-43923_CLASS = 4 + FRAME_-43923_CLASS_ID = -43923 + FRAME_-43923_CENTER = 10 + TKFRAME_-43923_RELATIVE = 'IAU_SUN' + TKFRAME_-43923_SPEC = 'MATRIX' + TKFRAME_-43923_MATRIX = ( 1 0 0 + 0 1 0 + 0 0 1 ) + \begintext + + + Heliocentric Aries Ecliptic (HAE) Frame ([3],[7]) + --------------------------------------------------------------------- + + Alias for SPICE ECLIPJ2000. + + The Z axis is the normal to the mean ecliptic at J2000. + + The X axis is the unit vector from Earth to the first point of + Aries at J2000. + + The Y axis is Z cross X, completing the right-handed reference + frame. + + \begindata + + FRAME_IMAP_HAE = -43924 + FRAME_-43924_NAME = 'IMAP_HAE' + FRAME_-43924_CLASS = 4 + FRAME_-43924_CLASS_ID = -43924 + FRAME_-43924_CENTER = 10 + TKFRAME_-43924_RELATIVE = 'ECLIPJ2000' + TKFRAME_-43924_SPEC = 'MATRIX' + TKFRAME_-43924_MATRIX = ( 1 0 0 + 0 1 0 + 0 0 1 ) + \begintext + + + Heliocentric Aries Ecliptic of Date (HAED) Frame ([3],[7]) + --------------------------------------------------------------------- + + Same orientation as IMAP_ECLIPDATE, but with Sun at the center + instead of Earth. + + The Z axis is the normal to the mean ecliptic of date. + + The X axis is the unit vector from Earth to the first point of + Aries of date. + + The Y axis is Z cross X, completing the right-handed reference + frame. + + \begindata + + FRAME_IMAP_HAED = -43925 + FRAME_-43925_NAME = 'IMAP_HAED' + FRAME_-43925_CLASS = 4 + FRAME_-43925_CLASS_ID = -43925 + FRAME_-43925_CENTER = 10 + TKFRAME_-43925_RELATIVE = 'IMAP_ECLIPDATE' + TKFRAME_-43925_SPEC = 'MATRIX' + TKFRAME_-43925_MATRIX = ( 1 0 0 + 0 1 0 + 0 0 1 ) + \begintext + + + Heliocentric Earth Ecliptic (HEE) Frame ([3],[7]) + --------------------------------------------------------------------- + + The position of the Earth relative to the Sun is the primary + vector: the X axis points from the Sun to the Earth. + + The northern surface normal to the mean ecliptic of date is the + secondary vector: the Z axis is the component of this vector + orthogonal to the X axis. + + The Y axis is Z cross X, completing the right-handed reference + frame. + + All vectors are geometric: no aberration corrections are used. + + \begindata + + FRAME_IMAP_HEE = -43926 + FRAME_-43926_NAME = 'IMAP_HEE' + FRAME_-43926_CLASS = 5 + FRAME_-43926_CLASS_ID = -43926 + FRAME_-43926_CENTER = 10 + FRAME_-43926_RELATIVE = 'J2000' + FRAME_-43926_DEF_STYLE = 'PARAMETERIZED' + FRAME_-43926_FAMILY = 'TWO-VECTOR' + FRAME_-43926_PRI_AXIS = 'X' + FRAME_-43926_PRI_VECTOR_DEF = 'OBSERVER_TARGET_POSITION' + FRAME_-43926_PRI_OBSERVER = 'SUN' + FRAME_-43926_PRI_TARGET = 'EARTH' + FRAME_-43926_PRI_ABCORR = 'NONE' + FRAME_-43926_SEC_AXIS = 'Z' + FRAME_-43926_SEC_VECTOR_DEF = 'CONSTANT' + FRAME_-43926_SEC_FRAME = 'IMAP_ECLIPDATE' + FRAME_-43926_SEC_SPEC = 'RECTANGULAR' + FRAME_-43926_SEC_VECTOR = ( 0, 0, 1 ) + + \begintext + + + Heliospheric Ram Ecliptic (HRE) Frame ([3],[8],[9]) + --------------------------------------------------------------------- + + This is a heliocentric frame oriented with respect to the current, + nominal ram direction of the Sun's motion relative to the local + interstellar medium and the ecliptic plane, otherwise known as the + heliospheric "nose" direction. + + The nose direction is the primary vector: the X axis points in the + direction [-0.2477, -0.9647, 0.0896] in the ECLIPJ2000 (IMAP_HAE) + frame. + + The northern surface normal to the mean ecliptic of J2000 is the + secondary vector: the Z axis is the component of this vector + orthogonal to the X axis. + + The Y axis is Z cross X, completing the right-handed reference + frame. + + \begindata + + FRAME_IMAP_HRE = -43927 + FRAME_-43927_NAME = 'IMAP_HRE' + FRAME_-43927_CLASS = 5 + FRAME_-43927_CLASS_ID = -43927 + FRAME_-43927_CENTER = 10 + FRAME_-43927_RELATIVE = 'J2000' + FRAME_-43927_DEF_STYLE = 'PARAMETERIZED' + FRAME_-43927_FAMILY = 'TWO-VECTOR' + FRAME_-43927_PRI_AXIS = 'X' + FRAME_-43927_PRI_VECTOR_DEF = 'CONSTANT' + FRAME_-43927_PRI_FRAME = 'ECLIPJ2000' + FRAME_-43927_PRI_SPEC = 'RECTANGULAR' + FRAME_-43927_PRI_VECTOR = ( -0.2477, -0.9647, 0.0896 ) + FRAME_-43927_SEC_AXIS = 'Z' + FRAME_-43927_SEC_VECTOR_DEF = 'CONSTANT' + FRAME_-43927_SEC_FRAME = 'ECLIPJ2000' + FRAME_-43927_SEC_SPEC = 'RECTANGULAR' + FRAME_-43927_SEC_VECTOR = ( 0, 0, 1 ) + + \begintext + + + Heliospheric Nose Upfield (HNU) Frame ([3],[8],[9]) + --------------------------------------------------------------------- + + Heliocentric frame oriented with respect to the current nominal + ram direction of the Sun's motion relative to the local + interstellar medium and the current best estimate of the + unperturbed magnetic field direction in the upstream local + interstellar medium. + + The nominal upfield direction of the ISM B-field is the primary + vector: the Z axis points in the direction + [-0.5583, -0.6046, 0.5681] in the ECLIPJ2000 (IMAP_HAE) frame. + + The nose direction [-0.2477, -0.9647, 0.0896] in the ECLIPJ2000 + (IMAP_HAE) frame is the secondary vector: the X axis is the + component of this vector orthogonal to the Z axis. + + The Y axis is Z cross X, completing the right-handed reference + frame. + + \begindata + + FRAME_IMAP_HNU = -43928 + FRAME_-43928_NAME = 'IMAP_HNU' + FRAME_-43928_CLASS = 5 + FRAME_-43928_CLASS_ID = -43928 + FRAME_-43928_CENTER = 10 + FRAME_-43928_RELATIVE = 'J2000' + FRAME_-43928_DEF_STYLE = 'PARAMETERIZED' + FRAME_-43928_FAMILY = 'TWO-VECTOR' + FRAME_-43928_PRI_AXIS = 'Z' + FRAME_-43928_PRI_VECTOR_DEF = 'CONSTANT' + FRAME_-43928_PRI_FRAME = 'ECLIPJ2000' + FRAME_-43928_PRI_SPEC = 'RECTANGULAR' + FRAME_-43928_PRI_VECTOR = ( -0.5583, -0.6046, 0.5681 ) + FRAME_-43928_SEC_AXIS = 'X' + FRAME_-43928_SEC_VECTOR_DEF = 'CONSTANT' + FRAME_-43928_SEC_FRAME = 'ECLIPJ2000' + FRAME_-43928_SEC_SPEC = 'RECTANGULAR' + FRAME_-43928_SEC_VECTOR = ( -0.2477, -0.9647, 0.0896 ) + + \begintext + + + Galactic Coordinate System (GCS) Frame ([3]) + --------------------------------------------------------------------- + + Alias for SPICE galactic system II frame GALACTIC. + + The primary axis is the normal to the galactic equatorial plane: + Z axis is this unit vector. + + The secondary axis is the vector from the Sun to the galatic + center (represented by Sagittarious): X axis is the component of + this vector orthogonal to the Z axis. + + The Y axis is Z cross X, completing the right-handed reference + frame. + + \begindata + + FRAME_IMAP_GCS = -43929 + FRAME_-43929_NAME = 'IMAP_GCS' + FRAME_-43929_CLASS = 4 + FRAME_-43929_CLASS_ID = -43929 + FRAME_-43929_CENTER = 10 + TKFRAME_-43929_RELATIVE = 'GALACTIC' + TKFRAME_-43929_SPEC = 'MATRIX' + TKFRAME_-43929_MATRIX = ( 1 0 0 + 0 1 0 + 0 0 1 ) + \begintext + + Heliospheric Ram Corotating (HRC) Frame ([3],[8]) + --------------------------------------------------------------------- + + This is a heliocentric frame oriented with respect to the current, + nominal ram direction of the Sun's motion relative to the local + interstellar medium and the solar equatorial plane. + + The nose direction is the primary vector: the X axis points in the + direction [-0.2477, -0.9647, 0.0896] in the ECLIPJ2000 (IMAP_HAE) + frame. + + The solar north pole direction is the secondary vector: the Z axis + is the component of the solar rotation axis orthogonal to the X + axis. + + The Y axis is Z cross X, completing the right-handed reference + frame. + + \begindata + + FRAME_IMAP_HRC = -43930 + FRAME_-43930_NAME = 'IMAP_HRC' + FRAME_-43930_CLASS = 5 + FRAME_-43930_CLASS_ID = -43930 + FRAME_-43930_CENTER = 10 + FRAME_-43930_RELATIVE = 'J2000' + FRAME_-43930_DEF_STYLE = 'PARAMETERIZED' + FRAME_-43930_FAMILY = 'TWO-VECTOR' + FRAME_-43930_PRI_AXIS = 'X' + FRAME_-43930_PRI_VECTOR_DEF = 'CONSTANT' + FRAME_-43930_PRI_FRAME = 'ECLIPJ2000' + FRAME_-43930_PRI_SPEC = 'RECTANGULAR' + FRAME_-43930_PRI_VECTOR = ( -0.2477, -0.9647, 0.0896 ) + FRAME_-43930_SEC_AXIS = 'Z' + FRAME_-43930_SEC_VECTOR_DEF = 'CONSTANT' + FRAME_-43930_SEC_FRAME = 'IAU_SUN' + FRAME_-43930_SEC_SPEC = 'RECTANGULAR' + FRAME_-43930_SEC_VECTOR = ( 0, 0, 1 ) + + \begintext + + +END OF FILE \ No newline at end of file diff --git a/imap_processing/ultra/l1c/sim_spice_kernels/imap_sclk_0000.tsc b/imap_processing/ultra/l1c/sim_spice_kernels/imap_sclk_0000.tsc new file mode 100644 index 0000000000..345cedeb03 --- /dev/null +++ b/imap_processing/ultra/l1c/sim_spice_kernels/imap_sclk_0000.tsc @@ -0,0 +1,156 @@ +\begintext + +FILENAME = "imap_0000.tsc" +CREATION_DATE = "5-January-2021" + + +IMAP Spacecraft Clock Kernel (SCLK) +=========================================================================== + + This file is a SPICE spacecraft clock (SCLK) kernel containing + information required for time conversions involving the on-board + IMAP spacecraft clock. + +Version +-------------------------------------------------------- + + IMAP SCLK Kernel Version: + + IMAP version 0.3 - April 22, 2022 -- Mike Ruffolo + Updated to use NAIF SC ID 43 + + IMAP Version 0.2 - June 2, 2021 -- Caroline Cocca + Updated to use temporary spacecraft id of 225 + + IMAP Version 0.1 - March 6, 2015 -- Eric Melin + Updated text to replace references to RBSP with SPP + + IMAP Version 0.0 - August 7, 2014 -- Eric Melin + The initial SPP spice kernel. + This file was created by using RBSPA initial kernel and + modifying the spacecraft ID. + + +Usage +-------------------------------------------------------- + + This file is used by the SPICE system as follows: programs that + make use of this SCLK kernel must 'load' the kernel, normally + during program initialization. Loading the kernel associates + the data items with their names in a data structure called the + 'kernel pool'. The SPICELIB routine FURNSH loads text kernel + files, such as this one, into the pool as shown below: + + FORTRAN: + + CALL FURNSH ( SCLK_kernel_name ) + + C: + + furnsh_c ( SCLK_kernel_name ); + + Once loaded, the SCLK time conversion routines will be able to + access the necessary data located in this kernel for their + designed purposes. + +References +-------------------------------------------------------- + + 1. "SCLK Required Reading" + +Inquiries +-------------------------------------------------------- + + If you have any questions regarding this file or its usage, + contact: + + Scott Turner + (443)778-1693 + Scott.Turner@jhuapl.edu + +Kernel Data +-------------------------------------------------------- + + The first block of keyword equals value assignments define the + type, parallel time system, and format of the spacecraft clock. + These fields are invariant from SCLK kernel update to SCLK + kernel update. + + The IMAP spacecraft clock is represented by the SPICE + type 1 SCLK kernel. It uses TDT, Terrestrial Dynamical Time, + as its parallel time system. + +\begindata + +SCLK_KERNEL_ID = ( @2009-07-09T12:20:32 ) +SCLK_DATA_TYPE_43 = ( 1 ) +SCLK01_TIME_SYSTEM_43 = ( 2 ) + + +\begintext + + In a particular partition of the IMAP spacecraft clock, + the clock read-out consists of two separate stages: + + 1/18424652:24251 + + The first stage, a 32 bit field, represents the spacecraft + clock seconds count. The second, a 16 bit field, represents + counts of 20 microsecond increments of the spacecraft clock. + + The following keywords and their values establish this structure: + +\begindata + +SCLK01_N_FIELDS_43 = ( 2 ) +SCLK01_MODULI_43 = ( 4294967296 50000 ) +SCLK01_OFFSETS_43 = ( 0 0 ) +SCLK01_OUTPUT_DELIM_43 = ( 2 ) + + +\begintext + + This concludes the invariant portion of the SCLK kernel data. The + remaining sections of the kernel may require updates as the clock + correlation coefficients evolve in time. The first section below + establishes the clock partitions. The data in this section consists + of two parallel arrays, which denote the start and end values in + ticks of each partition of the spacecraft clock. + + SPICE utilizes these two arrays to map from spacecraft clock ticks, + determined with the usual modulo arithmetic, to encoded SCLK--the + internal, monotonically increasing sequence used to tag various + data sources with spacecraft clock. + +\begindata + +SCLK_PARTITION_START_43 = ( 0.00000000000000e+00 ) + +SCLK_PARTITION_END_43 = ( 2.14748364799999e+14 ) + +\begintext + + The remaining section of the SCLK kernel defines the clock correlation + coefficients. Each line contains a 'coefficient triple': + + Encoded SCLK at which Rate is introduced. + Corresponding TDT Epoch at which Rate is introduced. + Rate in TDT (seconds) / most significant clock count (~seconds). + + SPICE uses linear extrapolation to convert between the parallel time + system and encoded SCLK. The triples are stored in the array defined + below. + + The first time triplet below was entered manually and represents the + approximate time (in TDT) at which SCLK = zero. The current plan for + IMAP is that the given epoch will be used for both Observatory I&T + and launch. Note that the conversion from UTC to TDT used 34 leap + seconds. + +\begindata + +SCLK01_COEFFICIENTS_43 = ( + + 0 @01-JAN-2010-00:01:06.184000 1.00000000000 + +) diff --git a/imap_processing/ultra/l1c/sim_spice_kernels/imap_spk_demo.bsp b/imap_processing/ultra/l1c/sim_spice_kernels/imap_spk_demo.bsp new file mode 100644 index 0000000000..e8b7578f69 Binary files /dev/null and b/imap_processing/ultra/l1c/sim_spice_kernels/imap_spk_demo.bsp differ diff --git a/imap_processing/ultra/l1c/sim_spice_kernels/naif0012.tls b/imap_processing/ultra/l1c/sim_spice_kernels/naif0012.tls new file mode 100644 index 0000000000..caa6a4d139 --- /dev/null +++ b/imap_processing/ultra/l1c/sim_spice_kernels/naif0012.tls @@ -0,0 +1,150 @@ +KPL/LSK + + +LEAPSECONDS KERNEL FILE +=========================================================================== + +Modifications: +-------------- + +2016, Jul. 14 NJB Modified file to account for the leapsecond that + will occur on December 31, 2016. + +2015, Jan. 5 NJB Modified file to account for the leapsecond that + will occur on June 30, 2015. + +2012, Jan. 5 NJB Modified file to account for the leapsecond that + will occur on June 30, 2012. + +2008, Jul. 7 NJB Modified file to account for the leapsecond that + will occur on December 31, 2008. + +2005, Aug. 3 NJB Modified file to account for the leapsecond that + will occur on December 31, 2005. + +1998, Jul 17 WLT Modified file to account for the leapsecond that + will occur on December 31, 1998. + +1997, Feb 22 WLT Modified file to account for the leapsecond that + will occur on June 30, 1997. + +1995, Dec 14 KSZ Corrected date of last leapsecond from 1-1-95 + to 1-1-96. + +1995, Oct 25 WLT Modified file to account for the leapsecond that + will occur on Dec 31, 1995. + +1994, Jun 16 WLT Modified file to account for the leapsecond on + June 30, 1994. + +1993, Feb. 22 CHA Modified file to account for the leapsecond on + June 30, 1993. + +1992, Mar. 6 HAN Modified file to account for the leapsecond on + June 30, 1992. + +1990, Oct. 8 HAN Modified file to account for the leapsecond on + Dec. 31, 1990. + + +Explanation: +------------ + +The contents of this file are used by the routine DELTET to compute the +time difference + +[1] DELTA_ET = ET - UTC + +the increment to be applied to UTC to give ET. + +The difference between UTC and TAI, + +[2] DELTA_AT = TAI - UTC + +is always an integral number of seconds. The value of DELTA_AT was 10 +seconds in January 1972, and increases by one each time a leap second +is declared. Combining [1] and [2] gives + +[3] DELTA_ET = ET - (TAI - DELTA_AT) + + = (ET - TAI) + DELTA_AT + +The difference (ET - TAI) is periodic, and is given by + +[4] ET - TAI = DELTA_T_A + K sin E + +where DELTA_T_A and K are constant, and E is the eccentric anomaly of the +heliocentric orbit of the Earth-Moon barycenter. Equation [4], which ignores +small-period fluctuations, is accurate to about 0.000030 seconds. + +The eccentric anomaly E is given by + +[5] E = M + EB sin M + +where M is the mean anomaly, which in turn is given by + +[6] M = M + M t + 0 1 + +where t is the number of ephemeris seconds past J2000. + +Thus, in order to compute DELTA_ET, the following items are necessary. + + DELTA_TA + K + EB + M0 + M1 + DELTA_AT after each leap second. + +The numbers, and the formulation, are taken from the following sources. + + 1) Moyer, T.D., Transformation from Proper Time on Earth to + Coordinate Time in Solar System Barycentric Space-Time Frame + of Reference, Parts 1 and 2, Celestial Mechanics 23 (1981), + 33-56 and 57-68. + + 2) Moyer, T.D., Effects of Conversion to the J2000 Astronomical + Reference System on Algorithms for Computing Time Differences + and Clock Rates, JPL IOM 314.5--942, 1 October 1985. + +The variable names used above are consistent with those used in the +Astronomical Almanac. + +\begindata + +DELTET/DELTA_T_A = 32.184 +DELTET/K = 1.657D-3 +DELTET/EB = 1.671D-2 +DELTET/M = ( 6.239996D0 1.99096871D-7 ) + +DELTET/DELTA_AT = ( 10, @1972-JAN-1 + 11, @1972-JUL-1 + 12, @1973-JAN-1 + 13, @1974-JAN-1 + 14, @1975-JAN-1 + 15, @1976-JAN-1 + 16, @1977-JAN-1 + 17, @1978-JAN-1 + 18, @1979-JAN-1 + 19, @1980-JAN-1 + 20, @1981-JUL-1 + 21, @1982-JUL-1 + 22, @1983-JUL-1 + 23, @1985-JUL-1 + 24, @1988-JAN-1 + 25, @1990-JAN-1 + 26, @1991-JAN-1 + 27, @1992-JUL-1 + 28, @1993-JUL-1 + 29, @1994-JUL-1 + 30, @1996-JAN-1 + 31, @1997-JUL-1 + 32, @1999-JAN-1 + 33, @2006-JAN-1 + 34, @2009-JAN-1 + 35, @2012-JUL-1 + 36, @2015-JUL-1 + 37, @2017-JAN-1 ) + +\begintext diff --git a/imap_processing/ultra/l1c/sim_spice_kernels/sim_1yr_imap_attitude.bc b/imap_processing/ultra/l1c/sim_spice_kernels/sim_1yr_imap_attitude.bc new file mode 100755 index 0000000000..589f2f08f5 Binary files /dev/null and b/imap_processing/ultra/l1c/sim_spice_kernels/sim_1yr_imap_attitude.bc differ diff --git a/imap_processing/ultra/l1c/sim_spice_kernels/sim_1yr_imap_pointing_frame.bc b/imap_processing/ultra/l1c/sim_spice_kernels/sim_1yr_imap_pointing_frame.bc new file mode 100644 index 0000000000..8ab7f76e3c Binary files /dev/null and b/imap_processing/ultra/l1c/sim_spice_kernels/sim_1yr_imap_pointing_frame.bc differ diff --git a/imap_processing/ultra/l1c/spacecraft_pset.py b/imap_processing/ultra/l1c/spacecraft_pset.py index 0e37e801c4..313b39df14 100644 --- a/imap_processing/ultra/l1c/spacecraft_pset.py +++ b/imap_processing/ultra/l1c/spacecraft_pset.py @@ -1,20 +1,33 @@ -"""Calculate Pointing Set Grids.""" +"""Calculate Spacecraft Pointing Set Grids.""" import logging +import astropy_healpix.healpy as hp import numpy as np -import pandas as pd import xarray as xr from imap_processing.cdf.utils import parse_filename_like -from imap_processing.ultra.l1b.ultra_l1b_culling import get_de_rejection_mask +from imap_processing.quality_flags import ImapPSETUltraFlags +from imap_processing.spice.repoint import get_pointing_times_from_id +from imap_processing.spice.time import ( + met_to_ttj2000ns, + ttj2000ns_to_et, +) +from imap_processing.ultra.constants import UltraConstants +from imap_processing.ultra.l1b.ultra_l1b_culling import ( + get_de_rejection_mask, + get_energy_and_spin_dependent_rejection_mask, +) from imap_processing.ultra.l1c.l1c_lookup_utils import ( - calculate_pixels_within_scattering_threshold, + build_energy_bins, + calculate_accepted_pixels, get_spacecraft_pointing_lookup_tables, + in_restricted_fov, ) +from imap_processing.ultra.l1c.ultra_l1c_culling import compute_culling_mask from imap_processing.ultra.l1c.ultra_l1c_pset_bins import ( - build_energy_bins, get_efficiencies_and_geometric_function, + get_energy_delta_minus_plus, get_spacecraft_background_rates, get_spacecraft_exposure_times, get_spacecraft_histogram, @@ -26,14 +39,13 @@ def calculate_spacecraft_pset( de_dataset: xr.Dataset, - extendedspin_dataset: xr.Dataset, - cullingmask_dataset: xr.Dataset, + goodtimes_dataset: xr.Dataset, rates_dataset: xr.Dataset, - params_dataset: xr.Dataset, + aux_dataset: xr.Dataset, name: str, ancillary_files: dict, instrument_id: int, - species_id: int = 1, + species_id: list, ) -> xr.Dataset: """ Create dictionary with defined datatype for Pointing Set Grid Data. @@ -42,22 +54,20 @@ def calculate_spacecraft_pset( ---------- de_dataset : xarray.Dataset Dataset containing de data. - extendedspin_dataset : xarray.Dataset - Dataset containing extendedspin data. - cullingmask_dataset : xarray.Dataset - Dataset containing cullingmask data. + goodtimes_dataset : xarray.Dataset + Dataset containing goodtimes data. rates_dataset : xarray.Dataset Dataset containing image rates data. - params_dataset : xarray.Dataset - Dataset containing image parameters data. + aux_dataset : xarray.Dataset + Dataset containing auxiliary data. name : str Name of the dataset. ancillary_files : dict Ancillary files. instrument_id : int Instrument ID, either 45 or 90. - species_id : int - Species ID, default of 1 refers to Hydrogen. + species_id : List + Species ID. Returns ------- @@ -65,96 +75,183 @@ def calculate_spacecraft_pset( Dataset containing the data. """ pset_dict: dict[str, np.ndarray] = {} - sensor = parse_filename_like(name)["sensor"][0:2] - # Select only the species we are interested in. - indices = np.where(de_dataset["species"].values == species_id)[0] + + sensor_id = int(parse_filename_like(name)["sensor"][0:2]) + indices = np.where(np.isin(de_dataset["ebin"].values, species_id))[0] species_dataset = de_dataset.isel(epoch=indices) + # If there are no species return None. + if indices.size == 0: + logger.info(f"No data available for {name}") + return None + + ################ Reject events based on quality flags ################ # Before we use the de_dataset to calculate the pointing set grid we need to filter. - rejected = get_de_rejection_mask( + de_rejected = get_de_rejection_mask( species_dataset["quality_scattering"].values, species_dataset["quality_outliers"].values, + UltraConstants.APPLY_SCATTERING_REJECTION_L1C, ) - species_dataset = species_dataset.isel(epoch=~rejected) - - v_mag_dps_spacecraft = np.linalg.norm( - species_dataset["velocity_dps_sc"].values, axis=1 - ) - vhat_dps_spacecraft = ( - species_dataset["velocity_dps_sc"].values / v_mag_dps_spacecraft[:, np.newaxis] + species_dataset = species_dataset.isel(epoch=~de_rejected) + # Check if spin_number is in the goodtimes dataset, if not then we can + # reject all events for that spin without checking energy bin flags. + spin_rejected = ~np.isin( + species_dataset["spin"].values, goodtimes_dataset["spin_number"].values ) + species_dataset = species_dataset.isel(epoch=~spin_rejected) intervals, _, energy_bin_geometric_means = build_energy_bins() - counts, latitude, longitude, n_pix = get_spacecraft_histogram( - vhat_dps_spacecraft, + + # Now check energy dependent flags. + energy_dependent_rejected = get_energy_and_spin_dependent_rejection_mask( + goodtimes_dataset, species_dataset["energy_spacecraft"].values, - intervals, - nside=128, + species_dataset["spin"].values, ) - healpix = np.arange(n_pix) + species_dataset = species_dataset.isel(epoch=~energy_dependent_rejected) # Get lookup table for FOR indices by spin phase step ( for_indices_by_spin_phase, theta_vals, phi_vals, - ra_and_dec, + _ra_and_dec, boundary_scale_factors, ) = get_spacecraft_pointing_lookup_tables(ancillary_files, instrument_id) - # Check that the number of rows in the lookup table matches the number of pixels - if for_indices_by_spin_phase.shape[0] != n_pix: - logger.warning( - "The lookup table is expected to have the same number of rows as " - "the number of HEALPix pixels." + + logger.info("calculating spun FWHM scattering values.") + valid_spun_pixels, scattering_theta, scattering_phi, scattering_thresholds = ( + calculate_accepted_pixels( + for_indices_by_spin_phase, + theta_vals, + phi_vals, + ancillary_files, + instrument_id, + reject_scattering=UltraConstants.APPLY_SCATTERING_REJECTION_L1C, + apply_fov_restriction=UltraConstants.APPLY_FOV_RESTRICTIONS_L1C, + ) + ) + + # Apply restricted FOV filter to counts. + # If a valid event's instrument frame theta/phi falls outside the restricted + # acceptance window it is excluded from the L1C fine energy-bin counts map. + if UltraConstants.APPLY_FOV_RESTRICTIONS_L1C: + fov_accepted = in_restricted_fov( + species_dataset["theta"].values, + species_dataset["phi"].values, + instrument_id, + ) + logger.info( + f"Restricted FOV counts filter: keeping {fov_accepted.sum()} / " + f"{len(fov_accepted)} events." ) + species_dataset = species_dataset.isel(epoch=fov_accepted) - pixels_below_scattering = calculate_pixels_within_scattering_threshold( - for_indices_by_spin_phase, theta_vals, phi_vals, ancillary_files, instrument_id + v_mag_dps_spacecraft = np.linalg.norm( + species_dataset["velocity_dps_sc"].values, axis=1 + ) + vhat_dps_spacecraft = ( + species_dataset["velocity_dps_sc"].values / v_mag_dps_spacecraft[:, np.newaxis] ) + counts, counts_n_pix = get_spacecraft_histogram( + vhat_dps_spacecraft, + species_dataset["energy_spacecraft"].values, + intervals, + nside=UltraConstants.L1C_COUNTS_NSIDE, + ) + counts_healpix = np.arange(counts_n_pix) + # Determine nside for non "counts" variables from the lookup table + n_pix = for_indices_by_spin_phase.sizes["pixel"] + nside = hp.npix2nside(n_pix) + healpix = np.arange(n_pix) + + # Calculate the corresponding longitude (az) latitude (el) + # center coordinates + longitude, latitude = hp.pix2ang(nside, healpix, lonlat=True) + + # Get the start and stop times of the pointing period + repoint_id = species_dataset.attrs.get("Repointing", None) + if repoint_id is None: + raise ValueError("Repointing ID attribute is missing from the dataset.") + + pointing_range_met = get_pointing_times_from_id(repoint_id) + + # Calculate exposure times + logger.info("Calculating spacecraft exposure times with deadtime correction.") + exposure_pointing, deadtime_ratios = get_spacecraft_exposure_times( + rates_dataset, + valid_spun_pixels, + boundary_scale_factors, + aux_dataset, + energy_bins=energy_bin_geometric_means, + sensor_id=sensor_id, + ancillary_files=ancillary_files, + apply_bsf=UltraConstants.APPLY_BOUNDARY_SCALE_FACTORS_L1C, + goodtimes_dataset=goodtimes_dataset, + ) + logger.info("Calculating spun efficiencies and geometric function.") # calculate efficiency and geometric function as a function of energy - efficiencies, geometric_function = get_efficiencies_and_geometric_function( - pixels_below_scattering, + geometric_function, efficiencies = get_efficiencies_and_geometric_function( + valid_spun_pixels, boundary_scale_factors, theta_vals, phi_vals, n_pix, + sensor_id, ancillary_files, + apply_bsf=UltraConstants.APPLY_BOUNDARY_SCALE_FACTORS_L1C, ) sensitivity = efficiencies * geometric_function - # Calculate exposure - constant_exposure = ancillary_files["l1c-90sensor-dps-exposure"] - df_exposure = pd.read_csv(constant_exposure) - - exposure_pointing, deadtime_ratios = get_spacecraft_exposure_times( - df_exposure, - rates_dataset, - params_dataset, - pixels_below_scattering, - boundary_scale_factors, - ) - # Calculate background rates background_rates = get_spacecraft_background_rates( rates_dataset, - sensor, + aux_dataset, + sensor_id, ancillary_files, intervals, - cullingmask_dataset["spin_number"].values, + goodtimes_dataset["spin_number"].values, + nside=nside, + ) + spacecraft_pset_quality_flags = np.full( + n_pix, ImapPSETUltraFlags.NONE.value, dtype=np.uint16 ) - # For ISTP, epoch should be the center of the time bin. - pset_dict["epoch"] = de_dataset.epoch.data[:1].astype(np.int64) + # Convert pointing start and end time to ttj2000ns + pointing_range_ns = met_to_ttj2000ns(pointing_range_met) + + start: float = np.min(species_dataset["event_times"].values) + end: float = np.max(species_dataset["event_times"].values) + + # use either the pointing end time + 30 mins or the max event time, + # whichever is smaller. + end = min(end + 1800, ttj2000ns_to_et(pointing_range_ns[1])) + # Time bins in 30 minute intervals in et + time_bins = np.arange(start, end, 1800) + # Compute mask for culling the Earth + compute_culling_mask( + time_bins, + UltraConstants.DEFAULT_EARTH_CULLING_RADIUS, + spacecraft_pset_quality_flags, + nside=nside, + ) + # Epoch should be the start of the pointing + pset_dict["epoch"] = np.atleast_1d(pointing_range_ns[0]).astype(np.int64) + pset_dict["epoch_delta"] = np.atleast_1d(np.diff(pointing_range_ns)).astype( + np.int64 + ) pset_dict["counts"] = counts[np.newaxis, ...] pset_dict["latitude"] = latitude[np.newaxis, ...] pset_dict["longitude"] = longitude[np.newaxis, ...] pset_dict["energy_bin_geometric_mean"] = energy_bin_geometric_means pset_dict["background_rates"] = background_rates[np.newaxis, ...] - pset_dict["exposure_factor"] = exposure_pointing + pset_dict["exposure_factor"] = exposure_pointing[np.newaxis, ...] pset_dict["pixel_index"] = healpix + pset_dict["counts_pixel_index"] = counts_healpix pset_dict["energy_bin_delta"] = np.diff(intervals, axis=1).squeeze()[ np.newaxis, ... ] + pset_dict["quality_flags"] = spacecraft_pset_quality_flags[np.newaxis, ...] pset_dict["sensitivity"] = sensitivity pset_dict["efficiency"] = efficiencies @@ -162,6 +259,18 @@ def calculate_spacecraft_pset( pset_dict["dead_time_ratio"] = deadtime_ratios pset_dict["spin_phase_step"] = np.arange(len(deadtime_ratios)) + # Convert FWHM to gaussian uncertainty by dividing by 2.355 + # See algorithm documentation (section 3.5.7, third bullet point) for more details + pset_dict["scatter_theta"] = scattering_theta / 2.355 + pset_dict["scatter_phi"] = scattering_phi / 2.355 + + pset_dict["scatter_threshold"] = scattering_thresholds + + # Add the energy delta plus/minus to the dataset + energy_delta_minus, energy_delta_plus = get_energy_delta_minus_plus() + pset_dict["energy_delta_minus"] = energy_delta_minus + pset_dict["energy_delta_plus"] = energy_delta_plus + dataset = create_dataset(pset_dict, name, "l1c") return dataset diff --git a/imap_processing/ultra/l1c/ultra_l1c.py b/imap_processing/ultra/l1c/ultra_l1c.py index 104829f4c7..7fe259e66e 100644 --- a/imap_processing/ultra/l1c/ultra_l1c.py +++ b/imap_processing/ultra/l1c/ultra_l1c.py @@ -2,13 +2,14 @@ import xarray as xr +from imap_processing.ultra.constants import UltraConstants +from imap_processing.ultra.l1b.lookup_utils import get_de_product_name from imap_processing.ultra.l1c.helio_pset import calculate_helio_pset -from imap_processing.ultra.l1c.histogram import calculate_histogram from imap_processing.ultra.l1c.spacecraft_pset import calculate_spacecraft_pset def ultra_l1c( - data_dict: dict, ancillary_files: dict, has_spice: bool + data_dict: dict, ancillary_files: dict, descriptor: str ) -> list[xr.Dataset]: """ Will process ULTRA L1A and L1B data into L1C CDF files at output_filepath. @@ -19,8 +20,8 @@ def ultra_l1c( The data itself and its dependent data. ancillary_files : dict Ancillary files. - has_spice : bool - Whether to use SPICE data. + descriptor : str + Job descriptor. Returns ------- @@ -28,51 +29,84 @@ def ultra_l1c( List of xarray.Dataset. """ output_datasets = [] + create_helio_pset = True if "helio" in descriptor else False - # Account for possibility of having 45 and 90 in dictionary. + # TODO + # Determine which l1b priority DE product to use in creating the l1c products. + # This will vary per-pointing by an ancillary file produced by the ULTRA team. + + # Account for the possibility of having 45 and 90 in the dictionary. for instrument_id in [45, 90]: - if ( - f"imap_ultra_l1a_{instrument_id}sensor-histogram" in data_dict - and f"imap_ultra_l1b_{instrument_id}sensor-cullingmask" in data_dict - ): - histogram_dataset = calculate_histogram( - data_dict[f"imap_ultra_l1a_{instrument_id}sensor-histogram"], - f"imap_ultra_l1c_{instrument_id}sensor-histogram", + # All l1c products require a l1b de dependency so check that first + # and calculate the correct l1b de product to use based on the repointing ID + # and ancillary files. + if f"imap_ultra_l1b_{instrument_id}sensor-de" in data_dict: + # get repoint number + repoint = data_dict[f"imap_ultra_l1b_{instrument_id}sensor-de"].attrs.get( + "Repointing", None ) - output_datasets = [histogram_dataset] - elif ( - f"imap_ultra_l1b_{instrument_id}sensor-cullingmask" in data_dict - and f"imap_ultra_l1b_{instrument_id}sensor-de" in data_dict - and f"imap_ultra_l1b_{instrument_id}sensor-extendedspin" in data_dict - and has_spice + if repoint is None: + raise ValueError("Repointing ID attribute is missing from the dataset.") + # Determine which l1b de product to use in calculating the l1c products. + # Will be either the raw de product or a priority 1-4 de product. + de_product_desc = get_de_product_name( + repoint, instrument_id, "l1c", ancillary_files + ) + if de_product_desc not in data_dict: + raise ValueError( + f"Selected L1B DE product '{de_product_desc}' for instrument " + f"{instrument_id} is not present in data_dict. Available L1B DE " + f"products: {data_dict.keys()}" + ) + else: + continue + if ( + f"imap_ultra_l1b_{instrument_id}sensor-goodtimes" in data_dict + and de_product_desc in data_dict + and f"imap_ultra_l1a_{instrument_id}sensor-rates" in data_dict + and f"imap_ultra_l1a_{instrument_id}sensor-aux" in data_dict + and create_helio_pset ): helio_pset = calculate_helio_pset( - data_dict[f"imap_ultra_l1b_{instrument_id}sensor-de"], - data_dict[f"imap_ultra_l1b_{instrument_id}sensor-extendedspin"], - data_dict[f"imap_ultra_l1b_{instrument_id}sensor-cullingmask"], + data_dict[de_product_desc], + data_dict[f"imap_ultra_l1b_{instrument_id}sensor-goodtimes"], data_dict[f"imap_ultra_l1a_{instrument_id}sensor-rates"], - data_dict[f"imap_ultra_l1a_{instrument_id}sensor-params"], + data_dict[f"imap_ultra_l1a_{instrument_id}sensor-aux"], f"imap_ultra_l1c_{instrument_id}sensor-heliopset", ancillary_files, instrument_id, + UltraConstants.TOFXPH_SPECIES_GROUPS["proton"], ) output_datasets = [helio_pset] elif ( - f"imap_ultra_l1b_{instrument_id}sensor-cullingmask" in data_dict - and f"imap_ultra_l1b_{instrument_id}sensor-de" in data_dict - and f"imap_ultra_l1b_{instrument_id}sensor-extendedspin" in data_dict + f"imap_ultra_l1b_{instrument_id}sensor-goodtimes" in data_dict + and de_product_desc in data_dict + and f"imap_ultra_l1a_{instrument_id}sensor-rates" in data_dict + and f"imap_ultra_l1a_{instrument_id}sensor-aux" in data_dict ): spacecraft_pset = calculate_spacecraft_pset( - data_dict[f"imap_ultra_l1b_{instrument_id}sensor-de"], - data_dict[f"imap_ultra_l1b_{instrument_id}sensor-extendedspin"], - data_dict[f"imap_ultra_l1b_{instrument_id}sensor-cullingmask"], + data_dict[de_product_desc], + data_dict[f"imap_ultra_l1b_{instrument_id}sensor-goodtimes"], data_dict[f"imap_ultra_l1a_{instrument_id}sensor-rates"], - data_dict[f"imap_ultra_l1a_{instrument_id}sensor-params"], + data_dict[f"imap_ultra_l1a_{instrument_id}sensor-aux"], f"imap_ultra_l1c_{instrument_id}sensor-spacecraftpset", ancillary_files, instrument_id, + UltraConstants.TOFXPH_SPECIES_GROUPS["proton"], ) output_datasets = [spacecraft_pset] + spacecraft_pset_non_proton = calculate_spacecraft_pset( + data_dict[de_product_desc], + data_dict[f"imap_ultra_l1b_{instrument_id}sensor-goodtimes"], + data_dict[f"imap_ultra_l1a_{instrument_id}sensor-rates"], + data_dict[f"imap_ultra_l1a_{instrument_id}sensor-aux"], + f"imap_ultra_l1c_{instrument_id}sensor-spacecraftpset-nonproton", + ancillary_files, + instrument_id, + UltraConstants.TOFXPH_SPECIES_GROUPS["non_proton"], + ) + if spacecraft_pset_non_proton is not None: + output_datasets.append(spacecraft_pset_non_proton) if not output_datasets: raise ValueError("Data dictionary does not contain the expected keys.") diff --git a/imap_processing/ultra/l1c/ultra_l1c_culling.py b/imap_processing/ultra/l1c/ultra_l1c_culling.py index f448a967e5..b1b86e4647 100644 --- a/imap_processing/ultra/l1c/ultra_l1c_culling.py +++ b/imap_processing/ultra/l1c/ultra_l1c_culling.py @@ -4,6 +4,7 @@ import numpy as np from numpy.typing import NDArray +from imap_processing.quality_flags import ImapPSETUltraFlags from imap_processing.spice.geometry import ( SpiceBody, SpiceFrame, @@ -14,6 +15,7 @@ def compute_culling_mask( et: NDArray, keepout_radius_km: float, + pset_quality_flags: NDArray, observer: SpiceBody = SpiceBody.EARTH, nside: int = 128, nested: bool = False, @@ -27,6 +29,9 @@ def compute_culling_mask( Ephemeris times in TDB seconds past J2000. keepout_radius_km : float Radius (in km) within which HEALPix pixels will be excluded. + pset_quality_flags : NDArray, + Quality flag to set when HEALPIX pixels are within a + keep-out radius of the target body. observer : SpiceBody, optional Body from which IMAP is observed. nside : int, optional @@ -81,5 +86,7 @@ def compute_culling_mask( # Exclude pixels within the keepout angle. # mask.shape = (len(et), npix) mask = sep_angle > keepout_angle[:, np.newaxis] + culled_any_time = np.any(~mask, axis=0) # shape: (npix,) + pset_quality_flags[culled_any_time] |= ImapPSETUltraFlags.EARTH_FOV.value return mask, unit_target_vecs diff --git a/imap_processing/ultra/l1c/ultra_l1c_pset_bins.py b/imap_processing/ultra/l1c/ultra_l1c_pset_bins.py index 84dbfcd27a..cc33e02596 100644 --- a/imap_processing/ultra/l1c/ultra_l1c_pset_bins.py +++ b/imap_processing/ultra/l1c/ultra_l1c_pset_bins.py @@ -1,67 +1,55 @@ """Module to create pointing sets.""" +import logging + import astropy_healpix.healpy as hp import numpy as np -import pandas import xarray as xr from numpy.typing import NDArray from scipy import interpolate from imap_processing.spice.geometry import ( - SpiceFrame, cartesian_to_spherical, - imap_state, ) -from imap_processing.spice.spin import get_spacecraft_spin_phase, get_spin_angle from imap_processing.ultra.constants import UltraConstants from imap_processing.ultra.l1b.lookup_utils import ( get_geometric_factor, get_image_params, load_geometric_factor_tables, ) +from imap_processing.ultra.l1b.quality_flag_filters import ( + ENERGY_DEPENDENT_SPIN_QUALITY_FLAG_FILTERS, +) from imap_processing.ultra.l1b.ultra_l1b_culling import ( get_pulses_per_spin, - get_spin_and_duration, ) from imap_processing.ultra.l1b.ultra_l1b_extended import ( get_efficiency, get_efficiency_interpolator, + get_spin_info, +) +from imap_processing.ultra.l1c.l1c_lookup_utils import ( + build_energy_bins, + get_static_deadtime_ratios, ) # TODO: add species binning. FILLVAL_FLOAT32 = -1.0e31 +logger = logging.getLogger(__name__) -def build_energy_bins() -> tuple[list[tuple[float, float]], np.ndarray, np.ndarray]: - """ - Build energy bin boundaries. - Returns - ------- - intervals : list[tuple[float, float]] - Energy bins. - energy_midpoints : np.ndarray - Array of energy bin midpoints. - energy_bin_geometric_means : np.ndarray - Array of geometric means of energy bins. - """ - # Create energy bins. - energy_bin_edges = np.array(UltraConstants.CULLING_ENERGY_BIN_EDGES) - energy_midpoints = (energy_bin_edges[:-1] + energy_bin_edges[1:]) / 2 - - intervals = [ - (float(energy_bin_edges[i]), float(energy_bin_edges[i + 1])) - for i in range(len(energy_bin_edges) - 1) - ] - energy_bin_geometric_means = np.sqrt(energy_bin_edges[:-1] * energy_bin_edges[1:]) - - return intervals, energy_midpoints, energy_bin_geometric_means - - -def get_energy_delta_minus_plus() -> tuple[NDArray, NDArray]: +def get_energy_delta_minus_plus( + energy_bin_edges: np.ndarray | None = None, +) -> tuple[NDArray, NDArray]: """ Calculate the energy_delta_minus and energy_delta_plus for use in the CDF. + Parameters + ---------- + energy_bin_edges : numpy.ndarray, optional + Array of energy bin edges. If None, default Ultra energy bins are used. + Returns ------- bins_energy_delta_minus : np.ndarray @@ -77,7 +65,7 @@ def get_energy_delta_minus_plus() -> tuple[NDArray, NDArray]: where bin_upper and bin_lower are the upper and lower bounds of the energy bins and bin_geom_mean is the geometric mean of the energy bin. """ - bins, _, bin_geom_means = build_energy_bins() + bins, _, bin_geom_means = build_energy_bins(energy_bin_edges) bins_energy_delta_plus, bins_energy_delta_minus = [], [] for bin_edges, bin_geom_mean in zip(bins, bin_geom_means, strict=False): bins_energy_delta_plus.append(bin_edges[1] - bin_geom_mean) @@ -91,7 +79,7 @@ def get_spacecraft_histogram( energy_bin_edges: list[tuple[float, float]], nside: int = 128, nested: bool = False, -) -> tuple[NDArray, NDArray, NDArray, NDArray]: +) -> tuple[NDArray, NDArray]: """ Compute a 2D histogram of the particle data using HEALPix binning. @@ -113,10 +101,6 @@ def get_spacecraft_histogram( ------- hist : np.ndarray A 2D histogram array with shape (n_pix, n_energy_bins). - latitude : np.ndarray - Array of latitude values. - longitude : np.ndarray - Array of longitude values. n_pix : int Number of healpix pixels. @@ -138,10 +122,6 @@ def get_spacecraft_histogram( # Compute number of HEALPix pixels that cover the sphere n_pix = hp.nside2npix(nside) - # Calculate the corresponding longitude (az) latitude (el) - # center coordinates - longitude, latitude = hp.pix2ang(nside, np.arange(n_pix), lonlat=True) - # Get HEALPix pixel indices for each event # HEALPix expects latitude in [-90, 90] so we don't need to change elevation hpix_idx = hp.ang2pix(nside, az, el, nest=nested, lonlat=True) @@ -155,7 +135,7 @@ def get_spacecraft_histogram( # Only count the events that fall within the energy bin hist[i, :] += np.bincount(hpix_idx[mask], minlength=n_pix).astype(np.float64) - return hist, latitude, longitude, n_pix + return hist, n_pix def get_spacecraft_count_rate_uncertainty(hist: NDArray, exposure: NDArray) -> NDArray: @@ -207,223 +187,258 @@ def get_deadtime_ratios(sectored_rates_ds: xr.Dataset) -> xr.DataArray: dead_time_ratio : xarray.DataArray Dead time correction factor for each sector. """ - # Compute the correction factor at each sector - a = sectored_rates_ds.fifo_valid_events / ( - 1 - - (sectored_rates_ds.event_active_time + 2 * sectored_rates_ds.start_pos) * 1e-7 - ) - - start_full = sectored_rates_ds.start_rf + sectored_rates_ds.start_lf - b = a * np.exp(start_full * 1e-7 * 5) - + tint = (24 / 360) * sectored_rates_ds.spin_durations + # compute the correction factor for each step in each sector + start_full_cdf = sectored_rates_ds.start_rf + sectored_rates_ds.start_lf coin_stop_nd = ( sectored_rates_ds.coin_tn + sectored_rates_ds.coin_bn - sectored_rates_ds.stop_tn - sectored_rates_ds.stop_bn ) + numerator = np.exp(5e-7 * start_full_cdf) * np.exp(8e-7 * coin_stop_nd) * tint + denominator = ( + tint + - (sectored_rates_ds.event_active_time + 2 * sectored_rates_ds.start_pos) * 1e-7 + ) - corrected_valid_events = b * np.exp(1e-7 * 8 * coin_stop_nd) - + correction_factor = numerator / denominator # Compute dead time ratio - dead_time_ratios = sectored_rates_ds.fifo_valid_events / corrected_valid_events + dead_time_ratios = 1 / correction_factor return dead_time_ratios -def get_sectored_rates(rates_ds: xr.Dataset, params_ds: xr.Dataset) -> xr.Dataset: +def get_sectored_rates(rates_ds: xr.Dataset) -> xr.Dataset | None: """ Filter rates dataset to only include sector mode data. + Identify intervals where ULTRA was in sector mode by examining contiguous runs + of identical spin values. At the normal 15-second spin period, each 24Β° sector + takes ~1 second, so a full spin in sector mode consists of 15 sectors. + Parameters ---------- rates_ds : xarray.Dataset Dataset containing image rates data. - params_ds : xarray.Dataset - Dataset containing image parameters data. Returns ------- - rates : xarray.Dataset + rates : xarray.Dataset or None Rates dataset with only the sector mode data. """ - # Find indices in which the parameters dataset, indicates that ULTRA was in - # sector mode. At the normal 15-second spin period, each 24Β° sector takes ~1 second. - - # This means that data was collected as a function of spin allowing for fine grained - # rate analysis. - sector_mode_start_inds = np.where(params_ds["imageratescadence"] == 3)[0] - # get the sector mode start and stop indices - sector_mode_stop_inds = sector_mode_start_inds + 1 - # get the sector mode start and stop times - mode_3_start = params_ds["epoch"].values[sector_mode_start_inds] - - # if the last mode is a sector mode, we can assume that the sector data goes through - # the end of the dataset, so we append np.inf to the end of the last time range. - if sector_mode_stop_inds[-1] == len(params_ds["epoch"]): - mode_3_end = np.append( - params_ds["epoch"].values[sector_mode_stop_inds[:-1]], np.inf - ) - else: - mode_3_end = params_ds["epoch"].values[sector_mode_stop_inds] - - # Build a list of conditions for each sector mode time range - conditions = [ - (rates_ds["epoch"] >= start) & (rates_ds["epoch"] < end) - for start, end in zip(mode_3_start, mode_3_end, strict=False) - ] - - sector_mode_mask = np.logical_or.reduce(conditions) - return rates_ds.isel(epoch=sector_mode_mask) + spins = rates_ds.spin.values + # Check if spins are monotonically increasing + if not np.all(np.diff(spins) >= 0): + logger.warning("Spin values in rates dataset are not monotonically increasing.") + # Get the indices where the spin value changes + spin_change = np.where(np.diff(spins) != 0)[0] + 1 + # add the first and last index + spin_change = np.concatenate(([0], spin_change, [len(spins)])) + # Get the length of each spin run + # e.g. 0,0,0,3,3,3,4,4 -> 3,3,2 + spin_runs = np.diff(spin_change) + # Find the indices where the spin run length is exactly 15 (sector mode) + spin_run_inds = np.where(spin_runs == 15)[0] + + if len(spin_run_inds) == 0: + return None + + # Get the start indices of each sector mode spin + sector_starts = spin_change[spin_run_inds] + sectored_mode_mask: np.ndarray = np.zeros(len(spins), dtype=bool) + starts = np.asarray(sector_starts) + # Create offsets 0..14 and broadcast + idx = starts[:, None] + np.arange(15) + sectored_mode_mask[idx] = True + # Return the sectored rates dataset + return rates_ds.isel(epoch=sectored_mode_mask) def get_deadtime_ratios_by_spin_phase( - sectored_rates: xr.Dataset, -) -> np.ndarray: + sectored_rates: xr.Dataset | None, + aux_dataset: xr.Dataset, + spin_steps: int, + sensor_id: int | None = None, + ancillary_files: dict | None = None, +) -> xr.DataArray: """ Calculate nominal deadtime ratios at every spin phase step (1ms res). Parameters ---------- - sectored_rates : xarray.Dataset + sectored_rates : xarray.Dataset, optional Dataset containing sector mode image rates data. + aux_dataset : xarray.Dataset + Auxiliary dataset containing spin information. + spin_steps : int + Number of spin phase steps (e.g. 15000 for 1ms resolution). + sensor_id : int, optional + Sensor ID, either 45 or 90. + ancillary_files : dict, optional + Dictionary containing ancillary files. Returns ------- - numpy.ndarray - Nominal deadtime ratios at every spin phase step (1ms res). + xarray.DataArray + Nominal deadtime ratios at every spin phase step. """ - deadtime_ratios = get_deadtime_ratios(sectored_rates) - # Get the spin phase at the start of each sector rate measurement - spin_phases = np.asarray( - get_spin_angle( - get_spacecraft_spin_phase(np.array(sectored_rates.epoch.data)), degrees=True + if sectored_rates is None or sectored_rates.epoch.size == 0: + logger.warning( + "No sector mode data found in the parameters dataset. Using " + "static dead time ratios from an ancillary file." ) - ) - # Assume the sectored rate data is evenly spaced in time, and find the middle spin - # phase value for each sector. - # The center spin phase is the closest / most accurate spin phase. - # There are 24 spin phases per sector so the nominal middle sector spin phases - # would be: array([ 12., 36., ..., 300., 324.]) for 15 sectors. - spin_phases_centered = (spin_phases[:-1] + spin_phases[1:]) / 2 - # Assume the last sector is nominal because we dont have enough data to determine - # the spin phase at the end of the last sector. - # TODO: is this assumption valid? - # Add the last spin phase value + half of a nominal sector. - spin_phases_centered = np.append(spin_phases_centered, spin_phases[-1] + 12) - # Wrap any spin phases > 360 back to [0, 360] - spin_phases_centered = spin_phases_centered % 360 + if sensor_id is None or ancillary_files is None: + raise ValueError( + "sensor_id and ancillary_files must be provided to " + "get static deadtime ratios." + ) + spin_phases_centered, deadtime_ratios = get_static_deadtime_ratios( + sensor_id, ancillary_files + ) + else: + num_spin_sectors = 15 + sector_indices: np.ndarray = ( + np.arange(len(sectored_rates["epoch"])) % num_spin_sectors + ) + # Get timestamps at the start of each spin (sector 0) + spin_start_indices = np.where(sector_indices == 0)[0] + met_time = sectored_rates["shcoarse"].values[spin_start_indices] + spin_ds = get_spin_info(aux_dataset, met_time) + # Repeat the spin duration for each of the 15 sectors. + # Sectors are all within a spin so each one corresponds to the same spin + # duration + sectored_rates["spin_durations"] = ( + "epoch", + np.repeat(spin_ds.spin_duration.data, num_spin_sectors), + ) + deadtime_ratios = get_deadtime_ratios(sectored_rates).data + # The center spin phase is the closest / most accurate spin phase. + # There are 24 spin phases per sector so the nominal middle sector spin phases + # would be: array([ 12., 36., ..., 300., 324.]) for 15 sectors. + # We can assume each sector 0 starts at spin phase 0 + spin_phases_centered = (sector_indices / num_spin_sectors) * 360.0 + 12.0 + # Create a dataset with spin phases and dead time ratios deadtime_by_spin_phase = xr.Dataset( - {"deadtime_ratio": deadtime_ratios}, - coords={ - "spin_phase": xr.DataArray(np.array(spin_phases_centered), dims="epoch") - }, + {"deadtime_ratio": (("spin_phase",), deadtime_ratios)}, + coords={"spin_phase": xr.DataArray(spin_phases_centered, dims="spin_phase")}, ) - # Sort the dataset by spin phase (ascending order) deadtime_by_spin_phase = deadtime_by_spin_phase.sortby("spin_phase") # Group by spin phase and calculate the median dead time ratio for each phase deadtime_medians = deadtime_by_spin_phase.groupby("spin_phase").median(skipna=True) - if np.any(np.isnan(deadtime_medians["deadtime_ratio"].values)): - raise ValueError( - "Dead time ratios contain NaN values, cannot create interpolator." + if not np.any(np.isfinite(deadtime_medians["deadtime_ratio"].values)): + raise ValueError("All dead time ratios are NaN, cannot interpolate.") + logger.warning( + "Dead time ratios contain NaN values, filtering data to only include " + "finite values." ) + deadtime_medians = deadtime_medians.where( + np.isfinite(deadtime_medians["deadtime_ratio"]), drop=True + ) interpolator = interpolate.PchipInterpolator( deadtime_medians["spin_phase"].values, deadtime_medians["deadtime_ratio"].values ) - # Calculate the nominal spin phases at 1 ms resolution and query the pchip + # Calculate the nominal spin phases at the supplied resolution and query the pchip # interpolator to get the deadtime ratios. - steps = 15 * 1000 # 15 seconds at 1 ms resolution - nominal_spin_phases_1ms_res = np.arange(0, 360, 360 / steps) - return interpolator(nominal_spin_phases_1ms_res) + nominal_spin_phases = np.arange(0, 360, 360 / spin_steps) + deadtime_ratios = xr.DataArray( + interpolator(nominal_spin_phases), dims="spin_phase_step" + ) + return deadtime_ratios -def apply_deadtime_correction( - exposure_pointing: pandas.DataFrame, - deadtime_ratios: np.ndarray, - pixels_below_scattering: list, - boundary_scale_factors: NDArray, -) -> np.ndarray: +def calculate_exposure_time( + deadtime_ratios: xr.DataArray, + valid_spun_pixels: xr.DataArray, + boundary_scale_factors: xr.DataArray, + apply_bsf: bool = True, +) -> xr.DataArray: """ Adjust the exposure time at each pixel to account for dead time. Parameters ---------- - exposure_pointing : pandas.DataFrame - Exposure data. - deadtime_ratios : PchipInterpolator - Interpolating function for dead time ratios. - pixels_below_scattering : list - A Nested list of arrays indicating pixels within the scattering threshold. - The outer list indicates spin phase steps, the middle list indicates energy - bins, and the inner arrays contain indices indicating pixels that are below - the FWHM scattering threshold. - boundary_scale_factors : np.ndarray + deadtime_ratios : xarray.DataArray + Deadtime ratios at each spin phase step. + valid_spun_pixels : xarray.DataArray + 3D Array of pixels valid at each spin phase step. If rejection based on + scattering was set, then these are the pixels below the FWHM scattering + threshold and in the field of regard at each spin phase step, and energy + shape = (spin_phase_steps, energy_bins, n_pix). IF no rejection, + then these are simply the pixels in the field of regard at each spin phase step + shape = (spin_phase_steps, 1, n_pix). + boundary_scale_factors : xr.DataArray Boundary scale factors for each pixel at each spin phase. + apply_bsf : bool, optional + Whether to apply boundary scale factors. Default is True. Returns ------- - exposure_pointing_adjusted : np.ndarray + exposure_pointing: xarray.DataArray Adjusted exposure times accounting for dead time. + Shape: ``(energy, pixel)``. """ - # Get energy bin geometric means - energy_bin_geometric_means = build_energy_bins()[2] - # Exposure time should now be of shape (npix, energy) - exposure_pointing = np.repeat( - exposure_pointing.to_numpy()[np.newaxis, :], - len(energy_bin_geometric_means), - axis=0, - ) # nominal spin phase step. - nominal_ms_step = 15 / len(pixels_below_scattering) # time step + nominal_ms_step = 15 / valid_spun_pixels.shape[0] # time step # Query the dead-time ratio and apply the nominal exposure time to pixels in the FOR - # and below the scattering threshold - # Loop through the spin phase steps. This is spinning the spacecraft by nominal - # 1 ms steps in the despun frame. - for i, pixels_at_spin in enumerate(pixels_below_scattering): - # Loop through energy bins - for energy_bin_idx in range(len(energy_bin_geometric_means)): - pixels_at_energy_and_spin = pixels_at_spin[energy_bin_idx] - if pixels_at_energy_and_spin.size == 0: - continue - # Apply the nominal exposure time (1 ms) scaled by the deadtime ratio to - # every pixel in the FOR, that is below the FWHM scattering threshold, - exposure_pointing[energy_bin_idx, pixels_at_energy_and_spin] += ( - nominal_ms_step - * deadtime_ratios[i] - * boundary_scale_factors[pixels_at_energy_and_spin, i] - ) - + # and below the scattering threshold (if scattering rejection is on). + # Sum over the first dim of valid_spun_pixels is the spin phase step. + # This is like spinning the spacecraft by nominal 1 ms steps in the despun frame. + all_counts = valid_spun_pixels * deadtime_ratios + if apply_bsf: + all_counts *= boundary_scale_factors + + counts = all_counts.sum(dim="spin_phase_step") + # Multiply by the nominal spin step to get the exposure time in ms + exposure_pointing = counts * nominal_ms_step return exposure_pointing def get_spacecraft_exposure_times( - constant_exposure: pandas.DataFrame, rates_dataset: xr.Dataset, - params_dataset: xr.Dataset, - pixels_below_scattering: list[list], - boundary_scale_factors: NDArray, + valid_spun_pixels: xr.DataArray, + boundary_scale_factors: xr.DataArray, + aux_dataset: xr.Dataset, + energy_bins: np.ndarray, + goodtimes_dataset: xr.Dataset, + sensor_id: int | None = None, + ancillary_files: dict | None = None, + apply_bsf: bool = True, ) -> tuple[NDArray, NDArray]: """ Compute exposure times for HEALPix pixels. Parameters ---------- - constant_exposure : pandas.DataFrame - Exposure data. rates_dataset : xarray.Dataset Dataset containing image rates data. - params_dataset : xarray.Dataset - Dataset containing image parameters data. - pixels_below_scattering : list - List of lists indicating pixels within the scattering threshold. - The outer list indicates spin phase steps, the middle list indicates energy - bins, and the inner list contains pixel indices indicating pixels that are - below the FWHM scattering threshold. - boundary_scale_factors : np.ndarray + valid_spun_pixels : xarray.DataArray + 3D Array of pixels valid at each spin phase step. If rejection based on + scattering was set, then these are the pixels below the FWHM scattering + threshold and in the field of regard at each spin phase step, and energy + shape = (spin_phase_steps, energy_bins, n_pix). IF no rejection, + then these are simply the pixels in the field of regard at each spin phase step + shape = (spin_phase_steps, 1, n_pix). + boundary_scale_factors : xarray.DataArray Boundary scale factors for each pixel at each spin phase. + aux_dataset : xarray.Dataset + Auxiliary dataset containing spin information. + energy_bins : np.ndarray + Array of energy bin geometric means. + goodtimes_dataset : xarray.Dataset + Dataset containing the quality-filtered spins with energy dependent quality + flags (quality_low_voltage, quality_high_energy, quality_statistics). + Exposure times are computed using only these good spins + and can be adjusted per energy bin based on quality flags. + sensor_id : int, optional + Sensor ID, either 45 or 90. + ancillary_files : dict, optional + Dictionary containing ancillary files. + apply_bsf : bool, optional + Whether to apply boundary scale factors. Default is True. Returns ------- @@ -431,32 +446,93 @@ def get_spacecraft_exposure_times( Total exposure times of pixels in a Healpix tessellation of the sky in the pointing (dps) frame. + Shape: (n_energy_bins, n_pix). nominal_deadtime_ratios : np.ndarray Deadtime ratios at each spin phase step (1ms res). """ - # TODO: use the universal spin table and - # universal pointing table here to determine actual number of spins - sectored_rates = get_sectored_rates(rates_dataset, params_dataset) - nominal_deadtime_ratios = get_deadtime_ratios_by_spin_phase(sectored_rates) - exposure_pointing = ( - constant_exposure["Exposure Time"] * 5760 - ) # 5760 spins per pointing (for now) - exposure_pointing_adjusted = apply_deadtime_correction( - exposure_pointing, - nominal_deadtime_ratios, - pixels_below_scattering, - boundary_scale_factors, + sectored_rates = get_sectored_rates(rates_dataset) + # Get the number of steps used in the spun pointing lookup tables + spin_steps = valid_spun_pixels.shape[0] + nominal_deadtime_ratios = get_deadtime_ratios_by_spin_phase( + sectored_rates, aux_dataset, spin_steps, sensor_id, ancillary_files + ) + # The exposure time will be approximately the same per spin, so to save + # computation time, calculate the exposure time for a single spin and then scale it + # by the number of spins in the pointing. For more information, see section 3.4.3 + # of the Ultra Algorithm Document. + exposure_time = calculate_exposure_time( + nominal_deadtime_ratios, valid_spun_pixels, boundary_scale_factors, apply_bsf + ) + if exposure_time.ndim != 2: + raise ValueError( + "Exposure time must be 2D with dimensions ('energy', 'pixel'); " + f"got dims {exposure_time.dims} and shape {exposure_time.shape}." + ) + nominal_spin_seconds = 15.0 + # Use filtered spins from goodtimes dataset to include only the spins that + # passed the quality flag filtering. + spin_periods = goodtimes_dataset["spin_period"].values + energy_flags = goodtimes_dataset["energy_range_flags"].values + # only get valid flags for the energy bins we are using at l1c + # Filter out fill values (0s) from energy_range_flags + energy_flags = energy_flags[energy_flags > 0] + # Filter out fill values from energy_range_edges + energy_range_edges = goodtimes_dataset["energy_range_edges"].values + # Remove fill values (negative or zero) + energy_range_edges_valid = energy_range_edges[energy_range_edges > 0] + # Get the quality flag arrays "turned on" for energy dependent culling from the + # goodtimes dataset. + flag_arrays = [ + goodtimes_dataset[flag_name].values + for flag_name in ENERGY_DEPENDENT_SPIN_QUALITY_FLAG_FILTERS + ] + bin_to_range = np.digitize(energy_bins, energy_range_edges_valid) + valid_spins = ( + np.bitwise_or.reduce(flag_arrays)[np.newaxis, :] & energy_flags[:, np.newaxis] + ) == 0 + # Pad valid_spins with arrays of all true at either end to account for energy bins + # that fall outside the range of the goodtimes dataset energy edges. Energy bins + # outside these ranges were not included in the quality flag filtering, so they are + # considered valid (all true). + valid_spins_padded = np.pad( + valid_spins, + pad_width=((1, 1), (0, 0)), + # pad only the energy axis + mode="constant", + constant_values=True, + ) + # Select the valid spins for each energy bin using the bin_to_range indices + good_spins_per_ebin = valid_spins_padded[bin_to_range] + # Broadcast spin periods to have the correct shape e.g. (energy_bins, spins) + spin_periods_2d = np.broadcast_to( + spin_periods[np.newaxis, :], good_spins_per_ebin.shape + ) + # Calculate total normalized spin count using spin periods from goodtimes + # Shape (n_energy_bins) + n_spins_in_pointing = ( + np.sum(spin_periods_2d, axis=1, where=good_spins_per_ebin) + / nominal_spin_seconds ) - return exposure_pointing_adjusted, nominal_deadtime_ratios + + logger.info( + f"Calculated total spins. Found {n_spins_in_pointing.tolist()} valid spins per " + f"energy range." + ) + # Shape (n_energy_bins, n_pix) + exposure_pointing_adjusted = exposure_time.data * n_spins_in_pointing[:, np.newaxis] + + return exposure_pointing_adjusted, nominal_deadtime_ratios.values def get_efficiencies_and_geometric_function( - pixels_below_scattering: list[list], - boundary_scale_factors: np.ndarray, + valid_spun_pixels: xr.DataArray, + boundary_scale_factors: xr.DataArray, theta_vals: np.ndarray, phi_vals: np.ndarray, npix: int, + sensor_id: int, ancillary_files: dict, + apply_bsf: bool = True, ) -> tuple[np.ndarray, np.ndarray]: """ Compute the geometric factor and efficiency for each pixel and energy bin. @@ -465,31 +541,45 @@ def get_efficiencies_and_geometric_function( Parameters ---------- - pixels_below_scattering : list - List of lists indicating pixels within the scattering threshold. - The outer list indicates spin phase steps, the middle list indicates energy - bins, and the inner list contains pixel indices indicating pixels that are - below the FWHM scattering threshold. - boundary_scale_factors : np.ndarray + valid_spun_pixels : xarray.DataArray + 3D Array of pixels valid at each spin phase step. If rejection based on + scattering was set, then these are the pixels below the FWHM scattering + threshold and in the field of regard at each spin phase step, and energy + shape = (spin_phase_steps, energy_bins, n_pix). IF no rejection, + then these are simply the pixels in the field of regard at each spin phase step + shape = (spin_phase_steps, 1, n_pix). + boundary_scale_factors : xarray.DataArray Boundary scale factors for each pixel at each spin phase. theta_vals : np.ndarray - A 2D array of theta values for each HEALPix pixel at each spin phase step. + 2D or 3D array of theta values. Shape is either (spin_phase_step, npix) + or (spin_phase_step, energy_bins, npix) when energy-dependent scattering + rejection is used. phi_vals : np.ndarray - A 2D array of phi values for each HEALPix pixel at each spin phase step. + Array of phi values with the same shape as `theta_vals`, giving the + corresponding phi for each pixel (and energy, if present). npix : int Number of HEALPix pixels. + sensor_id : int + Sensor ID, either 45 or 90. ancillary_files : dict Dictionary containing ancillary files. + apply_bsf : bool, optional + Whether to apply boundary scale factors. Default is True. Returns ------- - gf_summation : np.ndarray - Summation of geometric factors for each pixel and energy bin. - eff_summation : np.ndarray - Summation of efficiencies for each pixel and energy bin. + gf_averaged : np.ndarray + Averaged geometric factors across all spin phases. + Shape = (n_energy_bins, npix). + eff_averaged : np.ndarray + Averaged efficiencies across all spin phases. + Shape = (n_energy_bins, npix). """ + sensor_name = f"ultra{sensor_id}" # Load callable efficiency interpolator function - eff_interpolator = get_efficiency_interpolator(ancillary_files) + eff_interpolator, theta_min_max, phi_min_max, e_min_max = ( + get_efficiency_interpolator(ancillary_files, sensor_name) + ) # load geometric factor lookup table geometric_lookup_table = load_geometric_factor_tables( ancillary_files, "l1b-sensor-gf-blades" @@ -497,174 +587,104 @@ def get_efficiencies_and_geometric_function( # Get energy bin geometric means energy_bin_geometric_means = build_energy_bins()[2] energy_bins = len(energy_bin_geometric_means) + # clip arrays to avoid out of bounds errors + logger.info( + "Clipping Theta and Phi values to valid ranges for the efficiency " + "interpolation. \n" + f"Theta valid range: {theta_min_max}, Phi valid range: {phi_min_max}. \n " + f"Found " + f"{np.sum((theta_vals < theta_min_max[0]) | (theta_vals > theta_min_max[1]))}" + f" Theta values out of range. \n" + f"Found " + f"{np.sum((phi_vals < phi_min_max[0]) | (phi_vals > phi_min_max[1]))}" + f" Phi values out of range. \n" + f"Theta min and max values before clipping: " + f"{theta_vals.min()}, {theta_vals.max()} \n" + f"Phi min and max values before clipping:" + f" {phi_vals.min()}, {phi_vals.max()} \n" + ) + theta_vals_clipped = np.clip(theta_vals, theta_min_max[0], theta_min_max[1]) + phi_vals_clipped = np.clip(phi_vals, phi_min_max[0], phi_min_max[1]) # Initialize summation arrays for geometric factors and efficiencies gf_summation = np.zeros((energy_bins, npix)) eff_summation = np.zeros((energy_bins, npix)) sample_count = np.zeros((energy_bins, npix)) # Loop through spin phases - for i, pixels_at_spin in enumerate(pixels_below_scattering): + spin_steps = valid_spun_pixels.sizes["spin_phase_step"] + for i in range(spin_steps): # Loop through energy bins - # Compute gf and eff for these theta/phi pairs - theta_at_spin = theta_vals[:, i] - phi_at_spin = phi_vals[:, i] - gf_values = get_geometric_factor( - phi=phi_at_spin, - theta=theta_at_spin, - quality_flag=np.zeros(len(phi_at_spin)).astype(np.uint16), - geometric_factor_tables=geometric_lookup_table, - ) + # Get valid pixels at this spin phase + valid_at_spin = valid_spun_pixels.isel( + spin_phase_step=i + ) # shape: (energy, pixel) + for energy_bin_idx in range(energy_bins): - pixel_inds = pixels_at_spin[energy_bin_idx] + # Determine pixel indices based on energy dependence + if theta_vals.ndim < 3: + # Energy independent calculations + # TODO this may cause performance issues. Revisit later. + pixel_inds = np.where(valid_at_spin.isel(energy=0))[0] + # Compute gf and eff for these theta/phi pairs + theta_at_spin = theta_vals[i, :] + phi_at_spin = phi_vals[i, :] + theta_at_spin_clipped = theta_vals_clipped[i, :] + phi_at_spin_clipped = phi_vals_clipped[i, :] + else: + # Energy dependent calculations + pixel_inds = np.where(valid_at_spin.isel(energy=energy_bin_idx))[0] + # Compute gf and eff for these theta/phi pairs + theta_at_spin = theta_vals[i, energy_bin_idx, :] + phi_at_spin = phi_vals[i, energy_bin_idx, :] + theta_at_spin_clipped = theta_vals_clipped[i, energy_bin_idx, :] + phi_at_spin_clipped = phi_vals_clipped[i, energy_bin_idx, :] + if pixel_inds.size == 0: continue + + gf_values = get_geometric_factor( + phi=phi_at_spin[pixel_inds], + theta=theta_at_spin[pixel_inds], + quality_flag=np.zeros(len(phi_at_spin[pixel_inds])).astype(np.uint16), + geometric_factor_tables=geometric_lookup_table, + ) energy = energy_bin_geometric_means[energy_bin_idx] + # Clip energy to calibrated range + energy_clipped = np.clip(energy, e_min_max[0], e_min_max[1]) eff_values = get_efficiency( - np.full(phi_at_spin[pixel_inds].shape, energy), - phi_at_spin[pixel_inds], - theta_at_spin[pixel_inds], + np.full(pixel_inds.size, energy_clipped), + phi_at_spin_clipped[pixel_inds], + theta_at_spin_clipped[pixel_inds], ancillary_files, + sensor_name, interpolator=eff_interpolator, ) - # Accumulate gf and eff values - gf_summation[energy_bin_idx, pixel_inds] += ( - gf_values[pixel_inds] * boundary_scale_factors[pixel_inds, i] - ) - eff_summation[energy_bin_idx, pixel_inds] += ( - eff_values * boundary_scale_factors[pixel_inds, i] + + # Accumulate and sum eff and gf values + bsfs = ( + boundary_scale_factors[i, pixel_inds] + if apply_bsf + else np.ones(len(pixel_inds)) ) + gf_summation[energy_bin_idx, pixel_inds] += gf_values * bsfs + eff_summation[energy_bin_idx, pixel_inds] += eff_values * bsfs sample_count[energy_bin_idx, pixel_inds] += 1 # return averaged geometric factors and efficiencies across all spin phases # These are now energy dependent. - gf_averaged = np.divide(gf_summation, sample_count, where=sample_count != 0) - eff_averaged = np.divide(eff_summation, sample_count, where=sample_count != 0) + gf_averaged = np.zeros_like(gf_summation) + eff_averaged = np.zeros_like(eff_summation) + np.divide(gf_summation, sample_count, out=gf_averaged, where=sample_count != 0) + np.divide(eff_summation, sample_count, out=eff_averaged, where=sample_count != 0) return gf_averaged, eff_averaged -def get_helio_adjusted_data( - time: float, - exposure_time: np.ndarray, - geometric_factor: np.ndarray, - efficiency: np.ndarray, - ra: np.ndarray, - dec: np.ndarray, - nside: int = 128, - nested: bool = False, -) -> tuple[NDArray, NDArray, NDArray]: - """ - Compute 2D (Healpix index, energy) arrays for in the helio frame. - - Build CG corrected exposure, efficiency, and geometric factor arrays. - - Parameters - ---------- - time : float - Median time of pointing in et. - exposure_time : np.ndarray - Spacecraft exposure. Shape = (energy, npix). - geometric_factor : np.ndarray - Geometric factor values. Shape = (energy, npix). - efficiency : np.ndarray - Efficiency values. Shape = (energy, npix). - ra : np.ndarray - Right ascension in the spacecraft frame (degrees). - dec : np.ndarray - Declination in the spacecraft frame (degrees). - nside : int, optional - The nside parameter of the Healpix tessellation (default is 128). - nested : bool, optional - Whether the Healpix tessellation is nested (default is False). - - Returns - ------- - helio_exposure : np.ndarray - A 2D array of shape (n_energy_bins, npix). - helio_efficiency : np.ndarray - A 2D array of shape (n_energy_bins, npix). - helio_geometric_factors : np.ndarray - A 2D array of shape (n_energy_bins, npix). - - Notes - ----- - These calculations are performed once per pointing. - """ - # Get energy midpoints. - _, _, energy_bin_geometric_means = build_energy_bins() - - # The Cartesian state vector representing the position and velocity of the - # IMAP spacecraft. - state = imap_state(time, ref_frame=SpiceFrame.IMAP_DPS) - - # Extract the velocity part of the state vector - spacecraft_velocity = state[3:6] - # Convert (RA, Dec) angles into 3D unit vectors. - # Each unit vector represents a direction in the sky where the spacecraft observed - # and accumulated exposure time. - npix = hp.nside2npix(nside) - unit_dirs = hp.ang2vec(ra, dec, lonlat=True).T # Shape (N, 3) - shape = (len(energy_bin_geometric_means), int(npix)) - if np.any( - [arr.shape != shape for arr in [exposure_time, geometric_factor, efficiency]] - ): - raise ValueError( - f"Input arrays must have the same shape {shape}, but got " - f"{exposure_time.shape}, {geometric_factor.shape}, {efficiency.shape}." - ) - # Initialize output array. - # Each row corresponds to a HEALPix pixel, and each column to an energy bin. - helio_exposure = np.zeros(shape) - helio_efficiency = np.zeros(shape) - helio_geometric_factors = np.zeros(shape) - - # Loop through energy bins and compute transformed exposure. - for i, energy_mean in enumerate(energy_bin_geometric_means): - # Convert the midpoint energy to a velocity (km/s). - # Based on kinetic energy equation: E = 1/2 * m * v^2. - energy_velocity = ( - np.sqrt(2 * energy_mean * UltraConstants.KEV_J / UltraConstants.MASS_H) - / 1e3 - ) - - # Use Galilean Transform to transform the velocity wrt spacecraft - # to the velocity wrt heliosphere. - # energy_velocity * cartesian -> apply the magnitude of the velocity - # to every position on the grid in the despun grid. - helio_velocity = spacecraft_velocity.reshape(1, 3) + energy_velocity * unit_dirs - - # Normalized vectors representing the direction of the heliocentric velocity. - helio_normalized = helio_velocity / np.linalg.norm( - helio_velocity, axis=1, keepdims=True - ) - - # Convert Cartesian heliocentric vectors into spherical coordinates. - # Result: azimuth (longitude) and elevation (latitude) in degrees. - helio_spherical = cartesian_to_spherical(helio_normalized) - az, el = helio_spherical[:, 1], helio_spherical[:, 2] - - # Convert azimuth/elevation directions to HEALPix pixel indices. - hpix_idx = hp.ang2pix(nside, az, el, nest=nested, lonlat=True) - - # Accumulate exposure, eff, and gf values into HEALPix pixels for this energy - # bin. - helio_exposure[i, :] = np.bincount( - hpix_idx, weights=exposure_time[i, :], minlength=npix - ) - helio_efficiency[i, :] = np.bincount( - hpix_idx, weights=efficiency[i, :], minlength=npix - ) - helio_geometric_factors[i, :] = np.bincount( - hpix_idx, weights=geometric_factor[i, :], minlength=npix - ) - - return helio_exposure, helio_efficiency, helio_geometric_factors - - def get_spacecraft_background_rates( rates_dataset: xr.Dataset, - sensor: str, + aux_dataset: xr.Dataset, + sensor_id: int, ancillary_files: dict, energy_bin_edges: list[tuple[float, float]], - cullingmask_spin_number: NDArray, + goodtimes_spin_number: NDArray, nside: int = 128, ) -> NDArray: """ @@ -674,15 +694,17 @@ def get_spacecraft_background_rates( ---------- rates_dataset : xr.Dataset Rates dataset. - sensor : str - Sensor name: "ultra45" or "ultra90". + aux_dataset : xr.Dataset + Auxiliary dataset. + sensor_id : int + Sensor ID: either 45 or 90. ancillary_files : dict[Path] Ancillary files containing the lookup tables. energy_bin_edges : list[tuple[float, float]] Energy bin edges. - cullingmask_spin_number : NDArray + goodtimes_spin_number : NDArray Goodtime spins. - Ex. imap_ultra_l1b_45sensor-cullingmask[0]["spin_number"] + Ex. imap_ultra_l1b_45sensor-goodtimes[0]["spin_number"] This is used to determine the number of pulses per spin. nside : int, optional The nside parameter of the Healpix tessellation (default is 128). @@ -696,13 +718,12 @@ def get_spacecraft_background_rates( ----- See Eqn. 3, 8, and 20 in the Algorithm Document for the equation. """ - pulses = get_pulses_per_spin(rates_dataset) + pulses = get_pulses_per_spin(aux_dataset, rates_dataset) # Pulses for the pointing. - etof_min = get_image_params("eTOFMin", sensor, ancillary_files) - etof_max = get_image_params("eTOFMax", sensor, ancillary_files) - spin_number, _ = get_spin_and_duration( - rates_dataset["shcoarse"], rates_dataset["spin"] - ) + etof_min = get_image_params("eTOFMin", f"ultra{sensor_id}", ancillary_files) + etof_max = get_image_params("eTOFMax", f"ultra{sensor_id}", ancillary_files) + spin_ds = get_spin_info(aux_dataset, rates_dataset["shcoarse"].values) + spin_number = spin_ds["spin_number"].values # Get dmin for PH (mm). dmin_ctof = UltraConstants.DMIN_PH_CTOF @@ -714,7 +735,7 @@ def get_spacecraft_background_rates( background_rates = np.zeros((len(energy_bin_edges), n_pix)) # Only select pulses from goodtimes. - goodtime_mask = np.isin(spin_number, cullingmask_spin_number) + goodtime_mask = np.isin(spin_number, goodtimes_spin_number) mean_start_pulses = np.mean(pulses.start_pulses[goodtime_mask]) mean_stop_pulses = np.mean(pulses.stop_pulses[goodtime_mask]) mean_coin_pulses = np.mean(pulses.coin_pulses[goodtime_mask]) diff --git a/imap_processing/ultra/l2/ultra_l2.py b/imap_processing/ultra/l2/ultra_l2.py index 342075064a..00f09f37a0 100644 --- a/imap_processing/ultra/l2/ultra_l2.py +++ b/imap_processing/ultra/l2/ultra_l2.py @@ -1,5 +1,6 @@ """Calculate ULTRA Level 2 (L2) ENA Map Product.""" +# ruff: noqa: PLR0912 from __future__ import annotations import logging @@ -10,6 +11,7 @@ from numpy.typing import NDArray from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes +from imap_processing.cdf.utils import load_cdf from imap_processing.ena_maps import ena_maps from imap_processing.ena_maps.utils.coordinates import CoordNames from imap_processing.ena_maps.utils.naming import ( @@ -17,7 +19,13 @@ MapDescriptor, ns_to_duration_months, ) -from imap_processing.ultra.l1c.ultra_l1c_pset_bins import get_energy_delta_minus_plus +from imap_processing.quality_flags import ImapPSETUltraFlags +from imap_processing.ultra.constants import UltraConstants +from imap_processing.ultra.l1c.l1c_lookup_utils import build_energy_bins +from imap_processing.ultra.l1c.ultra_l1c_pset_bins import ( + FILLVAL_FLOAT32, + get_energy_delta_minus_plus, +) logger = logging.getLogger(__name__) @@ -47,6 +55,8 @@ DEFAULT_L2_HEALPIX_NSIDE = 32 DEFAULT_L2_HEALPIX_NESTED = False +# Set the default energy bin size +DEFAULT_BIN_SIZE = 4 # These variables must always be present in each L1C dataset REQUIRED_L1C_VARIABLES_PUSH = [ @@ -54,29 +64,38 @@ ] REQUIRED_L1C_VARIABLES_PULL = [ "exposure_factor", - "sensitivity", "background_rates", "obs_date", ] - +# These variables are expected but not strictly required. In certain test scenarios, +# they may be missing, in which case we will raise a warning and continue. +# All psets must be consistent and either have these variables or not. +EXPECTED_L1C_POINTING_INDEPENDENT_VARIABLES_PULL = [ + "geometric_function", + "scatter_theta", + "scatter_phi", + "sensitivity", + "efficiency", +] # These variables are projected to the map as the mean of pointing set pixels value, # weighted by that pointing set pixel's exposure and solid angle VARIABLES_TO_WEIGHT_BY_POINTING_SET_EXPOSURE_TIMES_SOLID_ANGLE = [ "sensitivity", "background_rates", "obs_date", + "scatter_theta", + "scatter_phi", + "geometric_function", + "efficiency", ] # These variables are dropped after they are used to # calculate ena_intensity and its statistical uncertainty # They will not be present in the final map VARIABLES_TO_DROP_AFTER_INTENSITY_CALCULATION = [ - "counts", - "background_rates", "pointing_set_exposure_times_solid_angle", "num_pointing_set_pixel_members", "corrected_count_rate", - "obs_date_for_std", "obs_date_squared_for_std", ] @@ -89,6 +108,25 @@ "obs_date_range", ] +VARIABLES_TO_AVERAGE_OVER_COARSE_ENERGY_BINS = [ + "sensitivity", + "efficiency", + "geometric_function", + "exposure_factor", + "background_rates", + "scatter_theta", + "scatter_phi", +] +VARIABLES_TO_SUM_OVER_COARSE_ENERGY_BINS = ["counts"] + +# Variables that must be converted from HEALPIX -> RECTANGULAR using recursive +# subdivision. We do this only for ENA intensity products, while other variables are +# projected directly on the rectangular grid from PSETs. +RECURSIVE_HEALPIX_TO_RECTANGULAR_VARIABLES = [ + "ena_intensity", + "ena_intensity_stat_uncert", +] + def get_variable_attributes_optional_energy_dependence( cdf_attrs: ImapCdfAttributes, @@ -127,6 +165,8 @@ def get_variable_attributes_optional_energy_dependence( and (CoordNames.ENERGY_ULTRA_L1C.value not in variable_dims) ): variable_name = f"{variable_name}_energy_independent" + if variable_name == "counts": + variable_name = "ena_count" metadata = cdf_attrs.get_variable_attributes( variable_name=variable_name, @@ -135,19 +175,140 @@ def get_variable_attributes_optional_energy_dependence( return metadata -def generate_ultra_healpix_skymap( +def build_default_coarse_bin_edges() -> np.ndarray: + """ + Define energy bin groups for binning L1C energy bins into coarser bins. + + Returns + ------- + numpy.ndarray + Array of indices defining the new energy bin edges. + """ + # Get number of fine energy bins used in L1C PSETs + n_fine_energy_bins = len(build_energy_bins()[2]) + bin_edges = np.arange(n_fine_energy_bins)[::DEFAULT_BIN_SIZE] + # Make sure the last bin includes the remainder of the fine bins + if bin_edges[-1] != n_fine_energy_bins: + bin_edges = np.append(bin_edges, n_fine_energy_bins) + + return bin_edges + + +def bin_pset_energy_bins( + pset: xr.Dataset, bin_groups: np.ndarray | None = None +) -> xr.Dataset: + """ + Group fine-grained L1C PSET energy bins into coarser bins for l2 ULTRA maps. + + Parameters + ---------- + pset : xarray.Dataset + Ultra L1C pointing set dataset to bin. + bin_groups : numpy.ndarray, optional + Array of indices defining the new energy bin edges. If not provided, + DEFAULT_BIN_EDGES will be used. + + Returns + ------- + xarray.Dataset + The input pset with energy bins grouped according to the bin_groups. + """ + if bin_groups is None: + bin_groups = build_default_coarse_bin_edges() + # Get a list of variables that have the energy bin dimension + energy_dep_vars = [ + var for var in pset.data_vars if "energy_bin_geometric_mean" in pset[var].dims + ] + # From those, get the variables that need to be averaged over the coarse bins + vars_to_average = [ + var + for var in energy_dep_vars + if var in VARIABLES_TO_AVERAGE_OVER_COARSE_ENERGY_BINS + ] + logger.info( + f"Binning pset fine energy bins into coarser bins with edges: {bin_groups}" + ) + n_fine_bins = pset["energy_bin_geometric_mean"].size + if bin_groups[-1] > n_fine_bins: + raise ValueError( + "The given bin_groups contain an index larger than the number of " + f"fine energy bins in the pset: {n_fine_bins}." + ) + # Select only the energy bins we want to keep (between first and last edge) + pset = pset.isel(energy_bin_geometric_mean=slice(bin_groups[0], bin_groups[-1])) + energy_inds = np.arange(n_fine_bins)[bin_groups[0] : bin_groups[-1]] + # Create a new coordinate for the new energy bin index + # For example, if bin_groups = [0,4,8,12...46], then the new coordinate will be: + # energy_bin_index = [0,0,0,0,1,1,1,1,2,2,2,2...12] That way we can groupby the new + # energy bin index to sum/average over the fine bins. + + pset = pset.assign_coords( + energy_bin_index=( + "energy_bin_geometric_mean", + np.digitize(energy_inds, bin_groups, right=False), + ) + ) + # Count number of pixels + non_zero_pixels_per_group = ( + ((pset[vars_to_average] != 0) & (pset[vars_to_average] != FILLVAL_FLOAT32)) + .astype(int) + .groupby("energy_bin_index") + .sum() + ) + # Sum variables over the new energy bins + pset[energy_dep_vars] = pset[energy_dep_vars].groupby("energy_bin_index").sum() + # Average variables by number of non-zero pixels at each new energy bin + # Create a mask to avoid division by zero + non_zero_pixels_per_group = non_zero_pixels_per_group.where( + non_zero_pixels_per_group != 0, 1 + ) + pset[vars_to_average] = pset[vars_to_average] / non_zero_pixels_per_group + # Calculate new energy bin geometric means + new_bin_edges = np.array(UltraConstants.PSET_ENERGY_BIN_EDGES)[bin_groups] + new_bin_geo_means = build_energy_bins(new_bin_edges)[2] + pset = pset.assign_coords( + energy_bin_geometric_mean=xr.DataArray( + new_bin_geo_means, + dims=["energy_bin_index"], + attrs=pset["energy_bin_geometric_mean"].attrs, + ) + ) + # Calculate new energy delta minus and plus + energy_delta_minus, energy_delta_plus = get_energy_delta_minus_plus(new_bin_edges) + pset.coords["energy_delta_minus"] = xr.DataArray( + energy_delta_minus, + dims=["energy_bin_index"], + ) + pset.coords["energy_delta_plus"] = xr.DataArray( + energy_delta_plus, + dims=["energy_bin_index"], + ) + # Make sure the variables use the new energy bin coordinate + pset = ( + pset.swap_dims({"energy_bin_index": "energy_bin_geometric_mean"}) + # Restore the original dimension order because groupby moves the grouped + # dimension to the front + .transpose("epoch", "energy_bin_geometric_mean", ...) + .drop_vars("energy_bin_index") + ) + return pset + + +def generate_ultra_skymap( ultra_l1c_psets: list[str | xr.Dataset], output_map_structure: ( ena_maps.RectangularSkyMap | ena_maps.HealpixSkyMap ) = DEFAULT_ULTRA_L2_MAP_STRUCTURE, -) -> tuple[ena_maps.HealpixSkyMap, NDArray]: + energy_bin_edges: np.ndarray | None = None, + build_rectangular_map: bool = False, +) -> tuple[ena_maps.HealpixSkyMap | ena_maps.RectangularSkyMap, NDArray]: """ - Generate a Healpix skymap from ULTRA L1C pointing sets. + Generate a skymap from ULTRA L1C pointing sets. - This function combines IMAP Ultra L1C pointing sets into a single L2 HealpixSkyMap. + This function combines IMAP Ultra L1C pointing sets into a single L2 SkyMap. It handles the projection of values from pointing sets to the map, applies necessary weighting and background subtraction, and calculates ena_intensity - and ena_intensity_stat_unc. + and ena_intensity_stat_uncert. Parameters ---------- @@ -157,12 +318,21 @@ def generate_ultra_healpix_skymap( output_map_structure : ena_maps.RectangularSkyMap | ena_maps.HealpixSkyMap, optional Empty SkyMap structure providing the properties of the map to be generated. Defaults to DEFAULT_ULTRA_L2_MAP_STRUCTURE defined in this module. + energy_bin_edges : numpy.ndarray, optional + Array of indices defining the new energy bin edges for binning + L1C energy bins into coarser bins. + Defaults to DEFAULT_BIN_EDGES defined in this module. + build_rectangular_map : bool, optional + Flag to indicate whether to build a rectangular map directly (True). Returns ------- - ena_maps.HealpixSkyMap - HealpixSkyMap object containing the combined data from all pointing sets, - with calculated ena_intensity and its statistical uncertainty values. + ena_maps.SkyMap + Either a RectangularSkyMap or a HealpixSkyMap object containing the combined + data from all pointing sets. If the map is a Healpix it will contain + calculated ena_intensity and its statistical uncertainty values. If rectangular, + It will contain the projected and weighted values but not the calculated + ena_intensity. NDArray Array of epochs corresponding to the pointing sets used in the map. @@ -174,7 +344,11 @@ def generate_ultra_healpix_skymap( Notes ----- The structure of this function goes as follows: - 1. Initialize the HealpixSkyMap object with the specified properties. + 1. Initialize the SkyMap object with the specified properties. + - If ``build_rectangular_map=True``, project directly to a rectangular map. + - Otherwise, build a Healpix map (even when final output is rectangular), + because some derived variables are later converted via recursive + Healpix->Rectangular subdivision. 2. Iterate over the input pointing sets and read them into UltraPointingSet objects. 3. For each pointing set, weight certain variables by exposure and solid angle of the pointing set pixels. @@ -183,29 +357,51 @@ def generate_ultra_healpix_skymap( (e.g., divide weighted quantities by their summed weights to get their weighted mean) 6. Calculate corrected count rate with background subtraction applied. - 7. Calculate ena_intensity and its statistical uncertainty. + 7. Calculate ena_intensity and its statistical uncertainty if the map is Healpix. 8. Drop unnecessary variables from the map. """ - if output_map_structure.tiling_type is ena_maps.SkyTilingType.HEALPIX: - map_nside, map_nested = ( - output_map_structure.nside, - output_map_structure.nested, + output_map_type = output_map_structure.tiling_type + if build_rectangular_map: + if output_map_type != ena_maps.SkyTilingType.RECTANGULAR: + raise ValueError( + "To build a rectangular map, the output_map_structure must" + " have tiling_type set to RECTANGULAR." + ) + # Initialize the RectangularSkyMap object + skymap: ena_maps.HealpixSkyMap | ena_maps.RectangularSkyMap = ( + ena_maps.RectangularSkyMap( + spacing_deg=output_map_structure.spacing_deg, + spice_frame=output_map_structure.spice_reference_frame, + ) ) else: - map_nside, map_nested = (DEFAULT_L2_HEALPIX_NSIDE, DEFAULT_L2_HEALPIX_NESTED) - - # Initialize the HealpixSkyMap object - skymap = ena_maps.HealpixSkyMap( - nside=map_nside, - nested=map_nested, - spice_frame=output_map_structure.spice_reference_frame, - ) + if output_map_type is ena_maps.SkyTilingType.HEALPIX: + map_nside, map_nested = ( + output_map_structure.nside, + output_map_structure.nested, + ) + elif output_map_type is ena_maps.SkyTilingType.RECTANGULAR: + map_nside, map_nested = ( + DEFAULT_L2_HEALPIX_NSIDE, + DEFAULT_L2_HEALPIX_NESTED, + ) + else: + raise ValueError( + f"Unsupported tiling type: {output_map_type}. " + "Only HEALPIX and RECTANGULAR are supported." + ) + # Initialize the HealpixSkyMap object + skymap = ena_maps.HealpixSkyMap( + nside=map_nside, + nested=map_nested, + spice_frame=output_map_structure.spice_reference_frame, + ) # Add additional data variables to the map output_map_structure.values_to_push_project.extend( [ "num_pointing_set_pixel_members", - "obs_date_for_std", + "obs_date_range", "obs_date_squared_for_std", ] ) @@ -235,10 +431,50 @@ def generate_ultra_healpix_skymap( f"PUSH Variables: {output_map_structure.values_to_push_project} \n" f"PULL Variables: {output_map_structure.values_to_pull_project}" ) + # TODO remove this in the future once all test data includes these variables + # Add expected but not required variables to the pull projection list + # Log a warning if they are missing from any PSET but continue processing. + expected_present_vars_pointing_ind = [] + first_pset = ( + load_cdf(ultra_l1c_psets[0]) + if isinstance(ultra_l1c_psets[0], (str, Path)) + else ultra_l1c_psets[0] + ) + + for var in EXPECTED_L1C_POINTING_INDEPENDENT_VARIABLES_PULL: + if var not in first_pset.variables: + logger.warning( + f"Expected variable {var} not found in the first L1C PSET. " + "This variable will not be projected to the map." + ) + else: + expected_present_vars_pointing_ind.append(var) + + # Get existing variables that should be weighted by exposure and solid angle + existing_vars_to_weight = [] + pointing_indep_vars = [] + for var in VARIABLES_TO_WEIGHT_BY_POINTING_SET_EXPOSURE_TIMES_SOLID_ANGLE: + if var in first_pset: + existing_vars_to_weight.append(var) + if "epoch" not in first_pset[var].dims: + pointing_indep_vars.append(var) + + output_map_structure.values_to_pull_project = list( + set( + output_map_structure.values_to_pull_project + + expected_present_vars_pointing_ind + ) + ) all_pset_epochs = [] for ultra_l1c_pset in ultra_l1c_psets: - pointing_set = ena_maps.UltraPointingSet(ultra_l1c_pset) + pset = ( + load_cdf(ultra_l1c_pset) + if isinstance(ultra_l1c_pset, (str, Path)) + else ultra_l1c_pset + ) + binned_pset = bin_pset_energy_bins(pset, energy_bin_edges) + pointing_set = ena_maps.UltraPointingSet(binned_pset) all_pset_epochs.append(pointing_set.epoch) logger.info( f"Projecting a PointingSet with {pointing_set.num_points} pixels " @@ -248,9 +484,15 @@ def generate_ultra_healpix_skymap( "\nThese values will be pull projected: " f">> {output_map_structure.values_to_pull_project}", ) + flags_1d = pointing_set.data["quality_flags"].isel(epoch=0) + # This is a good pixel mask where zero is when the earth is not in the FOV. + good_pixel_mask = ( + (flags_1d & ImapPSETUltraFlags.EARTH_FOV.value) == 0 + ).to_numpy() + # Only count the number of pointing set pixels which are not flagged. pointing_set.data["num_pointing_set_pixel_members"] = xr.DataArray( - np.ones(pointing_set.num_points, dtype=int), + good_pixel_mask.astype(int), dims=(CoordNames.HEALPIX_INDEX.value), ) @@ -261,11 +503,11 @@ def generate_ultra_healpix_skymap( fill_value=pointing_set.epoch, dtype=np.int64, ) - pointing_set.data["obs_date_for_std"] = pointing_set.data["obs_date"].astype( + pointing_set.data["obs_date_range"] = pointing_set.data["obs_date"].astype( np.float64 ) pointing_set.data["obs_date_squared_for_std"] = ( - pointing_set.data["obs_date_for_std"] ** 2 + pointing_set.data["obs_date_range"] ** 2 ) # Add solid_angle * exposure of pointing set as data_var @@ -273,18 +515,26 @@ def generate_ultra_healpix_skymap( pointing_set.data["pointing_set_exposure_times_solid_angle"] = ( pointing_set.data["exposure_factor"] * pointing_set.solid_angle ) - + # TODO add generalized code in ena_maps to handle this + # if the variable does not have an epoch dimension, add one temporarily + # to allow for correct broadcasting during weighting. + # Keep track of which variables were modified so we can revert them later. + for var in pointing_indep_vars: + pointing_set.data[var] = pointing_set.data[var].expand_dims("epoch", axis=0) # Initial processing for weighted quantities at PSET level # Weight the values by exposure and solid angle - pointing_set.data[ - VARIABLES_TO_WEIGHT_BY_POINTING_SET_EXPOSURE_TIMES_SOLID_ANGLE - ] *= pointing_set.data["pointing_set_exposure_times_solid_angle"] + # Ensure only valid pointing set pixels contribute to the weighted mean. + pointing_set.data[existing_vars_to_weight] = ( + pointing_set.data[existing_vars_to_weight] + * pointing_set.data["pointing_set_exposure_times_solid_angle"] + ).where(good_pixel_mask) # Project values such as counts via the PUSH method skymap.project_pset_values_to_map( pointing_set=pointing_set, value_keys=output_map_structure.values_to_push_project, index_match_method=ena_maps.IndexMatchMethod.PUSH, + pset_valid_mask=good_pixel_mask, ) # Project values such as exposure_factor via the PULL method @@ -292,18 +542,25 @@ def generate_ultra_healpix_skymap( pointing_set=pointing_set, value_keys=output_map_structure.values_to_pull_project, index_match_method=ena_maps.IndexMatchMethod.PULL, + pset_valid_mask=good_pixel_mask, ) # Subsequent processing for weighted quantities at SkyMap level - skymap.data_1d[VARIABLES_TO_WEIGHT_BY_POINTING_SET_EXPOSURE_TIMES_SOLID_ANGLE] /= ( - skymap.data_1d["pointing_set_exposure_times_solid_angle"] + skymap.data_1d[existing_vars_to_weight] /= skymap.data_1d[ + "pointing_set_exposure_times_solid_angle" + ] + # Revert any pointing independent variables back to their original dims + for var in pointing_indep_vars: + skymap.data_1d[var] = skymap.data_1d[var].squeeze("epoch", drop=True) + + # Background rates must be scaled by + # the ratio of the solid angles of the map pixel / pointing set pixel + skymap.data_1d["background_rates"] *= ( + skymap.solid_angle_points / pointing_set.solid_angle ) - # Background rates must be scaled by the ratio of the solid angles of the - # map pixel / pointing set pixel - skymap.data_1d["background_rates"] *= skymap.solid_angle / pointing_set.solid_angle - - # Get the energy bin widths from a PointingSet (they will all be the same) + # Get the energy bin widths and deltas from a PointingSet + # (they will all be the same) delta_energy = pointing_set.data["energy_bin_delta"] if CoordNames.TIME.value in delta_energy.dims: delta_energy = delta_energy.mean( @@ -315,26 +572,29 @@ def generate_ultra_healpix_skymap( # and ena_intensity. # These NaNs are not incorrect, so we temporarily ignore numpy div by 0 warnings. with np.errstate(divide="ignore"): - # Get corrected count rate with background subtraction applied - skymap.data_1d["corrected_count_rate"] = ( - skymap.data_1d["counts"].astype(float) / skymap.data_1d["exposure_factor"] - ) - skymap.data_1d["background_rates"] - - # Calculate ena_intensity = corrected_counts / ( - # sensitivity * solid_angle * delta_energy) - skymap.data_1d["ena_intensity"] = skymap.data_1d["corrected_count_rate"] / ( - skymap.data_1d["sensitivity"] * skymap.solid_angle * delta_energy - ) - - skymap.data_1d["ena_intensity_stat_unc"] = ( - skymap.data_1d["counts"].astype(float) ** 0.5 - ) / ( - skymap.data_1d["exposure_factor"] - * skymap.data_1d["sensitivity"] - * skymap.solid_angle - * delta_energy - ) + if not build_rectangular_map: + # Get corrected count rate with background subtraction applied + # TODO: do not remove background rates for now. Need to verify background + # rates first. + skymap.data_1d["corrected_count_rate"] = ( + skymap.data_1d["counts"].astype(float) + / skymap.data_1d["exposure_factor"] + ) # - skymap.data_1d["background_rates"] + + # Calculate ena_intensity = corrected_counts / ( + # sensitivity * solid_angle * delta_energy) + skymap.data_1d["ena_intensity"] = skymap.data_1d["corrected_count_rate"] / ( + skymap.data_1d["sensitivity"] * skymap.solid_angle * delta_energy + ) + skymap.data_1d["ena_intensity_stat_uncert"] = ( + skymap.data_1d["counts"].astype(float) ** 0.5 + ) / ( + skymap.data_1d["exposure_factor"] + * skymap.data_1d["sensitivity"] + * skymap.solid_angle + * delta_energy + ) # Calculate the standard deviation of the observation date as: # sqrt((sum(obs_date^2) / N) - (sum(obs_date) / N)^2) # where sum here refers to the projection process @@ -347,7 +607,7 @@ def generate_ultra_healpix_skymap( ) - ( ( - skymap.data_1d["obs_date_for_std"] + skymap.data_1d["obs_date_range"] / (skymap.data_1d["num_pointing_set_pixel_members"]) ) ** 2 @@ -357,10 +617,10 @@ def generate_ultra_healpix_skymap( ).astype(np.int64) # Drop the variables that are no longer needed - skymap.data_1d = skymap.data_1d.drop_vars( - VARIABLES_TO_DROP_AFTER_INTENSITY_CALCULATION, + vars_to_drop = set(VARIABLES_TO_DROP_AFTER_INTENSITY_CALCULATION).intersection( + set(skymap.data_1d.data_vars) ) - + skymap.data_1d = skymap.data_1d.drop_vars(vars_to_drop) return skymap, np.array(all_pset_epochs) @@ -369,6 +629,7 @@ def ultra_l2( output_map_structure: ( ena_maps.RectangularSkyMap | ena_maps.HealpixSkyMap ) = DEFAULT_ULTRA_L2_MAP_STRUCTURE, + energy_bin_edges_file: str | Path | None = None, *, descriptor: str | None = None, store_subdivision_depth: bool = False, @@ -384,6 +645,9 @@ def ultra_l2( Empty SkyMap structure providing the properties of the map to be generated. If a descriptor is provided, this will be ignored. Defaults to DEFAULT_ULTRA_L2_MAP_STRUCTURE defined in this module. + energy_bin_edges_file : pathlib.Path | str | None, optional + File path to a csv of energy bin edges to use for binning L1C energy bins into + coarser bins. If None, DEFAULT_BIN_EDGES defined in this module will be used. descriptor : str | None, optional A descriptor to set the output map structure If provided, this overrides the default output_map_structure parameter. @@ -401,6 +665,7 @@ def ultra_l2( Wrapped in a list for consistency with other product levels. """ inertial_frame = "unknown" + descriptor_duration: str | None = None if descriptor is not None: logger.info( f"Using the provided descriptor '{descriptor}' to set the map structure." @@ -409,6 +674,7 @@ def ultra_l2( map_descriptor = MapDescriptor.from_string(descriptor) output_map_structure = map_descriptor.to_empty_map() inertial_frame = map_descriptor.frame_descriptor + descriptor_duration = str(map_descriptor.duration) inertial_frame_long_name = INERTIAL_FRAME_LONG_NAMES.get(inertial_frame, "unknown") # Object which holds CDF attributes for the map @@ -421,16 +687,39 @@ def ultra_l2( ultra_sensor_number = 45 if "45sensor" in next(iter(data_dict.keys())) else 90 logger.info(f"Assuming all products are from sensor {ultra_sensor_number}") - + if energy_bin_edges_file is not None: + energy_bin_edges = np.loadtxt(energy_bin_edges_file, delimiter=",").astype( + np.uint8 + ) + else: + energy_bin_edges = build_default_coarse_bin_edges() # Regardless of the output sky tiling type, we will directly # project the PSET values into a healpix map. However, if we are outputting # a Healpix map, we can go directly to map with desired nside, nested params - healpix_skymap, pset_epochs = generate_ultra_healpix_skymap( + healpix_skymap, pset_epochs = generate_ultra_skymap( ultra_l1c_psets=l1c_products, output_map_structure=output_map_structure, + energy_bin_edges=energy_bin_edges, ) + # Build the rectangular map + if output_map_structure.tiling_type is ena_maps.SkyTilingType.RECTANGULAR: + rectangular_skymap, _ = generate_ultra_skymap( + ultra_l1c_psets=l1c_products, + output_map_structure=output_map_structure, + energy_bin_edges=energy_bin_edges, + build_rectangular_map=True, + ) + # Ensure that the epoch of the map is the earliest epoch of the input PSETs + rectangular_skymap.data_1d = rectangular_skymap.data_1d.assign_coords( + epoch=( + (CoordNames.TIME.value,), + [ + pset_epochs.min(), + ], + ), + ) # Ensure that the epoch of the map is the earliest epoch of the input PSETs - healpix_skymap.data_1d.assign_coords( + healpix_skymap.data_1d = healpix_skymap.data_1d.assign_coords( epoch=( (CoordNames.TIME.value,), [ @@ -442,9 +731,13 @@ def ultra_l2( # TODO: replace 1 day in ns below with the actual end time of the last PSET. # Currently assumes the end time of the last PSET is 1 day after its start. map_duration_ns = (pset_epochs.max() + (86400 * 1e9)) - pset_epochs.min() - map_duration_months_int = ns_to_duration_months(map_duration_ns) - map_duration = f"{map_duration_months_int}mo" - + # Use the duration from the descriptor if it is provided, otherwise use the + # calculated duration from the PSET epochs. + if descriptor_duration is None: + map_duration_months_int = ns_to_duration_months(map_duration_ns) + map_duration = f"{map_duration_months_int}mo" + else: + map_duration = descriptor_duration # Always add the common (non-tiling specific) attributes to the attr handler. # These can be updated/overwritten by the tiling specific attributes. cdf_attrs.add_instrument_variable_attrs(instrument="enamaps", level="l2-common") @@ -467,6 +760,7 @@ def ultra_l2( map_dataset = healpix_skymap.to_dataset() # Add attributes related to the map map_attrs = { + "HEALPix_solid_angle": str(healpix_skymap.solid_angle), "HEALPix_nside": str(output_map_structure.nside), "HEALPix_nest": str(output_map_structure.nested), } @@ -476,10 +770,16 @@ def ultra_l2( cdf_attrs.add_instrument_variable_attrs( instrument="enamaps", level="l2-rectangular" ) - rectangular_skymap, subdiv_depth_dict = healpix_skymap.to_rectangular_skymap( - rect_spacing_deg=output_map_structure.spacing_deg, - value_keys=healpix_skymap.data_1d.data_vars, + intensity_rectangular_skymap, subdiv_depth_dict = ( + healpix_skymap.to_rectangular_skymap( + rect_spacing_deg=output_map_structure.spacing_deg, + value_keys=RECURSIVE_HEALPIX_TO_RECTANGULAR_VARIABLES, + ) ) + # Merge recursively subdivided variables into the directly projected + # rectangular map. + for key in RECURSIVE_HEALPIX_TO_RECTANGULAR_VARIABLES: + rectangular_skymap.data_1d[key] = intensity_rectangular_skymap.data_1d[key] # Add the subdiv_depth_by_pixel of each key to the map dataset if requested if store_subdivision_depth: @@ -497,12 +797,17 @@ def ultra_l2( "long_name": f"Subdiv_depth of {key}", }, ) - map_dataset = rectangular_skymap.to_dataset() # Add longitude_delta, latitude_delta to the map dataset - map_dataset["longitude_delta"] = rectangular_skymap.spacing_deg / 2 - map_dataset["latitude_delta"] = rectangular_skymap.spacing_deg / 2 + map_dataset["longitude_delta"] = ( + "longitude", + np.full(map_dataset["longitude"].shape, rectangular_skymap.spacing_deg / 2), + ) + map_dataset["latitude_delta"] = ( + "latitude", + np.full(map_dataset["latitude"].shape, rectangular_skymap.spacing_deg / 2), + ) map_attrs = { "Spacing_degrees": str(output_map_structure.spacing_deg), @@ -541,12 +846,20 @@ def ultra_l2( # to "energy" for all instruments. map_dataset = map_dataset.rename({"energy_bin_geometric_mean": "energy"}) + # Rename positional uncertainty variables if present + map_dataset = map_dataset.rename({"scatter_theta": "positional_uncert_theta"}) + map_dataset = map_dataset.rename({"scatter_phi": "positional_uncert_phi"}) + + # Rename background rates to be compliant with the l2 map definitions + map_dataset = map_dataset.rename({"background_rates": "bg_rate"}) + # Add the defined attributes to the map's global attrs map_dataset.attrs.update(map_attrs) # Add the "label" coordinates to the map dataset for coord_var, coord_data in map_dataset.coords.items(): - if coord_var != "epoch": + # For energy_delta_minus and plus, the label should be "energy_label" + if coord_var not in ["epoch", "energy_delta_minus", "energy_delta_plus"]: map_dataset.coords[f"{coord_var}_label"] = xr.DataArray( coord_data.values.astype(str), dims=[ @@ -558,9 +871,15 @@ def ultra_l2( # Add systematic error as all zeros with shape matching statistical unc # TODO: update once we have information from the instrument team map_dataset["ena_intensity_sys_err"] = xr.zeros_like( - map_dataset["ena_intensity_stat_unc"], + map_dataset["ena_intensity_stat_uncert"], ) + # Add epoch_delta_minus + map_dataset.coords["epoch_delta_minus"] = xr.DataArray( + [0], + dims=(CoordNames.TIME.value,), + ) + map_dataset.coords["epoch"].attrs["DELTA_MINUS_VAR"] = "epoch_delta_minus" # Add epoch_delta map_dataset.coords["epoch_delta"] = xr.DataArray( [ @@ -570,17 +889,6 @@ def ultra_l2( ) map_dataset.coords["epoch"].attrs["DELTA_PLUS_VAR"] = "epoch_delta" - # Add the energy delta plus/minus to the map dataset - energy_delta_minus, energy_delta_plus = get_energy_delta_minus_plus() - map_dataset.coords["energy_delta_minus"] = xr.DataArray( - energy_delta_minus, - dims=(CoordNames.ENERGY_L2.value,), - ) - map_dataset.coords["energy_delta_plus"] = xr.DataArray( - energy_delta_plus, - dims=(CoordNames.ENERGY_L2.value,), - ) - # Add variable specific attributes to the map's data_vars and coords for variable in map_dataset.data_vars: # Skip the subdivision depth variables, as these will only be @@ -588,14 +896,25 @@ def ultra_l2( if "subdivision_depth" in variable: continue + # Support variables do not have epoch as the first dimension + # skip schema check for support variables or coords + skip_schema_check = not ( + "epoch" not in map_dataset[variable].dims # Support data + or variable + in [ + "longitude", + "latitude", + "longitude_delta", + "latitude_delta", + ] # Coordinate vars + ) # The longitude and latitude variables will be present only in Healpix tiled # map, and, as support_data, should not have schema validation map_dataset[variable].attrs.update( get_variable_attributes_optional_energy_dependence( cdf_attrs=cdf_attrs, variable_array=map_dataset[variable], - check_schema=variable - not in ["longitude", "latitude", "longitude_delta", "latitude_delta"], + check_schema=skip_schema_check, ) ) for coord_variable in map_dataset.coords: @@ -606,6 +925,15 @@ def ultra_l2( ) ) - # Adjust the dtype of obs_date to be int64 + # Adjust the dtype of obs dates to be int64 map_dataset["obs_date"] = map_dataset["obs_date"].astype(np.int64) + map_dataset["obs_date_range"] = map_dataset["obs_date_range"].astype(np.int64) + + # Adjust CATDESC per descriptor + if descriptor is not None: + md = MapDescriptor.from_string(descriptor) + principal_data = md.principal_data_var + if principal_data in map_dataset: + map_dataset[principal_data].attrs["CATDESC"] = md.to_catdesc() + return [map_dataset] diff --git a/imap_processing/ultra/packet_definitions/ULTRA_SCI_COMBINED.xml b/imap_processing/ultra/packet_definitions/ULTRA_SCI_COMBINED.xml index df36118015..21fb527295 100644 --- a/imap_processing/ultra/packet_definitions/ULTRA_SCI_COMBINED.xml +++ b/imap_processing/ultra/packet_definitions/ULTRA_SCI_COMBINED.xml @@ -4664,27 +4664,12 @@ - - - - - - - - - - - - - - - - + @@ -4692,27 +4677,12 @@ - - - - - - - - - - - - - - - - + @@ -4720,27 +4690,12 @@ - - - - - - - - - - - - - - - - + @@ -4748,27 +4703,12 @@ - - - - - - - - - - - - - - - - + @@ -4776,27 +4716,12 @@ - - - - - - - - - - - - - - - - + @@ -4804,27 +4729,12 @@ - - - - - - - - - - - - - - - - + @@ -9662,27 +9572,12 @@ - - - - - - - - - - - - - - - - + @@ -9690,27 +9585,12 @@ - - - - - - - - - - - - - - - - + @@ -9718,27 +9598,12 @@ - - - - - - - - - - - - - - - - + @@ -9746,27 +9611,12 @@ - - - - - - - - - - - - - - - - + @@ -9774,27 +9624,12 @@ - - - - - - - - - - - - - - - - + @@ -9802,27 +9637,12 @@ - - - - - - - - - - - - - - - - + @@ -11561,126 +11381,36 @@ CCSDS Packet 2nd Header Coarse Time - - Science ID - - - Spin number at integration start - - - Integration aborted - - - Integration start delay (ms) - - - Starting pixel - Image Packet Data CCSDS Packet 2nd Header Coarse Time - - Science ID - - - Spin number at integration start - - - Integration aborted - - - Integration start delay (ms) - - - Starting pixel - Image Packet Data CCSDS Packet 2nd Header Coarse Time - - Science ID - - - Spin number at integration start - - - Integration aborted - - - Integration start delay (ms) - - - Starting pixel - Image Packet Data CCSDS Packet 2nd Header Coarse Time - - Science ID - - - Spin number at integration start - - - Integration aborted - - - Integration start delay (ms) - - - Starting pixel - Image Packet Data CCSDS Packet 2nd Header Coarse Time - - Science ID - - - Spin number at integration start - - - Integration aborted - - - Integration start delay (ms) - - - Starting pixel - Image Packet Data CCSDS Packet 2nd Header Coarse Time - - Science ID - - - Spin number at integration start - - - Integration aborted - - - Integration start delay (ms) - - - Starting pixel - Image Packet Data @@ -13346,126 +13076,36 @@ CCSDS Packet 2nd Header Coarse Time - - Science ID - - - Spin number at integration start - - - Integration aborted - - - Integration start delay (ms) - - - Starting pixel - Image Packet Data CCSDS Packet 2nd Header Coarse Time - - Science ID - - - Spin number at integration start - - - Integration aborted - - - Integration start delay (ms) - - - Starting pixel - Image Packet Data CCSDS Packet 2nd Header Coarse Time - - Science ID - - - Spin number at integration start - - - Integration aborted - - - Integration start delay (ms) - - - Starting pixel - Image Packet Data CCSDS Packet 2nd Header Coarse Time - - Science ID - - - Spin number at integration start - - - Integration aborted - - - Integration start delay (ms) - - - Starting pixel - Image Packet Data CCSDS Packet 2nd Header Coarse Time - - Science ID - - - Spin number at integration start - - - Integration aborted - - - Integration start delay (ms) - - - Starting pixel - Image Packet Data CCSDS Packet 2nd Header Coarse Time - - Science ID - - - Spin number at integration start - - - Integration aborted - - - Integration start delay (ms) - - - Starting pixel - Image Packet Data @@ -14287,11 +13927,6 @@ - - - - - @@ -14303,11 +13938,6 @@ - - - - - @@ -14319,11 +13949,6 @@ - - - - - @@ -14335,11 +13960,6 @@ - - - - - @@ -14351,11 +13971,6 @@ - - - - - @@ -14367,11 +13982,6 @@ - - - - - @@ -15155,11 +14765,6 @@ - - - - - @@ -15171,11 +14776,6 @@ - - - - - @@ -15187,11 +14787,6 @@ - - - - - @@ -15203,11 +14798,6 @@ - - - - - @@ -15219,11 +14809,6 @@ - - - - - @@ -15235,11 +14820,6 @@ - - - - - diff --git a/imap_processing/ultra/utils/ultra_l1_utils.py b/imap_processing/ultra/utils/ultra_l1_utils.py index d61a0002c9..a22ca75819 100644 --- a/imap_processing/ultra/utils/ultra_l1_utils.py +++ b/imap_processing/ultra/utils/ultra_l1_utils.py @@ -1,6 +1,5 @@ """Create dataset.""" -import numpy as np import xarray as xr from imap_processing.cdf.imap_cdf_manager import ImapCdfAttributes @@ -32,7 +31,7 @@ def create_dataset( # noqa: PLR0912 cdf_manager.add_instrument_global_attrs("ultra") cdf_manager.add_instrument_variable_attrs("ultra", level) - # L1b extended spin, badtimes, and cullingmask data products + # L1b extended spin, badtimes, and goodtimes data products if "spin_number" in data_dict.keys(): coords = { "spin_number": ("spin_number", data_dict["spin_number"]), @@ -40,7 +39,6 @@ def create_dataset( # noqa: PLR0912 "energy_bin_geometric_mean", data_dict["energy_bin_geometric_mean"], ), - "epoch": ("spin_number", np.asarray(data_dict["epoch"])), } default_dimension = "spin_number" # L1c pset data products @@ -48,6 +46,7 @@ def create_dataset( # noqa: PLR0912 coords = { "epoch": data_dict["epoch"], "pixel_index": data_dict["pixel_index"], + "counts_pixel_index": data_dict["counts_pixel_index"], "energy_bin_geometric_mean": data_dict["energy_bin_geometric_mean"], "spin_phase_step": data_dict["spin_phase_step"], } @@ -95,22 +94,44 @@ def create_dataset( # noqa: PLR0912 rates_pulse_keys = {"start_per_spin", "stop_per_spin", "coin_per_spin"} for key, data in data_dict.items(): - # Skip keys that are coordinates. - if key in [ - "epoch", + if key == "epoch": + # epoch coordinate already created with correct attrs + continue + elif key == "epoch_delta": + dataset[key] = xr.DataArray( + data, + dims=["epoch"], + attrs=cdf_manager.get_variable_attributes(key, check_schema=False), + ) + elif key in [ "spin_number", "energy_bin_geometric_mean", "pixel_index", + "counts_pixel_index", "spin_phase_step", ]: - continue + # update attrs on existing coords + dataset[key].attrs = cdf_manager.get_variable_attributes( + key, check_schema=False + ) + elif key in ["energy_range_edges_dim", "energy_range_flags_dim"]: + dataset[key] = xr.DataArray( + data, + dims=[key], + attrs=cdf_manager.get_variable_attributes(key, check_schema=False), + ) elif key in velocity_keys: dataset[key] = xr.DataArray( data, dims=["epoch", "component"], attrs=cdf_manager.get_variable_attributes(key, check_schema=False), ) - elif key == "ena_rates_threshold": + elif key in [ + "ena_rates_threshold", + "scatter_threshold", + "energy_delta_minus", + "energy_delta_plus", + ]: dataset[key] = xr.DataArray( data, dims=["energy_bin_geometric_mean"], @@ -134,41 +155,58 @@ def create_dataset( # noqa: PLR0912 dims=["energy_bin_geometric_mean", "spin_number"], attrs=cdf_manager.get_variable_attributes(key, check_schema=False), ) - elif key in {"latitude", "longitude"}: + elif key in {"quality_flags", "latitude", "longitude"}: dataset[key] = xr.DataArray( data, dims=["epoch", "pixel_index"], attrs=cdf_manager.get_variable_attributes(key, check_schema=False), ) elif key in { - "counts", "background_rates", + "exposure_factor", + "helio_exposure_factor", }: dataset[key] = xr.DataArray( data, dims=["epoch", "energy_bin_geometric_mean", "pixel_index"], attrs=cdf_manager.get_variable_attributes(key, check_schema=False), ) + elif key in {"counts"}: + dataset[key] = xr.DataArray( + data, + dims=["epoch", "energy_bin_geometric_mean", "counts_pixel_index"], + attrs=cdf_manager.get_variable_attributes(key, check_schema=False), + ) elif key in { - "exposure_factor", - "helio_exposure_factor", + "geometric_function", + "scatter_theta", + "scatter_phi", "sensitivity", "efficiency", - "geometric_function", }: dataset[key] = xr.DataArray( data, dims=["energy_bin_geometric_mean", "pixel_index"], attrs=cdf_manager.get_variable_attributes(key, check_schema=False), ) - elif key in { - "dead_time_ratio", - }: + elif key in {"dead_time_ratio"}: dataset[key] = xr.DataArray( data, dims=["spin_phase_step"], attrs=cdf_manager.get_variable_attributes(key, check_schema=False), ) + elif key == "energy_range_edges": + dataset[key] = xr.DataArray( + data, + dims=["energy_range_edges_dim"], + attrs=cdf_manager.get_variable_attributes(key, check_schema=False), + ) + elif key == "energy_range_flags": + dataset[key] = xr.DataArray( + data, + dims=["energy_range_flags_dim"], + attrs=cdf_manager.get_variable_attributes(key, check_schema=False), + ) else: dataset[key] = xr.DataArray( data, @@ -197,7 +235,15 @@ def extract_data_dict(dataset: xr.Dataset) -> dict: data_dict.update( { coord: dataset.coords[coord].values - for coord in ("spin_number", "energy_bin_geometric_mean", "epoch") + for coord in ( + "spin_number", + "energy_bin_geometric_mean", + "epoch", + "energy_range_flags_dim", + "energy_range_edges_dim", + "energy_range_flags", + "energy_range_edges", + ) if coord in dataset.coords } ) diff --git a/imap_processing/utils.py b/imap_processing/utils.py index 1c3273add1..b1b8353c47 100644 --- a/imap_processing/utils.py +++ b/imap_processing/utils.py @@ -2,24 +2,36 @@ import collections import logging +from collections.abc import Generator +from datetime import datetime, timedelta from pathlib import Path import numpy as np import pandas as pd +import space_packet_parser as spp import xarray as xr -from space_packet_parser import definitions, encodings, parameters +from space_packet_parser.exceptions import UnrecognizedPacketTypeError +from space_packet_parser.generators.ccsds import SequenceFlags +from space_packet_parser.xtce import definitions, encodings, parameter_types -from imap_processing.spice.time import met_to_ttj2000ns +from imap_processing.spice.time import ( + met_to_ttj2000ns, + str_yyyymmdd_to_ttj2000ns, +) logger = logging.getLogger(__name__) +# The time key is the secondary header, right after the primary header +# in the data dictionary on IMAP (8th key overall) +TIME_KEY_INDEX = 7 + def convert_raw_to_eu( dataset: xr.Dataset, conversion_table_path: str, packet_name: str, **read_csv_kwargs: dict, -) -> xr.Dataset: +) -> xr.Dataset: # numpydoc ignore=PR01,PR09 """ Convert raw data to engineering unit. @@ -27,10 +39,10 @@ def convert_raw_to_eu( ---------- dataset : xr.Dataset Raw data. - conversion_table_path : str, + conversion_table_path : str Path object or file-like object Path to engineering unit conversion table. - Eg: + E.g. f"{imap_module_directory}/swe/l1b/engineering_unit_convert_table.csv" Engineering unit conversion table must be a csv file with required informational columns: ('packetName', 'mnemonic', 'convertAs') and @@ -43,7 +55,7 @@ def convert_raw_to_eu( E.g.: mnemonic convertAs … dn_range_start dn_range_stop c0 c1… - ------------------------------------------------------------------------- + -------------------------------------------------------------------------- temperature | SEGMENTED_POLY | 0 | 2063 | 0.1 | 0.2 temperature | SEGMENTED_POLY | 2064 | 3853 | 0 | 0.1 temperature | SEGMENTED_POLY | 3854 | 4094 | 0.6 | 0.3 @@ -158,11 +170,11 @@ def _get_minimum_numpy_datatype( # noqa: PLR0912 - Too many branches datatype : str The minimum datatype. """ - data_encoding = definition.named_parameters[name].parameter_type.encoding + data_encoding = definition.parameters[name].parameter_type.encoding if use_derived_value and isinstance( - definition.named_parameters[name].parameter_type, - parameters.EnumeratedParameterType, + definition.parameters[name].parameter_type, + parameter_types.EnumeratedParameterType, ): # We don't have a way of knowing what is enumerated, # let numpy infer the datatype @@ -254,43 +266,43 @@ def packet_file_to_datasets( variable_mapping: dict[int, set] = dict() # Set up the parser from the input packet definition - packet_definition = definitions.XtcePacketDefinition(xtce_packet_definition) + packet_definition = spp.load_xtce(xtce_packet_definition) + + for packet in packet_generator(packet_file, xtce_packet_definition): + apid = packet["PKT_APID"] + if apid not in data_dict: + # This is the first packet for this APID + data_dict[apid] = collections.defaultdict(list) + datatype_mapping[apid] = dict() + variable_mapping[apid] = packet.keys() + if variable_mapping[apid] != packet.keys(): + raise ValueError( + f"Packet fields do not match for APID {apid}. This could be " + f"due to a conditional packet definition in the XTCE, while this " + f"function currently only supports flat packet definitions." + f"\nExpected: {variable_mapping[apid]},\n" + f"got: {packet.keys()}" + ) - with open(packet_file, "rb") as binary_data: - packet_generator = packet_definition.packet_generator(binary_data) - for packet in packet_generator: - apid = packet["PKT_APID"] - if apid not in data_dict: - # This is the first packet for this APID - data_dict[apid] = collections.defaultdict(list) - datatype_mapping[apid] = dict() - variable_mapping[apid] = packet.keys() - if variable_mapping[apid] != packet.keys(): - raise ValueError( - f"Packet fields do not match for APID {apid}. This could be " - f"due to a conditional packet definition in the XTCE, while this " - f"function currently only supports flat packet definitions." - f"\nExpected: {variable_mapping[apid]},\n" - f"got: {packet.keys()}" + for key, value in packet.items(): + val = value if use_derived_value else value.raw_value + data_dict[apid][key].append(val) + if key not in datatype_mapping[apid]: + # Add this datatype to the mapping + datatype_mapping[apid][key] = _get_minimum_numpy_datatype( + key, packet_definition, use_derived_value=use_derived_value ) - # TODO: Do we want to give an option to remove the header content? - packet_content = packet.user_data | packet.header - - for key, value in packet_content.items(): - val = value if use_derived_value else value.raw_value - data_dict[apid][key].append(val) - if key not in datatype_mapping[apid]: - # Add this datatype to the mapping - datatype_mapping[apid][key] = _get_minimum_numpy_datatype( - key, packet_definition, use_derived_value=use_derived_value - ) - dataset_by_apid = {} for apid, data in data_dict.items(): - # The time key is always the first key in the data dictionary on IMAP - time_key = next(iter(data.keys())) + try: + time_key = list(data.keys())[TIME_KEY_INDEX] + except IndexError: + logger.debug( + f"Could not determine time key for APID {apid}, skipping dataset." + ) + continue # Convert to J2000 time and use that as our primary dimension time_data = met_to_ttj2000ns(data[time_key]) ds = xr.Dataset( @@ -325,6 +337,9 @@ def packet_file_to_datasets( ) ds = ds.isel(epoch=unique_indices) + # Log a warning if there are gaps in the source sequence counter + _check_source_sequence_counter(ds, apid) + # Strip any leading characters before "." from the field names which was due # to the packet_name being a part of the variable name in the XTCE definition ds = ds.rename( @@ -342,6 +357,205 @@ def packet_file_to_datasets( return dataset_by_apid +def combine_segmented_packets( + packets: xr.Dataset, binary_field_name: str = "packetdata" +) -> xr.Dataset: + """ + Combine segmented packets into unsegmented packets. + + To combine the segmented packets, we only concatenate along the `binary_field_name` + and place all values into the first packet of the group. The binary_field_name + is the name of the XTCE Parameter that contains the binary data for the packet. + The other fields are left as-is from the first packet of the group. + + Parameters + ---------- + packets : xarray.Dataset + Dataset containing the packets to combine. + binary_field_name : str, default "packetdata" + Name of the binary field in the dataset representing the packet data. + Defined in the XTCE definition for each instrument. + + Returns + ------- + combined_packets : xarray.Dataset + Dataset containing the combined packets. + """ + # Identification of group starts + # NOTE: seq_flgs is the same variable name for all instruments on IMAP + # but could be different for other missions depending on the XTCE definition. + is_group_start = (packets["seq_flgs"].data == SequenceFlags.UNSEGMENTED) | ( + packets["seq_flgs"].data == SequenceFlags.FIRST + ) + + # Assign group IDs using cumulative sum - each group start increments the ID + group_ids = np.cumsum(is_group_start) + + # Get indices of packets we'll keep (first packet of each group) + group_start_indices = np.where(is_group_start)[0] + # Keep track of the groups that don't have the expected sequences + bad_groups = [] + + # Concatenate binary data in-place for each group + for group_id in np.unique(group_ids): + # Find all packets belonging to this group + group_mask = group_ids == group_id + group_indices = np.where(group_mask)[0] + + # If multiple packets, concatenate into the first packet + # [b"abc", b"def", b"ghi"] -> b"abcdefghi" + if ( + len(group_indices) > 1 + or packets["seq_flgs"].data[group_indices[0]] != SequenceFlags.UNSEGMENTED + ): + start_index = group_indices[0] + # Lets do some quick validation on these packets since we've had + # some missing packet groups in the past + seq_flags = packets["seq_flgs"].data[group_indices] + if ( + seq_flags[0] != SequenceFlags.FIRST + or seq_flags[-1] != SequenceFlags.LAST + or ( + len(seq_flags) > 2 + and not np.all(seq_flags[1:-1] == SequenceFlags.CONTINUATION) + ) + ): + bad_groups.append(start_index) + logger.warning( + f"Incorrect/incomplete sequence flags in group {group_id}. " + f"Flags: {seq_flags}, " + f"SHCOARSEs: {packets['shcoarse'].data[group_indices]}" + ) + + packets[binary_field_name].data[start_index] = np.sum( + packets[binary_field_name].data[group_indices] + ) + + # Remove any bad groups from the start indices we are keeping + group_start_indices = np.setdiff1d(group_start_indices, bad_groups) + # Select only the first packet of each group (drop the middle/last packets) + combined_packets = packets.isel(epoch=group_start_indices) + + return combined_packets + + +def _check_source_sequence_counter(ds: xr.Dataset, apid: int) -> None: + """ + Check for gaps in the source sequence counter. + + Log a warning if gaps are found, but don't do anything else. + + Parameters + ---------- + ds : xarray.Dataset + Dataset containing the packets to check. + apid : int + APID of the packets. + """ + # Check for sequential source sequence counters + # CCSDS source sequence counter is a 14-bit field (0-16383) + counter_max = 16384 + src_seq_ctr = ds["src_seq_ctr"].data + + if len(src_seq_ctr) <= 1: + return + + # Check if each counter equals (previous + 1) % counter_max + # This handles both normal increments and rollover (16383 -> 0) + expected = (src_seq_ctr[:-1] + 1) % counter_max + actual = src_seq_ctr[1:] + non_sequential = expected != actual + + if np.any(non_sequential): + gap_indices = np.where(non_sequential)[0] + # Calculate total missing packets across all gaps + total_missing = sum( + (src_seq_ctr[idx + 1] - src_seq_ctr[idx] - 1) % counter_max + for idx in gap_indices + ) + # Show the counter values before and after each gap + gap_starts = src_seq_ctr[gap_indices].tolist() + gap_ends = src_seq_ctr[gap_indices + 1].tolist() + gap_pairs = list(zip(gap_starts, gap_ends, strict=True)) + logger.warning( + f"Found [{len(gap_indices)}] gap(s) in source sequence counter " + f"for APID {apid} at {gap_pairs} " + f"({total_missing} total missing packets)" + ) + + +def packet_generator( + packet_file: str | Path, + xtce_packet_definition: str | Path, +) -> Generator[spp.SpacePacket, None, None]: + """ + Parse packets from a packet file. + + Parameters + ---------- + packet_file : str | Path + Path to data packet path with filename. + xtce_packet_definition : str | Path + Path to XTCE file with filename. + + Yields + ------ + packet : space_packet_parser.SpacePacket + Parsed packet dictionary. + """ + # Set up the parser from the input packet definition + packet_definition = spp.load_xtce(xtce_packet_definition) + + with open(packet_file, "rb") as binary_data: + for binary_packet in spp.ccsds_generator(binary_data): + try: + packet = packet_definition.parse_bytes(binary_packet) + except UnrecognizedPacketTypeError as e: + # NOTE: Not all of our definitions have all of the APIDs + # we may encounter, so we only want to process ones + # we can actually parse. + logger.debug(e) + continue + yield packet + + +def separate_ccsds_header_userdata(packet: dict) -> tuple[dict, dict]: + """ + Separate header and userdata from a parsed packet. + + DO NOT USE: + This function is not used by instruments other than GLOWS and MAG and should + not be relied upon for general use since XTCE definitions may have different + structures defining the header items. + + This assumes that the first 7 items in the packet dictionary are the CCSDS + header and the following are the userdata section. It assumes insertion order + is kept and puts the first 7 items into one dictionary, with all of the following + variables assumed to be userdata in a second dictionary. All values are + raw values and it doesn't not return the derived values. + + Parameters + ---------- + packet : dict + Packet dictionary. + + Returns + ------- + header : dict + Packet header dictionary. + user_data : dict + Packet userdata dictionary (raw values). + """ + it = iter(packet.items()) + # take first 7 items for header (indices 0..6) + header = {} + for _, (k, v) in zip(range(7), it, strict=False): + header[k] = v + # remaining items are userdata; prefer raw_value if present + userdata = {k: v.raw_value for k, v in it} + return header, userdata + + def convert_to_binary_string(data: bytes) -> str: """ Convert bytes to a string representation. @@ -358,3 +572,84 @@ def convert_to_binary_string(data: bytes) -> str: """ binary_str_data = f"{int.from_bytes(data, byteorder='big'):0{len(data) * 8}b}" return binary_str_data + + +def filter_day_boundary_data(dataset: xr.Dataset, start_date: str) -> xr.Dataset: + """ + Filter out data that falls outside of the day boundary. + + This is needed for instruments that have a daily data and where the first + and last packets of the day may fall outside of the day boundary. This is + currently only needed for instrument with buffer data, but could be used by + other instruments in the future if they have similar issues. + + Parameters + ---------- + dataset : xr.Dataset + The dataset to filter. + start_date : str + The start date for the day boundary filter in 'YYYYMMDD' format. + + Returns + ------- + filtered_dataset : xr.Dataset + The filtered dataset with only data that falls within the day boundary. + """ + start_ttj2000ns = str_yyyymmdd_to_ttj2000ns(start_date) + next_day = (datetime.strptime(start_date, "%Y%m%d") + timedelta(days=1)).strftime( + "%Y%m%d" + ) + + # Eg. if start_date is 20250101, then we end_date to be 20250102T00:00:00.000000000 + # which is the start of the next day, minus 1 nanosecond to get the end of the + # current day + end_ttj2000ns = str_yyyymmdd_to_ttj2000ns(next_day) - 1 + logger.info(f"Filtering dataset out of day boundary of {start_date}.") + return dataset.sel(epoch=slice(start_ttj2000ns, end_ttj2000ns)) + + +def check_epochs_within_day_offsets( + datasets: list[xr.Dataset], + day: np.datetime64, +) -> None: + """ + Raise an error if any dataset epoch falls more than 24 hours outside day. + + A tolerance of Β±24 hours around the expected processing day is allowed + to accommodate data that straddles midnight. Epochs beyond that window + may indicate the wrong input file was provided. Eg. + day = "202605012" + lower = "20260511" + upper = "20260513" + + If any data outside of this range is found, this function throws an error. + Some instruments can have buffer times beyond daily file date, but they should not + be more than 24hrs from the daily file date. + + Parameters + ---------- + datasets : list[xarray.Dataset] + Datasets whose ``epoch`` coordinate will be checked. + day : numpy.datetime64 + The expected processing day. + + Raises + ------ + ValueError + If any epoch value is more than 24 hours before ``day`` or more + than 24 hours after the end of ``day``. + """ + lower = str_yyyymmdd_to_ttj2000ns( + str(day - np.timedelta64(1, "D")).replace("-", "") + ) + upper = str_yyyymmdd_to_ttj2000ns( + str(day + np.timedelta64(2, "D")).replace("-", "") + ) + for dataset in datasets: + epoch_ns = dataset["epoch"].values + if np.any(epoch_ns < lower) or np.any(epoch_ns >= upper): + dataset_logical_id = dataset.attrs.get("Logical_source", "unknown dataset") + raise ValueError( + f"Data in {dataset_logical_id} contains epochs more than" + f" 24 hours outside the expected processing day {day}." + ) diff --git a/poetry.lock b/poetry.lock index bbfad51492..722533509e 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.0 and should not be changed by hand. +# This file is automatically @generated by Poetry 2.3.4 and should not be changed by hand. [[package]] name = "accessible-pygments" @@ -6,6 +6,8 @@ version = "0.0.5" description = "A collection of accessible pygments styles" optional = true python-versions = ">=3.9" +groups = ["main"] +markers = "extra == \"doc\"" files = [ {file = "accessible_pygments-0.0.5-py3-none-any.whl", hash = "sha256:88ae3211e68a1d0b011504b2ffc1691feafce124b845bd072ab6f9f66f34d4b7"}, {file = "accessible_pygments-0.0.5.tar.gz", hash = "sha256:40918d3e6a2b619ad424cb91e556bd3bd8865443d9f22f1dcdf79e33c8046872"}, @@ -24,6 +26,8 @@ version = "1.0.0" description = "A light, configurable Sphinx theme" optional = true python-versions = ">=3.10" +groups = ["main"] +markers = "extra == \"doc\"" files = [ {file = "alabaster-1.0.0-py3-none-any.whl", hash = "sha256:fc6786402dc3fcb2de3cabd5fe455a2db534b371124f1f21de8731783dec828b"}, {file = "alabaster-1.0.0.tar.gz", hash = "sha256:c00dca57bca26fa62a6d7d0a9fcce65f3e026e9bfe33e9c538fd3fbb2144fd9e"}, @@ -35,6 +39,7 @@ version = "6.1.7" description = "Astronomy and astrophysics core library" optional = false python-versions = ">=3.10" +groups = ["main"] files = [ {file = "astropy-6.1.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:be954c5f7707a089609053665aeb76493b79e5c4753c39486761bc6d137bf040"}, {file = "astropy-6.1.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b5e48df5ab2e3e521e82a7233a4b1159d071e64e6cbb76c45415dc68d3b97af1"}, @@ -76,7 +81,7 @@ PyYAML = ">=3.13" [package.extras] all = ["asdf-astropy (>=0.3)", "astropy[recommended]", "astropy[typing]", "beautifulsoup4", "bleach", "bottleneck", "certifi", "dask[array]", "fsspec[http] (>=2023.4.0)", "h5py", "html5lib", "ipython (>=4.2)", "jplephem", "mpmath", "pandas", "pre-commit", "pyarrow (>=7.0.0)", "pytest (>=7.0)", "pytz", "s3fs (>=2023.4.0)", "sortedcontainers"] -docs = ["Jinja2 (>=3.1.3)", "astropy[recommended]", "matplotlib (>=3.9.1)", "numpy (<2.0)", "pytest (>=7.0)", "sphinx", "sphinx-astropy[confv2] (>=1.9.1)", "sphinx-changelog (>=1.2.0)", "sphinx_design", "sphinxcontrib-globalsubs (>=0.1.1)", "tomli"] +docs = ["Jinja2 (>=3.1.3)", "astropy[recommended]", "matplotlib (>=3.9.1)", "numpy (<2.0)", "pytest (>=7.0)", "sphinx", "sphinx-astropy[confv2] (>=1.9.1)", "sphinx-changelog (>=1.2.0)", "sphinx_design", "sphinxcontrib-globalsubs (>=0.1.1)", "tomli ; python_version < \"3.11\""] recommended = ["matplotlib (>=3.5.0,!=3.5.2)", "scipy (>=1.8)"] test = ["pytest (>=7.0)", "pytest-astropy (>=0.10)", "pytest-astropy-header (>=0.2.1)", "pytest-doctestplus (>=0.12)", "pytest-xdist", "threadpoolctl"] test-all = ["array-api-strict", "astropy[test]", "coverage[toml]", "ipython (>=4.2)", "objgraph", "sgp4 (>=2.3)", "skyfield (>=1.20)"] @@ -88,6 +93,7 @@ version = "1.1.2" description = "BSD-licensed HEALPix for Astropy" optional = false python-versions = ">=3.10" +groups = ["main"] files = [ {file = "astropy_healpix-1.1.2-cp310-abi3-macosx_10_9_x86_64.whl", hash = "sha256:fb504c998e1661215c74da9537558cd2048d29b44acb2d63e613aae133b91668"}, {file = "astropy_healpix-1.1.2-cp310-abi3-macosx_11_0_arm64.whl", hash = "sha256:00a0c9378d7e844aecb23d62c206a999e045a48781a320ac5f012f8c95ac4022"}, @@ -113,6 +119,7 @@ version = "0.2025.5.19.0.38.36" description = "IERS Earth Rotation and Leap Second tables for the astropy core package" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "astropy_iers_data-0.2025.5.19.0.38.36-py3-none-any.whl", hash = "sha256:561dcda3577dfe8186020c6a3fd305282183f533b158cb4b07887fb9af15cd6c"}, {file = "astropy_iers_data-0.2025.5.19.0.38.36.tar.gz", hash = "sha256:f273428b408f30c618a72e454dd68434564dea69d891777df36de3f1399e0fa5"}, @@ -128,18 +135,20 @@ version = "25.3.0" description = "Classes Without Boilerplate" optional = true python-versions = ">=3.8" +groups = ["main"] +markers = "extra == \"doc\"" files = [ {file = "attrs-25.3.0-py3-none-any.whl", hash = "sha256:427318ce031701fea540783410126f03899a97ffc6f61596ad581ac2e40e3bc3"}, {file = "attrs-25.3.0.tar.gz", hash = "sha256:75d7cefc7fb576747b2c81b4442d4d4a1ce0900973527c011d1030fd3bf4af1b"}, ] [package.extras] -benchmark = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-codspeed", "pytest-mypy-plugins", "pytest-xdist[psutil]"] -cov = ["cloudpickle", "coverage[toml] (>=5.3)", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] -dev = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pre-commit-uv", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] +benchmark = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pympler", "pytest (>=4.3.0)", "pytest-codspeed", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] +cov = ["cloudpickle ; platform_python_implementation == \"CPython\"", "coverage[toml] (>=5.3)", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] +dev = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pre-commit-uv", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] docs = ["cogapp", "furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier"] -tests = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] -tests-mypy = ["mypy (>=1.11.1)", "pytest-mypy-plugins"] +tests = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] +tests-mypy = ["mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\""] [[package]] name = "babel" @@ -147,13 +156,15 @@ version = "2.17.0" description = "Internationalization utilities" optional = true python-versions = ">=3.8" +groups = ["main"] +markers = "extra == \"doc\"" files = [ {file = "babel-2.17.0-py3-none-any.whl", hash = "sha256:4d0b53093fdfb4b21c92b5213dba5a1b23885afa8383709427046b21c366e5f2"}, {file = "babel-2.17.0.tar.gz", hash = "sha256:0c54cffb19f690cdcc52a3b50bcbf71e07a808d1c80d549f2459b9d2cf0afb9d"}, ] [package.extras] -dev = ["backports.zoneinfo", "freezegun (>=1.0,<2.0)", "jinja2 (>=3.0)", "pytest (>=6.0)", "pytest-cov", "pytz", "setuptools", "tzdata"] +dev = ["backports.zoneinfo ; python_version < \"3.9\"", "freezegun (>=1.0,<2.0)", "jinja2 (>=3.0)", "pytest (>=6.0)", "pytest-cov", "pytz", "setuptools", "tzdata ; sys_platform == \"win32\""] [[package]] name = "beautifulsoup4" @@ -161,6 +172,8 @@ version = "4.13.4" description = "Screen-scraping library" optional = true python-versions = ">=3.7.0" +groups = ["main"] +markers = "extra == \"doc\"" files = [ {file = "beautifulsoup4-4.13.4-py3-none-any.whl", hash = "sha256:9bbbb14bfde9d79f38b8cd5f8c7c85f4b8f2523190ebed90e950a8dea4cb1c4b"}, {file = "beautifulsoup4-4.13.4.tar.gz", hash = "sha256:dbb3c4e1ceae6aefebdaf2423247260cd062430a410e38c66f2baa50a8437195"}, @@ -183,6 +196,7 @@ version = "1.3.6" description = "A python CDF reader toolkit" optional = false python-versions = ">=3.9" +groups = ["main"] files = [ {file = "cdflib-1.3.6-py3-none-any.whl", hash = "sha256:ed343840b6cd0b5f32281405823c9b7b01360bc0480b5939e9abec1e9c0c2e60"}, {file = "cdflib-1.3.6.tar.gz", hash = "sha256:61084895f68c7a127305bcec3e4178e123db97fca6aff3824bd08b014e4ff1f2"}, @@ -202,6 +216,7 @@ version = "2025.4.26" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.6" +groups = ["main"] files = [ {file = "certifi-2025.4.26-py3-none-any.whl", hash = "sha256:30350364dfe371162649852c63336a15c70c6510c2ad5015b21c2345311805f3"}, {file = "certifi-2025.4.26.tar.gz", hash = "sha256:0a816057ea3cdefcef70270d2c515e4506bbc954f417fa5ade2021213bb8f0c6"}, @@ -213,6 +228,8 @@ version = "3.4.0" description = "Validate configuration and produce human readable error messages." optional = true python-versions = ">=3.8" +groups = ["main"] +markers = "extra == \"dev\"" files = [ {file = "cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9"}, {file = "cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560"}, @@ -224,6 +241,8 @@ version = "1.6.4.post1" description = "Time-handling functionality from netcdf4-python" optional = true python-versions = ">=3.8" +groups = ["main"] +markers = "extra == \"test\"" files = [ {file = "cftime-1.6.4.post1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0baa9bc4850929da9f92c25329aa1f651e2d6f23e237504f337ee9e12a769f5d"}, {file = "cftime-1.6.4.post1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6bb6b087f4b2513c37670bccd457e2a666ca489c5f2aad6e2c0e94604dc1b5b9"}, @@ -275,6 +294,7 @@ version = "3.4.2" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." optional = false python-versions = ">=3.7" +groups = ["main"] files = [ {file = "charset_normalizer-3.4.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7c48ed483eb946e6c04ccbe02c6b4d1d48e51944b6db70f697e089c193404941"}, {file = "charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b2d318c11350e10662026ad0eb71bb51c7812fc8590825304ae0bdd4ac283acd"}, @@ -370,12 +390,29 @@ files = [ {file = "charset_normalizer-3.4.2.tar.gz", hash = "sha256:5baececa9ecba31eff645232d59845c07aa030f0c81ee70184a90d35099a0e63"}, ] +[[package]] +name = "click" +version = "8.3.0" +description = "Composable command line interface toolkit" +optional = false +python-versions = ">=3.10" +groups = ["main"] +files = [ + {file = "click-8.3.0-py3-none-any.whl", hash = "sha256:9b9f285302c6e3064f4330c05f05b81945b2a39544279343e6e7c5f27a9baddc"}, + {file = "click-8.3.0.tar.gz", hash = "sha256:e7b8232224eba16f4ebe410c25ced9f7875cb5f3263ffc93cc3e8da705e229c4"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "platform_system == \"Windows\""} + [[package]] name = "colorama" version = "0.4.6" description = "Cross-platform colored terminal text." -optional = true +optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +groups = ["main"] +markers = "(extra == \"doc\" or extra == \"test\") and sys_platform == \"win32\" or platform_system == \"Windows\"" files = [ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, @@ -387,6 +424,8 @@ version = "7.8.0" description = "Code coverage measurement for Python" optional = true python-versions = ">=3.9" +groups = ["main"] +markers = "extra == \"test\"" files = [ {file = "coverage-7.8.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2931f66991175369859b5fd58529cd4b73582461877ecfd859b6549869287ffe"}, {file = "coverage-7.8.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:52a523153c568d2c0ef8826f6cc23031dc86cffb8c6aeab92c4ff776e7951b28"}, @@ -457,7 +496,7 @@ files = [ tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.11.0a6\" and extra == \"toml\""} [package.extras] -toml = ["tomli"] +toml = ["tomli ; python_full_version <= \"3.11.0a6\""] [[package]] name = "deepmerge" @@ -465,6 +504,8 @@ version = "2.0" description = "A toolset for deeply merging Python dictionaries." optional = true python-versions = ">=3.8" +groups = ["main"] +markers = "extra == \"doc\"" files = [ {file = "deepmerge-2.0-py3-none-any.whl", hash = "sha256:6de9ce507115cff0bed95ff0ce9ecc31088ef50cbdf09bc90a09349a318b3d00"}, {file = "deepmerge-2.0.tar.gz", hash = "sha256:5c3d86081fbebd04dd5de03626a0607b809a98fb6ccba5770b62466fe940ff20"}, @@ -479,6 +520,8 @@ version = "0.3.9" description = "Distribution utilities" optional = true python-versions = "*" +groups = ["main"] +markers = "extra == \"dev\"" files = [ {file = "distlib-0.3.9-py2.py3-none-any.whl", hash = "sha256:47f8c22fd27c27e25a65601af709b38e4f0a45ea4fc2e710f65755fa8caaaf87"}, {file = "distlib-0.3.9.tar.gz", hash = "sha256:a60f20dea646b8a33f3e7772f74dc0b2d0772d2837ee1342a00645c81edf9403"}, @@ -490,6 +533,8 @@ version = "0.21.2" description = "Docutils -- Python Documentation Utilities" optional = true python-versions = ">=3.9" +groups = ["main"] +markers = "extra == \"doc\"" files = [ {file = "docutils-0.21.2-py3-none-any.whl", hash = "sha256:dafca5b9e384f0e419294eb4d2ff9fa826435bf15f15b7bd45723e8ad76811b2"}, {file = "docutils-0.21.2.tar.gz", hash = "sha256:3a6b18732edf182daa3cd12775bbb338cf5691468f91eeeb109deff6ebfa986f"}, @@ -501,6 +546,8 @@ version = "2.0.0" description = "An implementation of lxml.xmlfile for the standard library" optional = true python-versions = ">=3.8" +groups = ["main"] +markers = "extra == \"test\" or extra == \"tools\"" files = [ {file = "et_xmlfile-2.0.0-py3-none-any.whl", hash = "sha256:7a91720bc756843502c3b7504c77b8fe44217c85c537d85037f0f536151b2caa"}, {file = "et_xmlfile-2.0.0.tar.gz", hash = "sha256:dab3f4764309081ce75662649be815c4c9081e88f0837825f90fd28317d4da54"}, @@ -512,6 +559,8 @@ version = "1.3.0" description = "Backport of PEP 654 (exception groups)" optional = true python-versions = ">=3.7" +groups = ["main"] +markers = "extra == \"test\" and python_version == \"3.10\"" files = [ {file = "exceptiongroup-1.3.0-py3-none-any.whl", hash = "sha256:4d111e6e0c13d0644cad6ddaa7ed0261a0b36971f6d23e7ec9b4b9097da78a10"}, {file = "exceptiongroup-1.3.0.tar.gz", hash = "sha256:b241f5885f560bc56a59ee63ca4c6a8bfa46ae4ad651af316d4e81817bb9fd88"}, @@ -529,6 +578,8 @@ version = "2.1.1" description = "execnet: rapid multi-Python deployment" optional = true python-versions = ">=3.8" +groups = ["main"] +markers = "extra == \"test\"" files = [ {file = "execnet-2.1.1-py3-none-any.whl", hash = "sha256:26dee51f1b80cebd6d0ca8e74dd8745419761d3bef34163928cbebbdc4749fdc"}, {file = "execnet-2.1.1.tar.gz", hash = "sha256:5189b52c6121c24feae288166ab41b32549c7e2348652736540b9e6e7d4e72e3"}, @@ -543,6 +594,8 @@ version = "3.18.0" description = "A platform independent file lock." optional = true python-versions = ">=3.9" +groups = ["main"] +markers = "extra == \"dev\"" files = [ {file = "filelock-3.18.0-py3-none-any.whl", hash = "sha256:c401f4f8377c4464e6db25fff06205fd89bdd83b65eb0488ed1b160f780e21de"}, {file = "filelock-3.18.0.tar.gz", hash = "sha256:adbc88eabb99d2fec8c9c1b229b171f18afa655400173ddc653d5d01501fb9f2"}, @@ -551,7 +604,7 @@ files = [ [package.extras] docs = ["furo (>=2024.8.6)", "sphinx (>=8.1.3)", "sphinx-autodoc-typehints (>=3)"] testing = ["covdefaults (>=2.3)", "coverage (>=7.6.10)", "diff-cover (>=9.2.1)", "pytest (>=8.3.4)", "pytest-asyncio (>=0.25.2)", "pytest-cov (>=6)", "pytest-mock (>=3.14)", "pytest-timeout (>=2.3.1)", "virtualenv (>=20.28.1)"] -typing = ["typing-extensions (>=4.12.2)"] +typing = ["typing-extensions (>=4.12.2) ; python_version < \"3.11\""] [[package]] name = "healpy" @@ -559,6 +612,8 @@ version = "1.18.1" description = "Healpix tools package for Python" optional = true python-versions = ">=3.10" +groups = ["main"] +markers = "extra == \"map-visualization\"" files = [ {file = "healpy-1.18.1-cp310-cp310-macosx_13_0_x86_64.whl", hash = "sha256:4821fca8c6ce6b5db41958b873275f21a367c234c69df488312dcca918e24e09"}, {file = "healpy-1.18.1-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:ddf62d19e8642c180c829443093170846ab94045014810d69d70b9c1f2058e9b"}, @@ -594,6 +649,8 @@ version = "2.6.10" description = "File identification library for Python" optional = true python-versions = ">=3.9" +groups = ["main"] +markers = "extra == \"dev\"" files = [ {file = "identify-2.6.10-py2.py3-none-any.whl", hash = "sha256:5f34248f54136beed1a7ba6a6b5c4b6cf21ff495aac7c359e1ef831ae3b8ab25"}, {file = "identify-2.6.10.tar.gz", hash = "sha256:45e92fd704f3da71cc3880036633f48b4b7265fd4de2b57627cb157216eb7eb8"}, @@ -608,6 +665,7 @@ version = "3.10" description = "Internationalized Domain Names in Applications (IDNA)" optional = false python-versions = ">=3.6" +groups = ["main"] files = [ {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"}, {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"}, @@ -622,6 +680,8 @@ version = "1.4.1" description = "Getting image size from png/jpeg/jpeg2000/gif file" optional = true python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +groups = ["main"] +markers = "extra == \"doc\"" files = [ {file = "imagesize-1.4.1-py2.py3-none-any.whl", hash = "sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b"}, {file = "imagesize-1.4.1.tar.gz", hash = "sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a"}, @@ -629,13 +689,14 @@ files = [ [[package]] name = "imap-data-access" -version = "0.32.0" +version = "0.37.0" description = "IMAP SDC Data Access" optional = false python-versions = "*" +groups = ["main"] files = [ - {file = "imap_data_access-0.32.0-py3-none-any.whl", hash = "sha256:e13f83bb26a2c0c5f15fe369a997e7a9ba07beab9411db7f2e4bb742f404fab1"}, - {file = "imap_data_access-0.32.0.tar.gz", hash = "sha256:d67f00a3037b9f1bd3acb032d2b6c45b5b62ba9206292bb7ee19c2118a6c9540"}, + {file = "imap_data_access-0.37.0-py3-none-any.whl", hash = "sha256:9801aba311311815866336636fdad9e37b530498f4c3f21abce283d860a7c643"}, + {file = "imap_data_access-0.37.0.tar.gz", hash = "sha256:7887ad43c4404c6465035af73621237aef7a8d88d506439dd4618aef1db8cf87"}, ] [package.dependencies] @@ -651,6 +712,8 @@ version = "2.1.0" description = "brain-dead simple config-ini parsing" optional = true python-versions = ">=3.8" +groups = ["main"] +markers = "extra == \"test\"" files = [ {file = "iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760"}, {file = "iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7"}, @@ -662,6 +725,8 @@ version = "3.1.6" description = "A very fast and expressive template engine." optional = true python-versions = ">=3.7" +groups = ["main"] +markers = "extra == \"doc\"" files = [ {file = "jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67"}, {file = "jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d"}, @@ -679,6 +744,8 @@ version = "4.23.0" description = "An implementation of JSON Schema validation for Python" optional = true python-versions = ">=3.8" +groups = ["main"] +markers = "extra == \"doc\"" files = [ {file = "jsonschema-4.23.0-py3-none-any.whl", hash = "sha256:fbadb6f8b144a8f8cf9f0b89ba94501d143e50411a1278633f56a7acf7fd5566"}, {file = "jsonschema-4.23.0.tar.gz", hash = "sha256:d71497fef26351a33265337fa77ffeb82423f3ea21283cd9467bb03999266bc4"}, @@ -686,7 +753,7 @@ files = [ [package.dependencies] attrs = ">=22.2.0" -jsonschema-specifications = ">=2023.03.6" +jsonschema-specifications = ">=2023.3.6" referencing = ">=0.28.4" rpds-py = ">=0.7.1" @@ -700,6 +767,8 @@ version = "2025.4.1" description = "The JSON Schema meta-schemas and vocabularies, exposed as a Registry" optional = true python-versions = ">=3.9" +groups = ["main"] +markers = "extra == \"doc\"" files = [ {file = "jsonschema_specifications-2025.4.1-py3-none-any.whl", hash = "sha256:4653bffbd6584f7de83a67e0d620ef16900b390ddc7939d56684d6c81e33f1af"}, {file = "jsonschema_specifications-2025.4.1.tar.gz", hash = "sha256:630159c9f4dbea161a6a2205c3011cc4f18ff381b189fff48bb39b9bf26ae608"}, @@ -714,6 +783,7 @@ version = "5.4.0" description = "Powerful and Pythonic XML processing library combining libxml2/libxslt with the ElementTree API." optional = false python-versions = ">=3.6" +groups = ["main"] files = [ {file = "lxml-5.4.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e7bc6df34d42322c5289e37e9971d6ed114e3776b45fa879f734bded9d1fea9c"}, {file = "lxml-5.4.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6854f8bd8a1536f8a1d9a3655e6354faa6406621cf857dc27b681b69860645c7"}, @@ -856,12 +926,38 @@ html5 = ["html5lib"] htmlsoup = ["BeautifulSoup4"] source = ["Cython (>=3.0.11,<3.1.0)"] +[[package]] +name = "markdown-it-py" +version = "4.0.0" +description = "Python port of markdown-it. Markdown parsing, done right!" +optional = false +python-versions = ">=3.10" +groups = ["main"] +files = [ + {file = "markdown_it_py-4.0.0-py3-none-any.whl", hash = "sha256:87327c59b172c5011896038353a81343b6754500a08cd7a4973bb48c6d578147"}, + {file = "markdown_it_py-4.0.0.tar.gz", hash = "sha256:cb0a2b4aa34f932c007117b194e945bd74e0ec24133ceb5bac59009cda1cb9f3"}, +] + +[package.dependencies] +mdurl = ">=0.1,<1.0" + +[package.extras] +benchmarking = ["psutil", "pytest", "pytest-benchmark"] +compare = ["commonmark (>=0.9,<1.0)", "markdown (>=3.4,<4.0)", "markdown-it-pyrs", "mistletoe (>=1.0,<2.0)", "mistune (>=3.0,<4.0)", "panflute (>=2.3,<3.0)"] +linkify = ["linkify-it-py (>=1,<3)"] +plugins = ["mdit-py-plugins (>=0.5.0)"] +profiling = ["gprof2dot"] +rtd = ["ipykernel", "jupyter_sphinx", "mdit-py-plugins (>=0.5.0)", "myst-parser", "pyyaml", "sphinx", "sphinx-book-theme (>=1.0,<2.0)", "sphinx-copybutton", "sphinx-design"] +testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions", "requests"] + [[package]] name = "markupsafe" version = "3.0.2" description = "Safely add untrusted strings to HTML/XML markup." optional = true python-versions = ">=3.9" +groups = ["main"] +markers = "extra == \"doc\"" files = [ {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8"}, {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9e2d922824181480953426608b81967de705c3cef4d1af983af849d7bd619158"}, @@ -926,12 +1022,26 @@ files = [ {file = "markupsafe-3.0.2.tar.gz", hash = "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0"}, ] +[[package]] +name = "mdurl" +version = "0.1.2" +description = "Markdown URL utilities" +optional = false +python-versions = ">=3.7" +groups = ["main"] +files = [ + {file = "mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8"}, + {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"}, +] + [[package]] name = "mistune" version = "3.1.3" description = "A sane and fast Markdown parser with useful plugins and renderers" optional = true python-versions = ">=3.8" +groups = ["main"] +markers = "extra == \"doc\"" files = [ {file = "mistune-3.1.3-py3-none-any.whl", hash = "sha256:1a32314113cff28aa6432e99e522677c8587fd83e3d51c29b82a52409c842bd9"}, {file = "mistune-3.1.3.tar.gz", hash = "sha256:a7035c21782b2becb6be62f8f25d3df81ccb4d6fa477a6525b15af06539f02a0"}, @@ -946,6 +1056,8 @@ version = "1.10.1" description = "Optional static typing for Python" optional = true python-versions = ">=3.8" +groups = ["main"] +markers = "extra == \"dev\"" files = [ {file = "mypy-1.10.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e36f229acfe250dc660790840916eb49726c928e8ce10fbdf90715090fe4ae02"}, {file = "mypy-1.10.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:51a46974340baaa4145363b9e051812a2446cf583dfaeba124af966fa44593f7"}, @@ -993,6 +1105,8 @@ version = "1.1.0" description = "Type system extensions for programs checked with the mypy type checker." optional = true python-versions = ">=3.8" +groups = ["main"] +markers = "extra == \"dev\"" files = [ {file = "mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505"}, {file = "mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558"}, @@ -1004,6 +1118,8 @@ version = "1.7.2" description = "Provides an object-oriented python interface to the netCDF version 4 library" optional = true python-versions = ">=3.8" +groups = ["main"] +markers = "extra == \"test\"" files = [ {file = "netCDF4-1.7.2-cp310-cp310-macosx_12_0_x86_64.whl", hash = "sha256:5e9b485e3bd9294d25ff7dc9addefce42b3d23c1ee7e3627605277d159819392"}, {file = "netCDF4-1.7.2-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:118b476fd00d7e3ab9aa7771186d547da645ae3b49c0c7bdab866793ebf22f07"}, @@ -1034,6 +1150,16 @@ files = [ {file = "netCDF4-1.7.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:572f71459ef4b30e8554dcc4e1e6f55de515acc82a50968b48fe622244a64548"}, {file = "netCDF4-1.7.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f77e72281acc5f331f82271e5f7f014d46f5ca9bcaa5aafe3e46d66cee21320"}, {file = "netCDF4-1.7.2-cp39-cp39-win_amd64.whl", hash = "sha256:d0fa7a9674fae8ae4877e813173c3ff7a6beee166b8730bdc847f517b282ed31"}, + {file = "netcdf4-1.7.2-cp310-cp310-macosx_13_0_x86_64.whl", hash = "sha256:16c3ba053930ed990e58827de6ab03184e407549004fb77438b98e5777e8cf3b"}, + {file = "netcdf4-1.7.2-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:142c9ed2db8a87a15ae0530c8a99f4f045435b0f495df733e9f111995e389d4f"}, + {file = "netcdf4-1.7.2-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:76cb3bbbbe4cd5fca612578eb105c16217380f7f93af2b549e8f38296bc906bb"}, + {file = "netcdf4-1.7.2-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:835ae7bcef666c967241baeeee9bef9376ddb7527297b24735597131f6f628e2"}, + {file = "netcdf4-1.7.2-cp310-cp310-win_amd64.whl", hash = "sha256:73bd7eda3cefb04c4076e76911f652f5ed56bf434e0a3958e367932953437557"}, + {file = "netcdf4-1.7.2-cp311-abi3-macosx_13_0_x86_64.whl", hash = "sha256:7e81c3c47f2772eab0b93fba8bb05b17b58dce17720e1bed25e9d76551deecd0"}, + {file = "netcdf4-1.7.2-cp311-abi3-macosx_14_0_arm64.whl", hash = "sha256:cb2791dba37fc98fd1ac4e236c97822909f54efbcdf7f1415c9777810e0a28f4"}, + {file = "netcdf4-1.7.2-cp311-abi3-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bf11480f6b8a5b246818ffff6b4d90481e51f8b9555b41af0c372eb0aaf8b65f"}, + {file = "netcdf4-1.7.2-cp311-abi3-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1ccc05328a8ff31921b539821791aeb20b054879f3fdf6d1d505bf6422824fec"}, + {file = "netcdf4-1.7.2-cp311-abi3-win_amd64.whl", hash = "sha256:999bfc4acebf400ed724d5e7329e2e768accc7ee1fa1d82d505da782f730301b"}, {file = "netcdf4-1.7.2.tar.gz", hash = "sha256:a4c6375540b19989896136943abb6d44850ff6f1fa7d3f063253b1ad3f8b7fce"}, ] @@ -1051,6 +1177,8 @@ version = "1.9.1" description = "Node.js virtual environment builder" optional = true python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +groups = ["main"] +markers = "extra == \"dev\"" files = [ {file = "nodeenv-1.9.1-py2.py3-none-any.whl", hash = "sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9"}, {file = "nodeenv-1.9.1.tar.gz", hash = "sha256:6ec12890a2dab7946721edbfbcd91f3319c6ccc9aec47be7c7e6b7011ee6645f"}, @@ -1062,6 +1190,7 @@ version = "2.2.6" description = "Fundamental package for array computing in Python" optional = false python-versions = ">=3.10" +groups = ["main"] files = [ {file = "numpy-2.2.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b412caa66f72040e6d268491a59f2c43bf03eb6c96dd8f0307829feb7fa2b6fb"}, {file = "numpy-2.2.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8e41fd67c52b86603a91c1a505ebaef50b3314de0213461c7a6e99c9a3beff90"}, @@ -1126,6 +1255,8 @@ version = "1.8.0" description = "Sphinx extension to support docstrings in Numpy format" optional = true python-versions = ">=3.9" +groups = ["main"] +markers = "extra == \"doc\"" files = [ {file = "numpydoc-1.8.0-py3-none-any.whl", hash = "sha256:72024c7fd5e17375dec3608a27c03303e8ad00c81292667955c6fea7a3ccf541"}, {file = "numpydoc-1.8.0.tar.gz", hash = "sha256:022390ab7464a44f8737f79f8b31ce1d3cfa4b4af79ccaa1aac5e8368db587fb"}, @@ -1137,7 +1268,7 @@ tabulate = ">=0.8.10" tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} [package.extras] -developer = ["pre-commit (>=3.3)", "tomli"] +developer = ["pre-commit (>=3.3)", "tomli ; python_version < \"3.11\""] doc = ["intersphinx-registry", "matplotlib (>=3.5)", "numpy (>=1.22)", "pydata-sphinx-theme (>=0.13.3)", "sphinx (>=7)"] test = ["matplotlib", "pytest", "pytest-cov"] @@ -1147,6 +1278,8 @@ version = "3.1.5" description = "A Python library to read/write Excel 2010 xlsx/xlsm files" optional = true python-versions = ">=3.8" +groups = ["main"] +markers = "extra == \"test\" or extra == \"tools\"" files = [ {file = "openpyxl-3.1.5-py2.py3-none-any.whl", hash = "sha256:5282c12b107bffeef825f4617dc029afaf41d0ea60823bbb665ef3079dc79de2"}, {file = "openpyxl-3.1.5.tar.gz", hash = "sha256:cf0e3cf56142039133628b5acffe8ef0c12bc902d2aadd3e0fe5878dc08d1050"}, @@ -1161,6 +1294,7 @@ version = "25.0" description = "Core utilities for Python packages" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484"}, {file = "packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f"}, @@ -1172,6 +1306,7 @@ version = "2.2.3" description = "Powerful data structures for data analysis, time series, and statistics" optional = false python-versions = ">=3.9" +groups = ["main"] files = [ {file = "pandas-2.2.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1948ddde24197a0f7add2bdc4ca83bf2b1ef84a1bc8ccffd95eda17fd836ecb5"}, {file = "pandas-2.2.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:381175499d3802cde0eabbaf6324cce0c4f5d52ca6f8c377c29ad442f50f6348"}, @@ -1258,6 +1393,8 @@ version = "4.0.0" description = "Dependency injection framework designed with Python in mind." optional = true python-versions = ">=3.8" +groups = ["main"] +markers = "extra == \"doc\"" files = [ {file = "picobox-4.0.0-py3-none-any.whl", hash = "sha256:4c27eb689fe45dabd9e64c382e04418147d0b746d155b4e80057dbb7ff82027e"}, {file = "picobox-4.0.0.tar.gz", hash = "sha256:114da1b5606b2f615e8b0eb68d04198ad9de75af5adbcf5b36fe4f664ab927b6"}, @@ -1269,6 +1406,8 @@ version = "4.3.8" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." optional = true python-versions = ">=3.9" +groups = ["main"] +markers = "extra == \"dev\"" files = [ {file = "platformdirs-4.3.8-py3-none-any.whl", hash = "sha256:ff7059bb7eb1179e2685604f4aaf157cfd9535242bd23742eadc3c13542139b4"}, {file = "platformdirs-4.3.8.tar.gz", hash = "sha256:3d512d96e16bcb959a814c9f348431070822a6496326a4be0911c40b5a74c2bc"}, @@ -1285,6 +1424,8 @@ version = "1.6.0" description = "plugin and hook calling mechanisms for python" optional = true python-versions = ">=3.9" +groups = ["main"] +markers = "extra == \"test\"" files = [ {file = "pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746"}, {file = "pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3"}, @@ -1300,6 +1441,8 @@ version = "3.8.0" description = "A framework for managing and maintaining multi-language pre-commit hooks." optional = true python-versions = ">=3.9" +groups = ["main"] +markers = "extra == \"dev\"" files = [ {file = "pre_commit-3.8.0-py2.py3-none-any.whl", hash = "sha256:9a90a53bf82fdd8778d58085faf8d83df56e40dfe18f45b19446e26bf1b3a63f"}, {file = "pre_commit-3.8.0.tar.gz", hash = "sha256:8bb6494d4a20423842e198980c9ecf9f96607a07ea29549e180eef9ae80fe7af"}, @@ -1318,6 +1461,8 @@ version = "0.16.1" description = "Bootstrap-based Sphinx theme from the PyData community" optional = true python-versions = ">=3.9" +groups = ["main"] +markers = "extra == \"doc\"" files = [ {file = "pydata_sphinx_theme-0.16.1-py3-none-any.whl", hash = "sha256:225331e8ac4b32682c18fcac5a57a6f717c4e632cea5dd0e247b55155faeccde"}, {file = "pydata_sphinx_theme-0.16.1.tar.gz", hash = "sha256:a08b7f0b7f70387219dc659bff0893a7554d5eb39b59d3b8ef37b8401b7642d7"}, @@ -1345,6 +1490,7 @@ version = "2.0.1.5" description = "Python bindings for ERFA" optional = false python-versions = ">=3.9" +groups = ["main"] files = [ {file = "pyerfa-2.0.1.5-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:b282d7c60c4c47cf629c484c17ac504fcb04abd7b3f4dfcf53ee042afc3a5944"}, {file = "pyerfa-2.0.1.5-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:be1aeb70390dd03a34faf96749d5cabc58437410b4aab7213c512323932427df"}, @@ -1370,8 +1516,9 @@ test = ["pytest", "pytest-doctestplus (>=0.7)"] name = "pygments" version = "2.19.1" description = "Pygments is a syntax highlighting package written in Python." -optional = true +optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "pygments-2.19.1-py3-none-any.whl", hash = "sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c"}, {file = "pygments-2.19.1.tar.gz", hash = "sha256:61c16d2a8576dc0649d9f39e089b5f02bcd27fba10d8fb4dcc28173f7a45151f"}, @@ -1386,6 +1533,8 @@ version = "8.3.5" description = "pytest: simple powerful testing with Python" optional = true python-versions = ">=3.8" +groups = ["main"] +markers = "extra == \"test\"" files = [ {file = "pytest-8.3.5-py3-none-any.whl", hash = "sha256:c69214aa47deac29fad6c2a4f590b9c4a9fdb16a403176fe154b79c0b4d4d820"}, {file = "pytest-8.3.5.tar.gz", hash = "sha256:f4efe70cc14e511565ac476b57c279e12a855b11f48f212af1080ef2263d3845"}, @@ -1408,6 +1557,8 @@ version = "4.1.0" description = "Pytest plugin for measuring coverage." optional = true python-versions = ">=3.7" +groups = ["main"] +markers = "extra == \"test\"" files = [ {file = "pytest-cov-4.1.0.tar.gz", hash = "sha256:3904b13dfbfec47f003b8e77fd5b589cd11904a21ddf1ab38a64f204d6a10ef6"}, {file = "pytest_cov-4.1.0-py3-none-any.whl", hash = "sha256:6ba70b9e97e69fcc3fb45bfeab2d0a138fb65c4d0d6a41ef33983ad114be8c3a"}, @@ -1426,6 +1577,8 @@ version = "3.6.1" description = "pytest xdist plugin for distributed testing, most importantly across multiple CPUs" optional = true python-versions = ">=3.8" +groups = ["main"] +markers = "extra == \"test\"" files = [ {file = "pytest_xdist-3.6.1-py3-none-any.whl", hash = "sha256:9ed4adfb68a016610848639bb7e02c9352d5d9f03d04809919e2dafc3be4cca7"}, {file = "pytest_xdist-3.6.1.tar.gz", hash = "sha256:ead156a4db231eec769737f57668ef58a2084a34b2e55c4a8fa20d861107300d"}, @@ -1446,6 +1599,7 @@ version = "2.9.0.post0" description = "Extensions to the standard Python datetime module" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +groups = ["main"] files = [ {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, @@ -1460,6 +1614,7 @@ version = "2025.2" description = "World timezone definitions, modern and historical" optional = false python-versions = "*" +groups = ["main"] files = [ {file = "pytz-2025.2-py2.py3-none-any.whl", hash = "sha256:5ddf76296dd8c44c26eb8f4b6f35488f3ccbf6fbbd7adee0b7262d43f0ec2f00"}, {file = "pytz-2025.2.tar.gz", hash = "sha256:360b9e3dbb49a209c21ad61809c7fb453643e048b38924c765813546746e81c3"}, @@ -1471,6 +1626,7 @@ version = "6.0.2" description = "YAML parser and emitter for Python" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086"}, {file = "PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf"}, @@ -1533,6 +1689,8 @@ version = "0.36.2" description = "JSON Referencing + Python" optional = true python-versions = ">=3.9" +groups = ["main"] +markers = "extra == \"doc\"" files = [ {file = "referencing-0.36.2-py3-none-any.whl", hash = "sha256:e8699adbbf8b5c7de96d8ffa0eb5c158b3beafce084968e2ea8bb08c6794dcd0"}, {file = "referencing-0.36.2.tar.gz", hash = "sha256:df2e89862cd09deabbdba16944cc3f10feb6b3e6f18e902f7cc25609a34775aa"}, @@ -1549,6 +1707,7 @@ version = "2.32.3" description = "Python HTTP for Humans." optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"}, {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"}, @@ -1564,12 +1723,33 @@ urllib3 = ">=1.21.1,<3" socks = ["PySocks (>=1.5.6,!=1.5.7)"] use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] +[[package]] +name = "rich" +version = "14.2.0" +description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" +optional = false +python-versions = ">=3.8.0" +groups = ["main"] +files = [ + {file = "rich-14.2.0-py3-none-any.whl", hash = "sha256:76bc51fe2e57d2b1be1f96c524b890b816e334ab4c1e45888799bfaab0021edd"}, + {file = "rich-14.2.0.tar.gz", hash = "sha256:73ff50c7c0c1c77c8243079283f4edb376f0f6442433aecb8ce7e6d0b92d1fe4"}, +] + +[package.dependencies] +markdown-it-py = ">=2.2.0" +pygments = ">=2.13.0,<3.0.0" + +[package.extras] +jupyter = ["ipywidgets (>=7.5.1,<9)"] + [[package]] name = "rpds-py" version = "0.25.0" description = "Python bindings to Rust's persistent data structures (rpds)" optional = true python-versions = ">=3.9" +groups = ["main"] +markers = "extra == \"doc\"" files = [ {file = "rpds_py-0.25.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:c146a24a8f0dc4a7846fb4640b88b3a68986585b8ce8397af15e66b7c5817439"}, {file = "rpds_py-0.25.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:77814c7a4e1dc43fba73aeb4c1ef0fe37d901f3aa869a4823de5ea843a283fd0"}, @@ -1689,28 +1869,31 @@ files = [ [[package]] name = "ruff" -version = "0.2.1" +version = "0.15.2" description = "An extremely fast Python linter and code formatter, written in Rust." optional = true python-versions = ">=3.7" -files = [ - {file = "ruff-0.2.1-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:dd81b911d28925e7e8b323e8d06951554655021df8dd4ac3045d7212ac4ba080"}, - {file = "ruff-0.2.1-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:dc586724a95b7d980aa17f671e173df00f0a2eef23f8babbeee663229a938fec"}, - {file = "ruff-0.2.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c92db7101ef5bfc18e96777ed7bc7c822d545fa5977e90a585accac43d22f18a"}, - {file = "ruff-0.2.1-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:13471684694d41ae0f1e8e3a7497e14cd57ccb7dd72ae08d56a159d6c9c3e30e"}, - {file = "ruff-0.2.1-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a11567e20ea39d1f51aebd778685582d4c56ccb082c1161ffc10f79bebe6df35"}, - {file = "ruff-0.2.1-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:00a818e2db63659570403e44383ab03c529c2b9678ba4ba6c105af7854008105"}, - {file = "ruff-0.2.1-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:be60592f9d218b52f03384d1325efa9d3b41e4c4d55ea022cd548547cc42cd2b"}, - {file = "ruff-0.2.1-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fbd2288890b88e8aab4499e55148805b58ec711053588cc2f0196a44f6e3d855"}, - {file = "ruff-0.2.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3ef052283da7dec1987bba8d8733051c2325654641dfe5877a4022108098683"}, - {file = "ruff-0.2.1-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:7022d66366d6fded4ba3889f73cd791c2d5621b2ccf34befc752cb0df70f5fad"}, - {file = "ruff-0.2.1-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:0a725823cb2a3f08ee743a534cb6935727d9e47409e4ad72c10a3faf042ad5ba"}, - {file = "ruff-0.2.1-py3-none-musllinux_1_2_i686.whl", hash = "sha256:0034d5b6323e6e8fe91b2a1e55b02d92d0b582d2953a2b37a67a2d7dedbb7acc"}, - {file = "ruff-0.2.1-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:e5cb5526d69bb9143c2e4d2a115d08ffca3d8e0fddc84925a7b54931c96f5c02"}, - {file = "ruff-0.2.1-py3-none-win32.whl", hash = "sha256:6b95ac9ce49b4fb390634d46d6ece32ace3acdd52814671ccaf20b7f60adb232"}, - {file = "ruff-0.2.1-py3-none-win_amd64.whl", hash = "sha256:e3affdcbc2afb6f5bd0eb3130139ceedc5e3f28d206fe49f63073cb9e65988e0"}, - {file = "ruff-0.2.1-py3-none-win_arm64.whl", hash = "sha256:efababa8e12330aa94a53e90a81eb6e2d55f348bc2e71adbf17d9cad23c03ee6"}, - {file = "ruff-0.2.1.tar.gz", hash = "sha256:3b42b5d8677cd0c72b99fcaf068ffc62abb5a19e71b4a3b9cfa50658a0af02f1"}, +groups = ["main"] +markers = "extra == \"dev\"" +files = [ + {file = "ruff-0.15.2-py3-none-linux_armv6l.whl", hash = "sha256:120691a6fdae2f16d65435648160f5b81a9625288f75544dc40637436b5d3c0d"}, + {file = "ruff-0.15.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:a89056d831256099658b6bba4037ac6dd06f49d194199215befe2bb10457ea5e"}, + {file = "ruff-0.15.2-py3-none-macosx_11_0_arm64.whl", hash = "sha256:e36dee3a64be0ebd23c86ffa3aa3fd3ac9a712ff295e192243f814a830b6bd87"}, + {file = "ruff-0.15.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a9fb47b6d9764677f8c0a193c0943ce9a05d6763523f132325af8a858eadc2b9"}, + {file = "ruff-0.15.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f376990f9d0d6442ea9014b19621d8f2aaf2b8e39fdbfc79220b7f0c596c9b80"}, + {file = "ruff-0.15.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2dcc987551952d73cbf5c88d9fdee815618d497e4df86cd4c4824cc59d5dd75f"}, + {file = "ruff-0.15.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:42a47fd785cbe8c01b9ff45031af875d101b040ad8f4de7bbb716487c74c9a77"}, + {file = "ruff-0.15.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cbe9f49354866e575b4c6943856989f966421870e85cd2ac94dccb0a9dcb2fea"}, + {file = "ruff-0.15.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b7a672c82b5f9887576087d97be5ce439f04bbaf548ee987b92d3a7dede41d3a"}, + {file = "ruff-0.15.2-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:72ecc64f46f7019e2bcc3cdc05d4a7da958b629a5ab7033195e11a438403d956"}, + {file = "ruff-0.15.2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:8dcf243b15b561c655c1ef2f2b0050e5d50db37fe90115507f6ff37d865dc8b4"}, + {file = "ruff-0.15.2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:dab6941c862c05739774677c6273166d2510d254dac0695c0e3f5efa1b5585de"}, + {file = "ruff-0.15.2-py3-none-musllinux_1_2_i686.whl", hash = "sha256:1b9164f57fc36058e9a6806eb92af185b0697c9fe4c7c52caa431c6554521e5c"}, + {file = "ruff-0.15.2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:80d24fcae24d42659db7e335b9e1531697a7102c19185b8dc4a028b952865fd8"}, + {file = "ruff-0.15.2-py3-none-win32.whl", hash = "sha256:fd5ff9e5f519a7e1bd99cbe8daa324010a74f5e2ebc97c6242c08f26f3714f6f"}, + {file = "ruff-0.15.2-py3-none-win_amd64.whl", hash = "sha256:d20014e3dfa400f3ff84830dfb5755ece2de45ab62ecea4af6b7262d0fb4f7c5"}, + {file = "ruff-0.15.2-py3-none-win_arm64.whl", hash = "sha256:cabddc5822acdc8f7b5527b36ceac55cc51eec7b1946e60181de8fe83ca8876e"}, + {file = "ruff-0.15.2.tar.gz", hash = "sha256:14b965afee0969e68bb871eba625343b8673375f457af4abe98553e8bbb98342"}, ] [[package]] @@ -1719,6 +1902,7 @@ version = "1.0.0" description = "A Python package to support metadata attriubte management for Space Weather data processing pipelines." optional = false python-versions = ">=3.9" +groups = ["main"] files = [ {file = "sammi_cdf-1.0.0.tar.gz", hash = "sha256:dec77b2d2ae45dae32540f7db7b74b4444d22e73ce3e0e346342f36360f02f89"}, ] @@ -1738,6 +1922,7 @@ version = "1.15.3" description = "Fundamental algorithms for scientific computing in Python" optional = false python-versions = ">=3.10" +groups = ["main"] files = [ {file = "scipy-1.15.3-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:a345928c86d535060c9c2b25e71e87c39ab2f22fc96e9636bd74d1dbf9de448c"}, {file = "scipy-1.15.3-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:ad3432cb0f9ed87477a8d97f03b763fd1d57709f1bbde3c9369b1dff5503b253"}, @@ -1793,7 +1978,7 @@ numpy = ">=1.23.5,<2.5" [package.extras] dev = ["cython-lint (>=0.12.2)", "doit (>=0.36.0)", "mypy (==1.10.0)", "pycodestyle", "pydevtool", "rich-click", "ruff (>=0.0.292)", "types-psutil", "typing_extensions"] doc = ["intersphinx_registry", "jupyterlite-pyodide-kernel", "jupyterlite-sphinx (>=0.19.1)", "jupytext", "matplotlib (>=3.5)", "myst-nb", "numpydoc", "pooch", "pydata-sphinx-theme (>=0.15.2)", "sphinx (>=5.0.0,<8.0.0)", "sphinx-copybutton", "sphinx-design (>=0.4.0)"] -test = ["Cython", "array-api-strict (>=2.0,<2.1.1)", "asv", "gmpy2", "hypothesis (>=6.30)", "meson", "mpmath", "ninja", "pooch", "pytest", "pytest-cov", "pytest-timeout", "pytest-xdist", "scikit-umfpack", "threadpoolctl"] +test = ["Cython", "array-api-strict (>=2.0,<2.1.1)", "asv", "gmpy2", "hypothesis (>=6.30)", "meson", "mpmath", "ninja ; sys_platform != \"emscripten\"", "pooch", "pytest", "pytest-cov", "pytest-timeout", "pytest-xdist", "scikit-umfpack", "threadpoolctl"] [[package]] name = "six" @@ -1801,6 +1986,7 @@ version = "1.17.0" description = "Python 2 and 3 compatibility utilities" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +groups = ["main"] files = [ {file = "six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274"}, {file = "six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"}, @@ -1812,6 +1998,8 @@ version = "3.0.1" description = "This package provides 32 stemmers for 30 languages generated from Snowball algorithms." optional = true python-versions = "!=3.0.*,!=3.1.*,!=3.2.*" +groups = ["main"] +markers = "extra == \"doc\"" files = [ {file = "snowballstemmer-3.0.1-py3-none-any.whl", hash = "sha256:6cd7b3897da8d6c9ffb968a6781fa6532dce9c3618a4b127d920dab764a19064"}, {file = "snowballstemmer-3.0.1.tar.gz", hash = "sha256:6d5eeeec8e9f84d4d56b847692bacf79bc2c8e90c7f80ca4444ff8b6f2e52895"}, @@ -1823,6 +2011,8 @@ version = "2.7" description = "A modern CSS selector implementation for Beautiful Soup." optional = true python-versions = ">=3.8" +groups = ["main"] +markers = "extra == \"doc\"" files = [ {file = "soupsieve-2.7-py3-none-any.whl", hash = "sha256:6e60cc5c1ffaf1cebcc12e8188320b72071e922c2e897f737cadce79ad5d30c4"}, {file = "soupsieve-2.7.tar.gz", hash = "sha256:ad282f9b6926286d2ead4750552c8a6142bc4c783fd66b0293547c8fe6ae126a"}, @@ -1830,17 +2020,26 @@ files = [ [[package]] name = "space-packet-parser" -version = "5.0.1" +version = "6.0.1" description = "A CCSDS telemetry packet decoding library based on the XTCE packet format description standard." optional = false python-versions = ">=3.9" +groups = ["main"] files = [ - {file = "space_packet_parser-5.0.1-py3-none-any.whl", hash = "sha256:f3f10cbc83aa306cce5c0689109c8cdbccab4da2515525b5657e0d53c1b6f4cc"}, - {file = "space_packet_parser-5.0.1.tar.gz", hash = "sha256:f72b937ec6d1bfb426124e8b2d4e500784f3963c4f88ce22339f24bb249cfad8"}, + {file = "space_packet_parser-6.0.1-py3-none-any.whl", hash = "sha256:ae87465f71ee7f91081c136034113bc9ba1994f2e1de9e8ce26f48ef0d6d9900"}, + {file = "space_packet_parser-6.0.1.tar.gz", hash = "sha256:eb21a857b8d73411bda2bd4f36f8dc27d362a0181753fca6470f76c46bfca979"}, ] [package.dependencies] +click = ">=8.0" lxml = ">=4.8.0" +rich = ">=13.0" + +[package.extras] +docs = ["myst-parser", "pyyaml", "sphinx", "sphinx-autoapi", "sphinx-rtd-theme"] +examples = ["matplotlib (>=3.4)"] +test = ["numpy", "pre-commit", "pytest", "pytest-benchmark", "pytest-cov", "pytest-randomly", "pyyaml", "ruff", "tomli", "xarray"] +xarray = ["numpy (>=1.26.0)", "xarray (>2024.0.0)"] [[package]] name = "sphinx" @@ -1848,6 +2047,8 @@ version = "8.1.3" description = "Python documentation generator" optional = true python-versions = ">=3.10" +groups = ["main"] +markers = "extra == \"doc\"" files = [ {file = "sphinx-8.1.3-py3-none-any.whl", hash = "sha256:09719015511837b76bf6e03e42eb7595ac8c2e41eeb9c29c5b755c6b677992a2"}, {file = "sphinx-8.1.3.tar.gz", hash = "sha256:43c1911eecb0d3e161ad78611bc905d1ad0e523e4ddc202a58a821773dc4c927"}, @@ -1883,6 +2084,8 @@ version = "0.6.2" description = "Markdown extension for Sphinx" optional = true python-versions = ">=3.8" +groups = ["main"] +markers = "extra == \"doc\"" files = [ {file = "sphinx_mdinclude-0.6.2-py3-none-any.whl", hash = "sha256:648e78edb067c0e4bffc22943278d49d54a0714494743592032fa3ad82a86984"}, {file = "sphinx_mdinclude-0.6.2.tar.gz", hash = "sha256:447462e82cb8be61404a2204227f920769eb923d2f57608e3325f3bb88286b4c"}, @@ -1895,7 +2098,7 @@ pygments = ">=2.8" sphinx = ">=6" [package.extras] -dev = ["attribution (==1.7.1)", "black (==24.4.2)", "coverage (==7.5.1)", "docutils (==0.20.1)", "docutils (==0.21.2)", "flake8 (==7.0.0)", "flit (==3.9.0)", "mistune (==3.0.2)", "mypy (==1.10.0)", "sphinx (==7.1.2)", "sphinx (==7.3.7)", "ufmt (==2.5.1)", "usort (==1.0.8.post1)"] +dev = ["attribution (==1.7.1)", "black (==24.4.2)", "coverage (==7.5.1)", "docutils (==0.20.1) ; python_version < \"3.9\"", "docutils (==0.21.2) ; python_version >= \"3.9\"", "flake8 (==7.0.0)", "flit (==3.9.0)", "mistune (==3.0.2)", "mypy (==1.10.0)", "sphinx (==7.1.2) ; python_version < \"3.9\"", "sphinx (==7.3.7) ; python_version >= \"3.9\"", "ufmt (==2.5.1)", "usort (==1.0.8.post1)"] [[package]] name = "sphinxcontrib-applehelp" @@ -1903,6 +2106,8 @@ version = "2.0.0" description = "sphinxcontrib-applehelp is a Sphinx extension which outputs Apple help books" optional = true python-versions = ">=3.9" +groups = ["main"] +markers = "extra == \"doc\"" files = [ {file = "sphinxcontrib_applehelp-2.0.0-py3-none-any.whl", hash = "sha256:4cd3f0ec4ac5dd9c17ec65e9ab272c9b867ea77425228e68ecf08d6b28ddbdb5"}, {file = "sphinxcontrib_applehelp-2.0.0.tar.gz", hash = "sha256:2f29ef331735ce958efa4734873f084941970894c6090408b079c61b2e1c06d1"}, @@ -1919,6 +2124,8 @@ version = "2.0.0" description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp documents" optional = true python-versions = ">=3.9" +groups = ["main"] +markers = "extra == \"doc\"" files = [ {file = "sphinxcontrib_devhelp-2.0.0-py3-none-any.whl", hash = "sha256:aefb8b83854e4b0998877524d1029fd3e6879210422ee3780459e28a1f03a8a2"}, {file = "sphinxcontrib_devhelp-2.0.0.tar.gz", hash = "sha256:411f5d96d445d1d73bb5d52133377b4248ec79db5c793ce7dbe59e074b4dd1ad"}, @@ -1935,6 +2142,8 @@ version = "2.1.0" description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files" optional = true python-versions = ">=3.9" +groups = ["main"] +markers = "extra == \"doc\"" files = [ {file = "sphinxcontrib_htmlhelp-2.1.0-py3-none-any.whl", hash = "sha256:166759820b47002d22914d64a075ce08f4c46818e17cfc9470a9786b759b19f8"}, {file = "sphinxcontrib_htmlhelp-2.1.0.tar.gz", hash = "sha256:c9e2916ace8aad64cc13a0d233ee22317f2b9025b9cf3295249fa985cc7082e9"}, @@ -1951,6 +2160,8 @@ version = "1.8.1" description = "Sphinx domain for documenting HTTP APIs" optional = true python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*" +groups = ["main"] +markers = "extra == \"doc\"" files = [ {file = "sphinxcontrib-httpdomain-1.8.1.tar.gz", hash = "sha256:6c2dfe6ca282d75f66df333869bb0ce7331c01b475db6809ff9d107b7cdfe04b"}, {file = "sphinxcontrib_httpdomain-1.8.1-py2.py3-none-any.whl", hash = "sha256:21eefe1270e4d9de8d717cc89ee92cc4871b8736774393bafc5e38a6bb77b1d5"}, @@ -1966,6 +2177,8 @@ version = "1.0.1" description = "A sphinx extension which renders display math in HTML via JavaScript" optional = true python-versions = ">=3.5" +groups = ["main"] +markers = "extra == \"doc\"" files = [ {file = "sphinxcontrib-jsmath-1.0.1.tar.gz", hash = "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8"}, {file = "sphinxcontrib_jsmath-1.0.1-py2.py3-none-any.whl", hash = "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178"}, @@ -1980,6 +2193,8 @@ version = "0.8.4" description = "OpenAPI (fka Swagger) spec renderer for Sphinx" optional = true python-versions = ">=3.7" +groups = ["main"] +markers = "extra == \"doc\"" files = [ {file = "sphinxcontrib-openapi-0.8.4.tar.gz", hash = "sha256:df883808a5b5e4b4113ad697185c43a3f42df3dce70453af78ba7076907e9a20"}, {file = "sphinxcontrib_openapi-0.8.4-py3-none-any.whl", hash = "sha256:50911c18d452d9390ee3a384ef8dc8bde6135f542ba55691f81e1fbc0b71014e"}, @@ -2000,6 +2215,8 @@ version = "2.0.0" description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp documents" optional = true python-versions = ">=3.9" +groups = ["main"] +markers = "extra == \"doc\"" files = [ {file = "sphinxcontrib_qthelp-2.0.0-py3-none-any.whl", hash = "sha256:b18a828cdba941ccd6ee8445dbe72ffa3ef8cbe7505d8cd1fa0d42d3f2d5f3eb"}, {file = "sphinxcontrib_qthelp-2.0.0.tar.gz", hash = "sha256:4fe7d0ac8fc171045be623aba3e2a8f613f8682731f9153bb2e40ece16b9bbab"}, @@ -2016,6 +2233,8 @@ version = "2.0.0" description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)" optional = true python-versions = ">=3.9" +groups = ["main"] +markers = "extra == \"doc\"" files = [ {file = "sphinxcontrib_serializinghtml-2.0.0-py3-none-any.whl", hash = "sha256:6e2cb0eef194e10c27ec0023bfeb25badbbb5868244cf5bc5bdc04e4464bf331"}, {file = "sphinxcontrib_serializinghtml-2.0.0.tar.gz", hash = "sha256:e9d912827f872c029017a53f0ef2180b327c3f7fd23c87229f7a8e8b70031d4d"}, @@ -2032,6 +2251,7 @@ version = "6.0.0" description = "A Python Wrapper for the NAIF CSPICE Toolkit" optional = false python-versions = "<4,>=3.6" +groups = ["main"] files = [ {file = "spiceypy-6.0.0-py3-none-macosx_10_9_x86_64.whl", hash = "sha256:70cda5b057d1b83dd8a4ecd9d4d2823b2f9c263b85fcdcc0df0370ca5b94c74f"}, {file = "spiceypy-6.0.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:20d70ce09e6efa78e9e3f2400c6ee85bd7065f19edf2d4ebce257c79eb43e534"}, @@ -2054,6 +2274,8 @@ version = "0.9.0" description = "Pretty-print tabular data" optional = true python-versions = ">=3.7" +groups = ["main"] +markers = "extra == \"doc\"" files = [ {file = "tabulate-0.9.0-py3-none-any.whl", hash = "sha256:024ca478df22e9340661486f85298cff5f6dcdba14f3813e8830015b9ed1948f"}, {file = "tabulate-0.9.0.tar.gz", hash = "sha256:0095b12bf5966de529c0feb1fa08671671b3368eec77d7ef7ab114be2c068b3c"}, @@ -2068,6 +2290,8 @@ version = "2.2.1" description = "A lil' TOML parser" optional = true python-versions = ">=3.8" +groups = ["main"] +markers = "python_version == \"3.10\" and (extra == \"dev\" or extra == \"doc\" or extra == \"test\")" files = [ {file = "tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249"}, {file = "tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6"}, @@ -2109,6 +2333,8 @@ version = "4.13.2" description = "Backported and Experimental Type Hints for Python 3.8+" optional = true python-versions = ">=3.8" +groups = ["main"] +markers = "extra == \"doc\" or extra == \"dev\" or python_version == \"3.10\" and (extra == \"test\" or extra == \"doc\" or extra == \"dev\")" files = [ {file = "typing_extensions-4.13.2-py3-none-any.whl", hash = "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c"}, {file = "typing_extensions-4.13.2.tar.gz", hash = "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef"}, @@ -2120,6 +2346,7 @@ version = "2025.2" description = "Provider of IANA time zone data" optional = false python-versions = ">=2" +groups = ["main"] files = [ {file = "tzdata-2025.2-py2.py3-none-any.whl", hash = "sha256:1a403fada01ff9221ca8044d701868fa132215d84beb92242d9acd2147f667a8"}, {file = "tzdata-2025.2.tar.gz", hash = "sha256:b60a638fcc0daffadf82fe0f57e53d06bdec2f36c4df66280ae79bce6bd6f2b9"}, @@ -2131,13 +2358,14 @@ version = "2.4.0" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false python-versions = ">=3.9" +groups = ["main"] files = [ {file = "urllib3-2.4.0-py3-none-any.whl", hash = "sha256:4e16665048960a0900c702d4a66415956a584919c03361cac9f1df5c5dd7e813"}, {file = "urllib3-2.4.0.tar.gz", hash = "sha256:414bc6535b787febd7567804cc015fee39daab8ad86268f1310a9250697de466"}, ] [package.extras] -brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] +brotli = ["brotli (>=1.0.9) ; platform_python_implementation == \"CPython\"", "brotlicffi (>=0.8.0) ; platform_python_implementation != \"CPython\""] h2 = ["h2 (>=4,<5)"] socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] zstd = ["zstandard (>=0.18.0)"] @@ -2148,6 +2376,8 @@ version = "20.31.2" description = "Virtual Python Environment builder" optional = true python-versions = ">=3.8" +groups = ["main"] +markers = "extra == \"dev\"" files = [ {file = "virtualenv-20.31.2-py3-none-any.whl", hash = "sha256:36efd0d9650ee985f0cad72065001e66d49a6f24eb44d98980f630686243cf11"}, {file = "virtualenv-20.31.2.tar.gz", hash = "sha256:e10c0a9d02835e592521be48b332b6caee6887f332c111aa79a09b9e79efc2af"}, @@ -2160,7 +2390,7 @@ platformdirs = ">=3.9.1,<5" [package.extras] docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.2,!=7.3)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"] -test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.4)", "pytest-env (>=0.8.2)", "pytest-freezer (>=0.4.8)", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=68)", "time-machine (>=2.10)"] +test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.4)", "pytest-env (>=0.8.2)", "pytest-freezer (>=0.4.8) ; platform_python_implementation == \"PyPy\" or platform_python_implementation == \"GraalVM\" or platform_python_implementation == \"CPython\" and sys_platform == \"win32\" and python_version >= \"3.13\"", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=68)", "time-machine (>=2.10) ; platform_python_implementation == \"CPython\""] [[package]] name = "xarray" @@ -2168,6 +2398,7 @@ version = "2025.4.0" description = "N-D labeled arrays and datasets in Python" optional = false python-versions = ">=3.10" +groups = ["main"] files = [ {file = "xarray-2025.4.0-py3-none-any.whl", hash = "sha256:b27defd082c5cb85d32c695708de6bb05c2838fb7caaf3f952982e602a35b9b8"}, {file = "xarray-2025.4.0.tar.gz", hash = "sha256:2a89cd6a1dfd589aa90ac45f4e483246f31fc641836db45dd2790bb78bd333dc"}, @@ -2182,7 +2413,7 @@ pandas = ">=2.1" accel = ["bottleneck", "flox", "numba (>=0.54)", "numbagg", "opt_einsum", "scipy"] complete = ["xarray[accel,etc,io,parallel,viz]"] etc = ["sparse"] -io = ["cftime", "fsspec", "h5netcdf", "netCDF4", "pooch", "pydap", "scipy", "zarr"] +io = ["cftime", "fsspec", "h5netcdf", "netCDF4", "pooch", "pydap ; python_version < \"3.10\"", "scipy", "zarr"] parallel = ["dask[complete]"] types = ["pandas-stubs", "scipy-stubs", "types-PyYAML", "types-Pygments", "types-colorama", "types-decorator", "types-defusedxml", "types-docutils", "types-networkx", "types-openpyxl", "types-pexpect", "types-psutil", "types-pycurl", "types-python-dateutil", "types-pytz", "types-setuptools"] viz = ["cartopy", "matplotlib", "nc-time-axis", "seaborn"] @@ -2195,6 +2426,6 @@ test = ["netcdf4", "openpyxl", "pytest", "pytest-cov", "pytest-xdist", "requests tools = ["openpyxl", "pandas"] [metadata] -lock-version = "2.0" -python-versions = ">=3.10,<4" -content-hash = "c860ea93477a883e5d7fdf45ed027d9289fb36dd56203b8cc48765cf9cdca493" +lock-version = "2.1" +python-versions = ">=3.10,<3.13" +content-hash = "3d52d625a144e78ed95e527798289d6b0d5780bd25e80a94bec7197cc9863f35" diff --git a/pyproject.toml b/pyproject.toml index beefe19497..230cee0344 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,21 +1,23 @@ [build-system] -requires = ["poetry-core>=1.0.0,<2.0", "poetry-dynamic-versioning>=1.0.0,<2.0.0"] +requires = ["poetry-core>=2.0.0", "poetry-dynamic-versioning>=1.0.0"] build-backend = "poetry_dynamic_versioning.backend" -[tool.poetry] +# Project configuration +# --------------------- + +[project] name = "imap-processing" -# Gets updated dynamically by the poetry-dynamic-versioning plugin -version = "0.0.0" +# Version is set dynamically by poetry-dynamic-versioning +dynamic = ["version"] description = "IMAP Science Operations Center Processing" -authors = ["IMAP SDC Developers "] +authors = [{name = "IMAP SDC Developers", email = "imap-sdc@lists.lasp.colorado.edu"}] readme = "README.md" -include = ["imap_processing/_version.py"] license = "MIT" keywords = ["IMAP", "SDC", "SOC", "Science Operations"] +requires-python = ">=3.10,<3.13" # upper bound due to scipy wheel availability; bump when scipy supports 3.14 classifiers = [ "Development Status :: 3 - Alpha", "Intended Audience :: Developers", - "License :: OSI Approved :: MIT License", "Natural Language :: English", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.10", @@ -28,50 +30,49 @@ classifiers = [ "Operating System :: Unix", "Operating System :: MacOS", ] +dependencies = [ + "astropy-healpix>=1.0", + "cdflib>=1.3.6", + "imap-data-access>=0.37.0", + "space_packet_parser>=6.0.0", + "spiceypy>=6.0.0", + "xarray>=2024.10.0,<2026", + "numpy>=2,<3", + "sammi-cdf>=1.0,<2", + "scipy>=1.13,<2" +] +[tool.poetry] # Exclude tests from build exclude = ["imap_processing/tests"] +include = ["imap_processing/_version.py", + "imap_processing/ultra/l1c/sim_spice_kernels/*"] +version = "0.0.0" + +[tool.poetry.requires-plugins] +poetry-dynamic-versioning = { version = ">1.0.0,<2.0.0", extras = ["plugin"]} -[tool.poetry.dependencies] -astropy-healpix = ">=1.0" -cdflib = "^1.3.6" -imap-data-access = ">=0.32.0" -python = ">=3.10,<4" -space_packet_parser = "^5.0.1" -spiceypy = ">=6.0.0" -xarray = '>=2024.10.0' -numpy = "<=3" -sammi-cdf = "^1.0" -scipy = "^1.13" - -# Optional dependencies -numpydoc = {version="^1.5.0", optional=true} -openpyxl = {version=">=3.0.7", optional=true} -pandas = {version=">=2.0.0", optional=true} -pre-commit = {version="^3.3.3", optional=true} -pydata-sphinx-theme = {version="*", optional=true} -pytest = {version=">=6.2.5", optional=true} -pytest-cov = {version="^4.0.0", optional=true} -pytest-xdist = {version="^3.2", optional=true} -ruff = {version="==0.2.1", optional=true} -sphinx = {version="*", optional=true} -sphinxcontrib-openapi = {version="^0.8.3", optional=true} -mypy = {version="1.10.1", optional=true} -requests = {version = "^2.32.3", optional = true} -healpy = {version = "^1.18.0", optional = true} -netcdf4 = {version ="^1.7.2", optional = true} - -[tool.poetry.extras] -dev = ["pre-commit", "ruff", "mypy"] -doc = ["numpydoc", "pydata-sphinx-theme", "sphinx", "sphinxcontrib-openapi"] -test = ["openpyxl", "pytest", "pytest-cov", "pytest-xdist", "requests", "netcdf4"] -tools = ["openpyxl", "pandas"] -map_visualization = ["healpy"] +[project.scripts] +imap_cli = 'imap_processing.cli:main' +imap_xtce = 'imap_processing.ccsds.excel_to_xtce:main' [project.urls] homepage = "https://github.com/IMAP-Science-Operations-Center" repository = "https://github.com/IMAP-Science-Operations-Center/imap_processing" +# Dependencies +# ------------ + +[project.optional-dependencies] +dev = ["pre-commit>=3.3.3,<4", "ruff==0.15.2", "mypy==1.10.1"] +doc = ["numpydoc>=1.5.0,<2", "pydata-sphinx-theme", "sphinx", "sphinxcontrib-openapi>=0.8.3,<0.9"] +test = ["openpyxl>=3.0.7", "pytest>=6.2.5", "pytest-cov>=4.0.0,<5", "pytest-xdist>=3.2,<4", "requests>=2.32.3,<3", "netcdf4>=1.7.2,<2"] +tools = ["openpyxl>=3.0.7", "pandas>=2.0.0"] +map_visualization = ["healpy>=1.18.0,<2"] + +# Tool settings +# ------------- + [tool.pytest.ini_options] testpaths = [ "imap_processing/tests", @@ -82,6 +83,9 @@ filterwarnings = [ "ignore:datetime.datetime.utcfromtimestamp:DeprecationWarning:cdflib", # Ignore Data_version warnings during tests because we default to v001 "ignore:No Data_version attribute found:UserWarning:imap_processing", + # Some test packet data is of the incorrect length and causes many warnings + # that can be ignored for testing purposes + "ignore:Number of bits:UserWarning:space_packet_parser", ] markers = [ "external_kernel: marks tests as requiring external SPICE kernels (deselect with '-m \"not external_kernel\"')", @@ -89,7 +93,6 @@ markers = [ "use_test_metakernel: Mark test to use a test metakernel" ] - [tool.ruff] target-version = "py310" lint.select = ["B", "D", "E", "F", "I", "N", "S", "W", "PL", "PT", "UP", "RUF"] @@ -99,23 +102,19 @@ lint.ignore = [ "PLR0915", # too-many-statements error "PLR2004", # Magic value in comparison "RUF002", # `βˆ’` (MINUS SIGN). Did you mean `-` (HYPHEN-MINUS) error - "RUF200", # pyproject missing field (poetry doesn't follow the spec) "S311", # suspicious-non-cryptographic-random-usage - "UP038", # Deprecated ] [tool.ruff.lint.per-file-ignores] -# S603 unchecked input in subprocess call is fine in our tests # PT006 Wrong type passed to first argument of @pytest.mark.parametrize -"*/tests/*" = ["D", "S101", "S603", "PT006"] +# RUF043 pattern match has regex characters like a period (.) that are not escaped +# RUF059 unused variables unpacked +# S603 unchecked input in subprocess call is fine in our tests +"*/tests/*" = ["D", "PT006", "RUF043", "RUF059", "S101", "S603", "PLW0108", "RUF061"] [tool.ruff.lint.pydocstyle] convention = "numpy" -[tool.poetry.scripts] -imap_cli = 'imap_processing.cli:main' -imap_xtce = 'imap_processing.ccsds.excel_to_xtce:main' - [tool.codespell] ignore-words-list = "livetime" @@ -137,7 +136,7 @@ checks = ["all", #report on all checks, except the following "SA01", # Ignore See Also section not found "ES01", # Ignore No extended summary found "RT02" ] # Ignore The first line of the Returns section -exclude = ['__init__' ] # don't report on objects that match any of these regex +exclude = ['__init__', '_version'] # don't report on objects that match any of these regex override_SS05 = [ # override SS05 to allow docstrings starting with these words '^Process ', ] @@ -155,4 +154,3 @@ explicit_package_bases = true follow_imports = 'skip' #may want to remove exclude = ["tests"] packages = ["imap_processing" , "tools"] -plugins = 'numpy.typing.mypy_plugin' diff --git a/tools/spice/spice_examples.py b/tools/spice/spice_examples.py index d765414b28..94e482c433 100644 --- a/tools/spice/spice_examples.py +++ b/tools/spice/spice_examples.py @@ -100,7 +100,7 @@ def _get_particle_velocity( # Spacecraft velocity in the DPS frame wrt the heliosphere # https://spiceypy.readthedocs.io/en/main/documentation.html#spiceypy.spiceypy.spkezr - state, lt = spiceypy.spkezr("IMAP", time, "IMAP_DPS", "NONE", "SUN") + state, _lt = spiceypy.spkezr("IMAP", time, "IMAP_DPS", "NONE", "SUN") # Extract the velocity part of the state vector imap_dps_velocity = state[3:6]